agent_first_mail/
runner.rs1mod dispatch;
2mod lock;
3mod output;
4mod purge;
5mod push;
6
7pub use dispatch::execute_command;
8pub use output::{emit_result, emit_value};
9
10use crate::cli::Command;
11use crate::progress::{object_with_phase, ProgressCallback};
12use agent_first_data::OutputFormat;
13use dispatch::execute_command_with_progress;
14use output::{command_name, log_enabled, log_event, output_format_name, redact_argv};
15use serde_json::{json, Value};
16use std::time::Instant;
17
18pub fn run_command(
19 command: Command,
20 output: OutputFormat,
21 log_filters: &[String],
22 argv: &[String],
23) -> i32 {
24 let started = Instant::now();
25 let command_name = command_name(&command).to_string();
26 if log_enabled(log_filters, "startup") {
27 let argv = redact_argv(argv);
28 emit_value(
29 &log_event(
30 "startup",
31 "info",
32 json!({
33 "version": env!("CARGO_PKG_VERSION"),
34 "argv": argv,
35 "command": command_name.as_str(),
36 "output_format": output_format_name(output),
37 "log_filters": log_filters,
38 }),
39 0,
40 ),
41 output,
42 );
43 }
44 if log_enabled(log_filters, "request") {
45 let cwd = std::env::current_dir()
46 .map(|path| path.to_string_lossy().replace('\\', "/"))
47 .unwrap_or_default();
48 emit_value(
49 &log_event(
50 "request",
51 "info",
52 json!({
53 "phase": "start",
54 "command": command_name.as_str(),
55 "cwd_path": cwd,
56 }),
57 0,
58 ),
59 output,
60 );
61 }
62
63 let progress_enabled = log_enabled(log_filters, "progress");
64 let mut emit_progress = |phase: &str, fields: Value| {
65 emit_value(
66 &log_event(
67 "progress",
68 "info",
69 object_with_phase(phase, fields),
70 started.elapsed().as_millis() as u64,
71 ),
72 output,
73 );
74 };
75 let progress = if progress_enabled {
76 Some(&mut emit_progress as &mut ProgressCallback<'_>)
77 } else {
78 None
79 };
80 let result = execute_command_with_progress(command, progress);
81 let duration_ms = started.elapsed().as_millis() as u64;
82 if let Err(err) = &result {
83 if err.retryable && log_enabled(log_filters, "retry") {
84 emit_value(
85 &log_event(
86 "retry",
87 "warn",
88 json!({
89 "phase": "retryable_error",
90 "command": command_name.as_str(),
91 "error_code": err.error_code,
92 "error": err.message,
93 }),
94 duration_ms,
95 ),
96 output,
97 );
98 }
99 }
100 if log_enabled(log_filters, "progress") {
101 emit_value(
102 &log_event(
103 "progress",
104 "info",
105 json!({
106 "phase": "finish",
107 "command": command_name.as_str(),
108 "success": result.is_ok(),
109 "exit_code": if result.is_ok() { 0 } else { 1 },
110 }),
111 duration_ms,
112 ),
113 output,
114 );
115 }
116 emit_result(result, output, duration_ms)
117}