Skip to main content

codex_cli/agent/
mod.rs

1use std::io::{self, BufRead, Write};
2
3pub mod commit;
4pub mod exec;
5
6pub fn prompt(prompt_args: &[String]) -> i32 {
7    let stdin = io::stdin();
8    let mut stdin = stdin.lock();
9    let stdout = io::stdout();
10    let mut stdout = stdout.lock();
11    let stderr = io::stderr();
12    let mut stderr = stderr.lock();
13    prompt_with_io(prompt_args, &mut stdin, &mut stdout, &mut stderr)
14}
15
16pub fn prompt_with_io<R: BufRead, WOut: Write, WErr: Write>(
17    prompt_args: &[String],
18    stdin: &mut R,
19    stdout: &mut WOut,
20    stderr: &mut WErr,
21) -> i32 {
22    let mut user_prompt = prompt_args.join(" ");
23
24    if user_prompt.is_empty() {
25        if write!(stdout, "Prompt: ").is_err() {
26            return 1;
27        }
28        let _ = stdout.flush();
29
30        user_prompt.clear();
31        if stdin
32            .read_line(&mut user_prompt)
33            .ok()
34            .filter(|n| *n > 0)
35            .is_none()
36        {
37            return 1;
38        }
39        user_prompt = user_prompt.trim_end_matches(&['\n', '\r'][..]).to_string();
40    }
41
42    if user_prompt.is_empty() {
43        let _ = writeln!(stderr, "codex-tools: missing prompt");
44        return 1;
45    }
46
47    exec::exec_dangerous(&user_prompt, "codex-tools:prompt", stderr)
48}
49
50pub fn advice(question_args: &[String]) -> i32 {
51    let stdin = io::stdin();
52    let mut stdin = stdin.lock();
53    let stdout = io::stdout();
54    let mut stdout = stdout.lock();
55    let stderr = io::stderr();
56    let mut stderr = stderr.lock();
57    run_template_with_io(
58        "actionable-advice",
59        question_args,
60        &mut stdin,
61        &mut stdout,
62        &mut stderr,
63    )
64}
65
66pub fn knowledge(concept_args: &[String]) -> i32 {
67    let stdin = io::stdin();
68    let mut stdin = stdin.lock();
69    let stdout = io::stdout();
70    let mut stdout = stdout.lock();
71    let stderr = io::stderr();
72    let mut stderr = stderr.lock();
73    run_template_with_io(
74        "actionable-knowledge",
75        concept_args,
76        &mut stdin,
77        &mut stdout,
78        &mut stderr,
79    )
80}
81
82fn run_template_with_io<R: BufRead, WOut: Write, WErr: Write>(
83    template_name: &str,
84    args: &[String],
85    stdin: &mut R,
86    stdout: &mut WOut,
87    stderr: &mut WErr,
88) -> i32 {
89    let mut user_query = args.join(" ");
90    if user_query.trim().is_empty() {
91        if write!(stdout, "Question: ").is_err() {
92            return 1;
93        }
94        let _ = stdout.flush();
95
96        user_query.clear();
97        if stdin
98            .read_line(&mut user_query)
99            .ok()
100            .filter(|n| *n > 0)
101            .is_none()
102        {
103            return 1;
104        }
105        user_query = user_query.trim_end_matches(&['\n', '\r'][..]).to_string();
106    }
107
108    if user_query.trim().is_empty() {
109        let _ = writeln!(stderr, "codex-tools: missing question");
110        return 1;
111    }
112
113    let template_content = match crate::prompts::read_template(template_name) {
114        Ok((_path, content)) => content,
115        Err(crate::prompts::PromptTemplateError::TemplateMissing { path }) => {
116            let _ = writeln!(
117                stderr,
118                "codex-tools: prompt template not found: {}",
119                path.to_string_lossy()
120            );
121            return 1;
122        }
123        Err(crate::prompts::PromptTemplateError::ReadFailed { path }) => {
124            let _ = writeln!(
125                stderr,
126                "codex-tools: failed to read prompt template: {}",
127                path.to_string_lossy()
128            );
129            return 1;
130        }
131        Err(crate::prompts::PromptTemplateError::PromptsDirNotFound) => return 1,
132    };
133
134    let final_prompt = template_content.replace("$ARGUMENTS", &user_query);
135    exec::exec_dangerous(
136        &final_prompt,
137        &format!("codex-tools:{template_name}"),
138        stderr,
139    )
140}