From 2e5c52e6dac792a1bb70171e6ec18eed307b4974 Mon Sep 17 00:00:00 2001 From: Leo Shimonaka Date: Fri, 20 Feb 2026 15:30:36 -0800 Subject: [PATCH] fix: [app-server] Schema mismatch prevents thread resume --- .../schema/json/ServerNotification.json | 22 ++++++++--------- .../codex_app_server_protocol.schemas.json | 9 ++++++- .../json/v2/ItemCompletedNotification.json | 4 ++-- .../json/v2/ItemStartedNotification.json | 4 ++-- .../schema/json/v2/ReviewStartResponse.json | 4 ++-- .../schema/json/v2/ThreadForkResponse.json | 4 ++-- .../schema/json/v2/ThreadListResponse.json | 4 ++-- .../schema/json/v2/ThreadReadResponse.json | 4 ++-- .../schema/json/v2/ThreadResumeResponse.json | 4 ++-- .../json/v2/ThreadRollbackResponse.json | 4 ++-- .../schema/json/v2/ThreadStartResponse.json | 4 ++-- .../json/v2/ThreadStartedNotification.json | 4 ++-- .../json/v2/ThreadUnarchiveResponse.json | 4 ++-- .../json/v2/TurnCompletedNotification.json | 4 ++-- .../schema/json/v2/TurnStartResponse.json | 4 ++-- .../json/v2/TurnStartedNotification.json | 4 ++-- .../v2/{MessagePhase.ts => MessagePhaseV2.ts} | 2 +- .../schema/typescript/v2/ThreadItem.ts | 4 ++-- .../schema/typescript/v2/index.ts | 2 +- .../src/protocol/thread_history.rs | 2 +- .../app-server-protocol/src/protocol/v2.rs | 24 +++++-------------- 21 files changed, 58 insertions(+), 63 deletions(-) rename codex-rs/app-server-protocol/schema/typescript/v2/{MessagePhase.ts => MessagePhaseV2.ts} (72%) diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 6a6bf2d7c7..8c93834b84 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -1551,7 +1551,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase2" + "$ref": "#/definitions/MessagePhase" }, { "type": "null" @@ -4593,13 +4593,6 @@ "type": "string" }, "MessagePhase": { - "enum": [ - "commentary", - "finalAnswer" - ], - "type": "string" - }, - "MessagePhase2": { "description": "Classifies an assistant message as interim commentary or final answer text.\n\nProviders do not emit this consistently, so callers must treat `None` as \"phase unknown\" and keep compatibility behavior for legacy models.", "oneOf": [ { @@ -4618,6 +4611,13 @@ } ] }, + "MessagePhaseV2": { + "enum": [ + "commentary", + "finalAnswer" + ], + "type": "string" + }, "ModeKind": { "description": "Initial collaboration mode to use when the TUI starts.", "enum": [ @@ -5551,7 +5551,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase2" + "$ref": "#/definitions/MessagePhase" }, { "type": "null" @@ -6848,7 +6848,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" @@ -7735,7 +7735,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase2" + "$ref": "#/definitions/MessagePhase" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 313c3e62b3..c7982d27db 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -13361,6 +13361,13 @@ } ] }, + "MessagePhaseV2": { + "enum": [ + "commentary", + "finalAnswer" + ], + "type": "string" + }, "ModeKind": { "description": "Initial collaboration mode to use when the TUI starts.", "enum": [ @@ -15818,7 +15825,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/v2/MessagePhase" + "$ref": "#/definitions/v2/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json index 1a0ef630a1..223cb886bd 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemCompletedNotification.json @@ -236,7 +236,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -370,7 +370,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json index 50e7e1e664..ba6e572e4f 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemStartedNotification.json @@ -236,7 +236,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -370,7 +370,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json index e71ebbdc7f..124e711f17 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json @@ -350,7 +350,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -484,7 +484,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json index dad39a512a..61815b9e9b 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json @@ -419,7 +419,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -937,7 +937,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json index 80a1d42a23..21df4767a5 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json @@ -373,7 +373,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -710,7 +710,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json index a4810d5850..a63958774f 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json @@ -373,7 +373,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -710,7 +710,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json index c4e1df8478..ef3379a7e0 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json @@ -419,7 +419,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -937,7 +937,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json index f8cdcd744c..a10bd5d04d 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json @@ -373,7 +373,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -710,7 +710,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json index 099a65d219..0dbec8675b 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json @@ -419,7 +419,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -937,7 +937,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json index 9927bb2f3c..36dc640da8 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json @@ -373,7 +373,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -710,7 +710,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json index 011a97a34c..23d47e31b0 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json @@ -373,7 +373,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -710,7 +710,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json index e20e71be29..6cce73fe4e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json @@ -350,7 +350,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -484,7 +484,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json index 4fb088a13e..db00f911c2 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json @@ -350,7 +350,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -484,7 +484,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json index 4e7f82f4e5..0c7aae4c7e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json @@ -350,7 +350,7 @@ ], "type": "string" }, - "MessagePhase": { + "MessagePhaseV2": { "enum": [ "commentary", "finalAnswer" @@ -484,7 +484,7 @@ "phase": { "anyOf": [ { - "$ref": "#/definitions/MessagePhase" + "$ref": "#/definitions/MessagePhaseV2" }, { "type": "null" diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/MessagePhase.ts b/codex-rs/app-server-protocol/schema/typescript/v2/MessagePhaseV2.ts similarity index 72% rename from codex-rs/app-server-protocol/schema/typescript/v2/MessagePhase.ts rename to codex-rs/app-server-protocol/schema/typescript/v2/MessagePhaseV2.ts index 80d7236e74..4466506130 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/MessagePhase.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/MessagePhaseV2.ts @@ -2,4 +2,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type MessagePhase = "commentary" | "finalAnswer"; +export type MessagePhaseV2 = "commentary" | "finalAnswer"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts index cbdad0bf2b..4dd1aebb77 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadItem.ts @@ -11,12 +11,12 @@ import type { FileUpdateChange } from "./FileUpdateChange"; import type { McpToolCallError } from "./McpToolCallError"; import type { McpToolCallResult } from "./McpToolCallResult"; import type { McpToolCallStatus } from "./McpToolCallStatus"; -import type { MessagePhase } from "./MessagePhase"; +import type { MessagePhaseV2 } from "./MessagePhaseV2"; import type { PatchApplyStatus } from "./PatchApplyStatus"; import type { UserInput } from "./UserInput"; import type { WebSearchAction } from "./WebSearchAction"; -export type ThreadItem = { "type": "userMessage", id: string, content: Array, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array, content: Array, } | { "type": "commandExecution", id: string, +export type ThreadItem = { "type": "userMessage", id: string, content: Array, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhaseV2 | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array, content: Array, } | { "type": "commandExecution", id: string, /** * The command to be executed. */ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts index c2f8494785..2511a25bb1 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts @@ -95,7 +95,7 @@ export type { McpToolCallProgressNotification } from "./McpToolCallProgressNotif export type { McpToolCallResult } from "./McpToolCallResult"; export type { McpToolCallStatus } from "./McpToolCallStatus"; export type { MergeStrategy } from "./MergeStrategy"; -export type { MessagePhase } from "./MessagePhase"; +export type { MessagePhaseV2 } from "./MessagePhaseV2"; export type { Model } from "./Model"; export type { ModelListParams } from "./ModelListParams"; export type { ModelListResponse } from "./ModelListResponse"; diff --git a/codex-rs/app-server-protocol/src/protocol/thread_history.rs b/codex-rs/app-server-protocol/src/protocol/thread_history.rs index fce6f4f263..85da081eeb 100644 --- a/codex-rs/app-server-protocol/src/protocol/thread_history.rs +++ b/codex-rs/app-server-protocol/src/protocol/thread_history.rs @@ -1196,7 +1196,7 @@ mod tests { ThreadItem::AgentMessage { id: "item-1".into(), text: "Final reply".into(), - phase: Some(crate::protocol::v2::MessagePhase::FinalAnswer), + phase: Some(crate::protocol::v2::MessagePhaseV2::FinalAnswer), } ); } diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index 833e628214..8e93b806cf 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -2664,23 +2664,11 @@ impl From for UserInput { } } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] -#[serde(rename_all = "camelCase")] -#[ts(rename_all = "camelCase")] -#[ts(export_to = "v2/")] -pub enum MessagePhase { - Commentary, - FinalAnswer, -} - -impl From for MessagePhase { - fn from(value: CoreMessagePhase) -> Self { - match value { - CoreMessagePhase::Commentary => Self::Commentary, - CoreMessagePhase::FinalAnswer => Self::FinalAnswer, - } +v2_enum_from_core!( + pub enum MessagePhaseV2 from CoreMessagePhase { + Commentary, FinalAnswer } -} +); #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(tag = "type", rename_all = "camelCase")] @@ -2696,7 +2684,7 @@ pub enum ThreadItem { id: String, text: String, #[serde(default)] - phase: Option, + phase: Option, }, #[serde(rename_all = "camelCase")] #[ts(rename_all = "camelCase")] @@ -3908,7 +3896,7 @@ mod tests { ThreadItem::AgentMessage { id: "agent-2".to_string(), text: "final".to_string(), - phase: Some(MessagePhase::FinalAnswer), + phase: Some(MessagePhaseV2::FinalAnswer), } );