Skip to main content

atomr_agents_coding_cli_vendor_codex/
lib.rs

1//! OpenAI Codex CLI adapter.
2
3#![forbid(unsafe_code)]
4
5mod command;
6mod mapper;
7mod parser;
8
9use std::path::Path;
10
11use async_trait::async_trait;
12
13use atomr_agents_coding_cli_core::{
14    CliCommand, CliEventParser, CliRequest, CliVendor, CliVendorKind, ConceptProjection,
15    MapperError,
16};
17
18pub use command::{build_headless, build_interactive};
19pub use mapper::materialize as materialize_codex_config;
20pub use parser::CodexParser;
21
22#[derive(Debug, Clone, Default)]
23pub struct CodexVendor;
24
25impl CodexVendor {
26    pub fn new() -> Self {
27        Self
28    }
29}
30
31#[async_trait]
32impl CliVendor for CodexVendor {
33    fn kind(&self) -> CliVendorKind {
34        CliVendorKind::Codex
35    }
36
37    fn label(&self) -> &str {
38        "OpenAI Codex"
39    }
40
41    fn build_headless_command(&self, req: &CliRequest, workdir: &Path) -> CliCommand {
42        build_headless(req, workdir)
43    }
44
45    fn build_interactive_command(&self, req: &CliRequest, workdir: &Path) -> CliCommand {
46        build_interactive(req, workdir)
47    }
48
49    fn new_parser(&self) -> Box<dyn CliEventParser> {
50        Box::new(CodexParser::new())
51    }
52
53    async fn materialize_config(
54        &self,
55        projection: &ConceptProjection,
56        workdir: &Path,
57    ) -> Result<(), MapperError> {
58        materialize_codex_config(projection, workdir).await
59    }
60
61    async fn is_available(&self) -> bool {
62        tokio::process::Command::new("which")
63            .arg("codex")
64            .output()
65            .await
66            .map(|o| o.status.success())
67            .unwrap_or(false)
68    }
69}