mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
Rename AgentBackend → AgentApiBackend and CliBackend → AgentCliBackend
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a535c6575f
commit
1a95cd6664
6 changed files with 45 additions and 45 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue