mirror of
https://github.com/openai/codex.git
synced 2026-11-09 08:40:33 +00:00
Precompute app-server protocol exports (#36212)
## Why Normal app-server protocol builds do not need the `ts-rs` and `schemars` implementations used to generate schema exports. ## What changed - Embed compressed stable and experimental TypeScript and JSON schema exports, and serve the existing export APIs from those artifacts. - Use no-op schema derives in non-test builds while keeping the real generators available for fixture regeneration and tests. - Move schema fixture regeneration behind a Python helper and update `just write-app-server-schema --experimental` to refresh the experimental embedded exports. ## Testing - Verify embedded exports match freshly generated stable and experimental schemas. - Verify export options and on-disk output remain compatible. GitOrigin-RevId: e8536338b457e6eec34bdf29ec0684144bd13734
This commit is contained in:
1 parent
0042b00986
commit
acd540f158
50 files changed
+720
-181
No files matched your search
Generated
+6
-1
@@ -2137,7 +2137,7 @@ name = "codex-app-server-protocol"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"codex-app-server-protocol-noop-macros",
|
||||||
"codex-experimental-api-macros",
|
"codex-experimental-api-macros",
|
||||||
"codex-extension-items",
|
"codex-extension-items",
|
||||||
"codex-protocol",
|
"codex-protocol",
|
||||||
@@ -2159,8 +2159,13 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
"ts-rs",
|
"ts-rs",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "codex-app-server-protocol-noop-macros"
|
||||||
|
version = "0.0.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codex-app-server-test-client"
|
name = "codex-app-server-test-client"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ members = [
|
|||||||
"app-server-daemon",
|
"app-server-daemon",
|
||||||
"app-server-client",
|
"app-server-client",
|
||||||
"app-server-protocol",
|
"app-server-protocol",
|
||||||
|
"app-server-protocol-noop-macros",
|
||||||
"app-server-test-client",
|
"app-server-test-client",
|
||||||
"apply-patch",
|
"apply-patch",
|
||||||
"arg0",
|
"arg0",
|
||||||
@@ -152,6 +153,7 @@ codex-app-server-transport = { path = "app-server-transport" }
|
|||||||
codex-app-server-daemon = { path = "app-server-daemon" }
|
codex-app-server-daemon = { path = "app-server-daemon" }
|
||||||
codex-app-server-client = { path = "app-server-client" }
|
codex-app-server-client = { path = "app-server-client" }
|
||||||
codex-app-server-protocol = { path = "app-server-protocol" }
|
codex-app-server-protocol = { path = "app-server-protocol" }
|
||||||
|
codex-app-server-protocol-noop-macros = { path = "app-server-protocol-noop-macros" }
|
||||||
codex-app-server-test-client = { path = "app-server-test-client" }
|
codex-app-server-test-client = { path = "app-server-test-client" }
|
||||||
codex-apply-patch = { path = "apply-patch" }
|
codex-apply-patch = { path = "apply-patch" }
|
||||||
codex-arg0 = { path = "arg0" }
|
codex-arg0 = { path = "arg0" }
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
load("//:defs.bzl", "codex_rust_crate")
|
||||||
|
|
||||||
|
codex_rust_crate(
|
||||||
|
name = "app-server-protocol-noop-macros",
|
||||||
|
crate_name = "codex_app_server_protocol_noop_macros",
|
||||||
|
proc_macro = True,
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "codex-app-server-protocol-noop-macros"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
test = false
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
//! No-op schema derives for production app-server protocol builds.
|
||||||
|
//!
|
||||||
|
//! The real `ts-rs` and `schemars` derives are only needed when regenerating
|
||||||
|
//! the vendored protocol exports. Normal builds retain the annotations so the
|
||||||
|
//! protocol definitions stay readable, but use these derives to avoid
|
||||||
|
//! generating implementations that cannot be reached at runtime.
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
/// Accepts `#[schemars(...)]` helper attributes without generating an impl.
|
||||||
|
#[proc_macro_derive(JsonSchema, attributes(schemars))]
|
||||||
|
pub fn derive_json_schema(_input: TokenStream) -> TokenStream {
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accepts `#[ts(...)]` helper attributes without generating an impl.
|
||||||
|
#[proc_macro_derive(TS, attributes(ts))]
|
||||||
|
pub fn derive_ts(_input: TokenStream) -> TokenStream {
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ load("//:defs.bzl", "codex_rust_crate")
|
|||||||
|
|
||||||
codex_rust_crate(
|
codex_rust_crate(
|
||||||
name = "app-server-protocol",
|
name = "app-server-protocol",
|
||||||
|
compile_data = glob(["schema/precomputed/**"]),
|
||||||
crate_name = "codex_app_server_protocol",
|
crate_name = "codex_app_server_protocol",
|
||||||
test_data_extra = glob(
|
test_data_extra = glob(
|
||||||
["schema/**"],
|
["schema/**"],
|
||||||
|
|||||||
@@ -14,14 +14,13 @@ workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
clap = { workspace = true, features = ["derive"] }
|
|
||||||
codex-experimental-api-macros = { workspace = true }
|
codex-experimental-api-macros = { workspace = true }
|
||||||
|
codex-app-server-protocol-noop-macros = { workspace = true }
|
||||||
codex-extension-items = { workspace = true }
|
codex-extension-items = { workspace = true }
|
||||||
codex-protocol = { workspace = true }
|
codex-protocol = { workspace = true }
|
||||||
codex-shell-command = { workspace = true }
|
codex-shell-command = { workspace = true }
|
||||||
codex-utils-absolute-path = { workspace = true }
|
codex-utils-absolute-path = { workspace = true }
|
||||||
codex-utils-path-uri = { workspace = true }
|
codex-utils-path-uri = { workspace = true }
|
||||||
schemars = { workspace = true }
|
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
serde_with = { workspace = true }
|
serde_with = { workspace = true }
|
||||||
@@ -30,17 +29,24 @@ thiserror = { workspace = true }
|
|||||||
rmcp = { workspace = true, default-features = false, features = [
|
rmcp = { workspace = true, default-features = false, features = [
|
||||||
"base64",
|
"base64",
|
||||||
"macros",
|
"macros",
|
||||||
"schemars",
|
|
||||||
"server",
|
"server",
|
||||||
] }
|
] }
|
||||||
ts-rs = { workspace = true }
|
|
||||||
inventory = { workspace = true }
|
inventory = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
uuid = { workspace = true, features = ["serde", "v7"] }
|
uuid = { workspace = true, features = ["serde", "v7"] }
|
||||||
|
zstd = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
codex-utils-cargo-bin = { workspace = true }
|
codex-utils-cargo-bin = { workspace = true }
|
||||||
pretty_assertions = { workspace = true }
|
pretty_assertions = { workspace = true }
|
||||||
|
rmcp = { workspace = true, default-features = false, features = [
|
||||||
|
"base64",
|
||||||
|
"macros",
|
||||||
|
"schemars",
|
||||||
|
"server",
|
||||||
|
] }
|
||||||
|
schemars = { workspace = true }
|
||||||
similar = { workspace = true }
|
similar = { workspace = true }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
|
ts-rs = { workspace = true }
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Regenerate vendored app-server schema fixtures"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--schema-root",
|
||||||
|
type=Path,
|
||||||
|
help="root directory containing the schema fixtures",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-p",
|
||||||
|
"--prettier",
|
||||||
|
type=Path,
|
||||||
|
help="optional Prettier executable used to format TypeScript files",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--experimental",
|
||||||
|
action="store_true",
|
||||||
|
help="regenerate the precomputed experimental exports",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
workspace_root = Path(__file__).resolve().parents[2]
|
||||||
|
schema_root = args.schema_root or workspace_root / "app-server-protocol" / "schema"
|
||||||
|
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["CODEX_APP_SERVER_SCHEMA_ROOT"] = str(schema_root)
|
||||||
|
env["CODEX_APP_SERVER_SCHEMA_EXPERIMENTAL"] = (
|
||||||
|
"1" if args.experimental else "0"
|
||||||
|
)
|
||||||
|
if args.prettier:
|
||||||
|
env["CODEX_APP_SERVER_SCHEMA_PRETTIER"] = str(args.prettier)
|
||||||
|
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"cargo",
|
||||||
|
"test",
|
||||||
|
"-p",
|
||||||
|
"codex-app-server-protocol",
|
||||||
|
"--lib",
|
||||||
|
"schema_fixtures_tests::write_schema_fixtures_from_env",
|
||||||
|
"--",
|
||||||
|
"--exact",
|
||||||
|
"--ignored",
|
||||||
|
],
|
||||||
|
cwd=workspace_root,
|
||||||
|
env=env,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use clap::Parser;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
|
||||||
#[command(
|
|
||||||
about = "Generate TypeScript bindings and JSON Schemas for the Codex app-server protocol"
|
|
||||||
)]
|
|
||||||
struct Args {
|
|
||||||
/// Output directory where generated files will be written
|
|
||||||
#[arg(short = 'o', long = "out", value_name = "DIR")]
|
|
||||||
out_dir: PathBuf,
|
|
||||||
|
|
||||||
/// Optional Prettier executable path to format generated TypeScript files
|
|
||||||
#[arg(short = 'p', long = "prettier", value_name = "PRETTIER_BIN")]
|
|
||||||
prettier: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// Include experimental API methods and fields in generated output.
|
|
||||||
#[arg(long = "experimental")]
|
|
||||||
experimental: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
let args = Args::parse();
|
|
||||||
codex_app_server_protocol::generate_ts_with_options(
|
|
||||||
&args.out_dir,
|
|
||||||
args.prettier.as_deref(),
|
|
||||||
codex_app_server_protocol::GenerateTsOptions {
|
|
||||||
experimental_api: args.experimental,
|
|
||||||
..codex_app_server_protocol::GenerateTsOptions::default()
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
codex_app_server_protocol::generate_json_with_experimental(&args.out_dir, args.experimental)
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
use anyhow::Context;
|
|
||||||
use anyhow::Result;
|
|
||||||
use clap::Parser;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
|
||||||
#[command(about = "Regenerate vendored app-server schema fixtures")]
|
|
||||||
struct Args {
|
|
||||||
/// Root directory containing `typescript/` and `json/`.
|
|
||||||
#[arg(long = "schema-root", value_name = "DIR")]
|
|
||||||
schema_root: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// Optional path to the Prettier executable to format generated TypeScript files.
|
|
||||||
#[arg(short = 'p', long = "prettier", value_name = "PRETTIER_BIN")]
|
|
||||||
prettier: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// Include experimental API methods and fields in generated fixtures.
|
|
||||||
#[arg(long = "experimental")]
|
|
||||||
experimental: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
let args = Args::parse();
|
|
||||||
|
|
||||||
let schema_root = args
|
|
||||||
.schema_root
|
|
||||||
.unwrap_or_else(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("schema"));
|
|
||||||
|
|
||||||
codex_app_server_protocol::write_schema_fixtures_with_options(
|
|
||||||
&schema_root,
|
|
||||||
args.prettier.as_deref(),
|
|
||||||
codex_app_server_protocol::SchemaFixtureOptions {
|
|
||||||
experimental_api: args.experimental,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_context(|| {
|
|
||||||
format!(
|
|
||||||
"failed to regenerate schema fixtures under {}",
|
|
||||||
schema_root.display()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
use crate::ClientNotification;
|
use crate::ClientNotification;
|
||||||
use crate::ClientRequest;
|
use crate::ClientRequest;
|
||||||
|
use crate::JsonSchema;
|
||||||
use crate::ServerNotification;
|
use crate::ServerNotification;
|
||||||
use crate::ServerNotificationEnvelope;
|
use crate::ServerNotificationEnvelope;
|
||||||
use crate::ServerRequest;
|
use crate::ServerRequest;
|
||||||
|
use crate::TS;
|
||||||
use crate::experimental_api::experimental_fields;
|
use crate::experimental_api::experimental_fields;
|
||||||
use crate::export_client_notification_schemas;
|
use crate::export_client_notification_schemas;
|
||||||
use crate::export_client_param_schemas;
|
use crate::export_client_param_schemas;
|
||||||
@@ -22,7 +24,6 @@ use anyhow::Context;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use codex_protocol::protocol::RolloutLine;
|
use codex_protocol::protocol::RolloutLine;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use schemars::schema_for;
|
use schemars::schema_for;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Map;
|
use serde_json::Map;
|
||||||
@@ -38,7 +39,6 @@ use std::path::Path;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
pub(crate) const GENERATED_TS_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 IGNORED_DEFINITIONS: &[&str] = &["Option<()>"];
|
||||||
@@ -87,11 +87,6 @@ impl GeneratedSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type JsonSchemaEmitter = fn(&Path) -> Result<GeneratedSchema>;
|
type JsonSchemaEmitter = fn(&Path) -> Result<GeneratedSchema>;
|
||||||
pub fn generate_types(out_dir: &Path, prettier: Option<&Path>) -> Result<()> {
|
|
||||||
generate_ts(out_dir, prettier)?;
|
|
||||||
generate_json(out_dir)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct GenerateTsOptions {
|
pub struct GenerateTsOptions {
|
||||||
@@ -112,10 +107,6 @@ impl Default for GenerateTsOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_ts(out_dir: &Path, prettier: Option<&Path>) -> Result<()> {
|
|
||||||
generate_ts_with_options(out_dir, prettier, GenerateTsOptions::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_ts_with_options(
|
pub fn generate_ts_with_options(
|
||||||
out_dir: &Path,
|
out_dir: &Path,
|
||||||
prettier: Option<&Path>,
|
prettier: Option<&Path>,
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
mod experimental_api;
|
mod experimental_api;
|
||||||
|
#[cfg(test)]
|
||||||
mod export;
|
mod export;
|
||||||
|
mod precomputed_exports;
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "precomputed_exports_tests.rs"]
|
||||||
|
mod precomputed_exports_tests;
|
||||||
mod protocol;
|
mod protocol;
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
|
#[cfg(test)]
|
||||||
mod schema_fixtures;
|
mod schema_fixtures;
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "schema_fixtures_tests.rs"]
|
||||||
|
mod schema_fixtures_tests;
|
||||||
|
|
||||||
pub use experimental_api::*;
|
pub use experimental_api::*;
|
||||||
pub use export::GenerateTsOptions;
|
pub use precomputed_exports::GenerateTsOptions;
|
||||||
pub use export::generate_internal_json_schema;
|
pub use precomputed_exports::generate_internal_json_schema;
|
||||||
pub use export::generate_json;
|
pub use precomputed_exports::generate_json;
|
||||||
pub use export::generate_json_with_experimental;
|
pub use precomputed_exports::generate_json_with_experimental;
|
||||||
pub use export::generate_ts;
|
pub use precomputed_exports::generate_ts;
|
||||||
pub use export::generate_ts_with_options;
|
pub use precomputed_exports::generate_ts_with_options;
|
||||||
pub use export::generate_types;
|
pub use precomputed_exports::generate_types;
|
||||||
pub use protocol::common::*;
|
pub use protocol::common::*;
|
||||||
pub use protocol::event_mapping::*;
|
pub use protocol::event_mapping::*;
|
||||||
pub use protocol::item_builders::*;
|
pub use protocol::item_builders::*;
|
||||||
@@ -41,10 +50,22 @@ pub use protocol::v1::Tools;
|
|||||||
pub use protocol::v1::UserSavedConfig;
|
pub use protocol::v1::UserSavedConfig;
|
||||||
pub use protocol::v2::*;
|
pub use protocol::v2::*;
|
||||||
pub use rpc::*;
|
pub use rpc::*;
|
||||||
|
#[cfg(test)]
|
||||||
pub use schema_fixtures::SchemaFixtureOptions;
|
pub use schema_fixtures::SchemaFixtureOptions;
|
||||||
#[doc(hidden)]
|
#[cfg(test)]
|
||||||
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_subtree;
|
||||||
|
#[cfg(test)]
|
||||||
pub use schema_fixtures::read_schema_fixture_tree;
|
pub use schema_fixtures::read_schema_fixture_tree;
|
||||||
|
#[cfg(test)]
|
||||||
pub use schema_fixtures::write_schema_fixtures;
|
pub use schema_fixtures::write_schema_fixtures;
|
||||||
|
#[cfg(test)]
|
||||||
pub use schema_fixtures::write_schema_fixtures_with_options;
|
pub use schema_fixtures::write_schema_fixtures_with_options;
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
pub(crate) use codex_app_server_protocol_noop_macros::JsonSchema;
|
||||||
|
#[cfg(not(test))]
|
||||||
|
pub(crate) use codex_app_server_protocol_noop_macros::TS;
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) use schemars::JsonSchema;
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) use ts_rs::TS;
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
use anyhow::Context;
|
||||||
|
use anyhow::Result;
|
||||||
|
use anyhow::bail;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::fs;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::path::Component;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
pub(crate) const GENERATED_TS_HEADER: &str = "// GENERATED CODE! DO NOT MODIFY BY HAND!\n\n";
|
||||||
|
const STABLE_EXPORTS: &[u8] =
|
||||||
|
include_bytes!("../schema/precomputed/app-server-exports-stable.json.zst");
|
||||||
|
const EXPERIMENTAL_EXPORTS: &[u8] =
|
||||||
|
include_bytes!("../schema/precomputed/app-server-exports-experimental.json.zst");
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct GenerateTsOptions {
|
||||||
|
pub generate_indices: bool,
|
||||||
|
pub ensure_headers: bool,
|
||||||
|
pub run_prettier: bool,
|
||||||
|
pub experimental_api: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GenerateTsOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
generate_indices: true,
|
||||||
|
ensure_headers: true,
|
||||||
|
run_prettier: true,
|
||||||
|
experimental_api: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[cfg_attr(test, derive(Debug, PartialEq, Eq, serde::Serialize))]
|
||||||
|
pub(crate) struct PrecomputedExports {
|
||||||
|
pub(crate) typescript: BTreeMap<String, String>,
|
||||||
|
pub(crate) json_schema: BTreeMap<String, String>,
|
||||||
|
pub(crate) internal_json_schema: BTreeMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum ExportSet {
|
||||||
|
Stable,
|
||||||
|
Experimental,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_types(out_dir: &Path, prettier: Option<&Path>) -> Result<()> {
|
||||||
|
generate_ts(out_dir, prettier)?;
|
||||||
|
generate_json(out_dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_ts(out_dir: &Path, prettier: Option<&Path>) -> Result<()> {
|
||||||
|
generate_ts_with_options(out_dir, prettier, GenerateTsOptions::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_ts_with_options(
|
||||||
|
out_dir: &Path,
|
||||||
|
prettier: Option<&Path>,
|
||||||
|
options: GenerateTsOptions,
|
||||||
|
) -> Result<()> {
|
||||||
|
let export_set = if options.experimental_api {
|
||||||
|
ExportSet::Experimental
|
||||||
|
} else {
|
||||||
|
ExportSet::Stable
|
||||||
|
};
|
||||||
|
let exports = load_exports(export_set)?;
|
||||||
|
let ts_files = write_typescript_exports(out_dir, &exports.typescript, options)?;
|
||||||
|
|
||||||
|
if options.run_prettier
|
||||||
|
&& let Some(prettier_bin) = prettier
|
||||||
|
&& !ts_files.is_empty()
|
||||||
|
{
|
||||||
|
let status = Command::new(prettier_bin)
|
||||||
|
.arg("--write")
|
||||||
|
.arg("--log-level")
|
||||||
|
.arg("warn")
|
||||||
|
.args(ts_files.iter().map(PathBuf::as_path))
|
||||||
|
.status()
|
||||||
|
.with_context(|| format!("Failed to invoke Prettier at {}", prettier_bin.display()))?;
|
||||||
|
if !status.success() {
|
||||||
|
bail!("Prettier failed with status {status}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trim_trailing_whitespace_in_ts_files(&ts_files)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_json(out_dir: &Path) -> Result<()> {
|
||||||
|
generate_json_with_experimental(out_dir, /*experimental_api*/ false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_json_with_experimental(out_dir: &Path, experimental_api: bool) -> Result<()> {
|
||||||
|
let export_set = if experimental_api {
|
||||||
|
ExportSet::Experimental
|
||||||
|
} else {
|
||||||
|
ExportSet::Stable
|
||||||
|
};
|
||||||
|
let exports = load_exports(export_set)?;
|
||||||
|
write_exports(out_dir, &exports.json_schema)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_internal_json_schema(out_dir: &Path) -> Result<()> {
|
||||||
|
let exports = load_exports(ExportSet::Stable)?;
|
||||||
|
write_exports(out_dir, &exports.internal_json_schema)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_exports(export_set: ExportSet) -> Result<PrecomputedExports> {
|
||||||
|
let compressed = match export_set {
|
||||||
|
ExportSet::Stable => STABLE_EXPORTS,
|
||||||
|
ExportSet::Experimental => EXPERIMENTAL_EXPORTS,
|
||||||
|
};
|
||||||
|
let bytes = zstd::stream::decode_all(Cursor::new(compressed))
|
||||||
|
.context("decompress precomputed app-server protocol exports")?;
|
||||||
|
serde_json::from_slice(&bytes).context("decode precomputed app-server protocol exports")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_typescript_exports(
|
||||||
|
out_dir: &Path,
|
||||||
|
exports: &BTreeMap<String, String>,
|
||||||
|
options: GenerateTsOptions,
|
||||||
|
) -> Result<Vec<PathBuf>> {
|
||||||
|
let mut written = Vec::new();
|
||||||
|
for (relative_path, archived_contents) in exports {
|
||||||
|
let is_index = Path::new(relative_path).file_name() == Some(OsStr::new("index.ts"));
|
||||||
|
if is_index && !options.generate_indices {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let contents = if options.ensure_headers || is_index {
|
||||||
|
archived_contents.as_str()
|
||||||
|
} else {
|
||||||
|
archived_contents
|
||||||
|
.strip_prefix(GENERATED_TS_HEADER)
|
||||||
|
.unwrap_or(archived_contents)
|
||||||
|
};
|
||||||
|
written.push(write_export(out_dir, relative_path, contents)?);
|
||||||
|
}
|
||||||
|
Ok(written)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_exports(out_dir: &Path, exports: &BTreeMap<String, String>) -> Result<Vec<PathBuf>> {
|
||||||
|
exports
|
||||||
|
.iter()
|
||||||
|
.map(|(relative_path, contents)| write_export(out_dir, relative_path, contents))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_export(out_dir: &Path, relative_path: &str, contents: &str) -> Result<PathBuf> {
|
||||||
|
let relative_path = validated_relative_path(relative_path)?;
|
||||||
|
let output_path = out_dir.join(relative_path);
|
||||||
|
let parent = output_path
|
||||||
|
.parent()
|
||||||
|
.context("precomputed export path should have a parent")?;
|
||||||
|
fs::create_dir_all(parent).with_context(|| format!("Failed to create {}", parent.display()))?;
|
||||||
|
fs::write(&output_path, contents)
|
||||||
|
.with_context(|| format!("Failed to write {}", output_path.display()))?;
|
||||||
|
Ok(output_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validated_relative_path(path: &str) -> Result<&Path> {
|
||||||
|
let path = Path::new(path);
|
||||||
|
if path.as_os_str().is_empty()
|
||||||
|
|| path
|
||||||
|
.components()
|
||||||
|
.any(|component| !matches!(component, Component::Normal(_)))
|
||||||
|
{
|
||||||
|
bail!("invalid precomputed export path: {}", path.display());
|
||||||
|
}
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trim_trailing_whitespace_in_ts_files(paths: &[PathBuf]) -> Result<()> {
|
||||||
|
for path in paths {
|
||||||
|
let content = fs::read_to_string(path)
|
||||||
|
.with_context(|| format!("Failed to read {}", path.display()))?;
|
||||||
|
let trimmed = trim_trailing_line_whitespace(&content);
|
||||||
|
if trimmed != content {
|
||||||
|
fs::write(path, trimmed)
|
||||||
|
.with_context(|| format!("Failed to write {}", path.display()))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trim_trailing_line_whitespace(content: &str) -> String {
|
||||||
|
let mut trimmed = String::with_capacity(content.len());
|
||||||
|
for line in content.split_inclusive('\n') {
|
||||||
|
if let Some(line_without_newline) = line.strip_suffix('\n') {
|
||||||
|
trimmed.push_str(line_without_newline.trim_end_matches([' ', '\t']));
|
||||||
|
trimmed.push('\n');
|
||||||
|
} else {
|
||||||
|
trimmed.push_str(line.trim_end_matches([' ', '\t']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trimmed
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) fn decode_precomputed_exports(experimental_api: bool) -> Result<PrecomputedExports> {
|
||||||
|
let export_set = if experimental_api {
|
||||||
|
ExportSet::Experimental
|
||||||
|
} else {
|
||||||
|
ExportSet::Stable
|
||||||
|
};
|
||||||
|
load_exports(export_set)
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
use crate::GenerateTsOptions;
|
||||||
|
use crate::generate_internal_json_schema;
|
||||||
|
use crate::generate_json_with_experimental;
|
||||||
|
use crate::generate_ts_with_options;
|
||||||
|
use crate::precomputed_exports::GENERATED_TS_HEADER;
|
||||||
|
use crate::precomputed_exports::decode_precomputed_exports;
|
||||||
|
use crate::schema_fixtures::collect_export_files_recursive;
|
||||||
|
use anyhow::Context;
|
||||||
|
use anyhow::Result;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn precomputed_exports_are_written_to_disk() -> Result<()> {
|
||||||
|
let output_dir = tempfile::tempdir().context("create export temp dir")?;
|
||||||
|
let typescript_dir = output_dir.path().join("typescript");
|
||||||
|
let json_dir = output_dir.path().join("json");
|
||||||
|
let internal_json_dir = output_dir.path().join("internal-json");
|
||||||
|
|
||||||
|
generate_ts_with_options(
|
||||||
|
&typescript_dir,
|
||||||
|
/*prettier*/ None,
|
||||||
|
GenerateTsOptions::default(),
|
||||||
|
)?;
|
||||||
|
generate_json_with_experimental(&json_dir, /*experimental_api*/ false)?;
|
||||||
|
generate_internal_json_schema(&internal_json_dir)?;
|
||||||
|
|
||||||
|
let exports = decode_precomputed_exports(/*experimental_api*/ false)?;
|
||||||
|
assert_eq!(
|
||||||
|
collect_export_files_recursive(&typescript_dir)?,
|
||||||
|
exports.typescript
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
collect_export_files_recursive(&json_dir)?,
|
||||||
|
exports.json_schema
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
collect_export_files_recursive(&internal_json_dir)?,
|
||||||
|
exports.internal_json_schema
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn typescript_export_options_preserve_generator_behavior() -> Result<()> {
|
||||||
|
let output_dir = tempfile::tempdir().context("create TypeScript export temp dir")?;
|
||||||
|
generate_ts_with_options(
|
||||||
|
output_dir.path(),
|
||||||
|
/*prettier*/ None,
|
||||||
|
GenerateTsOptions {
|
||||||
|
generate_indices: false,
|
||||||
|
ensure_headers: false,
|
||||||
|
..GenerateTsOptions::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let files = collect_export_files_recursive(output_dir.path())?;
|
||||||
|
assert!(!files.keys().any(|path| {
|
||||||
|
Path::new(path)
|
||||||
|
.file_name()
|
||||||
|
.is_some_and(|name| name == "index.ts")
|
||||||
|
}));
|
||||||
|
assert!(
|
||||||
|
files
|
||||||
|
.values()
|
||||||
|
.all(|contents| !contents.starts_with(GENERATED_TS_HEADER))
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
|
#[cfg(test)]
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::JSONRPCNotification;
|
use crate::JSONRPCNotification;
|
||||||
use crate::JSONRPCRequest;
|
use crate::JSONRPCRequest;
|
||||||
|
use crate::JsonSchema;
|
||||||
use crate::RequestId;
|
use crate::RequestId;
|
||||||
|
use crate::TS;
|
||||||
|
#[cfg(test)]
|
||||||
use crate::export::GeneratedSchema;
|
use crate::export::GeneratedSchema;
|
||||||
|
#[cfg(test)]
|
||||||
use crate::export::write_json_schema;
|
use crate::export::write_json_schema;
|
||||||
use crate::protocol::v1;
|
use crate::protocol::v1;
|
||||||
use crate::protocol::v2;
|
use crate::protocol::v2;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use strum_macros::Display;
|
use strum_macros::Display;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
/// Authentication mode for OpenAI-backed providers.
|
/// Authentication mode for OpenAI-backed providers.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Display, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Display, JsonSchema, TS)]
|
||||||
@@ -90,6 +93,7 @@ macro_rules! experimental_reason_expr {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
macro_rules! experimental_method_entry {
|
macro_rules! experimental_method_entry {
|
||||||
(#[experimental($reason:expr)] => $wire:literal) => {
|
(#[experimental($reason:expr)] => $wire:literal) => {
|
||||||
$wire
|
$wire
|
||||||
@@ -102,6 +106,7 @@ macro_rules! experimental_method_entry {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
macro_rules! experimental_type_entry {
|
macro_rules! experimental_type_entry {
|
||||||
(#[experimental($reason:expr)] $ty:ty) => {
|
(#[experimental($reason:expr)] $ty:ty) => {
|
||||||
stringify!($ty)
|
stringify!($ty)
|
||||||
@@ -393,22 +398,26 @@ macro_rules! client_request_definitions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) const EXPERIMENTAL_CLIENT_METHODS: &[&str] = &[
|
pub(crate) const EXPERIMENTAL_CLIENT_METHODS: &[&str] = &[
|
||||||
$(
|
$(
|
||||||
experimental_method_entry!($(#[experimental($reason)])? => $wire),
|
experimental_method_entry!($(#[experimental($reason)])? => $wire),
|
||||||
)*
|
)*
|
||||||
];
|
];
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) const EXPERIMENTAL_CLIENT_METHOD_PARAM_TYPES: &[&str] = &[
|
pub(crate) const EXPERIMENTAL_CLIENT_METHOD_PARAM_TYPES: &[&str] = &[
|
||||||
$(
|
$(
|
||||||
experimental_type_entry!($(#[experimental($reason)])? $params),
|
experimental_type_entry!($(#[experimental($reason)])? $params),
|
||||||
)*
|
)*
|
||||||
];
|
];
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) const EXPERIMENTAL_CLIENT_METHOD_RESPONSE_TYPES: &[&str] = &[
|
pub(crate) const EXPERIMENTAL_CLIENT_METHOD_RESPONSE_TYPES: &[&str] = &[
|
||||||
$(
|
$(
|
||||||
experimental_type_entry!($(#[experimental($reason)])? $response),
|
experimental_type_entry!($(#[experimental($reason)])? $response),
|
||||||
)*
|
)*
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn export_client_responses(
|
pub fn export_client_responses(
|
||||||
out_dir: &::std::path::Path,
|
out_dir: &::std::path::Path,
|
||||||
) -> ::std::result::Result<(), ::ts_rs::ExportError> {
|
) -> ::std::result::Result<(), ::ts_rs::ExportError> {
|
||||||
@@ -418,12 +427,14 @@ macro_rules! client_request_definitions {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) fn visit_client_response_types(v: &mut impl ::ts_rs::TypeVisitor) {
|
pub(crate) fn visit_client_response_types(v: &mut impl ::ts_rs::TypeVisitor) {
|
||||||
$(
|
$(
|
||||||
v.visit::<$response>();
|
v.visit::<$response>();
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[allow(clippy::vec_init_then_push)]
|
#[allow(clippy::vec_init_then_push)]
|
||||||
pub fn export_client_response_schemas(
|
pub fn export_client_response_schemas(
|
||||||
out_dir: &::std::path::Path,
|
out_dir: &::std::path::Path,
|
||||||
@@ -435,6 +446,7 @@ macro_rules! client_request_definitions {
|
|||||||
Ok(schemas)
|
Ok(schemas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[allow(clippy::vec_init_then_push)]
|
#[allow(clippy::vec_init_then_push)]
|
||||||
pub fn export_client_param_schemas(
|
pub fn export_client_param_schemas(
|
||||||
out_dir: &::std::path::Path,
|
out_dir: &::std::path::Path,
|
||||||
@@ -1330,22 +1342,26 @@ macro_rules! server_request_definitions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) const EXPERIMENTAL_SERVER_METHODS: &[&str] = &[
|
pub(crate) const EXPERIMENTAL_SERVER_METHODS: &[&str] = &[
|
||||||
$(
|
$(
|
||||||
experimental_method_entry!($(#[experimental($reason)])? $(=> $wire)?),
|
experimental_method_entry!($(#[experimental($reason)])? $(=> $wire)?),
|
||||||
)*
|
)*
|
||||||
];
|
];
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) const EXPERIMENTAL_SERVER_METHOD_PARAM_TYPES: &[&str] = &[
|
pub(crate) const EXPERIMENTAL_SERVER_METHOD_PARAM_TYPES: &[&str] = &[
|
||||||
$(
|
$(
|
||||||
experimental_type_entry!($(#[experimental($reason)])? $params),
|
experimental_type_entry!($(#[experimental($reason)])? $params),
|
||||||
)*
|
)*
|
||||||
];
|
];
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) const EXPERIMENTAL_SERVER_METHOD_RESPONSE_TYPES: &[&str] = &[
|
pub(crate) const EXPERIMENTAL_SERVER_METHOD_RESPONSE_TYPES: &[&str] = &[
|
||||||
$(
|
$(
|
||||||
experimental_type_entry!($(#[experimental($reason)])? $response),
|
experimental_type_entry!($(#[experimental($reason)])? $response),
|
||||||
)*
|
)*
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn export_server_responses(
|
pub fn export_server_responses(
|
||||||
out_dir: &::std::path::Path,
|
out_dir: &::std::path::Path,
|
||||||
) -> ::std::result::Result<(), ::ts_rs::ExportError> {
|
) -> ::std::result::Result<(), ::ts_rs::ExportError> {
|
||||||
@@ -1355,12 +1371,14 @@ macro_rules! server_request_definitions {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) fn visit_server_response_types(v: &mut impl ::ts_rs::TypeVisitor) {
|
pub(crate) fn visit_server_response_types(v: &mut impl ::ts_rs::TypeVisitor) {
|
||||||
$(
|
$(
|
||||||
v.visit::<$response>();
|
v.visit::<$response>();
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[allow(clippy::vec_init_then_push)]
|
#[allow(clippy::vec_init_then_push)]
|
||||||
pub fn export_server_response_schemas(
|
pub fn export_server_response_schemas(
|
||||||
out_dir: &Path,
|
out_dir: &Path,
|
||||||
@@ -1375,6 +1393,7 @@ macro_rules! server_request_definitions {
|
|||||||
Ok(schemas)
|
Ok(schemas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[allow(clippy::vec_init_then_push)]
|
#[allow(clippy::vec_init_then_push)]
|
||||||
pub fn export_server_param_schemas(
|
pub fn export_server_param_schemas(
|
||||||
out_dir: &Path,
|
out_dir: &Path,
|
||||||
@@ -1438,6 +1457,7 @@ macro_rules! server_notification_definitions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
#[allow(clippy::vec_init_then_push)]
|
#[allow(clippy::vec_init_then_push)]
|
||||||
pub fn export_server_notification_schemas(
|
pub fn export_server_notification_schemas(
|
||||||
out_dir: &::std::path::Path,
|
out_dir: &::std::path::Path,
|
||||||
@@ -1466,6 +1486,7 @@ macro_rules! client_notification_definitions {
|
|||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn export_client_notification_schemas(
|
pub fn export_client_notification_schemas(
|
||||||
_out_dir: &::std::path::Path,
|
_out_dir: &::std::path::Path,
|
||||||
) -> ::anyhow::Result<Vec<GeneratedSchema>> {
|
) -> ::anyhow::Result<Vec<GeneratedSchema>> {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use serde::Deserializer;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::Serializer;
|
use serde::Serializer;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) fn nullable_string_schema(
|
pub(crate) fn nullable_string_schema(
|
||||||
generator: &mut schemars::r#gen::SchemaGenerator,
|
generator: &mut schemars::r#gen::SchemaGenerator,
|
||||||
) -> schemars::schema::Schema {
|
) -> schemars::schema::Schema {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::ThreadId;
|
use codex_protocol::ThreadId;
|
||||||
use codex_protocol::config_types::ForcedLoginMethod;
|
use codex_protocol::config_types::ForcedLoginMethod;
|
||||||
use codex_protocol::config_types::ReasoningSummary;
|
use codex_protocol::config_types::ReasoningSummary;
|
||||||
@@ -16,10 +18,8 @@ use codex_protocol::protocol::SandboxPolicy;
|
|||||||
use codex_protocol::protocol::SessionSource;
|
use codex_protocol::protocol::SessionSource;
|
||||||
use codex_protocol::protocol::TurnAbortReason;
|
use codex_protocol::protocol::TurnAbortReason;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
use crate::protocol::common::AuthMode;
|
use crate::protocol::common::AuthMode;
|
||||||
use crate::protocol::v2::ForcedChatgptWorkspaceIds;
|
use crate::protocol::v2::ForcedChatgptWorkspaceIds;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use crate::protocol::common::AuthMode;
|
use crate::protocol::common::AuthMode;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use codex_protocol::account::PlanType;
|
use codex_protocol::account::PlanType;
|
||||||
@@ -7,11 +9,9 @@ use codex_protocol::protocol::RateLimitReachedType as CoreRateLimitReachedType;
|
|||||||
use codex_protocol::protocol::RateLimitSnapshot as CoreRateLimitSnapshot;
|
use codex_protocol::protocol::RateLimitSnapshot as CoreRateLimitSnapshot;
|
||||||
use codex_protocol::protocol::RateLimitWindow as CoreRateLimitWindow;
|
use codex_protocol::protocol::RateLimitWindow as CoreRateLimitWindow;
|
||||||
use codex_protocol::protocol::SpendControlLimitSnapshot as CoreSpendControlLimitSnapshot;
|
use codex_protocol::protocol::SpendControlLimitSnapshot as CoreSpendControlLimitSnapshot;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::shared::default_enabled;
|
use super::shared::default_enabled;
|
||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, Default)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::config_types::CollaborationModeMask as CoreCollaborationModeMask;
|
use codex_protocol::config_types::CollaborationModeMask as CoreCollaborationModeMask;
|
||||||
use codex_protocol::config_types::ModeKind;
|
use codex_protocol::config_types::ModeKind;
|
||||||
use codex_protocol::openai_models::ReasoningEffort;
|
use codex_protocol::openai_models::ReasoningEffort;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
/// EXPERIMENTAL - list collaboration mode presets.
|
/// EXPERIMENTAL - list collaboration mode presets.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use super::SandboxPolicy;
|
use super::SandboxPolicy;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
/// PTY size in character cells for `command/exec` PTY sessions.
|
/// PTY size in character cells for `command/exec` PTY sessions.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use super::AskForApproval;
|
|||||||
use super::SandboxMode;
|
use super::SandboxMode;
|
||||||
use super::WindowsSandboxSetupMode;
|
use super::WindowsSandboxSetupMode;
|
||||||
use super::shared::default_enabled;
|
use super::shared::default_enabled;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use codex_protocol::config_types::AutoCompactTokenLimitScope;
|
use codex_protocol::config_types::AutoCompactTokenLimitScope;
|
||||||
use codex_protocol::config_types::ForcedLoginMethod;
|
use codex_protocol::config_types::ForcedLoginMethod;
|
||||||
@@ -13,14 +15,12 @@ use codex_protocol::config_types::WebSearchToolConfig;
|
|||||||
use codex_protocol::openai_models::ReasoningEffort;
|
use codex_protocol::openai_models::ReasoningEffort;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use codex_utils_path_uri::PathUri;
|
use codex_utils_path_uri::PathUri;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_utils_path_uri::PathUri;
|
use codex_utils_path_uri::PathUri;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
/// Read a file from the host filesystem.
|
/// Read a file from the host filesystem.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::protocol::HookEventName as CoreHookEventName;
|
use codex_protocol::protocol::HookEventName as CoreHookEventName;
|
||||||
use codex_protocol::protocol::HookExecutionMode as CoreHookExecutionMode;
|
use codex_protocol::protocol::HookExecutionMode as CoreHookExecutionMode;
|
||||||
use codex_protocol::protocol::HookHandlerType as CoreHookHandlerType;
|
use codex_protocol::protocol::HookHandlerType as CoreHookHandlerType;
|
||||||
@@ -10,10 +12,8 @@ use codex_protocol::protocol::HookScope as CoreHookScope;
|
|||||||
use codex_protocol::protocol::HookSource as CoreHookSource;
|
use codex_protocol::protocol::HookSource as CoreHookSource;
|
||||||
use codex_protocol::protocol::HookTrustStatus as CoreHookTrustStatus;
|
use codex_protocol::protocol::HookTrustStatus as CoreHookTrustStatus;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
v2_enum_from_core!(
|
v2_enum_from_core!(
|
||||||
pub enum HookEventName from CoreHookEventName {
|
pub enum HookEventName from CoreHookEventName {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ use super::NetworkPolicyAmendment;
|
|||||||
use super::RequestPermissionProfile;
|
use super::RequestPermissionProfile;
|
||||||
use super::UserInput;
|
use super::UserInput;
|
||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use crate::protocol::item_builders::command_actions_for_path_uri;
|
use crate::protocol::item_builders::command_actions_for_path_uri;
|
||||||
use crate::protocol::item_builders::convert_patch_changes;
|
use crate::protocol::item_builders::convert_patch_changes;
|
||||||
use crate::protocol::item_builders::review_output_text;
|
use crate::protocol::item_builders::review_output_text;
|
||||||
@@ -44,7 +46,6 @@ use codex_protocol::protocol::SubAgentActivityKind as CoreSubAgentActivityKind;
|
|||||||
use codex_shell_command::parse_command::shlex_join;
|
use codex_shell_command::parse_command::shlex_join;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use codex_utils_path_uri::LegacyAppPathString;
|
use codex_utils_path_uri::LegacyAppPathString;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
@@ -52,7 +53,6 @@ use serde_with::serde_as;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::approvals::ElicitationRequest as CoreElicitationRequest;
|
use codex_protocol::approvals::ElicitationRequest as CoreElicitationRequest;
|
||||||
use codex_protocol::items::McpToolCallError as CoreMcpToolCallError;
|
use codex_protocol::items::McpToolCallError as CoreMcpToolCallError;
|
||||||
use codex_protocol::mcp::CallToolResult as CoreMcpCallToolResult;
|
use codex_protocol::mcp::CallToolResult as CoreMcpCallToolResult;
|
||||||
@@ -7,12 +9,10 @@ use codex_protocol::mcp::Resource as McpResource;
|
|||||||
pub use codex_protocol::mcp::ResourceContent as McpResourceContent;
|
pub use codex_protocol::mcp::ResourceContent as McpResourceContent;
|
||||||
use codex_protocol::mcp::ResourceTemplate as McpResourceTemplate;
|
use codex_protocol::mcp::ResourceTemplate as McpResourceTemplate;
|
||||||
use codex_protocol::mcp::Tool as McpTool;
|
use codex_protocol::mcp::Tool as McpTool;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
v2_enum_from_core!(
|
v2_enum_from_core!(
|
||||||
pub enum McpAuthStatus from codex_protocol::protocol::McpAuthStatus {
|
pub enum McpAuthStatus from codex_protocol::protocol::McpAuthStatus {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::openai_models::InputModality;
|
use codex_protocol::openai_models::InputModality;
|
||||||
use codex_protocol::openai_models::ModelAvailabilityNux as CoreModelAvailabilityNux;
|
use codex_protocol::openai_models::ModelAvailabilityNux as CoreModelAvailabilityNux;
|
||||||
use codex_protocol::openai_models::ReasoningEffort;
|
use codex_protocol::openai_models::ReasoningEffort;
|
||||||
use codex_protocol::openai_models::default_input_modalities;
|
use codex_protocol::openai_models::default_input_modalities;
|
||||||
use codex_protocol::protocol::ModelRerouteReason as CoreModelRerouteReason;
|
use codex_protocol::protocol::ModelRerouteReason as CoreModelRerouteReason;
|
||||||
use codex_protocol::protocol::ModelVerification as CoreModelVerification;
|
use codex_protocol::protocol::ModelVerification as CoreModelVerification;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
v2_enum_from_core!(
|
v2_enum_from_core!(
|
||||||
pub enum ModelRerouteReason from CoreModelRerouteReason {
|
pub enum ModelRerouteReason from CoreModelRerouteReason {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::TurnError;
|
use super::TurnError;
|
||||||
|
use crate::JsonSchema;
|
||||||
use crate::RequestId;
|
use crate::RequestId;
|
||||||
use schemars::JsonSchema;
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::approvals::ExecPolicyAmendment as CoreExecPolicyAmendment;
|
use codex_protocol::approvals::ExecPolicyAmendment as CoreExecPolicyAmendment;
|
||||||
use codex_protocol::approvals::NetworkApprovalContext as CoreNetworkApprovalContext;
|
use codex_protocol::approvals::NetworkApprovalContext as CoreNetworkApprovalContext;
|
||||||
use codex_protocol::approvals::NetworkApprovalProtocol as CoreNetworkApprovalProtocol;
|
use codex_protocol::approvals::NetworkApprovalProtocol as CoreNetworkApprovalProtocol;
|
||||||
@@ -19,13 +21,11 @@ use codex_protocol::request_permissions::RequestPermissionProfile as CoreRequest
|
|||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use codex_utils_path_uri::LegacyAppPathString;
|
use codex_utils_path_uri::LegacyAppPathString;
|
||||||
use codex_utils_path_uri::PathConvention;
|
use codex_utils_path_uri::PathConvention;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
v2_enum_from_core! {
|
v2_enum_from_core! {
|
||||||
pub enum NetworkApprovalProtocol from CoreNetworkApprovalProtocol {
|
pub enum NetworkApprovalProtocol from CoreNetworkApprovalProtocol {
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ use super::HookEventName;
|
|||||||
use super::HookHandlerType;
|
use super::HookHandlerType;
|
||||||
use super::HookSource;
|
use super::HookSource;
|
||||||
use super::HookTrustStatus;
|
use super::HookTrustStatus;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::protocol::SkillDependencies as CoreSkillDependencies;
|
use codex_protocol::protocol::SkillDependencies as CoreSkillDependencies;
|
||||||
use codex_protocol::protocol::SkillInterface as CoreSkillInterface;
|
use codex_protocol::protocol::SkillInterface as CoreSkillInterface;
|
||||||
use codex_protocol::protocol::SkillMetadata as CoreSkillMetadata;
|
use codex_protocol::protocol::SkillMetadata as CoreSkillMetadata;
|
||||||
use codex_protocol::protocol::SkillScope as CoreSkillScope;
|
use codex_protocol::protocol::SkillScope as CoreSkillScope;
|
||||||
use codex_protocol::protocol::SkillToolDependency as CoreSkillToolDependency;
|
use codex_protocol::protocol::SkillToolDependency as CoreSkillToolDependency;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
/// PTY size in character cells for `process/spawn` PTY sessions.
|
/// PTY size in character cells for `process/spawn` PTY sessions.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::protocol::CodexResponseHandoffMode;
|
use codex_protocol::protocol::CodexResponseHandoffMode;
|
||||||
use codex_protocol::protocol::ConversationTextRole;
|
use codex_protocol::protocol::ConversationTextRole;
|
||||||
use codex_protocol::protocol::RealtimeAudioFrame as CoreRealtimeAudioFrame;
|
use codex_protocol::protocol::RealtimeAudioFrame as CoreRealtimeAudioFrame;
|
||||||
@@ -5,12 +7,10 @@ use codex_protocol::protocol::RealtimeConversationVersion;
|
|||||||
use codex_protocol::protocol::RealtimeOutputModality;
|
use codex_protocol::protocol::RealtimeOutputModality;
|
||||||
use codex_protocol::protocol::RealtimeVoice;
|
use codex_protocol::protocol::RealtimeVoice;
|
||||||
use codex_protocol::protocol::RealtimeVoicesList;
|
use codex_protocol::protocol::RealtimeVoicesList;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
/// EXPERIMENTAL - thread realtime audio chunk.
|
/// EXPERIMENTAL - thread realtime audio chunk.
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::Turn;
|
use super::Turn;
|
||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
use schemars::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
v2_enum_from_core!(
|
v2_enum_from_core!(
|
||||||
pub enum ReviewDelivery from codex_protocol::protocol::ReviewDelivery {
|
pub enum ReviewDelivery from codex_protocol::protocol::ReviewDelivery {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use codex_protocol::config_types::ApprovalsReviewer as CoreApprovalsReviewer;
|
use codex_protocol::config_types::ApprovalsReviewer as CoreApprovalsReviewer;
|
||||||
use codex_protocol::config_types::SandboxMode as CoreSandboxMode;
|
use codex_protocol::config_types::SandboxMode as CoreSandboxMode;
|
||||||
@@ -5,16 +7,20 @@ use codex_protocol::protocol::AskForApproval as CoreAskForApproval;
|
|||||||
use codex_protocol::protocol::CodexErrorInfo as CoreCodexErrorInfo;
|
use codex_protocol::protocol::CodexErrorInfo as CoreCodexErrorInfo;
|
||||||
use codex_protocol::protocol::GranularApprovalConfig as CoreGranularApprovalConfig;
|
use codex_protocol::protocol::GranularApprovalConfig as CoreGranularApprovalConfig;
|
||||||
use codex_protocol::protocol::NonSteerableTurnKind as CoreNonSteerableTurnKind;
|
use codex_protocol::protocol::NonSteerableTurnKind as CoreNonSteerableTurnKind;
|
||||||
use schemars::JsonSchema;
|
#[cfg(test)]
|
||||||
use schemars::r#gen::SchemaGenerator;
|
use schemars::r#gen::SchemaGenerator;
|
||||||
|
#[cfg(test)]
|
||||||
use schemars::schema::InstanceType;
|
use schemars::schema::InstanceType;
|
||||||
|
#[cfg(test)]
|
||||||
use schemars::schema::Metadata;
|
use schemars::schema::Metadata;
|
||||||
|
#[cfg(test)]
|
||||||
use schemars::schema::Schema;
|
use schemars::schema::Schema;
|
||||||
|
#[cfg(test)]
|
||||||
use schemars::schema::SchemaObject;
|
use schemars::schema::SchemaObject;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
#[cfg(test)]
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
// Macro to declare a camelCased API v2 enum mirroring a core enum which
|
// Macro to declare a camelCased API v2 enum mirroring a core enum which
|
||||||
// tends to use either snake_case or kebab-case.
|
// tends to use either snake_case or kebab-case.
|
||||||
@@ -236,6 +242,7 @@ pub enum ApprovalsReviewer {
|
|||||||
AutoReview,
|
AutoReview,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
impl JsonSchema for ApprovalsReviewer {
|
impl JsonSchema for ApprovalsReviewer {
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
"ApprovalsReviewer".to_string()
|
"ApprovalsReviewer".to_string()
|
||||||
@@ -249,6 +256,7 @@ impl JsonSchema for ApprovalsReviewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema {
|
fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema {
|
||||||
let mut schema = SchemaObject {
|
let mut schema = SchemaObject {
|
||||||
instance_type: Some(InstanceType::String.into()),
|
instance_type: Some(InstanceType::String.into()),
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ use super::Turn;
|
|||||||
use super::TurnEnvironmentParams;
|
use super::TurnEnvironmentParams;
|
||||||
use super::TurnItemsView;
|
use super::TurnItemsView;
|
||||||
use super::shared::v2_enum_from_core;
|
use super::shared::v2_enum_from_core;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
pub use codex_protocol::capabilities::CapabilityRootLocation;
|
pub use codex_protocol::capabilities::CapabilityRootLocation;
|
||||||
pub use codex_protocol::capabilities::SelectedCapabilityRoot;
|
pub use codex_protocol::capabilities::SelectedCapabilityRoot;
|
||||||
@@ -31,13 +33,11 @@ use codex_protocol::protocol::TokenUsageInfo as CoreTokenUsageInfo;
|
|||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use codex_utils_path_uri::LegacyAppPathString;
|
use codex_utils_path_uri::LegacyAppPathString;
|
||||||
use codex_utils_path_uri::PathUri;
|
use codex_utils_path_uri::PathUri;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -2,20 +2,22 @@ use super::CodexErrorInfo;
|
|||||||
use super::ThreadItem;
|
use super::ThreadItem;
|
||||||
use super::ThreadStatus;
|
use super::ThreadStatus;
|
||||||
use super::TurnStatus;
|
use super::TurnStatus;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use codex_protocol::protocol::SessionSource as CoreSessionSource;
|
use codex_protocol::protocol::SessionSource as CoreSessionSource;
|
||||||
use codex_protocol::protocol::SubAgentSource as CoreSubAgentSource;
|
use codex_protocol::protocol::SubAgentSource as CoreSubAgentSource;
|
||||||
use codex_protocol::protocol::ThreadHistoryMode as CoreThreadHistoryMode;
|
use codex_protocol::protocol::ThreadHistoryMode as CoreThreadHistoryMode;
|
||||||
use codex_protocol::protocol::ThreadSource as CoreThreadSource;
|
use codex_protocol::protocol::ThreadSource as CoreThreadSource;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
#[cfg(test)]
|
||||||
use schemars::r#gen::SchemaGenerator;
|
use schemars::r#gen::SchemaGenerator;
|
||||||
|
#[cfg(test)]
|
||||||
use schemars::schema::Schema;
|
use schemars::schema::Schema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -103,6 +105,7 @@ pub enum ThreadSource {
|
|||||||
MemoryConsolidation,
|
MemoryConsolidation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
impl JsonSchema for ThreadSource {
|
impl JsonSchema for ThreadSource {
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
"ThreadSource".to_string()
|
"ThreadSource".to_string()
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ use super::ApprovalsReviewer;
|
|||||||
use super::AskForApproval;
|
use super::AskForApproval;
|
||||||
use super::SandboxPolicy;
|
use super::SandboxPolicy;
|
||||||
use super::Turn;
|
use super::Turn;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_experimental_api_macros::ExperimentalApi;
|
use codex_experimental_api_macros::ExperimentalApi;
|
||||||
use codex_protocol::config_types::CollaborationMode;
|
use codex_protocol::config_types::CollaborationMode;
|
||||||
use codex_protocol::config_types::MultiAgentMode;
|
use codex_protocol::config_types::MultiAgentMode;
|
||||||
@@ -16,13 +18,11 @@ use codex_protocol::user_input::TextElement as CoreTextElement;
|
|||||||
use codex_protocol::user_input::UserInput as CoreUserInput;
|
use codex_protocol::user_input::UserInput as CoreUserInput;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use codex_utils_path_uri::LegacyAppPathString;
|
use codex_utils_path_uri::LegacyAppPathString;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
//! We do not do true JSON-RPC 2.0, as we neither send nor expect the
|
//! We do not do true JSON-RPC 2.0, as we neither send nor expect the
|
||||||
//! "jsonrpc": "2.0" field.
|
//! "jsonrpc": "2.0" field.
|
||||||
|
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use crate::TS;
|
||||||
use codex_protocol::protocol::W3cTraceContext;
|
use codex_protocol::protocol::W3cTraceContext;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use ts_rs::TS;
|
|
||||||
|
|
||||||
pub const JSONRPC_VERSION: &str = "2.0";
|
pub const JSONRPC_VERSION: &str = "2.0";
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ use crate::ClientRequest;
|
|||||||
use crate::ServerNotification;
|
use crate::ServerNotification;
|
||||||
use crate::ServerNotificationEnvelope;
|
use crate::ServerNotificationEnvelope;
|
||||||
use crate::ServerRequest;
|
use crate::ServerRequest;
|
||||||
|
use crate::TS;
|
||||||
use crate::export::GENERATED_TS_HEADER;
|
use crate::export::GENERATED_TS_HEADER;
|
||||||
use crate::export::filter_experimental_ts_tree;
|
use crate::export::filter_experimental_ts_tree;
|
||||||
use crate::export::generate_index_ts_tree;
|
use crate::export::generate_index_ts_tree;
|
||||||
use crate::export::trim_trailing_line_whitespace;
|
use crate::export::trim_trailing_line_whitespace;
|
||||||
|
use crate::precomputed_exports::PrecomputedExports;
|
||||||
use crate::protocol::common::visit_client_response_types;
|
use crate::protocol::common::visit_client_response_types;
|
||||||
use crate::protocol::common::visit_server_response_types;
|
use crate::protocol::common::visit_server_response_types;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
@@ -17,9 +19,9 @@ use std::any::TypeId;
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::io::Cursor;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use ts_rs::TS;
|
|
||||||
use ts_rs::TypeVisitor;
|
use ts_rs::TypeVisitor;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
@@ -81,7 +83,7 @@ pub fn generate_typescript_schema_fixture_subtree_for_tests() -> Result<BTreeMap
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Regenerates `schema/typescript/` and `schema/json/`.
|
/// Regenerates `schema/typescript/`, `schema/json/`, and the stable embedded exports.
|
||||||
///
|
///
|
||||||
/// This is intended to be used by tooling (e.g., `just write-app-server-schema`).
|
/// This is intended to be used by tooling (e.g., `just write-app-server-schema`).
|
||||||
/// It deletes any previously generated files so stale artifacts are removed.
|
/// It deletes any previously generated files so stale artifacts are removed.
|
||||||
@@ -95,25 +97,77 @@ pub fn write_schema_fixtures_with_options(
|
|||||||
prettier: Option<&Path>,
|
prettier: Option<&Path>,
|
||||||
options: SchemaFixtureOptions,
|
options: SchemaFixtureOptions,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if options.experimental_api {
|
||||||
|
return write_experimental_precomputed_exports(schema_root, prettier);
|
||||||
|
}
|
||||||
|
|
||||||
let typescript_out_dir = schema_root.join("typescript");
|
let typescript_out_dir = schema_root.join("typescript");
|
||||||
let json_out_dir = schema_root.join("json");
|
let json_out_dir = schema_root.join("json");
|
||||||
|
|
||||||
ensure_empty_dir(&typescript_out_dir)?;
|
ensure_empty_dir(&typescript_out_dir)?;
|
||||||
ensure_empty_dir(&json_out_dir)?;
|
ensure_empty_dir(&json_out_dir)?;
|
||||||
|
|
||||||
crate::generate_ts_with_options(
|
crate::export::generate_ts_with_options(
|
||||||
&typescript_out_dir,
|
&typescript_out_dir,
|
||||||
prettier,
|
prettier,
|
||||||
crate::GenerateTsOptions {
|
crate::export::GenerateTsOptions::default(),
|
||||||
experimental_api: options.experimental_api,
|
|
||||||
..crate::GenerateTsOptions::default()
|
|
||||||
},
|
|
||||||
)?;
|
)?;
|
||||||
crate::generate_json_with_experimental(&json_out_dir, options.experimental_api)?;
|
crate::export::generate_json(&json_out_dir)?;
|
||||||
|
|
||||||
|
let internal_dir = tempfile::tempdir().context("create internal schema temp dir")?;
|
||||||
|
crate::export::generate_internal_json_schema(internal_dir.path())?;
|
||||||
|
let exports = PrecomputedExports {
|
||||||
|
typescript: collect_export_files_recursive(&typescript_out_dir)?,
|
||||||
|
json_schema: collect_export_files_recursive(&json_out_dir)?,
|
||||||
|
internal_json_schema: collect_export_files_recursive(internal_dir.path())?,
|
||||||
|
};
|
||||||
|
write_precomputed_exports(schema_root, "stable", &exports)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_experimental_precomputed_exports(
|
||||||
|
schema_root: &Path,
|
||||||
|
prettier: Option<&Path>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let temp_dir = tempfile::tempdir().context("create experimental schema temp dir")?;
|
||||||
|
let typescript_out_dir = temp_dir.path().join("typescript");
|
||||||
|
let json_out_dir = temp_dir.path().join("json");
|
||||||
|
|
||||||
|
crate::export::generate_ts_with_options(
|
||||||
|
&typescript_out_dir,
|
||||||
|
prettier,
|
||||||
|
crate::export::GenerateTsOptions {
|
||||||
|
experimental_api: true,
|
||||||
|
..crate::export::GenerateTsOptions::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
crate::export::generate_json_with_experimental(&json_out_dir, /*experimental_api*/ true)?;
|
||||||
|
|
||||||
|
let exports = PrecomputedExports {
|
||||||
|
typescript: collect_export_files_recursive(&typescript_out_dir)?,
|
||||||
|
json_schema: collect_export_files_recursive(&json_out_dir)?,
|
||||||
|
internal_json_schema: BTreeMap::new(),
|
||||||
|
};
|
||||||
|
write_precomputed_exports(schema_root, "experimental", &exports)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_precomputed_exports(
|
||||||
|
schema_root: &Path,
|
||||||
|
name: &str,
|
||||||
|
exports: &PrecomputedExports,
|
||||||
|
) -> Result<()> {
|
||||||
|
let output_dir = schema_root.join("precomputed");
|
||||||
|
std::fs::create_dir_all(&output_dir)
|
||||||
|
.with_context(|| format!("create {}", output_dir.display()))?;
|
||||||
|
let output_path = output_dir.join(format!("app-server-exports-{name}.json.zst"));
|
||||||
|
let json = serde_json::to_vec(exports).context("serialize precomputed protocol exports")?;
|
||||||
|
let compressed = zstd::stream::encode_all(Cursor::new(json), 19)
|
||||||
|
.context("compress precomputed protocol exports")?;
|
||||||
|
std::fs::write(&output_path, compressed)
|
||||||
|
.with_context(|| format!("write {}", output_path.display()))
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_empty_dir(dir: &Path) -> Result<()> {
|
fn ensure_empty_dir(dir: &Path) -> Result<()> {
|
||||||
if dir.exists() {
|
if dir.exists() {
|
||||||
std::fs::remove_dir_all(dir)
|
std::fs::remove_dir_all(dir)
|
||||||
@@ -229,8 +283,31 @@ fn schema_array_item_sort_key(item: &Value) -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_files_recursive(root: &Path) -> Result<BTreeMap<PathBuf, Vec<u8>>> {
|
fn collect_files_recursive(root: &Path) -> Result<BTreeMap<PathBuf, Vec<u8>>> {
|
||||||
let mut files = BTreeMap::new();
|
files_recursive(root)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|(relative_path, path)| Ok((relative_path, read_file_bytes(&path)?)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn collect_export_files_recursive(root: &Path) -> Result<BTreeMap<String, String>> {
|
||||||
|
files_recursive(root)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|(relative_path, path)| {
|
||||||
|
let relative_path = relative_path
|
||||||
|
.components()
|
||||||
|
.map(|component| component.as_os_str().to_string_lossy())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("/");
|
||||||
|
let contents = std::fs::read_to_string(&path)
|
||||||
|
.with_context(|| format!("read UTF-8 export {}", path.display()))?
|
||||||
|
.replace("\r\n", "\n");
|
||||||
|
Ok((relative_path, contents))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn files_recursive(root: &Path) -> Result<Vec<(PathBuf, PathBuf)>> {
|
||||||
|
let mut files = Vec::new();
|
||||||
let mut stack = vec![root.to_path_buf()];
|
let mut stack = vec![root.to_path_buf()];
|
||||||
while let Some(dir) = stack.pop() {
|
while let Some(dir) = stack.pop() {
|
||||||
for entry in std::fs::read_dir(&dir)
|
for entry in std::fs::read_dir(&dir)
|
||||||
@@ -262,10 +339,11 @@ fn collect_files_recursive(root: &Path) -> Result<BTreeMap<PathBuf, Vec<u8>>> {
|
|||||||
})?
|
})?
|
||||||
.to_path_buf();
|
.to_path_buf();
|
||||||
|
|
||||||
files.insert(rel, read_file_bytes(&path)?);
|
files.push((rel, path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
files.sort_by(|(left, _), (right, _)| left.cmp(right));
|
||||||
Ok(files)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+103
-9
@@ -1,8 +1,16 @@
|
|||||||
|
use crate::export::GenerateTsOptions;
|
||||||
|
use crate::export::generate_internal_json_schema;
|
||||||
|
use crate::export::generate_json_with_experimental;
|
||||||
|
use crate::export::generate_ts_with_options;
|
||||||
|
use crate::precomputed_exports::decode_precomputed_exports;
|
||||||
|
use crate::schema_fixtures::SchemaFixtureOptions;
|
||||||
|
use crate::schema_fixtures::collect_export_files_recursive;
|
||||||
|
use crate::schema_fixtures::generate_typescript_schema_fixture_subtree_for_tests;
|
||||||
|
use crate::schema_fixtures::read_schema_fixture_subtree;
|
||||||
|
use crate::schema_fixtures::write_schema_fixtures_with_options;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use codex_app_server_protocol::generate_json_with_experimental;
|
use pretty_assertions::assert_eq;
|
||||||
use codex_app_server_protocol::generate_typescript_schema_fixture_subtree_for_tests;
|
|
||||||
use codex_app_server_protocol::read_schema_fixture_subtree;
|
|
||||||
use similar::TextDiff;
|
use similar::TextDiff;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -35,6 +43,81 @@ fn json_schema_fixtures_match_generated() -> Result<()> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stable_precomputed_exports_match_schema_fixtures() -> Result<()> {
|
||||||
|
let schema_root = schema_root()?;
|
||||||
|
let exports = decode_precomputed_exports(/*experimental_api*/ false)?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
exports.typescript,
|
||||||
|
collect_export_files_recursive(&schema_root.join("typescript"))?
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
exports.json_schema,
|
||||||
|
collect_export_files_recursive(&schema_root.join("json"))?
|
||||||
|
);
|
||||||
|
|
||||||
|
let internal_dir = tempfile::tempdir().context("create internal schema temp dir")?;
|
||||||
|
generate_internal_json_schema(internal_dir.path())?;
|
||||||
|
assert_json_export_trees_match(
|
||||||
|
&exports.internal_json_schema,
|
||||||
|
&collect_export_files_recursive(internal_dir.path())?,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn experimental_precomputed_exports_match_generated() -> Result<()> {
|
||||||
|
let output_dir = tempfile::tempdir().context("create experimental schema temp dir")?;
|
||||||
|
let typescript_dir = output_dir.path().join("typescript");
|
||||||
|
let json_dir = output_dir.path().join("json");
|
||||||
|
generate_ts_with_options(
|
||||||
|
&typescript_dir,
|
||||||
|
/*prettier*/ None,
|
||||||
|
GenerateTsOptions {
|
||||||
|
experimental_api: true,
|
||||||
|
..GenerateTsOptions::default()
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
generate_json_with_experimental(&json_dir, /*experimental_api*/ true)?;
|
||||||
|
|
||||||
|
let exports = decode_precomputed_exports(/*experimental_api*/ true)?;
|
||||||
|
assert_eq!(
|
||||||
|
exports.typescript,
|
||||||
|
collect_export_files_recursive(&typescript_dir)?
|
||||||
|
);
|
||||||
|
assert_json_export_trees_match(
|
||||||
|
&exports.json_schema,
|
||||||
|
&collect_export_files_recursive(&json_dir)?,
|
||||||
|
)?;
|
||||||
|
assert_eq!(exports.internal_json_schema, BTreeMap::new());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore = "invoked by `just write-app-server-schema`"]
|
||||||
|
fn write_schema_fixtures_from_env() -> Result<()> {
|
||||||
|
let schema_root = std::env::var_os("CODEX_APP_SERVER_SCHEMA_ROOT")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.context("CODEX_APP_SERVER_SCHEMA_ROOT must be set")?;
|
||||||
|
let prettier = std::env::var_os("CODEX_APP_SERVER_SCHEMA_PRETTIER").map(PathBuf::from);
|
||||||
|
let experimental = std::env::var("CODEX_APP_SERVER_SCHEMA_EXPERIMENTAL")
|
||||||
|
.context("CODEX_APP_SERVER_SCHEMA_EXPERIMENTAL must be set")?;
|
||||||
|
let experimental_api = match experimental.as_str() {
|
||||||
|
"0" => false,
|
||||||
|
"1" => true,
|
||||||
|
value => {
|
||||||
|
anyhow::bail!("CODEX_APP_SERVER_SCHEMA_EXPERIMENTAL must be 0 or 1, got {value:?}")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
write_schema_fixtures_with_options(
|
||||||
|
&schema_root,
|
||||||
|
prettier.as_deref(),
|
||||||
|
SchemaFixtureOptions { experimental_api },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_schema_fixtures_match_generated(
|
fn assert_schema_fixtures_match_generated(
|
||||||
label: &'static str,
|
label: &'static str,
|
||||||
generate: impl FnOnce(&Path) -> Result<()>,
|
generate: impl FnOnce(&Path) -> Result<()>,
|
||||||
@@ -52,9 +135,24 @@ fn assert_schema_fixtures_match_generated(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let generated_tree = read_tree(temp_dir.path(), label)?;
|
let generated_tree = read_tree(temp_dir.path(), label)?;
|
||||||
|
assert_schema_trees_match(label, &fixture_tree, &generated_tree)
|
||||||
|
}
|
||||||
|
|
||||||
assert_schema_trees_match(label, &fixture_tree, &generated_tree)?;
|
fn assert_json_export_trees_match(
|
||||||
|
expected: &BTreeMap<String, String>,
|
||||||
|
actual: &BTreeMap<String, String>,
|
||||||
|
) -> Result<()> {
|
||||||
|
assert_eq!(
|
||||||
|
expected.keys().collect::<Vec<_>>(),
|
||||||
|
actual.keys().collect::<Vec<_>>()
|
||||||
|
);
|
||||||
|
for (path, expected) in expected {
|
||||||
|
let expected: serde_json::Value = serde_json::from_str(expected)
|
||||||
|
.with_context(|| format!("parse precomputed JSON export {path}"))?;
|
||||||
|
let actual: serde_json::Value = serde_json::from_str(&actual[path])
|
||||||
|
.with_context(|| format!("parse freshly generated JSON export {path}"))?;
|
||||||
|
assert_eq!(expected, actual, "JSON export differs: {path}");
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +184,6 @@ Run `just write-app-server-schema` to overwrite with your changes.\n\n{diff}"
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the file sets match, diff contents for each file for a nicer error.
|
|
||||||
for (path, expected) in fixture_tree {
|
for (path, expected) in fixture_tree {
|
||||||
let actual = generated_tree
|
let actual = generated_tree
|
||||||
.get(path)
|
.get(path)
|
||||||
@@ -113,8 +210,6 @@ Run `just write-app-server-schema` to overwrite with your changes.\n\n{diff}",
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn schema_root() -> Result<PathBuf> {
|
fn schema_root() -> Result<PathBuf> {
|
||||||
// In Bazel runfiles (especially manifest-only mode), resolving directories is not
|
|
||||||
// reliable. Resolve a known file, then walk up to the schema root.
|
|
||||||
let typescript_index = codex_utils_cargo_bin::find_resource!("schema/typescript/index.ts")
|
let typescript_index = codex_utils_cargo_bin::find_resource!("schema/typescript/index.ts")
|
||||||
.context("resolve TypeScript schema index.ts")?;
|
.context("resolve TypeScript schema index.ts")?;
|
||||||
let schema_root = typescript_index
|
let schema_root = typescript_index
|
||||||
@@ -123,7 +218,6 @@ fn schema_root() -> Result<PathBuf> {
|
|||||||
.context("derive schema root from schema/typescript/index.ts")?
|
.context("derive schema root from schema/typescript/index.ts")?
|
||||||
.to_path_buf();
|
.to_path_buf();
|
||||||
|
|
||||||
// Sanity check that the JSON fixtures resolve to the same schema root.
|
|
||||||
let json_bundle =
|
let json_bundle =
|
||||||
codex_utils_cargo_bin::find_resource!("schema/json/codex_app_server_protocol.schemas.json")
|
codex_utils_cargo_bin::find_resource!("schema/json/codex_app_server_protocol.schemas.json")
|
||||||
.context("resolve JSON schema bundle")?;
|
.context("resolve JSON schema bundle")?;
|
||||||
@@ -2438,7 +2438,7 @@ For server-initiated request payloads, annotate the field the same way so schema
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
just write-app-server-schema
|
just write-app-server-schema
|
||||||
# Include experimental API fields/methods in fixtures.
|
# Refresh the embedded exports that include experimental API fields/methods.
|
||||||
just write-app-server-schema --experimental
|
just write-app-server-schema --experimental
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user