Skip to content

chore(release): prepare v0.8.45#2118

Open
Hmbown wants to merge 3 commits into
mainfrom
work/v0.8.45-release
Open

chore(release): prepare v0.8.45#2118
Hmbown wants to merge 3 commits into
mainfrom
work/v0.8.45-release

Conversation

@Hmbown
Copy link
Copy Markdown
Owner

@Hmbown Hmbown commented May 25, 2026

Summary

Prepare CodeWhale v0.8.45 as a focused maintenance release: RLM session objects, cancellable directory/search tools, deterministic whale-species agent names, the /balance scaffold, contributor credit updates, config/runtime hardening, palette audit cleanup, and release metadata sync. Voice input and its hotkey are intentionally deferred to v0.8.46.

Changes since v0.8.44

Security

No Security changelog entries in this release.

Contributor thanks

Thanks @gaord, @zlh124, and @reidliu41 for the harvested fixes and reports credited in this release.

Local release checklist

  • ./scripts/release/check-versions.sh — passed (workspace=0.8.45, npm=0.8.45, lockfile in sync)
  • cargo fmt --all -- --check — passed
  • cargo check --workspace --all-targets --locked — passed
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings — passed
  • cargo test --workspace --all-features --locked — passed (codewhale-tui: 3342 passed; 0 failed; 3 ignored; all integration/doc tests green)
  • ./scripts/release/publish-crates.sh dry-run — passed; higher-level crates verified package contents and correctly wait for internal 0.8.45 dependencies to be published first
  • cargo build --release --locked -p codewhale-cli -p codewhale-tui — passed
  • ./target/release/codewhale --versioncodewhale 0.8.45 (b9822129968e)
  • ./target/release/codewhale-tui --versioncodewhale-tui 0.8.45 (b9822129968e)
  • node scripts/release/npm-wrapper-smoke.js — passed
  • npm --prefix web run lint — passed
  • Release surface search for Goal mode, /mode goal, voice input names, and voice hotkeys — no matches outside ignored build/cache dirs

Known issues

None documented for v0.8.45.

Copilot AI review requested due to automatic review settings May 25, 2026 09:46
Hmbown added 2 commits May 25, 2026 04:47
Replace the sequential-spawn-index whale-nickname system with a
deterministic hash-based naming scheme that maps each agent ID to a
stable whale species name. The same agent ID always gets the same
friendly name — even across session restarts for persisted agents.

- whale_name_for_id(id): hash agent ID → WHALE_NICKNAMES index
- assign_unique_whale_name(id, active_names): deterministic with
  collision avoidance, appends numeric suffix when base name is taken
- Expand WHALE_NICKNAMES from 25 to ~45 Cetacea species including
  baleen whales, toothed whales, and select dolphins (Delphinidae);
  porpoises excluded as labels that don't carry well
- SubAgent::new now accepts a pre-generated id parameter so the
  spawn method can hash it before construction
- SubAgentsView popup now shows friendly nickname next to raw agent
  ID (dimmed) instead of hiding it
- live_subagent_result accepts optional nickname parameter
- whale_nickname_for_index kept as legacy public API for test snapshots

137 sub-agent tests pass. Taxonomy source: Society for Marine
Mammalogy (2025).
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the project to version 0.8.45, introducing OpenAI model registry updates, bearer token authentication for the app server, and stricter project-level configuration overrides. UI improvements include a refreshed 'Whale' dark palette, a /balance command scaffold, cache savings displays, and deterministic sub-agent nicknames. Security and stability are enhanced through path validation for skills and the addition of timeouts to file-system tools. Review feedback highlights that background tasks for directory listing and file searching are not signaled to stop upon timeout, potentially leading to orphaned threads and resource exhaustion on large filesystems.

