v0.9.0 - The Unification Refactor
The Unification Refactor
This release eliminates the duplicated logic between singlePrompt() and chat() that caused bugs #37 and #43. Both now share a single processPrompt() function for retry, streaming, and MCP tool execution.
Bug Fixes
- Chat+MCP crash fixed (#43):
apfel --chat --mcp server.pyno longer crashes with "Last message has no text content". The session is now built directly with tool definitions instead of requiring a user message at init time. - Ctrl-C exits chat cleanly: SIGINT is properly handled via a C-level handler around libedit. Previously Ctrl-C was silently swallowed by readline.
- Context rotation preserves MCP tools: After context window rotation in chat mode, MCP tool definitions are re-injected into the new session. Previously, tools silently stopped working after the first rotation.
- Summarizer respects --permissive: The summarize context strategy now uses
makeModel(permissive:)instead ofSystemLanguageModel.default, honoring the--permissiveflag.
New Features
--debugfor all modes (#44): The--debugflag now works in CLI single-prompt, chat, and server modes. Debug output goes to stderr and includes prompt info, response length, MCP tool execution, and context rotation events.- Missing error cases (#41): Added
unsupportedGuideanddecodingFailuretoApfelErrorwith proper classification, CLI labels, HTTP status codes, and OpenAI error types. - Homebrew formula fix (#45): The
odie "apfel requires Apple Silicon"hard error has been replaced with a caveats warning, allowing installation on machines where Homebrew's ARM detection may report incorrectly (e.g., M4 Mac Mini).
Architecture
- Extracted
processPrompt()- unified retry + streaming + MCP tool execution shared bysinglePrompt()andchat() - Added
ToolLogEntryandProcessPromptResulttypes to ApfelCore - Added
apfelDebugEnabledglobal flag withdebugLog()functions - Added
ContextConfig.permissivefield threaded through to Summarizer - Dead code removed:
sseStopChunk(),buildSystemPrompt(),formatToolResult()
Testing
- 377 total tests (203 unit + 174 integration), all passing
- 35 new chat integration tests covering every TUI scenario:
- Startup, quit, exit, EOF, non-TTY rejection
- Chat + MCP (no crash, tool listing, tool execution, tool log, system prompt combo)
- Chat + system prompt (flag, short flag, env var)
- Chat + debug (stderr output, prompt info, response info, stdout isolation)
- Chat output formats (plain, JSON, JSONL, quiet)
- Chat + flags (temperature, max-tokens, permissive, retry)
- Chat multi-turn context retention
- Ctrl-C at prompt, mid-line, during response, multiple times
- Non-tool questions answered normally in MCP mode
- Integration test
conftest.pynow auto-starts servers (no manual server startup needed)
Closed Issues
- #41 - Review error handling: 3 GenerationError cases not classified
- #42 - Use Apple Intelligence's ChatGPT extension (closed as won't-fix, outside scope)
- #43 - Chat+MCP crash on startup
- #44 - Add --debug mode for CLI and chat
- #45 - Homebrew install returning Apple Silicon error on M4 Mac Mini
Update
brew upgrade apfel