Rename AgentBackend → AgentApiBackend and CliBackend → AgentCliBackend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-01 18:14:25 -05:00
parent a535c6575f
commit 1a95cd6664
6 changed files with 45 additions and 45 deletions

View file

@ -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,

View file

@ -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<HashMap<String, Session>>,
}
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,

View file

@ -215,12 +215,12 @@ pub fn parse_cli_response(provider: Provider, output: &str) -> Option<CliRespons
}
/// CLI backend that invokes external CLI tools (claude, codex, gemini) via `exec_command()`.
pub struct CliBackend {
pub struct AgentCliBackend {
model: String,
provider: Provider,
}
impl CliBackend {
impl AgentCliBackend {
#[must_use]
pub fn new(model: String, provider: Provider) -> 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<dyn CodergenBackend>,
cli_backend: CliBackend,
cli_backend: AgentCliBackend,
}
impl BackendRouter {
#[must_use]
pub fn new(api_backend: Box<dyn CodergenBackend>, cli_backend: CliBackend) -> Self {
pub fn new(api_backend: Box<dyn CodergenBackend>, 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));
}

View file

@ -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)))
}
});

View file

@ -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());

View file

@ -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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> =
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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> =
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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> = 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<dyn arc_agent::ExecutionEnvironment> = 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(