Compare commits

..

1 Commits

Author SHA1 Message Date
Michael Bolin
37133fb845 ## New Features
- Releases now ship one-step installers for macOS, Linux, and Windows, so Codex can be installed directly from published scripts instead of relying on npm-first setup. (#12740, #12741)
- Plugins can now be enabled from `config.toml`, and plugin bundles can contribute skills, MCP config, and app manifests that load automatically at runtime. (#12864, #13401)
- Memories gained more user control: Codex can forget or hard-clear stored memories, skip polluted captures, and optionally write memory files into the workspace. (#12900, #13008, #13085, #13467)
- Multi-agent work is easier in the TUI: you can launch it from `/agent`, review cross-agent approvals, get clearer agent names, and receive plan-mode or user-input notifications. (#12995, #13218, #13246, #13495)
- Realtime voice sessions now have an `/audio` picker for microphone and speaker selection, with device choices stored across sessions. (#12849, #12850, #13030)
- Sandboxing is more flexible: Linux bubblewrap now supports restricted read-only scopes, and read-only policies can preserve network access when explicitly allowed. (#12369, #13409)

## Bug Fixes
- `@` file search now follows Git’s ignore boundaries, so a parent `.gitignore` outside the repo no longer hides valid project files. (#13250)
- Diff and syntax highlighting now respect terminal and theme capabilities more reliably, fixing washed-out Windows Terminal diffs and broken ANSI-family syntax themes. (#13016, #13037, #13382)
- `/agent` flows are more stable: pending messages, status display, Escape handling, profile interactions, and several race conditions were fixed. (#13130, #13131, #13235, #13240, #13248)
- Command-line project trust overrides now correctly update project-local MCP transports instead of being dropped during config parsing. (#13090)

## Chores
- The deprecated app-server v1 surface was further removed in favor of v2, and a flat v2 schema bundle is now exported to simplify client code generation. (#13324, #13364, #13375)

## Changelog

Full Changelog: https://github.com/openai/codex/compare/rust-v0.108.0...rust-v0.109.0
2026-03-04 15:13:23 -08:00
316 changed files with 28195 additions and 23245 deletions

View File

@@ -47,7 +47,7 @@ jobs:
echo "pack_output=$PACK_OUTPUT" >> "$GITHUB_OUTPUT"
- name: Upload staged npm package artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: codex-npm-staging
path: ${{ steps.stage_npm_package.outputs.pack_output }}

View File

@@ -392,7 +392,7 @@ jobs:
- name: Upload Cargo timings (clippy)
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: cargo-timings-rust-ci-clippy-${{ matrix.target }}-${{ matrix.profile }}
path: codex-rs/target/**/cargo-timings/cargo-timing.html
@@ -605,7 +605,7 @@ jobs:
- name: Upload Cargo timings (nextest)
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: cargo-timings-rust-ci-nextest-${{ matrix.target }}-${{ matrix.profile }}
path: codex-rs/target/**/cargo-timings/cargo-timing.html

View File

@@ -92,7 +92,7 @@ jobs:
cargo build --target ${{ matrix.target }} --release --timings ${{ matrix.build_args }}
- name: Upload Cargo timings
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: cargo-timings-rust-release-windows-${{ matrix.target }}-${{ matrix.bundle }}
path: codex-rs/target/**/cargo-timings/cargo-timing.html
@@ -112,7 +112,7 @@ jobs:
fi
- name: Upload Windows binaries
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: windows-binaries-${{ matrix.target }}-${{ matrix.bundle }}
path: |
@@ -150,13 +150,13 @@ jobs:
- uses: actions/checkout@v6
- name: Download prebuilt Windows primary binaries
uses: actions/download-artifact@v8
uses: actions/download-artifact@v7
with:
name: windows-binaries-${{ matrix.target }}-primary
path: codex-rs/target/${{ matrix.target }}/release
- name: Download prebuilt Windows helper binaries
uses: actions/download-artifact@v8
uses: actions/download-artifact@v7
with:
name: windows-binaries-${{ matrix.target }}-helpers
path: codex-rs/target/${{ matrix.target }}/release
@@ -257,7 +257,7 @@ jobs:
"${GITHUB_WORKSPACE}/.github/workflows/zstd" -T0 -19 "$dest/$base"
done
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: ${{ matrix.target }}
path: |

View File

@@ -57,9 +57,7 @@ jobs:
run:
working-directory: codex-rs
env:
# 2026-03-04: temporarily change releases to use thin LTO because
# Ubuntu ARM is timing out at 60 minutes.
CARGO_PROFILE_RELEASE_LTO: ${{ contains(github.ref_name, '-alpha') && 'thin' || 'thin' }}
CARGO_PROFILE_RELEASE_LTO: ${{ contains(github.ref_name, '-alpha') && 'thin' || 'fat' }}
strategy:
fail-fast: false
@@ -213,11 +211,10 @@ jobs:
- name: Cargo build
shell: bash
run: |
echo "CARGO_PROFILE_RELEASE_LTO: ${CARGO_PROFILE_RELEASE_LTO}"
cargo build --target ${{ matrix.target }} --release --timings --bin codex --bin codex-responses-api-proxy
- name: Upload Cargo timings
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v6
with:
name: cargo-timings-rust-release-${{ matrix.target }}
path: codex-rs/target/**/cargo-timings/cargo-timing.html
@@ -356,7 +353,7 @@ jobs:
zstd -T0 -19 --rm "$dest/$base"
done
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: ${{ matrix.target }}
# Upload the per-binary .zst files as well as the new .tar.gz
@@ -420,7 +417,7 @@ jobs:
echo "path=${notes_path}" >> "${GITHUB_OUTPUT}"
- uses: actions/download-artifact@v8
- uses: actions/download-artifact@v7
with:
path: dist

View File

@@ -158,7 +158,7 @@ jobs:
mkdir -p "$dest"
cp bash "$dest/bash"
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: shell-tool-mcp-bash-${{ matrix.target }}-${{ matrix.variant }}
path: artifacts/**
@@ -199,7 +199,7 @@ jobs:
mkdir -p "$dest"
cp bash "$dest/bash"
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: shell-tool-mcp-bash-${{ matrix.target }}-${{ matrix.variant }}
path: artifacts/**
@@ -325,7 +325,7 @@ jobs:
grep -Fx "smoke-zsh" "$tmpdir/stdout.txt"
grep -Fx "/bin/echo" "$tmpdir/wrapper.log"
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: shell-tool-mcp-zsh-${{ matrix.target }}-${{ matrix.variant }}
path: artifacts/**
@@ -403,7 +403,7 @@ jobs:
grep -Fx "smoke-zsh" "$tmpdir/stdout.txt"
grep -Fx "/bin/echo" "$tmpdir/wrapper.log"
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: shell-tool-mcp-zsh-${{ matrix.target }}-${{ matrix.variant }}
path: artifacts/**
@@ -441,7 +441,7 @@ jobs:
run: pnpm --filter @openai/codex-shell-tool-mcp run build
- name: Download build artifacts
uses: actions/download-artifact@v8
uses: actions/download-artifact@v7
with:
path: artifacts
@@ -500,7 +500,7 @@ jobs:
filename=$(PACK_INFO="$pack_info" node -e 'const data = JSON.parse(process.env.PACK_INFO); console.log(data[0].filename);')
mv "dist/npm/${filename}" "dist/npm/codex-shell-tool-mcp-npm-${PACKAGE_VERSION}.tgz"
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v6
with:
name: codex-shell-tool-mcp-npm
path: dist/npm/codex-shell-tool-mcp-npm-${{ env.PACKAGE_VERSION }}.tgz
@@ -529,7 +529,7 @@ jobs:
run: npm install -g npm@latest
- name: Download npm tarball
uses: actions/download-artifact@v8
uses: actions/download-artifact@v7
with:
name: codex-shell-tool-mcp-npm
path: dist/npm

50
MODULE.bazel.lock generated

File diff suppressed because one or more lines are too long

729
codex-rs/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,8 @@ members = [
"mcp-server",
"network-proxy",
"ollama",
"artifact-presentation",
"artifact-spreadsheet",
"process-hardening",
"protocol",
"rmcp-client",
@@ -64,13 +66,11 @@ members = [
"state",
"codex-experimental-api-macros",
"test-macros",
"package-manager",
"artifacts",
]
resolver = "2"
[workspace.package]
version = "0.0.0"
version = "0.109.0"
# Track the edition for all workspace crates in one place. Individual
# crates can still override this value, but keeping it here means new
# crates created with `cargo new -w ...` automatically inherit the 2024
@@ -83,8 +83,6 @@ license = "Apache-2.0"
app_test_support = { path = "app-server/tests/common" }
codex-ansi-escape = { path = "ansi-escape" }
codex-api = { path = "codex-api" }
codex-artifacts = { path = "artifacts" }
codex-package-manager = { path = "package-manager" }
codex-app-server = { path = "app-server" }
codex-app-server-protocol = { path = "app-server-protocol" }
codex-app-server-test-client = { path = "app-server-test-client" }
@@ -113,6 +111,8 @@ codex-mcp-server = { path = "mcp-server" }
codex-network-proxy = { path = "network-proxy" }
codex-ollama = { path = "ollama" }
codex-otel = { path = "otel" }
codex-artifact-presentation = { path = "artifact-presentation" }
codex-artifact-spreadsheet = { path = "artifact-spreadsheet" }
codex-process-hardening = { path = "process-hardening" }
codex-protocol = { path = "protocol" }
codex-responses-api-proxy = { path = "responses-api-proxy" }
@@ -178,11 +178,9 @@ dirs = "6"
dotenvy = "0.15.7"
dunce = "1.0.4"
encoding_rs = "0.8.35"
fd-lock = "4.0.4"
env-flags = "0.1.1"
env_logger = "0.11.9"
eventsource-stream = "0.2.3"
flate2 = "1.1.4"
futures = { version = "0.3", default-features = false }
gethostname = "1.1.0"
globset = "0.4"
@@ -221,6 +219,7 @@ owo-colors = "4.3.0"
path-absolutize = "3.1.1"
pathdiff = "0.2"
portable-pty = "0.9.0"
ppt-rs = "0.2.6"
predicates = "3"
pretty_assertions = "1.4.1"
pulldown-cmark = "0.10"
@@ -243,7 +242,7 @@ sentry = "0.46.0"
serde = "1"
serde_json = "1"
serde_path_to_error = "0.1.20"
serde_with = "3.17"
serde_with = "3.16"
serde_yaml = "0.9"
serial_test = "3.2.0"
sha1 = "0.10.6"
@@ -263,12 +262,11 @@ sqlx = { version = "0.8.6", default-features = false, features = [
] }
starlark = "0.13.0"
strum = "0.27.2"
strum_macros = "0.28.0"
strum_macros = "0.27.2"
supports-color = "3.0.2"
syntect = "5"
sys-locale = "0.3.2"
tempfile = "3.23.0"
tar = "0.4.44"
test-log = "0.2.19"
textwrap = "0.16.2"
thiserror = "2.0.17"
@@ -355,7 +353,8 @@ ignored = [
"icu_provider",
"openssl-sys",
"codex-utils-readiness",
"codex-secrets"
"codex-secrets",
"codex-artifact-spreadsheet"
]
[profile.release]

View File

@@ -24,12 +24,6 @@ serde_with = { workspace = true }
shlex = { workspace = true }
strum_macros = { workspace = true }
thiserror = { workspace = true }
rmcp = { workspace = true, default-features = false, features = [
"base64",
"macros",
"schemars",
"server",
] }
ts-rs = { workspace = true }
inventory = { workspace = true }
tracing = { workspace = true }

View File

@@ -161,38 +161,6 @@
"null"
]
},
"disableOutputCap": {
"type": "boolean"
},
"disableTimeout": {
"type": "boolean"
},
"env": {
"additionalProperties": {
"type": [
"string",
"null"
]
},
"type": [
"object",
"null"
]
},
"outputBytesCap": {
"format": "uint",
"minimum": 0.0,
"type": [
"integer",
"null"
]
},
"processId": {
"type": [
"string",
"null"
]
},
"sandboxPolicy": {
"anyOf": [
{
@@ -203,31 +171,12 @@
}
]
},
"size": {
"anyOf": [
{
"$ref": "#/definitions/CommandExecTerminalSize"
},
{
"type": "null"
}
]
},
"streamStdin": {
"type": "boolean"
},
"streamStdoutStderr": {
"type": "boolean"
},
"timeoutMs": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"tty": {
"type": "boolean"
}
},
"required": [
@@ -235,71 +184,6 @@
],
"type": "object"
},
"CommandExecResizeParams": {
"properties": {
"processId": {
"type": "string"
},
"size": {
"$ref": "#/definitions/CommandExecTerminalSize"
}
},
"required": [
"processId",
"size"
],
"type": "object"
},
"CommandExecTerminalSize": {
"properties": {
"cols": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
},
"rows": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
}
},
"required": [
"cols",
"rows"
],
"type": "object"
},
"CommandExecTerminateParams": {
"properties": {
"processId": {
"type": "string"
}
},
"required": [
"processId"
],
"type": "object"
},
"CommandExecWriteParams": {
"properties": {
"closeStdin": {
"type": "boolean"
},
"deltaBase64": {
"type": [
"string",
"null"
]
},
"processId": {
"type": "string"
}
},
"required": [
"processId"
],
"type": "object"
},
"ConfigBatchWriteParams": {
"properties": {
"edits": {
@@ -1067,36 +951,6 @@
],
"type": "string"
},
"PluginInstallParams": {
"properties": {
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"pluginName": {
"type": "string"
}
},
"required": [
"marketplacePath",
"pluginName"
],
"type": "object"
},
"PluginListParams": {
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces. When omitted, only home-scoped marketplaces are considered.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
}
},
"type": "object"
},
"ProductSurface": {
"enum": [
"chatgpt",
@@ -3010,12 +2864,6 @@
},
"WindowsSandboxSetupStartParams": {
"properties": {
"cwd": {
"type": [
"string",
"null"
]
},
"mode": {
"$ref": "#/definitions/WindowsSandboxSetupMode"
}
@@ -3389,30 +3237,6 @@
"title": "Skills/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/list"
],
"title": "Plugin/listRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginListParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/listRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -3509,30 +3333,6 @@
"title": "Skills/config/writeRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/install"
],
"title": "Plugin/installRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginInstallParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/installRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -3915,78 +3715,6 @@
"title": "Command/execRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"command/exec/write"
],
"title": "Command/exec/writeRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecWriteParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Command/exec/writeRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"command/exec/terminate"
],
"title": "Command/exec/terminateRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecTerminateParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Command/exec/terminateRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"command/exec/resize"
],
"title": "Command/exec/resizeRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecResizeParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Command/exec/resizeRequest",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -31,24 +31,38 @@
"AdditionalMacOsPermissions": {
"properties": {
"accessibility": {
"type": "boolean"
"type": [
"boolean",
"null"
]
},
"automations": {
"$ref": "#/definitions/MacOsAutomationPermission"
"anyOf": [
{
"$ref": "#/definitions/MacOsAutomationValue"
},
{
"type": "null"
}
]
},
"calendar": {
"type": "boolean"
"type": [
"boolean",
"null"
]
},
"preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
"anyOf": [
{
"$ref": "#/definitions/MacOsPreferencesValue"
},
{
"type": "null"
}
]
}
},
"required": [
"accessibility",
"automations",
"calendar",
"preferences"
],
"type": "object"
},
"AdditionalNetworkPermissions": {
@@ -286,40 +300,28 @@
}
]
},
"MacOsAutomationPermission": {
"oneOf": [
"MacOsAutomationValue": {
"anyOf": [
{
"enum": [
"none",
"all"
],
"type": "string"
"type": "boolean"
},
{
"additionalProperties": false,
"properties": {
"bundle_ids": {
"items": {
"type": "string"
},
"type": "array"
}
"items": {
"type": "string"
},
"required": [
"bundle_ids"
],
"title": "BundleIdsMacOsAutomationPermission",
"type": "object"
"type": "array"
}
]
},
"MacOsPreferencesPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
"MacOsPreferencesValue": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"NetworkApprovalContext": {
"properties": {

View File

@@ -544,56 +544,6 @@
}
]
},
"ElicitationRequest": {
"oneOf": [
{
"properties": {
"message": {
"type": "string"
},
"mode": {
"enum": [
"form"
],
"type": "string"
},
"requested_schema": true
},
"required": [
"message",
"mode",
"requested_schema"
],
"type": "object"
},
{
"properties": {
"elicitation_id": {
"type": "string"
},
"message": {
"type": "string"
},
"mode": {
"enum": [
"url"
],
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"elicitation_id",
"message",
"mode",
"url"
],
"type": "object"
}
]
},
"EventMsg": {
"description": "Response event from the agent NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.",
"oneOf": [
@@ -1437,60 +1387,6 @@
"title": "WebSearchEndEventMsg",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"type": {
"enum": [
"image_generation_begin"
],
"title": "ImageGenerationBeginEventMsgType",
"type": "string"
}
},
"required": [
"call_id",
"type"
],
"title": "ImageGenerationBeginEventMsg",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"result": {
"type": "string"
},
"revised_prompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"image_generation_end"
],
"title": "ImageGenerationEndEventMsgType",
"type": "string"
}
},
"required": [
"call_id",
"result",
"status",
"type"
],
"title": "ImageGenerationEndEventMsg",
"type": "object"
},
{
"description": "Notification that the server is about to execute a command.",
"properties": {
@@ -2013,8 +1909,8 @@
"id": {
"$ref": "#/definitions/RequestId"
},
"request": {
"$ref": "#/definitions/ElicitationRequest"
"message": {
"type": "string"
},
"server_name": {
"type": "string"
@@ -2029,7 +1925,7 @@
},
"required": [
"id",
"request",
"message",
"server_name",
"type"
],
@@ -3756,64 +3652,66 @@
],
"type": "string"
},
"MacOsAutomationPermission": {
"oneOf": [
"MacOsAutomationValue": {
"anyOf": [
{
"enum": [
"none",
"all"
],
"type": "string"
"type": "boolean"
},
{
"additionalProperties": false,
"properties": {
"bundle_ids": {
"items": {
"type": "string"
},
"type": "array"
}
"items": {
"type": "string"
},
"required": [
"bundle_ids"
],
"title": "BundleIdsMacOsAutomationPermission",
"type": "object"
"type": "array"
}
]
},
"MacOsPreferencesPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"MacOsSeatbeltProfileExtensions": {
"MacOsPermissions": {
"properties": {
"macos_accessibility": {
"type": "boolean"
"accessibility": {
"type": [
"boolean",
"null"
]
},
"macos_automation": {
"$ref": "#/definitions/MacOsAutomationPermission"
"automations": {
"anyOf": [
{
"$ref": "#/definitions/MacOsAutomationValue"
},
{
"type": "null"
}
]
},
"macos_calendar": {
"type": "boolean"
"calendar": {
"type": [
"boolean",
"null"
]
},
"macos_preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
"preferences": {
"anyOf": [
{
"$ref": "#/definitions/MacOsPreferencesValue"
},
{
"type": "null"
}
]
}
},
"required": [
"macos_accessibility",
"macos_automation",
"macos_calendar",
"macos_preferences"
],
"type": "object"
},
"MacOsPreferencesValue": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"McpAuthStatus": {
"enum": [
"unsupported",
@@ -4157,7 +4055,7 @@
"macos": {
"anyOf": [
{
"$ref": "#/definitions/MacOsSeatbeltProfileExtensions"
"$ref": "#/definitions/MacOsPermissions"
},
{
"type": "null"
@@ -6103,40 +6001,6 @@
"title": "WebSearchTurnItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revised_prompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"ImageGeneration"
],
"title": "ImageGenerationTurnItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationTurnItem",
"type": "object"
},
{
"properties": {
"id": {
@@ -7228,60 +7092,6 @@
"title": "WebSearchEndEventMsg",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"type": {
"enum": [
"image_generation_begin"
],
"title": "ImageGenerationBeginEventMsgType",
"type": "string"
}
},
"required": [
"call_id",
"type"
],
"title": "ImageGenerationBeginEventMsg",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"result": {
"type": "string"
},
"revised_prompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"image_generation_end"
],
"title": "ImageGenerationEndEventMsgType",
"type": "string"
}
},
"required": [
"call_id",
"result",
"status",
"type"
],
"title": "ImageGenerationEndEventMsg",
"type": "object"
},
{
"description": "Notification that the server is about to execute a command.",
"properties": {
@@ -7804,8 +7614,8 @@
"id": {
"$ref": "#/definitions/RequestId"
},
"request": {
"$ref": "#/definitions/ElicitationRequest"
"message": {
"type": "string"
},
"server_name": {
"type": "string"
@@ -7820,7 +7630,7 @@
},
"required": [
"id",
"request",
"message",
"server_name",
"type"
],

View File

@@ -1,72 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"oneOf": [
{
"properties": {
"message": {
"type": "string"
},
"mode": {
"enum": [
"form"
],
"type": "string"
},
"requestedSchema": true
},
"required": [
"message",
"mode",
"requestedSchema"
],
"type": "object"
},
{
"properties": {
"elicitationId": {
"type": "string"
},
"message": {
"type": "string"
},
"mode": {
"enum": [
"url"
],
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"elicitationId",
"message",
"mode",
"url"
],
"type": "object"
}
],
"properties": {
"serverName": {
"type": "string"
},
"threadId": {
"type": "string"
},
"turnId": {
"description": "Active Codex turn when this elicitation was observed, if app-server could correlate one.\n\nThis is nullable because MCP models elicitation as a standalone server-to-client request identified by the MCP server request id. It may be triggered during a turn, but turn context is app-server correlation rather than part of the protocol identity of the elicitation itself.",
"type": [
"string",
"null"
]
}
},
"required": [
"serverName",
"threadId"
],
"title": "McpServerElicitationRequestParams",
"type": "object"
}

View File

@@ -1,26 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"McpServerElicitationAction": {
"enum": [
"accept",
"decline",
"cancel"
],
"type": "string"
}
},
"properties": {
"action": {
"$ref": "#/definitions/McpServerElicitationAction"
},
"content": {
"description": "Structured user input for accepted elicitations, mirroring RMCP `CreateElicitationResult`.\n\nThis is nullable because decline/cancel responses have no content."
}
},
"required": [
"action"
],
"title": "McpServerElicitationRequestResponse",
"type": "object"
}

View File

@@ -201,13 +201,6 @@
},
"name": {
"type": "string"
},
"pluginDisplayNames": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
@@ -670,36 +663,6 @@
}
]
},
"CommandExecOutputDeltaNotification": {
"properties": {
"capReached": {
"type": "boolean"
},
"deltaBase64": {
"type": "string"
},
"processId": {
"type": "string"
},
"stream": {
"$ref": "#/definitions/CommandExecOutputStream"
}
},
"required": [
"capReached",
"deltaBase64",
"processId",
"stream"
],
"type": "object"
},
"CommandExecOutputStream": {
"enum": [
"stdout",
"stderr"
],
"type": "string"
},
"CommandExecutionOutputDeltaNotification": {
"properties": {
"delta": {
@@ -2288,40 +2251,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {
@@ -3498,26 +3427,6 @@
"title": "Item/plan/deltaNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"command/exec/outputDelta"
],
"title": "Command/exec/outputDeltaNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecOutputDeltaNotification"
}
},
"required": [
"method",
"params"
],
"title": "Command/exec/outputDeltaNotification",
"type": "object"
},
{
"properties": {
"method": {

View File

@@ -31,24 +31,38 @@
"AdditionalMacOsPermissions": {
"properties": {
"accessibility": {
"type": "boolean"
"type": [
"boolean",
"null"
]
},
"automations": {
"$ref": "#/definitions/MacOsAutomationPermission"
"anyOf": [
{
"$ref": "#/definitions/MacOsAutomationValue"
},
{
"type": "null"
}
]
},
"calendar": {
"type": "boolean"
"type": [
"boolean",
"null"
]
},
"preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
"anyOf": [
{
"$ref": "#/definitions/MacOsPreferencesValue"
},
{
"type": "null"
}
]
}
},
"required": [
"accessibility",
"automations",
"calendar",
"preferences"
],
"type": "object"
},
"AdditionalNetworkPermissions": {
@@ -615,110 +629,28 @@
],
"type": "object"
},
"MacOsAutomationPermission": {
"oneOf": [
"MacOsAutomationValue": {
"anyOf": [
{
"enum": [
"none",
"all"
],
"type": "string"
"type": "boolean"
},
{
"additionalProperties": false,
"properties": {
"bundle_ids": {
"items": {
"type": "string"
},
"type": "array"
}
"items": {
"type": "string"
},
"required": [
"bundle_ids"
],
"title": "BundleIdsMacOsAutomationPermission",
"type": "object"
"type": "array"
}
]
},
"MacOsPreferencesPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"McpServerElicitationRequestParams": {
"oneOf": [
"MacOsPreferencesValue": {
"anyOf": [
{
"properties": {
"message": {
"type": "string"
},
"mode": {
"enum": [
"form"
],
"type": "string"
},
"requestedSchema": true
},
"required": [
"message",
"mode",
"requestedSchema"
],
"type": "object"
"type": "boolean"
},
{
"properties": {
"elicitationId": {
"type": "string"
},
"message": {
"type": "string"
},
"mode": {
"enum": [
"url"
],
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"elicitationId",
"message",
"mode",
"url"
],
"type": "object"
}
],
"properties": {
"serverName": {
"type": "string"
},
"threadId": {
"type": "string"
},
"turnId": {
"description": "Active Codex turn when this elicitation was observed, if app-server could correlate one.\n\nThis is nullable because MCP models elicitation as a standalone server-to-client request identified by the MCP server request id. It may be triggered during a turn, but turn context is app-server correlation rather than part of the protocol identity of the elicitation itself.",
"type": [
"string",
"null"
]
}
},
"required": [
"serverName",
"threadId"
],
"type": "object"
]
},
"NetworkApprovalContext": {
"properties": {
@@ -1049,31 +981,6 @@
"title": "Item/tool/requestUserInputRequest",
"type": "object"
},
{
"description": "Request input for an MCP server elicitation.",
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"mcpServer/elicitation/request"
],
"title": "McpServer/elicitation/requestRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/McpServerElicitationRequestParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "McpServer/elicitation/requestRequest",
"type": "object"
},
{
"description": "Execute a dynamic tool call on the client.",
"properties": {

View File

@@ -404,13 +404,6 @@
},
"name": {
"type": "string"
},
"pluginDisplayNames": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
@@ -1211,30 +1204,6 @@
"title": "Skills/listRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/list"
],
"title": "Plugin/listRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginListParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/listRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1331,30 +1300,6 @@
"title": "Skills/config/writeRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"plugin/install"
],
"title": "Plugin/installRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/PluginInstallParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Plugin/installRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -1737,78 +1682,6 @@
"title": "Command/execRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"command/exec/write"
],
"title": "Command/exec/writeRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecWriteParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Command/exec/writeRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"command/exec/terminate"
],
"title": "Command/exec/terminateRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecTerminateParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Command/exec/terminateRequest",
"type": "object"
},
{
"properties": {
"id": {
"$ref": "#/definitions/RequestId"
},
"method": {
"enum": [
"command/exec/resize"
],
"title": "Command/exec/resizeRequestMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecResizeParams"
}
},
"required": [
"id",
"method",
"params"
],
"title": "Command/exec/resizeRequest",
"type": "object"
},
{
"properties": {
"id": {
@@ -2403,38 +2276,6 @@
}
]
},
"CommandExecOutputDeltaNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"capReached": {
"type": "boolean"
},
"deltaBase64": {
"type": "string"
},
"processId": {
"type": "string"
},
"stream": {
"$ref": "#/definitions/CommandExecOutputStream"
}
},
"required": [
"capReached",
"deltaBase64",
"processId",
"stream"
],
"title": "CommandExecOutputDeltaNotification",
"type": "object"
},
"CommandExecOutputStream": {
"enum": [
"stdout",
"stderr"
],
"type": "string"
},
"CommandExecParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -2450,38 +2291,6 @@
"null"
]
},
"disableOutputCap": {
"type": "boolean"
},
"disableTimeout": {
"type": "boolean"
},
"env": {
"additionalProperties": {
"type": [
"string",
"null"
]
},
"type": [
"object",
"null"
]
},
"outputBytesCap": {
"format": "uint",
"minimum": 0.0,
"type": [
"integer",
"null"
]
},
"processId": {
"type": [
"string",
"null"
]
},
"sandboxPolicy": {
"anyOf": [
{
@@ -2492,31 +2301,12 @@
}
]
},
"size": {
"anyOf": [
{
"$ref": "#/definitions/CommandExecTerminalSize"
},
{
"type": "null"
}
]
},
"streamStdin": {
"type": "boolean"
},
"streamStdoutStderr": {
"type": "boolean"
},
"timeoutMs": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"tty": {
"type": "boolean"
}
},
"required": [
@@ -2525,28 +2315,6 @@
"title": "CommandExecParams",
"type": "object"
},
"CommandExecResizeParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"processId": {
"type": "string"
},
"size": {
"$ref": "#/definitions/CommandExecTerminalSize"
}
},
"required": [
"processId",
"size"
],
"title": "CommandExecResizeParams",
"type": "object"
},
"CommandExecResizeResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CommandExecResizeResponse",
"type": "object"
},
"CommandExecResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -2569,70 +2337,6 @@
"title": "CommandExecResponse",
"type": "object"
},
"CommandExecTerminalSize": {
"properties": {
"cols": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
},
"rows": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
}
},
"required": [
"cols",
"rows"
],
"type": "object"
},
"CommandExecTerminateParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"processId": {
"type": "string"
}
},
"required": [
"processId"
],
"title": "CommandExecTerminateParams",
"type": "object"
},
"CommandExecTerminateResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CommandExecTerminateResponse",
"type": "object"
},
"CommandExecWriteParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"closeStdin": {
"type": "boolean"
},
"deltaBase64": {
"type": [
"string",
"null"
]
},
"processId": {
"type": "string"
}
},
"required": [
"processId"
],
"title": "CommandExecWriteParams",
"type": "object"
},
"CommandExecWriteResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CommandExecWriteResponse",
"type": "object"
},
"CommandExecutionOutputDeltaNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -3558,56 +3262,6 @@
],
"type": "object"
},
"ElicitationRequest": {
"oneOf": [
{
"properties": {
"message": {
"type": "string"
},
"mode": {
"enum": [
"form"
],
"type": "string"
},
"requested_schema": true
},
"required": [
"message",
"mode",
"requested_schema"
],
"type": "object"
},
{
"properties": {
"elicitation_id": {
"type": "string"
},
"message": {
"type": "string"
},
"mode": {
"enum": [
"url"
],
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"elicitation_id",
"message",
"mode",
"url"
],
"type": "object"
}
]
},
"ErrorNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -4477,60 +4131,6 @@
"title": "WebSearchEndEventMsg",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"type": {
"enum": [
"image_generation_begin"
],
"title": "ImageGenerationBeginEventMsgType",
"type": "string"
}
},
"required": [
"call_id",
"type"
],
"title": "ImageGenerationBeginEventMsg",
"type": "object"
},
{
"properties": {
"call_id": {
"type": "string"
},
"result": {
"type": "string"
},
"revised_prompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"image_generation_end"
],
"title": "ImageGenerationEndEventMsgType",
"type": "string"
}
},
"required": [
"call_id",
"result",
"status",
"type"
],
"title": "ImageGenerationEndEventMsg",
"type": "object"
},
{
"description": "Notification that the server is about to execute a command.",
"properties": {
@@ -5053,8 +4653,8 @@
"id": {
"$ref": "#/definitions/RequestId"
},
"request": {
"$ref": "#/definitions/ElicitationRequest"
"message": {
"type": "string"
},
"server_name": {
"type": "string"
@@ -5069,7 +4669,7 @@
},
"required": [
"id",
"request",
"message",
"server_name",
"type"
],
@@ -7615,64 +7215,66 @@
"title": "LogoutAccountResponse",
"type": "object"
},
"MacOsAutomationPermission": {
"oneOf": [
"MacOsAutomationValue": {
"anyOf": [
{
"enum": [
"none",
"all"
],
"type": "string"
"type": "boolean"
},
{
"additionalProperties": false,
"properties": {
"bundle_ids": {
"items": {
"type": "string"
},
"type": "array"
}
"items": {
"type": "string"
},
"required": [
"bundle_ids"
],
"title": "BundleIdsMacOsAutomationPermission",
"type": "object"
"type": "array"
}
]
},
"MacOsPreferencesPermission": {
"enum": [
"none",
"read_only",
"read_write"
],
"type": "string"
},
"MacOsSeatbeltProfileExtensions": {
"MacOsPermissions": {
"properties": {
"macos_accessibility": {
"type": "boolean"
"accessibility": {
"type": [
"boolean",
"null"
]
},
"macos_automation": {
"$ref": "#/definitions/MacOsAutomationPermission"
"automations": {
"anyOf": [
{
"$ref": "#/definitions/MacOsAutomationValue"
},
{
"type": "null"
}
]
},
"macos_calendar": {
"type": "boolean"
"calendar": {
"type": [
"boolean",
"null"
]
},
"macos_preferences": {
"$ref": "#/definitions/MacOsPreferencesPermission"
"preferences": {
"anyOf": [
{
"$ref": "#/definitions/MacOsPreferencesValue"
},
{
"type": "null"
}
]
}
},
"required": [
"macos_accessibility",
"macos_automation",
"macos_calendar",
"macos_preferences"
],
"type": "object"
},
"MacOsPreferencesValue": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"McpAuthStatus": {
"enum": [
"unsupported",
@@ -8549,7 +8151,7 @@
"macos": {
"anyOf": [
{
"$ref": "#/definitions/MacOsSeatbeltProfileExtensions"
"$ref": "#/definitions/MacOsPermissions"
},
{
"type": "null"
@@ -8633,126 +8235,6 @@
],
"type": "string"
},
"PluginInstallParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"pluginName": {
"type": "string"
}
},
"required": [
"marketplacePath",
"pluginName"
],
"title": "PluginInstallParams",
"type": "object"
},
"PluginInstallResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PluginInstallResponse",
"type": "object"
},
"PluginListParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces. When omitted, only home-scoped marketplaces are considered.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
}
},
"title": "PluginListParams",
"type": "object"
},
"PluginListResponse": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"marketplaces": {
"items": {
"$ref": "#/definitions/PluginMarketplaceEntry"
},
"type": "array"
}
},
"required": [
"marketplaces"
],
"title": "PluginListResponse",
"type": "object"
},
"PluginMarketplaceEntry": {
"properties": {
"name": {
"type": "string"
},
"path": {
"type": "string"
},
"plugins": {
"items": {
"$ref": "#/definitions/PluginSummary"
},
"type": "array"
}
},
"required": [
"name",
"path",
"plugins"
],
"type": "object"
},
"PluginSource": {
"oneOf": [
{
"properties": {
"path": {
"type": "string"
},
"type": {
"enum": [
"local"
],
"title": "LocalPluginSourceType",
"type": "string"
}
},
"required": [
"path",
"type"
],
"title": "LocalPluginSource",
"type": "object"
}
]
},
"PluginSummary": {
"properties": {
"enabled": {
"type": "boolean"
},
"name": {
"type": "string"
},
"source": {
"$ref": "#/definitions/PluginSource"
}
},
"required": [
"enabled",
"name",
"source"
],
"type": "object"
},
"ProductSurface": {
"enum": [
"chatgpt",
@@ -10778,26 +10260,6 @@
"title": "Item/plan/deltaNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"command/exec/outputDelta"
],
"title": "Command/exec/outputDeltaNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/CommandExecOutputDeltaNotification"
}
},
"required": [
"method",
"params"
],
"title": "Command/exec/outputDeltaNotification",
"type": "object"
},
{
"properties": {
"method": {
@@ -12744,40 +12206,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {
@@ -14265,40 +13693,6 @@
"title": "WebSearchTurnItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revised_prompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"ImageGeneration"
],
"title": "ImageGenerationTurnItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationTurnItem",
"type": "object"
},
{
"properties": {
"id": {
@@ -14832,12 +14226,6 @@
"WindowsSandboxSetupStartParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"cwd": {
"type": [
"string",
"null"
]
},
"mode": {
"$ref": "#/definitions/WindowsSandboxSetupMode"
}

View File

@@ -119,13 +119,6 @@
},
"name": {
"type": "string"
},
"pluginDisplayNames": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [

View File

@@ -119,13 +119,6 @@
},
"name": {
"type": "string"
},
"pluginDisplayNames": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [

View File

@@ -1,34 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"CommandExecOutputStream": {
"enum": [
"stdout",
"stderr"
],
"type": "string"
}
},
"properties": {
"capReached": {
"type": "boolean"
},
"deltaBase64": {
"type": "string"
},
"processId": {
"type": "string"
},
"stream": {
"$ref": "#/definitions/CommandExecOutputStream"
}
},
"required": [
"capReached",
"deltaBase64",
"processId",
"stream"
],
"title": "CommandExecOutputDeltaNotification",
"type": "object"
}

View File

@@ -5,25 +5,6 @@
"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"
},
"CommandExecTerminalSize": {
"properties": {
"cols": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
},
"rows": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
}
},
"required": [
"cols",
"rows"
],
"type": "object"
},
"NetworkAccess": {
"enum": [
"restricted",
@@ -211,38 +192,6 @@
"null"
]
},
"disableOutputCap": {
"type": "boolean"
},
"disableTimeout": {
"type": "boolean"
},
"env": {
"additionalProperties": {
"type": [
"string",
"null"
]
},
"type": [
"object",
"null"
]
},
"outputBytesCap": {
"format": "uint",
"minimum": 0.0,
"type": [
"integer",
"null"
]
},
"processId": {
"type": [
"string",
"null"
]
},
"sandboxPolicy": {
"anyOf": [
{
@@ -253,31 +202,12 @@
}
]
},
"size": {
"anyOf": [
{
"$ref": "#/definitions/CommandExecTerminalSize"
},
{
"type": "null"
}
]
},
"streamStdin": {
"type": "boolean"
},
"streamStdoutStderr": {
"type": "boolean"
},
"timeoutMs": {
"format": "int64",
"type": [
"integer",
"null"
]
},
"tty": {
"type": "boolean"
}
},
"required": [

View File

@@ -1,38 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"CommandExecTerminalSize": {
"properties": {
"cols": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
},
"rows": {
"format": "uint16",
"minimum": 0.0,
"type": "integer"
}
},
"required": [
"cols",
"rows"
],
"type": "object"
}
},
"properties": {
"processId": {
"type": "string"
},
"size": {
"$ref": "#/definitions/CommandExecTerminalSize"
}
},
"required": [
"processId",
"size"
],
"title": "CommandExecResizeParams",
"type": "object"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CommandExecResizeResponse",
"type": "object"
}

View File

@@ -1,13 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"processId": {
"type": "string"
}
},
"required": [
"processId"
],
"title": "CommandExecTerminateParams",
"type": "object"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CommandExecTerminateResponse",
"type": "object"
}

View File

@@ -1,22 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"closeStdin": {
"type": "boolean"
},
"deltaBase64": {
"type": [
"string",
"null"
]
},
"processId": {
"type": "string"
}
},
"required": [
"processId"
],
"title": "CommandExecWriteParams",
"type": "object"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CommandExecWriteResponse",
"type": "object"
}

View File

@@ -863,40 +863,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -863,40 +863,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1,23 +0,0 @@
{
"$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"
}
},
"properties": {
"marketplacePath": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"pluginName": {
"type": "string"
}
},
"required": [
"marketplacePath",
"pluginName"
],
"title": "PluginInstallParams",
"type": "object"
}

View File

@@ -1,5 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "PluginInstallResponse",
"type": "object"
}

View File

@@ -1,23 +0,0 @@
{
"$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"
}
},
"properties": {
"cwds": {
"description": "Optional working directories used to discover repo marketplaces. When omitted, only home-scoped marketplaces are considered.",
"items": {
"$ref": "#/definitions/AbsolutePathBuf"
},
"type": [
"array",
"null"
]
}
},
"title": "PluginListParams",
"type": "object"
}

View File

@@ -1,83 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"PluginMarketplaceEntry": {
"properties": {
"name": {
"type": "string"
},
"path": {
"type": "string"
},
"plugins": {
"items": {
"$ref": "#/definitions/PluginSummary"
},
"type": "array"
}
},
"required": [
"name",
"path",
"plugins"
],
"type": "object"
},
"PluginSource": {
"oneOf": [
{
"properties": {
"path": {
"type": "string"
},
"type": {
"enum": [
"local"
],
"title": "LocalPluginSourceType",
"type": "string"
}
},
"required": [
"path",
"type"
],
"title": "LocalPluginSource",
"type": "object"
}
]
},
"PluginSummary": {
"properties": {
"enabled": {
"type": "boolean"
},
"name": {
"type": "string"
},
"source": {
"$ref": "#/definitions/PluginSource"
}
},
"required": [
"enabled",
"name",
"source"
],
"type": "object"
}
},
"properties": {
"marketplaces": {
"items": {
"$ref": "#/definitions/PluginMarketplaceEntry"
},
"type": "array"
}
},
"required": [
"marketplaces"
],
"title": "PluginListResponse",
"type": "object"
}

View File

@@ -977,40 +977,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1453,40 +1453,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1215,40 +1215,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1215,40 +1215,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1215,40 +1215,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1453,40 +1453,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1215,40 +1215,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1453,40 +1453,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1215,40 +1215,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -1215,40 +1215,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -977,40 +977,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -977,40 +977,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -977,40 +977,6 @@
"title": "ImageViewThreadItem",
"type": "object"
},
{
"properties": {
"id": {
"type": "string"
},
"result": {
"type": "string"
},
"revisedPrompt": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string"
},
"type": {
"enum": [
"imageGeneration"
],
"title": "ImageGenerationThreadItemType",
"type": "string"
}
},
"required": [
"id",
"result",
"status",
"type"
],
"title": "ImageGenerationThreadItem",
"type": "object"
},
{
"properties": {
"id": {

View File

@@ -10,12 +10,6 @@
}
},
"properties": {
"cwd": {
"type": [
"string",
"null"
]
},
"mode": {
"$ref": "#/definitions/WindowsSandboxSetupMode"
}

View File

@@ -10,9 +10,6 @@ import type { RequestId } from "./RequestId";
import type { AppsListParams } from "./v2/AppsListParams";
import type { CancelLoginAccountParams } from "./v2/CancelLoginAccountParams";
import type { CommandExecParams } from "./v2/CommandExecParams";
import type { CommandExecResizeParams } from "./v2/CommandExecResizeParams";
import type { CommandExecTerminateParams } from "./v2/CommandExecTerminateParams";
import type { CommandExecWriteParams } from "./v2/CommandExecWriteParams";
import type { ConfigBatchWriteParams } from "./v2/ConfigBatchWriteParams";
import type { ConfigReadParams } from "./v2/ConfigReadParams";
import type { ConfigValueWriteParams } from "./v2/ConfigValueWriteParams";
@@ -25,8 +22,6 @@ import type { ListMcpServerStatusParams } from "./v2/ListMcpServerStatusParams";
import type { LoginAccountParams } from "./v2/LoginAccountParams";
import type { McpServerOauthLoginParams } from "./v2/McpServerOauthLoginParams";
import type { ModelListParams } from "./v2/ModelListParams";
import type { PluginInstallParams } from "./v2/PluginInstallParams";
import type { PluginListParams } from "./v2/PluginListParams";
import type { ReviewStartParams } from "./v2/ReviewStartParams";
import type { SkillsConfigWriteParams } from "./v2/SkillsConfigWriteParams";
import type { SkillsListParams } from "./v2/SkillsListParams";
@@ -53,4 +48,4 @@ import type { WindowsSandboxSetupStartParams } from "./v2/WindowsSandboxSetupSta
/**
* Request from the client to the server.
*/
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, };
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, };

View File

@@ -1,6 +0,0 @@
// 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 { JsonValue } from "./serde_json/JsonValue";
export type ElicitationRequest = { "mode": "form", message: string, requested_schema: JsonValue, } | { "mode": "url", message: string, url: string, elicitation_id: string, };

View File

@@ -1,6 +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.
import type { ElicitationRequest } from "./ElicitationRequest";
export type ElicitationRequestEvent = { server_name: string, id: string | number, request: ElicitationRequest, };
export type ElicitationRequestEvent = { server_name: string, id: string | number, message: string, };

View File

@@ -33,8 +33,6 @@ import type { ExecCommandEndEvent } from "./ExecCommandEndEvent";
import type { ExecCommandOutputDeltaEvent } from "./ExecCommandOutputDeltaEvent";
import type { ExitedReviewModeEvent } from "./ExitedReviewModeEvent";
import type { GetHistoryEntryResponseEvent } from "./GetHistoryEntryResponseEvent";
import type { ImageGenerationBeginEvent } from "./ImageGenerationBeginEvent";
import type { ImageGenerationEndEvent } from "./ImageGenerationEndEvent";
import type { ItemCompletedEvent } from "./ItemCompletedEvent";
import type { ItemStartedEvent } from "./ItemStartedEvent";
import type { ListCustomPromptsResponseEvent } from "./ListCustomPromptsResponseEvent";
@@ -81,4 +79,4 @@ import type { WebSearchEndEvent } from "./WebSearchEndEvent";
* Response event from the agent
* NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.
*/
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "image_generation_begin" } & ImageGenerationBeginEvent | { "type": "image_generation_end" } & ImageGenerationEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;

View File

@@ -1,5 +0,0 @@
// 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 ImageGenerationBeginEvent = { call_id: string, };

View File

@@ -1,5 +0,0 @@
// 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 ImageGenerationEndEvent = { call_id: string, status: string, revised_prompt?: string, result: string, };

View File

@@ -1,5 +0,0 @@
// 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 ImageGenerationItem = { id: string, status: string, revised_prompt?: string, result: string, };

View File

@@ -1,5 +0,0 @@
// 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 MacOsAutomationPermission = "none" | "all" | { "bundle_ids": Array<string> };

View File

@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type CommandExecOutputStream = "stdout" | "stderr";
export type MacOsAutomationValue = boolean | Array<string>;

View File

@@ -0,0 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { MacOsAutomationValue } from "./MacOsAutomationValue";
import type { MacOsPreferencesValue } from "./MacOsPreferencesValue";
export type MacOsPermissions = { preferences: MacOsPreferencesValue | null, automations: MacOsAutomationValue | null, accessibility: boolean | null, calendar: boolean | null, };

View File

@@ -1,5 +0,0 @@
// 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 MacOsPreferencesPermission = "none" | "read_only" | "read_write";

View File

@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type PluginInstallResponse = Record<string, never>;
export type MacOsPreferencesValue = boolean | string;

View File

@@ -1,7 +0,0 @@
// 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 { MacOsAutomationPermission } from "./MacOsAutomationPermission";
import type { MacOsPreferencesPermission } from "./MacOsPreferencesPermission";
export type MacOsSeatbeltProfileExtensions = { macos_preferences: MacOsPreferencesPermission, macos_automation: MacOsAutomationPermission, macos_accessibility: boolean, macos_calendar: boolean, };

View File

@@ -2,7 +2,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { FileSystemPermissions } from "./FileSystemPermissions";
import type { MacOsSeatbeltProfileExtensions } from "./MacOsSeatbeltProfileExtensions";
import type { MacOsPermissions } from "./MacOsPermissions";
import type { NetworkPermissions } from "./NetworkPermissions";
export type PermissionProfile = { network: NetworkPermissions | null, file_system: FileSystemPermissions | null, macos: MacOsSeatbeltProfileExtensions | null, };
export type PermissionProfile = { network: NetworkPermissions | null, file_system: FileSystemPermissions | null, macos: MacOsPermissions | null, };

View File

@@ -8,7 +8,6 @@ import type { AccountRateLimitsUpdatedNotification } from "./v2/AccountRateLimit
import type { AccountUpdatedNotification } from "./v2/AccountUpdatedNotification";
import type { AgentMessageDeltaNotification } from "./v2/AgentMessageDeltaNotification";
import type { AppListUpdatedNotification } from "./v2/AppListUpdatedNotification";
import type { CommandExecOutputDeltaNotification } from "./v2/CommandExecOutputDeltaNotification";
import type { CommandExecutionOutputDeltaNotification } from "./v2/CommandExecutionOutputDeltaNotification";
import type { ConfigWarningNotification } from "./v2/ConfigWarningNotification";
import type { ContextCompactedNotification } from "./v2/ContextCompactedNotification";
@@ -50,4 +49,4 @@ import type { WindowsWorldWritableWarningNotification } from "./v2/WindowsWorldW
/**
* Notification sent from the server to the client.
*/
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };

View File

@@ -8,10 +8,9 @@ import type { ChatgptAuthTokensRefreshParams } from "./v2/ChatgptAuthTokensRefre
import type { CommandExecutionRequestApprovalParams } from "./v2/CommandExecutionRequestApprovalParams";
import type { DynamicToolCallParams } from "./v2/DynamicToolCallParams";
import type { FileChangeRequestApprovalParams } from "./v2/FileChangeRequestApprovalParams";
import type { McpServerElicitationRequestParams } from "./v2/McpServerElicitationRequestParams";
import type { ToolRequestUserInputParams } from "./v2/ToolRequestUserInputParams";
/**
* Request initiated from the server and sent to the client.
*/
export type ServerRequest = { "method": "item/commandExecution/requestApproval", id: RequestId, params: CommandExecutionRequestApprovalParams, } | { "method": "item/fileChange/requestApproval", id: RequestId, params: FileChangeRequestApprovalParams, } | { "method": "item/tool/requestUserInput", id: RequestId, params: ToolRequestUserInputParams, } | { "method": "mcpServer/elicitation/request", id: RequestId, params: McpServerElicitationRequestParams, } | { "method": "item/tool/call", id: RequestId, params: DynamicToolCallParams, } | { "method": "account/chatgptAuthTokens/refresh", id: RequestId, params: ChatgptAuthTokensRefreshParams, } | { "method": "applyPatchApproval", id: RequestId, params: ApplyPatchApprovalParams, } | { "method": "execCommandApproval", id: RequestId, params: ExecCommandApprovalParams, };
export type ServerRequest = { "method": "item/commandExecution/requestApproval", id: RequestId, params: CommandExecutionRequestApprovalParams, } | { "method": "item/fileChange/requestApproval", id: RequestId, params: FileChangeRequestApprovalParams, } | { "method": "item/tool/requestUserInput", id: RequestId, params: ToolRequestUserInputParams, } | { "method": "item/tool/call", id: RequestId, params: DynamicToolCallParams, } | { "method": "account/chatgptAuthTokens/refresh", id: RequestId, params: ChatgptAuthTokensRefreshParams, } | { "method": "applyPatchApproval", id: RequestId, params: ApplyPatchApprovalParams, } | { "method": "execCommandApproval", id: RequestId, params: ExecCommandApprovalParams, };

View File

@@ -3,10 +3,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentMessageItem } from "./AgentMessageItem";
import type { ContextCompactionItem } from "./ContextCompactionItem";
import type { ImageGenerationItem } from "./ImageGenerationItem";
import type { PlanItem } from "./PlanItem";
import type { ReasoningItem } from "./ReasoningItem";
import type { UserMessageItem } from "./UserMessageItem";
import type { WebSearchItem } from "./WebSearchItem";
export type TurnItem = { "type": "UserMessage" } & UserMessageItem | { "type": "AgentMessage" } & AgentMessageItem | { "type": "Plan" } & PlanItem | { "type": "Reasoning" } & ReasoningItem | { "type": "WebSearch" } & WebSearchItem | { "type": "ImageGeneration" } & ImageGenerationItem | { "type": "ContextCompaction" } & ContextCompactionItem;
export type TurnItem = { "type": "UserMessage" } & UserMessageItem | { "type": "AgentMessage" } & AgentMessageItem | { "type": "Plan" } & PlanItem | { "type": "Reasoning" } & ReasoningItem | { "type": "WebSearch" } & WebSearchItem | { "type": "ContextCompaction" } & ContextCompactionItem;

View File

@@ -48,7 +48,6 @@ export type { DeprecationNoticeEvent } from "./DeprecationNoticeEvent";
export type { DynamicToolCallOutputContentItem } from "./DynamicToolCallOutputContentItem";
export type { DynamicToolCallRequest } from "./DynamicToolCallRequest";
export type { DynamicToolCallResponseEvent } from "./DynamicToolCallResponseEvent";
export type { ElicitationRequest } from "./ElicitationRequest";
export type { ElicitationRequestEvent } from "./ElicitationRequestEvent";
export type { ErrorEvent } from "./ErrorEvent";
export type { EventMsg } from "./EventMsg";
@@ -85,9 +84,6 @@ export type { GitDiffToRemoteResponse } from "./GitDiffToRemoteResponse";
export type { GitSha } from "./GitSha";
export type { HistoryEntry } from "./HistoryEntry";
export type { ImageDetail } from "./ImageDetail";
export type { ImageGenerationBeginEvent } from "./ImageGenerationBeginEvent";
export type { ImageGenerationEndEvent } from "./ImageGenerationEndEvent";
export type { ImageGenerationItem } from "./ImageGenerationItem";
export type { InitializeCapabilities } from "./InitializeCapabilities";
export type { InitializeParams } from "./InitializeParams";
export type { InitializeResponse } from "./InitializeResponse";
@@ -100,9 +96,9 @@ export type { ListSkillsResponseEvent } from "./ListSkillsResponseEvent";
export type { LocalShellAction } from "./LocalShellAction";
export type { LocalShellExecAction } from "./LocalShellExecAction";
export type { LocalShellStatus } from "./LocalShellStatus";
export type { MacOsAutomationPermission } from "./MacOsAutomationPermission";
export type { MacOsPreferencesPermission } from "./MacOsPreferencesPermission";
export type { MacOsSeatbeltProfileExtensions } from "./MacOsSeatbeltProfileExtensions";
export type { MacOsAutomationValue } from "./MacOsAutomationValue";
export type { MacOsPermissions } from "./MacOsPermissions";
export type { MacOsPreferencesValue } from "./MacOsPreferencesValue";
export type { McpAuthStatus } from "./McpAuthStatus";
export type { McpInvocation } from "./McpInvocation";
export type { McpListToolsResponseEvent } from "./McpListToolsResponseEvent";

View File

@@ -1,7 +1,7 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { MacOsAutomationPermission } from "../MacOsAutomationPermission";
import type { MacOsPreferencesPermission } from "../MacOsPreferencesPermission";
import type { MacOsAutomationValue } from "../MacOsAutomationValue";
import type { MacOsPreferencesValue } from "../MacOsPreferencesValue";
export type AdditionalMacOsPermissions = { preferences: MacOsPreferencesPermission, automations: MacOsAutomationPermission, accessibility: boolean, calendar: boolean, };
export type AdditionalMacOsPermissions = { preferences: MacOsPreferencesValue | null, automations: MacOsAutomationValue | null, accessibility: boolean | null, calendar: boolean | null, };

View File

@@ -16,4 +16,4 @@ export type AppInfo = { id: string, name: string, description: string | null, lo
* enabled = false
* ```
*/
isEnabled: boolean, pluginDisplayNames: Array<string>, };
isEnabled: boolean, };

View File

@@ -1,6 +0,0 @@
// 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 { CommandExecOutputStream } from "./CommandExecOutputStream";
export type CommandExecOutputDeltaNotification = { processId: string, stream: CommandExecOutputStream, deltaBase64: string, capReached: boolean, };

View File

@@ -1,7 +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 { CommandExecTerminalSize } from "./CommandExecTerminalSize";
import type { SandboxPolicy } from "./SandboxPolicy";
export type CommandExecParams = { command: Array<string>, processId?: string | null, tty?: boolean, streamStdin?: boolean, streamStdoutStderr?: boolean, outputBytesCap?: number | null, disableOutputCap?: boolean, disableTimeout?: boolean, timeoutMs?: number | null, cwd?: string | null, env?: { [key in string]?: string | null } | null, size?: CommandExecTerminalSize | null, sandboxPolicy?: SandboxPolicy | null, };
export type CommandExecParams = { command: Array<string>, timeoutMs?: number | null, cwd?: string | null, sandboxPolicy?: SandboxPolicy | null, };

View File

@@ -1,6 +0,0 @@
// 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 { CommandExecTerminalSize } from "./CommandExecTerminalSize";
export type CommandExecResizeParams = { processId: string, size: CommandExecTerminalSize, };

View File

@@ -1,5 +0,0 @@
// 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 CommandExecResizeResponse = Record<string, never>;

View File

@@ -1,5 +0,0 @@
// 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 CommandExecTerminalSize = { rows: number, cols: number, };

View File

@@ -1,5 +0,0 @@
// 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 CommandExecTerminateParams = { processId: string, };

View File

@@ -1,5 +0,0 @@
// 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 CommandExecTerminateResponse = Record<string, never>;

View File

@@ -1,5 +0,0 @@
// 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 CommandExecWriteParams = { processId: string, deltaBase64?: string | null, closeStdin?: boolean, };

View File

@@ -1,5 +0,0 @@
// 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 CommandExecWriteResponse = Record<string, never>;

View File

@@ -1,5 +0,0 @@
// 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 McpServerElicitationAction = "accept" | "decline" | "cancel";

View File

@@ -1,15 +0,0 @@
// 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 { JsonValue } from "../serde_json/JsonValue";
export type McpServerElicitationRequestParams = { threadId: string,
/**
* Active Codex turn when this elicitation was observed, if app-server could correlate one.
*
* This is nullable because MCP models elicitation as a standalone server-to-client request
* identified by the MCP server request id. It may be triggered during a turn, but turn
* context is app-server correlation rather than part of the protocol identity of the
* elicitation itself.
*/
turnId: string | null, serverName: string, } & ({ "mode": "form", message: string, requestedSchema: JsonValue, } | { "mode": "url", message: string, url: string, elicitationId: string, });

View File

@@ -1,13 +0,0 @@
// 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 { JsonValue } from "../serde_json/JsonValue";
import type { McpServerElicitationAction } from "./McpServerElicitationAction";
export type McpServerElicitationRequestResponse = { action: McpServerElicitationAction,
/**
* Structured user input for accepted elicitations, mirroring RMCP `CreateElicitationResult`.
*
* This is nullable because decline/cancel responses have no content.
*/
content: JsonValue | null, };

View File

@@ -1,6 +0,0 @@
// 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 { AbsolutePathBuf } from "../AbsolutePathBuf";
export type PluginInstallParams = { marketplacePath: AbsolutePathBuf, pluginName: string, };

View File

@@ -1,11 +0,0 @@
// 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 { AbsolutePathBuf } from "../AbsolutePathBuf";
export type PluginListParams = {
/**
* Optional working directories used to discover repo marketplaces. When omitted,
* only home-scoped marketplaces are considered.
*/
cwds?: Array<AbsolutePathBuf> | null, };

View File

@@ -1,6 +0,0 @@
// 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 { PluginMarketplaceEntry } from "./PluginMarketplaceEntry";
export type PluginListResponse = { marketplaces: Array<PluginMarketplaceEntry>, };

View File

@@ -1,6 +0,0 @@
// 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 { PluginSummary } from "./PluginSummary";
export type PluginMarketplaceEntry = { name: string, path: string, plugins: Array<PluginSummary>, };

View File

@@ -1,5 +0,0 @@
// 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 PluginSource = { "type": "local", path: string, };

View File

@@ -1,6 +0,0 @@
// 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 { PluginSource } from "./PluginSource";
export type PluginSummary = { name: string, source: PluginSource, enabled: boolean, };

View File

@@ -85,4 +85,4 @@ prompt: string | null,
/**
* Last known status of the target agents, when available.
*/
agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: string, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, };
agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: string, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, };

View File

@@ -3,4 +3,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { WindowsSandboxSetupMode } from "./WindowsSandboxSetupMode";
export type WindowsSandboxSetupStartParams = { mode: WindowsSandboxSetupMode, cwd?: string | null, };
export type WindowsSandboxSetupStartParams = { mode: WindowsSandboxSetupMode, };

View File

@@ -37,17 +37,8 @@ export type { CollabAgentTool } from "./CollabAgentTool";
export type { CollabAgentToolCallStatus } from "./CollabAgentToolCallStatus";
export type { CollaborationModeMask } from "./CollaborationModeMask";
export type { CommandAction } from "./CommandAction";
export type { CommandExecOutputDeltaNotification } from "./CommandExecOutputDeltaNotification";
export type { CommandExecOutputStream } from "./CommandExecOutputStream";
export type { CommandExecParams } from "./CommandExecParams";
export type { CommandExecResizeParams } from "./CommandExecResizeParams";
export type { CommandExecResizeResponse } from "./CommandExecResizeResponse";
export type { CommandExecResponse } from "./CommandExecResponse";
export type { CommandExecTerminalSize } from "./CommandExecTerminalSize";
export type { CommandExecTerminateParams } from "./CommandExecTerminateParams";
export type { CommandExecTerminateResponse } from "./CommandExecTerminateResponse";
export type { CommandExecWriteParams } from "./CommandExecWriteParams";
export type { CommandExecWriteResponse } from "./CommandExecWriteResponse";
export type { CommandExecutionApprovalDecision } from "./CommandExecutionApprovalDecision";
export type { CommandExecutionOutputDeltaNotification } from "./CommandExecutionOutputDeltaNotification";
export type { CommandExecutionRequestApprovalParams } from "./CommandExecutionRequestApprovalParams";
@@ -106,9 +97,6 @@ export type { LoginAccountParams } from "./LoginAccountParams";
export type { LoginAccountResponse } from "./LoginAccountResponse";
export type { LogoutAccountResponse } from "./LogoutAccountResponse";
export type { McpAuthStatus } from "./McpAuthStatus";
export type { McpServerElicitationAction } from "./McpServerElicitationAction";
export type { McpServerElicitationRequestParams } from "./McpServerElicitationRequestParams";
export type { McpServerElicitationRequestResponse } from "./McpServerElicitationRequestResponse";
export type { McpServerOauthLoginCompletedNotification } from "./McpServerOauthLoginCompletedNotification";
export type { McpServerOauthLoginParams } from "./McpServerOauthLoginParams";
export type { McpServerOauthLoginResponse } from "./McpServerOauthLoginResponse";
@@ -136,13 +124,6 @@ export type { OverriddenMetadata } from "./OverriddenMetadata";
export type { PatchApplyStatus } from "./PatchApplyStatus";
export type { PatchChangeKind } from "./PatchChangeKind";
export type { PlanDeltaNotification } from "./PlanDeltaNotification";
export type { PluginInstallParams } from "./PluginInstallParams";
export type { PluginInstallResponse } from "./PluginInstallResponse";
export type { PluginListParams } from "./PluginListParams";
export type { PluginListResponse } from "./PluginListResponse";
export type { PluginMarketplaceEntry } from "./PluginMarketplaceEntry";
export type { PluginSource } from "./PluginSource";
export type { PluginSummary } from "./PluginSummary";
export type { ProductSurface } from "./ProductSurface";
export type { ProfileV2 } from "./ProfileV2";
export type { RateLimitSnapshot } from "./RateLimitSnapshot";

View File

@@ -248,10 +248,6 @@ client_request_definitions! {
params: v2::SkillsListParams,
response: v2::SkillsListResponse,
},
PluginList => "plugin/list" {
params: v2::PluginListParams,
response: v2::PluginListResponse,
},
SkillsRemoteList => "skills/remote/list" {
params: v2::SkillsRemoteReadParams,
response: v2::SkillsRemoteReadResponse,
@@ -268,10 +264,6 @@ client_request_definitions! {
params: v2::SkillsConfigWriteParams,
response: v2::SkillsConfigWriteResponse,
},
PluginInstall => "plugin/install" {
params: v2::PluginInstallParams,
response: v2::PluginInstallResponse,
},
TurnStart => "turn/start" {
params: v2::TurnStartParams,
inspect_params: true,
@@ -382,18 +374,6 @@ client_request_definitions! {
params: v2::CommandExecParams,
response: v2::CommandExecResponse,
},
CommandExecWrite => "command/exec/write" {
params: v2::CommandExecWriteParams,
response: v2::CommandExecWriteResponse,
},
CommandExecTerminate => "command/exec/terminate" {
params: v2::CommandExecTerminateParams,
response: v2::CommandExecTerminateResponse,
},
CommandExecResize => "command/exec/resize" {
params: v2::CommandExecResizeParams,
response: v2::CommandExecResizeResponse,
},
ConfigRead => "config/read" {
params: v2::ConfigReadParams,
@@ -666,12 +646,6 @@ server_request_definitions! {
response: v2::ToolRequestUserInputResponse,
},
/// Request input for an MCP server elicitation.
McpServerElicitationRequest => "mcpServer/elicitation/request" {
params: v2::McpServerElicitationRequestParams,
response: v2::McpServerElicitationRequestResponse,
},
/// Execute a dynamic tool call on the client.
DynamicToolCall => "item/tool/call" {
params: v2::DynamicToolCallParams,
@@ -793,7 +767,6 @@ server_notification_definitions! {
AgentMessageDelta => "item/agentMessage/delta" (v2::AgentMessageDeltaNotification),
/// EXPERIMENTAL - proposed plan streaming deltas for plan items.
PlanDelta => "item/plan/delta" (v2::PlanDeltaNotification),
CommandExecOutputDelta => "command/exec/outputDelta" (v2::CommandExecOutputDeltaNotification),
CommandExecutionOutputDelta => "item/commandExecution/outputDelta" (v2::CommandExecutionOutputDeltaNotification),
TerminalInteraction => "item/commandExecution/terminalInteraction" (v2::TerminalInteractionNotification),
FileChangeOutputDelta => "item/fileChange/outputDelta" (v2::FileChangeOutputDeltaNotification),
@@ -1069,60 +1042,6 @@ mod tests {
Ok(())
}
#[test]
fn serialize_mcp_server_elicitation_request() -> Result<()> {
let params = v2::McpServerElicitationRequestParams {
thread_id: "thr_123".to_string(),
turn_id: Some("turn_123".to_string()),
server_name: "codex_apps".to_string(),
request: v2::McpServerElicitationRequest::Form {
message: "Allow this request?".to_string(),
requested_schema: json!({
"type": "object",
"properties": {
"confirmed": {
"type": "boolean"
}
},
"required": ["confirmed"]
}),
},
};
let request = ServerRequest::McpServerElicitationRequest {
request_id: RequestId::Integer(9),
params: params.clone(),
};
assert_eq!(
json!({
"method": "mcpServer/elicitation/request",
"id": 9,
"params": {
"threadId": "thr_123",
"turnId": "turn_123",
"serverName": "codex_apps",
"mode": "form",
"message": "Allow this request?",
"requestedSchema": {
"type": "object",
"properties": {
"confirmed": {
"type": "boolean"
}
},
"required": ["confirmed"]
}
}
}),
serde_json::to_value(&request)?,
);
let payload = ServerRequestPayload::McpServerElicitationRequest(params);
assert_eq!(request.id(), &RequestId::Integer(9));
assert_eq!(payload.request_with_id(RequestId::Integer(9)), request);
Ok(())
}
#[test]
fn serialize_get_account_rate_limits() -> Result<()> {
let request = ClientRequest::GetAccountRateLimits {

View File

@@ -1,22 +1,14 @@
use crate::protocol::v1;
use crate::protocol::v2;
impl From<v1::ExecOneOffCommandParams> for v2::CommandExecParams {
fn from(value: v1::ExecOneOffCommandParams) -> Self {
Self {
command: value.command,
process_id: None,
tty: false,
stream_stdin: false,
stream_stdout_stderr: false,
output_bytes_cap: None,
disable_output_cap: false,
disable_timeout: false,
timeout_ms: value
.timeout_ms
.map(|timeout| i64::try_from(timeout).unwrap_or(60_000)),
cwd: value.cwd,
env: None,
size: None,
sandbox_policy: value.sandbox_policy.map(std::convert::Into::into),
}
}

View File

@@ -30,8 +30,6 @@ use codex_protocol::protocol::ErrorEvent;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::ExecCommandBeginEvent;
use codex_protocol::protocol::ExecCommandEndEvent;
use codex_protocol::protocol::ImageGenerationBeginEvent;
use codex_protocol::protocol::ImageGenerationEndEvent;
use codex_protocol::protocol::ItemCompletedEvent;
use codex_protocol::protocol::ItemStartedEvent;
use codex_protocol::protocol::McpToolCallBeginEvent;
@@ -143,8 +141,6 @@ impl ThreadHistoryBuilder {
EventMsg::McpToolCallBegin(payload) => self.handle_mcp_tool_call_begin(payload),
EventMsg::McpToolCallEnd(payload) => self.handle_mcp_tool_call_end(payload),
EventMsg::ViewImageToolCall(payload) => self.handle_view_image_tool_call(payload),
EventMsg::ImageGenerationBegin(payload) => self.handle_image_generation_begin(payload),
EventMsg::ImageGenerationEnd(payload) => self.handle_image_generation_end(payload),
EventMsg::CollabAgentSpawnBegin(payload) => {
self.handle_collab_agent_spawn_begin(payload)
}
@@ -273,7 +269,6 @@ impl ThreadHistoryBuilder {
| codex_protocol::items::TurnItem::AgentMessage(_)
| codex_protocol::items::TurnItem::Reasoning(_)
| codex_protocol::items::TurnItem::WebSearch(_)
| codex_protocol::items::TurnItem::ImageGeneration(_)
| codex_protocol::items::TurnItem::ContextCompaction(_) => {}
}
}
@@ -293,7 +288,6 @@ impl ThreadHistoryBuilder {
| codex_protocol::items::TurnItem::AgentMessage(_)
| codex_protocol::items::TurnItem::Reasoning(_)
| codex_protocol::items::TurnItem::WebSearch(_)
| codex_protocol::items::TurnItem::ImageGeneration(_)
| codex_protocol::items::TurnItem::ContextCompaction(_) => {}
}
}
@@ -522,26 +516,6 @@ impl ThreadHistoryBuilder {
self.upsert_item_in_current_turn(item);
}
fn handle_image_generation_begin(&mut self, payload: &ImageGenerationBeginEvent) {
let item = ThreadItem::ImageGeneration {
id: payload.call_id.clone(),
status: String::new(),
revised_prompt: None,
result: String::new(),
};
self.upsert_item_in_current_turn(item);
}
fn handle_image_generation_end(&mut self, payload: &ImageGenerationEndEvent) {
let item = ThreadItem::ImageGeneration {
id: payload.call_id.clone(),
status: payload.status.clone(),
revised_prompt: payload.revised_prompt.clone(),
result: payload.result.clone(),
};
self.upsert_item_in_current_turn(item);
}
fn handle_collab_agent_spawn_begin(
&mut self,
payload: &codex_protocol::protocol::CollabAgentSpawnBeginEvent,

View File

@@ -6,7 +6,6 @@ use crate::RequestId;
use crate::protocol::common::AuthMode;
use codex_experimental_api_macros::ExperimentalApi;
use codex_protocol::account::PlanType;
use codex_protocol::approvals::ElicitationRequest as CoreElicitationRequest;
use codex_protocol::approvals::ExecPolicyAmendment as CoreExecPolicyAmendment;
use codex_protocol::approvals::NetworkApprovalContext as CoreNetworkApprovalContext;
use codex_protocol::approvals::NetworkApprovalProtocol as CoreNetworkApprovalProtocol;
@@ -28,9 +27,9 @@ use codex_protocol::mcp::Resource as McpResource;
use codex_protocol::mcp::ResourceTemplate as McpResourceTemplate;
use codex_protocol::mcp::Tool as McpTool;
use codex_protocol::models::FileSystemPermissions as CoreFileSystemPermissions;
use codex_protocol::models::MacOsAutomationPermission as CoreMacOsAutomationPermission;
use codex_protocol::models::MacOsPreferencesPermission as CoreMacOsPreferencesPermission;
use codex_protocol::models::MacOsSeatbeltProfileExtensions as CoreMacOsSeatbeltProfileExtensions;
use codex_protocol::models::MacOsAutomationValue as CoreMacOsAutomationValue;
use codex_protocol::models::MacOsPermissions as CoreMacOsPermissions;
use codex_protocol::models::MacOsPreferencesValue as CoreMacOsPreferencesValue;
use codex_protocol::models::MessagePhase;
use codex_protocol::models::NetworkPermissions as CoreNetworkPermissions;
use codex_protocol::models::PermissionProfile as CorePermissionProfile;
@@ -638,7 +637,7 @@ pub struct NetworkRequirements {
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all = "lowercase")]
#[ts(export_to = "v2/")]
pub enum ResidencyRequirement {
Us,
@@ -837,19 +836,19 @@ impl From<CoreFileSystemPermissions> for AdditionalFileSystemPermissions {
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct AdditionalMacOsPermissions {
pub preferences: CoreMacOsPreferencesPermission,
pub automations: CoreMacOsAutomationPermission,
pub accessibility: bool,
pub calendar: bool,
pub preferences: Option<CoreMacOsPreferencesValue>,
pub automations: Option<CoreMacOsAutomationValue>,
pub accessibility: Option<bool>,
pub calendar: Option<bool>,
}
impl From<CoreMacOsSeatbeltProfileExtensions> for AdditionalMacOsPermissions {
fn from(value: CoreMacOsSeatbeltProfileExtensions) -> Self {
impl From<CoreMacOsPermissions> for AdditionalMacOsPermissions {
fn from(value: CoreMacOsPermissions) -> Self {
Self {
preferences: value.macos_preferences,
automations: value.macos_automation,
accessibility: value.macos_accessibility,
calendar: value.macos_calendar,
preferences: value.preferences,
automations: value.automations,
accessibility: value.accessibility,
calendar: value.calendar,
}
}
}
@@ -1709,8 +1708,6 @@ pub struct AppInfo {
/// ```
#[serde(default = "default_enabled")]
pub is_enabled: bool,
#[serde(default)]
pub plugin_display_names: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -1783,44 +1780,17 @@ pub struct FeedbackUploadResponse {
pub thread_id: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecTerminalSize {
pub rows: u16,
pub cols: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecParams {
pub command: Vec<String>,
#[ts(optional = nullable)]
pub process_id: Option<String>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub tty: bool,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub stream_stdin: bool,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub stream_stdout_stderr: bool,
#[ts(type = "number | null")]
#[ts(optional = nullable)]
pub output_bytes_cap: Option<usize>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub disable_output_cap: bool,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub disable_timeout: bool,
#[ts(type = "number | null")]
#[ts(optional = nullable)]
pub timeout_ms: Option<i64>,
#[ts(optional = nullable)]
pub cwd: Option<PathBuf>,
#[ts(optional = nullable)]
pub env: Option<HashMap<String, Option<String>>>,
#[ts(optional = nullable)]
pub size: Option<CommandExecTerminalSize>,
#[ts(optional = nullable)]
pub sandbox_policy: Option<SandboxPolicy>,
}
@@ -1833,55 +1803,6 @@ pub struct CommandExecResponse {
pub stderr: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecWriteParams {
pub process_id: String,
#[ts(optional = nullable)]
pub delta_base64: Option<String>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub close_stdin: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecWriteResponse {}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecTerminateParams {
pub process_id: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecTerminateResponse {}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecResizeParams {
pub process_id: String,
pub size: CommandExecTerminalSize,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecResizeResponse {}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub enum CommandExecOutputStream {
Stdout,
Stderr,
}
// === Threads, Turns, and Items ===
// Thread APIs
#[derive(
@@ -2447,23 +2368,6 @@ pub struct SkillsListResponse {
pub data: Vec<SkillsListEntry>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginListParams {
/// Optional working directories used to discover repo marketplaces. When omitted,
/// only home-scoped marketplaces are considered.
#[ts(optional = nullable)]
pub cwds: Option<Vec<AbsolutePathBuf>>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginListResponse {
pub marketplaces: Vec<PluginMarketplaceEntry>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -2489,8 +2393,8 @@ pub enum HazelnutScope {
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS, Default)]
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
#[serde(rename_all = "lowercase")]
#[ts(rename_all = "lowercase")]
#[ts(export_to = "v2/")]
pub enum ProductSurface {
Chatgpt,
@@ -2627,34 +2531,6 @@ pub struct SkillsListEntry {
pub errors: Vec<SkillErrorInfo>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginMarketplaceEntry {
pub name: String,
pub path: PathBuf,
pub plugins: Vec<PluginSummary>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginSummary {
pub name: String,
pub source: PluginSource,
pub enabled: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(tag = "type", rename_all = "camelCase")]
#[ts(tag = "type")]
#[ts(export_to = "v2/")]
pub enum PluginSource {
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
Local { path: PathBuf },
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -2670,19 +2546,6 @@ pub struct SkillsConfigWriteResponse {
pub effective_enabled: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginInstallParams {
pub marketplace_path: AbsolutePathBuf,
pub plugin_name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct PluginInstallResponse {}
impl From<CoreSkillMetadata> for SkillMetadata {
fn from(value: CoreSkillMetadata) -> Self {
Self {
@@ -3469,14 +3332,6 @@ pub enum ThreadItem {
ImageView { id: String, path: String },
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
ImageGeneration {
id: String,
status: String,
revised_prompt: Option<String>,
result: String,
},
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
EnteredReviewMode { id: String, review: String },
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
@@ -3500,7 +3355,6 @@ impl ThreadItem {
| ThreadItem::CollabAgentToolCall { id, .. }
| ThreadItem::WebSearch { id, .. }
| ThreadItem::ImageView { id, .. }
| ThreadItem::ImageGeneration { id, .. }
| ThreadItem::EnteredReviewMode { id, .. }
| ThreadItem::ExitedReviewMode { id, .. }
| ThreadItem::ContextCompaction { id, .. } => id,
@@ -3580,12 +3434,6 @@ impl From<CoreTurnItem> for ThreadItem {
query: search.query,
action: Some(WebSearchAction::from(search.action)),
},
CoreTurnItem::ImageGeneration(image) => ThreadItem::ImageGeneration {
id: image.id,
status: image.status,
revised_prompt: image.revised_prompt,
result: image.result,
},
CoreTurnItem::ContextCompaction(compaction) => {
ThreadItem::ContextCompaction { id: compaction.id }
}
@@ -4018,16 +3866,6 @@ pub struct CommandExecutionOutputDeltaNotification {
pub delta: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct CommandExecOutputDeltaNotification {
pub process_id: String,
pub stream: CommandExecOutputStream,
pub delta_base64: String,
pub cap_reached: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -4089,8 +3927,6 @@ pub enum WindowsSandboxSetupMode {
#[ts(export_to = "v2/")]
pub struct WindowsSandboxSetupStartParams {
pub mode: WindowsSandboxSetupMode,
#[ts(optional = nullable)]
pub cwd: Option<PathBuf>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
@@ -4213,138 +4049,6 @@ pub struct FileChangeRequestApprovalResponse {
pub decision: FileChangeApprovalDecision,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub enum McpServerElicitationAction {
Accept,
Decline,
Cancel,
}
impl McpServerElicitationAction {
pub fn to_core(self) -> codex_protocol::approvals::ElicitationAction {
match self {
Self::Accept => codex_protocol::approvals::ElicitationAction::Accept,
Self::Decline => codex_protocol::approvals::ElicitationAction::Decline,
Self::Cancel => codex_protocol::approvals::ElicitationAction::Cancel,
}
}
}
impl From<McpServerElicitationAction> for rmcp::model::ElicitationAction {
fn from(value: McpServerElicitationAction) -> Self {
match value {
McpServerElicitationAction::Accept => Self::Accept,
McpServerElicitationAction::Decline => Self::Decline,
McpServerElicitationAction::Cancel => Self::Cancel,
}
}
}
impl From<rmcp::model::ElicitationAction> for McpServerElicitationAction {
fn from(value: rmcp::model::ElicitationAction) -> Self {
match value {
rmcp::model::ElicitationAction::Accept => Self::Accept,
rmcp::model::ElicitationAction::Decline => Self::Decline,
rmcp::model::ElicitationAction::Cancel => Self::Cancel,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct McpServerElicitationRequestParams {
pub thread_id: String,
/// Active Codex turn when this elicitation was observed, if app-server could correlate one.
///
/// This is nullable because MCP models elicitation as a standalone server-to-client request
/// identified by the MCP server request id. It may be triggered during a turn, but turn
/// context is app-server correlation rather than part of the protocol identity of the
/// elicitation itself.
pub turn_id: Option<String>,
pub server_name: String,
#[serde(flatten)]
pub request: McpServerElicitationRequest,
// TODO: When core can correlate an elicitation with an MCP tool call, expose the associated
// McpToolCall item id here as an optional field. The current core event does not carry that
// association.
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(tag = "mode", rename_all = "camelCase")]
#[ts(tag = "mode")]
#[ts(export_to = "v2/")]
pub enum McpServerElicitationRequest {
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
Form {
message: String,
requested_schema: JsonValue,
},
#[serde(rename_all = "camelCase")]
#[ts(rename_all = "camelCase")]
Url {
message: String,
url: String,
elicitation_id: String,
},
}
impl From<CoreElicitationRequest> for McpServerElicitationRequest {
fn from(value: CoreElicitationRequest) -> Self {
match value {
CoreElicitationRequest::Form {
message,
requested_schema,
} => Self::Form {
message,
requested_schema,
},
CoreElicitationRequest::Url {
message,
url,
elicitation_id,
} => Self::Url {
message,
url,
elicitation_id,
},
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct McpServerElicitationRequestResponse {
pub action: McpServerElicitationAction,
/// Structured user input for accepted elicitations, mirroring RMCP `CreateElicitationResult`.
///
/// This is nullable because decline/cancel responses have no content.
pub content: Option<JsonValue>,
}
impl From<McpServerElicitationRequestResponse> for rmcp::model::CreateElicitationResult {
fn from(value: McpServerElicitationRequestResponse) -> Self {
Self {
action: value.action.into(),
content: value.content,
}
}
}
impl From<rmcp::model::CreateElicitationResult> for McpServerElicitationRequestResponse {
fn from(value: rmcp::model::CreateElicitationResult) -> Self {
Self {
action: value.action.into(),
content: value.content,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
@@ -4636,300 +4340,6 @@ mod tests {
);
}
#[test]
fn command_exec_params_default_optional_streaming_flags() {
let params = serde_json::from_value::<CommandExecParams>(json!({
"command": ["ls", "-la"],
"timeoutMs": 1000,
"cwd": "/tmp"
}))
.expect("command/exec payload should deserialize");
assert_eq!(
params,
CommandExecParams {
command: vec!["ls".to_string(), "-la".to_string()],
process_id: None,
tty: false,
stream_stdin: false,
stream_stdout_stderr: false,
output_bytes_cap: None,
disable_output_cap: false,
disable_timeout: false,
timeout_ms: Some(1000),
cwd: Some(PathBuf::from("/tmp")),
env: None,
size: None,
sandbox_policy: None,
}
);
}
#[test]
fn command_exec_params_round_trips_disable_timeout() {
let params = CommandExecParams {
command: vec!["sleep".to_string(), "30".to_string()],
process_id: Some("sleep-1".to_string()),
tty: false,
stream_stdin: false,
stream_stdout_stderr: false,
output_bytes_cap: None,
disable_output_cap: false,
disable_timeout: true,
timeout_ms: None,
cwd: None,
env: None,
size: None,
sandbox_policy: None,
};
let value = serde_json::to_value(&params).expect("serialize command/exec params");
assert_eq!(
value,
json!({
"command": ["sleep", "30"],
"processId": "sleep-1",
"disableTimeout": true,
"timeoutMs": null,
"cwd": null,
"env": null,
"size": null,
"sandboxPolicy": null,
"outputBytesCap": null,
})
);
let decoded =
serde_json::from_value::<CommandExecParams>(value).expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_params_round_trips_disable_output_cap() {
let params = CommandExecParams {
command: vec!["yes".to_string()],
process_id: Some("yes-1".to_string()),
tty: false,
stream_stdin: false,
stream_stdout_stderr: true,
output_bytes_cap: None,
disable_output_cap: true,
disable_timeout: false,
timeout_ms: None,
cwd: None,
env: None,
size: None,
sandbox_policy: None,
};
let value = serde_json::to_value(&params).expect("serialize command/exec params");
assert_eq!(
value,
json!({
"command": ["yes"],
"processId": "yes-1",
"streamStdoutStderr": true,
"outputBytesCap": null,
"disableOutputCap": true,
"timeoutMs": null,
"cwd": null,
"env": null,
"size": null,
"sandboxPolicy": null,
})
);
let decoded =
serde_json::from_value::<CommandExecParams>(value).expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_params_round_trips_env_overrides_and_unsets() {
let params = CommandExecParams {
command: vec!["printenv".to_string(), "FOO".to_string()],
process_id: Some("env-1".to_string()),
tty: false,
stream_stdin: false,
stream_stdout_stderr: false,
output_bytes_cap: None,
disable_output_cap: false,
disable_timeout: false,
timeout_ms: None,
cwd: None,
env: Some(HashMap::from([
("FOO".to_string(), Some("override".to_string())),
("BAR".to_string(), Some("added".to_string())),
("BAZ".to_string(), None),
])),
size: None,
sandbox_policy: None,
};
let value = serde_json::to_value(&params).expect("serialize command/exec params");
assert_eq!(
value,
json!({
"command": ["printenv", "FOO"],
"processId": "env-1",
"outputBytesCap": null,
"timeoutMs": null,
"cwd": null,
"env": {
"FOO": "override",
"BAR": "added",
"BAZ": null,
},
"size": null,
"sandboxPolicy": null,
})
);
let decoded =
serde_json::from_value::<CommandExecParams>(value).expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_write_round_trips_close_only_payload() {
let params = CommandExecWriteParams {
process_id: "proc-7".to_string(),
delta_base64: None,
close_stdin: true,
};
let value = serde_json::to_value(&params).expect("serialize command/exec/write params");
assert_eq!(
value,
json!({
"processId": "proc-7",
"deltaBase64": null,
"closeStdin": true,
})
);
let decoded = serde_json::from_value::<CommandExecWriteParams>(value)
.expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_terminate_round_trips() {
let params = CommandExecTerminateParams {
process_id: "proc-8".to_string(),
};
let value = serde_json::to_value(&params).expect("serialize command/exec/terminate params");
assert_eq!(
value,
json!({
"processId": "proc-8",
})
);
let decoded = serde_json::from_value::<CommandExecTerminateParams>(value)
.expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_params_round_trip_with_size() {
let params = CommandExecParams {
command: vec!["top".to_string()],
process_id: Some("pty-1".to_string()),
tty: true,
stream_stdin: false,
stream_stdout_stderr: false,
output_bytes_cap: None,
disable_output_cap: false,
disable_timeout: false,
timeout_ms: None,
cwd: None,
env: None,
size: Some(CommandExecTerminalSize {
rows: 40,
cols: 120,
}),
sandbox_policy: None,
};
let value = serde_json::to_value(&params).expect("serialize command/exec params");
assert_eq!(
value,
json!({
"command": ["top"],
"processId": "pty-1",
"tty": true,
"outputBytesCap": null,
"timeoutMs": null,
"cwd": null,
"env": null,
"size": {
"rows": 40,
"cols": 120,
},
"sandboxPolicy": null,
})
);
let decoded =
serde_json::from_value::<CommandExecParams>(value).expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_resize_round_trips() {
let params = CommandExecResizeParams {
process_id: "proc-9".to_string(),
size: CommandExecTerminalSize {
rows: 50,
cols: 160,
},
};
let value = serde_json::to_value(&params).expect("serialize command/exec/resize params");
assert_eq!(
value,
json!({
"processId": "proc-9",
"size": {
"rows": 50,
"cols": 160,
},
})
);
let decoded = serde_json::from_value::<CommandExecResizeParams>(value)
.expect("deserialize round-trip");
assert_eq!(decoded, params);
}
#[test]
fn command_exec_output_delta_round_trips() {
let notification = CommandExecOutputDeltaNotification {
process_id: "proc-1".to_string(),
stream: CommandExecOutputStream::Stdout,
delta_base64: "AQI=".to_string(),
cap_reached: false,
};
let value = serde_json::to_value(&notification)
.expect("serialize command/exec/outputDelta notification");
assert_eq!(
value,
json!({
"processId": "proc-1",
"stream": "stdout",
"deltaBase64": "AQI=",
"capReached": false,
})
);
let decoded = serde_json::from_value::<CommandExecOutputDeltaNotification>(value)
.expect("deserialize round-trip");
assert_eq!(decoded, notification);
}
#[test]
fn sandbox_policy_round_trips_external_sandbox_network_access() {
let v2_policy = SandboxPolicy::ExternalSandbox {
@@ -4975,65 +4385,6 @@ mod tests {
assert_eq!(back_to_v2, v2_policy);
}
#[test]
fn mcp_server_elicitation_response_round_trips_rmcp_result() {
let rmcp_result = rmcp::model::CreateElicitationResult {
action: rmcp::model::ElicitationAction::Accept,
content: Some(json!({
"confirmed": true,
})),
};
let v2_response = McpServerElicitationRequestResponse::from(rmcp_result.clone());
assert_eq!(
v2_response,
McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Accept,
content: Some(json!({
"confirmed": true,
})),
}
);
assert_eq!(
rmcp::model::CreateElicitationResult::from(v2_response),
rmcp_result
);
}
#[test]
fn mcp_server_elicitation_request_from_core_url_request() {
let request = McpServerElicitationRequest::from(CoreElicitationRequest::Url {
message: "Finish sign-in".to_string(),
url: "https://example.com/complete".to_string(),
elicitation_id: "elicitation-123".to_string(),
});
assert_eq!(
request,
McpServerElicitationRequest::Url {
message: "Finish sign-in".to_string(),
url: "https://example.com/complete".to_string(),
elicitation_id: "elicitation-123".to_string(),
}
);
}
#[test]
fn mcp_server_elicitation_response_serializes_nullable_content() {
let response = McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Decline,
content: None,
};
assert_eq!(
serde_json::to_value(response).expect("response should serialize"),
json!({
"action": "decline",
"content": null,
})
);
}
#[test]
fn sandbox_policy_round_trips_workspace_write_read_only_access() {
let readable_root = test_absolute_path();

View File

@@ -11,15 +11,9 @@ workspace = true
anyhow = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
codex-app-server-protocol = { workspace = true }
codex-core = { workspace = true }
codex-otel = { workspace = true }
codex-protocol = { workspace = true }
codex-utils-cli = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tokio = { workspace = true, features = ["rt"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
tungstenite = { workspace = true }
url = { workspace = true }
uuid = { workspace = true, features = ["v4"] }

View File

@@ -62,17 +62,10 @@ use codex_app_server_protocol::TurnStartParams;
use codex_app_server_protocol::TurnStartResponse;
use codex_app_server_protocol::TurnStatus;
use codex_app_server_protocol::UserInput as V2UserInput;
use codex_core::config::Config;
use codex_otel::current_span_w3c_trace_context;
use codex_otel::otel_provider::OtelProvider;
use codex_protocol::protocol::W3cTraceContext;
use codex_utils_cli::CliConfigOverrides;
use serde::Serialize;
use serde::de::DeserializeOwned;
use serde_json::Value;
use tracing::info_span;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tungstenite::Message;
use tungstenite::WebSocket;
use tungstenite::connect;
@@ -96,7 +89,6 @@ const NOTIFICATIONS_TO_OPT_OUT: &[&str] = &[
"codex/event/item_started",
"codex/event/item_completed",
// v2 item deltas.
"command/exec/outputDelta",
"item/agentMessage/delta",
"item/plan/delta",
"item/commandExecution/outputDelta",
@@ -106,10 +98,6 @@ const NOTIFICATIONS_TO_OPT_OUT: &[&str] = &[
];
const APP_SERVER_GRACEFUL_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
const APP_SERVER_GRACEFUL_SHUTDOWN_POLL_INTERVAL: Duration = Duration::from_millis(100);
const DEFAULT_ANALYTICS_ENABLED: bool = true;
const OTEL_SERVICE_NAME: &str = "codex-app-server-test-client";
const TRACE_DISABLED_MESSAGE: &str =
"Not enabled - enable tracing in $CODEX_HOME/config.toml to get a trace URL!";
/// Minimal launcher that initializes the Codex app-server and logs the handshake.
#[derive(Parser)]
@@ -248,7 +236,7 @@ enum CliCommand {
},
}
pub async fn run() -> Result<()> {
pub fn run() -> Result<()> {
let Cli {
codex_bin,
url,
@@ -268,7 +256,7 @@ pub async fn run() -> Result<()> {
CliCommand::SendMessage { user_message } => {
ensure_dynamic_tools_unused(&dynamic_tools, "send-message")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
send_message(&endpoint, &config_overrides, user_message).await
send_message(&endpoint, &config_overrides, user_message)
}
CliCommand::SendMessageV2 {
experimental_api,
@@ -282,7 +270,6 @@ pub async fn run() -> Result<()> {
experimental_api,
&dynamic_tools,
)
.await
}
CliCommand::ResumeMessageV2 {
thread_id,
@@ -296,29 +283,28 @@ pub async fn run() -> Result<()> {
user_message,
&dynamic_tools,
)
.await
}
CliCommand::ThreadResume { thread_id } => {
ensure_dynamic_tools_unused(&dynamic_tools, "thread-resume")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
thread_resume_follow(&endpoint, &config_overrides, thread_id).await
thread_resume_follow(&endpoint, &config_overrides, thread_id)
}
CliCommand::Watch => {
ensure_dynamic_tools_unused(&dynamic_tools, "watch")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
watch(&endpoint, &config_overrides).await
watch(&endpoint, &config_overrides)
}
CliCommand::TriggerCmdApproval { user_message } => {
let endpoint = resolve_endpoint(codex_bin, url)?;
trigger_cmd_approval(&endpoint, &config_overrides, user_message, &dynamic_tools).await
trigger_cmd_approval(&endpoint, &config_overrides, user_message, &dynamic_tools)
}
CliCommand::TriggerPatchApproval { user_message } => {
let endpoint = resolve_endpoint(codex_bin, url)?;
trigger_patch_approval(&endpoint, &config_overrides, user_message, &dynamic_tools).await
trigger_patch_approval(&endpoint, &config_overrides, user_message, &dynamic_tools)
}
CliCommand::NoTriggerCmdApproval => {
let endpoint = resolve_endpoint(codex_bin, url)?;
no_trigger_cmd_approval(&endpoint, &config_overrides, &dynamic_tools).await
no_trigger_cmd_approval(&endpoint, &config_overrides, &dynamic_tools)
}
CliCommand::SendFollowUpV2 {
first_message,
@@ -332,7 +318,6 @@ pub async fn run() -> Result<()> {
follow_up_message,
&dynamic_tools,
)
.await
}
CliCommand::TriggerZshForkMultiCmdApproval {
user_message,
@@ -348,27 +333,26 @@ pub async fn run() -> Result<()> {
abort_on,
&dynamic_tools,
)
.await
}
CliCommand::TestLogin => {
ensure_dynamic_tools_unused(&dynamic_tools, "test-login")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
test_login(&endpoint, &config_overrides).await
test_login(&endpoint, &config_overrides)
}
CliCommand::GetAccountRateLimits => {
ensure_dynamic_tools_unused(&dynamic_tools, "get-account-rate-limits")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
get_account_rate_limits(&endpoint, &config_overrides).await
get_account_rate_limits(&endpoint, &config_overrides)
}
CliCommand::ModelList => {
ensure_dynamic_tools_unused(&dynamic_tools, "model-list")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
model_list(&endpoint, &config_overrides).await
model_list(&endpoint, &config_overrides)
}
CliCommand::ThreadList { limit } => {
ensure_dynamic_tools_unused(&dynamic_tools, "thread-list")?;
let endpoint = resolve_endpoint(codex_bin, url)?;
thread_list(&endpoint, &config_overrides, limit).await
thread_list(&endpoint, &config_overrides, limit)
}
}
}
@@ -503,15 +487,7 @@ fn shell_quote(input: &str) -> String {
format!("'{}'", input.replace('\'', "'\\''"))
}
struct SendMessagePolicies<'a> {
command_name: &'static str,
experimental_api: bool,
approval_policy: Option<AskForApproval>,
sandbox_policy: Option<SandboxPolicy>,
dynamic_tools: &'a Option<Vec<DynamicToolSpec>>,
}
async fn send_message(
fn send_message(
endpoint: &Endpoint,
config_overrides: &[String],
user_message: String,
@@ -521,18 +497,14 @@ async fn send_message(
endpoint,
config_overrides,
user_message,
SendMessagePolicies {
command_name: "send-message",
experimental_api: false,
approval_policy: None,
sandbox_policy: None,
dynamic_tools: &dynamic_tools,
},
false,
None,
None,
&dynamic_tools,
)
.await
}
pub async fn send_message_v2(
pub fn send_message_v2(
codex_bin: &Path,
config_overrides: &[String],
user_message: String,
@@ -546,10 +518,9 @@ pub async fn send_message_v2(
true,
dynamic_tools,
)
.await
}
async fn send_message_v2_endpoint(
fn send_message_v2_endpoint(
endpoint: &Endpoint,
config_overrides: &[String],
user_message: String,
@@ -564,18 +535,14 @@ async fn send_message_v2_endpoint(
endpoint,
config_overrides,
user_message,
SendMessagePolicies {
command_name: "send-message-v2",
experimental_api,
approval_policy: None,
sandbox_policy: None,
dynamic_tools,
},
experimental_api,
None,
None,
dynamic_tools,
)
.await
}
async fn trigger_zsh_fork_multi_cmd_approval(
fn trigger_zsh_fork_multi_cmd_approval(
endpoint: &Endpoint,
config_overrides: &[String],
user_message: Option<String>,
@@ -592,96 +559,89 @@ async fn trigger_zsh_fork_multi_cmd_approval(
let default_prompt = "Run this exact command using shell command execution without rewriting or splitting it: /usr/bin/true && /usr/bin/true";
let message = user_message.unwrap_or_else(|| default_prompt.to_string());
with_client(
"trigger-zsh-fork-multi-cmd-approval",
endpoint,
config_overrides,
|client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
let thread_response = client.thread_start(ThreadStartParams {
dynamic_tools: dynamic_tools.clone(),
..Default::default()
})?;
println!("< thread/start response: {thread_response:?}");
let thread_response = client.thread_start(ThreadStartParams {
dynamic_tools: dynamic_tools.clone(),
..Default::default()
})?;
println!("< thread/start response: {thread_response:?}");
client.command_approval_behavior = match abort_on {
Some(index) => CommandApprovalBehavior::AbortOn(index),
None => CommandApprovalBehavior::AlwaysAccept,
};
client.command_approval_count = 0;
client.command_approval_item_ids.clear();
client.command_execution_statuses.clear();
client.last_turn_status = None;
client.command_approval_behavior = match abort_on {
Some(index) => CommandApprovalBehavior::AbortOn(index),
None => CommandApprovalBehavior::AlwaysAccept,
};
client.command_approval_count = 0;
client.command_approval_item_ids.clear();
client.command_execution_statuses.clear();
client.last_turn_status = None;
let mut turn_params = TurnStartParams {
thread_id: thread_response.thread.id.clone(),
input: vec![V2UserInput::Text {
text: message,
text_elements: Vec::new(),
}],
..Default::default()
};
turn_params.approval_policy = Some(AskForApproval::OnRequest);
turn_params.sandbox_policy = Some(SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
});
let mut turn_params = TurnStartParams {
thread_id: thread_response.thread.id.clone(),
input: vec![V2UserInput::Text {
text: message,
text_elements: Vec::new(),
}],
..Default::default()
};
turn_params.approval_policy = Some(AskForApproval::OnRequest);
turn_params.sandbox_policy = Some(SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
});
let turn_response = client.turn_start(turn_params)?;
println!("< turn/start response: {turn_response:?}");
client.stream_turn(&thread_response.thread.id, &turn_response.turn.id)?;
let turn_response = client.turn_start(turn_params)?;
println!("< turn/start response: {turn_response:?}");
client.stream_turn(&thread_response.thread.id, &turn_response.turn.id)?;
if client.command_approval_count < min_approvals {
bail!(
"expected at least {min_approvals} command approvals, got {}",
client.command_approval_count
);
}
let mut approvals_per_item = std::collections::BTreeMap::new();
for item_id in &client.command_approval_item_ids {
*approvals_per_item.entry(item_id.clone()).or_insert(0usize) += 1;
}
let max_approvals_for_one_item =
approvals_per_item.values().copied().max().unwrap_or(0);
if max_approvals_for_one_item < min_approvals {
bail!(
"expected at least {min_approvals} approvals for one command item, got max {max_approvals_for_one_item} with map {approvals_per_item:?}"
);
}
let last_command_status = client.command_execution_statuses.last();
if abort_on.is_none() {
if last_command_status != Some(&CommandExecutionStatus::Completed) {
bail!("expected completed command execution, got {last_command_status:?}");
}
if client.last_turn_status != Some(TurnStatus::Completed) {
bail!(
"expected completed turn in all-accept flow, got {:?}",
client.last_turn_status
);
}
} else if last_command_status == Some(&CommandExecutionStatus::Completed) {
bail!(
"expected non-completed command execution in mixed approval/decline flow, got {last_command_status:?}"
);
}
println!(
"[zsh-fork multi-approval summary] approvals={}, approvals_per_item={approvals_per_item:?}, command_statuses={:?}, turn_status={:?}",
client.command_approval_count,
client.command_execution_statuses,
client.last_turn_status
if client.command_approval_count < min_approvals {
bail!(
"expected at least {min_approvals} command approvals, got {}",
client.command_approval_count
);
}
let mut approvals_per_item = std::collections::BTreeMap::new();
for item_id in &client.command_approval_item_ids {
*approvals_per_item.entry(item_id.clone()).or_insert(0usize) += 1;
}
let max_approvals_for_one_item = approvals_per_item.values().copied().max().unwrap_or(0);
if max_approvals_for_one_item < min_approvals {
bail!(
"expected at least {min_approvals} approvals for one command item, got max {max_approvals_for_one_item} with map {approvals_per_item:?}"
);
}
Ok(())
},
)
.await
let last_command_status = client.command_execution_statuses.last();
if abort_on.is_none() {
if last_command_status != Some(&CommandExecutionStatus::Completed) {
bail!("expected completed command execution, got {last_command_status:?}");
}
if client.last_turn_status != Some(TurnStatus::Completed) {
bail!(
"expected completed turn in all-accept flow, got {:?}",
client.last_turn_status
);
}
} else if last_command_status == Some(&CommandExecutionStatus::Completed) {
bail!(
"expected non-completed command execution in mixed approval/decline flow, got {last_command_status:?}"
);
}
println!(
"[zsh-fork multi-approval summary] approvals={}, approvals_per_item={approvals_per_item:?}, command_statuses={:?}, turn_status={:?}",
client.command_approval_count,
client.command_execution_statuses,
client.last_turn_status
);
Ok(())
})
}
async fn resume_message_v2(
fn resume_message_v2(
endpoint: &Endpoint,
config_overrides: &[String],
thread_id: String,
@@ -690,7 +650,7 @@ async fn resume_message_v2(
) -> Result<()> {
ensure_dynamic_tools_unused(dynamic_tools, "resume-message-v2")?;
with_client("resume-message-v2", endpoint, config_overrides, |client| {
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
@@ -714,42 +674,39 @@ async fn resume_message_v2(
Ok(())
})
.await
}
async fn thread_resume_follow(
fn thread_resume_follow(
endpoint: &Endpoint,
config_overrides: &[String],
thread_id: String,
) -> Result<()> {
with_client("thread-resume", endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
let mut client = CodexClient::connect(endpoint, config_overrides)?;
let resume_response = client.thread_resume(ThreadResumeParams {
thread_id,
..Default::default()
})?;
println!("< thread/resume response: {resume_response:?}");
println!("< streaming notifications until process is terminated");
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
client.stream_notifications_forever()
})
.await
let resume_response = client.thread_resume(ThreadResumeParams {
thread_id,
..Default::default()
})?;
println!("< thread/resume response: {resume_response:?}");
println!("< streaming notifications until process is terminated");
client.stream_notifications_forever()
}
async fn watch(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client("watch", endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
println!("< streaming inbound messages until process is terminated");
fn watch(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
let mut client = CodexClient::connect(endpoint, config_overrides)?;
client.stream_notifications_forever()
})
.await
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
println!("< streaming inbound messages until process is terminated");
client.stream_notifications_forever()
}
async fn trigger_cmd_approval(
fn trigger_cmd_approval(
endpoint: &Endpoint,
config_overrides: &[String],
user_message: Option<String>,
@@ -762,21 +719,17 @@ async fn trigger_cmd_approval(
endpoint,
config_overrides,
message,
SendMessagePolicies {
command_name: "trigger-cmd-approval",
experimental_api: true,
approval_policy: Some(AskForApproval::OnRequest),
sandbox_policy: Some(SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
}),
dynamic_tools,
},
true,
Some(AskForApproval::OnRequest),
Some(SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
}),
dynamic_tools,
)
.await
}
async fn trigger_patch_approval(
fn trigger_patch_approval(
endpoint: &Endpoint,
config_overrides: &[String],
user_message: Option<String>,
@@ -789,21 +742,17 @@ async fn trigger_patch_approval(
endpoint,
config_overrides,
message,
SendMessagePolicies {
command_name: "trigger-patch-approval",
experimental_api: true,
approval_policy: Some(AskForApproval::OnRequest),
sandbox_policy: Some(SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
}),
dynamic_tools,
},
true,
Some(AskForApproval::OnRequest),
Some(SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::FullAccess,
network_access: false,
}),
dynamic_tools,
)
.await
}
async fn no_trigger_cmd_approval(
fn no_trigger_cmd_approval(
endpoint: &Endpoint,
config_overrides: &[String],
dynamic_tools: &Option<Vec<DynamicToolSpec>>,
@@ -813,67 +762,60 @@ async fn no_trigger_cmd_approval(
endpoint,
config_overrides,
prompt.to_string(),
SendMessagePolicies {
command_name: "no-trigger-cmd-approval",
experimental_api: true,
approval_policy: None,
sandbox_policy: None,
dynamic_tools,
},
true,
None,
None,
dynamic_tools,
)
.await
}
async fn send_message_v2_with_policies(
fn send_message_v2_with_policies(
endpoint: &Endpoint,
config_overrides: &[String],
user_message: String,
policies: SendMessagePolicies<'_>,
experimental_api: bool,
approval_policy: Option<AskForApproval>,
sandbox_policy: Option<SandboxPolicy>,
dynamic_tools: &Option<Vec<DynamicToolSpec>>,
) -> Result<()> {
with_client(
policies.command_name,
endpoint,
config_overrides,
|client| {
let initialize = client.initialize_with_experimental_api(policies.experimental_api)?;
println!("< initialize response: {initialize:?}");
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize_with_experimental_api(experimental_api)?;
println!("< initialize response: {initialize:?}");
let thread_response = client.thread_start(ThreadStartParams {
dynamic_tools: policies.dynamic_tools.clone(),
..Default::default()
})?;
println!("< thread/start response: {thread_response:?}");
let mut turn_params = TurnStartParams {
thread_id: thread_response.thread.id.clone(),
input: vec![V2UserInput::Text {
text: user_message,
// Test client sends plain text without UI element ranges.
text_elements: Vec::new(),
}],
..Default::default()
};
turn_params.approval_policy = policies.approval_policy;
turn_params.sandbox_policy = policies.sandbox_policy;
let thread_response = client.thread_start(ThreadStartParams {
dynamic_tools: dynamic_tools.clone(),
..Default::default()
})?;
println!("< thread/start response: {thread_response:?}");
let mut turn_params = TurnStartParams {
thread_id: thread_response.thread.id.clone(),
input: vec![V2UserInput::Text {
text: user_message,
// Test client sends plain text without UI element ranges.
text_elements: Vec::new(),
}],
..Default::default()
};
turn_params.approval_policy = approval_policy;
turn_params.sandbox_policy = sandbox_policy;
let turn_response = client.turn_start(turn_params)?;
println!("< turn/start response: {turn_response:?}");
let turn_response = client.turn_start(turn_params)?;
println!("< turn/start response: {turn_response:?}");
client.stream_turn(&thread_response.thread.id, &turn_response.turn.id)?;
client.stream_turn(&thread_response.thread.id, &turn_response.turn.id)?;
Ok(())
},
)
.await
Ok(())
})
}
async fn send_follow_up_v2(
fn send_follow_up_v2(
endpoint: &Endpoint,
config_overrides: &[String],
first_message: String,
follow_up_message: String,
dynamic_tools: &Option<Vec<DynamicToolSpec>>,
) -> Result<()> {
with_client("send-follow-up-v2", endpoint, config_overrides, |client| {
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
@@ -911,11 +853,10 @@ async fn send_follow_up_v2(
Ok(())
})
.await
}
async fn test_login(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client("test-login", endpoint, config_overrides, |client| {
fn test_login(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
@@ -942,29 +883,22 @@ async fn test_login(endpoint: &Endpoint, config_overrides: &[String]) -> Result<
);
}
})
.await
}
async fn get_account_rate_limits(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client(
"get-account-rate-limits",
endpoint,
config_overrides,
|client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
fn get_account_rate_limits(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
let response = client.get_account_rate_limits()?;
println!("< account/rateLimits/read response: {response:?}");
let response = client.get_account_rate_limits()?;
println!("< account/rateLimits/read response: {response:?}");
Ok(())
},
)
.await
Ok(())
})
}
async fn model_list(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client("model-list", endpoint, config_overrides, |client| {
fn model_list(endpoint: &Endpoint, config_overrides: &[String]) -> Result<()> {
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
@@ -973,11 +907,10 @@ async fn model_list(endpoint: &Endpoint, config_overrides: &[String]) -> Result<
Ok(())
})
.await
}
async fn thread_list(endpoint: &Endpoint, config_overrides: &[String], limit: u32) -> Result<()> {
with_client("thread-list", endpoint, config_overrides, |client| {
fn thread_list(endpoint: &Endpoint, config_overrides: &[String], limit: u32) -> Result<()> {
with_client(endpoint, config_overrides, |client| {
let initialize = client.initialize()?;
println!("< initialize response: {initialize:?}");
@@ -995,28 +928,16 @@ async fn thread_list(endpoint: &Endpoint, config_overrides: &[String], limit: u3
Ok(())
})
.await
}
async fn with_client<T>(
command_name: &'static str,
fn with_client<T>(
endpoint: &Endpoint,
config_overrides: &[String],
f: impl FnOnce(&mut CodexClient) -> Result<T>,
) -> Result<T> {
let tracing = TestClientTracing::initialize(config_overrides).await?;
let command_span = info_span!(
"app_server_test_client.command",
otel.kind = "client",
otel.name = command_name,
app_server_test_client.command = command_name,
);
let trace_summary = command_span.in_scope(|| TraceSummary::capture(tracing.traces_enabled));
let result = command_span.in_scope(|| {
let mut client = CodexClient::connect(endpoint, config_overrides)?;
f(&mut client)
});
print_trace_summary(&trace_summary);
let mut client = CodexClient::connect(endpoint, config_overrides)?;
let result = f(&mut client);
client.print_trace_summary();
result
}
@@ -1074,6 +995,8 @@ struct CodexClient {
command_approval_item_ids: Vec<String>,
command_execution_statuses: Vec<CommandExecutionStatus>,
last_turn_status: Option<TurnStatus>,
trace_id: String,
trace_root_span_id: String,
}
#[derive(Debug, Clone, Copy)]
@@ -1133,6 +1056,8 @@ impl CodexClient {
command_approval_item_ids: Vec::new(),
command_execution_statuses: Vec::new(),
last_turn_status: None,
trace_id: generate_trace_id(),
trace_root_span_id: generate_parent_span_id(),
})
}
@@ -1154,6 +1079,8 @@ impl CodexClient {
command_approval_item_ids: Vec::new(),
command_execution_statuses: Vec::new(),
last_turn_status: None,
trace_id: generate_trace_id(),
trace_root_span_id: generate_parent_span_id(),
})
}
@@ -1375,31 +1302,37 @@ impl CodexClient {
where
T: DeserializeOwned,
{
let request_span = info_span!(
"app_server_test_client.request",
otel.kind = "client",
otel.name = method,
rpc.system = "jsonrpc",
rpc.method = method,
rpc.request_id = ?request_id,
);
request_span.in_scope(|| {
self.write_request(&request)?;
self.wait_for_response(request_id, method)
})
self.write_request(&request)?;
self.wait_for_response(request_id, method)
}
fn write_request(&mut self, request: &ClientRequest) -> Result<()> {
let request_value = serde_json::to_value(request)?;
let mut request: JSONRPCRequest = serde_json::from_value(request_value)
.context("client request was not a valid JSON-RPC request")?;
request.trace = current_span_w3c_trace_context();
let request = self.jsonrpc_request_with_trace(request)?;
let request_json = serde_json::to_string(&request)?;
let request_pretty = serde_json::to_string_pretty(&request)?;
print_multiline_with_prefix("> ", &request_pretty);
self.write_payload(&request_json)
}
fn jsonrpc_request_with_trace(&self, request: &ClientRequest) -> Result<JSONRPCRequest> {
let request_value = serde_json::to_value(request)?;
let mut request: JSONRPCRequest = serde_json::from_value(request_value)
.context("client request was not a valid JSON-RPC request")?;
request.trace = Some(W3cTraceContext {
traceparent: Some(format!(
"00-{}-{}-01",
self.trace_id, self.trace_root_span_id
)),
tracestate: None,
});
Ok(request)
}
fn print_trace_summary(&self) {
println!("\n[Datadog trace]");
println!("go/trace/{}\n", self.trace_id);
}
fn wait_for_response<T>(&mut self, request_id: RequestId, method: &str) -> Result<T>
where
T: DeserializeOwned,
@@ -1665,91 +1598,21 @@ impl CodexClient {
}
}
fn generate_trace_id() -> String {
Uuid::new_v4().simple().to_string()
}
fn generate_parent_span_id() -> String {
let uuid = Uuid::new_v4().simple().to_string();
uuid[..16].to_string()
}
fn print_multiline_with_prefix(prefix: &str, payload: &str) {
for line in payload.lines() {
println!("{prefix}{line}");
}
}
struct TestClientTracing {
_otel_provider: Option<OtelProvider>,
traces_enabled: bool,
}
impl TestClientTracing {
async fn initialize(config_overrides: &[String]) -> Result<Self> {
let cli_kv_overrides = CliConfigOverrides {
raw_overrides: config_overrides.to_vec(),
}
.parse_overrides()
.map_err(|e| anyhow::anyhow!("error parsing -c overrides: {e}"))?;
let config = Config::load_with_cli_overrides(cli_kv_overrides)
.await
.context("error loading config")?;
let otel_provider = codex_core::otel_init::build_provider(
&config,
env!("CARGO_PKG_VERSION"),
Some(OTEL_SERVICE_NAME),
DEFAULT_ANALYTICS_ENABLED,
)
.map_err(|e| anyhow::anyhow!("error loading otel config: {e}"))?;
let traces_enabled = otel_provider
.as_ref()
.and_then(|provider| provider.tracer_provider.as_ref())
.is_some();
if let Some(provider) = otel_provider.as_ref()
&& traces_enabled
{
let _ = tracing_subscriber::registry()
.with(provider.tracing_layer())
.try_init();
}
Ok(Self {
traces_enabled,
_otel_provider: otel_provider,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum TraceSummary {
Enabled { url: String },
Disabled,
}
impl TraceSummary {
fn capture(traces_enabled: bool) -> Self {
if !traces_enabled {
return Self::Disabled;
}
current_span_w3c_trace_context()
.as_ref()
.and_then(trace_url_from_context)
.map_or(Self::Disabled, |url| Self::Enabled { url })
}
}
fn trace_url_from_context(trace: &W3cTraceContext) -> Option<String> {
let traceparent = trace.traceparent.as_deref()?;
let mut parts = traceparent.split('-');
match (parts.next(), parts.next(), parts.next(), parts.next()) {
(Some(_version), Some(trace_id), Some(_span_id), Some(_trace_flags))
if trace_id.len() == 32 =>
{
Some(format!("go/trace/{trace_id}"))
}
_ => None,
}
}
fn print_trace_summary(trace_summary: &TraceSummary) {
println!("\n[Datadog trace]");
match trace_summary {
TraceSummary::Enabled { url } => println!("{url}\n"),
TraceSummary::Disabled => println!("{TRACE_DISABLED_MESSAGE}\n"),
}
}
impl Drop for CodexClient {
fn drop(&mut self) {
let ClientTransport::Stdio { child, stdin, .. } = &mut self.transport else {

View File

@@ -1,7 +1,5 @@
use anyhow::Result;
use tokio::runtime::Builder;
fn main() -> Result<()> {
let runtime = Builder::new_current_thread().enable_all().build()?;
runtime.block_on(codex_app_server_test_client::run())
codex_app_server_test_client::run()
}

View File

@@ -18,14 +18,12 @@ workspace = true
[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
base64 = { workspace = true }
codex-arg0 = { workspace = true }
codex-cloud-requirements = { workspace = true }
codex-core = { workspace = true }
codex-otel = { workspace = true }
codex-shell-command = { workspace = true }
codex-utils-cli = { workspace = true }
codex-utils-pty = { workspace = true }
codex-backend-client = { workspace = true }
codex-file-search = { workspace = true }
codex-chatgpt = { workspace = true }
@@ -66,11 +64,11 @@ axum = { workspace = true, default-features = false, features = [
"json",
"tokio",
] }
base64 = { workspace = true }
core_test_support = { workspace = true }
codex-utils-cargo-bin = { workspace = true }
pretty_assertions = { workspace = true }
rmcp = { workspace = true, default-features = false, features = [
"elicitation",
"server",
"transport-streamable-http-server",
] }

View File

@@ -144,23 +144,20 @@ Example with notification opt-out:
- `thread/realtime/stop` — stop the active realtime session for the thread (experimental); returns `{}`.
- `review/start` — kick off Codexs automated reviewer for a thread; responds like `turn/start` and emits `item/started`/`item/completed` notifications with `enteredReviewMode` and `exitedReviewMode` items, plus a final assistant `agentMessage` containing the review.
- `command/exec` — run a single command under the server sandbox without starting a thread/turn (handy for utilities and validation).
- `command/exec/resize` — resize a running PTY-backed `command/exec` session by `processId`; returns `{}`.
- `model/list` — list available models (set `includeHidden: true` to include entries with `hidden: true`), with reasoning effort options, optional legacy `upgrade` model ids, optional `upgradeInfo` metadata (`model`, `upgradeCopy`, `modelLink`, `migrationMarkdown`), and optional `availabilityNux` metadata.
- `experimentalFeature/list` — list feature flags with stage metadata (`beta`, `underDevelopment`, `stable`, etc.), enabled/default-enabled state, and cursor pagination. For non-beta flags, `displayName`/`description`/`announcement` are `null`.
- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination). This response omits built-in developer instructions; clients should either pass `settings.developer_instructions: null` when setting a mode to use Codex's built-in instructions, or provide their own instructions explicitly.
- `skills/list` — list skills for one or more `cwd` values (optional `forceReload`).
- `plugin/list` — list discovered marketplaces reachable from optional `cwds` (unioned into a single list). When `cwds` is omitted, only home-scoped marketplaces are considered. Includes each plugin's current `enabled` state from config (**under development; do not call from production clients yet**).
- `skills/changed` — notification emitted when watched local skill files change.
- `skills/remote/list` — list public remote skills (**under development; do not call from production clients yet**).
- `skills/remote/export` — download a remote skill by `hazelnutId` into `skills` under `codex_home` (**under development; do not call from production clients yet**).
- `app/list` — list available apps.
- `skills/config/write` — write user-level skill config by path.
- `plugin/install` — install a plugin from a discovered marketplace entry by `pluginName` and `marketplacePath` (**under development; do not call from production clients yet**).
- `mcpServer/oauth/login` — start an OAuth login for a configured MCP server; returns an `authorization_url` and later emits `mcpServer/oauthLogin/completed` once the browser flow finishes.
- `tool/requestUserInput` — prompt the user with 13 short questions for a tool call and return their answers (experimental).
- `config/mcpServer/reload` — reload MCP server config from disk and queue a refresh for loaded threads (applied on each thread's next active turn); returns `{}`. Use this after editing `config.toml` without restarting the server.
- `mcpServerStatus/list` — enumerate configured MCP servers with their tools, resources, resource templates, and auth status; supports cursor+limit pagination.
- `windowsSandbox/setupStart` — start Windows sandbox setup for the selected mode (`elevated` or `unelevated`); accepts an optional `cwd` to target setup for a specific workspace, returns `{ started: true }` immediately, and later emits `windowsSandbox/setupCompleted`.
- `windowsSandbox/setupStart` — start Windows sandbox setup for the selected mode (`elevated` or `unelevated`); returns `{ started: true }` immediately and later emits `windowsSandbox/setupCompleted`.
- `feedback/upload` — submit a feedback report (classification + optional reason/logs, conversation_id, and optional `extraLogFiles` attachments array); returns the tracking thread id.
- `command/exec` — run a single command under the server sandbox without starting a thread/turn (handy for utilities and validation).
- `config/read` — fetch the effective config on disk after resolving config layering.
@@ -183,6 +180,7 @@ Start a fresh thread when you need a new Codex conversation.
"approvalPolicy": "never",
"sandbox": "workspaceWrite",
"personality": "friendly",
"serviceTier": "flex",
"serviceName": "my_app_server_client", // optional metrics tag (`service_name`)
// Experimental: requires opt-in
"dynamicTools": [
@@ -211,6 +209,7 @@ Start a fresh thread when you need a new Codex conversation.
```
Valid `personality` values are `"friendly"`, `"pragmatic"`, and `"none"`. When `"none"` is selected, the personality placeholder is replaced with an empty string.
Valid `serviceTier` values are `"fast"` and `"flex"`.
To continue a stored session, call `thread/resume` with the `thread.id` you previously recorded. The response shape matches `thread/start`, and no additional notifications are emitted. You can also pass the same configuration overrides supported by `thread/start`, such as `personality`:
@@ -418,6 +417,7 @@ You can optionally specify config overrides on the new turn. If specified, these
"networkAccess": true
},
"model": "gpt-5.1-codex",
"serviceTier": "flex",
"effort": "medium",
"summary": "concise",
"personality": "friendly",
@@ -594,21 +594,11 @@ Run a standalone command (argv vector) in the servers sandbox without creatin
```json
{ "method": "command/exec", "id": 32, "params": {
"command": ["ls", "-la"],
"processId": "ls-1", // optional string; required for streaming and ability to terminate the process
"cwd": "/Users/me/project", // optional; defaults to server cwd
"env": { "FOO": "override" }, // optional; merges into the server env and overrides matching names
"size": { "rows": 40, "cols": 120 }, // optional; PTY size in character cells, only valid with tty=true
"sandboxPolicy": { "type": "workspaceWrite" }, // optional; defaults to user config
"outputBytesCap": 1048576, // optional; per-stream capture cap
"disableOutputCap": false, // optional; cannot be combined with outputBytesCap
"timeoutMs": 10000, // optional; ms timeout; defaults to server timeout
"disableTimeout": false // optional; cannot be combined with timeoutMs
} }
{ "id": 32, "result": {
"exitCode": 0,
"stdout": "...",
"stderr": ""
"timeoutMs": 10000 // optional; ms timeout; defaults to server timeout
} }
{ "id": 32, "result": { "exitCode": 0, "stdout": "...", "stderr": "" } }
```
- For clients that are already sandboxed externally, set `sandboxPolicy` to `{"type":"externalSandbox","networkAccess":"enabled"}` (or omit `networkAccess` to keep it restricted). Codex will not enforce its own sandbox in this mode; it tells the model it has full file-system access and passes the `networkAccess` state through `environment_context`.
@@ -617,70 +607,7 @@ Notes:
- Empty `command` arrays are rejected.
- `sandboxPolicy` accepts the same shape used by `turn/start` (e.g., `dangerFullAccess`, `readOnly`, `workspaceWrite` with flags, `externalSandbox` with `networkAccess` `restricted|enabled`).
- `env` merges into the environment produced by the server's shell environment policy. Matching names are overridden; unspecified variables are left intact.
- When omitted, `timeoutMs` falls back to the server default.
- When omitted, `outputBytesCap` falls back to the server default of 1 MiB per stream.
- `disableOutputCap: true` disables stdout/stderr capture truncation for that `command/exec` request. It cannot be combined with `outputBytesCap`.
- `disableTimeout: true` disables the timeout entirely for that `command/exec` request. It cannot be combined with `timeoutMs`.
- `processId` is optional for buffered execution. When omitted, Codex generates an internal id for lifecycle tracking, but `tty`, `streamStdin`, and `streamStdoutStderr` must stay disabled and follow-up `command/exec/write` / `command/exec/terminate` calls are not available for that command.
- `size` is only valid when `tty: true`. It sets the initial PTY size in character cells.
- Buffered Windows sandbox execution accepts `processId` for correlation, but `command/exec/write` and `command/exec/terminate` are still unsupported for those requests.
- Buffered Windows sandbox execution also requires the default output cap; custom `outputBytesCap` and `disableOutputCap` are unsupported there.
- `tty`, `streamStdin`, and `streamStdoutStderr` are optional booleans. Legacy requests that omit them continue to use buffered execution.
- `tty: true` implies PTY mode plus `streamStdin: true` and `streamStdoutStderr: true`.
- `tty` and `streamStdin` do not disable the timeout on their own; omit `timeoutMs` to use the server default timeout, or set `disableTimeout: true` to keep the process alive until exit or explicit termination.
- `outputBytesCap` applies independently to `stdout` and `stderr`, and streamed bytes are not duplicated into the final response.
- The `command/exec` response is deferred until the process exits and is sent only after all `command/exec/outputDelta` notifications for that connection have been emitted.
- `command/exec/outputDelta` notifications are connection-scoped. If the originating connection closes, the server terminates the process.
Streaming stdin/stdout uses base64 so PTY sessions can carry arbitrary bytes:
```json
{ "method": "command/exec", "id": 33, "params": {
"command": ["bash", "-i"],
"processId": "bash-1",
"tty": true,
"outputBytesCap": 32768
} }
{ "method": "command/exec/outputDelta", "params": {
"processId": "bash-1",
"stream": "stdout",
"deltaBase64": "YmFzaC00LjQkIA==",
"capReached": false
} }
{ "method": "command/exec/write", "id": 34, "params": {
"processId": "bash-1",
"deltaBase64": "cHdkCg=="
} }
{ "id": 34, "result": {} }
{ "method": "command/exec/write", "id": 35, "params": {
"processId": "bash-1",
"closeStdin": true
} }
{ "id": 35, "result": {} }
{ "method": "command/exec/resize", "id": 36, "params": {
"processId": "bash-1",
"size": { "rows": 48, "cols": 160 }
} }
{ "id": 36, "result": {} }
{ "method": "command/exec/terminate", "id": 37, "params": {
"processId": "bash-1"
} }
{ "id": 37, "result": {} }
{ "id": 33, "result": {
"exitCode": 137,
"stdout": "",
"stderr": ""
} }
```
- `command/exec/write` accepts either `deltaBase64`, `closeStdin`, or both.
- Clients may supply a connection-scoped string `processId` in `command/exec`; `command/exec/write`, `command/exec/resize`, and `command/exec/terminate` only accept those client-supplied string ids.
- `command/exec/outputDelta.processId` is always the client-supplied string id from the original `command/exec` request.
- `command/exec/outputDelta.stream` is `stdout` or `stderr`. PTY mode multiplexes terminal output through `stdout`.
- `command/exec/outputDelta.capReached` is `true` on the final streamed chunk for a stream when `outputBytesCap` truncates that stream; later output on that stream is dropped.
- `command/exec.params.env` overrides the server-computed environment per key; set a key to `null` to unset an inherited variable.
- `command/exec/resize` is only supported for PTY-backed `command/exec` sessions.
## Events
@@ -839,20 +766,6 @@ UI guidance for IDEs: surface an approval dialog as soon as the request arrives.
When the client responds to `item/tool/requestUserInput`, the server emits `serverRequest/resolved` with `{ threadId, requestId }`. If the pending request is cleared by turn start, turn completion, or turn interruption before the client answers, the server emits the same notification for that cleanup.
### MCP server elicitations
MCP servers can interrupt a turn and ask the client for structured input via `mcpServer/elicitation/request`.
Order of messages:
1. `mcpServer/elicitation/request` (request) — includes `threadId`, nullable `turnId`, `serverName`, and either:
- a form request: `{ "mode": "form", "message": "...", "requestedSchema": { ... } }`
- a URL request: `{ "mode": "url", "message": "...", "url": "...", "elicitationId": "..." }`
2. Client response — `{ "action": "accept", "content": ... }`, `{ "action": "decline", "content": null }`, or `{ "action": "cancel", "content": null }`.
3. `serverRequest/resolved``{ threadId, requestId }` confirms the pending request has been resolved or cleared, including lifecycle cleanup on turn start/complete/interrupt.
`turnId` is best-effort. When the elicitation is correlated with an active turn, the request includes that turn id; otherwise it is `null`.
### Dynamic tool calls (experimental)
`dynamicTools` on `thread/start` and the corresponding `item/tool/call` request/response flow are experimental APIs. To enable them, set `initialize.params.capabilities.experimentalApi = true`.

View File

@@ -45,9 +45,6 @@ use codex_app_server_protocol::InterruptConversationResponse;
use codex_app_server_protocol::ItemCompletedNotification;
use codex_app_server_protocol::ItemStartedNotification;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_app_server_protocol::McpServerElicitationAction;
use codex_app_server_protocol::McpServerElicitationRequestParams;
use codex_app_server_protocol::McpServerElicitationRequestResponse;
use codex_app_server_protocol::McpToolCallError;
use codex_app_server_protocol::McpToolCallResult;
use codex_app_server_protocol::McpToolCallStatus;
@@ -612,38 +609,6 @@ pub(crate) async fn apply_bespoke_event_handling(
}
}
}
EventMsg::ElicitationRequest(request) => {
if matches!(api_version, ApiVersion::V2) {
let permission_guard = thread_watch_manager
.note_permission_requested(&conversation_id.to_string())
.await;
let turn_id = {
let state = thread_state.lock().await;
state.active_turn_snapshot().map(|turn| turn.id)
};
let params = McpServerElicitationRequestParams {
thread_id: conversation_id.to_string(),
turn_id,
server_name: request.server_name.clone(),
request: request.request.into(),
};
let (pending_request_id, rx) = outgoing
.send_request(ServerRequestPayload::McpServerElicitationRequest(params))
.await;
tokio::spawn(async move {
on_mcp_server_elicitation_response(
request.server_name,
request.id,
pending_request_id,
rx,
conversation,
thread_state,
permission_guard,
)
.await;
});
}
}
EventMsg::DynamicToolCallRequest(request) => {
if matches!(api_version, ApiVersion::V2) {
let call_id = request.call_id;
@@ -2024,68 +1989,6 @@ async fn on_request_user_input_response(
}
}
async fn on_mcp_server_elicitation_response(
server_name: String,
request_id: codex_protocol::mcp::RequestId,
pending_request_id: RequestId,
receiver: oneshot::Receiver<ClientRequestResult>,
conversation: Arc<CodexThread>,
thread_state: Arc<Mutex<ThreadState>>,
permission_guard: ThreadWatchActiveGuard,
) {
let response = receiver.await;
resolve_server_request_on_thread_listener(&thread_state, pending_request_id).await;
drop(permission_guard);
let response = mcp_server_elicitation_response_from_client_result(response);
if let Err(err) = conversation
.submit(Op::ResolveElicitation {
server_name,
request_id,
decision: response.action.to_core(),
content: response.content,
})
.await
{
error!("failed to submit ResolveElicitation: {err}");
}
}
fn mcp_server_elicitation_response_from_client_result(
response: std::result::Result<ClientRequestResult, oneshot::error::RecvError>,
) -> McpServerElicitationRequestResponse {
match response {
Ok(Ok(value)) => serde_json::from_value::<McpServerElicitationRequestResponse>(value)
.unwrap_or_else(|err| {
error!("failed to deserialize McpServerElicitationRequestResponse: {err}");
McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Decline,
content: None,
}
}),
Ok(Err(err)) if is_turn_transition_server_request_error(&err) => {
McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Cancel,
content: None,
}
}
Ok(Err(err)) => {
error!("request failed with client error: {err:?}");
McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Decline,
content: None,
}
}
Err(err) => {
error!("request failed: {err:?}");
McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Decline,
content: None,
}
}
}
}
const REVIEW_FALLBACK_MESSAGE: &str = "Reviewer failed to output a response.";
fn render_review_output_text(output: &ReviewOutputEvent) -> String {
@@ -2431,7 +2334,6 @@ mod tests {
use anyhow::Result;
use anyhow::anyhow;
use anyhow::bail;
use codex_app_server_protocol::JSONRPCErrorError;
use codex_app_server_protocol::TurnPlanStepStatus;
use codex_protocol::mcp::CallToolResult;
use codex_protocol::plan_tool::PlanItemArg;
@@ -2476,25 +2378,6 @@ mod tests {
assert_eq!(completion_status, None);
}
#[test]
fn mcp_server_elicitation_turn_transition_error_maps_to_cancel() {
let error = JSONRPCErrorError {
code: -1,
message: "client request resolved because the turn state was changed".to_string(),
data: Some(serde_json::json!({ "reason": "turnTransition" })),
};
let response = mcp_server_elicitation_response_from_client_result(Ok(Err(error)));
assert_eq!(
response,
McpServerElicitationRequestResponse {
action: McpServerElicitationAction::Cancel,
content: None,
}
);
}
#[test]
fn collab_resume_begin_maps_to_item_started_resume_agent() {
let event = CollabResumeBeginEvent {

View File

@@ -1,6 +1,4 @@
use crate::bespoke_event_handling::apply_bespoke_event_handling;
use crate::command_exec::CommandExecManager;
use crate::command_exec::StartCommandExecParams;
use crate::error_code::INPUT_TOO_LARGE_ERROR_CODE;
use crate::error_code::INTERNAL_ERROR_CODE;
use crate::error_code::INVALID_PARAMS_ERROR_CODE;
@@ -35,12 +33,10 @@ use codex_app_server_protocol::ClientRequest;
use codex_app_server_protocol::CollaborationModeListParams;
use codex_app_server_protocol::CollaborationModeListResponse;
use codex_app_server_protocol::CommandExecParams;
use codex_app_server_protocol::CommandExecResizeParams;
use codex_app_server_protocol::CommandExecTerminateParams;
use codex_app_server_protocol::CommandExecWriteParams;
use codex_app_server_protocol::ConversationGitInfo;
use codex_app_server_protocol::ConversationSummary;
use codex_app_server_protocol::DynamicToolSpec as ApiDynamicToolSpec;
use codex_app_server_protocol::ExecOneOffCommandResponse;
use codex_app_server_protocol::ExperimentalFeature as ApiExperimentalFeature;
use codex_app_server_protocol::ExperimentalFeatureListParams;
use codex_app_server_protocol::ExperimentalFeatureListResponse;
@@ -81,13 +77,6 @@ use codex_app_server_protocol::MockExperimentalMethodParams;
use codex_app_server_protocol::MockExperimentalMethodResponse;
use codex_app_server_protocol::ModelListParams;
use codex_app_server_protocol::ModelListResponse;
use codex_app_server_protocol::PluginInstallParams;
use codex_app_server_protocol::PluginInstallResponse;
use codex_app_server_protocol::PluginListParams;
use codex_app_server_protocol::PluginListResponse;
use codex_app_server_protocol::PluginMarketplaceEntry;
use codex_app_server_protocol::PluginSource;
use codex_app_server_protocol::PluginSummary;
use codex_app_server_protocol::ProductSurface as ApiProductSurface;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::ReviewDelivery as ApiReviewDelivery;
@@ -193,7 +182,6 @@ use codex_core::config::types::McpServerTransportConfig;
use codex_core::config_loader::CloudRequirementsLoader;
use codex_core::default_client::set_default_client_residency_requirement;
use codex_core::error::CodexErr;
use codex_core::exec::ExecExpiration;
use codex_core::exec::ExecParams;
use codex_core::exec_env::create_env;
use codex_core::features::FEATURES;
@@ -208,10 +196,6 @@ use codex_core::mcp::collect_mcp_snapshot;
use codex_core::mcp::group_tools_by_server;
use codex_core::models_manager::collaboration_mode_presets::CollaborationModesConfig;
use codex_core::parse_cursor;
use codex_core::plugins::MarketplaceError;
use codex_core::plugins::MarketplacePluginSourceSummary;
use codex_core::plugins::PluginInstallError as CorePluginInstallError;
use codex_core::plugins::PluginInstallRequest;
use codex_core::read_head_for_summary;
use codex_core::read_session_meta_line;
use codex_core::rollout_date_parts;
@@ -263,7 +247,6 @@ use codex_state::StateRuntime;
use codex_state::ThreadMetadataBuilder;
use codex_state::log_db::LogDbLayer;
use codex_utils_json_to_toml::json_to_toml;
use codex_utils_pty::DEFAULT_OUTPUT_BYTES_CAP;
use std::collections::HashMap;
use std::collections::HashSet;
use std::ffi::OsStr;
@@ -282,7 +265,6 @@ use tokio::sync::Mutex;
use tokio::sync::broadcast;
use tokio::sync::oneshot;
use tokio::sync::watch;
use tokio_util::sync::CancellationToken;
use toml::Value as TomlValue;
use tracing::error;
use tracing::info;
@@ -370,7 +352,6 @@ pub(crate) struct CodexMessageProcessor {
pending_thread_unloads: Arc<Mutex<HashSet<ThreadId>>>,
thread_state_manager: ThreadStateManager,
thread_watch_manager: ThreadWatchManager,
command_exec_manager: CommandExecManager,
pending_fuzzy_searches: Arc<Mutex<HashMap<String, Arc<AtomicBool>>>>,
fuzzy_search_sessions: Arc<Mutex<HashMap<String, FuzzyFileSearchSession>>>,
feedback: CodexFeedback,
@@ -469,7 +450,6 @@ impl CodexMessageProcessor {
pending_thread_unloads: Arc::new(Mutex::new(HashSet::new())),
thread_state_manager: ThreadStateManager::new(),
thread_watch_manager: ThreadWatchManager::new_with_outgoing(outgoing),
command_exec_manager: CommandExecManager::default(),
pending_fuzzy_searches: Arc::new(Mutex::new(HashMap::new())),
fuzzy_search_sessions: Arc::new(Mutex::new(HashMap::new())),
feedback,
@@ -662,10 +642,6 @@ impl CodexMessageProcessor {
self.skills_list(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::PluginList { request_id, params } => {
self.plugin_list(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::SkillsRemoteList { request_id, params } => {
self.skills_remote_list(to_connection_request_id(request_id), params)
.await;
@@ -682,10 +658,6 @@ impl CodexMessageProcessor {
self.skills_config_write(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::PluginInstall { request_id, params } => {
self.plugin_install(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::TurnStart { request_id, params } => {
self.turn_start(
to_connection_request_id(request_id),
@@ -815,18 +787,6 @@ impl CodexMessageProcessor {
self.exec_one_off_command(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::CommandExecWrite { request_id, params } => {
self.command_exec_write(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::CommandExecResize { request_id, params } => {
self.command_exec_resize(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::CommandExecTerminate { request_id, params } => {
self.command_exec_terminate(to_connection_request_id(request_id), params)
.await;
}
ClientRequest::ConfigRead { .. }
| ClientRequest::ConfigValueWrite { .. }
| ClientRequest::ConfigBatchWrite { .. } => {
@@ -1499,84 +1459,11 @@ impl CodexMessageProcessor {
return;
}
let CommandExecParams {
command,
process_id,
tty,
stream_stdin,
stream_stdout_stderr,
output_bytes_cap,
disable_output_cap,
disable_timeout,
timeout_ms,
cwd,
env: env_overrides,
size,
sandbox_policy,
} = params;
if size.is_some() && !tty {
let error = JSONRPCErrorError {
code: INVALID_PARAMS_ERROR_CODE,
message: "command/exec size requires tty: true".to_string(),
data: None,
};
self.outgoing.send_error(request, error).await;
return;
}
if disable_output_cap && output_bytes_cap.is_some() {
let error = JSONRPCErrorError {
code: INVALID_PARAMS_ERROR_CODE,
message: "command/exec cannot set both outputBytesCap and disableOutputCap"
.to_string(),
data: None,
};
self.outgoing.send_error(request, error).await;
return;
}
if disable_timeout && timeout_ms.is_some() {
let error = JSONRPCErrorError {
code: INVALID_PARAMS_ERROR_CODE,
message: "command/exec cannot set both timeoutMs and disableTimeout".to_string(),
data: None,
};
self.outgoing.send_error(request, error).await;
return;
}
let cwd = cwd.unwrap_or_else(|| self.config.cwd.clone());
let mut env = create_env(&self.config.permissions.shell_environment_policy, None);
if let Some(env_overrides) = env_overrides {
for (key, value) in env_overrides {
match value {
Some(value) => {
env.insert(key, value);
}
None => {
env.remove(&key);
}
}
}
}
let timeout_ms = match timeout_ms {
Some(timeout_ms) => match u64::try_from(timeout_ms) {
Ok(timeout_ms) => Some(timeout_ms),
Err(_) => {
let error = JSONRPCErrorError {
code: INVALID_PARAMS_ERROR_CODE,
message: format!(
"command/exec timeoutMs must be non-negative, got {timeout_ms}"
),
data: None,
};
self.outgoing.send_error(request, error).await;
return;
}
},
None => None,
};
let cwd = params.cwd.unwrap_or_else(|| self.config.cwd.clone());
let env = create_env(&self.config.permissions.shell_environment_policy, None);
let timeout_ms = params
.timeout_ms
.and_then(|timeout_ms| u64::try_from(timeout_ms).ok());
let managed_network_requirements_enabled =
self.config.managed_network_requirements_enabled();
let started_network_proxy = match self.config.permissions.network.as_ref() {
@@ -1604,23 +1491,10 @@ impl CodexMessageProcessor {
None => None,
};
let windows_sandbox_level = WindowsSandboxLevel::from_config(&self.config);
let output_bytes_cap = if disable_output_cap {
None
} else {
Some(output_bytes_cap.unwrap_or(DEFAULT_OUTPUT_BYTES_CAP))
};
let expiration = if disable_timeout {
ExecExpiration::Cancellation(CancellationToken::new())
} else {
match timeout_ms {
Some(timeout_ms) => timeout_ms.into(),
None => ExecExpiration::DefaultTimeout,
}
};
let exec_params = ExecParams {
command,
command: params.command,
cwd,
expiration,
expiration: timeout_ms.into(),
env,
network: started_network_proxy
.as_ref()
@@ -1631,7 +1505,7 @@ impl CodexMessageProcessor {
arg0: None,
};
let requested_policy = sandbox_policy.map(|policy| policy.to_core());
let requested_policy = params.sandbox_policy.map(|policy| policy.to_core());
let effective_policy = match requested_policy {
Some(policy) => match self.config.permissions.sandbox_policy.can_set(&policy) {
Ok(()) => policy,
@@ -1650,104 +1524,39 @@ impl CodexMessageProcessor {
let codex_linux_sandbox_exe = self.arg0_paths.codex_linux_sandbox_exe.clone();
let outgoing = self.outgoing.clone();
let request_for_task = request.clone();
let request_for_task = request;
let sandbox_cwd = self.config.cwd.clone();
let started_network_proxy_for_task = started_network_proxy;
let use_linux_sandbox_bwrap = self.config.features.enabled(Feature::UseLinuxSandboxBwrap);
let size = match size.map(crate::command_exec::terminal_size_from_protocol) {
Some(Ok(size)) => Some(size),
Some(Err(error)) => {
self.outgoing.send_error(request, error).await;
return;
}
None => None,
};
match codex_core::exec::build_exec_request(
exec_params,
&effective_policy,
sandbox_cwd.as_path(),
&codex_linux_sandbox_exe,
use_linux_sandbox_bwrap,
) {
Ok(exec_request) => {
if let Err(error) = self
.command_exec_manager
.start(StartCommandExecParams {
outgoing,
request_id: request_for_task,
process_id,
exec_request,
started_network_proxy: started_network_proxy_for_task,
tty,
stream_stdin,
stream_stdout_stderr,
output_bytes_cap,
size,
})
.await
{
self.outgoing.send_error(request, error).await;
tokio::spawn(async move {
let _started_network_proxy = started_network_proxy_for_task;
match codex_core::exec::process_exec_tool_call(
exec_params,
&effective_policy,
sandbox_cwd.as_path(),
&codex_linux_sandbox_exe,
use_linux_sandbox_bwrap,
None,
)
.await
{
Ok(output) => {
let response = ExecOneOffCommandResponse {
exit_code: output.exit_code,
stdout: output.stdout.text,
stderr: output.stderr.text,
};
outgoing.send_response(request_for_task, response).await;
}
Err(err) => {
let error = JSONRPCErrorError {
code: INTERNAL_ERROR_CODE,
message: format!("exec failed: {err}"),
data: None,
};
outgoing.send_error(request_for_task, error).await;
}
}
Err(err) => {
let error = JSONRPCErrorError {
code: INTERNAL_ERROR_CODE,
message: format!("exec failed: {err}"),
data: None,
};
self.outgoing.send_error(request, error).await;
}
}
}
async fn command_exec_write(
&self,
request_id: ConnectionRequestId,
params: CommandExecWriteParams,
) {
let command_exec_manager = self.command_exec_manager.clone();
let outgoing = self.outgoing.clone();
tokio::spawn(async move {
match command_exec_manager.write(request_id.clone(), params).await {
Ok(response) => outgoing.send_response(request_id, response).await,
Err(error) => outgoing.send_error(request_id, error).await,
}
});
}
async fn command_exec_resize(
&self,
request_id: ConnectionRequestId,
params: CommandExecResizeParams,
) {
let command_exec_manager = self.command_exec_manager.clone();
let outgoing = self.outgoing.clone();
tokio::spawn(async move {
match command_exec_manager
.resize(request_id.clone(), params)
.await
{
Ok(response) => outgoing.send_response(request_id, response).await,
Err(error) => outgoing.send_error(request_id, error).await,
}
});
}
async fn command_exec_terminate(
&self,
request_id: ConnectionRequestId,
params: CommandExecTerminateParams,
) {
let command_exec_manager = self.command_exec_manager.clone();
let outgoing = self.outgoing.clone();
tokio::spawn(async move {
match command_exec_manager
.terminate(request_id.clone(), params)
.await
{
Ok(response) => outgoing.send_response(request_id, response).await,
Err(error) => outgoing.send_error(request_id, error).await,
}
});
}
@@ -2884,13 +2693,7 @@ impl CodexMessageProcessor {
}
};
let loaded_thread = self.thread_manager.get_thread(thread_uuid).await.ok();
let loaded_thread_state_db = loaded_thread.as_ref().and_then(|thread| thread.state_db());
let db_summary = if let Some(state_db_ctx) = loaded_thread_state_db.as_ref() {
read_summary_from_state_db_context_by_thread_id(Some(state_db_ctx), thread_uuid).await
} else {
read_summary_from_state_db_by_thread_id(&self.config, thread_uuid).await
};
let db_summary = read_summary_from_state_db_by_thread_id(&self.config, thread_uuid).await;
let mut rollout_path = db_summary.as_ref().map(|summary| summary.path.clone());
if rollout_path.is_none() || include_turns {
rollout_path =
@@ -2944,7 +2747,7 @@ impl CodexMessageProcessor {
}
}
} else {
let Some(thread) = loaded_thread else {
let Ok(thread) = self.thread_manager.get_thread(thread_uuid).await else {
self.send_invalid_request_error(
request_id,
format!("thread not loaded: {thread_uuid}"),
@@ -3019,9 +2822,6 @@ impl CodexMessageProcessor {
}
pub(crate) async fn connection_closed(&mut self, connection_id: ConnectionId) {
self.command_exec_manager
.connection_closed(connection_id)
.await;
self.thread_state_manager
.remove_connection(connection_id)
.await;
@@ -3152,7 +2952,6 @@ impl CodexMessageProcessor {
};
let fallback_model_provider = config.model_provider_id.clone();
let response_history = thread_history.clone();
match self
.thread_manager
@@ -3166,8 +2965,8 @@ impl CodexMessageProcessor {
{
Ok(NewThread {
thread_id,
thread,
session_configured,
..
}) => {
let SessionConfiguredEvent { rollout_path, .. } = session_configured;
let Some(rollout_path) = rollout_path else {
@@ -3193,11 +2992,9 @@ impl CodexMessageProcessor {
);
let Some(mut thread) = self
.load_thread_from_resume_source_or_send_internal(
.load_thread_from_rollout_or_send_internal(
request_id.clone(),
thread_id,
thread.as_ref(),
&response_history,
rollout_path.as_path(),
fallback_model_provider.as_str(),
)
@@ -3352,20 +3149,6 @@ impl CodexMessageProcessor {
mismatch_details.join("; ")
);
}
let thread_summary = match load_thread_summary_for_rollout(
&self.config,
existing_thread_id,
rollout_path.as_path(),
config_snapshot.model_provider_id.as_str(),
)
.await
{
Ok(thread) => thread,
Err(message) => {
self.send_internal_error(request_id, message).await;
return true;
}
};
let listener_command_tx = {
let thread_state = thread_state.lock().await;
@@ -3386,9 +3169,8 @@ impl CodexMessageProcessor {
let command = crate::thread_state::ThreadListenerCommand::SendThreadResumeResponse(
Box::new(crate::thread_state::PendingThreadResumeRequest {
request_id: request_id.clone(),
rollout_path: rollout_path.clone(),
rollout_path,
config_snapshot,
thread_summary,
}),
);
if listener_command_tx.send(command).is_err() {
@@ -3486,61 +3268,45 @@ impl CodexMessageProcessor {
}
}
async fn load_thread_from_resume_source_or_send_internal(
async fn load_thread_from_rollout_or_send_internal(
&self,
request_id: ConnectionRequestId,
thread_id: ThreadId,
thread: &CodexThread,
thread_history: &InitialHistory,
rollout_path: &Path,
fallback_provider: &str,
) -> Option<Thread> {
let thread = match thread_history {
InitialHistory::Resumed(resumed) => {
load_thread_summary_for_rollout(
&self.config,
resumed.conversation_id,
resumed.rollout_path.as_path(),
fallback_provider,
let mut thread = match read_summary_from_rollout(rollout_path, fallback_provider).await {
Ok(summary) => summary_to_thread(summary),
Err(err) => {
self.send_internal_error(
request_id,
format!(
"failed to load rollout `{}` for thread {thread_id}: {err}",
rollout_path.display()
),
)
.await
}
InitialHistory::Forked(items) => {
let config_snapshot = thread.config_snapshot().await;
let mut thread = build_thread_from_snapshot(
thread_id,
&config_snapshot,
Some(rollout_path.into()),
);
thread.preview = preview_from_rollout_items(items);
Ok(thread)
}
InitialHistory::New => Err(format!(
"failed to build resume response for thread {thread_id}: initial history missing"
)),
};
let mut thread = match thread {
Ok(thread) => thread,
Err(message) => {
self.send_internal_error(request_id, message).await;
.await;
return None;
}
};
thread.id = thread_id.to_string();
thread.path = Some(rollout_path.to_path_buf());
let history_items = thread_history.get_rollout_items();
if let Err(message) = populate_resume_turns(
&mut thread,
ResumeTurnSource::HistoryItems(&history_items),
None,
)
.await
{
self.send_internal_error(request_id, message).await;
return None;
match read_rollout_items_from_rollout(rollout_path).await {
Ok(items) => {
thread.turns = build_turns_from_rollout_items(&items);
self.attach_thread_name(thread_id, &mut thread).await;
Some(thread)
}
Err(err) => {
self.send_internal_error(
request_id,
format!(
"failed to load rollout `{}` for thread {thread_id}: {err}",
rollout_path.display()
),
)
.await;
None
}
}
self.attach_thread_name(thread_id, &mut thread).await;
Some(thread)
}
async fn attach_thread_name(&self, thread_id: ThreadId, thread: &mut Thread) {
@@ -4504,30 +4270,6 @@ impl CodexMessageProcessor {
self.outgoing.send_error(request_id, error).await;
}
async fn send_marketplace_error(
&self,
request_id: ConnectionRequestId,
err: MarketplaceError,
action: &str,
) {
match err {
MarketplaceError::MarketplaceNotFound { .. } => {
self.send_invalid_request_error(request_id, err.to_string())
.await;
}
MarketplaceError::Io { .. } => {
self.send_internal_error(request_id, format!("failed to {action}: {err}"))
.await;
}
MarketplaceError::InvalidMarketplaceFile { .. }
| MarketplaceError::PluginNotFound { .. }
| MarketplaceError::InvalidPlugin(_) => {
self.send_invalid_request_error(request_id, err.to_string())
.await;
}
}
}
async fn wait_for_thread_shutdown(thread: &Arc<CodexThread>) -> ThreadShutdownResult {
match thread.submit(Op::Shutdown).await {
Ok(_) => {
@@ -5134,66 +4876,6 @@ impl CodexMessageProcessor {
.await;
}
async fn plugin_list(&self, request_id: ConnectionRequestId, params: PluginListParams) {
let plugins_manager = self.thread_manager.plugins_manager();
let roots = params.cwds.unwrap_or_default();
let config = match self.load_latest_config().await {
Ok(config) => config,
Err(err) => {
self.outgoing.send_error(request_id, err).await;
return;
}
};
let data = match tokio::task::spawn_blocking(move || {
let marketplaces = plugins_manager.list_marketplaces_for_config(&config, &roots)?;
Ok::<Vec<PluginMarketplaceEntry>, MarketplaceError>(
marketplaces
.into_iter()
.map(|marketplace| PluginMarketplaceEntry {
name: marketplace.name,
path: marketplace.path,
plugins: marketplace
.plugins
.into_iter()
.map(|plugin| PluginSummary {
enabled: plugin.enabled,
name: plugin.name,
source: match plugin.source {
MarketplacePluginSourceSummary::Local { path } => {
PluginSource::Local { path }
}
},
})
.collect(),
})
.collect(),
)
})
.await
{
Ok(Ok(data)) => data,
Ok(Err(err)) => {
self.send_marketplace_error(request_id, err, "list marketplace plugins")
.await;
return;
}
Err(err) => {
self.send_internal_error(
request_id,
format!("failed to list marketplace plugins: {err}"),
)
.await;
return;
}
};
self.outgoing
.send_response(request_id, PluginListResponse { marketplaces: data })
.await;
}
async fn skills_remote_list(
&self,
request_id: ConnectionRequestId,
@@ -5302,64 +4984,6 @@ impl CodexMessageProcessor {
}
}
async fn plugin_install(&self, request_id: ConnectionRequestId, params: PluginInstallParams) {
let PluginInstallParams {
marketplace_path,
plugin_name,
} = params;
let plugins_manager = self.thread_manager.plugins_manager();
let request = PluginInstallRequest {
plugin_name,
marketplace_path,
};
match plugins_manager.install_plugin(request).await {
Ok(_) => {
plugins_manager.clear_cache();
self.thread_manager.skills_manager().clear_cache();
self.outgoing
.send_response(request_id, PluginInstallResponse {})
.await;
}
Err(err) => {
if err.is_invalid_request() {
self.send_invalid_request_error(request_id, err.to_string())
.await;
return;
}
match err {
CorePluginInstallError::Marketplace(err) => {
self.send_marketplace_error(request_id, err, "install plugin")
.await;
}
CorePluginInstallError::Config(err) => {
self.send_internal_error(
request_id,
format!("failed to persist installed plugin config: {err}"),
)
.await;
}
CorePluginInstallError::Join(err) => {
self.send_internal_error(
request_id,
format!("failed to install plugin: {err}"),
)
.await;
}
CorePluginInstallError::Store(err) => {
self.send_internal_error(
request_id,
format!("failed to install plugin: {err}"),
)
.await;
}
}
}
}
}
async fn turn_start(
&self,
request_id: ConnectionRequestId,
@@ -6495,39 +6119,21 @@ impl CodexMessageProcessor {
WindowsSandboxSetupMode::Unelevated => CoreWindowsSandboxSetupMode::Unelevated,
};
let config = Arc::clone(&self.config);
let cli_overrides = self.cli_overrides.clone();
let cloud_requirements = self.current_cloud_requirements();
let command_cwd = params.cwd.unwrap_or_else(|| config.cwd.clone());
let outgoing = Arc::clone(&self.outgoing);
let connection_id = request_id.connection_id;
tokio::spawn(async move {
let derived_config = derive_config_for_cwd(
&cli_overrides,
None,
ConfigOverrides {
cwd: Some(command_cwd.clone()),
..Default::default()
},
Some(command_cwd.clone()),
&cloud_requirements,
)
.await;
let setup_result = match derived_config {
Ok(config) => {
let setup_request = WindowsSandboxSetupRequest {
mode,
policy: config.permissions.sandbox_policy.get().clone(),
policy_cwd: config.cwd.clone(),
command_cwd,
env_map: std::env::vars().collect(),
codex_home: config.codex_home.clone(),
active_profile: config.active_profile.clone(),
};
codex_core::windows_sandbox::run_windows_sandbox_setup(setup_request).await
}
Err(err) => Err(err.into()),
let setup_request = WindowsSandboxSetupRequest {
mode,
policy: config.permissions.sandbox_policy.get().clone(),
policy_cwd: config.cwd.clone(),
command_cwd: config.cwd.clone(),
env_map: std::env::vars().collect(),
codex_home: config.codex_home.clone(),
active_profile: config.active_profile.clone(),
};
let setup_result =
codex_core::windows_sandbox::run_windows_sandbox_setup(setup_request).await;
let notification = WindowsSandboxSetupCompletedNotification {
mode: match mode {
CoreWindowsSandboxSetupMode::Elevated => WindowsSandboxSetupMode::Elevated,
@@ -6618,26 +6224,29 @@ async fn handle_pending_thread_resume_request(
let request_id = pending.request_id;
let connection_id = request_id.connection_id;
let mut thread = pending.thread_summary;
if let Err(message) = populate_resume_turns(
&mut thread,
ResumeTurnSource::RolloutPath(pending.rollout_path.as_path()),
let mut thread = match load_thread_for_running_resume_response(
conversation_id,
pending.rollout_path.as_path(),
pending.config_snapshot.model_provider_id.as_str(),
active_turn.as_ref(),
)
.await
{
outgoing
.send_error(
request_id,
JSONRPCErrorError {
code: INTERNAL_ERROR_CODE,
message,
data: None,
},
)
.await;
return;
}
Ok(thread) => thread,
Err(message) => {
outgoing
.send_error(
request_id,
JSONRPCErrorError {
code: INTERNAL_ERROR_CODE,
message,
data: None,
},
)
.await;
return;
}
};
has_in_progress_turn = has_in_progress_turn
|| thread
@@ -6687,38 +6296,6 @@ async fn handle_pending_thread_resume_request(
.await;
}
enum ResumeTurnSource<'a> {
RolloutPath(&'a Path),
HistoryItems(&'a [RolloutItem]),
}
async fn populate_resume_turns(
thread: &mut Thread,
turn_source: ResumeTurnSource<'_>,
active_turn: Option<&Turn>,
) -> std::result::Result<(), String> {
let mut turns = match turn_source {
ResumeTurnSource::RolloutPath(rollout_path) => {
read_rollout_items_from_rollout(rollout_path)
.await
.map(|items| build_turns_from_rollout_items(&items))
.map_err(|err| {
format!(
"failed to load rollout `{}` for thread {}: {err}",
rollout_path.display(),
thread.id
)
})?
}
ResumeTurnSource::HistoryItems(items) => build_turns_from_rollout_items(items),
};
if let Some(active_turn) = active_turn {
merge_turn_history_with_active_turn(&mut turns, active_turn.clone());
}
thread.turns = turns;
Ok(())
}
async fn resolve_pending_server_request(
conversation_id: ThreadId,
thread_state_manager: &ThreadStateManager,
@@ -6744,6 +6321,38 @@ async fn resolve_pending_server_request(
.await;
}
async fn load_thread_for_running_resume_response(
conversation_id: ThreadId,
rollout_path: &Path,
fallback_provider: &str,
active_turn: Option<&Turn>,
) -> std::result::Result<Thread, String> {
let mut thread = read_summary_from_rollout(rollout_path, fallback_provider)
.await
.map(summary_to_thread)
.map_err(|err| {
format!(
"failed to load rollout `{}` for thread {conversation_id}: {err}",
rollout_path.display()
)
})?;
let mut turns = read_rollout_items_from_rollout(rollout_path)
.await
.map(|items| build_turns_from_rollout_items(&items))
.map_err(|err| {
format!(
"failed to load rollout `{}` for thread {conversation_id}: {err}",
rollout_path.display()
)
})?;
if let Some(active_turn) = active_turn {
merge_turn_history_with_active_turn(&mut turns, active_turn.clone());
}
thread.turns = turns;
Ok(thread)
}
fn merge_turn_history_with_active_turn(turns: &mut Vec<Turn>, active_turn: Turn) {
turns.retain(|turn| turn.id != active_turn.id);
turns.push(active_turn);
@@ -6771,14 +6380,6 @@ fn collect_resume_override_mismatches(
config_snapshot.model_provider_id
));
}
if let Some(requested_service_tier) = request.service_tier.as_ref()
&& requested_service_tier != &config_snapshot.service_tier
{
mismatch_details.push(format!(
"service_tier requested={requested_service_tier:?} active={:?}",
config_snapshot.service_tier
));
}
if let Some(requested_cwd) = request.cwd.as_deref() {
let requested_cwd_path = std::path::PathBuf::from(requested_cwd);
if requested_cwd_path != config_snapshot.cwd {
@@ -7349,48 +6950,6 @@ fn map_git_info(git_info: &CoreGitInfo) -> ConversationGitInfo {
}
}
async fn load_thread_summary_for_rollout(
config: &Config,
thread_id: ThreadId,
rollout_path: &Path,
fallback_provider: &str,
) -> std::result::Result<Thread, String> {
let mut thread = read_summary_from_rollout(rollout_path, fallback_provider)
.await
.map(summary_to_thread)
.map_err(|err| {
format!(
"failed to load rollout `{}` for thread {thread_id}: {err}",
rollout_path.display()
)
})?;
if let Some(summary) = read_summary_from_state_db_by_thread_id(config, thread_id).await {
merge_mutable_thread_metadata(&mut thread, summary_to_thread(summary));
}
Ok(thread)
}
fn merge_mutable_thread_metadata(thread: &mut Thread, persisted_thread: Thread) {
thread.git_info = persisted_thread.git_info;
}
fn preview_from_rollout_items(items: &[RolloutItem]) -> String {
items
.iter()
.find_map(|item| match item {
RolloutItem::ResponseItem(item) => match codex_core::parse_turn_item(item) {
Some(codex_protocol::items::TurnItem::UserMessage(user)) => Some(user.message()),
_ => None,
},
_ => None,
})
.map(|preview| match preview.find(USER_MESSAGE_BEGIN) {
Some(idx) => preview[idx + USER_MESSAGE_BEGIN.len()..].trim().to_string(),
None => preview,
})
.unwrap_or_default()
}
fn with_thread_spawn_agent_metadata(
source: codex_protocol::protocol::SessionSource,
agent_nickname: Option<String>,
@@ -7545,43 +7104,6 @@ mod tests {
validate_dynamic_tools(&tools).expect("valid schema");
}
#[test]
fn collect_resume_override_mismatches_includes_service_tier() {
let request = ThreadResumeParams {
thread_id: "thread-1".to_string(),
history: None,
path: None,
model: None,
model_provider: None,
service_tier: Some(Some(codex_protocol::config_types::ServiceTier::Fast)),
cwd: None,
approval_policy: None,
sandbox: None,
config: None,
base_instructions: None,
developer_instructions: None,
personality: None,
persist_extended_history: false,
};
let config_snapshot = ThreadConfigSnapshot {
model: "gpt-5".to_string(),
model_provider_id: "openai".to_string(),
service_tier: Some(codex_protocol::config_types::ServiceTier::Flex),
approval_policy: codex_protocol::protocol::AskForApproval::OnRequest,
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
cwd: PathBuf::from("/tmp"),
ephemeral: false,
reasoning_effort: None,
personality: None,
session_source: SessionSource::Cli,
};
assert_eq!(
collect_resume_override_mismatches(&request, &config_snapshot),
vec!["service_tier requested=Some(Fast) active=Some(Flex)".to_string()]
);
}
#[test]
fn extract_conversation_summary_prefers_plain_user_messages() -> Result<()> {
let conversation_id = ThreadId::from_string("3f941c35-29b3-493b-b0a4-e25800d9aeb0")?;

Some files were not shown because too many files have changed in this diff Show More