kcode_codex_runtime/model.rs
1use std::{path::PathBuf, time::Duration};
2
3use crate::DEFAULT_CODEX_EXECUTABLE;
4
5/// Maximum model reasoning effort.
6#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
7pub enum ReasoningEffort {
8 /// Disable reasoning when supported.
9 None,
10 /// Minimal reasoning.
11 Minimal,
12 /// Low reasoning.
13 Low,
14 /// Medium reasoning.
15 Medium,
16 /// High reasoning.
17 High,
18 /// Extra-high reasoning.
19 #[default]
20 XHigh,
21 /// Maximum reasoning when supported.
22 Max,
23}
24
25impl ReasoningEffort {
26 /// Returns the Codex configuration value.
27 pub const fn as_str(self) -> &'static str {
28 match self {
29 Self::None => "none",
30 Self::Minimal => "minimal",
31 Self::Low => "low",
32 Self::Medium => "medium",
33 Self::High => "high",
34 Self::XHigh => "xhigh",
35 Self::Max => "max",
36 }
37 }
38}
39
40/// Codex web-search context allocation.
41#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
42pub enum WebSearchContext {
43 /// Low-latency, narrow search context.
44 Low,
45 /// Default search context.
46 Medium,
47 /// Broad search context.
48 High,
49}
50
51impl WebSearchContext {
52 pub(crate) const fn as_str(self) -> &'static str {
53 match self {
54 Self::Low => "low",
55 Self::Medium => "medium",
56 Self::High => "high",
57 }
58 }
59}
60
61/// Research breadth requested from Codex.
62#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
63pub enum SearchDepth {
64 /// Focused research that stops once adequate evidence is available.
65 Focused,
66 /// Thorough bounded research that resolves material conflicts.
67 Thorough,
68}
69
70/// Runtime configuration shared by generation and web search.
71#[derive(Clone, Debug, Eq, PartialEq)]
72pub struct CodexConfig {
73 /// Codex or sandbox-launcher executable.
74 pub executable: String,
75 /// Directory supplied to Codex as its working directory.
76 pub working_directory: PathBuf,
77 /// Fixed application instruction supplied for ordinary generation.
78 pub base_instruction: String,
79 /// Model used for startup prompt-boundary validation.
80 pub validation_model: String,
81 /// Reasoning setting used for startup prompt-boundary validation.
82 pub validation_reasoning_effort: ReasoningEffort,
83}
84
85impl CodexConfig {
86 /// Constructs a configuration for one validation model.
87 pub fn new(validation_model: impl Into<String>) -> Self {
88 Self {
89 executable: DEFAULT_CODEX_EXECUTABLE.into(),
90 working_directory: std::env::temp_dir(),
91 base_instruction: String::new(),
92 validation_model: validation_model.into(),
93 validation_reasoning_effort: ReasoningEffort::XHigh,
94 }
95 }
96}
97
98/// One ordinary Codex generation request.
99#[derive(Clone, Debug, Eq, PartialEq)]
100pub struct GenerationRequest {
101 /// Exact model-visible prompt text.
102 pub prompt: String,
103 /// Codex model identifier.
104 pub model: String,
105 /// Requested reasoning effort.
106 pub reasoning_effort: ReasoningEffort,
107 /// Existing Codex thread identifier to resume, when any.
108 pub previous_thread_id: Option<String>,
109 /// Whether a fresh thread should avoid persistent Codex session storage.
110 pub ephemeral: bool,
111 /// Maximum wall-clock duration.
112 pub timeout: Duration,
113}
114
115impl GenerationRequest {
116 /// Constructs a fresh generation request.
117 pub fn new(prompt: impl Into<String>, model: impl Into<String>) -> Self {
118 Self {
119 prompt: prompt.into(),
120 model: model.into(),
121 reasoning_effort: ReasoningEffort::XHigh,
122 previous_thread_id: None,
123 ephemeral: false,
124 timeout: Duration::from_secs(10 * 60),
125 }
126 }
127}
128
129/// Normalized token accounting from one Codex turn.
130#[derive(Clone, Debug, Default, Eq, PartialEq)]
131pub struct TokenUsage {
132 /// Total input tokens reported for the thread.
133 pub input_tokens: u64,
134 /// Total output tokens reported for the thread.
135 pub output_tokens: u64,
136 /// Cached input tokens.
137 pub cached_input_tokens: u64,
138 /// Reasoning output tokens.
139 pub reasoning_output_tokens: u64,
140 /// Input tokens for only the most recent turn, when reported.
141 pub last_input_tokens: Option<u64>,
142 /// Output tokens for only the most recent turn, when reported.
143 pub last_output_tokens: Option<u64>,
144}
145
146/// Successful ordinary Codex generation.
147#[derive(Clone, Debug, Eq, PartialEq)]
148pub struct GenerationResponse {
149 /// Codex thread identifier used for continuation.
150 pub thread_id: String,
151 /// Final non-empty assistant message.
152 pub answer: String,
153 /// Provider usage, when reported.
154 pub usage: Option<TokenUsage>,
155}
156
157/// One Codex web-search request.
158#[derive(Clone, Debug, Eq, PartialEq)]
159pub struct WebSearchRequest {
160 /// Research question.
161 pub question: String,
162 /// Codex model identifier.
163 pub model: String,
164 /// Requested reasoning effort.
165 pub reasoning_effort: ReasoningEffort,
166 /// Provider web-search context allocation.
167 pub context: WebSearchContext,
168 /// Desired research breadth.
169 pub depth: SearchDepth,
170 /// Fixed application-selected wall-clock limit.
171 pub timeout: Duration,
172}
173
174/// One normalized public HTTP(S) source found in a Codex answer.
175#[derive(Clone, Debug, Eq, PartialEq)]
176pub struct WebSource {
177 /// Source title derived from the Markdown link when available.
178 pub title: String,
179 /// Canonical public HTTP(S) URL.
180 pub url: String,
181}
182
183/// Successful Codex web research.
184#[derive(Clone, Debug, Eq, PartialEq)]
185pub struct WebSearchResponse {
186 /// Evidence-focused answer text.
187 pub answer: String,
188 /// All deduplicated HTTP(S) sources present in the answer.
189 pub sources: Vec<WebSource>,
190 /// Provider usage, when reported.
191 pub usage: Option<TokenUsage>,
192}