Skip to content

Commit e35e616

Browse files
author
Lee Penkman
committed
Merge remote-tracking branch 'upstream/main'
# Conflicts: # codex-rs/Cargo.lock # codex-rs/cli/Cargo.toml # codex-rs/cli/src/doctor.rs # codex-rs/cli/src/doctor/output.rs # codex-rs/cli/src/doctor/output/detail.rs # codex-rs/code-mode/src/runtime/mod.rs # codex-rs/code-mode/src/service.rs # codex-rs/core-plugins/src/remote/share.rs # codex-rs/core-plugins/src/remote/share/tests.rs # codex-rs/core-plugins/src/remote_bundle.rs # codex-rs/core/src/tools/code_mode/execute_handler.rs
2 parents 480f84e + 9f42c89 commit e35e616

11 files changed

Lines changed: 570 additions & 246 deletions

File tree

codex-rs/code-mode/src/runtime/callbacks.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ pub(super) fn store_callback(
160160
}
161161
};
162162
if let Some(state) = scope.get_slot_mut::<RuntimeState>() {
163-
state.stored_values.insert(key, serialized);
163+
state.stored_values.insert(key.clone(), serialized.clone());
164+
state.stored_value_writes.insert(key, serialized);
164165
}
165166
}
166167

codex-rs/code-mode/src/runtime/mod.rs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ pub struct ExecuteRequest {
3434
pub tool_call_id: String,
3535
pub enabled_tools: Vec<ToolDefinition>,
3636
pub source: String,
37-
pub stored_values: HashMap<String, JsonValue>,
3837
pub yield_time_ms: Option<u64>,
3938
pub max_output_tokens: Option<usize>,
4039
}
@@ -82,7 +81,6 @@ pub enum RuntimeResponse {
8281
Result {
8382
cell_id: String,
8483
content_items: Vec<FunctionCallOutputContentItem>,
85-
stored_values: HashMap<String, JsonValue>,
8684
error_text: Option<String>,
8785
},
8886
}
@@ -133,12 +131,13 @@ pub(crate) enum RuntimeEvent {
133131
text: String,
134132
},
135133
Result {
136-
stored_values: HashMap<String, JsonValue>,
134+
stored_value_writes: HashMap<String, JsonValue>,
137135
error_text: Option<String>,
138136
},
139137
}
140138

