mirror of
https://github.com/openai/codex.git
synced 2026-10-24 18:18:41 +00:00
Merge branch 'main' into alexs/tui-migrate
This commit is contained in:
@@ -12,7 +12,7 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@v3.7.0
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
|
||||
|
||||
- name: Cosign Linux artifacts
|
||||
shell: bash
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
name: prepare-bazel-ci
|
||||
description: Prepare a Bazel CI job with shared setup, repository cache restore, and execution logs.
|
||||
inputs:
|
||||
target:
|
||||
description: Target triple used for setup and cache namespacing.
|
||||
required: true
|
||||
install-test-prereqs:
|
||||
description: Install Node.js and DotSlash for Bazel-backed test jobs.
|
||||
required: false
|
||||
default: "false"
|
||||
outputs:
|
||||
repository-cache-path:
|
||||
description: Filesystem path used for the Bazel repository cache.
|
||||
value: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
with:
|
||||
target: ${{ inputs.target }}
|
||||
install-test-prereqs: ${{ inputs.install-test-prereqs }}
|
||||
|
||||
# Restore the Bazel repository cache explicitly so external dependencies
|
||||
# do not need to be re-downloaded on every CI run. Keep restore failures
|
||||
# non-fatal so transient cache-service errors degrade to a cold build
|
||||
# instead of failing the job.
|
||||
- name: Restore bazel repository cache
|
||||
id: cache_bazel_repository_restore
|
||||
continue-on-error: true
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
key: bazel-cache-${{ inputs.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
bazel-cache-${{ inputs.target }}
|
||||
|
||||
- name: Set up Bazel execution logs
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "${RUNNER_TEMP}/bazel-execution-logs"
|
||||
echo "CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR=${RUNNER_TEMP}/bazel-execution-logs" >> "${GITHUB_ENV}"
|
||||
@@ -18,7 +18,7 @@ runs:
|
||||
steps:
|
||||
- name: Set up Node.js for js_repl tests
|
||||
if: inputs.install-test-prereqs == 'true'
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version-file: codex-rs/node-version.txt
|
||||
|
||||
@@ -26,7 +26,7 @@ runs:
|
||||
# See https://github.com/openai/codex/pull/7617.
|
||||
- name: Install DotSlash
|
||||
if: inputs.install-test-prereqs == 'true'
|
||||
uses: facebook/install-dotslash@v2
|
||||
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
||||
|
||||
- name: Make DotSlash available in PATH (Unix)
|
||||
if: inputs.install-test-prereqs == 'true' && runner.os != 'Windows'
|
||||
@@ -39,7 +39,7 @@ runs:
|
||||
run: Copy-Item (Get-Command dotslash).Source -Destination "$env:LOCALAPPDATA\Microsoft\WindowsApps\dotslash.exe"
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@v3
|
||||
uses: bazelbuild/setup-bazelisk@b39c379c82683a5f25d34f0d062761f62693e0b2 # v3
|
||||
|
||||
- name: Configure Bazel repository cache
|
||||
id: configure_bazel_repository_cache
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
name: setup-rusty-v8-musl
|
||||
description: Download and verify musl rusty_v8 artifacts for Cargo builds.
|
||||
inputs:
|
||||
target:
|
||||
description: Rust musl target triple.
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure musl rusty_v8 artifact overrides and verify checksums
|
||||
shell: bash
|
||||
env:
|
||||
TARGET: ${{ inputs.target }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
case "${TARGET}" in
|
||||
x86_64-unknown-linux-musl|aarch64-unknown-linux-musl)
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported musl rusty_v8 target: ${TARGET}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
version="$(python3 "${GITHUB_WORKSPACE}/.github/scripts/rusty_v8_bazel.py" resolved-v8-crate-version)"
|
||||
release_tag="rusty-v8-v${version}"
|
||||
base_url="https://github.com/openai/codex/releases/download/${release_tag}"
|
||||
binding_dir="${RUNNER_TEMP}/rusty_v8"
|
||||
archive_path="${binding_dir}/librusty_v8_release_${TARGET}.a.gz"
|
||||
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs"
|
||||
checksums_path="${binding_dir}/rusty_v8_release_${TARGET}.sha256"
|
||||
checksums_source="${GITHUB_WORKSPACE}/third_party/v8/rusty_v8_${version//./_}.sha256"
|
||||
|
||||
mkdir -p "${binding_dir}"
|
||||
curl -fsSL "${base_url}/librusty_v8_release_${TARGET}.a.gz" -o "${archive_path}"
|
||||
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}"
|
||||
grep -E " (librusty_v8_release_${TARGET}[.]a[.]gz|src_binding_release_${TARGET}[.]rs)$" \
|
||||
"${checksums_source}" > "${checksums_path}"
|
||||
|
||||
if [[ "$(wc -l < "${checksums_path}")" -ne 2 ]]; then
|
||||
echo "Expected exactly two checksums for ${TARGET} in ${checksums_source}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
(cd "${binding_dir}" && sha256sum -c "${checksums_path}")
|
||||
echo "RUSTY_V8_ARCHIVE=${archive_path}" >> "${GITHUB_ENV}"
|
||||
echo "RUSTY_V8_SRC_BINDING_PATH=${binding_path}" >> "${GITHUB_ENV}"
|
||||
@@ -27,14 +27,14 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Azure login for Trusted Signing (OIDC)
|
||||
uses: azure/login@v2
|
||||
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2
|
||||
with:
|
||||
client-id: ${{ inputs.client-id }}
|
||||
tenant-id: ${{ inputs.tenant-id }}
|
||||
subscription-id: ${{ inputs.subscription-id }}
|
||||
|
||||
- name: Sign Windows binaries with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@v0
|
||||
uses: azure/trusted-signing-action@1d365fec12862c4aa68fcac418143d73f0cea293 # v0
|
||||
with:
|
||||
endpoint: ${{ inputs.endpoint }}
|
||||
trusted-signing-account-name: ${{ inputs.account-name }}
|
||||
|
||||
@@ -92,7 +92,7 @@ print_bazel_test_log_tails() {
|
||||
|
||||
for target in "${failed_targets[@]}"; do
|
||||
local rel_path="${target#//}"
|
||||
rel_path="${rel_path/:/\/}"
|
||||
rel_path="${rel_path/://}"
|
||||
local test_log="${testlogs_dir}/${rel_path}/test.log"
|
||||
|
||||
echo "::group::Bazel test log tail for ${target}"
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import gzip
|
||||
import hashlib
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -12,8 +13,16 @@ import tempfile
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
from rusty_v8_module_bazel import (
|
||||
RustyV8ChecksumError,
|
||||
check_module_bazel,
|
||||
update_module_bazel,
|
||||
)
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
MODULE_BAZEL = ROOT / "MODULE.bazel"
|
||||
RUSTY_V8_CHECKSUMS_DIR = ROOT / "third_party" / "v8"
|
||||
MUSL_RUNTIME_ARCHIVE_LABELS = [
|
||||
"@llvm//runtimes/libcxx:libcxx.static",
|
||||
"@llvm//runtimes/libcxx:libcxxabi.static",
|
||||
@@ -146,6 +155,24 @@ def resolved_v8_crate_version() -> str:
|
||||
return matches[0]
|
||||
|
||||
|
||||
def rusty_v8_checksum_manifest_path(version: str) -> Path:
|
||||
return RUSTY_V8_CHECKSUMS_DIR / f"rusty_v8_{version.replace('.', '_')}.sha256"
|
||||
|
||||
|
||||
def command_version(version: str | None) -> str:
|
||||
if version is not None:
|
||||
return version
|
||||
return resolved_v8_crate_version()
|
||||
|
||||
|
||||
def command_manifest_path(manifest: Path | None, version: str) -> Path:
|
||||
if manifest is None:
|
||||
return rusty_v8_checksum_manifest_path(version)
|
||||
if manifest.is_absolute():
|
||||
return manifest
|
||||
return ROOT / manifest
|
||||
|
||||
|
||||
def staged_archive_name(target: str, source_path: Path) -> str:
|
||||
if source_path.suffix == ".lib":
|
||||
return f"rusty_v8_release_{target}.lib.gz"
|
||||
@@ -244,8 +271,18 @@ def stage_release_pair(
|
||||
|
||||
shutil.copyfile(binding_path, staged_binding)
|
||||
|
||||
staged_checksums = output_dir / f"rusty_v8_release_{target}.sha256"
|
||||
with staged_checksums.open("w", encoding="utf-8") as checksums:
|
||||
for path in [staged_library, staged_binding]:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as artifact:
|
||||
for chunk in iter(lambda: artifact.read(1024 * 1024), b""):
|
||||
digest.update(chunk)
|
||||
checksums.write(f"{digest.hexdigest()} {path.name}\n")
|
||||
|
||||
print(staged_library)
|
||||
print(staged_binding)
|
||||
print(staged_checksums)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
@@ -264,6 +301,24 @@ def parse_args() -> argparse.Namespace:
|
||||
|
||||
subparsers.add_parser("resolved-v8-crate-version")
|
||||
|
||||
check_module_bazel_parser = subparsers.add_parser("check-module-bazel")
|
||||
check_module_bazel_parser.add_argument("--version")
|
||||
check_module_bazel_parser.add_argument("--manifest", type=Path)
|
||||
check_module_bazel_parser.add_argument(
|
||||
"--module-bazel",
|
||||
type=Path,
|
||||
default=MODULE_BAZEL,
|
||||
)
|
||||
|
||||
update_module_bazel_parser = subparsers.add_parser("update-module-bazel")
|
||||
update_module_bazel_parser.add_argument("--version")
|
||||
update_module_bazel_parser.add_argument("--manifest", type=Path)
|
||||
update_module_bazel_parser.add_argument(
|
||||
"--module-bazel",
|
||||
type=Path,
|
||||
default=MODULE_BAZEL,
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -280,6 +335,22 @@ def main() -> int:
|
||||
if args.command == "resolved-v8-crate-version":
|
||||
print(resolved_v8_crate_version())
|
||||
return 0
|
||||
if args.command == "check-module-bazel":
|
||||
version = command_version(args.version)
|
||||
manifest_path = command_manifest_path(args.manifest, version)
|
||||
try:
|
||||
check_module_bazel(args.module_bazel, manifest_path, version)
|
||||
except RustyV8ChecksumError as exc:
|
||||
raise SystemExit(str(exc)) from exc
|
||||
return 0
|
||||
if args.command == "update-module-bazel":
|
||||
version = command_version(args.version)
|
||||
manifest_path = command_manifest_path(args.manifest, version)
|
||||
try:
|
||||
update_module_bazel(args.module_bazel, manifest_path, version)
|
||||
except RustyV8ChecksumError as exc:
|
||||
raise SystemExit(str(exc)) from exc
|
||||
return 0
|
||||
raise SystemExit(f"unsupported command: {args.command}")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SHA256_RE = re.compile(r"[0-9a-f]{64}")
|
||||
HTTP_FILE_BLOCK_RE = re.compile(r"(?ms)^http_file\(\n.*?^\)\n?")
|
||||
|
||||
|
||||
class RustyV8ChecksumError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RustyV8HttpFile:
|
||||
start: int
|
||||
end: int
|
||||
block: str
|
||||
name: str
|
||||
downloaded_file_path: str
|
||||
sha256: str | None
|
||||
|
||||
|
||||
def parse_checksum_manifest(path: Path) -> dict[str, str]:
|
||||
try:
|
||||
lines = path.read_text(encoding="utf-8").splitlines()
|
||||
except FileNotFoundError as exc:
|
||||
raise RustyV8ChecksumError(f"missing checksum manifest: {path}") from exc
|
||||
|
||||
checksums: dict[str, str] = {}
|
||||
for line_number, line in enumerate(lines, 1):
|
||||
if not line.strip():
|
||||
continue
|
||||
parts = line.split()
|
||||
if len(parts) != 2:
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: expected '<sha256> <filename>'"
|
||||
)
|
||||
checksum, filename = parts
|
||||
if not SHA256_RE.fullmatch(checksum):
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: invalid SHA-256 digest for {filename}"
|
||||
)
|
||||
if not filename or filename in {".", ".."} or "/" in filename:
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: expected a bare artifact filename"
|
||||
)
|
||||
if filename in checksums:
|
||||
raise RustyV8ChecksumError(
|
||||
f"{path}:{line_number}: duplicate checksum for {filename}"
|
||||
)
|
||||
checksums[filename] = checksum
|
||||
|
||||
if not checksums:
|
||||
raise RustyV8ChecksumError(f"empty checksum manifest: {path}")
|
||||
return checksums
|
||||
|
||||
|
||||
def string_field(block: str, field: str) -> str | None:
|
||||
# Matches one-line string fields inside http_file blocks, e.g. `sha256 = "...",`.
|
||||
match = re.search(rf'^\s*{re.escape(field)}\s*=\s*"([^"]+)",\s*$', block, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def rusty_v8_http_files(module_bazel: str, version: str) -> list[RustyV8HttpFile]:
|
||||
version_slug = version.replace(".", "_")
|
||||
name_prefix = f"rusty_v8_{version_slug}_"
|
||||
entries = []
|
||||
for match in HTTP_FILE_BLOCK_RE.finditer(module_bazel):
|
||||
block = match.group(0)
|
||||
name = string_field(block, "name")
|
||||
if not name or not name.startswith(name_prefix):
|
||||
continue
|
||||
downloaded_file_path = string_field(block, "downloaded_file_path")
|
||||
if not downloaded_file_path:
|
||||
raise RustyV8ChecksumError(
|
||||
f"MODULE.bazel {name} is missing downloaded_file_path"
|
||||
)
|
||||
entries.append(
|
||||
RustyV8HttpFile(
|
||||
start=match.start(),
|
||||
end=match.end(),
|
||||
block=block,
|
||||
name=name,
|
||||
downloaded_file_path=downloaded_file_path,
|
||||
sha256=string_field(block, "sha256"),
|
||||
)
|
||||
)
|
||||
return entries
|
||||
|
||||
|
||||
def module_entry_set_errors(
|
||||
entries: list[RustyV8HttpFile],
|
||||
checksums: dict[str, str],
|
||||
version: str,
|
||||
) -> list[str]:
|
||||
errors = []
|
||||
if not entries:
|
||||
errors.append(f"MODULE.bazel has no rusty_v8 http_file entries for {version}")
|
||||
return errors
|
||||
|
||||
module_files: dict[str, RustyV8HttpFile] = {}
|
||||
duplicate_files = set()
|
||||
for entry in entries:
|
||||
if entry.downloaded_file_path in module_files:
|
||||
duplicate_files.add(entry.downloaded_file_path)
|
||||
module_files[entry.downloaded_file_path] = entry
|
||||
|
||||
for filename in sorted(duplicate_files):
|
||||
errors.append(f"MODULE.bazel has duplicate http_file entries for {filename}")
|
||||
|
||||
for filename in sorted(set(module_files) - set(checksums)):
|
||||
entry = module_files[filename]
|
||||
errors.append(f"MODULE.bazel {entry.name} has no checksum in the manifest")
|
||||
|
||||
for filename in sorted(set(checksums) - set(module_files)):
|
||||
errors.append(f"manifest has {filename}, but MODULE.bazel has no http_file")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def module_checksum_errors(
|
||||
entries: list[RustyV8HttpFile],
|
||||
checksums: dict[str, str],
|
||||
) -> list[str]:
|
||||
errors = []
|
||||
for entry in entries:
|
||||
expected = checksums.get(entry.downloaded_file_path)
|
||||
if expected is None:
|
||||
continue
|
||||
if entry.sha256 is None:
|
||||
errors.append(f"MODULE.bazel {entry.name} is missing sha256")
|
||||
elif entry.sha256 != expected:
|
||||
errors.append(
|
||||
f"MODULE.bazel {entry.name} has sha256 {entry.sha256}, "
|
||||
f"expected {expected}"
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
def raise_checksum_errors(message: str, errors: list[str]) -> None:
|
||||
if errors:
|
||||
formatted_errors = "\n".join(f"- {error}" for error in errors)
|
||||
raise RustyV8ChecksumError(f"{message}:\n{formatted_errors}")
|
||||
|
||||
|
||||
def check_module_bazel_text(
|
||||
module_bazel: str,
|
||||
checksums: dict[str, str],
|
||||
version: str,
|
||||
) -> None:
|
||||
entries = rusty_v8_http_files(module_bazel, version)
|
||||
errors = [
|
||||
*module_entry_set_errors(entries, checksums, version),
|
||||
*module_checksum_errors(entries, checksums),
|
||||
]
|
||||
raise_checksum_errors("rusty_v8 MODULE.bazel checksum drift", errors)
|
||||
|
||||
|
||||
def block_with_sha256(block: str, checksum: str) -> str:
|
||||
sha256_line_re = re.compile(r'(?m)^(\s*)sha256\s*=\s*"[0-9a-f]+",\s*$')
|
||||
if sha256_line_re.search(block):
|
||||
return sha256_line_re.sub(
|
||||
lambda match: f'{match.group(1)}sha256 = "{checksum}",',
|
||||
block,
|
||||
count=1,
|
||||
)
|
||||
|
||||
downloaded_file_path_match = re.search(
|
||||
r'(?m)^(\s*)downloaded_file_path\s*=\s*"[^"]+",\n',
|
||||
block,
|
||||
)
|
||||
if not downloaded_file_path_match:
|
||||
raise RustyV8ChecksumError("http_file block is missing downloaded_file_path")
|
||||
insert_at = downloaded_file_path_match.end()
|
||||
indent = downloaded_file_path_match.group(1)
|
||||
return f'{block[:insert_at]}{indent}sha256 = "{checksum}",\n{block[insert_at:]}'
|
||||
|
||||
|
||||
def update_module_bazel_text(
|
||||
module_bazel: str,
|
||||
checksums: dict[str, str],
|
||||
version: str,
|
||||
) -> str:
|
||||
entries = rusty_v8_http_files(module_bazel, version)
|
||||
errors = module_entry_set_errors(entries, checksums, version)
|
||||
raise_checksum_errors("cannot update rusty_v8 MODULE.bazel checksums", errors)
|
||||
|
||||
updated = []
|
||||
previous_end = 0
|
||||
for entry in entries:
|
||||
updated.append(module_bazel[previous_end : entry.start])
|
||||
updated.append(
|
||||
block_with_sha256(entry.block, checksums[entry.downloaded_file_path])
|
||||
)
|
||||
previous_end = entry.end
|
||||
updated.append(module_bazel[previous_end:])
|
||||
return "".join(updated)
|
||||
|
||||
|
||||
def check_module_bazel(
|
||||
module_bazel_path: Path,
|
||||
manifest_path: Path,
|
||||
version: str,
|
||||
) -> None:
|
||||
checksums = parse_checksum_manifest(manifest_path)
|
||||
module_bazel = module_bazel_path.read_text(encoding="utf-8")
|
||||
check_module_bazel_text(module_bazel, checksums, version)
|
||||
print(f"{module_bazel_path} rusty_v8 {version} checksums match {manifest_path}")
|
||||
|
||||
|
||||
def update_module_bazel(
|
||||
module_bazel_path: Path,
|
||||
manifest_path: Path,
|
||||
version: str,
|
||||
) -> None:
|
||||
checksums = parse_checksum_manifest(manifest_path)
|
||||
module_bazel = module_bazel_path.read_text(encoding="utf-8")
|
||||
updated_module_bazel = update_module_bazel_text(module_bazel, checksums, version)
|
||||
if updated_module_bazel == module_bazel:
|
||||
print(f"{module_bazel_path} rusty_v8 {version} checksums are already current")
|
||||
return
|
||||
module_bazel_path.write_text(updated_module_bazel, encoding="utf-8")
|
||||
print(f"updated {module_bazel_path} rusty_v8 {version} checksums")
|
||||
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
import rusty_v8_module_bazel
|
||||
|
||||
|
||||
class RustyV8BazelTest(unittest.TestCase):
|
||||
def test_update_module_bazel_replaces_and_inserts_sha256(self) -> None:
|
||||
module_bazel = textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
urls = [
|
||||
"https://example.test/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_musl_binding",
|
||||
downloaded_file_path = "src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
urls = [
|
||||
"https://example.test/src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_145_0_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
urls = [
|
||||
"https://example.test/old.gz",
|
||||
],
|
||||
)
|
||||
"""
|
||||
)
|
||||
checksums = {
|
||||
"librusty_v8_release_x86_64-unknown-linux-gnu.a.gz": (
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
),
|
||||
"src_binding_release_x86_64-unknown-linux-musl.rs": (
|
||||
"2222222222222222222222222222222222222222222222222222222222222222"
|
||||
),
|
||||
}
|
||||
|
||||
updated = rusty_v8_module_bazel.update_module_bazel_text(
|
||||
module_bazel,
|
||||
checksums,
|
||||
"146.4.0",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
urls = [
|
||||
"https://example.test/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_musl_binding",
|
||||
downloaded_file_path = "src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
sha256 = "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
urls = [
|
||||
"https://example.test/src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "rusty_v8_145_0_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
urls = [
|
||||
"https://example.test/old.gz",
|
||||
],
|
||||
)
|
||||
"""
|
||||
),
|
||||
updated,
|
||||
)
|
||||
rusty_v8_module_bazel.check_module_bazel_text(updated, checksums, "146.4.0")
|
||||
|
||||
def test_check_module_bazel_rejects_manifest_drift(self) -> None:
|
||||
module_bazel = textwrap.dedent(
|
||||
"""\
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
urls = [
|
||||
"https://example.test/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
)
|
||||
"""
|
||||
)
|
||||
checksums = {
|
||||
"librusty_v8_release_x86_64-unknown-linux-gnu.a.gz": (
|
||||
"1111111111111111111111111111111111111111111111111111111111111111"
|
||||
),
|
||||
"orphan.gz": (
|
||||
"2222222222222222222222222222222222222222222222222222222222222222"
|
||||
),
|
||||
}
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
rusty_v8_module_bazel.RustyV8ChecksumError,
|
||||
"manifest has orphan.gz",
|
||||
):
|
||||
rusty_v8_module_bazel.check_module_bazel_text(
|
||||
module_bazel,
|
||||
checksums,
|
||||
"146.4.0",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+102
-54
@@ -51,38 +51,24 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
- name: Check rusty_v8 MODULE.bazel checksums
|
||||
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: |
|
||||
python3 .github/scripts/rusty_v8_bazel.py check-module-bazel
|
||||
python3 -m unittest discover -s .github/scripts -p test_rusty_v8_bazel.py
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
install-test-prereqs: "true"
|
||||
|
||||
# Restore the Bazel repository cache explicitly so external dependencies
|
||||
# do not need to be re-downloaded on every CI run. Keep restore failures
|
||||
# non-fatal so transient cache-service errors degrade to a cold build
|
||||
# instead of failing the job.
|
||||
- name: Restore bazel repository cache
|
||||
id: cache_bazel_repository_restore
|
||||
continue-on-error: true
|
||||
uses: actions/cache/restore@v5
|
||||
with:
|
||||
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
bazel-cache-${{ matrix.target }}
|
||||
|
||||
- name: Check MODULE.bazel.lock is up to date
|
||||
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: ./scripts/check-module-bazel-lock.sh
|
||||
|
||||
- name: Set up Bazel execution logs
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "${RUNNER_TEMP}/bazel-execution-logs"
|
||||
echo "CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR=${RUNNER_TEMP}/bazel-execution-logs" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: bazel test //...
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
@@ -123,14 +109,14 @@ jobs:
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save bazel repository cache explicitly; make non-fatal so cache uploading
|
||||
# never fails the overall job. Only save when key wasn't hit.
|
||||
# Save the Bazel repository cache after every non-cancelled run. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled() && steps.cache_bazel_repository_restore.outputs.cache-hit != 'true'
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
|
||||
clippy:
|
||||
@@ -155,32 +141,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel CI
|
||||
id: setup_bazel
|
||||
uses: ./.github/actions/setup-bazel-ci
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
# Restore the Bazel repository cache explicitly so external dependencies
|
||||
# do not need to be re-downloaded on every CI run. Keep restore failures
|
||||
# non-fatal so transient cache-service errors degrade to a cold build
|
||||
# instead of failing the job.
|
||||
- name: Restore bazel repository cache
|
||||
id: cache_bazel_repository_restore
|
||||
continue-on-error: true
|
||||
uses: actions/cache/restore@v5
|
||||
with:
|
||||
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
bazel-cache-${{ matrix.target }}
|
||||
|
||||
- name: Set up Bazel execution logs
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "${RUNNER_TEMP}/bazel-execution-logs"
|
||||
echo "CODEX_BAZEL_EXECUTION_LOG_COMPACT_DIR=${RUNNER_TEMP}/bazel-execution-logs" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: bazel build --config=clippy lint targets
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
@@ -220,12 +186,94 @@ jobs:
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save bazel repository cache explicitly; make non-fatal so cache uploading
|
||||
# never fails the overall job. Only save when key wasn't hit.
|
||||
# Save the Bazel repository cache after every non-cancelled run. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ steps.setup_bazel.outputs.repository-cache-path }}
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
|
||||
verify-release-build:
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-15-xlarge
|
||||
target: aarch64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-gnullvm
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Verify release build on ${{ matrix.os }} for ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Prepare Bazel CI
|
||||
id: prepare_bazel
|
||||
uses: ./.github/actions/prepare-bazel-ci
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: bazel build verify-release-build targets
|
||||
env:
|
||||
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
||||
shell: bash
|
||||
run: |
|
||||
# This job exists to compile Rust code behind
|
||||
# `cfg(not(debug_assertions))` so PR CI catches failures that would
|
||||
# otherwise show up only in a release build. We do not need the full
|
||||
# optimizer and debug-info work that normally comes with a release
|
||||
# build to get that signal, so keep Bazel in `fastbuild` and disable
|
||||
# Rust debug assertions explicitly.
|
||||
bazel_wrapper_args=()
|
||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
bazel_wrapper_args+=(--windows-msvc-host-platform)
|
||||
fi
|
||||
|
||||
bazel_build_args=(
|
||||
--compilation_mode=fastbuild
|
||||
--@rules_rust//rust/settings:extra_rustc_flag=-Cdebug-assertions=no
|
||||
--@rules_rust//rust/settings:extra_exec_rustc_flag=-Cdebug-assertions=no
|
||||
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
||||
--build_metadata=TAG_job=verify-release-build
|
||||
--build_metadata=TAG_rust_debug_assertions=off
|
||||
)
|
||||
|
||||
bazel_target_lines="$(bash ./scripts/list-bazel-release-targets.sh)"
|
||||
bazel_targets=()
|
||||
while IFS= read -r target; do
|
||||
bazel_targets+=("${target}")
|
||||
done <<< "${bazel_target_lines}"
|
||||
|
||||
./.github/scripts/run-bazel-ci.sh \
|
||||
"${bazel_wrapper_args[@]}" \
|
||||
-- \
|
||||
build \
|
||||
"${bazel_build_args[@]}" \
|
||||
-- \
|
||||
"${bazel_targets[@]}"
|
||||
|
||||
- name: Upload Bazel execution logs
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
with:
|
||||
name: bazel-execution-logs-verify-release-build-${{ matrix.target }}
|
||||
path: ${{ runner.temp }}/bazel-execution-logs
|
||||
if-no-files-found: ignore
|
||||
|
||||
# Save the Bazel repository cache after every non-cancelled run. Keep the
|
||||
# upload non-fatal so cache service issues never fail the job itself.
|
||||
- name: Save bazel repository cache
|
||||
if: always() && !cancelled()
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
||||
with:
|
||||
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
||||
key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
|
||||
|
||||
@@ -43,6 +43,9 @@ jobs:
|
||||
argument_comment_lint_package:
|
||||
name: Argument comment lint package
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
CARGO_DYLINT_VERSION: 5.0.0
|
||||
DYLINT_LINK_VERSION: 5.0.0
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
@@ -59,10 +62,13 @@ jobs:
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: argument-comment-lint-${{ runner.os }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml', '.github/workflows/rust-ci-full.yml') }}
|
||||
key: argument-comment-lint-${{ runner.os }}-${{ env.CARGO_DYLINT_VERSION }}-${{ env.DYLINT_LINK_VERSION }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml', '.github/workflows/rust-ci-full.yml') }}
|
||||
- name: Install cargo-dylint tooling
|
||||
if: ${{ steps.cargo_dylint_cache.outputs.cache-hit != 'true' }}
|
||||
run: cargo install --locked cargo-dylint dylint-link
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install --locked cargo-dylint --version "$CARGO_DYLINT_VERSION"
|
||||
cargo install --locked dylint-link --version "$DYLINT_LINK_VERSION"
|
||||
- name: Check Python wrapper syntax
|
||||
run: python3 -m py_compile tools/argument-comment-lint/wrapper_common.py tools/argument-comment-lint/run.py tools/argument-comment-lint/run-prebuilt-linter.py tools/argument-comment-lint/test_wrapper_common.py
|
||||
- name: Test Python wrapper helpers
|
||||
@@ -415,22 +421,10 @@ jobs:
|
||||
echo "CXXFLAGS=${cxxflags}" >> "$GITHUB_ENV"
|
||||
|
||||
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl' }}
|
||||
name: Configure musl rusty_v8 artifact overrides
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="$(python3 "${GITHUB_WORKSPACE}/.github/scripts/rusty_v8_bazel.py" resolved-v8-crate-version)"
|
||||
release_tag="rusty-v8-v${version}"
|
||||
base_url="https://github.com/openai/codex/releases/download/${release_tag}"
|
||||
archive="https://github.com/openai/codex/releases/download/rusty-v8-v${version}/librusty_v8_release_${TARGET}.a.gz"
|
||||
binding_dir="${RUNNER_TEMP}/rusty_v8"
|
||||
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs"
|
||||
mkdir -p "${binding_dir}"
|
||||
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}"
|
||||
echo "RUSTY_V8_ARCHIVE=${archive}" >> "$GITHUB_ENV"
|
||||
echo "RUSTY_V8_SRC_BINDING_PATH=${binding_path}" >> "$GITHUB_ENV"
|
||||
name: Configure musl rusty_v8 artifact overrides and verify checksums
|
||||
uses: ./.github/actions/setup-rusty-v8-musl
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Install cargo-chef
|
||||
if: ${{ matrix.profile == 'release' }}
|
||||
|
||||
@@ -90,6 +90,9 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: changed
|
||||
if: ${{ needs.changed.outputs.argument_comment_lint_package == 'true' }}
|
||||
env:
|
||||
CARGO_DYLINT_VERSION: 5.0.0
|
||||
DYLINT_LINK_VERSION: 5.0.0
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
||||
@@ -113,10 +116,13 @@ jobs:
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: argument-comment-lint-${{ runner.os }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml', '.github/workflows/rust-ci-full.yml') }}
|
||||
key: argument-comment-lint-${{ runner.os }}-${{ env.CARGO_DYLINT_VERSION }}-${{ env.DYLINT_LINK_VERSION }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml', '.github/workflows/rust-ci-full.yml') }}
|
||||
- name: Install cargo-dylint tooling
|
||||
if: ${{ steps.cargo_dylint_cache.outputs.cache-hit != 'true' }}
|
||||
run: cargo install --locked cargo-dylint dylint-link
|
||||
shell: bash
|
||||
run: |
|
||||
cargo install --locked cargo-dylint --version "$CARGO_DYLINT_VERSION"
|
||||
cargo install --locked dylint-link --version "$DYLINT_LINK_VERSION"
|
||||
- name: Check Python wrapper syntax
|
||||
run: python3 -m py_compile tools/argument-comment-lint/wrapper_common.py tools/argument-comment-lint/run.py tools/argument-comment-lint/run-prebuilt-linter.py tools/argument-comment-lint/test_wrapper_common.py
|
||||
- name: Test Python wrapper helpers
|
||||
|
||||
@@ -19,6 +19,9 @@ jobs:
|
||||
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CARGO_DYLINT_VERSION: 5.0.0
|
||||
DYLINT_LINK_VERSION: 5.0.0
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -65,8 +68,8 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
install_root="${RUNNER_TEMP}/argument-comment-lint-tools"
|
||||
cargo install --locked cargo-dylint --root "$install_root"
|
||||
cargo install --locked dylint-link
|
||||
cargo install --locked cargo-dylint --version "$CARGO_DYLINT_VERSION" --root "$install_root"
|
||||
cargo install --locked dylint-link --version "$DYLINT_LINK_VERSION"
|
||||
echo "INSTALL_ROOT=$install_root" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Cargo build
|
||||
|
||||
@@ -211,22 +211,10 @@ jobs:
|
||||
echo "CXXFLAGS=${cxxflags}" >> "$GITHUB_ENV"
|
||||
|
||||
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl' }}
|
||||
name: Configure musl rusty_v8 artifact overrides
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="$(python3 "${GITHUB_WORKSPACE}/.github/scripts/rusty_v8_bazel.py" resolved-v8-crate-version)"
|
||||
release_tag="rusty-v8-v${version}"
|
||||
base_url="https://github.com/openai/codex/releases/download/${release_tag}"
|
||||
archive="https://github.com/openai/codex/releases/download/rusty-v8-v${version}/librusty_v8_release_${TARGET}.a.gz"
|
||||
binding_dir="${RUNNER_TEMP}/rusty_v8"
|
||||
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs"
|
||||
mkdir -p "${binding_dir}"
|
||||
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}"
|
||||
echo "RUSTY_V8_ARCHIVE=${archive}" >> "$GITHUB_ENV"
|
||||
echo "RUSTY_V8_SRC_BINDING_PATH=${binding_path}" >> "$GITHUB_ENV"
|
||||
name: Configure musl rusty_v8 artifact overrides and verify checksums
|
||||
uses: ./.github/actions/setup-rusty-v8-musl
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
- name: Cargo build
|
||||
shell: bash
|
||||
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@6ecf4fd8b7d1f9721785f1dd656a689acf9add47 # v3
|
||||
uses: bazelbuild/setup-bazelisk@b39c379c82683a5f25d34f0d062761f62693e0b2 # v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Set up Bazel
|
||||
uses: bazelbuild/setup-bazelisk@6ecf4fd8b7d1f9721785f1dd656a689acf9add47 # v3
|
||||
uses: bazelbuild/setup-bazelisk@b39c379c82683a5f25d34f0d062761f62693e0b2 # v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
||||
|
||||
@@ -423,6 +423,7 @@ http_archive(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_aarch64_apple_darwin_archive",
|
||||
downloaded_file_path = "librusty_v8_release_aarch64-apple-darwin.a.gz",
|
||||
sha256 = "bfe2c9be32a56c28546f0f965825ee68fbf606405f310cc4e17b448a568cf98a",
|
||||
urls = [
|
||||
"https://github.com/denoland/rusty_v8/releases/download/v146.4.0/librusty_v8_release_aarch64-apple-darwin.a.gz",
|
||||
],
|
||||
@@ -431,6 +432,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_aarch64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_aarch64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "dbf165b07c81bdb054bc046b43d23e69fcf7bcc1a4c1b5b4776983a71062ecd8",
|
||||
urls = [
|
||||
"https://github.com/denoland/rusty_v8/releases/download/v146.4.0/librusty_v8_release_aarch64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
@@ -439,6 +441,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_aarch64_pc_windows_msvc_archive",
|
||||
downloaded_file_path = "rusty_v8_release_aarch64-pc-windows-msvc.lib.gz",
|
||||
sha256 = "ed13363659c6d08583ac8fdc40493445c5767d8b94955a4d5d7bb8d5a81f6bf8",
|
||||
urls = [
|
||||
"https://github.com/denoland/rusty_v8/releases/download/v146.4.0/rusty_v8_release_aarch64-pc-windows-msvc.lib.gz",
|
||||
],
|
||||
@@ -447,6 +450,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_apple_darwin_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-apple-darwin.a.gz",
|
||||
sha256 = "630cd240f1bbecdb071417dc18387ab81cf67c549c1c515a0b4fcf9eba647bb7",
|
||||
urls = [
|
||||
"https://github.com/denoland/rusty_v8/releases/download/v146.4.0/librusty_v8_release_x86_64-apple-darwin.a.gz",
|
||||
],
|
||||
@@ -455,6 +459,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_gnu_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
sha256 = "e64b4d99e4ae293a2e846244a89b80178ba10382c13fb591c1fa6968f5291153",
|
||||
urls = [
|
||||
"https://github.com/denoland/rusty_v8/releases/download/v146.4.0/librusty_v8_release_x86_64-unknown-linux-gnu.a.gz",
|
||||
],
|
||||
@@ -463,6 +468,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_pc_windows_msvc_archive",
|
||||
downloaded_file_path = "rusty_v8_release_x86_64-pc-windows-msvc.lib.gz",
|
||||
sha256 = "90a9a2346acd3685a355e98df85c24dbe406cb124367d16259a4b5d522621862",
|
||||
urls = [
|
||||
"https://github.com/denoland/rusty_v8/releases/download/v146.4.0/rusty_v8_release_x86_64-pc-windows-msvc.lib.gz",
|
||||
],
|
||||
@@ -471,6 +477,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_aarch64_unknown_linux_musl_archive",
|
||||
downloaded_file_path = "librusty_v8_release_aarch64-unknown-linux-musl.a.gz",
|
||||
sha256 = "27a08ed26c34297bfd93e514692ccc44b85f8b15c6aa39cf34e784f84fb37e8e",
|
||||
urls = [
|
||||
"https://github.com/openai/codex/releases/download/rusty-v8-v146.4.0/librusty_v8_release_aarch64-unknown-linux-musl.a.gz",
|
||||
],
|
||||
@@ -479,6 +486,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_aarch64_unknown_linux_musl_binding",
|
||||
downloaded_file_path = "src_binding_release_aarch64-unknown-linux-musl.rs",
|
||||
sha256 = "09f8900ced8297c229246c7a50b2e0ec23c54d0a554f369619cc29863f38dd1a",
|
||||
urls = [
|
||||
"https://github.com/openai/codex/releases/download/rusty-v8-v146.4.0/src_binding_release_aarch64-unknown-linux-musl.rs",
|
||||
],
|
||||
@@ -487,6 +495,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_musl_archive",
|
||||
downloaded_file_path = "librusty_v8_release_x86_64-unknown-linux-musl.a.gz",
|
||||
sha256 = "20d8271ad712323d352c1383c36e3c4b755abc41ece35819c49c75ec7134d2f8",
|
||||
urls = [
|
||||
"https://github.com/openai/codex/releases/download/rusty-v8-v146.4.0/librusty_v8_release_x86_64-unknown-linux-musl.a.gz",
|
||||
],
|
||||
@@ -495,6 +504,7 @@ http_file(
|
||||
http_file(
|
||||
name = "rusty_v8_146_4_0_x86_64_unknown_linux_musl_binding",
|
||||
downloaded_file_path = "src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
sha256 = "09f8900ced8297c229246c7a50b2e0ec23c54d0a554f369619cc29863f38dd1a",
|
||||
urls = [
|
||||
"https://github.com/openai/codex/releases/download/rusty-v8-v146.4.0/src_binding_release_x86_64-unknown-linux-musl.rs",
|
||||
],
|
||||
|
||||
Generated
+3
-2
@@ -782,6 +782,7 @@
|
||||
"debugid_0.8.0": "{\"dependencies\":[{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.85\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.37\"},{\"name\":\"uuid\",\"req\":\"^1.0.0\"}],\"features\":{}}",
|
||||
"debugserver-types_0.5.0": "{\"dependencies\":[{\"name\":\"schemafy\",\"req\":\"^0.5.0\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{}}",
|
||||
"deflate64_0.1.10": "{\"dependencies\":[{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"bytemuck\",\"req\":\"^1.13.1\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.2.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.7.1\"}],\"features\":{}}",
|
||||
"deno_core_icudata_0.77.0": "{\"dependencies\":[],\"features\":{}}",
|
||||
"der-parser_10.0.0": "{\"dependencies\":[{\"name\":\"asn1-rs\",\"req\":\"^0.7\"},{\"name\":\"bitvec\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"cookie-factory\",\"optional\":true,\"req\":\"^0.3.0\"},{\"default_features\":false,\"name\":\"displaydoc\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"name\":\"nom\",\"req\":\"^7.0\"},{\"name\":\"num-bigint\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"num-traits\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^1.0\"},{\"name\":\"rusticata-macros\",\"req\":\"^4.0\"},{\"kind\":\"dev\",\"name\":\"test-case\",\"req\":\"^3.0\"}],\"features\":{\"as_bitvec\":[\"bitvec\"],\"bigint\":[\"num-bigint\"],\"default\":[\"std\"],\"serialize\":[\"std\",\"cookie-factory\"],\"std\":[],\"unstable\":[]}}",
|
||||
"der_0.7.10": "{\"dependencies\":[{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.3\"},{\"default_features\":false,\"name\":\"bytes\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"const-oid\",\"optional\":true,\"req\":\"^0.9.2\"},{\"name\":\"der_derive\",\"optional\":true,\"req\":\"^0.7.2\"},{\"name\":\"flagset\",\"optional\":true,\"req\":\"^0.4.3\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4.1\"},{\"features\":[\"alloc\"],\"name\":\"pem-rfc7468\",\"optional\":true,\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"time\",\"optional\":true,\"req\":\"^0.3.4\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.5\"}],\"features\":{\"alloc\":[\"zeroize?/alloc\"],\"arbitrary\":[\"dep:arbitrary\",\"const-oid?/arbitrary\",\"std\"],\"bytes\":[\"dep:bytes\",\"alloc\"],\"derive\":[\"dep:der_derive\"],\"oid\":[\"dep:const-oid\"],\"pem\":[\"dep:pem-rfc7468\",\"alloc\",\"zeroize\"],\"real\":[],\"std\":[\"alloc\"]}}",
|
||||
"deranged_0.5.5": "{\"dependencies\":[{\"name\":\"deranged-macros\",\"optional\":true,\"req\":\"=0.3.0\"},{\"default_features\":false,\"name\":\"num-traits\",\"optional\":true,\"req\":\"^0.2.15\"},{\"default_features\":false,\"name\":\"powerfmt\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"name\":\"quickcheck\",\"optional\":true,\"req\":\"^1.0.3\"},{\"default_features\":false,\"name\":\"rand08\",\"optional\":true,\"package\":\"rand\",\"req\":\"^0.8.4\"},{\"kind\":\"dev\",\"name\":\"rand08\",\"package\":\"rand\",\"req\":\"^0.8.4\"},{\"default_features\":false,\"name\":\"rand09\",\"optional\":true,\"package\":\"rand\",\"req\":\"^0.9.0\"},{\"kind\":\"dev\",\"name\":\"rand09\",\"package\":\"rand\",\"req\":\"^0.9.0\"},{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.220\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.86\"}],\"features\":{\"alloc\":[],\"default\":[],\"macros\":[\"dep:deranged-macros\"],\"num\":[\"dep:num-traits\"],\"powerfmt\":[\"dep:powerfmt\"],\"quickcheck\":[\"dep:quickcheck\",\"alloc\"],\"rand\":[\"rand08\",\"rand09\"],\"rand08\":[\"dep:rand08\"],\"rand09\":[\"dep:rand09\"],\"serde\":[\"dep:serde_core\"]}}",
|
||||
@@ -903,8 +904,8 @@
|
||||
"git+https://github.com/juberti-oai/rust-sdks.git?rev=e2d1d1d230c6fc9df171ccb181423f957bb3c1f0#e2d1d1d230c6fc9df171ccb181423f957bb3c1f0_livekit-runtime": "{\"dependencies\":[{\"default_features\":true,\"features\":[],\"name\":\"async-io\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"async-std\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"async-task\",\"optional\":true},{\"name\":\"futures\",\"optional\":true},{\"default_features\":false,\"features\":[\"net\",\"rt\",\"rt-multi-thread\",\"time\"],\"name\":\"tokio\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"tokio-stream\",\"optional\":true}],\"features\":{\"async\":[\"dep:async-std\",\"dep:futures\",\"dep:async-io\"],\"default\":[\"tokio\"],\"dispatcher\":[\"dep:futures\",\"dep:async-io\",\"dep:async-std\",\"dep:async-task\"],\"tokio\":[\"dep:tokio\",\"dep:tokio-stream\"]},\"strip_prefix\":\"livekit-runtime\"}",
|
||||
"git+https://github.com/juberti-oai/rust-sdks.git?rev=e2d1d1d230c6fc9df171ccb181423f957bb3c1f0#e2d1d1d230c6fc9df171ccb181423f957bb3c1f0_webrtc-sys": "{\"dependencies\":[{\"name\":\"cxx\"},{\"name\":\"log\"},{\"kind\":\"build\",\"name\":\"cc\"},{\"kind\":\"build\",\"name\":\"cxx-build\"},{\"kind\":\"build\",\"name\":\"glob\"},{\"kind\":\"build\",\"name\":\"pkg-config\"},{\"default_features\":true,\"features\":[],\"kind\":\"build\",\"name\":\"webrtc-sys-build\",\"optional\":false}],\"features\":{\"default\":[]},\"strip_prefix\":\"webrtc-sys\"}",
|
||||
"git+https://github.com/juberti-oai/rust-sdks.git?rev=e2d1d1d230c6fc9df171ccb181423f957bb3c1f0#e2d1d1d230c6fc9df171ccb181423f957bb3c1f0_webrtc-sys-build": "{\"dependencies\":[{\"name\":\"anyhow\"},{\"name\":\"fs2\"},{\"name\":\"regex\"},{\"default_features\":false,\"features\":[\"rustls-tls-native-roots\",\"blocking\"],\"name\":\"reqwest\",\"optional\":false},{\"name\":\"scratch\"},{\"name\":\"semver\"},{\"name\":\"zip\"}],\"features\":{},\"strip_prefix\":\"webrtc-sys/build\"}",
|
||||
"git+https://github.com/nornagon/crossterm?branch=nornagon%2Fcolor-query#87db8bfa6dc99427fd3b071681b07fc31c6ce995_crossterm": "{\"dependencies\":[{\"default_features\":true,\"features\":[],\"name\":\"bitflags\",\"optional\":false},{\"default_features\":false,\"features\":[],\"name\":\"futures-core\",\"optional\":true},{\"name\":\"parking_lot\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"filedescriptor\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":false,\"features\":[],\"name\":\"libc\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[\"os-poll\"],\"name\":\"mio\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":false,\"features\":[\"std\",\"stdio\",\"termios\"],\"name\":\"rustix\",\"optional\":false,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[],\"name\":\"signal-hook\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[\"support-v1_0\"],\"name\":\"signal-hook-mio\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[],\"name\":\"crossterm_winapi\",\"optional\":true,\"target\":\"cfg(windows)\"},{\"default_features\":true,\"features\":[\"winuser\",\"winerror\"],\"name\":\"winapi\",\"optional\":true,\"target\":\"cfg(windows)\"}],\"features\":{\"bracketed-paste\":[],\"default\":[\"bracketed-paste\",\"windows\",\"events\"],\"event-stream\":[\"dep:futures-core\",\"events\"],\"events\":[\"dep:mio\",\"dep:signal-hook\",\"dep:signal-hook-mio\"],\"serde\":[\"dep:serde\",\"bitflags/serde\"],\"use-dev-tty\":[\"filedescriptor\",\"rustix/process\"],\"windows\":[\"dep:winapi\",\"dep:crossterm_winapi\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/nornagon/ratatui?branch=nornagon-v0.29.0-patch#9b2ad1298408c45918ee9f8241a6f95498cdbed2_ratatui": "{\"dependencies\":[{\"name\":\"bitflags\"},{\"name\":\"cassowary\"},{\"name\":\"compact_str\"},{\"default_features\":true,\"features\":[],\"name\":\"crossterm\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"document-features\",\"optional\":true},{\"name\":\"indoc\"},{\"name\":\"instability\"},{\"name\":\"itertools\"},{\"name\":\"lru\"},{\"default_features\":true,\"features\":[],\"name\":\"palette\",\"optional\":true},{\"name\":\"paste\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"strum\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"termwiz\",\"optional\":true},{\"default_features\":true,\"features\":[\"local-offset\"],\"name\":\"time\",\"optional\":true},{\"name\":\"unicode-segmentation\"},{\"name\":\"unicode-truncate\"},{\"name\":\"unicode-width\"},{\"default_features\":true,\"features\":[],\"name\":\"termion\",\"optional\":true,\"target\":\"cfg(not(windows))\"}],\"features\":{\"all-widgets\":[\"widget-calendar\"],\"crossterm\":[\"dep:crossterm\"],\"default\":[\"crossterm\",\"underline-color\"],\"macros\":[],\"palette\":[\"dep:palette\"],\"scrolling-regions\":[],\"serde\":[\"dep:serde\",\"bitflags/serde\",\"compact_str/serde\"],\"termion\":[\"dep:termion\"],\"termwiz\":[\"dep:termwiz\"],\"underline-color\":[\"dep:crossterm\"],\"unstable\":[\"unstable-rendered-line-info\",\"unstable-widget-ref\",\"unstable-backend-writer\"],\"unstable-backend-writer\":[],\"unstable-rendered-line-info\":[],\"unstable-widget-ref\":[],\"widget-calendar\":[\"dep:time\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/nornagon/crossterm?rev=87db8bfa6dc99427fd3b071681b07fc31c6ce995#87db8bfa6dc99427fd3b071681b07fc31c6ce995_crossterm": "{\"dependencies\":[{\"default_features\":true,\"features\":[],\"name\":\"bitflags\",\"optional\":false},{\"default_features\":false,\"features\":[],\"name\":\"futures-core\",\"optional\":true},{\"name\":\"parking_lot\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"filedescriptor\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":false,\"features\":[],\"name\":\"libc\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[\"os-poll\"],\"name\":\"mio\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":false,\"features\":[\"std\",\"stdio\",\"termios\"],\"name\":\"rustix\",\"optional\":false,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[],\"name\":\"signal-hook\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[\"support-v1_0\"],\"name\":\"signal-hook-mio\",\"optional\":true,\"target\":\"cfg(unix)\"},{\"default_features\":true,\"features\":[],\"name\":\"crossterm_winapi\",\"optional\":true,\"target\":\"cfg(windows)\"},{\"default_features\":true,\"features\":[\"winuser\",\"winerror\"],\"name\":\"winapi\",\"optional\":true,\"target\":\"cfg(windows)\"}],\"features\":{\"bracketed-paste\":[],\"default\":[\"bracketed-paste\",\"windows\",\"events\"],\"event-stream\":[\"dep:futures-core\",\"events\"],\"events\":[\"dep:mio\",\"dep:signal-hook\",\"dep:signal-hook-mio\"],\"serde\":[\"dep:serde\",\"bitflags/serde\"],\"use-dev-tty\":[\"filedescriptor\",\"rustix/process\"],\"windows\":[\"dep:winapi\",\"dep:crossterm_winapi\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/nornagon/ratatui?rev=9b2ad1298408c45918ee9f8241a6f95498cdbed2#9b2ad1298408c45918ee9f8241a6f95498cdbed2_ratatui": "{\"dependencies\":[{\"name\":\"bitflags\"},{\"name\":\"cassowary\"},{\"name\":\"compact_str\"},{\"default_features\":true,\"features\":[],\"name\":\"crossterm\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"document-features\",\"optional\":true},{\"name\":\"indoc\"},{\"name\":\"instability\"},{\"name\":\"itertools\"},{\"name\":\"lru\"},{\"default_features\":true,\"features\":[],\"name\":\"palette\",\"optional\":true},{\"name\":\"paste\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"strum\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"termwiz\",\"optional\":true},{\"default_features\":true,\"features\":[\"local-offset\"],\"name\":\"time\",\"optional\":true},{\"name\":\"unicode-segmentation\"},{\"name\":\"unicode-truncate\"},{\"name\":\"unicode-width\"},{\"default_features\":true,\"features\":[],\"name\":\"termion\",\"optional\":true,\"target\":\"cfg(not(windows))\"}],\"features\":{\"all-widgets\":[\"widget-calendar\"],\"crossterm\":[\"dep:crossterm\"],\"default\":[\"crossterm\",\"underline-color\"],\"macros\":[],\"palette\":[\"dep:palette\"],\"scrolling-regions\":[],\"serde\":[\"dep:serde\",\"bitflags/serde\",\"compact_str/serde\"],\"termion\":[\"dep:termion\"],\"termwiz\":[\"dep:termwiz\"],\"underline-color\":[\"dep:crossterm\"],\"unstable\":[\"unstable-rendered-line-info\",\"unstable-widget-ref\",\"unstable-backend-writer\"],\"unstable-backend-writer\":[],\"unstable-rendered-line-info\":[],\"unstable-widget-ref\":[],\"widget-calendar\":[\"dep:time\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/openai-oss-forks/tokio-tungstenite?rev=132f5b39c862e3a970f731d709608b3e6276d5f6#132f5b39c862e3a970f731d709608b3e6276d5f6_tokio-tungstenite": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"sink\",\"std\"],\"name\":\"futures-util\",\"optional\":false},{\"name\":\"log\"},{\"default_features\":true,\"features\":[],\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\"},{\"default_features\":false,\"features\":[],\"name\":\"rustls\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-native-certs\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-pki-types\",\"optional\":true},{\"default_features\":false,\"features\":[\"io-util\"],\"name\":\"tokio\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"tokio-native-tls\",\"optional\":true},{\"default_features\":false,\"features\":[],\"name\":\"tokio-rustls\",\"optional\":true},{\"default_features\":false,\"features\":[],\"name\":\"tungstenite\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"webpki-roots\",\"optional\":true}],\"features\":{\"__rustls-tls\":[\"rustls\",\"rustls-pki-types\",\"tokio-rustls\",\"stream\",\"tungstenite/__rustls-tls\",\"handshake\"],\"connect\":[\"stream\",\"tokio/net\",\"handshake\"],\"default\":[\"connect\",\"handshake\"],\"handshake\":[\"tungstenite/handshake\"],\"native-tls\":[\"native-tls-crate\",\"tokio-native-tls\",\"stream\",\"tungstenite/native-tls\",\"handshake\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate/vendored\",\"tungstenite/native-tls-vendored\"],\"proxy\":[\"tungstenite/proxy\",\"tokio/net\",\"handshake\"],\"rustls-tls-native-roots\":[\"__rustls-tls\",\"rustls-native-certs\"],\"rustls-tls-webpki-roots\":[\"__rustls-tls\",\"webpki-roots\"],\"stream\":[],\"url\":[\"tungstenite/url\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/openai-oss-forks/tungstenite-rs?rev=9200079d3b54a1ff51072e24d81fd354f085156f#9200079d3b54a1ff51072e24d81fd354f085156f_tungstenite": "{\"dependencies\":[{\"name\":\"bytes\"},{\"default_features\":true,\"features\":[],\"name\":\"data-encoding\",\"optional\":true},{\"default_features\":false,\"features\":[\"zlib\"],\"name\":\"flate2\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"headers\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"http\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"httparse\",\"optional\":true},{\"name\":\"log\"},{\"default_features\":true,\"features\":[],\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\"},{\"name\":\"rand\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"rustls\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-native-certs\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-pki-types\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"sha1\",\"optional\":true},{\"name\":\"thiserror\"},{\"default_features\":true,\"features\":[],\"name\":\"url\",\"optional\":true},{\"name\":\"utf-8\"},{\"default_features\":true,\"features\":[],\"name\":\"webpki-roots\",\"optional\":true}],\"features\":{\"__rustls-tls\":[\"rustls\",\"rustls-pki-types\"],\"default\":[\"handshake\"],\"deflate\":[\"headers\",\"flate2\"],\"handshake\":[\"data-encoding\",\"headers\",\"httparse\",\"sha1\"],\"headers\":[\"http\",\"dep:headers\"],\"native-tls\":[\"native-tls-crate\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate/vendored\"],\"proxy\":[\"handshake\"],\"rustls-tls-native-roots\":[\"__rustls-tls\",\"rustls-native-certs\"],\"rustls-tls-webpki-roots\":[\"__rustls-tls\",\"webpki-roots\"],\"url\":[\"dep:url\"]},\"strip_prefix\":\"\"}",
|
||||
"git+https://github.com/rust-lang/rust-clippy?rev=20ce69b9a63bcd2756cd906fe0964d1e901e042a#20ce69b9a63bcd2756cd906fe0964d1e901e042a_clippy_utils": "{\"dependencies\":[{\"default_features\":false,\"features\":[],\"name\":\"arrayvec\",\"optional\":false},{\"name\":\"itertools\"},{\"name\":\"rustc_apfloat\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":false}],\"features\":{},\"strip_prefix\":\"clippy_utils\"}",
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
[advisories]
|
||||
# Reviewed 2026-04-11. Keep this list in sync with ../deny.toml.
|
||||
ignore = [
|
||||
"RUSTSEC-2024-0388", # derivative 2.2.0 via starlark; upstream crate is unmaintained
|
||||
"RUSTSEC-2025-0057", # fxhash 0.2.1 via starlark_map; upstream crate is unmaintained
|
||||
"RUSTSEC-2024-0436", # paste 1.0.15 via starlark/ratatui; upstream crate is unmaintained
|
||||
"RUSTSEC-2024-0320", # yaml-rust via syntect; remove when syntect drops or updates it
|
||||
"RUSTSEC-2025-0141", # bincode via syntect; remove when syntect drops or updates it
|
||||
]
|
||||
|
||||
Generated
+39
-4
@@ -1375,6 +1375,7 @@ dependencies = [
|
||||
"codex-login",
|
||||
"codex-plugin",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"os_info",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
@@ -1669,6 +1670,7 @@ dependencies = [
|
||||
"assert_matches",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"codex-api",
|
||||
"codex-app-server",
|
||||
"codex-app-server-protocol",
|
||||
"codex-app-server-test-client",
|
||||
@@ -1828,6 +1830,7 @@ name = "codex-code-mode"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core_icudata",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1902,7 +1905,6 @@ dependencies = [
|
||||
"codex-api",
|
||||
"codex-app-server-protocol",
|
||||
"codex-apply-patch",
|
||||
"codex-arg0",
|
||||
"codex-async-utils",
|
||||
"codex-code-mode",
|
||||
"codex-config",
|
||||
@@ -1932,6 +1934,7 @@ dependencies = [
|
||||
"codex-shell-escalation",
|
||||
"codex-state",
|
||||
"codex-terminal-detection",
|
||||
"codex-test-binary-support",
|
||||
"codex-tools",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-cache",
|
||||
@@ -2012,6 +2015,7 @@ dependencies = [
|
||||
"codex-analytics",
|
||||
"codex-app-server-protocol",
|
||||
"codex-config",
|
||||
"codex-exec-server",
|
||||
"codex-instructions",
|
||||
"codex-login",
|
||||
"codex-otel",
|
||||
@@ -2101,9 +2105,10 @@ dependencies = [
|
||||
"codex-config",
|
||||
"codex-protocol",
|
||||
"codex-sandboxing",
|
||||
"codex-test-binary-support",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-cargo-bin",
|
||||
"codex-utils-pty",
|
||||
"ctor 0.6.3",
|
||||
"futures",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
@@ -2233,6 +2238,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"codex-config",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"futures",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
@@ -2382,6 +2388,7 @@ dependencies = [
|
||||
"codex-models-manager",
|
||||
"codex-protocol",
|
||||
"codex-shell-command",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-cli",
|
||||
"codex-utils-json-to-toml",
|
||||
"core_test_support",
|
||||
@@ -2813,6 +2820,25 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-test-binary-support"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-arg0",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-thread-store"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"codex-protocol",
|
||||
"serde",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-tools"
|
||||
version = "0.0.0"
|
||||
@@ -3050,10 +3076,13 @@ dependencies = [
|
||||
name = "codex-utils-plugins"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-exec-server",
|
||||
"codex-login",
|
||||
"codex-utils-absolute-path",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3527,7 +3556,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.28.1"
|
||||
source = "git+https://github.com/nornagon/crossterm?branch=nornagon%2Fcolor-query#87db8bfa6dc99427fd3b071681b07fc31c6ce995"
|
||||
source = "git+https://github.com/nornagon/crossterm?rev=87db8bfa6dc99427fd3b071681b07fc31c6ce995#87db8bfa6dc99427fd3b071681b07fc31c6ce995"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"crossterm_winapi",
|
||||
@@ -3890,6 +3919,12 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26bf8fc351c5ed29b5c2f0cbbac1b209b74f60ecd62e675a998df72c49af5204"
|
||||
|
||||
[[package]]
|
||||
name = "deno_core_icudata"
|
||||
version = "0.77.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9efff8990a82c1ae664292507e1a5c6749ddd2312898cdf9cd7cb1fd4bc64c6"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
@@ -8454,7 +8489,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
version = "0.29.0"
|
||||
source = "git+https://github.com/nornagon/ratatui?branch=nornagon-v0.29.0-patch#9b2ad1298408c45918ee9f8241a6f95498cdbed2"
|
||||
source = "git+https://github.com/nornagon/ratatui?rev=9b2ad1298408c45918ee9f8241a6f95498cdbed2#9b2ad1298408c45918ee9f8241a6f95498cdbed2"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cassowary",
|
||||
|
||||
+6
-2
@@ -86,6 +86,8 @@ members = [
|
||||
"codex-api",
|
||||
"state",
|
||||
"terminal-detection",
|
||||
"test-binary-support",
|
||||
"thread-store",
|
||||
"codex-experimental-api-macros",
|
||||
"plugin",
|
||||
]
|
||||
@@ -163,6 +165,7 @@ codex-skills = { path = "skills" }
|
||||
codex-state = { path = "state" }
|
||||
codex-stdio-to-uds = { path = "stdio-to-uds" }
|
||||
codex-terminal-detection = { path = "terminal-detection" }
|
||||
codex-test-binary-support = { path = "test-binary-support" }
|
||||
codex-tools = { path = "tools" }
|
||||
codex-tui = { path = "tui" }
|
||||
codex-utils-absolute-path = { path = "utils/absolute-path" }
|
||||
@@ -218,6 +221,7 @@ crossbeam-channel = "0.5.15"
|
||||
crossterm = "0.28.1"
|
||||
csv = "1.3.1"
|
||||
ctor = "0.6.3"
|
||||
deno_core_icudata = "0.77.0"
|
||||
derive_more = "2"
|
||||
diffy = "0.4.2"
|
||||
dirs = "6"
|
||||
@@ -427,8 +431,8 @@ opt-level = 0
|
||||
[patch.crates-io]
|
||||
# Uncomment to debug local changes.
|
||||
# ratatui = { path = "../../ratatui" }
|
||||
crossterm = { git = "https://github.com/nornagon/crossterm", branch = "nornagon/color-query" }
|
||||
ratatui = { git = "https://github.com/nornagon/ratatui", branch = "nornagon-v0.29.0-patch" }
|
||||
crossterm = { git = "https://github.com/nornagon/crossterm", rev = "87db8bfa6dc99427fd3b071681b07fc31c6ce995" }
|
||||
ratatui = { git = "https://github.com/nornagon/ratatui", rev = "9b2ad1298408c45918ee9f8241a6f95498cdbed2" }
|
||||
tokio-tungstenite = { git = "https://github.com/openai-oss-forks/tokio-tungstenite", rev = "132f5b39c862e3a970f731d709608b3e6276d5f6" }
|
||||
tungstenite = { git = "https://github.com/openai-oss-forks/tungstenite-rs", rev = "9200079d3b54a1ff51072e24d81fd354f085156f" }
|
||||
|
||||
|
||||
@@ -29,4 +29,5 @@ tokio = { workspace = true, features = [
|
||||
tracing = { workspace = true, features = ["log"] }
|
||||
|
||||
[dev-dependencies]
|
||||
codex-utils-absolute-path = { workspace = true }
|
||||
pretty_assertions = { workspace = true }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ use crate::events::TrackEventRequest;
|
||||
use crate::events::TrackEventsRequest;
|
||||
use crate::events::current_runtime_metadata;
|
||||
use crate::facts::AnalyticsFact;
|
||||
use crate::facts::AnalyticsJsonRpcError;
|
||||
use crate::facts::AppInvocation;
|
||||
use crate::facts::AppMentionedInput;
|
||||
use crate::facts::AppUsedInput;
|
||||
@@ -14,9 +15,15 @@ use crate::facts::SkillInvocation;
|
||||
use crate::facts::SkillInvokedInput;
|
||||
use crate::facts::SubAgentThreadStartedInput;
|
||||
use crate::facts::TrackEventsContext;
|
||||
use crate::facts::TurnResolvedConfigFact;
|
||||
use crate::facts::TurnTokenUsageFact;
|
||||
use crate::reducer::AnalyticsReducer;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::ClientResponse;
|
||||
use codex_app_server_protocol::InitializeParams;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_login::AuthManager;
|
||||
use codex_login::default_client::create_client;
|
||||
use codex_plugin::PluginTelemetryMetadata;
|
||||
@@ -167,6 +174,14 @@ impl AnalyticsEventsClient {
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn track_request(&self, connection_id: u64, request_id: RequestId, request: ClientRequest) {
|
||||
self.record_fact(AnalyticsFact::Request {
|
||||
connection_id,
|
||||
request_id,
|
||||
request: Box::new(request),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn track_app_used(&self, tracking: TrackEventsContext, app: AppInvocation) {
|
||||
if !self.queue.should_enqueue_app_used(&tracking, &app) {
|
||||
return;
|
||||
@@ -191,6 +206,18 @@ impl AnalyticsEventsClient {
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn track_turn_resolved_config(&self, fact: TurnResolvedConfigFact) {
|
||||
self.record_fact(AnalyticsFact::Custom(
|
||||
CustomAnalyticsFact::TurnResolvedConfig(Box::new(fact)),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn track_turn_token_usage(&self, fact: TurnTokenUsageFact) {
|
||||
self.record_fact(AnalyticsFact::Custom(CustomAnalyticsFact::TurnTokenUsage(
|
||||
Box::new(fact),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn track_plugin_installed(&self, plugin: PluginTelemetryMetadata) {
|
||||
self.record_fact(AnalyticsFact::Custom(
|
||||
CustomAnalyticsFact::PluginStateChanged(PluginStateChangedInput {
|
||||
@@ -240,6 +267,25 @@ impl AnalyticsEventsClient {
|
||||
response: Box::new(response),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn track_error_response(
|
||||
&self,
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
error: JSONRPCErrorError,
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
) {
|
||||
self.record_fact(AnalyticsFact::ErrorResponse {
|
||||
connection_id,
|
||||
request_id,
|
||||
error,
|
||||
error_type,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn track_notification(&self, notification: ServerNotification) {
|
||||
self.record_fact(AnalyticsFact::Notification(Box::new(notification)));
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_track_events(
|
||||
|
||||
@@ -3,13 +3,18 @@ use crate::facts::CodexCompactionEvent;
|
||||
use crate::facts::InvocationType;
|
||||
use crate::facts::PluginState;
|
||||
use crate::facts::SubAgentThreadStartedInput;
|
||||
use crate::facts::ThreadInitializationMode;
|
||||
use crate::facts::TrackEventsContext;
|
||||
use crate::facts::TurnStatus;
|
||||
use crate::facts::TurnSteerRejectionReason;
|
||||
use crate::facts::TurnSteerResult;
|
||||
use crate::facts::TurnSubmissionType;
|
||||
use codex_app_server_protocol::CodexErrorInfo;
|
||||
use codex_login::default_client::originator;
|
||||
use codex_plugin::PluginTelemetryMetadata;
|
||||
use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::SandboxPermissions;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -21,14 +26,6 @@ pub enum AppServerRpcTransport {
|
||||
InProcess,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub(crate) enum ThreadInitializationMode {
|
||||
New,
|
||||
Forked,
|
||||
Resumed,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct TrackEventsRequest {
|
||||
pub(crate) events: Vec<TrackEventRequest>,
|
||||
@@ -43,6 +40,8 @@ pub(crate) enum TrackEventRequest {
|
||||
AppMentioned(CodexAppMentionedEventRequest),
|
||||
AppUsed(CodexAppUsedEventRequest),
|
||||
Compaction(Box<CodexCompactionEventRequest>),
|
||||
TurnEvent(Box<CodexTurnEventRequest>),
|
||||
TurnSteer(CodexTurnSteerEventRequest),
|
||||
PluginUsed(CodexPluginUsedEventRequest),
|
||||
PluginInstalled(CodexPluginEventRequest),
|
||||
PluginUninstalled(CodexPluginEventRequest),
|
||||
@@ -330,6 +329,84 @@ pub(crate) struct CodexCompactionEventRequest {
|
||||
pub(crate) event_params: CodexCompactionEventParams,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct CodexTurnEventParams {
|
||||
pub(crate) thread_id: String,
|
||||
pub(crate) turn_id: String,
|
||||
// TODO(rhan-oai): Populate once queued/default submission type is plumbed from
|
||||
// the turn/start callsites instead of always being reported as None.
|
||||
pub(crate) submission_type: Option<TurnSubmissionType>,
|
||||
pub(crate) app_server_client: CodexAppServerClientMetadata,
|
||||
pub(crate) runtime: CodexRuntimeMetadata,
|
||||
pub(crate) ephemeral: bool,
|
||||
pub(crate) thread_source: Option<String>,
|
||||
pub(crate) initialization_mode: ThreadInitializationMode,
|
||||
pub(crate) subagent_source: Option<String>,
|
||||
pub(crate) parent_thread_id: Option<String>,
|
||||
pub(crate) model: Option<String>,
|
||||
pub(crate) model_provider: String,
|
||||
pub(crate) sandbox_policy: Option<&'static str>,
|
||||
pub(crate) reasoning_effort: Option<String>,
|
||||
pub(crate) reasoning_summary: Option<String>,
|
||||
pub(crate) service_tier: String,
|
||||
pub(crate) approval_policy: String,
|
||||
pub(crate) approvals_reviewer: String,
|
||||
pub(crate) sandbox_network_access: bool,
|
||||
pub(crate) collaboration_mode: Option<&'static str>,
|
||||
pub(crate) personality: Option<String>,
|
||||
pub(crate) num_input_images: usize,
|
||||
pub(crate) is_first_turn: bool,
|
||||
pub(crate) status: Option<TurnStatus>,
|
||||
pub(crate) turn_error: Option<CodexErrorInfo>,
|
||||
pub(crate) steer_count: Option<usize>,
|
||||
// TODO(rhan-oai): Populate these once tool-call accounting is emitted from
|
||||
// core; the schema is reserved but these fields are currently always None.
|
||||
pub(crate) total_tool_call_count: Option<usize>,
|
||||
pub(crate) shell_command_count: Option<usize>,
|
||||
pub(crate) file_change_count: Option<usize>,
|
||||
pub(crate) mcp_tool_call_count: Option<usize>,
|
||||
pub(crate) dynamic_tool_call_count: Option<usize>,
|
||||
pub(crate) subagent_tool_call_count: Option<usize>,
|
||||
pub(crate) web_search_count: Option<usize>,
|
||||
pub(crate) image_generation_count: Option<usize>,
|
||||
pub(crate) input_tokens: Option<i64>,
|
||||
pub(crate) cached_input_tokens: Option<i64>,
|
||||
pub(crate) output_tokens: Option<i64>,
|
||||
pub(crate) reasoning_output_tokens: Option<i64>,
|
||||
pub(crate) total_tokens: Option<i64>,
|
||||
pub(crate) duration_ms: Option<u64>,
|
||||
pub(crate) started_at: Option<u64>,
|
||||
pub(crate) completed_at: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct CodexTurnEventRequest {
|
||||
pub(crate) event_type: &'static str,
|
||||
pub(crate) event_params: CodexTurnEventParams,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct CodexTurnSteerEventParams {
|
||||
pub(crate) thread_id: String,
|
||||
pub(crate) expected_turn_id: Option<String>,
|
||||
pub(crate) accepted_turn_id: Option<String>,
|
||||
pub(crate) app_server_client: CodexAppServerClientMetadata,
|
||||
pub(crate) runtime: CodexRuntimeMetadata,
|
||||
pub(crate) thread_source: Option<String>,
|
||||
pub(crate) subagent_source: Option<String>,
|
||||
pub(crate) parent_thread_id: Option<String>,
|
||||
pub(crate) num_input_images: usize,
|
||||
pub(crate) result: TurnSteerResult,
|
||||
pub(crate) rejection_reason: Option<TurnSteerRejectionReason>,
|
||||
pub(crate) created_at: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct CodexTurnSteerEventRequest {
|
||||
pub(crate) event_type: &'static str,
|
||||
pub(crate) event_params: CodexTurnSteerEventParams,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct CodexPluginMetadata {
|
||||
pub(crate) plugin_id: Option<String>,
|
||||
@@ -452,14 +529,6 @@ pub(crate) fn codex_plugin_used_metadata(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn thread_source_name(thread_source: &SessionSource) -> Option<&'static str> {
|
||||
match thread_source {
|
||||
SessionSource::Cli | SessionSource::VSCode | SessionSource::Exec => Some("user"),
|
||||
SessionSource::SubAgent(_) => Some("subagent"),
|
||||
SessionSource::Mcp | SessionSource::Custom(_) | SessionSource::Unknown => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn current_runtime_metadata() -> CodexRuntimeMetadata {
|
||||
let os_info = os_info::get();
|
||||
CodexRuntimeMetadata {
|
||||
|
||||
@@ -4,11 +4,22 @@ use crate::events::GuardianReviewEventParams;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::ClientResponse;
|
||||
use codex_app_server_protocol::InitializeParams;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_plugin::PluginTelemetryMetadata;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use serde::Serialize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -31,6 +42,126 @@ pub fn build_track_events_context(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TurnSubmissionType {
|
||||
Default,
|
||||
Queued,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TurnResolvedConfigFact {
|
||||
pub turn_id: String,
|
||||
pub thread_id: String,
|
||||
pub num_input_images: usize,
|
||||
pub submission_type: Option<TurnSubmissionType>,
|
||||
pub ephemeral: bool,
|
||||
pub session_source: SessionSource,
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
pub sandbox_policy: SandboxPolicy,
|
||||
pub reasoning_effort: Option<ReasoningEffort>,
|
||||
pub reasoning_summary: Option<ReasoningSummary>,
|
||||
pub service_tier: Option<ServiceTier>,
|
||||
pub approval_policy: AskForApproval,
|
||||
pub approvals_reviewer: ApprovalsReviewer,
|
||||
pub sandbox_network_access: bool,
|
||||
pub collaboration_mode: ModeKind,
|
||||
pub personality: Option<Personality>,
|
||||
pub is_first_turn: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ThreadInitializationMode {
|
||||
New,
|
||||
Forked,
|
||||
Resumed,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TurnTokenUsageFact {
|
||||
pub turn_id: String,
|
||||
pub thread_id: String,
|
||||
pub token_usage: TokenUsage,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TurnStatus {
|
||||
Completed,
|
||||
Failed,
|
||||
Interrupted,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TurnSteerResult {
|
||||
Accepted,
|
||||
Rejected,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TurnSteerRejectionReason {
|
||||
NoActiveTurn,
|
||||
ExpectedTurnMismatch,
|
||||
NonSteerableReview,
|
||||
NonSteerableCompact,
|
||||
EmptyInput,
|
||||
InputTooLarge,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CodexTurnSteerEvent {
|
||||
pub expected_turn_id: Option<String>,
|
||||
pub accepted_turn_id: Option<String>,
|
||||
pub num_input_images: usize,
|
||||
pub result: TurnSteerResult,
|
||||
pub rejection_reason: Option<TurnSteerRejectionReason>,
|
||||
pub created_at: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum AnalyticsJsonRpcError {
|
||||
TurnSteer(TurnSteerRequestError),
|
||||
Input(InputError),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TurnSteerRequestError {
|
||||
NoActiveTurn,
|
||||
ExpectedTurnMismatch,
|
||||
NonSteerableReview,
|
||||
NonSteerableCompact,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum InputError {
|
||||
Empty,
|
||||
TooLarge,
|
||||
}
|
||||
|
||||
impl From<TurnSteerRequestError> for TurnSteerRejectionReason {
|
||||
fn from(error: TurnSteerRequestError) -> Self {
|
||||
match error {
|
||||
TurnSteerRequestError::NoActiveTurn => Self::NoActiveTurn,
|
||||
TurnSteerRequestError::ExpectedTurnMismatch => Self::ExpectedTurnMismatch,
|
||||
TurnSteerRequestError::NonSteerableReview => Self::NonSteerableReview,
|
||||
TurnSteerRequestError::NonSteerableCompact => Self::NonSteerableCompact,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InputError> for TurnSteerRejectionReason {
|
||||
fn from(error: InputError) -> Self {
|
||||
match error {
|
||||
InputError::Empty => Self::EmptyInput,
|
||||
InputError::TooLarge => Self::InputTooLarge,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SkillInvocation {
|
||||
pub skill_name: String,
|
||||
@@ -146,6 +277,12 @@ pub(crate) enum AnalyticsFact {
|
||||
connection_id: u64,
|
||||
response: Box<ClientResponse>,
|
||||
},
|
||||
ErrorResponse {
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
error: JSONRPCErrorError,
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
},
|
||||
Notification(Box<ServerNotification>),
|
||||
// Facts that do not naturally exist on the app-server protocol surface, or
|
||||
// would require non-trivial protocol reshaping on this branch.
|
||||
@@ -156,6 +293,8 @@ pub(crate) enum CustomAnalyticsFact {
|
||||
SubAgentThreadStarted(SubAgentThreadStartedInput),
|
||||
Compaction(Box<CodexCompactionEvent>),
|
||||
GuardianReview(Box<GuardianReviewEventParams>),
|
||||
TurnResolvedConfig(Box<TurnResolvedConfigFact>),
|
||||
TurnTokenUsage(Box<TurnTokenUsageFact>),
|
||||
SkillInvoked(SkillInvokedInput),
|
||||
AppMentioned(AppMentionedInput),
|
||||
AppUsed(AppUsedInput),
|
||||
|
||||
@@ -3,6 +3,9 @@ mod events;
|
||||
mod facts;
|
||||
mod reducer;
|
||||
|
||||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
pub use client::AnalyticsEventsClient;
|
||||
pub use events::AppServerRpcTransport;
|
||||
pub use events::GuardianApprovalRequestSource;
|
||||
@@ -16,19 +19,36 @@ pub use events::GuardianReviewSessionKind;
|
||||
pub use events::GuardianReviewTerminalStatus;
|
||||
pub use events::GuardianReviewUserAuthorization;
|
||||
pub use events::GuardianReviewedAction;
|
||||
pub use facts::AnalyticsJsonRpcError;
|
||||
pub use facts::AppInvocation;
|
||||
pub use facts::CodexCompactionEvent;
|
||||
pub use facts::CodexTurnSteerEvent;
|
||||
pub use facts::CompactionImplementation;
|
||||
pub use facts::CompactionPhase;
|
||||
pub use facts::CompactionReason;
|
||||
pub use facts::CompactionStatus;
|
||||
pub use facts::CompactionStrategy;
|
||||
pub use facts::CompactionTrigger;
|
||||
pub use facts::InputError;
|
||||
pub use facts::InvocationType;
|
||||
pub use facts::SkillInvocation;
|
||||
pub use facts::SubAgentThreadStartedInput;
|
||||
pub use facts::ThreadInitializationMode;
|
||||
pub use facts::TrackEventsContext;
|
||||
pub use facts::TurnResolvedConfigFact;
|
||||
pub use facts::TurnStatus;
|
||||
pub use facts::TurnSteerRejectionReason;
|
||||
pub use facts::TurnSteerRequestError;
|
||||
pub use facts::TurnSteerResult;
|
||||
pub use facts::TurnTokenUsageFact;
|
||||
pub use facts::build_track_events_context;
|
||||
|
||||
#[cfg(test)]
|
||||
mod analytics_client_tests;
|
||||
|
||||
pub fn now_unix_seconds() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
@@ -6,12 +6,15 @@ use crate::events::CodexCompactionEventRequest;
|
||||
use crate::events::CodexPluginEventRequest;
|
||||
use crate::events::CodexPluginUsedEventRequest;
|
||||
use crate::events::CodexRuntimeMetadata;
|
||||
use crate::events::CodexTurnEventParams;
|
||||
use crate::events::CodexTurnEventRequest;
|
||||
use crate::events::CodexTurnSteerEventParams;
|
||||
use crate::events::CodexTurnSteerEventRequest;
|
||||
use crate::events::GuardianReviewEventParams;
|
||||
use crate::events::GuardianReviewEventPayload;
|
||||
use crate::events::GuardianReviewEventRequest;
|
||||
use crate::events::SkillInvocationEventParams;
|
||||
use crate::events::SkillInvocationEventRequest;
|
||||
use crate::events::ThreadInitializationMode;
|
||||
use crate::events::ThreadInitializedEvent;
|
||||
use crate::events::ThreadInitializedEventParams;
|
||||
use crate::events::TrackEventRequest;
|
||||
@@ -23,8 +26,8 @@ use crate::events::plugin_state_event_type;
|
||||
use crate::events::subagent_parent_thread_id;
|
||||
use crate::events::subagent_source_name;
|
||||
use crate::events::subagent_thread_started_event_request;
|
||||
use crate::events::thread_source_name;
|
||||
use crate::facts::AnalyticsFact;
|
||||
use crate::facts::AnalyticsJsonRpcError;
|
||||
use crate::facts::AppMentionedInput;
|
||||
use crate::facts::AppUsedInput;
|
||||
use crate::facts::CodexCompactionEvent;
|
||||
@@ -34,19 +37,39 @@ use crate::facts::PluginStateChangedInput;
|
||||
use crate::facts::PluginUsedInput;
|
||||
use crate::facts::SkillInvokedInput;
|
||||
use crate::facts::SubAgentThreadStartedInput;
|
||||
use crate::facts::ThreadInitializationMode;
|
||||
use crate::facts::TurnResolvedConfigFact;
|
||||
use crate::facts::TurnStatus;
|
||||
use crate::facts::TurnSteerRejectionReason;
|
||||
use crate::facts::TurnSteerResult;
|
||||
use crate::facts::TurnTokenUsageFact;
|
||||
use crate::now_unix_seconds;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::ClientResponse;
|
||||
use codex_app_server_protocol::CodexErrorInfo;
|
||||
use codex_app_server_protocol::InitializeParams;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_app_server_protocol::TurnSteerResponse;
|
||||
use codex_app_server_protocol::UserInput;
|
||||
use codex_git_utils::collect_git_info;
|
||||
use codex_git_utils::get_git_repo_root;
|
||||
use codex_login::default_client::originator;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SkillScope;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use sha1::Digest;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct AnalyticsReducer {
|
||||
requests: HashMap<(u64, RequestId), RequestState>,
|
||||
turns: HashMap<String, TurnState>,
|
||||
connections: HashMap<u64, ConnectionState>,
|
||||
thread_connections: HashMap<String, u64>,
|
||||
thread_metadata: HashMap<String, ThreadMetadataState>,
|
||||
@@ -60,12 +83,16 @@ struct ConnectionState {
|
||||
#[derive(Clone)]
|
||||
struct ThreadMetadataState {
|
||||
thread_source: Option<&'static str>,
|
||||
initialization_mode: ThreadInitializationMode,
|
||||
subagent_source: Option<String>,
|
||||
parent_thread_id: Option<String>,
|
||||
}
|
||||
|
||||
impl ThreadMetadataState {
|
||||
fn from_session_source(session_source: &SessionSource) -> Self {
|
||||
fn from_thread_metadata(
|
||||
session_source: &SessionSource,
|
||||
initialization_mode: ThreadInitializationMode,
|
||||
) -> Self {
|
||||
let (subagent_source, parent_thread_id) = match session_source {
|
||||
SessionSource::SubAgent(subagent_source) => (
|
||||
Some(subagent_source_name(subagent_source)),
|
||||
@@ -79,13 +106,50 @@ impl ThreadMetadataState {
|
||||
| SessionSource::Unknown => (None, None),
|
||||
};
|
||||
Self {
|
||||
thread_source: thread_source_name(session_source),
|
||||
thread_source: session_source.thread_source_name(),
|
||||
initialization_mode,
|
||||
subagent_source,
|
||||
parent_thread_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum RequestState {
|
||||
TurnStart(PendingTurnStartState),
|
||||
TurnSteer(PendingTurnSteerState),
|
||||
}
|
||||
|
||||
struct PendingTurnStartState {
|
||||
thread_id: String,
|
||||
num_input_images: usize,
|
||||
}
|
||||
|
||||
struct PendingTurnSteerState {
|
||||
thread_id: String,
|
||||
expected_turn_id: String,
|
||||
num_input_images: usize,
|
||||
created_at: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct CompletedTurnState {
|
||||
status: Option<TurnStatus>,
|
||||
turn_error: Option<CodexErrorInfo>,
|
||||
completed_at: u64,
|
||||
duration_ms: Option<u64>,
|
||||
}
|
||||
|
||||
struct TurnState {
|
||||
connection_id: Option<u64>,
|
||||
thread_id: Option<String>,
|
||||
num_input_images: Option<usize>,
|
||||
resolved_config: Option<TurnResolvedConfigFact>,
|
||||
started_at: Option<u64>,
|
||||
token_usage: Option<TokenUsage>,
|
||||
completed: Option<CompletedTurnState>,
|
||||
steer_count: usize,
|
||||
}
|
||||
|
||||
impl AnalyticsReducer {
|
||||
pub(crate) async fn ingest(&mut self, input: AnalyticsFact, out: &mut Vec<TrackEventRequest>) {
|
||||
match input {
|
||||
@@ -105,17 +169,29 @@ impl AnalyticsReducer {
|
||||
);
|
||||
}
|
||||
AnalyticsFact::Request {
|
||||
connection_id: _connection_id,
|
||||
request_id: _request_id,
|
||||
request: _request,
|
||||
} => {}
|
||||
connection_id,
|
||||
request_id,
|
||||
request,
|
||||
} => {
|
||||
self.ingest_request(connection_id, request_id, *request);
|
||||
}
|
||||
AnalyticsFact::Response {
|
||||
connection_id,
|
||||
response,
|
||||
} => {
|
||||
self.ingest_response(connection_id, *response, out);
|
||||
}
|
||||
AnalyticsFact::Notification(_notification) => {}
|
||||
AnalyticsFact::ErrorResponse {
|
||||
connection_id,
|
||||
request_id,
|
||||
error: _,
|
||||
error_type,
|
||||
} => {
|
||||
self.ingest_error_response(connection_id, request_id, error_type, out);
|
||||
}
|
||||
AnalyticsFact::Notification(notification) => {
|
||||
self.ingest_notification(*notification, out);
|
||||
}
|
||||
AnalyticsFact::Custom(input) => match input {
|
||||
CustomAnalyticsFact::SubAgentThreadStarted(input) => {
|
||||
self.ingest_subagent_thread_started(input, out);
|
||||
@@ -126,6 +202,12 @@ impl AnalyticsReducer {
|
||||
CustomAnalyticsFact::GuardianReview(input) => {
|
||||
self.ingest_guardian_review(*input, out);
|
||||
}
|
||||
CustomAnalyticsFact::TurnResolvedConfig(input) => {
|
||||
self.ingest_turn_resolved_config(*input, out);
|
||||
}
|
||||
CustomAnalyticsFact::TurnTokenUsage(input) => {
|
||||
self.ingest_turn_token_usage(*input, out);
|
||||
}
|
||||
CustomAnalyticsFact::SkillInvoked(input) => {
|
||||
self.ingest_skill_invoked(input, out).await;
|
||||
}
|
||||
@@ -216,6 +298,82 @@ impl AnalyticsReducer {
|
||||
)));
|
||||
}
|
||||
|
||||
fn ingest_request(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
request: ClientRequest,
|
||||
) {
|
||||
match request {
|
||||
ClientRequest::TurnStart { params, .. } => {
|
||||
self.requests.insert(
|
||||
(connection_id, request_id),
|
||||
RequestState::TurnStart(PendingTurnStartState {
|
||||
thread_id: params.thread_id,
|
||||
num_input_images: num_input_images(¶ms.input),
|
||||
}),
|
||||
);
|
||||
}
|
||||
ClientRequest::TurnSteer { params, .. } => {
|
||||
self.requests.insert(
|
||||
(connection_id, request_id),
|
||||
RequestState::TurnSteer(PendingTurnSteerState {
|
||||
thread_id: params.thread_id,
|
||||
expected_turn_id: params.expected_turn_id,
|
||||
num_input_images: num_input_images(¶ms.input),
|
||||
created_at: now_unix_seconds(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn ingest_turn_resolved_config(
|
||||
&mut self,
|
||||
input: TurnResolvedConfigFact,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let turn_id = input.turn_id.clone();
|
||||
let thread_id = input.thread_id.clone();
|
||||
let num_input_images = input.num_input_images;
|
||||
let turn_state = self.turns.entry(turn_id.clone()).or_insert(TurnState {
|
||||
connection_id: None,
|
||||
thread_id: None,
|
||||
num_input_images: None,
|
||||
resolved_config: None,
|
||||
started_at: None,
|
||||
token_usage: None,
|
||||
completed: None,
|
||||
steer_count: 0,
|
||||
});
|
||||
turn_state.thread_id = Some(thread_id);
|
||||
turn_state.num_input_images = Some(num_input_images);
|
||||
turn_state.resolved_config = Some(input);
|
||||
self.maybe_emit_turn_event(&turn_id, out);
|
||||
}
|
||||
|
||||
fn ingest_turn_token_usage(
|
||||
&mut self,
|
||||
input: TurnTokenUsageFact,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let turn_id = input.turn_id.clone();
|
||||
let turn_state = self.turns.entry(turn_id.clone()).or_insert(TurnState {
|
||||
connection_id: None,
|
||||
thread_id: None,
|
||||
num_input_images: None,
|
||||
resolved_config: None,
|
||||
started_at: None,
|
||||
token_usage: None,
|
||||
completed: None,
|
||||
steer_count: 0,
|
||||
});
|
||||
turn_state.thread_id = Some(input.thread_id);
|
||||
turn_state.token_usage = Some(input.token_usage);
|
||||
self.maybe_emit_turn_event(&turn_id, out);
|
||||
}
|
||||
|
||||
async fn ingest_skill_invoked(
|
||||
&mut self,
|
||||
input: SkillInvokedInput,
|
||||
@@ -316,30 +474,193 @@ impl AnalyticsReducer {
|
||||
response: ClientResponse,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let (thread, model, initialization_mode) = match response {
|
||||
ClientResponse::ThreadStart { response, .. } => (
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::New,
|
||||
),
|
||||
ClientResponse::ThreadResume { response, .. } => (
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::Resumed,
|
||||
),
|
||||
ClientResponse::ThreadFork { response, .. } => (
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::Forked,
|
||||
),
|
||||
_ => return,
|
||||
match response {
|
||||
ClientResponse::ThreadStart { response, .. } => {
|
||||
self.emit_thread_initialized(
|
||||
connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::New,
|
||||
out,
|
||||
);
|
||||
}
|
||||
ClientResponse::ThreadResume { response, .. } => {
|
||||
self.emit_thread_initialized(
|
||||
connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::Resumed,
|
||||
out,
|
||||
);
|
||||
}
|
||||
ClientResponse::ThreadFork { response, .. } => {
|
||||
self.emit_thread_initialized(
|
||||
connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::Forked,
|
||||
out,
|
||||
);
|
||||
}
|
||||
ClientResponse::TurnStart {
|
||||
request_id,
|
||||
response,
|
||||
} => {
|
||||
let turn_id = response.turn.id;
|
||||
let Some(RequestState::TurnStart(pending_request)) =
|
||||
self.requests.remove(&(connection_id, request_id))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let turn_state = self.turns.entry(turn_id.clone()).or_insert(TurnState {
|
||||
connection_id: None,
|
||||
thread_id: None,
|
||||
num_input_images: None,
|
||||
resolved_config: None,
|
||||
started_at: None,
|
||||
token_usage: None,
|
||||
completed: None,
|
||||
steer_count: 0,
|
||||
});
|
||||
turn_state.connection_id = Some(connection_id);
|
||||
turn_state.thread_id = Some(pending_request.thread_id);
|
||||
turn_state.num_input_images = Some(pending_request.num_input_images);
|
||||
self.maybe_emit_turn_event(&turn_id, out);
|
||||
}
|
||||
ClientResponse::TurnSteer {
|
||||
request_id,
|
||||
response,
|
||||
} => {
|
||||
self.ingest_turn_steer_response(connection_id, request_id, response, out);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn ingest_error_response(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let Some(request) = self.requests.remove(&(connection_id, request_id)) else {
|
||||
return;
|
||||
};
|
||||
self.ingest_request_error_response(connection_id, request, error_type, out);
|
||||
}
|
||||
|
||||
fn ingest_request_error_response(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
request: RequestState,
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
match request {
|
||||
RequestState::TurnStart(_) => {}
|
||||
RequestState::TurnSteer(pending_request) => {
|
||||
self.ingest_turn_steer_error_response(
|
||||
connection_id,
|
||||
pending_request,
|
||||
error_type,
|
||||
out,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ingest_turn_steer_error_response(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
pending_request: PendingTurnSteerState,
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
self.emit_turn_steer_event(
|
||||
connection_id,
|
||||
pending_request,
|
||||
/*accepted_turn_id*/ None,
|
||||
TurnSteerResult::Rejected,
|
||||
rejection_reason_from_error_type(error_type),
|
||||
out,
|
||||
);
|
||||
}
|
||||
|
||||
fn ingest_notification(
|
||||
&mut self,
|
||||
notification: ServerNotification,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
match notification {
|
||||
ServerNotification::TurnStarted(notification) => {
|
||||
let turn_state = self.turns.entry(notification.turn.id).or_insert(TurnState {
|
||||
connection_id: None,
|
||||
thread_id: None,
|
||||
num_input_images: None,
|
||||
resolved_config: None,
|
||||
started_at: None,
|
||||
token_usage: None,
|
||||
completed: None,
|
||||
steer_count: 0,
|
||||
});
|
||||
turn_state.started_at = notification
|
||||
.turn
|
||||
.started_at
|
||||
.and_then(|started_at| u64::try_from(started_at).ok());
|
||||
}
|
||||
ServerNotification::TurnCompleted(notification) => {
|
||||
let turn_state =
|
||||
self.turns
|
||||
.entry(notification.turn.id.clone())
|
||||
.or_insert(TurnState {
|
||||
connection_id: None,
|
||||
thread_id: None,
|
||||
num_input_images: None,
|
||||
resolved_config: None,
|
||||
started_at: None,
|
||||
token_usage: None,
|
||||
completed: None,
|
||||
steer_count: 0,
|
||||
});
|
||||
turn_state.completed = Some(CompletedTurnState {
|
||||
status: analytics_turn_status(notification.turn.status),
|
||||
turn_error: notification
|
||||
.turn
|
||||
.error
|
||||
.and_then(|error| error.codex_error_info),
|
||||
completed_at: notification
|
||||
.turn
|
||||
.completed_at
|
||||
.and_then(|completed_at| u64::try_from(completed_at).ok())
|
||||
.unwrap_or_default(),
|
||||
duration_ms: notification
|
||||
.turn
|
||||
.duration_ms
|
||||
.and_then(|duration_ms| u64::try_from(duration_ms).ok()),
|
||||
});
|
||||
let turn_id = notification.turn.id;
|
||||
self.maybe_emit_turn_event(&turn_id, out);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_thread_initialized(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
thread: codex_app_server_protocol::Thread,
|
||||
model: String,
|
||||
initialization_mode: ThreadInitializationMode,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let thread_source: SessionSource = thread.source.into();
|
||||
let thread_id = thread.id;
|
||||
let Some(connection_state) = self.connections.get(&connection_id) else {
|
||||
return;
|
||||
};
|
||||
let thread_metadata = ThreadMetadataState::from_session_source(&thread_source);
|
||||
let thread_metadata =
|
||||
ThreadMetadataState::from_thread_metadata(&thread_source, initialization_mode);
|
||||
self.thread_connections
|
||||
.insert(thread_id.clone(), connection_id);
|
||||
self.thread_metadata
|
||||
@@ -403,6 +724,275 @@ impl AnalyticsReducer {
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
||||
fn ingest_turn_steer_response(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
response: TurnSteerResponse,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let Some(RequestState::TurnSteer(pending_request)) =
|
||||
self.requests.remove(&(connection_id, request_id))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Some(turn_state) = self.turns.get_mut(&response.turn_id) {
|
||||
turn_state.steer_count += 1;
|
||||
}
|
||||
self.emit_turn_steer_event(
|
||||
connection_id,
|
||||
pending_request,
|
||||
Some(response.turn_id),
|
||||
TurnSteerResult::Accepted,
|
||||
/*rejection_reason*/ None,
|
||||
out,
|
||||
);
|
||||
}
|
||||
|
||||
fn emit_turn_steer_event(
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
pending_request: PendingTurnSteerState,
|
||||
accepted_turn_id: Option<String>,
|
||||
result: TurnSteerResult,
|
||||
rejection_reason: Option<TurnSteerRejectionReason>,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let Some(connection_state) = self.connections.get(&connection_id) else {
|
||||
return;
|
||||
};
|
||||
let Some(thread_metadata) = self.thread_metadata.get(&pending_request.thread_id) else {
|
||||
tracing::warn!(
|
||||
thread_id = %pending_request.thread_id,
|
||||
"dropping turn steer analytics event: missing thread lifecycle metadata"
|
||||
);
|
||||
return;
|
||||
};
|
||||
out.push(TrackEventRequest::TurnSteer(CodexTurnSteerEventRequest {
|
||||
event_type: "codex_turn_steer_event",
|
||||
event_params: CodexTurnSteerEventParams {
|
||||
thread_id: pending_request.thread_id,
|
||||
expected_turn_id: Some(pending_request.expected_turn_id),
|
||||
accepted_turn_id,
|
||||
app_server_client: connection_state.app_server_client.clone(),
|
||||
runtime: connection_state.runtime.clone(),
|
||||
thread_source: thread_metadata.thread_source.map(str::to_string),
|
||||
subagent_source: thread_metadata.subagent_source.clone(),
|
||||
parent_thread_id: thread_metadata.parent_thread_id.clone(),
|
||||
num_input_images: pending_request.num_input_images,
|
||||
result,
|
||||
rejection_reason,
|
||||
created_at: pending_request.created_at,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
fn maybe_emit_turn_event(&mut self, turn_id: &str, out: &mut Vec<TrackEventRequest>) {
|
||||
let Some(turn_state) = self.turns.get(turn_id) else {
|
||||
return;
|
||||
};
|
||||
if turn_state.thread_id.is_none()
|
||||
|| turn_state.num_input_images.is_none()
|
||||
|| turn_state.resolved_config.is_none()
|
||||
|| turn_state.completed.is_none()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let connection_metadata = turn_state
|
||||
.connection_id
|
||||
.and_then(|connection_id| self.connections.get(&connection_id))
|
||||
.map(|connection_state| {
|
||||
(
|
||||
connection_state.app_server_client.clone(),
|
||||
connection_state.runtime.clone(),
|
||||
)
|
||||
});
|
||||
let Some((app_server_client, runtime)) = connection_metadata else {
|
||||
if let Some(connection_id) = turn_state.connection_id {
|
||||
tracing::warn!(
|
||||
turn_id,
|
||||
connection_id,
|
||||
"dropping turn analytics event: missing connection metadata"
|
||||
);
|
||||
}
|
||||
return;
|
||||
};
|
||||
let Some(thread_id) = turn_state.thread_id.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let Some(thread_metadata) = self.thread_metadata.get(thread_id) else {
|
||||
tracing::warn!(
|
||||
thread_id,
|
||||
turn_id,
|
||||
"dropping turn analytics event: missing thread lifecycle metadata"
|
||||
);
|
||||
return;
|
||||
};
|
||||
out.push(TrackEventRequest::TurnEvent(Box::new(
|
||||
CodexTurnEventRequest {
|
||||
event_type: "codex_turn_event",
|
||||
event_params: codex_turn_event_params(
|
||||
app_server_client,
|
||||
runtime,
|
||||
turn_id.to_string(),
|
||||
turn_state,
|
||||
thread_metadata,
|
||||
),
|
||||
},
|
||||
)));
|
||||
self.turns.remove(turn_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn codex_turn_event_params(
|
||||
app_server_client: CodexAppServerClientMetadata,
|
||||
runtime: CodexRuntimeMetadata,
|
||||
turn_id: String,
|
||||
turn_state: &TurnState,
|
||||
thread_metadata: &ThreadMetadataState,
|
||||
) -> CodexTurnEventParams {
|
||||
let (Some(thread_id), Some(num_input_images), Some(resolved_config), Some(completed)) = (
|
||||
turn_state.thread_id.clone(),
|
||||
turn_state.num_input_images,
|
||||
turn_state.resolved_config.clone(),
|
||||
turn_state.completed.clone(),
|
||||
) else {
|
||||
unreachable!("turn event params require a fully populated turn state");
|
||||
};
|
||||
let started_at = turn_state.started_at;
|
||||
let TurnResolvedConfigFact {
|
||||
turn_id: _resolved_turn_id,
|
||||
thread_id: _resolved_thread_id,
|
||||
num_input_images: _resolved_num_input_images,
|
||||
submission_type,
|
||||
ephemeral,
|
||||
session_source: _session_source,
|
||||
model,
|
||||
model_provider,
|
||||
sandbox_policy,
|
||||
reasoning_effort,
|
||||
reasoning_summary,
|
||||
service_tier,
|
||||
approval_policy,
|
||||
approvals_reviewer,
|
||||
sandbox_network_access,
|
||||
collaboration_mode,
|
||||
personality,
|
||||
is_first_turn,
|
||||
} = resolved_config;
|
||||
let token_usage = turn_state.token_usage.clone();
|
||||
CodexTurnEventParams {
|
||||
thread_id,
|
||||
turn_id,
|
||||
app_server_client,
|
||||
runtime,
|
||||
submission_type,
|
||||
ephemeral,
|
||||
thread_source: thread_metadata.thread_source.map(str::to_string),
|
||||
initialization_mode: thread_metadata.initialization_mode,
|
||||
subagent_source: thread_metadata.subagent_source.clone(),
|
||||
parent_thread_id: thread_metadata.parent_thread_id.clone(),
|
||||
model: Some(model),
|
||||
model_provider,
|
||||
sandbox_policy: Some(sandbox_policy_mode(&sandbox_policy)),
|
||||
reasoning_effort: reasoning_effort.map(|value| value.to_string()),
|
||||
reasoning_summary: reasoning_summary_mode(reasoning_summary),
|
||||
service_tier: service_tier
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|| "default".to_string()),
|
||||
approval_policy: approval_policy.to_string(),
|
||||
approvals_reviewer: approvals_reviewer.to_string(),
|
||||
sandbox_network_access,
|
||||
collaboration_mode: Some(collaboration_mode_mode(collaboration_mode)),
|
||||
personality: personality_mode(personality),
|
||||
num_input_images,
|
||||
is_first_turn,
|
||||
status: completed.status,
|
||||
turn_error: completed.turn_error,
|
||||
steer_count: Some(turn_state.steer_count),
|
||||
total_tool_call_count: None,
|
||||
shell_command_count: None,
|
||||
file_change_count: None,
|
||||
mcp_tool_call_count: None,
|
||||
dynamic_tool_call_count: None,
|
||||
subagent_tool_call_count: None,
|
||||
web_search_count: None,
|
||||
image_generation_count: None,
|
||||
input_tokens: token_usage
|
||||
.as_ref()
|
||||
.map(|token_usage| token_usage.input_tokens),
|
||||
cached_input_tokens: token_usage
|
||||
.as_ref()
|
||||
.map(|token_usage| token_usage.cached_input_tokens),
|
||||
output_tokens: token_usage
|
||||
.as_ref()
|
||||
.map(|token_usage| token_usage.output_tokens),
|
||||
reasoning_output_tokens: token_usage
|
||||
.as_ref()
|
||||
.map(|token_usage| token_usage.reasoning_output_tokens),
|
||||
total_tokens: token_usage
|
||||
.as_ref()
|
||||
.map(|token_usage| token_usage.total_tokens),
|
||||
duration_ms: completed.duration_ms,
|
||||
started_at,
|
||||
completed_at: Some(completed.completed_at),
|
||||
}
|
||||
}
|
||||
|
||||
fn sandbox_policy_mode(sandbox_policy: &SandboxPolicy) -> &'static str {
|
||||
match sandbox_policy {
|
||||
SandboxPolicy::DangerFullAccess => "full_access",
|
||||
SandboxPolicy::ReadOnly { .. } => "read_only",
|
||||
SandboxPolicy::WorkspaceWrite { .. } => "workspace_write",
|
||||
SandboxPolicy::ExternalSandbox { .. } => "external_sandbox",
|
||||
}
|
||||
}
|
||||
|
||||
fn collaboration_mode_mode(mode: ModeKind) -> &'static str {
|
||||
match mode {
|
||||
ModeKind::Plan => "plan",
|
||||
ModeKind::Default | ModeKind::PairProgramming | ModeKind::Execute => "default",
|
||||
}
|
||||
}
|
||||
|
||||
fn reasoning_summary_mode(summary: Option<ReasoningSummary>) -> Option<String> {
|
||||
match summary {
|
||||
Some(ReasoningSummary::None) | None => None,
|
||||
Some(summary) => Some(summary.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn personality_mode(personality: Option<Personality>) -> Option<String> {
|
||||
match personality {
|
||||
Some(Personality::None) | None => None,
|
||||
Some(personality) => Some(personality.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn analytics_turn_status(status: codex_app_server_protocol::TurnStatus) -> Option<TurnStatus> {
|
||||
match status {
|
||||
codex_app_server_protocol::TurnStatus::Completed => Some(TurnStatus::Completed),
|
||||
codex_app_server_protocol::TurnStatus::Failed => Some(TurnStatus::Failed),
|
||||
codex_app_server_protocol::TurnStatus::Interrupted => Some(TurnStatus::Interrupted),
|
||||
codex_app_server_protocol::TurnStatus::InProgress => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn num_input_images(input: &[UserInput]) -> usize {
|
||||
input
|
||||
.iter()
|
||||
.filter(|item| matches!(item, UserInput::Image { .. } | UserInput::LocalImage { .. }))
|
||||
.count()
|
||||
}
|
||||
|
||||
fn rejection_reason_from_error_type(
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
) -> Option<TurnSteerRejectionReason> {
|
||||
match error_type? {
|
||||
AnalyticsJsonRpcError::TurnSteer(error) => Some(error.into()),
|
||||
AnalyticsJsonRpcError::Input(error) => Some(error.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn skill_id_for_local_skill(
|
||||
|
||||
@@ -605,6 +605,16 @@
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MigrationDetails"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"itemType": {
|
||||
"$ref": "#/definitions/ExternalAgentConfigMigrationItemType"
|
||||
}
|
||||
@@ -620,6 +630,7 @@
|
||||
"AGENTS_MD",
|
||||
"CONFIG",
|
||||
"SKILLS",
|
||||
"PLUGINS",
|
||||
"MCP_SERVER_CONFIG"
|
||||
],
|
||||
"type": "string"
|
||||
@@ -1233,6 +1244,32 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MarketplaceAddParams": {
|
||||
"properties": {
|
||||
"refName": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"sparsePaths": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"McpResourceReadParams": {
|
||||
"properties": {
|
||||
"server": {
|
||||
@@ -1333,6 +1370,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MigrationDetails": {
|
||||
"properties": {
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginsMigration"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"plugins"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
@@ -1452,6 +1503,24 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginsMigration": {
|
||||
"properties": {
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"pluginNames": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"marketplaceName",
|
||||
"pluginNames"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReadOnlyAccess": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -1499,6 +1568,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"RealtimeOutputModality": {
|
||||
"enum": [
|
||||
"text",
|
||||
"audio"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"RealtimeVoice": {
|
||||
"enum": [
|
||||
"alloy",
|
||||
@@ -4025,6 +4101,30 @@
|
||||
"title": "Skills/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"marketplace/add"
|
||||
],
|
||||
"title": "Marketplace/addRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/MarketplaceAddParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Marketplace/addRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
|
||||
+10
-6
@@ -75,7 +75,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -326,11 +326,15 @@
|
||||
]
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"itemId": {
|
||||
"type": "string"
|
||||
|
||||
@@ -608,7 +608,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1180,7 +1180,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/definitions/GuardianCommandSource"
|
||||
@@ -1211,7 +1211,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"program": {
|
||||
"type": "string"
|
||||
@@ -1240,11 +1240,11 @@
|
||||
{
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -1518,7 +1518,7 @@
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
@@ -2461,8 +2461,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -2769,8 +2773,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -3099,7 +3107,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -3132,9 +3140,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
@@ -3384,13 +3396,35 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeTranscriptUpdatedNotification": {
|
||||
"ThreadRealtimeTranscriptDeltaNotification": {
|
||||
"description": "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.",
|
||||
"properties": {
|
||||
"delta": {
|
||||
"description": "Live transcript delta from the realtime event.",
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"delta",
|
||||
"role",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeTranscriptDoneNotification": {
|
||||
"description": "EXPERIMENTAL - final transcript text emitted when realtime completes a transcript part.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"description": "Final complete text for the transcript part.",
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
@@ -4949,20 +4983,40 @@
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/realtime/transcriptUpdated"
|
||||
"thread/realtime/transcript/delta"
|
||||
],
|
||||
"title": "Thread/realtime/transcriptUpdatedNotificationMethod",
|
||||
"title": "Thread/realtime/transcript/deltaNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadRealtimeTranscriptUpdatedNotification"
|
||||
"$ref": "#/definitions/ThreadRealtimeTranscriptDeltaNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/realtime/transcriptUpdatedNotification",
|
||||
"title": "Thread/realtime/transcript/deltaNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/realtime/transcript/done"
|
||||
],
|
||||
"title": "Thread/realtime/transcript/doneNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadRealtimeTranscriptDoneNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/realtime/transcript/doneNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -346,11 +346,15 @@
|
||||
]
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"itemId": {
|
||||
"type": "string"
|
||||
|
||||
@@ -627,6 +627,30 @@
|
||||
"title": "Skills/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/v2/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"marketplace/add"
|
||||
],
|
||||
"title": "Marketplace/addRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/MarketplaceAddParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Marketplace/addRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -1817,11 +1841,15 @@
|
||||
]
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"itemId": {
|
||||
"type": "string"
|
||||
@@ -4355,20 +4383,40 @@
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/realtime/transcriptUpdated"
|
||||
"thread/realtime/transcript/delta"
|
||||
],
|
||||
"title": "Thread/realtime/transcriptUpdatedNotificationMethod",
|
||||
"title": "Thread/realtime/transcript/deltaNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadRealtimeTranscriptUpdatedNotification"
|
||||
"$ref": "#/definitions/v2/ThreadRealtimeTranscriptDeltaNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/realtime/transcriptUpdatedNotification",
|
||||
"title": "Thread/realtime/transcript/deltaNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/realtime/transcript/done"
|
||||
],
|
||||
"title": "Thread/realtime/transcript/doneNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadRealtimeTranscriptDoneNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/realtime/transcript/doneNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
@@ -5906,7 +5954,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -7461,6 +7509,16 @@
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/MigrationDetails"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"itemType": {
|
||||
"$ref": "#/definitions/v2/ExternalAgentConfigMigrationItemType"
|
||||
}
|
||||
@@ -7476,6 +7534,7 @@
|
||||
"AGENTS_MD",
|
||||
"CONFIG",
|
||||
"SKILLS",
|
||||
"PLUGINS",
|
||||
"MCP_SERVER_CONFIG"
|
||||
],
|
||||
"type": "string"
|
||||
@@ -7713,11 +7772,15 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"isDirectory": {
|
||||
"description": "Whether the path currently resolves to a directory.",
|
||||
"description": "Whether the path resolves to a directory.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"isFile": {
|
||||
"description": "Whether the path currently resolves to a regular file.",
|
||||
"description": "Whether the path resolves to a regular file.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"isSymlink": {
|
||||
"description": "Whether the path itself is a symbolic link.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"modifiedAtMs": {
|
||||
@@ -7730,6 +7793,7 @@
|
||||
"createdAtMs",
|
||||
"isDirectory",
|
||||
"isFile",
|
||||
"isSymlink",
|
||||
"modifiedAtMs"
|
||||
],
|
||||
"title": "FsGetMetadataResponse",
|
||||
@@ -8194,7 +8258,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/definitions/v2/GuardianCommandSource"
|
||||
@@ -8225,7 +8289,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"program": {
|
||||
"type": "string"
|
||||
@@ -8254,11 +8318,11 @@
|
||||
{
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -8534,7 +8598,7 @@
|
||||
"$ref": "#/definitions/v2/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
@@ -9055,6 +9119,55 @@
|
||||
"title": "LogoutAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"MarketplaceAddParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"refName": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"sparsePaths": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source"
|
||||
],
|
||||
"title": "MarketplaceAddParams",
|
||||
"type": "object"
|
||||
},
|
||||
"MarketplaceAddResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"alreadyAdded": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"installedRoot": {
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"alreadyAdded",
|
||||
"installedRoot",
|
||||
"marketplaceName"
|
||||
],
|
||||
"title": "MarketplaceAddResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"MarketplaceInterface": {
|
||||
"properties": {
|
||||
"displayName": {
|
||||
@@ -9449,6 +9562,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MigrationDetails": {
|
||||
"properties": {
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/PluginsMigration"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"plugins"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
@@ -9731,12 +9858,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dangerFullAccessDenylistOnly": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dangerouslyAllowAllUnixSockets": {
|
||||
"type": [
|
||||
"boolean",
|
||||
@@ -10377,6 +10498,24 @@
|
||||
"title": "PluginUninstallResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"PluginsMigration": {
|
||||
"properties": {
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"pluginNames": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"marketplaceName",
|
||||
"pluginNames"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ProfileV2": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -10640,6 +10779,13 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"RealtimeOutputModality": {
|
||||
"enum": [
|
||||
"text",
|
||||
"audio"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"RealtimeVoice": {
|
||||
"enum": [
|
||||
"alloy",
|
||||
@@ -12059,15 +12205,23 @@
|
||||
]
|
||||
},
|
||||
"iconLarge": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"iconSmall": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"shortDescription": {
|
||||
@@ -12548,8 +12702,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -12829,13 +12987,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -13093,8 +13251,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -13423,7 +13585,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -13456,9 +13618,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
@@ -14010,14 +14176,38 @@
|
||||
"title": "ThreadRealtimeStartedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeTranscriptUpdatedNotification": {
|
||||
"ThreadRealtimeTranscriptDeltaNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.",
|
||||
"properties": {
|
||||
"delta": {
|
||||
"description": "Live transcript delta from the realtime event.",
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"delta",
|
||||
"role",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadRealtimeTranscriptDeltaNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeTranscriptDoneNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "EXPERIMENTAL - final transcript text emitted when realtime completes a transcript part.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"description": "Final complete text for the transcript part.",
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
@@ -14029,7 +14219,7 @@
|
||||
"text",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadRealtimeTranscriptUpdatedNotification",
|
||||
"title": "ThreadRealtimeTranscriptDoneNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadResumeParams": {
|
||||
@@ -14157,13 +14347,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -14456,13 +14646,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/v2/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
+226
-40
@@ -1209,6 +1209,30 @@
|
||||
"title": "Skills/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"marketplace/add"
|
||||
],
|
||||
"title": "Marketplace/addRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/MarketplaceAddParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Marketplace/addRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -2547,7 +2571,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -4102,6 +4126,16 @@
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MigrationDetails"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"itemType": {
|
||||
"$ref": "#/definitions/ExternalAgentConfigMigrationItemType"
|
||||
}
|
||||
@@ -4117,6 +4151,7 @@
|
||||
"AGENTS_MD",
|
||||
"CONFIG",
|
||||
"SKILLS",
|
||||
"PLUGINS",
|
||||
"MCP_SERVER_CONFIG"
|
||||
],
|
||||
"type": "string"
|
||||
@@ -4354,11 +4389,15 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"isDirectory": {
|
||||
"description": "Whether the path currently resolves to a directory.",
|
||||
"description": "Whether the path resolves to a directory.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"isFile": {
|
||||
"description": "Whether the path currently resolves to a regular file.",
|
||||
"description": "Whether the path resolves to a regular file.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"isSymlink": {
|
||||
"description": "Whether the path itself is a symbolic link.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"modifiedAtMs": {
|
||||
@@ -4371,6 +4410,7 @@
|
||||
"createdAtMs",
|
||||
"isDirectory",
|
||||
"isFile",
|
||||
"isSymlink",
|
||||
"modifiedAtMs"
|
||||
],
|
||||
"title": "FsGetMetadataResponse",
|
||||
@@ -4946,7 +4986,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/definitions/GuardianCommandSource"
|
||||
@@ -4977,7 +5017,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"program": {
|
||||
"type": "string"
|
||||
@@ -5006,11 +5046,11 @@
|
||||
{
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -5286,7 +5326,7 @@
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
@@ -5851,6 +5891,55 @@
|
||||
"title": "LogoutAccountResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"MarketplaceAddParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"refName": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"sparsePaths": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source"
|
||||
],
|
||||
"title": "MarketplaceAddParams",
|
||||
"type": "object"
|
||||
},
|
||||
"MarketplaceAddResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"alreadyAdded": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"installedRoot": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"alreadyAdded",
|
||||
"installedRoot",
|
||||
"marketplaceName"
|
||||
],
|
||||
"title": "MarketplaceAddResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"MarketplaceInterface": {
|
||||
"properties": {
|
||||
"displayName": {
|
||||
@@ -6245,6 +6334,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MigrationDetails": {
|
||||
"properties": {
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginsMigration"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"plugins"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ModeKind": {
|
||||
"description": "Initial collaboration mode to use when the TUI starts.",
|
||||
"enum": [
|
||||
@@ -6527,12 +6630,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dangerFullAccessDenylistOnly": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dangerouslyAllowAllUnixSockets": {
|
||||
"type": [
|
||||
"boolean",
|
||||
@@ -7173,6 +7270,24 @@
|
||||
"title": "PluginUninstallResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"PluginsMigration": {
|
||||
"properties": {
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"pluginNames": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"marketplaceName",
|
||||
"pluginNames"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ProfileV2": {
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
@@ -7436,6 +7551,13 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"RealtimeOutputModality": {
|
||||
"enum": [
|
||||
"text",
|
||||
"audio"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"RealtimeVoice": {
|
||||
"enum": [
|
||||
"alloy",
|
||||
@@ -9605,20 +9727,40 @@
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/realtime/transcriptUpdated"
|
||||
"thread/realtime/transcript/delta"
|
||||
],
|
||||
"title": "Thread/realtime/transcriptUpdatedNotificationMethod",
|
||||
"title": "Thread/realtime/transcript/deltaNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadRealtimeTranscriptUpdatedNotification"
|
||||
"$ref": "#/definitions/ThreadRealtimeTranscriptDeltaNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/realtime/transcriptUpdatedNotification",
|
||||
"title": "Thread/realtime/transcript/deltaNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/realtime/transcript/done"
|
||||
],
|
||||
"title": "Thread/realtime/transcript/doneNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadRealtimeTranscriptDoneNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/realtime/transcript/doneNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
@@ -9907,15 +10049,23 @@
|
||||
]
|
||||
},
|
||||
"iconLarge": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"iconSmall": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"shortDescription": {
|
||||
@@ -10396,8 +10546,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -10677,13 +10831,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -10941,8 +11095,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -11271,7 +11429,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -11304,9 +11462,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
@@ -11858,14 +12020,38 @@
|
||||
"title": "ThreadRealtimeStartedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeTranscriptUpdatedNotification": {
|
||||
"ThreadRealtimeTranscriptDeltaNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.",
|
||||
"properties": {
|
||||
"delta": {
|
||||
"description": "Live transcript delta from the realtime event.",
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"delta",
|
||||
"role",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadRealtimeTranscriptDeltaNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadRealtimeTranscriptDoneNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "EXPERIMENTAL - final transcript text emitted when realtime completes a transcript part.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"description": "Final complete text for the transcript part.",
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
@@ -11877,7 +12063,7 @@
|
||||
"text",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadRealtimeTranscriptUpdatedNotification",
|
||||
"title": "ThreadRealtimeTranscriptDoneNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadResumeParams": {
|
||||
@@ -12005,13 +12191,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -12304,13 +12490,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
@@ -151,12 +151,6 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dangerFullAccessDenylistOnly": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dangerouslyAllowAllUnixSockets": {
|
||||
"type": [
|
||||
"boolean",
|
||||
|
||||
@@ -13,6 +13,16 @@
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MigrationDetails"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"itemType": {
|
||||
"$ref": "#/definitions/ExternalAgentConfigMigrationItemType"
|
||||
}
|
||||
@@ -28,9 +38,42 @@
|
||||
"AGENTS_MD",
|
||||
"CONFIG",
|
||||
"SKILLS",
|
||||
"PLUGINS",
|
||||
"MCP_SERVER_CONFIG"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MigrationDetails": {
|
||||
"properties": {
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginsMigration"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"plugins"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginsMigration": {
|
||||
"properties": {
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"pluginNames": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"marketplaceName",
|
||||
"pluginNames"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -13,6 +13,16 @@
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MigrationDetails"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"itemType": {
|
||||
"$ref": "#/definitions/ExternalAgentConfigMigrationItemType"
|
||||
}
|
||||
@@ -28,9 +38,42 @@
|
||||
"AGENTS_MD",
|
||||
"CONFIG",
|
||||
"SKILLS",
|
||||
"PLUGINS",
|
||||
"MCP_SERVER_CONFIG"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MigrationDetails": {
|
||||
"properties": {
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginsMigration"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"plugins"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginsMigration": {
|
||||
"properties": {
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"pluginNames": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"marketplaceName",
|
||||
"pluginNames"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"isDirectory": {
|
||||
"description": "Whether the path currently resolves to a directory.",
|
||||
"description": "Whether the path resolves to a directory.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"isFile": {
|
||||
"description": "Whether the path currently resolves to a regular file.",
|
||||
"description": "Whether the path resolves to a regular file.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"isSymlink": {
|
||||
"description": "Whether the path itself is a symbolic link.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"modifiedAtMs": {
|
||||
@@ -25,6 +29,7 @@
|
||||
"createdAtMs",
|
||||
"isDirectory",
|
||||
"isFile",
|
||||
"isSymlink",
|
||||
"modifiedAtMs"
|
||||
],
|
||||
"title": "FsGetMetadataResponse",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"preToolUse",
|
||||
@@ -103,7 +107,7 @@
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"preToolUse",
|
||||
@@ -103,7 +107,7 @@
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
@@ -78,7 +82,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -665,8 +669,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -995,7 +1003,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1028,9 +1036,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
+8
-4
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AutoReviewDecisionSource": {
|
||||
"description": "[UNSTABLE] Source that produced a terminal guardian approval review decision.",
|
||||
"enum": [
|
||||
@@ -54,7 +58,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/definitions/GuardianCommandSource"
|
||||
@@ -85,7 +89,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"program": {
|
||||
"type": "string"
|
||||
@@ -114,11 +118,11 @@
|
||||
{
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
+8
-4
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"GuardianApprovalReview": {
|
||||
"description": "[UNSTABLE] Temporary guardian approval review payload used by `item/autoApprovalReview/*` notifications. This shape is expected to change soon.",
|
||||
"properties": {
|
||||
@@ -47,7 +51,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/definitions/GuardianCommandSource"
|
||||
@@ -78,7 +82,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"program": {
|
||||
"type": "string"
|
||||
@@ -107,11 +111,11 @@
|
||||
{
|
||||
"properties": {
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"files": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
@@ -78,7 +82,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -665,8 +669,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -995,7 +1003,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1028,9 +1036,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"refName": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"sparsePaths": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source"
|
||||
],
|
||||
"title": "MarketplaceAddParams",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"alreadyAdded": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"installedRoot": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"marketplaceName": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"alreadyAdded",
|
||||
"installedRoot",
|
||||
"marketplaceName"
|
||||
],
|
||||
"title": "MarketplaceAddResponse",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -293,15 +293,23 @@
|
||||
]
|
||||
},
|
||||
"iconLarge": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"iconSmall": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"shortDescription": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
@@ -214,7 +218,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -808,8 +812,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1138,7 +1146,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1171,9 +1179,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -55,15 +55,23 @@
|
||||
]
|
||||
},
|
||||
"iconLarge": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"iconSmall": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"shortDescription": {
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1036,8 +1036,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1322,8 +1326,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1652,7 +1660,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1685,9 +1693,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
@@ -2185,13 +2197,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -217,7 +221,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -794,8 +798,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1080,8 +1088,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1410,7 +1422,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1443,9 +1455,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -217,7 +221,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -794,8 +798,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1080,8 +1088,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1410,7 +1422,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1443,9 +1455,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -217,7 +221,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -794,8 +798,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1080,8 +1088,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1410,7 +1422,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1443,9 +1455,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
+5
-4
@@ -2,10 +2,11 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "EXPERIMENTAL - flat transcript delta emitted whenever realtime transcript text changes.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"delta": {
|
||||
"description": "Live transcript delta from the realtime event.",
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
@@ -13,10 +14,10 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"delta",
|
||||
"role",
|
||||
"text",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadRealtimeTranscriptUpdatedNotification",
|
||||
"title": "ThreadRealtimeTranscriptDeltaNotification",
|
||||
"type": "object"
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "EXPERIMENTAL - final transcript text emitted when realtime completes a transcript part.",
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"description": "Final complete text for the transcript part.",
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"role",
|
||||
"text",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadRealtimeTranscriptDoneNotification",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -279,7 +279,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1036,8 +1036,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1322,8 +1326,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1652,7 +1660,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1685,9 +1693,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
@@ -2185,13 +2197,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -217,7 +221,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -794,8 +798,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1080,8 +1088,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1410,7 +1422,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1443,9 +1455,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1036,8 +1036,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1322,8 +1326,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1652,7 +1660,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1685,9 +1693,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
@@ -2185,13 +2197,13 @@
|
||||
"description": "Reviewer currently used for approval requests on this thread."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"instructionSources": {
|
||||
"default": [],
|
||||
"description": "Instruction source files currently loaded for this thread.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -217,7 +221,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -794,8 +798,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1080,8 +1088,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1410,7 +1422,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1443,9 +1455,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -217,7 +221,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -794,8 +798,12 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "Working directory captured for the thread.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "Working directory captured for the thread."
|
||||
},
|
||||
"ephemeral": {
|
||||
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
||||
@@ -1080,8 +1088,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1410,7 +1422,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1443,9 +1455,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
@@ -214,7 +218,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -808,8 +812,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1138,7 +1146,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1171,9 +1179,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
@@ -214,7 +218,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -808,8 +812,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1138,7 +1146,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1171,9 +1179,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"AbsolutePathBuf": {
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ByteRange": {
|
||||
"properties": {
|
||||
"end": {
|
||||
@@ -214,7 +218,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -808,8 +812,12 @@
|
||||
"type": "array"
|
||||
},
|
||||
"cwd": {
|
||||
"description": "The command's working directory.",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
}
|
||||
],
|
||||
"description": "The command's working directory."
|
||||
},
|
||||
"durationMs": {
|
||||
"description": "The duration of the command execution in milliseconds.",
|
||||
@@ -1138,7 +1146,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -1171,9 +1179,13 @@
|
||||
]
|
||||
},
|
||||
"savedPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -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 RealtimeOutputModality = "text" | "audio";
|
||||
@@ -43,7 +43,8 @@ import type { ThreadRealtimeItemAddedNotification } from "./v2/ThreadRealtimeIte
|
||||
import type { ThreadRealtimeOutputAudioDeltaNotification } from "./v2/ThreadRealtimeOutputAudioDeltaNotification";
|
||||
import type { ThreadRealtimeSdpNotification } from "./v2/ThreadRealtimeSdpNotification";
|
||||
import type { ThreadRealtimeStartedNotification } from "./v2/ThreadRealtimeStartedNotification";
|
||||
import type { ThreadRealtimeTranscriptUpdatedNotification } from "./v2/ThreadRealtimeTranscriptUpdatedNotification";
|
||||
import type { ThreadRealtimeTranscriptDeltaNotification } from "./v2/ThreadRealtimeTranscriptDeltaNotification";
|
||||
import type { ThreadRealtimeTranscriptDoneNotification } from "./v2/ThreadRealtimeTranscriptDoneNotification";
|
||||
import type { ThreadStartedNotification } from "./v2/ThreadStartedNotification";
|
||||
import type { ThreadStatusChangedNotification } from "./v2/ThreadStatusChangedNotification";
|
||||
import type { ThreadTokenUsageUpdatedNotification } from "./v2/ThreadTokenUsageUpdatedNotification";
|
||||
@@ -58,4 +59,4 @@ import type { WindowsWorldWritableWarningNotification } from "./v2/WindowsWorldW
|
||||
/**
|
||||
* Notification sent from the server to the client.
|
||||
*/
|
||||
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "hook/started", "params": HookStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "hook/completed", "params": HookCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/autoApprovalReview/started", "params": ItemGuardianApprovalReviewStartedNotification } | { "method": "item/autoApprovalReview/completed", "params": ItemGuardianApprovalReviewCompletedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "mcpServer/startupStatus/updated", "params": McpServerStatusUpdatedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "fs/changed", "params": FsChangedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/transcriptUpdated", "params": ThreadRealtimeTranscriptUpdatedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/sdp", "params": ThreadRealtimeSdpNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
|
||||
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "hook/started", "params": HookStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "hook/completed", "params": HookCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/autoApprovalReview/started", "params": ItemGuardianApprovalReviewStartedNotification } | { "method": "item/autoApprovalReview/completed", "params": ItemGuardianApprovalReviewCompletedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "mcpServer/startupStatus/updated", "params": McpServerStatusUpdatedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "fs/changed", "params": FsChangedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/transcript/delta", "params": ThreadRealtimeTranscriptDeltaNotification } | { "method": "thread/realtime/transcript/done", "params": ThreadRealtimeTranscriptDoneNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/sdp", "params": ThreadRealtimeSdpNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
|
||||
|
||||
@@ -49,6 +49,7 @@ export type { ParsedCommand } from "./ParsedCommand";
|
||||
export type { Personality } from "./Personality";
|
||||
export type { PlanType } from "./PlanType";
|
||||
export type { RealtimeConversationVersion } from "./RealtimeConversationVersion";
|
||||
export type { RealtimeOutputModality } from "./RealtimeOutputModality";
|
||||
export type { RealtimeVoice } from "./RealtimeVoice";
|
||||
export type { RealtimeVoicesList } from "./RealtimeVoicesList";
|
||||
export type { ReasoningEffort } from "./ReasoningEffort";
|
||||
|
||||
@@ -1,5 +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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
|
||||
export type CommandAction = { "type": "read", command: string, name: string, path: string, } | { "type": "listFiles", command: string, path: string | null, } | { "type": "search", command: string, query: string | null, path: string | null, } | { "type": "unknown", command: string, };
|
||||
export type CommandAction = { "type": "read", command: string, name: string, path: AbsolutePathBuf, } | { "type": "listFiles", command: string, path: string | null, } | { "type": "search", command: string, query: string | null, path: string | null, } | { "type": "unknown", command: string, };
|
||||
|
||||
+2
-1
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { AdditionalPermissionProfile } from "./AdditionalPermissionProfile";
|
||||
import type { CommandAction } from "./CommandAction";
|
||||
import type { CommandExecutionApprovalDecision } from "./CommandExecutionApprovalDecision";
|
||||
@@ -34,7 +35,7 @@ command?: string | null,
|
||||
/**
|
||||
* The command's working directory.
|
||||
*/
|
||||
cwd?: string | null,
|
||||
cwd?: AbsolutePathBuf | null,
|
||||
/**
|
||||
* Best-effort parsed command actions for friendly display.
|
||||
*/
|
||||
|
||||
+2
-1
@@ -2,9 +2,10 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ExternalAgentConfigMigrationItemType } from "./ExternalAgentConfigMigrationItemType";
|
||||
import type { MigrationDetails } from "./MigrationDetails";
|
||||
|
||||
export type ExternalAgentConfigMigrationItem = { itemType: ExternalAgentConfigMigrationItemType, description: string,
|
||||
/**
|
||||
* Null or empty means home-scoped migration; non-empty means repo-scoped migration.
|
||||
*/
|
||||
cwd: string | null, };
|
||||
cwd: string | null, details: MigrationDetails | null, };
|
||||
|
||||
+1
-1
@@ -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 ExternalAgentConfigMigrationItemType = "AGENTS_MD" | "CONFIG" | "SKILLS" | "MCP_SERVER_CONFIG";
|
||||
export type ExternalAgentConfigMigrationItemType = "AGENTS_MD" | "CONFIG" | "SKILLS" | "PLUGINS" | "MCP_SERVER_CONFIG";
|
||||
|
||||
@@ -7,13 +7,17 @@
|
||||
*/
|
||||
export type FsGetMetadataResponse = {
|
||||
/**
|
||||
* Whether the path currently resolves to a directory.
|
||||
* Whether the path resolves to a directory.
|
||||
*/
|
||||
isDirectory: boolean,
|
||||
/**
|
||||
* Whether the path currently resolves to a regular file.
|
||||
* Whether the path resolves to a regular file.
|
||||
*/
|
||||
isFile: boolean,
|
||||
/**
|
||||
* Whether the path itself is a symbolic link.
|
||||
*/
|
||||
isSymlink: boolean,
|
||||
/**
|
||||
* File creation time in Unix milliseconds when available, otherwise `0`.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { GuardianCommandSource } from "./GuardianCommandSource";
|
||||
import type { NetworkApprovalProtocol } from "./NetworkApprovalProtocol";
|
||||
|
||||
export type GuardianApprovalReviewAction = { "type": "command", source: GuardianCommandSource, command: string, cwd: string, } | { "type": "execve", source: GuardianCommandSource, program: string, argv: Array<string>, cwd: string, } | { "type": "applyPatch", cwd: string, files: Array<string>, } | { "type": "networkAccess", target: string, host: string, protocol: NetworkApprovalProtocol, port: number, } | { "type": "mcpToolCall", server: string, toolName: string, connectorId: string | null, connectorName: string | null, toolTitle: string | null, };
|
||||
export type GuardianApprovalReviewAction = { "type": "command", source: GuardianCommandSource, command: string, cwd: AbsolutePathBuf, } | { "type": "execve", source: GuardianCommandSource, program: string, argv: Array<string>, cwd: AbsolutePathBuf, } | { "type": "applyPatch", cwd: AbsolutePathBuf, files: Array<AbsolutePathBuf>, } | { "type": "networkAccess", target: string, host: string, protocol: NetworkApprovalProtocol, port: number, } | { "type": "mcpToolCall", server: string, toolName: string, connectorId: string | null, connectorName: string | null, toolTitle: string | null, };
|
||||
|
||||
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { HookEventName } from "./HookEventName";
|
||||
import type { HookExecutionMode } from "./HookExecutionMode";
|
||||
import type { HookHandlerType } from "./HookHandlerType";
|
||||
@@ -8,4 +9,4 @@ import type { HookOutputEntry } from "./HookOutputEntry";
|
||||
import type { HookRunStatus } from "./HookRunStatus";
|
||||
import type { HookScope } from "./HookScope";
|
||||
|
||||
export type HookRunSummary = { id: string, eventName: HookEventName, handlerType: HookHandlerType, executionMode: HookExecutionMode, scope: HookScope, sourcePath: string, displayOrder: bigint, status: HookRunStatus, statusMessage: string | null, startedAt: bigint, completedAt: bigint | null, durationMs: bigint | null, entries: Array<HookOutputEntry>, };
|
||||
export type HookRunSummary = { id: string, eventName: HookEventName, handlerType: HookHandlerType, executionMode: HookExecutionMode, scope: HookScope, sourcePath: AbsolutePathBuf, displayOrder: bigint, status: HookRunStatus, statusMessage: string | null, startedAt: bigint, completedAt: bigint | null, durationMs: bigint | null, entries: Array<HookOutputEntry>, };
|
||||
|
||||
@@ -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 MarketplaceAddParams = { source: string, refName?: string | null, sparsePaths?: Array<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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
|
||||
export type MarketplaceAddResponse = { marketplaceName: string, installedRoot: AbsolutePathBuf, alreadyAdded: boolean, };
|
||||
@@ -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 { PluginsMigration } from "./PluginsMigration";
|
||||
|
||||
export type MigrationDetails = { plugins: Array<PluginsMigration>, };
|
||||
@@ -29,4 +29,4 @@ unixSockets: { [key in string]?: NetworkUnixSocketPermission } | null,
|
||||
/**
|
||||
* Legacy compatibility view derived from `unix_sockets`.
|
||||
*/
|
||||
allowUnixSockets: Array<string> | null, allowLocalBinding: boolean | null, dangerFullAccessDenylistOnly: boolean | null, };
|
||||
allowUnixSockets: Array<string> | null, allowLocalBinding: boolean | 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 PluginsMigration = { marketplaceName: string, pluginNames: Array<string>, };
|
||||
@@ -1,5 +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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
|
||||
export type SkillInterface = { displayName?: string, shortDescription?: string, iconSmall?: string, iconLarge?: string, brandColor?: string, defaultPrompt?: string, };
|
||||
export type SkillInterface = { displayName?: string, shortDescription?: string, iconSmall?: AbsolutePathBuf, iconLarge?: AbsolutePathBuf, brandColor?: string, defaultPrompt?: string, };
|
||||
|
||||
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { GitInfo } from "./GitInfo";
|
||||
import type { SessionSource } from "./SessionSource";
|
||||
import type { ThreadStatus } from "./ThreadStatus";
|
||||
@@ -42,7 +43,7 @@ path: string | null,
|
||||
/**
|
||||
* Working directory captured for the thread.
|
||||
*/
|
||||
cwd: string,
|
||||
cwd: AbsolutePathBuf,
|
||||
/**
|
||||
* Version of the CLI that created the thread.
|
||||
*/
|
||||
|
||||
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { ReasoningEffort } from "../ReasoningEffort";
|
||||
import type { ServiceTier } from "../ServiceTier";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
@@ -8,11 +9,11 @@ import type { AskForApproval } from "./AskForApproval";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
import type { Thread } from "./Thread";
|
||||
|
||||
export type ThreadForkResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string,
|
||||
export type ThreadForkResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf,
|
||||
/**
|
||||
* Instruction source files currently loaded for this thread.
|
||||
*/
|
||||
instructionSources: Array<string>, approvalPolicy: AskForApproval,
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
||||
/**
|
||||
* Reviewer currently used for approval requests on this thread.
|
||||
*/
|
||||
|
||||
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { MessagePhase } from "../MessagePhase";
|
||||
import type { ReasoningEffort } from "../ReasoningEffort";
|
||||
import type { JsonValue } from "../serde_json/JsonValue";
|
||||
@@ -30,7 +31,7 @@ command: string,
|
||||
/**
|
||||
* The command's working directory.
|
||||
*/
|
||||
cwd: string,
|
||||
cwd: AbsolutePathBuf,
|
||||
/**
|
||||
* Identifier for the underlying PTY process (when available).
|
||||
*/
|
||||
@@ -97,4 +98,4 @@ reasoningEffort: ReasoningEffort | null,
|
||||
/**
|
||||
* Last known status of the target agents, when available.
|
||||
*/
|
||||
agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: string, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, savedPath?: string, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, };
|
||||
agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: AbsolutePathBuf, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, savedPath?: AbsolutePathBuf, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, };
|
||||
|
||||
+5
-1
@@ -6,4 +6,8 @@
|
||||
* EXPERIMENTAL - flat transcript delta emitted whenever realtime
|
||||
* transcript text changes.
|
||||
*/
|
||||
export type ThreadRealtimeTranscriptUpdatedNotification = { threadId: string, role: string, text: string, };
|
||||
export type ThreadRealtimeTranscriptDeltaNotification = { threadId: string, role: string,
|
||||
/**
|
||||
* Live transcript delta from the realtime event.
|
||||
*/
|
||||
delta: string, };
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL - final transcript text emitted when realtime completes
|
||||
* a transcript part.
|
||||
*/
|
||||
export type ThreadRealtimeTranscriptDoneNotification = { threadId: string, role: string,
|
||||
/**
|
||||
* Final complete text for the transcript part.
|
||||
*/
|
||||
text: string, };
|
||||
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { ReasoningEffort } from "../ReasoningEffort";
|
||||
import type { ServiceTier } from "../ServiceTier";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
@@ -8,11 +9,11 @@ import type { AskForApproval } from "./AskForApproval";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
import type { Thread } from "./Thread";
|
||||
|
||||
export type ThreadResumeResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string,
|
||||
export type ThreadResumeResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf,
|
||||
/**
|
||||
* Instruction source files currently loaded for this thread.
|
||||
*/
|
||||
instructionSources: Array<string>, approvalPolicy: AskForApproval,
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
||||
/**
|
||||
* Reviewer currently used for approval requests on this thread.
|
||||
*/
|
||||
|
||||
@@ -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 { AbsolutePathBuf } from "../AbsolutePathBuf";
|
||||
import type { ReasoningEffort } from "../ReasoningEffort";
|
||||
import type { ServiceTier } from "../ServiceTier";
|
||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||
@@ -8,11 +9,11 @@ import type { AskForApproval } from "./AskForApproval";
|
||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||
import type { Thread } from "./Thread";
|
||||
|
||||
export type ThreadStartResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: string,
|
||||
export type ThreadStartResponse = { thread: Thread, model: string, modelProvider: string, serviceTier: ServiceTier | null, cwd: AbsolutePathBuf,
|
||||
/**
|
||||
* Instruction source files currently loaded for this thread.
|
||||
*/
|
||||
instructionSources: Array<string>, approvalPolicy: AskForApproval,
|
||||
instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
||||
/**
|
||||
* Reviewer currently used for approval requests on this thread.
|
||||
*/
|
||||
|
||||
@@ -149,6 +149,8 @@ export type { ListMcpServerStatusResponse } from "./ListMcpServerStatusResponse"
|
||||
export type { LoginAccountParams } from "./LoginAccountParams";
|
||||
export type { LoginAccountResponse } from "./LoginAccountResponse";
|
||||
export type { LogoutAccountResponse } from "./LogoutAccountResponse";
|
||||
export type { MarketplaceAddParams } from "./MarketplaceAddParams";
|
||||
export type { MarketplaceAddResponse } from "./MarketplaceAddResponse";
|
||||
export type { MarketplaceInterface } from "./MarketplaceInterface";
|
||||
export type { MarketplaceLoadErrorInfo } from "./MarketplaceLoadErrorInfo";
|
||||
export type { McpAuthStatus } from "./McpAuthStatus";
|
||||
@@ -196,6 +198,7 @@ export type { McpToolCallStatus } from "./McpToolCallStatus";
|
||||
export type { MemoryCitation } from "./MemoryCitation";
|
||||
export type { MemoryCitationEntry } from "./MemoryCitationEntry";
|
||||
export type { MergeStrategy } from "./MergeStrategy";
|
||||
export type { MigrationDetails } from "./MigrationDetails";
|
||||
export type { Model } from "./Model";
|
||||
export type { ModelAvailabilityNux } from "./ModelAvailabilityNux";
|
||||
export type { ModelListParams } from "./ModelListParams";
|
||||
@@ -234,6 +237,7 @@ export type { PluginSource } from "./PluginSource";
|
||||
export type { PluginSummary } from "./PluginSummary";
|
||||
export type { PluginUninstallParams } from "./PluginUninstallParams";
|
||||
export type { PluginUninstallResponse } from "./PluginUninstallResponse";
|
||||
export type { PluginsMigration } from "./PluginsMigration";
|
||||
export type { ProfileV2 } from "./ProfileV2";
|
||||
export type { RateLimitSnapshot } from "./RateLimitSnapshot";
|
||||
export type { RateLimitWindow } from "./RateLimitWindow";
|
||||
@@ -303,7 +307,8 @@ export type { ThreadRealtimeOutputAudioDeltaNotification } from "./ThreadRealtim
|
||||
export type { ThreadRealtimeSdpNotification } from "./ThreadRealtimeSdpNotification";
|
||||
export type { ThreadRealtimeStartTransport } from "./ThreadRealtimeStartTransport";
|
||||
export type { ThreadRealtimeStartedNotification } from "./ThreadRealtimeStartedNotification";
|
||||
export type { ThreadRealtimeTranscriptUpdatedNotification } from "./ThreadRealtimeTranscriptUpdatedNotification";
|
||||
export type { ThreadRealtimeTranscriptDeltaNotification } from "./ThreadRealtimeTranscriptDeltaNotification";
|
||||
export type { ThreadRealtimeTranscriptDoneNotification } from "./ThreadRealtimeTranscriptDoneNotification";
|
||||
export type { ThreadResumeParams } from "./ThreadResumeParams";
|
||||
export type { ThreadResumeResponse } from "./ThreadResumeResponse";
|
||||
export type { ThreadRollbackParams } from "./ThreadRollbackParams";
|
||||
|
||||
@@ -331,6 +331,10 @@ client_request_definitions! {
|
||||
params: v2::SkillsListParams,
|
||||
response: v2::SkillsListResponse,
|
||||
},
|
||||
MarketplaceAdd => "marketplace/add" {
|
||||
params: v2::MarketplaceAddParams,
|
||||
response: v2::MarketplaceAddResponse,
|
||||
},
|
||||
PluginList => "plugin/list" {
|
||||
params: v2::PluginListParams,
|
||||
response: v2::PluginListResponse,
|
||||
@@ -1022,8 +1026,10 @@ server_notification_definitions! {
|
||||
ThreadRealtimeStarted => "thread/realtime/started" (v2::ThreadRealtimeStartedNotification),
|
||||
#[experimental("thread/realtime/itemAdded")]
|
||||
ThreadRealtimeItemAdded => "thread/realtime/itemAdded" (v2::ThreadRealtimeItemAddedNotification),
|
||||
#[experimental("thread/realtime/transcriptUpdated")]
|
||||
ThreadRealtimeTranscriptUpdated => "thread/realtime/transcriptUpdated" (v2::ThreadRealtimeTranscriptUpdatedNotification),
|
||||
#[experimental("thread/realtime/transcript/delta")]
|
||||
ThreadRealtimeTranscriptDelta => "thread/realtime/transcript/delta" (v2::ThreadRealtimeTranscriptDeltaNotification),
|
||||
#[experimental("thread/realtime/transcript/done")]
|
||||
ThreadRealtimeTranscriptDone => "thread/realtime/transcript/done" (v2::ThreadRealtimeTranscriptDoneNotification),
|
||||
#[experimental("thread/realtime/outputAudio/delta")]
|
||||
ThreadRealtimeOutputAudioDelta => "thread/realtime/outputAudio/delta" (v2::ThreadRealtimeOutputAudioDeltaNotification),
|
||||
#[experimental("thread/realtime/sdp")]
|
||||
@@ -1056,22 +1062,23 @@ mod tests {
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use codex_protocol::protocol::RealtimeConversationVersion;
|
||||
use codex_protocol::protocol::RealtimeOutputModality;
|
||||
use codex_protocol::protocol::RealtimeVoice;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_absolute_path::test_support::PathBufExt;
|
||||
use codex_utils_absolute_path::test_support::test_path_buf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn absolute_path_string(path: &str) -> String {
|
||||
let trimmed = path.trim_start_matches('/');
|
||||
if cfg!(windows) {
|
||||
format!(r"C:\{}", trimmed.replace('/', "\\"))
|
||||
} else {
|
||||
format!("/{trimmed}")
|
||||
}
|
||||
let path = format!("/{}", path.trim_start_matches('/'));
|
||||
test_path_buf(&path).display().to_string()
|
||||
}
|
||||
|
||||
fn absolute_path(path: &str) -> AbsolutePathBuf {
|
||||
AbsolutePathBuf::from_absolute_path(absolute_path_string(path)).expect("absolute path")
|
||||
let path = format!("/{}", path.trim_start_matches('/'));
|
||||
test_path_buf(&path).abs()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1402,7 +1409,7 @@ mod tests {
|
||||
updated_at: 2,
|
||||
status: v2::ThreadStatus::Idle,
|
||||
path: None,
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: absolute_path("/tmp"),
|
||||
cli_version: "0.0.0".to_string(),
|
||||
source: v2::SessionSource::Exec,
|
||||
agent_nickname: None,
|
||||
@@ -1414,8 +1421,8 @@ mod tests {
|
||||
model: "gpt-5".to_string(),
|
||||
model_provider: "openai".to_string(),
|
||||
service_tier: None,
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
instruction_sources: vec![PathBuf::from("/tmp/AGENTS.md")],
|
||||
cwd: absolute_path("/tmp"),
|
||||
instruction_sources: vec![absolute_path("/tmp/AGENTS.md")],
|
||||
approval_policy: v2::AskForApproval::OnFailure,
|
||||
approvals_reviewer: v2::ApprovalsReviewer::User,
|
||||
sandbox: v2::SandboxPolicy::DangerFullAccess,
|
||||
@@ -1442,7 +1449,7 @@ mod tests {
|
||||
"type": "idle"
|
||||
},
|
||||
"path": null,
|
||||
"cwd": "/tmp",
|
||||
"cwd": absolute_path_string("tmp"),
|
||||
"cliVersion": "0.0.0",
|
||||
"source": "exec",
|
||||
"agentNickname": null,
|
||||
@@ -1454,8 +1461,8 @@ mod tests {
|
||||
"model": "gpt-5",
|
||||
"modelProvider": "openai",
|
||||
"serviceTier": null,
|
||||
"cwd": "/tmp",
|
||||
"instructionSources": ["/tmp/AGENTS.md"],
|
||||
"cwd": absolute_path_string("tmp"),
|
||||
"instructionSources": [absolute_path_string("tmp/AGENTS.md")],
|
||||
"approvalPolicy": "on-failure",
|
||||
"approvalsReviewer": "user",
|
||||
"sandbox": {
|
||||
@@ -1784,10 +1791,11 @@ mod tests {
|
||||
request_id: RequestId::Integer(9),
|
||||
params: v2::ThreadRealtimeStartParams {
|
||||
thread_id: "thr_123".to_string(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("You are on a call".to_string())),
|
||||
session_id: Some("sess_456".to_string()),
|
||||
transport: None,
|
||||
voice: Some(codex_protocol::protocol::RealtimeVoice::Marin),
|
||||
voice: Some(RealtimeVoice::Marin),
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
@@ -1796,6 +1804,7 @@ mod tests {
|
||||
"id": 9,
|
||||
"params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"prompt": "You are on a call",
|
||||
"sessionId": "sess_456",
|
||||
"transport": null,
|
||||
@@ -1813,6 +1822,7 @@ mod tests {
|
||||
request_id: RequestId::Integer(9),
|
||||
params: v2::ThreadRealtimeStartParams {
|
||||
thread_id: "thr_123".to_string(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: None,
|
||||
session_id: None,
|
||||
transport: None,
|
||||
@@ -1825,6 +1835,7 @@ mod tests {
|
||||
"id": 9,
|
||||
"params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"sessionId": null,
|
||||
"transport": null,
|
||||
"voice": null
|
||||
@@ -1837,6 +1848,7 @@ mod tests {
|
||||
request_id: RequestId::Integer(9),
|
||||
params: v2::ThreadRealtimeStartParams {
|
||||
thread_id: "thr_123".to_string(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(None),
|
||||
session_id: None,
|
||||
transport: None,
|
||||
@@ -1849,6 +1861,7 @@ mod tests {
|
||||
"id": 9,
|
||||
"params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"prompt": null,
|
||||
"sessionId": null,
|
||||
"transport": null,
|
||||
@@ -1863,6 +1876,7 @@ mod tests {
|
||||
"id": 9,
|
||||
"params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"sessionId": null,
|
||||
"transport": null,
|
||||
"voice": null
|
||||
@@ -1878,6 +1892,7 @@ mod tests {
|
||||
"id": 9,
|
||||
"params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"prompt": null,
|
||||
"sessionId": null,
|
||||
"transport": null,
|
||||
@@ -1962,6 +1977,7 @@ mod tests {
|
||||
request_id: RequestId::Integer(1),
|
||||
params: v2::ThreadRealtimeStartParams {
|
||||
thread_id: "thr_123".to_string(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("You are on a call".to_string())),
|
||||
session_id: None,
|
||||
transport: None,
|
||||
|
||||
@@ -78,7 +78,7 @@ pub fn build_command_execution_approval_request_item(
|
||||
.parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(CommandAction::from)
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, &payload.cwd))
|
||||
.collect(),
|
||||
aggregated_output: None,
|
||||
exit_code: None,
|
||||
@@ -98,7 +98,7 @@ pub fn build_command_execution_begin_item(payload: &ExecCommandBeginEvent) -> Th
|
||||
.parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(CommandAction::from)
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, &payload.cwd))
|
||||
.collect(),
|
||||
aggregated_output: None,
|
||||
exit_code: None,
|
||||
@@ -125,7 +125,7 @@ pub fn build_command_execution_end_item(payload: &ExecCommandEndEvent) -> Thread
|
||||
.parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(CommandAction::from)
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, &payload.cwd))
|
||||
.collect(),
|
||||
aggregated_output,
|
||||
exit_code: Some(payload.exit_code),
|
||||
@@ -179,7 +179,10 @@ pub fn build_item_from_guardian_event(
|
||||
command: command.clone(),
|
||||
}]
|
||||
} else {
|
||||
parsed_cmd.into_iter().map(CommandAction::from).collect()
|
||||
parsed_cmd
|
||||
.into_iter()
|
||||
.map(|parsed| CommandAction::from_core_with_cwd(parsed, cwd))
|
||||
.collect()
|
||||
};
|
||||
Some(ThreadItem::CommandExecution {
|
||||
id: id.clone(),
|
||||
|
||||
@@ -552,7 +552,7 @@ impl ThreadHistoryBuilder {
|
||||
fn handle_view_image_tool_call(&mut self, payload: &ViewImageToolCallEvent) {
|
||||
let item = ThreadItem::ImageView {
|
||||
id: payload.call_id.clone(),
|
||||
path: payload.path.to_string_lossy().into_owned(),
|
||||
path: payload.path.clone(),
|
||||
};
|
||||
self.upsert_item_in_current_turn(item);
|
||||
}
|
||||
@@ -1193,6 +1193,8 @@ mod tests {
|
||||
use codex_protocol::protocol::TurnStartedEvent;
|
||||
use codex_protocol::protocol::UserMessageEvent;
|
||||
use codex_protocol::protocol::WebSearchEndEvent;
|
||||
use codex_utils_absolute_path::test_support::PathBufExt;
|
||||
use codex_utils_absolute_path::test_support::test_path_buf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
@@ -1397,7 +1399,7 @@ mod tests {
|
||||
status: "completed".into(),
|
||||
revised_prompt: Some("final prompt".into()),
|
||||
result: "Zm9v".into(),
|
||||
saved_path: Some("/tmp/ig_123.png".into()),
|
||||
saved_path: Some(test_path_buf("/tmp/ig_123.png").abs()),
|
||||
})),
|
||||
RolloutItem::EventMsg(EventMsg::TurnComplete(TurnCompleteEvent {
|
||||
turn_id: "turn-image".into(),
|
||||
@@ -1431,7 +1433,7 @@ mod tests {
|
||||
status: "completed".into(),
|
||||
revised_prompt: Some("final prompt".into()),
|
||||
result: "Zm9v".into(),
|
||||
saved_path: Some("/tmp/ig_123.png".into()),
|
||||
saved_path: Some(test_path_buf("/tmp/ig_123.png").abs()),
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1786,7 +1788,7 @@ mod tests {
|
||||
process_id: Some("pid-1".into()),
|
||||
turn_id: "turn-1".into(),
|
||||
command: vec!["echo".into(), "hello world".into()],
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
parsed_cmd: vec![ParsedCommand::Unknown {
|
||||
cmd: "echo hello world".into(),
|
||||
}],
|
||||
@@ -1835,7 +1837,7 @@ mod tests {
|
||||
ThreadItem::CommandExecution {
|
||||
id: "exec-1".into(),
|
||||
command: "echo 'hello world'".into(),
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
process_id: Some("pid-1".into()),
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::Completed,
|
||||
@@ -2005,7 +2007,7 @@ mod tests {
|
||||
process_id: Some("pid-2".into()),
|
||||
turn_id: "turn-1".into(),
|
||||
command: vec!["ls".into()],
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
parsed_cmd: vec![ParsedCommand::Unknown { cmd: "ls".into() }],
|
||||
source: ExecCommandSource::Agent,
|
||||
interaction_input: None,
|
||||
@@ -2047,7 +2049,7 @@ mod tests {
|
||||
ThreadItem::CommandExecution {
|
||||
id: "exec-declined".into(),
|
||||
command: "ls".into(),
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
process_id: Some("pid-2".into()),
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::Declined,
|
||||
@@ -2101,7 +2103,7 @@ mod tests {
|
||||
"type": "command",
|
||||
"source": "shell",
|
||||
"command": "rm -rf /tmp/guardian",
|
||||
"cwd": "/tmp",
|
||||
"cwd": test_path_buf("/tmp"),
|
||||
}))
|
||||
.expect("guardian action"),
|
||||
}),
|
||||
@@ -2120,7 +2122,7 @@ mod tests {
|
||||
"type": "command",
|
||||
"source": "shell",
|
||||
"command": "rm -rf /tmp/guardian",
|
||||
"cwd": "/tmp",
|
||||
"cwd": test_path_buf("/tmp"),
|
||||
}))
|
||||
.expect("guardian action"),
|
||||
}),
|
||||
@@ -2138,7 +2140,7 @@ mod tests {
|
||||
ThreadItem::CommandExecution {
|
||||
id: "guardian-exec".into(),
|
||||
command: "rm -rf /tmp/guardian".into(),
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
process_id: None,
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::Declined,
|
||||
@@ -2181,7 +2183,7 @@ mod tests {
|
||||
"source": "shell",
|
||||
"program": "/bin/rm",
|
||||
"argv": ["/usr/bin/rm", "-f", "/tmp/file.sqlite"],
|
||||
"cwd": "/tmp",
|
||||
"cwd": test_path_buf("/tmp"),
|
||||
}))
|
||||
.expect("guardian action"),
|
||||
}),
|
||||
@@ -2199,7 +2201,7 @@ mod tests {
|
||||
ThreadItem::CommandExecution {
|
||||
id: "guardian-execve".into(),
|
||||
command: "/bin/rm -f /tmp/file.sqlite".into(),
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
process_id: None,
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::InProgress,
|
||||
@@ -2251,7 +2253,7 @@ mod tests {
|
||||
process_id: Some("pid-42".into()),
|
||||
turn_id: "turn-a".into(),
|
||||
command: vec!["echo".into(), "done".into()],
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
parsed_cmd: vec![ParsedCommand::Unknown {
|
||||
cmd: "echo done".into(),
|
||||
}],
|
||||
@@ -2288,7 +2290,7 @@ mod tests {
|
||||
ThreadItem::CommandExecution {
|
||||
id: "exec-late".into(),
|
||||
command: "echo done".into(),
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
process_id: Some("pid-42".into()),
|
||||
source: CommandExecutionSource::Agent,
|
||||
status: CommandExecutionStatus::Completed,
|
||||
@@ -2340,7 +2342,7 @@ mod tests {
|
||||
process_id: Some("pid-42".into()),
|
||||
turn_id: "turn-missing".into(),
|
||||
command: vec!["echo".into(), "done".into()],
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
parsed_cmd: vec![ParsedCommand::Unknown {
|
||||
cmd: "echo done".into(),
|
||||
}],
|
||||
|
||||
@@ -74,12 +74,12 @@ use codex_protocol::protocol::RateLimitWindow as CoreRateLimitWindow;
|
||||
use codex_protocol::protocol::ReadOnlyAccess as CoreReadOnlyAccess;
|
||||
use codex_protocol::protocol::RealtimeAudioFrame as CoreRealtimeAudioFrame;
|
||||
use codex_protocol::protocol::RealtimeConversationVersion;
|
||||
use codex_protocol::protocol::RealtimeOutputModality;
|
||||
use codex_protocol::protocol::RealtimeVoice;
|
||||
use codex_protocol::protocol::RealtimeVoicesList;
|
||||
use codex_protocol::protocol::ReviewDecision as CoreReviewDecision;
|
||||
use codex_protocol::protocol::SessionSource as CoreSessionSource;
|
||||
use codex_protocol::protocol::SkillDependencies as CoreSkillDependencies;
|
||||
use codex_protocol::protocol::SkillErrorInfo as CoreSkillErrorInfo;
|
||||
use codex_protocol::protocol::SkillInterface as CoreSkillInterface;
|
||||
use codex_protocol::protocol::SkillMetadata as CoreSkillMetadata;
|
||||
use codex_protocol::protocol::SkillScope as CoreSkillScope;
|
||||
@@ -448,7 +448,7 @@ pub struct HookRunSummary {
|
||||
pub handler_type: HookHandlerType,
|
||||
pub execution_mode: HookExecutionMode,
|
||||
pub scope: HookScope,
|
||||
pub source_path: PathBuf,
|
||||
pub source_path: AbsolutePathBuf,
|
||||
pub display_order: i64,
|
||||
pub status: HookRunStatus,
|
||||
pub status_message: Option<String>,
|
||||
@@ -898,7 +898,6 @@ pub struct NetworkRequirements {
|
||||
/// Legacy compatibility view derived from `unix_sockets`.
|
||||
pub allow_unix_sockets: Option<Vec<String>>,
|
||||
pub allow_local_binding: Option<bool>,
|
||||
pub danger_full_access_denylist_only: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||
@@ -945,11 +944,33 @@ pub enum ExternalAgentConfigMigrationItemType {
|
||||
#[serde(rename = "SKILLS")]
|
||||
#[ts(rename = "SKILLS")]
|
||||
Skills,
|
||||
#[serde(rename = "PLUGINS")]
|
||||
#[ts(rename = "PLUGINS")]
|
||||
Plugins,
|
||||
#[serde(rename = "MCP_SERVER_CONFIG")]
|
||||
#[ts(rename = "MCP_SERVER_CONFIG")]
|
||||
McpServerConfig,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct PluginsMigration {
|
||||
#[serde(rename = "marketplaceName")]
|
||||
#[ts(rename = "marketplaceName")]
|
||||
pub marketplace_name: String,
|
||||
#[serde(rename = "pluginNames")]
|
||||
#[ts(rename = "pluginNames")]
|
||||
pub plugin_names: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct MigrationDetails {
|
||||
pub plugins: Vec<PluginsMigration>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
@@ -958,6 +979,7 @@ pub struct ExternalAgentConfigMigrationItem {
|
||||
pub description: String,
|
||||
/// Null or empty means home-scoped migration; non-empty means repo-scoped migration.
|
||||
pub cwd: Option<PathBuf>,
|
||||
pub details: Option<MigrationDetails>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
@@ -1467,7 +1489,7 @@ pub enum CommandAction {
|
||||
Read {
|
||||
command: String,
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
path: AbsolutePathBuf,
|
||||
},
|
||||
ListFiles {
|
||||
command: String,
|
||||
@@ -1545,7 +1567,11 @@ impl CommandAction {
|
||||
command: cmd,
|
||||
name,
|
||||
path,
|
||||
} => CoreParsedCommand::Read { cmd, name, path },
|
||||
} => CoreParsedCommand::Read {
|
||||
cmd,
|
||||
name,
|
||||
path: path.into_path_buf(),
|
||||
},
|
||||
CommandAction::ListFiles { command: cmd, path } => {
|
||||
CoreParsedCommand::ListFiles { cmd, path }
|
||||
}
|
||||
@@ -1559,13 +1585,13 @@ impl CommandAction {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CoreParsedCommand> for CommandAction {
|
||||
fn from(value: CoreParsedCommand) -> Self {
|
||||
impl CommandAction {
|
||||
pub fn from_core_with_cwd(value: CoreParsedCommand, cwd: &AbsolutePathBuf) -> Self {
|
||||
match value {
|
||||
CoreParsedCommand::Read { cmd, name, path } => CommandAction::Read {
|
||||
command: cmd,
|
||||
name,
|
||||
path,
|
||||
path: cwd.join(path),
|
||||
},
|
||||
CoreParsedCommand::ListFiles { cmd, path } => {
|
||||
CommandAction::ListFiles { command: cmd, path }
|
||||
@@ -2320,10 +2346,12 @@ pub struct FsGetMetadataParams {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct FsGetMetadataResponse {
|
||||
/// Whether the path currently resolves to a directory.
|
||||
/// Whether the path resolves to a directory.
|
||||
pub is_directory: bool,
|
||||
/// Whether the path currently resolves to a regular file.
|
||||
/// Whether the path resolves to a regular file.
|
||||
pub is_file: bool,
|
||||
/// Whether the path itself is a symbolic link.
|
||||
pub is_symlink: bool,
|
||||
/// File creation time in Unix milliseconds when available, otherwise `0`.
|
||||
#[ts(type = "number")]
|
||||
pub created_at_ms: i64,
|
||||
@@ -2718,10 +2746,10 @@ pub struct ThreadStartResponse {
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
pub service_tier: Option<ServiceTier>,
|
||||
pub cwd: PathBuf,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
/// Instruction source files currently loaded for this thread.
|
||||
#[serde(default)]
|
||||
pub instruction_sources: Vec<PathBuf>,
|
||||
pub instruction_sources: Vec<AbsolutePathBuf>,
|
||||
#[experimental(nested)]
|
||||
pub approval_policy: AskForApproval,
|
||||
/// Reviewer currently used for approval requests on this thread.
|
||||
@@ -2807,10 +2835,10 @@ pub struct ThreadResumeResponse {
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
pub service_tier: Option<ServiceTier>,
|
||||
pub cwd: PathBuf,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
/// Instruction source files currently loaded for this thread.
|
||||
#[serde(default)]
|
||||
pub instruction_sources: Vec<PathBuf>,
|
||||
pub instruction_sources: Vec<AbsolutePathBuf>,
|
||||
#[experimental(nested)]
|
||||
pub approval_policy: AskForApproval,
|
||||
/// Reviewer currently used for approval requests on this thread.
|
||||
@@ -2887,10 +2915,10 @@ pub struct ThreadForkResponse {
|
||||
pub model: String,
|
||||
pub model_provider: String,
|
||||
pub service_tier: Option<ServiceTier>,
|
||||
pub cwd: PathBuf,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
/// Instruction source files currently loaded for this thread.
|
||||
#[serde(default)]
|
||||
pub instruction_sources: Vec<PathBuf>,
|
||||
pub instruction_sources: Vec<AbsolutePathBuf>,
|
||||
#[experimental(nested)]
|
||||
pub approval_policy: AskForApproval,
|
||||
/// Reviewer currently used for approval requests on this thread.
|
||||
@@ -3324,6 +3352,26 @@ pub struct SkillsListResponse {
|
||||
pub data: Vec<SkillsListEntry>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct MarketplaceAddParams {
|
||||
pub source: String,
|
||||
#[ts(optional = nullable)]
|
||||
pub ref_name: Option<String>,
|
||||
#[ts(optional = nullable)]
|
||||
pub sparse_paths: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct MarketplaceAddResponse {
|
||||
pub marketplace_name: String,
|
||||
pub installed_root: AbsolutePathBuf,
|
||||
pub already_added: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
@@ -3414,9 +3462,9 @@ pub struct SkillInterface {
|
||||
#[ts(optional)]
|
||||
pub short_description: Option<String>,
|
||||
#[ts(optional)]
|
||||
pub icon_small: Option<PathBuf>,
|
||||
pub icon_small: Option<AbsolutePathBuf>,
|
||||
#[ts(optional)]
|
||||
pub icon_large: Option<PathBuf>,
|
||||
pub icon_large: Option<AbsolutePathBuf>,
|
||||
#[ts(optional)]
|
||||
pub brand_color: Option<String>,
|
||||
#[ts(optional)]
|
||||
@@ -3700,15 +3748,6 @@ impl From<CoreSkillScope> for SkillScope {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CoreSkillErrorInfo> for SkillErrorInfo {
|
||||
fn from(value: CoreSkillErrorInfo) -> Self {
|
||||
Self {
|
||||
path: value.path,
|
||||
message: value.message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
@@ -3733,7 +3772,7 @@ pub struct Thread {
|
||||
/// [UNSTABLE] Path to the thread on disk.
|
||||
pub path: Option<PathBuf>,
|
||||
/// Working directory captured for the thread.
|
||||
pub cwd: PathBuf,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
/// Version of the CLI that created the thread.
|
||||
pub cli_version: String,
|
||||
/// Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).
|
||||
@@ -3954,11 +3993,14 @@ impl From<ThreadRealtimeAudioChunk> for CoreRealtimeAudioFrame {
|
||||
}
|
||||
|
||||
/// EXPERIMENTAL - start a thread-scoped realtime session.
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadRealtimeStartParams {
|
||||
pub thread_id: String,
|
||||
/// Selects text or audio output for the realtime session. Transport and voice stay
|
||||
/// independent so clients can choose how they connect separately from what the model emits.
|
||||
pub output_modality: RealtimeOutputModality,
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "super::serde_helpers::deserialize_double_option",
|
||||
@@ -4076,9 +4118,22 @@ pub struct ThreadRealtimeItemAddedNotification {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadRealtimeTranscriptUpdatedNotification {
|
||||
pub struct ThreadRealtimeTranscriptDeltaNotification {
|
||||
pub thread_id: String,
|
||||
pub role: String,
|
||||
/// Live transcript delta from the realtime event.
|
||||
pub delta: String,
|
||||
}
|
||||
|
||||
/// EXPERIMENTAL - final transcript text emitted when realtime completes
|
||||
/// a transcript part.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadRealtimeTranscriptDoneNotification {
|
||||
pub thread_id: String,
|
||||
pub role: String,
|
||||
/// Final complete text for the transcript part.
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
@@ -4492,7 +4547,7 @@ pub enum ThreadItem {
|
||||
/// The command to be executed.
|
||||
command: String,
|
||||
/// The command's working directory.
|
||||
cwd: PathBuf,
|
||||
cwd: AbsolutePathBuf,
|
||||
/// Identifier for the underlying PTY process (when available).
|
||||
process_id: Option<String>,
|
||||
#[serde(default)]
|
||||
@@ -4576,7 +4631,7 @@ pub enum ThreadItem {
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
ImageView { id: String, path: String },
|
||||
ImageView { id: String, path: AbsolutePathBuf },
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
ImageGeneration {
|
||||
@@ -4586,7 +4641,7 @@ pub enum ThreadItem {
|
||||
result: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
saved_path: Option<String>,
|
||||
saved_path: Option<AbsolutePathBuf>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
@@ -4748,7 +4803,7 @@ impl From<GuardianCommandSource> for CoreGuardianCommandSource {
|
||||
pub struct GuardianCommandReviewAction {
|
||||
pub source: GuardianCommandSource,
|
||||
pub command: String,
|
||||
pub cwd: PathBuf,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
@@ -4758,15 +4813,15 @@ pub struct GuardianExecveReviewAction {
|
||||
pub source: GuardianCommandSource,
|
||||
pub program: String,
|
||||
pub argv: Vec<String>,
|
||||
pub cwd: PathBuf,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct GuardianApplyPatchReviewAction {
|
||||
pub cwd: PathBuf,
|
||||
pub files: Vec<PathBuf>,
|
||||
pub cwd: AbsolutePathBuf,
|
||||
pub files: Vec<AbsolutePathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
@@ -4800,7 +4855,7 @@ pub enum GuardianApprovalReviewAction {
|
||||
Command {
|
||||
source: GuardianCommandSource,
|
||||
command: String,
|
||||
cwd: PathBuf,
|
||||
cwd: AbsolutePathBuf,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
@@ -4808,11 +4863,14 @@ pub enum GuardianApprovalReviewAction {
|
||||
source: GuardianCommandSource,
|
||||
program: String,
|
||||
argv: Vec<String>,
|
||||
cwd: PathBuf,
|
||||
cwd: AbsolutePathBuf,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
ApplyPatch { cwd: PathBuf, files: Vec<PathBuf> },
|
||||
ApplyPatch {
|
||||
cwd: AbsolutePathBuf,
|
||||
files: Vec<AbsolutePathBuf>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
NetworkAccess {
|
||||
@@ -5721,7 +5779,7 @@ pub struct CommandExecutionRequestApprovalParams {
|
||||
/// The command's working directory.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub cwd: Option<PathBuf>,
|
||||
pub cwd: Option<AbsolutePathBuf>,
|
||||
/// Best-effort parsed command actions for friendly display.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
@@ -6526,22 +6584,20 @@ mod tests {
|
||||
use codex_protocol::protocol::NetworkAccess as CoreNetworkAccess;
|
||||
use codex_protocol::protocol::ReadOnlyAccess as CoreReadOnlyAccess;
|
||||
use codex_protocol::user_input::UserInput as CoreUserInput;
|
||||
use codex_utils_absolute_path::test_support::PathBufExt;
|
||||
use codex_utils_absolute_path::test_support::test_path_buf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn absolute_path_string(path: &str) -> String {
|
||||
let trimmed = path.trim_start_matches('/');
|
||||
if cfg!(windows) {
|
||||
format!(r"C:\{}", trimmed.replace('/', "\\"))
|
||||
} else {
|
||||
format!("/{trimmed}")
|
||||
}
|
||||
let path = format!("/{}", path.trim_start_matches('/'));
|
||||
test_path_buf(&path).display().to_string()
|
||||
}
|
||||
|
||||
fn absolute_path(path: &str) -> AbsolutePathBuf {
|
||||
AbsolutePathBuf::from_absolute_path(absolute_path_string(path))
|
||||
.expect("path must be absolute")
|
||||
let path = format!("/{}", path.trim_start_matches('/'));
|
||||
test_path_buf(&path).abs()
|
||||
}
|
||||
|
||||
fn test_absolute_path() -> AbsolutePathBuf {
|
||||
@@ -6559,6 +6615,39 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_agent_config_plugins_details_round_trip() {
|
||||
let item: ExternalAgentConfigMigrationItem = serde_json::from_value(json!({
|
||||
"itemType": "PLUGINS",
|
||||
"description": "Install supported plugins from Claude settings",
|
||||
"cwd": absolute_path_string("repo"),
|
||||
"details": {
|
||||
"plugins": [
|
||||
{
|
||||
"marketplaceName": "team-marketplace",
|
||||
"pluginNames": ["asana"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}))
|
||||
.expect("plugins migration item should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
item,
|
||||
ExternalAgentConfigMigrationItem {
|
||||
item_type: ExternalAgentConfigMigrationItemType::Plugins,
|
||||
description: "Install supported plugins from Claude settings".to_string(),
|
||||
cwd: Some(PathBuf::from(absolute_path_string("repo"))),
|
||||
details: Some(MigrationDetails {
|
||||
plugins: vec![PluginsMigration {
|
||||
marketplace_name: "team-marketplace".to_string(),
|
||||
plugin_names: vec!["asana".to_string()],
|
||||
}],
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_execution_request_approval_rejects_relative_additional_permission_paths() {
|
||||
let err = serde_json::from_value::<CommandExecutionRequestApprovalParams>(json!({
|
||||
@@ -6566,7 +6655,7 @@ mod tests {
|
||||
"turnId": "turn_123",
|
||||
"itemId": "call_123",
|
||||
"command": "cat file",
|
||||
"cwd": "/tmp",
|
||||
"cwd": absolute_path_string("tmp"),
|
||||
"commandActions": null,
|
||||
"reason": null,
|
||||
"networkApprovalContext": null,
|
||||
@@ -6765,6 +6854,7 @@ mod tests {
|
||||
let response = FsGetMetadataResponse {
|
||||
is_directory: false,
|
||||
is_file: true,
|
||||
is_symlink: false,
|
||||
created_at_ms: 123,
|
||||
modified_at_ms: 456,
|
||||
};
|
||||
@@ -6775,6 +6865,7 @@ mod tests {
|
||||
json!({
|
||||
"isDirectory": false,
|
||||
"isFile": true,
|
||||
"isSymlink": false,
|
||||
"createdAtMs": 123,
|
||||
"modifiedAtMs": 456,
|
||||
})
|
||||
@@ -8023,7 +8114,7 @@ mod tests {
|
||||
"type": "command",
|
||||
"source": "shell",
|
||||
"command": "rm -rf /tmp/example.sqlite",
|
||||
"cwd": "/tmp",
|
||||
"cwd": absolute_path_string("tmp"),
|
||||
});
|
||||
let action: GuardianApprovalReviewAction =
|
||||
serde_json::from_value(value.clone()).expect("guardian review action");
|
||||
@@ -8033,7 +8124,7 @@ mod tests {
|
||||
GuardianApprovalReviewAction::Command {
|
||||
source: GuardianCommandSource::Shell,
|
||||
command: "rm -rf /tmp/example.sqlite".to_string(),
|
||||
cwd: "/tmp".into(),
|
||||
cwd: absolute_path("tmp"),
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -8062,7 +8153,6 @@ mod tests {
|
||||
dangerously_allow_all_unix_sockets: None,
|
||||
domains: None,
|
||||
managed_allowed_domains_only: None,
|
||||
danger_full_access_denylist_only: None,
|
||||
allowed_domains: Some(vec!["api.openai.com".to_string()]),
|
||||
denied_domains: Some(vec!["blocked.example.com".to_string()]),
|
||||
unix_sockets: None,
|
||||
@@ -8089,7 +8179,6 @@ mod tests {
|
||||
),
|
||||
])),
|
||||
managed_allowed_domains_only: Some(true),
|
||||
danger_full_access_denylist_only: Some(true),
|
||||
allowed_domains: Some(vec!["api.openai.com".to_string()]),
|
||||
denied_domains: Some(vec!["blocked.example.com".to_string()]),
|
||||
unix_sockets: Some(BTreeMap::from([
|
||||
@@ -8120,7 +8209,6 @@ mod tests {
|
||||
"blocked.example.com": "deny"
|
||||
},
|
||||
"managedAllowedDomainsOnly": true,
|
||||
"dangerFullAccessDenylistOnly": true,
|
||||
"allowedDomains": ["api.openai.com"],
|
||||
"deniedDomains": ["blocked.example.com"],
|
||||
"unixSockets": {
|
||||
@@ -8348,6 +8436,37 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn marketplace_add_params_serialization_uses_optional_ref_name_and_sparse_paths() {
|
||||
assert_eq!(
|
||||
serde_json::to_value(MarketplaceAddParams {
|
||||
source: "owner/repo".to_string(),
|
||||
ref_name: None,
|
||||
sparse_paths: None,
|
||||
})
|
||||
.unwrap(),
|
||||
json!({
|
||||
"source": "owner/repo",
|
||||
"refName": null,
|
||||
"sparsePaths": null,
|
||||
}),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(MarketplaceAddParams {
|
||||
source: "owner/repo".to_string(),
|
||||
ref_name: Some("main".to_string()),
|
||||
sparse_paths: Some(vec!["plugins/foo".to_string()]),
|
||||
})
|
||||
.unwrap(),
|
||||
json!({
|
||||
"source": "owner/repo",
|
||||
"refName": "main",
|
||||
"sparsePaths": ["plugins/foo"],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_install_params_serialization_uses_force_remote_sync() {
|
||||
let marketplace_path = if cfg!(windows) {
|
||||
@@ -8579,7 +8698,7 @@ mod tests {
|
||||
"updatedAt": 1,
|
||||
"status": { "type": "idle" },
|
||||
"path": null,
|
||||
"cwd": "/tmp",
|
||||
"cwd": absolute_path_string("tmp"),
|
||||
"cliVersion": "0.0.0",
|
||||
"source": "exec",
|
||||
"agentNickname": null,
|
||||
@@ -8591,7 +8710,7 @@ mod tests {
|
||||
"model": "gpt-5",
|
||||
"modelProvider": "openai",
|
||||
"serviceTier": null,
|
||||
"cwd": "/tmp",
|
||||
"cwd": absolute_path_string("tmp"),
|
||||
"approvalPolicy": "on-failure",
|
||||
"approvalsReviewer": "user",
|
||||
"sandbox": { "type": "dangerFullAccess" },
|
||||
@@ -8605,9 +8724,9 @@ mod tests {
|
||||
let fork: ThreadForkResponse =
|
||||
serde_json::from_value(response).expect("thread/fork response");
|
||||
|
||||
assert_eq!(start.instruction_sources, Vec::<PathBuf>::new());
|
||||
assert_eq!(resume.instruction_sources, Vec::<PathBuf>::new());
|
||||
assert_eq!(fork.instruction_sources, Vec::<PathBuf>::new());
|
||||
assert_eq!(start.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
||||
assert_eq!(resume.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
||||
assert_eq!(fork.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -154,7 +154,7 @@ Example with notification opt-out:
|
||||
- `thread/inject_items` — append raw Responses API items to a loaded thread’s model-visible history without starting a user turn; returns `{}` on success.
|
||||
- `turn/steer` — add user input to an already in-flight regular turn without starting a new turn; returns the active `turnId` that accepted the input. Review and manual compaction turns reject `turn/steer`.
|
||||
- `turn/interrupt` — request cancellation of an in-flight turn by `(thread_id, turn_id)`; success is an empty `{}` response and the turn finishes with `status: "interrupted"`.
|
||||
- `thread/realtime/start` — start a thread-scoped realtime session (experimental); returns `{}` and streams `thread/realtime/*` notifications. Omit `transport` for the websocket transport, or pass `{ "type": "webrtc", "sdp": "..." }` to create a WebRTC session from a browser-generated SDP offer; the remote answer SDP is emitted as `thread/realtime/sdp`.
|
||||
- `thread/realtime/start` — start a thread-scoped realtime session (experimental); pass `outputModality: "text"` or `outputModality: "audio"` to choose model output, returns `{}` and streams `thread/realtime/*` notifications. Omit `transport` for the websocket transport, or pass `{ "type": "webrtc", "sdp": "..." }` to create a WebRTC session from a browser-generated SDP offer; the remote answer SDP is emitted as `thread/realtime/sdp`.
|
||||
- `thread/realtime/appendAudio` — append an input audio chunk to the active realtime session (experimental); returns `{}`.
|
||||
- `thread/realtime/appendText` — append text input to the active realtime session (experimental); returns `{}`.
|
||||
- `thread/realtime/stop` — stop the active realtime session for the thread (experimental); returns `{}`.
|
||||
@@ -167,7 +167,7 @@ Example with notification opt-out:
|
||||
- `fs/readFile` — read an absolute file path and return `{ dataBase64 }`.
|
||||
- `fs/writeFile` — write an absolute file path from base64-encoded `{ dataBase64 }`; returns `{}`.
|
||||
- `fs/createDirectory` — create an absolute directory path; `recursive` defaults to `true`.
|
||||
- `fs/getMetadata` — return metadata for an absolute path: `isDirectory`, `isFile`, `createdAtMs`, and `modifiedAtMs`.
|
||||
- `fs/getMetadata` — return metadata for an absolute path: `isDirectory`, `isFile`, `isSymlink`, `createdAtMs`, and `modifiedAtMs`.
|
||||
- `fs/readDirectory` — list direct child entries for an absolute directory path; each entry contains `fileName`, `isDirectory`, and `isFile`, and `fileName` is just the child name, not a path.
|
||||
- `fs/remove` — remove an absolute file or directory tree; `recursive` and `force` default to `true`.
|
||||
- `fs/copy` — copy between absolute paths; directory copies require `recursive: true`.
|
||||
@@ -179,6 +179,7 @@ Example with notification opt-out:
|
||||
- `experimentalFeature/enablement/set` — patch the in-memory process-wide runtime feature enablement for the currently supported feature keys (`apps`, `plugins`). For each feature, precedence is: cloud requirements > --enable <feature_name> > config.toml > experimentalFeature/enablement/set (new) > code default.
|
||||
- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination). This response omits built-in developer instructions; clients should either pass `settings.developer_instructions: null` when setting a mode to use Codex's built-in instructions, or provide their own instructions explicitly.
|
||||
- `skills/list` — list skills for one or more `cwd` values (optional `forceReload`).
|
||||
- `marketplace/add` — add a remote plugin marketplace from an HTTP(S) Git URL, SSH Git URL, or GitHub `owner/repo` shorthand, then persist it into the user marketplace config. Returns the installed root path plus whether the marketplace was already present.
|
||||
- `plugin/list` — list discovered plugin marketplaces and plugin state, including effective marketplace install/auth policy metadata, fail-open `marketplaceLoadErrors` entries for marketplace files that could not be parsed or loaded, and best-effort `featuredPluginIds` for the official curated marketplace. `interface.category` uses the marketplace category when present; otherwise it falls back to the plugin manifest category. Pass `forceRemoteSync: true` to refresh curated plugin state before listing (**under development; do not call from production clients yet**).
|
||||
- `plugin/read` — read one plugin by `marketplacePath` plus `pluginName`, returning marketplace info, a list-style `summary`, manifest descriptions/interface metadata, and bundled skills/apps/MCP server names. Returned plugin skills include their current `enabled` state after local config filtering. Plugin app summaries also include `needsAuth` when the server can determine connector accessibility (**under development; do not call from production clients yet**).
|
||||
- `skills/changed` — notification emitted when watched local skill files change.
|
||||
@@ -195,11 +196,11 @@ Example with notification opt-out:
|
||||
- `windowsSandbox/setupStart` — start Windows sandbox setup for the selected mode (`elevated` or `unelevated`); accepts an optional absolute `cwd` to target setup for a specific workspace, returns `{ started: true }` immediately, and later emits `windowsSandbox/setupCompleted`.
|
||||
- `feedback/upload` — submit a feedback report (classification + optional reason/logs, conversation_id, and optional `extraLogFiles` attachments array); returns the tracking thread id.
|
||||
- `config/read` — fetch the effective config on disk after resolving config layering.
|
||||
- `externalAgentConfig/detect` — detect migratable external-agent artifacts with `includeHome` and optional `cwds`; each detected item includes `cwd` (`null` for home).
|
||||
- `externalAgentConfig/import` — apply selected external-agent migration items by passing explicit `migrationItems` with `cwd` (`null` for home).
|
||||
- `externalAgentConfig/detect` — detect migratable external-agent artifacts with `includeHome` and optional `cwds`; each detected item includes `cwd` (`null` for home), and plugin migration items may additionally include structured `details` grouping plugin ids under each detected marketplace name.
|
||||
- `externalAgentConfig/import` — apply selected external-agent migration items by passing explicit `migrationItems` with `cwd` (`null` for home) and any plugin `details` returned by detect.
|
||||
- `config/value/write` — write a single config key/value to the user's config.toml on disk.
|
||||
- `config/batchWrite` — apply multiple config edits atomically to the user's config.toml on disk, with optional `reloadUserConfig: true` to hot-reload loaded threads.
|
||||
- `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), pinned feature values (`featureRequirements`), `enforceResidency`, and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly` and `dangerFullAccessDenylistOnly`.
|
||||
- `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), pinned feature values (`featureRequirements`), `enforceResidency`, and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly`.
|
||||
|
||||
### Example: Start or resume a thread
|
||||
|
||||
@@ -627,6 +628,7 @@ Then send `offer.sdp` to app-server. Core uses `experimental_realtime_ws_backend
|
||||
```json
|
||||
{ "method": "thread/realtime/start", "id": 40, "params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"prompt": "You are on a call.",
|
||||
"sessionId": null,
|
||||
"transport": { "type": "webrtc", "sdp": "v=0\r\no=..." }
|
||||
@@ -878,6 +880,7 @@ All filesystem paths in this section must be absolute.
|
||||
{ "id": 42, "result": {
|
||||
"isDirectory": false,
|
||||
"isFile": true,
|
||||
"isSymlink": false,
|
||||
"createdAtMs": 1730910000000,
|
||||
"modifiedAtMs": 1730910000000
|
||||
} }
|
||||
@@ -889,7 +892,7 @@ All filesystem paths in this section must be absolute.
|
||||
} }
|
||||
```
|
||||
|
||||
- `fs/getMetadata` returns whether the path currently resolves to a directory or regular file, plus `createdAtMs` and `modifiedAtMs` in Unix milliseconds. If a timestamp is unavailable on the current platform, that field is `0`.
|
||||
- `fs/getMetadata` returns whether the path resolves to a directory or regular file, whether the path itself is a symlink, plus `createdAtMs` and `modifiedAtMs` in Unix milliseconds. If a timestamp is unavailable on the current platform, that field is `0`.
|
||||
- `fs/createDirectory` defaults `recursive` to `true` when omitted.
|
||||
- `fs/remove` defaults both `recursive` and `force` to `true` when omitted.
|
||||
- `fs/readFile` always returns base64 bytes via `dataBase64`, and `fs/writeFile` always expects base64 bytes in `dataBase64`.
|
||||
@@ -950,7 +953,8 @@ The thread realtime API emits thread-scoped notifications for session lifecycle
|
||||
|
||||
- `thread/realtime/started` — `{ threadId, sessionId }` once realtime starts for the thread (experimental).
|
||||
- `thread/realtime/itemAdded` — `{ threadId, item }` for raw non-audio realtime items that do not have a dedicated typed app-server notification, including `handoff_request` (experimental). `item` is forwarded as raw JSON while the upstream websocket item schema remains unstable.
|
||||
- `thread/realtime/transcriptUpdated` — `{ threadId, role, text }` whenever realtime transcript text changes (experimental). This forwards the live transcript delta from that realtime event, not the full accumulated transcript.
|
||||
- `thread/realtime/transcript/delta` — `{ threadId, role, delta }` for live realtime transcript deltas (experimental).
|
||||
- `thread/realtime/transcript/done` — `{ threadId, role, text }` when realtime emits the final full text for a transcript part (experimental).
|
||||
- `thread/realtime/outputAudio/delta` — `{ threadId, audio }` for streamed output audio chunks (experimental). `audio` uses camelCase fields (`data`, `sampleRate`, `numChannels`, `samplesPerChannel`).
|
||||
- `thread/realtime/error` — `{ threadId, message }` when realtime encounters a transport or backend error (experimental).
|
||||
- `thread/realtime/closed` — `{ threadId, reason }` when the realtime transport closes (experimental).
|
||||
|
||||
@@ -72,10 +72,10 @@ pub(crate) fn typed_request_span(
|
||||
&span,
|
||||
client_info
|
||||
.map(|(client_name, _)| client_name)
|
||||
.or(session.app_server_client_name.as_deref()),
|
||||
.or(session.app_server_client_name()),
|
||||
client_info
|
||||
.map(|(_, client_version)| client_version)
|
||||
.or(session.client_version.as_deref()),
|
||||
.or(session.client_version()),
|
||||
);
|
||||
|
||||
attach_parent_context(&span, &method, request.id(), /*parent_trace*/ None);
|
||||
@@ -147,7 +147,7 @@ fn client_name<'a>(
|
||||
if let Some(params) = initialize_client_info {
|
||||
return Some(params.client_info.name.as_str());
|
||||
}
|
||||
session.app_server_client_name.as_deref()
|
||||
session.app_server_client_name()
|
||||
}
|
||||
|
||||
fn client_version<'a>(
|
||||
@@ -157,7 +157,7 @@ fn client_version<'a>(
|
||||
if let Some(params) = initialize_client_info {
|
||||
return Some(params.client_info.version.as_str());
|
||||
}
|
||||
session.client_version.as_deref()
|
||||
session.client_version()
|
||||
}
|
||||
|
||||
fn initialize_client_info(request: &JSONRPCRequest) -> Option<InitializeParams> {
|
||||
|
||||
@@ -12,6 +12,7 @@ use crate::thread_state::TurnSummary;
|
||||
use crate::thread_state::resolve_server_request_on_thread_listener;
|
||||
use crate::thread_status::ThreadWatchActiveGuard;
|
||||
use crate::thread_status::ThreadWatchManager;
|
||||
use codex_analytics::AnalyticsEventsClient;
|
||||
use codex_app_server_protocol::AccountRateLimitsUpdatedNotification;
|
||||
use codex_app_server_protocol::AdditionalPermissionProfile as V2AdditionalPermissionProfile;
|
||||
use codex_app_server_protocol::AgentMessageDeltaNotification;
|
||||
@@ -82,7 +83,8 @@ use codex_app_server_protocol::ThreadRealtimeItemAddedNotification;
|
||||
use codex_app_server_protocol::ThreadRealtimeOutputAudioDeltaNotification;
|
||||
use codex_app_server_protocol::ThreadRealtimeSdpNotification;
|
||||
use codex_app_server_protocol::ThreadRealtimeStartedNotification;
|
||||
use codex_app_server_protocol::ThreadRealtimeTranscriptUpdatedNotification;
|
||||
use codex_app_server_protocol::ThreadRealtimeTranscriptDeltaNotification;
|
||||
use codex_app_server_protocol::ThreadRealtimeTranscriptDoneNotification;
|
||||
use codex_app_server_protocol::ThreadRollbackResponse;
|
||||
use codex_app_server_protocol::ThreadTokenUsage;
|
||||
use codex_app_server_protocol::ThreadTokenUsageUpdatedNotification;
|
||||
@@ -138,9 +140,9 @@ use codex_protocol::request_user_input::RequestUserInputAnswer as CoreRequestUse
|
||||
use codex_protocol::request_user_input::RequestUserInputResponse as CoreRequestUserInputResponse;
|
||||
use codex_sandboxing::policy_transforms::intersect_permission_profiles;
|
||||
use codex_shell_command::parse_command::shlex_join;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::sync::oneshot;
|
||||
@@ -157,7 +159,7 @@ enum CommandExecutionApprovalPresentation {
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct CommandExecutionCompletionItem {
|
||||
command: String,
|
||||
cwd: PathBuf,
|
||||
cwd: AbsolutePathBuf,
|
||||
command_actions: Vec<V2ParsedCommand>,
|
||||
}
|
||||
|
||||
@@ -167,6 +169,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
conversation_id: ThreadId,
|
||||
conversation: Arc<CodexThread>,
|
||||
thread_manager: Arc<ThreadManager>,
|
||||
analytics_events_client: Option<AnalyticsEventsClient>,
|
||||
outgoing: ThreadScopedOutgoingMessageSender,
|
||||
thread_state: Arc<tokio::sync::Mutex<ThreadState>>,
|
||||
thread_watch_manager: ThreadWatchManager,
|
||||
@@ -202,6 +205,10 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
thread_id: conversation_id.to_string(),
|
||||
turn,
|
||||
};
|
||||
if let Some(analytics_events_client) = analytics_events_client.as_ref() {
|
||||
analytics_events_client
|
||||
.track_notification(ServerNotification::TurnStarted(notification.clone()));
|
||||
}
|
||||
outgoing
|
||||
.send_server_notification(ServerNotification::TurnStarted(notification))
|
||||
.await;
|
||||
@@ -218,6 +225,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
conversation_id,
|
||||
event_turn_id,
|
||||
turn_complete_event,
|
||||
analytics_events_client.as_ref(),
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -401,26 +409,50 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
.await;
|
||||
}
|
||||
RealtimeEvent::InputTranscriptDelta(event) => {
|
||||
let notification = ThreadRealtimeTranscriptUpdatedNotification {
|
||||
let notification = ThreadRealtimeTranscriptDeltaNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
role: "user".to_string(),
|
||||
text: event.delta,
|
||||
delta: event.delta,
|
||||
};
|
||||
outgoing
|
||||
.send_server_notification(
|
||||
ServerNotification::ThreadRealtimeTranscriptUpdated(notification),
|
||||
ServerNotification::ThreadRealtimeTranscriptDelta(notification),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
RealtimeEvent::InputTranscriptDone(event) => {
|
||||
let notification = ThreadRealtimeTranscriptDoneNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
role: "user".to_string(),
|
||||
text: event.text,
|
||||
};
|
||||
outgoing
|
||||
.send_server_notification(
|
||||
ServerNotification::ThreadRealtimeTranscriptDone(notification),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
RealtimeEvent::OutputTranscriptDelta(event) => {
|
||||
let notification = ThreadRealtimeTranscriptUpdatedNotification {
|
||||
let notification = ThreadRealtimeTranscriptDeltaNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
role: "assistant".to_string(),
|
||||
text: event.delta,
|
||||
delta: event.delta,
|
||||
};
|
||||
outgoing
|
||||
.send_server_notification(
|
||||
ServerNotification::ThreadRealtimeTranscriptUpdated(notification),
|
||||
ServerNotification::ThreadRealtimeTranscriptDelta(notification),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
RealtimeEvent::OutputTranscriptDone(event) => {
|
||||
let notification = ThreadRealtimeTranscriptDoneNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
role: "assistant".to_string(),
|
||||
text: event.text,
|
||||
};
|
||||
outgoing
|
||||
.send_server_notification(
|
||||
ServerNotification::ThreadRealtimeTranscriptDone(notification),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -612,7 +644,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
call_id: call_id.clone(),
|
||||
approval_id,
|
||||
command,
|
||||
cwd,
|
||||
cwd: cwd.to_path_buf(),
|
||||
reason,
|
||||
parsed_cmd,
|
||||
};
|
||||
@@ -634,7 +666,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
let command_actions = parsed_cmd
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(V2ParsedCommand::from)
|
||||
.map(|parsed| V2ParsedCommand::from_core_with_cwd(parsed, &cwd))
|
||||
.collect::<Vec<_>>();
|
||||
let presentation = if let Some(network_approval_context) =
|
||||
network_approval_context.map(V2NetworkApprovalContext::from)
|
||||
@@ -1431,7 +1463,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
EventMsg::ViewImageToolCall(view_image_event) => {
|
||||
let item = ThreadItem::ImageView {
|
||||
id: view_image_event.call_id.clone(),
|
||||
path: view_image_event.path.to_string_lossy().into_owned(),
|
||||
path: view_image_event.path.clone(),
|
||||
};
|
||||
let started = ItemStartedNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
@@ -1616,13 +1648,13 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
return;
|
||||
}
|
||||
let item_id = exec_command_begin_event.call_id.clone();
|
||||
let cwd = exec_command_begin_event.cwd.clone();
|
||||
let command_actions = exec_command_begin_event
|
||||
.parsed_cmd
|
||||
.into_iter()
|
||||
.map(V2ParsedCommand::from)
|
||||
.map(|parsed| V2ParsedCommand::from_core_with_cwd(parsed, &cwd))
|
||||
.collect::<Vec<_>>();
|
||||
let command = shlex_join(&exec_command_begin_event.command);
|
||||
let cwd = exec_command_begin_event.cwd;
|
||||
let process_id = exec_command_begin_event.process_id;
|
||||
let first_start = {
|
||||
let mut state = thread_state.lock().await;
|
||||
@@ -1773,6 +1805,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
conversation_id,
|
||||
event_turn_id,
|
||||
turn_aborted_event,
|
||||
analytics_events_client.as_ref(),
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -1801,7 +1834,8 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
.await
|
||||
{
|
||||
Ok(summary) => {
|
||||
let mut thread = summary_to_thread(summary);
|
||||
let fallback_cwd = conversation.config_snapshot().await.cwd;
|
||||
let mut thread = summary_to_thread(summary, &fallback_cwd);
|
||||
match read_rollout_items_from_rollout(rollout_path.as_path()).await {
|
||||
Ok(items) => {
|
||||
thread.turns = build_turns_from_rollout_items(&items);
|
||||
@@ -1950,6 +1984,7 @@ async fn emit_turn_completed_with_status(
|
||||
conversation_id: ThreadId,
|
||||
event_turn_id: String,
|
||||
turn_completion_metadata: TurnCompletionMetadata,
|
||||
analytics_events_client: Option<&AnalyticsEventsClient>,
|
||||
outgoing: &ThreadScopedOutgoingMessageSender,
|
||||
) {
|
||||
let notification = TurnCompletedNotification {
|
||||
@@ -1964,6 +1999,10 @@ async fn emit_turn_completed_with_status(
|
||||
duration_ms: turn_completion_metadata.duration_ms,
|
||||
},
|
||||
};
|
||||
if let Some(analytics_events_client) = analytics_events_client {
|
||||
analytics_events_client
|
||||
.track_notification(ServerNotification::TurnCompleted(notification.clone()));
|
||||
}
|
||||
outgoing
|
||||
.send_server_notification(ServerNotification::TurnCompleted(notification))
|
||||
.await;
|
||||
@@ -1997,7 +2036,7 @@ async fn start_command_execution_item(
|
||||
turn_id: String,
|
||||
item_id: String,
|
||||
command: String,
|
||||
cwd: PathBuf,
|
||||
cwd: AbsolutePathBuf,
|
||||
command_actions: Vec<V2ParsedCommand>,
|
||||
source: CommandExecutionSource,
|
||||
outgoing: &ThreadScopedOutgoingMessageSender,
|
||||
@@ -2040,7 +2079,7 @@ async fn complete_command_execution_item(
|
||||
turn_id: String,
|
||||
item_id: String,
|
||||
command: String,
|
||||
cwd: PathBuf,
|
||||
cwd: AbsolutePathBuf,
|
||||
process_id: Option<String>,
|
||||
source: CommandExecutionSource,
|
||||
command_actions: Vec<V2ParsedCommand>,
|
||||
@@ -2156,6 +2195,7 @@ async fn handle_turn_complete(
|
||||
conversation_id: ThreadId,
|
||||
event_turn_id: String,
|
||||
turn_complete_event: TurnCompleteEvent,
|
||||
analytics_events_client: Option<&AnalyticsEventsClient>,
|
||||
outgoing: &ThreadScopedOutgoingMessageSender,
|
||||
thread_state: &Arc<Mutex<ThreadState>>,
|
||||
) {
|
||||
@@ -2176,6 +2216,7 @@ async fn handle_turn_complete(
|
||||
completed_at: turn_complete_event.completed_at,
|
||||
duration_ms: turn_complete_event.duration_ms,
|
||||
},
|
||||
analytics_events_client,
|
||||
outgoing,
|
||||
)
|
||||
.await;
|
||||
@@ -2185,6 +2226,7 @@ async fn handle_turn_interrupted(
|
||||
conversation_id: ThreadId,
|
||||
event_turn_id: String,
|
||||
turn_aborted_event: TurnAbortedEvent,
|
||||
analytics_events_client: Option<&AnalyticsEventsClient>,
|
||||
outgoing: &ThreadScopedOutgoingMessageSender,
|
||||
thread_state: &Arc<Mutex<ThreadState>>,
|
||||
) {
|
||||
@@ -2200,6 +2242,7 @@ async fn handle_turn_interrupted(
|
||||
completed_at: turn_aborted_event.completed_at,
|
||||
duration_ms: turn_aborted_event.duration_ms,
|
||||
},
|
||||
analytics_events_client,
|
||||
outgoing,
|
||||
)
|
||||
.await;
|
||||
@@ -2940,6 +2983,7 @@ mod tests {
|
||||
use codex_app_server_protocol::GuardianApprovalReviewStatus;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::TurnPlanStepStatus;
|
||||
use codex_login::AuthManager;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_protocol::items::HookPromptFragment;
|
||||
use codex_protocol::items::build_hook_prompt_message;
|
||||
@@ -2959,6 +3003,8 @@ mod tests {
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use codex_protocol::protocol::TokenUsageInfo;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_absolute_path::test_support::PathBufExt;
|
||||
use codex_utils_absolute_path::test_support::test_path_buf;
|
||||
use core_test_support::load_default_config_for_test;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rmcp::model::Content;
|
||||
@@ -3011,7 +3057,7 @@ mod tests {
|
||||
fn command_execution_completion_item(command: &str) -> CommandExecutionCompletionItem {
|
||||
CommandExecutionCompletionItem {
|
||||
command: command.to_string(),
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
command_actions: vec![V2ParsedCommand::Unknown {
|
||||
command: command.to_string(),
|
||||
}],
|
||||
@@ -3057,7 +3103,7 @@ mod tests {
|
||||
"type": "command",
|
||||
"source": "shell",
|
||||
"command": format!("rm -f /tmp/{id}.sqlite"),
|
||||
"cwd": "/tmp",
|
||||
"cwd": test_path_buf("/tmp"),
|
||||
}))
|
||||
.expect("guardian action"),
|
||||
}
|
||||
@@ -3070,6 +3116,7 @@ mod tests {
|
||||
outgoing: ThreadScopedOutgoingMessageSender,
|
||||
thread_state: Arc<Mutex<ThreadState>>,
|
||||
thread_watch_manager: ThreadWatchManager,
|
||||
analytics_events_client: AnalyticsEventsClient,
|
||||
codex_home: PathBuf,
|
||||
}
|
||||
|
||||
@@ -3084,6 +3131,7 @@ mod tests {
|
||||
self.conversation_id,
|
||||
self.conversation.clone(),
|
||||
self.thread_manager.clone(),
|
||||
Some(self.analytics_events_client.clone()),
|
||||
self.outgoing.clone(),
|
||||
self.thread_state.clone(),
|
||||
self.thread_watch_manager.clone(),
|
||||
@@ -3101,7 +3149,7 @@ mod tests {
|
||||
let action = codex_protocol::protocol::GuardianAssessmentAction::Command {
|
||||
source: codex_protocol::protocol::GuardianCommandSource::Shell,
|
||||
command: "rm -rf /tmp/example.sqlite".to_string(),
|
||||
cwd: "/tmp".into(),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
};
|
||||
let notification = guardian_auto_approval_review_notification(
|
||||
&conversation_id,
|
||||
@@ -3144,7 +3192,7 @@ mod tests {
|
||||
let action = codex_protocol::protocol::GuardianAssessmentAction::Command {
|
||||
source: codex_protocol::protocol::GuardianCommandSource::Shell,
|
||||
command: "rm -rf /tmp/example.sqlite".to_string(),
|
||||
cwd: "/tmp".into(),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
};
|
||||
let notification = guardian_auto_approval_review_notification(
|
||||
&conversation_id,
|
||||
@@ -3410,6 +3458,13 @@ mod tests {
|
||||
outgoing: outgoing.clone(),
|
||||
thread_state: thread_state.clone(),
|
||||
thread_watch_manager: thread_watch_manager.clone(),
|
||||
analytics_events_client: AnalyticsEventsClient::new(
|
||||
AuthManager::from_auth_for_testing(
|
||||
CodexAuth::create_dummy_chatgpt_auth_for_testing(),
|
||||
),
|
||||
"http://localhost".to_string(),
|
||||
Some(false),
|
||||
),
|
||||
codex_home: codex_home.path().to_path_buf(),
|
||||
};
|
||||
|
||||
@@ -3860,6 +3915,7 @@ mod tests {
|
||||
conversation_id,
|
||||
event_turn_id.clone(),
|
||||
turn_complete_event(&event_turn_id),
|
||||
/*analytics_events_client*/ None,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -3908,6 +3964,7 @@ mod tests {
|
||||
conversation_id,
|
||||
event_turn_id.clone(),
|
||||
turn_aborted_event(&event_turn_id),
|
||||
/*analytics_events_client*/ None,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -3955,6 +4012,7 @@ mod tests {
|
||||
conversation_id,
|
||||
event_turn_id.clone(),
|
||||
turn_complete_event(&event_turn_id),
|
||||
/*analytics_events_client*/ None,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -4221,6 +4279,7 @@ mod tests {
|
||||
conversation_a,
|
||||
a_turn1.clone(),
|
||||
turn_complete_event(&a_turn1),
|
||||
/*analytics_events_client*/ None,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -4242,6 +4301,7 @@ mod tests {
|
||||
conversation_b,
|
||||
b_turn1.clone(),
|
||||
turn_complete_event(&b_turn1),
|
||||
/*analytics_events_client*/ None,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
@@ -4253,6 +4313,7 @@ mod tests {
|
||||
conversation_a,
|
||||
a_turn2.clone(),
|
||||
turn_complete_event(&a_turn2),
|
||||
/*analytics_events_client*/ None,
|
||||
&outgoing,
|
||||
&thread_state,
|
||||
)
|
||||
|
||||
@@ -22,6 +22,9 @@ use chrono::DateTime;
|
||||
use chrono::SecondsFormat;
|
||||
use chrono::Utc;
|
||||
use codex_analytics::AnalyticsEventsClient;
|
||||
use codex_analytics::AnalyticsJsonRpcError;
|
||||
use codex_analytics::InputError;
|
||||
use codex_analytics::TurnSteerRequestError;
|
||||
use codex_app_server_protocol::Account;
|
||||
use codex_app_server_protocol::AccountLoginCompletedNotification;
|
||||
use codex_app_server_protocol::AccountUpdatedNotification;
|
||||
@@ -36,7 +39,7 @@ use codex_app_server_protocol::CancelLoginAccountResponse;
|
||||
use codex_app_server_protocol::CancelLoginAccountStatus;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::ClientResponse;
|
||||
use codex_app_server_protocol::CodexErrorInfo as AppServerCodexErrorInfo;
|
||||
use codex_app_server_protocol::CodexErrorInfo;
|
||||
use codex_app_server_protocol::CollaborationModeListParams;
|
||||
use codex_app_server_protocol::CollaborationModeListResponse;
|
||||
use codex_app_server_protocol::CommandExecParams;
|
||||
@@ -76,6 +79,8 @@ use codex_app_server_protocol::LoginAccountParams;
|
||||
use codex_app_server_protocol::LoginAccountResponse;
|
||||
use codex_app_server_protocol::LoginApiKeyParams;
|
||||
use codex_app_server_protocol::LogoutAccountResponse;
|
||||
use codex_app_server_protocol::MarketplaceAddParams;
|
||||
use codex_app_server_protocol::MarketplaceAddResponse;
|
||||
use codex_app_server_protocol::MarketplaceInterface;
|
||||
use codex_app_server_protocol::McpResourceReadParams;
|
||||
use codex_app_server_protocol::McpResourceReadResponse;
|
||||
@@ -228,6 +233,7 @@ use codex_core::find_thread_names_by_ids;
|
||||
use codex_core::find_thread_path_by_id_str;
|
||||
use codex_core::parse_cursor;
|
||||
use codex_core::path_utils;
|
||||
use codex_core::plugins::MarketplaceAddError;
|
||||
use codex_core::plugins::MarketplaceError;
|
||||
use codex_core::plugins::MarketplacePluginSource;
|
||||
use codex_core::plugins::OPENAI_CURATED_MARKETPLACE_NAME;
|
||||
@@ -235,6 +241,7 @@ use codex_core::plugins::PluginInstallError as CorePluginInstallError;
|
||||
use codex_core::plugins::PluginInstallRequest;
|
||||
use codex_core::plugins::PluginReadRequest;
|
||||
use codex_core::plugins::PluginUninstallError as CorePluginUninstallError;
|
||||
use codex_core::plugins::add_marketplace as add_marketplace_to_codex_home;
|
||||
use codex_core::plugins::load_plugin_apps;
|
||||
use codex_core::plugins::load_plugin_mcp_servers;
|
||||
use codex_core::read_head_for_summary;
|
||||
@@ -604,15 +611,12 @@ pub(crate) struct CodexMessageProcessorArgs {
|
||||
}
|
||||
|
||||
impl CodexMessageProcessor {
|
||||
async fn instruction_sources_from_config(config: &Config) -> Vec<PathBuf> {
|
||||
let mut paths: Vec<PathBuf> = config.user_instructions_path.iter().cloned().collect();
|
||||
async fn instruction_sources_from_config(config: &Config) -> Vec<AbsolutePathBuf> {
|
||||
let mut paths: Vec<AbsolutePathBuf> =
|
||||
config.user_instructions_path.iter().cloned().collect();
|
||||
match codex_core::discover_project_doc_paths(config, LOCAL_FS.as_ref()).await {
|
||||
Ok(project_doc_paths) => {
|
||||
paths.extend(
|
||||
project_doc_paths
|
||||
.into_iter()
|
||||
.map(|path| path.as_path().to_path_buf()),
|
||||
);
|
||||
paths.extend(project_doc_paths);
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::warn!(error = %err, "failed to discover project docs for thread response");
|
||||
@@ -638,6 +642,22 @@ impl CodexMessageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn track_error_response(
|
||||
&self,
|
||||
request_id: &ConnectionRequestId,
|
||||
error: &JSONRPCErrorError,
|
||||
error_type: Option<AnalyticsJsonRpcError>,
|
||||
) {
|
||||
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
||||
self.analytics_events_client.track_error_response(
|
||||
request_id.connection_id.0,
|
||||
request_id.request_id.clone(),
|
||||
error.clone(),
|
||||
error_type,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_thread(
|
||||
&self,
|
||||
thread_id: &str,
|
||||
@@ -927,6 +947,10 @@ impl CodexMessageProcessor {
|
||||
self.skills_list(to_connection_request_id(request_id), params)
|
||||
.await;
|
||||
}
|
||||
ClientRequest::MarketplaceAdd { request_id, params } => {
|
||||
self.marketplace_add(to_connection_request_id(request_id), params)
|
||||
.await;
|
||||
}
|
||||
ClientRequest::PluginList { request_id, params } => {
|
||||
self.plugin_list(to_connection_request_id(request_id), params)
|
||||
.await;
|
||||
@@ -2135,7 +2159,7 @@ impl CodexMessageProcessor {
|
||||
&effective_policy,
|
||||
&effective_file_system_sandbox_policy,
|
||||
effective_network_sandbox_policy,
|
||||
sandbox_cwd.as_path(),
|
||||
&sandbox_cwd,
|
||||
&codex_linux_sandbox_exe,
|
||||
use_legacy_landlock,
|
||||
) {
|
||||
@@ -3174,7 +3198,7 @@ impl CodexMessageProcessor {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut thread = summary_to_thread(summary);
|
||||
let mut thread = summary_to_thread(summary, &self.config.cwd);
|
||||
self.attach_thread_name(thread_uuid, &mut thread).await;
|
||||
thread.status = resolve_thread_status(
|
||||
self.thread_watch_manager
|
||||
@@ -3257,7 +3281,7 @@ impl CodexMessageProcessor {
|
||||
config_snapshot.session_source.clone(),
|
||||
);
|
||||
builder.model_provider = Some(model_provider.clone());
|
||||
builder.cwd = config_snapshot.cwd.clone();
|
||||
builder.cwd = config_snapshot.cwd.to_path_buf();
|
||||
builder.cli_version = Some(env!("CARGO_PKG_VERSION").to_string());
|
||||
builder.sandbox_policy = config_snapshot.sandbox_policy.clone();
|
||||
builder.approval_mode = config_snapshot.approval_policy;
|
||||
@@ -3482,7 +3506,7 @@ impl CodexMessageProcessor {
|
||||
message: format!("failed to read unarchived thread: {err}"),
|
||||
data: None,
|
||||
})?;
|
||||
Ok(summary_to_thread(summary))
|
||||
Ok(summary_to_thread(summary, &self.config.cwd))
|
||||
}
|
||||
.await;
|
||||
|
||||
@@ -3743,7 +3767,7 @@ impl CodexMessageProcessor {
|
||||
let conversation_id = summary.conversation_id;
|
||||
thread_ids.insert(conversation_id);
|
||||
|
||||
let thread = summary_to_thread(summary);
|
||||
let thread = summary_to_thread(summary, &self.config.cwd);
|
||||
status_ids.push(thread.id.clone());
|
||||
threads.push((conversation_id, thread));
|
||||
}
|
||||
@@ -3887,11 +3911,11 @@ impl CodexMessageProcessor {
|
||||
}
|
||||
|
||||
let mut thread = if let Some(summary) = db_summary {
|
||||
summary_to_thread(summary)
|
||||
summary_to_thread(summary, &self.config.cwd)
|
||||
} else if let Some(rollout_path) = rollout_path.as_ref() {
|
||||
let fallback_provider = self.config.model_provider_id.as_str();
|
||||
match read_summary_from_rollout(rollout_path, fallback_provider).await {
|
||||
Ok(summary) => summary_to_thread(summary),
|
||||
Ok(summary) => summary_to_thread(summary, &self.config.cwd),
|
||||
Err(err) => {
|
||||
self.send_internal_error(
|
||||
request_id,
|
||||
@@ -4397,9 +4421,7 @@ impl CodexMessageProcessor {
|
||||
);
|
||||
}
|
||||
let mut config_for_instruction_sources = self.config.as_ref().clone();
|
||||
if let Ok(cwd) = AbsolutePathBuf::try_from(config_snapshot.cwd.clone()) {
|
||||
config_for_instruction_sources.cwd = cwd;
|
||||
}
|
||||
config_for_instruction_sources.cwd = config_snapshot.cwd.clone();
|
||||
let instruction_sources =
|
||||
Self::instruction_sources_from_config(&config_for_instruction_sources).await;
|
||||
let thread_summary = match load_thread_summary_for_rollout(
|
||||
@@ -4782,7 +4804,7 @@ impl CodexMessageProcessor {
|
||||
.await
|
||||
{
|
||||
Ok(summary) => {
|
||||
let mut thread = summary_to_thread(summary);
|
||||
let mut thread = summary_to_thread(summary, &self.config.cwd);
|
||||
thread.forked_from_id =
|
||||
forked_from_id_from_rollout(fork_rollout_path.as_path()).await;
|
||||
thread
|
||||
@@ -5320,7 +5342,11 @@ impl CodexMessageProcessor {
|
||||
&self,
|
||||
config: &Config,
|
||||
) -> Result<(), JSONRPCErrorError> {
|
||||
let configured_servers = self.thread_manager.mcp_manager().configured_servers(config);
|
||||
let configured_servers = self
|
||||
.thread_manager
|
||||
.mcp_manager()
|
||||
.configured_servers(config)
|
||||
.await;
|
||||
let mcp_servers = match serde_json::to_value(configured_servers) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
@@ -5380,7 +5406,8 @@ impl CodexMessageProcessor {
|
||||
let configured_servers = self
|
||||
.thread_manager
|
||||
.mcp_manager()
|
||||
.configured_servers(&config);
|
||||
.configured_servers(&config)
|
||||
.await;
|
||||
let Some(server) = configured_servers.get(&name) else {
|
||||
let error = JSONRPCErrorError {
|
||||
code: INVALID_REQUEST_ERROR_CODE,
|
||||
@@ -5482,7 +5509,9 @@ impl CodexMessageProcessor {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mcp_config = config.to_mcp_config(self.thread_manager.plugins_manager().as_ref());
|
||||
let mcp_config = config
|
||||
.to_mcp_config(self.thread_manager.plugins_manager().as_ref())
|
||||
.await;
|
||||
let auth = self.auth_manager.auth().await;
|
||||
|
||||
tokio::spawn(async move {
|
||||
@@ -6263,6 +6292,23 @@ impl CodexMessageProcessor {
|
||||
};
|
||||
let skills_manager = self.thread_manager.skills_manager();
|
||||
let plugins_manager = self.thread_manager.plugins_manager();
|
||||
let fs = match self.thread_manager.environment_manager().current().await {
|
||||
Ok(Some(environment)) => Some(environment.get_filesystem()),
|
||||
Ok(None) => None,
|
||||
Err(err) => {
|
||||
self.outgoing
|
||||
.send_error(
|
||||
request_id,
|
||||
JSONRPCErrorError {
|
||||
code: INTERNAL_ERROR_CODE,
|
||||
message: format!("failed to create environment: {err}"),
|
||||
data: None,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
let cli_overrides = self.current_cli_overrides();
|
||||
let mut data = Vec::new();
|
||||
for cwd in cwds {
|
||||
@@ -6307,18 +6353,25 @@ impl CodexMessageProcessor {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let effective_skill_roots = plugins_manager.effective_skill_roots_for_layer_stack(
|
||||
&config_layer_stack,
|
||||
config.features.enabled(Feature::Plugins),
|
||||
);
|
||||
let effective_skill_roots = plugins_manager
|
||||
.effective_skill_roots_for_layer_stack(
|
||||
&config_layer_stack,
|
||||
config.features.enabled(Feature::Plugins),
|
||||
)
|
||||
.await;
|
||||
let skills_input = codex_core::skills::SkillsLoadInput::new(
|
||||
cwd_abs,
|
||||
cwd_abs.clone(),
|
||||
effective_skill_roots,
|
||||
config_layer_stack,
|
||||
config.bundled_skills_enabled(),
|
||||
);
|
||||
let outcome = skills_manager
|
||||
.skills_for_cwd_with_extra_user_roots(&skills_input, force_reload, extra_roots)
|
||||
.skills_for_cwd_with_extra_user_roots(
|
||||
&skills_input,
|
||||
force_reload,
|
||||
extra_roots,
|
||||
fs.clone(),
|
||||
)
|
||||
.await;
|
||||
let errors = errors_to_info(&outcome.errors);
|
||||
let skills = skills_to_info(&outcome.skills, &outcome.disabled_paths);
|
||||
@@ -6483,6 +6536,39 @@ impl CodexMessageProcessor {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn marketplace_add(&self, request_id: ConnectionRequestId, params: MarketplaceAddParams) {
|
||||
let result = add_marketplace_to_codex_home(
|
||||
self.config.codex_home.to_path_buf(),
|
||||
codex_core::plugins::MarketplaceAddRequest {
|
||||
source: params.source,
|
||||
ref_name: params.ref_name,
|
||||
sparse_paths: params.sparse_paths.unwrap_or_default(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(outcome) => {
|
||||
self.outgoing
|
||||
.send_response(
|
||||
request_id,
|
||||
MarketplaceAddResponse {
|
||||
marketplace_name: outcome.marketplace_name,
|
||||
installed_root: outcome.installed_root,
|
||||
already_added: outcome.already_added,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(MarketplaceAddError::InvalidRequest(message)) => {
|
||||
self.send_invalid_request_error(request_id, message).await;
|
||||
}
|
||||
Err(MarketplaceAddError::Internal(message)) => {
|
||||
self.send_internal_error(request_id, message).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn plugin_read(&self, request_id: ConnectionRequestId, params: PluginReadParams) {
|
||||
let plugins_manager = self.thread_manager.plugins_manager();
|
||||
let PluginReadParams {
|
||||
@@ -6503,26 +6589,16 @@ impl CodexMessageProcessor {
|
||||
plugin_name,
|
||||
marketplace_path,
|
||||
};
|
||||
let config_for_read = config.clone();
|
||||
let outcome = match tokio::task::spawn_blocking(move || {
|
||||
plugins_manager.read_plugin_for_config(&config_for_read, &request)
|
||||
})
|
||||
.await
|
||||
let outcome = match plugins_manager
|
||||
.read_plugin_for_config(&config, &request)
|
||||
.await
|
||||
{
|
||||
Ok(Ok(outcome)) => outcome,
|
||||
Ok(Err(err)) => {
|
||||
Ok(outcome) => outcome,
|
||||
Err(err) => {
|
||||
self.send_marketplace_error(request_id, err, "read plugin details")
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
self.send_internal_error(
|
||||
request_id,
|
||||
format!("failed to read plugin details: {err}"),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
let app_summaries =
|
||||
plugin_app_helpers::load_plugin_app_summaries(&config, &outcome.plugin.apps).await;
|
||||
@@ -6663,7 +6739,8 @@ impl CodexMessageProcessor {
|
||||
|
||||
self.clear_plugin_related_caches();
|
||||
|
||||
let plugin_mcp_servers = load_plugin_mcp_servers(result.installed_path.as_path());
|
||||
let plugin_mcp_servers =
|
||||
load_plugin_mcp_servers(result.installed_path.as_path()).await;
|
||||
|
||||
if !plugin_mcp_servers.is_empty() {
|
||||
if let Err(err) = self.queue_mcp_server_refresh_for_config(&config).await {
|
||||
@@ -6676,7 +6753,7 @@ impl CodexMessageProcessor {
|
||||
.await;
|
||||
}
|
||||
|
||||
let plugin_apps = load_plugin_apps(result.installed_path.as_path());
|
||||
let plugin_apps = load_plugin_apps(result.installed_path.as_path()).await;
|
||||
let auth = self.auth_manager.auth().await;
|
||||
let apps_needing_auth = if plugin_apps.is_empty()
|
||||
|| !config.features.apps_enabled_for_auth(
|
||||
@@ -6879,12 +6956,18 @@ impl CodexMessageProcessor {
|
||||
app_server_client_version: Option<String>,
|
||||
) {
|
||||
if let Err(error) = Self::validate_v2_input_limit(¶ms.input) {
|
||||
self.track_error_response(
|
||||
&request_id,
|
||||
&error,
|
||||
Some(AnalyticsJsonRpcError::Input(InputError::TooLarge)),
|
||||
);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
return;
|
||||
}
|
||||
let (_, thread) = match self.load_thread(¶ms.thread_id).await {
|
||||
Ok(v) => v,
|
||||
Err(error) => {
|
||||
self.track_error_response(&request_id, &error, /*error_type*/ None);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
return;
|
||||
}
|
||||
@@ -6896,6 +6979,7 @@ impl CodexMessageProcessor {
|
||||
)
|
||||
.await
|
||||
{
|
||||
self.track_error_response(&request_id, &error, /*error_type*/ None);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
return;
|
||||
}
|
||||
@@ -6979,6 +7063,15 @@ impl CodexMessageProcessor {
|
||||
};
|
||||
|
||||
let response = TurnStartResponse { turn };
|
||||
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
||||
self.analytics_events_client.track_response(
|
||||
request_id.connection_id.0,
|
||||
ClientResponse::TurnStart {
|
||||
request_id: request_id.request_id.clone(),
|
||||
response: response.clone(),
|
||||
},
|
||||
);
|
||||
}
|
||||
self.outgoing.send_response(request_id, response).await;
|
||||
}
|
||||
Err(err) => {
|
||||
@@ -6987,6 +7080,7 @@ impl CodexMessageProcessor {
|
||||
message: format!("failed to start turn: {err}"),
|
||||
data: None,
|
||||
};
|
||||
self.track_error_response(&request_id, &error, /*error_type*/ None);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
}
|
||||
}
|
||||
@@ -7060,6 +7154,7 @@ impl CodexMessageProcessor {
|
||||
let (_, thread) = match self.load_thread(¶ms.thread_id).await {
|
||||
Ok(v) => v,
|
||||
Err(error) => {
|
||||
self.track_error_response(&request_id, &error, /*error_type*/ None);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
return;
|
||||
}
|
||||
@@ -7077,6 +7172,11 @@ impl CodexMessageProcessor {
|
||||
.record_request_turn_id(&request_id, ¶ms.expected_turn_id)
|
||||
.await;
|
||||
if let Err(error) = Self::validate_v2_input_limit(¶ms.input) {
|
||||
self.track_error_response(
|
||||
&request_id,
|
||||
&error,
|
||||
Some(AnalyticsJsonRpcError::Input(InputError::TooLarge)),
|
||||
);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
return;
|
||||
}
|
||||
@@ -7097,36 +7197,51 @@ impl CodexMessageProcessor {
|
||||
{
|
||||
Ok(turn_id) => {
|
||||
let response = TurnSteerResponse { turn_id };
|
||||
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
||||
self.analytics_events_client.track_response(
|
||||
request_id.connection_id.0,
|
||||
ClientResponse::TurnSteer {
|
||||
request_id: request_id.request_id.clone(),
|
||||
response: response.clone(),
|
||||
},
|
||||
);
|
||||
}
|
||||
self.outgoing.send_response(request_id, response).await;
|
||||
}
|
||||
Err(err) => {
|
||||
let (code, message, data) = match err {
|
||||
let (code, message, data, error_type) = match err {
|
||||
SteerInputError::NoActiveTurn(_) => (
|
||||
INVALID_REQUEST_ERROR_CODE,
|
||||
"no active turn to steer".to_string(),
|
||||
None,
|
||||
Some(AnalyticsJsonRpcError::TurnSteer(
|
||||
TurnSteerRequestError::NoActiveTurn,
|
||||
)),
|
||||
),
|
||||
SteerInputError::ExpectedTurnMismatch { expected, actual } => (
|
||||
INVALID_REQUEST_ERROR_CODE,
|
||||
format!("expected active turn id `{expected}` but found `{actual}`"),
|
||||
None,
|
||||
Some(AnalyticsJsonRpcError::TurnSteer(
|
||||
TurnSteerRequestError::ExpectedTurnMismatch,
|
||||
)),
|
||||
),
|
||||
SteerInputError::ActiveTurnNotSteerable { turn_kind } => {
|
||||
let message = match turn_kind {
|
||||
codex_protocol::protocol::NonSteerableTurnKind::Review => {
|
||||
"cannot steer a review turn".to_string()
|
||||
}
|
||||
codex_protocol::protocol::NonSteerableTurnKind::Compact => {
|
||||
"cannot steer a compact turn".to_string()
|
||||
}
|
||||
let (message, turn_steer_error) = match turn_kind {
|
||||
codex_protocol::protocol::NonSteerableTurnKind::Review => (
|
||||
"cannot steer a review turn".to_string(),
|
||||
TurnSteerRequestError::NonSteerableReview,
|
||||
),
|
||||
codex_protocol::protocol::NonSteerableTurnKind::Compact => (
|
||||
"cannot steer a compact turn".to_string(),
|
||||
TurnSteerRequestError::NonSteerableCompact,
|
||||
),
|
||||
};
|
||||
let error = TurnError {
|
||||
message: message.clone(),
|
||||
codex_error_info: Some(
|
||||
AppServerCodexErrorInfo::ActiveTurnNotSteerable {
|
||||
turn_kind: turn_kind.into(),
|
||||
},
|
||||
),
|
||||
codex_error_info: Some(CodexErrorInfo::ActiveTurnNotSteerable {
|
||||
turn_kind: turn_kind.into(),
|
||||
}),
|
||||
additional_details: None,
|
||||
};
|
||||
let data = match serde_json::to_value(error) {
|
||||
@@ -7139,12 +7254,18 @@ impl CodexMessageProcessor {
|
||||
None
|
||||
}
|
||||
};
|
||||
(INVALID_REQUEST_ERROR_CODE, message, data)
|
||||
(
|
||||
INVALID_REQUEST_ERROR_CODE,
|
||||
message,
|
||||
data,
|
||||
Some(AnalyticsJsonRpcError::TurnSteer(turn_steer_error)),
|
||||
)
|
||||
}
|
||||
SteerInputError::EmptyInput => (
|
||||
INVALID_REQUEST_ERROR_CODE,
|
||||
"input must not be empty".to_string(),
|
||||
None,
|
||||
Some(AnalyticsJsonRpcError::Input(InputError::Empty)),
|
||||
),
|
||||
};
|
||||
let error = JSONRPCErrorError {
|
||||
@@ -7152,6 +7273,7 @@ impl CodexMessageProcessor {
|
||||
message,
|
||||
data,
|
||||
};
|
||||
self.track_error_response(&request_id, &error, error_type);
|
||||
self.outgoing.send_error(request_id, error).await;
|
||||
}
|
||||
}
|
||||
@@ -7218,6 +7340,7 @@ impl CodexMessageProcessor {
|
||||
&request_id,
|
||||
thread.as_ref(),
|
||||
Op::RealtimeConversationStart(ConversationStartParams {
|
||||
output_modality: params.output_modality,
|
||||
prompt: params.prompt,
|
||||
session_id: params.session_id,
|
||||
transport: params.transport.map(|transport| match transport {
|
||||
@@ -7509,7 +7632,7 @@ impl CodexMessageProcessor {
|
||||
if let Some(rollout_path) = review_thread.rollout_path() {
|
||||
match read_summary_from_rollout(rollout_path.as_path(), fallback_provider).await {
|
||||
Ok(summary) => {
|
||||
let mut thread = summary_to_thread(summary);
|
||||
let mut thread = summary_to_thread(summary, &self.config.cwd);
|
||||
self.thread_watch_manager
|
||||
.upsert_thread_silently(thread.clone())
|
||||
.await;
|
||||
@@ -7899,6 +8022,9 @@ impl CodexMessageProcessor {
|
||||
conversation_id,
|
||||
conversation.clone(),
|
||||
thread_manager.clone(),
|
||||
listener_task_context
|
||||
.general_analytics_enabled
|
||||
.then(|| listener_task_context.analytics_events_client.clone()),
|
||||
thread_outgoing,
|
||||
thread_state.clone(),
|
||||
thread_watch_manager.clone(),
|
||||
@@ -8708,7 +8834,7 @@ fn collect_resume_override_mismatches(
|
||||
}
|
||||
if let Some(requested_cwd) = request.cwd.as_deref() {
|
||||
let requested_cwd_path = std::path::PathBuf::from(requested_cwd);
|
||||
if requested_cwd_path != config_snapshot.cwd {
|
||||
if requested_cwd_path != config_snapshot.cwd.as_path() {
|
||||
mismatch_details.push(format!(
|
||||
"cwd requested={} active={}",
|
||||
requested_cwd_path.display(),
|
||||
@@ -9492,7 +9618,7 @@ async fn load_thread_summary_for_rollout(
|
||||
) -> std::result::Result<Thread, String> {
|
||||
let mut thread = read_summary_from_rollout(rollout_path, fallback_provider)
|
||||
.await
|
||||
.map(summary_to_thread)
|
||||
.map(|summary| summary_to_thread(summary, &config.cwd))
|
||||
.map_err(|err| {
|
||||
format!(
|
||||
"failed to load rollout `{}` for thread {thread_id}: {err}",
|
||||
@@ -9503,10 +9629,13 @@ async fn load_thread_summary_for_rollout(
|
||||
if let Some(persisted_metadata) = persisted_metadata {
|
||||
merge_mutable_thread_metadata(
|
||||
&mut thread,
|
||||
summary_to_thread(summary_from_thread_metadata(persisted_metadata)),
|
||||
summary_to_thread(
|
||||
summary_from_thread_metadata(persisted_metadata),
|
||||
&config.cwd,
|
||||
),
|
||||
);
|
||||
} else if let Some(summary) = read_summary_from_state_db_by_thread_id(config, thread_id).await {
|
||||
merge_mutable_thread_metadata(&mut thread, summary_to_thread(summary));
|
||||
merge_mutable_thread_metadata(&mut thread, summary_to_thread(summary, &config.cwd));
|
||||
}
|
||||
let title = if let Some(metadata) = persisted_metadata {
|
||||
non_empty_title(metadata)
|
||||
@@ -9594,7 +9723,7 @@ async fn read_updated_at(path: &Path, created_at: Option<&str>) -> Option<String
|
||||
.and_then(|meta| meta.modified().ok())
|
||||
.map(|modified| {
|
||||
let updated_at: DateTime<Utc> = modified.into();
|
||||
updated_at.to_rfc3339_opts(SecondsFormat::Secs, true)
|
||||
updated_at.to_rfc3339_opts(SecondsFormat::Millis, true)
|
||||
});
|
||||
updated_at.or_else(|| created_at.map(str::to_string))
|
||||
}
|
||||
@@ -9626,7 +9755,10 @@ fn build_thread_from_snapshot(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn summary_to_thread(summary: ConversationSummary) -> Thread {
|
||||
pub(crate) fn summary_to_thread(
|
||||
summary: ConversationSummary,
|
||||
fallback_cwd: &AbsolutePathBuf,
|
||||
) -> Thread {
|
||||
let ConversationSummary {
|
||||
conversation_id,
|
||||
path,
|
||||
@@ -9647,6 +9779,15 @@ pub(crate) fn summary_to_thread(summary: ConversationSummary) -> Thread {
|
||||
branch: info.branch,
|
||||
origin_url: info.origin_url,
|
||||
});
|
||||
let cwd =
|
||||
AbsolutePathBuf::relative_to_current_dir(path_utils::normalize_for_native_workdir(cwd))
|
||||
.unwrap_or_else(|err| {
|
||||
warn!(
|
||||
path = %path.display(),
|
||||
"failed to normalize thread cwd while summarizing thread: {err}"
|
||||
);
|
||||
fallback_cwd.clone()
|
||||
});
|
||||
|
||||
Thread {
|
||||
id: conversation_id.to_string(),
|
||||
@@ -9680,6 +9821,8 @@ mod tests {
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_utils_absolute_path::test_support::PathBufExt;
|
||||
use codex_utils_absolute_path::test_support::test_path_buf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use std::path::PathBuf;
|
||||
@@ -9814,7 +9957,7 @@ mod tests {
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::OnRequest,
|
||||
approvals_reviewer: codex_protocol::config_types::ApprovalsReviewer::User,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
cwd: test_path_buf("/tmp").abs(),
|
||||
ephemeral: false,
|
||||
reasoning_effort: None,
|
||||
personality: None,
|
||||
@@ -9845,6 +9988,22 @@ mod tests {
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn summary_from_thread_metadata_formats_protocol_timestamps_as_seconds() -> Result<()> {
|
||||
let mut metadata =
|
||||
test_thread_metadata(/*model*/ None, /*reasoning_effort*/ None)?;
|
||||
metadata.created_at =
|
||||
DateTime::parse_from_rfc3339("2025-09-05T16:53:11.123Z")?.with_timezone(&Utc);
|
||||
metadata.updated_at =
|
||||
DateTime::parse_from_rfc3339("2025-09-05T16:53:12.456Z")?.with_timezone(&Utc);
|
||||
|
||||
let summary = summary_from_thread_metadata(&metadata);
|
||||
|
||||
assert_eq!(summary.timestamp, Some("2025-09-05T16:53:11Z".to_string()));
|
||||
assert_eq!(summary.updated_at, Some("2025-09-05T16:53:12Z".to_string()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_persisted_resume_metadata_prefers_persisted_model_and_reasoning_effort() -> Result<()>
|
||||
{
|
||||
@@ -10104,7 +10263,7 @@ mod tests {
|
||||
let expected = ConversationSummary {
|
||||
conversation_id,
|
||||
timestamp: Some(timestamp.clone()),
|
||||
updated_at: Some("2025-09-05T16:53:11Z".to_string()),
|
||||
updated_at: Some(timestamp),
|
||||
path: path.clone(),
|
||||
preview: String::new(),
|
||||
model_provider: "fallback".to_string(),
|
||||
@@ -10158,7 +10317,8 @@ mod tests {
|
||||
fs::write(&path, format!("{}\n", serde_json::to_string(&line)?))?;
|
||||
|
||||
let summary = read_summary_from_rollout(path.as_path(), "fallback").await?;
|
||||
let thread = summary_to_thread(summary);
|
||||
let fallback_cwd = AbsolutePathBuf::from_absolute_path("/")?;
|
||||
let thread = summary_to_thread(summary, &fallback_cwd);
|
||||
|
||||
assert_eq!(thread.agent_nickname, Some("atlas".to_string()));
|
||||
assert_eq!(thread.agent_role, Some("explorer".to_string()));
|
||||
@@ -10292,7 +10452,8 @@ mod tests {
|
||||
/*git_origin_url*/ None,
|
||||
);
|
||||
|
||||
let thread = summary_to_thread(summary);
|
||||
let fallback_cwd = AbsolutePathBuf::from_absolute_path("/")?;
|
||||
let thread = summary_to_thread(summary, &fallback_cwd);
|
||||
|
||||
assert_eq!(thread.agent_nickname, Some("atlas".to_string()));
|
||||
assert_eq!(thread.agent_role, Some("explorer".to_string()));
|
||||
|
||||
@@ -210,7 +210,7 @@ impl ConfigApi {
|
||||
.write_value(params)
|
||||
.await
|
||||
.map_err(map_error)?;
|
||||
self.emit_plugin_toggle_events(pending_changes);
|
||||
self.emit_plugin_toggle_events(pending_changes).await;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ impl ConfigApi {
|
||||
.batch_write(params)
|
||||
.await
|
||||
.map_err(map_error)?;
|
||||
self.emit_plugin_toggle_events(pending_changes);
|
||||
self.emit_plugin_toggle_events(pending_changes).await;
|
||||
if reload_user_config {
|
||||
self.user_config_reloader.reload_user_config().await;
|
||||
}
|
||||
@@ -299,13 +299,16 @@ impl ConfigApi {
|
||||
Ok(ExperimentalFeatureEnablementSetResponse { enablement })
|
||||
}
|
||||
|
||||
fn emit_plugin_toggle_events(&self, pending_changes: std::collections::BTreeMap<String, bool>) {
|
||||
async fn emit_plugin_toggle_events(
|
||||
&self,
|
||||
pending_changes: std::collections::BTreeMap<String, bool>,
|
||||
) {
|
||||
for (plugin_id, enabled) in pending_changes {
|
||||
let Ok(plugin_id) = PluginId::parse(&plugin_id) else {
|
||||
continue;
|
||||
};
|
||||
let metadata =
|
||||
installed_plugin_telemetry_metadata(self.codex_home.as_path(), &plugin_id);
|
||||
installed_plugin_telemetry_metadata(self.codex_home.as_path(), &plugin_id).await;
|
||||
if enabled {
|
||||
self.analytics_events_client.track_plugin_enabled(metadata);
|
||||
} else {
|
||||
@@ -449,7 +452,6 @@ fn map_network_requirements_to_api(
|
||||
.collect()
|
||||
}),
|
||||
managed_allowed_domains_only: network.managed_allowed_domains_only,
|
||||
danger_full_access_denylist_only: network.danger_full_access_denylist_only,
|
||||
allowed_domains,
|
||||
denied_domains,
|
||||
unix_sockets: network.unix_sockets.map(|unix_sockets| {
|
||||
@@ -595,7 +597,6 @@ mod tests {
|
||||
]),
|
||||
}),
|
||||
managed_allowed_domains_only: Some(false),
|
||||
danger_full_access_denylist_only: Some(true),
|
||||
unix_sockets: Some(CoreNetworkUnixSocketPermissionsToml {
|
||||
entries: std::collections::BTreeMap::from([(
|
||||
"/tmp/proxy.sock".to_string(),
|
||||
@@ -655,7 +656,6 @@ mod tests {
|
||||
("example.com".to_string(), NetworkDomainPermission::Deny),
|
||||
])),
|
||||
managed_allowed_domains_only: Some(false),
|
||||
danger_full_access_denylist_only: Some(true),
|
||||
allowed_domains: Some(vec!["api.openai.com".to_string()]),
|
||||
denied_domains: Some(vec!["example.com".to_string()]),
|
||||
unix_sockets: Some(std::collections::BTreeMap::from([(
|
||||
@@ -690,7 +690,6 @@ mod tests {
|
||||
dangerously_allow_all_unix_sockets: None,
|
||||
domains: None,
|
||||
managed_allowed_domains_only: None,
|
||||
danger_full_access_denylist_only: None,
|
||||
unix_sockets: Some(CoreNetworkUnixSocketPermissionsToml {
|
||||
entries: std::collections::BTreeMap::from([(
|
||||
"/tmp/ignored.sock".to_string(),
|
||||
@@ -714,7 +713,6 @@ mod tests {
|
||||
dangerously_allow_all_unix_sockets: None,
|
||||
domains: None,
|
||||
managed_allowed_domains_only: None,
|
||||
danger_full_access_denylist_only: None,
|
||||
allowed_domains: None,
|
||||
denied_domains: None,
|
||||
unix_sockets: Some(std::collections::BTreeMap::from([(
|
||||
|
||||
@@ -6,6 +6,8 @@ use codex_app_server_protocol::ExternalAgentConfigImportResponse;
|
||||
use codex_app_server_protocol::ExternalAgentConfigMigrationItem;
|
||||
use codex_app_server_protocol::ExternalAgentConfigMigrationItemType;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::MigrationDetails;
|
||||
use codex_app_server_protocol::PluginsMigration;
|
||||
use codex_core::external_agent_config::ExternalAgentConfigDetectOptions;
|
||||
use codex_core::external_agent_config::ExternalAgentConfigMigrationItem as CoreMigrationItem;
|
||||
use codex_core::external_agent_config::ExternalAgentConfigMigrationItemType as CoreMigrationItemType;
|
||||
@@ -51,12 +53,25 @@ impl ExternalAgentConfigApi {
|
||||
CoreMigrationItemType::AgentsMd => {
|
||||
ExternalAgentConfigMigrationItemType::AgentsMd
|
||||
}
|
||||
CoreMigrationItemType::Plugins => {
|
||||
ExternalAgentConfigMigrationItemType::Plugins
|
||||
}
|
||||
CoreMigrationItemType::McpServerConfig => {
|
||||
ExternalAgentConfigMigrationItemType::McpServerConfig
|
||||
}
|
||||
},
|
||||
description: migration_item.description,
|
||||
cwd: migration_item.cwd,
|
||||
details: migration_item.details.map(|details| MigrationDetails {
|
||||
plugins: details
|
||||
.plugins
|
||||
.into_iter()
|
||||
.map(|plugin| PluginsMigration {
|
||||
marketplace_name: plugin.marketplace_name,
|
||||
plugin_names: plugin.plugin_names,
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
@@ -82,15 +97,33 @@ impl ExternalAgentConfigApi {
|
||||
ExternalAgentConfigMigrationItemType::AgentsMd => {
|
||||
CoreMigrationItemType::AgentsMd
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Plugins => {
|
||||
CoreMigrationItemType::Plugins
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::McpServerConfig => {
|
||||
CoreMigrationItemType::McpServerConfig
|
||||
}
|
||||
},
|
||||
description: migration_item.description,
|
||||
cwd: migration_item.cwd,
|
||||
details: migration_item.details.map(|details| {
|
||||
codex_core::external_agent_config::MigrationDetails {
|
||||
plugins: details
|
||||
.plugins
|
||||
.into_iter()
|
||||
.map(|plugin| {
|
||||
codex_core::external_agent_config::PluginsMigration {
|
||||
marketplace_name: plugin.marketplace_name,
|
||||
plugin_names: plugin.plugin_names,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.await
|
||||
.map_err(map_io_error)?;
|
||||
|
||||
Ok(ExternalAgentConfigImportResponse {})
|
||||
|
||||
@@ -99,6 +99,7 @@ impl FsApi {
|
||||
Ok(FsGetMetadataResponse {
|
||||
is_directory: metadata.is_directory,
|
||||
is_file: metadata.is_file,
|
||||
is_symlink: metadata.is_symlink,
|
||||
created_at_ms: metadata.created_at_ms,
|
||||
modified_at_ms: metadata.modified_at_ms,
|
||||
})
|
||||
|
||||
@@ -14,7 +14,6 @@ use codex_core::file_watcher::FileWatcherSubscriber;
|
||||
use codex_core::file_watcher::Receiver;
|
||||
use codex_core::file_watcher::WatchPath;
|
||||
use codex_core::file_watcher::WatchRegistration;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::hash_map::Entry;
|
||||
@@ -128,7 +127,7 @@ impl FsWatchManager {
|
||||
};
|
||||
let outgoing = self.outgoing.clone();
|
||||
let (subscriber, rx) = self.file_watcher.add_subscriber();
|
||||
let watch_root = params.path.to_path_buf().clone();
|
||||
let watch_root = params.path.clone();
|
||||
let registration = subscriber.register_paths(vec![WatchPath {
|
||||
path: params.path.to_path_buf(),
|
||||
recursive: false,
|
||||
@@ -166,7 +165,7 @@ impl FsWatchManager {
|
||||
let mut changed_paths = event
|
||||
.paths
|
||||
.into_iter()
|
||||
.map(|path| AbsolutePathBuf::resolve_path_against_base(&path, &watch_root))
|
||||
.map(|path| watch_root.join(path))
|
||||
.collect::<Vec<_>>();
|
||||
changed_paths.sort_by(|left, right| left.as_path().cmp(right.as_path()));
|
||||
if !changed_paths.is_empty() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user