diff --git a/AGENTS.md b/AGENTS.md index 310cd594..87933379 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,7 +24,7 @@ Use [vhs](https://github.com/charmbracelet/vhs) to capture deterministic mp4 / g - **Build the worktree's binaries.** vhs records whatever `agent` you point it at, so make sure the worktree has been built (`cargo build` per the workflow above) before recording. For a before/after pair, prepare two worktrees so each side has its own binaries — never re-record `before` from a tree that already has the change applied. - **Isolated daemon.** Run vhs against a fresh `AGENTD_RUNTIME_DIR` / `AGENTD_STATE_DIR` / `AGENTD_DATA_DIR` / `AGENTD_CONFIG_DIR` under `/tmp/` so it doesn't collide with the user's running daemon. Each recording gets its own dir and its own daemon process; tear them down at the end. - **Put the TUI in a state that actually shows your change.** This part varies most by change — pick whichever shape fits: - - **Specific harness features** (a zarvis tool, codex output rendering, claude resume, …): spawn that harness with a representative prompt, e.g. `agent new zarvis ""`. Use a prompt whose output exercises the diff (tool calls if you changed tool rendering, long messages if you changed wrapping, etc.). + - **Specific harness features** (a smith tool, codex output rendering, claude resume, …): spawn that harness with a representative prompt, e.g. `agent new smith ""`. Use a prompt whose output exercises the diff (tool calls if you changed tool rendering, long messages if you changed wrapping, etc.). - **Minibuffer / keymap / popup / palette**: send the keystrokes from inside the vhs tape with `Type`, `Ctrl+X`, `Enter`, `Sleep`, etc. — no extra sessions needed if the feature is reachable from a stock TUI. - **Session-list / modeline / matrix rain / anything driven by fleet activity**: spawn 2–4 sessions producing ambient activity. The most robust pattern is `agent new shell ""` (interactive shell) followed by `agent send ""` pushing a noise loop into each. *Don't* pass the loop as the `new shell` prompt — both bash and zsh observed to fall back to interactive mode under PTY and never actually run `-lc `, leaving the daemon silent. - **Single-session views** (transcript, scrollback, diff): spawn one session, then trigger the view via tape keystrokes (`C-x z` for zoom, mouse-wheel events, etc.). @@ -142,16 +142,16 @@ Optional. Concrete behavior examples without relying on current file names or fu ## The minibuffer is just another session -Most TUIs make the bottom command bar a special UI primitive. We don't — it's a regular zarvis session, persisted on disk like any other. Differences: +Most TUIs make the bottom command bar a special UI primitive. We don't — it's a regular smith session, persisted on disk like any other. Differences: - **Hidden from the list.** `kind: SessionKind::Orchestrator` filters it out of `list_items`. - **Auto-created.** `SessionManager::ensure_orchestrator()` runs at daemon start. - **Rendered in the bottom strip.** Same `ItemHistory::replay` pipeline as the main view, just a different Rect. -- **Specialized system prompt.** Zarvis branches on `AGENTD_SESSION_KIND` to act as the fleet dispatcher instead of a worker. +- **Specialized system prompt.** Smith branches on `AGENTD_SESSION_KIND` to act as the fleet dispatcher instead of a worker. - **Subscribes to fleet events.** A second IPC connection turns other sessions' `Status{AwaitingInput|Errored|Done}` and `ToolApprovalRequest` into `OBSERVATION:` messages the orchestrator can react to. - **Approvals render inline in the PTY.** No global minibuffer preempt — the panel *is* the PTY. -Everything else — slash commands, tool-block expand/collapse, input queue during turns, persistence across daemon restart, automode, resume — works identically to any zarvis session, *because the minibuffer is one*. Add minibuffer features as session features. +Everything else — slash commands, tool-block expand/collapse, input queue during turns, persistence across daemon restart, automode, resume — works identically to any smith session, *because the minibuffer is one*. Add minibuffer features as session features. ## Rendering across resize and restart diff --git a/Cargo.toml b/Cargo.toml index 54393bf1..8100f105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ "crates/adapter-claude", "crates/adapter-codex", "crates/adapter-antigravity", - "crates/adapter-zarvis", + "crates/adapter-smith", "crates/e2e", ] diff --git a/crates/adapter-zarvis/Cargo.toml b/crates/adapter-smith/Cargo.toml similarity index 100% rename from crates/adapter-zarvis/Cargo.toml rename to crates/adapter-smith/Cargo.toml diff --git a/crates/adapter-zarvis/src/agent.rs b/crates/adapter-smith/src/agent.rs similarity index 99% rename from crates/adapter-zarvis/src/agent.rs rename to crates/adapter-smith/src/agent.rs index 436997fb..fc327cda 100644 --- a/crates/adapter-zarvis/src/agent.rs +++ b/crates/adapter-smith/src/agent.rs @@ -1,4 +1,4 @@ -//! The zarvis agent loop. Pulls user input from the inbox, calls the +//! The smith agent loop. Pulls user input from the inbox, calls the //! provider, runs any tool calls (gating Risky ones behind an approval //! prompt unless unsafe-auto is on), feeds results back, and loops until //! the model signals end-of-turn. @@ -184,7 +184,7 @@ impl<'a> TextSink for MessageSink<'a> { } } -pub(crate) const SYSTEM_PROMPT_USER: &str = r#"You are zarvis, an AI agent embedded in agentd (a multi-session terminal agent fleet). +pub(crate) const SYSTEM_PROMPT_USER: &str = r#"You are smith, an AI agent embedded in agentd (a multi-session terminal agent fleet). You have access to: - Local tools: shell (run any command — read files with `cat`/`sed -n`, search with `rg`/`grep`, list with `ls`, run tests, git), edit_file (apply one or many find/replace hunks across files; also creates files), write_stdin (drive an interactive process started by `shell interactive:true`). @@ -203,7 +203,7 @@ Dynamic session UI: when a task is long-running, multi-step, decision-heavy, or Be concise. When you finish a turn, emit a short summary of what you did; the user will see your messages and tool calls in the transcript."#; -pub(crate) const SYSTEM_PROMPT_ORCHESTRATOR: &str = r#"You are the agentd orchestrator — a default zarvis session created by agentd itself, surfaced in the user's TUI minibuffer. You are the always-available control surface for the user's session fleet. +pub(crate) const SYSTEM_PROMPT_ORCHESTRATOR: &str = r#"You are the agentd orchestrator — a default smith session created by agentd itself, surfaced in the user's TUI minibuffer. You are the always-available control surface for the user's session fleet. Your job is to help the user run, inspect, and reason about *other* sessions in agentd. Prefer agentd-control tools (prefix `agentd_`) over editing files or running ad-hoc shell commands yourself: - `agentd_list_sessions` / `agentd_get_session` / `agentd_get_transcript` to inspect state. @@ -375,7 +375,7 @@ pub(crate) async fn run_safe_call( } /// Push a `Message` to the in-memory vec and persist the same message -/// (best-effort) to `zarvis.jsonl` so a daemon restart can hydrate it. +/// (best-effort) to `smith.jsonl` so a daemon restart can hydrate it. macro_rules! push_msg { ($messages:expr, $persist:expr, $msg:expr) => {{ let m = $msg; @@ -461,7 +461,7 @@ pub async fn run( procs: Arc::new(crate::tools::proc::ProcRegistry::default()), }; - // Per-session message persistence (`zarvis.jsonl`). On resume, + // Per-session message persistence (`smith.jsonl`). On resume, // hydrate `messages` from the file before the loop starts. let data_dir = persist::session_data_dir_from_env(); let mut persist = Persist::open(data_dir.as_deref()); diff --git a/crates/adapter-zarvis/src/compact.rs b/crates/adapter-smith/src/compact.rs similarity index 100% rename from crates/adapter-zarvis/src/compact.rs rename to crates/adapter-smith/src/compact.rs diff --git a/crates/adapter-zarvis/src/context.rs b/crates/adapter-smith/src/context.rs similarity index 100% rename from crates/adapter-zarvis/src/context.rs rename to crates/adapter-smith/src/context.rs diff --git a/crates/adapter-zarvis/src/hooks.rs b/crates/adapter-smith/src/hooks.rs similarity index 95% rename from crates/adapter-zarvis/src/hooks.rs rename to crates/adapter-smith/src/hooks.rs index 94949d69..4127361b 100644 --- a/crates/adapter-zarvis/src/hooks.rs +++ b/crates/adapter-smith/src/hooks.rs @@ -1,4 +1,4 @@ -//! Optional zarvis hook runner. +//! Optional smith hook runner. //! //! Hooks are intentionally opt-in through env/config, not auto-loaded from //! the project tree, because they execute local commands with the user's @@ -41,7 +41,7 @@ impl Hooks { match Self::try_load(cwd) { Ok(hooks) => hooks, Err(e) => { - emit.log(format!("zarvis hooks disabled: {e}")); + emit.log(format!("smith hooks disabled: {e}")); Self::default() } } @@ -75,7 +75,7 @@ impl Hooks { }; for hook in commands { if let Err(e) = hook.run(event, cwd, payload.clone()).await { - emit.log(format!("zarvis hook `{event}` failed: {e}")); + emit.log(format!("smith hook `{event}` failed: {e}")); } } } @@ -107,14 +107,14 @@ impl Hooks { } } Ok(_) => emit.log(format!( - "zarvis hook `{event}` ignored: mutating hooks must return a JSON object" + "smith hook `{event}` ignored: mutating hooks must return a JSON object" )), Err(e) => emit.log(format!( - "zarvis hook `{event}` ignored invalid JSON stdout: {e}" + "smith hook `{event}` ignored invalid JSON stdout: {e}" )), } } - Err(e) => emit.log(format!("zarvis hook `{event}` failed: {e}")), + Err(e) => emit.log(format!("smith hook `{event}` failed: {e}")), } } current diff --git a/crates/adapter-zarvis/src/interactive.rs b/crates/adapter-smith/src/interactive.rs similarity index 99% rename from crates/adapter-zarvis/src/interactive.rs rename to crates/adapter-smith/src/interactive.rs index 91708e95..6e1ff622 100644 --- a/crates/adapter-zarvis/src/interactive.rs +++ b/crates/adapter-smith/src/interactive.rs @@ -1,6 +1,6 @@ -//! Interactive (PTY) mode for zarvis. +//! Interactive (PTY) mode for smith. //! -//! Zarvis doesn't spawn a child — there's no CLI to attach a real PTY +//! Smith doesn't spawn a child — there's no CLI to attach a real PTY //! to. Instead we synthesize a terminal session: we emit //! `SessionEvent::Pty` bytes that look like a chat-style REPL (banner //! + colored prompt + streaming assistant text + inline tool blocks + @@ -57,7 +57,7 @@ impl<'a> Terminal<'a> { None => String::new(), }; let banner = format!( - "\r\n\x1b[1;35mzarvis\x1b[0m \x1b[2m{provider}:{model}\x1b[0m{mode_badge}\r\n", + "\r\n\x1b[1;35msmith\x1b[0m \x1b[2m{provider}:{model}\x1b[0m{mode_badge}\r\n", ); self.write(banner.as_bytes()); } @@ -85,7 +85,7 @@ impl<'a> Terminal<'a> { } /// Open a tool-block region in the PTY stream with a custom OSC /// marker. Ratatui clients use this as a fence: the bytes between - /// the open and matching close are zarvis's truncated rendering, + /// the open and matching close are smith's truncated rendering, /// which the items-model renderer skips in favor of synthesizing /// its own representation from the structured `ToolUse` / /// `ToolResult` events (and which can therefore expand/collapse @@ -1978,7 +1978,7 @@ pub async fn run( ApprovalMode::Manual }; // Per-model learned input-token limits. Shared with `agent.rs` - // via `state_dir/zarvis-model-limits.json`, so a context-overflow + // via `state_dir/smith-model-limits.json`, so a context-overflow // learned in one session benefits every later session on the same // machine. We hold one instance for the lifetime of this run and // mutate through `record_overflow` / `record_call`. @@ -2294,7 +2294,7 @@ pub async fn run( // Slash commands never reach the model. Resolve the verb once via the // shared registry (crates/protocol/src/slash.rs), then branch on the // typed CommandId / routing — never on the raw string: - // * Adapter → mutate zarvis state here (model / reset / compact) + // * Adapter → mutate smith state here (model / reset / compact) // * ToolCall → synthesize a real tool call (/loop → loop_create) // * Client → hand off to the attached client as a ClientCommand let trimmed = user_text.trim(); diff --git a/crates/adapter-zarvis/src/interval_suggest.rs b/crates/adapter-smith/src/interval_suggest.rs similarity index 100% rename from crates/adapter-zarvis/src/interval_suggest.rs rename to crates/adapter-smith/src/interval_suggest.rs diff --git a/crates/adapter-zarvis/src/main.rs b/crates/adapter-smith/src/main.rs similarity index 100% rename from crates/adapter-zarvis/src/main.rs rename to crates/adapter-smith/src/main.rs diff --git a/crates/adapter-zarvis/src/model_limits.rs b/crates/adapter-smith/src/model_limits.rs similarity index 97% rename from crates/adapter-zarvis/src/model_limits.rs rename to crates/adapter-smith/src/model_limits.rs index d871bef4..feb35b3d 100644 --- a/crates/adapter-zarvis/src/model_limits.rs +++ b/crates/adapter-smith/src/model_limits.rs @@ -1,6 +1,6 @@ //! Persisted per-model input-token limit table. //! -//! Zarvis treats provider-reported limits as the ground truth: when +//! Smith treats provider-reported limits as the ground truth: when //! a request fails with a context-overflow error we (a) extract the //! limit out of the error body if the provider includes it, (b) save //! the new value here, and (c) reduce-then-retry. To detect a model @@ -9,7 +9,7 @@ //! we bump the saved limit by however many tokens the provider //! actually accepted. //! -//! The table lives in `state_dir/zarvis-model-limits.json` so every +//! The table lives in `state_dir/smith-model-limits.json` so every //! agentd session on the same machine shares the learning. The file //! is JSON to stay forgiving: extra keys are ignored, a corrupt file //! falls back to defaults instead of failing the launch. @@ -71,7 +71,7 @@ fn key(provider: &str, model: &str) -> String { } fn store_path() -> PathBuf { - Paths::discover().zarvis_model_limits_file() + Paths::discover().smith_model_limits_file() } impl ModelLimits { @@ -294,7 +294,7 @@ mod tests { /// Corrupt / empty file path: `load()` must NOT panic. Used by /// agent.rs and interactive.rs at session start; failure there - /// would block every zarvis session from running. + /// would block every smith session from running. #[test] fn from_garbage_falls_back_to_default() { let s: ModelLimits = serde_json::from_str("not json").unwrap_or_default(); diff --git a/crates/adapter-zarvis/src/observe.rs b/crates/adapter-smith/src/observe.rs similarity index 99% rename from crates/adapter-zarvis/src/observe.rs rename to crates/adapter-smith/src/observe.rs index 68b873de..4bcb8eba 100644 --- a/crates/adapter-zarvis/src/observe.rs +++ b/crates/adapter-smith/src/observe.rs @@ -1,6 +1,6 @@ //! Orchestrator-only event observer. //! -//! When the zarvis adapter is running as the daemon's orchestrator +//! When the smith adapter is running as the daemon's orchestrator //! session (`CONSTRUCT_SESSION_KIND=orchestrator`), it opens a second //! IPC connection to the daemon and subscribes to events from every //! other session. Filtered, those events flow back to the interactive diff --git a/crates/adapter-zarvis/src/persist.rs b/crates/adapter-smith/src/persist.rs similarity index 90% rename from crates/adapter-zarvis/src/persist.rs rename to crates/adapter-smith/src/persist.rs index 51eca3d8..b674ee8f 100644 --- a/crates/adapter-zarvis/src/persist.rs +++ b/crates/adapter-smith/src/persist.rs @@ -1,4 +1,4 @@ -//! Per-session message persistence — `zarvis.jsonl`. +//! Per-session message persistence — `smith.jsonl`. //! //! One JSON-serialized [`Message`] per line, append-only. The agent //! loop writes to it as it pushes messages into the in-memory vec; on @@ -20,22 +20,22 @@ pub struct Persist { } impl Persist { - /// Create a persister rooted at `/zarvis.jsonl`, + /// Create a persister rooted at `/smith.jsonl`, /// or `None` when no data dir was provided (the daemon should always /// set one, but in standalone invocations it may be missing). pub fn open(session_data_dir: Option<&Path>) -> Option { let dir = session_data_dir?; if let Err(e) = std::fs::create_dir_all(dir) { - tracing::warn!(dir = %dir.display(), error = ?e, "zarvis persist: mkdir failed"); + tracing::warn!(dir = %dir.display(), error = ?e, "smith persist: mkdir failed"); return None; } - let path = dir.join("zarvis.jsonl"); + let path = dir.join("smith.jsonl"); let file = OpenOptions::new() .create(true) .append(true) .open(&path) .map_err(|e| { - tracing::warn!(path = %path.display(), error = ?e, "zarvis persist: open failed"); + tracing::warn!(path = %path.display(), error = ?e, "smith persist: open failed"); e }) .ok()?; @@ -53,12 +53,12 @@ impl Persist { let line = match serde_json::to_string(msg) { Ok(s) => s, Err(e) => { - tracing::warn!(error = ?e, "zarvis persist: serialize failed"); + tracing::warn!(error = ?e, "smith persist: serialize failed"); return; } }; if let Err(e) = writeln!(file, "{line}") { - tracing::warn!(error = ?e, "zarvis persist: write failed"); + tracing::warn!(error = ?e, "smith persist: write failed"); } let _ = file.flush(); } @@ -76,7 +76,7 @@ impl Persist { Err(e) => tracing::warn!( path = %self.path.display(), error = ?e, - "zarvis persist: reset failed" + "smith persist: reset failed" ), } } @@ -84,9 +84,9 @@ impl Persist { /// Atomically replace the persisted conversation with `messages`. /// /// Writes a sibling tempfile, fsyncs, then `rename`s it over - /// `zarvis.jsonl`. A crash mid-write leaves the original file + /// `smith.jsonl`. A crash mid-write leaves the original file /// untouched (the tempfile is orphaned but not loaded on resume, - /// since `load` reads `zarvis.jsonl`). After a successful swap the + /// since `load` reads `smith.jsonl`). After a successful swap the /// append handle is reopened so the next [`append`](Self::append) /// continues at the end of the new file. /// @@ -126,7 +126,7 @@ impl Persist { Err(e) => tracing::warn!( path = %self.path.display(), error = ?e, - "zarvis persist: reopen after rewrite failed" + "smith persist: reopen after rewrite failed" ), } Ok(()) @@ -146,7 +146,7 @@ impl Persist { match serde_json::from_str::(&line) { Ok(m) => out.push(m), Err(e) => { - tracing::warn!(line = i + 1, error = ?e, "zarvis persist: skipping malformed line"); + tracing::warn!(line = i + 1, error = ?e, "smith persist: skipping malformed line"); } } } @@ -178,7 +178,7 @@ mod tests { #[test] fn reset_truncates_persisted_messages_and_keeps_appending() { let dir = - std::env::temp_dir().join(format!("agentd-zarvis-persist-test-{}", std::process::id())); + std::env::temp_dir().join(format!("agentd-smith-persist-test-{}", std::process::id())); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); @@ -209,7 +209,7 @@ mod tests { #[test] fn rewrite_swaps_atomically_and_appends_continue() { let dir = std::env::temp_dir().join(format!( - "agentd-zarvis-rewrite-test-{}-{}", + "agentd-smith-rewrite-test-{}-{}", std::process::id(), std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) diff --git a/crates/adapter-zarvis/src/project_guide.rs b/crates/adapter-smith/src/project_guide.rs similarity index 98% rename from crates/adapter-zarvis/src/project_guide.rs rename to crates/adapter-smith/src/project_guide.rs index 64c3173b..8629c461 100644 --- a/crates/adapter-zarvis/src/project_guide.rs +++ b/crates/adapter-smith/src/project_guide.rs @@ -3,7 +3,7 @@ //! `AGENTS.md` (also commonly `CLAUDE.md`) is the convention for //! per-project guidance the user wants every AI-assistant action to //! honor — coding style, file layout, prohibited patterns, etc. -//! Zarvis reads it once at session start (and on resume) and +//! Smith reads it once at session start (and on resume) and //! appends the contents to the system prompt under a dedicated //! `## Project guide` section. The file is the user's voice; the //! model is told to honor it unless explicitly overridden. @@ -162,7 +162,7 @@ mod tests { use std::sync::atomic::{AtomicU64, Ordering}; static N: AtomicU64 = AtomicU64::new(0); let p = std::env::temp_dir().join(format!( - "zarvis-guide-test-{}-{}", + "smith-guide-test-{}-{}", std::process::id(), N.fetch_add(1, Ordering::SeqCst) )); diff --git a/crates/adapter-zarvis/src/provider/anthropic.rs b/crates/adapter-smith/src/provider/anthropic.rs similarity index 100% rename from crates/adapter-zarvis/src/provider/anthropic.rs rename to crates/adapter-smith/src/provider/anthropic.rs diff --git a/crates/adapter-zarvis/src/provider/codex_oauth.rs b/crates/adapter-smith/src/provider/codex_oauth.rs similarity index 99% rename from crates/adapter-zarvis/src/provider/codex_oauth.rs rename to crates/adapter-smith/src/provider/codex_oauth.rs index 130fac29..46296f96 100644 --- a/crates/adapter-zarvis/src/provider/codex_oauth.rs +++ b/crates/adapter-smith/src/provider/codex_oauth.rs @@ -197,7 +197,7 @@ pub fn save_auth_json_atomic(path: &std::path::Path, auth: &AuthDotJson) -> Resu Ok(()) } -/// In-process refresh coordination. Multiple zarvis sessions in the +/// In-process refresh coordination. Multiple smith sessions in the /// same adapter process share one of these so only one of them at a /// time performs the rotation-prone refresh. Cross-process (multiple /// adapter instances) races remain possible; documented as a known @@ -232,7 +232,7 @@ impl CodexOauth { // Use the same identity codex CLI uses so we look like a // CLI client, not an anonymous Rust HTTP library. .user_agent(format!( - "codex_cli_rs/{} (agentd zarvis)", + "codex_cli_rs/{} (agentd smith)", env!("CARGO_PKG_VERSION") )) // NOTE: a cookie jar would let cf_clearance challenge @@ -674,7 +674,7 @@ fn resolve_instructions(system: &str) -> Result { } Err(anyhow!( "codex-oauth: no `instructions` available. Either set \ - {INSTRUCTIONS_ENV} to a non-empty value, or run zarvis with \ + {INSTRUCTIONS_ENV} to a non-empty value, or run smith with \ a non-empty `system` prompt (the agent loop populates this \ from its system-prompt builder). Empty / unset → Codex \ backend will reject the request with a 400." @@ -880,7 +880,7 @@ impl LlmProvider for CodexOauth { let body = build_responses_body(model, &instructions, messages, tools); // Take the auth lock for the duration of the request so - // concurrent zarvis turns don't race on token rotation. + // concurrent smith turns don't race on token rotation. let mut state = self.state.lock().await; if Self::needs_refresh(&state.auth) { self.refresh_locked(&mut state).await?; @@ -1224,7 +1224,7 @@ async fn connect_codex_ws(access_token: &str, account_id: &str) -> Result Option { let mut out = String::from( "## Agent skills\n\n\ - The user has Codex/Claude-style agent skills installed. Use a skill when the user explicitly names it, or when the task clearly matches its description. Before using a skill, read its `SKILL.md` with `shell` (e.g. `cat`) and follow that file's workflow. Resolve referenced scripts, assets, and relative paths from the directory containing that `SKILL.md`. Load only the skill you need, and only the referenced files needed for the task. If a skill requires a tool that Zarvis does not have, explain the limitation and continue with the closest available workflow.\n\n\ + The user has Codex/Claude-style agent skills installed. Use a skill when the user explicitly names it, or when the task clearly matches its description. Before using a skill, read its `SKILL.md` with `shell` (e.g. `cat`) and follow that file's workflow. Resolve referenced scripts, assets, and relative paths from the directory containing that `SKILL.md`. Load only the skill you need, and only the referenced files needed for the task. If a skill requires a tool that Smith does not have, explain the limitation and continue with the closest available workflow.\n\n\ Available skills:\n", ); for skill in skills { @@ -331,7 +331,7 @@ metadata: use std::sync::atomic::{AtomicU64, Ordering}; static N: AtomicU64 = AtomicU64::new(0); let p = std::env::temp_dir().join(format!( - "zarvis-skills-test-{}-{}", + "smith-skills-test-{}-{}", std::process::id(), N.fetch_add(1, Ordering::SeqCst) )); diff --git a/crates/adapter-zarvis/src/tasks.rs b/crates/adapter-smith/src/tasks.rs similarity index 100% rename from crates/adapter-zarvis/src/tasks.rs rename to crates/adapter-smith/src/tasks.rs diff --git a/crates/adapter-zarvis/src/title_mode.rs b/crates/adapter-smith/src/title_mode.rs similarity index 100% rename from crates/adapter-zarvis/src/title_mode.rs rename to crates/adapter-smith/src/title_mode.rs diff --git a/crates/adapter-zarvis/src/tools/agentd.rs b/crates/adapter-smith/src/tools/agentd.rs similarity index 99% rename from crates/adapter-zarvis/src/tools/agentd.rs rename to crates/adapter-smith/src/tools/agentd.rs index 4663b0ac..3210a161 100644 --- a/crates/adapter-zarvis/src/tools/agentd.rs +++ b/crates/adapter-smith/src/tools/agentd.rs @@ -1,5 +1,5 @@ //! Agentd-control tools: thin wrappers over `agentd_client::Client`. -//! Lets a zarvis session drive the daemon (list/spawn/send-input to +//! Lets a smith session drive the daemon (list/spawn/send-input to //! other sessions) using natural-language tool calls — the same surface //! the MCP server exposes. @@ -238,7 +238,7 @@ impl Tool for ListHarnesses { "agentd_list_harnesses" } fn description(&self) -> &str { - "List available adapter harnesses (shell, claude, codex, zarvis, …)." + "List available adapter harnesses (shell, claude, codex, smith, …)." } fn schema(&self) -> Value { json!({ "type": "object", "properties": {} }) diff --git a/crates/adapter-zarvis/src/tools/browser.rs b/crates/adapter-smith/src/tools/browser.rs similarity index 99% rename from crates/adapter-zarvis/src/tools/browser.rs rename to crates/adapter-smith/src/tools/browser.rs index a3598694..2ff2a7e7 100644 --- a/crates/adapter-zarvis/src/tools/browser.rs +++ b/crates/adapter-smith/src/tools/browser.rs @@ -1,4 +1,4 @@ -//! Chrome DevTools browser tools for Zarvis. +//! Chrome DevTools browser tools for Smith. //! //! These tools talk to a Chrome/Chromium instance running with //! `--remote-debugging-port`. They intentionally use the HTTP JSON @@ -338,7 +338,7 @@ async fn start_chrome(endpoint: &Endpoint) -> Result<()> { )); } let chrome = chrome_path().ok_or_else(|| anyhow!("Chrome/Chromium binary not found"))?; - let profile = format!("/tmp/zarvis-chrome-debug-{}", endpoint.port); + let profile = format!("/tmp/smith-chrome-debug-{}", endpoint.port); let mut cmd = Command::new(chrome); cmd.arg(format!("--remote-debugging-port={}", endpoint.port)) .arg(format!("--user-data-dir={profile}")) diff --git a/crates/adapter-zarvis/src/tools/fs.rs b/crates/adapter-smith/src/tools/fs.rs similarity index 96% rename from crates/adapter-zarvis/src/tools/fs.rs rename to crates/adapter-smith/src/tools/fs.rs index 1a1e2d2a..b7437f93 100644 --- a/crates/adapter-zarvis/src/tools/fs.rs +++ b/crates/adapter-smith/src/tools/fs.rs @@ -525,8 +525,8 @@ mod tests { "edits": [ {"find": "old app one", "replace": "new app one"}, {"find": "old app two", "replace": "new app two"}, - {"path": "crates/adapter-zarvis/src/interactive.rs", "find": "old prompt", "replace": "new prompt"}, - {"path": "crates/adapter-zarvis/src/tools/fs.rs", "find": "old summary", "replace": "new summary"} + {"path": "crates/adapter-smith/src/interactive.rs", "find": "old prompt", "replace": "new prompt"}, + {"path": "crates/adapter-smith/src/tools/fs.rs", "find": "old summary", "replace": "new summary"} ] })); @@ -535,10 +535,10 @@ mod tests { "crates/cli/src/app.rs (2 edits: `old app one` -> `new app one`; `old app two` -> `new app two`)" )); assert!(summary.contains( - "crates/adapter-zarvis/src/interactive.rs (1 edit: `old prompt` -> `new prompt`)" + "crates/adapter-smith/src/interactive.rs (1 edit: `old prompt` -> `new prompt`)" )); assert!(summary.contains( - "crates/adapter-zarvis/src/tools/fs.rs (1 edit: `old summary` -> `new summary`)" + "crates/adapter-smith/src/tools/fs.rs (1 edit: `old summary` -> `new summary`)" )); assert!(!summary.contains("file(s)")); } @@ -556,7 +556,7 @@ mod tests { #[tokio::test] async fn single_edit_replaces_unique_match() { - let dir = std::env::temp_dir().join(format!("zarvis-edit-single-{}", std::process::id())); + let dir = std::env::temp_dir().join(format!("smith-edit-single-{}", std::process::id())); let _ = std::fs::create_dir_all(&dir); let f = dir.join("a.txt"); std::fs::write(&f, "alpha\nbeta\ngamma\n").unwrap(); @@ -575,7 +575,7 @@ mod tests { #[tokio::test] async fn multi_hunk_is_atomic_on_failure() { - let dir = std::env::temp_dir().join(format!("zarvis-edit-atomic-{}", std::process::id())); + let dir = std::env::temp_dir().join(format!("smith-edit-atomic-{}", std::process::id())); let _ = std::fs::create_dir_all(&dir); let f = dir.join("b.txt"); std::fs::write(&f, "one\ntwo\nthree\n").unwrap(); @@ -602,7 +602,7 @@ mod tests { #[tokio::test] async fn multi_hunk_applies_in_order() { - let dir = std::env::temp_dir().join(format!("zarvis-edit-order-{}", std::process::id())); + let dir = std::env::temp_dir().join(format!("smith-edit-order-{}", std::process::id())); let _ = std::fs::create_dir_all(&dir); let f = dir.join("c.txt"); std::fs::write(&f, "one\ntwo\nthree\n").unwrap(); @@ -624,7 +624,7 @@ mod tests { #[tokio::test] async fn empty_find_creates_new_file() { - let dir = std::env::temp_dir().join(format!("zarvis-edit-create-{}", std::process::id())); + let dir = std::env::temp_dir().join(format!("smith-edit-create-{}", std::process::id())); let _ = std::fs::create_dir_all(&dir); let f = dir.join("nested/new.txt"); let ctx = ctx_with_cwd(dir.clone()); diff --git a/crates/adapter-zarvis/src/tools/mod.rs b/crates/adapter-smith/src/tools/mod.rs similarity index 99% rename from crates/adapter-zarvis/src/tools/mod.rs rename to crates/adapter-smith/src/tools/mod.rs index 91901731..d53db76b 100644 --- a/crates/adapter-zarvis/src/tools/mod.rs +++ b/crates/adapter-smith/src/tools/mod.rs @@ -51,7 +51,7 @@ pub trait Tool: Send + Sync { /// - its target path is covered by /// [`agentd_protocol::adapter::policy::AutoApprovePolicy`] — that's how the /// "agentd defines the policy once, harnesses honor it" abstraction lands -/// on zarvis; or +/// on smith; or /// - it is a `shell` call the model explicitly flagged `read_only: true` /// (see [`shell_read_only_optin`]). /// @@ -193,7 +193,7 @@ impl ToolRegistry { Box::new(agentd::LoopList), Box::new(agentd::LoopUpdate), Box::new(agentd::LoopRemove), - // Zarvis-owned subagents: hidden backing sessions exposed as + // Smith-owned subagents: hidden backing sessions exposed as // task-like child agents to this parent session. Box::new(subagent::Create), Box::new(subagent::List), diff --git a/crates/adapter-zarvis/src/tools/proc.rs b/crates/adapter-smith/src/tools/proc.rs similarity index 100% rename from crates/adapter-zarvis/src/tools/proc.rs rename to crates/adapter-smith/src/tools/proc.rs diff --git a/crates/adapter-zarvis/src/tools/shell.rs b/crates/adapter-smith/src/tools/shell.rs similarity index 99% rename from crates/adapter-zarvis/src/tools/shell.rs rename to crates/adapter-smith/src/tools/shell.rs index a7cf4038..169d40ac 100644 --- a/crates/adapter-zarvis/src/tools/shell.rs +++ b/crates/adapter-smith/src/tools/shell.rs @@ -293,7 +293,7 @@ mod tests { #[tokio::test] async fn returns_descriptive_error_when_cwd_missing() { - let missing = std::env::temp_dir().join("agentd-zarvis-shell-test-missing-cwd-xyz123"); + let missing = std::env::temp_dir().join("agentd-smith-shell-test-missing-cwd-xyz123"); assert!(!missing.exists(), "test precondition: path must not exist"); let ctx = ctx_with_cwd(missing.clone()); diff --git a/crates/adapter-zarvis/src/tools/subagent.rs b/crates/adapter-smith/src/tools/subagent.rs similarity index 97% rename from crates/adapter-zarvis/src/tools/subagent.rs rename to crates/adapter-smith/src/tools/subagent.rs index 3f267499..2ee740ae 100644 --- a/crates/adapter-zarvis/src/tools/subagent.rs +++ b/crates/adapter-smith/src/tools/subagent.rs @@ -1,8 +1,8 @@ -//! Zarvis subagent tools. +//! Smith subagent tools. //! //! A subagent is backed by an agentd session so every harness can run //! unchanged, but it is marked `SessionKind::Subagent` and tracked in -//! the parent Zarvis session's data dir. The parent sees task-like +//! the parent Smith session's data dir. The parent sees task-like //! create/list/peek/enqueue/cancel/delete operations; the main TUI list //! does not show the backing sessions. @@ -53,7 +53,7 @@ fn now_ms() -> i64 { fn registry_path() -> Result { let dir = std::env::var("CONSTRUCT_SESSION_DATA_DIR") .context("CONSTRUCT_SESSION_DATA_DIR is not set; subagents require an agentd session")?; - Ok(PathBuf::from(dir).join("zarvis-subagents.json")) + Ok(PathBuf::from(dir).join("smith-subagents.json")) } fn load_registry() -> Result { @@ -229,7 +229,7 @@ impl Tool for List { "agentd_subagent_list" } fn description(&self) -> &str { - "List subagents created by this Zarvis session, including current backing \ + "List subagents created by this Smith session, including current backing \ session summaries when still present." } fn schema(&self) -> Value { @@ -412,7 +412,7 @@ impl Tool for Delete { "agentd_subagent_delete" } fn description(&self) -> &str { - "Delete a subagent and remove it from this Zarvis session's registry." + "Delete a subagent and remove it from this Smith session's registry." } fn schema(&self) -> Value { schema_id_only() diff --git a/crates/cli/src/app.rs b/crates/cli/src/app.rs index bf4434a4..4e5d208b 100644 --- a/crates/cli/src/app.rs +++ b/crates/cli/src/app.rs @@ -493,7 +493,7 @@ pub struct App { /// events feed an [`ItemHistory`] that the render path replays /// onto a fresh parser. This enables expand/collapse of tool /// blocks via height mutation rather than vt100 cursor-edit - /// gymnastics. Non-zarvis sessions degrade to a single + /// gymnastics. Non-smith sessions degrade to a single /// `PtyChunk` and render identically to the old pipeline. pub histories: HashMap, /// Per-session cached block hit-test ranges (call_id, row range @@ -592,7 +592,7 @@ pub struct App { /// native drag selection/copy. pub mouse_capture_enabled: bool, /// ID of the daemon-owned orchestrator session, if one is present - /// in the sessions list. The orchestrator runs as a zarvis + /// in the sessions list. The orchestrator runs as a smith /// interactive (PTY) session; the TUI renders its PTY in the /// minibuffer panel and routes keystrokes there when the panel is /// focused. `None` falls back to the static palette UX. @@ -649,7 +649,7 @@ pub struct App { pub remote_control_task: Option)>>, /// Per-session input editor state, fed by `SessionEvent::EditorState` - /// from the adapter (currently zarvis interactive). Drives the + /// from the adapter (currently smith interactive). Drives the /// fixed bottom input pane. pub editor_states: HashMap, /// Per-session live agent status, fed by `SessionEvent::AgentStatus` @@ -941,7 +941,7 @@ async fn load_session_hydration(req: SessionHydrationRequest) -> Result Keymap { (Chord(vec![shift('G')]), ScrollBottom), (Chord(vec![key(KeyCode::PageDown)]), ScrollPageDown), (Chord(vec![key(KeyCode::PageUp)]), ScrollPageUp), - // Cycle approval mode on the selected session (zarvis / future agents). + // Cycle approval mode on the selected session (smith / future agents). (Chord(vec![ctrl('x'), shift('A')]), ToggleAutomode), // Give the terminal mouse back for native text selection/copy. (Chord(vec![ctrl('x'), ch('m')]), ToggleMouseCapture), diff --git a/crates/cli/src/matrix_rain.rs b/crates/cli/src/matrix_rain.rs index e7975b6d..9fb389bc 100644 --- a/crates/cli/src/matrix_rain.rs +++ b/crates/cli/src/matrix_rain.rs @@ -18,7 +18,7 @@ const PTY_REVEAL_GAP: Duration = Duration::from_millis(3500); /// Fallback activity words used only when the PTY byte stream /// hasn't yielded any extractable word for a session yet (or the -/// pool was already drained by the last reveal). Zarvis already +/// pool was already drained by the last reveal). Smith already /// emits structured tool events that map to richer words via /// `word_for_event`; this list is just so the rain isn't silent /// during the very first PTY chunk of a session. diff --git a/crates/cli/src/pty_render.rs b/crates/cli/src/pty_render.rs index 858b8299..07f45bc3 100644 --- a/crates/cli/src/pty_render.rs +++ b/crates/cli/src/pty_render.rs @@ -21,7 +21,7 @@ //! viewport. //! //! Sessions whose adapter never emits OSC `7700` markers (shell, -//! claude, codex, headless zarvis) just produce a single +//! claude, codex, headless smith) just produce a single //! [`Item::PtyChunk`] for the entire stream and render identically //! to the old direct-parser pipeline. @@ -205,7 +205,7 @@ pub struct ItemHistory { pending_block_hydrations: VecDeque, /// `ToolResult` events that arrived before their matching OSC /// open. Keyed by call_id (the `tool` field on `ToolResult` - /// carries call_id by zarvis convention). + /// carries call_id by smith convention). pending_tool_results: HashMap, /// Whether the next [`replay`] should account for a mutation. /// Set by every mutation; cleared by `replay`. @@ -215,7 +215,7 @@ pub struct ItemHistory { /// have items mutate underfoot, so we can process only the /// items appended since the last replay and just `set_size` on /// resize instead of replaying the full history. - /// Sessions with synthesized items (zarvis tool blocks and + /// Sessions with synthesized items (smith tool blocks and /// headless messages) keep signatures so unchanged frames reuse /// the parser and only mutations rebuild. cached: Option, @@ -360,7 +360,7 @@ fn block_sig(b: &ToolBlock) -> ItemSig { } /// How many output lines a collapsed tool block shows (must match -/// the zarvis-side cap so the synthesized version mirrors the +/// the smith-side cap so the synthesized version mirrors the /// inline-stream version's information density). /// Minimum geometry we'll feed into `vt100::Parser`. The crate /// (0.16.2) underflows in `grid.rs::col_wrap` when rows or cols is @@ -376,7 +376,7 @@ pub const VT100_MIN_DIM: u16 = 2; pub const TOOL_BLOCK_COLLAPSED_LINES: usize = 5; pub const TOOL_BLOCK_EXPANDED_LINES: usize = 240; -/// Per-line truncation in collapsed mode (mirrors zarvis). +/// Per-line truncation in collapsed mode (mirrors smith). pub const TOOL_BLOCK_MAX_COLS: usize = 200; const TOOL_BLOCK_HISTORY_LINE_CHARS: usize = TOOL_BLOCK_MAX_COLS * 2; @@ -774,7 +774,7 @@ impl ItemHistory { /// Apply a `TaskStart` event. Unlike `ToolUse`, this carries an /// explicit `call_id` — so the block is created and hydrated /// in a single step. This is the primary block-creation path - /// for new zarvis sessions; the OSC-fence path remains as a + /// for new smith sessions; the OSC-fence path remains as a /// backstop for byte streams loaded from older `pty.log` /// files that still contain inline fenced tool blocks. pub fn feed_task_start(&mut self, call_id: String, tool: String, args_summary: String) { @@ -812,7 +812,7 @@ impl ItemHistory { } /// Apply a `ToolResult` event. The protocol's `tool` field - /// carries the *call_id* (zarvis convention), so we can match + /// carries the *call_id* (smith convention), so we can match /// directly. If the OSC open hasn't arrived yet, stash for later. pub fn feed_tool_result(&mut self, call_id: &str, ok: bool, output: String) { let output = tool_output_preview_for_history(&output); @@ -874,7 +874,7 @@ impl ItemHistory { /// Render the session's accumulated content into a `vt100::Screen` /// at the requested size. Two strategies: /// - /// 1. **Tool-block sessions (zarvis):** use per-item signatures to + /// 1. **Tool-block sessions (smith):** use per-item signatures to /// reuse the parser across unchanged frames and rebuild only when /// synthesized state changes (control hints, expand/collapse, /// output arrival). @@ -912,9 +912,9 @@ impl ItemHistory { // main parser so block hit-test geometry, animated tool // block counters, etc. stay correct. // - // Tool-block sessions (zarvis) take the main parser path + // Tool-block sessions (smith) take the main parser path // even when scrolled. Two reasons: - // 1. zarvis is `\r\n`-shaped chat; its main parser + // 1. smith is `\r\n`-shaped chat; its main parser // naturally populates scrollback, so the shadow // isn't needed. // 2. The shadow only sees the truncated PTY-side @@ -926,7 +926,7 @@ impl ItemHistory { // row and the surrounding chat would shift — the // user perceives that as "the tool block // disappeared". See - // `zarvis_tool_block_survives_one_row_of_scroll` + // `smith_tool_block_survives_one_row_of_scroll` // for the regression repro. if scrollback > 0 && !needs_synth { let max_scrollback = self.render_shadow(cols, rows, scrollback); @@ -977,7 +977,7 @@ impl ItemHistory { // // - Rows change but cols don't: `set_size` is enough. // vt100 keeps the grid without replay and, importantly, - // avoids cursor-relocating reset escapes. The zarvis + // avoids cursor-relocating reset escapes. The smith // editor pane grows as the user types, shrinking // `chat_area.height` and tripping this path on nearly // every keystroke; closing the minibuffer grows the main @@ -1217,7 +1217,7 @@ impl ItemHistory { // scrollback window and avoids replaying ancient history. // We no longer re-scan the whole history with // `count_visible_lines` / `synth_block` every frame. That - // O(history)-per-frame re-scan was the zarvis typing lag. + // O(history)-per-frame re-scan was the smith typing lag. let start_processing_at = flushed_pending_layout .map(|(idx, _, _, _)| idx + 1) .unwrap_or_else(|| rebuild_from.unwrap_or(cache.processed_count)); @@ -1624,7 +1624,7 @@ fn count_visible_lines(bytes: &[u8], cols: u16) -> usize { } /// Build the byte sequence representing a tool block at its current -/// state. Matches the visual idiom zarvis writes inline so +/// state. Matches the visual idiom smith writes inline so /// non-ratatui consumers and the items-model render stay coherent. /// /// States rendered: @@ -1688,16 +1688,16 @@ fn synth_message(kind: MessageKind, text: &str, break_before: bool) -> Vec { } fn synth_block(block: &ToolBlock, cols: u16) -> SynthOutput { - /// Placeholder string the zarvis adapter writes into a tool's + /// Placeholder string the smith adapter writes into a tool's /// `output` when it auto-backgrounds. Kept in sync via the - /// `agentd_adapter_zarvis::tasks::BG_PLACEHOLDER_OUTPUT` + /// `agentd_adapter_smith::tasks::BG_PLACEHOLDER_OUTPUT` /// constant — duplicated here only to avoid a cross-crate /// dep just for one string. const BG_PLACEHOLDER_OUTPUT: &str = "(running in background; will report when complete)"; let mut out: Vec = Vec::with_capacity(128); // Leading blank — separates the block from prior chat content - // (mirrors zarvis's `\r\n→ ...` line layout). This blank takes + // (mirrors smith's `\r\n→ ...` line layout). This blank takes // one visible row, then the header. out.extend_from_slice(b"\r\n"); @@ -2093,7 +2093,7 @@ mod tests { #[test] fn tool_events_before_marker_are_buffered() { let mut h = ItemHistory::new(); - // Events arrive first (in zarvis's emit order). + // Events arrive first (in smith's emit order). h.feed_tool_use("shell".into(), "ls /tmp".into()); h.feed_tool_result("c1", true, "file_a\nfile_b\nfile_c".into()); // Then the PTY marker. @@ -2682,7 +2682,7 @@ mod tests { // Per-harness regression suite // // Each agentd-supported harness writes to the PTY in a different - // shape (shell = plain stdout, claude = alt-screen TUI, zarvis = + // shape (shell = plain stdout, claude = alt-screen TUI, smith = // chat + tool blocks, orchestrator = chat + EditorState, codex = // normal-screen TUI with accumulated history). Bugs that show up // in one frequently don't show up in another — these tests pin @@ -2701,7 +2701,7 @@ mod tests { // populated history; per-event cost stays bounded. // * "resize perf" — cost of resizing an already-populated // session. Currently passes for sessions whose accumulated - // `pending_chunk` is small (shell / zarvis / orchestrator / + // `pending_chunk` is small (shell / smith / orchestrator / // claude-via-alt-screen) and FAILS for codex (which // accumulates a lot of normal-screen content). // ============================================================ @@ -2829,10 +2829,10 @@ mod tests { ); } - // ----- zarvis (chat text + occasional tool blocks) ----- + // ----- smith (chat text + occasional tool blocks) ----- - fn zarvis_feed_chat(h: &mut ItemHistory) { - // A few chat exchanges. zarvis bytes look much like a plain + fn smith_feed_chat(h: &mut ItemHistory) { + // A few chat exchanges. smith bytes look much like a plain // CLI for the chat portion — the special bits are // tool-block events (TaskStart/feed_tool_use), not OSC // markers anymore. Use OSC here to exercise the tool-block @@ -2845,7 +2845,7 @@ mod tests { h.feed_pty(b"\xe2\x97\x8f done.\r\n"); } - /// Daemon-restart restore path for a zarvis session. + /// Daemon-restart restore path for a smith session. /// /// `bootstrap_terminal` reads pty.log via `pty_replay` and /// feeds the bytes to a fresh `ItemHistory`. The OSC fences @@ -2872,7 +2872,7 @@ mod tests { /// `args_summary` / `output` it would have had if it'd been /// built live. #[test] - fn zarvis_restart_restore_rehydrates_tool_block_details() { + fn smith_restart_restore_rehydrates_tool_block_details() { // Pre-restart: build the full live byte stream the adapter // would have produced, mirroring `interactive.rs`'s actual // sequence: tool_block_open → tool_use header → tool_result_body @@ -2946,28 +2946,28 @@ mod tests { } #[test] - fn zarvis_renders_after_bootstrap() { + fn smith_renders_after_bootstrap() { let mut h = ItemHistory::new(); - zarvis_feed_chat(&mut h); + smith_feed_chat(&mut h); let out = h.replay(80, 24, 0); // Don't assert exact cells (tool-block synth shifts rows); // just confirm we have a block recorded. assert!( !out.blocks.is_empty(), - "zarvis tool block should be hit-testable" + "smith tool block should be hit-testable" ); } #[test] - fn zarvis_renders_after_resize() { + fn smith_renders_after_resize() { let mut h = ItemHistory::new(); - zarvis_feed_chat(&mut h); + smith_feed_chat(&mut h); let _ = h.replay(80, 24, 0); let out = h.replay(120, 30, 0); - assert!(!out.blocks.is_empty(), "zarvis blocks survive resize"); + assert!(!out.blocks.is_empty(), "smith blocks survive resize"); } - /// Regression: when the zarvis editor pane grows (user types + /// Regression: when the smith editor pane grows (user types /// → multi-line input), `chat_area.height` shrinks, so the /// next `replay` call passes a smaller `rows`. The cached /// parser must absorb that via `set_size` without sending any @@ -3108,16 +3108,16 @@ mod tests { ); } - /// User-reported regression: after loading a zarvis session + /// User-reported regression: after loading a smith session /// with history, the *next* PTY bytes (user input / agent /// output) land at the top of the viewport instead of after /// the existing history. This test reproduces the scenario. #[test] - fn zarvis_new_content_after_bootstrap_does_not_overwrite_first_row() { + fn smith_new_content_after_bootstrap_does_not_overwrite_first_row() { let mut h = ItemHistory::new(); // Bootstrap: load history (mirrors what bootstrap_terminal // does after `pty_replay` returns the snapshot bytes). - zarvis_feed_chat(&mut h); + smith_feed_chat(&mut h); // Add several screens of additional chat so the viewport // is "full" — exercises the scrollback path where the // cursor should be parked at the bottom row after history. @@ -3129,10 +3129,10 @@ mod tests { // the session. let _ = h.replay(80, 24, 0); - // Now new bytes arrive — user typed something OR zarvis + // Now new bytes arrive — user typed something OR smith // emitted a follow-up message. These are exactly the bytes // the user reported as "overwriting the first row". - const MARKER: &str = "ZARVIS_NEW_LINE_MARKER"; + const MARKER: &str = "SMITH_NEW_LINE_MARKER"; h.feed_pty(format!("\x1b[36muser\x1b[0m: {MARKER}\r\n").as_bytes()); let out = h.replay(80, 24, 0); @@ -3166,9 +3166,9 @@ mod tests { } #[test] - fn zarvis_resize_steady_state_is_cheap() { + fn smith_resize_steady_state_is_cheap() { let mut h = ItemHistory::new(); - zarvis_feed_chat(&mut h); + smith_feed_chat(&mut h); // Warm the cache at the post-bootstrap state. let _ = h.replay(80, 24, 0); let _ = h.replay(80, 24, 0); @@ -3180,11 +3180,11 @@ mod tests { let t = Instant::now(); let _ = h.replay(120, 30, 0); let us = t.elapsed().as_micros(); - assert!(us < 5_000, "zarvis resize too slow: {us} µs"); + assert!(us < 5_000, "smith resize too slow: {us} µs"); } - /// PERF / regression: typing into a long zarvis session was - /// "super laggy". zarvis history has tool blocks, so it takes the + /// PERF / regression: typing into a long smith session was + /// "super laggy". smith history has tool blocks, so it takes the /// `replay_full` path. Unlike the streaming-bootstrap case (where /// the bulk sits in `pending_chunk` and is handled incrementally), /// a real session FLUSHES chat into many `Item::PtyChunk` entries @@ -3198,7 +3198,7 @@ mod tests { /// Steady-state re-render (same size, nothing changed) must be /// cheap regardless of history size. #[test] - fn zarvis_steady_state_render_is_cheap_with_many_items() { + fn smith_steady_state_render_is_cheap_with_many_items() { use std::time::Instant; let mut h = ItemHistory::new(); let cols = 100u16; @@ -3242,19 +3242,19 @@ mod tests { } let total_us = t.elapsed().as_micros(); let per_frame = total_us / frames as u128; - eprintln!("zarvis steady-state: {per_frame} µs/frame ({total_us} µs / {frames})"); + eprintln!("smith steady-state: {per_frame} µs/frame ({total_us} µs / {frames})"); // A no-op re-render must not re-scan the whole history. Loose // bound to avoid CI flakiness; the pre-fix cost was ~10-50× // this on the same hardware. assert!( per_frame < 300, - "zarvis steady-state render too slow: {per_frame} µs/frame — replay_full is re-scanning history every frame" + "smith steady-state render too slow: {per_frame} µs/frame — replay_full is re-scanning history every frame" ); } #[test] - fn zarvis_tool_expand_collapse_rebuilds_only_retained_suffix() { + fn smith_tool_expand_collapse_rebuilds_only_retained_suffix() { use std::time::Instant; let mut h = ItemHistory::new(); let cols = 100u16; @@ -3314,7 +3314,7 @@ mod tests { ); eprintln!( - "zarvis expand/collapse after long history: expand {expand_us} µs, collapse {collapse_us} µs" + "smith expand/collapse after long history: expand {expand_us} µs, collapse {collapse_us} µs" ); assert!( expand_us < 80_000, @@ -3327,7 +3327,7 @@ mod tests { } #[test] - fn zarvis_tool_start_reuses_already_rendered_pending_text() { + fn smith_tool_start_reuses_already_rendered_pending_text() { use std::time::Instant; let mut h = ItemHistory::new(); let cols = 100u16; @@ -3367,7 +3367,7 @@ mod tests { rendered.blocks.iter().any(|hit| hit.call_id == target), "new tool block hit rect should render after pending flush" ); - eprintln!("zarvis tool start after live pending: {tool_start_us} µs"); + eprintln!("smith tool start after live pending: {tool_start_us} µs"); assert!( tool_start_us < 80_000, "tool start replay too slow after pending flush: {tool_start_us} µs" @@ -3375,7 +3375,7 @@ mod tests { } #[test] - fn zarvis_tool_start_reuses_partially_rendered_pending_text() { + fn smith_tool_start_reuses_partially_rendered_pending_text() { use std::time::Instant; let mut h = ItemHistory::new(); let cols = 100u16; @@ -3416,7 +3416,7 @@ mod tests { rendered.blocks.iter().any(|hit| hit.call_id == target), "new tool block hit rect should render after partial pending flush" ); - eprintln!("zarvis tool start after partial pending: {tool_start_us} µs"); + eprintln!("smith tool start after partial pending: {tool_start_us} µs"); assert!( tool_start_us < 80_000, "tool start replay too slow after partial pending flush: {tool_start_us} µs" @@ -3507,7 +3507,7 @@ mod tests { assert!(matches!(h.items[1], Item::ToolBlock(_)), "{:?}", h.items); } - // ----- orchestrator / minibuffer (zarvis-like content, no + // ----- orchestrator / minibuffer (smith-like content, no // tool blocks in the common case) ----- fn orchestrator_feed(h: &mut ItemHistory) { @@ -4031,9 +4031,9 @@ mod tests { /// previous frame's buffer, since dims changed). /// /// Expected pattern (working hypothesis): codex's count is - /// significantly higher than claude's or zarvis's, because + /// significantly higher than claude's or smith's, because /// codex's normal-screen scroll fills the viewport with content - /// while claude's alt-screen + zarvis's chat-bubble layout leave + /// while claude's alt-screen + smith's chat-bubble layout leave /// more rows sparse. #[test] fn buffer_paint_cost_per_harness_after_resize() { @@ -4058,17 +4058,17 @@ mod tests { let claude_buf = render_main_view_buffer(&mut claude, w_post, h_post); let (claude_p, claude_s) = populated_or_styled_cells(&claude_buf); - // --- zarvis (chat + tool block) --- - let mut zarvis = ItemHistory::new(); - zarvis_feed_chat(&mut zarvis); + // --- smith (chat + tool block) --- + let mut smith = ItemHistory::new(); + smith_feed_chat(&mut smith); // Add more chat to make it comparable. for i in 0..50 { - zarvis.feed_pty(format!("\x1b[1;36m> hi {i}\x1b[0m\r\n").as_bytes()); - zarvis.feed_pty(format!("\x1b[1;35m* response {i}\x1b[0m\r\n").as_bytes()); + smith.feed_pty(format!("\x1b[1;36m> hi {i}\x1b[0m\r\n").as_bytes()); + smith.feed_pty(format!("\x1b[1;35m* response {i}\x1b[0m\r\n").as_bytes()); } - let _ = render_main_view_buffer(&mut zarvis, w_pre, h_pre); - let zarvis_buf = render_main_view_buffer(&mut zarvis, w_post, h_post); - let (zarvis_p, zarvis_s) = populated_or_styled_cells(&zarvis_buf); + let _ = render_main_view_buffer(&mut smith, w_pre, h_pre); + let smith_buf = render_main_view_buffer(&mut smith, w_post, h_post); + let (smith_p, smith_s) = populated_or_styled_cells(&smith_buf); // --- codex (normal-screen, dense scroll) --- let mut codex = ItemHistory::new(); @@ -4088,8 +4088,8 @@ mod tests { 100.0 * claude_p as f64 / total_cells as f64 ); eprintln!( - " zarvis: populated={zarvis_p:>5} styled={zarvis_s:>5} ({:.1}% populated)", - 100.0 * zarvis_p as f64 / total_cells as f64 + " smith: populated={smith_p:>5} styled={smith_s:>5} ({:.1}% populated)", + 100.0 * smith_p as f64 / total_cells as f64 ); eprintln!( " codex: populated={codex_p:>5} styled={codex_s:>5} ({:.1}% populated)", @@ -4099,7 +4099,7 @@ mod tests { // Sanity: every harness should produce non-empty buffers. assert!(shell_p > 0); assert!(claude_p > 0); - assert!(zarvis_p > 0); + assert!(smith_p > 0); assert!(codex_p > 0); } @@ -4154,15 +4154,15 @@ mod tests { let claude_bytes = approximate_paint_bytes(&render_main_view_buffer(&mut claude, w_post, h_post)); - let mut zarvis = ItemHistory::new(); - zarvis_feed_chat(&mut zarvis); + let mut smith = ItemHistory::new(); + smith_feed_chat(&mut smith); for i in 0..50 { - zarvis.feed_pty(format!("\x1b[1;36m> hi {i}\x1b[0m\r\n").as_bytes()); - zarvis.feed_pty(format!("\x1b[1;35m* resp {i}\x1b[0m\r\n").as_bytes()); + smith.feed_pty(format!("\x1b[1;36m> hi {i}\x1b[0m\r\n").as_bytes()); + smith.feed_pty(format!("\x1b[1;35m* resp {i}\x1b[0m\r\n").as_bytes()); } - let _ = render_main_view_buffer(&mut zarvis, w_pre, h_pre); - let zarvis_bytes = - approximate_paint_bytes(&render_main_view_buffer(&mut zarvis, w_post, h_post)); + let _ = render_main_view_buffer(&mut smith, w_pre, h_pre); + let smith_bytes = + approximate_paint_bytes(&render_main_view_buffer(&mut smith, w_post, h_post)); let mut codex = ItemHistory::new(); codex_feed_long_session(&mut codex); @@ -4173,7 +4173,7 @@ mod tests { eprintln!("approximate paint bytes after {w_post}x{h_post} resize:"); eprintln!(" shell: {shell_bytes:>8} bytes"); eprintln!(" claude: {claude_bytes:>8} bytes"); - eprintln!(" zarvis: {zarvis_bytes:>8} bytes"); + eprintln!(" smith: {smith_bytes:>8} bytes"); eprintln!(" codex: {codex_bytes:>8} bytes"); } @@ -4671,7 +4671,7 @@ mod tests { ); } - /// REGRESSION: zarvis tool-call rendering "disappears" the + /// REGRESSION: smith tool-call rendering "disappears" the /// moment the user scrolls. /// /// Mechanism: the live view (`scrollback = 0`) renders a @@ -4689,9 +4689,9 @@ mod tests { /// tool block visible in the live render survives into a render /// where the user has scrolled only a single row. #[test] - fn zarvis_tool_block_survives_one_row_of_scroll() { + fn smith_tool_block_survives_one_row_of_scroll() { let mut h = ItemHistory::new(); - // Tool block: OSC open + truncated zarvis preview + close, + // Tool block: OSC open + truncated smith preview + close, // followed by structured ToolUse/ToolResult so the live path // can synthesize the rich block. h.feed_pty(b"\x1b]7700;open;call=t1\x07"); @@ -4726,7 +4726,7 @@ mod tests { scrolled.contains("→ shell"), "REGRESSION: scrolling a single row replaces the synthesized \ tool block (`→ tool(args)` + status row + body) with the \ - one-line zarvis preview from the shadow parser. The user \ + one-line smith preview from the shadow parser. The user \ perceives the tool block as 'disappearing' since several \ rows of UI vanish and every row below shifts up. \ Got:\n{scrolled}", @@ -4835,7 +4835,7 @@ mod tests { ); } - /// REGRESSION: a fresh TUI re-attaching to an existing zarvis + /// REGRESSION: a fresh TUI re-attaching to an existing smith /// session must show tool blocks just like the session that /// originally rendered them — including in scrollback. /// @@ -4847,10 +4847,10 @@ mod tests { /// `apply_transcript_to_local_state`, which forwards events /// to the history. /// - /// Current zarvis interactive sessions do NOT write OSC 7700 + /// Current smith interactive sessions do NOT write OSC 7700 /// fences to the PTY (they're defined in `interactive.rs` but /// never called); the OSC backstop only fires for `pty.log` - /// files left over from older zarvis builds. New sessions + /// files left over from older smith builds. New sessions /// communicate tool blocks exclusively through /// `SessionEvent::TaskStart` (which carries the `call_id`) + /// `ToolUse` + `ToolResult`. If `apply_transcript_to_local_state` @@ -4860,20 +4860,20 @@ mod tests { /// runs and the user sees raw chat with no synthesized blocks /// at any scroll position. /// - /// This test simulates a current zarvis session: PTY bytes + /// This test simulates a current smith session: PTY bytes /// without OSC fences, plus a TaskStart + ToolResult on the /// transcript side. After both replays the synthesized block /// must appear in both live and scrolled renders. #[test] - fn zarvis_tool_block_visible_after_bootstrap_via_task_start() { + fn smith_tool_block_visible_after_bootstrap_via_task_start() { let mut h = ItemHistory::new(); // Step 1: pty_replay bytes — pure chat, no OSC fences (that's - // what current zarvis adapters actually write). + // what current smith adapters actually write). for i in 0..10u32 { h.feed_pty(format!("chat line {i:02}\r\n").as_bytes()); } // Step 2: transcript replay — TaskStart carries the call_id - // and is the canonical block-creation event for new zarvis + // and is the canonical block-creation event for new smith // sessions. apply_transcript_to_local_state must forward it. h.feed_task_start("t1".to_string(), "shell".to_string(), "ls".to_string()); h.feed_tool_result("t1", true, "OUTPUT-LINE".to_string()); @@ -4889,7 +4889,7 @@ mod tests { assert!( scrolled.contains("→ shell"), "scrolled render after bootstrap should keep the synthesized \ - header (companion to zarvis_tool_block_survives_one_row_of_scroll \ + header (companion to smith_tool_block_survives_one_row_of_scroll \ — same fix, different bootstrap source). got:\n{scrolled}", ); } diff --git a/crates/cli/src/ui.rs b/crates/cli/src/ui.rs index abd94565..5ad2b0f1 100644 --- a/crates/cli/src/ui.rs +++ b/crates/cli/src/ui.rs @@ -1880,7 +1880,7 @@ fn render_matrix_reveal_tooltip(f: &mut Frame, rain_area: Rect, app: &App) { let harness = harness_label(s); // Title if the session has a distinct one, else just the // harness; append harness too when a title exists so the - // tooltip says both (e.g. "fix auth · zarvis"). + // tooltip says both (e.g. "fix auth · smith"). let title = s.title.as_deref().filter(|t| !t.is_empty()); match title { Some(t) => format!(" {t} · {harness} "), @@ -2951,7 +2951,7 @@ fn render_terminal_for_window(f: &mut Frame, area: Rect, app: &mut App, window_i } let scroll = app.scrollback_for_window(window_id); // Only adapters that publish `SessionEvent::EditorState` (currently - // zarvis interactive) get the fixed editor pane at the bottom. + // smith interactive) get the fixed editor pane at the bottom. // claude / codex / shell render their own input prompt inside the // PTY, so a second editor pane would just look like a duplicate. let editor_state = app.editor_states.get(&id).cloned(); @@ -3022,7 +3022,7 @@ fn render_terminal_for_window(f: &mut Frame, area: Rect, app: &mut App, window_i } }; // Render the chat at the FULL pane height, not `chat_area.height`. - // The zarvis editor pane below grows/shrinks on nearly every + // The smith editor pane below grows/shrinks on nearly every // keystroke; sizing the parser to the shrinking chat area forced an // O(history) vt100 rebuild each time (the typing lag). Keeping the // parser at the stable `area.height` means editor growth never @@ -4934,7 +4934,7 @@ fn blit_image_quadrants(f: &mut Frame, area: Rect, img: &image::RgbaImage, cover /// - the active editor — one row per `\n`-separated buf line, cyan `❯` /// on the first row, two-space indent on continuation rows. /// Cursor is placed on the active line/col that corresponds to `state.cursor`. -const ZARVIS_READY_HINT: &str = "type your prompt and press Enter"; +const SMITH_READY_HINT: &str = "type your prompt and press Enter"; fn editor_ready_hint( state: Option<&crate::app::EditorState>, @@ -4948,9 +4948,9 @@ fn editor_ready_hint( match state { Some(s) if s.buf.is_empty() && s.queued.is_empty() && s.completions.is_empty() => { - Some(ZARVIS_READY_HINT) + Some(SMITH_READY_HINT) } - None => Some(ZARVIS_READY_HINT), + None => Some(SMITH_READY_HINT), _ => None, } } @@ -5209,7 +5209,7 @@ fn editor_pane_rows( .unwrap_or(0); let completion_lines = state.map(|s| s.completions.len()).unwrap_or(0); let buf_lines = if ready_hint.is_some() { - wrapped_text_rows(ZARVIS_READY_HINT, text_width) + wrapped_text_rows(SMITH_READY_HINT, text_width) } else { state .map(|s| wrapped_text_rows(&s.buf, text_width)) @@ -5495,7 +5495,7 @@ fn render_modeline_approval_mode_tooltip(f: &mut Frame, app: &App) { /// Compute how many rows the minibuffer footer occupies this frame. /// The default footer is 1 row (palette / hints / intent prompts). /// When the orchestrator panel is focused (its `MinibufferIntent` -/// active) it expands to a fixed cap so the embedded zarvis REPL has +/// active) it expands to a fixed cap so the embedded smith REPL has /// room to render its banner + chat bubbles, leaving the main view /// most of the screen. pub fn compute_minibuffer_height(app: &App, total_h: u16) -> u16 { @@ -6221,7 +6221,7 @@ pub fn pin_tile_layout(area: Rect, n: usize) -> Vec { /// Render a slice of a vt100 screen into `area`, preserving colors and /// attributes. The window is anchored at the bottom of the source screen so -/// harness status/input bars (zarvis, codex, claude all park them in the +/// harness status/input bars (smith, codex, claude all park them in the /// last few rows) stay visible on pinned tiles. Used by the pin strip. /// Translate tool-block hit-rects from full-parser-screen rows into /// `chat_area`-relative rows when the chat is rendered as the bottom @@ -6269,7 +6269,7 @@ fn translate_block_hits( /// Paint `screen` into `area`, showing the rows starting at `row_offset`. /// /// `row_offset` is non-zero only when the parser is taller than the chat -/// area — i.e. a zarvis editor pane is carved out below. We keep the +/// area — i.e. a smith editor pane is carved out below. We keep the /// parser at the full pane height (so the editor growing/shrinking on /// every keystroke never resizes — and rebuilds — it) and render only /// its bottom `area.height` rows here. `row_offset = full_height - @@ -6373,7 +6373,7 @@ fn vt100_cell_style(cell: &vt100::Cell, theme: &Theme) -> Style { mods.insert(Modifier::BOLD); } // `\x1b[2m` (dim/faint) — without this the pin tile renders - // styled-dim text (e.g. zarvis's `[+N lines — click to expand]` + // styled-dim text (e.g. smith's `[+N lines — click to expand]` // markers and tool args) at full intensity, while the main view // shows them correctly because `tui_term::PseudoTerminal` // translates the attribute itself. @@ -6433,7 +6433,7 @@ fn vt100_color(c: vt100::Color) -> Option { fn session_status_glyph(app: &App, s: &SessionSummary) -> &'static str { // `agent_statuses` only holds entries while a turn is active (the live // handler removes them on the `active=false` turn-end event), so a - // present, active entry means zarvis is working right now. + // present, active entry means smith is working right now. let agent_active = app .agent_statuses .get(&s.id) @@ -6450,8 +6450,8 @@ fn session_should_animate_status(s: &SessionSummary, pty_active: bool, agent_act if !matches!(s.state, SessionState::Running) { return false; } - // Zarvis reports an explicit agent-turn signal (`AgentStatus`): - // active=true at turn start, active=false at every turn end. A zarvis + // Smith reports an explicit agent-turn signal (`AgentStatus`): + // active=true at turn start, active=false at every turn end. A smith // session can linger in `Running` while idle (e.g. an interrupted turn // that returned without flipping back to AwaitingInput), so animate // strictly while that turn is active — not merely because the @@ -6646,7 +6646,7 @@ fn primary_label(s: &agentd_protocol::SessionSummary) -> String { } /// Render the orchestrator's PTY in the bottom strip. The orchestrator -/// is a zarvis interactive session; the same items-model history that +/// is a smith interactive session; the same items-model history that /// renders any other PTY-backed session is replayed onto a fresh /// parser sized to the panel's inner area each frame. Tool-block /// hit ranges land in `app.block_hits` for click-toggle dispatch. @@ -6677,7 +6677,7 @@ fn render_orchestrator_panel(f: &mut Frame, area: Rect, app: &mut App) { // is publishing `EditorState`, carve out a fixed editor pane at // the bottom of the panel so the `❯` and live typing are always // visible — otherwise this panel rendered only the PTY scrollback - // and the editor was invisible (zarvis stopped painting it). + // and the editor was invisible (smith stopped painting it). // // On a fresh TUI attach, the user can open the orchestrator panel // before the adapter's initial `EditorState` notification has @@ -7479,7 +7479,7 @@ mod tests { } } - /// User-reported regression: zarvis emits `\x1b[2m` (DIM/faint) + /// User-reported regression: smith emits `\x1b[2m` (DIM/faint) /// for markers like `[+N lines — click to expand]` and tool /// args. The main session view renders that as dim/gray because /// `tui_term::PseudoTerminal` translates the attribute itself, @@ -7514,7 +7514,7 @@ mod tests { assert!( dimmed_style.add_modifier.contains(Modifier::DIM), "dim cell must carry DIM modifier — without it the pin \ - tile renders zarvis's gray markers at full intensity" + tile renders smith's gray markers at full intensity" ); } @@ -7976,7 +7976,7 @@ mod tests { assert!(session_should_animate_status(&s, false, true)); // Running but the turn has ended (agent inactive) → stay static, // even though the lifecycle state still reads Running. This is the - // idle-zarvis regression: PR #179 spun the glyph here. + // idle-smith regression: PR #179 spun the glyph here. assert!(!session_should_animate_status(&s, false, false)); assert!(!session_should_animate_status(&s, true, false)); } @@ -7986,7 +7986,7 @@ mod tests { let mut s = summary_with_mode("shell", None); s.state = SessionState::Running; // Shell has no agent-status signal; gate on recent PTY bytes - // (agent_active is irrelevant for non-zarvis harnesses). + // (agent_active is irrelevant for non-smith harnesses). assert!(!session_should_animate_status(&s, false, false)); assert!(session_should_animate_status(&s, true, false)); } diff --git a/crates/cli/src/upgrade.rs b/crates/cli/src/upgrade.rs index 879a1483..f53e7779 100644 --- a/crates/cli/src/upgrade.rs +++ b/crates/cli/src/upgrade.rs @@ -15,7 +15,7 @@ use agentd_client::Client; use agentd_protocol::paths::Paths; /// GitHub `owner/repo` the release assets and installer come from. -const REPO: &str = "zarvis-ai/agentd"; +const REPO: &str = "smith-ai/agentd"; /// The installer, baked in at build time so `construct upgrade` and `install.sh` /// can never drift apart. const INSTALL_SH: &str = include_str!("../../../install.sh"); diff --git a/crates/daemon/assets/index.html b/crates/daemon/assets/index.html index e86336c7..50c2a7bc 100644 --- a/crates/daemon/assets/index.html +++ b/crates/daemon/assets/index.html @@ -1519,10 +1519,10 @@