diff --git a/CHANGELOG.md b/CHANGELOG.md index 5368eabfe..b5ada0dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,74 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.9.7] - 2026-08-12 + +Codewhale v0.9.7 keeps the catalog ordinary. Grok 4.6 lands as a normal catalog +row instead of a provider-shaped pile of special cases, OrcaRouter joins as a +named provider, and a panic-safety advisory in `lru` is cleared by lifting the +pin that caused it rather than living around it. + ### Added -- Add Grok 4.6 as the direct xAI default with its official 500K context, - text/image input, tool and structured-output support, four reasoning efforts, - native web search, and usage-aware 200K-token pricing boundary. Reconcile the - existing `deepseek-v4-pro` registration with DeepSeek's live - `DeepSeek-V4-Pro-0813` backend label without changing the callable API ID. +- Grok 4.6 is the direct xAI default, with the `grok` alias moving onto it and + `grok-4.5` still explicitly selectable. Its 500K context, text/image input, + tool and structured-output support, `low`/`medium`/`high`/`xhigh` reasoning + efforts (default `high`), and server-side web search all come from the + Models.dev-shaped catalog rather than model-specific code. `reasoning_effort` + reaches the wire only on the exact first-party `https://api.x.ai/v1` route, + and the usage-aware 200K-token pricing boundary is scoped to direct xAI so + aggregator routes reusing the model slug cannot inherit xAI billing. +- OrcaRouter is a first-class named provider: `ORCAROUTER_API_KEY`, default base + URL `https://api.orcarouter.ai/v1`, `deepseek/deepseek-v4-pro` default, + `orcarouter/auto` routing, CLI `--provider` selector, and TUI picker entries + (#5321). + +### Changed + +- Reasoning-effort normalization and the model picker read a model's published + `reasoning_options` list from the catalog instead of collapsing every route to + the historic Low/Medium ladder. Any catalog row that publishes an effort list + keeps its own vocabulary. +- Docs record DeepSeek's live `DeepSeek-V4-Pro-0813` backend label while the + callable API ID stays `deepseek-v4-pro`. No aliases are remapped and no + `deepseek-v4-pro[1m]` selector is sent. + +### Fixed + +- Copying a user or assistant message takes its canonical content instead of + reserialized transcript lines, keeping role glyphs, continuation rails, and + visual wrapping out of the clipboard while preserving authored Unicode, + Markdown, and hard line breaks. Tool and Thinking cells stay on the existing + full-transcript path (#5319). +- `load_session` no longer runs crash recovery on every read. Snapshot reads go + through a side-effect-free `load_session_snapshot` and recovery is explicit + via `recover_session_for_resume`, so an embedding host inspecting a durable + session while a tool is still running no longer gets a spurious crash repair + (#5320). + +### Security + +- `lru` moves to 0.18 to clear RUSTSEC-2026-0253, where `LruCache::pop()` was + not panic-safe and could leave dangling list pointers. The `ratatui-core` + `=0.1.0` pin that transitively forced `lru` ^0.16 is lifted, so + `ColorCompatBackend` now answers `get_cursor_position()` from tracked cursor + state — the upstream-recommended workaround for the startup CPR race + (ratatui/ratatui#2483, ratatui/ratatui#2640) that the pin originally worked + around. `ratatui` itself stays pinned at `=0.30.0`, so the API surface is + unchanged. + +### Known issues + +- The integration test + `exec_persistent_service::failed_exec_kills_pending_service_and_exits_nonzero` + is a confirmed flake under parallel load ("service pid file never appeared"). + It passes in isolation and is unrelated to any v0.9.7 change. + +### Contributors + +- XhesicaFrost (@XhesicaFrost) — canonical message copy (#5319). +- h3c-hexin (@h3c-hexin) — session snapshot and crash-recovery split (#5320). +- XiaoHuo888-hue (@XiaoHuo888-hue) — OrcaRouter provider registration (#5321). ## [0.9.6] - 2026-08-11 @@ -5453,7 +5514,8 @@ overflow report and `/theme` picker edge-wrapping patch in #1814. Older releases (v0.8.39 and earlier) are archived in [docs/CHANGELOG_ARCHIVE.md](docs/CHANGELOG_ARCHIVE.md). -[Unreleased]: https://github.com/Hmbown/CodeWhale/compare/v0.9.6...HEAD +[Unreleased]: https://github.com/Hmbown/CodeWhale/compare/v0.9.7...HEAD +[0.9.7]: https://github.com/Hmbown/CodeWhale/compare/v0.9.6...v0.9.7 [0.9.6]: https://github.com/Hmbown/CodeWhale/compare/v0.9.5...v0.9.6 [0.9.5]: https://github.com/Hmbown/CodeWhale/compare/v0.9.4...v0.9.5 [0.9.4]: https://github.com/Hmbown/CodeWhale/compare/v0.9.3...v0.9.4 diff --git a/Cargo.lock b/Cargo.lock index a09313e06..d3368aaf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "codewhale-agent" -version = "0.9.6" +version = "0.9.7" dependencies = [ "codewhale-config", "serde", @@ -765,7 +765,7 @@ dependencies = [ [[package]] name = "codewhale-app-server" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "axum", @@ -793,11 +793,11 @@ dependencies = [ [[package]] name = "codewhale-build-support" -version = "0.9.6" +version = "0.9.7" [[package]] name = "codewhale-cli" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "chrono", @@ -837,7 +837,7 @@ dependencies = [ [[package]] name = "codewhale-config" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "codewhale-execpolicy", @@ -857,7 +857,7 @@ dependencies = [ [[package]] name = "codewhale-core" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "async-trait", @@ -882,7 +882,7 @@ dependencies = [ [[package]] name = "codewhale-execpolicy" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "codewhale-protocol", @@ -891,7 +891,7 @@ dependencies = [ [[package]] name = "codewhale-hooks" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "async-trait", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "codewhale-lane" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "chrono", @@ -921,7 +921,7 @@ dependencies = [ [[package]] name = "codewhale-mcp" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "serde", @@ -931,14 +931,14 @@ dependencies = [ [[package]] name = "codewhale-paths" -version = "0.9.6" +version = "0.9.7" dependencies = [ "dirs", ] [[package]] name = "codewhale-protocol" -version = "0.9.6" +version = "0.9.7" dependencies = [ "chrono", "serde", @@ -948,7 +948,7 @@ dependencies = [ [[package]] name = "codewhale-release" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "reqwest 0.13.4", @@ -962,7 +962,7 @@ dependencies = [ [[package]] name = "codewhale-secrets" -version = "0.9.6" +version = "0.9.7" dependencies = [ "chrono", "codewhale-paths", @@ -977,7 +977,7 @@ dependencies = [ [[package]] name = "codewhale-state" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "chrono", @@ -992,7 +992,7 @@ dependencies = [ [[package]] name = "codewhale-telemetry" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "chrono", @@ -1012,7 +1012,7 @@ dependencies = [ [[package]] name = "codewhale-tools" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "async-trait", @@ -1026,7 +1026,7 @@ dependencies = [ [[package]] name = "codewhale-tui" -version = "0.9.6" +version = "0.9.7" dependencies = [ "ahash", "anyhow", @@ -1119,7 +1119,7 @@ dependencies = [ [[package]] name = "codewhale-workflow" -version = "0.9.6" +version = "0.9.7" dependencies = [ "serde", "serde_json", @@ -1131,7 +1131,7 @@ dependencies = [ [[package]] name = "codewhale-workflow-js" -version = "0.9.6" +version = "0.9.7" dependencies = [ "async-trait", "jsonschema", diff --git a/Cargo.toml b/Cargo.toml index c651efc53..87858ca8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ default-members = ["crates/cli"] resolver = "2" [workspace.package] -version = "0.9.6" +version = "0.9.7" edition = "2024" # Rust 1.88 stabilized `let_chains` in `if`/`while` conditions, which the # codebase relies on extensively. Cargo enforces this so users on older diff --git a/crates/agent/Cargo.toml b/crates/agent/Cargo.toml index 46e339386..4e0d44f28 100644 --- a/crates/agent/Cargo.toml +++ b/crates/agent/Cargo.toml @@ -8,5 +8,5 @@ repository.workspace = true description = "Model/provider registry and fallback strategy for Codewhale" [dependencies] -codewhale-config = { path = "../config", version = "0.9.6" } +codewhale-config = { path = "../config", version = "0.9.7" } serde.workspace = true diff --git a/crates/app-server/Cargo.toml b/crates/app-server/Cargo.toml index f6c389439..8125cbfdc 100644 --- a/crates/app-server/Cargo.toml +++ b/crates/app-server/Cargo.toml @@ -12,16 +12,16 @@ autobins = false [dependencies] anyhow.workspace = true axum.workspace = true -codewhale-agent = { path = "../agent", version = "0.9.6" } -codewhale-config = { path = "../config", version = "0.9.6" } -codewhale-core = { path = "../core", version = "0.9.6" } -codewhale-execpolicy = { path = "../execpolicy", version = "0.9.6" } -codewhale-hooks = { path = "../hooks", version = "0.9.6" } -codewhale-mcp = { path = "../mcp", version = "0.9.6" } -codewhale-protocol = { path = "../protocol", version = "0.9.6" } -codewhale-release = { path = "../release", version = "0.9.6" } -codewhale-state = { path = "../state", version = "0.9.6" } -codewhale-tools = { path = "../tools", version = "0.9.6" } +codewhale-agent = { path = "../agent", version = "0.9.7" } +codewhale-config = { path = "../config", version = "0.9.7" } +codewhale-core = { path = "../core", version = "0.9.7" } +codewhale-execpolicy = { path = "../execpolicy", version = "0.9.7" } +codewhale-hooks = { path = "../hooks", version = "0.9.7" } +codewhale-mcp = { path = "../mcp", version = "0.9.7" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } +codewhale-release = { path = "../release", version = "0.9.7" } +codewhale-state = { path = "../state", version = "0.9.7" } +codewhale-tools = { path = "../tools", version = "0.9.7" } serde.workspace = true serde_json.workspace = true rustls.workspace = true diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 037b2beeb..cbcf4f42c 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -15,19 +15,19 @@ path = "src/main.rs" anyhow.workspace = true clap.workspace = true clap_complete.workspace = true -codewhale-tui = { path = "../tui", version = "0.9.6" } -codewhale-agent = { path = "../agent", version = "0.9.6" } -codewhale-app-server = { path = "../app-server", version = "0.9.6" } -codewhale-config = { path = "../config", version = "0.9.6" } -codewhale-lane = { path = "../lane", version = "0.9.6" } -codewhale-workflow = { path = "../workflow", version = "0.9.6" } -codewhale-execpolicy = { path = "../execpolicy", version = "0.9.6" } -codewhale-mcp = { path = "../mcp", version = "0.9.6" } -codewhale-paths = { path = "../paths", version = "0.9.6" } -codewhale-release = { path = "../release", version = "0.9.6" } -codewhale-secrets = { path = "../secrets", version = "0.9.6" } -codewhale-state = { path = "../state", version = "0.9.6" } -codewhale-telemetry = { path = "../telemetry", version = "0.9.6" } +codewhale-tui = { path = "../tui", version = "0.9.7" } +codewhale-agent = { path = "../agent", version = "0.9.7" } +codewhale-app-server = { path = "../app-server", version = "0.9.7" } +codewhale-config = { path = "../config", version = "0.9.7" } +codewhale-lane = { path = "../lane", version = "0.9.7" } +codewhale-workflow = { path = "../workflow", version = "0.9.7" } +codewhale-execpolicy = { path = "../execpolicy", version = "0.9.7" } +codewhale-mcp = { path = "../mcp", version = "0.9.7" } +codewhale-paths = { path = "../paths", version = "0.9.7" } +codewhale-release = { path = "../release", version = "0.9.7" } +codewhale-secrets = { path = "../secrets", version = "0.9.7" } +codewhale-state = { path = "../state", version = "0.9.7" } +codewhale-telemetry = { path = "../telemetry", version = "0.9.7" } chrono.workspace = true console = "0.16.3" dirs.workspace = true @@ -45,7 +45,7 @@ webbrowser = "1.0" zeroize = "1.8.2" [build-dependencies] -codewhale-build-support = { path = "../build-support", version = "0.9.6" } +codewhale-build-support = { path = "../build-support", version = "0.9.7" } # Parent-death cleanup for delegated server children (#3259): on Linux the # dispatcher sets PR_SET_PDEATHSIG so the child is signalled if the dispatcher diff --git a/crates/config/Cargo.toml b/crates/config/Cargo.toml index e50eb8da9..a6b4f1597 100644 --- a/crates/config/Cargo.toml +++ b/crates/config/Cargo.toml @@ -9,9 +9,9 @@ description = "Config schema and precedence model for Codewhale" [dependencies] anyhow.workspace = true -codewhale-execpolicy = { path = "../execpolicy", version = "0.9.6" } -codewhale-paths = { path = "../paths", version = "0.9.6" } -codewhale-secrets = { path = "../secrets", version = "0.9.6" } +codewhale-execpolicy = { path = "../execpolicy", version = "0.9.7" } +codewhale-paths = { path = "../paths", version = "0.9.7" } +codewhale-secrets = { path = "../secrets", version = "0.9.7" } fd-lock = "4.0.4" libc = "0.2" serde.workspace = true diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 5259e5805..69da4900b 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -13,14 +13,14 @@ chrono.workspace = true serde.workspace = true thiserror.workspace = true tokio-util.workspace = true -codewhale-agent = { path = "../agent", version = "0.9.6" } -codewhale-config = { path = "../config", version = "0.9.6" } -codewhale-execpolicy = { path = "../execpolicy", version = "0.9.6" } -codewhale-hooks = { path = "../hooks", version = "0.9.6" } -codewhale-mcp = { path = "../mcp", version = "0.9.6" } -codewhale-protocol = { path = "../protocol", version = "0.9.6" } -codewhale-state = { path = "../state", version = "0.9.6" } -codewhale-tools = { path = "../tools", version = "0.9.6" } +codewhale-agent = { path = "../agent", version = "0.9.7" } +codewhale-config = { path = "../config", version = "0.9.7" } +codewhale-execpolicy = { path = "../execpolicy", version = "0.9.7" } +codewhale-hooks = { path = "../hooks", version = "0.9.7" } +codewhale-mcp = { path = "../mcp", version = "0.9.7" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } +codewhale-state = { path = "../state", version = "0.9.7" } +codewhale-tools = { path = "../tools", version = "0.9.7" } serde_json = { workspace = true, features = ["preserve_order"] } tokio = { workspace = true, features = ["time"] } tracing.workspace = true diff --git a/crates/execpolicy/Cargo.toml b/crates/execpolicy/Cargo.toml index 46485db44..8be4a051a 100644 --- a/crates/execpolicy/Cargo.toml +++ b/crates/execpolicy/Cargo.toml @@ -9,5 +9,5 @@ description = "Execution policy and approval model for Codewhale" [dependencies] anyhow.workspace = true -codewhale-protocol = { path = "../protocol", version = "0.9.6" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } serde.workspace = true diff --git a/crates/hooks/Cargo.toml b/crates/hooks/Cargo.toml index 712f82f9a..de351e111 100644 --- a/crates/hooks/Cargo.toml +++ b/crates/hooks/Cargo.toml @@ -11,8 +11,8 @@ description = "Hook dispatch and notifications support for Codewhale" anyhow.workspace = true async-trait.workspace = true chrono.workspace = true -codewhale-protocol = { path = "../protocol", version = "0.9.6" } -codewhale-release = { path = "../release", version = "0.9.6" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } +codewhale-release = { path = "../release", version = "0.9.7" } reqwest.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/crates/lane/Cargo.toml b/crates/lane/Cargo.toml index 57a54c4c6..d9147b9db 100644 --- a/crates/lane/Cargo.toml +++ b/crates/lane/Cargo.toml @@ -10,7 +10,7 @@ description = "Lane registry and Runtime backends for Codewhale workflow instanc [dependencies] anyhow.workspace = true chrono.workspace = true -codewhale-config = { path = "../config", version = "0.9.6" } +codewhale-config = { path = "../config", version = "0.9.7" } fd-lock = "4.0.4" serde.workspace = true serde_json.workspace = true diff --git a/crates/secrets/Cargo.toml b/crates/secrets/Cargo.toml index 8793faf23..567447286 100644 --- a/crates/secrets/Cargo.toml +++ b/crates/secrets/Cargo.toml @@ -8,7 +8,7 @@ repository.workspace = true description = "Secret storage backends for Codewhale, with OS keyring and file fallback" [dependencies] -codewhale-paths = { path = "../paths", version = "0.9.6" } +codewhale-paths = { path = "../paths", version = "0.9.7" } chrono.workspace = true serde = { workspace = true } serde_json = { workspace = true } diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index e39f614a1..52dbae4e6 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -10,8 +10,8 @@ description = "Session/thread persistence and recovery model for Codewhale" [dependencies] anyhow.workspace = true chrono.workspace = true -codewhale-paths = { path = "../paths", version = "0.9.6" } -codewhale-protocol = { path = "../protocol", version = "0.9.6" } +codewhale-paths = { path = "../paths", version = "0.9.7" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } fd-lock = "4.0.4" rusqlite.workspace = true serde.workspace = true diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index eb4d62d8c..3e7ee8e30 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -10,9 +10,9 @@ description = "Anonymous, user-disableable product usage counting for Codewhale" [dependencies] anyhow.workspace = true chrono.workspace = true -codewhale-config = { path = "../config", version = "0.9.6" } -codewhale-paths = { path = "../paths", version = "0.9.6" } -codewhale-release = { path = "../release", version = "0.9.6" } +codewhale-config = { path = "../config", version = "0.9.7" } +codewhale-paths = { path = "../paths", version = "0.9.7" } +codewhale-release = { path = "../release", version = "0.9.7" } fd-lock = "4.0.4" reqwest = { workspace = true, features = ["blocking"] } serde.workspace = true @@ -22,9 +22,9 @@ tracing.workspace = true uuid.workspace = true [build-dependencies] -codewhale-build-support = { path = "../build-support", version = "0.9.6" } +codewhale-build-support = { path = "../build-support", version = "0.9.7" } [dev-dependencies] # Used as an *assertion*, never as a filter: every string leaf of a serialized # batch is run through `redact_for_disclosure` and must come back unredacted. -codewhale-workflow = { path = "../workflow", version = "0.9.6" } +codewhale-workflow = { path = "../workflow", version = "0.9.7" } diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml index 5425d9019..8516b6302 100644 --- a/crates/tools/Cargo.toml +++ b/crates/tools/Cargo.toml @@ -10,7 +10,7 @@ description = "Tool invocation lifecycle, schema validation, and scheduler paral [dependencies] anyhow.workspace = true async-trait.workspace = true -codewhale-protocol = { path = "../protocol", version = "0.9.6" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } serde.workspace = true serde_json.workspace = true thiserror.workspace = true diff --git a/crates/tui/CHANGELOG.md b/crates/tui/CHANGELOG.md index ca8b92e76..abb7dd89e 100644 --- a/crates/tui/CHANGELOG.md +++ b/crates/tui/CHANGELOG.md @@ -7,12 +7,74 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.9.7] - 2026-08-12 + +Codewhale v0.9.7 keeps the catalog ordinary. Grok 4.6 lands as a normal catalog +row instead of a provider-shaped pile of special cases, OrcaRouter joins as a +named provider, and a panic-safety advisory in `lru` is cleared by lifting the +pin that caused it rather than living around it. + ### Added -- Add Grok 4.6 to the direct xAI picker as the default, including its official - reasoning efforts, image-input capability, 500K context, native web search, - and long-context pricing tier; retain `deepseek-v4-pro` as the API ID for - DeepSeek's live V4-Pro-0813 backend. +- Grok 4.6 is the direct xAI default, with the `grok` alias moving onto it and + `grok-4.5` still explicitly selectable. Its 500K context, text/image input, + tool and structured-output support, `low`/`medium`/`high`/`xhigh` reasoning + efforts (default `high`), and server-side web search all come from the + Models.dev-shaped catalog rather than model-specific code. `reasoning_effort` + reaches the wire only on the exact first-party `https://api.x.ai/v1` route, + and the usage-aware 200K-token pricing boundary is scoped to direct xAI so + aggregator routes reusing the model slug cannot inherit xAI billing. +- OrcaRouter is a first-class named provider: `ORCAROUTER_API_KEY`, default base + URL `https://api.orcarouter.ai/v1`, `deepseek/deepseek-v4-pro` default, + `orcarouter/auto` routing, CLI `--provider` selector, and TUI picker entries + (#5321). + +### Changed + +- Reasoning-effort normalization and the model picker read a model's published + `reasoning_options` list from the catalog instead of collapsing every route to + the historic Low/Medium ladder. Any catalog row that publishes an effort list + keeps its own vocabulary. +- Docs record DeepSeek's live `DeepSeek-V4-Pro-0813` backend label while the + callable API ID stays `deepseek-v4-pro`. No aliases are remapped and no + `deepseek-v4-pro[1m]` selector is sent. + +### Fixed + +- Copying a user or assistant message takes its canonical content instead of + reserialized transcript lines, keeping role glyphs, continuation rails, and + visual wrapping out of the clipboard while preserving authored Unicode, + Markdown, and hard line breaks. Tool and Thinking cells stay on the existing + full-transcript path (#5319). +- `load_session` no longer runs crash recovery on every read. Snapshot reads go + through a side-effect-free `load_session_snapshot` and recovery is explicit + via `recover_session_for_resume`, so an embedding host inspecting a durable + session while a tool is still running no longer gets a spurious crash repair + (#5320). + +### Security + +- `lru` moves to 0.18 to clear RUSTSEC-2026-0253, where `LruCache::pop()` was + not panic-safe and could leave dangling list pointers. The `ratatui-core` + `=0.1.0` pin that transitively forced `lru` ^0.16 is lifted, so + `ColorCompatBackend` now answers `get_cursor_position()` from tracked cursor + state — the upstream-recommended workaround for the startup CPR race + (ratatui/ratatui#2483, ratatui/ratatui#2640) that the pin originally worked + around. `ratatui` itself stays pinned at `=0.30.0`, so the API surface is + unchanged. + +### Known issues + +- The integration test + `exec_persistent_service::failed_exec_kills_pending_service_and_exits_nonzero` + is a confirmed flake under parallel load ("service pid file never appeared"). + It passes in isolation and is unrelated to any v0.9.7 change. + +### Contributors + +- XhesicaFrost (@XhesicaFrost) — canonical message copy (#5319). +- h3c-hexin (@h3c-hexin) — session snapshot and crash-recovery split (#5320). +- XiaoHuo888-hue (@XiaoHuo888-hue) — OrcaRouter provider registration (#5321). ## [0.9.6] - 2026-08-11 @@ -3405,97 +3467,6 @@ recorded in this changelog. Crediting them now, with the version they shipped in - `ExternalTool` abstraction layer — thanks @aboimpinto (#1794, #2294, v0.8.48) - Ephemeral generated project context — thanks @Final527 (report) (#3058, v0.8.59) -## [0.8.61] - 2026-06-15 - -This release lands the **runtime control plane** for multi-agent work: the TUI stays -responsive while sub-agents run, sub-agents converge toward fleet-style durable workers -with per-role model routing, and provider/model routes are isolated per session. It also -folds in several community contributions. - -### Added - -- **WhaleFlow runtime foundations** — worker runtime profiles (role / permissions / shell / - tools / model-route, with non-escalating child derivation), a cross-provider model registry - with offline catalog hydration, and provider-readiness / context-budget / provider-adapter / - resource-telemetry services. (#3217, #3071, #3072, #3073) -- **Per-role, heterogeneous-model sub-agent routing** — sub-agents can be assigned a model and - provider per role (e.g. scout vs. synthesis; verifiers route to a fast model). (#2027, #1768) -- **Durable goal mode** — cross-turn goal progress with token/time accounting and a - verifier-as-judge gate before a goal may complete. (#3215, #891, #1976, #2058, #2029) -- Parent-visible worker interaction contract — a recommended action per worker. (#3226) -- Maintainer GitHub workflow skills; ACP registry submission prepared. (#3192) -- OpenAI-compatible `/v1/chat/completions` endpoint on the legacy app-server HTTP transport, - provider-neutral, with model registry resolution and configured-credential forwarding. - -### Changed - -- **Sub-agents converge toward fleet-style durable workers** — real worker lifecycle states are - projected to the sidebar instead of a hardcoded "running", and a sub-agent returns a structured - needs-input checkpoint instead of parking. (#3226, #3096, #3154) -- The per-turn runtime tag exposes capability posture instead of human-facing mode labels. (#3213) -- Independent shell and verifier work defaults to background jobs with nonblocking waits and a - completion notification; blocking now requires an explicit wait. (#3212) -- Sub-agent launches now expose explicit `model_strength` and `thinking` controls to the model - instead of hidden child-model auto-routing; `explore` work is documented as a good fit for - faster models and `thinking: "off"`. -- Plan mode is strictly read-only (no shell tools), consistent with its runtime posture. -- `/swarm` is gated behind the durable worker substrate. (#3218) -- Legacy `deepseek` install/update path resolves to `codewhale`. (#2960, #2924, #2917) - -### Fixed - -- **TUI freeze when multiple sub-agents spawn (launch blocker)** — the terminal input pump runs - off the render thread, AgentProgress events are coalesced, and sub-agents no longer park on - input with no orchestrator to answer; a six-worker stress test guards input/render/cancel - liveness. (#3216, #3096) -- Idle sub-agent completion notifications now resume the parent turn instead of waiting for a - later user message; thanks @giovanni-paolilla for the deadlock report (#3266). -- **Provider/model route isolation** — provider and model state is session-local, and a - mismatched provider+model tuple is rejected at the route boundary. (#3227) -- Route-effective context-window metadata, over-limit preflight, and bounded recovery from - `context_length_exceeded` instead of re-looping. (#3204) -- Synchronous tools (`file_search`, `grep_files`, `list_dir`) are cancellable and no longer hold - a turn open against cancellation. (#1791) -- MCP stdio proxy startup prompts no longer strand YOLO / non-interactive runs. (#2475) -- Stalled / failed background-shell recovery; configurable sub-agent API timeout. (#1737, #1786, #1806) -- Composer: reliable queued steering + Ctrl+S send (#3203, #3224); footer busy/idle indicator - (#2982); CJK word-wrap (#963); clickable sidebar stop targets (#3028); live token throughput - (#3190); auto-expiring terminal sub-agent cards (#3078). -- Linux glibc preflight in the installer/update path with a clear error. (#3207, #1067) -- Self-update retries transient GitHub metadata/asset failures and falls back from the GitHub - REST API to the public `releases/latest` redirect before constructing release asset URLs. (#3232) -- Provider picker lists providers in neutral alphabetical order instead of hard-coding DeepSeek first; the active provider stays pre-selected. (#3076) -- Work sidebar no longer shows stale `phase now:` / `phase next:` strategy rows once the checklist - is 100% complete. -- Plan mode no longer shortcuts investigation for requests that name a repository, URL, version, - release, build state, bug, PR, issue, API surface, or local code path. -- Oversized pasted text stays editable in the composer, with a file backup appended at submit - time for model access; thanks @idling11 (#3267, closes #3263). -- Bare digit keys `1`-`8` now insert text instead of firing hotbar slots; use `Alt+digit` for - hotbar actions. Thanks @wjq2026 for the report and @DieMoe233 for the paste-path note (#3243). -- Kimi/Moonshot tool schemas normalize empty function parameters to a root object schema; thanks - @jghwwnq for the provider repro (#3265). -- Novita defaults to its OpenAI-compatible `/openai/v1` endpoint so chat completions no longer - 404 out of the box; thanks @buko for the report and endpoint verification (#3255). -- Dependency security: `ws` pinned to 8.21.0 across npm packages to close remote memory-exhaustion - DoS (dependabot). - -### Community contributions - -- Non-DeepSeek model pricing — thanks @mvanhorn (#3201) -- Telegram polling transport — thanks @cyq1017 (#3195) -- Mobile event history — thanks @RobertEmprechtinger (#3220) -- Runtime-API session save — thanks @gaord (#3199) -- Whale-accent rename — thanks @nightt5879 (#3197) -- `DEEPSEEK_BASE_URL` / `MODEL` honored in `exec` — thanks @hongchen1993 (#3221) -- VS Code read-only API documentation — thanks @cyq1017 (#3013) -- Atomic ask-only permission rule persistence — thanks @greyfreedom (#3233) -- DeepInfra provider support and release-surface follow-through — thanks @idling11 (#3235, closes #3231) and @nightt5879 (#3236) -- Editable oversized paste composer flow — thanks @idling11 (#3267, closes #3263) -- WeChat bridge (`integrations/weixin-bridge` via Feishu + Tencent OpenClaw) — thanks @VincentCorleone (#3206) -- Config robustness: atomic permission-rule save, one-time config `.bak` backup before the first changed write, `CODEWHALE_HOME` as primary config home, and accepting the dispatcher-written config shape (camelCase aliases + `[features.enabled]` table) so legacy/dual-written configs parse cleanly -- Dependency/CI bumps: docker login/qemu actions, softprops gh-release, download-artifact, vitest, @opennextjs/cloudflare, form-data, js-yaml, dompurify, ws - --- Older releases: [CHANGELOG.md](https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md) and [docs/CHANGELOG_ARCHIVE.md](https://github.com/Hmbown/CodeWhale/blob/main/docs/CHANGELOG_ARCHIVE.md). diff --git a/crates/tui/Cargo.toml b/crates/tui/Cargo.toml index 6d17fc8d3..4853ccef7 100644 --- a/crates/tui/Cargo.toml +++ b/crates/tui/Cargo.toml @@ -27,18 +27,18 @@ path = "src/main.rs" [dependencies] ahash = "0.8" anyhow.workspace = true -codewhale-config = { path = "../config", version = "0.9.6" } -codewhale-core = { path = "../core", version = "0.9.6" } -codewhale-execpolicy = { path = "../execpolicy", version = "0.9.6" } -codewhale-lane = { path = "../lane", version = "0.9.6" } -codewhale-paths = { path = "../paths", version = "0.9.6" } -codewhale-protocol = { path = "../protocol", version = "0.9.6" } -codewhale-release = { path = "../release", version = "0.9.6" } -codewhale-secrets = { path = "../secrets", version = "0.9.6" } -codewhale-telemetry = { path = "../telemetry", version = "0.9.6" } -codewhale-tools = { path = "../tools", version = "0.9.6" } -codewhale-workflow = { path = "../workflow", version = "0.9.6" } -codewhale-workflow-js = { path = "../workflow-js", version = "0.9.6" } +codewhale-config = { path = "../config", version = "0.9.7" } +codewhale-core = { path = "../core", version = "0.9.7" } +codewhale-execpolicy = { path = "../execpolicy", version = "0.9.7" } +codewhale-lane = { path = "../lane", version = "0.9.7" } +codewhale-paths = { path = "../paths", version = "0.9.7" } +codewhale-protocol = { path = "../protocol", version = "0.9.7" } +codewhale-release = { path = "../release", version = "0.9.7" } +codewhale-secrets = { path = "../secrets", version = "0.9.7" } +codewhale-telemetry = { path = "../telemetry", version = "0.9.7" } +codewhale-tools = { path = "../tools", version = "0.9.7" } +codewhale-workflow = { path = "../workflow", version = "0.9.7" } +codewhale-workflow-js = { path = "../workflow-js", version = "0.9.7" } schemaui = { version = "0.12.0", default-features = false, optional = true } async-stream = "0.3.6" async-trait.workspace = true @@ -107,7 +107,7 @@ shell-words = "1.1.1" mimalloc.workspace = true [build-dependencies] -codewhale-build-support = { path = "../build-support", version = "0.9.6" } +codewhale-build-support = { path = "../build-support", version = "0.9.7" } [dev-dependencies] cucumber = "0.23.0" diff --git a/docs/public-surface-facts.json b/docs/public-surface-facts.json index 2781d3f5b..deafc3aa6 100644 --- a/docs/public-surface-facts.json +++ b/docs/public-surface-facts.json @@ -20,7 +20,7 @@ ] }, "sourceCandidate": { - "version": "0.9.6", + "version": "0.9.7", "providerCount": 42, "toolCount": 74, "sandboxBackends": [ diff --git a/extensions/vscode/package-lock.json b/extensions/vscode/package-lock.json index 670bb9020..f7ad74dcc 100644 --- a/extensions/vscode/package-lock.json +++ b/extensions/vscode/package-lock.json @@ -1,12 +1,12 @@ { "name": "codewhale-vscode", - "version": "0.9.6", + "version": "0.9.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codewhale-vscode", - "version": "0.9.6", + "version": "0.9.7", "license": "MIT", "devDependencies": { "@types/node": "^20.19.27", diff --git a/extensions/vscode/package.json b/extensions/vscode/package.json index ebad6ed34..eeea3e036 100644 --- a/extensions/vscode/package.json +++ b/extensions/vscode/package.json @@ -2,7 +2,7 @@ "name": "codewhale-vscode", "displayName": "CodeWhale", "description": "Official CodeWhale VS Code integration scaffold for local runtime attach and terminal launch.", - "version": "0.9.6", + "version": "0.9.7", "publisher": "codewhale", "license": "MIT", "repository": { diff --git a/npm/codewhale/package.json b/npm/codewhale/package.json index cc945c804..0a33dfb1d 100644 --- a/npm/codewhale/package.json +++ b/npm/codewhale/package.json @@ -1,7 +1,7 @@ { "name": "codewhale", - "version": "0.9.6", - "codewhaleBinaryVersion": "0.9.6", + "version": "0.9.7", + "codewhaleBinaryVersion": "0.9.7", "description": "Terminal coding agent for supported hosted and local models. One runtime on your machine. Rust, MIT.", "author": "Hmbown", "license": "MIT", diff --git a/npm/runtime-sdk/package.json b/npm/runtime-sdk/package.json index 31991ad3f..226da99d2 100644 --- a/npm/runtime-sdk/package.json +++ b/npm/runtime-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@codewhale/runtime-sdk", - "version": "0.9.6", + "version": "0.9.7", "description": "Typed JavaScript helpers for Codewhale Runtime API Fleet endpoints.", "license": "MIT", "type": "module", diff --git a/package-lock.json b/package-lock.json index 01f5f3cce..48754c0a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1559,7 +1559,7 @@ } }, "npm/codewhale": { - "version": "0.9.6", + "version": "0.9.7", "funding": [ { "type": "github", @@ -1600,7 +1600,7 @@ }, "npm/runtime-sdk": { "name": "@codewhale/runtime-sdk", - "version": "0.9.6", + "version": "0.9.7", "license": "MIT", "engines": { "node": ">=18" diff --git a/scripts/remote-smoke/setup-vm.sh b/scripts/remote-smoke/setup-vm.sh index a712562cb..8a2c0cf3d 100644 --- a/scripts/remote-smoke/setup-vm.sh +++ b/scripts/remote-smoke/setup-vm.sh @@ -20,7 +20,7 @@ # Uses prebuilt release binaries instead of a Rust build. set -euo pipefail -RELEASE_TAG="${RELEASE_TAG:-v0.9.6}" +RELEASE_TAG="${RELEASE_TAG:-v0.9.7}" REPO_URL="${REPO_URL:-https://github.com/Hmbown/CodeWhale.git}" REPO_BRANCH="${REPO_BRANCH:-main}" SECRETS_FILE="${SECRETS_FILE:-/tmp/cw-secrets.env}" diff --git a/web/lib/facts.generated.ts b/web/lib/facts.generated.ts index 9e2daa297..8d2cab6d1 100644 --- a/web/lib/facts.generated.ts +++ b/web/lib/facts.generated.ts @@ -27,10 +27,10 @@ export interface RepoFacts { } export const FACTS: RepoFacts = { - "generatedAt": "2026-08-12T09:03:56.410Z", + "generatedAt": "2026-08-13T03:52:54.997Z", "sourceRevision": null, "sourceCommittedAt": null, - "version": "0.9.6", + "version": "0.9.7", "crates": [ "agent", "app-server",