From 1a95cd666476bdc1773d783587c3931874aef296 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 1 Mar 2026 18:14:25 -0500 Subject: [PATCH] =?UTF-8?q?Rename=20AgentBackend=20=E2=86=92=20AgentApiBac?= =?UTF-8?q?kend=20and=20CliBackend=20=E2=86=92=20AgentCliBackend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- crates/arc-api/src/serve.rs | 4 +- crates/arc-workflows/src/cli/backend.rs | 12 +++--- crates/arc-workflows/src/cli/cli_backend.rs | 16 ++++---- crates/arc-workflows/src/cli/run.rs | 12 +++--- .../tests/daytona_integration.rs | 6 +-- crates/arc-workflows/tests/integration.rs | 40 +++++++++---------- 6 files changed, 45 insertions(+), 45 deletions(-) diff --git a/crates/arc-api/src/serve.rs b/crates/arc-api/src/serve.rs index 20c277070..5ade3a22f 100644 --- a/crates/arc-api/src/serve.rs +++ b/crates/arc-api/src/serve.rs @@ -7,7 +7,7 @@ use tokio::net::TcpListener; use clap::Args; use crate::server::{build_router, create_app_state_with_options}; -use arc_workflows::cli::backend::AgentBackend; +use arc_workflows::cli::backend::AgentApiBackend; use arc_workflows::cli::ExecutionEnvKind; use arc_workflows::handler::default_registry; use arc_workflows::interviewer::Interviewer; @@ -98,7 +98,7 @@ pub async fn serve_command(args: ServeArgs, styles: &'static Styles) -> anyhow:: if dry_run_mode { None } else { - Some(Box::new(AgentBackend::new( + Some(Box::new(AgentApiBackend::new( model.clone(), provider_enum, 0, diff --git a/crates/arc-workflows/src/cli/backend.rs b/crates/arc-workflows/src/cli/backend.rs index a8b411e8d..b5d716c5e 100644 --- a/crates/arc-workflows/src/cli/backend.rs +++ b/crates/arc-workflows/src/cli/backend.rs @@ -22,7 +22,7 @@ use crate::outcome::StageUsage; /// /// For `full` fidelity nodes sharing a thread key, sessions are cached /// and reused so the LLM sees the full conversation history. -pub struct AgentBackend { +pub struct AgentApiBackend { model: String, provider: Provider, verbose: u8, @@ -30,7 +30,7 @@ pub struct AgentBackend { sessions: Mutex>, } -impl AgentBackend { +impl AgentApiBackend { #[must_use] pub fn new(model: String, provider: Provider, verbose: u8, styles: &'static Styles) -> Self { Self { @@ -113,7 +113,7 @@ impl AgentBackend { } #[async_trait] -impl CodergenBackend for AgentBackend { +impl CodergenBackend for AgentApiBackend { async fn one_shot( &self, node: &Node, @@ -469,7 +469,7 @@ mod tests { #[test] fn agent_backend_stores_config() { let styles = Box::leak(Box::new(Styles::new(false))); - let backend = AgentBackend::new("claude-opus-4-6".to_string(), Provider::OpenAi, 2, styles); + let backend = AgentApiBackend::new("claude-opus-4-6".to_string(), Provider::OpenAi, 2, styles); assert_eq!(backend.model, "claude-opus-4-6"); assert_eq!(backend.provider, Provider::OpenAi); assert_eq!(backend.verbose, 2); @@ -478,7 +478,7 @@ mod tests { #[test] fn agent_backend_initializes_empty_sessions() { let styles = Box::leak(Box::new(Styles::new(false))); - let backend = AgentBackend::new( + let backend = AgentApiBackend::new( "claude-opus-4-6".to_string(), Provider::Anthropic, 0, @@ -490,7 +490,7 @@ mod tests { #[test] fn build_profile_can_register_subagent_tools() { let styles = Box::leak(Box::new(Styles::new(false))); - let backend = AgentBackend::new( + let backend = AgentApiBackend::new( "claude-opus-4-6".to_string(), Provider::Anthropic, 0, diff --git a/crates/arc-workflows/src/cli/cli_backend.rs b/crates/arc-workflows/src/cli/cli_backend.rs index b68ff13f3..79d34ea54 100644 --- a/crates/arc-workflows/src/cli/cli_backend.rs +++ b/crates/arc-workflows/src/cli/cli_backend.rs @@ -215,12 +215,12 @@ pub fn parse_cli_response(provider: Provider, output: &str) -> Option Self { Self { model, provider } @@ -280,7 +280,7 @@ impl CliBackend { } #[async_trait] -impl CodergenBackend for CliBackend { +impl CodergenBackend for AgentCliBackend { async fn run( &self, node: &Node, @@ -376,12 +376,12 @@ impl CodergenBackend for CliBackend { /// based on node attributes and model type. pub struct BackendRouter { api_backend: Box, - cli_backend: CliBackend, + cli_backend: AgentCliBackend, } impl BackendRouter { #[must_use] - pub fn new(api_backend: Box, cli_backend: CliBackend) -> Self { + pub fn new(api_backend: Box, cli_backend: AgentCliBackend) -> Self { Self { api_backend, cli_backend, @@ -615,7 +615,7 @@ mod tests { node.attrs .insert("backend".to_string(), AttrValue::String("cli".to_string())); - let cli_backend = CliBackend::new("model".into(), Provider::Anthropic); + let cli_backend = AgentCliBackend::new("model".into(), Provider::Anthropic); let router = BackendRouter::new(Box::new(StubBackend), cli_backend); assert!(router.should_use_cli(&node)); } @@ -624,7 +624,7 @@ mod tests { fn router_uses_api_by_default() { let node = Node::new("test"); - let cli_backend = CliBackend::new("model".into(), Provider::Anthropic); + let cli_backend = AgentCliBackend::new("model".into(), Provider::Anthropic); let router = BackendRouter::new(Box::new(StubBackend), cli_backend); assert!(!router.should_use_cli(&node)); } @@ -637,7 +637,7 @@ mod tests { AttrValue::String("claude-opus-4-6".to_string()), ); - let cli_backend = CliBackend::new("model".into(), Provider::Anthropic); + let cli_backend = AgentCliBackend::new("model".into(), Provider::Anthropic); let router = BackendRouter::new(Box::new(StubBackend), cli_backend); assert!(!router.should_use_cli(&node)); } diff --git a/crates/arc-workflows/src/cli/run.rs b/crates/arc-workflows/src/cli/run.rs index 9156e67fd..052da479d 100644 --- a/crates/arc-workflows/src/cli/run.rs +++ b/crates/arc-workflows/src/cli/run.rs @@ -22,8 +22,8 @@ use crate::validation::Severity; use arc_llm::provider::Provider; -use super::backend::AgentBackend; -use super::cli_backend::{BackendRouter, CliBackend}; +use super::backend::AgentApiBackend; +use super::cli_backend::{BackendRouter, AgentCliBackend}; use super::task_config; use super::{ compute_stage_cost, format_cost, format_duration_human, format_event_detail, @@ -522,8 +522,8 @@ pub async fn run_command(args: RunArgs, styles: &'static Styles) -> anyhow::Resu if dry_run_mode { None } else { - let api = AgentBackend::new(model.clone(), provider_enum, args.verbose, styles); - let cli = CliBackend::new(model.clone(), provider_enum); + let api = AgentApiBackend::new(model.clone(), provider_enum, args.verbose, styles); + let cli = AgentCliBackend::new(model.clone(), provider_enum); Some(Box::new(BackendRouter::new(Box::new(api), cli))) } }); @@ -884,8 +884,8 @@ async fn run_from_branch( if dry_run_mode { None } else { - let api = AgentBackend::new(model.clone(), provider_enum, args.verbose, styles); - let cli = CliBackend::new(model.clone(), provider_enum); + let api = AgentApiBackend::new(model.clone(), provider_enum, args.verbose, styles); + let cli = AgentCliBackend::new(model.clone(), provider_enum); Some(Box::new(BackendRouter::new(Box::new(api), cli))) } }); diff --git a/crates/arc-workflows/tests/daytona_integration.rs b/crates/arc-workflows/tests/daytona_integration.rs index b4d7229f1..366815293 100644 --- a/crates/arc-workflows/tests/daytona_integration.rs +++ b/crates/arc-workflows/tests/daytona_integration.rs @@ -769,12 +769,12 @@ async fn daytona_parallel_git_branching_e2e() { // CLI Backend on Daytona — real CLI tools via exec_command // --------------------------------------------------------------------------- -use arc_workflows::cli::cli_backend::CliBackend; +use arc_workflows::cli::cli_backend::AgentCliBackend; use arc_workflows::handler::codergen::{CodergenBackend, CodergenResult}; /// Helper: run a real CLI backend test on Daytona. /// -/// Installs the CLI tool in the sandbox, then runs the CliBackend against it. +/// Installs the CLI tool in the sandbox, then runs the AgentCliBackend against it. async fn run_daytona_cli_test(provider: Provider, model: &str, install_command: &str) { let env = create_env().await; env.initialize().await.unwrap(); @@ -791,7 +791,7 @@ async fn run_daytona_cli_test(provider: Provider, model: &str, install_command: install_result.exit_code, install_result.stdout ); - let backend = CliBackend::new(model.to_string(), provider); + let backend = AgentCliBackend::new(model.to_string(), provider); let node = Node::new("daytona_cli_test"); let context = Context::new(); let emitter = Arc::new(EventEmitter::new()); diff --git a/crates/arc-workflows/tests/integration.rs b/crates/arc-workflows/tests/integration.rs index b198347a0..695282311 100644 --- a/crates/arc-workflows/tests/integration.rs +++ b/crates/arc-workflows/tests/integration.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use arc_llm::provider::Provider; use arc_util::terminal::Styles; use arc_workflows::checkpoint::Checkpoint; -use arc_workflows::cli::backend::AgentBackend; +use arc_workflows::cli::backend::AgentApiBackend; use arc_workflows::context::Context; use arc_workflows::engine::{PipelineEngine, RunConfig}; use arc_workflows::error::ArcError; @@ -7008,7 +7008,7 @@ async fn arc_e2e_with_real_llm() { let model = "claude-haiku-4-5-20251001".to_string(); let registry = default_registry(interviewer, move || { - Some(Box::new(AgentBackend::new( + Some(Box::new(AgentApiBackend::new( model.clone(), Provider::Anthropic, 0, @@ -7720,7 +7720,7 @@ async fn node_dir_uses_visit_count_on_revisit() { // CLI Backend end-to-end tests // --------------------------------------------------------------------------- -use arc_workflows::cli::cli_backend::{BackendRouter, CliBackend}; +use arc_workflows::cli::cli_backend::{BackendRouter, AgentCliBackend}; /// A mock execution environment for CLI backend e2e tests. /// Records all exec_command and write_file calls, and returns configurable @@ -7872,14 +7872,14 @@ impl arc_agent::ExecutionEnvironment for CliTestEnv { } } -// -- Cycle 8: CliBackend::run() e2e via mock ExecutionEnvironment -- +// -- Cycle 8: AgentCliBackend::run() e2e via mock ExecutionEnvironment -- #[tokio::test] async fn cli_backend_run_writes_prompt_and_calls_exec() { let claude_output = r#"{"type":"result","result":"I fixed the bug.","usage":{"input_tokens":500,"output_tokens":200}}"#; let test_env = Arc::new(CliTestEnv::new(claude_output)); let env: Arc = test_env.clone(); - let backend = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let node = Node::new("fix_code"); let context = Context::new(); @@ -7947,7 +7947,7 @@ async fn cli_backend_run_detects_changed_files() { let claude_output = r#"{"type":"result","result":"Created new file.","usage":{"input_tokens":100,"output_tokens":50}}"#; let env: Arc = Arc::new(CliTestEnv::new(claude_output).with_git_diff_after("src/main.rs\nsrc/lib.rs\n")); - let backend = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let node = Node::new("implement"); let context = Context::new(); @@ -7980,7 +7980,7 @@ async fn cli_backend_run_with_codex_provider() { let codex_output = "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_0\",\"type\":\"agent_message\",\"text\":\"Implemented the feature.\"}}\n{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":300,\"output_tokens\":150}}"; let test_env = Arc::new(CliTestEnv::new(codex_output)); let env: Arc = test_env.clone(); - let backend = CliBackend::new("gpt-5.3-codex".into(), Provider::OpenAi); + let backend = AgentCliBackend::new("gpt-5.3-codex".into(), Provider::OpenAi); let node = Node::new("implement"); let context = Context::new(); @@ -8109,7 +8109,7 @@ async fn cli_backend_run_fails_on_nonzero_exit() { } let failing_env: Arc = Arc::new(FailingCliEnv); - let backend = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let node = Node::new("step"); let context = Context::new(); let emitter = Arc::new(EventEmitter::new()); @@ -8148,7 +8148,7 @@ async fn cli_backend_run_fails_on_nonzero_exit() { async fn cli_backend_run_fails_on_unparseable_output() { let env: Arc = Arc::new(CliTestEnv::new("this is not json at all")); - let backend = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let node = Node::new("step"); let context = Context::new(); @@ -8184,7 +8184,7 @@ async fn cli_backend_run_uses_node_model_override() { r#"{"type":"result","result":"ok","usage":{"input_tokens":10,"output_tokens":5}}"#; let test_env = Arc::new(CliTestEnv::new(claude_output)); let env: Arc = test_env.clone(); - let backend = CliBackend::new("default-model".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("default-model".into(), Provider::Anthropic); let mut node = Node::new("step"); node.attrs.insert( @@ -8218,7 +8218,7 @@ async fn cli_backend_run_uses_node_provider_override() { let codex_output = "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_0\",\"type\":\"agent_message\",\"text\":\"ok\"}}\n{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":10,\"output_tokens\":5}}"; let test_env = Arc::new(CliTestEnv::new(codex_output)); let env: Arc = test_env.clone(); - let backend = CliBackend::new("default-model".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("default-model".into(), Provider::Anthropic); let mut node = Node::new("step"); node.attrs.insert( @@ -8252,7 +8252,7 @@ async fn cli_backend_run_writes_provider_used_json() { let claude_output = r#"{"type":"result","result":"done","usage":{"input_tokens":10,"output_tokens":5}}"#; let env: Arc = Arc::new(CliTestEnv::new(claude_output)); - let backend = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let backend = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let node = Node::new("step"); let context = Context::new(); @@ -8285,7 +8285,7 @@ async fn backend_router_delegates_to_cli_for_cli_node() { let env: Arc = Arc::new(CliTestEnv::new(claude_output)); let api_backend = Box::new(MockCodergenBackend); // would return "Response for ..." - let cli = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let cli = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let router = BackendRouter::new(api_backend, cli); let mut node = Node::new("cli_step"); @@ -8329,7 +8329,7 @@ async fn backend_router_delegates_to_api_for_normal_node() { let env = local_env(); let api_backend = Box::new(MockCodergenBackend); - let cli = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let cli = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let router = BackendRouter::new(api_backend, cli); let mut node = Node::new("api_step"); @@ -8372,7 +8372,7 @@ async fn backend_router_delegates_to_cli_for_backend_attr() { let env: Arc = Arc::new(CliTestEnv::new(codex_output)); let api_backend = Box::new(MockCodergenBackend); - let cli = CliBackend::new("gpt-5.3-codex".into(), Provider::OpenAi); + let cli = AgentCliBackend::new("gpt-5.3-codex".into(), Provider::OpenAi); let router = BackendRouter::new(api_backend, cli); let mut node = Node::new("codex_step"); @@ -8465,7 +8465,7 @@ async fn full_pipeline_with_cli_backend_node() { // Build engine with BackendRouter let api = MockCodergenBackend; - let cli = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let cli = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let router = BackendRouter::new(Box::new(api), cli); let codergen_handler = CodergenHandler::new(Some(Box::new(router))); @@ -8477,7 +8477,7 @@ async fn full_pipeline_with_cli_backend_node() { Box::new(CodergenHandler::new(Some(Box::new({ // Second BackendRouter for the "codergen" handler let api2 = MockCodergenBackend; - let cli2 = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let cli2 = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); BackendRouter::new(Box::new(api2), cli2) })))), ); @@ -8594,14 +8594,14 @@ async fn stylesheet_backend_property_routes_to_cli() { // Run the pipeline let api = MockCodergenBackend; - let cli = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let cli = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let router = BackendRouter::new(Box::new(api), cli); let mut registry = HandlerRegistry::new(Box::new(CodergenHandler::new(Some(Box::new(router))))); registry.register("start", Box::new(StartHandler)); registry.register("exit", Box::new(ExitHandler)); let api2 = MockCodergenBackend; - let cli2 = CliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); + let cli2 = AgentCliBackend::new("claude-opus-4-6".into(), Provider::Anthropic); let router2 = BackendRouter::new(Box::new(api2), cli2); registry.register( "codergen", @@ -8644,7 +8644,7 @@ use arc_workflows::cli::cli_backend::parse_cli_response; /// Run a real CLI tool via LocalExecutionEnvironment and verify the full flow. async fn run_real_cli_test(provider: Provider, model: &str) { let env = local_env(); - let backend = CliBackend::new(model.to_string(), provider); + let backend = AgentCliBackend::new(model.to_string(), provider); let mut node = Node::new("real_cli_test"); node.attrs.insert(