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