- Fixed memory backend API: getAll() now includes all memory types (lesson, gotcha, pattern, preference, discovery, context, ephemeral)
- Fixed memory test assertions: use MEMORY_TYPES.LESSON instead of undefined FACT, await retrieve() calls
- Added getAll() method to JSONBackend for grouped memory access
- Fixed InMemoryBackend to support all memory types in getAll()
- Fixed smoke test to properly await async methods and check correct properties
When file_write gets a 15KB+ HTML payload, the streaming JSON gets
truncated. Now catches JSON parse errors and returns a specific
hint to use bash heredoc instead of silently failing.
The old logic stopped typing on first stream token, leaving tool
execution gaps (30s+) with zero visual feedback. Now typing persists
until the full response + streaming edits are complete.
OLD: streaming and non-streaming were separate paths. Streaming detected tool
calls and recursively called non-streaming which only did ONE round of tool
execution with no loop-back. This caused silent hangs.
NEW: single chatWithAI with internal while loop (max 10 turns):
1. Call API (stream or non-stream)
2. If tool_calls → execute all → append results → loop
3. If text content → return final answer
Key fixes:
- streamChat now ACCUMULATES tool_call deltas instead of aborting
- Tool results are fed back to the AI in the same conversation
- Multi-turn: AI can call tools multiple times before answering
- Max 10 turns with forced final answer as safety net
- Proper { content, tool_calls, error } return type from both paths
- Non-streaming fallback if SSE fails
- No more recursive calls between stream/non-stream
Previously tool calls in non-streaming path returned raw tool output as the
response. Now executes tool, sends results back to model for a synthesized
answer. Fixes the 'silent after streaming fallback' bug.
- DelegateTool.js: multi-turn sub-agent (max 10 turns), feeds tool results back
- Moved TOOL_DEFS to startBot scope so delegate handler can access tool schemas
- Fixed scoping: delegate handler resolves model from svc.config instead of chatWithAI local
- Wired into tools/index.js, TOOL_DEFS, and toolHandlers
- delegate_agent: now makes actual AI call with role-specific system prompts
(coder=code review, architect=system design, devops=infrastructure)
- run_skill: now makes actual AI call with skill-specific system prompts
(code_review, bug_fix, refactor, documentation, testing)
- Both return structured AI-generated results instead of placeholder text
Model says "let me research" then calls web_search tool.
Streaming path ignored tool_calls entirely (no-op comment).
Now: detect tool_calls delta, cancel stream, fall back to non-streaming
which properly executes tools and returns results.
- Pidfile lock prevents duplicate instances (auto-kills stale PIDs)
- EADDRINUSE retry: kills port hog, retries up to 3x with 1.5s delay
- releasePidfile() on graceful shutdown
- Added fs/path imports needed by pidfile utilities
- ConversationStore: per-chat JSON files in data/, survives restarts
- 6000 token budget per chat context (fits ~20-30 exchanges)
- Auto-trims old messages, always includes most recent
- Wired into message handler: loads history before AI call, saves after
- /reset command to clear chat history per chat
- Cross-session, cross-model, cross-chat isolation