Merge branch 'main' into cooper/app-server-pat-auth-precedence

This commit is contained in:
cooper-oai
2026-07-06 17:05:22 -05:00
committed by GitHub
793 changed files with 48386 additions and 6912 deletions
+9 -7
View File
@@ -107,8 +107,9 @@ common:ci-bazel --config=ci
common:ci-bazel --build_metadata=TAG_workflow=bazel
# Keep code-mode integration cases out of ordinary Bazel legs. The
# Windows-cross config below re-enables them after generating its Windows V8
# snapshot on the Windows runner.
common:ci-bazel --test_env=CODEX_BAZEL_TEST_SKIP_FILTERS=suite::code_mode::
# snapshot on the Windows runner. Also skip the ConPTY Ctrl-C integration test
# until Windows Bazel CI can reliably interrupt foreground processes.
common:ci-bazel --test_env=CODEX_BAZEL_TEST_SKIP_FILTERS=suite::code_mode::,tests::windows_tests::conpty_ctrl_c_interrupts_powershell_foreground_child
# Shared config for Bazel-backed Rust linting.
build:clippy --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
@@ -191,11 +192,12 @@ common:ci-windows-cross --strategy=TestRunner=local
common:ci-windows-cross --strategy=V8Mksnapshot=local
common:ci-windows-cross --local_test_jobs=4
common:ci-windows-cross --test_env=RUST_TEST_THREADS=1
# Native Windows CI still covers the PowerShell tests. The cross-built gnullvm
# binaries currently hang in PowerShell AST parser tests when those binaries are
# run on the Windows runner. Keep V8-backed code-mode tests enabled except for
# the hidden dynamic-tool callback test, which currently times out on Windows.
common:ci-windows-cross --test_env=CODEX_BAZEL_TEST_SKIP_FILTERS=powershell,suite::code_mode::code_mode_can_call_hidden_dynamic_tools
# Native Windows CI still covers the PowerShell parser-process tests. The
# cross-built gnullvm binaries currently hang in those tests when run on the
# Windows runner. Keep V8-backed code-mode tests enabled except for the hidden
# dynamic-tool callback test, which currently times out on Windows. This config
# replaces the base skip list, so repeat the exact ConPTY Ctrl-C test exclusion.
common:ci-windows-cross --test_env=CODEX_BAZEL_TEST_SKIP_FILTERS=command_safety::powershell_parser::tests::,suite::code_mode::code_mode_can_call_hidden_dynamic_tools,tests::windows_tests::conpty_ctrl_c_interrupts_powershell_foreground_child
common:ci-windows-cross --platforms=//:windows_x86_64_gnullvm
common:ci-windows-cross --extra_execution_platforms=//:rbe,//:windows_x86_64_msvc
common:ci-windows-cross --extra_toolchains=//:windows_gnullvm_tests_on_msvc_host_toolchain
+1 -1
View File
@@ -3,7 +3,7 @@ name: code-review
description: Run a final code review on a pull request
---
Use subagents to review code using all code-review-* skills in this repository other than this orchestrator. One subagent per skill. Pass full skill path to subagents. Use xhigh reasoning.
Use subagents to review code using all code-review-* skills other than this orchestrator. One subagent per skill. Pass full skill path to subagents. Use xhigh reasoning.
You must return every single issue from every subagent. You can return an unlimited number of findings.
Use raw Markdown to report findings.
+4
View File
@@ -5,21 +5,25 @@
"macos-aarch64": {
"name": "codex-zsh-aarch64-apple-darwin.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-zsh/bin/zsh"
},
"macos-x86_64": {
"name": "codex-zsh-x86_64-apple-darwin.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-zsh/bin/zsh"
},
"linux-x86_64": {
"name": "codex-zsh-x86_64-unknown-linux-musl.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-zsh/bin/zsh"
},
"linux-aarch64": {
"name": "codex-zsh-aarch64-unknown-linux-musl.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-zsh/bin/zsh"
}
}
@@ -9,6 +9,7 @@ Usage: build-codex-package-archive.sh \
--entrypoint-dir <dir> \
--archive-dir <dir> \
[--bwrap-bin <path>] \
[--zsh-manifest <path>] \
[--codex-command-runner-bin <path>] \
[--codex-windows-sandbox-setup-bin <path>] \
[--target-suffixed-entrypoint]
@@ -48,6 +49,10 @@ while [[ $# -gt 0 ]]; do
bwrap_bin_provided="true"
shift 2
;;
--zsh-manifest)
resource_args+=(--zsh-manifest "${2:?--zsh-manifest requires a value}")
shift 2
;;
--codex-command-runner-bin)
resource_args+=(
--codex-command-runner-bin
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env python3
"""Fail a terminal CI job unless every serialized dependency succeeded.
Parent workflows pass GitHub's `toJSON(needs)` object through the NEEDS
environment variable. Treat skipped and cancelled dependencies as failures too:
for a required fan-in job, only an explicit success is safe to accept.
"""
import json
import os
def main() -> None:
# Keep result policy in one script so blocking-ci and postmerge-ci cannot
# drift in how they interpret dependency conclusions.
needs = json.loads(os.environ["NEEDS"])
failures = sorted(
(name, dependency["result"])
for name, dependency in needs.items()
if dependency["result"] != "success"
)
if failures:
print("CI dependencies did not succeed:")
for name, result in failures:
print(f"{name}: {result}")
raise SystemExit(1)
print("All CI dependencies succeeded.")
if __name__ == "__main__":
main()
+87 -9
View File
@@ -1,12 +1,44 @@
#!/usr/bin/env python3
"""Decide which V8 canary work is needed for a commit range.
The workflow deliberately has no trigger-level path filters because it is both
directly triggered for pull requests and called by postmerge-ci. Keeping the
patterns here gives those entrypoints one source of truth; unrelated events
still run metadata but skip the expensive build matrices.
"""
import argparse
import subprocess
import tomllib
from fnmatch import fnmatchcase
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
# These patterns replace the old pull_request/push path filters. Include parent
# workflow changes because they can alter whether the canary is invoked.
CANARY_PATH_PATTERNS = {
".bazelrc",
".github/actions/setup-bazel-ci/**",
".github/scripts/run_bazel_with_buildbuddy.py",
".github/scripts/rusty_v8_bazel.py",
".github/scripts/rusty_v8_module_bazel.py",
".github/scripts/v8_canary_changes.py",
".github/workflows/postmerge-ci.yml",
".github/workflows/rusty-v8-release.yml",
".github/workflows/v8-canary.yml",
"MODULE.bazel",
"MODULE.bazel.lock",
"codex-rs/Cargo.toml",
"patches/BUILD.bazel",
"patches/llvm_*.patch",
"patches/rules_cc_*.patch",
"patches/v8_*.patch",
"third_party/v8/**",
}
# Windows source builds are a narrower, more expensive subset of the canary.
# A V8 version change also requires them even when no path below changed.
WINDOWS_SOURCE_BUILD_PATHS = {
".github/scripts/rusty_v8_bazel.py",
".github/scripts/rusty_v8_module_bazel.py",
@@ -16,6 +48,30 @@ WINDOWS_SOURCE_BUILD_PATHS = {
}
def matching_canary_paths(changed_files: set[str]) -> set[str]:
"""Return changed paths that require the general V8 build matrix."""
return {
path
for path in changed_files
if any(fnmatchcase(path, pattern) for pattern in CANARY_PATH_PATTERNS)
}
def canary_required(
changed_files: set[str],
base_v8_version: str,
head_v8_version: str,
*,
force: bool = False,
) -> bool:
"""Return whether the general V8 build matrix should run."""
return (
force
or base_v8_version != head_v8_version
or bool(matching_canary_paths(changed_files))
)
def resolved_v8_version(cargo_lock: bytes) -> str:
versions = sorted(
{
@@ -36,6 +92,7 @@ def windows_source_required(
*,
force: bool = False,
) -> bool:
"""Return whether Windows must rebuild rusty_v8 from source."""
return (
force
or base_v8_version != head_v8_version
@@ -58,6 +115,8 @@ def merge_base(base: str, head: str, *, root: Path = ROOT) -> str:
def changed_files(base: str, head: str, *, root: Path = ROOT) -> set[str]:
# Three-dot diff gives PRs merge-base semantics while remaining equivalent
# to before/after for ordinary linear pushes to main.
output = git_output(
"diff",
"--name-only",
@@ -79,25 +138,44 @@ def parse_args() -> argparse.Namespace:
def main() -> None:
args = parse_args()
if args.force:
required = True
reason = "manual workflow dispatch"
# workflow_dispatch has no comparison range, and callers use it as a
# manual retry path, so it intentionally runs every variant.
canary = True
canary_reason = "manual workflow dispatch"
windows_source = True
windows_source_reason = "manual workflow dispatch"
elif not args.base or not args.head:
raise SystemExit("--base and --head are required unless --force is set")
else:
files = changed_files(args.base, args.head)
base_version = v8_version_at_revision(merge_base(args.base, args.head))
head_version = v8_version_at_revision(args.head)
required = windows_source_required(files, base_version, head_version)
matched_canary_paths = sorted(matching_canary_paths(files))
canary = canary_required(files, base_version, head_version)
windows_source = windows_source_required(files, base_version, head_version)
if base_version != head_version:
reason = f"v8 version changed from {base_version} to {head_version}"
canary_reason = (
f"v8 version changed from {base_version} to {head_version}"
)
windows_source_reason = canary_reason
else:
matched_paths = sorted(files & WINDOWS_SOURCE_BUILD_PATHS)
reason = (
", ".join(matched_paths) if matched_paths else "no relevant changes"
canary_reason = (
", ".join(matched_canary_paths)
if matched_canary_paths
else "no relevant changes"
)
matched_windows_paths = sorted(files & WINDOWS_SOURCE_BUILD_PATHS)
windows_source_reason = (
", ".join(matched_windows_paths)
if matched_windows_paths
else "no relevant changes"
)
print(f"windows_source_required={str(required).lower()}")
print(f"windows_source_reason={reason}")
print(f"canary_required={str(canary).lower()}")
print(f"canary_reason={canary_reason}")
print(f"windows_source_required={str(windows_source).lower()}")
print(f"windows_source_reason={windows_source_reason}")
if __name__ == "__main__":
+1 -4
View File
@@ -4,10 +4,7 @@ name: Bazel
# https://github.com/cerisier/toolchains_llvm_bootstrapped/blob/main/.github/workflows/ci.yaml
on:
pull_request: {}
push:
branches:
- main
workflow_call:
workflow_dispatch:
concurrency:
+15 -4
View File
@@ -1,7 +1,7 @@
name: blob-size-policy
on:
pull_request: {}
workflow_call:
jobs:
check:
@@ -14,13 +14,24 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Determine PR comparison range
- name: Determine comparison range
id: range
shell: bash
run: |
set -euo pipefail
echo "base=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT"
echo "head=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
# PRs inspect the proposed diff; main pushes inspect only the commit
# range that just landed. Both paths feed the same blob-size checker.
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
base='${{ github.event.pull_request.base.sha }}'
head='${{ github.event.pull_request.head.sha }}'
else
base='${{ github.event.before }}'
head='${{ github.sha }}'
fi
echo "base=$base" >> "$GITHUB_OUTPUT"
echo "head=$head" >> "$GITHUB_OUTPUT"
- name: Check changed blob sizes
env:
+79
View File
@@ -0,0 +1,79 @@
name: blocking-ci
# This is the single entrypoint for checks that block a PR merge. It also runs
# after pushes to main so the same check family stays grouped in the Actions UI.
on:
pull_request: {}
push:
branches: [main]
jobs:
# Keep reusable workflow calls alphabetized. The `required` job below is the
# version-controlled list that the main-branch ruleset should require.
bazel:
name: Bazel
uses: ./.github/workflows/bazel.yml
secrets: inherit
blob-size-policy:
name: Blob size policy
uses: ./.github/workflows/blob-size-policy.yml
secrets: inherit
cargo-deny:
name: cargo-deny
uses: ./.github/workflows/cargo-deny.yml
secrets: inherit
codespell:
name: Codespell
uses: ./.github/workflows/codespell.yml
secrets: inherit
repo-checks:
name: repo-checks
uses: ./.github/workflows/repo-checks.yml
secrets: inherit
rust-ci:
name: rust-ci
uses: ./.github/workflows/rust-ci.yml
secrets: inherit
sdk:
name: sdk
uses: ./.github/workflows/sdk.yml
secrets: inherit
required:
name: CI required
# Without `always()`, GitHub skips this job after a failed dependency and a
# required check can appear successful instead of reporting the failure.
if: ${{ always() }}
needs:
- bazel
- blob-size-policy
- cargo-deny
- codespell
- repo-checks
- rust-ci
- sdk
runs-on: ubuntu-24.04
steps:
# Keep the helper on the same revision as the caller and child workflows.
# CI workflow uploads are restricted, so this repository does not need a
# separate trusted-base checkout for the terminal policy step. Using the
# PR head also lets the introducing PR exercise a newly added helper.
#
# During the initial rollout, PR branches created before
# check_ci_results.py exists must rebase onto main before this gate can
# run.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Require successful dependencies
env:
NEEDS: ${{ toJSON(needs) }}
run: python3 .github/scripts/check_ci_results.py
+1 -4
View File
@@ -1,10 +1,7 @@
name: cargo-deny
on:
pull_request:
push:
branches:
- main
workflow_call:
# Cargo's libgit2 transport has been flaky when fetching git dependencies with
# nested submodules. Prefer the system git CLI across every Cargo invocation.
+1 -4
View File
@@ -3,10 +3,7 @@
name: Codespell
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_call:
permissions:
contents: read
+1
View File
@@ -78,6 +78,7 @@ jobs:
30. automations - Issues involving scheduled automation tasks or heartbeats.
31. pets - Issues involving pets avatars and animations.
32. agent - Fallback only for core agent loop or agent-related issues that do not fit app-server, connectivity, subagent, session, config, plan, computer-use, browser, memory, imagen, remote, performance, automations, or pets.
33. aws-bedrock - Issues involving the Amazon Bedrock model provider or Bedrock Mantle. Do not use for unrelated AWS services or generic AWS mentions.
Issue number: ${{ github.event.issue.number }}
+40
View File
@@ -0,0 +1,40 @@
name: postmerge-ci
# This is the single entrypoint for main-only CI that is intentionally outside
# the merge-blocking suite. It keeps the broader postmerge signal in one run.
on:
push:
branches: [main]
jobs:
# Keep reusable workflow calls alphabetized. Each child retains its own
# workflow_dispatch trigger so maintainers can rerun flaky suites directly.
rust-ci-full:
name: rust-ci-full
uses: ./.github/workflows/rust-ci-full.yml
secrets: inherit
v8-canary:
name: v8-canary
uses: ./.github/workflows/v8-canary.yml
secrets: inherit
results:
name: Postmerge CI results
needs:
- rust-ci-full
- v8-canary
if: ${{ always() }}
runs-on: ubuntu-24.04
steps:
# Postmerge runs use the pushed main commit, so this helper always comes
# from the same revision that defined the parent workflow.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Require successful dependencies
env:
NEEDS: ${{ toJSON(needs) }}
run: python3 .github/scripts/check_ci_results.py
@@ -1,8 +1,7 @@
name: ci
name: repo-checks
on:
pull_request: {}
push: { branches: [main] }
workflow_call:
jobs:
build-test:
@@ -29,6 +28,9 @@ jobs:
- name: Test Codex package builder
run: python3 -m unittest discover -s scripts/codex_package -p 'test_*.py'
- name: Test standalone installer
run: python3 -m unittest discover -s scripts/install -p 'test_*.py'
- name: Setup pnpm
uses: pnpm/action-setup@a8198c4bff370c8506180b035930dea56dbd5288 # v5
with:
+3 -1
View File
@@ -1,8 +1,10 @@
name: rust-ci-full
on:
workflow_call:
push:
branches:
- main
# Main pushes enter through postmerge-ci. Keep this opt-in branch trigger
# for developers who want the full suite before merging.
- "**full-ci**"
workflow_dispatch:
+1 -1
View File
@@ -1,6 +1,6 @@
name: rust-ci
on:
pull_request: {}
workflow_call:
workflow_dispatch:
# Cargo's libgit2 transport has been flaky when fetching git dependencies with
+80 -1
View File
@@ -1,15 +1,56 @@
name: rust-release-zsh
on:
workflow_call:
push:
tags:
- "codex-zsh-v*.*.*"
env:
ZSH_COMMIT: 77045ef899e53b9598bebc5a41db93a548a40ca6
ZSH_PATCH: codex-rs/shell-escalation/patches/zsh-exec-wrapper.patch
concurrency:
group: ${{ github.workflow }}::${{ github.ref_name }}
cancel-in-progress: false
jobs:
metadata:
runs-on: ubuntu-latest
outputs:
release_tag: ${{ steps.release_tag.outputs.release_tag }}
steps:
- name: Validate release tag
id: release_tag
env:
RELEASE_TAG: ${{ github.ref_name }}
shell: bash
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^codex-zsh-v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Tag ${RELEASE_TAG} does not match codex-zsh-vX.Y.Z." >&2
exit 1
fi
echo "release_tag=${RELEASE_TAG}" >> "${GITHUB_OUTPUT}"
- name: Ensure release does not exist
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ steps.release_tag.outputs.release_tag }}
shell: bash
run: |
set -euo pipefail
if gh release view "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" > /dev/null 2>&1; then
echo "Release ${RELEASE_TAG} already exists; publish changed artifacts under a new tag." >&2
exit 1
fi
linux:
name: Build zsh (Linux) - ${{ matrix.variant }} - ${{ matrix.target }}
needs: metadata
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
container:
@@ -62,6 +103,7 @@ jobs:
darwin:
name: Build zsh (macOS) - ${{ matrix.variant }} - ${{ matrix.target }}
needs: metadata
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
@@ -101,3 +143,40 @@ jobs:
with:
name: codex-zsh-${{ matrix.target }}
path: dist/zsh/${{ matrix.target }}/*
publish-release:
needs:
- metadata
- linux
- darwin
runs-on: ubuntu-latest
permissions:
contents: write
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
- name: Create GitHub Release
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
with:
tag_name: ${{ needs.metadata.outputs.release_tag }}
name: ${{ needs.metadata.outputs.release_tag }}
files: dist/**
# Keep zsh artifact releases out of Codex's normal "latest release" channel.
prerelease: true
- name: Publish DotSlash manifest
uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ needs.metadata.outputs.release_tag }}
config: .github/dotslash-zsh-config.json
+26 -18
View File
@@ -14,6 +14,9 @@ on:
tags:
- "rust-v*.*.*"
env:
CODEX_ZSH_RELEASE_TAG: codex-zsh-v0.1.0
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
@@ -354,6 +357,15 @@ jobs:
cp target/${{ matrix.target }}/release/codex-${{ matrix.target }}.dmg "$dest/codex-${{ matrix.target }}.dmg"
fi
- name: Download packaged zsh manifest
if: ${{ runner.os != 'macOS' }}
shell: bash
run: |
set -euo pipefail
curl -fsSL \
"https://github.com/${GITHUB_REPOSITORY}/releases/download/${CODEX_ZSH_RELEASE_TAG}/codex-zsh" \
-o "${RUNNER_TEMP}/codex-zsh"
- name: Build Codex package archive
if: ${{ runner.os != 'macOS' }}
shell: bash
@@ -366,7 +378,8 @@ jobs:
--target "$TARGET" \
--bundle "$BUNDLE" \
--entrypoint-dir "target/${TARGET}/release" \
--archive-dir "dist/${TARGET}"
--archive-dir "dist/${TARGET}" \
--zsh-manifest "${RUNNER_TEMP}/codex-zsh"
- name: Build Python runtime wheel
if: ${{ matrix.bundle == 'primary' && runner.os != 'macOS' }}
@@ -697,6 +710,14 @@ jobs:
cp "target/${{ matrix.target }}/release/${binary}" "$dest/${binary}-${{ matrix.target }}"
done
- name: Download packaged zsh manifest
shell: bash
run: |
set -euo pipefail
curl -fsSL \
"https://github.com/${GITHUB_REPOSITORY}/releases/download/${CODEX_ZSH_RELEASE_TAG}/codex-zsh" \
-o "${RUNNER_TEMP}/codex-zsh"
- name: Build Codex package archive
shell: bash
env:
@@ -708,7 +729,8 @@ jobs:
--target "$TARGET" \
--bundle "$BUNDLE" \
--entrypoint-dir "target/${TARGET}/release" \
--archive-dir "dist/${TARGET}"
--archive-dir "dist/${TARGET}" \
--zsh-manifest "${RUNNER_TEMP}/codex-zsh"
- name: Build Python runtime wheel
if: ${{ matrix.bundle == 'primary' }}
@@ -1043,11 +1065,6 @@ jobs:
with:
publish: true
zsh-release-assets:
name: zsh release assets
needs: tag-check
uses: ./.github/workflows/rust-release-zsh.yml
release:
needs:
- tag-check
@@ -1055,7 +1072,6 @@ jobs:
- finalize-macos
- build-windows
- argument-comment-lint-release-assets
- zsh-release-assets
if: >-
${{
always() &&
@@ -1063,8 +1079,7 @@ jobs:
needs.build.result == 'success' &&
needs.finalize-macos.result == 'success' &&
needs.build-windows.result == 'success' &&
needs.argument-comment-lint-release-assets.result == 'success' &&
needs.zsh-release-assets.result == 'success'
needs.argument-comment-lint-release-assets.result == 'success'
}}
name: release
runs-on: ubuntu-latest
@@ -1113,7 +1128,7 @@ jobs:
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
pattern: "{*-symbols,argument-comment-lint-*,codex-zsh-*,python-runtime-wheel-*}"
pattern: "{*-symbols,argument-comment-lint-*,python-runtime-wheel-*}"
- name: List
run: ls -R dist/
@@ -1236,13 +1251,6 @@ jobs:
tag: ${{ github.ref_name }}
config: .github/dotslash-config.json
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ github.ref_name }}
config: .github/dotslash-zsh-config.json
- uses: facebook/dotslash-publish-release@9c9ec027515c34db9282a09a25a9cab5880b2c52 # v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1 -3
View File
@@ -1,9 +1,7 @@
name: sdk
on:
push:
branches: [main]
pull_request: {}
workflow_call:
jobs:
python-sdk:
+15 -39
View File
@@ -1,44 +1,12 @@
name: v8-canary
# Do not use trigger-level path filters here. This workflow is also called by
# postmerge-ci, and GitHub cannot share a path filter between pull_request and
# workflow_call. v8_canary_changes.py is the single source of truth instead;
# unrelated events run only the cheap metadata job below.
on:
pull_request:
paths:
- ".bazelrc"
- ".github/actions/setup-bazel-ci/**"
- ".github/scripts/run_bazel_with_buildbuddy.py"
- ".github/scripts/rusty_v8_bazel.py"
- ".github/scripts/rusty_v8_module_bazel.py"
- ".github/scripts/v8_canary_changes.py"
- ".github/workflows/rusty-v8-release.yml"
- ".github/workflows/v8-canary.yml"
- "MODULE.bazel"
- "MODULE.bazel.lock"
- "codex-rs/Cargo.toml"
- "patches/BUILD.bazel"
- "patches/llvm_*.patch"
- "patches/rules_cc_*.patch"
- "patches/v8_*.patch"
- "third_party/v8/**"
push:
branches:
- main
paths:
- ".bazelrc"
- ".github/actions/setup-bazel-ci/**"
- ".github/scripts/run_bazel_with_buildbuddy.py"
- ".github/scripts/rusty_v8_bazel.py"
- ".github/scripts/rusty_v8_module_bazel.py"
- ".github/scripts/v8_canary_changes.py"
- ".github/workflows/rusty-v8-release.yml"
- ".github/workflows/v8-canary.yml"
- "MODULE.bazel"
- "MODULE.bazel.lock"
- "codex-rs/Cargo.toml"
- "patches/BUILD.bazel"
- "patches/llvm_*.patch"
- "patches/rules_cc_*.patch"
- "patches/v8_*.patch"
- "third_party/v8/**"
workflow_call:
pull_request: {}
workflow_dispatch:
# Cargo's libgit2 transport has been flaky when fetching git dependencies with
@@ -54,6 +22,10 @@ jobs:
metadata:
runs-on: ubuntu-latest
outputs:
# A stale PR head can contain the old detector, which does not emit this
# output. Missing must mean "run" so older branches cannot silently skip
# the expensive V8 coverage while reporting success.
canary_required: ${{ steps.changes.outputs.canary_required || 'true' }}
v8_version: ${{ steps.v8_version.outputs.version }}
windows_source_required: ${{ steps.changes.outputs.windows_source_required }}
@@ -77,7 +49,7 @@ jobs:
version="$(python3 .github/scripts/rusty_v8_bazel.py resolved-v8-crate-version)"
echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: Detect whether Windows source artifacts need rebuilding
- name: Detect V8 canary changes
id: changes
env:
BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
@@ -87,6 +59,8 @@ jobs:
run: |
set -euo pipefail
# Manual runs have no meaningful before/after range. Force every V8
# variant so workflow_dispatch remains a reliable retry path.
if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
output="$(python3 .github/scripts/v8_canary_changes.py --force)"
else
@@ -104,6 +78,8 @@ jobs:
build:
name: Build ${{ matrix.variant }} ${{ matrix.target }}
needs: metadata
# Metadata always runs; only relevant changes pay for the large matrix.
if: ${{ needs.metadata.outputs.canary_required == 'true' }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
+4 -3
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -21,7 +21,7 @@ curl -fsSL https://chatgpt.com/codex/install.sh | sh
Run the following on Windows to install Codex CLI:
```
```shell
powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"
```
-46
View File
@@ -1,46 +0,0 @@
# https://git-cliff.org/docs/configuration
[changelog]
header = """
# Changelog
You can install any of these versions: `npm install -g @openai/codex@<version>`
"""
body = """
{% if version -%}
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{%- else %}
## [unreleased]
{% endif %}
{%- for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim }}
{% for commit in commits %}- {% if commit.scope %}*({{ commit.scope }})* {% endif %}{% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}
{% endfor %}
{%- endfor -%}
"""
footer = """
<!-- generated - do not edit -->
"""
trim = true
postprocessors = []
[git]
conventional_commits = true
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🪲 Bug Fixes" },
{ message = "^bump", group = "<!-- 6 -->🛳️ Release" },
# Fallback – skip anything that didn't match the above rules.
{ message = ".*", group = "<!-- 10 -->💼 Other" },
]
filter_unconventional = false
sort_commits = "oldest"
topo_order = false
+3 -1
View File
@@ -1,5 +1,5 @@
[advisories]
# Reviewed 2026-06-07. Keep this list in sync with ../deny.toml.
# Reviewed 2026-07-02. Keep this list in sync with ../deny.toml.
ignore = [
"RUSTSEC-2024-0388", # derivative 2.2.0 via starlark/starlark_syntax; upstream crate is unmaintained
"RUSTSEC-2025-0057", # fxhash 0.2.1 via starlark_map/bm25; upstream crate is unmaintained
@@ -10,4 +10,6 @@ ignore = [
"RUSTSEC-2026-0118", # hickory-proto via rama-dns/rama-tcp; remove when rama updates to hickory 0.26.1 or hickory-net
"RUSTSEC-2026-0119", # hickory-proto via rama-dns/rama-tcp; remove when rama updates to hickory 0.26.1 or hickory-net
"RUSTSEC-2026-0173", # proc-macro-error2 via i18n-embed-fl/age/codex-secrets; remove when local secrets storage migrates off age or age drops i18n-embed-fl
"RUSTSEC-2026-0194", # quick-xml via plist/syntect and wayland-scanner; trusted inputs only; remove when rust-plist#191 and wayland-rs#938 are released
"RUSTSEC-2026-0195", # quick-xml via plist/syntect and wayland-scanner; trusted inputs only; remove when rust-plist#191 and wayland-rs#938 are released
]
+63 -12
View File
@@ -2173,9 +2173,11 @@ dependencies = [
"futures",
"gethostname",
"hmac 0.12.1",
"httpdate",
"jsonwebtoken",
"owo-colors",
"pretty_assertions",
"rand 0.9.3",
"serde",
"serde_json",
"sha2 0.10.9",
@@ -2314,6 +2316,7 @@ name = "codex-cli"
version = "0.0.0"
dependencies = [
"anyhow",
"app_test_support",
"assert_cmd",
"assert_matches",
"clap",
@@ -2503,6 +2506,7 @@ dependencies = [
"codex-code-mode-protocol",
"codex-protocol",
"deno_core_icudata",
"futures",
"pretty_assertions",
"serde_json",
"tokio",
@@ -2514,6 +2518,17 @@ dependencies = [
[[package]]
name = "codex-code-mode-host"
version = "0.0.0"
dependencies = [
"anyhow",
"codex-code-mode",
"codex-code-mode-protocol",
"codex-protocol",
"codex-utils-cargo-bin",
"pretty_assertions",
"serde_json",
"tokio",
"tokio-util",
]
[[package]]
name = "codex-code-mode-protocol"
@@ -2557,6 +2572,7 @@ dependencies = [
"multimap",
"pretty_assertions",
"prost 0.14.3",
"regex-lite",
"schemars 0.8.22",
"serde",
"serde_ignored",
@@ -2584,6 +2600,8 @@ version = "0.0.0"
dependencies = [
"anyhow",
"codex-config",
"codex-plugin",
"indexmap 2.14.0",
"pretty_assertions",
"serde",
"serde_json",
@@ -2594,6 +2612,18 @@ dependencies = [
"urlencoding",
]
[[package]]
name = "codex-connectors-extension"
version = "0.0.0"
dependencies = [
"codex-connectors",
"codex-core-plugins",
"codex-plugin",
"codex-utils-path-uri",
"serde_json",
"thiserror 2.0.18",
]
[[package]]
name = "codex-context-fragments"
version = "0.0.0"
@@ -2615,6 +2645,7 @@ dependencies = [
"bm25",
"chrono",
"clap",
"codex-agent-graph-store",
"codex-analytics",
"codex-api",
"codex-app-server-protocol",
@@ -2755,6 +2786,7 @@ dependencies = [
"codex-analytics",
"codex-app-server-protocol",
"codex-config",
"codex-connectors",
"codex-core-skills",
"codex-exec-server",
"codex-git-utils",
@@ -2772,7 +2804,6 @@ dependencies = [
"codex-utils-plugins",
"dirs",
"flate2",
"indexmap 2.14.0",
"libc",
"pretty_assertions",
"regex",
@@ -2888,6 +2919,7 @@ dependencies = [
"codex-exec-server-protocol",
"codex-file-system",
"codex-network-proxy",
"codex-otel",
"codex-protocol",
"codex-sandboxing",
"codex-test-binary-support",
@@ -2899,9 +2931,13 @@ dependencies = [
"futures",
"http 1.4.0",
"libc",
"opentelemetry",
"opentelemetry_sdk",
"pretty_assertions",
"prost 0.14.3",
"rcgen",
"reqwest 0.12.28",
"rustls",
"serde",
"serde_json",
"serial_test",
@@ -2913,6 +2949,8 @@ dependencies = [
"tokio-util",
"toml 0.9.11+spec-1.1.0",
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
"uuid",
"windows-sys 0.52.0",
"wiremock",
@@ -2989,6 +3027,7 @@ dependencies = [
"codex-tools",
"codex-utils-absolute-path",
"pretty_assertions",
"serde_json",
"tokio",
]
@@ -3038,6 +3077,7 @@ dependencies = [
"anyhow",
"codex-login",
"codex-protocol",
"mime_guess",
"pretty_assertions",
"sentry",
"tracing",
@@ -3224,6 +3264,7 @@ dependencies = [
"clap",
"codex-core",
"codex-install-context",
"codex-network-proxy",
"codex-process-hardening",
"codex-protocol",
"codex-sandboxing",
@@ -3306,6 +3347,7 @@ dependencies = [
"codex-api",
"codex-async-utils",
"codex-config",
"codex-connectors",
"codex-exec-server",
"codex-login",
"codex-model-provider",
@@ -3335,6 +3377,7 @@ name = "codex-mcp-extension"
version = "0.0.0"
dependencies = [
"codex-config",
"codex-connectors-extension",
"codex-core",
"codex-core-plugins",
"codex-exec-server",
@@ -3548,6 +3591,7 @@ dependencies = [
"rama-tcp",
"rama-tls-rustls",
"rama-unix",
"rand 0.9.3",
"rustls-native-certs",
"schannel",
"security-framework 3.5.1",
@@ -3670,7 +3714,7 @@ dependencies = [
"icu_provider",
"landlock",
"pretty_assertions",
"quick-xml",
"quick-xml 0.41.0",
"reqwest 0.12.28",
"schemars 0.8.22",
"seccompiler",
@@ -3735,7 +3779,6 @@ dependencies = [
"base64 0.22.1",
"bytes",
"codex-api",
"codex-client",
"codex-config",
"codex-exec-server",
"codex-keyring-store",
@@ -4013,7 +4056,6 @@ dependencies = [
name = "codex-tools"
version = "0.0.0"
dependencies = [
"codex-app-server-protocol",
"codex-code-mode",
"codex-connectors",
"codex-features",
@@ -10231,13 +10273,13 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "plist"
version = "1.8.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1"
dependencies = [
"base64 0.22.1",
"indexmap 2.14.0",
"quick-xml",
"quick-xml 0.39.4",
"serde",
"time",
]
@@ -10670,9 +10712,18 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
version = "0.38.4"
version = "0.39.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e"
dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
dependencies = [
"memchr",
"serde",
@@ -14633,12 +14684,12 @@ dependencies = [
[[package]]
name = "wayland-scanner"
version = "0.31.8"
version = "0.31.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3"
checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a"
dependencies = [
"proc-macro2",
"quick-xml",
"quick-xml 0.39.4",
"quote",
]
+4 -2
View File
@@ -48,6 +48,7 @@ members = [
"exec-server",
"execpolicy",
"execpolicy-legacy",
"ext/connectors",
"ext/extension-api",
"ext/goal",
"ext/guardian",
@@ -165,6 +166,7 @@ codex-code-mode-protocol = { path = "code-mode-protocol" }
codex-home = { path = "codex-home" }
codex-config = { path = "config" }
codex-connectors = { path = "connectors" }
codex-connectors-extension = { path = "ext/connectors" }
codex-context-fragments = { path = "context-fragments" }
codex-core = { path = "core" }
codex-core-api = { path = "core-api" }
@@ -316,6 +318,7 @@ glob = "0.3"
globset = "0.4"
hmac = "0.12.1"
http = "1.3.1"
httpdate = "1.0.3"
iana-time-zone = "0.1.64"
icu_decimal = "2.1"
icu_locale_core = "2.1"
@@ -359,7 +362,7 @@ portable-pty = "0.9.0"
predicates = "3"
pretty_assertions = "1.4.1"
pulldown-cmark = "0.10"
quick-xml = "0.38.4"
quick-xml = "0.41.0"
rand = "0.9"
ratatui = "0.29.0"
ratatui-macros = "0.6.0"
@@ -504,7 +507,6 @@ unwrap_used = "deny"
# silence the false positive here instead of deleting a real dependency.
[workspace.metadata.cargo-shear]
ignored = [
"codex-agent-graph-store",
"icu_provider",
"openssl-sys",
"codex-v8-poc",
+1 -1
View File
@@ -22,4 +22,4 @@ thiserror = { workspace = true }
pretty_assertions = { workspace = true }
serde_json = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
+1
View File
@@ -9,4 +9,5 @@ pub use error::AgentGraphStoreError;
pub use error::AgentGraphStoreResult;
pub use local::LocalAgentGraphStore;
pub use store::AgentGraphStore;
pub use store::AgentGraphStoreFuture;
pub use types::ThreadSpawnEdgeStatus;
+58 -40
View File
@@ -4,7 +4,7 @@ use std::sync::Arc;
use crate::AgentGraphStore;
use crate::AgentGraphStoreError;
use crate::AgentGraphStoreResult;
use crate::AgentGraphStoreFuture;
use crate::ThreadSpawnEdgeStatus;
/// SQLite-backed implementation of [`AgentGraphStore`] using an existing state runtime.
@@ -29,65 +29,83 @@ impl LocalAgentGraphStore {
}
impl AgentGraphStore for LocalAgentGraphStore {
async fn upsert_thread_spawn_edge(
fn upsert_thread_spawn_edge(
&self,
parent_thread_id: ThreadId,
child_thread_id: ThreadId,
status: ThreadSpawnEdgeStatus,
) -> AgentGraphStoreResult<()> {
self.state_db
.upsert_thread_spawn_edge(parent_thread_id, child_thread_id, to_state_status(status))
.await
.map_err(internal_error)
) -> AgentGraphStoreFuture<'_, ()> {
Box::pin(async move {
self.state_db
.upsert_thread_spawn_edge(
parent_thread_id,
child_thread_id,
to_state_status(status),
)
.await
.map_err(internal_error)
})
}
async fn set_thread_spawn_edge_status(
fn set_thread_spawn_edge_status(
&self,
child_thread_id: ThreadId,
status: ThreadSpawnEdgeStatus,
) -> AgentGraphStoreResult<()> {
self.state_db
.set_thread_spawn_edge_status(child_thread_id, to_state_status(status))
.await
.map_err(internal_error)
) -> AgentGraphStoreFuture<'_, ()> {
Box::pin(async move {
self.state_db
.set_thread_spawn_edge_status(child_thread_id, to_state_status(status))
.await
.map_err(internal_error)
})
}
async fn list_thread_spawn_children(
fn list_thread_spawn_children(
&self,
parent_thread_id: ThreadId,
status_filter: Option<ThreadSpawnEdgeStatus>,
) -> AgentGraphStoreResult<Vec<ThreadId>> {
if let Some(status) = status_filter {
return self
.state_db
.list_thread_spawn_children_with_status(parent_thread_id, to_state_status(status))
.await
.map_err(internal_error);
}
) -> AgentGraphStoreFuture<'_, Vec<ThreadId>> {
Box::pin(async move {
if let Some(status) = status_filter {
return self
.state_db
.list_thread_spawn_children_with_status(
parent_thread_id,
to_state_status(status),
)
.await
.map_err(internal_error);
}
self.state_db
.list_thread_spawn_children(parent_thread_id)
.await
.map_err(internal_error)
self.state_db
.list_thread_spawn_children(parent_thread_id)
.await
.map_err(internal_error)
})
}
async fn list_thread_spawn_descendants(
fn list_thread_spawn_descendants(
&self,
root_thread_id: ThreadId,
status_filter: Option<ThreadSpawnEdgeStatus>,
) -> AgentGraphStoreResult<Vec<ThreadId>> {
match status_filter {
Some(status) => self
.state_db
.list_thread_spawn_descendants_with_status(root_thread_id, to_state_status(status))
.await
.map_err(internal_error),
None => self
.state_db
.list_thread_spawn_descendants(root_thread_id)
.await
.map_err(internal_error),
}
) -> AgentGraphStoreFuture<'_, Vec<ThreadId>> {
Box::pin(async move {
match status_filter {
Some(status) => self
.state_db
.list_thread_spawn_descendants_with_status(
root_thread_id,
to_state_status(status),
)
.await
.map_err(internal_error),
None => self
.state_db
.list_thread_spawn_descendants(root_thread_id)
.await
.map_err(internal_error),
}
})
}
}
+11 -4
View File
@@ -1,8 +1,15 @@
use std::future::Future;
use std::pin::Pin;
use codex_protocol::ThreadId;
use crate::AgentGraphStoreResult;
use crate::ThreadSpawnEdgeStatus;
/// Future returned by [`AgentGraphStore`] operations.
pub type AgentGraphStoreFuture<'a, T> =
Pin<Box<dyn Future<Output = AgentGraphStoreResult<T>> + Send + 'a>>;
/// Storage-neutral boundary for persisted thread-spawn parent/child topology.
///
/// Implementations are expected to return stable ordering for list methods so callers can merge
@@ -17,7 +24,7 @@ pub trait AgentGraphStore: Send + Sync {
parent_thread_id: ThreadId,
child_thread_id: ThreadId,
status: ThreadSpawnEdgeStatus,
) -> impl std::future::Future<Output = AgentGraphStoreResult<()>> + Send;
) -> AgentGraphStoreFuture<'_, ()>;
/// Update the persisted lifecycle status of a spawned thread's incoming edge.
///
@@ -26,7 +33,7 @@ pub trait AgentGraphStore: Send + Sync {
&self,
child_thread_id: ThreadId,
status: ThreadSpawnEdgeStatus,
) -> impl std::future::Future<Output = AgentGraphStoreResult<()>> + Send;
) -> AgentGraphStoreFuture<'_, ()>;
/// List direct spawned children of a parent thread.
///
@@ -37,7 +44,7 @@ pub trait AgentGraphStore: Send + Sync {
&self,
parent_thread_id: ThreadId,
status_filter: Option<ThreadSpawnEdgeStatus>,
) -> impl std::future::Future<Output = AgentGraphStoreResult<Vec<ThreadId>>> + Send;
) -> AgentGraphStoreFuture<'_, Vec<ThreadId>>;
/// List spawned descendants breadth-first by depth, then by thread id.
///
@@ -49,5 +56,5 @@ pub trait AgentGraphStore: Send + Sync {
&self,
root_thread_id: ThreadId,
status_filter: Option<ThreadSpawnEdgeStatus>,
) -> impl std::future::Future<Output = AgentGraphStoreResult<Vec<ThreadId>>> + Send;
) -> AgentGraphStoreFuture<'_, Vec<ThreadId>>;
}
@@ -62,6 +62,10 @@ use crate::facts::HookRunInput;
use crate::facts::InputError;
use crate::facts::InvocationType;
use crate::facts::PluginInstallFailedInput;
use crate::facts::PluginInstallRequestSource;
use crate::facts::PluginInstallRequested;
use crate::facts::PluginInstallRequestedInput;
use crate::facts::PluginInstallRequestedPlugin;
use crate::facts::PluginState;
use crate::facts::PluginStateChangedInput;
use crate::facts::PluginUsedInput;
@@ -194,6 +198,7 @@ fn sample_thread_with_metadata(
parent_thread_id,
preview: "first prompt".to_string(),
ephemeral,
history_mode: Default::default(),
model_provider: "openai".to_string(),
created_at: 1,
updated_at: 2,
@@ -554,6 +559,7 @@ async fn ingest_rejected_turn_steer(
response: Box::new(sample_thread_resume_response(
"thread-2", /*ephemeral*/ false, "gpt-5",
)),
thread_originator: None,
},
out,
)
@@ -627,6 +633,7 @@ async fn ingest_turn_prerequisites(
response: Box::new(sample_thread_start_response(
"thread-2", /*ephemeral*/ false, "gpt-5",
)),
thread_originator: None,
},
out,
)
@@ -650,6 +657,7 @@ async fn ingest_turn_prerequisites(
connection_id: 7,
request_id: RequestId::Integer(3),
response: Box::new(sample_turn_start_response("turn-2")),
thread_originator: None,
},
out,
)
@@ -716,6 +724,7 @@ async fn ingest_review_prerequisites(
response: Box::new(sample_thread_start_response(
"thread-1", /*ephemeral*/ false, "gpt-5",
)),
thread_originator: None,
},
events,
)
@@ -1648,6 +1657,7 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize
/*ephemeral*/ false,
"gpt-5",
)),
thread_originator: None,
},
&mut events,
)
@@ -1693,6 +1703,7 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize
response: Box::new(sample_thread_resume_response(
"thread-1", /*ephemeral*/ true, "gpt-5",
)),
thread_originator: None,
},
&mut events,
)
@@ -1737,6 +1748,157 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize
);
}
#[tokio::test]
async fn thread_originator_overrides_shared_connection_across_thread_events() {
let mut reducer = AnalyticsReducer::default();
let mut events = Vec::new();
reducer
.ingest(sample_initialize_fact(/*connection_id*/ 7), &mut events)
.await;
for (request_id, thread_id, thread_originator) in [
(1, "thread-work", Some(TEST_PRODUCT_CLIENT_ID.to_string())),
(2, "thread-default", None),
] {
reducer
.ingest(
AnalyticsFact::ClientResponse {
connection_id: 7,
request_id: RequestId::Integer(request_id),
response: Box::new(sample_thread_start_response(
thread_id, /*ephemeral*/ false, "gpt-5",
)),
thread_originator,
},
&mut events,
)
.await;
}
let initialized = serde_json::to_value(&events).expect("serialize thread events");
assert_eq!(
initialized
.as_array()
.expect("thread events")
.iter()
.map(|event| {
json!({
"thread_id": event["event_params"]["thread_id"],
"app_server_client": event["event_params"]["app_server_client"],
})
})
.collect::<Vec<_>>(),
vec![
json!({
"thread_id": "thread-work",
"app_server_client": {
"product_client_id": TEST_PRODUCT_CLIENT_ID,
"client_name": "codex-tui",
"client_version": "1.0.0",
"rpc_transport": "websocket",
"experimental_api_enabled": false,
},
}),
json!({
"thread_id": "thread-default",
"app_server_client": {
"product_client_id": DEFAULT_ORIGINATOR,
"client_name": "codex-tui",
"client_version": "1.0.0",
"rpc_transport": "websocket",
"experimental_api_enabled": false,
},
}),
]
);
events.clear();
reducer
.ingest(
AnalyticsFact::ClientRequest {
connection_id: 7,
request_id: RequestId::Integer(3),
request: Box::new(sample_turn_start_request(
"thread-work",
/*request_id*/ 3,
)),
},
&mut events,
)
.await;
reducer
.ingest(
AnalyticsFact::ClientResponse {
connection_id: 7,
request_id: RequestId::Integer(3),
response: Box::new(sample_turn_start_response("turn-1")),
thread_originator: None,
},
&mut events,
)
.await;
ingest_completed_command_execution_item(&mut reducer, &mut events, "thread-work", "item-work")
.await;
ingest_complete_child_turn(&mut reducer, &mut events, "thread-work", "turn-1").await;
reducer
.ingest(
AnalyticsFact::Custom(CustomAnalyticsFact::Compaction(Box::new(
CodexCompactionEvent {
thread_id: "thread-work".to_string(),
turn_id: "turn-compact".to_string(),
trigger: CompactionTrigger::Manual,
reason: CompactionReason::UserRequested,
implementation: CompactionImplementation::Responses,
phase: CompactionPhase::StandaloneTurn,
strategy: CompactionStrategy::Memento,
status: CompactionStatus::Completed,
codex_error_kind: None,
codex_error_http_status_code: None,
active_context_tokens_before: 131_000,
active_context_tokens_after: 64_000,
retained_image_count: None,
compaction_summary_tokens: None,
cached_input_tokens: None,
started_at: 100,
completed_at: 101,
duration_ms: Some(1200),
},
))),
&mut events,
)
.await;
let lifecycle = serde_json::to_value(&events).expect("serialize lifecycle events");
assert_eq!(
lifecycle
.as_array()
.expect("lifecycle events")
.iter()
.map(|event| {
json!({
"event_type": event["event_type"],
"product_client_id":
event["event_params"]["app_server_client"]["product_client_id"],
})
})
.collect::<Vec<_>>(),
vec![
json!({
"event_type": "codex_command_execution_event",
"product_client_id": TEST_PRODUCT_CLIENT_ID,
}),
json!({
"event_type": "codex_turn_event",
"product_client_id": TEST_PRODUCT_CLIENT_ID,
}),
json!({
"event_type": "codex_compaction_event",
"product_client_id": TEST_PRODUCT_CLIENT_ID,
}),
]
);
}
#[tokio::test]
async fn unrelated_client_requests_are_ignored_by_reducer() {
let mut reducer = AnalyticsReducer::default();
@@ -1763,6 +1925,7 @@ async fn unrelated_client_requests_are_ignored_by_reducer() {
connection_id: 7,
request_id: RequestId::Integer(3),
response: Box::new(sample_turn_start_response("turn-2")),
thread_originator: None,
},
&mut events,
)
@@ -1788,6 +1951,7 @@ async fn unrelated_client_responses_are_ignored_by_reducer() {
response: Box::new(ClientResponsePayload::ThreadArchive(
ThreadArchiveResponse {},
)),
thread_originator: None,
},
&mut events,
)
@@ -1847,6 +2011,7 @@ async fn compaction_event_ingests_custom_fact() {
Some(AppServerThreadSource::Subagent),
Some(parent_thread_id.to_string()),
)),
thread_originator: None,
},
&mut events,
)
@@ -1967,6 +2132,7 @@ async fn guardian_review_event_ingests_custom_fact_with_optional_target_item() {
/*ephemeral*/ false,
"gpt-5",
)),
thread_originator: None,
},
&mut events,
)
@@ -2495,6 +2661,7 @@ async fn item_review_summaries_do_not_cross_threads_with_reused_item_ids() {
response: Box::new(sample_thread_start_response(
"thread-2", /*ephemeral*/ false, "gpt-5",
)),
thread_originator: None,
},
&mut events,
)
@@ -2745,7 +2912,7 @@ async fn subagent_thread_started_publishes_without_initialize() {
}
#[tokio::test]
async fn subagent_events_use_inherited_connection_unless_turn_connection_is_explicit() {
async fn subagent_events_keep_thread_originator_with_explicit_turn_connection() {
let mut reducer = AnalyticsReducer::default();
let mut events = Vec::new();
let parent_thread_id =
@@ -2782,6 +2949,7 @@ async fn subagent_events_use_inherited_connection_unless_turn_connection_is_expl
/*ephemeral*/ false,
"gpt-5",
)),
thread_originator: None,
},
&mut events,
)
@@ -2904,6 +3072,7 @@ async fn subagent_events_use_inherited_connection_unless_turn_connection_is_expl
connection_id: 8,
request_id: RequestId::Integer(3),
response: Box::new(sample_turn_start_response("turn-explicit")),
thread_originator: None,
},
&mut events,
)
@@ -2914,7 +3083,11 @@ async fn subagent_events_use_inherited_connection_unless_turn_connection_is_expl
};
assert_eq!(
event.event_params.app_server_client.product_client_id,
DEFAULT_ORIGINATOR
"parent-client"
);
assert_eq!(
event.event_params.app_server_client.client_name.as_deref(),
Some("codex-tui")
);
}
@@ -3447,6 +3620,66 @@ async fn reducer_ingests_plugin_state_changed_fact() {
);
}
#[tokio::test]
async fn reducer_ingests_plugin_install_requested_fact() {
let mut reducer = AnalyticsReducer::default();
let mut events = Vec::new();
let tracking = test_tracking_context("thread-1", "turn-1");
let request = PluginInstallRequested {
suggestion_id: "request_plugin_install_call-1".to_string(),
plugins: vec![
PluginInstallRequestedPlugin {
plugin_id: "calendar@openai-curated-remote".to_string(),
remote_plugin_id: Some("plugin_calendar".to_string()),
plugin_name: "Calendar".to_string(),
connector_ids: vec!["connector_calendar".to_string()],
},
PluginInstallRequestedPlugin {
plugin_id: "github@openai-curated-remote".to_string(),
remote_plugin_id: None,
plugin_name: "GitHub".to_string(),
connector_ids: vec!["connector_github".to_string()],
},
],
source: PluginInstallRequestSource::EndpointRecommendation,
};
reducer
.ingest(
AnalyticsFact::Custom(CustomAnalyticsFact::PluginInstallRequested(
PluginInstallRequestedInput { tracking, request },
)),
&mut events,
)
.await;
assert_eq!(
serde_json::to_value(&events).expect("serialize events"),
json!([{
"event_type": "codex_plugin_install_requested",
"event_params": {
"suggestion_id": "request_plugin_install_call-1",
"plugins": [{
"plugin_id": "calendar@openai-curated-remote",
"remote_plugin_id": "plugin_calendar",
"plugin_name": "Calendar",
"connector_ids": ["connector_calendar"],
}, {
"plugin_id": "github@openai-curated-remote",
"remote_plugin_id": null,
"plugin_name": "GitHub",
"connector_ids": ["connector_github"],
}],
"source": "endpoint_recommendation",
"thread_id": "thread-1",
"turn_id": "turn-1",
"model_slug": "gpt-5",
"product_client_id": originator().value,
}
}])
);
}
#[tokio::test]
async fn reducer_ingests_plugin_install_failed_fact() {
let mut reducer = AnalyticsReducer::default();
@@ -3804,6 +4037,7 @@ async fn accepted_turn_steer_emits_expected_event() {
connection_id: 7,
request_id: RequestId::Integer(4),
response: Box::new(sample_turn_steer_response("turn-2")),
thread_originator: None,
},
&mut out,
)
@@ -3975,6 +4209,7 @@ async fn turn_start_error_response_discards_pending_start_request() {
connection_id: 7,
request_id: RequestId::Integer(3),
response: Box::new(sample_turn_start_response("turn-2")),
thread_originator: None,
},
&mut out,
)
@@ -4303,6 +4538,7 @@ async fn accepted_steers_increment_turn_steer_count() {
connection_id: 7,
request_id: RequestId::Integer(4),
response: Box::new(sample_turn_steer_response("turn-2")),
thread_originator: None,
},
&mut out,
)
@@ -4350,6 +4586,7 @@ async fn accepted_steers_increment_turn_steer_count() {
connection_id: 7,
request_id: RequestId::Integer(6),
response: Box::new(sample_turn_steer_response("turn-2")),
thread_originator: None,
},
&mut out,
)
+41
View File
@@ -16,6 +16,8 @@ use crate::facts::ExternalAgentConfigImportFailureInput;
use crate::facts::HookRunFact;
use crate::facts::HookRunInput;
use crate::facts::PluginInstallFailedInput;
use crate::facts::PluginInstallRequested;
use crate::facts::PluginInstallRequestedInput;
use crate::facts::PluginState;
use crate::facts::PluginStateChangedInput;
use crate::facts::SkillInvocation;
@@ -310,6 +312,19 @@ impl AnalyticsEventsClient {
)));
}
pub fn track_plugin_install_requested(
&self,
tracking: TrackEventsContext,
request: PluginInstallRequested,
) {
self.record_fact(AnalyticsFact::Custom(
CustomAnalyticsFact::PluginInstallRequested(PluginInstallRequestedInput {
tracking,
request,
}),
));
}
pub fn track_compaction(&self, event: crate::facts::CodexCompactionEvent) {
self.record_fact(AnalyticsFact::Custom(CustomAnalyticsFact::Compaction(
Box::new(event),
@@ -420,6 +435,31 @@ impl AnalyticsEventsClient {
connection_id: u64,
request_id: RequestId,
response: ClientResponsePayload,
) {
self.track_response_inner(
connection_id,
request_id,
response,
/*thread_originator*/ None,
);
}
pub fn track_response_with_thread_originator(
&self,
connection_id: u64,
request_id: RequestId,
response: ClientResponsePayload,
thread_originator: String,
) {
self.track_response_inner(connection_id, request_id, response, Some(thread_originator));
}
fn track_response_inner(
&self,
connection_id: u64,
request_id: RequestId,
response: ClientResponsePayload,
thread_originator: Option<String>,
) {
if !matches!(
response,
@@ -435,6 +475,7 @@ impl AnalyticsEventsClient {
connection_id,
request_id,
response: Box::new(response),
thread_originator,
});
}
+1
View File
@@ -283,6 +283,7 @@ fn sample_thread(thread_id: &str) -> Thread {
parent_thread_id: None,
preview: "first prompt".to_string(),
ephemeral: false,
history_mode: Default::default(),
model_provider: "openai".to_string(),
created_at: 1,
updated_at: 2,
+51
View File
@@ -14,6 +14,7 @@ use crate::facts::CompactionTrigger;
use crate::facts::GoalEventKind;
use crate::facts::HookRunFact;
use crate::facts::InvocationType;
use crate::facts::PluginInstallRequested;
use crate::facts::PluginState;
use crate::facts::SubAgentThreadStartedInput;
use crate::facts::ThreadInitializationMode;
@@ -80,6 +81,7 @@ pub(crate) enum TrackEventRequest {
#[allow(dead_code)]
ReviewEvent(CodexReviewEventRequest),
PluginUsed(CodexPluginUsedEventRequest),
PluginInstallRequested(CodexPluginInstallRequestedEventRequest),
PluginInstalled(CodexPluginEventRequest),
PluginUninstalled(CodexPluginEventRequest),
PluginEnabled(CodexPluginEventRequest),
@@ -954,6 +956,31 @@ pub(crate) struct CodexPluginUsedMetadata {
pub(crate) model_slug: Option<String>,
}
#[derive(Serialize)]
pub(crate) struct CodexPluginInstallRequestedPluginMetadata {
pub(crate) plugin_id: String,
pub(crate) remote_plugin_id: Option<String>,
pub(crate) plugin_name: String,
pub(crate) connector_ids: Vec<String>,
}
#[derive(Serialize)]
pub(crate) struct CodexPluginInstallRequestedMetadata {
pub(crate) suggestion_id: String,
pub(crate) plugins: Vec<CodexPluginInstallRequestedPluginMetadata>,
pub(crate) source: crate::facts::PluginInstallRequestSource,
pub(crate) thread_id: String,
pub(crate) turn_id: String,
pub(crate) model_slug: String,
pub(crate) product_client_id: Option<String>,
}
#[derive(Serialize)]
pub(crate) struct CodexPluginInstallRequestedEventRequest {
pub(crate) event_type: &'static str,
pub(crate) event_params: CodexPluginInstallRequestedMetadata,
}
#[derive(Serialize)]
pub(crate) struct CodexPluginEventRequest {
pub(crate) event_type: &'static str,
@@ -1074,6 +1101,30 @@ fn codex_plugin_metadata_with_product_client_id(
}
}
pub(crate) fn codex_plugin_install_requested_metadata(
tracking: &TrackEventsContext,
request: PluginInstallRequested,
) -> CodexPluginInstallRequestedMetadata {
CodexPluginInstallRequestedMetadata {
suggestion_id: request.suggestion_id,
plugins: request
.plugins
.into_iter()
.map(|plugin| CodexPluginInstallRequestedPluginMetadata {
plugin_id: plugin.plugin_id,
remote_plugin_id: plugin.remote_plugin_id,
plugin_name: plugin.plugin_name,
connector_ids: plugin.connector_ids,
})
.collect(),
source: request.source,
thread_id: tracking.thread_id.clone(),
turn_id: tracking.turn_id.clone(),
model_slug: tracking.model_slug.clone(),
product_client_id: Some(originator().value),
}
}
pub(crate) fn codex_compaction_event_params(
input: CodexCompactionEvent,
session_id: String,
+29
View File
@@ -464,6 +464,7 @@ pub(crate) enum AnalyticsFact {
connection_id: u64,
request_id: RequestId,
response: Box<ClientResponsePayload>,
thread_originator: Option<String>,
},
ErrorResponse {
connection_id: u64,
@@ -508,6 +509,7 @@ pub(crate) enum CustomAnalyticsFact {
AppUsed(AppUsedInput),
HookRun(HookRunInput),
PluginUsed(PluginUsedInput),
PluginInstallRequested(PluginInstallRequestedInput),
PluginStateChanged(PluginStateChangedInput),
PluginInstallFailed(PluginInstallFailedInput),
ExternalAgentConfigImportCompleted(ExternalAgentConfigImportCompletedInput),
@@ -545,6 +547,33 @@ pub(crate) struct PluginUsedInput {
pub plugin: PluginTelemetryMetadata,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum PluginInstallRequestSource {
EndpointRecommendation,
LegacyDiscovery,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PluginInstallRequested {
pub suggestion_id: String,
pub plugins: Vec<PluginInstallRequestedPlugin>,
pub source: PluginInstallRequestSource,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PluginInstallRequestedPlugin {
pub plugin_id: String,
pub remote_plugin_id: Option<String>,
pub plugin_name: String,
pub connector_ids: Vec<String>,
}
pub(crate) struct PluginInstallRequestedInput {
pub tracking: TrackEventsContext,
pub request: PluginInstallRequested,
}
pub(crate) struct PluginStateChangedInput {
pub plugin: PluginTelemetryMetadata,
pub state: PluginState,
+3
View File
@@ -42,6 +42,9 @@ pub use facts::GoalEventKind;
pub use facts::HookRunFact;
pub use facts::InputError;
pub use facts::InvocationType;
pub use facts::PluginInstallRequestSource;
pub use facts::PluginInstallRequested;
pub use facts::PluginInstallRequestedPlugin;
pub use facts::SkillInvocation;
pub use facts::SubAgentThreadStartedInput;
pub use facts::ThreadInitializationMode;
+96 -38
View File
@@ -28,6 +28,7 @@ use crate::events::CodexOnboardingExternalAgentImportFailureMetadata;
use crate::events::CodexPluginEventRequest;
use crate::events::CodexPluginInstallFailedEventRequest;
use crate::events::CodexPluginInstallFailedMetadata;
use crate::events::CodexPluginInstallRequestedEventRequest;
use crate::events::CodexPluginUsedEventRequest;
use crate::events::CodexReviewEventParams;
use crate::events::CodexReviewEventRequest;
@@ -60,6 +61,7 @@ use crate::events::codex_app_metadata;
use crate::events::codex_compaction_event_params;
use crate::events::codex_goal_event_params;
use crate::events::codex_hook_run_metadata;
use crate::events::codex_plugin_install_requested_metadata;
use crate::events::codex_plugin_metadata;
use crate::events::codex_plugin_used_metadata;
use crate::events::plugin_state_event_type;
@@ -76,6 +78,7 @@ use crate::facts::ExternalAgentConfigImportCompletedInput;
use crate::facts::ExternalAgentConfigImportFailureInput;
use crate::facts::HookRunInput;
use crate::facts::PluginInstallFailedInput;
use crate::facts::PluginInstallRequestedInput;
use crate::facts::PluginState;
use crate::facts::PluginStateChangedInput;
use crate::facts::PluginUsedInput;
@@ -162,6 +165,20 @@ struct ConnectionState {
struct ThreadAnalyticsState {
connection_id: Option<u64>,
metadata: Option<ThreadMetadataState>,
originator: Option<String>,
}
impl ThreadAnalyticsState {
fn app_server_client(
&self,
connection_state: &ConnectionState,
) -> CodexAppServerClientMetadata {
let mut app_server_client = connection_state.app_server_client.clone();
if let Some(originator) = self.originator.as_ref() {
app_server_client.product_client_id.clone_from(originator);
}
app_server_client
}
}
#[derive(Clone, Copy)]
@@ -431,9 +448,11 @@ impl AnalyticsReducer {
connection_id,
request_id,
response,
thread_originator,
} => {
if let Some(response) = response.into_client_response(request_id) {
self.ingest_response(connection_id, response, out).await;
self.ingest_response(connection_id, response, thread_originator, out)
.await;
}
}
AnalyticsFact::ErrorResponse {
@@ -517,6 +536,9 @@ impl AnalyticsReducer {
CustomAnalyticsFact::PluginUsed(input) => {
self.ingest_plugin_used(input, out);
}
CustomAnalyticsFact::PluginInstallRequested(input) => {
self.ingest_plugin_install_requested(input, out);
}
CustomAnalyticsFact::PluginStateChanged(input) => {
self.ingest_plugin_state_changed(input, out);
}
@@ -569,6 +591,9 @@ impl AnalyticsReducer {
.and_then(|parent_thread_id| self.threads.get(parent_thread_id))
.and_then(|thread| thread.connection_id);
let thread_state = self.threads.entry(input.thread_id.clone()).or_default();
thread_state
.originator
.get_or_insert_with(|| input.product_client_id.clone());
thread_state
.metadata
.get_or_insert_with(|| ThreadMetadataState {
@@ -591,7 +616,7 @@ impl AnalyticsReducer {
input: GuardianReviewEventParams,
out: &mut Vec<TrackEventRequest>,
) {
let Some((connection_state, thread_metadata)) =
let Some((connection_state, thread_state, thread_metadata)) =
self.thread_context_or_warn(AnalyticsDropSite::guardian(&input))
else {
return;
@@ -601,7 +626,7 @@ impl AnalyticsReducer {
event_type: "codex_guardian_review",
event_params: GuardianReviewEventPayload {
session_id: thread_metadata.session_id.clone(),
app_server_client: connection_state.app_server_client.clone(),
app_server_client: thread_state.app_server_client(connection_state),
runtime: connection_state.runtime.clone(),
guardian_review: input,
},
@@ -775,6 +800,20 @@ impl AnalyticsReducer {
}));
}
fn ingest_plugin_install_requested(
&mut self,
input: PluginInstallRequestedInput,
out: &mut Vec<TrackEventRequest>,
) {
let PluginInstallRequestedInput { tracking, request } = input;
out.push(TrackEventRequest::PluginInstallRequested(
CodexPluginInstallRequestedEventRequest {
event_type: "codex_plugin_install_requested",
event_params: codex_plugin_install_requested_metadata(&tracking, request),
},
));
}
fn ingest_plugin_state_changed(
&mut self,
input: PluginStateChangedInput,
@@ -854,6 +893,7 @@ impl AnalyticsReducer {
&mut self,
connection_id: u64,
response: ClientResponse,
thread_originator: Option<String>,
out: &mut Vec<TrackEventRequest>,
) {
match response {
@@ -863,6 +903,7 @@ impl AnalyticsReducer {
response.thread,
response.model,
ThreadInitializationMode::New,
thread_originator,
out,
);
}
@@ -872,6 +913,7 @@ impl AnalyticsReducer {
response.thread,
response.model,
ThreadInitializationMode::Resumed,
thread_originator,
out,
);
}
@@ -881,6 +923,7 @@ impl AnalyticsReducer {
response.thread,
response.model,
ThreadInitializationMode::Forked,
thread_originator,
out,
);
}
@@ -1228,7 +1271,7 @@ impl AnalyticsReducer {
else {
return;
};
let Some((connection_state, thread_metadata)) = self
let Some((connection_state, thread_state, thread_metadata)) = self
.thread_context_or_warn(AnalyticsDropSite::tool_item(&notification, item_id))
else {
return;
@@ -1240,6 +1283,7 @@ impl AnalyticsReducer {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary: self.item_review_summaries.get(&key),
}) {
@@ -1296,6 +1340,7 @@ impl AnalyticsReducer {
thread: codex_app_server_protocol::Thread,
model: String,
initialization_mode: ThreadInitializationMode,
thread_originator: Option<String>,
out: &mut Vec<TrackEventRequest>,
) {
let session_source: SessionSource = thread.source.into();
@@ -1313,20 +1358,20 @@ impl AnalyticsReducer {
parent_thread_id,
initialization_mode,
);
self.threads.insert(
thread_id.clone(),
ThreadAnalyticsState {
connection_id: Some(connection_id),
metadata: Some(thread_metadata.clone()),
},
);
let thread_state = self.threads.entry(thread_id.clone()).or_default();
if let Some(originator) = thread_originator {
thread_state.originator = Some(originator);
}
thread_state.connection_id = Some(connection_id);
thread_state.metadata = Some(thread_metadata.clone());
let app_server_client = thread_state.app_server_client(connection_state);
out.push(TrackEventRequest::ThreadInitialized(
ThreadInitializedEvent {
event_type: "codex_thread_initialized",
event_params: ThreadInitializedEventParams {
thread_id,
session_id,
app_server_client: connection_state.app_server_client.clone(),
app_server_client,
runtime: connection_state.runtime.clone(),
model,
ephemeral: thread.ephemeral,
@@ -1342,7 +1387,7 @@ impl AnalyticsReducer {
}
fn ingest_compaction(&mut self, input: CodexCompactionEvent, out: &mut Vec<TrackEventRequest>) {
let Some((connection_state, thread_metadata)) =
let Some((connection_state, thread_state, thread_metadata)) =
self.thread_context_or_warn(AnalyticsDropSite::compaction(&input))
else {
return;
@@ -1353,7 +1398,7 @@ impl AnalyticsReducer {
event_params: codex_compaction_event_params(
input,
thread_metadata.session_id.clone(),
connection_state.app_server_client.clone(),
thread_state.app_server_client(connection_state),
connection_state.runtime.clone(),
thread_metadata.thread_source.clone(),
thread_metadata.subagent_source.clone(),
@@ -1364,7 +1409,7 @@ impl AnalyticsReducer {
}
fn ingest_goal(&mut self, input: CodexGoalEvent, out: &mut Vec<TrackEventRequest>) {
let Some((connection_state, thread_metadata)) =
let Some((connection_state, thread_state, thread_metadata)) =
self.thread_context_or_warn(AnalyticsDropSite::goal(&input))
else {
return;
@@ -1374,7 +1419,7 @@ impl AnalyticsReducer {
event_params: codex_goal_event_params(
input,
thread_metadata.session_id.clone(),
connection_state.app_server_client.clone(),
thread_state.app_server_client(connection_state),
connection_state.runtime.clone(),
thread_metadata.thread_source.clone(),
thread_metadata.subagent_source.clone(),
@@ -1463,11 +1508,11 @@ impl AnalyticsReducer {
return;
};
let drop_site = AnalyticsDropSite::turn_steer(&pending_request.thread_id);
let Some(thread_metadata) = self
.threads
.get(drop_site.thread_id)
.and_then(|thread| thread.metadata.as_ref())
else {
let Some(thread_state) = self.threads.get(drop_site.thread_id) else {
warn_missing_analytics_context(&drop_site, MissingAnalyticsContext::ThreadMetadata);
return;
};
let Some(thread_metadata) = thread_state.metadata.as_ref() else {
warn_missing_analytics_context(&drop_site, MissingAnalyticsContext::ThreadMetadata);
return;
};
@@ -1478,7 +1523,7 @@ impl AnalyticsReducer {
session_id: thread_metadata.session_id.clone(),
expected_turn_id: Some(pending_request.expected_turn_id),
accepted_turn_id,
app_server_client: connection_state.app_server_client.clone(),
app_server_client: thread_state.app_server_client(connection_state),
runtime: connection_state.runtime.clone(),
thread_source: thread_metadata.thread_source.clone(),
subagent_source: thread_metadata.subagent_source.clone(),
@@ -1509,7 +1554,7 @@ impl AnalyticsReducer {
&pending_review,
);
}
let Some((connection_state, thread_metadata)) =
let Some((connection_state, thread_state, thread_metadata)) =
self.thread_context_or_warn(AnalyticsDropSite::review(&pending_review))
else {
return;
@@ -1521,7 +1566,7 @@ impl AnalyticsReducer {
turn_id: pending_review.turn_id,
item_id: pending_review.item_id,
review_id: pending_review.review_id,
app_server_client: connection_state.app_server_client.clone(),
app_server_client: thread_state.app_server_client(connection_state),
runtime: connection_state.runtime.clone(),
thread_source: thread_metadata.thread_source.clone(),
subagent_source: thread_metadata.subagent_source.clone(),
@@ -1590,18 +1635,18 @@ impl AnalyticsReducer {
);
return;
};
let Some(thread_metadata) = self
.threads
.get(drop_site.thread_id)
.and_then(|thread| thread.metadata.as_ref())
else {
let Some(thread_state) = self.threads.get(drop_site.thread_id) else {
warn_missing_analytics_context(&drop_site, MissingAnalyticsContext::ThreadMetadata);
return;
};
let Some(thread_metadata) = thread_state.metadata.as_ref() else {
warn_missing_analytics_context(&drop_site, MissingAnalyticsContext::ThreadMetadata);
return;
};
let turn_event = TrackEventRequest::TurnEvent(Box::new(CodexTurnEventRequest {
event_type: "codex_turn_event",
event_params: codex_turn_event_params(
connection_state.app_server_client.clone(),
thread_state.app_server_client(connection_state),
connection_state.runtime.clone(),
turn_id.to_string(),
turn_state,
@@ -1643,17 +1688,18 @@ impl AnalyticsReducer {
fn thread_context_or_warn(
&self,
drop_site: AnalyticsDropSite<'_>,
) -> Option<(&ConnectionState, &ThreadMetadataState)> {
) -> Option<(
&ConnectionState,
&ThreadAnalyticsState,
&ThreadMetadataState,
)> {
let connection_state = self.thread_connection_or_warn(drop_site)?;
let Some(thread_metadata) = self
.threads
.get(drop_site.thread_id)
.and_then(|thread| thread.metadata.as_ref())
else {
let thread_state = self.threads.get(drop_site.thread_id)?;
let Some(thread_metadata) = thread_state.metadata.as_ref() else {
warn_missing_analytics_context(&drop_site, MissingAnalyticsContext::ThreadMetadata);
return None;
};
Some((connection_state, thread_metadata))
Some((connection_state, thread_state, thread_metadata))
}
}
@@ -1723,6 +1769,7 @@ struct ToolItemEventInput<'a> {
started_at_ms: u64,
completed_at_ms: u64,
connection_state: &'a ConnectionState,
thread_state: &'a ThreadAnalyticsState,
thread_metadata: &'a ThreadMetadataState,
review_summary: Option<&'a ItemReviewSummary>,
}
@@ -1735,6 +1782,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
} = input;
@@ -1764,6 +1812,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -1805,6 +1854,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -1846,6 +1896,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -1890,6 +1941,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -1934,6 +1986,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -1989,6 +2042,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -2025,6 +2079,7 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
started_at_ms,
completed_at_ms,
connection_state,
thread_state,
thread_metadata,
review_summary,
},
@@ -2080,6 +2135,7 @@ struct ToolItemContext<'a> {
started_at_ms: u64,
completed_at_ms: u64,
connection_state: &'a ConnectionState,
thread_state: &'a ThreadAnalyticsState,
thread_metadata: &'a ThreadMetadataState,
review_summary: Option<&'a ItemReviewSummary>,
}
@@ -2098,7 +2154,9 @@ fn tool_item_base(
thread_id: thread_id.to_string(),
turn_id: turn_id.to_string(),
item_id,
app_server_client: context.connection_state.app_server_client.clone(),
app_server_client: context
.thread_state
.app_server_client(context.connection_state),
runtime: context.connection_state.runtime.clone(),
thread_source: thread_metadata.thread_source.clone(),
subagent_source: thread_metadata.subagent_source.clone(),
-3
View File
@@ -78,9 +78,6 @@ pub use crate::remote::RemoteAppServerEndpoint;
/// module exists so clients can remove a direct `codex-core` dependency
/// while legacy startup/config paths are migrated to RPCs.
pub mod legacy_core {
pub use codex_core::check_execpolicy_for_warnings;
pub use codex_core::format_exec_policy_error_with_source;
pub mod config {
pub use codex_core::config::*;
+8
View File
@@ -15,6 +15,7 @@ use anyhow::anyhow;
pub use backend::BackendKind;
use backend::BackendPaths;
use codex_app_server_protocol::RemoteControlConnectionStatus;
use codex_app_server_protocol::RemoteControlPairingStartResponse;
use codex_app_server_transport::app_server_control_socket_path;
use codex_utils_home_dir::find_codex_home;
use managed_install::managed_codex_bin;
@@ -225,6 +226,13 @@ pub async fn enable_remote_control_on_socket(
.await
}
/// Starts a manual pairing session through an already-running daemon app-server.
pub async fn start_remote_control_pairing() -> Result<RemoteControlPairingStartResponse> {
ensure_supported_platform()?;
let daemon = Daemon::from_environment()?;
remote_control_client::start_pairing(&daemon.socket_path).await
}
pub async fn set_remote_control(mode: RemoteControlMode) -> Result<RemoteControlOutput> {
ensure_supported_platform()?;
Daemon::from_environment()?.set_remote_control(mode).await
@@ -12,6 +12,8 @@ use codex_app_server_protocol::RemoteControlDisableParams;
use codex_app_server_protocol::RemoteControlDisableResponse;
use codex_app_server_protocol::RemoteControlEnableParams;
use codex_app_server_protocol::RemoteControlEnableResponse;
use codex_app_server_protocol::RemoteControlPairingStartParams;
use codex_app_server_protocol::RemoteControlPairingStartResponse;
use codex_app_server_protocol::RemoteControlStatusChangedNotification;
use codex_app_server_protocol::RequestId;
use serde::de::DeserializeOwned;
@@ -53,6 +55,35 @@ pub(crate) async fn disable_remote_control(socket_path: &Path) -> Result<RemoteC
Ok(RemoteControlReadyStatus::from(response))
}
pub(crate) async fn start_pairing(socket_path: &Path) -> Result<RemoteControlPairingStartResponse> {
let mut websocket = client::connect(socket_path).await?;
initialize_client(&mut websocket).await?;
let params = serde_json::to_value(RemoteControlPairingStartParams { manual_code: true })?;
send_remote_control_request(
&mut websocket,
REMOTE_CONTROL_REQUEST_ID.clone(),
"remoteControl/pairing/start",
Some(params),
)
.await?;
let response = match read_remote_control_response(
&mut websocket,
&REMOTE_CONTROL_REQUEST_ID,
"remoteControl/pairing/start",
)
.await?
{
RemoteControlRpcResponse::Success(response) => response,
RemoteControlRpcResponse::InvalidParams => {
return Err(anyhow!(
"remoteControl/pairing/start rejected manual pairing parameters"
));
}
};
websocket.close(None).await.ok();
Ok(response)
}
pub(crate) async fn enable_remote_control_with_connect_retry(
socket_path: &Path,
connect_timeout: Duration,
@@ -538,6 +569,53 @@ mod tests {
Ok(())
}
#[tokio::test]
async fn start_pairing_requests_manual_code() -> Result<()> {
let dir = TempDir::new()?;
let socket_path = dir.path().join("app-server.sock");
let listener = UnixListener::bind(&socket_path).await?;
let server_task = tokio::spawn(async move {
let mut websocket = accept_initialized_client(listener).await?;
let pairing = client::read_message(&mut websocket).await?;
let JSONRPCMessage::Request(pairing) = pairing else {
panic!("expected remoteControl/pairing/start request");
};
assert_eq!(pairing.id, REMOTE_CONTROL_REQUEST_ID);
assert_eq!(pairing.method, "remoteControl/pairing/start");
assert_eq!(
pairing.params,
Some(serde_json::json!({ "manualCode": true }))
);
client::send_message(
&mut websocket,
&JSONRPCMessage::Response(JSONRPCResponse {
id: REMOTE_CONTROL_REQUEST_ID,
result: serde_json::to_value(RemoteControlPairingStartResponse {
pairing_code: "pairing-code".to_string(),
manual_pairing_code: Some("ABCD-EFGH".to_string()),
environment_id: "env_test".to_string(),
expires_at: 1_700_000_000,
})?,
}),
)
.await?;
Ok::<_, anyhow::Error>(())
});
let response = start_pairing(&socket_path).await?;
server_task.await??;
assert_eq!(
response,
RemoteControlPairingStartResponse {
pairing_code: "pairing-code".to_string(),
manual_pairing_code: Some("ABCD-EFGH".to_string()),
environment_id: "env_test".to_string(),
expires_at: 1_700_000_000,
}
);
Ok(())
}
struct EnableScenario {
initial_notification: Option<RemoteControlStatusChangedNotification>,
enable_response: RemoteControlStatusChangedNotification,
+57 -7
View File
@@ -556,6 +556,13 @@
},
"ConsumeAccountRateLimitResetCreditParams": {
"properties": {
"creditId": {
"description": "Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.",
"type": [
"string",
"null"
]
},
"idempotencyKey": {
"description": "Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.",
"type": "string"
@@ -1619,6 +1626,12 @@
"null"
]
},
"threadId": {
"type": [
"string",
"null"
]
},
"timeoutSecs": {
"format": "int64",
"type": [
@@ -1780,13 +1793,29 @@
"type": "object"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -2677,6 +2706,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"status": {
"type": [
"string",
@@ -3625,6 +3660,13 @@
"ephemeral": {
"type": "boolean"
},
"lastTurnId": {
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
"type": [
"string",
"null"
]
},
"model": {
"description": "Configuration overrides for the forked thread, if any.",
"type": [
@@ -3741,6 +3783,13 @@
],
"type": "string"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadInjectItemsParams": {
"properties": {
"items": {
@@ -4168,6 +4217,7 @@
"type": "object"
},
"ThreadRollbackParams": {
"description": "DEPRECATED: `thread/rollback` will be removed soon.",
"properties": {
"numTurns": {
"description": "The number of turns to drop from the end of the thread. Must be >= 1.\n\nThis only modifies the thread's history and does not revert local file changes that have been made by the agent. Clients are responsible for reverting these changes.",
@@ -241,6 +241,24 @@
"null"
]
},
"iconAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"iconDarkAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"id": {
"type": "string"
},
@@ -2352,6 +2370,12 @@
},
"success": {
"type": "boolean"
},
"threadId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -2360,6 +2384,12 @@
],
"type": "object"
},
"McpServerStartupFailureReason": {
"enum": [
"reauthenticationRequired"
],
"type": "string"
},
"McpServerStartupState": {
"enum": [
"starting",
@@ -2377,6 +2407,16 @@
"null"
]
},
"failureReason": {
"anyOf": [
{
"$ref": "#/definitions/McpServerStartupFailureReason"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
@@ -2398,6 +2438,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -2412,6 +2464,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -2655,13 +2713,29 @@
"type": "object"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -3859,6 +3933,13 @@
],
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -6406,6 +6406,24 @@
"null"
]
},
"iconAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"iconDarkAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"id": {
"type": "string"
},
@@ -8396,6 +8414,16 @@
"object",
"null"
]
},
"models": {
"anyOf": [
{
"$ref": "#/definitions/v2/ModelsRequirements"
},
{
"type": "null"
}
]
}
},
"type": "object"
@@ -8660,6 +8688,13 @@
"ConsumeAccountRateLimitResetCreditParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"creditId": {
"description": "Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.",
"type": [
"string",
"null"
]
},
"idempotencyKey": {
"description": "Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.",
"type": "string"
@@ -12008,6 +12043,12 @@
},
"success": {
"type": "boolean"
},
"threadId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -12032,6 +12073,12 @@
"null"
]
},
"threadId": {
"type": [
"string",
"null"
]
},
"timeoutSecs": {
"format": "int64",
"type": [
@@ -12064,6 +12111,12 @@
"title": "McpServerRefreshResponse",
"type": "object"
},
"McpServerStartupFailureReason": {
"enum": [
"reauthenticationRequired"
],
"type": "string"
},
"McpServerStartupState": {
"enum": [
"starting",
@@ -12135,6 +12188,16 @@
"null"
]
},
"failureReason": {
"anyOf": [
{
"$ref": "#/definitions/v2/McpServerStartupFailureReason"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
@@ -12202,6 +12265,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -12216,6 +12291,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -12770,14 +12851,45 @@
"title": "ModelVerificationNotification",
"type": "object"
},
"ModelsRequirements": {
"properties": {
"newThread": {
"anyOf": [
{
"$ref": "#/definitions/v2/NewThreadModelDefaults"
},
{
"type": "null"
}
]
}
},
"type": "object"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -12917,6 +13029,33 @@
],
"type": "string"
},
"NewThreadModelDefaults": {
"properties": {
"model": {
"type": [
"string",
"null"
]
},
"modelReasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/v2/ReasoningEffort"
},
{
"type": "null"
}
]
},
"serviceTier": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"NonSteerableTurnKind": {
"enum": [
"review",
@@ -14091,6 +14230,40 @@
"title": "GitPluginSource",
"type": "object"
},
{
"properties": {
"package": {
"type": "string"
},
"registry": {
"description": "Optional HTTPS registry URL. Authentication stays in the user's npm config.",
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"npm"
],
"title": "NpmPluginSourceType",
"type": "string"
},
"version": {
"description": "Optional npm version or version range.",
"type": [
"string",
"null"
]
}
},
"required": [
"package",
"type"
],
"title": "NpmPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
@@ -14184,6 +14357,14 @@
},
"source": {
"$ref": "#/definitions/v2/PluginSource"
},
"version": {
"default": null,
"description": "Version advertised by the remote marketplace backend when available.",
"type": [
"string",
"null"
]
}
},
"required": [
@@ -14359,11 +14540,78 @@
],
"type": "string"
},
"RateLimitResetCredit": {
"properties": {
"description": {
"description": "Backend-provided display description for this credit, or `null` when unavailable.",
"type": [
"string",
"null"
]
},
"expiresAt": {
"description": "Unix timestamp in seconds when the credit expires, or `null` if it does not expire.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"grantedAt": {
"description": "Unix timestamp in seconds when the credit was granted.",
"format": "int64",
"type": "integer"
},
"id": {
"description": "Opaque backend identifier for this reset credit.",
"type": "string"
},
"resetType": {
"$ref": "#/definitions/v2/RateLimitResetType"
},
"status": {
"$ref": "#/definitions/v2/RateLimitResetCreditStatus"
},
"title": {
"description": "Backend-provided display title for this credit, or `null` when unavailable.",
"type": [
"string",
"null"
]
}
},
"required": [
"grantedAt",
"id",
"resetType",
"status"
],
"type": "object"
},
"RateLimitResetCreditStatus": {
"enum": [
"available",
"redeeming",
"redeemed",
"unknown"
],
"type": "string"
},
"RateLimitResetCreditsSummary": {
"properties": {
"availableCount": {
"format": "int64",
"type": "integer"
},
"credits": {
"description": "Detail rows for available reset credits, when the backend provides them.\n\n`null` means only `availableCount` is known, while an empty array means details were fetched and no available credits were returned. The backend may cap this list, so its length can be less than `availableCount`.",
"items": {
"$ref": "#/definitions/v2/RateLimitResetCredit"
},
"type": [
"array",
"null"
]
}
},
"required": [
@@ -14371,6 +14619,13 @@
],
"type": "object"
},
"RateLimitResetType": {
"enum": [
"codexRateLimits",
"unknown"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -15360,6 +15615,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"status": {
"type": [
"string",
@@ -17129,6 +17390,13 @@
"ephemeral": {
"type": "boolean"
},
"lastTurnId": {
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
"type": [
"string",
"null"
]
},
"model": {
"description": "Configuration overrides for the forked thread, if any.",
"type": [
@@ -17448,6 +17716,13 @@
"title": "ThreadGoalUpdatedNotification",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -18967,6 +19242,7 @@
},
"ThreadRollbackParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "DEPRECATED: `thread/rollback` will be removed soon.",
"properties": {
"numTurns": {
"description": "The number of turns to drop from the end of the thread. Must be >= 1.\n\nThis only modifies the thread's history and does not revert local file changes that have been made by the agent. Clients are responsible for reverting these changes.",
@@ -532,6 +532,24 @@
"null"
]
},
"iconAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"iconDarkAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"id": {
"type": "string"
},
@@ -4636,6 +4654,16 @@
"object",
"null"
]
},
"models": {
"anyOf": [
{
"$ref": "#/definitions/ModelsRequirements"
},
{
"type": "null"
}
]
}
},
"type": "object"
@@ -4900,6 +4928,13 @@
"ConsumeAccountRateLimitResetCreditParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"creditId": {
"description": "Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.",
"type": [
"string",
"null"
]
},
"idempotencyKey": {
"description": "Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.",
"type": "string"
@@ -8412,6 +8447,12 @@
},
"success": {
"type": "boolean"
},
"threadId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -8436,6 +8477,12 @@
"null"
]
},
"threadId": {
"type": [
"string",
"null"
]
},
"timeoutSecs": {
"format": "int64",
"type": [
@@ -8468,6 +8515,12 @@
"title": "McpServerRefreshResponse",
"type": "object"
},
"McpServerStartupFailureReason": {
"enum": [
"reauthenticationRequired"
],
"type": "string"
},
"McpServerStartupState": {
"enum": [
"starting",
@@ -8539,6 +8592,16 @@
"null"
]
},
"failureReason": {
"anyOf": [
{
"$ref": "#/definitions/McpServerStartupFailureReason"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
@@ -8606,6 +8669,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -8620,6 +8695,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -9174,14 +9255,45 @@
"title": "ModelVerificationNotification",
"type": "object"
},
"ModelsRequirements": {
"properties": {
"newThread": {
"anyOf": [
{
"$ref": "#/definitions/NewThreadModelDefaults"
},
{
"type": "null"
}
]
}
},
"type": "object"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -9321,6 +9433,33 @@
],
"type": "string"
},
"NewThreadModelDefaults": {
"properties": {
"model": {
"type": [
"string",
"null"
]
},
"modelReasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
]
},
"serviceTier": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"NonSteerableTurnKind": {
"enum": [
"review",
@@ -10495,6 +10634,40 @@
"title": "GitPluginSource",
"type": "object"
},
{
"properties": {
"package": {
"type": "string"
},
"registry": {
"description": "Optional HTTPS registry URL. Authentication stays in the user's npm config.",
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"npm"
],
"title": "NpmPluginSourceType",
"type": "string"
},
"version": {
"description": "Optional npm version or version range.",
"type": [
"string",
"null"
]
}
},
"required": [
"package",
"type"
],
"title": "NpmPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
@@ -10588,6 +10761,14 @@
},
"source": {
"$ref": "#/definitions/PluginSource"
},
"version": {
"default": null,
"description": "Version advertised by the remote marketplace backend when available.",
"type": [
"string",
"null"
]
}
},
"required": [
@@ -10763,11 +10944,78 @@
],
"type": "string"
},
"RateLimitResetCredit": {
"properties": {
"description": {
"description": "Backend-provided display description for this credit, or `null` when unavailable.",
"type": [
"string",
"null"
]
},
"expiresAt": {
"description": "Unix timestamp in seconds when the credit expires, or `null` if it does not expire.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"grantedAt": {
"description": "Unix timestamp in seconds when the credit was granted.",
"format": "int64",
"type": "integer"
},
"id": {
"description": "Opaque backend identifier for this reset credit.",
"type": "string"
},
"resetType": {
"$ref": "#/definitions/RateLimitResetType"
},
"status": {
"$ref": "#/definitions/RateLimitResetCreditStatus"
},
"title": {
"description": "Backend-provided display title for this credit, or `null` when unavailable.",
"type": [
"string",
"null"
]
}
},
"required": [
"grantedAt",
"id",
"resetType",
"status"
],
"type": "object"
},
"RateLimitResetCreditStatus": {
"enum": [
"available",
"redeeming",
"redeemed",
"unknown"
],
"type": "string"
},
"RateLimitResetCreditsSummary": {
"properties": {
"availableCount": {
"format": "int64",
"type": "integer"
},
"credits": {
"description": "Detail rows for available reset credits, when the backend provides them.\n\n`null` means only `availableCount` is known, while an empty array means details were fetched and no available credits were returned. The backend may cap this list, so its length can be less than `availableCount`.",
"items": {
"$ref": "#/definitions/RateLimitResetCredit"
},
"type": [
"array",
"null"
]
}
},
"required": [
@@ -10775,6 +11023,13 @@
],
"type": "object"
},
"RateLimitResetType": {
"enum": [
"codexRateLimits",
"unknown"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -11764,6 +12019,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"status": {
"type": [
"string",
@@ -14908,6 +15169,13 @@
"ephemeral": {
"type": "boolean"
},
"lastTurnId": {
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
"type": [
"string",
"null"
]
},
"model": {
"description": "Configuration overrides for the forked thread, if any.",
"type": [
@@ -15227,6 +15495,13 @@
"title": "ThreadGoalUpdatedNotification",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -16746,6 +17021,7 @@
},
"ThreadRollbackParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "DEPRECATED: `thread/rollback` will be removed soon.",
"properties": {
"numTurns": {
"description": "The number of turns to drop from the end of the thread. Must be >= 1.\n\nThis only modifies the thread's history and does not revert local file changes that have been made by the agent. Clients are responsible for reverting these changes.",
@@ -78,6 +78,24 @@
"null"
]
},
"iconAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"iconDarkAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"id": {
"type": "string"
},
@@ -78,6 +78,24 @@
"null"
]
},
"iconAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"iconDarkAssets": {
"additionalProperties": {
"type": "string"
},
"type": [
"object",
"null"
]
},
"id": {
"type": "string"
},
@@ -169,6 +169,16 @@
"object",
"null"
]
},
"models": {
"anyOf": [
{
"$ref": "#/definitions/ModelsRequirements"
},
{
"type": "null"
}
]
}
},
"type": "object"
@@ -362,6 +372,21 @@
],
"type": "object"
},
"ModelsRequirements": {
"properties": {
"newThread": {
"anyOf": [
{
"$ref": "#/definitions/NewThreadModelDefaults"
},
{
"type": "null"
}
]
}
},
"type": "object"
},
"NetworkDomainPermission": {
"enum": [
"allow",
@@ -484,6 +509,38 @@
],
"type": "string"
},
"NewThreadModelDefaults": {
"properties": {
"model": {
"type": [
"string",
"null"
]
},
"modelReasoningEffort": {
"anyOf": [
{
"$ref": "#/definitions/ReasoningEffort"
},
{
"type": "null"
}
]
},
"serviceTier": {
"type": [
"string",
"null"
]
}
},
"type": "object"
},
"ReasoningEffort": {
"description": "A non-empty reasoning effort value advertised by the model.",
"minLength": 1,
"type": "string"
},
"ResidencyRequirement": {
"enum": [
"us"
@@ -1,6 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"creditId": {
"description": "Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.",
"type": [
"string",
"null"
]
},
"idempotencyKey": {
"description": "Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.",
"type": "string"
@@ -49,11 +49,78 @@
],
"type": "string"
},
"RateLimitResetCredit": {
"properties": {
"description": {
"description": "Backend-provided display description for this credit, or `null` when unavailable.",
"type": [
"string",
"null"
]
},
"expiresAt": {
"description": "Unix timestamp in seconds when the credit expires, or `null` if it does not expire.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"grantedAt": {
"description": "Unix timestamp in seconds when the credit was granted.",
"format": "int64",
"type": "integer"
},
"id": {
"description": "Opaque backend identifier for this reset credit.",
"type": "string"
},
"resetType": {
"$ref": "#/definitions/RateLimitResetType"
},
"status": {
"$ref": "#/definitions/RateLimitResetCreditStatus"
},
"title": {
"description": "Backend-provided display title for this credit, or `null` when unavailable.",
"type": [
"string",
"null"
]
}
},
"required": [
"grantedAt",
"id",
"resetType",
"status"
],
"type": "object"
},
"RateLimitResetCreditStatus": {
"enum": [
"available",
"redeeming",
"redeemed",
"unknown"
],
"type": "string"
},
"RateLimitResetCreditsSummary": {
"properties": {
"availableCount": {
"format": "int64",
"type": "integer"
},
"credits": {
"description": "Detail rows for available reset credits, when the backend provides them.\n\n`null` means only `availableCount` is known, while an empty array means details were fetched and no available credits were returned. The backend may cap this list, so its length can be less than `availableCount`.",
"items": {
"$ref": "#/definitions/RateLimitResetCredit"
},
"type": [
"array",
"null"
]
}
},
"required": [
@@ -61,6 +128,13 @@
],
"type": "object"
},
"RateLimitResetType": {
"enum": [
"codexRateLimits",
"unknown"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -299,6 +299,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -313,6 +325,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -299,6 +299,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -313,6 +325,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -12,6 +12,12 @@
},
"success": {
"type": "boolean"
},
"threadId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -13,6 +13,12 @@
"null"
]
},
"threadId": {
"type": [
"string",
"null"
]
},
"timeoutSecs": {
"format": "int64",
"type": [
@@ -1,6 +1,12 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"McpServerStartupFailureReason": {
"enum": [
"reauthenticationRequired"
],
"type": "string"
},
"McpServerStartupState": {
"enum": [
"starting",
@@ -18,6 +24,16 @@
"null"
]
},
"failureReason": {
"anyOf": [
{
"$ref": "#/definitions/McpServerStartupFailureReason"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
@@ -413,6 +413,40 @@
"title": "GitPluginSource",
"type": "object"
},
{
"properties": {
"package": {
"type": "string"
},
"registry": {
"description": "Optional HTTPS registry URL. Authentication stays in the user's npm config.",
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"npm"
],
"title": "NpmPluginSourceType",
"type": "string"
},
"version": {
"description": "Optional npm version or version range.",
"type": [
"string",
"null"
]
}
},
"required": [
"package",
"type"
],
"title": "NpmPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
@@ -506,6 +540,14 @@
},
"source": {
"$ref": "#/definitions/PluginSource"
},
"version": {
"default": null,
"description": "Version advertised by the remote marketplace backend when available.",
"type": [
"string",
"null"
]
}
},
"required": [
@@ -413,6 +413,40 @@
"title": "GitPluginSource",
"type": "object"
},
{
"properties": {
"package": {
"type": "string"
},
"registry": {
"description": "Optional HTTPS registry URL. Authentication stays in the user's npm config.",
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"npm"
],
"title": "NpmPluginSourceType",
"type": "string"
},
"version": {
"description": "Optional npm version or version range.",
"type": [
"string",
"null"
]
}
},
"required": [
"package",
"type"
],
"title": "NpmPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
@@ -506,6 +540,14 @@
},
"source": {
"$ref": "#/definitions/PluginSource"
},
"version": {
"default": null,
"description": "Version advertised by the remote marketplace backend when available.",
"type": [
"string",
"null"
]
}
},
"required": [
@@ -553,6 +553,40 @@
"title": "GitPluginSource",
"type": "object"
},
{
"properties": {
"package": {
"type": "string"
},
"registry": {
"description": "Optional HTTPS registry URL. Authentication stays in the user's npm config.",
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"npm"
],
"title": "NpmPluginSourceType",
"type": "string"
},
"version": {
"description": "Optional npm version or version range.",
"type": [
"string",
"null"
]
}
},
"required": [
"package",
"type"
],
"title": "NpmPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
@@ -646,6 +680,14 @@
},
"source": {
"$ref": "#/definitions/PluginSource"
},
"version": {
"default": null,
"description": "Version advertised by the remote marketplace backend when available.",
"type": [
"string",
"null"
]
}
},
"required": [
@@ -369,6 +369,40 @@
"title": "GitPluginSource",
"type": "object"
},
{
"properties": {
"package": {
"type": "string"
},
"registry": {
"description": "Optional HTTPS registry URL. Authentication stays in the user's npm config.",
"type": [
"string",
"null"
]
},
"type": {
"enum": [
"npm"
],
"title": "NpmPluginSourceType",
"type": "string"
},
"version": {
"description": "Optional npm version or version range.",
"type": [
"string",
"null"
]
}
},
"required": [
"package",
"type"
],
"title": "NpmPluginSource",
"type": "object"
},
{
"description": "The plugin is available in the remote catalog. Download metadata is kept server-side and is not exposed through the app-server API.",
"properties": {
@@ -462,6 +496,14 @@
},
"source": {
"$ref": "#/definitions/PluginSource"
},
"version": {
"default": null,
"description": "Version advertised by the remote marketplace backend when available.",
"type": [
"string",
"null"
]
}
},
"required": [
@@ -751,6 +751,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"status": {
"type": [
"string",
@@ -437,6 +437,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -451,6 +463,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -126,6 +126,13 @@
"ephemeral": {
"type": "boolean"
},
"lastTurnId": {
"description": "Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.",
"type": [
"string",
"null"
]
},
"model": {
"description": "Configuration overrides for the forked thread, if any.",
"type": [
@@ -541,6 +541,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -555,6 +567,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -663,13 +681,29 @@
]
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -1170,6 +1204,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -463,6 +463,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -477,6 +489,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -977,6 +995,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -463,6 +463,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -477,6 +489,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -977,6 +995,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -463,6 +463,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -477,6 +489,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -977,6 +995,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -821,6 +821,12 @@
"name": {
"type": "string"
},
"namespace": {
"type": [
"string",
"null"
]
},
"status": {
"type": [
"string",
@@ -541,6 +541,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -555,6 +567,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -663,13 +681,29 @@
]
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -1170,6 +1204,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "DEPRECATED: `thread/rollback` will be removed soon.",
"properties": {
"numTurns": {
"description": "The number of turns to drop from the end of the thread. Must be >= 1.\n\nThis only modifies the thread's history and does not revert local file changes that have been made by the agent. Clients are responsible for reverting these changes.",
@@ -463,6 +463,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -477,6 +489,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -977,6 +995,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -108,13 +108,29 @@
"type": "string"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -195,13 +195,29 @@
"type": "string"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"Personality": {
"enum": [
@@ -241,6 +257,13 @@
],
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadSource": {
"type": "string"
},
@@ -541,6 +541,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -555,6 +567,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -663,13 +681,29 @@
]
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -1170,6 +1204,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -463,6 +463,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -477,6 +489,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -977,6 +995,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -463,6 +463,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -477,6 +489,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -977,6 +995,13 @@
"description": "Extra app-server data for a thread.",
"type": "object"
},
"ThreadHistoryMode": {
"enum": [
"legacy",
"paginated"
],
"type": "string"
},
"ThreadId": {
"type": "string"
},
@@ -437,6 +437,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -451,6 +463,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -141,13 +141,29 @@
"type": "string"
},
"MultiAgentMode": {
"description": "Controls whether the model receives multi-agent delegation instructions and, when it does, whether it should only spawn sub-agents after an explicit user request or may delegate proactively when doing so would help. `none` leaves the multi-agent tools available without injecting delegation instructions.",
"enum": [
"none",
"explicitRequestOnly",
"proactive"
],
"type": "string"
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
"oneOf": [
{
"enum": [
"explicitRequestOnly",
"proactive"
],
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"custom": {
"type": "string"
}
},
"required": [
"custom"
],
"title": "CustomMultiAgentMode",
"type": "object"
}
]
},
"NetworkAccess": {
"enum": [
@@ -437,6 +437,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -451,6 +463,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -437,6 +437,18 @@
},
"McpToolCallAppContext": {
"properties": {
"actionName": {
"type": [
"string",
"null"
]
},
"appName": {
"type": [
"string",
"null"
]
},
"connectorId": {
"type": "string"
},
@@ -451,6 +463,12 @@
"string",
"null"
]
},
"templateId": {
"type": [
"string",
"null"
]
}
},
"required": [
@@ -3,9 +3,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Controls whether the model receives multi-agent delegation instructions and,
* when it does, whether it should only spawn sub-agents after an explicit user
* request or may delegate proactively when doing so would help. `none` leaves
* the multi-agent tools available without injecting delegation instructions.
* Controls the effective multi-agent delegation instructions for a turn. `custom` means the
* configured mode hint defines the policy instead of a built-in policy.
*/
export type MultiAgentMode = "none" | "explicitRequestOnly" | "proactive";
export type MultiAgentMode = { "custom": string } | "explicitRequestOnly" | "proactive";
@@ -20,4 +20,4 @@ id?: string,
/**
* Set when using the Responses API.
*/
call_id: string | null, status: LocalShellStatus, action: LocalShellAction, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "function_call", id?: string, name: string, namespace?: string, arguments: string, call_id: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "tool_search_call", id?: string, call_id: string | null, status?: string, execution: string, arguments: unknown, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "function_call_output", id?: string, call_id: string, output: FunctionCallOutputBody, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "custom_tool_call", id?: string, status?: string, call_id: string, name: string, input: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "custom_tool_call_output", id?: string, call_id: string, name?: string, output: FunctionCallOutputBody, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "tool_search_output", id?: string, call_id: string | null, status: string, execution: string, tools: unknown[], internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "web_search_call", id?: string, status?: string, action?: WebSearchAction, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "image_generation_call", id?: string, status: string, revised_prompt?: string, result: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "compaction", id?: string, encrypted_content: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "compaction_trigger", } | { "type": "context_compaction", id?: string, encrypted_content?: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "other" };
call_id: string | null, status: LocalShellStatus, action: LocalShellAction, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "function_call", id?: string, name: string, namespace?: string, arguments: string, call_id: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "tool_search_call", id?: string, call_id: string | null, status?: string, execution: string, arguments: unknown, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "function_call_output", id?: string, call_id: string, output: FunctionCallOutputBody, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "custom_tool_call", id?: string, status?: string, call_id: string, name: string, namespace?: string, input: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "custom_tool_call_output", id?: string, call_id: string, name?: string, output: FunctionCallOutputBody, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "tool_search_output", id?: string, call_id: string | null, status: string, execution: string, tools: unknown[], internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "web_search_call", id?: string, status?: string, action?: WebSearchAction, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "image_generation_call", id?: string, status: string, revised_prompt?: string, result: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "compaction", id?: string, encrypted_content: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "compaction_trigger", } | { "type": "context_compaction", id?: string, encrypted_content?: string, internal_chat_message_metadata_passthrough?: InternalChatMessageMetadataPassthrough, } | { "type": "other" };
@@ -7,7 +7,7 @@ import type { AppMetadata } from "./AppMetadata";
/**
* EXPERIMENTAL - app metadata returned by app-list APIs.
*/
export type AppInfo = { id: string, name: string, description: string | null, logoUrl: string | null, logoUrlDark: string | null, distributionChannel: string | null, branding: AppBranding | null, appMetadata: AppMetadata | null, labels: { [key in string]?: string } | null, installUrl: string | null, isAccessible: boolean,
export type AppInfo = { id: string, name: string, description: string | null, logoUrl: string | null, logoUrlDark: string | null, iconAssets: { [key in string]?: string } | null, iconDarkAssets: { [key in string]?: string } | null, distributionChannel: string | null, branding: AppBranding | null, appMetadata: AppMetadata | null, labels: { [key in string]?: string } | null, installUrl: string | null, isAccessible: boolean,
/**
* Whether this app is enabled in config.toml.
* Example:
@@ -4,8 +4,9 @@
import type { WebSearchMode } from "../WebSearchMode";
import type { AskForApproval } from "./AskForApproval";
import type { ComputerUseRequirements } from "./ComputerUseRequirements";
import type { ModelsRequirements } from "./ModelsRequirements";
import type { ResidencyRequirement } from "./ResidencyRequirement";
import type { SandboxMode } from "./SandboxMode";
import type { WindowsSandboxSetupMode } from "./WindowsSandboxSetupMode";
export type ConfigRequirements = {allowedApprovalPolicies: Array<AskForApproval> | null, allowedSandboxModes: Array<SandboxMode> | null, allowedWindowsSandboxImplementations: Array<WindowsSandboxSetupMode> | null, allowedPermissionProfiles: { [key in string]?: boolean } | null, defaultPermissions: string | null, allowedWebSearchModes: Array<WebSearchMode> | null, allowManagedHooksOnly: boolean | null, allowAppshots: boolean | null, allowRemoteControl: boolean | null, computerUse: ComputerUseRequirements | null, featureRequirements: { [key in string]?: boolean } | null, enforceResidency: ResidencyRequirement | null};
export type ConfigRequirements = {allowedApprovalPolicies: Array<AskForApproval> | null, allowedSandboxModes: Array<SandboxMode> | null, allowedWindowsSandboxImplementations: Array<WindowsSandboxSetupMode> | null, allowedPermissionProfiles: { [key in string]?: boolean } | null, defaultPermissions: string | null, allowedWebSearchModes: Array<WebSearchMode> | null, allowManagedHooksOnly: boolean | null, allowAppshots: boolean | null, allowRemoteControl: boolean | null, computerUse: ComputerUseRequirements | null, featureRequirements: { [key in string]?: boolean } | null, enforceResidency: ResidencyRequirement | null, models: ModelsRequirements | null};
@@ -7,4 +7,9 @@ export type ConsumeAccountRateLimitResetCreditParams = {
* Identifies one logical reset attempt. A UUID is recommended; reuse the same value when
* retrying that attempt.
*/
idempotencyKey: string, };
idempotencyKey: string,
/**
* Opaque reset-credit identifier to redeem. When omitted, the backend selects the next
* available credit.
*/
creditId?: string | null, };
@@ -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 McpServerOauthLoginCompletedNotification = { name: string, success: boolean, error?: string, };
export type McpServerOauthLoginCompletedNotification = { name: string, threadId: string | null, success: boolean, error?: string, };
@@ -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 McpServerOauthLoginParams = { name: string, scopes?: Array<string> | null, timeoutSecs?: bigint | null, };
export type McpServerOauthLoginParams = { name: string, threadId?: string | null, scopes?: Array<string> | null, timeoutSecs?: bigint | null, };
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type McpServerStartupFailureReason = "reauthenticationRequired";
@@ -1,6 +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 { McpServerStartupFailureReason } from "./McpServerStartupFailureReason";
import type { McpServerStartupState } from "./McpServerStartupState";
export type McpServerStatusUpdatedNotification = { threadId: string | null, name: string, status: McpServerStartupState, error: string | null, };
export type McpServerStatusUpdatedNotification = { threadId: string | null, name: string, status: McpServerStartupState, error: string | null, failureReason: McpServerStartupFailureReason | null, };
@@ -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 McpToolCallAppContext = { connectorId: string, linkId: string | null, resourceUri: string | null, };
export type McpToolCallAppContext = { connectorId: string, linkId: string | null, resourceUri: string | null, appName: string | null, templateId: string | null, actionName: string | null, };
@@ -0,0 +1,6 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { NewThreadModelDefaults } from "./NewThreadModelDefaults";
export type ModelsRequirements = { newThread: NewThreadModelDefaults | null, };
@@ -0,0 +1,6 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ReasoningEffort } from "../ReasoningEffort";
export type NewThreadModelDefaults = { model: string | null, modelReasoningEffort: ReasoningEffort | null, serviceTier: string | null, };
@@ -3,4 +3,12 @@
// 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 PluginSource = { "type": "local", path: AbsolutePathBuf, } | { "type": "git", url: string, path: string | null, refName: string | null, sha: string | null, } | { "type": "remote" };
export type PluginSource = { "type": "local", path: AbsolutePathBuf, } | { "type": "git", url: string, path: string | null, refName: string | null, sha: string | null, } | { "type": "npm", package: string,
/**
* Optional npm version or version range.
*/
version: string | null,
/**
* Optional HTTPS registry URL. Authentication stays in the user's npm config.
*/
registry: string | null, } | { "type": "remote" };
@@ -13,6 +13,10 @@ export type PluginSummary = { id: string,
* Backend remote plugin identifier when available.
*/
remotePluginId: string | null,
/**
* Version advertised by the remote marketplace backend when available.
*/
version: string | null,
/**
* Version of the locally materialized plugin package when available.
*/
@@ -0,0 +1,27 @@
// 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 { RateLimitResetCreditStatus } from "./RateLimitResetCreditStatus";
import type { RateLimitResetType } from "./RateLimitResetType";
export type RateLimitResetCredit = {
/**
* Opaque backend identifier for this reset credit.
*/
id: string, resetType: RateLimitResetType, status: RateLimitResetCreditStatus,
/**
* Unix timestamp in seconds when the credit was granted.
*/
grantedAt: number,
/**
* Unix timestamp in seconds when the credit expires, or `null` if it does not expire.
*/
expiresAt: number | null,
/**
* Backend-provided display title for this credit, or `null` when unavailable.
*/
title: string | null,
/**
* Backend-provided display description for this credit, or `null` when unavailable.
*/
description: string | null, };
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type RateLimitResetCreditStatus = "available" | "redeeming" | "redeemed" | "unknown";
@@ -1,5 +1,14 @@
// 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 { RateLimitResetCredit } from "./RateLimitResetCredit";
export type RateLimitResetCreditsSummary = { availableCount: bigint, };
export type RateLimitResetCreditsSummary = { availableCount: bigint,
/**
* Detail rows for available reset credits, when the backend provides them.
*
* `null` means only `availableCount` is known, while an empty array means details were fetched
* and no available credits were returned. The backend may cap this list, so its length can be
* less than `availableCount`.
*/
credits: Array<RateLimitResetCredit> | null, };
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type RateLimitResetType = "codexRateLimits" | "unknown";
@@ -18,6 +18,12 @@ import type { ThreadSource } from "./ThreadSource";
* Prefer using thread_id whenever possible.
*/
export type ThreadForkParams = {threadId: string, /**
* Optional last turn id to fork through, inclusive.
*
* When specified, turns after `last_turn_id` are omitted from the fork.
* The referenced turn cannot be in progress.
*/
lastTurnId?: string | null, /**
* Configuration overrides for the forked thread, if any.
*/
model?: string | null, modelProvider?: string | null, serviceTier?: string | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, /**
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ThreadHistoryMode = "legacy" | "paginated";
@@ -2,6 +2,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* DEPRECATED: `thread/rollback` will be removed soon.
*/
export type ThreadRollbackParams = { threadId: string,
/**
* The number of turns to drop from the end of the thread. Must be >= 1.
@@ -238,6 +238,7 @@ export type { McpServerOauthLoginCompletedNotification } from "./McpServerOauthL
export type { McpServerOauthLoginParams } from "./McpServerOauthLoginParams";
export type { McpServerOauthLoginResponse } from "./McpServerOauthLoginResponse";
export type { McpServerRefreshResponse } from "./McpServerRefreshResponse";
export type { McpServerStartupFailureReason } from "./McpServerStartupFailureReason";
export type { McpServerStartupState } from "./McpServerStartupState";
export type { McpServerStatus } from "./McpServerStatus";
export type { McpServerStatusDetail } from "./McpServerStatusDetail";
@@ -266,6 +267,7 @@ export type { ModelServiceTier } from "./ModelServiceTier";
export type { ModelUpgradeInfo } from "./ModelUpgradeInfo";
export type { ModelVerification } from "./ModelVerification";
export type { ModelVerificationNotification } from "./ModelVerificationNotification";
export type { ModelsRequirements } from "./ModelsRequirements";
export type { NetworkAccess } from "./NetworkAccess";
export type { NetworkApprovalContext } from "./NetworkApprovalContext";
export type { NetworkApprovalProtocol } from "./NetworkApprovalProtocol";
@@ -274,6 +276,7 @@ export type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment";
export type { NetworkPolicyRuleAction } from "./NetworkPolicyRuleAction";
export type { NetworkRequirements } from "./NetworkRequirements";
export type { NetworkUnixSocketPermission } from "./NetworkUnixSocketPermission";
export type { NewThreadModelDefaults } from "./NewThreadModelDefaults";
export type { NonSteerableTurnKind } from "./NonSteerableTurnKind";
export type { OverriddenMetadata } from "./OverriddenMetadata";
export type { PatchApplyStatus } from "./PatchApplyStatus";
@@ -332,7 +335,10 @@ export type { ProcessOutputDeltaNotification } from "./ProcessOutputDeltaNotific
export type { ProcessOutputStream } from "./ProcessOutputStream";
export type { ProcessTerminalSize } from "./ProcessTerminalSize";
export type { RateLimitReachedType } from "./RateLimitReachedType";
export type { RateLimitResetCredit } from "./RateLimitResetCredit";
export type { RateLimitResetCreditStatus } from "./RateLimitResetCreditStatus";
export type { RateLimitResetCreditsSummary } from "./RateLimitResetCreditsSummary";
export type { RateLimitResetType } from "./RateLimitResetType";
export type { RateLimitSnapshot } from "./RateLimitSnapshot";
export type { RateLimitWindow } from "./RateLimitWindow";
export type { RawResponseItemCompletedNotification } from "./RawResponseItemCompletedNotification";
@@ -409,6 +415,7 @@ export type { ThreadGoalSetParams } from "./ThreadGoalSetParams";
export type { ThreadGoalSetResponse } from "./ThreadGoalSetResponse";
export type { ThreadGoalStatus } from "./ThreadGoalStatus";
export type { ThreadGoalUpdatedNotification } from "./ThreadGoalUpdatedNotification";
export type { ThreadHistoryMode } from "./ThreadHistoryMode";
export type { ThreadInjectItemsParams } from "./ThreadInjectItemsParams";
export type { ThreadInjectItemsResponse } from "./ThreadInjectItemsResponse";
export type { ThreadItem } from "./ThreadItem";

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