Addresses chatgpt-codex review: the previous full serde_json::to_string
included internal-only fields (allowed_callers, defer_loading,
input_examples, cache_control) that are never sent to the chat API.
This caused spurious drift detection when those fields changed.
- New tool_to_api_json() helper mirrors tool_to_chat() serialization:
only type, name, description, parameters, strict
- Doc comment fixed: 'sorted by name' → 'sorted lexicographically
by JSON text' (greptile review)
Phase 1.5 — upgrade PrefixFingerprint::compute() to hash the full tool
JSON serialization (name + description + schema) instead of just tool
names. This catches schema/description drift in addition to name changes.
- Serialize each tool via serde_json::to_string, sort by name, join
- New test: fingerprint_detects_schema_change_not_just_name_change
- All 21 prefix_cache tests pass
- Aligned with prompt_zones.rs tool_catalog_digest approach
Treat a missing tui.status_items field as None even when the [tui]
table exists, preserving the documented default footer behavior.
Add a regression test for configs that define [tui] without status_items.
with_agent_tools() unconditionally registered web_search/fetch_url/web.run
(via with_web_tools) and apply_patch (via with_patch_tools), but tool_setup.rs
conditionally registered them again based on Feature::WebSearch and
Feature::ApplyPatch flags. This caused double registration (overwritten
with a warning log on the second insert).
Changes:
- Remove with_web_tools() and with_patch_tools() from with_agent_tools()
- Move finance tool out of with_web_tools() into its own with_finance_tool()
(finance is market data, not web search — it should not be gated behind
the web-search feature flag)
- Add with_finance_tool() to with_agent_tools() so finance stays always
available
- Update tests: new test for with_finance_tool(), updated web_tools test
to verify finance is no longer in the web group
Moonshot/Kimi is a shipped provider with full support (model registry entry,
provider ID, env var plumbing, CLI provider picker), but config.example.toml
was missing its [providers.moonshot] table block while all other 15 providers
had one. This made Moonshot the only shipped provider absent from the example.
Added the section between siliconflow and sglang, matching the shipped-provider
ordering in docs/PROVIDERS.md. Includes the Kimi Code alternate path and
kimi_oauth auth_mode comment.
v0.8.48 removed the Qwen 3.7 Max preset (it's a hosted model, not open-weight).
Two references remained in config.example.toml:
- Default Models comment (line 41)
- OpenRouter provider section comment (line 280)
These stale references could confuse users into trying a removed model.
- Fix false 'Turn stalled' during long active turns with running tools.
Add turn_last_activity_at tracking and active-tool awareness to
reconcile_turn_liveness(). Three new tests cover the fix.
- Remove Qwen 3.7 Max OpenRouter preset from registry, picker, docs,
and tests. Qwen 3.7 Max is a hosted model; the preset will return
when an open-weight Qwen 3.7 release ships. MiniMax M3 remains as
a full 1M-context multimodal route.
- Sync root CHANGELOG to crates/tui/CHANGELOG for crates.io packaging.
Update docs/CONFIGURATION.md, docs/PROVIDERS.md, and README to
reflect the Qwen 3.7 removal. Regenerate web facts timestamp.
All dead_code in prompt_zones.rs is intentional — these types are
scaffolding awaiting future integration. Pre-existing schema_migration
warnings remain as-is.
Narrower slice per Hmbown's review: typed zone structs as foundation
without wiring into the request path. Future phases will integrate
AppendLog/TurnScratch/ThreeZoneRequest into turn_loop.
- prompt_zones.rs (663 lines, 16 tests): PinnedPrefix / FrozenPrefix /
PrefixDrift (ready), AppendLog / TurnScratch / ThreeZoneRequest
(scaffolding, #[allow(dead_code)])
- FrozenPrefix: full tool JSON hash (name+desc+schema), raw-text
fast-path in verify(), cache_control preserved in build_messages()
- /cache zones subcommand with three-zone status display
- merge_compaction_summary: zone affiliation doc comment
- No turn_loop/session changes — engine continues using
PrefixStabilityManager / MessageRequest as before
Clear stale busy state and retry/title animations on local cancel.\n\nLocal verification:\n- cargo test -p codewhale-tui\n- codewhale doctor\n- codewhale --provider deepseek --model deepseek-v4-pro exec "Reply with exactly: OK"