Merge remote-tracking branch 'origin/rebrand/r1-cargo-workspace' into work/v0.8.41-codewhale-ready

This commit is contained in:
Hunter Bown
2026-05-23 13:18:47 -05:00
40 changed files with 395 additions and 393 deletions
+2 -2
View File
@@ -92,7 +92,7 @@ jobs:
- name: Lockfile drift guard
run: git diff --exit-code -- Cargo.lock
- name: Run Offline Eval Harness
run: cargo run -p deepseek-tui --all-features -- eval
run: cargo run -p codewhale-tui --all-features -- eval
npm-wrapper-smoke:
name: npm wrapper smoke
@@ -120,7 +120,7 @@ jobs:
with:
cache-bin: false
- name: Build wrapper binaries
run: cargo build --release --locked -p deepseek-tui-cli -p deepseek-tui
run: cargo build --release --locked -p codewhale-cli -p codewhale-tui
- name: Smoke wrapper install and delegated entrypoints
run: node scripts/release/npm-wrapper-smoke.js
Generated
+232 -232
View File
@@ -801,6 +801,238 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9b18233253483ce2f65329a24072ec414db782531bdbb7d0bbc4bd2ce6b7e21"
[[package]]
name = "codewhale-agent"
version = "0.8.40"
dependencies = [
"codewhale-config",
"serde",
]
[[package]]
name = "codewhale-app-server"
version = "0.8.40"
dependencies = [
"anyhow",
"axum",
"clap",
"codewhale-agent",
"codewhale-config",
"codewhale-core",
"codewhale-execpolicy",
"codewhale-hooks",
"codewhale-mcp",
"codewhale-protocol",
"codewhale-state",
"codewhale-tools",
"serde",
"serde_json",
"tokio",
"tower-http",
]
[[package]]
name = "codewhale-cli"
version = "0.8.40"
dependencies = [
"anyhow",
"chrono",
"clap",
"clap_complete",
"codewhale-agent",
"codewhale-app-server",
"codewhale-config",
"codewhale-execpolicy",
"codewhale-mcp",
"codewhale-secrets",
"codewhale-state",
"dirs",
"reqwest",
"serde",
"serde_json",
"sha2 0.10.9",
"tempfile",
"tokio",
"tracing",
]
[[package]]
name = "codewhale-config"
version = "0.8.40"
dependencies = [
"anyhow",
"codewhale-secrets",
"dirs",
"serde",
"toml 0.9.11+spec-1.1.0",
"tracing",
]
[[package]]
name = "codewhale-core"
version = "0.8.40"
dependencies = [
"anyhow",
"chrono",
"codewhale-agent",
"codewhale-config",
"codewhale-execpolicy",
"codewhale-hooks",
"codewhale-mcp",
"codewhale-protocol",
"codewhale-state",
"codewhale-tools",
"serde_json",
"uuid",
]
[[package]]
name = "codewhale-execpolicy"
version = "0.8.40"
dependencies = [
"anyhow",
"codewhale-protocol",
"serde",
]
[[package]]
name = "codewhale-hooks"
version = "0.8.40"
dependencies = [
"anyhow",
"async-trait",
"chrono",
"codewhale-protocol",
"reqwest",
"serde",
"serde_json",
"tokio",
]
[[package]]
name = "codewhale-mcp"
version = "0.8.40"
dependencies = [
"anyhow",
"serde",
"serde_json",
]
[[package]]
name = "codewhale-protocol"
version = "0.8.40"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "codewhale-secrets"
version = "0.8.40"
dependencies = [
"dirs",
"keyring",
"serde",
"serde_json",
"tempfile",
"thiserror 2.0.17",
"tracing",
]
[[package]]
name = "codewhale-state"
version = "0.8.40"
dependencies = [
"anyhow",
"chrono",
"dirs",
"rusqlite",
"serde",
"serde_json",
]
[[package]]
name = "codewhale-tools"
version = "0.8.40"
dependencies = [
"anyhow",
"async-trait",
"codewhale-protocol",
"serde",
"serde_json",
"tokio",
"uuid",
]
[[package]]
name = "codewhale-tui"
version = "0.8.40"
dependencies = [
"anyhow",
"arboard",
"async-stream",
"async-trait",
"axum",
"base64",
"chrono",
"clap",
"clap_complete",
"codewhale-secrets",
"codewhale-tools",
"colored",
"crossterm 0.28.1",
"dirs",
"dotenvy",
"fd-lock",
"flate2",
"futures-util",
"ignore",
"image",
"libc",
"multimap",
"objc2",
"objc2-foundation",
"pdf-extract",
"portable-pty",
"pretty_assertions",
"ratatui",
"regex",
"reqwest",
"rustyline 15.0.0",
"schemars",
"schemaui",
"serde",
"serde_json",
"sha2 0.10.9",
"shellexpand",
"shlex",
"similar",
"starlark",
"tar",
"tempfile",
"thiserror 2.0.17",
"tiny_http",
"tokio",
"tokio-util",
"toml 0.9.11+spec-1.1.0",
"tower-http",
"tracing",
"tracing-appender",
"tracing-subscriber",
"unicode-segmentation",
"unicode-width 0.2.0",
"uuid",
"vt100",
"wait-timeout",
"windows",
"wiremock",
"zeroize",
]
[[package]]
name = "codewhale-tui-core"
version = "0.8.40"
[[package]]
name = "colorchoice"
version = "1.0.4"
@@ -1158,238 +1390,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "deepseek-agent"
version = "0.8.40"
dependencies = [
"deepseek-config",
"serde",
]
[[package]]
name = "deepseek-app-server"
version = "0.8.40"
dependencies = [
"anyhow",
"axum",
"clap",
"deepseek-agent",
"deepseek-config",
"deepseek-core",
"deepseek-execpolicy",
"deepseek-hooks",
"deepseek-mcp",
"deepseek-protocol",
"deepseek-state",
"deepseek-tools",
"serde",
"serde_json",
"tokio",
"tower-http",
]
[[package]]
name = "deepseek-config"
version = "0.8.40"
dependencies = [
"anyhow",
"deepseek-secrets",
"dirs",
"serde",
"toml 0.9.11+spec-1.1.0",
"tracing",
]
[[package]]
name = "deepseek-core"
version = "0.8.40"
dependencies = [
"anyhow",
"chrono",
"deepseek-agent",
"deepseek-config",
"deepseek-execpolicy",
"deepseek-hooks",
"deepseek-mcp",
"deepseek-protocol",
"deepseek-state",
"deepseek-tools",
"serde_json",
"uuid",
]
[[package]]
name = "deepseek-execpolicy"
version = "0.8.40"
dependencies = [
"anyhow",
"deepseek-protocol",
"serde",
]
[[package]]
name = "deepseek-hooks"
version = "0.8.40"
dependencies = [
"anyhow",
"async-trait",
"chrono",
"deepseek-protocol",
"reqwest",
"serde",
"serde_json",
"tokio",
]
[[package]]
name = "deepseek-mcp"
version = "0.8.40"
dependencies = [
"anyhow",
"serde",
"serde_json",
]
[[package]]
name = "deepseek-protocol"
version = "0.8.40"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "deepseek-secrets"
version = "0.8.40"
dependencies = [
"dirs",
"keyring",
"serde",
"serde_json",
"tempfile",
"thiserror 2.0.17",
"tracing",
]
[[package]]
name = "deepseek-state"
version = "0.8.40"
dependencies = [
"anyhow",
"chrono",
"dirs",
"rusqlite",
"serde",
"serde_json",
]
[[package]]
name = "deepseek-tools"
version = "0.8.40"
dependencies = [
"anyhow",
"async-trait",
"deepseek-protocol",
"serde",
"serde_json",
"tokio",
"uuid",
]
[[package]]
name = "deepseek-tui"
version = "0.8.40"
dependencies = [
"anyhow",
"arboard",
"async-stream",
"async-trait",
"axum",
"base64",
"chrono",
"clap",
"clap_complete",
"colored",
"crossterm 0.28.1",
"deepseek-secrets",
"deepseek-tools",
"dirs",
"dotenvy",
"fd-lock",
"flate2",
"futures-util",
"ignore",
"image",
"libc",
"multimap",
"objc2",
"objc2-foundation",
"pdf-extract",
"portable-pty",
"pretty_assertions",
"ratatui",
"regex",
"reqwest",
"rustyline 15.0.0",
"schemars",
"schemaui",
"serde",
"serde_json",
"sha2 0.10.9",
"shellexpand",
"shlex",
"similar",
"starlark",
"tar",
"tempfile",
"thiserror 2.0.17",
"tiny_http",
"tokio",
"tokio-util",
"toml 0.9.11+spec-1.1.0",
"tower-http",
"tracing",
"tracing-appender",
"tracing-subscriber",
"unicode-segmentation",
"unicode-width 0.2.0",
"uuid",
"vt100",
"wait-timeout",
"windows",
"wiremock",
"zeroize",
]
[[package]]
name = "deepseek-tui-cli"
version = "0.8.40"
dependencies = [
"anyhow",
"chrono",
"clap",
"clap_complete",
"deepseek-agent",
"deepseek-app-server",
"deepseek-config",
"deepseek-execpolicy",
"deepseek-mcp",
"deepseek-secrets",
"deepseek-state",
"dirs",
"reqwest",
"serde",
"serde_json",
"sha2 0.10.9",
"tempfile",
"tokio",
"tracing",
]
[[package]]
name = "deepseek-tui-core"
version = "0.8.40"
[[package]]
name = "deltae"
version = "0.3.2"
+2 -2
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-agent"
name = "codewhale-agent"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -7,5 +7,5 @@ repository.workspace = true
description = "Model/provider registry and fallback strategy for DeepSeek workspace architecture"
[dependencies]
deepseek-config = { path = "../config", version = "0.8.40" }
codewhale-config = { path = "../config", version = "0.8.40" }
serde.workspace = true
+1 -1
View File
@@ -1,6 +1,6 @@
use std::collections::HashMap;
use deepseek_config::ProviderKind;
use codewhale_config::ProviderKind;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
+10 -10
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-app-server"
name = "codewhale-app-server"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -10,15 +10,15 @@ description = "Codex-style app-server transport for DeepSeek workspace architect
anyhow.workspace = true
axum.workspace = true
clap.workspace = true
deepseek-agent = { path = "../agent", version = "0.8.40" }
deepseek-config = { path = "../config", version = "0.8.40" }
deepseek-core = { path = "../core", version = "0.8.40" }
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.40" }
deepseek-hooks = { path = "../hooks", version = "0.8.40" }
deepseek-mcp = { path = "../mcp", version = "0.8.40" }
deepseek-protocol = { path = "../protocol", version = "0.8.40" }
deepseek-state = { path = "../state", version = "0.8.40" }
deepseek-tools = { path = "../tools", version = "0.8.40" }
codewhale-agent = { path = "../agent", version = "0.8.40" }
codewhale-config = { path = "../config", version = "0.8.40" }
codewhale-core = { path = "../core", version = "0.8.40" }
codewhale-execpolicy = { path = "../execpolicy", version = "0.8.40" }
codewhale-hooks = { path = "../hooks", version = "0.8.40" }
codewhale-mcp = { path = "../mcp", version = "0.8.40" }
codewhale-protocol = { path = "../protocol", version = "0.8.40" }
codewhale-state = { path = "../state", version = "0.8.40" }
codewhale-tools = { path = "../tools", version = "0.8.40" }
serde.workspace = true
serde_json.workspace = true
tokio.workspace = true
+14 -14
View File
@@ -6,17 +6,17 @@ use anyhow::Result;
use axum::extract::State;
use axum::routing::{get, post};
use axum::{Json, Router};
use deepseek_agent::ModelRegistry;
use deepseek_config::{CliRuntimeOverrides, ConfigStore};
use deepseek_core::Runtime;
use deepseek_execpolicy::ExecPolicyEngine;
use deepseek_hooks::{HookDispatcher, JsonlHookSink, StdoutHookSink};
use deepseek_mcp::McpManager;
use deepseek_protocol::{
use codewhale_agent::ModelRegistry;
use codewhale_config::{CliRuntimeOverrides, ConfigStore};
use codewhale_core::Runtime;
use codewhale_execpolicy::ExecPolicyEngine;
use codewhale_hooks::{HookDispatcher, JsonlHookSink, StdoutHookSink};
use codewhale_mcp::McpManager;
use codewhale_protocol::{
AppRequest, AppResponse, PromptRequest, PromptResponse, ThreadRequest, ThreadResponse,
};
use deepseek_state::StateStore;
use deepseek_tools::{ToolCall, ToolRegistry};
use codewhale_state::StateStore;
use codewhale_tools::{ToolCall, ToolRegistry};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
@@ -33,7 +33,7 @@ pub struct AppServerOptions {
#[derive(Clone)]
struct AppState {
config_path: Option<PathBuf>,
config: Arc<RwLock<deepseek_config::ConfigToml>>,
config: Arc<RwLock<codewhale_config::ConfigToml>>,
runtime: Arc<Mutex<Runtime>>,
registry: ModelRegistry,
}
@@ -230,7 +230,7 @@ async fn tool_handler(
match runtime
.invoke_tool(
req.call,
deepseek_execpolicy::AskForApproval::OnRequest,
codewhale_execpolicy::AskForApproval::OnRequest,
&cwd,
)
.await
@@ -750,8 +750,8 @@ async fn process_app_request(state: &AppState, req: AppRequest) -> AppResponse {
AppRequest::ThreadLoadedList => {
let mut runtime = state.runtime.lock().await;
let response = runtime
.handle_thread(deepseek_protocol::ThreadRequest::List(
deepseek_protocol::ThreadListParams {
.handle_thread(codewhale_protocol::ThreadRequest::List(
codewhale_protocol::ThreadListParams {
include_archived: false,
limit: Some(50),
},
@@ -773,7 +773,7 @@ async fn process_app_request(state: &AppState, req: AppRequest) -> AppResponse {
}
}
async fn persist_config(state: &AppState, config: deepseek_config::ConfigToml) -> Result<()> {
async fn persist_config(state: &AppState, config: codewhale_config::ConfigToml) -> Result<()> {
if state.config_path.is_none() {
return Ok(());
}
+1 -1
View File
@@ -3,7 +3,7 @@ use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::Parser;
use deepseek_app_server::{AppServerOptions, run};
use codewhale_app_server::{AppServerOptions, run};
#[derive(Debug, Parser)]
#[command(
+8 -8
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-tui-cli"
name = "codewhale-cli"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -14,13 +14,13 @@ path = "src/main.rs"
anyhow.workspace = true
clap.workspace = true
clap_complete.workspace = true
deepseek-agent = { path = "../agent", version = "0.8.40" }
deepseek-app-server = { path = "../app-server", version = "0.8.40" }
deepseek-config = { path = "../config", version = "0.8.40" }
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.40" }
deepseek-mcp = { path = "../mcp", version = "0.8.40" }
deepseek-secrets = { path = "../secrets", version = "0.8.40" }
deepseek-state = { path = "../state", version = "0.8.40" }
codewhale-agent = { path = "../agent", version = "0.8.40" }
codewhale-app-server = { path = "../app-server", version = "0.8.40" }
codewhale-config = { path = "../config", version = "0.8.40" }
codewhale-execpolicy = { path = "../execpolicy", version = "0.8.40" }
codewhale-mcp = { path = "../mcp", version = "0.8.40" }
codewhale-secrets = { path = "../secrets", version = "0.8.40" }
codewhale-state = { path = "../state", version = "0.8.40" }
chrono.workspace = true
dirs.workspace = true
serde.workspace = true
+15 -15
View File
@@ -9,17 +9,17 @@ use std::process::Command;
use anyhow::{Context, Result, anyhow, bail};
use clap::{Args, CommandFactory, Parser, Subcommand, ValueEnum};
use clap_complete::{Shell, generate};
use deepseek_agent::ModelRegistry;
use deepseek_app_server::{
use codewhale_agent::ModelRegistry;
use codewhale_app_server::{
AppServerOptions, run as run_app_server, run_stdio as run_app_server_stdio,
};
use deepseek_config::{
use codewhale_config::{
CliRuntimeOverrides, ConfigStore, ProviderKind, ResolvedRuntimeOptions, RuntimeApiKeySource,
};
use deepseek_execpolicy::{AskForApproval, ExecPolicyContext, ExecPolicyEngine};
use deepseek_mcp::{McpServerDefinition, run_stdio_server};
use deepseek_secrets::Secrets;
use deepseek_state::{StateStore, ThreadListFilters};
use codewhale_execpolicy::{AskForApproval, ExecPolicyContext, ExecPolicyEngine};
use codewhale_mcp::{McpServerDefinition, run_stdio_server};
use codewhale_secrets::Secrets;
use codewhale_state::{StateStore, ThreadListFilters};
#[derive(Debug, Clone, Copy, ValueEnum)]
enum ProviderArg {
@@ -715,7 +715,7 @@ const PROVIDER_LIST: [ProviderKind; 11] = [
#[cfg(test)]
fn no_keyring_secrets() -> Secrets {
Secrets::new(std::sync::Arc::new(
deepseek_secrets::InMemoryKeyringStore::new(),
codewhale_secrets::InMemoryKeyringStore::new(),
))
}
@@ -2149,7 +2149,7 @@ mod tests {
#[test]
fn auth_set_writes_to_shared_config_file() {
use deepseek_secrets::{InMemoryKeyringStore, KeyringStore};
use codewhale_secrets::{InMemoryKeyringStore, KeyringStore};
use std::sync::Arc;
let nanos = chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default();
@@ -2220,7 +2220,7 @@ mod tests {
#[test]
fn auth_clear_removes_from_config() {
use deepseek_secrets::{InMemoryKeyringStore, KeyringStore};
use codewhale_secrets::{InMemoryKeyringStore, KeyringStore};
use std::sync::Arc;
let nanos = chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default();
@@ -2255,7 +2255,7 @@ mod tests {
#[test]
fn auth_status_and_list_only_probe_active_provider_keyring() {
use deepseek_secrets::{KeyringStore, SecretsError};
use codewhale_secrets::{KeyringStore, SecretsError};
use std::sync::{Arc, Mutex};
#[derive(Default)]
@@ -2307,7 +2307,7 @@ mod tests {
#[test]
fn auth_status_reports_all_active_provider_sources_with_last4() {
use deepseek_secrets::{InMemoryKeyringStore, KeyringStore};
use codewhale_secrets::{InMemoryKeyringStore, KeyringStore};
use std::sync::Arc;
let _lock = env_lock();
@@ -2345,7 +2345,7 @@ mod tests {
#[test]
fn dispatch_keyring_recovery_self_heals_into_config_file() {
use deepseek_secrets::{InMemoryKeyringStore, KeyringStore};
use codewhale_secrets::{InMemoryKeyringStore, KeyringStore};
use std::sync::Arc;
let nanos = chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default();
@@ -2418,7 +2418,7 @@ mod tests {
#[test]
fn auth_migrate_moves_plaintext_keys_into_keyring_and_strips_file() {
use deepseek_secrets::{InMemoryKeyringStore, KeyringStore};
use codewhale_secrets::{InMemoryKeyringStore, KeyringStore};
use std::sync::Arc;
let nanos = chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default();
@@ -2463,7 +2463,7 @@ mod tests {
#[test]
fn auth_migrate_dry_run_does_not_modify_anything() {
use deepseek_secrets::{InMemoryKeyringStore, KeyringStore};
use codewhale_secrets::{InMemoryKeyringStore, KeyringStore};
use std::sync::Arc;
let nanos = chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default();
+1 -1
View File
@@ -1,3 +1,3 @@
fn main() -> std::process::ExitCode {
deepseek_tui_cli::run_cli()
codewhale_cli::run_cli()
}
+2 -2
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-config"
name = "codewhale-config"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -8,7 +8,7 @@ description = "Config schema and precedence model for DeepSeek workspace archite
[dependencies]
anyhow.workspace = true
deepseek-secrets = { path = "../secrets", version = "0.8.40" }
codewhale-secrets = { path = "../secrets", version = "0.8.40" }
dirs.workspace = true
serde.workspace = true
toml.workspace = true
+18 -18
View File
@@ -6,8 +6,8 @@ use std::path::{Component, Path, PathBuf};
use std::sync::OnceLock;
use anyhow::{Context, Result, bail};
use deepseek_secrets::SecretSource;
pub use deepseek_secrets::Secrets;
use codewhale_secrets::SecretSource;
pub use codewhale_secrets::Secrets;
use serde::{Deserialize, Serialize};
#[cfg(unix)]
@@ -952,7 +952,7 @@ impl ConfigToml {
#[must_use]
pub fn resolve_runtime_options(&self, cli: &CliRuntimeOverrides) -> ResolvedRuntimeOptions {
let no_keyring = Secrets::new(std::sync::Arc::new(
deepseek_secrets::InMemoryKeyringStore::new(),
codewhale_secrets::InMemoryKeyringStore::new(),
));
self.resolve_runtime_options_with_secrets(cli, &no_keyring)
}
@@ -1014,7 +1014,7 @@ impl ConfigToml {
} else if let Some(value) = from_file.clone().filter(|v| !v.trim().is_empty()) {
(Some(value), Some(RuntimeApiKeySource::ConfigFile))
} else if should_skip_secret_store_for_provider(provider, &base_url, auth_mode.as_deref()) {
match deepseek_secrets::env_for(provider.as_str()) {
match codewhale_secrets::env_for(provider.as_str()) {
Some(value) => (Some(value), Some(RuntimeApiKeySource::Env)),
None => (None, None),
}
@@ -1420,7 +1420,7 @@ impl ConfigStore {
/// Process-wide default [`Secrets`] façade. The first caller wins; the
/// lock is exposed so test or CLI code can install an explicit
/// backend (e.g. an [`deepseek_secrets::InMemoryKeyringStore`]) before
/// backend (e.g. an [`codewhale_secrets::InMemoryKeyringStore`]) before
/// any resolver runs.
pub fn default_secrets() -> &'static Secrets {
static SECRETS: OnceLock<Secrets> = OnceLock::new();
@@ -1432,7 +1432,7 @@ pub fn default_secrets() -> &'static Secrets {
#[cfg(test)]
{
Secrets::new(std::sync::Arc::new(
deepseek_secrets::InMemoryKeyringStore::new(),
codewhale_secrets::InMemoryKeyringStore::new(),
))
}
#[cfg(not(test))]
@@ -1864,17 +1864,17 @@ mod tests {
}
}
impl deepseek_secrets::KeyringStore for RecordingSecretsStore {
fn get(&self, key: &str) -> Result<Option<String>, deepseek_secrets::SecretsError> {
impl codewhale_secrets::KeyringStore for RecordingSecretsStore {
fn get(&self, key: &str) -> Result<Option<String>, codewhale_secrets::SecretsError> {
self.gets.lock().unwrap().push(key.to_string());
Ok(self.value.clone())
}
fn set(&self, _key: &str, _value: &str) -> Result<(), deepseek_secrets::SecretsError> {
fn set(&self, _key: &str, _value: &str) -> Result<(), codewhale_secrets::SecretsError> {
Ok(())
}
fn delete(&self, _key: &str) -> Result<(), deepseek_secrets::SecretsError> {
fn delete(&self, _key: &str) -> Result<(), codewhale_secrets::SecretsError> {
Ok(())
}
@@ -2695,13 +2695,13 @@ mod tests {
#[test]
fn config_file_resolves_above_env_and_keyring() {
use deepseek_secrets::KeyringStore;
use codewhale_secrets::KeyringStore;
let _lock = env_lock();
let _env = EnvGuard::without_deepseek_runtime_overrides();
// Safety: env mutation guarded by env_lock().
unsafe { std::env::set_var("DEEPSEEK_API_KEY", "env-key") };
let store = std::sync::Arc::new(deepseek_secrets::InMemoryKeyringStore::new());
let store = std::sync::Arc::new(codewhale_secrets::InMemoryKeyringStore::new());
store.set("deepseek", "ring-key").unwrap();
let secrets = Secrets::new(store);
@@ -2728,7 +2728,7 @@ mod tests {
unsafe { std::env::set_var("DEEPSEEK_API_KEY", "env-key") };
let secrets = Secrets::new(std::sync::Arc::new(
deepseek_secrets::InMemoryKeyringStore::new(),
codewhale_secrets::InMemoryKeyringStore::new(),
));
let config = ConfigToml::default();
@@ -2747,7 +2747,7 @@ mod tests {
let _env = EnvGuard::without_deepseek_runtime_overrides();
let secrets = Secrets::new(std::sync::Arc::new(
deepseek_secrets::InMemoryKeyringStore::new(),
codewhale_secrets::InMemoryKeyringStore::new(),
));
let mut config = ConfigToml::default();
config.providers.deepseek.api_key = Some("file-key".to_string());
@@ -2763,13 +2763,13 @@ mod tests {
#[test]
fn keyring_resolves_when_config_file_empty_even_if_env_is_set() {
use deepseek_secrets::KeyringStore;
use codewhale_secrets::KeyringStore;
let _lock = env_lock();
let _env = EnvGuard::without_deepseek_runtime_overrides();
// Safety: env mutation guarded by env_lock().
unsafe { std::env::set_var("DEEPSEEK_API_KEY", "stale-env-key") };
let store = std::sync::Arc::new(deepseek_secrets::InMemoryKeyringStore::new());
let store = std::sync::Arc::new(codewhale_secrets::InMemoryKeyringStore::new());
store.set("deepseek", "ring-key").unwrap();
let secrets = Secrets::new(store);
@@ -2784,11 +2784,11 @@ mod tests {
#[test]
fn cli_flag_still_overrides_keyring() {
use deepseek_secrets::KeyringStore;
use codewhale_secrets::KeyringStore;
let _lock = env_lock();
let _env = EnvGuard::without_deepseek_runtime_overrides();
let store = std::sync::Arc::new(deepseek_secrets::InMemoryKeyringStore::new());
let store = std::sync::Arc::new(codewhale_secrets::InMemoryKeyringStore::new());
store.set("deepseek", "ring-key").unwrap();
let secrets = Secrets::new(store);
+9 -9
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-core"
name = "codewhale-core"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -9,13 +9,13 @@ description = "Core runtime boundaries for DeepSeek workspace architecture"
[dependencies]
anyhow.workspace = true
chrono.workspace = true
deepseek-agent = { path = "../agent", version = "0.8.40" }
deepseek-config = { path = "../config", version = "0.8.40" }
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.40" }
deepseek-hooks = { path = "../hooks", version = "0.8.40" }
deepseek-mcp = { path = "../mcp", version = "0.8.40" }
deepseek-protocol = { path = "../protocol", version = "0.8.40" }
deepseek-state = { path = "../state", version = "0.8.40" }
deepseek-tools = { path = "../tools", version = "0.8.40" }
codewhale-agent = { path = "../agent", version = "0.8.40" }
codewhale-config = { path = "../config", version = "0.8.40" }
codewhale-execpolicy = { path = "../execpolicy", version = "0.8.40" }
codewhale-hooks = { path = "../hooks", version = "0.8.40" }
codewhale-mcp = { path = "../mcp", version = "0.8.40" }
codewhale-protocol = { path = "../protocol", version = "0.8.40" }
codewhale-state = { path = "../state", version = "0.8.40" }
codewhale-tools = { path = "../tools", version = "0.8.40" }
serde_json.workspace = true
uuid.workspace = true
+32 -32
View File
@@ -3,27 +3,27 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use anyhow::Result;
use deepseek_agent::ModelRegistry;
use deepseek_config::{CliRuntimeOverrides, ConfigToml, ProviderKind};
use deepseek_execpolicy::{
use codewhale_agent::ModelRegistry;
use codewhale_config::{CliRuntimeOverrides, ConfigToml, ProviderKind};
use codewhale_execpolicy::{
AskForApproval, ExecApprovalRequirement, ExecPolicyContext, ExecPolicyDecision,
ExecPolicyEngine,
};
use deepseek_hooks::{HookDispatcher, HookEvent};
use deepseek_mcp::{
use codewhale_hooks::{HookDispatcher, HookEvent};
use codewhale_mcp::{
McpManager, McpStartupCompleteEvent, McpStartupStatus as McpManagerStartupStatus,
};
use deepseek_protocol::{
use codewhale_protocol::{
AppResponse, EventFrame, ExecApprovalRequestEvent, PromptRequest, PromptResponse,
ResponseChannel, ReviewDecision, Thread, ThreadForkParams, ThreadListParams, ThreadReadParams,
ThreadRequest, ThreadResponse, ThreadResumeParams, ThreadSetNameParams, ThreadStatus,
ToolPayload,
};
use deepseek_state::{
use codewhale_state::{
JobStateRecord, JobStateStatus, SessionSource, StateStore, ThreadListFilters, ThreadMetadata,
ThreadStatus as PersistedThreadStatus,
};
use deepseek_tools::{ToolCall, ToolRegistry};
use codewhale_tools::{ToolCall, ToolRegistry};
use serde_json::{Value, json};
use uuid::Uuid;
@@ -425,11 +425,11 @@ impl ThreadManager {
cwd: cwd.clone(),
cli_version: self.cli_version.clone(),
source: match source {
SessionSource::Interactive => deepseek_protocol::SessionSource::Interactive,
SessionSource::Resume => deepseek_protocol::SessionSource::Resume,
SessionSource::Fork => deepseek_protocol::SessionSource::Fork,
SessionSource::Api => deepseek_protocol::SessionSource::Api,
SessionSource::Unknown => deepseek_protocol::SessionSource::Unknown,
SessionSource::Interactive => codewhale_protocol::SessionSource::Interactive,
SessionSource::Resume => codewhale_protocol::SessionSource::Resume,
SessionSource::Fork => codewhale_protocol::SessionSource::Fork,
SessionSource::Api => codewhale_protocol::SessionSource::Api,
SessionSource::Unknown => codewhale_protocol::SessionSource::Unknown,
},
name: None,
};
@@ -1196,19 +1196,19 @@ impl Runtime {
});
for update in updates {
let status = match update.status {
McpManagerStartupStatus::Starting => deepseek_protocol::McpStartupStatus::Starting,
McpManagerStartupStatus::Ready => deepseek_protocol::McpStartupStatus::Ready,
McpManagerStartupStatus::Starting => codewhale_protocol::McpStartupStatus::Starting,
McpManagerStartupStatus::Ready => codewhale_protocol::McpStartupStatus::Ready,
McpManagerStartupStatus::Failed { error } => {
deepseek_protocol::McpStartupStatus::Failed { error }
codewhale_protocol::McpStartupStatus::Failed { error }
}
McpManagerStartupStatus::Cancelled => {
deepseek_protocol::McpStartupStatus::Cancelled
codewhale_protocol::McpStartupStatus::Cancelled
}
};
self.hooks
.emit(HookEvent::GenericEventFrame {
frame: EventFrame::McpStartupUpdate {
update: deepseek_protocol::McpStartupUpdateEvent {
update: codewhale_protocol::McpStartupUpdateEvent {
server_name: update.server_name,
status,
},
@@ -1219,12 +1219,12 @@ impl Runtime {
self.hooks
.emit(HookEvent::GenericEventFrame {
frame: EventFrame::McpStartupComplete {
summary: deepseek_protocol::McpStartupCompleteEvent {
summary: codewhale_protocol::McpStartupCompleteEvent {
ready: summary.ready.clone(),
failed: summary
.failed
.iter()
.map(|f| deepseek_protocol::McpStartupFailure {
.map(|f| codewhale_protocol::McpStartupFailure {
server_name: f.server_name.clone(),
error: f.error.clone(),
})
@@ -1422,11 +1422,11 @@ fn to_protocol_thread(thread: ThreadMetadata) -> Thread {
cwd: thread.cwd,
cli_version: thread.cli_version,
source: match thread.source {
SessionSource::Interactive => deepseek_protocol::SessionSource::Interactive,
SessionSource::Resume => deepseek_protocol::SessionSource::Resume,
SessionSource::Fork => deepseek_protocol::SessionSource::Fork,
SessionSource::Api => deepseek_protocol::SessionSource::Api,
SessionSource::Unknown => deepseek_protocol::SessionSource::Unknown,
SessionSource::Interactive => codewhale_protocol::SessionSource::Interactive,
SessionSource::Resume => codewhale_protocol::SessionSource::Resume,
SessionSource::Fork => codewhale_protocol::SessionSource::Fork,
SessionSource::Api => codewhale_protocol::SessionSource::Api,
SessionSource::Unknown => codewhale_protocol::SessionSource::Unknown,
},
name: thread.name,
}
@@ -1443,13 +1443,13 @@ fn to_persisted_status(status: &ThreadStatus) -> PersistedThreadStatus {
}
}
fn to_persisted_source(source: &deepseek_protocol::SessionSource) -> SessionSource {
fn to_persisted_source(source: &codewhale_protocol::SessionSource) -> SessionSource {
match source {
deepseek_protocol::SessionSource::Interactive => SessionSource::Interactive,
deepseek_protocol::SessionSource::Resume => SessionSource::Resume,
deepseek_protocol::SessionSource::Fork => SessionSource::Fork,
deepseek_protocol::SessionSource::Api => SessionSource::Api,
deepseek_protocol::SessionSource::Unknown => SessionSource::Unknown,
codewhale_protocol::SessionSource::Interactive => SessionSource::Interactive,
codewhale_protocol::SessionSource::Resume => SessionSource::Resume,
codewhale_protocol::SessionSource::Fork => SessionSource::Fork,
codewhale_protocol::SessionSource::Api => SessionSource::Api,
codewhale_protocol::SessionSource::Unknown => SessionSource::Unknown,
}
}
@@ -1568,7 +1568,7 @@ fn tool_payload_value(payload: &ToolPayload) -> Value {
)
}
fn tool_output_value(output: &deepseek_protocol::ToolOutput) -> Value {
fn tool_output_value(output: &codewhale_protocol::ToolOutput) -> Value {
serde_json::to_value(output).unwrap_or_else(
|_| json!({"type":"serialization_error","message":"tool output unavailable"}),
)
+2 -2
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-execpolicy"
name = "codewhale-execpolicy"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -8,5 +8,5 @@ description = "Execution policy and approval model parity for DeepSeek workspace
[dependencies]
anyhow.workspace = true
deepseek-protocol = { path = "../protocol", version = "0.8.40" }
codewhale-protocol = { path = "../protocol", version = "0.8.40" }
serde.workspace = true
+1 -1
View File
@@ -267,7 +267,7 @@ pub static BASH_ARITY_TABLE: &[(&str, u8)] = &[
/// # Example
///
/// ```rust
/// use deepseek_execpolicy::bash_arity::BashArityDict;
/// use codewhale_execpolicy::bash_arity::BashArityDict;
///
/// let dict = BashArityDict::new();
/// assert_eq!(dict.classify(&["git", "status", "-s"]), "git status");
+1 -1
View File
@@ -4,7 +4,7 @@ use std::collections::HashSet;
use anyhow::Result;
use bash_arity::BashArityDict;
use deepseek_protocol::{NetworkPolicyAmendment, NetworkPolicyRuleAction};
use codewhale_protocol::{NetworkPolicyAmendment, NetworkPolicyRuleAction};
use serde::{Deserialize, Serialize};
/// Priority layer for a permission ruleset. Higher ordinal = higher priority.
+2 -2
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-hooks"
name = "codewhale-hooks"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -10,7 +10,7 @@ description = "Hook dispatch and notifications parity for DeepSeek workspace arc
anyhow.workspace = true
async-trait.workspace = true
chrono.workspace = true
deepseek-protocol = { path = "../protocol", version = "0.8.40" }
codewhale-protocol = { path = "../protocol", version = "0.8.40" }
reqwest.workspace = true
serde.workspace = true
serde_json.workspace = true
+1 -1
View File
@@ -4,7 +4,7 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use async_trait::async_trait;
use chrono::Utc;
use deepseek_protocol::EventFrame;
use codewhale_protocol::EventFrame;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use tokio::io::AsyncWriteExt;
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-mcp"
name = "codewhale-mcp"
version.workspace = true
edition.workspace = true
license.workspace = true
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-protocol"
name = "codewhale-protocol"
version.workspace = true
edition.workspace = true
license.workspace = true
+1 -1
View File
@@ -1,4 +1,4 @@
use deepseek_protocol::{EventFrame, ThreadListParams, ThreadRequest, ThreadResumeParams};
use codewhale_protocol::{EventFrame, ThreadListParams, ThreadRequest, ThreadResumeParams};
#[test]
fn thread_resume_params_round_trip() {
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-secrets"
name = "codewhale-secrets"
version.workspace = true
edition.workspace = true
license.workspace = true
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-state"
name = "codewhale-state"
version.workspace = true
edition.workspace = true
license.workspace = true
+1 -1
View File
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use deepseek_state::{SessionSource, StateStore, ThreadListFilters, ThreadMetadata, ThreadStatus};
use codewhale_state::{SessionSource, StateStore, ThreadListFilters, ThreadMetadata, ThreadStatus};
fn temp_state_path(label: &str) -> PathBuf {
std::env::temp_dir().join(format!(
+2 -2
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-tools"
name = "codewhale-tools"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -9,7 +9,7 @@ description = "Tool invocation lifecycle, schema validation, and scheduler paral
[dependencies]
anyhow.workspace = true
async-trait.workspace = true
deepseek-protocol = { path = "../protocol", version = "0.8.40" }
codewhale-protocol = { path = "../protocol", version = "0.8.40" }
serde.workspace = true
serde_json.workspace = true
tokio.workspace = true
+1 -1
View File
@@ -5,7 +5,7 @@ use std::time::Duration;
use anyhow::Result;
use async_trait::async_trait;
use deepseek_protocol::{ToolKind, ToolOutput, ToolPayload};
use codewhale_protocol::{ToolKind, ToolOutput, ToolPayload};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use tokio::sync::RwLock;
+3 -3
View File
@@ -1,8 +1,8 @@
use std::sync::Arc;
use async_trait::async_trait;
use deepseek_protocol::{ToolKind, ToolOutput, ToolPayload};
use deepseek_tools::{
use codewhale_protocol::{ToolKind, ToolOutput, ToolPayload};
use codewhale_tools::{
ToolCall, ToolCallSource, ToolHandler, ToolInvocation, ToolRegistry, ToolSpec,
};
use serde_json::json;
@@ -22,7 +22,7 @@ impl ToolHandler for EchoHandler {
async fn handle(
&self,
invocation: ToolInvocation,
) -> std::result::Result<ToolOutput, deepseek_tools::FunctionCallError> {
) -> std::result::Result<ToolOutput, codewhale_tools::FunctionCallError> {
Ok(ToolOutput::Function {
body: Some(json!({
"tool": invocation.tool_name,
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-tui-core"
name = "codewhale-tui-core"
version.workspace = true
edition.workspace = true
license.workspace = true
+1 -1
View File
@@ -1,4 +1,4 @@
use deepseek_tui_core::{Pane, UiEvent, UiState};
use codewhale_tui_core::{Pane, UiEvent, UiState};
#[test]
fn reducer_produces_stable_snapshot_for_core_workflow() {
+3 -3
View File
@@ -1,5 +1,5 @@
[package]
name = "deepseek-tui"
name = "codewhale-tui"
version.workspace = true
edition.workspace = true
license.workspace = true
@@ -21,8 +21,8 @@ path = "src/main.rs"
[dependencies]
anyhow = "1.0.100"
arboard = "3.4"
deepseek-secrets = { path = "../secrets", version = "0.8.40" }
deepseek-tools = { path = "../tools", version = "0.8.40" }
codewhale-secrets = { path = "../secrets", version = "0.8.40" }
codewhale-tools = { path = "../tools", version = "0.8.40" }
schemaui = { version = "0.12.0", default-features = false, optional = true }
async-stream = "0.3.6"
async-trait = "0.1"
+1 -1
View File
@@ -1490,7 +1490,7 @@ fn map_tool_choice_for_chat(choice: &Value) -> Option<Value> {
/// reasoning can stay omitted once a later user text turn begins.
///
/// Also tallies the size of all replayed `reasoning_content` and logs it, so
/// users on `RUST_LOG=deepseek_tui=debug` can see how much of their input
/// users on `RUST_LOG=codewhale_tui=debug` can see how much of their input
/// budget is being spent re-sending prior thinking traces.
pub(super) fn sanitize_thinking_mode_messages(
body: &mut Value,
+2 -2
View File
@@ -258,7 +258,7 @@ pub static COMMAND_ARITY: &[(&str, u8)] = &[
/// # Examples
///
/// ```
/// # use deepseek_tui::command_safety::classify_command;
/// # use codewhale_tui::command_safety::classify_command;
/// assert_eq!(classify_command(&["git", "status", "-s"]), "git status");
/// assert_eq!(classify_command(&["git", "push", "origin"]), "git push");
/// assert_eq!(classify_command(&["cargo", "check", "--workspace"]), "cargo check");
@@ -319,7 +319,7 @@ pub fn classify_command(tokens: &[&str]) -> String {
/// # Examples
///
/// ```
/// # use deepseek_tui::command_safety::prefix_allow_matches;
/// # use codewhale_tui::command_safety::prefix_allow_matches;
/// assert!( prefix_allow_matches("git status", "git status --porcelain"));
/// assert!(!prefix_allow_matches("git status", "git push origin main"));
/// assert!( prefix_allow_matches("cargo check", "cargo check --workspace"));
+1 -1
View File
@@ -1179,7 +1179,7 @@ async fn create_summary(
// adding UI surface. The event is emitted with
// `target = "compaction"`, so the filter is
// `RUST_LOG=compaction=debug` (the module-path form
// `deepseek_tui::compaction=debug` does NOT match — `EnvFilter`
// `codewhale_tui::compaction=debug` does NOT match — `EnvFilter`
// matches the explicit target string when one is set).
log_summary_cache_telemetry(telemetry_cache_aligned, &response.usage);
+5 -5
View File
@@ -1099,7 +1099,7 @@ impl SkillsConfig {
}
}
/// `[network]` table — mirrors `deepseek_config::NetworkPolicyToml` so the live
/// `[network]` table — mirrors `codewhale_config::NetworkPolicyToml` so the live
/// TUI runtime can construct a [`crate::network_policy::NetworkPolicy`]
/// without reaching into the workspace config crate. See `config.example.toml`
/// for documentation.
@@ -1667,7 +1667,7 @@ impl Config {
// 2. Environment variables. Do not query platform credential stores
// here; routine startup and doctor checks must stay prompt-free.
if let Some(value) = deepseek_secrets::env_for(slot)
if let Some(value) = codewhale_secrets::env_for(slot)
&& !value.trim().is_empty()
{
return Ok(value);
@@ -3192,7 +3192,7 @@ pub enum SavedCredential {
/// `keyring → env → config-file` resolution-order shadow that
/// would otherwise let a stale OS-keyring entry from a previous
/// install hide the freshly-entered key (#593). The `backend`
/// label is the value of [`deepseek_secrets::Secrets::backend_name`]
/// label is the value of [`codewhale_secrets::Secrets::backend_name`]
/// at write time so the toast text can name the actual backend
/// (`"system keyring"`, `"file-based (~/.deepseek/secrets/)"`).
KeyringAndConfigFile {
@@ -3224,7 +3224,7 @@ impl SavedCredential {
/// Save the active provider's API key.
///
/// **Dual-write strategy (#593):** writes to `~/.deepseek/config.toml`
/// (always) and to the OS keyring via [`deepseek_secrets::Secrets`]
/// (always) and to the OS keyring via [`codewhale_secrets::Secrets`]
/// (when a backend is reachable). The runtime resolves credentials in
/// `keyring → env → config-file` order; writing to the config file
/// alone — as v0.8.8 through v0.8.10 did — let a stale keyring entry
@@ -3262,7 +3262,7 @@ pub fn save_api_key(api_key: &str) -> Result<SavedCredential> {
// cross-test contamination).
#[cfg(not(test))]
{
let secrets = deepseek_secrets::Secrets::auto_detect();
let secrets = codewhale_secrets::Secrets::auto_detect();
match secrets.set("deepseek", trimmed) {
Ok(()) => {
let backend = secrets.backend_name().to_string();
+4 -2
View File
@@ -68,8 +68,10 @@ mod tests {
fn log_value_parser_accepts_common_rust_log_directives() {
assert!(log_value_enables_verbose("debug"));
assert!(log_value_enables_verbose("deepseek_cli=debug"));
assert!(log_value_enables_verbose("warn,deepseek_tui::client=trace"));
assert!(log_value_enables_verbose(
"warn,codewhale_tui::client=trace"
));
assert!(!log_value_enables_verbose("warn"));
assert!(!log_value_enables_verbose("deepseek_tui=off"));
assert!(!log_value_enables_verbose("codewhale_tui=off"));
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ use crate::sandbox::backend::SandboxBackend;
use crate::tools::handle::{SharedHandleStore, new_shared_handle_store};
use crate::tools::shell::{SharedShellManager, new_shared_shell_manager};
#[allow(unused_imports)]
pub use deepseek_tools::{
pub use codewhale_tools::{
ApprovalRequirement, ToolCapability, ToolError, ToolResult, optional_bool, optional_str,
optional_u64, required_str, required_u64,
};
+2 -2
View File
@@ -152,7 +152,7 @@ pub fn find_file_mention_completions(
// Never-mentioned candidates fall back to the workspace ranker's order.
let entries = super::file_frecency::rerank_by_frecency(entries);
tracing::debug!(
target: "deepseek_tui::file_mention",
target: "codewhale_tui::file_mention",
partial = %partial,
workspace = %workspace.root.display(),
cwd = ?std::env::current_dir().ok(),
@@ -585,7 +585,7 @@ fn local_context_from_file_mentions(
}
};
tracing::debug!(
target: "deepseek_tui::file_mention",
target: "codewhale_tui::file_mention",
raw_typed = %mention,
workspace = %workspace.display(),
cwd = ?std::env::current_dir().ok(),
+3 -3
View File
@@ -608,7 +608,7 @@ fn parse_inline_spans(line: &str, base_style: Style, link_style: Style) -> Vec<I
let after = &rest[1 + end + 1..];
// Closing delimiter must not be immediately followed by a
// letter, digit, or underscore (otherwise it's part of an
// identifier like `deepseek_tui`, not italic markup).
// identifier like `codewhale_tui`, not italic markup).
if !after.starts_with(|c: char| c.is_alphanumeric() || c == '_') {
out.push(InlineToken::new(inner.to_string(), italic_style, None));
rest = after;
@@ -1047,14 +1047,14 @@ mod tests {
#[test]
fn underscores_inside_identifiers_render_as_literal_text() {
// Regression for PR #1455 / @tiger-dog: previously the inline
// markdown parser ate the underscore in `deepseek_tui` because
// markdown parser ate the underscore in `codewhale_tui` because
// it matched the `_italic_` pattern without a CommonMark-style
// boundary check. The closing `_` followed by `t` (a letter)
// must now be treated as part of the identifier, not as
// markup. The same rule applies to `*` so identifiers like
// `crate*foo` round-trip cleanly.
let cases = [
"crate deepseek_tui handles approvals",
"crate codewhale_tui handles approvals",
"see foo_bar_baz for details",
"look at *not_emphasised*tail",
];
+5 -5
View File
@@ -257,7 +257,7 @@ impl ViewStack {
pub fn push<V: ModalView + 'static>(&mut self, view: V) {
let kind = view.kind();
self.views.push(Box::new(view));
tracing::debug!(target: "deepseek_tui::view_stack", action = "push", kind = ?kind, depth = self.views.len(), "view pushed");
tracing::debug!(target: "codewhale_tui::view_stack", action = "push", kind = ?kind, depth = self.views.len(), "view pushed");
}
/// Push an already-boxed view back onto the stack. Used by call sites
@@ -266,13 +266,13 @@ impl ViewStack {
pub fn push_boxed(&mut self, view: Box<dyn ModalView>) {
let kind = view.kind();
self.views.push(view);
tracing::debug!(target: "deepseek_tui::view_stack", action = "push_boxed", kind = ?kind, depth = self.views.len(), "view pushed");
tracing::debug!(target: "codewhale_tui::view_stack", action = "push_boxed", kind = ?kind, depth = self.views.len(), "view pushed");
}
pub fn pop(&mut self) -> Option<Box<dyn ModalView>> {
let popped = self.views.pop();
if let Some(view) = popped.as_ref() {
tracing::debug!(target: "deepseek_tui::view_stack", action = "pop", kind = ?view.kind(), depth = self.views.len(), "view popped");
tracing::debug!(target: "codewhale_tui::view_stack", action = "pop", kind = ?view.kind(), depth = self.views.len(), "view popped");
}
popped
}
@@ -330,7 +330,7 @@ impl ViewStack {
ViewAction::None => {}
ViewAction::Close => {
if let Some(view) = self.views.pop() {
tracing::debug!(target: "deepseek_tui::view_stack", action = "close", kind = ?view.kind(), depth = self.views.len(), "view closed via action");
tracing::debug!(target: "codewhale_tui::view_stack", action = "close", kind = ?view.kind(), depth = self.views.len(), "view closed via action");
}
}
ViewAction::Emit(event) => {
@@ -339,7 +339,7 @@ impl ViewStack {
ViewAction::EmitAndClose(event) => {
events.push(event);
if let Some(view) = self.views.pop() {
tracing::debug!(target: "deepseek_tui::view_stack", action = "emit_and_close", kind = ?view.kind(), depth = self.views.len(), "view closed via action");
tracing::debug!(target: "codewhale_tui::view_stack", action = "emit_and_close", kind = ?view.kind(), depth = self.views.len(), "view closed via action");
}
}
}