Skip to content

Commit 6688252

Browse files
committed
chore: bump codex version
1 parent 9506e18 commit 6688252

File tree

11 files changed

+364
-282
lines changed

11 files changed

+364
-282
lines changed

Cargo.lock

Lines changed: 285 additions & 207 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "codex-acp"
33
authors = ["angao<gawaine2111@gmail.com>"]
4-
version = "0.4.1"
4+
version = "0.4.2"
55
edition = "2024"
66
description = "ACP-compatible agent that bridges the OpenAI Codex runtime with ACP clients over stdio."
77
readme = "README.md"
@@ -12,32 +12,33 @@ rust-version = "1.91"
1212
agent-client-protocol = { version = "0.9.2", features = ["unstable"] }
1313
anyhow = { version = "1" }
1414
async-trait = { version = "0.1" }
15+
codex-app-server-protocol = { git = "https://github.com/openai/codex", branch = "main" }
1516
codex-common = { git = "https://github.com/openai/codex", branch = "main", features = [
16-
"cli",
17+
"cli",
1718
] }
1819
codex-core = { git = "https://github.com/openai/codex", branch = "main" }
1920
codex-protocol = { git = "https://github.com/openai/codex", branch = "main" }
20-
codex-app-server-protocol = { git = "https://github.com/openai/codex", branch = "main" }
21+
codex-utils-absolute-path = { git = "https://github.com/openai/codex", branch = "main" }
22+
diffy = { version = "0.4.2" }
23+
rmcp = { version = "0.12.0", features = [
24+
"macros",
25+
"schemars",
26+
"server",
27+
"transport-io",
28+
] }
29+
schemars = { version = "1", features = ["derive"] }
30+
serde = { version = "1.0", features = ["derive"] }
31+
serde_json = { version = "1.0.145", features = ["raw_value"] }
2132
tokio = { version = "1.48.0", features = [
22-
"macros",
23-
"rt",
24-
"io-std",
25-
"io-util",
26-
"net",
27-
"sync",
33+
"io-std",
34+
"io-util",
35+
"macros",
36+
"net",
37+
"rt",
38+
"sync",
2839
] }
2940
tokio-util = { version = "0.7.17", features = ["compat"] }
30-
serde_json = { version = "1.0.145", features = ["raw_value"] }
31-
serde = { version = "1.0", features = ["derive"] }
32-
diffy = { version = "0.4.2" }
3341
tracing = { version = "0.1", features = ["log"] }
42+
tracing-appender = { version = "0.2.3" }
3443
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
3544
uuid = { version = "1", features = ["v4"] }
36-
rmcp = { version = "0.12.0", features = [
37-
"transport-io",
38-
"server",
39-
"macros",
40-
"schemars",
41-
] }
42-
schemars = { version = "1", features = ["derive"] }
43-
tracing-appender = { version = "0.2.3" }

src/agent/commands.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ impl CodexAgent {
1919
items: vec![UserInput::Text {
2020
text: prompt.into(),
2121
}],
22+
final_output_json_schema: None,
2223
})
2324
}
2425
"status" => {

src/agent/config_builder.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,13 @@ impl CodexAgent {
2525
})?;
2626

2727
let mut env = HashMap::new();
28-
env.insert(
29-
"ACP_FS_BRIDGE_ADDR".to_string(),
30-
bridge.address().to_string(),
31-
);
32-
env.insert("ACP_FS_SESSION_ID".to_string(), session_id.to_string());
28+
env.insert("ACP_FS_BRIDGE_ADDR".into(), bridge.address().to_string());
29+
env.insert("ACP_FS_SESSION_ID".into(), session_id.to_owned());
3330

