mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-04 02:33:56 +00:00
refactor(run): drop debug-only node artifact files
Remove API/CLI request and log artifact writes plus panic.txt now that run state and events are store-backed. Update the direct tests to assert returned behavior instead of on-disk debug files.
This commit is contained in:
parent
679728a1a8
commit
58a1380865
7 changed files with 20 additions and 103 deletions
|
|
@ -25,8 +25,6 @@ async fn run_real_cli_test(provider: Provider, model: &str) {
|
|||
|
||||
let context = Context::new();
|
||||
let emitter = Arc::new(EventEmitter::default());
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
let result = backend
|
||||
.run(
|
||||
&node,
|
||||
|
|
@ -34,7 +32,7 @@ async fn run_real_cli_test(provider: Provider, model: &str) {
|
|||
&context,
|
||||
None,
|
||||
&emitter,
|
||||
dir.path(),
|
||||
workspace.path(),
|
||||
&env,
|
||||
None,
|
||||
)
|
||||
|
|
@ -56,29 +54,6 @@ async fn run_real_cli_test(provider: Provider, model: &str) {
|
|||
}
|
||||
CodergenResult::Full(_) => panic!("expected Text result from {provider}/{model}"),
|
||||
}
|
||||
|
||||
// Verify log files were written
|
||||
let provider_path = dir.path().join("provider_used.json");
|
||||
assert!(
|
||||
provider_path.exists(),
|
||||
"{provider}/{model}: provider_used.json should exist"
|
||||
);
|
||||
let provider_json: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(&provider_path).unwrap()).unwrap();
|
||||
assert_eq!(provider_json["mode"], "cli");
|
||||
assert_eq!(provider_json["provider"], provider.as_str());
|
||||
|
||||
// Verify CLI output was streamed to stage_dir during poll
|
||||
let stdout_log = dir.path().join("cli_stdout.log");
|
||||
assert!(
|
||||
stdout_log.exists(),
|
||||
"{provider}/{model}: cli_stdout.log should be written during poll"
|
||||
);
|
||||
let stdout_content = std::fs::read_to_string(&stdout_log).unwrap();
|
||||
assert!(
|
||||
!stdout_content.is_empty(),
|
||||
"{provider}/{model}: cli_stdout.log should not be empty"
|
||||
);
|
||||
}
|
||||
|
||||
#[fabro_macros::e2e_test(live("ANTHROPIC_API_KEY"))]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use fabro_llm::types::{Message, Request, Usage};
|
|||
use fabro_mcp::config::McpServerSettings;
|
||||
use fabro_model::FallbackTarget;
|
||||
use fabro_model::Provider;
|
||||
use tokio::fs;
|
||||
use tokio::sync::Mutex as TokioMutex;
|
||||
|
||||
use super::super::agent::{CodergenBackend, CodergenResult};
|
||||
|
|
@ -269,7 +268,7 @@ impl CodergenBackend for AgentApiBackend {
|
|||
node: &Node,
|
||||
prompt: &str,
|
||||
system_prompt: Option<&str>,
|
||||
stage_dir: &std::path::Path,
|
||||
_stage_dir: &std::path::Path,
|
||||
) -> Result<CodergenResult, FabroError> {
|
||||
let client = Client::from_env()
|
||||
.await
|
||||
|
|
@ -310,11 +309,6 @@ impl CodergenBackend for AgentApiBackend {
|
|||
provider_options: None,
|
||||
};
|
||||
|
||||
let _ = fs::create_dir_all(stage_dir).await;
|
||||
if let Ok(json) = serde_json::to_string_pretty(&request) {
|
||||
let _ = fs::write(stage_dir.join("api_request.json"), json).await;
|
||||
}
|
||||
|
||||
// Build per-request fallback chain: if the node overrides the provider,
|
||||
// no failover is available; otherwise use the backend's.
|
||||
let fallback_chain: &[FallbackTarget] = if node.provider().is_some() {
|
||||
|
|
@ -391,10 +385,6 @@ impl CodergenBackend for AgentApiBackend {
|
|||
Err(sdk_err) => return Err(FabroError::Llm(sdk_err)),
|
||||
};
|
||||
|
||||
if let Ok(json) = serde_json::to_string_pretty(&response) {
|
||||
let _ = fs::write(stage_dir.join("api_response.json"), json).await;
|
||||
}
|
||||
|
||||
let mut stage_usage = StageUsage {
|
||||
model: actual_model,
|
||||
input_tokens: response.usage.input_tokens,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use async_trait::async_trait;
|
|||
use fabro_agent::Sandbox;
|
||||
use fabro_agent::sandbox::ExecResult;
|
||||
use fabro_model::Provider;
|
||||
use tokio::fs;
|
||||
use tokio::time::sleep;
|
||||
|
||||
use super::super::agent::{CodergenBackend, CodergenResult};
|
||||
|
|
@ -466,7 +465,7 @@ impl CodergenBackend for AgentCliBackend {
|
|||
_context: &Context,
|
||||
_thread_id: Option<&str>,
|
||||
emitter: &Arc<EventEmitter>,
|
||||
stage_dir: &Path,
|
||||
_stage_dir: &Path,
|
||||
sandbox: &Arc<dyn Sandbox>,
|
||||
_tool_hooks: Option<Arc<dyn fabro_agent::ToolHookCallback>>,
|
||||
) -> Result<CodergenResult, FabroError> {
|
||||
|
|
@ -508,8 +507,6 @@ impl CodergenBackend for AgentCliBackend {
|
|||
command: command.clone(),
|
||||
});
|
||||
|
||||
let _ = fs::create_dir_all(stage_dir).await;
|
||||
|
||||
// Forward provider API key and custom env vars so the CLI tool can authenticate.
|
||||
// Build a HashMap to pass via exec_command's env_vars parameter — this
|
||||
// prepends `export` statements directly into the base64-encoded command,
|
||||
|
|
@ -602,21 +599,6 @@ impl CodergenBackend for AgentCliBackend {
|
|||
.map_err(|e| FabroError::handler(format!("Failed to poll CLI command: {e}")))?;
|
||||
let status = poll_result.stdout.trim();
|
||||
|
||||
// Sync CLI output to stage_dir for visibility (best-effort)
|
||||
for (remote, local) in [
|
||||
(&stdout_path, "cli_stdout.log"),
|
||||
(&stderr_path, "cli_stderr.log"),
|
||||
] {
|
||||
if let Ok(r) = sandbox
|
||||
.exec_command(&format!("cat {remote}"), 30_000, None, None, None)
|
||||
.await
|
||||
{
|
||||
if !r.stdout.is_empty() {
|
||||
let _ = fs::write(stage_dir.join(local), &r.stdout).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if status != "running" {
|
||||
break status.parse::<i32>().unwrap_or(-1);
|
||||
}
|
||||
|
|
@ -653,19 +635,7 @@ impl CodergenBackend for AgentCliBackend {
|
|||
.exec_command(&format!("rm -f {tmp_prefix}_*"), 30_000, None, None, None)
|
||||
.await;
|
||||
|
||||
if let Ok(json) = serde_json::to_string_pretty(&serde_json::json!({
|
||||
"exit_code": result.exit_code,
|
||||
"stdout_len": result.stdout.len(),
|
||||
"stderr_len": result.stderr.len(),
|
||||
"duration_ms": result.duration_ms,
|
||||
})) {
|
||||
let _ = fs::write(stage_dir.join("cli_result_meta.json"), json).await;
|
||||
}
|
||||
|
||||
if result.exit_code != 0 {
|
||||
let _ = fs::write(stage_dir.join("cli_stdout.log"), &result.stdout).await;
|
||||
let _ = fs::write(stage_dir.join("cli_stderr.log"), &result.stderr).await;
|
||||
|
||||
let tail = |s: &str, n: usize| -> String {
|
||||
s.chars()
|
||||
.rev()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ use crate::graph::WorkflowNode;
|
|||
use crate::handler::{EngineServices, dispatch_handler, format_panic_message};
|
||||
use crate::outcome::{Outcome, StageStatus};
|
||||
use crate::retry::build_retry_policy;
|
||||
use crate::run_dir;
|
||||
use fabro_graphviz::graph::types::Graph as GvGraph;
|
||||
use tokio::time::timeout;
|
||||
|
||||
|
|
@ -100,10 +99,6 @@ impl NodeHandler<WorkflowGraph> for WorkflowNodeHandler {
|
|||
}
|
||||
Err(panic_payload) => {
|
||||
let msg = format_panic_message(&panic_payload);
|
||||
let visit = context.node_visit_count().max(1);
|
||||
let panic_dir = run_dir::node_dir(&self.run_dir, &gv_node.id, visit);
|
||||
let _ = std::fs::create_dir_all(&panic_dir);
|
||||
let _ = std::fs::write(panic_dir.join("panic.txt"), &msg);
|
||||
Err(CoreError::handler(HandlerErrorDetail {
|
||||
message: msg,
|
||||
retryable: false,
|
||||
|
|
|
|||
|
|
@ -768,7 +768,7 @@ async fn max_node_visits_errors_on_cycle() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn panic_handler_writes_panic_txt() {
|
||||
async fn panic_handler_returns_panic_message() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let mut g = Graph::new("panic_test");
|
||||
let mut start = Node::new("start");
|
||||
|
|
@ -790,7 +790,7 @@ async fn panic_handler_writes_panic_txt() {
|
|||
|
||||
let mut registry = make_registry();
|
||||
registry.register("panicker", Box::new(PanickingHandler));
|
||||
let _ = run_graph(
|
||||
let result = run_graph(
|
||||
registry,
|
||||
test_emitter_arc("test-run"),
|
||||
local_env(),
|
||||
|
|
@ -799,10 +799,10 @@ async fn panic_handler_writes_panic_txt() {
|
|||
)
|
||||
.await;
|
||||
|
||||
let outcome = result.expect("runner should convert panic into a failed outcome");
|
||||
assert_eq!(outcome.status, StageStatus::Fail);
|
||||
let panic_path = dir.path().join("nodes").join("boom").join("panic.txt");
|
||||
assert!(panic_path.exists());
|
||||
let content = std::fs::read_to_string(&panic_path).unwrap();
|
||||
assert!(content.contains("test panic message"));
|
||||
assert!(!panic_path.exists(), "panic.txt should not be written");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
|||
|
|
@ -982,16 +982,6 @@ async fn run_daytona_cli_test(provider: Provider, model: &str, install_command:
|
|||
Err(e) => panic!("{provider}/{model} on Daytona failed: {e}"),
|
||||
}
|
||||
|
||||
// Verify log files
|
||||
let provider_path = dir.path().join("provider_used.json");
|
||||
assert!(
|
||||
provider_path.exists(),
|
||||
"{provider}/{model}: provider_used.json should exist"
|
||||
);
|
||||
let provider_json: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(&provider_path).unwrap()).unwrap();
|
||||
assert_eq!(provider_json["mode"], "cli");
|
||||
|
||||
env.cleanup().await.unwrap();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9475,7 +9475,7 @@ async fn cli_backend_run_uses_node_provider_override() {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn cli_backend_run_writes_provider_used_json() {
|
||||
async fn cli_backend_run_returns_text_and_usage() {
|
||||
let claude_output =
|
||||
r#"{"type":"result","result":"done","usage":{"input_tokens":10,"output_tokens":5}}"#;
|
||||
let env: Arc<dyn fabro_agent::Sandbox> = Arc::new(CliTestEnv::new(claude_output));
|
||||
|
|
@ -9487,7 +9487,7 @@ async fn cli_backend_run_writes_provider_used_json() {
|
|||
let emitter = Arc::new(EventEmitter::default());
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
backend
|
||||
let result = backend
|
||||
.run(
|
||||
&node,
|
||||
"test",
|
||||
|
|
@ -9501,19 +9501,16 @@ async fn cli_backend_run_writes_provider_used_json() {
|
|||
.await
|
||||
.expect("should succeed");
|
||||
|
||||
let provider_path = dir.path().join("provider_used.json");
|
||||
assert!(provider_path.exists(), "should write provider_used.json");
|
||||
let provider_json: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(&provider_path).unwrap()).unwrap();
|
||||
assert_eq!(provider_json["mode"], "cli");
|
||||
assert_eq!(provider_json["provider"], "anthropic");
|
||||
assert_eq!(provider_json["model"], "claude-opus-4-6");
|
||||
assert!(
|
||||
provider_json["command"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.contains("claude")
|
||||
);
|
||||
match result {
|
||||
CodergenResult::Text { text, usage, .. } => {
|
||||
assert_eq!(text, "done");
|
||||
let usage = usage.expect("CLI backend should report usage");
|
||||
assert_eq!(usage.input_tokens, 10);
|
||||
assert_eq!(usage.output_tokens, 5);
|
||||
assert_eq!(usage.model, "claude-opus-4-6");
|
||||
}
|
||||
CodergenResult::Full(_) => panic!("expected Text result"),
|
||||
}
|
||||
}
|
||||
|
||||
// -- BackendRouter e2e: delegates to correct backend --
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue