feat: expand api snapshots and schema tooling

This commit is contained in:
Nathan Flurry 2026-01-26 00:13:17 -08:00
parent ee014b0838
commit 011ca27287
72 changed files with 29480 additions and 1081 deletions

View file

@ -0,0 +1,19 @@
[package]
name = "sandbox-agent-extracted-agent-schemas"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
[dependencies]
serde.workspace = true
serde_json.workspace = true
regress.workspace = true
chrono.workspace = true
[build-dependencies]
typify.workspace = true
serde_json.workspace = true
schemars.workspace = true
prettyplease.workspace = true
syn.workspace = true

View file

@ -0,0 +1,71 @@
use std::fs;
use std::io::{self, Write};
use std::path::Path;
fn main() {
let out_dir = std::env::var("OUT_DIR").unwrap();
let schema_dir = Path::new("../../../resources/agent-schemas/artifacts/json-schema");
let schemas = [
("opencode", "opencode.json"),
("claude", "claude.json"),
("codex", "codex.json"),
("amp", "amp.json"),
];
for (name, file) in schemas {
let schema_path = schema_dir.join(file);
// Tell cargo to rerun if schema changes
emit_stdout(&format!(
"cargo:rerun-if-changed={}",
schema_path.display()
));
if !schema_path.exists() {
emit_stdout(&format!(
"cargo:warning=Schema file not found: {}",
schema_path.display()
));
// Write empty module
let out_path = Path::new(&out_dir).join(format!("{}.rs", name));
fs::write(&out_path, "// Schema not found\n").unwrap();
continue;
}
let schema_content = fs::read_to_string(&schema_path)
.unwrap_or_else(|e| panic!("Failed to read {}: {}", schema_path.display(), e));
let schema: schemars::schema::RootSchema = serde_json::from_str(&schema_content)
.unwrap_or_else(|e| panic!("Failed to parse {}: {}", schema_path.display(), e));
let mut type_space = typify::TypeSpace::default();
type_space
.add_root_schema(schema)
.unwrap_or_else(|e| panic!("Failed to process {}: {}", schema_path.display(), e));
let contents = type_space.to_stream();
// Format the generated code
let formatted = prettyplease::unparse(&syn::parse2(contents.clone()).unwrap_or_else(|e| {
panic!("Failed to parse generated code for {}: {}", name, e)
}));
let out_path = Path::new(&out_dir).join(format!("{}.rs", name));
fs::write(&out_path, formatted)
.unwrap_or_else(|e| panic!("Failed to write {}: {}", out_path.display(), e));
emit_stdout(&format!(
"cargo:warning=Generated {} types from {}",
name, file
));
}
}
fn emit_stdout(message: &str) {
let mut out = io::stdout();
let _ = out.write_all(message.as_bytes());
let _ = out.write_all(b"\n");
let _ = out.flush();
}

View file

@ -0,0 +1,111 @@
//! Generated types from AI coding agent JSON schemas.
//!
//! This crate provides Rust types for:
//! - OpenCode SDK
//! - Claude Code SDK
//! - Codex SDK
//! - AMP Code SDK
pub mod opencode {
//! OpenCode SDK types extracted from OpenAPI 3.1.1 spec.
include!(concat!(env!("OUT_DIR"), "/opencode.rs"));
}
pub mod claude {
//! Claude Code SDK types extracted from TypeScript definitions.
include!(concat!(env!("OUT_DIR"), "/claude.rs"));
}
pub mod codex {
//! Codex SDK types.
include!(concat!(env!("OUT_DIR"), "/codex.rs"));
}
pub mod amp {
//! AMP Code SDK types.
include!(concat!(env!("OUT_DIR"), "/amp.rs"));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_claude_bash_input() {
let input = claude::BashInput {
command: "ls -la".to_string(),
timeout: Some(5000.0),
working_directory: None,
};
let json = serde_json::to_string(&input).unwrap();
assert!(json.contains("ls -la"));
let parsed: claude::BashInput = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.command, "ls -la");
}
#[test]
fn test_codex_server_notification() {
// Test ItemCompletedNotification with AgentMessage
let notification = codex::ServerNotification::ItemCompleted(
codex::ItemCompletedNotification {
item: codex::ThreadItem::AgentMessage {
id: "msg-123".to_string(),
text: "Hello from Codex".to_string(),
},
thread_id: "thread-123".to_string(),
turn_id: "turn-456".to_string(),
}
);
let json = serde_json::to_string(&notification).unwrap();
assert!(json.contains("item/completed"));
assert!(json.contains("Hello from Codex"));
assert!(json.contains("agentMessage"));
}
#[test]
fn test_codex_thread_item_variants() {
// Test UserMessage variant
let user_msg = codex::ThreadItem::UserMessage {
content: vec![codex::UserInput::Text {
text: "Hello".to_string(),
text_elements: vec![],
}],
id: "user-1".to_string(),
};
let json = serde_json::to_string(&user_msg).unwrap();
assert!(json.contains("userMessage"));
assert!(json.contains("Hello"));
// Test CommandExecution variant
let cmd = codex::ThreadItem::CommandExecution {
aggregated_output: Some("output".to_string()),
command: "ls -la".to_string(),
command_actions: vec![],
cwd: "/tmp".to_string(),
duration_ms: Some(100),
exit_code: Some(0),
id: "cmd-1".to_string(),
process_id: None,
status: codex::CommandExecutionStatus::Completed,
};
let json = serde_json::to_string(&cmd).unwrap();
assert!(json.contains("commandExecution"));
assert!(json.contains("ls -la"));
}
#[test]
fn test_amp_message() {
let msg = amp::Message {
role: amp::MessageRole::User,
content: "Hello".to_string(),
tool_calls: vec![],
};
let json = serde_json::to_string(&msg).unwrap();
assert!(json.contains("user"));
assert!(json.contains("Hello"));
}
}