3431
Ok(McpServerConfig {
3532
transport: McpServerTransportConfig::Stdio {
3633
command: exe_path.to_string_lossy().into_owned(),
37-
args: vec!["--acp-fs-mcp".to_string()],
34+
args: vec!["--acp-fs-mcp".into()],
3835
env: Some(env),
3936
env_vars: vec![],
4037
cwd: None,
@@ -47,12 +44,12 @@ impl CodexAgent {
4744
let caps = self.session_manager.client_capabilities();
4845
let mut v: Vec<String> = Vec::new();
4946
if !caps.fs.read_text_file {
50-
v.push("read_text_file".to_string());
47+
v.push("read_text_file".into());
5148
}
5249
if !caps.fs.write_text_file {
53-
v.push("write_text_file".to_string());
54-
v.push("edit_text_file".to_string());
55-
v.push("multi_edit_text_file".to_string());
50+
v.push("write_text_file".into());
51+
v.push("edit_text_file".into());
52+
v.push("multi_edit_text_file".into());
5653
}
5754
if v.is_empty() { None } else { Some(v) }
5855
},

src/agent/events.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl EventHandler {
111111
)))];
112112
let mut meta_map = serde_json::Map::new();
113113
meta_map.insert(
114-
"terminal_info".to_string(),
114+
"terminal_info".into(),
115115
json!({
116116
"terminal_id": call_id,
117117
"cwd": cwd
@@ -230,7 +230,7 @@ impl EventHandler {
230230
}
231231
FileChange::Delete { content } => {
232232
contents.push(ToolCallContent::from(
233-
Diff::new(PathBuf::from(path), "".to_string()).old_text(content.clone()),
233+
Diff::new(PathBuf::from(path), String::new()).old_text(content.clone()),
234234
));
235235
}
236236
FileChange::Update { unified_diff, .. } => {
@@ -243,7 +243,7 @@ impl EventHandler {
243243
}
244244

245245
let title = if changes.len() == 1 {
246-
"Apply changes".to_string()
246+
String::from("Apply changes")
247247
} else {
248248
format!("Edit {} files", changes.len())
249249
};

src/agent/prompt.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl CodexAgent {
3333
pub(super) async fn prompt(&self, args: PromptRequest) -> Result<PromptResponse, Error> {
3434
info!(?args, "Received prompt request");
3535
let event_handler = EventHandler::new(
36-
self.config.cwd.clone(),
36+
self.config.cwd.clone(), // Required: EventHandler stores PathBuf
3737
self.session_manager.support_terminal(),
3838
);
3939
let mut reason = ReasoningAggregator::new();
@@ -97,7 +97,10 @@ impl CodexAgent {
9797

9898
let op = match op_opt {
9999
Some(op) => op,
100-
None => Op::UserInput { items },
100+
None => Op::UserInput {
101+
items,
102+
final_output_json_schema: None,
103+
},
101104
};
102105

103106
// Enqueue work and then stream corresponding events back as ACP updates.
@@ -148,7 +151,7 @@ impl CodexAgent {
148151
&& !text.trim().is_empty()
149152
{
150153
self.session_manager
151-
.send_thought_chunk(&args.session_id, text.clone().into())
154+
.send_thought_chunk(&args.session_id, text.into())
152155
.await?;
153156
}
154157
}
@@ -361,6 +364,7 @@ impl CodexAgent {
361364
| EventMsg::StreamError(StreamErrorEvent {
362365
message,
363366
codex_error_info: _,
367+
additional_details: _,
364368
}) => {
365369
let mut msg = String::from(&message);
366370
msg.push_str("\n\n");

src/agent/session_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl SessionState {
5050
fs_session_id,
5151
conversation,
5252
current_approval: config.approval_policy.value(),
53-
current_sandbox: config.sandbox_policy.clone(),
53+
current_sandbox: config.sandbox_policy.get().clone(),
5454
current_mode,
5555
current_model: Some(format!("{}@{}", provider_id, model_name)),
5656
current_effort: config.model_reasoning_effort,

src/agent/utils.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub fn display_fs_path(cwd: &Path, raw_path: &str) -> String {
109109

110110
path.file_name()
111111
.map(|name| name.to_string_lossy().into_owned())
112-
.unwrap_or_else(|| raw_path.to_string())
112+
.unwrap_or_else(|| raw_path.to_owned())
113113
}
114114

115115
/// Extract FS tool metadata from an MCP invocation, when applicable.
@@ -125,7 +125,7 @@ pub fn fs_tool_metadata(invocation: &McpInvocation, cwd: &Path) -> Option<FsTool
125125
}
126126

127127
let args = invocation.arguments.as_ref()?.as_object()?;
128-
let path = args.get("path")?.as_str()?.to_string();
128+
let path = args.get("path")?.as_str()?.to_owned();
129129
let line = args
130130
.get("line")
131131
.and_then(|value| value.as_u64())
@@ -176,7 +176,7 @@ pub fn current_mode_id_for_config(config: &Config) -> Option<SessionModeId> {
176176
.iter()
177177
.find(|preset| {
178178
preset.approval == config.approval_policy.value()
179-
&& preset.sandbox == config.sandbox_policy
179+
&& preset.sandbox == config.sandbox_policy.get().clone()
180180
})
181181
.map(|preset| SessionModeId::new(preset.id))
182182
}
@@ -197,11 +197,11 @@ pub fn available_modes() -> Vec<SessionMode> {
197197
APPROVAL_PRESETS
198198
.iter()
199199
.map(|preset| {
200-
let mode = SessionMode::new(SessionModeId::new(preset.id), preset.label.to_string());
200+
let mode = SessionMode::new(SessionModeId::new(preset.id), preset.label);
201201
if preset.description.is_empty() {
202202
mode
203203
} else {
204-
mode.description(preset.description.to_string())
204+
mode.description(preset.description)
205205
}
206206
})
207207
.collect()
@@ -263,7 +263,7 @@ pub fn available_models_from_profiles(
263263
}
264264

265265
candidates.push((
266-
provider_id.clone(),
266+
provider_id.as_str(),
267267
(
268268
provider_id.clone(),
269269
model_name.clone(),
@@ -274,7 +274,7 @@ pub fn available_models_from_profiles(
274274
}
275275

276276
// Sort by provider id then model name for stable output.
277-
candidates.sort_by(|a, b| a.0.cmp(&b.0).then_with(|| a.1.1.cmp(&b.1.1)));
277+
candidates.sort_by(|a, b| a.0.cmp(b.0).then_with(|| a.1.1.cmp(&b.1.1)));
278278

279279
for (_provider, (provider_id, model_name, _effort)) in candidates {
280280
let model_id = format!("{}@{}", provider_id, model_name);
@@ -299,7 +299,7 @@ pub fn parse_and_validate_model(
299299
let id_str = model_id.0.as_ref();
300300
let (provider_id, model_name) = id_str
301301
.split_once('@')
302-
.map(|(p, m)| (p.to_string(), m.to_string()))?;
302+
.map(|(p, m)| (p.to_owned(), m.to_owned()))?;
303303

304304
// Validate that the provider exists
305305
if !config.model_providers.contains_key(&provider_id) {

src/fs/bridge.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,14 @@ impl FsBridgeInner {
279279
Some(start_line) => {
280280
let start = start_line.saturating_sub(1) as usize;
281281
let count = limit.unwrap_or(u32::MAX) as usize;
282-
let lines: Vec<&str> = content.lines().collect();
283-
if start >= lines.len() {
282+
283+
// Efficient line slicing: skip + take to avoid collecting all lines
284+
let selected_lines: Vec<&str> = content.lines().skip(start).take(count).collect();
285+
286+
if selected_lines.is_empty() {
284287
Ok(String::new())
285288
} else {
286-
let end = (start + count).min(lines.len());
287-
Ok(lines[start..end].join("\n"))
289+
Ok(selected_lines.join("\n"))
288290
}
289291
}
290292
None => Ok(content),

src/fs/mcp_server.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77
},
88
};
99

10-
use anyhow::{Context, Result, anyhow};
10+
use anyhow::{Context, Result, anyhow, bail};
1111
use diffy::{PatchFormatter, create_patch};
1212
use rmcp::{
1313
ErrorData as McpError, ServerHandler,
@@ -178,15 +178,15 @@ impl FsTools {
178178
});
179179

180180
if truncated && let Some(obj) = meta.as_object_mut() {
181-
obj.insert("next_line".to_string(), json!(end_line.saturating_add(1)));
181+
obj.insert("next_line".into(), json!(end_line.saturating_add(1)));
182182
}
183183

184184
if truncated_by_bytes && let Some(obj) = meta.as_object_mut() {
185-
obj.insert("max_bytes".to_string(), json!(MAX_READ_BYTES));
185+
obj.insert("max_bytes".into(), json!(MAX_READ_BYTES));
186186
}
187187

188188
let mut meta_obj = Meta::new();
189-
meta_obj.insert("codex_fs_read".to_string(), meta);
189+
meta_obj.insert("codex_fs_read".into(), meta);
190190
let content = RawContent::Text(RawTextContent {
191191
text,
192192
meta: Some(meta_obj),
@@ -310,9 +310,9 @@ impl ServerHandler for FsTools {
310310
protocol_version: ProtocolVersion::default(),
311311
capabilities: caps,
312312
server_info: Implementation {
313-
name: "codex-acp-fs".to_string(),
314-
title: Some("Codex ACP Filesystem".to_string()),
315-
version: env!("CARGO_PKG_VERSION").to_string(),
313+
name: "codex-acp-fs".into(),
314+
title: Some("Codex ACP Filesystem".into()),
315+
version: env!("CARGO_PKG_VERSION").into(),
316316
icons: None,
317317
website_url: None,
318318
},
@@ -429,7 +429,7 @@ async fn stage_edits(
429429
)
430430
})?;
431431

432-
staged_edits.stage(path.to_string(), write_content).await;
432+
staged_edits.stage(path.to_owned(), write_content).await;
433433
info!(file = %path, bytes = staged_bytes, "Staged edits committed");
434434

435435
let (new_ranges, old_ranges) = parse_diff_line_ranges(&diff_text);
@@ -440,7 +440,7 @@ async fn stage_edits(
440440
});
441441

442442
let mut meta_obj = Meta::new();
443-
meta_obj.insert("codex_fs_diff".to_string(), diff_meta);
443+
meta_obj.insert("codex_fs_diff".into(), diff_meta);
444444
let diff_content = RawContent::Text(RawTextContent {
445445
text: diff_text,
446446
meta: Some(meta_obj),
@@ -453,27 +453,25 @@ async fn stage_edits(
453453
}
454454

455455
fn apply_edits(base: &str, edits: &[EditInstruction]) -> Result<String> {
456-
let mut content = base.to_string();
456+
let mut content = base.to_owned();
457457
for edit in edits {
458458
if edit.old_text.is_empty() {
459-
return Err(anyhow!(
460-
"the provided `old_string` is empty. No edits were applied."
461-
));
459+
bail!("the provided `old_string` is empty. No edits were applied.")
462460
}
463461

464462
if edit.replace_all {
465463
let replaced = content.replace(&edit.old_text, &edit.new_text);
466464
if replaced == content {
467-
return Err(anyhow!(
465+
bail!(
468466
"The provided `old_string` does not appear in the file. No edits were applied."
469-
));
467+
)
470468
}
471469
content = replaced;
472470
} else {
473471
let Some(index) = content.find(&edit.old_text) else {
474-
return Err(anyhow!(
472+
bail!(
475473
"The provided `old_string` does not appear in the file. No edits were applied."
476-
));
474+
)
477475
};
478476
let end = index + edit.old_text.len();
479477
content.replace_range(index..end, &edit.new_text);

0 commit comments

Comments
 (0)