diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index cbcf8b886..c181b8bcf 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -1558,7 +1558,7 @@ "action": { "anyOf": [ { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, { "type": "null" @@ -1684,6 +1684,107 @@ } ] }, + "ResponsesApiWebSearchAction": { + "oneOf": [ + { + "properties": { + "queries": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "search" + ], + "title": "SearchResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "SearchResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "open_page" + ], + "title": "OpenPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "OpenPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "pattern": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "find_in_page" + ], + "title": "FindInPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "FindInPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "other" + ], + "title": "OtherResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "OtherResponsesApiWebSearchAction", + "type": "object" + } + ] + }, "ReviewDelivery": { "enum": [ "inline", @@ -2930,107 +3031,6 @@ } ] }, - "WebSearchAction": { - "oneOf": [ - { - "properties": { - "queries": { - "items": { - "type": "string" - }, - "type": [ - "array", - "null" - ] - }, - "query": { - "type": [ - "string", - "null" - ] - }, - "type": { - "enum": [ - "search" - ], - "title": "SearchWebSearchActionType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "SearchWebSearchAction", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "open_page" - ], - "title": "OpenPageWebSearchActionType", - "type": "string" - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "type" - ], - "title": "OpenPageWebSearchAction", - "type": "object" - }, - { - "properties": { - "pattern": { - "type": [ - "string", - "null" - ] - }, - "type": { - "enum": [ - "find_in_page" - ], - "title": "FindInPageWebSearchActionType", - "type": "string" - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "type" - ], - "title": "FindInPageWebSearchAction", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "other" - ], - "title": "OtherWebSearchActionType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "OtherWebSearchAction", - "type": "object" - } - ] - }, "WindowsSandboxSetupMode": { "enum": [ "elevated", diff --git a/codex-rs/app-server-protocol/schema/json/EventMsg.json b/codex-rs/app-server-protocol/schema/json/EventMsg.json index e17940056..70ddde458 100644 --- a/codex-rs/app-server-protocol/schema/json/EventMsg.json +++ b/codex-rs/app-server-protocol/schema/json/EventMsg.json @@ -1414,7 +1414,7 @@ { "properties": { "action": { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, "call_id": { "type": "string" @@ -5072,7 +5072,7 @@ "action": { "anyOf": [ { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, { "type": "null" @@ -5198,6 +5198,107 @@ } ] }, + "ResponsesApiWebSearchAction": { + "oneOf": [ + { + "properties": { + "queries": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "search" + ], + "title": "SearchResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "SearchResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "open_page" + ], + "title": "OpenPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "OpenPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "pattern": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "find_in_page" + ], + "title": "FindInPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "FindInPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "other" + ], + "title": "OtherResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "OtherResponsesApiWebSearchAction", + "type": "object" + } + ] + }, "Result_of_CallToolResult_or_String": { "oneOf": [ { @@ -6095,7 +6196,7 @@ { "properties": { "action": { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, "id": { "type": "string" @@ -6306,107 +6407,6 @@ "type": "object" } ] - }, - "WebSearchAction": { - "oneOf": [ - { - "properties": { - "queries": { - "items": { - "type": "string" - }, - "type": [ - "array", - "null" - ] - }, - "query": { - "type": [ - "string", - "null" - ] - }, - "type": { - "enum": [ - "search" - ], - "title": "SearchWebSearchActionType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "SearchWebSearchAction", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "open_page" - ], - "title": "OpenPageWebSearchActionType", - "type": "string" - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "type" - ], - "title": "OpenPageWebSearchAction", - "type": "object" - }, - { - "properties": { - "pattern": { - "type": [ - "string", - "null" - ] - }, - "type": { - "enum": [ - "find_in_page" - ], - "title": "FindInPageWebSearchActionType", - "type": "string" - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "type" - ], - "title": "FindInPageWebSearchAction", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "other" - ], - "title": "OtherWebSearchActionType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "OtherWebSearchAction", - "type": "object" - } - ] } }, "description": "Response event from the agent NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.", @@ -7226,7 +7226,7 @@ { "properties": { "action": { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, "call_id": { "type": "string" 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 3cc179456..495339982 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 @@ -2730,7 +2730,7 @@ { "properties": { "action": { - "$ref": "#/definitions/v2/WebSearchAction" + "$ref": "#/definitions/v2/ResponsesApiWebSearchAction" }, "call_id": { "type": "string" @@ -8236,7 +8236,7 @@ { "properties": { "action": { - "$ref": "#/definitions/v2/WebSearchAction" + "$ref": "#/definitions/v2/ResponsesApiWebSearchAction" }, "id": { "type": "string" @@ -13191,7 +13191,7 @@ "action": { "anyOf": [ { - "$ref": "#/definitions/v2/WebSearchAction" + "$ref": "#/definitions/v2/ResponsesApiWebSearchAction" }, { "type": "null" @@ -13317,6 +13317,107 @@ } ] }, + "ResponsesApiWebSearchAction": { + "oneOf": [ + { + "properties": { + "queries": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "search" + ], + "title": "SearchResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "SearchResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "open_page" + ], + "title": "OpenPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "OpenPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "pattern": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "find_in_page" + ], + "title": "FindInPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "FindInPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "other" + ], + "title": "OtherResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "OtherResponsesApiWebSearchAction", + "type": "object" + } + ] + }, "ReviewDelivery": { "enum": [ "inline", @@ -16722,7 +16823,7 @@ "properties": { "type": { "enum": [ - "open_page" + "openPage" ], "title": "OpenPageWebSearchActionType", "type": "string" @@ -16750,7 +16851,7 @@ }, "type": { "enum": [ - "find_in_page" + "findInPage" ], "title": "FindInPageWebSearchActionType", "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 76f1d19d9..cbc28994b 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -4543,7 +4543,7 @@ { "properties": { "action": { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, "call_id": { "type": "string" @@ -10052,7 +10052,7 @@ "action": { "anyOf": [ { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, { "type": "null" @@ -10178,6 +10178,107 @@ } ] }, + "ResponsesApiWebSearchAction": { + "oneOf": [ + { + "properties": { + "queries": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "search" + ], + "title": "SearchResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "SearchResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "open_page" + ], + "title": "OpenPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "OpenPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "pattern": { + "type": [ + "string", + "null" + ] + }, + "type": { + "enum": [ + "find_in_page" + ], + "title": "FindInPageResponsesApiWebSearchActionType", + "type": "string" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "type" + ], + "title": "FindInPageResponsesApiWebSearchAction", + "type": "object" + }, + { + "properties": { + "type": { + "enum": [ + "other" + ], + "title": "OtherResponsesApiWebSearchActionType", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "OtherResponsesApiWebSearchAction", + "type": "object" + } + ] + }, "Result_of_CallToolResult_or_String": { "oneOf": [ { @@ -14485,7 +14586,7 @@ { "properties": { "action": { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, "id": { "type": "string" @@ -14978,7 +15079,7 @@ "properties": { "type": { "enum": [ - "open_page" + "openPage" ], "title": "OpenPageWebSearchActionType", "type": "string" @@ -15006,7 +15107,7 @@ }, "type": { "enum": [ - "find_in_page" + "findInPage" ], "title": "FindInPageWebSearchActionType", "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json index cb1454260..94a6c8ba7 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json @@ -607,7 +607,7 @@ "action": { "anyOf": [ { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, { "type": "null" @@ -733,7 +733,7 @@ } ] }, - "WebSearchAction": { + "ResponsesApiWebSearchAction": { "oneOf": [ { "properties": { @@ -756,14 +756,14 @@ "enum": [ "search" ], - "title": "SearchWebSearchActionType", + "title": "SearchResponsesApiWebSearchActionType", "type": "string" } }, "required": [ "type" ], - "title": "SearchWebSearchAction", + "title": "SearchResponsesApiWebSearchAction", "type": "object" }, { @@ -772,7 +772,7 @@ "enum": [ "open_page" ], - "title": "OpenPageWebSearchActionType", + "title": "OpenPageResponsesApiWebSearchActionType", "type": "string" }, "url": { @@ -785,7 +785,7 @@ "required": [ "type" ], - "title": "OpenPageWebSearchAction", + "title": "OpenPageResponsesApiWebSearchAction", "type": "object" }, { @@ -800,7 +800,7 @@ "enum": [ "find_in_page" ], - "title": "FindInPageWebSearchActionType", + "title": "FindInPageResponsesApiWebSearchActionType", "type": "string" }, "url": { @@ -813,7 +813,7 @@ "required": [ "type" ], - "title": "FindInPageWebSearchAction", + "title": "FindInPageResponsesApiWebSearchAction", "type": "object" }, { @@ -822,14 +822,14 @@ "enum": [ "other" ], - "title": "OtherWebSearchActionType", + "title": "OtherResponsesApiWebSearchActionType", "type": "string" } }, "required": [ "type" ], - "title": "OtherWebSearchAction", + "title": "OtherResponsesApiWebSearchAction", "type": "object" } ] diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json index 3dce8b5df..75c8a3967 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json @@ -657,7 +657,7 @@ "action": { "anyOf": [ { - "$ref": "#/definitions/WebSearchAction" + "$ref": "#/definitions/ResponsesApiWebSearchAction" }, { "type": "null" @@ -783,22 +783,7 @@ } ] }, - "SandboxMode": { - "enum": [ - "read-only", - "workspace-write", - "danger-full-access" - ], - "type": "string" - }, - "ServiceTier": { - "enum": [ - "fast", - "flex" - ], - "type": "string" - }, - "WebSearchAction": { + "ResponsesApiWebSearchAction": { "oneOf": [ { "properties": { @@ -821,14 +806,14 @@ "enum": [ "search" ], - "title": "SearchWebSearchActionType", + "title": "SearchResponsesApiWebSearchActionType", "type": "string" } }, "required": [ "type" ], - "title": "SearchWebSearchAction", + "title": "SearchResponsesApiWebSearchAction", "type": "object" }, { @@ -837,7 +822,7 @@ "enum": [ "open_page" ], - "title": "OpenPageWebSearchActionType", + "title": "OpenPageResponsesApiWebSearchActionType", "type": "string" }, "url": { @@ -850,7 +835,7 @@ "required": [ "type" ], - "title": "OpenPageWebSearchAction", + "title": "OpenPageResponsesApiWebSearchAction", "type": "object" }, { @@ -865,7 +850,7 @@ "enum": [ "find_in_page" ], - "title": "FindInPageWebSearchActionType", + "title": "FindInPageResponsesApiWebSearchActionType", "type": "string" }, "url": { @@ -878,7 +863,7 @@ "required": [ "type" ], - "title": "FindInPageWebSearchAction", + "title": "FindInPageResponsesApiWebSearchAction", "type": "object" }, { @@ -887,17 +872,32 @@ "enum": [ "other" ], - "title": "OtherWebSearchActionType", + "title": "OtherResponsesApiWebSearchActionType", "type": "string" } }, "required": [ "type" ], - "title": "OtherWebSearchAction", + "title": "OtherResponsesApiWebSearchAction", "type": "object" } ] + }, + "SandboxMode": { + "enum": [ + "read-only", + "workspace-write", + "danger-full-access" + ], + "type": "string" + }, + "ServiceTier": { + "enum": [ + "fast", + "flex" + ], + "type": "string" } }, "description": "There are three ways to resume a thread: 1. By thread_id: load the thread from disk by thread_id and resume it. 2. By history: instantiate the thread from memory and resume it. 3. By path: load the thread from disk by path and resume it.\n\nThe precedence is: history > path > thread_id. If using history or path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.", diff --git a/codex-rs/app-server-protocol/src/export.rs b/codex-rs/app-server-protocol/src/export.rs index aad5ab723..ba151046a 100644 --- a/codex-rs/app-server-protocol/src/export.rs +++ b/codex-rs/app-server-protocol/src/export.rs @@ -1154,13 +1154,40 @@ fn insert_into_namespace( .or_insert_with(|| Value::Object(Map::new())); match entry { Value::Object(map) => { - map.insert(name, schema); - Ok(()) + insert_definition(map, name, schema, &format!("namespace `{namespace}`")) } _ => Err(anyhow!("expected namespace {namespace} to be an object")), } } +fn insert_definition( + definitions: &mut Map, + name: String, + schema: Value, + location: &str, +) -> Result<()> { + if let Some(existing) = definitions.get(&name) { + if existing == &schema { + return Ok(()); + } + + let existing_title = existing + .get("title") + .and_then(Value::as_str) + .unwrap_or(""); + let new_title = schema + .get("title") + .and_then(Value::as_str) + .unwrap_or(""); + return Err(anyhow!( + "schema definition collision in {location}: {name} (existing title: {existing_title}, new title: {new_title}); use #[schemars(rename = \"...\")] to rename one of the conflicting schema definitions" + )); + } + + definitions.insert(name, schema); + Ok(()) +} + fn write_json_schema_with_return(out_dir: &Path, name: &str) -> Result where T: JsonSchema, @@ -2291,6 +2318,48 @@ mod tests { Ok(()) } + #[test] + fn build_schema_bundle_rejects_conflicting_duplicate_definitions() { + let err = build_schema_bundle(vec![ + GeneratedSchema { + namespace: Some("v2".to_string()), + logical_name: "First".to_string(), + in_v1_dir: false, + value: serde_json::json!({ + "title": "First", + "type": "object", + "definitions": { + "Shared": { + "title": "SharedString", + "type": "string" + } + } + }), + }, + GeneratedSchema { + namespace: Some("v2".to_string()), + logical_name: "Second".to_string(), + in_v1_dir: false, + value: serde_json::json!({ + "title": "Second", + "type": "object", + "definitions": { + "Shared": { + "title": "SharedInteger", + "type": "integer" + } + } + }), + }, + ]) + .expect_err("conflicting schema definitions should be rejected"); + + assert_eq!( + err.to_string(), + "schema definition collision in namespace `v2`: Shared (existing title: SharedString, new title: SharedInteger); use #[schemars(rename = \"...\")] to rename one of the conflicting schema definitions" + ); + } + #[test] fn build_flat_v2_schema_keeps_shared_root_schemas_and_dependencies() -> Result<()> { let bundle = serde_json::json!({ diff --git a/codex-rs/protocol/src/models.rs b/codex-rs/protocol/src/models.rs index f211e4eff..a4a2aa2cb 100644 --- a/codex-rs/protocol/src/models.rs +++ b/codex-rs/protocol/src/models.rs @@ -879,6 +879,7 @@ pub struct LocalShellExecAction { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema, TS)] #[serde(tag = "type", rename_all = "snake_case")] +#[schemars(rename = "ResponsesApiWebSearchAction")] pub enum WebSearchAction { Search { #[serde(default, skip_serializing_if = "Option::is_none")]