mirror of
https://github.com/openai/codex.git
synced 2026-04-24 22:54:54 +00:00
This PR does two things:
1. populate a new `codex_error_code` protocol in error events sent from
core to client;
2. old v1 core events `codex/event/stream_error` and `codex/event/error`
will now both become `error`. We also show codex error code for
turncompleted -> error status.
new events in app server test:
```
< {
< "method": "codex/event/stream_error",
< "params": {
< "conversationId": "019aa34c-0c14-70e0-9706-98520a760d67",
< "id": "0",
< "msg": {
< "codex_error_code": {
< "response_stream_disconnected": {
< "http_status_code": 401
< }
< },
< "message": "Reconnecting... 2/5",
< "type": "stream_error"
< }
< }
< }
{
< "method": "error",
< "params": {
< "error": {
< "codexErrorCode": {
< "responseStreamDisconnected": {
< "httpStatusCode": 401
< }
< },
< "message": "Reconnecting... 2/5"
< }
< }
< }
< {
< "method": "turn/completed",
< "params": {
< "turn": {
< "error": {
< "codexErrorCode": {
< "responseTooManyFailedAttempts": {
< "httpStatusCode": 401
< }
< },
< "message": "exceeded retry limit, last status: 401 Unauthorized, request id: 9a1b495a1a97ed3e-SJC"
< },
< "id": "0",
< "items": [],
< "status": "failed"
< }
< }
< }
```
84 lines
2.6 KiB
Rust
84 lines
2.6 KiB
Rust
use std::sync::Arc;
|
|
|
|
use crate::Prompt;
|
|
use crate::codex::Session;
|
|
use crate::codex::TurnContext;
|
|
use crate::error::Result as CodexResult;
|
|
use crate::protocol::AgentMessageEvent;
|
|
use crate::protocol::CompactedItem;
|
|
use crate::protocol::EventMsg;
|
|
use crate::protocol::RolloutItem;
|
|
use crate::protocol::TaskStartedEvent;
|
|
use codex_protocol::models::ResponseItem;
|
|
|
|
pub(crate) async fn run_inline_remote_auto_compact_task(
|
|
sess: Arc<Session>,
|
|
turn_context: Arc<TurnContext>,
|
|
) {
|
|
run_remote_compact_task_inner(&sess, &turn_context).await;
|
|
}
|
|
|
|
pub(crate) async fn run_remote_compact_task(sess: Arc<Session>, turn_context: Arc<TurnContext>) {
|
|
let start_event = EventMsg::TaskStarted(TaskStartedEvent {
|
|
model_context_window: turn_context.client.get_model_context_window(),
|
|
});
|
|
sess.send_event(&turn_context, start_event).await;
|
|
|
|
run_remote_compact_task_inner(&sess, &turn_context).await;
|
|
}
|
|
|
|
async fn run_remote_compact_task_inner(sess: &Arc<Session>, turn_context: &Arc<TurnContext>) {
|
|
if let Err(err) = run_remote_compact_task_inner_impl(sess, turn_context).await {
|
|
let event = EventMsg::Error(
|
|
err.to_error_event(Some("Error running remote compact task".to_string())),
|
|
);
|
|
sess.send_event(turn_context, event).await;
|
|
}
|
|
}
|
|
|
|
async fn run_remote_compact_task_inner_impl(
|
|
sess: &Arc<Session>,
|
|
turn_context: &Arc<TurnContext>,
|
|
) -> CodexResult<()> {
|
|
let mut history = sess.clone_history().await;
|
|
let prompt = Prompt {
|
|
input: history.get_history_for_prompt(),
|
|
tools: vec![],
|
|
parallel_tool_calls: false,
|
|
base_instructions_override: turn_context.base_instructions.clone(),
|
|
output_schema: None,
|
|
};
|
|
|
|
let mut new_history = turn_context
|
|
.client
|
|
.compact_conversation_history(&prompt)
|
|
.await?;
|
|
// Required to keep `/undo` available after compaction
|
|
let ghost_snapshots: Vec<ResponseItem> = history
|
|
.get_history()
|
|
.iter()
|
|
.filter(|item| matches!(item, ResponseItem::GhostSnapshot { .. }))
|
|
.cloned()
|
|
.collect();
|
|
|
|
if !ghost_snapshots.is_empty() {
|
|
new_history.extend(ghost_snapshots);
|
|
}
|
|
sess.replace_history(new_history.clone()).await;
|
|
sess.recompute_token_usage(turn_context).await;
|
|
|
|
let compacted_item = CompactedItem {
|
|
message: String::new(),
|
|
replacement_history: Some(new_history),
|
|
};
|
|
sess.persist_rollout_items(&[RolloutItem::Compacted(compacted_item)])
|
|
.await;
|
|
|
|
let event = EventMsg::AgentMessage(AgentMessageEvent {
|
|
message: "Compact task completed".to_string(),
|
|
});
|
|
sess.send_event(turn_context, event).await;
|
|
|
|
Ok(())
|
|
}
|