Full changelog in CHANGELOG.md. macOS failure is pre-existing flaky MCP network test; Windows was a CI timeout during compilation. Both unrelated to harvested changes.
Users copying text from the output area and right-clicking in the
composer expect Paste to be the first, most accessible action.
Previously Paste appeared after all cell-specific actions (Open
Details, Copy Message, etc.), requiring extra mouse travel or
keyboard navigation.
Reported by a WeChat/Chinese UX user during the v0.8.50 triage pass.
Add test plan_mode_toggle_preserves_catalog_byte_stability that verifies
three invariants critical for DeepSeek's KV prefix cache:
1. Building the tool catalog twice for the same mode produces identical
JSON bytes. This catches any non-determinism in catalog construction
(e.g., HashMap iteration order, timestamp-dependent logic).
2. Non-deferred tools common to Plan and Agent modes appear in the same
order. Plan mode excludes execution tools, but the tools that are
present in both modes must have stable byte positions so that toggling
between modes doesn't shift byte offsets of shared tools.
3. Activating a deferred tool mid-session appends to the tail without
reordering the catalog head. This is the existing invariant from #263,
now covered by a dedicated byte-level assertion.
Also add a doc comment to build_model_tool_catalog documenting the
catalog-head stability invariant.
- Comment: remove 'never auto-re-pins' (it does auto-re-freeze),
describe accurately as 'auto-re-freeze on drift'
- Perf: use as_deref().unwrap_or_default() to borrow &[Tool] for
verify(), only to_vec() when constructing PinnedPrefix
Adds a three-zone diagnostic layer alongside the existing
PrefixStabilityManager::check_and_update(). On the first turn,
freeze the PinnedPrefix baseline; on subsequent turns, verify
the current system+tool state against the frozen baseline and
log drift via tracing::debug!. Phase 2 is warn-only — no
request refusal — auto-re-freezes on drift to keep subsequent
turn comparisons meaningful.
- Session: add frozen_prefix: Option<FrozenPrefix> field
- turn_loop: import PinnedPrefix, insert verify block after
check_and_update, before MessageRequest construction
Refs #2571
Harvests the core idea from PR #2573 by @idling11, with local cleanup for normal-exit inherited pipe handles and a foreground orphan-pipe regression.
Co-authored-by: Hanmiao Li <894876246@qq.com>
Refs #2569
Harvests the safe part of PR #2569 by allowing AtlasCloud provider-hinted namespaced model IDs to route exactly as requested, without freezing a volatile provider model catalog in the static registry.
Co-authored-by: lucaszhu-hue <lucas.zhu@atlascloud.ai>
- Define UnStrStr macro for uninstaller string functions
- Use un.StrStr instead of StrStr in uninstaller context
- Rewrite un.RemoveFromPath with correct offset calculations
and semicolon handling to prevent PATH corruption
- Use dynamic version fetch from GitHub API in CLASSROOM_INSTALL.md
Closes#1983
- Add scripts/installer/codewhale.nsi: NSIS installer that installs both
codewhale.exe and codewhale-tui.exe to %LOCALAPPDATA%\Programs\CodeWhale\bin,
adds to current-user PATH, and includes an uninstaller that cleans PATH
- Add docs/CLASSROOM_INSTALL.md: step-by-step checklist for IT admins
deploying CodeWhale in labs/classrooms, covering silent install, manual
fallback, API key provisioning, imaging notes, and troubleshooting
- Update docs/INSTALL.md: add Windows NSIS Installer section referencing
the new installer and classroom checklist
When switching themes, ratatui's incremental diff engine may miss
color-only changes in sidebar cells that were rendered with
theme-resolved UiTheme fields rather than palette constants routed
through the backend remap layer. This manifests as the sidebar
retaining the previous theme's colors until a window resize or
conversation turn triggers a full repaint.
Add a force_next_full_repaint flag on App that is set whenever a
theme or background_color ConfigUpdated event is processed. The
main render loop merges this into the existing force_terminal_repaint
mechanism, which clears the terminal and redraws every cell.
The task, work, agents, and context sidebar panels were using hardcoded
palette::DEEPSEEK_SKY, palette::TEXT_MUTED, palette::STATUS_WARNING etc.
constants (Whale dark theme colors) that never change when the user
switches themes. This caused the sidebar content to remain in Whale dark
colors even after switching to Claude, Catppuccin, Dracula, or other
community themes.
Root cause:
- task_panel_lines() used palette::DEEPSEEK_SKY, TEXT_MUTED, STATUS_* etc.
- work_panel_lines() and helpers used palette::TEXT_MUTED, STATUS_* etc.
- subagent_panel_lines() used palette::DEEPSEEK_SKY, TEXT_DIM, STATUS_* etc.
- render_context_panel() used palette::DEEPSEEK_SKY, TEXT_MUTED, TEXT_DIM
- tool_status_marker() returned hardcoded palette::STATUS_* colors
- agent_status_marker() returned hardcoded palette::STATUS_* colors
Fix:
- All sidebar panel functions now accept &UiTheme and use theme fields
- task_panel_lines: uses app.ui_theme directly
- work_panel_lines: passes ui_theme to all helpers
- subagent_panel_lines: accepts theme parameter
- render_context_panel: uses app.ui_theme
- tool_status_marker/agent_status_marker: accept theme parameter
- All palette::DEEPSEEK_SKY -> theme.accent_primary
- All palette::TEXT_MUTED -> theme.text_muted
- All palette::TEXT_DIM -> theme.text_dim
- All palette::STATUS_WARNING -> theme.warning
- All palette::STATUS_SUCCESS -> theme.success
- All palette::STATUS_ERROR -> theme.error_fg
This ensures sidebar panels immediately reflect the active theme when
switching, without requiring a conversation turn to trigger a refresh.
Also creates a theme modification guide for future contributors.
Support `! <command>` and `!command` in the TUI composer to run shell commands through the existing exec_shell path.
The shortcut keeps normal approval, sandbox, policy, transcript, and work-panel handling, while avoiding model context
pollution from local-only tool results.
Refs #1546