- Import resolveOverlayPath from shared.ts
- Add checkOverlayExists check (skip when no FLYNN_ENV, pass/fail for overlay file)
- Insert after checkConfigExists in allChecks array
- All 1087 tests pass, typecheck clean
- Add resolveOverlayPath() that maps FLYNN_ENV to {configDir}/{env}.yaml
- Update loadConfigSafe to pass overlay path through to loadConfig
- All CLI commands using loadConfigSafe() automatically get overlay support
- No FLYNN_ENV = exact same behavior as before (backward compatible)
- Full test suite passes (1087 tests, zero regressions)
- Add deepMerge utility for recursive object merging (arrays replace, not concat)
- Extend loadConfig with optional overlayPath parameter
- Merge happens before env var expansion and Zod validation
- Add 6 deepMerge unit tests and 4 overlay integration tests
- Re-export deepMerge from config/index.ts
- All 1087 existing tests still pass
- Create initAgents() function encapsulating AgentConfigRegistry, AgentRouter, SandboxManager init
- Replace ~26 lines in startDaemon() with single initAgents() call
- Lifecycle shutdown handler for sandbox cleanup included in agents.ts
- Zero type errors, routing tests pass
- Move createMessageRouter function (~220 lines) to dedicated routing module
- Add import from ./routing.js in daemon/index.ts
- routing.test.ts passes without modification
- Zero type errors
Adds zhipuai as a new provider using the OpenAI-compatible API at
api.z.ai. Supports api_key config or ZHIPUAI_API_KEY env var, with
optional endpoint override.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check model capabilities via /api/show before sending tools.
Models without 'tools' capability get requests without tools
(they can still answer, just without tool use). Result is cached
per client instance. Defense-in-depth: 'does not support' added
to retry nonRetryablePatterns to avoid wasting retries on
permanent errors.
- Ollama: pass tools to API, parse tool_calls responses, handle thinking field from reasoning models (deepseek-r1, glm-4.7-flash)
- llama.cpp: pass tools via OpenAI-compatible endpoint, parse tool_calls, accumulate streaming tool call deltas
- Both clients now set stopReason to 'tool_use' when tool calls are present
- Tests: 12 new tests (8 Ollama + 5 llama.cpp, total 983→995)
- assembleSystemPrompt() now injects '# Runtime Context' with current date/time
- New system.info tool: date, time, hostname, platform, arch, uptime, memory, Node.js version
- Tool available in all profiles (minimal/messaging/coding/full)
- 983 tests passing (+7 new)
- README: features list, Gmail config section with field reference and
template variables, hook examples, architecture tree, CLI description
- CHANGELOG: new Added entries for both features
- SOUL.md: file.patch in capabilities list
- config/default.yaml: file.patch in confirm hooks, commented-out
automation section with cron, webhooks, gmail, heartbeat examples
New ChannelAdapter that monitors Gmail via Google Cloud Pub/Sub push
notifications with polling fallback. Supports OAuth2 auth, configurable
watch labels, template rendering with email metadata placeholders
(from, to, subject, snippet, date, id, labels).
Wired into daemon lifecycle and gateway (POST /gmail/push endpoint).
Includes 16 tests covering auth, templates, push notifications, and
channel routing.
Implements apply_patch equivalent: a single tool call can make multiple
line-based edits (replacements, insertions, deletions) across one or more
files. Hunks are applied bottom-up to preserve line numbers.
Includes 10 tests covering replacement, multi-hunk, insertion, deletion,
multi-file, overlapping hunks error, OOB error, and edge cases.
Two issues prevented the GitHub Models fallback from working:
1. The X-GitHub-Api-Version: 2022-11-28 header caused '400 invalid
apiVersion' errors. The Copilot chat completions endpoint does not
use this header — removed from both constructor and rebuildClient.
2. The anthropicToGitHubModel mapping was incomplete: it only knew
three models and the generic date-stripping fallback produced wrong
names (e.g. 'claude-sonnet-4-5' instead of 'claude-sonnet-4.5').
GitHub Copilot uses dots for sub-versions, not hyphens.
Updated with explicit mappings for all current models (sonnet 4,
4.5; opus 4, 4.5, 4.6; haiku 4.5) and a smarter generic fallback
that converts digit-hyphen-digit to digit.digit at the end.
3. createClientFromConfig now auto-maps Anthropic-style model names
when the provider is 'github', so users can copy model names from
their Anthropic config into fallback blocks without manual renaming.
The TUI was building its own ModelRouter with a duplicated client factory
that lacked auto same-model fallback, local_providers resolution, retry
config, and per-tier fallback logic. When Anthropic failed, it skipped
GitHub Models and fell straight to the local Ollama model.
Replace the duplicated ~50-line createClient + router setup in tui.ts
with a single call to the daemon's createModelRouter(), which already
handles all of these correctly. This removes ~50 lines of duplicated
code and ensures TUI and daemon have identical fallback behavior.