The whale-route fallback in the picker constructor used show_custom_model_row
as the gate for selecting the 'auto' vs custom row, but a known DeepSeek model
(e.g. v4-pro) paired with ReasoningEffort::Auto would not match any whale route
yet still have show_custom_model_row=false — silently landing on the auto row
and replacing the explicit model with 'auto' on apply.
Key the fallback on whether the initial model is actually 'auto' instead.
When a whale-route fallback selects the custom row, ensure show_custom_model_row
is set to true so the row is visible in the picker UI.
Also:
- Add regression test: known-model + Auto effort must not fall to auto row.
- Clean up picker_auto_model_forces_auto_effort_on_apply: remove manual
mutations of selected_model_idx / selected_effort_idx which whale-route
mode never reads.
- Rename Porpoise → Beluga per #2016, which excludes porpoises from the
user-facing whale pool.
Adds native xiaomi-mimo provider configuration, auth/env aliases, model registry entries, TUI request handling, tests, and docs. Keeps credentials in existing provider-scoped config/env/keyring paths and uses placeholders only in docs.
Resolve the prompt-layer conflict by keeping the core tool taxonomy block while routing base prompt composition through the override accessor. Tighten the override API so duplicate registrations return the rejected string, and make locale preamble/closer overrides symmetric across supported bookend locales.
Route user cells in the transcript cache through the existing user-message renderer.
The live chat view renders through lines_with_copy_metadata(), which previously
bypassed the user-message highlight path. As a result, submitted user prompts did
not show the intended full-row background in the main transcript.
Add a regression test for the transcript cache path.
The second feature-flag gate in tool_setup.rs was calling
with_shell_tools() again when allow_shell was already true, causing
duplicate tool registration. Remove the redundant gate since
with_agent_tools() already handles the allow_shell check.
Also add task_shell_wait to MODES.md alongside task_shell_start.
task_shell_start delegates to ExecShellTool, providing the same shell
execution capability as exec_shell. Previously, task_shell_start was
registered unconditionally in with_runtime_task_tools while exec_shell
was gated behind allow_shell, creating an inconsistent security gate.
This caused the model to try exec_shell first, fail, then fall back to
task_shell_start — wasting tokens and bypassing the intended security
boundary.
Split TaskShellStartTool and TaskShellWaitTool out of
with_runtime_task_tools into a new with_runtime_task_shell_tools method,
and gate both behind the allow_shell check in with_agent_tools.
Closes#2303
Two bugs in the folded-thinking rendering path:
1. Cache invalidation: changing folded_thinking did not invalidate cached
cell renders because the cell revision stayed the same. Now track
folded_cells in the cache and force re-render when it changes.
2. Index mapping: in the slow path (with collapsed cells), the cache idx
is a filtered position, but folded_cells uses original virtual indices.
Add original_index_map parameter to ensure_split so fold lookups
resolve correctly.
Added two regression tests:
- folded_thinking_cache_invalidation: verifies fold/unfold triggers re-render
- folded_thinking_with_collapsed_cells_uses_original_indices: verifies
correct fold behavior when collapsed_cells filtering is active
Change from to so Space
toggles the collapsed state relative to the global verbose flag:
- verbose off (default): thinking collapsed; Space unfolds it
- verbose on: thinking expanded; Space folds it
This lets users expand individual thinking blocks even when the global
verbose mode is off, without needing to toggle verbose for all blocks.
Closes#2074
Adds FauxStep::Factory(Box<dyn Fn(&MessageRequest) -> CannedTurn + Send + Sync>)
to MockLlmClient. When a Factory step is dequeued, its closure runs
against the real outgoing MessageRequest before the response stream is
built, so any assert! panic surfaces directly from the client call
instead of later in stream polling.
Internal storage moves from VecDeque<CannedTurn> to VecDeque<FauxStep>,
but every existing public method keeps working:
- MockLlmClient::new(Vec<CannedTurn>) wraps each turn in FauxStep::Canned.
- push_turn(CannedTurn) appends as FauxStep::Canned.
Adds push_factory(closure) for tests that want the Factory branch.
Doc comment on the Factory variant captures the DeepSeek V4
thinking-mode tool-call invariant (the v0.4.9-v0.5.1 reasoning_content
drop that produced HTTP 400 on follow-up turns).
Adds:
- crates/tui/tests/reasoning_content_replayed_after_tool_call.rs — a
regression test whose factory asserts the assistant tool-call turn
carries a Thinking content block after a thinking + tool-call round.
- An additional unit test in mock.rs covering create_message_synthesizes_from_factory_turn.
All 20 tests in the new file pass, and the existing
integration_mock_llm suite (27 tests) is unchanged.
Previously, Space on a thinking cell hid it entirely from the transcript.
Now Space toggles between folded (summary preview) and unfolded (full
content) for thinking cells, while other cells retain the existing
hide/show behavior.
Changes:
- Add folded_thinking HashSet to App for per-cell fold tracking
- Add lines_with_options_folded / lines_with_copy_metadata_folded that
accept an explicit folded flag, overriding the global verbose setting
- Update transcript cache to pass fold state during rendering
- Update Space key handler to toggle fold for thinking cells
- Update affordance text to mention Space for expanding folded thinking
Closes#2348
Adds riscv64 to build pipelines so CodeWhale ships prebuilt binaries
and npm wrappers for 64-bit RISC-V Linux (glibc) systems.
Changes:
**CI / build**
- release.yml: +2 build matrix entries (codewhale + codewhale-tui for
riscv64gc-unknown-linux-gnu), cross-compilation toolchain step using
a dedicated DEB822-format apt source for ports.ubuntu.com, bundle
step, and release-notes table row.
- nightly.yml: +2 matrix entries, matching cross-compilation setup.
- resolve job: handle workflow_dispatch when the target tag does not
yet exist (fall back to HEAD SHA).
**Packaging**
- npm/codewhale/scripts/artifacts.js: add riscv64 to ASSET_MATRIX
under linux so npm install -g codewhale resolves on RISC-V.
**Docs**
- docs/INSTALL.md: add riscv64 row to supported platforms table;
replace with clearer 'other architectures' wording.
Build strategy: cross-compile from ubuntu-latest (x86_64) using
gcc-riscv64-linux-gnu. The dbus runtime dependency (from the keyring
crate's secret-service backend) is satisfied via ports.ubuntu.com.
PKG_CONFIG_ALLOW_CROSS and a cross-target libdir are set so the
keyring crate finds dbus-1 during cross-compilation.
Docker support for linux/riscv64 is intentionally not added here:
GitHub Actions does not yet provide the infrastructure to build or
emulate riscv64 containers. The Dockerfile changes will follow when
the hosted CI surface supports it.