mirror of
https://github.com/openai/codex.git
synced 2026-05-09 13:52:41 +00:00
Compare commits
1 Commits
abhinav/ho
...
dev/efraze
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3204f0731c |
@@ -3643,6 +3643,65 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueAddParams": {
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueDeleteParams": {
|
||||
"properties": {
|
||||
"queuedTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueListParams": {
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueReorderParams": {
|
||||
"properties": {
|
||||
"queuedTurnIds": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnIds",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadReadParams": {
|
||||
"properties": {
|
||||
"includeTurns": {
|
||||
@@ -4572,6 +4631,102 @@
|
||||
"title": "Thread/name/setRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/add"
|
||||
],
|
||||
"title": "Thread/queue/addRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueAddParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/addRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/list"
|
||||
],
|
||||
"title": "Thread/queue/listRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueListParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/delete"
|
||||
],
|
||||
"title": "Thread/queue/deleteRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueDeleteParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/deleteRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/reorder"
|
||||
],
|
||||
"title": "Thread/queue/reorderRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueReorderParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/reorderRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -6206,4 +6361,4 @@
|
||||
}
|
||||
],
|
||||
"title": "ClientRequest"
|
||||
}
|
||||
}
|
||||
@@ -415,6 +415,65 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ApprovalsReviewer": {
|
||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||
"enum": [
|
||||
"user",
|
||||
"auto_review",
|
||||
"guardian_subagent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"granular": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"granular"
|
||||
],
|
||||
"title": "GranularAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"AuthMode": {
|
||||
"description": "Authentication mode for OpenAI-backed providers.",
|
||||
"oneOf": [
|
||||
@@ -658,6 +717,22 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"CollaborationMode": {
|
||||
"description": "Collaboration mode for a Codex session.",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "#/definitions/Settings"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"settings"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CommandAction": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -2232,6 +2307,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ModelRerouteReason": {
|
||||
"enum": [
|
||||
"highRiskCyberActivity"
|
||||
@@ -2293,6 +2376,13 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"NetworkAccess": {
|
||||
"enum": [
|
||||
"restricted",
|
||||
"enabled"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkApprovalProtocol": {
|
||||
"enum": [
|
||||
"http",
|
||||
@@ -2376,6 +2466,73 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileModificationParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Additional concrete directory that should be writable.",
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"additionalWritableRoot"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileSelectionParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Select a named built-in or user-defined profile and optionally apply bounded modifications that Codex knows how to validate.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"modifications": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionProfileModificationParams"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"profile"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Personality": {
|
||||
"enum": [
|
||||
"none",
|
||||
"friendly",
|
||||
"pragmatic"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanDeltaNotification": {
|
||||
"description": "EXPERIMENTAL - proposed plan streaming deltas for plan items. Clients should not assume concatenated deltas match the completed plan item content.",
|
||||
"properties": {
|
||||
@@ -2507,6 +2664,21 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RateLimitReachedType": {
|
||||
"enum": [
|
||||
"rate_limit_reached",
|
||||
@@ -2629,6 +2801,26 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningSummary": {
|
||||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"auto",
|
||||
"concise",
|
||||
"detailed"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Option to disable reasoning summaries.",
|
||||
"enum": [
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ReasoningSummaryPartAddedNotification": {
|
||||
"properties": {
|
||||
"itemId": {
|
||||
@@ -2773,6 +2965,105 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"dangerFullAccess"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"readOnly"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NetworkAccess"
|
||||
}
|
||||
],
|
||||
"default": "restricted"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"externalSandbox"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"excludeSlashTmp": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"excludeTmpdirEnvVar": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicyType",
|
||||
"type": "string"
|
||||
},
|
||||
"writableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicy",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ServerRequestResolvedNotification": {
|
||||
"properties": {
|
||||
"requestId": {
|
||||
@@ -2828,6 +3119,34 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"description": "Settings for a collaboration mode.",
|
||||
"properties": {
|
||||
"developer_instructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"model"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsChangedNotification": {
|
||||
"description": "Notification emitted when watched local skill files change.\n\nTreat this as an invalidation signal and re-run `skills/list` with the client's current parameters when refreshed skill metadata is needed.",
|
||||
"type": "object"
|
||||
@@ -3930,6 +4249,24 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueChangedNotification": {
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeAudioChunk": {
|
||||
"description": "EXPERIMENTAL - thread realtime audio chunk.",
|
||||
"properties": {
|
||||
@@ -4407,6 +4744,21 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnError": {
|
||||
"properties": {
|
||||
"additionalDetails": {
|
||||
@@ -4511,6 +4863,114 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartParams": {
|
||||
"properties": {
|
||||
"approvalPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the approval policy for this turn and subsequent turns."
|
||||
},
|
||||
"approvalsReviewer": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalsReviewer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Override the working directory for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning effort for this turn and subsequent turns."
|
||||
},
|
||||
"input": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UserInput"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"model": {
|
||||
"description": "Override the model for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Personality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the personality for this turn and subsequent turns."
|
||||
},
|
||||
"sandboxPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SandboxPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the sandbox policy for this turn and subsequent turns."
|
||||
},
|
||||
"serviceTier": {
|
||||
"description": "Override the service tier for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning summary for this turn and subsequent turns."
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"input",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartedNotification": {
|
||||
"properties": {
|
||||
"threadId": {
|
||||
@@ -5031,6 +5491,26 @@
|
||||
"title": "Thread/goal/clearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/changed"
|
||||
],
|
||||
"title": "Thread/queue/changedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueChangedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/changedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
|
||||
@@ -353,6 +353,102 @@
|
||||
"title": "Thread/name/setRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/v2/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/add"
|
||||
],
|
||||
"title": "Thread/queue/addRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadQueueAddParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/addRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/v2/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/list"
|
||||
],
|
||||
"title": "Thread/queue/listRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadQueueListParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/v2/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/delete"
|
||||
],
|
||||
"title": "Thread/queue/deleteRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadQueueDeleteParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/deleteRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/v2/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/reorder"
|
||||
],
|
||||
"title": "Thread/queue/reorderRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadQueueReorderParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/reorderRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -3941,6 +4037,26 @@
|
||||
"title": "Thread/goal/clearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/changed"
|
||||
],
|
||||
"title": "Thread/queue/changedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadQueueChangedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/changedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -12852,6 +12968,21 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/v2/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RateLimitReachedType": {
|
||||
"enum": [
|
||||
"rate_limit_reached",
|
||||
@@ -16431,6 +16562,151 @@
|
||||
"title": "ThreadNameUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueAddParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/v2/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId",
|
||||
"turnStartParams"
|
||||
],
|
||||
"title": "ThreadQueueAddParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueAddResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurn": {
|
||||
"$ref": "#/definitions/v2/QueuedTurn"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurn"
|
||||
],
|
||||
"title": "ThreadQueueAddResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueChangedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueChangedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueDeleteParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueDeleteParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueDeleteResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"deleted": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"deleted"
|
||||
],
|
||||
"title": "ThreadQueueDeleteResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueListParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueListParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueListResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns"
|
||||
],
|
||||
"title": "ThreadQueueListResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueReorderParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurnIds": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnIds",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueReorderParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueReorderResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns"
|
||||
],
|
||||
"title": "ThreadQueueReorderResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadReadParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -18389,4 +18665,4 @@
|
||||
},
|
||||
"title": "CodexAppServerProtocol",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
@@ -1112,6 +1112,102 @@
|
||||
"title": "Thread/name/setRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/add"
|
||||
],
|
||||
"title": "Thread/queue/addRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueAddParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/addRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/list"
|
||||
],
|
||||
"title": "Thread/queue/listRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueListParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/delete"
|
||||
],
|
||||
"title": "Thread/queue/deleteRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueDeleteParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/deleteRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/reorder"
|
||||
],
|
||||
"title": "Thread/queue/reorderRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueReorderParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/reorderRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -9463,6 +9559,21 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RateLimitReachedType": {
|
||||
"enum": [
|
||||
"rate_limit_reached",
|
||||
@@ -11140,6 +11251,26 @@
|
||||
"title": "Thread/goal/clearedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/queue/changed"
|
||||
],
|
||||
"title": "Thread/queue/changedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadQueueChangedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/queue/changedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -14317,6 +14448,151 @@
|
||||
"title": "ThreadNameUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueAddParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId",
|
||||
"turnStartParams"
|
||||
],
|
||||
"title": "ThreadQueueAddParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueAddResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurn": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurn"
|
||||
],
|
||||
"title": "ThreadQueueAddResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueChangedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueChangedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueDeleteParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueDeleteParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueDeleteResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"deleted": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"deleted"
|
||||
],
|
||||
"title": "ThreadQueueDeleteResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueListParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueListParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueListResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns"
|
||||
],
|
||||
"title": "ThreadQueueListResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueReorderParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurnIds": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnIds",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueReorderParams",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadQueueReorderResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns"
|
||||
],
|
||||
"title": "ThreadQueueReorderResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadReadParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -16274,4 +16550,4 @@
|
||||
},
|
||||
"title": "CodexAppServerProtocolV2",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
624
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueAddParams.json
generated
Normal file
624
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueAddParams.json
generated
Normal file
@@ -0,0 +1,624 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ApprovalsReviewer": {
|
||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||
"enum": [
|
||||
"user",
|
||||
"auto_review",
|
||||
"guardian_subagent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"granular": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"granular"
|
||||
],
|
||||
"title": "GranularAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"start": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"end",
|
||||
"start"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollaborationMode": {
|
||||
"description": "Collaboration mode for a Codex session.",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "#/definitions/Settings"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"settings"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkAccess": {
|
||||
"enum": [
|
||||
"restricted",
|
||||
"enabled"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfileModificationParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Additional concrete directory that should be writable.",
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"additionalWritableRoot"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileSelectionParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Select a named built-in or user-defined profile and optionally apply bounded modifications that Codex knows how to validate.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"modifications": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionProfileModificationParams"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"profile"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Personality": {
|
||||
"enum": [
|
||||
"none",
|
||||
"friendly",
|
||||
"pragmatic"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
"none",
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningSummary": {
|
||||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"auto",
|
||||
"concise",
|
||||
"detailed"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Option to disable reasoning summaries.",
|
||||
"enum": [
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"dangerFullAccess"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"readOnly"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NetworkAccess"
|
||||
}
|
||||
],
|
||||
"default": "restricted"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"externalSandbox"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"excludeSlashTmp": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"excludeTmpdirEnvVar": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicyType",
|
||||
"type": "string"
|
||||
},
|
||||
"writableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicy",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"description": "Settings for a collaboration mode.",
|
||||
"properties": {
|
||||
"developer_instructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"model"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ByteRange"
|
||||
}
|
||||
],
|
||||
"description": "Byte range in the parent `text` buffer that this element occupies."
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "Optional human-readable placeholder for the element, displayed in the UI.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"byteRange"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartParams": {
|
||||
"properties": {
|
||||
"approvalPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the approval policy for this turn and subsequent turns."
|
||||
},
|
||||
"approvalsReviewer": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalsReviewer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Override the working directory for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning effort for this turn and subsequent turns."
|
||||
},
|
||||
"input": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UserInput"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"model": {
|
||||
"description": "Override the model for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Personality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the personality for this turn and subsequent turns."
|
||||
},
|
||||
"sandboxPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SandboxPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the sandbox policy for this turn and subsequent turns."
|
||||
},
|
||||
"serviceTier": {
|
||||
"description": "Override the service tier for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning summary for this turn and subsequent turns."
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"input",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text_elements": {
|
||||
"default": [],
|
||||
"description": "UI-defined spans within `text` used to render or persist special elements.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TextElement"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"text"
|
||||
],
|
||||
"title": "TextUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text",
|
||||
"type"
|
||||
],
|
||||
"title": "TextUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"image"
|
||||
],
|
||||
"title": "ImageUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "ImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localImage"
|
||||
],
|
||||
"title": "LocalImageUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"skill"
|
||||
],
|
||||
"title": "SkillUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "SkillUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"mention"
|
||||
],
|
||||
"title": "MentionUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "MentionUserInput",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId",
|
||||
"turnStartParams"
|
||||
],
|
||||
"title": "ThreadQueueAddParams",
|
||||
"type": "object"
|
||||
}
|
||||
635
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueAddResponse.json
generated
Normal file
635
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueAddResponse.json
generated
Normal file
@@ -0,0 +1,635 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ApprovalsReviewer": {
|
||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||
"enum": [
|
||||
"user",
|
||||
"auto_review",
|
||||
"guardian_subagent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"granular": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"granular"
|
||||
],
|
||||
"title": "GranularAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"start": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"end",
|
||||
"start"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollaborationMode": {
|
||||
"description": "Collaboration mode for a Codex session.",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "#/definitions/Settings"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"settings"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkAccess": {
|
||||
"enum": [
|
||||
"restricted",
|
||||
"enabled"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfileModificationParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Additional concrete directory that should be writable.",
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"additionalWritableRoot"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileSelectionParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Select a named built-in or user-defined profile and optionally apply bounded modifications that Codex knows how to validate.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"modifications": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionProfileModificationParams"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"profile"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Personality": {
|
||||
"enum": [
|
||||
"none",
|
||||
"friendly",
|
||||
"pragmatic"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
"none",
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningSummary": {
|
||||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"auto",
|
||||
"concise",
|
||||
"detailed"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Option to disable reasoning summaries.",
|
||||
"enum": [
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"dangerFullAccess"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"readOnly"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NetworkAccess"
|
||||
}
|
||||
],
|
||||
"default": "restricted"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"externalSandbox"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"excludeSlashTmp": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"excludeTmpdirEnvVar": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicyType",
|
||||
"type": "string"
|
||||
},
|
||||
"writableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicy",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"description": "Settings for a collaboration mode.",
|
||||
"properties": {
|
||||
"developer_instructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"model"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ByteRange"
|
||||
}
|
||||
],
|
||||
"description": "Byte range in the parent `text` buffer that this element occupies."
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "Optional human-readable placeholder for the element, displayed in the UI.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"byteRange"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartParams": {
|
||||
"properties": {
|
||||
"approvalPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the approval policy for this turn and subsequent turns."
|
||||
},
|
||||
"approvalsReviewer": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalsReviewer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Override the working directory for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning effort for this turn and subsequent turns."
|
||||
},
|
||||
"input": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UserInput"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"model": {
|
||||
"description": "Override the model for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Personality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the personality for this turn and subsequent turns."
|
||||
},
|
||||
"sandboxPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SandboxPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the sandbox policy for this turn and subsequent turns."
|
||||
},
|
||||
"serviceTier": {
|
||||
"description": "Override the service tier for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning summary for this turn and subsequent turns."
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"input",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text_elements": {
|
||||
"default": [],
|
||||
"description": "UI-defined spans within `text` used to render or persist special elements.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TextElement"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"text"
|
||||
],
|
||||
"title": "TextUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text",
|
||||
"type"
|
||||
],
|
||||
"title": "TextUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"image"
|
||||
],
|
||||
"title": "ImageUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "ImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localImage"
|
||||
],
|
||||
"title": "LocalImageUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"skill"
|
||||
],
|
||||
"title": "SkillUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "SkillUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"mention"
|
||||
],
|
||||
"title": "MentionUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "MentionUserInput",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"queuedTurn": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurn"
|
||||
],
|
||||
"title": "ThreadQueueAddResponse",
|
||||
"type": "object"
|
||||
}
|
||||
642
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueChangedNotification.json
generated
Normal file
642
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueChangedNotification.json
generated
Normal file
@@ -0,0 +1,642 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ApprovalsReviewer": {
|
||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||
"enum": [
|
||||
"user",
|
||||
"auto_review",
|
||||
"guardian_subagent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"granular": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"granular"
|
||||
],
|
||||
"title": "GranularAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"start": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"end",
|
||||
"start"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollaborationMode": {
|
||||
"description": "Collaboration mode for a Codex session.",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "#/definitions/Settings"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"settings"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkAccess": {
|
||||
"enum": [
|
||||
"restricted",
|
||||
"enabled"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfileModificationParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Additional concrete directory that should be writable.",
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"additionalWritableRoot"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileSelectionParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Select a named built-in or user-defined profile and optionally apply bounded modifications that Codex knows how to validate.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"modifications": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionProfileModificationParams"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"profile"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Personality": {
|
||||
"enum": [
|
||||
"none",
|
||||
"friendly",
|
||||
"pragmatic"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
"none",
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningSummary": {
|
||||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"auto",
|
||||
"concise",
|
||||
"detailed"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Option to disable reasoning summaries.",
|
||||
"enum": [
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"dangerFullAccess"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"readOnly"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NetworkAccess"
|
||||
}
|
||||
],
|
||||
"default": "restricted"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"externalSandbox"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"excludeSlashTmp": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"excludeTmpdirEnvVar": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicyType",
|
||||
"type": "string"
|
||||
},
|
||||
"writableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicy",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"description": "Settings for a collaboration mode.",
|
||||
"properties": {
|
||||
"developer_instructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"model"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ByteRange"
|
||||
}
|
||||
],
|
||||
"description": "Byte range in the parent `text` buffer that this element occupies."
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "Optional human-readable placeholder for the element, displayed in the UI.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"byteRange"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartParams": {
|
||||
"properties": {
|
||||
"approvalPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the approval policy for this turn and subsequent turns."
|
||||
},
|
||||
"approvalsReviewer": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalsReviewer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Override the working directory for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning effort for this turn and subsequent turns."
|
||||
},
|
||||
"input": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UserInput"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"model": {
|
||||
"description": "Override the model for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Personality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the personality for this turn and subsequent turns."
|
||||
},
|
||||
"sandboxPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SandboxPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the sandbox policy for this turn and subsequent turns."
|
||||
},
|
||||
"serviceTier": {
|
||||
"description": "Override the service tier for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning summary for this turn and subsequent turns."
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"input",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text_elements": {
|
||||
"default": [],
|
||||
"description": "UI-defined spans within `text` used to render or persist special elements.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TextElement"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"text"
|
||||
],
|
||||
"title": "TextUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text",
|
||||
"type"
|
||||
],
|
||||
"title": "TextUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"image"
|
||||
],
|
||||
"title": "ImageUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "ImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localImage"
|
||||
],
|
||||
"title": "LocalImageUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"skill"
|
||||
],
|
||||
"title": "SkillUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "SkillUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"mention"
|
||||
],
|
||||
"title": "MentionUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "MentionUserInput",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueChangedNotification",
|
||||
"type": "object"
|
||||
}
|
||||
17
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueDeleteParams.json
generated
Normal file
17
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueDeleteParams.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueDeleteParams",
|
||||
"type": "object"
|
||||
}
|
||||
13
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueDeleteResponse.json
generated
Normal file
13
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueDeleteResponse.json
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"deleted": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"deleted"
|
||||
],
|
||||
"title": "ThreadQueueDeleteResponse",
|
||||
"type": "object"
|
||||
}
|
||||
13
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueListParams.json
generated
Normal file
13
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueListParams.json
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueListParams",
|
||||
"type": "object"
|
||||
}
|
||||
638
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueListResponse.json
generated
Normal file
638
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueListResponse.json
generated
Normal file
@@ -0,0 +1,638 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ApprovalsReviewer": {
|
||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||
"enum": [
|
||||
"user",
|
||||
"auto_review",
|
||||
"guardian_subagent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"granular": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"granular"
|
||||
],
|
||||
"title": "GranularAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"start": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"end",
|
||||
"start"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollaborationMode": {
|
||||
"description": "Collaboration mode for a Codex session.",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "#/definitions/Settings"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"settings"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkAccess": {
|
||||
"enum": [
|
||||
"restricted",
|
||||
"enabled"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfileModificationParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Additional concrete directory that should be writable.",
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"additionalWritableRoot"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileSelectionParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Select a named built-in or user-defined profile and optionally apply bounded modifications that Codex knows how to validate.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"modifications": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionProfileModificationParams"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"profile"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Personality": {
|
||||
"enum": [
|
||||
"none",
|
||||
"friendly",
|
||||
"pragmatic"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
"none",
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningSummary": {
|
||||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"auto",
|
||||
"concise",
|
||||
"detailed"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Option to disable reasoning summaries.",
|
||||
"enum": [
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"dangerFullAccess"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"readOnly"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NetworkAccess"
|
||||
}
|
||||
],
|
||||
"default": "restricted"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"externalSandbox"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"excludeSlashTmp": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"excludeTmpdirEnvVar": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicyType",
|
||||
"type": "string"
|
||||
},
|
||||
"writableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicy",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"description": "Settings for a collaboration mode.",
|
||||
"properties": {
|
||||
"developer_instructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"model"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ByteRange"
|
||||
}
|
||||
],
|
||||
"description": "Byte range in the parent `text` buffer that this element occupies."
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "Optional human-readable placeholder for the element, displayed in the UI.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"byteRange"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartParams": {
|
||||
"properties": {
|
||||
"approvalPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the approval policy for this turn and subsequent turns."
|
||||
},
|
||||
"approvalsReviewer": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalsReviewer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Override the working directory for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning effort for this turn and subsequent turns."
|
||||
},
|
||||
"input": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UserInput"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"model": {
|
||||
"description": "Override the model for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Personality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the personality for this turn and subsequent turns."
|
||||
},
|
||||
"sandboxPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SandboxPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the sandbox policy for this turn and subsequent turns."
|
||||
},
|
||||
"serviceTier": {
|
||||
"description": "Override the service tier for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning summary for this turn and subsequent turns."
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"input",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text_elements": {
|
||||
"default": [],
|
||||
"description": "UI-defined spans within `text` used to render or persist special elements.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TextElement"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"text"
|
||||
],
|
||||
"title": "TextUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text",
|
||||
"type"
|
||||
],
|
||||
"title": "TextUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"image"
|
||||
],
|
||||
"title": "ImageUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "ImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localImage"
|
||||
],
|
||||
"title": "LocalImageUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"skill"
|
||||
],
|
||||
"title": "SkillUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "SkillUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"mention"
|
||||
],
|
||||
"title": "MentionUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "MentionUserInput",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns"
|
||||
],
|
||||
"title": "ThreadQueueListResponse",
|
||||
"type": "object"
|
||||
}
|
||||
20
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueReorderParams.json
generated
Normal file
20
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueReorderParams.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"queuedTurnIds": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurnIds",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadQueueReorderParams",
|
||||
"type": "object"
|
||||
}
|
||||
638
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueReorderResponse.json
generated
Normal file
638
codex-rs/app-server-protocol/schema/json/v2/ThreadQueueReorderResponse.json
generated
Normal file
@@ -0,0 +1,638 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ApprovalsReviewer": {
|
||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||
"enum": [
|
||||
"user",
|
||||
"auto_review",
|
||||
"guardian_subagent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"untrusted",
|
||||
"on-failure",
|
||||
"on-request",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"granular": {
|
||||
"properties": {
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mcp_elicitations",
|
||||
"rules",
|
||||
"sandbox_approval"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"granular"
|
||||
],
|
||||
"title": "GranularAskForApproval",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"start": {
|
||||
"format": "uint",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"end",
|
||||
"start"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollaborationMode": {
|
||||
"description": "Collaboration mode for a Codex session.",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"$ref": "#/definitions/ModeKind"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "#/definitions/Settings"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"mode",
|
||||
"settings"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
"plan",
|
||||
"default"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkAccess": {
|
||||
"enum": [
|
||||
"restricted",
|
||||
"enabled"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionProfileModificationParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Additional concrete directory that should be writable.",
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"additionalWritableRoot"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "AdditionalWritableRootPermissionProfileModificationParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionProfileSelectionParams": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Select a named built-in or user-defined profile and optionally apply bounded modifications that Codex knows how to validate.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"modifications": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionProfileModificationParams"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"profile"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParamsType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"type"
|
||||
],
|
||||
"title": "ProfilePermissionProfileSelectionParams",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Personality": {
|
||||
"enum": [
|
||||
"none",
|
||||
"friendly",
|
||||
"pragmatic"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"QueuedTurn": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnStartParams": {
|
||||
"$ref": "#/definitions/TurnStartParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"turnStartParams"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
"none",
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ReasoningSummary": {
|
||||
"description": "A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process. See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"auto",
|
||||
"concise",
|
||||
"detailed"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Option to disable reasoning summaries.",
|
||||
"enum": [
|
||||
"none"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SandboxPolicy": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"dangerFullAccess"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "DangerFullAccessSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"readOnly"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ReadOnlySandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"networkAccess": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/NetworkAccess"
|
||||
}
|
||||
],
|
||||
"default": "restricted"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"externalSandbox"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicyType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "ExternalSandboxSandboxPolicy",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"excludeSlashTmp": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"excludeTmpdirEnvVar": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"networkAccess": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"workspaceWrite"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicyType",
|
||||
"type": "string"
|
||||
},
|
||||
"writableRoots": {
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "WorkspaceWriteSandboxPolicy",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Settings": {
|
||||
"description": "Settings for a collaboration mode.",
|
||||
"properties": {
|
||||
"developer_instructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"model"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ByteRange"
|
||||
}
|
||||
],
|
||||
"description": "Byte range in the parent `text` buffer that this element occupies."
|
||||
},
|
||||
"placeholder": {
|
||||
"description": "Optional human-readable placeholder for the element, displayed in the UI.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"byteRange"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnEnvironmentParams": {
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"environmentId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"cwd",
|
||||
"environmentId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TurnStartParams": {
|
||||
"properties": {
|
||||
"approvalPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AskForApproval"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the approval policy for this turn and subsequent turns."
|
||||
},
|
||||
"approvalsReviewer": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalsReviewer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override where approval requests are routed for review on this turn and subsequent turns."
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Override the working directory for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"effort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning effort for this turn and subsequent turns."
|
||||
},
|
||||
"input": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UserInput"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"model": {
|
||||
"description": "Override the model for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"description": "Optional JSON Schema used to constrain the final assistant message for this turn."
|
||||
},
|
||||
"personality": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Personality"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the personality for this turn and subsequent turns."
|
||||
},
|
||||
"sandboxPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SandboxPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the sandbox policy for this turn and subsequent turns."
|
||||
},
|
||||
"serviceTier": {
|
||||
"description": "Override the service tier for this turn and subsequent turns.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ReasoningSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Override the reasoning summary for this turn and subsequent turns."
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"input",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text_elements": {
|
||||
"default": [],
|
||||
"description": "UI-defined spans within `text` used to render or persist special elements.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TextElement"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"text"
|
||||
],
|
||||
"title": "TextUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text",
|
||||
"type"
|
||||
],
|
||||
"title": "TextUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"image"
|
||||
],
|
||||
"title": "ImageUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "ImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localImage"
|
||||
],
|
||||
"title": "LocalImageUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"skill"
|
||||
],
|
||||
"title": "SkillUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "SkillUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"mention"
|
||||
],
|
||||
"title": "MentionUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "MentionUserInput",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"queuedTurns": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/QueuedTurn"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"queuedTurns"
|
||||
],
|
||||
"title": "ThreadQueueReorderResponse",
|
||||
"type": "object"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
codex-rs/app-server-protocol/schema/typescript/v2/QueuedTurn.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/QueuedTurn.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 { TurnStartParams } from "./TurnStartParams";
|
||||
|
||||
export type QueuedTurn = { id: string, turnStartParams: TurnStartParams, };
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueAddParams.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueAddParams.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 { TurnStartParams } from "./TurnStartParams";
|
||||
|
||||
export type ThreadQueueAddParams = { threadId: string, turnStartParams: TurnStartParams, };
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueAddResponse.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueAddResponse.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 { QueuedTurn } from "./QueuedTurn";
|
||||
|
||||
export type ThreadQueueAddResponse = { queuedTurn: QueuedTurn, };
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueChangedNotification.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueChangedNotification.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 { QueuedTurn } from "./QueuedTurn";
|
||||
|
||||
export type ThreadQueueChangedNotification = { threadId: string, queuedTurns: Array<QueuedTurn>, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueDeleteParams.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueDeleteParams.ts
generated
Normal 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 ThreadQueueDeleteParams = { threadId: string, queuedTurnId: string, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueDeleteResponse.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueDeleteResponse.ts
generated
Normal 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 ThreadQueueDeleteResponse = { deleted: boolean, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueListParams.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueListParams.ts
generated
Normal 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 ThreadQueueListParams = { threadId: string, };
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueListResponse.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueListResponse.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 { QueuedTurn } from "./QueuedTurn";
|
||||
|
||||
export type ThreadQueueListResponse = { queuedTurns: Array<QueuedTurn>, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueReorderParams.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueReorderParams.ts
generated
Normal 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 ThreadQueueReorderParams = { threadId: string, queuedTurnIds: Array<string>, };
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueReorderResponse.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/ThreadQueueReorderResponse.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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 { QueuedTurn } from "./QueuedTurn";
|
||||
|
||||
export type ThreadQueueReorderResponse = { queuedTurns: Array<QueuedTurn>, };
|
||||
@@ -301,6 +301,7 @@ export type { ProcessOutputDeltaNotification } from "./ProcessOutputDeltaNotific
|
||||
export type { ProcessOutputStream } from "./ProcessOutputStream";
|
||||
export type { ProcessTerminalSize } from "./ProcessTerminalSize";
|
||||
export type { ProfileV2 } from "./ProfileV2";
|
||||
export type { QueuedTurn } from "./QueuedTurn";
|
||||
export type { RateLimitReachedType } from "./RateLimitReachedType";
|
||||
export type { RateLimitSnapshot } from "./RateLimitSnapshot";
|
||||
export type { RateLimitWindow } from "./RateLimitWindow";
|
||||
@@ -372,6 +373,15 @@ export type { ThreadMetadataGitInfoUpdateParams } from "./ThreadMetadataGitInfoU
|
||||
export type { ThreadMetadataUpdateParams } from "./ThreadMetadataUpdateParams";
|
||||
export type { ThreadMetadataUpdateResponse } from "./ThreadMetadataUpdateResponse";
|
||||
export type { ThreadNameUpdatedNotification } from "./ThreadNameUpdatedNotification";
|
||||
export type { ThreadQueueAddParams } from "./ThreadQueueAddParams";
|
||||
export type { ThreadQueueAddResponse } from "./ThreadQueueAddResponse";
|
||||
export type { ThreadQueueChangedNotification } from "./ThreadQueueChangedNotification";
|
||||
export type { ThreadQueueDeleteParams } from "./ThreadQueueDeleteParams";
|
||||
export type { ThreadQueueDeleteResponse } from "./ThreadQueueDeleteResponse";
|
||||
export type { ThreadQueueListParams } from "./ThreadQueueListParams";
|
||||
export type { ThreadQueueListResponse } from "./ThreadQueueListResponse";
|
||||
export type { ThreadQueueReorderParams } from "./ThreadQueueReorderParams";
|
||||
export type { ThreadQueueReorderResponse } from "./ThreadQueueReorderResponse";
|
||||
export type { ThreadReadParams } from "./ThreadReadParams";
|
||||
export type { ThreadReadResponse } from "./ThreadReadResponse";
|
||||
export type { ThreadRealtimeAudioChunk } from "./ThreadRealtimeAudioChunk";
|
||||
|
||||
@@ -1291,6 +1291,12 @@ fn insert_definition(
|
||||
if existing == &schema {
|
||||
return Ok(());
|
||||
}
|
||||
if schemas_match_ignoring_root_metadata(existing, &schema) {
|
||||
if existing.get("title").is_none() && schema.get("title").is_some() {
|
||||
definitions.insert(name, schema);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let existing_title = existing
|
||||
.get("title")
|
||||
@@ -1309,6 +1315,19 @@ fn insert_definition(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn schemas_match_ignoring_root_metadata(left: &Value, right: &Value) -> bool {
|
||||
let (Value::Object(left), Value::Object(right)) = (left, right) else {
|
||||
return false;
|
||||
};
|
||||
let mut left = left.clone();
|
||||
let mut right = right.clone();
|
||||
left.remove("title");
|
||||
right.remove("title");
|
||||
left.remove("$schema");
|
||||
right.remove("$schema");
|
||||
left == right
|
||||
}
|
||||
|
||||
fn write_json_schema_with_return<T>(out_dir: &Path, name: &str) -> Result<GeneratedSchema>
|
||||
where
|
||||
T: JsonSchema,
|
||||
@@ -2099,6 +2118,26 @@ mod tests {
|
||||
use std::path::PathBuf;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn schema_match_ignores_top_level_metadata() {
|
||||
let nested = serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"threadId": { "type": "string" },
|
||||
},
|
||||
});
|
||||
let root = serde_json::json!({
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "TurnStartParams",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"threadId": { "type": "string" },
|
||||
},
|
||||
});
|
||||
|
||||
assert!(schemas_match_ignoring_root_metadata(&nested, &root));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generated_ts_optional_nullable_fields_only_in_params() -> Result<()> {
|
||||
// Assert that "?: T | null" only appears in generated *Params types.
|
||||
|
||||
@@ -511,6 +511,27 @@ client_request_definitions! {
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadGoalClearResponse,
|
||||
},
|
||||
ThreadQueueAdd => "thread/queue/add" {
|
||||
params: v2::ThreadQueueAddParams,
|
||||
inspect_params: true,
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadQueueAddResponse,
|
||||
},
|
||||
ThreadQueueList => "thread/queue/list" {
|
||||
params: v2::ThreadQueueListParams,
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadQueueListResponse,
|
||||
},
|
||||
ThreadQueueDelete => "thread/queue/delete" {
|
||||
params: v2::ThreadQueueDeleteParams,
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadQueueDeleteResponse,
|
||||
},
|
||||
ThreadQueueReorder => "thread/queue/reorder" {
|
||||
params: v2::ThreadQueueReorderParams,
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadQueueReorderResponse,
|
||||
},
|
||||
ThreadMetadataUpdate => "thread/metadata/update" {
|
||||
params: v2::ThreadMetadataUpdateParams,
|
||||
serialization: thread_id(params.thread_id),
|
||||
@@ -1423,6 +1444,7 @@ server_notification_definitions! {
|
||||
ThreadGoalUpdated => "thread/goal/updated" (v2::ThreadGoalUpdatedNotification),
|
||||
#[experimental("thread/goal/cleared")]
|
||||
ThreadGoalCleared => "thread/goal/cleared" (v2::ThreadGoalClearedNotification),
|
||||
ThreadQueueChanged => "thread/queue/changed" (v2::ThreadQueueChangedNotification),
|
||||
ThreadTokenUsageUpdated => "thread/tokenUsage/updated" (v2::ThreadTokenUsageUpdatedNotification),
|
||||
TurnStarted => "turn/started" (v2::TurnStartedNotification),
|
||||
HookStarted => "hook/started" (v2::HookStartedNotification),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::QueuedTurn;
|
||||
use super::TurnError;
|
||||
use crate::RequestId;
|
||||
use schemars::JsonSchema;
|
||||
@@ -54,3 +55,11 @@ pub struct ServerRequestResolvedNotification {
|
||||
pub thread_id: String,
|
||||
pub request_id: RequestId,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueChangedNotification {
|
||||
pub thread_id: String,
|
||||
pub queued_turns: Vec<QueuedTurn>,
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use super::ThreadSource;
|
||||
use super::Turn;
|
||||
use super::TurnEnvironmentParams;
|
||||
use super::TurnItemsView;
|
||||
use super::TurnStartParams;
|
||||
use super::shared::v2_enum_from_core;
|
||||
use codex_experimental_api_macros::ExperimentalApi;
|
||||
use codex_protocol::config_types::Personality;
|
||||
@@ -635,6 +636,74 @@ pub struct ThreadGoalClearResponse {
|
||||
pub cleared: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct QueuedTurn {
|
||||
pub id: String,
|
||||
pub turn_start_params: TurnStartParams,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueAddParams {
|
||||
pub thread_id: String,
|
||||
#[experimental(nested)]
|
||||
pub turn_start_params: TurnStartParams,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueAddResponse {
|
||||
pub queued_turn: QueuedTurn,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueListParams {
|
||||
pub thread_id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueListResponse {
|
||||
pub queued_turns: Vec<QueuedTurn>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueDeleteParams {
|
||||
pub thread_id: String,
|
||||
pub queued_turn_id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueDeleteResponse {
|
||||
pub deleted: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueReorderParams {
|
||||
pub thread_id: String,
|
||||
pub queued_turn_ids: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadQueueReorderResponse {
|
||||
pub queued_turns: Vec<QueuedTurn>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
|
||||
@@ -159,6 +159,11 @@ Example with notification opt-out:
|
||||
- `thread/goal/clear` — clear the current persisted goal for a materialized thread; returns whether a goal was removed and emits `thread/goal/cleared` when state changes.
|
||||
- `thread/goal/updated` — notification emitted whenever a thread goal changes; includes the full current goal.
|
||||
- `thread/goal/cleared` — notification emitted whenever a thread goal is removed.
|
||||
- `thread/queue/add` — append one future `turn/start` payload to a materialized thread queue and emit `thread/queue/changed`.
|
||||
- `thread/queue/list` — read the current queued turns for a materialized thread.
|
||||
- `thread/queue/delete` — remove one queued turn by id and emit `thread/queue/changed` when state changes.
|
||||
- `thread/queue/reorder` — replace the queued-turn order with the supplied ids and emit `thread/queue/changed`.
|
||||
- `thread/queue/changed` — notification emitted whenever the queued-turn list changes; includes the full ordered queue snapshot.
|
||||
- `thread/status/changed` — notification emitted when a loaded thread’s status changes (`threadId` + new `status`).
|
||||
- `thread/archive` — move a thread’s rollout file into the archived directory and attempt to move any spawned descendant thread rollout files; returns `{}` on success and emits `thread/archived` for each archived thread.
|
||||
- `thread/unsubscribe` — unsubscribe this connection from thread turn/item events. If this was the last subscriber, the server keeps the thread loaded and unloads it only after it has had no subscribers and no thread activity for 30 minutes, then emits `thread/closed`.
|
||||
@@ -563,6 +568,37 @@ Use `thread/goal/clear` to remove the current goal.
|
||||
{ "method": "thread/goal/cleared", "params": { "threadId": "thr_123" } }
|
||||
```
|
||||
|
||||
### Example: Queue a follow-up turn
|
||||
|
||||
Use `thread/queue/add` to persist a future turn for a materialized thread. App-server stores the same normalized inputs that `turn/start` accepts, starts the head queued turn after the active turn reaches a terminal state, and emits the full queue snapshot whenever the queue changes.
|
||||
|
||||
```json
|
||||
{ "method": "thread/queue/add", "id": 31, "params": {
|
||||
"threadId": "thr_123",
|
||||
"turnStartParams": {
|
||||
"threadId": "thr_123",
|
||||
"input": [{ "type": "text", "text": "Run the smoke tests", "textElements": [] }]
|
||||
}
|
||||
} }
|
||||
{ "id": 31, "result": { "queuedTurn": {
|
||||
"id": "queued_123",
|
||||
"turnStartParams": {
|
||||
"threadId": "thr_123",
|
||||
"input": [{ "type": "text", "text": "Run the smoke tests", "textElements": [] }]
|
||||
}
|
||||
} } }
|
||||
{ "method": "thread/queue/changed", "params": {
|
||||
"threadId": "thr_123",
|
||||
"queuedTurns": [{
|
||||
"id": "queued_123",
|
||||
"turnStartParams": {
|
||||
"threadId": "thr_123",
|
||||
"input": [{ "type": "text", "text": "Run the smoke tests", "textElements": [] }]
|
||||
}
|
||||
}]
|
||||
} }
|
||||
```
|
||||
|
||||
### Example: Archive a thread
|
||||
|
||||
Use `thread/archive` to move the persisted rollout (stored as a JSONL file on disk) into the archived sessions directory and attempt to move any spawned descendant thread rollouts.
|
||||
|
||||
@@ -28,6 +28,7 @@ use crate::request_processors::PluginRequestProcessor;
|
||||
use crate::request_processors::ProcessExecRequestProcessor;
|
||||
use crate::request_processors::SearchRequestProcessor;
|
||||
use crate::request_processors::ThreadGoalRequestProcessor;
|
||||
use crate::request_processors::ThreadQueueRequestProcessor;
|
||||
use crate::request_processors::ThreadRequestProcessor;
|
||||
use crate::request_processors::TurnRequestProcessor;
|
||||
use crate::request_processors::WindowsSandboxRequestProcessor;
|
||||
@@ -168,6 +169,7 @@ pub(crate) struct MessageProcessor {
|
||||
plugin_processor: PluginRequestProcessor,
|
||||
search_processor: SearchRequestProcessor,
|
||||
thread_goal_processor: ThreadGoalRequestProcessor,
|
||||
thread_queue_processor: ThreadQueueRequestProcessor,
|
||||
thread_processor: ThreadRequestProcessor,
|
||||
turn_processor: TurnRequestProcessor,
|
||||
windows_sandbox_processor: WindowsSandboxRequestProcessor,
|
||||
@@ -375,6 +377,27 @@ impl MessageProcessor {
|
||||
thread_state_manager.clone(),
|
||||
state_db.clone(),
|
||||
);
|
||||
let turn_processor = TurnRequestProcessor::new(
|
||||
auth_manager.clone(),
|
||||
Arc::clone(&thread_manager),
|
||||
outgoing.clone(),
|
||||
analytics_events_client.clone(),
|
||||
arg0_paths.clone(),
|
||||
Arc::clone(&config),
|
||||
config_manager.clone(),
|
||||
Arc::clone(&pending_thread_unloads),
|
||||
thread_state_manager.clone(),
|
||||
thread_watch_manager.clone(),
|
||||
Arc::clone(&thread_list_state_permit),
|
||||
);
|
||||
let thread_queue_processor = ThreadQueueRequestProcessor::new(
|
||||
Arc::clone(&thread_manager),
|
||||
outgoing.clone(),
|
||||
Arc::clone(&config),
|
||||
thread_state_manager.clone(),
|
||||
state_db.clone(),
|
||||
turn_processor.clone(),
|
||||
);
|
||||
let thread_processor = ThreadRequestProcessor::new(
|
||||
auth_manager.clone(),
|
||||
Arc::clone(&thread_manager),
|
||||
@@ -384,24 +407,12 @@ impl MessageProcessor {
|
||||
config_manager.clone(),
|
||||
Arc::clone(&thread_store),
|
||||
Arc::clone(&pending_thread_unloads),
|
||||
thread_state_manager.clone(),
|
||||
thread_watch_manager.clone(),
|
||||
Arc::clone(&thread_list_state_permit),
|
||||
thread_goal_processor.clone(),
|
||||
state_db,
|
||||
);
|
||||
let turn_processor = TurnRequestProcessor::new(
|
||||
auth_manager.clone(),
|
||||
Arc::clone(&thread_manager),
|
||||
outgoing.clone(),
|
||||
analytics_events_client.clone(),
|
||||
arg0_paths.clone(),
|
||||
Arc::clone(&config),
|
||||
config_manager.clone(),
|
||||
pending_thread_unloads,
|
||||
thread_state_manager,
|
||||
thread_watch_manager,
|
||||
thread_list_state_permit,
|
||||
Arc::clone(&thread_list_state_permit),
|
||||
thread_goal_processor.clone(),
|
||||
thread_queue_processor.clone(),
|
||||
state_db.clone(),
|
||||
);
|
||||
if matches!(plugin_startup_tasks, crate::PluginStartupTasks::Start) {
|
||||
// Keep plugin startup warmups aligned at app-server startup.
|
||||
@@ -463,6 +474,7 @@ impl MessageProcessor {
|
||||
plugin_processor,
|
||||
search_processor,
|
||||
thread_goal_processor,
|
||||
thread_queue_processor,
|
||||
thread_processor,
|
||||
turn_processor,
|
||||
windows_sandbox_processor,
|
||||
@@ -969,6 +981,22 @@ impl MessageProcessor {
|
||||
.thread_goal_clear(request_id.clone(), params)
|
||||
.await
|
||||
}
|
||||
ClientRequest::ThreadQueueAdd { params, .. } => {
|
||||
self.thread_queue_processor.thread_queue_add(params).await
|
||||
}
|
||||
ClientRequest::ThreadQueueList { params, .. } => {
|
||||
self.thread_queue_processor.thread_queue_list(params).await
|
||||
}
|
||||
ClientRequest::ThreadQueueDelete { params, .. } => {
|
||||
self.thread_queue_processor
|
||||
.thread_queue_delete(params)
|
||||
.await
|
||||
}
|
||||
ClientRequest::ThreadQueueReorder { params, .. } => {
|
||||
self.thread_queue_processor
|
||||
.thread_queue_reorder(params)
|
||||
.await
|
||||
}
|
||||
ClientRequest::ThreadMetadataUpdate { params, .. } => {
|
||||
self.thread_processor.thread_metadata_update(params).await
|
||||
}
|
||||
|
||||
@@ -465,6 +465,7 @@ pub(crate) use process_exec_processor::ProcessExecRequestProcessor;
|
||||
pub(crate) use search::SearchRequestProcessor;
|
||||
pub(crate) use thread_goal_processor::ThreadGoalRequestProcessor;
|
||||
pub(crate) use thread_processor::ThreadRequestProcessor;
|
||||
pub(crate) use thread_queue_processor::ThreadQueueRequestProcessor;
|
||||
pub(crate) use turn_processor::TurnRequestProcessor;
|
||||
pub(crate) use windows_sandbox_processor::WindowsSandboxRequestProcessor;
|
||||
|
||||
@@ -482,12 +483,14 @@ mod config_errors;
|
||||
mod request_errors;
|
||||
mod thread_goal_processor;
|
||||
mod thread_lifecycle;
|
||||
mod thread_queue_processor;
|
||||
mod thread_summary;
|
||||
|
||||
use self::config_errors::*;
|
||||
use self::request_errors::*;
|
||||
use self::thread_goal_processor::api_thread_goal_from_state;
|
||||
use self::thread_lifecycle::*;
|
||||
use self::thread_queue_processor::send_thread_queue_snapshot_notification;
|
||||
use self::thread_summary::*;
|
||||
|
||||
pub(crate) use self::thread_lifecycle::populate_thread_turns_from_history;
|
||||
|
||||
@@ -322,7 +322,7 @@ impl ThreadGoalRequestProcessor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn state_db_for_materialized_thread(
|
||||
pub(super) async fn state_db_for_materialized_thread(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
) -> Result<StateDbHandle, JSONRPCErrorError> {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use codex_app_server_protocol::ThreadQueueChangedNotification;
|
||||
|
||||
pub(super) const THREAD_UNLOADING_DELAY: Duration = Duration::from_secs(30 * 60);
|
||||
|
||||
@@ -12,6 +13,7 @@ pub(super) struct ListenerTaskContext {
|
||||
pub(super) thread_list_state_permit: Arc<Semaphore>,
|
||||
pub(super) fallback_model_provider: String,
|
||||
pub(super) codex_home: PathBuf,
|
||||
pub(super) thread_queue_processor: Option<ThreadQueueRequestProcessor>,
|
||||
}
|
||||
|
||||
struct UnloadingState {
|
||||
@@ -242,6 +244,7 @@ pub(super) async fn ensure_listener_task_running(
|
||||
thread_list_state_permit,
|
||||
fallback_model_provider,
|
||||
codex_home,
|
||||
thread_queue_processor,
|
||||
} = listener_task_context;
|
||||
let outgoing_for_task = Arc::clone(&outgoing);
|
||||
tokio::spawn(async move {
|
||||
@@ -320,6 +323,13 @@ pub(super) async fn ensure_listener_task_running(
|
||||
fallback_model_provider.clone(),
|
||||
)
|
||||
.await;
|
||||
if matches!(event.msg, EventMsg::TurnComplete(_) | EventMsg::TurnAborted(_))
|
||||
&& let Some(thread_queue_processor) = thread_queue_processor.as_ref()
|
||||
{
|
||||
thread_queue_processor
|
||||
.drain_thread_queue_after_terminal_turn(conversation_id)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
unloading_watchers_open = unloading_state.wait_for_unloading_trigger() => {
|
||||
if !unloading_watchers_open {
|
||||
@@ -475,6 +485,19 @@ pub(super) async fn handle_thread_listener_command(
|
||||
ThreadListenerCommand::EmitThreadGoalSnapshot { state_db } => {
|
||||
send_thread_goal_snapshot_notification(outgoing, conversation_id, &state_db).await;
|
||||
}
|
||||
ThreadListenerCommand::EmitThreadQueueChanged { queued_turns } => {
|
||||
outgoing
|
||||
.send_server_notification(ServerNotification::ThreadQueueChanged(
|
||||
ThreadQueueChangedNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
queued_turns,
|
||||
},
|
||||
))
|
||||
.await;
|
||||
}
|
||||
ThreadListenerCommand::EmitThreadQueueSnapshot { state_db } => {
|
||||
send_thread_queue_snapshot_notification(outgoing, conversation_id, &state_db).await;
|
||||
}
|
||||
ThreadListenerCommand::ResolveServerRequest {
|
||||
request_id,
|
||||
completion_tx,
|
||||
@@ -643,6 +666,16 @@ pub(super) async fn handle_pending_thread_resume_request(
|
||||
);
|
||||
}
|
||||
}
|
||||
if pending.emit_thread_queue_update {
|
||||
if let Some(state_db) = pending.thread_queue_state_db {
|
||||
send_thread_queue_snapshot_notification(outgoing, conversation_id, &state_db).await;
|
||||
} else {
|
||||
tracing::warn!(
|
||||
thread_id = %conversation_id,
|
||||
"state db unavailable when reading thread queue for running thread resume"
|
||||
);
|
||||
}
|
||||
}
|
||||
outgoing
|
||||
.replay_requests_to_connection_for_thread(connection_id, conversation_id)
|
||||
.await;
|
||||
|
||||
@@ -315,6 +315,7 @@ pub(crate) struct ThreadRequestProcessor {
|
||||
pub(super) thread_watch_manager: ThreadWatchManager,
|
||||
pub(super) thread_list_state_permit: Arc<Semaphore>,
|
||||
pub(super) thread_goal_processor: ThreadGoalRequestProcessor,
|
||||
pub(super) thread_queue_processor: ThreadQueueRequestProcessor,
|
||||
pub(super) state_db: Option<StateDbHandle>,
|
||||
pub(super) background_tasks: TaskTracker,
|
||||
}
|
||||
@@ -334,6 +335,7 @@ impl ThreadRequestProcessor {
|
||||
thread_watch_manager: ThreadWatchManager,
|
||||
thread_list_state_permit: Arc<Semaphore>,
|
||||
thread_goal_processor: ThreadGoalRequestProcessor,
|
||||
thread_queue_processor: ThreadQueueRequestProcessor,
|
||||
state_db: Option<StateDbHandle>,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -349,6 +351,7 @@ impl ThreadRequestProcessor {
|
||||
thread_watch_manager,
|
||||
thread_list_state_permit,
|
||||
thread_goal_processor,
|
||||
thread_queue_processor,
|
||||
state_db,
|
||||
background_tasks: TaskTracker::new(),
|
||||
}
|
||||
@@ -752,6 +755,7 @@ impl ThreadRequestProcessor {
|
||||
thread_list_state_permit: self.thread_list_state_permit.clone(),
|
||||
fallback_model_provider: self.config.model_provider_id.clone(),
|
||||
codex_home: self.config.codex_home.to_path_buf(),
|
||||
thread_queue_processor: Some(self.thread_queue_processor.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,6 +853,7 @@ impl ThreadRequestProcessor {
|
||||
thread_list_state_permit: self.thread_list_state_permit.clone(),
|
||||
fallback_model_provider: self.config.model_provider_id.clone(),
|
||||
codex_home: self.config.codex_home.to_path_buf(),
|
||||
thread_queue_processor: Some(self.thread_queue_processor.clone()),
|
||||
};
|
||||
let request_trace = request_context.request_trace();
|
||||
let config_manager = self.config_manager.clone();
|
||||
@@ -2561,6 +2566,9 @@ impl ThreadRequestProcessor {
|
||||
self.thread_goal_processor
|
||||
.emit_resume_goal_snapshot_and_continue(thread_id, codex_thread.as_ref())
|
||||
.await;
|
||||
self.thread_queue_processor
|
||||
.emit_resume_queue_snapshot_and_drain(thread_id)
|
||||
.await;
|
||||
}
|
||||
Err(err) => {
|
||||
let error = internal_error(format!("error resuming thread: {err}"));
|
||||
@@ -2719,6 +2727,8 @@ impl ThreadRequestProcessor {
|
||||
.thread_goal_processor
|
||||
.pending_resume_goal_state(existing_thread.as_ref())
|
||||
.await;
|
||||
let emit_thread_queue_update = true;
|
||||
let thread_queue_state_db = self.state_db.clone();
|
||||
|
||||
let command = crate::thread_state::ThreadListenerCommand::SendThreadResumeResponse(
|
||||
Box::new(crate::thread_state::PendingThreadResumeRequest {
|
||||
@@ -2729,6 +2739,8 @@ impl ThreadRequestProcessor {
|
||||
thread_summary,
|
||||
emit_thread_goal_update,
|
||||
thread_goal_state_db,
|
||||
emit_thread_queue_update,
|
||||
thread_queue_state_db,
|
||||
include_turns: !params.exclude_turns,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
use super::*;
|
||||
use codex_app_server_protocol::QueuedTurn;
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_app_server_protocol::ThreadQueueAddParams;
|
||||
use codex_app_server_protocol::ThreadQueueAddResponse;
|
||||
use codex_app_server_protocol::ThreadQueueChangedNotification;
|
||||
use codex_app_server_protocol::ThreadQueueDeleteParams;
|
||||
use codex_app_server_protocol::ThreadQueueDeleteResponse;
|
||||
use codex_app_server_protocol::ThreadQueueListParams;
|
||||
use codex_app_server_protocol::ThreadQueueListResponse;
|
||||
use codex_app_server_protocol::ThreadQueueReorderParams;
|
||||
use codex_app_server_protocol::ThreadQueueReorderResponse;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ThreadQueueRequestProcessor {
|
||||
thread_manager: Arc<ThreadManager>,
|
||||
outgoing: Arc<OutgoingMessageSender>,
|
||||
config: Arc<Config>,
|
||||
thread_state_manager: ThreadStateManager,
|
||||
state_db: Option<StateDbHandle>,
|
||||
turn_processor: TurnRequestProcessor,
|
||||
}
|
||||
|
||||
impl ThreadQueueRequestProcessor {
|
||||
pub(crate) fn new(
|
||||
thread_manager: Arc<ThreadManager>,
|
||||
outgoing: Arc<OutgoingMessageSender>,
|
||||
config: Arc<Config>,
|
||||
thread_state_manager: ThreadStateManager,
|
||||
state_db: Option<StateDbHandle>,
|
||||
turn_processor: TurnRequestProcessor,
|
||||
) -> Self {
|
||||
Self {
|
||||
thread_manager,
|
||||
outgoing,
|
||||
config,
|
||||
thread_state_manager,
|
||||
state_db,
|
||||
turn_processor,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_queue_add(
|
||||
&self,
|
||||
params: ThreadQueueAddParams,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
TurnRequestProcessor::validate_v2_input_limit(¶ms.turn_start_params.input)?;
|
||||
let thread_id = parse_thread_id_for_request(params.thread_id.as_str())?;
|
||||
if params.turn_start_params.thread_id != params.thread_id {
|
||||
return Err(invalid_request(
|
||||
"threadId must match turnStartParams.threadId".to_string(),
|
||||
));
|
||||
}
|
||||
let state_db = self.state_db_for_materialized_thread(thread_id).await?;
|
||||
let turn_start_params_json =
|
||||
serde_json::to_string(¶ms.turn_start_params).map_err(|err| {
|
||||
internal_error(format!("failed to serialize queued turn params: {err}"))
|
||||
})?;
|
||||
let queued_turn = state_db
|
||||
.append_thread_queued_turn(thread_id, turn_start_params_json)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to add queued turn: {err}")))?;
|
||||
let queued_turn = api_queued_turn_from_state(queued_turn)
|
||||
.map_err(|err| internal_error(format!("failed to decode queued turn params: {err}")))?;
|
||||
let queued_turns = read_api_thread_queue(&state_db, thread_id).await?;
|
||||
self.emit_thread_queue_changed_ordered(thread_id, queued_turns)
|
||||
.await;
|
||||
self.drain_thread_queue_if_idle(thread_id, &state_db).await;
|
||||
Ok(Some(
|
||||
ThreadQueueAddResponse {
|
||||
queued_turn: queued_turn.clone(),
|
||||
}
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_queue_list(
|
||||
&self,
|
||||
params: ThreadQueueListParams,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
let thread_id = parse_thread_id_for_request(params.thread_id.as_str())?;
|
||||
let state_db = self.state_db_for_materialized_thread(thread_id).await?;
|
||||
let queued_turns = read_api_thread_queue(&state_db, thread_id).await?;
|
||||
Ok(Some(ThreadQueueListResponse { queued_turns }.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_queue_delete(
|
||||
&self,
|
||||
params: ThreadQueueDeleteParams,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
let thread_id = parse_thread_id_for_request(params.thread_id.as_str())?;
|
||||
let state_db = self.state_db_for_materialized_thread(thread_id).await?;
|
||||
let deleted = state_db
|
||||
.delete_thread_queued_turn(thread_id, params.queued_turn_id.as_str())
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to delete queued turn: {err}")))?;
|
||||
if deleted {
|
||||
let queued_turns = read_api_thread_queue(&state_db, thread_id).await?;
|
||||
self.emit_thread_queue_changed_ordered(thread_id, queued_turns)
|
||||
.await;
|
||||
}
|
||||
Ok(Some(ThreadQueueDeleteResponse { deleted }.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_queue_reorder(
|
||||
&self,
|
||||
params: ThreadQueueReorderParams,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
let thread_id = parse_thread_id_for_request(params.thread_id.as_str())?;
|
||||
let state_db = self.state_db_for_materialized_thread(thread_id).await?;
|
||||
state_db
|
||||
.reorder_thread_queued_turns(thread_id, params.queued_turn_ids.as_slice())
|
||||
.await
|
||||
.map_err(|err| invalid_request(err.to_string()))?;
|
||||
let queued_turns = read_api_thread_queue(&state_db, thread_id).await?;
|
||||
self.emit_thread_queue_changed_ordered(thread_id, queued_turns.clone())
|
||||
.await;
|
||||
Ok(Some(ThreadQueueReorderResponse { queued_turns }.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn emit_resume_queue_snapshot_and_drain(&self, thread_id: ThreadId) {
|
||||
self.emit_thread_queue_snapshot(thread_id).await;
|
||||
self.drain_thread_queue_after_terminal_turn(thread_id).await;
|
||||
}
|
||||
|
||||
pub(crate) async fn drain_thread_queue_after_terminal_turn(&self, thread_id: ThreadId) {
|
||||
let state_db = match self.state_db_for_materialized_thread(thread_id).await {
|
||||
Ok(state_db) => state_db,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"failed to open state db before draining thread queue for {thread_id}: {}",
|
||||
err.message
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
self.drain_thread_queue_if_idle(thread_id, &state_db).await;
|
||||
}
|
||||
|
||||
async fn drain_thread_queue_if_idle(&self, thread_id: ThreadId, state_db: &StateDbHandle) {
|
||||
let Ok(thread) = self.thread_manager.get_thread(thread_id).await else {
|
||||
return;
|
||||
};
|
||||
if self
|
||||
.thread_has_live_in_progress_turn(thread_id, thread.as_ref())
|
||||
.await
|
||||
{
|
||||
return;
|
||||
}
|
||||
let queued_turn = match state_db.first_thread_queued_turn(thread_id).await {
|
||||
Ok(Some(queued_turn)) => queued_turn,
|
||||
Ok(None) => return,
|
||||
Err(err) => {
|
||||
warn!("failed to read next queued turn for {thread_id}: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let turn_start_params = match api_queued_turn_from_state(queued_turn.clone()) {
|
||||
Ok(queued_turn) => queued_turn.turn_start_params,
|
||||
Err(err) => {
|
||||
warn!("failed to decode next queued turn for {thread_id}: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match self
|
||||
.turn_processor
|
||||
.queued_turn_start(turn_start_params)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
if let Err(err) = state_db
|
||||
.delete_thread_queued_turn(thread_id, queued_turn.queued_turn_id.as_str())
|
||||
.await
|
||||
{
|
||||
warn!(
|
||||
"failed to remove dispatched queued turn {} for {thread_id}: {err}",
|
||||
queued_turn.queued_turn_id
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
warn!(
|
||||
"failed to dispatch queued turn {} for {thread_id}: {}",
|
||||
queued_turn.queued_turn_id, error.message
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
match read_api_thread_queue(state_db, thread_id).await {
|
||||
Ok(queued_turns) => {
|
||||
self.emit_thread_queue_changed_ordered(thread_id, queued_turns)
|
||||
.await;
|
||||
}
|
||||
Err(err) => warn!("{}", err.message),
|
||||
}
|
||||
}
|
||||
|
||||
async fn thread_has_live_in_progress_turn(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
thread: &CodexThread,
|
||||
) -> bool {
|
||||
if matches!(thread.agent_status().await, AgentStatus::Running) {
|
||||
return true;
|
||||
}
|
||||
let thread_state = self.thread_state_manager.thread_state(thread_id).await;
|
||||
thread_state.lock().await.active_turn_snapshot().is_some()
|
||||
}
|
||||
|
||||
async fn state_db_for_materialized_thread(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
) -> Result<StateDbHandle, JSONRPCErrorError> {
|
||||
if let Ok(thread) = self.thread_manager.get_thread(thread_id).await {
|
||||
if thread.rollout_path().is_none() {
|
||||
return Err(invalid_request(format!(
|
||||
"ephemeral thread does not support persistent app-server state: {thread_id}"
|
||||
)));
|
||||
}
|
||||
if let Some(state_db) = thread.state_db() {
|
||||
return Ok(state_db);
|
||||
}
|
||||
} else {
|
||||
find_thread_path_by_id_str(
|
||||
&self.config.codex_home,
|
||||
&thread_id.to_string(),
|
||||
self.state_db.as_deref(),
|
||||
)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
internal_error(format!("failed to locate thread id {thread_id}: {err}"))
|
||||
})?
|
||||
.ok_or_else(|| invalid_request(format!("thread not found: {thread_id}")))?;
|
||||
}
|
||||
|
||||
self.state_db.clone().ok_or_else(|| {
|
||||
invalid_request(format!(
|
||||
"thread does not support persistent app-server state: {thread_id}"
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
async fn emit_thread_queue_snapshot(&self, thread_id: ThreadId) {
|
||||
let state_db = match self.state_db_for_materialized_thread(thread_id).await {
|
||||
Ok(state_db) => state_db,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"failed to open state db before emitting thread queue resume snapshot for {thread_id}: {}",
|
||||
err.message
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let listener_command_tx = {
|
||||
let thread_state = self.thread_state_manager.thread_state(thread_id).await;
|
||||
let thread_state = thread_state.lock().await;
|
||||
thread_state.listener_command_tx()
|
||||
};
|
||||
if let Some(listener_command_tx) = listener_command_tx {
|
||||
let command = ThreadListenerCommand::EmitThreadQueueSnapshot {
|
||||
state_db: state_db.clone(),
|
||||
};
|
||||
if listener_command_tx.send(command).is_ok() {
|
||||
return;
|
||||
}
|
||||
warn!(
|
||||
"failed to enqueue thread queue snapshot for {thread_id}: listener command channel is closed"
|
||||
);
|
||||
}
|
||||
send_thread_queue_snapshot_notification(&self.outgoing, thread_id, &state_db).await;
|
||||
}
|
||||
|
||||
async fn emit_thread_queue_changed_ordered(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
queued_turns: Vec<QueuedTurn>,
|
||||
) {
|
||||
let listener_command_tx = {
|
||||
let thread_state = self.thread_state_manager.thread_state(thread_id).await;
|
||||
let thread_state = thread_state.lock().await;
|
||||
thread_state.listener_command_tx()
|
||||
};
|
||||
if let Some(listener_command_tx) = listener_command_tx {
|
||||
let command = ThreadListenerCommand::EmitThreadQueueChanged {
|
||||
queued_turns: queued_turns.clone(),
|
||||
};
|
||||
if listener_command_tx.send(command).is_ok() {
|
||||
return;
|
||||
}
|
||||
warn!(
|
||||
"failed to enqueue thread queue update for {thread_id}: listener command channel is closed"
|
||||
);
|
||||
}
|
||||
self.outgoing
|
||||
.send_server_notification(ServerNotification::ThreadQueueChanged(
|
||||
ThreadQueueChangedNotification {
|
||||
thread_id: thread_id.to_string(),
|
||||
queued_turns,
|
||||
},
|
||||
))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_thread_id_for_request(thread_id: &str) -> Result<ThreadId, JSONRPCErrorError> {
|
||||
ThreadId::from_string(thread_id)
|
||||
.map_err(|err| invalid_request(format!("invalid thread id: {err}")))
|
||||
}
|
||||
|
||||
fn api_queued_turn_from_state(
|
||||
queued_turn: codex_state::ThreadQueuedTurn,
|
||||
) -> anyhow::Result<QueuedTurn> {
|
||||
Ok(QueuedTurn {
|
||||
id: queued_turn.queued_turn_id,
|
||||
turn_start_params: serde_json::from_str(queued_turn.turn_start_params_json.as_str())?,
|
||||
})
|
||||
}
|
||||
|
||||
async fn read_api_thread_queue(
|
||||
state_db: &StateDbHandle,
|
||||
thread_id: ThreadId,
|
||||
) -> Result<Vec<QueuedTurn>, JSONRPCErrorError> {
|
||||
state_db
|
||||
.list_thread_queued_turns(thread_id)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to read thread queue: {err}")))?
|
||||
.into_iter()
|
||||
.map(api_queued_turn_from_state)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|err| internal_error(format!("failed to decode queued turn params: {err}")))
|
||||
}
|
||||
|
||||
pub(super) async fn send_thread_queue_snapshot_notification(
|
||||
outgoing: &Arc<OutgoingMessageSender>,
|
||||
thread_id: ThreadId,
|
||||
state_db: &StateDbHandle,
|
||||
) {
|
||||
match read_api_thread_queue(state_db, thread_id).await {
|
||||
Ok(queued_turns) => {
|
||||
outgoing
|
||||
.send_server_notification(ServerNotification::ThreadQueueChanged(
|
||||
ThreadQueueChangedNotification {
|
||||
thread_id: thread_id.to_string(),
|
||||
queued_turns,
|
||||
},
|
||||
))
|
||||
.await;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(thread_id = %thread_id, "{}", err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,13 @@ pub(crate) struct TurnRequestProcessor {
|
||||
thread_list_state_permit: Arc<Semaphore>,
|
||||
}
|
||||
|
||||
struct PreparedTurnStart {
|
||||
thread_id: ThreadId,
|
||||
thread: Arc<CodexThread>,
|
||||
turn_op: Op,
|
||||
turn_has_input: bool,
|
||||
}
|
||||
|
||||
impl TurnRequestProcessor {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
@@ -52,14 +59,33 @@ impl TurnRequestProcessor {
|
||||
app_server_client_name: Option<String>,
|
||||
app_server_client_version: Option<String>,
|
||||
) -> Result<Option<ClientResponsePayload>, JSONRPCErrorError> {
|
||||
self.turn_start_inner(
|
||||
request_id,
|
||||
params,
|
||||
app_server_client_name,
|
||||
app_server_client_version,
|
||||
)
|
||||
.await
|
||||
.map(|response| Some(response.into()))
|
||||
if let Err(error) = Self::validate_v2_input_limit(¶ms.input) {
|
||||
self.track_error_response(
|
||||
&request_id,
|
||||
&error,
|
||||
Some(AnalyticsJsonRpcError::Input(InputError::TooLarge)),
|
||||
);
|
||||
return Err(error);
|
||||
}
|
||||
let prepared = self
|
||||
.prepare_turn_start(params, app_server_client_name, app_server_client_version)
|
||||
.await
|
||||
.inspect_err(|error| {
|
||||
self.track_error_response(&request_id, error, /*error_type*/ None);
|
||||
})?;
|
||||
let response = self
|
||||
.submit_prepared_turn_start(
|
||||
prepared,
|
||||
self.request_trace_context(Some(&request_id)).await,
|
||||
)
|
||||
.await
|
||||
.inspect_err(|error| {
|
||||
self.track_error_response(&request_id, error, /*error_type*/ None);
|
||||
})?;
|
||||
self.outgoing
|
||||
.record_request_turn_id(&request_id, &response.turn.id)
|
||||
.await;
|
||||
Ok(Some(response.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn thread_inject_items(
|
||||
@@ -71,6 +97,15 @@ impl TurnRequestProcessor {
|
||||
.map(|response| Some(response.into()))
|
||||
}
|
||||
|
||||
pub(crate) async fn queued_turn_start(
|
||||
&self,
|
||||
params: TurnStartParams,
|
||||
) -> Result<TurnStartResponse, JSONRPCErrorError> {
|
||||
Self::validate_v2_input_limit(¶ms.input)?;
|
||||
let prepared = self.prepare_turn_start(params, None, None).await?;
|
||||
self.submit_prepared_turn_start(prepared, None).await
|
||||
}
|
||||
|
||||
pub(crate) async fn turn_steer(
|
||||
&self,
|
||||
request_id: &ConnectionRequestId,
|
||||
@@ -273,14 +308,17 @@ impl TurnRequestProcessor {
|
||||
|
||||
async fn request_trace_context(
|
||||
&self,
|
||||
request_id: &ConnectionRequestId,
|
||||
request_id: Option<&ConnectionRequestId>,
|
||||
) -> Option<codex_protocol::protocol::W3cTraceContext> {
|
||||
self.outgoing.request_trace_context(request_id).await
|
||||
match request_id {
|
||||
Some(request_id) => self.outgoing.request_trace_context(request_id).await,
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn submit_core_op(
|
||||
&self,
|
||||
request_id: &ConnectionRequestId,
|
||||
request_id: Option<&ConnectionRequestId>,
|
||||
thread: &CodexThread,
|
||||
op: Op,
|
||||
) -> CodexResult<String> {
|
||||
@@ -301,7 +339,7 @@ impl TurnRequestProcessor {
|
||||
error
|
||||
}
|
||||
|
||||
fn validate_v2_input_limit(items: &[V2UserInput]) -> Result<(), JSONRPCErrorError> {
|
||||
pub(crate) fn validate_v2_input_limit(items: &[V2UserInput]) -> Result<(), JSONRPCErrorError> {
|
||||
let actual_chars: usize = items.iter().map(V2UserInput::text_char_count).sum();
|
||||
if actual_chars > MAX_USER_INPUT_TEXT_CHARS {
|
||||
return Err(Self::input_too_large_error(actual_chars));
|
||||
@@ -309,36 +347,19 @@ impl TurnRequestProcessor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn turn_start_inner(
|
||||
async fn prepare_turn_start(
|
||||
&self,
|
||||
request_id: ConnectionRequestId,
|
||||
params: TurnStartParams,
|
||||
app_server_client_name: Option<String>,
|
||||
app_server_client_version: Option<String>,
|
||||
) -> Result<TurnStartResponse, JSONRPCErrorError> {
|
||||
if let Err(error) = Self::validate_v2_input_limit(¶ms.input) {
|
||||
self.track_error_response(
|
||||
&request_id,
|
||||
&error,
|
||||
Some(AnalyticsJsonRpcError::Input(InputError::TooLarge)),
|
||||
);
|
||||
return Err(error);
|
||||
}
|
||||
let (thread_id, thread) =
|
||||
self.load_thread(¶ms.thread_id)
|
||||
.await
|
||||
.inspect_err(|error| {
|
||||
self.track_error_response(&request_id, error, /*error_type*/ None);
|
||||
})?;
|
||||
) -> Result<PreparedTurnStart, JSONRPCErrorError> {
|
||||
let (thread_id, thread) = self.load_thread(¶ms.thread_id).await?;
|
||||
Self::set_app_server_client_info(
|
||||
thread.as_ref(),
|
||||
app_server_client_name,
|
||||
app_server_client_version,
|
||||
)
|
||||
.await
|
||||
.inspect_err(|error| {
|
||||
self.track_error_response(&request_id, error, /*error_type*/ None);
|
||||
})?;
|
||||
.await?;
|
||||
|
||||
let collaboration_mode = params
|
||||
.collaboration_mode
|
||||
@@ -475,14 +496,29 @@ impl TurnRequestProcessor {
|
||||
responsesapi_client_metadata: params.responsesapi_client_metadata,
|
||||
}
|
||||
};
|
||||
let turn_id = self
|
||||
.submit_core_op(&request_id, thread.as_ref(), turn_op)
|
||||
Ok(PreparedTurnStart {
|
||||
thread_id,
|
||||
thread,
|
||||
turn_op,
|
||||
turn_has_input,
|
||||
})
|
||||
}
|
||||
|
||||
async fn submit_prepared_turn_start(
|
||||
&self,
|
||||
prepared: PreparedTurnStart,
|
||||
trace_context: Option<codex_protocol::protocol::W3cTraceContext>,
|
||||
) -> Result<TurnStartResponse, JSONRPCErrorError> {
|
||||
let PreparedTurnStart {
|
||||
thread_id,
|
||||
thread,
|
||||
turn_op,
|
||||
turn_has_input,
|
||||
} = prepared;
|
||||
let turn_id = thread
|
||||
.submit_with_trace(turn_op, trace_context)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
let error = internal_error(format!("failed to start turn: {err}"));
|
||||
self.track_error_response(&request_id, &error, /*error_type*/ None);
|
||||
error
|
||||
})?;
|
||||
.map_err(|err| internal_error(format!("failed to start turn: {err}")))?;
|
||||
|
||||
if turn_has_input {
|
||||
let config_snapshot = thread.config_snapshot().await;
|
||||
@@ -496,9 +532,6 @@ impl TurnRequestProcessor {
|
||||
);
|
||||
}
|
||||
|
||||
self.outgoing
|
||||
.record_request_turn_id(&request_id, &turn_id)
|
||||
.await;
|
||||
let turn = Turn {
|
||||
id: turn_id,
|
||||
items: vec![],
|
||||
@@ -706,7 +739,7 @@ impl TurnRequestProcessor {
|
||||
return Ok(None);
|
||||
};
|
||||
self.submit_core_op(
|
||||
request_id,
|
||||
Some(request_id),
|
||||
thread.as_ref(),
|
||||
Op::RealtimeConversationStart(ConversationStartParams {
|
||||
output_modality: params.output_modality,
|
||||
@@ -740,7 +773,7 @@ impl TurnRequestProcessor {
|
||||
return Ok(None);
|
||||
};
|
||||
self.submit_core_op(
|
||||
request_id,
|
||||
Some(request_id),
|
||||
thread.as_ref(),
|
||||
Op::RealtimeConversationAudio(ConversationAudioParams {
|
||||
frame: params.audio.into(),
|
||||
@@ -767,7 +800,7 @@ impl TurnRequestProcessor {
|
||||
return Ok(None);
|
||||
};
|
||||
self.submit_core_op(
|
||||
request_id,
|
||||
Some(request_id),
|
||||
thread.as_ref(),
|
||||
Op::RealtimeConversationText(ConversationTextParams { text: params.text }),
|
||||
)
|
||||
@@ -791,11 +824,13 @@ impl TurnRequestProcessor {
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
self.submit_core_op(request_id, thread.as_ref(), Op::RealtimeConversationClose)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
internal_error(format!("failed to stop realtime conversation: {err}"))
|
||||
})?;
|
||||
self.submit_core_op(
|
||||
Some(request_id),
|
||||
thread.as_ref(),
|
||||
Op::RealtimeConversationClose,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to stop realtime conversation: {err}")))?;
|
||||
Ok(Some(ThreadRealtimeStopResponse::default()))
|
||||
}
|
||||
|
||||
@@ -850,7 +885,7 @@ impl TurnRequestProcessor {
|
||||
) -> std::result::Result<(), JSONRPCErrorError> {
|
||||
let turn_id = self
|
||||
.submit_core_op(
|
||||
request_id,
|
||||
Some(request_id),
|
||||
parent_thread.as_ref(),
|
||||
Op::Review { review_request },
|
||||
)
|
||||
@@ -906,7 +941,7 @@ impl TurnRequestProcessor {
|
||||
}),
|
||||
/*thread_source*/ None,
|
||||
/*persist_extended_history*/ false,
|
||||
self.request_trace_context(request_id).await,
|
||||
self.request_trace_context(Some(request_id)).await,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -957,7 +992,7 @@ impl TurnRequestProcessor {
|
||||
|
||||
let turn_id = self
|
||||
.submit_core_op(
|
||||
request_id,
|
||||
Some(request_id),
|
||||
review_thread.as_ref(),
|
||||
Op::Review { review_request },
|
||||
)
|
||||
@@ -1052,7 +1087,7 @@ impl TurnRequestProcessor {
|
||||
// Submit the interrupt. Turn interrupts respond upon TurnAborted; startup
|
||||
// interrupts respond here because startup cancellation has no turn event.
|
||||
match self
|
||||
.submit_core_op(request_id, thread.as_ref(), Op::Interrupt)
|
||||
.submit_core_op(Some(request_id), thread.as_ref(), Op::Interrupt)
|
||||
.await
|
||||
{
|
||||
Ok(_) if is_startup_interrupt => Ok(Some(TurnInterruptResponse {})),
|
||||
@@ -1087,6 +1122,7 @@ impl TurnRequestProcessor {
|
||||
thread_list_state_permit: self.thread_list_state_permit.clone(),
|
||||
fallback_model_provider: self.config.model_provider_id.clone(),
|
||||
codex_home: self.config.codex_home.to_path_buf(),
|
||||
thread_queue_processor: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::outgoing_message::ConnectionId;
|
||||
use crate::outgoing_message::ConnectionRequestId;
|
||||
use codex_app_server_protocol::QueuedTurn;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::ThreadGoal;
|
||||
use codex_app_server_protocol::ThreadHistoryBuilder;
|
||||
@@ -32,6 +33,8 @@ pub(crate) struct PendingThreadResumeRequest {
|
||||
pub(crate) thread_summary: codex_app_server_protocol::Thread,
|
||||
pub(crate) emit_thread_goal_update: bool,
|
||||
pub(crate) thread_goal_state_db: Option<StateDbHandle>,
|
||||
pub(crate) emit_thread_queue_update: bool,
|
||||
pub(crate) thread_queue_state_db: Option<StateDbHandle>,
|
||||
pub(crate) include_turns: bool,
|
||||
}
|
||||
|
||||
@@ -49,6 +52,14 @@ pub(crate) enum ThreadListenerCommand {
|
||||
EmitThreadGoalSnapshot {
|
||||
state_db: StateDbHandle,
|
||||
},
|
||||
// EmitThreadQueueChanged is used to order app-server queue updates with running-thread resume responses.
|
||||
EmitThreadQueueChanged {
|
||||
queued_turns: Vec<QueuedTurn>,
|
||||
},
|
||||
// EmitThreadQueueSnapshot is used to read and emit the latest queue state in listener order.
|
||||
EmitThreadQueueSnapshot {
|
||||
state_db: StateDbHandle,
|
||||
},
|
||||
// ResolveServerRequest is used to notify the client that the request has been resolved.
|
||||
// It is executed in the thread listener's context to ensure that the resolved notification is ordered with regard to the request itself.
|
||||
ResolveServerRequest {
|
||||
|
||||
@@ -52,6 +52,7 @@ mod thread_loaded_list;
|
||||
mod thread_memory_mode_set;
|
||||
mod thread_metadata_update;
|
||||
mod thread_name_websocket;
|
||||
mod thread_queue;
|
||||
mod thread_read;
|
||||
mod thread_resume;
|
||||
mod thread_rollback;
|
||||
|
||||
472
codex-rs/app-server/tests/suite/v2/thread_queue.rs
Normal file
472
codex-rs/app-server/tests/suite/v2/thread_queue.rs
Normal file
@@ -0,0 +1,472 @@
|
||||
use anyhow::Result;
|
||||
use app_test_support::McpProcess;
|
||||
use app_test_support::create_final_assistant_message_sse_response;
|
||||
use app_test_support::create_mock_responses_server_sequence_unchecked;
|
||||
use app_test_support::create_shell_command_sse_response;
|
||||
use app_test_support::to_response;
|
||||
use codex_app_server_protocol::ItemStartedNotification;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::ThreadItem;
|
||||
use codex_app_server_protocol::ThreadQueueAddResponse;
|
||||
use codex_app_server_protocol::ThreadQueueDeleteResponse;
|
||||
use codex_app_server_protocol::ThreadQueueListResponse;
|
||||
use codex_app_server_protocol::ThreadQueueReorderResponse;
|
||||
use codex_app_server_protocol::ThreadResumeParams;
|
||||
use codex_app_server_protocol::ThreadResumeResponse;
|
||||
use codex_app_server_protocol::ThreadStartParams;
|
||||
use codex_app_server_protocol::ThreadStartResponse;
|
||||
use codex_app_server_protocol::TurnStartParams;
|
||||
use codex_app_server_protocol::TurnStartResponse;
|
||||
use codex_app_server_protocol::UserInput;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::timeout;
|
||||
|
||||
#[cfg(windows)]
|
||||
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(25);
|
||||
#[cfg(not(windows))]
|
||||
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_queue_supports_add_list_reorder_and_delete() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(vec![
|
||||
create_final_assistant_message_sse_response("materialized")?,
|
||||
create_shell_command_sse_response(
|
||||
sleep_command(/*seconds*/ 10),
|
||||
/*workdir*/ None,
|
||||
Some(10_000),
|
||||
"keep-open",
|
||||
)?,
|
||||
])
|
||||
.await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let thread = start_materialized_thread(&mut mcp).await?;
|
||||
let blocking_turn = start_blocking_turn(&mut mcp, thread.id.as_str()).await?;
|
||||
|
||||
let first = add_queued_turn(&mut mcp, thread.id.as_str(), "first").await?;
|
||||
let second = add_queued_turn(&mut mcp, thread.id.as_str(), "second").await?;
|
||||
|
||||
let list_id = mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/list",
|
||||
Some(json!({
|
||||
"threadId": thread.id,
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let list_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(list_id)),
|
||||
)
|
||||
.await??;
|
||||
let list: ThreadQueueListResponse = to_response(list_resp)?;
|
||||
assert_eq!(
|
||||
list.queued_turns
|
||||
.iter()
|
||||
.map(|turn| turn.id.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
vec![
|
||||
first.queued_turn.id.as_str(),
|
||||
second.queued_turn.id.as_str()
|
||||
]
|
||||
);
|
||||
|
||||
let reorder_id = mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/reorder",
|
||||
Some(json!({
|
||||
"threadId": thread.id,
|
||||
"queuedTurnIds": [
|
||||
second.queued_turn.id,
|
||||
first.queued_turn.id,
|
||||
],
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let reorder_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(reorder_id)),
|
||||
)
|
||||
.await??;
|
||||
let reordered: ThreadQueueReorderResponse = to_response(reorder_resp)?;
|
||||
assert_eq!(
|
||||
reordered
|
||||
.queued_turns
|
||||
.iter()
|
||||
.map(|turn| turn.id.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
vec![
|
||||
second.queued_turn.id.as_str(),
|
||||
first.queued_turn.id.as_str()
|
||||
]
|
||||
);
|
||||
|
||||
let delete_id = mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/delete",
|
||||
Some(json!({
|
||||
"threadId": thread.id,
|
||||
"queuedTurnId": second.queued_turn.id,
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let delete_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(delete_id)),
|
||||
)
|
||||
.await??;
|
||||
let deleted: ThreadQueueDeleteResponse = to_response(delete_resp)?;
|
||||
assert!(deleted.deleted);
|
||||
|
||||
mcp.interrupt_turn_and_wait_for_aborted(thread.id, blocking_turn.id, DEFAULT_READ_TIMEOUT)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_queue_drains_after_the_next_terminal_turn() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(vec![
|
||||
create_final_assistant_message_sse_response("materialized")?,
|
||||
create_shell_command_sse_response(
|
||||
sleep_command(/*seconds*/ 1),
|
||||
/*workdir*/ None,
|
||||
Some(10_000),
|
||||
"call1",
|
||||
)?,
|
||||
create_final_assistant_message_sse_response("manual")?,
|
||||
create_final_assistant_message_sse_response("queued")?,
|
||||
])
|
||||
.await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let thread = start_materialized_thread(&mut mcp).await?;
|
||||
start_blocking_turn(&mut mcp, thread.id.as_str()).await?;
|
||||
add_queued_turn(&mut mcp, thread.id.as_str(), "queued").await?;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/started"),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let list_id = mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/list",
|
||||
Some(json!({
|
||||
"threadId": thread.id,
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let list_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(list_id)),
|
||||
)
|
||||
.await??;
|
||||
let list: ThreadQueueListResponse = to_response(list_resp)?;
|
||||
assert!(list.queued_turns.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_queue_add_drains_immediately_when_the_thread_is_idle() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(vec![
|
||||
create_final_assistant_message_sse_response("materialized")?,
|
||||
create_final_assistant_message_sse_response("queued")?,
|
||||
])
|
||||
.await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let thread = start_materialized_thread(&mut mcp).await?;
|
||||
add_queued_turn(&mut mcp, thread.id.as_str(), "queued").await?;
|
||||
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/started"),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let list_id = mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/list",
|
||||
Some(json!({
|
||||
"threadId": thread.id,
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let list_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(list_id)),
|
||||
)
|
||||
.await??;
|
||||
let list: ThreadQueueListResponse = to_response(list_resp)?;
|
||||
assert!(list.queued_turns.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_queue_drains_after_restart_and_resume() -> Result<()> {
|
||||
let server = create_mock_responses_server_sequence_unchecked(vec![
|
||||
create_final_assistant_message_sse_response("materialized")?,
|
||||
create_shell_command_sse_response(
|
||||
sleep_command(/*seconds*/ 10),
|
||||
/*workdir*/ None,
|
||||
Some(10_000),
|
||||
"keep-open",
|
||||
)?,
|
||||
create_final_assistant_message_sse_response("queued")?,
|
||||
])
|
||||
.await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
|
||||
let mut first_mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, first_mcp.initialize()).await??;
|
||||
let thread = start_materialized_thread(&mut first_mcp).await?;
|
||||
start_blocking_turn(&mut first_mcp, thread.id.as_str()).await?;
|
||||
add_queued_turn(&mut first_mcp, thread.id.as_str(), "queued").await?;
|
||||
drop(first_mcp);
|
||||
|
||||
let mut second_mcp = McpProcess::new(codex_home.path()).await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, second_mcp.initialize()).await??;
|
||||
let resume_id = second_mcp
|
||||
.send_thread_resume_request(ThreadResumeParams {
|
||||
thread_id: thread.id.clone(),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let resume_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
second_mcp.read_stream_until_response_message(RequestId::Integer(resume_id)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadResumeResponse {
|
||||
thread: resumed, ..
|
||||
} = to_response(resume_resp)?;
|
||||
assert_eq!(resumed.id, thread.id);
|
||||
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
second_mcp.read_stream_until_notification_message("thread/queue/changed"),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
second_mcp.read_stream_until_notification_message("turn/started"),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
second_mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let list_id = second_mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/list",
|
||||
Some(json!({
|
||||
"threadId": thread.id,
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let list_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
second_mcp.read_stream_until_response_message(RequestId::Integer(list_id)),
|
||||
)
|
||||
.await??;
|
||||
let list: ThreadQueueListResponse = to_response(list_resp)?;
|
||||
assert!(list.queued_turns.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn start_materialized_thread(
|
||||
mcp: &mut McpProcess,
|
||||
) -> Result<codex_app_server_protocol::Thread> {
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let start_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(start_id)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(start_resp)?;
|
||||
|
||||
let turn_id = mcp
|
||||
.send_turn_start_request(turn_start_params(thread.id.as_str(), "materialize"))
|
||||
.await?;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(turn_id)),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/started"),
|
||||
)
|
||||
.await??;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/completed"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
Ok(thread)
|
||||
}
|
||||
|
||||
async fn add_queued_turn(
|
||||
mcp: &mut McpProcess,
|
||||
thread_id: &str,
|
||||
text: &str,
|
||||
) -> Result<ThreadQueueAddResponse> {
|
||||
let add_id = mcp
|
||||
.send_raw_request(
|
||||
"thread/queue/add",
|
||||
Some(json!({
|
||||
"threadId": thread_id,
|
||||
"turnStartParams": queued_turn_start_params(thread_id, text),
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
let add_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(add_id)),
|
||||
)
|
||||
.await??;
|
||||
to_response(add_resp)
|
||||
}
|
||||
|
||||
async fn start_blocking_turn(
|
||||
mcp: &mut McpProcess,
|
||||
thread_id: &str,
|
||||
) -> Result<codex_app_server_protocol::Turn> {
|
||||
let turn_id = mcp
|
||||
.send_turn_start_request(turn_start_params(thread_id, "manual"))
|
||||
.await?;
|
||||
let turn_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(turn_id)),
|
||||
)
|
||||
.await??;
|
||||
let TurnStartResponse { turn } = to_response(turn_resp)?;
|
||||
timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("turn/started"),
|
||||
)
|
||||
.await??;
|
||||
wait_for_command_execution_started(mcp).await?;
|
||||
Ok(turn)
|
||||
}
|
||||
|
||||
async fn wait_for_command_execution_started(mcp: &mut McpProcess) -> Result<()> {
|
||||
loop {
|
||||
let notif = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("item/started"),
|
||||
)
|
||||
.await??;
|
||||
let started: ItemStartedNotification = serde_json::from_value(
|
||||
notif
|
||||
.params
|
||||
.ok_or_else(|| anyhow::anyhow!("missing item/started params"))?,
|
||||
)?;
|
||||
if matches!(started.item, ThreadItem::CommandExecution { .. }) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sleep_command(seconds: u64) -> Vec<String> {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
vec![
|
||||
"powershell".to_string(),
|
||||
"-Command".to_string(),
|
||||
format!("Start-Sleep -Seconds {seconds}"),
|
||||
]
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
vec!["sleep".to_string(), seconds.to_string()]
|
||||
}
|
||||
}
|
||||
|
||||
fn queued_turn_start_params(thread_id: &str, text: &str) -> TurnStartParams {
|
||||
TurnStartParams {
|
||||
thread_id: thread_id.to_string(),
|
||||
input: vec![UserInput::Text {
|
||||
text: text.to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn turn_start_params(thread_id: &str, text: &str) -> TurnStartParams {
|
||||
TurnStartParams {
|
||||
thread_id: thread_id.to_string(),
|
||||
input: vec![UserInput::Text {
|
||||
text: text.to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn create_config_toml(codex_home: &std::path::Path, server_uri: &str) -> std::io::Result<()> {
|
||||
let config_toml = codex_home.join("config.toml");
|
||||
std::fs::write(
|
||||
config_toml,
|
||||
format!(
|
||||
r#"
|
||||
model = "gpt-5.3-codex"
|
||||
approval_policy = "never"
|
||||
sandbox_mode = "read-only"
|
||||
|
||||
model_provider = "mock_provider"
|
||||
|
||||
[features]
|
||||
personality = true
|
||||
|
||||
[model_providers.mock_provider]
|
||||
name = "Mock provider for test"
|
||||
base_url = "{server_uri}/v1"
|
||||
wire_api = "responses"
|
||||
request_max_retries = 0
|
||||
stream_max_retries = 0
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
7
codex-rs/state/migrations/0032_thread_queued_turns.sql
Normal file
7
codex-rs/state/migrations/0032_thread_queued_turns.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE thread_queued_turns (
|
||||
queued_turn_id TEXT PRIMARY KEY NOT NULL,
|
||||
thread_id TEXT NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
|
||||
turn_start_params_json TEXT NOT NULL,
|
||||
queue_order INTEGER NOT NULL,
|
||||
UNIQUE(thread_id, queue_order)
|
||||
);
|
||||
@@ -46,6 +46,7 @@ pub use model::ThreadGoal;
|
||||
pub use model::ThreadGoalStatus;
|
||||
pub use model::ThreadMetadata;
|
||||
pub use model::ThreadMetadataBuilder;
|
||||
pub use model::ThreadQueuedTurn;
|
||||
pub use model::ThreadsPage;
|
||||
pub use runtime::RemoteControlEnrollmentRecord;
|
||||
pub use runtime::ThreadFilterOptions;
|
||||
|
||||
@@ -5,6 +5,7 @@ mod log;
|
||||
mod memories;
|
||||
mod thread_goal;
|
||||
mod thread_metadata;
|
||||
mod thread_queued_turn;
|
||||
|
||||
pub use agent_job::AgentJob;
|
||||
pub use agent_job::AgentJobCreateParams;
|
||||
@@ -34,6 +35,7 @@ pub use thread_metadata::SortKey;
|
||||
pub use thread_metadata::ThreadMetadata;
|
||||
pub use thread_metadata::ThreadMetadataBuilder;
|
||||
pub use thread_metadata::ThreadsPage;
|
||||
pub use thread_queued_turn::ThreadQueuedTurn;
|
||||
|
||||
pub(crate) use agent_job::AgentJobItemRow;
|
||||
pub(crate) use agent_job::AgentJobRow;
|
||||
@@ -44,3 +46,4 @@ pub(crate) use thread_metadata::anchor_from_item;
|
||||
pub(crate) use thread_metadata::datetime_to_epoch_millis;
|
||||
pub(crate) use thread_metadata::datetime_to_epoch_seconds;
|
||||
pub(crate) use thread_metadata::epoch_millis_to_datetime;
|
||||
pub(crate) use thread_queued_turn::ThreadQueuedTurnRow;
|
||||
|
||||
43
codex-rs/state/src/model/thread_queued_turn.rs
Normal file
43
codex-rs/state/src/model/thread_queued_turn.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use anyhow::Result;
|
||||
use codex_protocol::ThreadId;
|
||||
use sqlx::Row;
|
||||
use sqlx::sqlite::SqliteRow;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ThreadQueuedTurn {
|
||||
pub queued_turn_id: String,
|
||||
pub thread_id: ThreadId,
|
||||
pub turn_start_params_json: String,
|
||||
pub queue_order: i64,
|
||||
}
|
||||
|
||||
pub(crate) struct ThreadQueuedTurnRow {
|
||||
pub queued_turn_id: String,
|
||||
pub thread_id: String,
|
||||
pub turn_start_params_json: String,
|
||||
pub queue_order: i64,
|
||||
}
|
||||
|
||||
impl ThreadQueuedTurnRow {
|
||||
pub(crate) fn try_from_row(row: &SqliteRow) -> Result<Self> {
|
||||
Ok(Self {
|
||||
queued_turn_id: row.try_get("queued_turn_id")?,
|
||||
thread_id: row.try_get("thread_id")?,
|
||||
turn_start_params_json: row.try_get("turn_start_params_json")?,
|
||||
queue_order: row.try_get("queue_order")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ThreadQueuedTurnRow> for ThreadQueuedTurn {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(row: ThreadQueuedTurnRow) -> Result<Self> {
|
||||
Ok(Self {
|
||||
queued_turn_id: row.queued_turn_id,
|
||||
thread_id: ThreadId::try_from(row.thread_id)?,
|
||||
turn_start_params_json: row.turn_start_params_json,
|
||||
queue_order: row.queue_order,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,7 @@ mod backfill;
|
||||
mod goals;
|
||||
mod logs;
|
||||
mod memories;
|
||||
mod queued_turns;
|
||||
mod remote_control;
|
||||
#[cfg(test)]
|
||||
mod test_support;
|
||||
|
||||
278
codex-rs/state/src/runtime/queued_turns.rs
Normal file
278
codex-rs/state/src/runtime/queued_turns.rs
Normal file
@@ -0,0 +1,278 @@
|
||||
use super::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
impl StateRuntime {
|
||||
pub async fn list_thread_queued_turns(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
) -> anyhow::Result<Vec<crate::ThreadQueuedTurn>> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
queued_turn_id,
|
||||
thread_id,
|
||||
turn_start_params_json,
|
||||
queue_order
|
||||
FROM thread_queued_turns
|
||||
WHERE thread_id = ?
|
||||
ORDER BY queue_order ASC
|
||||
"#,
|
||||
)
|
||||
.bind(thread_id.to_string())
|
||||
.fetch_all(self.pool.as_ref())
|
||||
.await?;
|
||||
|
||||
rows.iter().map(thread_queued_turn_from_row).collect()
|
||||
}
|
||||
|
||||
pub async fn append_thread_queued_turn(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
turn_start_params_json: String,
|
||||
) -> anyhow::Result<crate::ThreadQueuedTurn> {
|
||||
let queued_turn_id = Uuid::new_v4().to_string();
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO thread_queued_turns (
|
||||
queued_turn_id,
|
||||
thread_id,
|
||||
turn_start_params_json,
|
||||
queue_order
|
||||
)
|
||||
VALUES (
|
||||
?,
|
||||
?,
|
||||
?,
|
||||
COALESCE((SELECT MAX(queue_order) + 1 FROM thread_queued_turns WHERE thread_id = ?), 0)
|
||||
)
|
||||
RETURNING
|
||||
queued_turn_id,
|
||||
thread_id,
|
||||
turn_start_params_json,
|
||||
queue_order
|
||||
"#,
|
||||
)
|
||||
.bind(queued_turn_id)
|
||||
.bind(thread_id.to_string())
|
||||
.bind(turn_start_params_json)
|
||||
.bind(thread_id.to_string())
|
||||
.fetch_one(self.pool.as_ref())
|
||||
.await?;
|
||||
|
||||
thread_queued_turn_from_row(&row)
|
||||
}
|
||||
|
||||
pub async fn delete_thread_queued_turn(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
queued_turn_id: &str,
|
||||
) -> anyhow::Result<bool> {
|
||||
Ok(sqlx::query(
|
||||
r#"
|
||||
DELETE FROM thread_queued_turns
|
||||
WHERE thread_id = ? AND queued_turn_id = ?
|
||||
"#,
|
||||
)
|
||||
.bind(thread_id.to_string())
|
||||
.bind(queued_turn_id)
|
||||
.execute(self.pool.as_ref())
|
||||
.await?
|
||||
.rows_affected()
|
||||
> 0)
|
||||
}
|
||||
|
||||
pub async fn reorder_thread_queued_turns(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
ordered_queued_turn_ids: &[String],
|
||||
) -> anyhow::Result<()> {
|
||||
let current = self.list_thread_queued_turns(thread_id).await?;
|
||||
let current_ids = current
|
||||
.iter()
|
||||
.map(|turn| turn.queued_turn_id.as_str())
|
||||
.collect::<std::collections::BTreeSet<_>>();
|
||||
let next_ids = ordered_queued_turn_ids
|
||||
.iter()
|
||||
.map(String::as_str)
|
||||
.collect::<std::collections::BTreeSet<_>>();
|
||||
if current.len() != ordered_queued_turn_ids.len() || current_ids != next_ids {
|
||||
anyhow::bail!("queued turn reorder ids must match the current queue");
|
||||
}
|
||||
|
||||
let mut tx = self.pool.begin().await?;
|
||||
for (queue_order, queued_turn_id) in ordered_queued_turn_ids.iter().enumerate() {
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE thread_queued_turns
|
||||
SET queue_order = ?
|
||||
WHERE thread_id = ? AND queued_turn_id = ?
|
||||
"#,
|
||||
)
|
||||
.bind(-(queue_order as i64) - 1)
|
||||
.bind(thread_id.to_string())
|
||||
.bind(queued_turn_id)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
}
|
||||
for (queue_order, queued_turn_id) in ordered_queued_turn_ids.iter().enumerate() {
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE thread_queued_turns
|
||||
SET queue_order = ?
|
||||
WHERE thread_id = ? AND queued_turn_id = ?
|
||||
"#,
|
||||
)
|
||||
.bind(queue_order as i64)
|
||||
.bind(thread_id.to_string())
|
||||
.bind(queued_turn_id)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
}
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn first_thread_queued_turn(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
) -> anyhow::Result<Option<crate::ThreadQueuedTurn>> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
queued_turn_id,
|
||||
thread_id,
|
||||
turn_start_params_json,
|
||||
queue_order
|
||||
FROM thread_queued_turns
|
||||
WHERE thread_id = ?
|
||||
ORDER BY queue_order ASC
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(thread_id.to_string())
|
||||
.fetch_optional(self.pool.as_ref())
|
||||
.await?;
|
||||
|
||||
row.map(|row| thread_queued_turn_from_row(&row)).transpose()
|
||||
}
|
||||
}
|
||||
|
||||
fn thread_queued_turn_from_row(
|
||||
row: &sqlx::sqlite::SqliteRow,
|
||||
) -> anyhow::Result<crate::ThreadQueuedTurn> {
|
||||
crate::model::ThreadQueuedTurnRow::try_from_row(row)?.try_into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::test_support::test_thread_metadata;
|
||||
use super::super::test_support::unique_temp_dir;
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[tokio::test]
|
||||
async fn append_list_reorder_and_delete_thread_queued_turns() {
|
||||
let codex_home = unique_temp_dir();
|
||||
let runtime = StateRuntime::init(codex_home.clone(), "mock".to_string())
|
||||
.await
|
||||
.expect("state db should initialize");
|
||||
let thread_id = ThreadId::new();
|
||||
let metadata = test_thread_metadata(&codex_home, thread_id, codex_home.clone());
|
||||
runtime
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
.expect("thread metadata insert should succeed");
|
||||
|
||||
let first = runtime
|
||||
.append_thread_queued_turn(thread_id, "{\"first\":true}".to_string())
|
||||
.await
|
||||
.expect("first queued turn insert should succeed");
|
||||
let second = runtime
|
||||
.append_thread_queued_turn(thread_id, "{\"second\":true}".to_string())
|
||||
.await
|
||||
.expect("second queued turn insert should succeed");
|
||||
assert_eq!(
|
||||
runtime
|
||||
.list_thread_queued_turns(thread_id)
|
||||
.await
|
||||
.expect("queued turn list should succeed"),
|
||||
vec![first.clone(), second.clone()]
|
||||
);
|
||||
|
||||
runtime
|
||||
.reorder_thread_queued_turns(
|
||||
thread_id,
|
||||
&[second.queued_turn_id.clone(), first.queued_turn_id.clone()],
|
||||
)
|
||||
.await
|
||||
.expect("queued turn reorder should succeed");
|
||||
assert_eq!(
|
||||
runtime
|
||||
.list_thread_queued_turns(thread_id)
|
||||
.await
|
||||
.expect("queued turn list should succeed")
|
||||
.into_iter()
|
||||
.map(|turn| turn.queued_turn_id)
|
||||
.collect::<Vec<_>>(),
|
||||
vec![second.queued_turn_id.clone(), first.queued_turn_id.clone()]
|
||||
);
|
||||
|
||||
assert!(
|
||||
runtime
|
||||
.reorder_thread_queued_turns(
|
||||
thread_id,
|
||||
&[second.queued_turn_id.clone(), second.queued_turn_id.clone()],
|
||||
)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
|
||||
assert!(
|
||||
runtime
|
||||
.delete_thread_queued_turn(thread_id, second.queued_turn_id.as_str())
|
||||
.await
|
||||
.expect("queued turn delete should succeed")
|
||||
);
|
||||
assert_eq!(
|
||||
runtime
|
||||
.list_thread_queued_turns(thread_id)
|
||||
.await
|
||||
.expect("queued turn list should succeed")
|
||||
.into_iter()
|
||||
.map(|turn| turn.queued_turn_id)
|
||||
.collect::<Vec<_>>(),
|
||||
vec![first.queued_turn_id]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn first_thread_queued_turn_reads_the_head() {
|
||||
let codex_home = unique_temp_dir();
|
||||
let runtime = StateRuntime::init(codex_home.clone(), "mock".to_string())
|
||||
.await
|
||||
.expect("state db should initialize");
|
||||
let thread_id = ThreadId::new();
|
||||
let metadata = test_thread_metadata(&codex_home, thread_id, codex_home.clone());
|
||||
runtime
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
.expect("thread metadata insert should succeed");
|
||||
let queued_turn = runtime
|
||||
.append_thread_queued_turn(thread_id, "{}".to_string())
|
||||
.await
|
||||
.expect("queued turn insert should succeed");
|
||||
runtime
|
||||
.append_thread_queued_turn(thread_id, "{\"later\":true}".to_string())
|
||||
.await
|
||||
.expect("later queued turn insert should succeed");
|
||||
|
||||
assert_eq!(
|
||||
runtime
|
||||
.first_thread_queued_turn(thread_id)
|
||||
.await
|
||||
.expect("queued turn read should succeed")
|
||||
.map(|turn| turn.queued_turn_id),
|
||||
Some(queued_turn.queued_turn_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,9 @@ pub(super) fn server_notification_thread_target(
|
||||
ServerNotification::ThreadGoalCleared(notification) => {
|
||||
Some(notification.thread_id.as_str())
|
||||
}
|
||||
ServerNotification::ThreadQueueChanged(notification) => {
|
||||
Some(notification.thread_id.as_str())
|
||||
}
|
||||
ServerNotification::TurnStarted(notification) => Some(notification.thread_id.as_str()),
|
||||
ServerNotification::HookStarted(notification) => Some(notification.thread_id.as_str()),
|
||||
ServerNotification::TurnCompleted(notification) => Some(notification.thread_id.as_str()),
|
||||
|
||||
@@ -6430,6 +6430,7 @@ impl ChatWidget {
|
||||
| ServerNotification::ThreadStatusChanged(_)
|
||||
| ServerNotification::ThreadArchived(_)
|
||||
| ServerNotification::ThreadUnarchived(_)
|
||||
| ServerNotification::ThreadQueueChanged(_)
|
||||
| ServerNotification::RawResponseItemCompleted(_)
|
||||
| ServerNotification::CommandExecOutputDelta(_)
|
||||
| ServerNotification::ProcessOutputDelta(_)
|
||||
|
||||
Reference in New Issue
Block a user