From a010c1b7fcce994601f53807ecc6ee2642908087 Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Sun, 2 Nov 2025 08:58:43 -0800 Subject: [PATCH] add v2 server notifications --- .../src/protocol/common.rs | 55 +++++++++++ .../app-server-protocol/src/protocol/v2.rs | 94 +++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index d62e333f5c..50122af293 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -508,6 +508,61 @@ pub struct FuzzyFileSearchResponse { server_notification_definitions! { /// NEW NOTIFICATIONS + #[serde(rename = "thread/started")] + #[ts(rename = "thread/started")] + #[strum(serialize = "thread/started")] + ThreadStarted(v2::ThreadStartedNotification), + + #[serde(rename = "thread/error")] + #[ts(rename = "thread/error")] + #[strum(serialize = "thread/error")] + ThreadError(v2::ThreadErrorNotification), + + #[serde(rename = "turn/started")] + #[ts(rename = "turn/started")] + #[strum(serialize = "turn/started")] + TurnStarted(v2::TurnStartedNotification), + + #[serde(rename = "turn/completed")] + #[ts(rename = "turn/completed")] + #[strum(serialize = "turn/completed")] + TurnCompleted(v2::TurnCompletedNotification), + + #[serde(rename = "turn/failed")] + #[ts(rename = "turn/failed")] + #[strum(serialize = "turn/failed")] + TurnFailed(v2::TurnFailedNotification), + + #[serde(rename = "item/started")] + #[ts(rename = "item/started")] + #[strum(serialize = "item/started")] + ItemStarted(v2::ItemStartedNotification), + + #[serde(rename = "item/updated")] + #[ts(rename = "item/updated")] + #[strum(serialize = "item/updated")] + ItemUpdated(v2::ItemUpdatedNotification), + + #[serde(rename = "item/completed")] + #[ts(rename = "item/completed")] + #[strum(serialize = "item/completed")] + ItemCompleted(v2::ItemCompletedNotification), + + #[serde(rename = "item/agentMessage/delta")] + #[ts(rename = "item/agentMessage/delta")] + #[strum(serialize = "item/agentMessage/delta")] + AgentMessageDelta(v2::AgentMessageDeltaNotification), + + #[serde(rename = "item/commandExecution/outputDelta")] + #[ts(rename = "item/commandExecution/outputDelta")] + #[strum(serialize = "item/commandExecution/outputDelta")] + CommandExecutionOutputDelta(v2::CommandExecutionOutputDeltaNotification), + + #[serde(rename = "item/mcp/progress")] + #[ts(rename = "item/mcp/progress")] + #[strum(serialize = "item/mcp/progress")] + McpProgress(v2::McpProgressNotification), + #[serde(rename = "account/rateLimits/updated")] #[ts(rename = "account/rateLimits/updated")] #[strum(serialize = "account/rateLimits/updated")] diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index 8d4d3f44b8..bcc9728c9f 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -431,6 +431,100 @@ pub struct TodoItem { } // === Server Notifications === +// Thread/Turn lifecycle notifications and item progress events +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ThreadStartedNotification { + pub thread: Thread, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct TurnStartedNotification { + pub turn: Turn, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct Usage { + pub input_tokens: i32, + pub cached_input_tokens: i32, + pub output_tokens: i32, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct TurnCompletedNotification { + pub turn: Turn, + // TODO: should usage be stored on the Turn object, and we return that instead? + pub usage: Usage, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct TurnFailedNotification { + // TODO: should the error be stored on the Turn object, and we return that instead? + pub error: TurnError, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ItemStartedNotification { + pub item: ThreadItem, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ItemUpdatedNotification { + pub item: ThreadItem, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ItemCompletedNotification { + pub item: ThreadItem, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ThreadErrorNotification { + pub message: String, +} + +// Item-specific progress notifications +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct AgentMessageDeltaNotification { + pub item_id: String, + pub delta: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct CommandExecutionOutputDeltaNotification { + pub item_id: String, + pub delta: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct McpProgressNotification { + pub item_id: String, + pub message: String, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")]