zag_agent/providers/
common.rs1use crate::output::AgentOutput;
2use crate::sandbox::SandboxConfig;
3use anyhow::Context;
4use std::path::Path;
5use std::process::Stdio;
6use tokio::process::Command;
7
8pub struct CommonAgentState {
13 pub system_prompt: String,
14 pub model: String,
15 pub root: Option<String>,
16 pub skip_permissions: bool,
17 pub output_format: Option<String>,
18 pub add_dirs: Vec<String>,
19 pub capture_output: bool,
20 pub sandbox: Option<SandboxConfig>,
21 pub max_turns: Option<u32>,
22 pub env_vars: Vec<(String, String)>,
23}
24
25impl CommonAgentState {
26 pub fn new(default_model: &str) -> Self {
27 Self {
28 system_prompt: String::new(),
29 model: default_model.to_string(),
30 root: None,
31 skip_permissions: false,
32 output_format: None,
33 add_dirs: Vec::new(),
34 capture_output: false,
35 sandbox: None,
36 max_turns: None,
37 env_vars: Vec::new(),
38 }
39 }
40
41 pub fn get_base_path(&self) -> &Path {
43 self.root.as_ref().map(Path::new).unwrap_or(Path::new("."))
44 }
45
46 pub fn make_command(&self, binary_name: &str, agent_args: Vec<String>) -> Command {
52 if let Some(ref sb) = self.sandbox {
53 let std_cmd = crate::sandbox::build_sandbox_command(sb, agent_args);
54 Command::from(std_cmd)
55 } else {
56 let mut cmd = Command::new(binary_name);
57 if let Some(ref root) = self.root {
58 cmd.current_dir(root);
59 }
60 cmd.args(&agent_args);
61 for (key, value) in &self.env_vars {
62 cmd.env(key, value);
63 }
64 cmd
65 }
66 }
67
68 pub async fn run_interactive_command(
72 cmd: &mut Command,
73 agent_display_name: &str,
74 ) -> anyhow::Result<()> {
75 cmd.stdin(Stdio::inherit())
76 .stdout(Stdio::inherit())
77 .stderr(Stdio::inherit());
78 let status = cmd.status().await.with_context(|| {
79 format!(
80 "Failed to execute '{}' CLI. Is it installed and in PATH?",
81 agent_display_name.to_lowercase()
82 )
83 })?;
84 if !status.success() {
85 return Err(crate::process::ProcessError {
86 exit_code: status.code(),
87 stderr: String::new(),
88 agent_name: agent_display_name.to_string(),
89 }
90 .into());
91 }
92 Ok(())
93 }
94
95 pub async fn run_non_interactive_simple(
103 &self,
104 cmd: &mut Command,
105 agent_display_name: &str,
106 ) -> anyhow::Result<Option<AgentOutput>> {
107 if self.capture_output {
108 let text = crate::process::run_captured(cmd, agent_display_name).await?;
109 log::debug!(
110 "{} raw response ({} bytes): {}",
111 agent_display_name,
112 text.len(),
113 text
114 );
115 Ok(Some(AgentOutput::from_text(
116 &agent_display_name.to_lowercase(),
117 &text,
118 )))
119 } else {
120 cmd.stdin(Stdio::inherit()).stdout(Stdio::inherit());
121 crate::process::run_with_captured_stderr(cmd).await?;
122 Ok(None)
123 }
124 }
125}
126
127macro_rules! impl_common_agent_setters {
132 () => {
133 fn system_prompt(&self) -> &str {
134 &self.common.system_prompt
135 }
136
137 fn set_system_prompt(&mut self, prompt: String) {
138 self.common.system_prompt = prompt;
139 }
140
141 fn get_model(&self) -> &str {
142 &self.common.model
143 }
144
145 fn set_model(&mut self, model: String) {
146 self.common.model = model;
147 }
148
149 fn set_root(&mut self, root: String) {
150 self.common.root = Some(root);
151 }
152
153 fn set_output_format(&mut self, format: Option<String>) {
154 self.common.output_format = format;
155 }
156
157 fn set_add_dirs(&mut self, dirs: Vec<String>) {
158 self.common.add_dirs = dirs;
159 }
160
161 fn set_env_vars(&mut self, vars: Vec<(String, String)>) {
162 self.common.env_vars = vars;
163 }
164
165 fn set_capture_output(&mut self, capture: bool) {
166 self.common.capture_output = capture;
167 }
168
169 fn set_sandbox(&mut self, config: crate::sandbox::SandboxConfig) {
170 self.common.sandbox = Some(config);
171 }
172
173 fn set_max_turns(&mut self, turns: u32) {
174 self.common.max_turns = Some(turns);
175 }
176 };
177}
178pub(crate) use impl_common_agent_setters;
179
180macro_rules! impl_as_any {
182 () => {
183 fn as_any_ref(&self) -> &dyn std::any::Any {
184 self
185 }
186
187 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
188 self
189 }
190 };
191}
192pub(crate) use impl_as_any;