Compare commits

...

11 Commits

Author SHA1 Message Date
Keyan Zhang
315f6c9a31 Merge branch 'main' into keyz/codegen 2026-03-11 22:53:11 -07:00
Keyan Zhang
f07b39c86d up 1019 - Wed Mar 11 2026 22:39:06 2026-03-11 22:39:06 -07:00
Keyan Zhang
f160f94cff up 1018 - Wed Mar 11 2026 22:32:50 2026-03-11 22:32:50 -07:00
Keyan Zhang
68826a0c18 up 1017 - Wed Mar 11 2026 22:28:26 2026-03-11 22:28:26 -07:00
Keyan Zhang
c219ab8b46 simplify 2026-03-11 22:20:44 -07:00
Keyan Zhang
ff831df213 . 2026-03-11 22:07:43 -07:00
Keyan Zhang
c5fe26aa02 simplify 2026-03-11 21:57:42 -07:00
Keyan Zhang
2c0e68a98b update 2026-03-11 13:02:37 -07:00
Keyan Zhang
49986a1679 schema 2026-03-11 13:02:37 -07:00
Keyan Zhang
69f6adec3b script 2026-03-11 13:02:37 -07:00
Keyan Zhang
56b60a1790 add TS codegen 2026-03-11 13:02:37 -07:00
3 changed files with 120 additions and 1 deletions

View File

@@ -0,0 +1,115 @@
use codex_protocol::protocol::RolloutLine;
use schemars::r#gen::SchemaSettings;
use serde_json::Map;
use serde_json::Value;
use std::any::TypeId;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::io;
use std::path::PathBuf;
use ts_rs::TS;
use ts_rs::TypeVisitor;
const GENERATED_TS_HEADER: &str = "// GENERATED CODE! DO NOT MODIFY BY HAND!\n\n";
const TS_RS_NOTE: &str = "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n";
const JSON_SCHEMA_FILENAME: &str = "rollout-line.schema.json";
const TYPESCRIPT_FILENAME: &str = "rollout-line.schema.ts";
fn main() -> io::Result<()> {
let out_dir = std::env::args_os()
.nth(1)
.map(PathBuf::from)
.unwrap_or_else(|| {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let codex_rs_dir = manifest_dir.parent().unwrap_or(&manifest_dir);
codex_rs_dir.join("out/rollout-line-schema")
});
std::fs::create_dir_all(&out_dir)?;
std::fs::write(
out_dir.join(JSON_SCHEMA_FILENAME),
rollout_line_schema_json()?,
)?;
std::fs::write(
out_dir.join(TYPESCRIPT_FILENAME),
generate_typescript_bundle::<RolloutLine>(),
)?;
for filename in [JSON_SCHEMA_FILENAME, TYPESCRIPT_FILENAME] {
println!("Wrote {}", out_dir.join(filename).display());
}
Ok(())
}
fn rollout_line_schema_json() -> io::Result<Vec<u8>> {
let schema = SchemaSettings::draft07()
.into_generator()
.into_root_schema_for::<RolloutLine>();
let value = serde_json::to_value(schema).map_err(io::Error::other)?;
let value = canonicalize_json(&value);
serde_json::to_vec_pretty(&value).map_err(io::Error::other)
}
fn canonicalize_json(value: &Value) -> Value {
match value {
Value::Array(items) => Value::Array(items.iter().map(canonicalize_json).collect()),
Value::Object(map) => {
let mut entries: Vec<_> = map.iter().collect();
entries.sort_by(|(left, _), (right, _)| left.cmp(right));
let mut sorted = Map::with_capacity(map.len());
for (key, child) in entries {
sorted.insert(key.clone(), canonicalize_json(child));
}
Value::Object(sorted)
}
_ => value.clone(),
}
}
fn generate_typescript_bundle<T: TS + 'static + ?Sized>() -> String {
let mut declarations = BTreeMap::new();
let mut seen = HashSet::new();
collect_typescript_declarations::<T>(&mut declarations, &mut seen);
let body = declarations
.into_values()
.collect::<Vec<_>>()
.join("\n\n")
.replace("\r\n", "\n")
.replace('\r', "\n");
format!("{GENERATED_TS_HEADER}{TS_RS_NOTE}\n{body}\n")
}
fn collect_typescript_declarations<T: TS + 'static + ?Sized>(
declarations: &mut BTreeMap<PathBuf, String>,
seen: &mut HashSet<TypeId>,
) {
let Some(output_path) = T::output_path() else {
return;
};
if !seen.insert(TypeId::of::<T>()) {
return;
}
let mut declaration = String::new();
if let Some(docs) = T::docs() {
declaration.push_str(&docs.replace("\r\n", "\n").replace('\r', "\n"));
}
declaration.push_str("export ");
declaration.push_str(&T::decl().replace("\r\n", "\n").replace('\r', "\n"));
declarations.insert(output_path.components().collect(), declaration);
let mut visitor = TypeScriptDeclarationCollector { declarations, seen };
T::visit_dependencies(&mut visitor);
}
struct TypeScriptDeclarationCollector<'a> {
declarations: &'a mut BTreeMap<PathBuf, String>,
seen: &'a mut HashSet<TypeId>,
}
impl TypeVisitor for TypeScriptDeclarationCollector<'_> {
fn visit<T: TS + 'static + ?Sized>(&mut self) {
collect_typescript_declarations::<T>(self.declarations, self.seen);
}
}

View File

@@ -2423,7 +2423,7 @@ pub enum TruncationPolicy {
Tokens(usize),
}
#[derive(Serialize, Deserialize, Clone, JsonSchema)]
#[derive(Serialize, Deserialize, Clone, JsonSchema, TS)]
pub struct RolloutLine {
pub timestamp: String,
#[serde(flatten)]

View File

@@ -78,6 +78,10 @@ mcp-server-run *args:
write-config-schema:
cargo run -p codex-core --bin codex-write-config-schema
# Generate RolloutLine schema artifacts.
write-rollout-line-schema *args:
cargo run -p codex-protocol --bin codex-write-rollout-line-schema -- "$@"
# Regenerate vendored app-server protocol schema artifacts.
write-app-server-schema *args:
cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- "$@"