Add with_embed_service() builder and embed_service() accessor to ToolContext,
wired through ChatService so function-calling tools can access Qdrant vector search.
- chunk_text(): char-boundary-safe text chunking at paragraph/sentence breaks (7000 char limit)
- embed_memories_batch(): groups messages by room, batch-embeds all texts to reduce Qdrant calls
- embed_issue_chunked(): auto-chunks long issue bodies
- embed_skill(): upgraded with auto-chunking via chunk_text
- TagEmbedInput struct for batch tag embedding
- embed_tags_batch() / search_tags() with project isolation
- ensure_collections() now creates embed_repo_tag collection
Critical fixes:
- Wrap balance updates in database transactions with SELECT FOR UPDATE
- Move history insert after balance validation to prevent orphaned records
- Use Decimal throughout to avoid silent conversion failures
- Prevent concurrent requests from causing negative balances
Tasks resolved:
- Task #4: Silent Decimal conversion failures
- Task #5: Missing transaction isolation (race conditions)
- Task #6: History inserted before validation
- process_react now returns (String, i64, i64) tuple with token counts
- Extract token stats from rig Agent FinalResponse usage field
- Both streaming and non-streaming ReAct modes now bill correctly
- Add record_ai_session() helper calling billing::record_ai_usage()
- Replace all Set(None) cost/currency with actual calculated values
- Cost computed from model_pricing via Decimal precision
- Use AgentBuilder for native tool-calling with stream_prompt()
- Add RecordingTool wrapper preserving retry + DB recording
- Fix tool_choice bug in do_completion (same as call_stream_once)
- Add seq field to RoomMessageStreamChunkEvent for strict ordering
- Map streaming events: Text→Answer, Reasoning→Thought, ToolCall→Action
- Only final event has done=true, removed premature stream ending
- Store __chunks__ JSON in thinking_content for ordered replay
- Start SSH rate limiter cleanup task that was missing (prevent memory leak)
- Create single ToolContext outside tool execution loop so max_tool_calls
and max_depth guards actually fire across batch tool calls (was creating
fresh context per call, bypassing all limits)
When a user mentions a repository in room chat, extract the repo name
from @[repo:name:label] brackets, look up the full repo model from the
database, and inject its details (name, description, default branch,
visibility) into the AI message context. Works independently of
embed_service availability.
When APP_AI_BASIC_URL already ends with /v1 (e.g. openrouter.ai/api/v1),
appending /v1/models produces /v1/v1/models. Detect trailing /v1 and
only append /models in that case.
- StreamChunk/StreamChunkType types for preserving arrival order
- Chunk collection in call_stream_once and process_stream
- Add "error sending request" and "Http client error" to retryable errors
- StreamResult includes chunks vector for ordered replay
- Streaming path: on tool_call execution error, emit an [Observation]
chunk so the model sees the failure and can retry/adapt
- Non-streaming path: inject error as a user message so the loop
continues with error context, not silently stop
ReAct loop was terminating early when the model returned:
[Agent ran through N steps...]
{"thought": "...", "action": {...}}
The extract_json function only checked the string start or code fences.
Now scans for { or [ at non-word positions and uses depth-counting
to strip trailing text, allowing JSON buried anywhere in the response.
- Refactor room-context.tsx with improved WebSocket state management
- Enhance room-ws-client.ts with reconnect logic and message handling
- Update Discord layout components with message editor improvements
- Add WebSocket universal endpoint support in ws_universal.rs
Model sync:
- Filter OpenRouter models by what the user's AI client can actually access,
before upserting metadata (avoids bloating with inaccessible models).
- Fall back to direct endpoint sync when no OpenRouter metadata matches
(handles Bailian/MiniMax and other non-OpenRouter providers).
Git stability fixes:
- SSH: add 5s timeout on stdin flush/shutdown in channel_eof and
cleanup_channel to prevent blocking the event loop on unresponsive git.
- SSH: remove dbg!() calls from production code paths.
- HTTP auth: pass proper Logger to SshAuthService instead of discarding
all auth events to slog::Discard.
Dependencies:
- reqwest: add native-tls feature for HTTPS on Windows/Linux/macOS.