Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ macro_rules! client_request_definitions {
)*
}

impl ClientRequest {
pub fn request_id(&self) -> &RequestId {
match self {
$(Self::$variant { request_id, .. } => request_id,)*
}
}
}

pub fn export_client_responses(
out_dir: &::std::path::Path,
) -> ::std::result::Result<(), ::ts_rs::ExportError> {
Expand Down Expand Up @@ -140,6 +148,14 @@ client_request_definitions! {
params: v2::ThreadRollbackParams,
response: v2::ThreadRollbackResponse,
},
ThreadCompact => "thread/compact" {
params: v2::ThreadCompactParams,
response: v2::ThreadCompactResponse,
},
ThreadShutdown => "thread/shutdown" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooc can we reuse turn/interrupt ?

params: v2::ThreadShutdownParams,
response: v2::ThreadShutdownResponse,
},
ThreadList => "thread/list" {
params: v2::ThreadListParams,
response: v2::ThreadListResponse,
Expand Down Expand Up @@ -201,6 +217,10 @@ client_request_definitions! {
params: v2::ListMcpServerStatusParams,
response: v2::ListMcpServerStatusResponse,
},
McpElicitationResolve => "mcp/elicitation/resolve" {
params: v2::McpElicitationResolveParams,
response: v2::McpElicitationResolveResponse,
},

LoginAccount => "account/login/start" {
params: v2::LoginAccountParams,
Expand Down
54 changes: 54 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::PathBuf;

use crate::protocol::common::AuthMode;
use codex_protocol::account::PlanType;
use codex_protocol::approvals::ElicitationAction as CoreElicitationAction;
use codex_protocol::approvals::ExecPolicyAmendment as CoreExecPolicyAmendment;
use codex_protocol::config_types::CollaborationMode;
use codex_protocol::config_types::CollaborationModeMask;
Expand All @@ -12,6 +13,7 @@ use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::config_types::SandboxMode as CoreSandboxMode;
use codex_protocol::config_types::Verbosity;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::config_types::WindowsSandboxLevel;
use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent;
use codex_protocol::items::TurnItem as CoreTurnItem;
use codex_protocol::models::ResponseItem;
Expand Down Expand Up @@ -41,6 +43,7 @@ use codex_protocol::user_input::TextElement as CoreTextElement;
use codex_protocol::user_input::UserInput as CoreUserInput;
use codex_utils_absolute_path::AbsolutePathBuf;
use mcp_types::ContentBlock as McpContentBlock;
use mcp_types::RequestId as McpRequestId;
use mcp_types::Resource as McpResource;
use mcp_types::ResourceTemplate as McpResourceTemplate;
use mcp_types::Tool as McpTool;
Expand Down Expand Up @@ -233,6 +236,14 @@ v2_enum_from_core!(
}
);

v2_enum_from_core!(
pub enum ElicitationAction from CoreElicitationAction {
Accept,
Decline,
Cancel
}
);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(tag = "type", rename_all = "camelCase")]
#[ts(tag = "type")]
Expand Down Expand Up @@ -1061,6 +1072,21 @@ pub struct ListMcpServerStatusResponse {
pub next_cursor: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct McpElicitationResolveParams {
pub thread_id: String,
pub server_name: String,
pub request_id: McpRequestId,
pub decision: ElicitationAction,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct McpElicitationResolveResponse {}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
Expand Down Expand Up @@ -1354,6 +1380,32 @@ pub struct ThreadRollbackResponse {
pub thread: Thread,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadCompactParams {
pub thread_id: String,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadCompactResponse {
pub turn: Turn,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadShutdownParams {
pub thread_id: String,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadShutdownResponse {}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
Expand Down Expand Up @@ -1810,6 +1862,8 @@ pub struct TurnStartParams {
pub approval_policy: Option<AskForApproval>,
/// Override the sandbox policy for this turn and subsequent turns.
pub sandbox_policy: Option<SandboxPolicy>,
/// Override the Windows sandbox level for this turn and subsequent turns.
pub windows_sandbox_level: Option<WindowsSandboxLevel>,
/// Override the model for this turn and subsequent turns.
pub model: Option<String>,
/// Override the reasoning effort for this turn and subsequent turns.
Expand Down
103 changes: 102 additions & 1 deletion codex-rs/app-server/src/codex_message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ use codex_app_server_protocol::LoginChatGptCompleteNotification;
use codex_app_server_protocol::LoginChatGptResponse;
use codex_app_server_protocol::LogoutAccountResponse;
use codex_app_server_protocol::LogoutChatGptResponse;
use codex_app_server_protocol::McpElicitationResolveParams;
use codex_app_server_protocol::McpElicitationResolveResponse;
use codex_app_server_protocol::McpServerOauthLoginCompletedNotification;
use codex_app_server_protocol::McpServerOauthLoginParams;
use codex_app_server_protocol::McpServerOauthLoginResponse;
Expand Down Expand Up @@ -98,6 +100,8 @@ use codex_app_server_protocol::SkillsListResponse;
use codex_app_server_protocol::Thread;
use codex_app_server_protocol::ThreadArchiveParams;
use codex_app_server_protocol::ThreadArchiveResponse;
use codex_app_server_protocol::ThreadCompactParams;
use codex_app_server_protocol::ThreadCompactResponse;
use codex_app_server_protocol::ThreadForkParams;
use codex_app_server_protocol::ThreadForkResponse;
use codex_app_server_protocol::ThreadItem;
Expand All @@ -112,6 +116,8 @@ use codex_app_server_protocol::ThreadResumeResponse;
use codex_app_server_protocol::ThreadRollbackParams;
use codex_app_server_protocol::ThreadSetNameParams;
use codex_app_server_protocol::ThreadSetNameResponse;
use codex_app_server_protocol::ThreadShutdownParams;
use codex_app_server_protocol::ThreadShutdownResponse;
use codex_app_server_protocol::ThreadSortKey;
use codex_app_server_protocol::ThreadSourceKind;
use codex_app_server_protocol::ThreadStartParams;
Expand Down Expand Up @@ -447,6 +453,12 @@ impl CodexMessageProcessor {
ClientRequest::ThreadRollback { request_id, params } => {
self.thread_rollback(request_id, params).await;
}
ClientRequest::ThreadCompact { request_id, params } => {
self.thread_compact(request_id, params).await;
}
ClientRequest::ThreadShutdown { request_id, params } => {
self.thread_shutdown(request_id, params).await;
}
ClientRequest::ThreadList { request_id, params } => {
self.thread_list(request_id, params).await;
}
Expand Down Expand Up @@ -513,6 +525,9 @@ impl CodexMessageProcessor {
ClientRequest::McpServerStatusList { request_id, params } => {
self.list_mcp_server_status(request_id, params).await;
}
ClientRequest::McpElicitationResolve { request_id, params } => {
self.mcp_elicitation_resolve(request_id, params).await;
}
ClientRequest::LoginAccount { request_id, params } => {
self.login_v2(request_id, params).await;
}
Expand Down Expand Up @@ -2051,6 +2066,63 @@ impl CodexMessageProcessor {
}
}

async fn thread_compact(&mut self, request_id: RequestId, params: ThreadCompactParams) {
let ThreadCompactParams { thread_id } = params;
let (thread_uuid, thread) = match self.load_thread(&thread_id).await {
Ok(v) => v,
Err(error) => {
self.outgoing.send_error(request_id, error).await;
return;
}
};

match thread.submit(Op::Compact).await {
Ok(turn_id) => {
let turn = Turn {
id: turn_id.clone(),
items: Vec::new(),
error: None,
status: TurnStatus::InProgress,
};
let response = ThreadCompactResponse { turn: turn.clone() };
self.outgoing.send_response(request_id, response).await;

let notif = TurnStartedNotification {
thread_id: thread_uuid.to_string(),
turn,
};
self.outgoing
.send_server_notification(ServerNotification::TurnStarted(notif))
.await;
}
Err(err) => {
let error = JSONRPCErrorError {
code: INTERNAL_ERROR_CODE,
message: format!("failed to start compact turn: {err}"),
data: None,
};
self.outgoing.send_error(request_id, error).await;
}
}
}

async fn thread_shutdown(&mut self, request_id: RequestId, params: ThreadShutdownParams) {
let ThreadShutdownParams { thread_id } = params;
let (thread_uuid, thread) = match self.load_thread(&thread_id).await {
Ok(v) => v,
Err(error) => {
self.outgoing.send_error(request_id, error).await;
return;
}
};

let _ = thread.submit(Op::Shutdown).await;
self.thread_manager.remove_thread(&thread_uuid).await;

let response = ThreadShutdownResponse {};
self.outgoing.send_response(request_id, response).await;
}

async fn thread_list(&self, request_id: RequestId, params: ThreadListParams) {
let ThreadListParams {
cursor,
Expand Down Expand Up @@ -3143,6 +3215,34 @@ impl CodexMessageProcessor {
});
}

async fn mcp_elicitation_resolve(
&self,
request_id: RequestId,
params: McpElicitationResolveParams,
) {
let McpElicitationResolveParams {
thread_id,
server_name,
request_id: elicitation_id,
decision,
} = params;
let (_, thread) = match self.load_thread(&thread_id).await {
Ok(v) => v,
Err(error) => {
self.outgoing.send_error(request_id, error).await;
return;
}
};
let op = Op::ResolveElicitation {
server_name,
request_id: elicitation_id,
decision: decision.to_core(),
};
let _ = thread.submit(op).await;
let response = McpElicitationResolveResponse {};
self.outgoing.send_response(request_id, response).await;
}

async fn list_mcp_server_status_task(
outgoing: Arc<OutgoingMessageSender>,
request_id: RequestId,
Expand Down Expand Up @@ -4090,6 +4190,7 @@ impl CodexMessageProcessor {
let has_any_overrides = params.cwd.is_some()
|| params.approval_policy.is_some()
|| params.sandbox_policy.is_some()
|| params.windows_sandbox_level.is_some()
|| params.model.is_some()
|| params.effort.is_some()
|| params.summary.is_some()
Expand All @@ -4103,7 +4204,7 @@ impl CodexMessageProcessor {
cwd: params.cwd,
approval_policy: params.approval_policy.map(AskForApproval::to_core),
sandbox_policy: params.sandbox_policy.map(|p| p.to_core()),
windows_sandbox_level: None,
windows_sandbox_level: params.windows_sandbox_level,
model: params.model,
effort: params.effort.map(Some),
summary: params.summary,
Expand Down
Loading
Loading