141139
pub(crate) fn spawn_runtime(
140+
stored_values: HashMap<String, JsonValue>,
142141
request: ExecuteRequest,
143142
event_tx: mpsc::UnboundedSender<RuntimeEvent>,
144143
) -> Result<(std_mpsc::Sender<RuntimeCommand>, v8::IsolateHandle), String> {
@@ -156,7 +155,7 @@ pub(crate) fn spawn_runtime(
156155
tool_call_id: request.tool_call_id,
157156
enabled_tools,
158157
source: request.source,
159-
stored_values: request.stored_values,
158+
stored_values,
160159
};
161160

162161
thread::spawn(move || {
@@ -188,6 +187,7 @@ pub(super) struct RuntimeState {
188187
pending_tool_calls: HashMap<String, v8::Global<v8::PromiseResolver>>,
189188
pending_timeouts: HashMap<u64, timers::ScheduledTimeout>,
190189
stored_values: HashMap<String, JsonValue>,
190+
stored_value_writes: HashMap<String, JsonValue>,
191191
enabled_tools: Vec<EnabledToolMetadata>,
192192
next_tool_call_id: u64,
193193
next_timeout_id: u64,
@@ -199,7 +199,7 @@ pub(super) struct RuntimeState {
199199
pub(super) enum CompletionState {
200200
Pending,
201201
Completed {
202-
stored_values: HashMap<String, JsonValue>,
202+
stored_value_writes: HashMap<String, JsonValue>,
203203
error_text: Option<String>,
204204
},
205205
}
@@ -243,6 +243,7 @@ fn run_runtime(
243243
pending_tool_calls: HashMap::new(),
244244
pending_timeouts: HashMap::new(),
245245
stored_values: config.stored_values,
246+
stored_value_writes: HashMap::new(),
246247
enabled_tools: config.enabled_tools,
247248
next_tool_call_id: 1,
248249
next_timeout_id: 1,
@@ -268,10 +269,10 @@ fn run_runtime(
268269

269270
match module_loader::completion_state(scope, pending_promise.as_ref()) {
270271
CompletionState::Completed {
271-
stored_values,
272+
stored_value_writes,
272273
error_text,
273274
} => {
274-
send_result(&event_tx, stored_values, error_text);
275+
send_result(&event_tx, stored_value_writes, error_text);
275276
return;
276277
}
277278
CompletionState::Pending => {}
@@ -312,10 +313,10 @@ fn run_runtime(
312313
scope.perform_microtask_checkpoint();
313314
match module_loader::completion_state(scope, pending_promise.as_ref()) {
314315
CompletionState::Completed {
315-
stored_values,
316+
stored_value_writes,
316317
error_text,
317318
} => {
318-
send_result(&event_tx, stored_values, error_text);
319+
send_result(&event_tx, stored_value_writes, error_text);
319320
return;
320321
}
321322
CompletionState::Pending => {}
@@ -335,21 +336,21 @@ fn capture_scope_send_error(
335336
event_tx: &mpsc::UnboundedSender<RuntimeEvent>,
336337
error_text: Option<String>,
337338
) {
338-
let stored_values = scope
339+
let stored_value_writes = scope
339340
.get_slot::<RuntimeState>()
340-
.map(|state| state.stored_values.clone())
341+
.map(|state| state.stored_value_writes.clone())
341342
.unwrap_or_default();
342343

343-
send_result(event_tx, stored_values, error_text);
344+
send_result(event_tx, stored_value_writes, error_text);
344345
}
345346

346347
fn send_result(
347348
event_tx: &mpsc::UnboundedSender<RuntimeEvent>,
348-
stored_values: HashMap<String, JsonValue>,
349+
stored_value_writes: HashMap<String, JsonValue>,
349350
error_text: Option<String>,
350351
) {
351352
let _ = event_tx.send(RuntimeEvent::Result {
352-
stored_values,
353+
stored_value_writes,
353354
error_text,
354355
});
355356
}
@@ -372,7 +373,6 @@ mod tests {
372373
tool_call_id: "call_1".to_string(),
373374
enabled_tools: Vec::new(),
374375
source: source.to_string(),
375-
stored_values: HashMap::new(),
376376
yield_time_ms: Some(1),
377377
max_output_tokens: None,
378378
}
@@ -382,7 +382,7 @@ mod tests {
382382
async fn terminate_execution_stops_cpu_bound_module() {
383383
let (event_tx, mut event_rx) = mpsc::unbounded_channel();
384384
let (_runtime_tx, runtime_terminate_handle) =
385-
spawn_runtime(execute_request("while (true) {}"), event_tx).unwrap();
385+
spawn_runtime(HashMap::new(), execute_request("while (true) {}"), event_tx).unwrap();
386386

387387
let started_event = tokio::time::timeout(Duration::from_secs(1), event_rx.recv())
388388
.await
@@ -396,14 +396,9 @@ mod tests {
396396
.await
397397
.unwrap()
398398
.unwrap();
399-
let RuntimeEvent::Result {
400-
stored_values,
401-
error_text,
402-
} = result_event
403-
else {
399+
let RuntimeEvent::Result { error_text, .. } = result_event else {
404400
panic!("expected runtime result after termination");
405401
};
406-
assert_eq!(stored_values, HashMap::new());
407402
assert!(error_text.is_some());
408403

409404
assert!(

codex-rs/code-mode/src/runtime/module_loader.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,14 @@ pub(super) fn completion_state(
104104
scope: &mut v8::PinScope<'_, '_>,
105105
pending_promise: Option<&v8::Global<v8::Promise>>,
106106
) -> CompletionState {
107-
let stored_values = scope
107+
let stored_value_writes = scope
108108
.get_slot::<RuntimeState>()
109-
.map(|state| state.stored_values.clone())
109+
.map(|state| state.stored_value_writes.clone())
110110
.unwrap_or_default();
111111

112112
let Some(pending_promise) = pending_promise else {
113113
return CompletionState::Completed {
114-
stored_values,
114+
stored_value_writes,
115115
error_text: None,
116116
};
117117
};
@@ -120,7 +120,7 @@ pub(super) fn completion_state(
120120
match promise.state() {
121121
v8::PromiseState::Pending => CompletionState::Pending,
122122
v8::PromiseState::Fulfilled => CompletionState::Completed {
123-
stored_values,
123+
stored_value_writes,
124124
error_text: None,
125125
},
126126
v8::PromiseState::Rejected => {
@@ -131,7 +131,7 @@ pub(super) fn completion_state(
131131
Some(value_to_error_text(scope, result))
132132
};
133133
CompletionState::Completed {
134-
stored_values,
134+
stored_value_writes,
135135
error_text,
136136
}
137137
}

codex-rs/code-mode/src/service.rs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,10 @@ impl CodeModeService {
6868
}
6969
}
7070

71-
pub async fn stored_values(&self) -> HashMap<String, JsonValue> {
71+
async fn stored_values(&self) -> HashMap<String, JsonValue> {
7272
self.inner.stored_values.lock().await.clone()
7373
}
7474

75-
pub async fn replace_stored_values(&self, values: HashMap<String, JsonValue>) {
76-
*self.inner.stored_values.lock().await = values;
77-
}
78-
7975
/// Reserves the runtime cell id for a future `execute` request.
8076
///
8177
/// The runtime can issue nested tool calls before the first `execute`
@@ -94,14 +90,16 @@ impl CodeModeService {
9490
let initial_yield_time_ms = request.yield_time_ms.unwrap_or(DEFAULT_EXEC_YIELD_TIME_MS);
9591
let (event_tx, event_rx) = mpsc::unbounded_channel();
9692
let (control_tx, control_rx) = mpsc::unbounded_channel();
93+
let stored_values = self.stored_values().await;
9794
let (response_tx, response_rx) = oneshot::channel();
9895
let (runtime_tx, runtime_terminate_handle) = {
9996
let mut sessions = self.inner.sessions.lock().await;
10097
if sessions.contains_key(&cell_id) {
10198
return Err(format!("exec cell {cell_id} already exists"));
10299
}
103100

104-
let (runtime_tx, runtime_terminate_handle) = spawn_runtime(request, event_tx)?;
101+
let (runtime_tx, runtime_terminate_handle) =
102+
spawn_runtime(stored_values, request, event_tx)?;
105103

106104
// Keep the session registry locked through insertion so a
107105
// caller-owned cell id cannot race with another execute and replace
@@ -262,7 +260,6 @@ enum SessionControlCommand {
262260

263261
struct PendingResult {
264262
content_items: Vec<FunctionCallOutputContentItem>,
265-
stored_values: HashMap<String, JsonValue>,
266263
error_text: Option<String>,
267264
}
268265

@@ -277,15 +274,13 @@ fn missing_cell_response(cell_id: String) -> RuntimeResponse {
277274
error_text: Some(format!("exec cell {cell_id} not found")),
278275
cell_id,
279276
content_items: Vec::new(),
280-
stored_values: HashMap::new(),
281277
}
282278
}
283279

284280
fn pending_result_response(cell_id: &str, result: PendingResult) -> RuntimeResponse {
285281
RuntimeResponse::Result {
286282
cell_id: cell_id.to_string(),
287283
content_items: result.content_items,
288-
stored_values: result.stored_values,
289284
error_text: result.error_text,
290285
}
291286
}
@@ -348,7 +343,6 @@ async fn run_session_control(
348343
if pending_result.is_none() {
349344
let result = PendingResult {
350345
content_items: std::mem::take(&mut content_items),
351-
stored_values: HashMap::new(),
352346
error_text: Some("exec runtime ended unexpectedly".to_string()),
353347
};
354348
if send_or_buffer_result(
@@ -398,7 +392,7 @@ async fn run_session_control(
398392
.await;
399393
}
400394
RuntimeEvent::Result {
401-
stored_values,
395+
stored_value_writes,
402396
error_text,
403397
} => {
404398
yield_timer = None;
@@ -411,9 +405,13 @@ async fn run_session_control(
411405
}
412406
break;
413407
}
408+
inner
409+
.stored_values
410+
.lock()
411+
.await
412+
.extend(stored_value_writes);
414413
let result = PendingResult {
415414
content_items: std::mem::take(&mut content_items),
416-
stored_values,
417415
error_text,
418416
};
419417
if send_or_buffer_result(
@@ -522,7 +520,6 @@ mod tests {
522520
tool_call_id: "call_1".to_string(),
523521
enabled_tools: Vec::new(),
524522
source: source.to_string(),
525-
stored_values: HashMap::new(),
526523
yield_time_ms: Some(1),
527524
max_output_tokens: None,
528525
}
@@ -559,7 +556,6 @@ mod tests {
559556
content_items: vec![FunctionCallOutputContentItem::InputText {
560557
text: "before".to_string(),
561558
}],
562-
stored_values: HashMap::new(),
563559
error_text: None,
564560
}
565561
);
@@ -585,7 +581,6 @@ mod tests {
585581
content_items: vec![FunctionCallOutputContentItem::InputText {
586582
text: "false".to_string(),
587583
}],
588-
stored_values: HashMap::new(),
589584
error_text: None,
590585
}
591586
);
@@ -625,7 +620,6 @@ text(value);
625620
content_items: vec![FunctionCallOutputContentItem::InputText {
626621
text: "jeudi 2 janvier \u{e0} 03:04:05".to_string(),
627622
}],
628-
stored_values: HashMap::new(),
629623
error_text: None,
630624
}
631625
);
@@ -664,7 +658,6 @@ text(formatter.format(new Date("2025-01-02T03:04:05Z")));
664658
content_items: vec![FunctionCallOutputContentItem::InputText {
665659
text: "jeudi 2 janvier \u{e0} 03:04:05".to_string(),
666660
}],
667-
stored_values: HashMap::new(),
668661
error_text: None,
669662
}
670663
);
@@ -707,7 +700,6 @@ text(JSON.stringify(returnsUndefined));
707700
text: "[true,true,true]".to_string(),
708701
},
709702
],
710-
stored_values: HashMap::new(),
711703
error_text: None,
712704
}
713705
);
@@ -742,7 +734,6 @@ image({
742734
image_url: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==".to_string(),
743735
detail: Some(crate::ImageDetail::Original),
744736
}],
745-
stored_values: HashMap::new(),
746737
error_text: None,
747738
}
748739
);
@@ -778,7 +769,6 @@ image(
778769
image_url: "https://example.com/image.jpg".to_string(),
779770
detail: Some(crate::ImageDetail::Original),
780771
}],
781-
stored_values: HashMap::new(),
782772
error_text: None,
783773
}
784774
);
@@ -816,7 +806,6 @@ image(
816806
image_url: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==".to_string(),
817807
detail: Some(crate::ImageDetail::Low),
818808
}],
819-
stored_values: HashMap::new(),
820809
error_text: None,
821810
}
822811
);
@@ -853,7 +842,6 @@ image({
853842
RuntimeResponse::Result {
854843
cell_id: "1".to_string(),
855844
content_items: Vec::new(),
856-
stored_values: HashMap::new(),
857845
error_text: Some(
858846
"image expects a non-empty image URL string, an object with image_url and optional detail, or a raw MCP image block".to_string(),
859847
),
@@ -879,7 +867,6 @@ image({
879867
WaitOutcome::MissingCell(RuntimeResponse::Result {
880868
cell_id: "missing".to_string(),
881869
content_items: Vec::new(),
882-
stored_values: HashMap::new(),
883870
error_text: Some("exec cell missing not found".to_string()),
884871
})
885872
);
@@ -893,6 +880,7 @@ image({
893880
let (initial_response_tx, initial_response_rx) = oneshot::channel();
894881
let (runtime_event_tx, _runtime_event_rx) = mpsc::unbounded_channel();
895882
let (runtime_tx, runtime_terminate_handle) = spawn_runtime(
883+
HashMap::new(),
896884
ExecuteRequest {
897885
source: "await new Promise(() => {})".to_string(),
898886
yield_time_ms: None,

codex-rs/core-plugins/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod marketplace;
55
pub mod marketplace_add;
66
pub mod marketplace_remove;
77
pub mod marketplace_upgrade;
8+
mod plugin_bundle_archive;
89
pub mod remote;
910
pub mod remote_bundle;
1011
pub mod remote_legacy;

0 commit comments

Comments
 (0)