From 79d97ebb5c06e756c8a4b6bd2fc0ad56b69f2beb Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 2 Mar 2026 11:43:34 -0500 Subject: [PATCH] Fix stale labels, grammar, and comments from sandbox rename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix display label `image:` → `name:` for SnapshotPulling/SnapshotPulled in format_event_detail - Fix grammar: "an Sandbox" → "a Sandbox" in README and parallel.rs - Fix typo: "sandboxs" → "sandboxes" in parallel.rs - Update remaining "execution environment" comments to "sandbox" Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/arc-web/app/api-client.test.ts | 60 ++++++++++++++++++++ apps/arc-web/app/api-client.ts | 2 +- apps/arc-web/package.json | 1 + apps/arc-web/tsconfig.json | 1 + crates/arc-agent/README.md | 2 +- crates/arc-agent/src/cli.rs | 2 +- crates/arc-agent/src/docker_sandbox.rs | 4 +- crates/arc-agent/src/session.rs | 2 +- crates/arc-agent/src/test_support.rs | 2 +- crates/arc-agent/src/v4a_patch.rs | 2 +- crates/arc-api/src/serve.rs | 2 +- crates/arc-workflows/src/cli/mod.rs | 6 +- crates/arc-workflows/src/cli/run.rs | 2 +- crates/arc-workflows/src/handler/parallel.rs | 4 +- crates/arc-workflows/tests/integration.rs | 8 +-- 15 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 apps/arc-web/app/api-client.test.ts diff --git a/apps/arc-web/app/api-client.test.ts b/apps/arc-web/app/api-client.test.ts new file mode 100644 index 000000000..b77950166 --- /dev/null +++ b/apps/arc-web/app/api-client.test.ts @@ -0,0 +1,60 @@ +import { describe, test, expect, beforeEach, mock } from "bun:test"; +import { apiJson } from "./api-client"; + +const originalFetch = globalThis.fetch; + +beforeEach(() => { + globalThis.fetch = originalFetch; +}); + +describe("apiJson", () => { + test("returns parsed JSON on 200", async () => { + globalThis.fetch = mock(() => + Promise.resolve(new Response(JSON.stringify({ id: 1, name: "test" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + })) + ); + + const result = await apiJson<{ id: number; name: string }>("/items/1"); + + expect(result).toEqual({ id: 1, name: "test" }); + }); + + test("throws Response with status 404 and null body on not found", async () => { + globalThis.fetch = mock(() => + Promise.resolve(new Response("Not Found: /items/999", { status: 404 })) + ); + + try { + await apiJson("/items/999"); + expect.unreachable("should have thrown"); + } catch (thrown) { + expect(thrown).toBeInstanceOf(Response); + const res = thrown as Response; + expect(res.status).toBe(404); + expect(res.body).toBeNull(); + } + }); + + test("throws Response with status 500 and null body, stripping sensitive details", async () => { + globalThis.fetch = mock(() => + Promise.resolve( + new Response( + "Internal error: database connection string is postgres://admin:secret@db.internal:5432/prod", + { status: 500 } + ) + ) + ); + + try { + await apiJson("/items/1"); + expect.unreachable("should have thrown"); + } catch (thrown) { + expect(thrown).toBeInstanceOf(Response); + const res = thrown as Response; + expect(res.status).toBe(500); + expect(res.body).toBeNull(); + } + }); +}); diff --git a/apps/arc-web/app/api-client.ts b/apps/arc-web/app/api-client.ts index 30d920b2b..48907714c 100644 --- a/apps/arc-web/app/api-client.ts +++ b/apps/arc-web/app/api-client.ts @@ -51,6 +51,6 @@ export async function apiFetch( */ export async function apiJson(path: string, init?: RequestInit): Promise { const res = await apiFetch(path, init); - if (!res.ok) throw new Response(await res.text(), { status: res.status }); + if (!res.ok) throw new Response(null, { status: res.status }); return res.json() as Promise; } diff --git a/apps/arc-web/package.json b/apps/arc-web/package.json index de962a943..8a1e888cc 100644 --- a/apps/arc-web/package.json +++ b/apps/arc-web/package.json @@ -6,6 +6,7 @@ "build": "react-router build", "dev": "react-router dev", "start": "react-router-serve ./build/server/index.js", + "test": "ARC_API_BASE_URL=http://localhost:9999 bun test", "typecheck": "react-router typegen && tsc" }, "dependencies": { diff --git a/apps/arc-web/tsconfig.json b/apps/arc-web/tsconfig.json index 385cfbfa4..f5bacb582 100644 --- a/apps/arc-web/tsconfig.json +++ b/apps/arc-web/tsconfig.json @@ -5,6 +5,7 @@ "**/.client/**/*", ".react-router/types/**/*" ], + "exclude": ["**/*.test.ts"], "compilerOptions": { "lib": ["DOM", "DOM.Iterable", "ES2022"], "types": ["node", "vite/client"], diff --git a/crates/arc-agent/README.md b/crates/arc-agent/README.md index a26bb5434..4c8e99b0d 100644 --- a/crates/arc-agent/README.md +++ b/crates/arc-agent/README.md @@ -9,7 +9,7 @@ The crate is organized around a central `Session` that drives an agentic loop: 1. **User input** is appended to a conversation `History` 2. The session builds a `Request` with system prompt, history, and tools 3. An LLM generates a response (text and/or tool calls) via `unified-llm` -4. Tool calls are executed through a `ToolRegistry` against an `Sandbox` +4. Tool calls are executed through a `ToolRegistry` against a `Sandbox` 5. Results are recorded and the loop continues until the LLM responds with text only (natural completion), a turn limit is reached, or the session is aborted ``` diff --git a/crates/arc-agent/src/cli.rs b/crates/arc-agent/src/cli.rs index 25536d099..54a207649 100644 --- a/crates/arc-agent/src/cli.rs +++ b/crates/arc-agent/src/cli.rs @@ -382,7 +382,7 @@ pub async fn run_with_args(args: AgentArgs) -> anyhow::Result<()> { eprintln!("{}Using model: {model}{}", styles.dim, styles.reset,); let mut profile = build_profile(provider, model, Some(client.clone())); - // Build execution environment + // Build sandbox let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); let cwd_str = cwd.to_string_lossy().to_string(); let env: Arc = Arc::new(LocalSandbox::new(cwd)); diff --git a/crates/arc-agent/src/docker_sandbox.rs b/crates/arc-agent/src/docker_sandbox.rs index 6db2285de..c94b0a995 100644 --- a/crates/arc-agent/src/docker_sandbox.rs +++ b/crates/arc-agent/src/docker_sandbox.rs @@ -15,7 +15,7 @@ use std::collections::HashMap; use std::time::Instant; use tokio_util::sync::CancellationToken; -/// Configuration for a Docker-based execution environment. +/// Configuration for a Docker-based sandbox. pub struct DockerSandboxConfig { /// Docker image to use. Default: `"arc-agent:latest"`. pub image: String, @@ -53,7 +53,7 @@ impl Default for DockerSandboxConfig { } } -/// Execution environment that runs all operations inside a Docker container. +/// Sandbox that runs all operations inside a Docker container. /// /// The host working directory is bind-mounted at `container_mount_point`. All file /// operations, commands, grep, and glob execute inside the container via `docker exec`. diff --git a/crates/arc-agent/src/session.rs b/crates/arc-agent/src/session.rs index a8229a41a..4ea16137f 100644 --- a/crates/arc-agent/src/session.rs +++ b/crates/arc-agent/src/session.rs @@ -170,7 +170,7 @@ impl Session { let today = chrono::Local::now().format("%Y-%m-%d").to_string(); let model_name = self.provider_profile.model().to_string(); - // Detect git info via execution environment + // Detect git info via sandbox let git_branch = self .sandbox .exec_command("git rev-parse --abbrev-ref HEAD", 5000, None, None, None) diff --git a/crates/arc-agent/src/test_support.rs b/crates/arc-agent/src/test_support.rs index 7fe0e9ceb..6c24d661c 100644 --- a/crates/arc-agent/src/test_support.rs +++ b/crates/arc-agent/src/test_support.rs @@ -199,7 +199,7 @@ impl Sandbox for MockSandbox { // --- MutableMockSandbox --- -/// A mock execution environment with Mutex-protected files for tests that need +/// A mock sandbox with Mutex-protected files for tests that need /// write operations to be visible to subsequent reads (e.g., `apply_patch` tests). pub struct MutableMockSandbox { pub files: Mutex>, diff --git a/crates/arc-agent/src/v4a_patch.rs b/crates/arc-agent/src/v4a_patch.rs index 2d85ec2ff..ee040ab4e 100644 --- a/crates/arc-agent/src/v4a_patch.rs +++ b/crates/arc-agent/src/v4a_patch.rs @@ -124,7 +124,7 @@ pub fn parse_v4a_patch(text: &str) -> Result, String> { Ok(ops) } -/// Applies a list of patch operations using the given execution environment. +/// Applies a list of patch operations using the given sandbox. /// /// # Errors /// Returns an error if any file operation fails. diff --git a/crates/arc-api/src/serve.rs b/crates/arc-api/src/serve.rs index f33298b05..5f85b816b 100644 --- a/crates/arc-api/src/serve.rs +++ b/crates/arc-api/src/serve.rs @@ -35,7 +35,7 @@ pub struct ServeArgs { #[arg(long)] pub dry_run: bool, - /// Execution environment for agent tools + /// Sandbox for agent tools #[arg(long, value_enum)] pub sandbox: Option, diff --git a/crates/arc-workflows/src/cli/mod.rs b/crates/arc-workflows/src/cli/mod.rs index 5ec55131b..beeec7ecf 100644 --- a/crates/arc-workflows/src/cli/mod.rs +++ b/crates/arc-workflows/src/cli/mod.rs @@ -110,7 +110,7 @@ pub struct RunArgs { #[arg(short, long, action = clap::ArgAction::Count)] pub verbose: u8, - /// Execution environment for agent tools + /// Sandbox for agent tools #[arg(long, value_enum)] pub sandbox: Option, @@ -868,10 +868,10 @@ pub fn format_event_detail(event: &WorkflowRunEvent, styles: &Styles) -> String format!("{d}── SANDBOX_CLEANUP_FAILED ──────────────────{r}\n {d}provider:{r} {provider}\n {d}error:{r} {error}\n") } SandboxEvent::SnapshotPulling { name } => { - format!("{d}── SANDBOX_SNAPSHOT_PULLING ───────────────────{r}\n {d}image:{r} {name}\n") + format!("{d}── SANDBOX_SNAPSHOT_PULLING ───────────────────{r}\n {d}name:{r} {name}\n") } SandboxEvent::SnapshotPulled { name, duration_ms } => { - format!("{d}── SANDBOX_SNAPSHOT_PULLED ────────────────────{r}\n {d}image:{r} {name}\n {d}duration_ms:{r} {duration_ms}\n") + format!("{d}── SANDBOX_SNAPSHOT_PULLED ────────────────────{r}\n {d}name:{r} {name}\n {d}duration_ms:{r} {duration_ms}\n") } SandboxEvent::SnapshotEnsuring { name } => { format!("{d}── SANDBOX_SNAPSHOT_ENSURING ───────────────{r}\n {d}name:{r} {name}\n") diff --git a/crates/arc-workflows/src/cli/run.rs b/crates/arc-workflows/src/cli/run.rs index 5e0fcc1ca..145b076a1 100644 --- a/crates/arc-workflows/src/cli/run.rs +++ b/crates/arc-workflows/src/cli/run.rs @@ -376,7 +376,7 @@ pub async fn run_command(args: RunArgs, styles: &'static Styles) -> anyhow::Resu if let Ok(handle) = rt { handle.spawn(async move { if let Err(e) = sandbox_for_cleanup.cleanup().await { - tracing::warn!(error = %e, "Execution environment cleanup failed"); + tracing::warn!(error = %e, "Sandbox cleanup failed"); eprintln!("Warning: sandbox cleanup failed: {e}"); } }); diff --git a/crates/arc-workflows/src/handler/parallel.rs b/crates/arc-workflows/src/handler/parallel.rs index 436896041..c7a61f07e 100644 --- a/crates/arc-workflows/src/handler/parallel.rs +++ b/crates/arc-workflows/src/handler/parallel.rs @@ -16,7 +16,7 @@ use crate::outcome::{Outcome, StageStatus}; use super::{EngineServices, Handler}; // --------------------------------------------------------------------------- -// WorktreeSandbox — decorates an Sandbox with a custom working dir +// WorktreeSandbox — decorates a Sandbox with a custom working dir // --------------------------------------------------------------------------- /// Wraps an existing `Sandbox` so that all operations use a @@ -256,7 +256,7 @@ impl Handler for ParallelHandler { None }; - // Build per-branch sandboxs (sequentially for git setup) + // Build per-branch sandboxes (sequentially for git setup) struct BranchSetup { target_id: String, branch_index: usize, diff --git a/crates/arc-workflows/tests/integration.rs b/crates/arc-workflows/tests/integration.rs index 3bb1b682b..9936fe3df 100644 --- a/crates/arc-workflows/tests/integration.rs +++ b/crates/arc-workflows/tests/integration.rs @@ -7608,10 +7608,10 @@ async fn large_context_values_are_offloaded_to_artifact_store() { } // --------------------------------------------------------------------------- -// Artifact sync to remote execution environments +// Artifact sync to remote sandboxs // --------------------------------------------------------------------------- -/// A mock execution environment where `file_exists` always returns false, +/// A mock sandbox where `file_exists` always returns false, /// simulating a remote container that doesn't have local artifact files. struct RemoteMockEnv { working_dir: String, @@ -7924,7 +7924,7 @@ async fn node_dir_uses_visit_count_on_revisit() { use arc_workflows::cli::cli_backend::{BackendRouter, AgentCliBackend}; -/// A mock execution environment for CLI backend e2e tests. +/// A mock sandbox for CLI backend e2e tests. /// Records all exec_command and write_file calls, and returns configurable /// responses based on command content. struct CliTestEnv { @@ -8966,7 +8966,7 @@ use arc_workflows::engine::GitCheckpointMode; use arc_workflows::handler::fan_in::FanInHandler; use arc_workflows::handler::parallel::ParallelHandler; -/// A handler that writes a file named `{node_id}.txt` into the execution environment's +/// A handler that writes a file named `{node_id}.txt` into the sandbox's /// working directory. Used to verify git worktree isolation in parallel branches. struct FileWriterHandler;