mirror of
https://github.com/openai/codex.git
synced 2026-03-12 17:43:22 +00:00
Compare commits
123 Commits
test-asdgf
...
dev/cc/mul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b69f643dc0 | ||
|
|
f50e88db82 | ||
|
|
8791f0ab9a | ||
|
|
f548309797 | ||
|
|
5a89660ae4 | ||
|
|
5259e5e236 | ||
|
|
f5bb338fdb | ||
|
|
c32c445f1c | ||
|
|
52a3bde6cc | ||
|
|
8f8a0f55ce | ||
|
|
65b325159d | ||
|
|
7b2cee53db | ||
|
|
fa1242c83b | ||
|
|
548583198a | ||
|
|
7f22329389 | ||
|
|
fd4a673525 | ||
|
|
f385199cc0 | ||
|
|
180a5820fc | ||
|
|
12ee9eb6e0 | ||
|
|
a4d884c767 | ||
|
|
39c1bc1c68 | ||
|
|
31bf1dbe63 | ||
|
|
01792a4c61 | ||
|
|
da74da6684 | ||
|
|
c8446d7cf3 | ||
|
|
285b3a5143 | ||
|
|
8a099b3dfb | ||
|
|
e77b2fd925 | ||
|
|
9b5078d3e8 | ||
|
|
c1a424691f | ||
|
|
83b22bb612 | ||
|
|
2621ba17e3 | ||
|
|
889b4796fc | ||
|
|
8ac27b2a16 | ||
|
|
07c22d20f6 | ||
|
|
ce1d9abf11 | ||
|
|
b1dddcb76e | ||
|
|
a67660da2d | ||
|
|
3d41ff0b77 | ||
|
|
ee8f84153e | ||
|
|
d5694529ca | ||
|
|
722e8f08e1 | ||
|
|
91ca20c7c3 | ||
|
|
3d4628c9c4 | ||
|
|
d751e68f44 | ||
|
|
f2d66fadd8 | ||
|
|
b7f8e9195a | ||
|
|
3b1c78a5c5 | ||
|
|
4ac6042850 | ||
|
|
c4d35084f5 | ||
|
|
52a7f4b68b | ||
|
|
00ea8aa7ee | ||
|
|
f9cba5cb16 | ||
|
|
026cfde023 | ||
|
|
7144f84c69 | ||
|
|
f3f47cf455 | ||
|
|
b39ae9501f | ||
|
|
6b7253b123 | ||
|
|
aa6a57dfa2 | ||
|
|
2e24be2134 | ||
|
|
c6343e0649 | ||
|
|
79307b7933 | ||
|
|
566e4cee4b | ||
|
|
a9ae43621b | ||
|
|
0c33af7746 | ||
|
|
710682598d | ||
|
|
772259b01f | ||
|
|
d71e042694 | ||
|
|
63597d1b2d | ||
|
|
244b2d53f4 | ||
|
|
da616136cc | ||
|
|
a3cd9f16f5 | ||
|
|
aa04ea6bd7 | ||
|
|
a5af11211a | ||
|
|
1165a16e6f | ||
|
|
b0cbc25a48 | ||
|
|
6da84efed8 | ||
|
|
c1defcc98c | ||
|
|
66e71cce11 | ||
|
|
d309c102ef | ||
|
|
d241dc598c | ||
|
|
831ee51c86 | ||
|
|
42f20a6845 | ||
|
|
44ecc527cb | ||
|
|
da991bdf3a | ||
|
|
6ad448b658 | ||
|
|
0334ddeccb | ||
|
|
fefd01b9e0 | ||
|
|
e03e9b63ea | ||
|
|
ad57505ef5 | ||
|
|
203a70a191 | ||
|
|
b15cfe9329 | ||
|
|
c1f3ef16ec | ||
|
|
75e608343c | ||
|
|
4a0e6dc916 | ||
|
|
10bf6008f4 | ||
|
|
0dc242a672 | ||
|
|
6b68d1ef66 | ||
|
|
5d9db0f995 | ||
|
|
6052558a01 | ||
|
|
615ed0e437 | ||
|
|
3f1280ce1c | ||
|
|
f23fcd6ced | ||
|
|
2bc3e52a91 | ||
|
|
06f82c123c | ||
|
|
05332b0e96 | ||
|
|
e6b93841c5 | ||
|
|
4ad3b59de3 | ||
|
|
f41b1638c9 | ||
|
|
340f9c9ecb | ||
|
|
da3689f0ef | ||
|
|
a684a36091 | ||
|
|
1f150eda8b | ||
|
|
7ba1fccfc1 | ||
|
|
a30edb6c17 | ||
|
|
dcc4d7b634 | ||
|
|
dc19e78962 | ||
|
|
3b5fe5ca35 | ||
|
|
46b8d127cf | ||
|
|
07a30da3fb | ||
|
|
a4a9536fd7 | ||
|
|
590cfa6176 | ||
|
|
bf5c2f48a5 |
8
.github/blob-size-allowlist.txt
vendored
Normal file
8
.github/blob-size-allowlist.txt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Paths are matched exactly, relative to the repository root.
|
||||
# Keep this list short and limited to intentional large checked-in assets.
|
||||
|
||||
.github/codex-cli-splash.png
|
||||
MODULE.bazel.lock
|
||||
codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
|
||||
codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
|
||||
codex-rs/tui/tests/fixtures/oss-story.jsonl
|
||||
29
.github/workflows/blob-size-policy.yml
vendored
Normal file
29
.github/workflows/blob-size-policy.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: blob-size-policy
|
||||
|
||||
on:
|
||||
pull_request: {}
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Blob size policy
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine PR comparison range
|
||||
id: range
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "base=$(git rev-parse HEAD^1)" >> "$GITHUB_OUTPUT"
|
||||
echo "head=$(git rev-parse HEAD^2)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Check changed blob sizes
|
||||
run: |
|
||||
python3 scripts/check_blob_size.py \
|
||||
--base "${{ steps.range.outputs.base }}" \
|
||||
--head "${{ steps.range.outputs.head }}" \
|
||||
--max-bytes 512000 \
|
||||
--allowlist .github/blob-size-allowlist.txt
|
||||
4
.github/workflows/sdk.yml
vendored
4
.github/workflows/sdk.yml
vendored
@@ -7,7 +7,9 @@ on:
|
||||
|
||||
jobs:
|
||||
sdks:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on:
|
||||
group: codex-runners
|
||||
labels: codex-linux-x64
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
||||
11
AGENTS.md
11
AGENTS.md
@@ -20,6 +20,17 @@ In the codex-rs folder where the rust code lives:
|
||||
- After dependency changes, run `just bazel-lock-check` from the repo root so lockfile drift is caught
|
||||
locally before CI.
|
||||
- Do not create small helper methods that are referenced only once.
|
||||
- Avoid large modules:
|
||||
- Prefer adding new modules instead of growing existing ones.
|
||||
- Target Rust modules under 500 LoC, excluding tests.
|
||||
- If a file exceeds roughly 800 LoC, add new functionality in a new module instead of extending
|
||||
the existing file unless there is a strong documented reason not to.
|
||||
- This rule applies especially to high-touch files that already attract unrelated changes, such
|
||||
as `codex-rs/tui/src/app.rs`, `codex-rs/tui/src/bottom_pane/chat_composer.rs`,
|
||||
`codex-rs/tui/src/bottom_pane/footer.rs`, `codex-rs/tui/src/chatwidget.rs`,
|
||||
`codex-rs/tui/src/bottom_pane/mod.rs`, and similarly central orchestration modules.
|
||||
- When extracting code from a large module, move the related tests and module/type docs toward
|
||||
the new implementation so the invariants stay close to the code that owns them.
|
||||
|
||||
Run `just fmt` (in `codex-rs` directory) automatically after you have finished making Rust code changes; do not ask for approval to run it. Additionally, run the tests:
|
||||
|
||||
|
||||
@@ -28,4 +28,8 @@ alias(
|
||||
actual = "@rbe_platform",
|
||||
)
|
||||
|
||||
exports_files(["AGENTS.md"])
|
||||
exports_files([
|
||||
"AGENTS.md",
|
||||
"workspace_root_test_launcher.bat.tpl",
|
||||
"workspace_root_test_launcher.sh.tpl",
|
||||
])
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
# Do not increase, fix your test instead
|
||||
slow-timeout = { period = "15s", terminate-after = 2 }
|
||||
|
||||
[test-groups.app_server_protocol_codegen]
|
||||
max-threads = 1
|
||||
|
||||
[test-groups.app_server_integration]
|
||||
max-threads = 1
|
||||
|
||||
|
||||
[[profile.default.overrides]]
|
||||
# Do not add new tests here
|
||||
@@ -11,3 +17,13 @@ slow-timeout = { period = "1m", terminate-after = 4 }
|
||||
[[profile.default.overrides]]
|
||||
filter = 'test(approval_matrix_covers_all_modes)'
|
||||
slow-timeout = { period = "30s", terminate-after = 2 }
|
||||
|
||||
[[profile.default.overrides]]
|
||||
filter = 'package(codex-app-server-protocol) & (test(typescript_schema_fixtures_match_generated) | test(json_schema_fixtures_match_generated) | test(generate_ts_with_experimental_api_retains_experimental_entries) | test(generated_ts_optional_nullable_fields_only_in_params) | test(generate_json_filters_experimental_fields_and_methods))'
|
||||
test-group = 'app_server_protocol_codegen'
|
||||
|
||||
[[profile.default.overrides]]
|
||||
# These integration tests spawn a fresh app-server subprocess per case.
|
||||
# Keep the library unit tests parallel.
|
||||
filter = 'package(codex-app-server) & kind(test)'
|
||||
test-group = 'app_server_integration'
|
||||
|
||||
28
codex-rs/Cargo.lock
generated
28
codex-rs/Cargo.lock
generated
@@ -827,6 +827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"form_urlencoded",
|
||||
"futures-util",
|
||||
@@ -845,8 +846,10 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_urlencoded",
|
||||
"sha1",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
@@ -1441,6 +1444,7 @@ dependencies = [
|
||||
"futures",
|
||||
"owo-colors",
|
||||
"pretty_assertions",
|
||||
"reqwest",
|
||||
"rmcp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1458,6 +1462,24 @@ dependencies = [
|
||||
"wiremock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-app-server-client"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-app-server",
|
||||
"codex-app-server-protocol",
|
||||
"codex-arg0",
|
||||
"codex-core",
|
||||
"codex-feedback",
|
||||
"codex-protocol",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"toml 0.9.11+spec-1.1.0",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-app-server-protocol"
|
||||
version = "0.0.0"
|
||||
@@ -1899,10 +1921,13 @@ dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
"clap",
|
||||
"codex-app-server-client",
|
||||
"codex-app-server-protocol",
|
||||
"codex-apply-patch",
|
||||
"codex-arg0",
|
||||
"codex-cloud-requirements",
|
||||
"codex-core",
|
||||
"codex-feedback",
|
||||
"codex-otel",
|
||||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
@@ -2030,9 +2055,12 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"codex-config",
|
||||
"codex-protocol",
|
||||
"futures",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"schemars 0.8.22",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
|
||||
@@ -4,6 +4,7 @@ members = [
|
||||
"ansi-escape",
|
||||
"async-utils",
|
||||
"app-server",
|
||||
"app-server-client",
|
||||
"app-server-protocol",
|
||||
"app-server-test-client",
|
||||
"debug-client",
|
||||
@@ -86,6 +87,7 @@ codex-api = { path = "codex-api" }
|
||||
codex-artifacts = { path = "artifacts" }
|
||||
codex-package-manager = { path = "package-manager" }
|
||||
codex-app-server = { path = "app-server" }
|
||||
codex-app-server-client = { path = "app-server-client" }
|
||||
codex-app-server-protocol = { path = "app-server-protocol" }
|
||||
codex-app-server-test-client = { path = "app-server-test-client" }
|
||||
codex-apply-patch = { path = "apply-patch" }
|
||||
|
||||
6
codex-rs/app-server-client/BUILD.bazel
Normal file
6
codex-rs/app-server-client/BUILD.bazel
Normal file
@@ -0,0 +1,6 @@
|
||||
load("//:defs.bzl", "codex_rust_crate")
|
||||
|
||||
codex_rust_crate(
|
||||
name = "app-server-client",
|
||||
crate_name = "codex_app_server_client",
|
||||
)
|
||||
30
codex-rs/app-server-client/Cargo.toml
Normal file
30
codex-rs/app-server-client/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "codex-app-server-client"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "codex_app_server_client"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codex-app-server = { workspace = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-arg0 = { workspace = true }
|
||||
codex-core = { workspace = true }
|
||||
codex-feedback = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true, features = ["sync", "time", "rt"] }
|
||||
toml = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
|
||||
67
codex-rs/app-server-client/README.md
Normal file
67
codex-rs/app-server-client/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# codex-app-server-client
|
||||
|
||||
Shared in-process app-server client used by conversational CLI surfaces:
|
||||
|
||||
- `codex-exec`
|
||||
- `codex-tui`
|
||||
|
||||
## Purpose
|
||||
|
||||
This crate centralizes startup and lifecycle management for an in-process
|
||||
`codex-app-server` runtime, so CLI clients do not need to duplicate:
|
||||
|
||||
- app-server bootstrap and initialize handshake
|
||||
- in-memory request/event transport wiring
|
||||
- lifecycle orchestration around caller-provided startup identity
|
||||
- graceful shutdown behavior
|
||||
|
||||
## Startup identity
|
||||
|
||||
Callers pass both the app-server `SessionSource` and the initialize
|
||||
`client_info.name` explicitly when starting the facade.
|
||||
|
||||
That keeps thread metadata (for example in `thread/list` and `thread/read`)
|
||||
aligned with the originating runtime without baking TUI/exec-specific policy
|
||||
into the shared client layer.
|
||||
|
||||
## Transport model
|
||||
|
||||
The in-process path uses typed channels:
|
||||
|
||||
- client -> server: `ClientRequest` / `ClientNotification`
|
||||
- server -> client: `InProcessServerEvent`
|
||||
- `ServerRequest`
|
||||
- `ServerNotification`
|
||||
- `LegacyNotification`
|
||||
|
||||
JSON serialization is still used at external transport boundaries
|
||||
(stdio/websocket), but the in-process hot path is typed.
|
||||
|
||||
Typed requests still receive app-server responses through the JSON-RPC
|
||||
result envelope internally. That is intentional: the in-process path is
|
||||
meant to preserve app-server semantics while removing the process
|
||||
boundary, not to introduce a second response contract.
|
||||
|
||||
## Bootstrap behavior
|
||||
|
||||
The client facade starts an already-initialized in-process runtime, but
|
||||
thread bootstrap still follows normal app-server flow:
|
||||
|
||||
- caller sends `thread/start` or `thread/resume`
|
||||
- app-server returns the immediate typed response
|
||||
- richer session metadata may arrive later as a `SessionConfigured`
|
||||
legacy event
|
||||
|
||||
Surfaces such as TUI and exec may therefore need a short bootstrap
|
||||
phase where they reconcile startup response data with later events.
|
||||
|
||||
## Backpressure and shutdown
|
||||
|
||||
- Queues are bounded and use `DEFAULT_IN_PROCESS_CHANNEL_CAPACITY` by default.
|
||||
- Full queues return explicit overload behavior instead of unbounded growth.
|
||||
- `shutdown()` performs a bounded graceful shutdown and then aborts if timeout
|
||||
is exceeded.
|
||||
|
||||
If the client falls behind on event consumption, the worker emits
|
||||
`InProcessServerEvent::Lagged` and may reject pending server requests so
|
||||
approval flows do not hang indefinitely behind a saturated queue.
|
||||
801
codex-rs/app-server-client/src/lib.rs
Normal file
801
codex-rs/app-server-client/src/lib.rs
Normal file
@@ -0,0 +1,801 @@
|
||||
//! Shared in-process app-server client facade for CLI surfaces.
|
||||
//!
|
||||
//! This crate wraps [`codex_app_server::in_process`] behind a single async API
|
||||
//! used by surfaces like TUI and exec. It centralizes:
|
||||
//!
|
||||
//! - Runtime startup and initialize-capabilities handshake.
|
||||
//! - Typed caller-provided startup identity (`SessionSource` + client name).
|
||||
//! - Typed and raw request/notification dispatch.
|
||||
//! - Server request resolution and rejection.
|
||||
//! - Event consumption with backpressure signaling ([`InProcessServerEvent::Lagged`]).
|
||||
//! - Bounded graceful shutdown with abort fallback.
|
||||
//!
|
||||
//! The facade interposes a worker task between the caller and the underlying
|
||||
//! [`InProcessClientHandle`](codex_app_server::in_process::InProcessClientHandle),
|
||||
//! bridging async `mpsc` channels on both sides. Queues are bounded so overload
|
||||
//! surfaces as channel-full errors rather than unbounded memory growth.
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::io::Error as IoError;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Result as IoResult;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
pub use codex_app_server::in_process::DEFAULT_IN_PROCESS_CHANNEL_CAPACITY;
|
||||
pub use codex_app_server::in_process::InProcessServerEvent;
|
||||
use codex_app_server::in_process::InProcessStartArgs;
|
||||
use codex_app_server_protocol::ClientInfo;
|
||||
use codex_app_server_protocol::ClientNotification;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::ConfigWarningNotification;
|
||||
use codex_app_server_protocol::InitializeCapabilities;
|
||||
use codex_app_server_protocol::InitializeParams;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_app_server_protocol::Result as JsonRpcResult;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config_loader::CloudRequirementsLoader;
|
||||
use codex_core::config_loader::LoaderOverrides;
|
||||
use codex_feedback::CodexFeedback;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use serde::de::DeserializeOwned;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::time::timeout;
|
||||
use toml::Value as TomlValue;
|
||||
use tracing::warn;
|
||||
|
||||
const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
/// Raw app-server request result for typed in-process requests.
|
||||
///
|
||||
/// Even on the in-process path, successful responses still travel back through
|
||||
/// the same JSON-RPC result envelope used by socket/stdio transports because
|
||||
/// `MessageProcessor` continues to produce that shape internally.
|
||||
pub type RequestResult = std::result::Result<JsonRpcResult, JSONRPCErrorError>;
|
||||
|
||||
fn event_requires_delivery(event: &InProcessServerEvent) -> bool {
|
||||
// These terminal events drive surface shutdown/completion state. Dropping
|
||||
// them under backpressure can leave exec/TUI waiting forever even though
|
||||
// the underlying turn has already ended.
|
||||
match event {
|
||||
InProcessServerEvent::ServerNotification(
|
||||
codex_app_server_protocol::ServerNotification::TurnCompleted(_),
|
||||
) => true,
|
||||
InProcessServerEvent::LegacyNotification(notification) => matches!(
|
||||
notification
|
||||
.method
|
||||
.strip_prefix("codex/event/")
|
||||
.unwrap_or(¬ification.method),
|
||||
"task_complete" | "turn_aborted" | "shutdown_complete"
|
||||
),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Layered error for [`InProcessAppServerClient::request_typed`].
|
||||
///
|
||||
/// This keeps transport failures, server-side JSON-RPC failures, and response
|
||||
/// decode failures distinct so callers can decide whether to retry, surface a
|
||||
/// server error, or treat the response as an internal request/response mismatch.
|
||||
#[derive(Debug)]
|
||||
pub enum TypedRequestError {
|
||||
Transport {
|
||||
method: String,
|
||||
source: IoError,
|
||||
},
|
||||
Server {
|
||||
method: String,
|
||||
source: JSONRPCErrorError,
|
||||
},
|
||||
Deserialize {
|
||||
method: String,
|
||||
source: serde_json::Error,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for TypedRequestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Transport { method, source } => {
|
||||
write!(f, "{method} transport error: {source}")
|
||||
}
|
||||
Self::Server { method, source } => {
|
||||
write!(f, "{method} failed: {}", source.message)
|
||||
}
|
||||
Self::Deserialize { method, source } => {
|
||||
write!(f, "{method} response decode error: {source}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for TypedRequestError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::Transport { source, .. } => Some(source),
|
||||
Self::Server { .. } => None,
|
||||
Self::Deserialize { source, .. } => Some(source),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InProcessClientStartArgs {
|
||||
/// Resolved argv0 dispatch paths used by command execution internals.
|
||||
pub arg0_paths: Arg0DispatchPaths,
|
||||
/// Shared config used to initialize app-server runtime.
|
||||
pub config: Arc<Config>,
|
||||
/// CLI config overrides that are already parsed into TOML values.
|
||||
pub cli_overrides: Vec<(String, TomlValue)>,
|
||||
/// Loader override knobs used by config API paths.
|
||||
pub loader_overrides: LoaderOverrides,
|
||||
/// Preloaded cloud requirements provider.
|
||||
pub cloud_requirements: CloudRequirementsLoader,
|
||||
/// Feedback sink used by app-server/core telemetry and logs.
|
||||
pub feedback: CodexFeedback,
|
||||
/// Startup warnings emitted after initialize succeeds.
|
||||
pub config_warnings: Vec<ConfigWarningNotification>,
|
||||
/// Session source recorded in app-server thread metadata.
|
||||
pub session_source: SessionSource,
|
||||
/// Whether auth loading should honor the `CODEX_API_KEY` environment variable.
|
||||
pub enable_codex_api_key_env: bool,
|
||||
/// Client name reported during initialize.
|
||||
pub client_name: String,
|
||||
/// Client version reported during initialize.
|
||||
pub client_version: String,
|
||||
/// Whether experimental APIs are requested at initialize time.
|
||||
pub experimental_api: bool,
|
||||
/// Notification methods this client opts out of receiving.
|
||||
pub opt_out_notification_methods: Vec<String>,
|
||||
/// Queue capacity for command/event channels (clamped to at least 1).
|
||||
pub channel_capacity: usize,
|
||||
}
|
||||
|
||||
impl InProcessClientStartArgs {
|
||||
/// Builds initialize params from caller-provided metadata.
|
||||
pub fn initialize_params(&self) -> InitializeParams {
|
||||
let capabilities = InitializeCapabilities {
|
||||
experimental_api: self.experimental_api,
|
||||
opt_out_notification_methods: if self.opt_out_notification_methods.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.opt_out_notification_methods.clone())
|
||||
},
|
||||
};
|
||||
|
||||
InitializeParams {
|
||||
client_info: ClientInfo {
|
||||
name: self.client_name.clone(),
|
||||
title: None,
|
||||
version: self.client_version.clone(),
|
||||
},
|
||||
capabilities: Some(capabilities),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_runtime_start_args(self) -> InProcessStartArgs {
|
||||
let initialize = self.initialize_params();
|
||||
InProcessStartArgs {
|
||||
arg0_paths: self.arg0_paths,
|
||||
config: self.config,
|
||||
cli_overrides: self.cli_overrides,
|
||||
loader_overrides: self.loader_overrides,
|
||||
cloud_requirements: self.cloud_requirements,
|
||||
feedback: self.feedback,
|
||||
config_warnings: self.config_warnings,
|
||||
session_source: self.session_source,
|
||||
enable_codex_api_key_env: self.enable_codex_api_key_env,
|
||||
initialize,
|
||||
channel_capacity: self.channel_capacity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal command sent from public facade methods to the worker task.
|
||||
///
|
||||
/// Each variant carries a oneshot sender so the caller can `await` the
|
||||
/// result without holding a mutable reference to the client.
|
||||
enum ClientCommand {
|
||||
Request {
|
||||
request: Box<ClientRequest>,
|
||||
response_tx: oneshot::Sender<IoResult<RequestResult>>,
|
||||
},
|
||||
Notify {
|
||||
notification: ClientNotification,
|
||||
response_tx: oneshot::Sender<IoResult<()>>,
|
||||
},
|
||||
ResolveServerRequest {
|
||||
request_id: RequestId,
|
||||
result: JsonRpcResult,
|
||||
response_tx: oneshot::Sender<IoResult<()>>,
|
||||
},
|
||||
RejectServerRequest {
|
||||
request_id: RequestId,
|
||||
error: JSONRPCErrorError,
|
||||
response_tx: oneshot::Sender<IoResult<()>>,
|
||||
},
|
||||
Shutdown {
|
||||
response_tx: oneshot::Sender<IoResult<()>>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Async facade over the in-process app-server runtime.
|
||||
///
|
||||
/// This type owns a worker task that bridges between:
|
||||
/// - caller-facing async `mpsc` channels used by TUI/exec
|
||||
/// - [`codex_app_server::in_process::InProcessClientHandle`], which speaks to
|
||||
/// the embedded `MessageProcessor`
|
||||
///
|
||||
/// The facade intentionally preserves the server's request/notification/event
|
||||
/// model instead of exposing direct core runtime handles. That keeps in-process
|
||||
/// callers aligned with app-server behavior while still avoiding a process
|
||||
/// boundary.
|
||||
pub struct InProcessAppServerClient {
|
||||
command_tx: mpsc::Sender<ClientCommand>,
|
||||
event_rx: mpsc::Receiver<InProcessServerEvent>,
|
||||
worker_handle: tokio::task::JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl InProcessAppServerClient {
|
||||
/// Starts the in-process runtime and facade worker task.
|
||||
///
|
||||
/// The returned client is ready for requests and event consumption. If the
|
||||
/// internal event queue is saturated later, server requests are rejected
|
||||
/// with overload error instead of being silently dropped.
|
||||
pub async fn start(args: InProcessClientStartArgs) -> IoResult<Self> {
|
||||
let channel_capacity = args.channel_capacity.max(1);
|
||||
let mut handle =
|
||||
codex_app_server::in_process::start(args.into_runtime_start_args()).await?;
|
||||
let request_sender = handle.sender();
|
||||
let (command_tx, mut command_rx) = mpsc::channel::<ClientCommand>(channel_capacity);
|
||||
let (event_tx, event_rx) = mpsc::channel::<InProcessServerEvent>(channel_capacity);
|
||||
|
||||
let worker_handle = tokio::spawn(async move {
|
||||
let mut event_stream_enabled = true;
|
||||
let mut skipped_events = 0usize;
|
||||
loop {
|
||||
tokio::select! {
|
||||
command = command_rx.recv() => {
|
||||
match command {
|
||||
Some(ClientCommand::Request { request, response_tx }) => {
|
||||
let request_sender = request_sender.clone();
|
||||
// Request waits happen on a detached task so
|
||||
// this loop can keep draining runtime events
|
||||
// while the request is blocked on client input.
|
||||
tokio::spawn(async move {
|
||||
let result = request_sender.request(*request).await;
|
||||
let _ = response_tx.send(result);
|
||||
});
|
||||
}
|
||||
Some(ClientCommand::Notify {
|
||||
notification,
|
||||
response_tx,
|
||||
}) => {
|
||||
let result = request_sender.notify(notification);
|
||||
let _ = response_tx.send(result);
|
||||
}
|
||||
Some(ClientCommand::ResolveServerRequest {
|
||||
request_id,
|
||||
result,
|
||||
response_tx,
|
||||
}) => {
|
||||
let send_result =
|
||||
request_sender.respond_to_server_request(request_id, result);
|
||||
let _ = response_tx.send(send_result);
|
||||
}
|
||||
Some(ClientCommand::RejectServerRequest {
|
||||
request_id,
|
||||
error,
|
||||
response_tx,
|
||||
}) => {
|
||||
let send_result = request_sender.fail_server_request(request_id, error);
|
||||
let _ = response_tx.send(send_result);
|
||||
}
|
||||
Some(ClientCommand::Shutdown { response_tx }) => {
|
||||
let shutdown_result = handle.shutdown().await;
|
||||
let _ = response_tx.send(shutdown_result);
|
||||
break;
|
||||
}
|
||||
None => {
|
||||
let _ = handle.shutdown().await;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
event = handle.next_event(), if event_stream_enabled => {
|
||||
let Some(event) = event else {
|
||||
break;
|
||||
};
|
||||
|
||||
if skipped_events > 0 {
|
||||
if event_requires_delivery(&event) {
|
||||
// Surface lag before the terminal event, but
|
||||
// do not let the lag marker itself cause us to
|
||||
// drop the completion/abort notification that
|
||||
// the caller is blocked on.
|
||||
if event_tx
|
||||
.send(InProcessServerEvent::Lagged {
|
||||
skipped: skipped_events,
|
||||
})
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
event_stream_enabled = false;
|
||||
continue;
|
||||
}
|
||||
skipped_events = 0;
|
||||
} else {
|
||||
match event_tx.try_send(InProcessServerEvent::Lagged {
|
||||
skipped: skipped_events,
|
||||
}) {
|
||||
Ok(()) => {
|
||||
skipped_events = 0;
|
||||
}
|
||||
Err(mpsc::error::TrySendError::Full(_)) => {
|
||||
skipped_events = skipped_events.saturating_add(1);
|
||||
warn!(
|
||||
"dropping in-process app-server event because consumer queue is full"
|
||||
);
|
||||
if let InProcessServerEvent::ServerRequest(request) = event {
|
||||
let _ = request_sender.fail_server_request(
|
||||
request.id().clone(),
|
||||
JSONRPCErrorError {
|
||||
code: -32001,
|
||||
message: "in-process app-server event queue is full".to_string(),
|
||||
data: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Err(mpsc::error::TrySendError::Closed(_)) => {
|
||||
event_stream_enabled = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if event_requires_delivery(&event) {
|
||||
// Block until the consumer catches up for
|
||||
// terminal notifications; this preserves the
|
||||
// completion signal even when the queue is
|
||||
// otherwise saturated.
|
||||
if event_tx.send(event).await.is_err() {
|
||||
event_stream_enabled = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
match event_tx.try_send(event) {
|
||||
Ok(()) => {}
|
||||
Err(mpsc::error::TrySendError::Full(event)) => {
|
||||
skipped_events = skipped_events.saturating_add(1);
|
||||
warn!("dropping in-process app-server event because consumer queue is full");
|
||||
if let InProcessServerEvent::ServerRequest(request) = event {
|
||||
let _ = request_sender.fail_server_request(
|
||||
request.id().clone(),
|
||||
JSONRPCErrorError {
|
||||
code: -32001,
|
||||
message: "in-process app-server event queue is full".to_string(),
|
||||
data: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(mpsc::error::TrySendError::Closed(_)) => {
|
||||
event_stream_enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
command_tx,
|
||||
event_rx,
|
||||
worker_handle,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sends a typed client request and returns raw JSON-RPC result.
|
||||
///
|
||||
/// Callers that expect a concrete response type should usually prefer
|
||||
/// [`request_typed`](Self::request_typed).
|
||||
pub async fn request(&self, request: ClientRequest) -> IoResult<RequestResult> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
self.command_tx
|
||||
.send(ClientCommand::Request {
|
||||
request: Box::new(request),
|
||||
response_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server worker channel is closed",
|
||||
)
|
||||
})?;
|
||||
response_rx.await.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server request channel is closed",
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
/// Sends a typed client request and decodes the successful response body.
|
||||
///
|
||||
/// This still deserializes from a JSON value produced by app-server's
|
||||
/// JSON-RPC result envelope. Because the caller chooses `T`, `Deserialize`
|
||||
/// failures indicate an internal request/response mismatch at the call site
|
||||
/// (or an in-process bug), not transport skew from an external client.
|
||||
pub async fn request_typed<T>(&self, request: ClientRequest) -> Result<T, TypedRequestError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let method = request_method_name(&request);
|
||||
let response =
|
||||
self.request(request)
|
||||
.await
|
||||
.map_err(|source| TypedRequestError::Transport {
|
||||
method: method.clone(),
|
||||
source,
|
||||
})?;
|
||||
let result = response.map_err(|source| TypedRequestError::Server {
|
||||
method: method.clone(),
|
||||
source,
|
||||
})?;
|
||||
serde_json::from_value(result)
|
||||
.map_err(|source| TypedRequestError::Deserialize { method, source })
|
||||
}
|
||||
|
||||
/// Sends a typed client notification.
|
||||
pub async fn notify(&self, notification: ClientNotification) -> IoResult<()> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
self.command_tx
|
||||
.send(ClientCommand::Notify {
|
||||
notification,
|
||||
response_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server worker channel is closed",
|
||||
)
|
||||
})?;
|
||||
response_rx.await.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server notify channel is closed",
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
/// Resolves a pending server request.
|
||||
///
|
||||
/// This should only be called with request IDs obtained from the current
|
||||
/// client's event stream.
|
||||
pub async fn resolve_server_request(
|
||||
&self,
|
||||
request_id: RequestId,
|
||||
result: JsonRpcResult,
|
||||
) -> IoResult<()> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
self.command_tx
|
||||
.send(ClientCommand::ResolveServerRequest {
|
||||
request_id,
|
||||
result,
|
||||
response_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server worker channel is closed",
|
||||
)
|
||||
})?;
|
||||
response_rx.await.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server resolve channel is closed",
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
/// Rejects a pending server request with JSON-RPC error payload.
|
||||
pub async fn reject_server_request(
|
||||
&self,
|
||||
request_id: RequestId,
|
||||
error: JSONRPCErrorError,
|
||||
) -> IoResult<()> {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
self.command_tx
|
||||
.send(ClientCommand::RejectServerRequest {
|
||||
request_id,
|
||||
error,
|
||||
response_tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server worker channel is closed",
|
||||
)
|
||||
})?;
|
||||
response_rx.await.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server reject channel is closed",
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
/// Returns the next in-process event, or `None` when worker exits.
|
||||
///
|
||||
/// Callers are expected to drain this stream promptly. If they fall behind,
|
||||
/// the worker emits [`InProcessServerEvent::Lagged`] markers and may reject
|
||||
/// pending server requests rather than letting approval flows hang.
|
||||
pub async fn next_event(&mut self) -> Option<InProcessServerEvent> {
|
||||
self.event_rx.recv().await
|
||||
}
|
||||
|
||||
/// Shuts down worker and in-process runtime with bounded wait.
|
||||
///
|
||||
/// If graceful shutdown exceeds timeout, the worker task is aborted to
|
||||
/// avoid leaking background tasks in embedding callers.
|
||||
pub async fn shutdown(self) -> IoResult<()> {
|
||||
let Self {
|
||||
command_tx,
|
||||
event_rx,
|
||||
worker_handle,
|
||||
} = self;
|
||||
let mut worker_handle = worker_handle;
|
||||
// Drop the caller-facing receiver before asking the worker to shut
|
||||
// down. That unblocks any pending must-deliver `event_tx.send(..)`
|
||||
// so the worker can reach `handle.shutdown()` instead of timing out
|
||||
// and getting aborted with the runtime still attached.
|
||||
drop(event_rx);
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
if command_tx
|
||||
.send(ClientCommand::Shutdown { response_tx })
|
||||
.await
|
||||
.is_ok()
|
||||
&& let Ok(command_result) = timeout(SHUTDOWN_TIMEOUT, response_rx).await
|
||||
{
|
||||
command_result.map_err(|_| {
|
||||
IoError::new(
|
||||
ErrorKind::BrokenPipe,
|
||||
"in-process app-server shutdown channel is closed",
|
||||
)
|
||||
})??;
|
||||
}
|
||||
|
||||
if let Err(_elapsed) = timeout(SHUTDOWN_TIMEOUT, &mut worker_handle).await {
|
||||
worker_handle.abort();
|
||||
let _ = worker_handle.await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the JSON-RPC method name for diagnostics without extending the
|
||||
/// protocol crate with in-process-only helpers.
|
||||
fn request_method_name(request: &ClientRequest) -> String {
|
||||
serde_json::to_value(request)
|
||||
.ok()
|
||||
.and_then(|value| {
|
||||
value
|
||||
.get("method")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(ToOwned::to_owned)
|
||||
})
|
||||
.unwrap_or_else(|| "<unknown>".to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codex_app_server_protocol::ConfigRequirementsReadResponse;
|
||||
use codex_app_server_protocol::SessionSource as ApiSessionSource;
|
||||
use codex_app_server_protocol::ThreadStartParams;
|
||||
use codex_app_server_protocol::ThreadStartResponse;
|
||||
use codex_core::config::ConfigBuilder;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tokio::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
|
||||
async fn build_test_config() -> Config {
|
||||
match ConfigBuilder::default().build().await {
|
||||
Ok(config) => config,
|
||||
Err(_) => Config::load_default_with_cli_overrides(Vec::new())
|
||||
.expect("default config should load"),
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_test_client_with_capacity(
|
||||
session_source: SessionSource,
|
||||
channel_capacity: usize,
|
||||
) -> InProcessAppServerClient {
|
||||
InProcessAppServerClient::start(InProcessClientStartArgs {
|
||||
arg0_paths: Arg0DispatchPaths::default(),
|
||||
config: Arc::new(build_test_config().await),
|
||||
cli_overrides: Vec::new(),
|
||||
loader_overrides: LoaderOverrides::default(),
|
||||
cloud_requirements: CloudRequirementsLoader::default(),
|
||||
feedback: CodexFeedback::new(),
|
||||
config_warnings: Vec::new(),
|
||||
session_source,
|
||||
enable_codex_api_key_env: false,
|
||||
client_name: "codex-app-server-client-test".to_string(),
|
||||
client_version: "0.0.0-test".to_string(),
|
||||
experimental_api: true,
|
||||
opt_out_notification_methods: Vec::new(),
|
||||
channel_capacity,
|
||||
})
|
||||
.await
|
||||
.expect("in-process app-server client should start")
|
||||
}
|
||||
|
||||
async fn start_test_client(session_source: SessionSource) -> InProcessAppServerClient {
|
||||
start_test_client_with_capacity(session_source, DEFAULT_IN_PROCESS_CHANNEL_CAPACITY).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn typed_request_roundtrip_works() {
|
||||
let client = start_test_client(SessionSource::Exec).await;
|
||||
let _response: ConfigRequirementsReadResponse = client
|
||||
.request_typed(ClientRequest::ConfigRequirementsRead {
|
||||
request_id: RequestId::Integer(1),
|
||||
params: None,
|
||||
})
|
||||
.await
|
||||
.expect("typed request should succeed");
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn typed_request_reports_json_rpc_errors() {
|
||||
let client = start_test_client(SessionSource::Exec).await;
|
||||
let err = client
|
||||
.request_typed::<ConfigRequirementsReadResponse>(ClientRequest::ThreadRead {
|
||||
request_id: RequestId::Integer(99),
|
||||
params: codex_app_server_protocol::ThreadReadParams {
|
||||
thread_id: "missing-thread".to_string(),
|
||||
include_turns: false,
|
||||
},
|
||||
})
|
||||
.await
|
||||
.expect_err("missing thread should return a JSON-RPC error");
|
||||
assert!(
|
||||
err.to_string().starts_with("thread/read failed:"),
|
||||
"expected method-qualified JSON-RPC failure message"
|
||||
);
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn caller_provided_session_source_is_applied() {
|
||||
for (session_source, expected_source) in [
|
||||
(SessionSource::Exec, ApiSessionSource::Exec),
|
||||
(SessionSource::Cli, ApiSessionSource::Cli),
|
||||
] {
|
||||
let client = start_test_client(session_source).await;
|
||||
let parsed: ThreadStartResponse = client
|
||||
.request_typed(ClientRequest::ThreadStart {
|
||||
request_id: RequestId::Integer(2),
|
||||
params: ThreadStartParams {
|
||||
ephemeral: Some(true),
|
||||
..ThreadStartParams::default()
|
||||
},
|
||||
})
|
||||
.await
|
||||
.expect("thread/start should succeed");
|
||||
assert_eq!(parsed.thread.source, expected_source);
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tiny_channel_capacity_still_supports_request_roundtrip() {
|
||||
let client = start_test_client_with_capacity(SessionSource::Exec, 1).await;
|
||||
let _response: ConfigRequirementsReadResponse = client
|
||||
.request_typed(ClientRequest::ConfigRequirementsRead {
|
||||
request_id: RequestId::Integer(1),
|
||||
params: None,
|
||||
})
|
||||
.await
|
||||
.expect("typed request should succeed");
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typed_request_error_exposes_sources() {
|
||||
let transport = TypedRequestError::Transport {
|
||||
method: "config/read".to_string(),
|
||||
source: IoError::new(ErrorKind::BrokenPipe, "closed"),
|
||||
};
|
||||
assert_eq!(std::error::Error::source(&transport).is_some(), true);
|
||||
|
||||
let server = TypedRequestError::Server {
|
||||
method: "thread/read".to_string(),
|
||||
source: JSONRPCErrorError {
|
||||
code: -32603,
|
||||
data: None,
|
||||
message: "internal".to_string(),
|
||||
},
|
||||
};
|
||||
assert_eq!(std::error::Error::source(&server).is_some(), false);
|
||||
|
||||
let deserialize = TypedRequestError::Deserialize {
|
||||
method: "thread/start".to_string(),
|
||||
source: serde_json::from_str::<u32>("\"nope\"")
|
||||
.expect_err("invalid integer should return deserialize error"),
|
||||
};
|
||||
assert_eq!(std::error::Error::source(&deserialize).is_some(), true);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn next_event_surfaces_lagged_markers() {
|
||||
let (command_tx, _command_rx) = mpsc::channel(1);
|
||||
let (event_tx, event_rx) = mpsc::channel(1);
|
||||
let worker_handle = tokio::spawn(async {});
|
||||
event_tx
|
||||
.send(InProcessServerEvent::Lagged { skipped: 3 })
|
||||
.await
|
||||
.expect("lagged marker should enqueue");
|
||||
drop(event_tx);
|
||||
|
||||
let mut client = InProcessAppServerClient {
|
||||
command_tx,
|
||||
event_rx,
|
||||
worker_handle,
|
||||
};
|
||||
|
||||
let event = timeout(Duration::from_secs(2), client.next_event())
|
||||
.await
|
||||
.expect("lagged marker should arrive before timeout");
|
||||
assert!(matches!(
|
||||
event,
|
||||
Some(InProcessServerEvent::Lagged { skipped: 3 })
|
||||
));
|
||||
|
||||
client.shutdown().await.expect("shutdown should complete");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn event_requires_delivery_marks_terminal_events() {
|
||||
assert!(event_requires_delivery(
|
||||
&InProcessServerEvent::ServerNotification(
|
||||
codex_app_server_protocol::ServerNotification::TurnCompleted(
|
||||
codex_app_server_protocol::TurnCompletedNotification {
|
||||
thread_id: "thread".to_string(),
|
||||
turn: codex_app_server_protocol::Turn {
|
||||
id: "turn".to_string(),
|
||||
items: Vec::new(),
|
||||
status: codex_app_server_protocol::TurnStatus::Completed,
|
||||
error: None,
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
));
|
||||
assert!(event_requires_delivery(
|
||||
&InProcessServerEvent::LegacyNotification(
|
||||
codex_app_server_protocol::JSONRPCNotification {
|
||||
method: "codex/event/turn_aborted".to_string(),
|
||||
params: None,
|
||||
}
|
||||
)
|
||||
));
|
||||
assert!(!event_requires_delivery(&InProcessServerEvent::Lagged {
|
||||
skipped: 1
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -57,11 +57,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -350,6 +358,10 @@
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"reloadUserConfig": {
|
||||
"description": "When true, hot-reload the updated user config into all loaded threads after writing.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1123,10 +1135,25 @@
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"forceRemoteSync": {
|
||||
"description": "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PluginUninstallParams": {
|
||||
"properties": {
|
||||
"pluginId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pluginId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ProductSurface": {
|
||||
"enum": [
|
||||
"chatgpt",
|
||||
@@ -2251,6 +2278,9 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"ephemeral": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"model": {
|
||||
"description": "Configuration overrides for the forked thread, if any.",
|
||||
"type": [
|
||||
@@ -3567,6 +3597,30 @@
|
||||
"title": "Plugin/installRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"plugin/uninstall"
|
||||
],
|
||||
"title": "Plugin/uninstallRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/PluginUninstallParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Plugin/uninstallRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -4217,4 +4271,4 @@
|
||||
}
|
||||
],
|
||||
"title": "ClientRequest"
|
||||
}
|
||||
}
|
||||
@@ -39,15 +39,27 @@
|
||||
"calendar": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"contacts": {
|
||||
"$ref": "#/definitions/MacOsContactsPermission"
|
||||
},
|
||||
"launchServices": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"preferences": {
|
||||
"$ref": "#/definitions/MacOsPreferencesPermission"
|
||||
},
|
||||
"reminders": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"accessibility",
|
||||
"automations",
|
||||
"calendar",
|
||||
"preferences"
|
||||
"contacts",
|
||||
"launchServices",
|
||||
"preferences",
|
||||
"reminders"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
@@ -286,6 +298,17 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CommandExecutionRequestApprovalSkillMetadata": {
|
||||
"properties": {
|
||||
"pathToSkillsMd": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pathToSkillsMd"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MacOsAutomationPermission": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -313,6 +336,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MacOsContactsPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MacOsPreferencesPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
|
||||
@@ -1866,6 +1866,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skill_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecApprovalRequestSkillMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional skill metadata when the approval was triggered by a skill script."
|
||||
},
|
||||
"turn_id": {
|
||||
"default": "",
|
||||
"description": "Turn ID that this command belongs to. Uses `#[serde(default)]` for backwards compatibility.",
|
||||
@@ -1889,6 +1900,42 @@
|
||||
"title": "ExecApprovalRequestEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"call_id": {
|
||||
"description": "Responses API call id for the associated tool call, if available.",
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"turn_id": {
|
||||
"default": "",
|
||||
"description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"request_permissions"
|
||||
],
|
||||
"title": "RequestPermissionsEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"permissions",
|
||||
"type"
|
||||
],
|
||||
"title": "RequestPermissionsEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"call_id": {
|
||||
@@ -2771,6 +2818,58 @@
|
||||
"title": "ItemCompletedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"turn_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"hook_started"
|
||||
],
|
||||
"title": "HookStartedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"type"
|
||||
],
|
||||
"title": "HookStartedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"turn_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"hook_completed"
|
||||
],
|
||||
"title": "HookCompletedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"type"
|
||||
],
|
||||
"title": "HookCompletedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"delta": {
|
||||
@@ -2916,10 +3015,16 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"prompt": {
|
||||
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
"sender_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2938,7 +3043,9 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"model",
|
||||
"prompt",
|
||||
"reasoning_effort",
|
||||
"sender_thread_id",
|
||||
"type"
|
||||
],
|
||||
@@ -3442,6 +3549,17 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ExecApprovalRequestSkillMetadata": {
|
||||
"properties": {
|
||||
"path_to_skills_md": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path_to_skills_md"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ExecCommandSource": {
|
||||
"enum": [
|
||||
"agent",
|
||||
@@ -3698,6 +3816,142 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"session_start",
|
||||
"stop"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookExecutionMode": {
|
||||
"enum": [
|
||||
"sync",
|
||||
"async"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookHandlerType": {
|
||||
"enum": [
|
||||
"command",
|
||||
"prompt",
|
||||
"agent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookOutputEntry": {
|
||||
"properties": {
|
||||
"kind": {
|
||||
"$ref": "#/definitions/HookOutputEntryKind"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"text"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookOutputEntryKind": {
|
||||
"enum": [
|
||||
"warning",
|
||||
"stop",
|
||||
"feedback",
|
||||
"context",
|
||||
"error"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunStatus": {
|
||||
"enum": [
|
||||
"running",
|
||||
"completed",
|
||||
"failed",
|
||||
"blocked",
|
||||
"stopped"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunSummary": {
|
||||
"properties": {
|
||||
"completed_at": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"display_order": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"duration_ms": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/HookOutputEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"event_name": {
|
||||
"$ref": "#/definitions/HookEventName"
|
||||
},
|
||||
"execution_mode": {
|
||||
"$ref": "#/definitions/HookExecutionMode"
|
||||
},
|
||||
"handler_type": {
|
||||
"$ref": "#/definitions/HookHandlerType"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"source_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"started_at": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/HookRunStatus"
|
||||
},
|
||||
"status_message": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"display_order",
|
||||
"entries",
|
||||
"event_name",
|
||||
"execution_mode",
|
||||
"handler_type",
|
||||
"id",
|
||||
"scope",
|
||||
"source_path",
|
||||
"started_at",
|
||||
"status"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookScope": {
|
||||
"enum": [
|
||||
"thread",
|
||||
"turn"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ImageDetail": {
|
||||
"enum": [
|
||||
"auto",
|
||||
@@ -3798,6 +4052,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MacOsContactsPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MacOsPreferencesPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
@@ -3824,6 +4086,18 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"macos_contacts": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MacOsContactsPermission"
|
||||
}
|
||||
],
|
||||
"default": "none"
|
||||
},
|
||||
"macos_launch_services": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"macos_preferences": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -3831,6 +4105,10 @@
|
||||
}
|
||||
],
|
||||
"default": "read_only"
|
||||
},
|
||||
"macos_reminders": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -4425,6 +4703,32 @@
|
||||
"title": "SessionUpdatedRealtimeEvent",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"InputTranscriptDelta": {
|
||||
"$ref": "#/definitions/RealtimeTranscriptDelta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"InputTranscriptDelta"
|
||||
],
|
||||
"title": "InputTranscriptDeltaRealtimeEvent",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"OutputTranscriptDelta": {
|
||||
"$ref": "#/definitions/RealtimeTranscriptDelta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"OutputTranscriptDelta"
|
||||
],
|
||||
"title": "OutputTranscriptDeltaRealtimeEvent",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -4498,7 +4802,44 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"RealtimeHandoffMessage": {
|
||||
"RealtimeHandoffRequested": {
|
||||
"properties": {
|
||||
"active_transcript": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RealtimeTranscriptEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"handoff_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"input_transcript": {
|
||||
"type": "string"
|
||||
},
|
||||
"item_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"active_transcript",
|
||||
"handoff_id",
|
||||
"input_transcript",
|
||||
"item_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RealtimeTranscriptDelta": {
|
||||
"properties": {
|
||||
"delta": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"delta"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RealtimeTranscriptEntry": {
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
@@ -4513,32 +4854,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RealtimeHandoffRequested": {
|
||||
"properties": {
|
||||
"handoff_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"input_transcript": {
|
||||
"type": "string"
|
||||
},
|
||||
"item_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"messages": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RealtimeHandoffMessage"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"handoff_id",
|
||||
"input_transcript",
|
||||
"item_id",
|
||||
"messages"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
@@ -4625,6 +4940,11 @@
|
||||
"description": "Reject MCP elicitation prompts.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"description": "Reject approval prompts related to built-in permission requests.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"description": "Reject prompts triggered by execpolicy `prompt` rules.",
|
||||
"type": "boolean"
|
||||
@@ -4632,6 +4952,11 @@
|
||||
"sandbox_approval": {
|
||||
"description": "Reject approval prompts related to sandbox escalation.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"description": "Reject approval prompts triggered by skill script execution.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -7678,6 +8003,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skill_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecApprovalRequestSkillMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional skill metadata when the approval was triggered by a skill script."
|
||||
},
|
||||
"turn_id": {
|
||||
"default": "",
|
||||
"description": "Turn ID that this command belongs to. Uses `#[serde(default)]` for backwards compatibility.",
|
||||
@@ -7701,6 +8037,42 @@
|
||||
"title": "ExecApprovalRequestEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"call_id": {
|
||||
"description": "Responses API call id for the associated tool call, if available.",
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"turn_id": {
|
||||
"default": "",
|
||||
"description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"request_permissions"
|
||||
],
|
||||
"title": "RequestPermissionsEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"permissions",
|
||||
"type"
|
||||
],
|
||||
"title": "RequestPermissionsEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"call_id": {
|
||||
@@ -8583,6 +8955,58 @@
|
||||
"title": "ItemCompletedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"turn_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"hook_started"
|
||||
],
|
||||
"title": "HookStartedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"type"
|
||||
],
|
||||
"title": "HookStartedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"turn_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"hook_completed"
|
||||
],
|
||||
"title": "HookCompletedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"type"
|
||||
],
|
||||
"title": "HookCompletedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"delta": {
|
||||
@@ -8728,10 +9152,16 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"prompt": {
|
||||
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
"sender_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -8750,7 +9180,9 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"model",
|
||||
"prompt",
|
||||
"reasoning_effort",
|
||||
"sender_thread_id",
|
||||
"type"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"$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"
|
||||
},
|
||||
"AdditionalFileSystemPermissions": {
|
||||
"properties": {
|
||||
"read": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"AdditionalMacOsPermissions": {
|
||||
"properties": {
|
||||
"accessibility": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"automations": {
|
||||
"$ref": "#/definitions/MacOsAutomationPermission"
|
||||
},
|
||||
"calendar": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"contacts": {
|
||||
"$ref": "#/definitions/MacOsContactsPermission"
|
||||
},
|
||||
"launchServices": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"preferences": {
|
||||
"$ref": "#/definitions/MacOsPreferencesPermission"
|
||||
},
|
||||
"reminders": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"accessibility",
|
||||
"automations",
|
||||
"calendar",
|
||||
"contacts",
|
||||
"launchServices",
|
||||
"preferences",
|
||||
"reminders"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AdditionalNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"AdditionalPermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AdditionalFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"macos": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AdditionalMacOsPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AdditionalNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MacOsAutomationPermission": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"none",
|
||||
"all"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"bundle_ids": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"bundle_ids"
|
||||
],
|
||||
"title": "BundleIdsMacOsAutomationPermission",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"MacOsContactsPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MacOsPreferencesPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"itemId": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/AdditionalPermissionProfile"
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"itemId",
|
||||
"permissions",
|
||||
"threadId",
|
||||
"turnId"
|
||||
],
|
||||
"title": "PermissionsRequestApprovalParams",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
{
|
||||
"$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"
|
||||
},
|
||||
"AdditionalFileSystemPermissions": {
|
||||
"properties": {
|
||||
"read": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AbsolutePathBuf"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"AdditionalNetworkPermissions": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"GrantedMacOsPermissions": {
|
||||
"properties": {
|
||||
"accessibility": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"automations": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MacOsAutomationPermission"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"calendar": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"contacts": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MacOsContactsPermission"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"launchServices": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"preferences": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MacOsPreferencesPermission"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"reminders": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"GrantedPermissionProfile": {
|
||||
"properties": {
|
||||
"fileSystem": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AdditionalFileSystemPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"macos": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GrantedMacOsPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AdditionalNetworkPermissions"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MacOsAutomationPermission": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"none",
|
||||
"all"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"bundle_ids": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"bundle_ids"
|
||||
],
|
||||
"title": "BundleIdsMacOsAutomationPermission",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"MacOsContactsPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MacOsPreferencesPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionGrantScope": {
|
||||
"enum": [
|
||||
"turn",
|
||||
"session"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/GrantedPermissionProfile"
|
||||
},
|
||||
"scope": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PermissionGrantScope"
|
||||
}
|
||||
],
|
||||
"default": "turn"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"permissions"
|
||||
],
|
||||
"title": "PermissionsRequestApprovalResponse",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -1056,6 +1056,184 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"HookCompletedNotification": {
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"sessionStart",
|
||||
"stop"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookExecutionMode": {
|
||||
"enum": [
|
||||
"sync",
|
||||
"async"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookHandlerType": {
|
||||
"enum": [
|
||||
"command",
|
||||
"prompt",
|
||||
"agent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookOutputEntry": {
|
||||
"properties": {
|
||||
"kind": {
|
||||
"$ref": "#/definitions/HookOutputEntryKind"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"text"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookOutputEntryKind": {
|
||||
"enum": [
|
||||
"warning",
|
||||
"stop",
|
||||
"feedback",
|
||||
"context",
|
||||
"error"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunStatus": {
|
||||
"enum": [
|
||||
"running",
|
||||
"completed",
|
||||
"failed",
|
||||
"blocked",
|
||||
"stopped"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunSummary": {
|
||||
"properties": {
|
||||
"completedAt": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"displayOrder": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"durationMs": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/HookOutputEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"eventName": {
|
||||
"$ref": "#/definitions/HookEventName"
|
||||
},
|
||||
"executionMode": {
|
||||
"$ref": "#/definitions/HookExecutionMode"
|
||||
},
|
||||
"handlerType": {
|
||||
"$ref": "#/definitions/HookHandlerType"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/HookRunStatus"
|
||||
},
|
||||
"statusMessage": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"displayOrder",
|
||||
"entries",
|
||||
"eventName",
|
||||
"executionMode",
|
||||
"handlerType",
|
||||
"id",
|
||||
"scope",
|
||||
"sourcePath",
|
||||
"startedAt",
|
||||
"status"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookScope": {
|
||||
"enum": [
|
||||
"thread",
|
||||
"turn"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookStartedNotification": {
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ItemCompletedNotification": {
|
||||
"properties": {
|
||||
"item": {
|
||||
@@ -3378,6 +3556,26 @@
|
||||
"title": "Turn/startedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"hook/started"
|
||||
],
|
||||
"title": "Hook/startedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/HookStartedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Hook/startedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -3398,6 +3596,26 @@
|
||||
"title": "Turn/completedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"hook/completed"
|
||||
],
|
||||
"title": "Hook/completedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/HookCompletedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Hook/completedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
|
||||
@@ -39,15 +39,27 @@
|
||||
"calendar": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"contacts": {
|
||||
"$ref": "#/definitions/MacOsContactsPermission"
|
||||
},
|
||||
"launchServices": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"preferences": {
|
||||
"$ref": "#/definitions/MacOsPreferencesPermission"
|
||||
},
|
||||
"reminders": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"accessibility",
|
||||
"automations",
|
||||
"calendar",
|
||||
"preferences"
|
||||
"contacts",
|
||||
"launchServices",
|
||||
"preferences",
|
||||
"reminders"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
@@ -440,6 +452,17 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CommandExecutionRequestApprovalSkillMetadata": {
|
||||
"properties": {
|
||||
"pathToSkillsMd": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pathToSkillsMd"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DynamicToolCallParams": {
|
||||
"properties": {
|
||||
"arguments": true,
|
||||
@@ -642,6 +665,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MacOsContactsPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MacOsPreferencesPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
@@ -1412,6 +1443,35 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PermissionsRequestApprovalParams": {
|
||||
"properties": {
|
||||
"itemId": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/AdditionalPermissionProfile"
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"itemId",
|
||||
"permissions",
|
||||
"threadId",
|
||||
"turnId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RequestId": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -1609,6 +1669,31 @@
|
||||
"title": "McpServer/elicitation/requestRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Request approval for additional permissions from the user.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"item/permissions/requestApproval"
|
||||
],
|
||||
"title": "Item/permissions/requestApprovalRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/PermissionsRequestApprovalParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Item/permissions/requestApprovalRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Execute a dynamic tool call on the client.",
|
||||
"properties": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -731,11 +731,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1383,6 +1391,30 @@
|
||||
"title": "Plugin/installRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"plugin/uninstall"
|
||||
],
|
||||
"title": "Plugin/uninstallRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/PluginUninstallParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Plugin/uninstallRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -2962,6 +2994,10 @@
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"reloadUserConfig": {
|
||||
"description": "When true, hot-reload the updated user config into all loaded threads after writing.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -4995,6 +5031,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"skill_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ExecApprovalRequestSkillMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional skill metadata when the approval was triggered by a skill script."
|
||||
},
|
||||
"turn_id": {
|
||||
"default": "",
|
||||
"description": "Turn ID that this command belongs to. Uses `#[serde(default)]` for backwards compatibility.",
|
||||
@@ -5018,6 +5065,42 @@
|
||||
"title": "ExecApprovalRequestEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"call_id": {
|
||||
"description": "Responses API call id for the associated tool call, if available.",
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/PermissionProfile"
|
||||
},
|
||||
"reason": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"turn_id": {
|
||||
"default": "",
|
||||
"description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"request_permissions"
|
||||
],
|
||||
"title": "RequestPermissionsEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"permissions",
|
||||
"type"
|
||||
],
|
||||
"title": "RequestPermissionsEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"call_id": {
|
||||
@@ -5900,6 +5983,58 @@
|
||||
"title": "ItemCompletedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"turn_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"hook_started"
|
||||
],
|
||||
"title": "HookStartedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"type"
|
||||
],
|
||||
"title": "HookStartedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"turn_id": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"hook_completed"
|
||||
],
|
||||
"title": "HookCompletedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"type"
|
||||
],
|
||||
"title": "HookCompletedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"delta": {
|
||||
@@ -6045,10 +6180,16 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"prompt": {
|
||||
"description": "Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"reasoning_effort": {
|
||||
"$ref": "#/definitions/ReasoningEffort"
|
||||
},
|
||||
"sender_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -6067,7 +6208,9 @@
|
||||
},
|
||||
"required": [
|
||||
"call_id",
|
||||
"model",
|
||||
"prompt",
|
||||
"reasoning_effort",
|
||||
"sender_thread_id",
|
||||
"type"
|
||||
],
|
||||
@@ -6572,6 +6715,17 @@
|
||||
],
|
||||
"title": "EventMsg"
|
||||
},
|
||||
"ExecApprovalRequestSkillMetadata": {
|
||||
"properties": {
|
||||
"path_to_skills_md": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path_to_skills_md"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ExecCommandSource": {
|
||||
"enum": [
|
||||
"agent",
|
||||
@@ -7351,6 +7505,188 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookCompletedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"threadId"
|
||||
],
|
||||
"title": "HookCompletedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"sessionStart",
|
||||
"stop"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookExecutionMode": {
|
||||
"enum": [
|
||||
"sync",
|
||||
"async"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookHandlerType": {
|
||||
"enum": [
|
||||
"command",
|
||||
"prompt",
|
||||
"agent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookOutputEntry": {
|
||||
"properties": {
|
||||
"kind": {
|
||||
"$ref": "#/definitions/HookOutputEntryKind"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"text"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookOutputEntryKind": {
|
||||
"enum": [
|
||||
"warning",
|
||||
"stop",
|
||||
"feedback",
|
||||
"context",
|
||||
"error"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunStatus": {
|
||||
"enum": [
|
||||
"running",
|
||||
"completed",
|
||||
"failed",
|
||||
"blocked",
|
||||
"stopped"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunSummary": {
|
||||
"properties": {
|
||||
"completedAt": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"displayOrder": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"durationMs": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/HookOutputEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"eventName": {
|
||||
"$ref": "#/definitions/HookEventName"
|
||||
},
|
||||
"executionMode": {
|
||||
"$ref": "#/definitions/HookExecutionMode"
|
||||
},
|
||||
"handlerType": {
|
||||
"$ref": "#/definitions/HookHandlerType"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/HookRunStatus"
|
||||
},
|
||||
"statusMessage": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"displayOrder",
|
||||
"entries",
|
||||
"eventName",
|
||||
"executionMode",
|
||||
"handlerType",
|
||||
"id",
|
||||
"scope",
|
||||
"sourcePath",
|
||||
"startedAt",
|
||||
"status"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookScope": {
|
||||
"enum": [
|
||||
"thread",
|
||||
"turn"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookStartedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"threadId"
|
||||
],
|
||||
"title": "HookStartedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ImageDetail": {
|
||||
"enum": [
|
||||
"auto",
|
||||
@@ -7746,6 +8082,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"MacOsContactsPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
"read_only",
|
||||
"read_write"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MacOsPreferencesPermission": {
|
||||
"enum": [
|
||||
"none",
|
||||
@@ -7772,6 +8116,18 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"macos_contacts": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/MacOsContactsPermission"
|
||||
}
|
||||
],
|
||||
"default": "none"
|
||||
},
|
||||
"macos_launch_services": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"macos_preferences": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -7779,6 +8135,10 @@
|
||||
}
|
||||
],
|
||||
"default": "read_only"
|
||||
},
|
||||
"macos_reminders": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -8737,6 +9097,13 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginAuthPolicy": {
|
||||
"enum": [
|
||||
"ON_INSTALL",
|
||||
"ON_USE"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginInstallParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -8754,6 +9121,14 @@
|
||||
"title": "PluginInstallParams",
|
||||
"type": "object"
|
||||
},
|
||||
"PluginInstallPolicy": {
|
||||
"enum": [
|
||||
"NOT_AVAILABLE",
|
||||
"AVAILABLE",
|
||||
"INSTALLED_BY_DEFAULT"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginInstallResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -8762,6 +9137,16 @@
|
||||
"$ref": "#/definitions/AppSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"authPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginAuthPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -8883,6 +9268,10 @@
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"forceRemoteSync": {
|
||||
"description": "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"title": "PluginListParams",
|
||||
@@ -8896,6 +9285,12 @@
|
||||
"$ref": "#/definitions/PluginMarketplaceEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"remoteSyncError": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -8952,12 +9347,32 @@
|
||||
},
|
||||
"PluginSummary": {
|
||||
"properties": {
|
||||
"authPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginAuthPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"installPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginInstallPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"installed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -8987,6 +9402,24 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginUninstallParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"pluginId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pluginId"
|
||||
],
|
||||
"title": "PluginUninstallParams",
|
||||
"type": "object"
|
||||
},
|
||||
"PluginUninstallResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "PluginUninstallResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ProductSurface": {
|
||||
"enum": [
|
||||
"chatgpt",
|
||||
@@ -9301,6 +9734,32 @@
|
||||
"title": "SessionUpdatedRealtimeEvent",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"InputTranscriptDelta": {
|
||||
"$ref": "#/definitions/RealtimeTranscriptDelta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"InputTranscriptDelta"
|
||||
],
|
||||
"title": "InputTranscriptDeltaRealtimeEvent",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"OutputTranscriptDelta": {
|
||||
"$ref": "#/definitions/RealtimeTranscriptDelta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"OutputTranscriptDelta"
|
||||
],
|
||||
"title": "OutputTranscriptDeltaRealtimeEvent",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -9374,7 +9833,44 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"RealtimeHandoffMessage": {
|
||||
"RealtimeHandoffRequested": {
|
||||
"properties": {
|
||||
"active_transcript": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RealtimeTranscriptEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"handoff_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"input_transcript": {
|
||||
"type": "string"
|
||||
},
|
||||
"item_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"active_transcript",
|
||||
"handoff_id",
|
||||
"input_transcript",
|
||||
"item_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RealtimeTranscriptDelta": {
|
||||
"properties": {
|
||||
"delta": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"delta"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RealtimeTranscriptEntry": {
|
||||
"properties": {
|
||||
"role": {
|
||||
"type": "string"
|
||||
@@ -9389,32 +9885,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RealtimeHandoffRequested": {
|
||||
"properties": {
|
||||
"handoff_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"input_transcript": {
|
||||
"type": "string"
|
||||
},
|
||||
"item_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"messages": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RealtimeHandoffMessage"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"handoff_id",
|
||||
"input_transcript",
|
||||
"item_id",
|
||||
"messages"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningEffort": {
|
||||
"description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning",
|
||||
"enum": [
|
||||
@@ -10982,6 +11452,26 @@
|
||||
"title": "Turn/startedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"hook/started"
|
||||
],
|
||||
"title": "Hook/startedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/HookStartedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Hook/startedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -11002,6 +11492,26 @@
|
||||
"title": "Turn/completedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"hook/completed"
|
||||
],
|
||||
"title": "Hook/completedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/HookCompletedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Hook/completedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -12514,6 +13024,9 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"ephemeral": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"model": {
|
||||
"description": "Configuration overrides for the forked thread, if any.",
|
||||
"type": [
|
||||
@@ -15326,4 +15839,4 @@
|
||||
},
|
||||
"title": "CodexAppServerProtocolV2",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,10 @@
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"reloadUserConfig": {
|
||||
"description": "When true, hot-reload the updated user config into all loaded threads after writing.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -148,11 +148,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -20,11 +20,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"sessionStart",
|
||||
"stop"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookExecutionMode": {
|
||||
"enum": [
|
||||
"sync",
|
||||
"async"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookHandlerType": {
|
||||
"enum": [
|
||||
"command",
|
||||
"prompt",
|
||||
"agent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookOutputEntry": {
|
||||
"properties": {
|
||||
"kind": {
|
||||
"$ref": "#/definitions/HookOutputEntryKind"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"text"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookOutputEntryKind": {
|
||||
"enum": [
|
||||
"warning",
|
||||
"stop",
|
||||
"feedback",
|
||||
"context",
|
||||
"error"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunStatus": {
|
||||
"enum": [
|
||||
"running",
|
||||
"completed",
|
||||
"failed",
|
||||
"blocked",
|
||||
"stopped"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunSummary": {
|
||||
"properties": {
|
||||
"completedAt": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"displayOrder": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"durationMs": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/HookOutputEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"eventName": {
|
||||
"$ref": "#/definitions/HookEventName"
|
||||
},
|
||||
"executionMode": {
|
||||
"$ref": "#/definitions/HookExecutionMode"
|
||||
},
|
||||
"handlerType": {
|
||||
"$ref": "#/definitions/HookHandlerType"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/HookRunStatus"
|
||||
},
|
||||
"statusMessage": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"displayOrder",
|
||||
"entries",
|
||||
"eventName",
|
||||
"executionMode",
|
||||
"handlerType",
|
||||
"id",
|
||||
"scope",
|
||||
"sourcePath",
|
||||
"startedAt",
|
||||
"status"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookScope": {
|
||||
"enum": [
|
||||
"thread",
|
||||
"turn"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"threadId"
|
||||
],
|
||||
"title": "HookCompletedNotification",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"HookEventName": {
|
||||
"enum": [
|
||||
"sessionStart",
|
||||
"stop"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookExecutionMode": {
|
||||
"enum": [
|
||||
"sync",
|
||||
"async"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookHandlerType": {
|
||||
"enum": [
|
||||
"command",
|
||||
"prompt",
|
||||
"agent"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookOutputEntry": {
|
||||
"properties": {
|
||||
"kind": {
|
||||
"$ref": "#/definitions/HookOutputEntryKind"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"text"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookOutputEntryKind": {
|
||||
"enum": [
|
||||
"warning",
|
||||
"stop",
|
||||
"feedback",
|
||||
"context",
|
||||
"error"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunStatus": {
|
||||
"enum": [
|
||||
"running",
|
||||
"completed",
|
||||
"failed",
|
||||
"blocked",
|
||||
"stopped"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"HookRunSummary": {
|
||||
"properties": {
|
||||
"completedAt": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"displayOrder": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"durationMs": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"entries": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/HookOutputEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"eventName": {
|
||||
"$ref": "#/definitions/HookEventName"
|
||||
},
|
||||
"executionMode": {
|
||||
"$ref": "#/definitions/HookExecutionMode"
|
||||
},
|
||||
"handlerType": {
|
||||
"$ref": "#/definitions/HookHandlerType"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"$ref": "#/definitions/HookScope"
|
||||
},
|
||||
"sourcePath": {
|
||||
"type": "string"
|
||||
},
|
||||
"startedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/HookRunStatus"
|
||||
},
|
||||
"statusMessage": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"displayOrder",
|
||||
"entries",
|
||||
"eventName",
|
||||
"executionMode",
|
||||
"handlerType",
|
||||
"id",
|
||||
"scope",
|
||||
"sourcePath",
|
||||
"startedAt",
|
||||
"status"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"HookScope": {
|
||||
"enum": [
|
||||
"thread",
|
||||
"turn"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"run": {
|
||||
"$ref": "#/definitions/HookRunSummary"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
},
|
||||
"turnId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"run",
|
||||
"threadId"
|
||||
],
|
||||
"title": "HookStartedNotification",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -28,6 +28,13 @@
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"PluginAuthPolicy": {
|
||||
"enum": [
|
||||
"ON_INSTALL",
|
||||
"ON_USE"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
@@ -36,6 +43,16 @@
|
||||
"$ref": "#/definitions/AppSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"authPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginAuthPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"forceRemoteSync": {
|
||||
"description": "When true, reconcile the official curated marketplace against the remote plugin state before listing marketplaces.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"title": "PluginListParams",
|
||||
|
||||
@@ -5,6 +5,21 @@
|
||||
"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"
|
||||
},
|
||||
"PluginAuthPolicy": {
|
||||
"enum": [
|
||||
"ON_INSTALL",
|
||||
"ON_USE"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginInstallPolicy": {
|
||||
"enum": [
|
||||
"NOT_AVAILABLE",
|
||||
"AVAILABLE",
|
||||
"INSTALLED_BY_DEFAULT"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PluginInterface": {
|
||||
"properties": {
|
||||
"brandColor": {
|
||||
@@ -154,12 +169,32 @@
|
||||
},
|
||||
"PluginSummary": {
|
||||
"properties": {
|
||||
"authPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginAuthPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"installPolicy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginInstallPolicy"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"installed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -196,6 +231,12 @@
|
||||
"$ref": "#/definitions/PluginMarketplaceEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"remoteSyncError": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"pluginId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pluginId"
|
||||
],
|
||||
"title": "PluginUninstallParams",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "PluginUninstallResponse",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -20,11 +20,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -96,6 +104,9 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"ephemeral": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"model": {
|
||||
"description": "Configuration overrides for the forked thread, if any.",
|
||||
"type": [
|
||||
|
||||
@@ -24,11 +24,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -20,11 +20,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -24,11 +24,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -20,11 +20,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -24,11 +24,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -24,11 +24,19 @@
|
||||
"mcp_elicitations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_permissions": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sandbox_approval": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"skill_approval": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -33,4 +33,4 @@
|
||||
],
|
||||
"title": "WindowsSandboxSetupStartParams",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import type { McpServerOauthLoginParams } from "./v2/McpServerOauthLoginParams";
|
||||
import type { ModelListParams } from "./v2/ModelListParams";
|
||||
import type { PluginInstallParams } from "./v2/PluginInstallParams";
|
||||
import type { PluginListParams } from "./v2/PluginListParams";
|
||||
import type { PluginUninstallParams } from "./v2/PluginUninstallParams";
|
||||
import type { ReviewStartParams } from "./v2/ReviewStartParams";
|
||||
import type { SkillsConfigWriteParams } from "./v2/SkillsConfigWriteParams";
|
||||
import type { SkillsListParams } from "./v2/SkillsListParams";
|
||||
@@ -53,4 +54,4 @@ import type { WindowsSandboxSetupStartParams } from "./v2/WindowsSandboxSetupSta
|
||||
/**
|
||||
* Request from the client to the server.
|
||||
*/
|
||||
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, };
|
||||
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "skills/remote/list", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/export", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "plugin/uninstall", id: RequestId, params: PluginUninstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, };
|
||||
|
||||
@@ -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 { ReasoningEffort } from "./ReasoningEffort";
|
||||
import type { ThreadId } from "./ThreadId";
|
||||
|
||||
export type CollabAgentSpawnBeginEvent = {
|
||||
@@ -16,4 +17,4 @@ sender_thread_id: ThreadId,
|
||||
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
|
||||
* beginning.
|
||||
*/
|
||||
prompt: string, };
|
||||
prompt: string, model: string, reasoning_effort: ReasoningEffort, };
|
||||
|
||||
@@ -33,6 +33,8 @@ import type { ExecCommandEndEvent } from "./ExecCommandEndEvent";
|
||||
import type { ExecCommandOutputDeltaEvent } from "./ExecCommandOutputDeltaEvent";
|
||||
import type { ExitedReviewModeEvent } from "./ExitedReviewModeEvent";
|
||||
import type { GetHistoryEntryResponseEvent } from "./GetHistoryEntryResponseEvent";
|
||||
import type { HookCompletedEvent } from "./HookCompletedEvent";
|
||||
import type { HookStartedEvent } from "./HookStartedEvent";
|
||||
import type { ImageGenerationBeginEvent } from "./ImageGenerationBeginEvent";
|
||||
import type { ImageGenerationEndEvent } from "./ImageGenerationEndEvent";
|
||||
import type { ItemCompletedEvent } from "./ItemCompletedEvent";
|
||||
@@ -56,6 +58,7 @@ import type { RealtimeConversationStartedEvent } from "./RealtimeConversationSta
|
||||
import type { ReasoningContentDeltaEvent } from "./ReasoningContentDeltaEvent";
|
||||
import type { ReasoningRawContentDeltaEvent } from "./ReasoningRawContentDeltaEvent";
|
||||
import type { RemoteSkillDownloadedEvent } from "./RemoteSkillDownloadedEvent";
|
||||
import type { RequestPermissionsEvent } from "./RequestPermissionsEvent";
|
||||
import type { RequestUserInputEvent } from "./RequestUserInputEvent";
|
||||
import type { ReviewRequest } from "./ReviewRequest";
|
||||
import type { SessionConfiguredEvent } from "./SessionConfiguredEvent";
|
||||
@@ -81,4 +84,4 @@ import type { WebSearchEndEvent } from "./WebSearchEndEvent";
|
||||
* Response event from the agent
|
||||
* NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.
|
||||
*/
|
||||
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "image_generation_begin" } & ImageGenerationBeginEvent | { "type": "image_generation_end" } & ImageGenerationEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;
|
||||
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "realtime_conversation_started" } & RealtimeConversationStartedEvent | { "type": "realtime_conversation_realtime" } & RealtimeConversationRealtimeEvent | { "type": "realtime_conversation_closed" } & RealtimeConversationClosedEvent | { "type": "model_reroute" } & ModelRerouteEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "image_generation_begin" } & ImageGenerationBeginEvent | { "type": "image_generation_end" } & ImageGenerationEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_permissions" } & RequestPermissionsEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "dynamic_tool_call_response" } & DynamicToolCallResponseEvent | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "hook_started" } & HookStartedEvent | { "type": "hook_completed" } & HookCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent | { "type": "collab_resume_begin" } & CollabResumeBeginEvent | { "type": "collab_resume_end" } & CollabResumeEndEvent;
|
||||
|
||||
@@ -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 { ExecApprovalRequestSkillMetadata } from "./ExecApprovalRequestSkillMetadata";
|
||||
import type { ExecPolicyAmendment } from "./ExecPolicyAmendment";
|
||||
import type { NetworkApprovalContext } from "./NetworkApprovalContext";
|
||||
import type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment";
|
||||
@@ -53,6 +54,10 @@ proposed_network_policy_amendments?: Array<NetworkPolicyAmendment>,
|
||||
* Optional additional filesystem permissions requested for this command.
|
||||
*/
|
||||
additional_permissions?: PermissionProfile,
|
||||
/**
|
||||
* Optional skill metadata when the approval was triggered by a skill script.
|
||||
*/
|
||||
skill_metadata?: ExecApprovalRequestSkillMetadata,
|
||||
/**
|
||||
* Ordered list of decisions the client may present for this prompt.
|
||||
*
|
||||
|
||||
@@ -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 ExecApprovalRequestSkillMetadata = { path_to_skills_md: string, };
|
||||
@@ -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 { HookRunSummary } from "./HookRunSummary";
|
||||
|
||||
export type HookCompletedEvent = { turn_id: string | null, run: HookRunSummary, };
|
||||
@@ -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 RealtimeHandoffMessage = { role: string, text: string, };
|
||||
export type HookEventName = "session_start" | "stop";
|
||||
@@ -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 HookExecutionMode = "sync" | "async";
|
||||
@@ -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 HookHandlerType = "command" | "prompt" | "agent";
|
||||
@@ -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 { HookOutputEntryKind } from "./HookOutputEntryKind";
|
||||
|
||||
export type HookOutputEntry = { kind: HookOutputEntryKind, text: string, };
|
||||
@@ -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 HookOutputEntryKind = "warning" | "stop" | "feedback" | "context" | "error";
|
||||
@@ -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 HookRunStatus = "running" | "completed" | "failed" | "blocked" | "stopped";
|
||||
@@ -0,0 +1,11 @@
|
||||
// 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 { HookEventName } from "./HookEventName";
|
||||
import type { HookExecutionMode } from "./HookExecutionMode";
|
||||
import type { HookHandlerType } from "./HookHandlerType";
|
||||
import type { HookOutputEntry } from "./HookOutputEntry";
|
||||
import type { HookRunStatus } from "./HookRunStatus";
|
||||
import type { HookScope } from "./HookScope";
|
||||
|
||||
export type HookRunSummary = { id: string, event_name: HookEventName, handler_type: HookHandlerType, execution_mode: HookExecutionMode, scope: HookScope, source_path: string, display_order: bigint, status: HookRunStatus, status_message: string | null, started_at: number, completed_at: number | null, duration_ms: number | 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 HookScope = "thread" | "turn";
|
||||
@@ -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 { HookRunSummary } from "./HookRunSummary";
|
||||
|
||||
export type HookStartedEvent = { turn_id: string | null, run: HookRunSummary, };
|
||||
@@ -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 MacOsContactsPermission = "none" | "read_only" | "read_write";
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { MacOsAutomationPermission } from "./MacOsAutomationPermission";
|
||||
import type { MacOsContactsPermission } from "./MacOsContactsPermission";
|
||||
import type { MacOsPreferencesPermission } from "./MacOsPreferencesPermission";
|
||||
|
||||
export type MacOsSeatbeltProfileExtensions = { macos_preferences: MacOsPreferencesPermission, macos_automation: MacOsAutomationPermission, macos_accessibility: boolean, macos_calendar: boolean, };
|
||||
export type MacOsSeatbeltProfileExtensions = { macos_preferences: MacOsPreferencesPermission, macos_automation: MacOsAutomationPermission, macos_launch_services: boolean, macos_accessibility: boolean, macos_calendar: boolean, macos_reminders: boolean, macos_contacts: MacOsContactsPermission, };
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { RealtimeAudioFrame } from "./RealtimeAudioFrame";
|
||||
import type { RealtimeHandoffRequested } from "./RealtimeHandoffRequested";
|
||||
import type { RealtimeTranscriptDelta } from "./RealtimeTranscriptDelta";
|
||||
import type { JsonValue } from "./serde_json/JsonValue";
|
||||
|
||||
export type RealtimeEvent = { "SessionUpdated": { session_id: string, instructions: string | null, } } | { "AudioOut": RealtimeAudioFrame } | { "ConversationItemAdded": JsonValue } | { "ConversationItemDone": { item_id: string, } } | { "HandoffRequested": RealtimeHandoffRequested } | { "Error": string };
|
||||
export type RealtimeEvent = { "SessionUpdated": { session_id: string, instructions: string | null, } } | { "InputTranscriptDelta": RealtimeTranscriptDelta } | { "OutputTranscriptDelta": RealtimeTranscriptDelta } | { "AudioOut": RealtimeAudioFrame } | { "ConversationItemAdded": JsonValue } | { "ConversationItemDone": { item_id: string, } } | { "HandoffRequested": RealtimeHandoffRequested } | { "Error": string };
|
||||
|
||||
@@ -1,6 +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 { RealtimeHandoffMessage } from "./RealtimeHandoffMessage";
|
||||
import type { RealtimeTranscriptEntry } from "./RealtimeTranscriptEntry";
|
||||
|
||||
export type RealtimeHandoffRequested = { handoff_id: string, item_id: string, input_transcript: string, messages: Array<RealtimeHandoffMessage>, };
|
||||
export type RealtimeHandoffRequested = { handoff_id: string, item_id: string, input_transcript: string, active_transcript: Array<RealtimeTranscriptEntry>, };
|
||||
|
||||
@@ -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 RealtimeTranscriptDelta = { delta: string, };
|
||||
@@ -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 RealtimeTranscriptEntry = { role: string, text: string, };
|
||||
@@ -11,6 +11,14 @@ sandbox_approval: boolean,
|
||||
* Reject prompts triggered by execpolicy `prompt` rules.
|
||||
*/
|
||||
rules: boolean,
|
||||
/**
|
||||
* Reject approval prompts triggered by skill script execution.
|
||||
*/
|
||||
skill_approval: boolean,
|
||||
/**
|
||||
* Reject approval prompts related to built-in permission requests.
|
||||
*/
|
||||
request_permissions: boolean,
|
||||
/**
|
||||
* Reject MCP elicitation prompts.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// 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 { PermissionProfile } from "./PermissionProfile";
|
||||
|
||||
export type RequestPermissionsEvent = {
|
||||
/**
|
||||
* Responses API call id for the associated tool call, if available.
|
||||
*/
|
||||
call_id: string,
|
||||
/**
|
||||
* Turn ID that this request belongs to.
|
||||
* Uses `#[serde(default)]` for backwards compatibility.
|
||||
*/
|
||||
turn_id: string, reason: string | null, permissions: PermissionProfile, };
|
||||
@@ -15,6 +15,8 @@ import type { ContextCompactedNotification } from "./v2/ContextCompactedNotifica
|
||||
import type { DeprecationNoticeNotification } from "./v2/DeprecationNoticeNotification";
|
||||
import type { ErrorNotification } from "./v2/ErrorNotification";
|
||||
import type { FileChangeOutputDeltaNotification } from "./v2/FileChangeOutputDeltaNotification";
|
||||
import type { HookCompletedNotification } from "./v2/HookCompletedNotification";
|
||||
import type { HookStartedNotification } from "./v2/HookStartedNotification";
|
||||
import type { ItemCompletedNotification } from "./v2/ItemCompletedNotification";
|
||||
import type { ItemStartedNotification } from "./v2/ItemStartedNotification";
|
||||
import type { McpServerOauthLoginCompletedNotification } from "./v2/McpServerOauthLoginCompletedNotification";
|
||||
@@ -50,4 +52,4 @@ import type { WindowsWorldWritableWarningNotification } from "./v2/WindowsWorldW
|
||||
/**
|
||||
* Notification sent from the server to the client.
|
||||
*/
|
||||
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
|
||||
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "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/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
|
||||
|
||||
@@ -9,9 +9,10 @@ import type { CommandExecutionRequestApprovalParams } from "./v2/CommandExecutio
|
||||
import type { DynamicToolCallParams } from "./v2/DynamicToolCallParams";
|
||||
import type { FileChangeRequestApprovalParams } from "./v2/FileChangeRequestApprovalParams";
|
||||
import type { McpServerElicitationRequestParams } from "./v2/McpServerElicitationRequestParams";
|
||||
import type { PermissionsRequestApprovalParams } from "./v2/PermissionsRequestApprovalParams";
|
||||
import type { ToolRequestUserInputParams } from "./v2/ToolRequestUserInputParams";
|
||||
|
||||
/**
|
||||
* Request initiated from the server and sent to the client.
|
||||
*/
|
||||
export type ServerRequest = { "method": "item/commandExecution/requestApproval", id: RequestId, params: CommandExecutionRequestApprovalParams, } | { "method": "item/fileChange/requestApproval", id: RequestId, params: FileChangeRequestApprovalParams, } | { "method": "item/tool/requestUserInput", id: RequestId, params: ToolRequestUserInputParams, } | { "method": "mcpServer/elicitation/request", id: RequestId, params: McpServerElicitationRequestParams, } | { "method": "item/tool/call", id: RequestId, params: DynamicToolCallParams, } | { "method": "account/chatgptAuthTokens/refresh", id: RequestId, params: ChatgptAuthTokensRefreshParams, } | { "method": "applyPatchApproval", id: RequestId, params: ApplyPatchApprovalParams, } | { "method": "execCommandApproval", id: RequestId, params: ExecCommandApprovalParams, };
|
||||
export type ServerRequest = { "method": "item/commandExecution/requestApproval", id: RequestId, params: CommandExecutionRequestApprovalParams, } | { "method": "item/fileChange/requestApproval", id: RequestId, params: FileChangeRequestApprovalParams, } | { "method": "item/tool/requestUserInput", id: RequestId, params: ToolRequestUserInputParams, } | { "method": "mcpServer/elicitation/request", id: RequestId, params: McpServerElicitationRequestParams, } | { "method": "item/permissions/requestApproval", id: RequestId, params: PermissionsRequestApprovalParams, } | { "method": "item/tool/call", id: RequestId, params: DynamicToolCallParams, } | { "method": "account/chatgptAuthTokens/refresh", id: RequestId, params: ChatgptAuthTokensRefreshParams, } | { "method": "applyPatchApproval", id: RequestId, params: ApplyPatchApprovalParams, } | { "method": "execCommandApproval", id: RequestId, params: ExecCommandApprovalParams, };
|
||||
|
||||
@@ -53,6 +53,7 @@ export type { ElicitationRequestEvent } from "./ElicitationRequestEvent";
|
||||
export type { ErrorEvent } from "./ErrorEvent";
|
||||
export type { EventMsg } from "./EventMsg";
|
||||
export type { ExecApprovalRequestEvent } from "./ExecApprovalRequestEvent";
|
||||
export type { ExecApprovalRequestSkillMetadata } from "./ExecApprovalRequestSkillMetadata";
|
||||
export type { ExecCommandApprovalParams } from "./ExecCommandApprovalParams";
|
||||
export type { ExecCommandApprovalResponse } from "./ExecCommandApprovalResponse";
|
||||
export type { ExecCommandBeginEvent } from "./ExecCommandBeginEvent";
|
||||
@@ -84,6 +85,16 @@ export type { GitDiffToRemoteParams } from "./GitDiffToRemoteParams";
|
||||
export type { GitDiffToRemoteResponse } from "./GitDiffToRemoteResponse";
|
||||
export type { GitSha } from "./GitSha";
|
||||
export type { HistoryEntry } from "./HistoryEntry";
|
||||
export type { HookCompletedEvent } from "./HookCompletedEvent";
|
||||
export type { HookEventName } from "./HookEventName";
|
||||
export type { HookExecutionMode } from "./HookExecutionMode";
|
||||
export type { HookHandlerType } from "./HookHandlerType";
|
||||
export type { HookOutputEntry } from "./HookOutputEntry";
|
||||
export type { HookOutputEntryKind } from "./HookOutputEntryKind";
|
||||
export type { HookRunStatus } from "./HookRunStatus";
|
||||
export type { HookRunSummary } from "./HookRunSummary";
|
||||
export type { HookScope } from "./HookScope";
|
||||
export type { HookStartedEvent } from "./HookStartedEvent";
|
||||
export type { ImageDetail } from "./ImageDetail";
|
||||
export type { ImageGenerationBeginEvent } from "./ImageGenerationBeginEvent";
|
||||
export type { ImageGenerationEndEvent } from "./ImageGenerationEndEvent";
|
||||
@@ -101,6 +112,7 @@ export type { LocalShellAction } from "./LocalShellAction";
|
||||
export type { LocalShellExecAction } from "./LocalShellExecAction";
|
||||
export type { LocalShellStatus } from "./LocalShellStatus";
|
||||
export type { MacOsAutomationPermission } from "./MacOsAutomationPermission";
|
||||
export type { MacOsContactsPermission } from "./MacOsContactsPermission";
|
||||
export type { MacOsPreferencesPermission } from "./MacOsPreferencesPermission";
|
||||
export type { MacOsSeatbeltProfileExtensions } from "./MacOsSeatbeltProfileExtensions";
|
||||
export type { McpAuthStatus } from "./McpAuthStatus";
|
||||
@@ -141,8 +153,9 @@ export type { RealtimeConversationClosedEvent } from "./RealtimeConversationClos
|
||||
export type { RealtimeConversationRealtimeEvent } from "./RealtimeConversationRealtimeEvent";
|
||||
export type { RealtimeConversationStartedEvent } from "./RealtimeConversationStartedEvent";
|
||||
export type { RealtimeEvent } from "./RealtimeEvent";
|
||||
export type { RealtimeHandoffMessage } from "./RealtimeHandoffMessage";
|
||||
export type { RealtimeHandoffRequested } from "./RealtimeHandoffRequested";
|
||||
export type { RealtimeTranscriptDelta } from "./RealtimeTranscriptDelta";
|
||||
export type { RealtimeTranscriptEntry } from "./RealtimeTranscriptEntry";
|
||||
export type { ReasoningContentDeltaEvent } from "./ReasoningContentDeltaEvent";
|
||||
export type { ReasoningEffort } from "./ReasoningEffort";
|
||||
export type { ReasoningItem } from "./ReasoningItem";
|
||||
@@ -154,6 +167,7 @@ export type { RejectConfig } from "./RejectConfig";
|
||||
export type { RemoteSkillDownloadedEvent } from "./RemoteSkillDownloadedEvent";
|
||||
export type { RemoteSkillSummary } from "./RemoteSkillSummary";
|
||||
export type { RequestId } from "./RequestId";
|
||||
export type { RequestPermissionsEvent } from "./RequestPermissionsEvent";
|
||||
export type { RequestUserInputEvent } from "./RequestUserInputEvent";
|
||||
export type { RequestUserInputQuestion } from "./RequestUserInputQuestion";
|
||||
export type { RequestUserInputQuestionOption } from "./RequestUserInputQuestionOption";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { MacOsAutomationPermission } from "../MacOsAutomationPermission";
|
||||
import type { MacOsContactsPermission } from "../MacOsContactsPermission";
|
||||
import type { MacOsPreferencesPermission } from "../MacOsPreferencesPermission";
|
||||
|
||||
export type AdditionalMacOsPermissions = { preferences: MacOsPreferencesPermission, automations: MacOsAutomationPermission, accessibility: boolean, calendar: boolean, };
|
||||
export type AdditionalMacOsPermissions = { preferences: MacOsPreferencesPermission, automations: MacOsAutomationPermission, launchServices: boolean, accessibility: boolean, calendar: boolean, reminders: boolean, contacts: MacOsContactsPermission, };
|
||||
|
||||
@@ -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 AskForApproval = "untrusted" | "on-failure" | "on-request" | { "reject": { sandbox_approval: boolean, rules: boolean, mcp_elicitations: boolean, } } | "never";
|
||||
export type AskForApproval = "untrusted" | "on-failure" | "on-request" | { "reject": { sandbox_approval: boolean, rules: boolean, skill_approval: boolean, request_permissions: boolean, mcp_elicitations: boolean, } } | "never";
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import type { AdditionalPermissionProfile } from "./AdditionalPermissionProfile";
|
||||
import type { CommandAction } from "./CommandAction";
|
||||
import type { CommandExecutionApprovalDecision } from "./CommandExecutionApprovalDecision";
|
||||
import type { CommandExecutionRequestApprovalSkillMetadata } from "./CommandExecutionRequestApprovalSkillMetadata";
|
||||
import type { ExecPolicyAmendment } from "./ExecPolicyAmendment";
|
||||
import type { NetworkApprovalContext } from "./NetworkApprovalContext";
|
||||
import type { NetworkPolicyAmendment } from "./NetworkPolicyAmendment";
|
||||
@@ -43,6 +44,10 @@ commandActions?: Array<CommandAction> | null,
|
||||
* Optional additional permissions requested for this command.
|
||||
*/
|
||||
additionalPermissions?: AdditionalPermissionProfile | null,
|
||||
/**
|
||||
* Optional skill metadata when the approval was triggered by a skill script.
|
||||
*/
|
||||
skillMetadata?: CommandExecutionRequestApprovalSkillMetadata | null,
|
||||
/**
|
||||
* Optional proposed execpolicy amendment to allow similar commands without prompting.
|
||||
*/
|
||||
|
||||
@@ -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 CommandExecutionRequestApprovalSkillMetadata = { pathToSkillsMd: string, };
|
||||
@@ -7,4 +7,8 @@ export type ConfigBatchWriteParams = { edits: Array<ConfigEdit>,
|
||||
/**
|
||||
* Path to the config file to write; defaults to the user's `config.toml` when omitted.
|
||||
*/
|
||||
filePath?: string | null, expectedVersion?: string | null, };
|
||||
filePath?: string | null, expectedVersion?: string | null,
|
||||
/**
|
||||
* When true, hot-reload the updated user config into all loaded threads after writing.
|
||||
*/
|
||||
reloadUserConfig?: boolean, };
|
||||
|
||||
@@ -0,0 +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 { MacOsAutomationPermission } from "../MacOsAutomationPermission";
|
||||
import type { MacOsContactsPermission } from "../MacOsContactsPermission";
|
||||
import type { MacOsPreferencesPermission } from "../MacOsPreferencesPermission";
|
||||
|
||||
export type GrantedMacOsPermissions = { preferences?: MacOsPreferencesPermission, automations?: MacOsAutomationPermission, launchServices?: boolean, accessibility?: boolean, calendar?: boolean, reminders?: boolean, contacts?: MacOsContactsPermission, };
|
||||
@@ -0,0 +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 { AdditionalFileSystemPermissions } from "./AdditionalFileSystemPermissions";
|
||||
import type { AdditionalNetworkPermissions } from "./AdditionalNetworkPermissions";
|
||||
import type { GrantedMacOsPermissions } from "./GrantedMacOsPermissions";
|
||||
|
||||
export type GrantedPermissionProfile = { network?: AdditionalNetworkPermissions, fileSystem?: AdditionalFileSystemPermissions, macos?: GrantedMacOsPermissions, };
|
||||
@@ -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 { HookRunSummary } from "./HookRunSummary";
|
||||
|
||||
export type HookCompletedNotification = { threadId: string, turnId: string | null, run: HookRunSummary, };
|
||||
@@ -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 HookEventName = "sessionStart" | "stop";
|
||||
@@ -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 HookExecutionMode = "sync" | "async";
|
||||
@@ -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 HookHandlerType = "command" | "prompt" | "agent";
|
||||
@@ -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 { HookOutputEntryKind } from "./HookOutputEntryKind";
|
||||
|
||||
export type HookOutputEntry = { kind: HookOutputEntryKind, text: string, };
|
||||
@@ -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 HookOutputEntryKind = "warning" | "stop" | "feedback" | "context" | "error";
|
||||
@@ -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 HookRunStatus = "running" | "completed" | "failed" | "blocked" | "stopped";
|
||||
@@ -0,0 +1,11 @@
|
||||
// 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 { HookEventName } from "./HookEventName";
|
||||
import type { HookExecutionMode } from "./HookExecutionMode";
|
||||
import type { HookHandlerType } from "./HookHandlerType";
|
||||
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>, };
|
||||
@@ -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 HookScope = "thread" | "turn";
|
||||
@@ -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 { HookRunSummary } from "./HookRunSummary";
|
||||
|
||||
export type HookStartedNotification = { threadId: string, turnId: string | null, run: HookRunSummary, };
|
||||
@@ -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 PermissionGrantScope = "turn" | "session";
|
||||
@@ -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 { AdditionalPermissionProfile } from "./AdditionalPermissionProfile";
|
||||
|
||||
export type PermissionsRequestApprovalParams = { threadId: string, turnId: string, itemId: string, reason: string | null, permissions: AdditionalPermissionProfile, };
|
||||
@@ -0,0 +1,7 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { GrantedPermissionProfile } from "./GrantedPermissionProfile";
|
||||
import type { PermissionGrantScope } from "./PermissionGrantScope";
|
||||
|
||||
export type PermissionsRequestApprovalResponse = { permissions: GrantedPermissionProfile, scope: PermissionGrantScope, };
|
||||
@@ -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 PluginAuthPolicy = "ON_INSTALL" | "ON_USE";
|
||||
@@ -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 PluginInstallPolicy = "NOT_AVAILABLE" | "AVAILABLE" | "INSTALLED_BY_DEFAULT";
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AppSummary } from "./AppSummary";
|
||||
import type { PluginAuthPolicy } from "./PluginAuthPolicy";
|
||||
|
||||
export type PluginInstallResponse = { appsNeedingAuth: Array<AppSummary>, };
|
||||
export type PluginInstallResponse = { authPolicy: PluginAuthPolicy | null, appsNeedingAuth: Array<AppSummary>, };
|
||||
|
||||
@@ -8,4 +8,9 @@ export type PluginListParams = {
|
||||
* Optional working directories used to discover repo marketplaces. When omitted,
|
||||
* only home-scoped marketplaces and the official curated marketplace are considered.
|
||||
*/
|
||||
cwds?: Array<AbsolutePathBuf> | null, };
|
||||
cwds?: Array<AbsolutePathBuf> | null,
|
||||
/**
|
||||
* When true, reconcile the official curated marketplace against the remote plugin state
|
||||
* before listing marketplaces.
|
||||
*/
|
||||
forceRemoteSync?: boolean, };
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { PluginMarketplaceEntry } from "./PluginMarketplaceEntry";
|
||||
|
||||
export type PluginListResponse = { marketplaces: Array<PluginMarketplaceEntry>, };
|
||||
export type PluginListResponse = { marketplaces: Array<PluginMarketplaceEntry>, remoteSyncError: string | null, };
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// 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 { PluginAuthPolicy } from "./PluginAuthPolicy";
|
||||
import type { PluginInstallPolicy } from "./PluginInstallPolicy";
|
||||
import type { PluginInterface } from "./PluginInterface";
|
||||
import type { PluginSource } from "./PluginSource";
|
||||
|
||||
export type PluginSummary = { id: string, name: string, source: PluginSource, installed: boolean, enabled: boolean, interface: PluginInterface | null, };
|
||||
export type PluginSummary = { id: string, name: string, source: PluginSource, installed: boolean, enabled: boolean, installPolicy: PluginInstallPolicy | null, authPolicy: PluginAuthPolicy | null, interface: PluginInterface | 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 PluginUninstallParams = { pluginId: string, };
|
||||
@@ -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 PluginUninstallResponse = Record<string, never>;
|
||||
@@ -22,7 +22,7 @@ export type ThreadForkParams = {threadId: string, /**
|
||||
path?: string | null, /**
|
||||
* Configuration overrides for the forked thread, if any.
|
||||
*/
|
||||
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, /**
|
||||
model?: string | null, modelProvider?: string | null, serviceTier?: ServiceTier | null | null, cwd?: string | null, approvalPolicy?: AskForApproval | null, sandbox?: SandboxMode | null, config?: { [key in string]?: JsonValue } | null, baseInstructions?: string | null, developerInstructions?: string | null, ephemeral?: boolean, /**
|
||||
* If true, persist additional rollout EventMsg variants required to
|
||||
* reconstruct a richer thread history on subsequent resume/fork/read.
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,7 @@ export type { CommandExecutionApprovalDecision } from "./CommandExecutionApprova
|
||||
export type { CommandExecutionOutputDeltaNotification } from "./CommandExecutionOutputDeltaNotification";
|
||||
export type { CommandExecutionRequestApprovalParams } from "./CommandExecutionRequestApprovalParams";
|
||||
export type { CommandExecutionRequestApprovalResponse } from "./CommandExecutionRequestApprovalResponse";
|
||||
export type { CommandExecutionRequestApprovalSkillMetadata } from "./CommandExecutionRequestApprovalSkillMetadata";
|
||||
export type { CommandExecutionStatus } from "./CommandExecutionStatus";
|
||||
export type { Config } from "./Config";
|
||||
export type { ConfigBatchWriteParams } from "./ConfigBatchWriteParams";
|
||||
@@ -98,7 +99,19 @@ export type { GetAccountParams } from "./GetAccountParams";
|
||||
export type { GetAccountRateLimitsResponse } from "./GetAccountRateLimitsResponse";
|
||||
export type { GetAccountResponse } from "./GetAccountResponse";
|
||||
export type { GitInfo } from "./GitInfo";
|
||||
export type { GrantedMacOsPermissions } from "./GrantedMacOsPermissions";
|
||||
export type { GrantedPermissionProfile } from "./GrantedPermissionProfile";
|
||||
export type { HazelnutScope } from "./HazelnutScope";
|
||||
export type { HookCompletedNotification } from "./HookCompletedNotification";
|
||||
export type { HookEventName } from "./HookEventName";
|
||||
export type { HookExecutionMode } from "./HookExecutionMode";
|
||||
export type { HookHandlerType } from "./HookHandlerType";
|
||||
export type { HookOutputEntry } from "./HookOutputEntry";
|
||||
export type { HookOutputEntryKind } from "./HookOutputEntryKind";
|
||||
export type { HookRunStatus } from "./HookRunStatus";
|
||||
export type { HookRunSummary } from "./HookRunSummary";
|
||||
export type { HookScope } from "./HookScope";
|
||||
export type { HookStartedNotification } from "./HookStartedNotification";
|
||||
export type { ItemCompletedNotification } from "./ItemCompletedNotification";
|
||||
export type { ItemStartedNotification } from "./ItemStartedNotification";
|
||||
export type { ListMcpServerStatusParams } from "./ListMcpServerStatusParams";
|
||||
@@ -158,8 +171,13 @@ export type { NetworkRequirements } from "./NetworkRequirements";
|
||||
export type { OverriddenMetadata } from "./OverriddenMetadata";
|
||||
export type { PatchApplyStatus } from "./PatchApplyStatus";
|
||||
export type { PatchChangeKind } from "./PatchChangeKind";
|
||||
export type { PermissionGrantScope } from "./PermissionGrantScope";
|
||||
export type { PermissionsRequestApprovalParams } from "./PermissionsRequestApprovalParams";
|
||||
export type { PermissionsRequestApprovalResponse } from "./PermissionsRequestApprovalResponse";
|
||||
export type { PlanDeltaNotification } from "./PlanDeltaNotification";
|
||||
export type { PluginAuthPolicy } from "./PluginAuthPolicy";
|
||||
export type { PluginInstallParams } from "./PluginInstallParams";
|
||||
export type { PluginInstallPolicy } from "./PluginInstallPolicy";
|
||||
export type { PluginInstallResponse } from "./PluginInstallResponse";
|
||||
export type { PluginInterface } from "./PluginInterface";
|
||||
export type { PluginListParams } from "./PluginListParams";
|
||||
@@ -167,6 +185,8 @@ export type { PluginListResponse } from "./PluginListResponse";
|
||||
export type { PluginMarketplaceEntry } from "./PluginMarketplaceEntry";
|
||||
export type { PluginSource } from "./PluginSource";
|
||||
export type { PluginSummary } from "./PluginSummary";
|
||||
export type { PluginUninstallParams } from "./PluginUninstallParams";
|
||||
export type { PluginUninstallResponse } from "./PluginUninstallResponse";
|
||||
export type { ProductSurface } from "./ProductSurface";
|
||||
export type { ProfileV2 } from "./ProfileV2";
|
||||
export type { RateLimitSnapshot } from "./RateLimitSnapshot";
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Marker trait for protocol types that can signal experimental usage.
|
||||
pub trait ExperimentalApi {
|
||||
/// Returns a short reason identifier when an experimental method or field is
|
||||
@@ -28,8 +31,34 @@ pub fn experimental_required_message(reason: &str) -> String {
|
||||
format!("{reason} requires experimentalApi capability")
|
||||
}
|
||||
|
||||
impl<T: ExperimentalApi> ExperimentalApi for Option<T> {
|
||||
fn experimental_reason(&self) -> Option<&'static str> {
|
||||
self.as_ref().and_then(ExperimentalApi::experimental_reason)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ExperimentalApi> ExperimentalApi for Vec<T> {
|
||||
fn experimental_reason(&self) -> Option<&'static str> {
|
||||
self.iter().find_map(ExperimentalApi::experimental_reason)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V: ExperimentalApi, S> ExperimentalApi for HashMap<K, V, S> {
|
||||
fn experimental_reason(&self) -> Option<&'static str> {
|
||||
self.values().find_map(ExperimentalApi::experimental_reason)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: ExperimentalApi> ExperimentalApi for BTreeMap<K, V> {
|
||||
fn experimental_reason(&self) -> Option<&'static str> {
|
||||
self.values().find_map(ExperimentalApi::experimental_reason)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::ExperimentalApi as ExperimentalApiTrait;
|
||||
use codex_experimental_api_macros::ExperimentalApi;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -48,6 +77,27 @@ mod tests {
|
||||
StableTuple(u8),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(ExperimentalApi)]
|
||||
struct NestedFieldShape {
|
||||
#[experimental(nested)]
|
||||
inner: Option<EnumVariantShapes>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(ExperimentalApi)]
|
||||
struct NestedCollectionShape {
|
||||
#[experimental(nested)]
|
||||
inners: Vec<EnumVariantShapes>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(ExperimentalApi)]
|
||||
struct NestedMapShape {
|
||||
#[experimental(nested)]
|
||||
inners: HashMap<String, EnumVariantShapes>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_supports_all_enum_variant_shapes() {
|
||||
assert_eq!(
|
||||
@@ -67,4 +117,56 @@ mod tests {
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_supports_nested_experimental_fields() {
|
||||
assert_eq!(
|
||||
ExperimentalApiTrait::experimental_reason(&NestedFieldShape {
|
||||
inner: Some(EnumVariantShapes::Named { value: 1 }),
|
||||
}),
|
||||
Some("enum/named")
|
||||
);
|
||||
assert_eq!(
|
||||
ExperimentalApiTrait::experimental_reason(&NestedFieldShape { inner: None }),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_supports_nested_collections() {
|
||||
assert_eq!(
|
||||
ExperimentalApiTrait::experimental_reason(&NestedCollectionShape {
|
||||
inners: vec![
|
||||
EnumVariantShapes::StableTuple(1),
|
||||
EnumVariantShapes::Tuple(2)
|
||||
],
|
||||
}),
|
||||
Some("enum/tuple")
|
||||
);
|
||||
assert_eq!(
|
||||
ExperimentalApiTrait::experimental_reason(&NestedCollectionShape {
|
||||
inners: Vec::new()
|
||||
}),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_supports_nested_maps() {
|
||||
assert_eq!(
|
||||
ExperimentalApiTrait::experimental_reason(&NestedMapShape {
|
||||
inners: HashMap::from([(
|
||||
"default".to_string(),
|
||||
EnumVariantShapes::Named { value: 1 },
|
||||
)]),
|
||||
}),
|
||||
Some("enum/named")
|
||||
);
|
||||
assert_eq!(
|
||||
ExperimentalApiTrait::experimental_reason(&NestedMapShape {
|
||||
inners: HashMap::new(),
|
||||
}),
|
||||
None
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ use schemars::schema_for;
|
||||
use serde::Serialize;
|
||||
use serde_json::Map;
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::OsStr;
|
||||
@@ -32,9 +33,10 @@ use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::thread;
|
||||
use ts_rs::TS;
|
||||
|
||||
const HEADER: &str = "// GENERATED CODE! DO NOT MODIFY BY HAND!\n\n";
|
||||
pub(crate) const GENERATED_TS_HEADER: &str = "// GENERATED CODE! DO NOT MODIFY BY HAND!\n\n";
|
||||
const IGNORED_DEFINITIONS: &[&str] = &["Option<()>"];
|
||||
const JSON_V1_ALLOWLIST: &[&str] = &["InitializeParams", "InitializeResponse"];
|
||||
const SPECIAL_DEFINITIONS: &[&str] = &[
|
||||
@@ -137,9 +139,29 @@ pub fn generate_ts_with_options(
|
||||
}
|
||||
|
||||
if options.ensure_headers {
|
||||
for file in &ts_files {
|
||||
prepend_header_if_missing(file)?;
|
||||
}
|
||||
let worker_count = thread::available_parallelism()
|
||||
.map_or(1, usize::from)
|
||||
.min(ts_files.len().max(1));
|
||||
let chunk_size = ts_files.len().div_ceil(worker_count);
|
||||
thread::scope(|scope| -> Result<()> {
|
||||
let mut workers = Vec::new();
|
||||
for chunk in ts_files.chunks(chunk_size.max(1)) {
|
||||
workers.push(scope.spawn(move || -> Result<()> {
|
||||
for file in chunk {
|
||||
prepend_header_if_missing(file)?;
|
||||
}
|
||||
Ok(())
|
||||
}));
|
||||
}
|
||||
|
||||
for worker in workers {
|
||||
worker
|
||||
.join()
|
||||
.map_err(|_| anyhow!("TypeScript header worker panicked"))??;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
|
||||
// Optionally run Prettier on all generated TS files.
|
||||
@@ -231,6 +253,41 @@ fn filter_experimental_ts(out_dir: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn filter_experimental_ts_tree(tree: &mut BTreeMap<PathBuf, String>) -> Result<()> {
|
||||
let registered_fields = experimental_fields();
|
||||
let experimental_method_types = experimental_method_types();
|
||||
if let Some(content) = tree.get_mut(Path::new("ClientRequest.ts")) {
|
||||
let filtered =
|
||||
filter_client_request_ts_contents(std::mem::take(content), EXPERIMENTAL_CLIENT_METHODS);
|
||||
*content = filtered;
|
||||
}
|
||||
|
||||
let mut fields_by_type_name: HashMap<String, HashSet<String>> = HashMap::new();
|
||||
for field in registered_fields {
|
||||
fields_by_type_name
|
||||
.entry(field.type_name.to_string())
|
||||
.or_default()
|
||||
.insert(field.field_name.to_string());
|
||||
}
|
||||
|
||||
for (path, content) in tree.iter_mut() {
|
||||
let Some(type_name) = path.file_stem().and_then(|stem| stem.to_str()) else {
|
||||
continue;
|
||||
};
|
||||
let Some(experimental_field_names) = fields_by_type_name.get(type_name) else {
|
||||
continue;
|
||||
};
|
||||
let filtered = filter_experimental_type_fields_ts_contents(
|
||||
std::mem::take(content),
|
||||
experimental_field_names,
|
||||
);
|
||||
*content = filtered;
|
||||
}
|
||||
|
||||
remove_generated_type_entries(tree, &experimental_method_types, "ts");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes union arms from `ClientRequest.ts` for methods marked experimental.
|
||||
fn filter_client_request_ts(out_dir: &Path, experimental_methods: &[&str]) -> Result<()> {
|
||||
let path = out_dir.join("ClientRequest.ts");
|
||||
@@ -239,9 +296,15 @@ fn filter_client_request_ts(out_dir: &Path, experimental_methods: &[&str]) -> Re
|
||||
}
|
||||
let mut content =
|
||||
fs::read_to_string(&path).with_context(|| format!("Failed to read {}", path.display()))?;
|
||||
content = filter_client_request_ts_contents(content, experimental_methods);
|
||||
|
||||
fs::write(&path, content).with_context(|| format!("Failed to write {}", path.display()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn filter_client_request_ts_contents(mut content: String, experimental_methods: &[&str]) -> String {
|
||||
let Some((prefix, body, suffix)) = split_type_alias(&content) else {
|
||||
return Ok(());
|
||||
return content;
|
||||
};
|
||||
let experimental_methods: HashSet<&str> = experimental_methods
|
||||
.iter()
|
||||
@@ -259,12 +322,9 @@ fn filter_client_request_ts(out_dir: &Path, experimental_methods: &[&str]) -> Re
|
||||
let new_body = filtered_arms.join(" | ");
|
||||
content = format!("{prefix}{new_body}{suffix}");
|
||||
let import_usage_scope = split_type_alias(&content)
|
||||
.map(|(_, body, _)| body)
|
||||
.map(|(_, filtered_body, _)| filtered_body)
|
||||
.unwrap_or_else(|| new_body.clone());
|
||||
content = prune_unused_type_imports(content, &import_usage_scope);
|
||||
|
||||
fs::write(&path, content).with_context(|| format!("Failed to write {}", path.display()))?;
|
||||
Ok(())
|
||||
prune_unused_type_imports(content, &import_usage_scope)
|
||||
}
|
||||
|
||||
/// Removes experimental properties from generated TypeScript type files.
|
||||
@@ -302,8 +362,17 @@ fn filter_experimental_fields_in_ts_file(
|
||||
) -> Result<()> {
|
||||
let mut content =
|
||||
fs::read_to_string(path).with_context(|| format!("Failed to read {}", path.display()))?;
|
||||
content = filter_experimental_type_fields_ts_contents(content, experimental_field_names);
|
||||
fs::write(path, content).with_context(|| format!("Failed to write {}", path.display()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn filter_experimental_type_fields_ts_contents(
|
||||
mut content: String,
|
||||
experimental_field_names: &HashSet<String>,
|
||||
) -> String {
|
||||
let Some((open_brace, close_brace)) = type_body_brace_span(&content) else {
|
||||
return Ok(());
|
||||
return content;
|
||||
};
|
||||
let inner = &content[open_brace + 1..close_brace];
|
||||
let fields = split_top_level_multi(inner, &[',', ';']);
|
||||
@@ -322,9 +391,7 @@ fn filter_experimental_fields_in_ts_file(
|
||||
let import_usage_scope = split_type_alias(&content)
|
||||
.map(|(_, body, _)| body)
|
||||
.unwrap_or_else(|| new_inner.clone());
|
||||
content = prune_unused_type_imports(content, &import_usage_scope);
|
||||
fs::write(path, content).with_context(|| format!("Failed to write {}", path.display()))?;
|
||||
Ok(())
|
||||
prune_unused_type_imports(content, &import_usage_scope)
|
||||
}
|
||||
|
||||
fn filter_experimental_schema(bundle: &mut Value) -> Result<()> {
|
||||
@@ -526,6 +593,23 @@ fn remove_generated_type_files(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_generated_type_entries(
|
||||
tree: &mut BTreeMap<PathBuf, String>,
|
||||
type_names: &HashSet<String>,
|
||||
extension: &str,
|
||||
) {
|
||||
for type_name in type_names {
|
||||
for subdir in ["", "v1", "v2"] {
|
||||
let path = if subdir.is_empty() {
|
||||
PathBuf::from(format!("{type_name}.{extension}"))
|
||||
} else {
|
||||
PathBuf::from(subdir).join(format!("{type_name}.{extension}"))
|
||||
};
|
||||
tree.remove(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_experimental_method_type_definitions(bundle: &mut Value) {
|
||||
let type_names = experimental_method_types();
|
||||
let Some(definitions) = bundle.get_mut("definitions").and_then(Value::as_object_mut) else {
|
||||
@@ -1807,13 +1891,13 @@ fn prepend_header_if_missing(path: &Path) -> Result<()> {
|
||||
.with_context(|| format!("Failed to read {}", path.display()))?;
|
||||
}
|
||||
|
||||
if content.starts_with(HEADER) {
|
||||
if content.starts_with(GENERATED_TS_HEADER) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut f = fs::File::create(path)
|
||||
.with_context(|| format!("Failed to open {} for writing", path.display()))?;
|
||||
f.write_all(HEADER.as_bytes())
|
||||
f.write_all(GENERATED_TS_HEADER.as_bytes())
|
||||
.with_context(|| format!("Failed to write header to {}", path.display()))?;
|
||||
f.write_all(content.as_bytes())
|
||||
.with_context(|| format!("Failed to write content to {}", path.display()))?;
|
||||
@@ -1858,35 +1942,15 @@ fn ts_files_in_recursive(dir: &Path) -> Result<Vec<PathBuf>> {
|
||||
/// Generate an index.ts file that re-exports all generated types.
|
||||
/// This allows consumers to import all types from a single file.
|
||||
fn generate_index_ts(out_dir: &Path) -> Result<PathBuf> {
|
||||
let mut entries: Vec<String> = Vec::new();
|
||||
let mut stems: Vec<String> = ts_files_in(out_dir)?
|
||||
.into_iter()
|
||||
.filter_map(|p| {
|
||||
let stem = p.file_stem()?.to_string_lossy().into_owned();
|
||||
if stem == "index" { None } else { Some(stem) }
|
||||
})
|
||||
.collect();
|
||||
stems.sort();
|
||||
stems.dedup();
|
||||
|
||||
for name in stems {
|
||||
entries.push(format!("export type {{ {name} }} from \"./{name}\";\n"));
|
||||
}
|
||||
|
||||
// If this is the root out_dir and a ./v2 folder exists with TS files,
|
||||
// expose it as a namespace to avoid symbol collisions at the root.
|
||||
let v2_dir = out_dir.join("v2");
|
||||
let has_v2_ts = ts_files_in(&v2_dir).map(|v| !v.is_empty()).unwrap_or(false);
|
||||
if has_v2_ts {
|
||||
entries.push("export * as v2 from \"./v2\";\n".to_string());
|
||||
}
|
||||
|
||||
let mut content =
|
||||
String::with_capacity(HEADER.len() + entries.iter().map(String::len).sum::<usize>());
|
||||
content.push_str(HEADER);
|
||||
for line in &entries {
|
||||
content.push_str(line);
|
||||
}
|
||||
let content = generated_index_ts_with_header(index_ts_entries(
|
||||
&ts_files_in(out_dir)?
|
||||
.iter()
|
||||
.map(PathBuf::as_path)
|
||||
.collect::<Vec<_>>(),
|
||||
ts_files_in(&out_dir.join("v2"))
|
||||
.map(|v| !v.is_empty())
|
||||
.unwrap_or(false),
|
||||
));
|
||||
|
||||
let index_path = out_dir.join("index.ts");
|
||||
let mut f = fs::File::create(&index_path)
|
||||
@@ -1896,244 +1960,278 @@ fn generate_index_ts(out_dir: &Path) -> Result<PathBuf> {
|
||||
Ok(index_path)
|
||||
}
|
||||
|
||||
pub(crate) fn generate_index_ts_tree(tree: &mut BTreeMap<PathBuf, String>) {
|
||||
let root_entries = tree
|
||||
.keys()
|
||||
.filter(|path| path.components().count() == 1)
|
||||
.map(PathBuf::as_path)
|
||||
.collect::<Vec<_>>();
|
||||
let has_v2_ts = tree.keys().any(|path| {
|
||||
path.parent()
|
||||
.is_some_and(|parent| parent == Path::new("v2"))
|
||||
&& path.extension() == Some(OsStr::new("ts"))
|
||||
&& path.file_stem().is_some_and(|stem| stem != "index")
|
||||
});
|
||||
tree.insert(
|
||||
PathBuf::from("index.ts"),
|
||||
index_ts_entries(&root_entries, has_v2_ts),
|
||||
);
|
||||
|
||||
let v2_entries = tree
|
||||
.keys()
|
||||
.filter(|path| {
|
||||
path.parent()
|
||||
.is_some_and(|parent| parent == Path::new("v2"))
|
||||
})
|
||||
.map(PathBuf::as_path)
|
||||
.collect::<Vec<_>>();
|
||||
if !v2_entries.is_empty() {
|
||||
tree.insert(
|
||||
PathBuf::from("v2").join("index.ts"),
|
||||
index_ts_entries(&v2_entries, false),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn generated_index_ts_with_header(content: String) -> String {
|
||||
let mut with_header = String::with_capacity(GENERATED_TS_HEADER.len() + content.len());
|
||||
with_header.push_str(GENERATED_TS_HEADER);
|
||||
with_header.push_str(&content);
|
||||
with_header
|
||||
}
|
||||
|
||||
fn index_ts_entries(paths: &[&Path], has_v2_ts: bool) -> String {
|
||||
let mut stems: Vec<String> = paths
|
||||
.iter()
|
||||
.filter(|path| path.extension() == Some(OsStr::new("ts")))
|
||||
.filter_map(|path| {
|
||||
let stem = path.file_stem()?.to_string_lossy().into_owned();
|
||||
if stem == "index" { None } else { Some(stem) }
|
||||
})
|
||||
.collect();
|
||||
stems.sort();
|
||||
stems.dedup();
|
||||
|
||||
let mut entries = String::new();
|
||||
for name in stems {
|
||||
entries.push_str(&format!("export type {{ {name} }} from \"./{name}\";\n"));
|
||||
}
|
||||
if has_v2_ts {
|
||||
entries.push_str("export * as v2 from \"./v2\";\n");
|
||||
}
|
||||
entries
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::protocol::v2;
|
||||
use crate::schema_fixtures::read_schema_fixture_subtree;
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn generated_ts_optional_nullable_fields_only_in_params() -> Result<()> {
|
||||
// Assert that "?: T | null" only appears in generated *Params types.
|
||||
let output_dir = std::env::temp_dir().join(format!("codex_ts_types_{}", Uuid::now_v7()));
|
||||
fs::create_dir(&output_dir)?;
|
||||
let fixture_tree = read_schema_fixture_subtree(&schema_root()?, "typescript")?;
|
||||
|
||||
struct TempDirGuard(PathBuf);
|
||||
|
||||
impl Drop for TempDirGuard {
|
||||
fn drop(&mut self) {
|
||||
let _ = fs::remove_dir_all(&self.0);
|
||||
}
|
||||
}
|
||||
|
||||
let _guard = TempDirGuard(output_dir.clone());
|
||||
|
||||
// Avoid doing more work than necessary to keep the test from timing out.
|
||||
let options = GenerateTsOptions {
|
||||
generate_indices: false,
|
||||
ensure_headers: false,
|
||||
run_prettier: false,
|
||||
experimental_api: false,
|
||||
};
|
||||
generate_ts_with_options(&output_dir, None, options)?;
|
||||
|
||||
let client_request_ts = fs::read_to_string(output_dir.join("ClientRequest.ts"))?;
|
||||
let client_request_ts = std::str::from_utf8(
|
||||
fixture_tree
|
||||
.get(Path::new("ClientRequest.ts"))
|
||||
.ok_or_else(|| anyhow::anyhow!("missing ClientRequest.ts fixture"))?,
|
||||
)?;
|
||||
assert_eq!(client_request_ts.contains("mock/experimentalMethod"), false);
|
||||
assert_eq!(
|
||||
client_request_ts.contains("MockExperimentalMethodParams"),
|
||||
false
|
||||
);
|
||||
assert_eq!(output_dir.join("EventMsg.ts").exists(), true);
|
||||
let thread_start_ts =
|
||||
fs::read_to_string(output_dir.join("v2").join("ThreadStartParams.ts"))?;
|
||||
assert_eq!(fixture_tree.contains_key(Path::new("EventMsg.ts")), true);
|
||||
let thread_start_ts = std::str::from_utf8(
|
||||
fixture_tree
|
||||
.get(Path::new("v2/ThreadStartParams.ts"))
|
||||
.ok_or_else(|| anyhow::anyhow!("missing v2/ThreadStartParams.ts fixture"))?,
|
||||
)?;
|
||||
assert_eq!(thread_start_ts.contains("mockExperimentalField"), false);
|
||||
assert_eq!(
|
||||
output_dir
|
||||
.join("v2")
|
||||
.join("MockExperimentalMethodParams.ts")
|
||||
.exists(),
|
||||
fixture_tree.contains_key(Path::new("v2/MockExperimentalMethodParams.ts")),
|
||||
false
|
||||
);
|
||||
assert_eq!(
|
||||
output_dir
|
||||
.join("v2")
|
||||
.join("MockExperimentalMethodResponse.ts")
|
||||
.exists(),
|
||||
fixture_tree.contains_key(Path::new("v2/MockExperimentalMethodResponse.ts")),
|
||||
false
|
||||
);
|
||||
|
||||
let mut undefined_offenders = Vec::new();
|
||||
let mut optional_nullable_offenders = BTreeSet::new();
|
||||
let mut stack = vec![output_dir];
|
||||
while let Some(dir) = stack.pop() {
|
||||
for entry in fs::read_dir(&dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
stack.push(path);
|
||||
for (path, contents) in &fixture_tree {
|
||||
if !matches!(path.extension().and_then(|ext| ext.to_str()), Some("ts")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only allow "?: T | null" in objects representing JSON-RPC requests,
|
||||
// which we assume are called "*Params".
|
||||
let allow_optional_nullable = path
|
||||
.file_stem()
|
||||
.and_then(|stem| stem.to_str())
|
||||
.is_some_and(|stem| {
|
||||
stem.ends_with("Params")
|
||||
|| stem == "InitializeCapabilities"
|
||||
|| matches!(
|
||||
stem,
|
||||
"CollabAgentRef"
|
||||
| "CollabAgentStatusEntry"
|
||||
| "CollabAgentSpawnEndEvent"
|
||||
| "CollabAgentInteractionEndEvent"
|
||||
| "CollabCloseEndEvent"
|
||||
| "CollabResumeBeginEvent"
|
||||
| "CollabResumeEndEvent"
|
||||
)
|
||||
});
|
||||
|
||||
let contents = std::str::from_utf8(contents)?;
|
||||
if contents.contains("| undefined") {
|
||||
undefined_offenders.push(path.clone());
|
||||
}
|
||||
|
||||
const SKIP_PREFIXES: &[&str] = &[
|
||||
"const ",
|
||||
"let ",
|
||||
"var ",
|
||||
"export const ",
|
||||
"export let ",
|
||||
"export var ",
|
||||
];
|
||||
|
||||
let mut search_start = 0;
|
||||
while let Some(idx) = contents[search_start..].find("| null") {
|
||||
let abs_idx = search_start + idx;
|
||||
// Find the property-colon for this field by scanning forward
|
||||
// from the start of the segment and ignoring nested braces,
|
||||
// brackets, and parens. This avoids colons inside nested
|
||||
// type literals like `{ [k in string]?: string }`.
|
||||
|
||||
let line_start_idx = contents[..abs_idx].rfind('\n').map(|i| i + 1).unwrap_or(0);
|
||||
|
||||
let mut segment_start_idx = line_start_idx;
|
||||
if let Some(rel_idx) = contents[line_start_idx..abs_idx].rfind(',') {
|
||||
segment_start_idx = segment_start_idx.max(line_start_idx + rel_idx + 1);
|
||||
}
|
||||
if let Some(rel_idx) = contents[line_start_idx..abs_idx].rfind('{') {
|
||||
segment_start_idx = segment_start_idx.max(line_start_idx + rel_idx + 1);
|
||||
}
|
||||
if let Some(rel_idx) = contents[line_start_idx..abs_idx].rfind('}') {
|
||||
segment_start_idx = segment_start_idx.max(line_start_idx + rel_idx + 1);
|
||||
}
|
||||
|
||||
// Scan forward for the colon that separates the field name from its type.
|
||||
let mut level_brace = 0_i32;
|
||||
let mut level_brack = 0_i32;
|
||||
let mut level_paren = 0_i32;
|
||||
let mut in_single = false;
|
||||
let mut in_double = false;
|
||||
let mut escape = false;
|
||||
let mut prop_colon_idx = None;
|
||||
for (i, ch) in contents[segment_start_idx..abs_idx].char_indices() {
|
||||
let idx_abs = segment_start_idx + i;
|
||||
if escape {
|
||||
escape = false;
|
||||
continue;
|
||||
}
|
||||
match ch {
|
||||
'\\' => {
|
||||
if in_single || in_double {
|
||||
escape = true;
|
||||
}
|
||||
}
|
||||
'\'' => {
|
||||
if !in_double {
|
||||
in_single = !in_single;
|
||||
}
|
||||
}
|
||||
'"' => {
|
||||
if !in_single {
|
||||
in_double = !in_double;
|
||||
}
|
||||
}
|
||||
'{' if !in_single && !in_double => level_brace += 1,
|
||||
'}' if !in_single && !in_double => level_brace -= 1,
|
||||
'[' if !in_single && !in_double => level_brack += 1,
|
||||
']' if !in_single && !in_double => level_brack -= 1,
|
||||
'(' if !in_single && !in_double => level_paren += 1,
|
||||
')' if !in_single && !in_double => level_paren -= 1,
|
||||
':' if !in_single
|
||||
&& !in_double
|
||||
&& level_brace == 0
|
||||
&& level_brack == 0
|
||||
&& level_paren == 0 =>
|
||||
{
|
||||
prop_colon_idx = Some(idx_abs);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(colon_idx) = prop_colon_idx else {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut field_prefix = contents[segment_start_idx..colon_idx].trim();
|
||||
if field_prefix.is_empty() {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if matches!(path.extension().and_then(|ext| ext.to_str()), Some("ts")) {
|
||||
// Only allow "?: T | null" in objects representing JSON-RPC requests,
|
||||
// which we assume are called "*Params".
|
||||
let allow_optional_nullable = path
|
||||
.file_stem()
|
||||
.and_then(|stem| stem.to_str())
|
||||
.is_some_and(|stem| {
|
||||
stem.ends_with("Params")
|
||||
|| stem == "InitializeCapabilities"
|
||||
|| matches!(
|
||||
stem,
|
||||
"CollabAgentRef"
|
||||
| "CollabAgentStatusEntry"
|
||||
| "CollabAgentSpawnEndEvent"
|
||||
| "CollabAgentInteractionEndEvent"
|
||||
| "CollabCloseEndEvent"
|
||||
| "CollabResumeBeginEvent"
|
||||
| "CollabResumeEndEvent"
|
||||
)
|
||||
});
|
||||
|
||||
let contents = fs::read_to_string(&path)?;
|
||||
if contents.contains("| undefined") {
|
||||
undefined_offenders.push(path.clone());
|
||||
}
|
||||
|
||||
const SKIP_PREFIXES: &[&str] = &[
|
||||
"const ",
|
||||
"let ",
|
||||
"var ",
|
||||
"export const ",
|
||||
"export let ",
|
||||
"export var ",
|
||||
];
|
||||
|
||||
let mut search_start = 0;
|
||||
while let Some(idx) = contents[search_start..].find("| null") {
|
||||
let abs_idx = search_start + idx;
|
||||
// Find the property-colon for this field by scanning forward
|
||||
// from the start of the segment and ignoring nested braces,
|
||||
// brackets, and parens. This avoids colons inside nested
|
||||
// type literals like `{ [k in string]?: string }`.
|
||||
|
||||
let line_start_idx =
|
||||
contents[..abs_idx].rfind('\n').map(|i| i + 1).unwrap_or(0);
|
||||
|
||||
let mut segment_start_idx = line_start_idx;
|
||||
if let Some(rel_idx) = contents[line_start_idx..abs_idx].rfind(',') {
|
||||
segment_start_idx = segment_start_idx.max(line_start_idx + rel_idx + 1);
|
||||
}
|
||||
if let Some(rel_idx) = contents[line_start_idx..abs_idx].rfind('{') {
|
||||
segment_start_idx = segment_start_idx.max(line_start_idx + rel_idx + 1);
|
||||
}
|
||||
if let Some(rel_idx) = contents[line_start_idx..abs_idx].rfind('}') {
|
||||
segment_start_idx = segment_start_idx.max(line_start_idx + rel_idx + 1);
|
||||
}
|
||||
|
||||
// Scan forward for the colon that separates the field name from its type.
|
||||
let mut level_brace = 0_i32;
|
||||
let mut level_brack = 0_i32;
|
||||
let mut level_paren = 0_i32;
|
||||
let mut in_single = false;
|
||||
let mut in_double = false;
|
||||
let mut escape = false;
|
||||
let mut prop_colon_idx = None;
|
||||
for (i, ch) in contents[segment_start_idx..abs_idx].char_indices() {
|
||||
let idx_abs = segment_start_idx + i;
|
||||
if escape {
|
||||
escape = false;
|
||||
continue;
|
||||
}
|
||||
match ch {
|
||||
'\\' => {
|
||||
// Only treat as escape when inside a string.
|
||||
if in_single || in_double {
|
||||
escape = true;
|
||||
}
|
||||
}
|
||||
'\'' => {
|
||||
if !in_double {
|
||||
in_single = !in_single;
|
||||
}
|
||||
}
|
||||
'"' => {
|
||||
if !in_single {
|
||||
in_double = !in_double;
|
||||
}
|
||||
}
|
||||
'{' if !in_single && !in_double => level_brace += 1,
|
||||
'}' if !in_single && !in_double => level_brace -= 1,
|
||||
'[' if !in_single && !in_double => level_brack += 1,
|
||||
']' if !in_single && !in_double => level_brack -= 1,
|
||||
'(' if !in_single && !in_double => level_paren += 1,
|
||||
')' if !in_single && !in_double => level_paren -= 1,
|
||||
':' if !in_single
|
||||
&& !in_double
|
||||
&& level_brace == 0
|
||||
&& level_brack == 0
|
||||
&& level_paren == 0 =>
|
||||
{
|
||||
prop_colon_idx = Some(idx_abs);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(colon_idx) = prop_colon_idx else {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut field_prefix = contents[segment_start_idx..colon_idx].trim();
|
||||
if field_prefix.is_empty() {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(comment_idx) = field_prefix.rfind("*/") {
|
||||
field_prefix = field_prefix[comment_idx + 2..].trim_start();
|
||||
}
|
||||
|
||||
if field_prefix.is_empty() {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if SKIP_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| field_prefix.starts_with(prefix))
|
||||
{
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if field_prefix.contains('(') {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the last non-whitespace before ':' is '?', then this is an
|
||||
// optional field with a nullable type (i.e., "?: T | null").
|
||||
// These are only allowed in *Params types.
|
||||
if field_prefix.chars().rev().find(|c| !c.is_whitespace()) == Some('?')
|
||||
&& !allow_optional_nullable
|
||||
{
|
||||
let line_number =
|
||||
contents[..abs_idx].chars().filter(|c| *c == '\n').count() + 1;
|
||||
let offending_line_end = contents[line_start_idx..]
|
||||
.find('\n')
|
||||
.map(|i| line_start_idx + i)
|
||||
.unwrap_or(contents.len());
|
||||
let offending_snippet =
|
||||
contents[line_start_idx..offending_line_end].trim();
|
||||
|
||||
optional_nullable_offenders.insert(format!(
|
||||
"{}:{}: {offending_snippet}",
|
||||
path.display(),
|
||||
line_number
|
||||
));
|
||||
}
|
||||
|
||||
search_start = abs_idx + 5;
|
||||
}
|
||||
if let Some(comment_idx) = field_prefix.rfind("*/") {
|
||||
field_prefix = field_prefix[comment_idx + 2..].trim_start();
|
||||
}
|
||||
|
||||
if field_prefix.is_empty() {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if SKIP_PREFIXES
|
||||
.iter()
|
||||
.any(|prefix| field_prefix.starts_with(prefix))
|
||||
{
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if field_prefix.contains('(') {
|
||||
search_start = abs_idx + 5;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the last non-whitespace before ':' is '?', then this is an
|
||||
// optional field with a nullable type (i.e., "?: T | null").
|
||||
// These are only allowed in *Params types.
|
||||
if field_prefix.chars().rev().find(|c| !c.is_whitespace()) == Some('?')
|
||||
&& !allow_optional_nullable
|
||||
{
|
||||
let line_number =
|
||||
contents[..abs_idx].chars().filter(|c| *c == '\n').count() + 1;
|
||||
let offending_line_end = contents[line_start_idx..]
|
||||
.find('\n')
|
||||
.map(|i| line_start_idx + i)
|
||||
.unwrap_or(contents.len());
|
||||
let offending_snippet = contents[line_start_idx..offending_line_end].trim();
|
||||
|
||||
optional_nullable_offenders.insert(format!(
|
||||
"{}:{}: {offending_snippet}",
|
||||
path.display(),
|
||||
line_number
|
||||
));
|
||||
}
|
||||
|
||||
search_start = abs_idx + 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2153,59 +2251,48 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn schema_root() -> Result<PathBuf> {
|
||||
let typescript_index = codex_utils_cargo_bin::find_resource!("schema/typescript/index.ts")
|
||||
.context("resolve TypeScript schema index.ts")?;
|
||||
let schema_root = typescript_index
|
||||
.parent()
|
||||
.and_then(|parent| parent.parent())
|
||||
.context("derive schema root from schema/typescript/index.ts")?
|
||||
.to_path_buf();
|
||||
Ok(schema_root)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_ts_with_experimental_api_retains_experimental_entries() -> Result<()> {
|
||||
let output_dir =
|
||||
std::env::temp_dir().join(format!("codex_ts_types_experimental_{}", Uuid::now_v7()));
|
||||
fs::create_dir(&output_dir)?;
|
||||
|
||||
struct TempDirGuard(PathBuf);
|
||||
|
||||
impl Drop for TempDirGuard {
|
||||
fn drop(&mut self) {
|
||||
let _ = fs::remove_dir_all(&self.0);
|
||||
}
|
||||
}
|
||||
|
||||
let _guard = TempDirGuard(output_dir.clone());
|
||||
|
||||
let options = GenerateTsOptions {
|
||||
generate_indices: false,
|
||||
ensure_headers: false,
|
||||
run_prettier: false,
|
||||
experimental_api: true,
|
||||
};
|
||||
generate_ts_with_options(&output_dir, None, options)?;
|
||||
|
||||
let client_request_ts = fs::read_to_string(output_dir.join("ClientRequest.ts"))?;
|
||||
let client_request_ts = ClientRequest::export_to_string()?;
|
||||
assert_eq!(client_request_ts.contains("mock/experimentalMethod"), true);
|
||||
assert_eq!(
|
||||
output_dir
|
||||
.join("v2")
|
||||
.join("MockExperimentalMethodParams.ts")
|
||||
.exists(),
|
||||
client_request_ts.contains("MockExperimentalMethodParams"),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
output_dir
|
||||
.join("v2")
|
||||
.join("MockExperimentalMethodResponse.ts")
|
||||
.exists(),
|
||||
v2::MockExperimentalMethodParams::export_to_string()?
|
||||
.contains("MockExperimentalMethodParams"),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
v2::MockExperimentalMethodResponse::export_to_string()?
|
||||
.contains("MockExperimentalMethodResponse"),
|
||||
true
|
||||
);
|
||||
|
||||
let thread_start_ts =
|
||||
fs::read_to_string(output_dir.join("v2").join("ThreadStartParams.ts"))?;
|
||||
let thread_start_ts = v2::ThreadStartParams::export_to_string()?;
|
||||
assert_eq!(thread_start_ts.contains("mockExperimentalField"), true);
|
||||
let command_execution_request_approval_ts = fs::read_to_string(
|
||||
output_dir
|
||||
.join("v2")
|
||||
.join("CommandExecutionRequestApprovalParams.ts"),
|
||||
)?;
|
||||
let command_execution_request_approval_ts =
|
||||
v2::CommandExecutionRequestApprovalParams::export_to_string()?;
|
||||
assert_eq!(
|
||||
command_execution_request_approval_ts.contains("additionalPermissions"),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
command_execution_request_approval_ts.contains("skillMetadata"),
|
||||
true
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2318,48 +2405,6 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_schema_bundle_rejects_conflicting_duplicate_definitions() {
|
||||
let err = build_schema_bundle(vec![
|
||||
GeneratedSchema {
|
||||
namespace: Some("v2".to_string()),
|
||||
logical_name: "First".to_string(),
|
||||
in_v1_dir: false,
|
||||
value: serde_json::json!({
|
||||
"title": "First",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"Shared": {
|
||||
"title": "SharedString",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}),
|
||||
},
|
||||
GeneratedSchema {
|
||||
namespace: Some("v2".to_string()),
|
||||
logical_name: "Second".to_string(),
|
||||
in_v1_dir: false,
|
||||
value: serde_json::json!({
|
||||
"title": "Second",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"Shared": {
|
||||
"title": "SharedInteger",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}),
|
||||
},
|
||||
])
|
||||
.expect_err("conflicting schema definitions should be rejected");
|
||||
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
"schema definition collision in namespace `v2`: Shared (existing title: SharedString, new title: SharedInteger); use #[schemars(rename = \"...\")] to rename one of the conflicting schema definitions"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_flat_v2_schema_keeps_shared_root_schemas_and_dependencies() -> Result<()> {
|
||||
let bundle = serde_json::json!({
|
||||
@@ -2668,6 +2713,10 @@ export type Config = { stableField: Keep, unstableField: string | null } & ({ [k
|
||||
command_execution_request_approval_json.contains("additionalPermissions"),
|
||||
false
|
||||
);
|
||||
assert_eq!(
|
||||
command_execution_request_approval_json.contains("skillMetadata"),
|
||||
false
|
||||
);
|
||||
|
||||
let client_request_json = fs::read_to_string(output_dir.join("ClientRequest.json"))?;
|
||||
assert_eq!(
|
||||
@@ -2679,6 +2728,7 @@ export type Config = { stableField: Keep, unstableField: string | null } & ({ [k
|
||||
fs::read_to_string(output_dir.join("codex_app_server_protocol.schemas.json"))?;
|
||||
assert_eq!(bundle_json.contains("mockExperimentalField"), false);
|
||||
assert_eq!(bundle_json.contains("additionalPermissions"), false);
|
||||
assert_eq!(bundle_json.contains("skillMetadata"), false);
|
||||
assert_eq!(bundle_json.contains("MockExperimentalMethodParams"), false);
|
||||
assert_eq!(
|
||||
bundle_json.contains("MockExperimentalMethodResponse"),
|
||||
@@ -2688,6 +2738,7 @@ export type Config = { stableField: Keep, unstableField: string | null } & ({ [k
|
||||
fs::read_to_string(output_dir.join("codex_app_server_protocol.v2.schemas.json"))?;
|
||||
assert_eq!(flat_v2_bundle_json.contains("mockExperimentalField"), false);
|
||||
assert_eq!(flat_v2_bundle_json.contains("additionalPermissions"), false);
|
||||
assert_eq!(flat_v2_bundle_json.contains("skillMetadata"), false);
|
||||
assert_eq!(
|
||||
flat_v2_bundle_json.contains("MockExperimentalMethodParams"),
|
||||
false
|
||||
|
||||
@@ -17,6 +17,9 @@ pub use protocol::thread_history::*;
|
||||
pub use protocol::v1::*;
|
||||
pub use protocol::v2::*;
|
||||
pub use schema_fixtures::SchemaFixtureOptions;
|
||||
#[doc(hidden)]
|
||||
pub use schema_fixtures::generate_typescript_schema_fixture_subtree_for_tests;
|
||||
pub use schema_fixtures::read_schema_fixture_subtree;
|
||||
pub use schema_fixtures::read_schema_fixture_tree;
|
||||
pub use schema_fixtures::write_schema_fixtures;
|
||||
pub use schema_fixtures::write_schema_fixtures_with_options;
|
||||
|
||||
@@ -44,15 +44,15 @@ pub enum AuthMode {
|
||||
|
||||
macro_rules! experimental_reason_expr {
|
||||
// If a request variant is explicitly marked experimental, that reason wins.
|
||||
(#[experimental($reason:expr)] $params:ident $(, $inspect_params:tt)?) => {
|
||||
(variant $variant:ident, #[experimental($reason:expr)] $params:ident $(, $inspect_params:tt)?) => {
|
||||
Some($reason)
|
||||
};
|
||||
// `inspect_params: true` is used when a method is mostly stable but needs
|
||||
// field-level gating from its params type (for example, ThreadStart).
|
||||
($params:ident, true) => {
|
||||
(variant $variant:ident, $params:ident, true) => {
|
||||
crate::experimental_api::ExperimentalApi::experimental_reason($params)
|
||||
};
|
||||
($params:ident $(, $inspect_params:tt)?) => {
|
||||
(variant $variant:ident, $params:ident $(, $inspect_params:tt)?) => {
|
||||
None
|
||||
};
|
||||
}
|
||||
@@ -110,12 +110,33 @@ macro_rules! client_request_definitions {
|
||||
)*
|
||||
}
|
||||
|
||||
impl ClientRequest {
|
||||
pub fn id(&self) -> &RequestId {
|
||||
match self {
|
||||
$(Self::$variant { request_id, .. } => request_id,)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn method(&self) -> String {
|
||||
serde_json::to_value(self)
|
||||
.ok()
|
||||
.and_then(|value| {
|
||||
value
|
||||
.get("method")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::to_owned)
|
||||
})
|
||||
.unwrap_or_else(|| "<unknown>".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::experimental_api::ExperimentalApi for ClientRequest {
|
||||
fn experimental_reason(&self) -> Option<&'static str> {
|
||||
match self {
|
||||
$(
|
||||
Self::$variant { params: _params, .. } => {
|
||||
experimental_reason_expr!(
|
||||
variant $variant,
|
||||
$(#[experimental($reason)])?
|
||||
_params
|
||||
$(, $inspect_params)?
|
||||
@@ -151,6 +172,12 @@ macro_rules! client_request_definitions {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn visit_client_response_types(v: &mut impl ::ts_rs::TypeVisitor) {
|
||||
$(
|
||||
v.visit::<$response>();
|
||||
)*
|
||||
}
|
||||
|
||||
#[allow(clippy::vec_init_then_push)]
|
||||
pub fn export_client_response_schemas(
|
||||
out_dir: &::std::path::Path,
|
||||
@@ -207,6 +234,23 @@ client_request_definitions! {
|
||||
params: v2::ThreadUnsubscribeParams,
|
||||
response: v2::ThreadUnsubscribeResponse,
|
||||
},
|
||||
#[experimental("thread/increment_elicitation")]
|
||||
/// Increment the thread-local out-of-band elicitation counter.
|
||||
///
|
||||
/// This is used by external helpers to pause timeout accounting while a user
|
||||
/// approval or other elicitation is pending outside the app-server request flow.
|
||||
ThreadIncrementElicitation => "thread/increment_elicitation" {
|
||||
params: v2::ThreadIncrementElicitationParams,
|
||||
response: v2::ThreadIncrementElicitationResponse,
|
||||
},
|
||||
#[experimental("thread/decrement_elicitation")]
|
||||
/// Decrement the thread-local out-of-band elicitation counter.
|
||||
///
|
||||
/// When the count reaches zero, timeout accounting resumes for the thread.
|
||||
ThreadDecrementElicitation => "thread/decrement_elicitation" {
|
||||
params: v2::ThreadDecrementElicitationParams,
|
||||
response: v2::ThreadDecrementElicitationResponse,
|
||||
},
|
||||
ThreadSetName => "thread/name/set" {
|
||||
params: v2::ThreadSetNameParams,
|
||||
response: v2::ThreadSetNameResponse,
|
||||
@@ -272,6 +316,10 @@ client_request_definitions! {
|
||||
params: v2::PluginInstallParams,
|
||||
response: v2::PluginInstallResponse,
|
||||
},
|
||||
PluginUninstall => "plugin/uninstall" {
|
||||
params: v2::PluginUninstallParams,
|
||||
response: v2::PluginUninstallResponse,
|
||||
},
|
||||
TurnStart => "turn/start" {
|
||||
params: v2::TurnStartParams,
|
||||
inspect_params: true,
|
||||
@@ -525,6 +573,12 @@ macro_rules! server_request_definitions {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn visit_server_response_types(v: &mut impl ::ts_rs::TypeVisitor) {
|
||||
$(
|
||||
v.visit::<$response>();
|
||||
)*
|
||||
}
|
||||
|
||||
#[allow(clippy::vec_init_then_push)]
|
||||
pub fn export_server_response_schemas(
|
||||
out_dir: &Path,
|
||||
@@ -675,6 +729,12 @@ server_request_definitions! {
|
||||
response: v2::McpServerElicitationRequestResponse,
|
||||
},
|
||||
|
||||
/// Request approval for additional permissions from the user.
|
||||
PermissionsRequestApproval => "item/permissions/requestApproval" {
|
||||
params: v2::PermissionsRequestApprovalParams,
|
||||
response: v2::PermissionsRequestApprovalResponse,
|
||||
},
|
||||
|
||||
/// Execute a dynamic tool call on the client.
|
||||
DynamicToolCall => "item/tool/call" {
|
||||
params: v2::DynamicToolCallParams,
|
||||
@@ -786,7 +846,9 @@ server_notification_definitions! {
|
||||
ThreadNameUpdated => "thread/name/updated" (v2::ThreadNameUpdatedNotification),
|
||||
ThreadTokenUsageUpdated => "thread/tokenUsage/updated" (v2::ThreadTokenUsageUpdatedNotification),
|
||||
TurnStarted => "turn/started" (v2::TurnStartedNotification),
|
||||
HookStarted => "hook/started" (v2::HookStartedNotification),
|
||||
TurnCompleted => "turn/completed" (v2::TurnCompletedNotification),
|
||||
HookCompleted => "hook/completed" (v2::HookCompletedNotification),
|
||||
TurnDiffUpdated => "turn/diff/updated" (v2::TurnDiffUpdatedNotification),
|
||||
TurnPlanUpdated => "turn/plan/updated" (v2::TurnPlanUpdatedNotification),
|
||||
ItemStarted => "item/started" (v2::ItemStartedNotification),
|
||||
@@ -1136,6 +1198,8 @@ mod tests {
|
||||
request_id: RequestId::Integer(1),
|
||||
params: None,
|
||||
};
|
||||
assert_eq!(request.id(), &RequestId::Integer(1));
|
||||
assert_eq!(request.method(), "account/rateLimits/read");
|
||||
assert_eq!(
|
||||
json!({
|
||||
"method": "account/rateLimits/read",
|
||||
@@ -1540,6 +1604,7 @@ mod tests {
|
||||
}),
|
||||
macos: None,
|
||||
}),
|
||||
skill_metadata: None,
|
||||
proposed_execpolicy_amendment: None,
|
||||
proposed_network_policy_amendments: None,
|
||||
available_decisions: None,
|
||||
@@ -1550,4 +1615,31 @@ mod tests {
|
||||
Some("item/commandExecution/requestApproval.additionalPermissions")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_execution_request_approval_skill_metadata_is_marked_experimental() {
|
||||
let params = v2::CommandExecutionRequestApprovalParams {
|
||||
thread_id: "thr_123".to_string(),
|
||||
turn_id: "turn_123".to_string(),
|
||||
item_id: "call_123".to_string(),
|
||||
approval_id: None,
|
||||
reason: None,
|
||||
network_approval_context: None,
|
||||
command: Some("cat file".to_string()),
|
||||
cwd: None,
|
||||
command_actions: None,
|
||||
additional_permissions: None,
|
||||
skill_metadata: Some(v2::CommandExecutionRequestApprovalSkillMetadata {
|
||||
path_to_skills_md: PathBuf::from("/tmp/SKILLS.md"),
|
||||
}),
|
||||
proposed_execpolicy_amendment: None,
|
||||
proposed_network_policy_amendments: None,
|
||||
available_decisions: None,
|
||||
};
|
||||
let reason = crate::experimental_api::ExperimentalApi::experimental_reason(¶ms);
|
||||
assert_eq!(
|
||||
reason,
|
||||
Some("item/commandExecution/requestApproval.skillMetadata")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ impl ThreadHistoryBuilder {
|
||||
EventMsg::ExitedReviewMode(payload) => self.handle_exited_review_mode(payload),
|
||||
EventMsg::ItemStarted(payload) => self.handle_item_started(payload),
|
||||
EventMsg::ItemCompleted(payload) => self.handle_item_completed(payload),
|
||||
EventMsg::HookStarted(_) | EventMsg::HookCompleted(_) => {}
|
||||
EventMsg::Error(payload) => self.handle_error(payload),
|
||||
EventMsg::TokenCount(_) => {}
|
||||
EventMsg::ThreadRolledBack(payload) => self.handle_thread_rollback(payload),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user