pub mod context; pub mod events; pub(crate) mod handlers; pub mod orchestrator; pub mod parallel; pub mod registry; pub mod router; pub mod runtimes; pub mod sandboxing; pub mod spec; use crate::context_manager::format_output_for_model_body; use crate::exec::ExecToolCallOutput; pub use router::ToolRouter; use serde::Serialize; // Telemetry preview limits: keep log events smaller than model budgets. pub(crate) const TELEMETRY_PREVIEW_MAX_BYTES: usize = 2 * 1024; // 2 KiB pub(crate) const TELEMETRY_PREVIEW_MAX_LINES: usize = 64; // lines pub(crate) const TELEMETRY_PREVIEW_TRUNCATION_NOTICE: &str = "[... telemetry preview truncated ...]"; /// Format the combined exec output for sending back to the model. /// Includes exit code and duration metadata; truncates large bodies safely. pub fn format_exec_output_for_model(exec_output: &ExecToolCallOutput) -> String { let ExecToolCallOutput { exit_code, duration, .. } = exec_output; #[derive(Serialize)] struct ExecMetadata { exit_code: i32, duration_seconds: f32, } #[derive(Serialize)] struct ExecOutput<'a> { output: &'a str, metadata: ExecMetadata, } // round to 1 decimal place let duration_seconds = ((duration.as_secs_f32()) * 10.0).round() / 10.0; let formatted_output = format_exec_output_str(exec_output); let payload = ExecOutput { output: &formatted_output, metadata: ExecMetadata { exit_code: *exit_code, duration_seconds, }, }; #[expect(clippy::expect_used)] serde_json::to_string(&payload).expect("serialize ExecOutput") } pub fn format_exec_output_str(exec_output: &ExecToolCallOutput) -> String { let ExecToolCallOutput { aggregated_output, .. } = exec_output; let content = aggregated_output.text.as_str(); let body = if exec_output.timed_out { format!( "command timed out after {} milliseconds\n{content}", exec_output.duration.as_millis() ) } else { content.to_string() }; // Truncate for model consumption before serialization. format_output_for_model_body(&body) }