diff --git a/Cargo.lock b/Cargo.lock index 2a7f7d35..f946eca2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,6 +31,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anstream" version = "1.0.0" @@ -81,12 +87,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "anyhow" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" - [[package]] name = "arboard" version = "3.7.0" @@ -145,18 +145,18 @@ checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "bit-set" -version = "0.5.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" @@ -179,6 +179,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "borrow-or-share" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" + [[package]] name = "bumpalo" version = "3.20.3" @@ -385,6 +391,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "data-encoding" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" + [[package]] name = "deranged" version = "0.5.8" @@ -426,6 +438,15 @@ dependencies = [ "syn 3.0.6", ] +[[package]] +name = "email_address" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" +dependencies = [ + "serde", +] + [[package]] name = "encode_unicode" version = "1.0.0" @@ -456,9 +477,9 @@ checksum = "0b5343afd4a8365a643ac588dab4cf234a190c7f6c88c9f6dd6ffe00837661b7" [[package]] name = "fancy-regex" -version = "0.13.0" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" +checksum = "d301f5bf187b3c295fce6468d3875037a0bccc5f6b151c63cac2f85babf21912" dependencies = [ "bit-set", "regex-automata", @@ -507,12 +528,29 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "fluent-uri" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" +dependencies = [ + "borrow-or-share", + "ref-cast", + "serde", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -524,12 +562,12 @@ dependencies = [ [[package]] name = "fraction" -version = "0.15.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" +checksum = "e246562084dde8ebbcc943b261c406ce4f68e5032ec28029a251a47d6a295500" dependencies = [ - "lazy_static", "num", + "num-bigint", ] [[package]] @@ -621,9 +659,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 5.3.0", "wasip2", + "wasm-bindgen", ] [[package]] @@ -664,6 +704,11 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "hdrhistogram" @@ -964,15 +1009,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "iso8601" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffd3254cf2b0fc53e38414bdba99719f3e269db8a6519731b68a3a90040c41b" -dependencies = [ - "nom", -] - [[package]] name = "itoa" version = "1.0.18" @@ -992,39 +1028,56 @@ dependencies = [ [[package]] name = "jsonschema" -version = "0.18.3" +version = "0.58.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0f4bea31643be4c6a678e9aa4ae44f0db9e5609d5ca9dc9083d06eb3e9a27a" +checksum = "f622c574a29fb3034a0a90645afee194dfedc75fc124228801b6e77041075bd1" dependencies = [ "ahash", - "anyhow", - "base64 0.22.1", "bytecount", - "clap", + "data-encoding", + "email_address", "fancy-regex", "fraction", - "getrandom 0.2.17", - "iso8601", + "getrandom 0.3.4", "itoa", - "memchr", + "jsonschema-regex", + "jsonschema-value", "num-cmp", - "once_cell", - "parking_lot", + "num-traits", "percent-encoding", + "referencing", "regex", - "reqwest", "serde", "serde_json", - "time", - "url", - "uuid", + "strum", + "unicode-general-category", + "uuid-simd", ] [[package]] -name = "lazy_static" -version = "1.5.1" +name = "jsonschema-regex" +version = "0.58.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" +checksum = "a968fffd387b2ab005bf00c1851f5d26e90df05b6f7ad609ed0d620033cca5e7" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "jsonschema-value" +version = "0.58.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39b7670345e5ce87371339d13705dbb9276b7e3e934bbe1efa2c6734a1f65a96" +dependencies = [ + "ahash", + "bytecount", + "fraction", + "getrandom 0.3.4", + "num-cmp", + "num-traits", + "serde_json", + "zmij", +] [[package]] name = "libc" @@ -1078,7 +1131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53353550a17c04ac46c585feb189c2db82154fc84b79c7a66c96c2c644f66071" dependencies = [ "bitflags 1.3.2", - "fluent-uri", + "fluent-uri 0.1.4", "serde", "serde_json", "serde_repr", @@ -1090,6 +1143,12 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "micromap" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74" + [[package]] name = "miniz_oxide" version = "0.9.1" @@ -1111,15 +1170,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - [[package]] name = "num" version = "0.4.3" @@ -1305,6 +1355,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + [[package]] name = "parking_lot" version = "0.12.5" @@ -1500,6 +1556,43 @@ dependencies = [ "bitflags 2.13.2", ] +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "referencing" +version = "0.58.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558f3855529c0a7e78a48e409fa653456e55f1b167eab4109c16a255b7727e3f" +dependencies = [ + "ahash", + "fluent-uri 0.4.1", + "getrandom 0.3.4", + "hashbrown", + "itoa", + "micromap", + "parking_lot", + "percent-encoding", + "serde_json", +] + [[package]] name = "regex" version = "1.13.1" @@ -1835,6 +1928,27 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2100,6 +2214,12 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +[[package]] +name = "unicode-general-category" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" + [[package]] name = "unicode-ident" version = "1.0.26" @@ -2146,13 +2266,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "uuid" -version = "1.26.1" +name = "uuid-simd" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" dependencies = [ - "js-sys", - "wasm-bindgen", + "outref", + "vsimd", ] [[package]] @@ -2161,6 +2281,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "want" version = "0.3.2" diff --git a/crates/wright-cli/Cargo.toml b/crates/wright-cli/Cargo.toml index 102d441d..4d479977 100644 --- a/crates/wright-cli/Cargo.toml +++ b/crates/wright-cli/Cargo.toml @@ -36,7 +36,7 @@ tiny_http = { version = "0.12", optional = true } [dev-dependencies] insta = { version = "1", features = ["json"] } -jsonschema = "0.18" +jsonschema = { version = "0.58", default-features = false } sha2.workspace = true wright-analyzer.workspace = true workshop-rs.workspace = true diff --git a/crates/wright-cli/tests/agent_contract.rs b/crates/wright-cli/tests/agent_contract.rs index 6a83da62..14e8abc8 100644 --- a/crates/wright-cli/tests/agent_contract.rs +++ b/crates/wright-cli/tests/agent_contract.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use jsonschema::JSONSchema; +use jsonschema::validator_for; use serde_json::{Value, json}; use wright_driver::service::{AGENT_CONTRACT, ToolRequest, ToolResponse, ToolService}; use wright_driver::{CompilerSession, FindingSelection, InputSpec, SessionConfig, SourceKind}; @@ -211,19 +211,17 @@ fn agent_v1_schema_covers_every_advertised_request_and_response() { &std::fs::read_to_string(root.join("schemas/wright-agent-v1.schema.json")).unwrap(), ) .unwrap(); - let request_schema = JSONSchema::compile(&schema).expect("request schema compiles"); + let request_schema = validator_for(&schema).expect("request schema compiles"); let mut response_document = schema.clone(); response_document["$ref"] = Value::String("#/$defs/ToolResponse".to_string()); - let response_schema = - JSONSchema::compile(&response_document).expect("response schema compiles"); + let response_schema = validator_for(&response_document).expect("response schema compiles"); let mut capabilities_document = schema.clone(); capabilities_document["$ref"] = Value::String("#/$defs/Capabilities".to_string()); let capabilities_schema = - JSONSchema::compile(&capabilities_document).expect("capability schema compiles"); + validator_for(&capabilities_document).expect("capability schema compiles"); let mut edit_range_document = schema.clone(); edit_range_document["$ref"] = Value::String("#/$defs/EditRange".to_string()); - let edit_range_schema = - JSONSchema::compile(&edit_range_document).expect("range schema compiles"); + let edit_range_schema = validator_for(&edit_range_document).expect("range schema compiles"); assert_eq!(AGENT_CONTRACT, "wright-agent/v1"); assert_eq!( @@ -392,7 +390,7 @@ fn agent_v1_schema_covers_every_advertised_request_and_response() { let mut operation_document = schema.clone(); operation_document["$ref"] = Value::String(reference.to_string()); let operation_schema = - JSONSchema::compile(&operation_document).expect("operation result schema compiles"); + validator_for(&operation_document).expect("operation result schema compiles"); assert!( operation_schema.is_valid(result), "{operation} result does not match {reference}: {result}" @@ -422,7 +420,7 @@ fn agent_v1_schema_covers_every_advertised_request_and_response() { let mut operation_document = schema.clone(); operation_document["$ref"] = Value::String(reference.to_string()); let operation_schema = - JSONSchema::compile(&operation_document).expect("operation result schema compiles"); + validator_for(&operation_document).expect("operation result schema compiles"); assert!( operation_schema.is_valid(&result), "{} all result does not match {reference}: {result}", @@ -692,7 +690,7 @@ fn rule_content_conforms_to_the_owner_schema() { }; let owner: Value = serde_json::from_str(workshop_rs::rules::content::RULE_CONTENT_V1_SCHEMA).unwrap(); - let owner = JSONSchema::compile(&owner).expect("owner schema compiles"); + let owner = validator_for(&owner).expect("owner schema compiles"); let wright: Value = serde_json::from_str( &std::fs::read_to_string(workspace_root().join("schemas/wright-agent-v1.schema.json")) .unwrap(), @@ -700,7 +698,7 @@ fn rule_content_conforms_to_the_owner_schema() { .unwrap(); let mut response = wright.clone(); response["$ref"] = json!("#/$defs/RulesResult"); - let response = JSONSchema::compile(&response).expect("response schema compiles"); + let response = validator_for(&response).expect("response schema compiles"); assert!(response.is_valid(&result), "{result}"); for rule in result["rules"].as_array().unwrap() { // Wright adds `span` to each statement; the owner's document has none. diff --git a/crates/wright-cli/tests/agent_contract_vocabulary.rs b/crates/wright-cli/tests/agent_contract_vocabulary.rs index 432056eb..087b3cd1 100644 --- a/crates/wright-cli/tests/agent_contract_vocabulary.rs +++ b/crates/wright-cli/tests/agent_contract_vocabulary.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; -use jsonschema::JSONSchema; +use jsonschema::validator_for; use serde_json::{Value, json}; use wright_driver::service::{ToolRequest, ToolResponse, ToolService}; use wright_driver::{CompilerSession, InputSpec, SessionConfig, SourceKind}; @@ -36,7 +36,7 @@ fn lookup_result_schema_covers_callable_returns_and_variadic() { .unwrap(); let mut document = schema.clone(); document["$ref"] = Value::String("#/$defs/LookupResult".to_string()); - let result_schema = JSONSchema::compile(&document).expect("result schema compiles"); + let result_schema = validator_for(&document).expect("result schema compiles"); let ToolResponse::Ok { result } = service_response(&ToolRequest::Lookup { language: "workshop".to_string(), @@ -73,7 +73,7 @@ fn list_entries_request_and_result_validate_against_the_committed_schema() { .unwrap(); let mut request = schema.clone(); request["$ref"] = Value::String("#/$defs/ListEntriesRequest".to_string()); - let request_schema = JSONSchema::compile(&request).expect("request schema compiles"); + let request_schema = validator_for(&request).expect("request schema compiles"); let valid = json!({"op":"listEntries","language":"workshop","kind":"enumMember","within":"Hero","pageSize":500,"cursor":"a.b"}); assert!(request_schema.is_valid(&valid)); for invalid in [ @@ -88,7 +88,7 @@ fn list_entries_request_and_result_validate_against_the_committed_schema() { let mut result_document = schema.clone(); result_document["$ref"] = Value::String("#/$defs/ListEntriesResult".to_string()); - let result_schema = JSONSchema::compile(&result_document).expect("result schema compiles"); + let result_schema = validator_for(&result_document).expect("result schema compiles"); let ToolResponse::Ok { result } = service_response(&ToolRequest::ListEntries { language: "workshop".to_string(), kind: "action".to_string(), diff --git a/crates/wright-cli/tests/diagnostics_schema.rs b/crates/wright-cli/tests/diagnostics_schema.rs index 44ab61e1..a742ae22 100644 --- a/crates/wright-cli/tests/diagnostics_schema.rs +++ b/crates/wright-cli/tests/diagnostics_schema.rs @@ -69,9 +69,12 @@ fn check_json_matches_schema_and_snapshot() { fn validate_output(schema: &serde_json::Value, output: &[u8]) -> serde_json::Value { let value: serde_json::Value = serde_json::from_slice(output).expect("JSON output"); - let validator = jsonschema::JSONSchema::compile(schema).expect("schema compiles"); - if let Err(errors) = validator.validate(&value) { - let errors = errors.map(|error| error.to_string()).collect::>(); + let validator = jsonschema::validator_for(schema).expect("schema compiles"); + let errors = validator + .iter_errors(&value) + .map(|error| error.to_string()) + .collect::>(); + if !errors.is_empty() { panic!("check output does not validate: {errors:?}"); } value