Comment on lines +823 to +854
async fn run_blocking_list_dir<F>(
timeout: Duration,
cancel_token: Option<CancellationToken>,
list_dir: F,
) -> Result<Vec<Value>, ToolError>
where
F: FnOnce() -> Result<Vec<Value>, ToolError> + Send + 'static,
{
if cancel_token
.as_ref()
.is_some_and(CancellationToken::is_cancelled)
{
return Err(list_dir_cancelled());
}

let task = tokio::task::spawn_blocking(list_dir);
let result = match cancel_token {
Some(token) => {
tokio::select! {
biased;
() = token.cancelled() => return Err(list_dir_cancelled()),
result = tokio::time::timeout(timeout, task) => result,
}
}
None => tokio::time::timeout(timeout, task).await,
};

ToolResult::json(&entries).map_err(|e| ToolError::execution_failed(e.to_string()))
let joined = result.map_err(|_| list_dir_timeout(timeout))?;
joined.map_err(|err| {
ToolError::execution_failed(format!("list_dir worker failed before completion: {err}"))
})?
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The spawn_blocking task for directory listing is not signaled to stop when a timeout occurs. While tokio::time::timeout correctly returns an error to the caller, the background thread running the directory walk will continue to execute until it either finishes or the turn's cancel_token is manually triggered by the user. On large or slow filesystems, this can lead to a build-up of orphaned threads. Consider creating a child cancellation token that is explicitly cancelled when the timeout expires to signal the worker to stop immediately.

Comment on lines +131 to +164
async fn run_blocking_file_search<F>(
timeout: Duration,
cancel_token: Option<CancellationToken>,
search: F,
) -> Result<Vec<FileSearchMatch>, ToolError>
where
F: FnOnce() -> Result<Vec<FileSearchMatch>, ToolError> + Send + 'static,
{
if cancel_token
.as_ref()
.is_some_and(CancellationToken::is_cancelled)
{
return Err(file_search_cancelled());
}

let task = tokio::task::spawn_blocking(search);
let result = match cancel_token {
Some(token) => {
tokio::select! {
biased;
() = token.cancelled() => return Err(file_search_cancelled()),
result = tokio::time::timeout(timeout, task) => result,
}
}
None => tokio::time::timeout(timeout, task).await,
};

let joined = result.map_err(|_| file_search_timeout(timeout))?;
joined.map_err(|err| {
ToolError::execution_failed(format!(
"file_search worker failed before completion: {err}"
))
})?
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the directory listing tool, the file search worker is not signaled to stop upon timeout. The spawn_blocking task will continue to consume resources in the background even after the TUI has reported a timeout to the user. This is particularly problematic for deep recursive searches on large volumes. The worker should be provided with a cancellation signal that triggers on both user intervention and tool-specific timeout to prevent thread pool exhaustion.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prepare CodeWhale v0.8.45 as a maintenance release, syncing version metadata while landing hardening and UX improvements across the TUI/tools/config/app-server surfaces.

Changes:

  • Release/version bumps and changelog/contributor credit updates for v0.8.45 (Cargo + npm + docs).
  • Tooling/UI improvements: cancellable list_dir/file_search, sub-agent whale nicknames + display updates, cache-savings footer hint, palette/theme audits, /balance scaffold.
  • Hardening: safer project-config overlay rules, skill install path validation, app-server HTTP auth + constrained CORS, OpenAI/Codex auth & model registry updates.

Reviewed changes

Copilot reviewed 46 out of 47 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
web/app/[locale]/faq/page.tsx Updates FAQ copy for /goal behavior.
README.md Updates contributor credits.
npm/deepseek-tui/package.json Bumps npm wrapper version to 0.8.45.
npm/codewhale/package.json Bumps package + binary pin to 0.8.45.
crates/tui/tests/palette_audit.rs Adjusts palette audit assertions to semantic tokens.
crates/tui/src/tui/views/mod.rs Sub-agent list rendering now shows nickname + id.
crates/tui/src/tui/ui/tests.rs Updates session metadata fixtures with new field(s).
crates/tui/src/tui/ui.rs Restores persisted cumulative turn duration on session load.
crates/tui/src/tui/session_picker.rs Updates session metadata fixtures with new field(s).
crates/tui/src/tui/markdown_render.rs Updates test strings to remove current-release wording.
crates/tui/src/tui/footer_ui.rs Adds cache-savings hint in footer cost display.
crates/tui/src/tui/command_palette.rs Adds “Action” section and related filtering/sorting behavior.
crates/tui/src/tui/color_compat.rs Aligns test to palette alias token.
crates/tui/src/tui/app.rs Persists cumulative turn duration; exposes last-turn cache savings.
crates/tui/src/tools/subagent/tests.rs Updates sub-agent constructor usage to accept caller-provided id.
crates/tui/src/tools/subagent/mod.rs Deterministic whale naming + unique assignment; caller-provided agent id.
crates/tui/src/tools/file.rs Makes list_dir cancellable + timeout-protected via blocking worker.
crates/tui/src/tools/file_search.rs Makes file_search cancellable + timeout-protected via blocking worker.
crates/tui/src/theme_qa_audit.rs Adds theme QA audit tests for palette completeness/contrast.
crates/tui/src/skills/install.rs Hardens skill name/path handling to prevent traversal/escape.
crates/tui/src/session_manager.rs Persists cumulative turn duration in session metadata.
crates/tui/src/pricing.rs Adds helper to estimate cache-hit savings.
crates/tui/src/palette.rs Introduces Whale palette tokens, semantic UiTheme fields, updated mappings.
crates/tui/src/models.rs Updates context-window heuristics for more OpenAI model IDs.
crates/tui/src/main.rs Wires theme QA module; tightens project overlay policy handling.
crates/tui/src/localization.rs Adds localized help text for /balance.
crates/tui/src/config.rs Adds OpenAI model list + additional OpenAI provider aliases.
crates/tui/src/commands/mod.rs Registers /balance command and adds tests.
crates/tui/src/commands/balance.rs Adds /balance scaffold behavior.
crates/tui/CHANGELOG.md Adds v0.8.45 changelog entry and compare link.
crates/tui/Cargo.toml Bumps internal crate dependency versions to 0.8.45.
crates/tools/Cargo.toml Bumps protocol dependency version to 0.8.45.
crates/hooks/Cargo.toml Bumps protocol dependency version to 0.8.45.
crates/execpolicy/Cargo.toml Bumps protocol dependency version to 0.8.45.
crates/core/Cargo.toml Bumps internal crate dependency versions to 0.8.45.
crates/config/src/lib.rs Hardens project overlay merge; adds OpenAI OAuth token sourcing + ranks.
crates/config/Cargo.toml Bumps secrets dep + adds serde_json dependency.
crates/cli/src/lib.rs Adds Codex OAuth login/status support; app-server auth/cors flags; env pass-through.
crates/cli/Cargo.toml Bumps internal crate dependency versions to 0.8.45.
crates/app-server/src/main.rs Adds auth token, insecure-no-auth, and CORS origin CLI flags.
crates/app-server/src/lib.rs Requires bearer token for HTTP routes; constrained CORS; redacts config over HTTP.
crates/app-server/Cargo.toml Bumps internal crate versions; adds uuid + dev-deps for tests.
crates/agent/src/lib.rs Expands OpenAI model registry entries + aliasing; adjusts reasoning support flags.
crates/agent/Cargo.toml Bumps config dep version to 0.8.45.
crates/tui/CHANGELOG.md Adds v0.8.45 entry mirroring root changelog.
CHANGELOG.md Adds v0.8.45 entry and compare link.
Cargo.toml Bumps workspace version to 0.8.45.
Cargo.lock Updates lockfile versions and adds new deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +838 to +842
let task = tokio::task::spawn_blocking(list_dir);
let result = match cancel_token {
Some(token) => {
tokio::select! {
biased;
Comment on lines +146 to +163
let task = tokio::task::spawn_blocking(search);
let result = match cancel_token {
Some(token) => {
tokio::select! {
biased;
() = token.cancelled() => return Err(file_search_cancelled()),
result = tokio::time::timeout(timeout, task) => result,
}
}
None => tokio::time::timeout(timeout, task).await,
};

let joined = result.map_err(|_| file_search_timeout(timeout))?;
joined.map_err(|err| {
ToolError::execution_failed(format!(
"file_search worker failed before completion: {err}"
))
})?
Comment on lines +209 to +215
pub fn whale_name_for_id(id: &str) -> String {
use std::hash::{Hash, Hasher};
let mut hasher = std::collections::hash_map::DefaultHasher::new();
id.hash(&mut hasher);
let idx = (hasher.finish() as usize) % WHALE_NICKNAMES.len();
WHALE_NICKNAMES[idx].to_string()
}
Comment on lines +229 to +233
// Deterministic suffix from the same hash to keep it stable
use std::hash::{Hash, Hasher};
let mut hasher = std::collections::hash_map::DefaultHasher::new();
id.hash(&mut hasher);
let suffix_seed = hasher.finish();
Comment on lines +1868 to +1872
let display_name = agent
.nickname
.as_deref()
.map(|nick| format!("{nick:<12}"))
.unwrap_or_else(|| format!("{id:<12}"));
@Hmbown Hmbown force-pushed the work/v0.8.45-release branch from 62d1771 to b982212 Compare May 25, 2026 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants