Compare commits

...

1 Commits

Author SHA1 Message Date
celia-oai
d7d64631b0 changes 2026-03-18 19:02:19 -07:00
43 changed files with 3031 additions and 217 deletions

View File

@@ -163,6 +163,10 @@
],
"type": "object"
},
"CollaborationModeListParams": {
"description": "EXPERIMENTAL - list collaboration mode presets.",
"type": "object"
},
"CommandExecParams": {
"description": "Run a standalone command (argv vector) in the server sandbox without creating a thread or turn.\n\nThe final `command/exec` response is deferred until the process exits and is sent only after all `command/exec/outputDelta` notifications for that connection have been emitted.",
"properties": {
@@ -895,6 +899,50 @@
],
"type": "object"
},
"FuzzyFileSearchSessionStartParams": {
"properties": {
"roots": {
"items": {
"type": "string"
},
"type": "array"
},
"sessionId": {
"type": "string"
}
},
"required": [
"roots",
"sessionId"
],
"type": "object"
},
"FuzzyFileSearchSessionStopParams": {
"properties": {
"sessionId": {
"type": "string"
}
},
"required": [
"sessionId"
],
"type": "object"
},
"FuzzyFileSearchSessionUpdateParams": {
"properties": {
"query": {
"type": "string"
},
"sessionId": {
"type": "string"
}
},
"required": [
"query",
"sessionId"
],
"type": "object"
},
"GetAccountParams": {
"properties": {
"refreshToken": {
@@ -1200,6 +1248,18 @@
}
]
},
"MockExperimentalMethodParams": {
"properties": {
"value": {
"description": "Test-only payload field.",
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"ModeKind": {
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
@@ -2432,6 +2492,17 @@
],
"type": "object"
},
"ThreadBackgroundTerminalsCleanParams": {
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"type": "object"
},
"ThreadCompactStartParams": {
"properties": {
"threadId": {
@@ -2443,6 +2514,19 @@
],
"type": "object"
},
"ThreadDecrementElicitationParams": {
"description": "Parameters for `thread/decrement_elicitation`.",
"properties": {
"threadId": {
"description": "Thread whose out-of-band elicitation counter should be decremented.",
"type": "string"
}
},
"required": [
"threadId"
],
"type": "object"
},
"ThreadForkParams": {
"description": "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
"properties": {
@@ -2508,6 +2592,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to fork from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"sandbox": {
"anyOf": [
{
@@ -2544,6 +2640,19 @@
],
"type": "object"
},
"ThreadIncrementElicitationParams": {
"description": "Parameters for `thread/increment_elicitation`.",
"properties": {
"threadId": {
"description": "Thread whose out-of-band elicitation counter should be incremented.",
"type": "string"
}
},
"required": [
"threadId"
],
"type": "object"
},
"ThreadListParams": {
"properties": {
"archived": {
@@ -2702,6 +2811,38 @@
],
"type": "object"
},
"ThreadRealtimeAppendAudioParams": {
"description": "EXPERIMENTAL - append audio input to thread realtime.",
"properties": {
"audio": {
"$ref": "#/definitions/ThreadRealtimeAudioChunk"
},
"threadId": {
"type": "string"
}
},
"required": [
"audio",
"threadId"
],
"type": "object"
},
"ThreadRealtimeAppendTextParams": {
"description": "EXPERIMENTAL - append text input to thread realtime.",
"properties": {
"text": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"text",
"threadId"
],
"type": "object"
},
"ThreadRealtimeAudioChunk": {
"description": "EXPERIMENTAL - thread realtime audio chunk.",
"properties": {
@@ -2740,6 +2881,40 @@
],
"type": "object"
},
"ThreadRealtimeStartParams": {
"description": "EXPERIMENTAL - start a thread-scoped realtime session.",
"properties": {
"prompt": {
"type": "string"
},
"sessionId": {
"type": [
"string",
"null"
]
},
"threadId": {
"type": "string"
}
},
"required": [
"prompt",
"threadId"
],
"type": "object"
},
"ThreadRealtimeStopParams": {
"description": "EXPERIMENTAL - stop thread realtime.",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"type": "object"
},
"ThreadResumeParams": {
"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.",
"properties": {
@@ -2789,6 +2964,16 @@
"null"
]
},
"history": {
"description": "[UNSTABLE] FOR CODEX CLOUD - DO NOT USE. If specified, the thread will be resumed with the provided history instead of loaded from disk.",
"items": {
"$ref": "#/definitions/ResponseItem"
},
"type": [
"array",
"null"
]
},
"model": {
"description": "Configuration overrides for the resumed thread, if any.",
"type": [
@@ -2802,6 +2987,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to resume from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{
@@ -2952,12 +3149,33 @@
"null"
]
},
"dynamicTools": {
"items": {
"$ref": "#/definitions/DynamicToolSpec"
},
"type": [
"array",
"null"
]
},
"ephemeral": {
"type": [
"boolean",
"null"
]
},
"experimentalRawEvents": {
"default": false,
"description": "If true, opt into emitting raw Responses API items on the event stream. This is for internal use only (e.g. Codex Cloud).",
"type": "boolean"
},
"mockExperimentalField": {
"description": "Test-only experimental field used to validate experimental gating and schema filtering behavior in a stable way.",
"type": [
"string",
"null"
]
},
"model": {
"type": [
"string",
@@ -2970,6 +3188,11 @@
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{
@@ -3077,6 +3300,17 @@
],
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
},
"collaborationMode": {
"anyOf": [
{
"$ref": "#/definitions/CollaborationMode"
},
{
"type": "null"
}
],
"description": "EXPERIMENTAL - Set a pre-set collaboration mode. Takes precedence over model, reasoning_effort, and developer instructions if set.\n\nFor `collaboration_mode.settings.developer_instructions`, `null` means \"use the built-in instructions for the selected mode\"."
},
"cwd": {
"description": "Override the working directory for this turn and subsequent turns.",
"type": [
@@ -3491,6 +3725,56 @@
"title": "Thread/unsubscribeRequest",
"type": "object"
},
{
"description": "Increment the thread-local out-of-band elicitation counter.\n\nThis is used by external helpers to pause timeout accounting while a user approval or other elicitation is pending outside the app-server request flow.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/increment_elicitation"
],
"title": "Thread/incrementElicitationRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadIncrementElicitationParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/incrementElicitationRequest",
"type": "object"
},
{
"description": "Decrement the thread-local out-of-band elicitation counter.\n\nWhen the count reaches zero, timeout accounting resumes for the thread.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/decrement_elicitation"
],
"title": "Thread/decrementElicitationRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadDecrementElicitationParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/decrementElicitationRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -3587,6 +3871,30 @@
"title": "Thread/compact/startRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/backgroundTerminals/clean"
],
"title": "Thread/backgroundTerminals/cleanRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadBackgroundTerminalsCleanParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/backgroundTerminals/cleanRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4091,6 +4399,102 @@
"title": "Turn/interruptRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/start"
],
"title": "Thread/realtime/startRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeStartParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/startRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/appendAudio"
],
"title": "Thread/realtime/appendAudioRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeAppendAudioParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/appendAudioRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/appendText"
],
"title": "Thread/realtime/appendTextRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeAppendTextParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/appendTextRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/stop"
],
"title": "Thread/realtime/stopRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeStopParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/stopRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4163,6 +4567,56 @@
"title": "ExperimentalFeature/listRequest",
"type": "object"
},
{
"description": "Lists collaboration mode presets.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"collaborationMode/list"
],
"title": "CollaborationMode/listRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CollaborationModeListParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "CollaborationMode/listRequest",
"type": "object"
},
{
"description": "Test-only method used to validate experimental gating.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"mock/experimentalMethod"
],
"title": "Mock/experimentalMethodRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/MockExperimentalMethodParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Mock/experimentalMethodRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -4666,6 +5120,78 @@
],
"title": "FuzzyFileSearchRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionStart"
],
"title": "FuzzyFileSearch/sessionStartRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionStartParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionStartRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionUpdate"
],
"title": "FuzzyFileSearch/sessionUpdateRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionUpdateParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionUpdateRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionStop"
],
"title": "FuzzyFileSearch/sessionStopRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionStopParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionStopRequest",
"type": "object"
}
],
"title": "ClientRequest"

View File

@@ -400,6 +400,17 @@
}
},
"properties": {
"additionalPermissions": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalPermissionProfile"
},
{
"type": "null"
}
],
"description": "Optional additional permissions requested for this command."
},
"approvalId": {
"description": "Unique identifier for this specific approval callback.\n\nFor regular shell/unified_exec approvals, this is null.\n\nFor zsh-exec-bridge subcommand approvals, multiple callbacks can belong to one parent `itemId`, so `approvalId` is a distinct opaque callback id (a UUID) used to disambiguate routing.",
"type": [
@@ -407,6 +418,16 @@
"null"
]
},
"availableDecisions": {
"description": "Ordered list of decisions the client may present for this prompt.",
"items": {
"$ref": "#/definitions/CommandExecutionApprovalDecision"
},
"type": [
"array",
"null"
]
},
"command": {
"description": "The command to be executed.",
"type": [
@@ -472,6 +493,17 @@
"null"
]
},
"skillMetadata": {
"anyOf": [
{
"$ref": "#/definitions/CommandExecutionRequestApprovalSkillMetadata"
},
{
"type": "null"
}
],
"description": "Optional skill metadata when the approval was triggered by a skill script."
},
"threadId": {
"type": "string"
},

View File

@@ -366,6 +366,17 @@
},
"CommandExecutionRequestApprovalParams": {
"properties": {
"additionalPermissions": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalPermissionProfile"
},
{
"type": "null"
}
],
"description": "Optional additional permissions requested for this command."
},
"approvalId": {
"description": "Unique identifier for this specific approval callback.\n\nFor regular shell/unified_exec approvals, this is null.\n\nFor zsh-exec-bridge subcommand approvals, multiple callbacks can belong to one parent `itemId`, so `approvalId` is a distinct opaque callback id (a UUID) used to disambiguate routing.",
"type": [
@@ -373,6 +384,16 @@
"null"
]
},
"availableDecisions": {
"description": "Ordered list of decisions the client may present for this prompt.",
"items": {
"$ref": "#/definitions/CommandExecutionApprovalDecision"
},
"type": [
"array",
"null"
]
},
"command": {
"description": "The command to be executed.",
"type": [
@@ -438,6 +459,17 @@
"null"
]
},
"skillMetadata": {
"anyOf": [
{
"$ref": "#/definitions/CommandExecutionRequestApprovalSkillMetadata"
},
{
"type": "null"
}
],
"description": "Optional skill metadata when the approval was triggered by a skill script."
},
"threadId": {
"type": "string"
},

View File

@@ -403,6 +403,56 @@
"title": "Thread/unsubscribeRequest",
"type": "object"
},
{
"description": "Increment the thread-local out-of-band elicitation counter.\n\nThis is used by external helpers to pause timeout accounting while a user approval or other elicitation is pending outside the app-server request flow.",
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/increment_elicitation"
],
"title": "Thread/incrementElicitationRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadIncrementElicitationParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/incrementElicitationRequest",
"type": "object"
},
{
"description": "Decrement the thread-local out-of-band elicitation counter.\n\nWhen the count reaches zero, timeout accounting resumes for the thread.",
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/decrement_elicitation"
],
"title": "Thread/decrementElicitationRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadDecrementElicitationParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/decrementElicitationRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -499,6 +549,30 @@
"title": "Thread/compact/startRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/backgroundTerminals/clean"
],
"title": "Thread/backgroundTerminals/cleanRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadBackgroundTerminalsCleanParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/backgroundTerminals/cleanRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1003,6 +1077,102 @@
"title": "Turn/interruptRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/realtime/start"
],
"title": "Thread/realtime/startRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadRealtimeStartParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/startRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/realtime/appendAudio"
],
"title": "Thread/realtime/appendAudioRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadRealtimeAppendAudioParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/appendAudioRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/realtime/appendText"
],
"title": "Thread/realtime/appendTextRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadRealtimeAppendTextParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/appendTextRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"thread/realtime/stop"
],
"title": "Thread/realtime/stopRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/ThreadRealtimeStopParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/stopRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1075,6 +1245,56 @@
"title": "ExperimentalFeature/listRequest",
"type": "object"
},
{
"description": "Lists collaboration mode presets.",
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"collaborationMode/list"
],
"title": "CollaborationMode/listRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/CollaborationModeListParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "CollaborationMode/listRequest",
"type": "object"
},
{
"description": "Test-only method used to validate experimental gating.",
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"mock/experimentalMethod"
],
"title": "Mock/experimentalMethodRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/MockExperimentalMethodParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Mock/experimentalMethodRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1578,6 +1798,78 @@
],
"title": "FuzzyFileSearchRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionStart"
],
"title": "FuzzyFileSearch/sessionStartRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionStartParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionStartRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionUpdate"
],
"title": "FuzzyFileSearch/sessionUpdateRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionUpdateParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionUpdateRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/v2/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionStop"
],
"title": "FuzzyFileSearch/sessionStopRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionStopParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionStopRequest",
"type": "object"
}
],
"title": "ClientRequest"
@@ -1664,6 +1956,17 @@
"CommandExecutionRequestApprovalParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"additionalPermissions": {
"anyOf": [
{
"$ref": "#/definitions/AdditionalPermissionProfile"
},
{
"type": "null"
}
],
"description": "Optional additional permissions requested for this command."
},
"approvalId": {
"description": "Unique identifier for this specific approval callback.\n\nFor regular shell/unified_exec approvals, this is null.\n\nFor zsh-exec-bridge subcommand approvals, multiple callbacks can belong to one parent `itemId`, so `approvalId` is a distinct opaque callback id (a UUID) used to disambiguate routing.",
"type": [
@@ -1671,6 +1974,16 @@
"null"
]
},
"availableDecisions": {
"description": "Ordered list of decisions the client may present for this prompt.",
"items": {
"$ref": "#/definitions/CommandExecutionApprovalDecision"
},
"type": [
"array",
"null"
]
},
"command": {
"description": "The command to be executed.",
"type": [
@@ -1736,6 +2049,17 @@
"null"
]
},
"skillMetadata": {
"anyOf": [
{
"$ref": "#/definitions/CommandExecutionRequestApprovalSkillMetadata"
},
{
"type": "null"
}
],
"description": "Optional skill metadata when the approval was triggered by a skill script."
},
"threadId": {
"type": "string"
},
@@ -2126,6 +2450,71 @@
"title": "FuzzyFileSearchSessionCompletedNotification",
"type": "object"
},
"FuzzyFileSearchSessionStartParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"roots": {
"items": {
"type": "string"
},
"type": "array"
},
"sessionId": {
"type": "string"
}
},
"required": [
"roots",
"sessionId"
],
"title": "FuzzyFileSearchSessionStartParams",
"type": "object"
},
"FuzzyFileSearchSessionStartResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchSessionStartResponse",
"type": "object"
},
"FuzzyFileSearchSessionStopParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"sessionId": {
"type": "string"
}
},
"required": [
"sessionId"
],
"title": "FuzzyFileSearchSessionStopParams",
"type": "object"
},
"FuzzyFileSearchSessionStopResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchSessionStopResponse",
"type": "object"
},
"FuzzyFileSearchSessionUpdateParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"query": {
"type": "string"
},
"sessionId": {
"type": "string"
}
},
"required": [
"query",
"sessionId"
],
"title": "FuzzyFileSearchSessionUpdateParams",
"type": "object"
},
"FuzzyFileSearchSessionUpdateResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FuzzyFileSearchSessionUpdateResponse",
"type": "object"
},
"FuzzyFileSearchSessionUpdatedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -5642,6 +6031,29 @@
],
"type": "object"
},
"CollaborationModeListParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - list collaboration mode presets.",
"title": "CollaborationModeListParams",
"type": "object"
},
"CollaborationModeListResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - collaboration mode presets response.",
"properties": {
"data": {
"items": {
"$ref": "#/definitions/v2/CollaborationModeMask"
},
"type": "array"
}
},
"required": [
"data"
],
"title": "CollaborationModeListResponse",
"type": "object"
},
"CollaborationModeMask": {
"description": "EXPERIMENTAL - collaboration mode preset metadata for clients.",
"properties": {
@@ -6153,6 +6565,17 @@
],
"description": "[UNSTABLE] Optional default for where approval requests are routed for review."
},
"apps": {
"anyOf": [
{
"$ref": "#/definitions/v2/AppsConfig"
},
{
"type": "null"
}
],
"default": null
},
"compact_prompt": {
"type": [
"string",
@@ -6653,6 +7076,16 @@
"object",
"null"
]
},
"network": {
"anyOf": [
{
"$ref": "#/definitions/v2/NetworkRequirements"
},
{
"type": "null"
}
]
}
},
"type": "object"
@@ -8674,6 +9107,34 @@
}
]
},
"MockExperimentalMethodParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"value": {
"description": "Test-only payload field.",
"type": [
"string",
"null"
]
}
},
"title": "MockExperimentalMethodParams",
"type": "object"
},
"MockExperimentalMethodResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"echoed": {
"description": "Echoes the input `value`.",
"type": [
"string",
"null"
]
}
},
"title": "MockExperimentalMethodResponse",
"type": "object"
},
"ModeKind": {
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
@@ -8899,6 +9360,14 @@
],
"type": "string"
},
"NetworkDomainPermission": {
"enum": [
"allow",
"deny",
"none"
],
"type": "string"
},
"NetworkRequirements": {
"properties": {
"allowLocalBinding": {
@@ -8907,30 +9376,12 @@
"null"
]
},
"allowUnixSockets": {
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"allowUpstreamProxy": {
"type": [
"boolean",
"null"
]
},
"allowedDomains": {
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"dangerouslyAllowAllUnixSockets": {
"type": [
"boolean",
@@ -8943,12 +9394,12 @@
"null"
]
},
"deniedDomains": {
"items": {
"type": "string"
"domains": {
"additionalProperties": {
"$ref": "#/definitions/v2/NetworkDomainPermission"
},
"type": [
"array",
"object",
"null"
]
},
@@ -8973,10 +9424,26 @@
"integer",
"null"
]
},
"unixSockets": {
"additionalProperties": {
"$ref": "#/definitions/v2/NetworkUnixSocketPermission"
},
"type": [
"object",
"null"
]
}
},
"type": "object"
},
"NetworkUnixSocketPermission": {
"enum": [
"allow",
"none"
],
"type": "string"
},
"OverriddenMetadata": {
"properties": {
"effectiveValue": true,
@@ -11675,6 +12142,24 @@
"title": "ThreadArchivedNotification",
"type": "object"
},
"ThreadBackgroundTerminalsCleanParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadBackgroundTerminalsCleanParams",
"type": "object"
},
"ThreadBackgroundTerminalsCleanResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ThreadBackgroundTerminalsCleanResponse",
"type": "object"
},
"ThreadClosedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -11706,6 +12191,43 @@
"title": "ThreadCompactStartResponse",
"type": "object"
},
"ThreadDecrementElicitationParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Parameters for `thread/decrement_elicitation`.",
"properties": {
"threadId": {
"description": "Thread whose out-of-band elicitation counter should be decremented.",
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadDecrementElicitationParams",
"type": "object"
},
"ThreadDecrementElicitationResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Response for `thread/decrement_elicitation`.",
"properties": {
"count": {
"description": "Current out-of-band elicitation count after the decrement.",
"format": "uint64",
"minimum": 0.0,
"type": "integer"
},
"paused": {
"description": "Whether timeout accounting remains paused after applying the decrement.",
"type": "boolean"
}
},
"required": [
"count",
"paused"
],
"title": "ThreadDecrementElicitationResponse",
"type": "object"
},
"ThreadForkParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
@@ -11772,6 +12294,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to fork from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"sandbox": {
"anyOf": [
{
@@ -11874,6 +12408,43 @@
"ThreadId": {
"type": "string"
},
"ThreadIncrementElicitationParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Parameters for `thread/increment_elicitation`.",
"properties": {
"threadId": {
"description": "Thread whose out-of-band elicitation counter should be incremented.",
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadIncrementElicitationParams",
"type": "object"
},
"ThreadIncrementElicitationResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Response for `thread/increment_elicitation`.",
"properties": {
"count": {
"description": "Current out-of-band elicitation count after the increment.",
"format": "uint64",
"minimum": 0.0,
"type": "integer"
},
"paused": {
"description": "Whether timeout accounting is paused after applying the increment.",
"type": "boolean"
}
},
"required": [
"count",
"paused"
],
"title": "ThreadIncrementElicitationResponse",
"type": "object"
},
"ThreadItem": {
"oneOf": [
{
@@ -12731,6 +13302,54 @@
"title": "ThreadReadResponse",
"type": "object"
},
"ThreadRealtimeAppendAudioParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - append audio input to thread realtime.",
"properties": {
"audio": {
"$ref": "#/definitions/v2/ThreadRealtimeAudioChunk"
},
"threadId": {
"type": "string"
}
},
"required": [
"audio",
"threadId"
],
"title": "ThreadRealtimeAppendAudioParams",
"type": "object"
},
"ThreadRealtimeAppendAudioResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for appending realtime audio input.",
"title": "ThreadRealtimeAppendAudioResponse",
"type": "object"
},
"ThreadRealtimeAppendTextParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - append text input to thread realtime.",
"properties": {
"text": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"text",
"threadId"
],
"title": "ThreadRealtimeAppendTextParams",
"type": "object"
},
"ThreadRealtimeAppendTextResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for appending realtime text input.",
"title": "ThreadRealtimeAppendTextResponse",
"type": "object"
},
"ThreadRealtimeAudioChunk": {
"description": "EXPERIMENTAL - thread realtime audio chunk.",
"properties": {
@@ -12841,6 +13460,36 @@
"title": "ThreadRealtimeOutputAudioDeltaNotification",
"type": "object"
},
"ThreadRealtimeStartParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - start a thread-scoped realtime session.",
"properties": {
"prompt": {
"type": "string"
},
"sessionId": {
"type": [
"string",
"null"
]
},
"threadId": {
"type": "string"
}
},
"required": [
"prompt",
"threadId"
],
"title": "ThreadRealtimeStartParams",
"type": "object"
},
"ThreadRealtimeStartResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for starting thread realtime.",
"title": "ThreadRealtimeStartResponse",
"type": "object"
},
"ThreadRealtimeStartedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted when thread realtime startup is accepted.",
@@ -12865,6 +13514,26 @@
"title": "ThreadRealtimeStartedNotification",
"type": "object"
},
"ThreadRealtimeStopParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - stop thread realtime.",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadRealtimeStopParams",
"type": "object"
},
"ThreadRealtimeStopResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for stopping thread realtime.",
"title": "ThreadRealtimeStopResponse",
"type": "object"
},
"ThreadResumeParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"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.",
@@ -12915,6 +13584,16 @@
"null"
]
},
"history": {
"description": "[UNSTABLE] FOR CODEX CLOUD - DO NOT USE. If specified, the thread will be resumed with the provided history instead of loaded from disk.",
"items": {
"$ref": "#/definitions/v2/ResponseItem"
},
"type": [
"array",
"null"
]
},
"model": {
"description": "Configuration overrides for the resumed thread, if any.",
"type": [
@@ -12928,6 +13607,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to resume from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{
@@ -13169,12 +13860,33 @@
"null"
]
},
"dynamicTools": {
"items": {
"$ref": "#/definitions/v2/DynamicToolSpec"
},
"type": [
"array",
"null"
]
},
"ephemeral": {
"type": [
"boolean",
"null"
]
},
"experimentalRawEvents": {
"default": false,
"description": "If true, opt into emitting raw Responses API items on the event stream. This is for internal use only (e.g. Codex Cloud).",
"type": "boolean"
},
"mockExperimentalField": {
"description": "Test-only experimental field used to validate experimental gating and schema filtering behavior in a stable way.",
"type": [
"string",
"null"
]
},
"model": {
"type": [
"string",
@@ -13187,6 +13899,11 @@
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{
@@ -13807,6 +14524,17 @@
],
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
},
"collaborationMode": {
"anyOf": [
{
"$ref": "#/definitions/v2/CollaborationMode"
},
{
"type": "null"
}
],
"description": "EXPERIMENTAL - Set a pre-set collaboration mode. Takes precedence over model, reasoning_effort, and developer instructions if set.\n\nFor `collaboration_mode.settings.developer_instructions`, `null` means \"use the built-in instructions for the selected mode\"."
},
"cwd": {
"description": "Override the working directory for this turn and subsequent turns.",
"type": [

View File

@@ -930,6 +930,56 @@
"title": "Thread/unsubscribeRequest",
"type": "object"
},
{
"description": "Increment the thread-local out-of-band elicitation counter.\n\nThis is used by external helpers to pause timeout accounting while a user approval or other elicitation is pending outside the app-server request flow.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/increment_elicitation"
],
"title": "Thread/incrementElicitationRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadIncrementElicitationParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/incrementElicitationRequest",
"type": "object"
},
{
"description": "Decrement the thread-local out-of-band elicitation counter.\n\nWhen the count reaches zero, timeout accounting resumes for the thread.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/decrement_elicitation"
],
"title": "Thread/decrementElicitationRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadDecrementElicitationParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/decrementElicitationRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1026,6 +1076,30 @@
"title": "Thread/compact/startRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/backgroundTerminals/clean"
],
"title": "Thread/backgroundTerminals/cleanRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadBackgroundTerminalsCleanParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/backgroundTerminals/cleanRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1530,6 +1604,102 @@
"title": "Turn/interruptRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/start"
],
"title": "Thread/realtime/startRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeStartParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/startRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/appendAudio"
],
"title": "Thread/realtime/appendAudioRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeAppendAudioParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/appendAudioRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/appendText"
],
"title": "Thread/realtime/appendTextRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeAppendTextParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/appendTextRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"thread/realtime/stop"
],
"title": "Thread/realtime/stopRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/ThreadRealtimeStopParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Thread/realtime/stopRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1602,6 +1772,56 @@
"title": "ExperimentalFeature/listRequest",
"type": "object"
},
{
"description": "Lists collaboration mode presets.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"collaborationMode/list"
],
"title": "CollaborationMode/listRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CollaborationModeListParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "CollaborationMode/listRequest",
"type": "object"
},
{
"description": "Test-only method used to validate experimental gating.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"mock/experimentalMethod"
],
"title": "Mock/experimentalMethodRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/MockExperimentalMethodParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Mock/experimentalMethodRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -2105,6 +2325,78 @@
],
"title": "FuzzyFileSearchRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionStart"
],
"title": "FuzzyFileSearch/sessionStartRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionStartParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionStartRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionUpdate"
],
"title": "FuzzyFileSearch/sessionUpdateRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionUpdateParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionUpdateRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"fuzzyFileSearch/sessionStop"
],
"title": "FuzzyFileSearch/sessionStopRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/FuzzyFileSearchSessionStopParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "FuzzyFileSearch/sessionStopRequest",
"type": "object"
}
],
"title": "ClientRequest"
@@ -2286,6 +2578,29 @@
],
"type": "object"
},
"CollaborationModeListParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - list collaboration mode presets.",
"title": "CollaborationModeListParams",
"type": "object"
},
"CollaborationModeListResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - collaboration mode presets response.",
"properties": {
"data": {
"items": {
"$ref": "#/definitions/CollaborationModeMask"
},
"type": "array"
}
},
"required": [
"data"
],
"title": "CollaborationModeListResponse",
"type": "object"
},
"CollaborationModeMask": {
"description": "EXPERIMENTAL - collaboration mode preset metadata for clients.",
"properties": {
@@ -2797,6 +3112,17 @@
],
"description": "[UNSTABLE] Optional default for where approval requests are routed for review."
},
"apps": {
"anyOf": [
{
"$ref": "#/definitions/AppsConfig"
},
{
"type": "null"
}
],
"default": null
},
"compact_prompt": {
"type": [
"string",
@@ -3297,6 +3623,16 @@
"object",
"null"
]
},
"network": {
"anyOf": [
{
"$ref": "#/definitions/NetworkRequirements"
},
{
"type": "null"
}
]
}
},
"type": "object"
@@ -4403,6 +4739,56 @@
"title": "FuzzyFileSearchSessionCompletedNotification",
"type": "object"
},
"FuzzyFileSearchSessionStartParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"roots": {
"items": {
"type": "string"
},
"type": "array"
},
"sessionId": {
"type": "string"
}
},
"required": [
"roots",
"sessionId"
],
"title": "FuzzyFileSearchSessionStartParams",
"type": "object"
},
"FuzzyFileSearchSessionStopParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"sessionId": {
"type": "string"
}
},
"required": [
"sessionId"
],
"title": "FuzzyFileSearchSessionStopParams",
"type": "object"
},
"FuzzyFileSearchSessionUpdateParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"query": {
"type": "string"
},
"sessionId": {
"type": "string"
}
},
"required": [
"query",
"sessionId"
],
"title": "FuzzyFileSearchSessionUpdateParams",
"type": "object"
},
"FuzzyFileSearchSessionUpdatedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -5462,6 +5848,34 @@
}
]
},
"MockExperimentalMethodParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"value": {
"description": "Test-only payload field.",
"type": [
"string",
"null"
]
}
},
"title": "MockExperimentalMethodParams",
"type": "object"
},
"MockExperimentalMethodResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"echoed": {
"description": "Echoes the input `value`.",
"type": [
"string",
"null"
]
}
},
"title": "MockExperimentalMethodResponse",
"type": "object"
},
"ModeKind": {
"description": "Initial collaboration mode to use when the TUI starts.",
"enum": [
@@ -5687,6 +6101,14 @@
],
"type": "string"
},
"NetworkDomainPermission": {
"enum": [
"allow",
"deny",
"none"
],
"type": "string"
},
"NetworkRequirements": {
"properties": {
"allowLocalBinding": {
@@ -5695,30 +6117,12 @@
"null"
]
},
"allowUnixSockets": {
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"allowUpstreamProxy": {
"type": [
"boolean",
"null"
]
},
"allowedDomains": {
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"dangerouslyAllowAllUnixSockets": {
"type": [
"boolean",
@@ -5731,12 +6135,12 @@
"null"
]
},
"deniedDomains": {
"items": {
"type": "string"
"domains": {
"additionalProperties": {
"$ref": "#/definitions/NetworkDomainPermission"
},
"type": [
"array",
"object",
"null"
]
},
@@ -5761,10 +6165,26 @@
"integer",
"null"
]
},
"unixSockets": {
"additionalProperties": {
"$ref": "#/definitions/NetworkUnixSocketPermission"
},
"type": [
"object",
"null"
]
}
},
"type": "object"
},
"NetworkUnixSocketPermission": {
"enum": [
"allow",
"none"
],
"type": "string"
},
"OverriddenMetadata": {
"properties": {
"effectiveValue": true,
@@ -9435,6 +9855,24 @@
"title": "ThreadArchivedNotification",
"type": "object"
},
"ThreadBackgroundTerminalsCleanParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadBackgroundTerminalsCleanParams",
"type": "object"
},
"ThreadBackgroundTerminalsCleanResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ThreadBackgroundTerminalsCleanResponse",
"type": "object"
},
"ThreadClosedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -9466,6 +9904,43 @@
"title": "ThreadCompactStartResponse",
"type": "object"
},
"ThreadDecrementElicitationParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Parameters for `thread/decrement_elicitation`.",
"properties": {
"threadId": {
"description": "Thread whose out-of-band elicitation counter should be decremented.",
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadDecrementElicitationParams",
"type": "object"
},
"ThreadDecrementElicitationResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Response for `thread/decrement_elicitation`.",
"properties": {
"count": {
"description": "Current out-of-band elicitation count after the decrement.",
"format": "uint64",
"minimum": 0.0,
"type": "integer"
},
"paused": {
"description": "Whether timeout accounting remains paused after applying the decrement.",
"type": "boolean"
}
},
"required": [
"count",
"paused"
],
"title": "ThreadDecrementElicitationResponse",
"type": "object"
},
"ThreadForkParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "There are two ways to fork a thread: 1. By thread_id: load the thread from disk by thread_id and fork it into a new thread. 2. By path: load the thread from disk by path and fork it into a new thread.\n\nIf using path, the thread_id param will be ignored.\n\nPrefer using thread_id whenever possible.",
@@ -9532,6 +10007,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to fork from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"sandbox": {
"anyOf": [
{
@@ -9634,6 +10121,43 @@
"ThreadId": {
"type": "string"
},
"ThreadIncrementElicitationParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Parameters for `thread/increment_elicitation`.",
"properties": {
"threadId": {
"description": "Thread whose out-of-band elicitation counter should be incremented.",
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadIncrementElicitationParams",
"type": "object"
},
"ThreadIncrementElicitationResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Response for `thread/increment_elicitation`.",
"properties": {
"count": {
"description": "Current out-of-band elicitation count after the increment.",
"format": "uint64",
"minimum": 0.0,
"type": "integer"
},
"paused": {
"description": "Whether timeout accounting is paused after applying the increment.",
"type": "boolean"
}
},
"required": [
"count",
"paused"
],
"title": "ThreadIncrementElicitationResponse",
"type": "object"
},
"ThreadItem": {
"oneOf": [
{
@@ -10491,6 +11015,54 @@
"title": "ThreadReadResponse",
"type": "object"
},
"ThreadRealtimeAppendAudioParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - append audio input to thread realtime.",
"properties": {
"audio": {
"$ref": "#/definitions/ThreadRealtimeAudioChunk"
},
"threadId": {
"type": "string"
}
},
"required": [
"audio",
"threadId"
],
"title": "ThreadRealtimeAppendAudioParams",
"type": "object"
},
"ThreadRealtimeAppendAudioResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for appending realtime audio input.",
"title": "ThreadRealtimeAppendAudioResponse",
"type": "object"
},
"ThreadRealtimeAppendTextParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - append text input to thread realtime.",
"properties": {
"text": {
"type": "string"
},
"threadId": {
"type": "string"
}
},
"required": [
"text",
"threadId"
],
"title": "ThreadRealtimeAppendTextParams",
"type": "object"
},
"ThreadRealtimeAppendTextResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for appending realtime text input.",
"title": "ThreadRealtimeAppendTextResponse",
"type": "object"
},
"ThreadRealtimeAudioChunk": {
"description": "EXPERIMENTAL - thread realtime audio chunk.",
"properties": {
@@ -10601,6 +11173,36 @@
"title": "ThreadRealtimeOutputAudioDeltaNotification",
"type": "object"
},
"ThreadRealtimeStartParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - start a thread-scoped realtime session.",
"properties": {
"prompt": {
"type": "string"
},
"sessionId": {
"type": [
"string",
"null"
]
},
"threadId": {
"type": "string"
}
},
"required": [
"prompt",
"threadId"
],
"title": "ThreadRealtimeStartParams",
"type": "object"
},
"ThreadRealtimeStartResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for starting thread realtime.",
"title": "ThreadRealtimeStartResponse",
"type": "object"
},
"ThreadRealtimeStartedNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - emitted when thread realtime startup is accepted.",
@@ -10625,6 +11227,26 @@
"title": "ThreadRealtimeStartedNotification",
"type": "object"
},
"ThreadRealtimeStopParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - stop thread realtime.",
"properties": {
"threadId": {
"type": "string"
}
},
"required": [
"threadId"
],
"title": "ThreadRealtimeStopParams",
"type": "object"
},
"ThreadRealtimeStopResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "EXPERIMENTAL - response for stopping thread realtime.",
"title": "ThreadRealtimeStopResponse",
"type": "object"
},
"ThreadResumeParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"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.",
@@ -10675,6 +11297,16 @@
"null"
]
},
"history": {
"description": "[UNSTABLE] FOR CODEX CLOUD - DO NOT USE. If specified, the thread will be resumed with the provided history instead of loaded from disk.",
"items": {
"$ref": "#/definitions/ResponseItem"
},
"type": [
"array",
"null"
]
},
"model": {
"description": "Configuration overrides for the resumed thread, if any.",
"type": [
@@ -10688,6 +11320,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to resume from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{
@@ -10929,12 +11573,33 @@
"null"
]
},
"dynamicTools": {
"items": {
"$ref": "#/definitions/DynamicToolSpec"
},
"type": [
"array",
"null"
]
},
"ephemeral": {
"type": [
"boolean",
"null"
]
},
"experimentalRawEvents": {
"default": false,
"description": "If true, opt into emitting raw Responses API items on the event stream. This is for internal use only (e.g. Codex Cloud).",
"type": "boolean"
},
"mockExperimentalField": {
"description": "Test-only experimental field used to validate experimental gating and schema filtering behavior in a stable way.",
"type": [
"string",
"null"
]
},
"model": {
"type": [
"string",
@@ -10947,6 +11612,11 @@
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{
@@ -11567,6 +12237,17 @@
],
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
},
"collaborationMode": {
"anyOf": [
{
"$ref": "#/definitions/CollaborationMode"
},
{
"type": "null"
}
],
"description": "EXPERIMENTAL - Set a pre-set collaboration mode. Takes precedence over model, reasoning_effort, and developer instructions if set.\n\nFor `collaboration_mode.settings.developer_instructions`, `null` means \"use the built-in instructions for the selected mode\"."
},
"cwd": {
"description": "Override the working directory for this turn and subsequent turns.",
"type": [

View File

@@ -221,6 +221,17 @@
],
"description": "[UNSTABLE] Optional default for where approval requests are routed for review."
},
"apps": {
"anyOf": [
{
"$ref": "#/definitions/AppsConfig"
},
{
"type": "null"
}
],
"default": null
},
"compact_prompt": {
"type": [
"string",

View File

@@ -98,10 +98,28 @@
"object",
"null"
]
},
"network": {
"anyOf": [
{
"$ref": "#/definitions/NetworkRequirements"
},
{
"type": "null"
}
]
}
},
"type": "object"
},
"NetworkDomainPermission": {
"enum": [
"allow",
"deny",
"none"
],
"type": "string"
},
"NetworkRequirements": {
"properties": {
"allowLocalBinding": {
@@ -110,30 +128,12 @@
"null"
]
},
"allowUnixSockets": {
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"allowUpstreamProxy": {
"type": [
"boolean",
"null"
]
},
"allowedDomains": {
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
},
"dangerouslyAllowAllUnixSockets": {
"type": [
"boolean",
@@ -146,12 +146,12 @@
"null"
]
},
"deniedDomains": {
"items": {
"type": "string"
"domains": {
"additionalProperties": {
"$ref": "#/definitions/NetworkDomainPermission"
},
"type": [
"array",
"object",
"null"
]
},
@@ -176,10 +176,26 @@
"integer",
"null"
]
},
"unixSockets": {
"additionalProperties": {
"$ref": "#/definitions/NetworkUnixSocketPermission"
},
"type": [
"object",
"null"
]
}
},
"type": "object"
},
"NetworkUnixSocketPermission": {
"enum": [
"allow",
"none"
],
"type": "string"
},
"ResidencyRequirement": {
"enum": [
"us"

View File

@@ -139,6 +139,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to fork from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"sandbox": {
"anyOf": [
{

View File

@@ -1029,6 +1029,16 @@
"null"
]
},
"history": {
"description": "[UNSTABLE] FOR CODEX CLOUD - DO NOT USE. If specified, the thread will be resumed with the provided history instead of loaded from disk.",
"items": {
"$ref": "#/definitions/ResponseItem"
},
"type": [
"array",
"null"
]
},
"model": {
"description": "Configuration overrides for the resumed thread, if any.",
"type": [
@@ -1042,6 +1052,18 @@
"null"
]
},
"path": {
"description": "[UNSTABLE] Specify the rollout path to resume from. If specified, the thread_id param will be ignored.",
"type": [
"string",
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on subsequent resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{

View File

@@ -150,12 +150,33 @@
"null"
]
},
"dynamicTools": {
"items": {
"$ref": "#/definitions/DynamicToolSpec"
},
"type": [
"array",
"null"
]
},
"ephemeral": {
"type": [
"boolean",
"null"
]
},
"experimentalRawEvents": {
"default": false,
"description": "If true, opt into emitting raw Responses API items on the event stream. This is for internal use only (e.g. Codex Cloud).",
"type": "boolean"
},
"mockExperimentalField": {
"description": "Test-only experimental field used to validate experimental gating and schema filtering behavior in a stable way.",
"type": [
"string",
"null"
]
},
"model": {
"type": [
"string",
@@ -168,6 +189,11 @@
"null"
]
},
"persistExtendedHistory": {
"default": false,
"description": "If true, persist additional rollout EventMsg variants required to reconstruct a richer thread history on resume/fork/read.",
"type": "boolean"
},
"personality": {
"anyOf": [
{

View File

@@ -521,6 +521,17 @@
],
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
},
"collaborationMode": {
"anyOf": [
{
"$ref": "#/definitions/CollaborationMode"
},
{
"type": "null"
}
],
"description": "EXPERIMENTAL - Set a pre-set collaboration mode. Takes precedence over model, reasoning_effort, and developer instructions if set.\n\nFor `collaboration_mode.settings.developer_instructions`, `null` means \"use the built-in instructions for the selected mode\"."
},
"cwd": {
"description": "Override the working directory for this turn and subsequent turns.",
"type": [

File diff suppressed because one or more lines are too long

View File

@@ -22,6 +22,12 @@ export type { FuzzyFileSearchParams } from "./FuzzyFileSearchParams";
export type { FuzzyFileSearchResponse } from "./FuzzyFileSearchResponse";
export type { FuzzyFileSearchResult } from "./FuzzyFileSearchResult";
export type { FuzzyFileSearchSessionCompletedNotification } from "./FuzzyFileSearchSessionCompletedNotification";
export type { FuzzyFileSearchSessionStartParams } from "./FuzzyFileSearchSessionStartParams";
export type { FuzzyFileSearchSessionStartResponse } from "./FuzzyFileSearchSessionStartResponse";
export type { FuzzyFileSearchSessionStopParams } from "./FuzzyFileSearchSessionStopParams";
export type { FuzzyFileSearchSessionStopResponse } from "./FuzzyFileSearchSessionStopResponse";
export type { FuzzyFileSearchSessionUpdateParams } from "./FuzzyFileSearchSessionUpdateParams";
export type { FuzzyFileSearchSessionUpdateResponse } from "./FuzzyFileSearchSessionUpdateResponse";
export type { FuzzyFileSearchSessionUpdatedNotification } from "./FuzzyFileSearchSessionUpdatedNotification";
export type { GetAuthStatusParams } from "./GetAuthStatusParams";
export type { GetAuthStatusResponse } from "./GetAuthStatusResponse";

View File

@@ -10,14 +10,16 @@ import type { WebSearchMode } from "../WebSearchMode";
import type { JsonValue } from "../serde_json/JsonValue";
import type { AnalyticsConfig } from "./AnalyticsConfig";
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
import type { AppsConfig } from "./AppsConfig";
import type { AskForApproval } from "./AskForApproval";
import type { ProfileV2 } from "./ProfileV2";
import type { SandboxMode } from "./SandboxMode";
import type { SandboxWorkspaceWrite } from "./SandboxWorkspaceWrite";
import type { ToolsV2 } from "./ToolsV2";
export type Config = {model: string | null, review_model: string | null, model_context_window: bigint | null, model_auto_compact_token_limit: bigint | null, model_provider: string | null, approval_policy: AskForApproval | null, /**
export type Config = { model: string | null, review_model: string | null, model_context_window: bigint | null, model_auto_compact_token_limit: bigint | null, model_provider: string | null, approval_policy: AskForApproval | null,
/**
* [UNSTABLE] Optional default for where approval requests are routed for
* review.
*/
approvals_reviewer: ApprovalsReviewer | null, sandbox_mode: SandboxMode | null, sandbox_workspace_write: SandboxWorkspaceWrite | null, forced_chatgpt_workspace_id: string | null, forced_login_method: ForcedLoginMethod | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, profile: string | null, profiles: { [key in string]?: ProfileV2 }, instructions: string | null, developer_instructions: string | null, compact_prompt: string | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, service_tier: ServiceTier | null, analytics: AnalyticsConfig | null} & ({ [key in string]?: number | string | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null });
approvals_reviewer: ApprovalsReviewer | null, sandbox_mode: SandboxMode | null, sandbox_workspace_write: SandboxWorkspaceWrite | null, forced_chatgpt_workspace_id: string | null, forced_login_method: ForcedLoginMethod | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, profile: string | null, profiles: { [key in string]?: ProfileV2 }, instructions: string | null, developer_instructions: string | null, compact_prompt: string | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, service_tier: ServiceTier | null, analytics: AnalyticsConfig | null, apps: AppsConfig | null, } & ({ [key in string]?: number | string | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null });

View File

@@ -3,7 +3,8 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { WebSearchMode } from "../WebSearchMode";
import type { AskForApproval } from "./AskForApproval";
import type { NetworkRequirements } from "./NetworkRequirements";
import type { ResidencyRequirement } from "./ResidencyRequirement";
import type { SandboxMode } from "./SandboxMode";
export type ConfigRequirements = {allowedApprovalPolicies: Array<AskForApproval> | null, allowedSandboxModes: Array<SandboxMode> | null, allowedWebSearchModes: Array<WebSearchMode> | null, featureRequirements: { [key in string]?: boolean } | null, enforceResidency: ResidencyRequirement | null};
export type ConfigRequirements = { allowedApprovalPolicies: Array<AskForApproval> | null, allowedSandboxModes: Array<SandboxMode> | null, allowedWebSearchModes: Array<WebSearchMode> | null, featureRequirements: { [key in string]?: boolean } | null, enforceResidency: ResidencyRequirement | null, network: NetworkRequirements | null, };

View File

@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type NetworkDomainPermission = "allow" | "deny" | "none";

View File

@@ -1,5 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { NetworkDomainPermission } from "./NetworkDomainPermission";
import type { NetworkUnixSocketPermission } from "./NetworkUnixSocketPermission";
export type NetworkRequirements = { enabled: boolean | null, httpPort: number | null, socksPort: number | null, allowUpstreamProxy: boolean | null, dangerouslyAllowNonLoopbackProxy: boolean | null, dangerouslyAllowAllUnixSockets: boolean | null, allowedDomains: Array<string> | null, deniedDomains: Array<string> | null, allowUnixSockets: Array<string> | null, allowLocalBinding: boolean | null, };
export type NetworkRequirements = { enabled: boolean | null, httpPort: number | null, socksPort: number | null, allowUpstreamProxy: boolean | null, dangerouslyAllowNonLoopbackProxy: boolean | null, dangerouslyAllowAllUnixSockets: boolean | null, domains: { [key in string]?: NetworkDomainPermission } | null, unixSockets: { [key in string]?: NetworkUnixSocketPermission } | null, allowLocalBinding: boolean | null, };

View File

@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type NetworkUnixSocketPermission = "allow" | "none";

View File

@@ -11,9 +11,10 @@ import type { ApprovalsReviewer } from "./ApprovalsReviewer";
import type { AskForApproval } from "./AskForApproval";
import type { ToolsV2 } from "./ToolsV2";
export type ProfileV2 = {model: string | null, model_provider: string | null, approval_policy: AskForApproval | null, /**
export type ProfileV2 = { model: string | null, model_provider: string | null, approval_policy: AskForApproval | null,
/**
* [UNSTABLE] Optional profile-level override for where approval requests
* are routed for review. If omitted, the enclosing config default is
* used.
*/
approvals_reviewer: ApprovalsReviewer | null, service_tier: ServiceTier | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, chatgpt_base_url: string | null} & ({ [key in string]?: number | string | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null });
approvals_reviewer: ApprovalsReviewer | null, service_tier: ServiceTier | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, chatgpt_base_url: string | null, } & ({ [key in string]?: number | string | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null });

View File

@@ -16,19 +16,23 @@ import type { SandboxMode } from "./SandboxMode";
*
* Prefer using thread_id whenever possible.
*/
export type ThreadForkParams = {threadId: string, /**
export type ThreadForkParams = { threadId: string,
/**
* [UNSTABLE] Specify the rollout path to fork from.
* If specified, the thread_id param will be ignored.
*/
path?: string | null, /**
path?: string | null,
/**
* Configuration overrides for the forked thread, if any.
*/
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null,
/**
* Override where approval requests are routed for review on this thread
* and subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean, /**
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean,
/**
* If true, persist additional rollout EventMsg variants required to
* reconstruct a richer thread history on subsequent resume/fork/read.
*/
persistExtendedHistory: boolean};
persistExtendedHistory: boolean, };

View File

@@ -20,24 +20,29 @@ import type { SandboxMode } from "./SandboxMode";
*
* Prefer using thread_id whenever possible.
*/
export type ThreadResumeParams = {threadId: string, /**
export type ThreadResumeParams = { threadId: string,
/**
* [UNSTABLE] FOR CODEX CLOUD - DO NOT USE.
* If specified, the thread will be resumed with the provided history
* instead of loaded from disk.
*/
history?: Array<ResponseItem> | null, /**
history?: Array<ResponseItem> | null,
/**
* [UNSTABLE] Specify the rollout path to resume from.
* If specified, the thread_id param will be ignored.
*/
path?: string | null, /**
path?: string | null,
/**
* Configuration overrides for the resumed thread, if any.
*/
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null,
/**
* Override where approval requests are routed for review on this thread
* and subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, /**
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null,
/**
* If true, persist additional rollout EventMsg variants required to
* reconstruct a richer thread history on subsequent resume/fork/read.
*/
persistExtendedHistory: boolean};
persistExtendedHistory: boolean, };

View File

@@ -6,18 +6,27 @@ import type { ServiceTier } from "../ServiceTier";
import type { JsonValue } from "../serde_json/JsonValue";
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
import type { AskForApproval } from "./AskForApproval";
import type { DynamicToolSpec } from "./DynamicToolSpec";
import type { SandboxMode } from "./SandboxMode";
export type ThreadStartParams = {model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
export type ThreadStartParams = { model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null,
/**
* Override where approval requests are routed for review on this thread
* and subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, serviceName?: string | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, ephemeral?: boolean | null, /**
approvalsReviewer?: ApprovalsReviewer | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, serviceName?: string | null, baseInstructions?: string | null, developerInstructions?: string | null, personality?: Personality | null, ephemeral?: boolean | null, dynamicTools?: Array<DynamicToolSpec> | null,
/**
* Test-only experimental field used to validate experimental gating and
* schema filtering behavior in a stable way.
*/
mockExperimentalField?: string | null,
/**
* If true, opt into emitting raw Responses API items on the event stream.
* This is for internal use only (e.g. Codex Cloud).
*/
experimentalRawEvents: boolean, /**
experimentalRawEvents: boolean,
/**
* If true, persist additional rollout EventMsg variants required to
* reconstruct a richer thread history on resume/fork/read.
*/
persistExtendedHistory: boolean};
persistExtendedHistory: boolean, };

View File

@@ -12,43 +12,54 @@ import type { AskForApproval } from "./AskForApproval";
import type { SandboxPolicy } from "./SandboxPolicy";
import type { UserInput } from "./UserInput";
export type TurnStartParams = {threadId: string, input: Array<UserInput>, /**
export type TurnStartParams = { threadId: string, input: Array<UserInput>,
/**
* Override the working directory for this turn and subsequent turns.
*/
cwd?: string | null, /**
cwd?: string | null,
/**
* Override the approval policy for this turn and subsequent turns.
*/
approvalPolicy?: AskForApproval | null, /**
approvalPolicy?: AskForApproval | null,
/**
* Override where approval requests are routed for review on this turn and
* subsequent turns.
*/
approvalsReviewer?: ApprovalsReviewer | null, /**
approvalsReviewer?: ApprovalsReviewer | null,
/**
* Override the sandbox policy for this turn and subsequent turns.
*/
sandboxPolicy?: SandboxPolicy | null, /**
sandboxPolicy?: SandboxPolicy | null,
/**
* Override the model for this turn and subsequent turns.
*/
model?: string | null, /**
model?: string | null,
/**
* Override the service tier for this turn and subsequent turns.
*/
serviceTier?: ServiceTier | null | null, /**
serviceTier?: ServiceTier | null | null,
/**
* Override the reasoning effort for this turn and subsequent turns.
*/
effort?: ReasoningEffort | null, /**
effort?: ReasoningEffort | null,
/**
* Override the reasoning summary for this turn and subsequent turns.
*/
summary?: ReasoningSummary | null, /**
summary?: ReasoningSummary | null,
/**
* Override the personality for this turn and subsequent turns.
*/
personality?: Personality | null, /**
personality?: Personality | null,
/**
* Optional JSON Schema used to constrain the final assistant message for
* this turn.
*/
outputSchema?: JsonValue | null, /**
outputSchema?: JsonValue | null,
/**
* EXPERIMENTAL - Set a pre-set collaboration mode.
* Takes precedence over model, reasoning_effort, and developer instructions if set.
*
* For `collaboration_mode.settings.developer_instructions`, `null` means
* "use the built-in instructions for the selected mode".
*/
collaborationMode?: CollaborationMode | null};
collaborationMode?: CollaborationMode | null, };

View File

@@ -37,6 +37,8 @@ export type { CollabAgentState } from "./CollabAgentState";
export type { CollabAgentStatus } from "./CollabAgentStatus";
export type { CollabAgentTool } from "./CollabAgentTool";
export type { CollabAgentToolCallStatus } from "./CollabAgentToolCallStatus";
export type { CollaborationModeListParams } from "./CollaborationModeListParams";
export type { CollaborationModeListResponse } from "./CollaborationModeListResponse";
export type { CollaborationModeMask } from "./CollaborationModeMask";
export type { CommandAction } from "./CommandAction";
export type { CommandExecOutputDeltaNotification } from "./CommandExecOutputDeltaNotification";
@@ -177,6 +179,8 @@ export type { McpToolCallStatus } from "./McpToolCallStatus";
export type { MemoryCitation } from "./MemoryCitation";
export type { MemoryCitationEntry } from "./MemoryCitationEntry";
export type { MergeStrategy } from "./MergeStrategy";
export type { MockExperimentalMethodParams } from "./MockExperimentalMethodParams";
export type { MockExperimentalMethodResponse } from "./MockExperimentalMethodResponse";
export type { Model } from "./Model";
export type { ModelAvailabilityNux } from "./ModelAvailabilityNux";
export type { ModelListParams } from "./ModelListParams";
@@ -187,9 +191,11 @@ export type { ModelUpgradeInfo } from "./ModelUpgradeInfo";
export type { NetworkAccess } from "./NetworkAccess";
export type { NetworkApprovalContext } from "./NetworkApprovalContext";
export type { NetworkApprovalProtocol } from "./NetworkApprovalProtocol";
export type { NetworkDomainPermission } from "./NetworkDomainPermission";
export type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment";
export type { NetworkPolicyRuleAction } from "./NetworkPolicyRuleAction";
export type { NetworkRequirements } from "./NetworkRequirements";
export type { NetworkUnixSocketPermission } from "./NetworkUnixSocketPermission";
export type { OverriddenMetadata } from "./OverriddenMetadata";
export type { PatchApplyStatus } from "./PatchApplyStatus";
export type { PatchChangeKind } from "./PatchChangeKind";
@@ -255,11 +261,17 @@ export type { ThreadActiveFlag } from "./ThreadActiveFlag";
export type { ThreadArchiveParams } from "./ThreadArchiveParams";
export type { ThreadArchiveResponse } from "./ThreadArchiveResponse";
export type { ThreadArchivedNotification } from "./ThreadArchivedNotification";
export type { ThreadBackgroundTerminalsCleanParams } from "./ThreadBackgroundTerminalsCleanParams";
export type { ThreadBackgroundTerminalsCleanResponse } from "./ThreadBackgroundTerminalsCleanResponse";
export type { ThreadClosedNotification } from "./ThreadClosedNotification";
export type { ThreadCompactStartParams } from "./ThreadCompactStartParams";
export type { ThreadCompactStartResponse } from "./ThreadCompactStartResponse";
export type { ThreadDecrementElicitationParams } from "./ThreadDecrementElicitationParams";
export type { ThreadDecrementElicitationResponse } from "./ThreadDecrementElicitationResponse";
export type { ThreadForkParams } from "./ThreadForkParams";
export type { ThreadForkResponse } from "./ThreadForkResponse";
export type { ThreadIncrementElicitationParams } from "./ThreadIncrementElicitationParams";
export type { ThreadIncrementElicitationResponse } from "./ThreadIncrementElicitationResponse";
export type { ThreadItem } from "./ThreadItem";
export type { ThreadListParams } from "./ThreadListParams";
export type { ThreadListResponse } from "./ThreadListResponse";
@@ -271,12 +283,20 @@ export type { ThreadMetadataUpdateResponse } from "./ThreadMetadataUpdateRespons
export type { ThreadNameUpdatedNotification } from "./ThreadNameUpdatedNotification";
export type { ThreadReadParams } from "./ThreadReadParams";
export type { ThreadReadResponse } from "./ThreadReadResponse";
export type { ThreadRealtimeAppendAudioParams } from "./ThreadRealtimeAppendAudioParams";
export type { ThreadRealtimeAppendAudioResponse } from "./ThreadRealtimeAppendAudioResponse";
export type { ThreadRealtimeAppendTextParams } from "./ThreadRealtimeAppendTextParams";
export type { ThreadRealtimeAppendTextResponse } from "./ThreadRealtimeAppendTextResponse";
export type { ThreadRealtimeAudioChunk } from "./ThreadRealtimeAudioChunk";
export type { ThreadRealtimeClosedNotification } from "./ThreadRealtimeClosedNotification";
export type { ThreadRealtimeErrorNotification } from "./ThreadRealtimeErrorNotification";
export type { ThreadRealtimeItemAddedNotification } from "./ThreadRealtimeItemAddedNotification";
export type { ThreadRealtimeOutputAudioDeltaNotification } from "./ThreadRealtimeOutputAudioDeltaNotification";
export type { ThreadRealtimeStartParams } from "./ThreadRealtimeStartParams";
export type { ThreadRealtimeStartResponse } from "./ThreadRealtimeStartResponse";
export type { ThreadRealtimeStartedNotification } from "./ThreadRealtimeStartedNotification";
export type { ThreadRealtimeStopParams } from "./ThreadRealtimeStopParams";
export type { ThreadRealtimeStopResponse } from "./ThreadRealtimeStopResponse";
export type { ThreadResumeParams } from "./ThreadResumeParams";
export type { ThreadResumeResponse } from "./ThreadResumeResponse";
export type { ThreadRollbackParams } from "./ThreadRollbackParams";

View File

@@ -839,12 +839,28 @@ pub struct NetworkRequirements {
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
pub allowed_domains: Option<Vec<String>>,
pub denied_domains: Option<Vec<String>>,
pub allow_unix_sockets: Option<Vec<String>>,
pub domains: Option<BTreeMap<String, NetworkDomainPermission>>,
pub unix_sockets: Option<BTreeMap<String, NetworkUnixSocketPermission>>,
pub allow_local_binding: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "lowercase")]
#[ts(export_to = "v2/")]
pub enum NetworkDomainPermission {
Allow,
Deny,
None,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "lowercase")]
#[ts(export_to = "v2/")]
pub enum NetworkUnixSocketPermission {
Allow,
None,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]

View File

@@ -10,7 +10,9 @@ use codex_app_server_protocol::ConfigValueWriteParams;
use codex_app_server_protocol::ConfigWriteErrorCode;
use codex_app_server_protocol::ConfigWriteResponse;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_app_server_protocol::NetworkDomainPermission;
use codex_app_server_protocol::NetworkRequirements;
use codex_app_server_protocol::NetworkUnixSocketPermission;
use codex_app_server_protocol::SandboxMode;
use codex_core::AnalyticsEventsClient;
use codex_core::ThreadManager;
@@ -231,13 +233,57 @@ fn map_network_requirements_to_api(
allow_upstream_proxy: network.allow_upstream_proxy,
dangerously_allow_non_loopback_proxy: network.dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets: network.dangerously_allow_all_unix_sockets,
allowed_domains: network.allowed_domains,
denied_domains: network.denied_domains,
allow_unix_sockets: network.allow_unix_sockets,
domains: network.domains.map(|domains| {
domains
.entries
.into_iter()
.map(|(pattern, permission)| {
(pattern, map_network_domain_permission_to_api(permission))
})
.collect()
}),
unix_sockets: network.unix_sockets.map(|unix_sockets| {
unix_sockets
.entries
.into_iter()
.map(|(path, permission)| {
(path, map_network_unix_socket_permission_to_api(permission))
})
.collect()
}),
allow_local_binding: network.allow_local_binding,
}
}
fn map_network_domain_permission_to_api(
permission: codex_core::config_loader::NetworkDomainPermissionToml,
) -> NetworkDomainPermission {
match permission {
codex_core::config_loader::NetworkDomainPermissionToml::Allow => {
NetworkDomainPermission::Allow
}
codex_core::config_loader::NetworkDomainPermissionToml::Deny => {
NetworkDomainPermission::Deny
}
codex_core::config_loader::NetworkDomainPermissionToml::None => {
NetworkDomainPermission::None
}
}
}
fn map_network_unix_socket_permission_to_api(
permission: codex_core::config_loader::NetworkUnixSocketPermissionToml,
) -> NetworkUnixSocketPermission {
match permission {
codex_core::config_loader::NetworkUnixSocketPermissionToml::Allow => {
NetworkUnixSocketPermission::Allow
}
codex_core::config_loader::NetworkUnixSocketPermissionToml::None => {
NetworkUnixSocketPermission::None
}
}
}
fn map_error(err: ConfigServiceError) -> JSONRPCErrorError {
if let Some(code) = err.write_error_code() {
return config_write_error(code, err.to_string());
@@ -264,7 +310,11 @@ fn config_write_error(code: ConfigWriteErrorCode, message: impl Into<String>) ->
mod tests {
use super::*;
use codex_core::AnalyticsEventsClient;
use codex_core::config_loader::NetworkDomainPermissionToml as CoreNetworkDomainPermissionToml;
use codex_core::config_loader::NetworkDomainPermissionsToml as CoreNetworkDomainPermissionsToml;
use codex_core::config_loader::NetworkRequirementsToml as CoreNetworkRequirementsToml;
use codex_core::config_loader::NetworkUnixSocketPermissionToml as CoreNetworkUnixSocketPermissionToml;
use codex_core::config_loader::NetworkUnixSocketPermissionsToml as CoreNetworkUnixSocketPermissionsToml;
use codex_protocol::protocol::AskForApproval as CoreAskForApproval;
use pretty_assertions::assert_eq;
use serde_json::json;
@@ -316,10 +366,25 @@ mod tests {
allow_upstream_proxy: Some(false),
dangerously_allow_non_loopback_proxy: Some(false),
dangerously_allow_all_unix_sockets: Some(true),
allowed_domains: Some(vec!["api.openai.com".to_string()]),
domains: Some(CoreNetworkDomainPermissionsToml {
entries: std::collections::BTreeMap::from([
(
"api.openai.com".to_string(),
CoreNetworkDomainPermissionToml::Allow,
),
(
"example.com".to_string(),
CoreNetworkDomainPermissionToml::Deny,
),
]),
}),
managed_allowed_domains_only: Some(false),
denied_domains: Some(vec!["example.com".to_string()]),
allow_unix_sockets: Some(vec!["/tmp/proxy.sock".to_string()]),
unix_sockets: Some(CoreNetworkUnixSocketPermissionsToml {
entries: std::collections::BTreeMap::from([(
"/tmp/proxy.sock".to_string(),
CoreNetworkUnixSocketPermissionToml::Allow,
)]),
}),
allow_local_binding: Some(true),
}),
};
@@ -361,9 +426,14 @@ mod tests {
allow_upstream_proxy: Some(false),
dangerously_allow_non_loopback_proxy: Some(false),
dangerously_allow_all_unix_sockets: Some(true),
allowed_domains: Some(vec!["api.openai.com".to_string()]),
denied_domains: Some(vec!["example.com".to_string()]),
allow_unix_sockets: Some(vec!["/tmp/proxy.sock".to_string()]),
domains: Some(std::collections::BTreeMap::from([
("api.openai.com".to_string(), NetworkDomainPermission::Allow,),
("example.com".to_string(), NetworkDomainPermission::Deny),
])),
unix_sockets: Some(std::collections::BTreeMap::from([(
"/tmp/proxy.sock".to_string(),
NetworkUnixSocketPermission::Allow,
)])),
allow_local_binding: Some(true),
}),
);

View File

@@ -132,7 +132,46 @@ pub struct McpServerRequirement {
pub identity: McpServerIdentity,
}
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
pub struct NetworkDomainPermissionsToml {
#[serde(flatten)]
pub entries: BTreeMap<String, NetworkDomainPermissionToml>,
}
impl NetworkDomainPermissionsToml {
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
pub enum NetworkDomainPermissionToml {
Allow,
Deny,
None,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq)]
pub struct NetworkUnixSocketPermissionsToml {
#[serde(flatten)]
pub entries: BTreeMap<String, NetworkUnixSocketPermissionToml>,
}
impl NetworkUnixSocketPermissionsToml {
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
pub enum NetworkUnixSocketPermissionToml {
Allow,
None,
}
#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq)]
pub struct NetworkRequirementsToml {
pub enabled: Option<bool>,
pub http_port: Option<u16>,
@@ -140,17 +179,16 @@ pub struct NetworkRequirementsToml {
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
pub allowed_domains: Option<Vec<String>>,
pub domains: Option<NetworkDomainPermissionsToml>,
/// When true, only managed `allowed_domains` are respected while managed
/// network enforcement is active. User allowlist entries are ignored.
pub managed_allowed_domains_only: Option<bool>,
pub denied_domains: Option<Vec<String>>,
pub allow_unix_sockets: Option<Vec<String>>,
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
pub allow_local_binding: Option<bool>,
}
/// Normalized network constraints derived from requirements TOML.
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
pub struct NetworkConstraints {
pub enabled: Option<bool>,
pub http_port: Option<u16>,
@@ -158,15 +196,78 @@ pub struct NetworkConstraints {
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
pub allowed_domains: Option<Vec<String>>,
pub domains: Option<NetworkDomainPermissionsToml>,
/// When true, only managed `allowed_domains` are respected while managed
/// network enforcement is active. User allowlist entries are ignored.
pub managed_allowed_domains_only: Option<bool>,
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
pub allow_local_binding: Option<bool>,
}
#[derive(Deserialize)]
struct RawNetworkRequirementsToml {
pub enabled: Option<bool>,
pub http_port: Option<u16>,
pub socks_port: Option<u16>,
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
pub domains: Option<NetworkDomainPermissionsToml>,
pub managed_allowed_domains_only: Option<bool>,
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
pub allowed_domains: Option<Vec<String>>,
pub denied_domains: Option<Vec<String>>,
pub allow_unix_sockets: Option<Vec<String>>,
pub allow_local_binding: Option<bool>,
}
impl<'de> Deserialize<'de> for NetworkRequirementsToml {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw = RawNetworkRequirementsToml::deserialize(deserializer)?;
let RawNetworkRequirementsToml {
enabled,
http_port,
socks_port,
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
domains,
managed_allowed_domains_only,
unix_sockets,
allowed_domains,
denied_domains,
allow_unix_sockets,
allow_local_binding,
} = raw;
Ok(Self {
enabled,
http_port,
socks_port,
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
domains: merge_domain_permissions(allowed_domains, denied_domains, domains),
managed_allowed_domains_only,
unix_sockets: merge_unix_socket_permissions(allow_unix_sockets, unix_sockets),
allow_local_binding,
})
}
}
impl<'de> Deserialize<'de> for NetworkConstraints {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let requirements = NetworkRequirementsToml::deserialize(deserializer)?;
Ok(requirements.into())
}
}
impl From<NetworkRequirementsToml> for NetworkConstraints {
fn from(value: NetworkRequirementsToml) -> Self {
let NetworkRequirementsToml {
@@ -176,10 +277,9 @@ impl From<NetworkRequirementsToml> for NetworkConstraints {
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
allowed_domains,
domains,
managed_allowed_domains_only,
denied_domains,
allow_unix_sockets,
unix_sockets,
allow_local_binding,
} = value;
Self {
@@ -189,15 +289,104 @@ impl From<NetworkRequirementsToml> for NetworkConstraints {
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
allowed_domains,
domains,
managed_allowed_domains_only,
denied_domains,
allow_unix_sockets,
unix_sockets,
allow_local_binding,
}
}
}
impl NetworkConstraints {
pub fn allowed_domains(&self) -> Vec<String> {
self.domains
.as_ref()
.map(|domains| {
domains
.entries
.iter()
.filter(|(_, permission)| {
matches!(permission, NetworkDomainPermissionToml::Allow)
})
.map(|(pattern, _)| pattern.clone())
.collect()
})
.unwrap_or_default()
}
pub fn denied_domains(&self) -> Vec<String> {
self.domains
.as_ref()
.map(|domains| {
domains
.entries
.iter()
.filter(|(_, permission)| {
matches!(permission, NetworkDomainPermissionToml::Deny)
})
.map(|(pattern, _)| pattern.clone())
.collect()
})
.unwrap_or_default()
}
pub fn allow_unix_sockets(&self) -> Vec<String> {
self.unix_sockets
.as_ref()
.map(|unix_sockets| {
unix_sockets
.entries
.iter()
.filter(|(_, permission)| {
matches!(permission, NetworkUnixSocketPermissionToml::Allow)
})
.map(|(path, _)| path.clone())
.collect()
})
.unwrap_or_default()
}
}
fn merge_domain_permissions(
allowed_domains: Option<Vec<String>>,
denied_domains: Option<Vec<String>>,
domains: Option<NetworkDomainPermissionsToml>,
) -> Option<NetworkDomainPermissionsToml> {
let mut entries = BTreeMap::new();
for pattern in allowed_domains.unwrap_or_default() {
entries.insert(pattern, NetworkDomainPermissionToml::Allow);
}
for pattern in denied_domains.unwrap_or_default() {
entries.insert(pattern, NetworkDomainPermissionToml::Deny);
}
if let Some(domains) = domains {
for (pattern, permission) in domains.entries {
entries.insert(pattern, permission);
}
}
(!entries.is_empty()).then_some(NetworkDomainPermissionsToml { entries })
}
fn merge_unix_socket_permissions(
allow_unix_sockets: Option<Vec<String>>,
unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
) -> Option<NetworkUnixSocketPermissionsToml> {
let mut entries = BTreeMap::new();
for path in allow_unix_sockets.unwrap_or_default() {
entries.insert(path, NetworkUnixSocketPermissionToml::Allow);
}
if let Some(unix_sockets) = unix_sockets {
for (path, permission) in unix_sockets.entries {
entries.insert(path, permission);
}
}
(!entries.is_empty()).then_some(NetworkUnixSocketPermissionsToml { entries })
}
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(rename_all = "lowercase")]
pub enum WebSearchModeRequirement {
@@ -1475,11 +1664,16 @@ guardian_developer_instructions = """
enabled = true
allow_upstream_proxy = false
dangerously_allow_all_unix_sockets = true
allowed_domains = ["api.example.com", "*.openai.com"]
managed_allowed_domains_only = true
denied_domains = ["blocked.example.com"]
allow_unix_sockets = ["/tmp/example.sock"]
allow_local_binding = false
[experimental_network.domains]
"api.example.com" = "allow"
"*.openai.com" = "allow"
"blocked.example.com" = "deny"
[experimental_network.unix_sockets]
"/tmp/example.sock" = "allow"
"#;
let source = RequirementSource::CloudRequirements;
@@ -1499,23 +1693,36 @@ guardian_developer_instructions = """
Some(true)
);
assert_eq!(
sourced_network.value.allowed_domains.as_ref(),
Some(&vec![
"api.example.com".to_string(),
"*.openai.com".to_string()
])
sourced_network.value.domains.as_ref(),
Some(&NetworkDomainPermissionsToml {
entries: BTreeMap::from([
(
"*.openai.com".to_string(),
NetworkDomainPermissionToml::Allow,
),
(
"api.example.com".to_string(),
NetworkDomainPermissionToml::Allow,
),
(
"blocked.example.com".to_string(),
NetworkDomainPermissionToml::Deny,
),
]),
})
);
assert_eq!(
sourced_network.value.managed_allowed_domains_only,
Some(true)
);
assert_eq!(
sourced_network.value.denied_domains.as_ref(),
Some(&vec!["blocked.example.com".to_string()])
);
assert_eq!(
sourced_network.value.allow_unix_sockets.as_ref(),
Some(&vec!["/tmp/example.sock".to_string()])
sourced_network.value.unix_sockets.as_ref(),
Some(&NetworkUnixSocketPermissionsToml {
entries: BTreeMap::from([(
"/tmp/example.sock".to_string(),
NetworkUnixSocketPermissionToml::Allow,
)]),
})
);
assert_eq!(sourced_network.value.allow_local_binding, Some(false));

View File

@@ -23,7 +23,11 @@ pub use config_requirements::FeatureRequirementsToml;
pub use config_requirements::McpServerIdentity;
pub use config_requirements::McpServerRequirement;
pub use config_requirements::NetworkConstraints;
pub use config_requirements::NetworkDomainPermissionToml;
pub use config_requirements::NetworkDomainPermissionsToml;
pub use config_requirements::NetworkRequirementsToml;
pub use config_requirements::NetworkUnixSocketPermissionToml;
pub use config_requirements::NetworkUnixSocketPermissionsToml;
pub use config_requirements::RequirementSource;
pub use config_requirements::ResidencyRequirement;
pub use config_requirements::SandboxModeRequirement;

View File

@@ -898,6 +898,17 @@
],
"type": "object"
},
"NetworkDomainPermissionToml": {
"enum": [
"allow",
"deny",
"none"
],
"type": "string"
},
"NetworkDomainPermissionsToml": {
"type": "object"
},
"NetworkModeSchema": {
"enum": [
"limited",
@@ -911,32 +922,17 @@
"allow_local_binding": {
"type": "boolean"
},
"allow_unix_sockets": {
"items": {
"type": "string"
},
"type": "array"
},
"allow_upstream_proxy": {
"type": "boolean"
},
"allowed_domains": {
"items": {
"type": "string"
},
"type": "array"
},
"dangerously_allow_all_unix_sockets": {
"type": "boolean"
},
"dangerously_allow_non_loopback_proxy": {
"type": "boolean"
},
"denied_domains": {
"items": {
"type": "string"
},
"type": "array"
"domains": {
"$ref": "#/definitions/NetworkDomainPermissionsToml"
},
"enable_socks5": {
"type": "boolean"
@@ -955,10 +951,23 @@
},
"socks_url": {
"type": "string"
},
"unix_sockets": {
"$ref": "#/definitions/NetworkUnixSocketPermissionsToml"
}
},
"type": "object"
},
"NetworkUnixSocketPermissionToml": {
"enum": [
"allow",
"none"
],
"type": "string"
},
"NetworkUnixSocketPermissionsToml": {
"type": "object"
},
"Notice": {
"description": "Settings for notices we display to users via the tui and app-server clients (primarily the Codex IDE extension). NOTE: these are different from notifications - notices are warnings, NUX screens, acknowledgements, etc.",
"properties": {

View File

@@ -982,8 +982,8 @@ impl TurnContext {
.network
.as_ref()?;
Some(TurnContextNetworkItem {
allowed_domains: network.allowed_domains.clone().unwrap_or_default(),
denied_domains: network.denied_domains.clone().unwrap_or_default(),
allowed_domains: network.allowed_domains(),
denied_domains: network.denied_domains(),
})
}
}

View File

@@ -5,6 +5,8 @@ use crate::config::test_config;
use crate::config_loader::ConfigLayerStack;
use crate::config_loader::ConfigLayerStackOrdering;
use crate::config_loader::NetworkConstraints;
use crate::config_loader::NetworkDomainPermissionToml;
use crate::config_loader::NetworkDomainPermissionsToml;
use crate::config_loader::RequirementSource;
use crate::config_loader::Sourced;
use crate::exec::ExecToolCallOutput;
@@ -467,7 +469,12 @@ async fn start_managed_network_proxy_ignores_invalid_execpolicy_network_rules()
let spec = crate::config::NetworkProxySpec::from_config_and_constraints(
NetworkProxyConfig::default(),
Some(NetworkConstraints {
allowed_domains: Some(vec!["managed.example.com".to_string()]),
domains: Some(NetworkDomainPermissionsToml {
entries: std::collections::BTreeMap::from([(
"managed.example.com".to_string(),
NetworkDomainPermissionToml::Allow,
)]),
}),
managed_allowed_domains_only: Some(true),
..Default::default()
}),
@@ -3476,8 +3483,18 @@ async fn build_settings_update_items_emits_environment_item_for_network_changes(
let mut requirements = config.config_layer_stack.requirements().clone();
requirements.network = Some(Sourced::new(
NetworkConstraints {
allowed_domains: Some(vec!["api.example.com".to_string()]),
denied_domains: Some(vec!["blocked.example.com".to_string()]),
domains: Some(NetworkDomainPermissionsToml {
entries: std::collections::BTreeMap::from([
(
"api.example.com".to_string(),
NetworkDomainPermissionToml::Allow,
),
(
"blocked.example.com".to_string(),
NetworkDomainPermissionToml::Deny,
),
]),
}),
..Default::default()
},
RequirementSource::CloudRequirements,

View File

@@ -317,9 +317,13 @@ allowed_domains = ["openai.com"]
dangerously_allow_non_loopback_proxy: None,
dangerously_allow_all_unix_sockets: None,
mode: None,
allowed_domains: Some(vec!["openai.com".to_string()]),
denied_domains: None,
allow_unix_sockets: None,
domains: Some(NetworkDomainPermissionsToml {
entries: BTreeMap::from([(
"openai.com".to_string(),
NetworkDomainPermissionToml::Allow,
)]),
}),
unix_sockets: None,
allow_local_binding: None,
}),
},
@@ -395,7 +399,12 @@ fn permissions_profiles_network_disabled_by_default_does_not_start_proxy() -> st
)]),
}),
network: Some(NetworkToml {
allowed_domains: Some(vec!["openai.com".to_string()]),
domains: Some(NetworkDomainPermissionsToml {
entries: BTreeMap::from([(
"openai.com".to_string(),
NetworkDomainPermissionToml::Allow,
)]),
}),
..Default::default()
}),
},

View File

@@ -123,7 +123,11 @@ pub use network_proxy_spec::NetworkProxySpec;
pub use network_proxy_spec::StartedNetworkProxy;
pub use permissions::FilesystemPermissionToml;
pub use permissions::FilesystemPermissionsToml;
pub use permissions::NetworkDomainPermissionToml;
pub use permissions::NetworkDomainPermissionsToml;
pub use permissions::NetworkToml;
pub use permissions::NetworkUnixSocketPermissionToml;
pub use permissions::NetworkUnixSocketPermissionsToml;
pub use permissions::PermissionProfileToml;
pub use permissions::PermissionsToml;
pub(crate) use permissions::resolve_permission_profile;

View File

@@ -226,9 +226,11 @@ impl NetworkProxySpec {
Some(dangerously_allow_all_unix_sockets);
}
let managed_allowed_domains = if hard_deny_allowlist_misses {
Some(requirements.allowed_domains.clone().unwrap_or_default())
Some(requirements.allowed_domains())
} else if requirements.domains.is_some() {
Some(requirements.allowed_domains())
} else {
requirements.allowed_domains.clone()
None
};
if let Some(allowed_domains) = managed_allowed_domains {
// Managed requirements seed the baseline allowlist. User additions
@@ -242,7 +244,8 @@ impl NetworkProxySpec {
constraints.allowed_domains = Some(allowed_domains);
constraints.allowlist_expansion_enabled = Some(allowlist_expansion_enabled);
}
if let Some(denied_domains) = requirements.denied_domains.clone() {
if requirements.domains.is_some() {
let denied_domains = requirements.denied_domains();
config.network.denied_domains = if denylist_expansion_enabled {
Self::merge_domain_lists(denied_domains.clone(), &config.network.denied_domains)
} else {
@@ -251,7 +254,8 @@ impl NetworkProxySpec {
constraints.denied_domains = Some(denied_domains);
constraints.denylist_expansion_enabled = Some(denylist_expansion_enabled);
}
if let Some(allow_unix_sockets) = requirements.allow_unix_sockets.clone() {
if requirements.unix_sockets.is_some() {
let allow_unix_sockets = requirements.allow_unix_sockets();
config.network.allow_unix_sockets = allow_unix_sockets.clone();
constraints.allow_unix_sockets = Some(allow_unix_sockets);
}

View File

@@ -1,6 +1,19 @@
use super::*;
use crate::config_loader::NetworkDomainPermissionToml;
use crate::config_loader::NetworkDomainPermissionsToml;
use pretty_assertions::assert_eq;
fn domain_permissions(
entries: impl IntoIterator<Item = (&'static str, NetworkDomainPermissionToml)>,
) -> NetworkDomainPermissionsToml {
NetworkDomainPermissionsToml {
entries: entries
.into_iter()
.map(|(pattern, permission)| (pattern.to_string(), permission))
.collect(),
}
}
#[test]
fn build_state_with_audit_metadata_threads_metadata_to_state() {
let spec = NetworkProxySpec {
@@ -26,7 +39,10 @@ fn requirements_allowed_domains_are_a_baseline_for_user_allowlist() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["*.example.com".to_string()]),
domains: Some(domain_permissions([(
"*.example.com",
NetworkDomainPermissionToml::Allow,
)])),
..Default::default()
};
@@ -54,8 +70,10 @@ fn danger_full_access_keeps_managed_allowlist_and_denylist_fixed() {
config.network.allowed_domains = vec!["evil.com".to_string()];
config.network.denied_domains = vec!["more-blocked.example.com".to_string()];
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["*.example.com".to_string()]),
denied_domains: Some(vec!["blocked.example.com".to_string()]),
domains: Some(domain_permissions([
("*.example.com", NetworkDomainPermissionToml::Allow),
("blocked.example.com", NetworkDomainPermissionToml::Deny),
])),
..Default::default()
};
@@ -83,7 +101,10 @@ fn managed_allowed_domains_only_disables_default_mode_allowlist_expansion() {
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["*.example.com".to_string()]),
domains: Some(domain_permissions([(
"*.example.com",
NetworkDomainPermissionToml::Allow,
)])),
managed_allowed_domains_only: Some(true),
..Default::default()
};
@@ -107,7 +128,10 @@ fn managed_allowed_domains_only_ignores_user_allowlist_and_hard_denies_misses()
let mut config = NetworkProxyConfig::default();
config.network.allowed_domains = vec!["api.example.com".to_string()];
let requirements = NetworkConstraints {
allowed_domains: Some(vec!["managed.example.com".to_string()]),
domains: Some(domain_permissions([(
"managed.example.com",
NetworkDomainPermissionToml::Allow,
)])),
managed_allowed_domains_only: Some(true),
..Default::default()
};
@@ -180,7 +204,10 @@ fn requirements_denied_domains_are_a_baseline_for_default_mode() {
let mut config = NetworkProxyConfig::default();
config.network.denied_domains = vec!["blocked.example.com".to_string()];
let requirements = NetworkConstraints {
denied_domains: Some(vec!["managed-blocked.example.com".to_string()]),
domains: Some(domain_permissions([(
"managed-blocked.example.com",
NetworkDomainPermissionToml::Deny,
)])),
..Default::default()
};

View File

@@ -57,6 +57,49 @@ pub enum FilesystemPermissionToml {
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
pub struct NetworkDomainPermissionsToml {
#[serde(flatten)]
pub entries: BTreeMap<String, NetworkDomainPermissionToml>,
}
impl NetworkDomainPermissionsToml {
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[derive(
Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, JsonSchema,
)]
#[serde(rename_all = "lowercase")]
pub enum NetworkDomainPermissionToml {
Allow,
Deny,
None,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
pub struct NetworkUnixSocketPermissionsToml {
#[serde(flatten)]
pub entries: BTreeMap<String, NetworkUnixSocketPermissionToml>,
}
impl NetworkUnixSocketPermissionsToml {
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[derive(
Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, JsonSchema,
)]
#[serde(rename_all = "lowercase")]
pub enum NetworkUnixSocketPermissionToml {
Allow,
None,
}
#[derive(Serialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)]
#[schemars(deny_unknown_fields)]
pub struct NetworkToml {
pub enabled: Option<bool>,
@@ -69,9 +112,8 @@ pub struct NetworkToml {
pub dangerously_allow_all_unix_sockets: Option<bool>,
#[schemars(with = "Option<NetworkModeSchema>")]
pub mode: Option<NetworkMode>,
pub allowed_domains: Option<Vec<String>>,
pub denied_domains: Option<Vec<String>>,
pub allow_unix_sockets: Option<Vec<String>>,
pub domains: Option<NetworkDomainPermissionsToml>,
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
pub allow_local_binding: Option<bool>,
}
@@ -82,6 +124,66 @@ enum NetworkModeSchema {
Full,
}
#[derive(Deserialize)]
struct RawNetworkToml {
pub enabled: Option<bool>,
pub proxy_url: Option<String>,
pub enable_socks5: Option<bool>,
pub socks_url: Option<String>,
pub enable_socks5_udp: Option<bool>,
pub allow_upstream_proxy: Option<bool>,
pub dangerously_allow_non_loopback_proxy: Option<bool>,
pub dangerously_allow_all_unix_sockets: Option<bool>,
pub mode: Option<NetworkMode>,
pub domains: Option<NetworkDomainPermissionsToml>,
pub unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
pub allowed_domains: Option<Vec<String>>,
pub denied_domains: Option<Vec<String>>,
pub allow_unix_sockets: Option<Vec<String>>,
pub allow_local_binding: Option<bool>,
}
impl<'de> Deserialize<'de> for NetworkToml {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw = RawNetworkToml::deserialize(deserializer)?;
let RawNetworkToml {
enabled,
proxy_url,
enable_socks5,
socks_url,
enable_socks5_udp,
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
mode,
domains,
unix_sockets,
allowed_domains,
denied_domains,
allow_unix_sockets,
allow_local_binding,
} = raw;
Ok(Self {
enabled,
proxy_url,
enable_socks5,
socks_url,
enable_socks5_udp,
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
mode,
domains: merge_domain_permissions(allowed_domains, denied_domains, domains),
unix_sockets: merge_unix_socket_permissions(allow_unix_sockets, unix_sockets),
allow_local_binding,
})
}
}
impl NetworkToml {
pub(crate) fn apply_to_network_proxy_config(&self, config: &mut NetworkProxyConfig) {
if let Some(enabled) = self.enabled {
@@ -114,14 +216,12 @@ impl NetworkToml {
if let Some(mode) = self.mode {
config.network.mode = mode;
}
if let Some(allowed_domains) = self.allowed_domains.as_ref() {
config.network.allowed_domains = allowed_domains.clone();
if self.domains.is_some() {
config.network.allowed_domains = self.allowed_domains();
config.network.denied_domains = self.denied_domains();
}
if let Some(denied_domains) = self.denied_domains.as_ref() {
config.network.denied_domains = denied_domains.clone();
}
if let Some(allow_unix_sockets) = self.allow_unix_sockets.as_ref() {
config.network.allow_unix_sockets = allow_unix_sockets.clone();
if self.unix_sockets.is_some() {
config.network.allow_unix_sockets = self.allow_unix_sockets();
}
if let Some(allow_local_binding) = self.allow_local_binding {
config.network.allow_local_binding = allow_local_binding;
@@ -133,6 +233,94 @@ impl NetworkToml {
self.apply_to_network_proxy_config(&mut config);
config
}
pub(crate) fn allowed_domains(&self) -> Vec<String> {
self.domains
.as_ref()
.map(|domains| {
domains
.entries
.iter()
.filter(|(_, permission)| {
matches!(permission, NetworkDomainPermissionToml::Allow)
})
.map(|(pattern, _)| pattern.clone())
.collect()
})
.unwrap_or_default()
}
pub(crate) fn denied_domains(&self) -> Vec<String> {
self.domains
.as_ref()
.map(|domains| {
domains
.entries
.iter()
.filter(|(_, permission)| {
matches!(permission, NetworkDomainPermissionToml::Deny)
})
.map(|(pattern, _)| pattern.clone())
.collect()
})
.unwrap_or_default()
}
pub(crate) fn allow_unix_sockets(&self) -> Vec<String> {
self.unix_sockets
.as_ref()
.map(|unix_sockets| {
unix_sockets
.entries
.iter()
.filter(|(_, permission)| {
matches!(permission, NetworkUnixSocketPermissionToml::Allow)
})
.map(|(path, _)| path.clone())
.collect()
})
.unwrap_or_default()
}
}
fn merge_domain_permissions(
allowed_domains: Option<Vec<String>>,
denied_domains: Option<Vec<String>>,
domains: Option<NetworkDomainPermissionsToml>,
) -> Option<NetworkDomainPermissionsToml> {
let mut entries = BTreeMap::new();
for pattern in allowed_domains.unwrap_or_default() {
entries.insert(pattern, NetworkDomainPermissionToml::Allow);
}
for pattern in denied_domains.unwrap_or_default() {
entries.insert(pattern, NetworkDomainPermissionToml::Deny);
}
if let Some(domains) = domains {
for (pattern, permission) in domains.entries {
entries.insert(pattern, permission);
}
}
(!entries.is_empty()).then_some(NetworkDomainPermissionsToml { entries })
}
fn merge_unix_socket_permissions(
allow_unix_sockets: Option<Vec<String>>,
unix_sockets: Option<NetworkUnixSocketPermissionsToml>,
) -> Option<NetworkUnixSocketPermissionsToml> {
let mut entries = BTreeMap::new();
for path in allow_unix_sockets.unwrap_or_default() {
entries.insert(path, NetworkUnixSocketPermissionToml::Allow);
}
if let Some(unix_sockets) = unix_sockets {
for (path, permission) in unix_sockets.entries {
entries.insert(path, permission);
}
}
(!entries.is_empty()).then_some(NetworkUnixSocketPermissionsToml { entries })
}
pub(crate) fn network_proxy_config_from_profile_network(

View File

@@ -42,7 +42,11 @@ pub use codex_config::LoaderOverrides;
pub use codex_config::McpServerIdentity;
pub use codex_config::McpServerRequirement;
pub use codex_config::NetworkConstraints;
pub use codex_config::NetworkDomainPermissionToml;
pub use codex_config::NetworkDomainPermissionsToml;
pub use codex_config::NetworkRequirementsToml;
pub use codex_config::NetworkUnixSocketPermissionToml;
pub use codex_config::NetworkUnixSocketPermissionsToml;
pub use codex_config::RequirementSource;
pub use codex_config::ResidencyRequirement;
pub use codex_config::SandboxModeRequirement;

View File

@@ -130,8 +130,8 @@ impl EnvironmentContext {
.as_ref()?;
Some(NetworkContext {
allowed_domains: network.allowed_domains.clone().unwrap_or_default(),
denied_domains: network.denied_domains.clone().unwrap_or_default(),
allowed_domains: network.allowed_domains(),
denied_domains: network.denied_domains(),
})
}

View File

@@ -11,6 +11,8 @@ use crate::config::test_config;
use crate::config_loader::ConfigLayerStack;
use crate::config_loader::FeatureRequirementsToml;
use crate::config_loader::NetworkConstraints;
use crate::config_loader::NetworkDomainPermissionToml;
use crate::config_loader::NetworkDomainPermissionsToml;
use crate::config_loader::RequirementSource;
use crate::config_loader::Sourced;
use crate::protocol::SandboxPolicy;
@@ -865,7 +867,12 @@ fn guardian_review_session_config_preserves_parent_network_proxy() {
NetworkProxyConfig::default(),
Some(NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["github.com".to_string()]),
domains: Some(NetworkDomainPermissionsToml {
entries: std::collections::BTreeMap::from([(
"github.com".to_string(),
NetworkDomainPermissionToml::Allow,
)]),
}),
..Default::default()
}),
parent_config.permissions.sandbox_policy.get(),

View File

@@ -150,13 +150,14 @@ fn apply_network_constraints(network: NetworkToml, constraints: &mut NetworkProx
if let Some(dangerously_allow_all_unix_sockets) = network.dangerously_allow_all_unix_sockets {
constraints.dangerously_allow_all_unix_sockets = Some(dangerously_allow_all_unix_sockets);
}
if let Some(allowed_domains) = network.allowed_domains {
if network.domains.is_some() {
let allowed_domains = network.allowed_domains();
constraints.allowed_domains = Some(allowed_domains);
}
if let Some(denied_domains) = network.denied_domains {
let denied_domains = network.denied_domains();
constraints.denied_domains = Some(denied_domains);
}
if let Some(allow_unix_sockets) = network.allow_unix_sockets {
if network.unix_sockets.is_some() {
let allow_unix_sockets = network.allow_unix_sockets();
constraints.allow_unix_sockets = Some(allow_unix_sockets);
}
if let Some(allow_local_binding) = network.allow_local_binding {

View File

@@ -34,6 +34,41 @@ impl NetworkSandboxPolicy {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display, JsonSchema, TS)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
pub enum NetworkDomainRuleAction {
Allow,
Deny,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
pub struct NetworkDomainRuleEntry {
pub pattern: String,
pub action: NetworkDomainRuleAction,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Display, JsonSchema, TS)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
pub enum NetworkUnixSocketRuleAction {
Allow,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
pub struct NetworkUnixSocketRuleEntry {
pub path: AbsolutePathBuf,
pub action: NetworkUnixSocketRuleAction,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
pub struct NetworkRulePolicy {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub domains: Vec<NetworkDomainRuleEntry>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub unix_sockets: Vec<NetworkUnixSocketRuleEntry>,
}
/// Access mode for a filesystem entry.
///
/// When two equally specific entries target the same path, we compare these by

View File

@@ -333,10 +333,9 @@ fn format_network_constraints(network: &NetworkConstraints) -> String {
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
allowed_domains,
domains,
managed_allowed_domains_only,
denied_domains,
allow_unix_sockets,
unix_sockets,
allow_local_binding,
} = network;
@@ -362,21 +361,21 @@ fn format_network_constraints(network: &NetworkConstraints) -> String {
"dangerously_allow_all_unix_sockets={dangerously_allow_all_unix_sockets}"
));
}
if let Some(allowed_domains) = allowed_domains {
parts.push(format!("allowed_domains=[{}]", allowed_domains.join(", ")));
if let Some(domains) = domains {
parts.push(format!(
"domains={}",
format_network_permission_entries(&domains.entries)
));
}
if let Some(managed_allowed_domains_only) = managed_allowed_domains_only {
parts.push(format!(
"managed_allowed_domains_only={managed_allowed_domains_only}"
));
}
if let Some(denied_domains) = denied_domains {
parts.push(format!("denied_domains=[{}]", denied_domains.join(", ")));
}
if let Some(allow_unix_sockets) = allow_unix_sockets {
if let Some(unix_sockets) = unix_sockets {
parts.push(format!(
"allow_unix_sockets=[{}]",
allow_unix_sockets.join(", ")
"unix_sockets={}",
format_network_permission_entries(&unix_sockets.entries)
));
}
if let Some(allow_local_binding) = allow_local_binding {
@@ -386,6 +385,16 @@ fn format_network_constraints(network: &NetworkConstraints) -> String {
join_or_empty(parts)
}
fn format_network_permission_entries<T: std::fmt::Display>(
entries: &std::collections::BTreeMap<String, T>,
) -> String {
let parts = entries
.iter()
.map(|(key, value)| format!("{key}={value}"))
.collect::<Vec<_>>();
format!("{{{}}}", parts.join(", "))
}
#[cfg(test)]
mod tests {
use super::render_debug_config_lines;
@@ -400,6 +409,8 @@ mod tests {
use codex_core::config_loader::McpServerIdentity;
use codex_core::config_loader::McpServerRequirement;
use codex_core::config_loader::NetworkConstraints;
use codex_core::config_loader::NetworkDomainPermissionToml;
use codex_core::config_loader::NetworkDomainPermissionsToml;
use codex_core::config_loader::RequirementSource;
use codex_core::config_loader::ResidencyRequirement;
use codex_core::config_loader::SandboxModeRequirement;
@@ -516,7 +527,12 @@ mod tests {
network: Some(Sourced::new(
NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["example.com".to_string()]),
domains: Some(NetworkDomainPermissionsToml {
entries: BTreeMap::from([(
"example.com".to_string(),
NetworkDomainPermissionToml::Allow,
)]),
}),
..Default::default()
},
RequirementSource::CloudRequirements,
@@ -580,7 +596,7 @@ mod tests {
assert!(rendered.contains("mcp_servers: docs (source: MDM managed_config.toml (legacy))"));
assert!(rendered.contains("enforce_residency: us (source: cloud requirements)"));
assert!(rendered.contains(
"experimental_network: enabled=true, allowed_domains=[example.com] (source: cloud requirements)"
"experimental_network: enabled=true, domains={example.com=allow} (source: cloud requirements)"
));
assert!(!rendered.contains(" - rules:"));
}

View File

@@ -333,10 +333,9 @@ fn format_network_constraints(network: &NetworkConstraints) -> String {
allow_upstream_proxy,
dangerously_allow_non_loopback_proxy,
dangerously_allow_all_unix_sockets,
allowed_domains,
domains,
managed_allowed_domains_only,
denied_domains,
allow_unix_sockets,
unix_sockets,
allow_local_binding,
} = network;
@@ -362,21 +361,21 @@ fn format_network_constraints(network: &NetworkConstraints) -> String {
"dangerously_allow_all_unix_sockets={dangerously_allow_all_unix_sockets}"
));
}
if let Some(allowed_domains) = allowed_domains {
parts.push(format!("allowed_domains=[{}]", allowed_domains.join(", ")));
if let Some(domains) = domains {
parts.push(format!(
"domains={}",
format_network_permission_entries(&domains.entries)
));
}
if let Some(managed_allowed_domains_only) = managed_allowed_domains_only {
parts.push(format!(
"managed_allowed_domains_only={managed_allowed_domains_only}"
));
}
if let Some(denied_domains) = denied_domains {
parts.push(format!("denied_domains=[{}]", denied_domains.join(", ")));
}
if let Some(allow_unix_sockets) = allow_unix_sockets {
if let Some(unix_sockets) = unix_sockets {
parts.push(format!(
"allow_unix_sockets=[{}]",
allow_unix_sockets.join(", ")
"unix_sockets={}",
format_network_permission_entries(&unix_sockets.entries)
));
}
if let Some(allow_local_binding) = allow_local_binding {
@@ -386,6 +385,16 @@ fn format_network_constraints(network: &NetworkConstraints) -> String {
join_or_empty(parts)
}
fn format_network_permission_entries<T: std::fmt::Display>(
entries: &std::collections::BTreeMap<String, T>,
) -> String {
let parts = entries
.iter()
.map(|(key, value)| format!("{key}={value}"))
.collect::<Vec<_>>();
format!("{{{}}}", parts.join(", "))
}
#[cfg(test)]
mod tests {
use super::render_debug_config_lines;
@@ -400,6 +409,8 @@ mod tests {
use codex_core::config_loader::McpServerIdentity;
use codex_core::config_loader::McpServerRequirement;
use codex_core::config_loader::NetworkConstraints;
use codex_core::config_loader::NetworkDomainPermissionToml;
use codex_core::config_loader::NetworkDomainPermissionsToml;
use codex_core::config_loader::RequirementSource;
use codex_core::config_loader::ResidencyRequirement;
use codex_core::config_loader::SandboxModeRequirement;
@@ -516,7 +527,12 @@ mod tests {
network: Some(Sourced::new(
NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["example.com".to_string()]),
domains: Some(NetworkDomainPermissionsToml {
entries: BTreeMap::from([(
"example.com".to_string(),
NetworkDomainPermissionToml::Allow,
)]),
}),
..Default::default()
},
RequirementSource::CloudRequirements,
@@ -580,7 +596,7 @@ mod tests {
assert!(rendered.contains("mcp_servers: docs (source: MDM managed_config.toml (legacy))"));
assert!(rendered.contains("enforce_residency: us (source: cloud requirements)"));
assert!(rendered.contains(
"experimental_network: enabled=true, allowed_domains=[example.com] (source: cloud requirements)"
"experimental_network: enabled=true, domains={example.com=allow} (source: cloud requirements)"
));
assert!(!rendered.contains(" - rules:"));
}