diff --git a/crates/model-connector/tests/fixtures/wire_v2/.gitattributes b/crates/model-connector/tests/fixtures/wire_v2/.gitattributes deleted file mode 100644 index bf62110..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.mp binary -*.bin binary diff --git a/crates/model-connector/tests/fixtures/wire_v2/README.md b/crates/model-connector/tests/fixtures/wire_v2/README.md deleted file mode 100644 index 476b362..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Golden v2 wire fixtures - -Bytes of the v2 connector wire, produced once by CodexConnector at commit -`fd7cec4176f4e3f9a5aaa75e77ba10ce5e1522f8`. Ghostlight pins CodexConnector -`68fe94b`, not that commit; `src/lib.rs`, the whole v2 wire, is identical in -both, so these bytes are Ghostlight's wire. They are pinned by `tests/wire_golden_v2.rs`, so the kit cannot drift from -them. No CodexConnector code or dependency is part of this repository. - -Generator: `generator.rs` (not compiled here). Command, run in a clone of -CodexConnector at that commit: - - cp /crates/model-connector/tests/fixtures/wire_v2/generator.rs examples/gen_wire_v2.rs - cargo run --locked -q --example gen_wire_v2 - -It prints `FIXTURE ` lines; each file is the hex decoded. It was -run on Yggdrasil through the verify container with codex-connector at that -commit as a dev-dependency of the kit at d1d28f0 (same source). The `.mp` -files are rmp-serde output; `envelope_*` files carry random nonces and -AES-256-GCM ciphertext sealed under the connection key -`parity-distinct-test-key`. Regenerating changes the envelopes' bytes; the -plaintext fixtures must regenerate byte-identically. diff --git a/crates/model-connector/tests/fixtures/wire_v2/canonical_invocation.bin b/crates/model-connector/tests/fixtures/wire_v2/canonical_invocation.bin deleted file mode 100644 index 727edf6..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/canonical_invocation.bin and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/canonical_provider_request.bin b/crates/model-connector/tests/fixtures/wire_v2/canonical_provider_request.bin deleted file mode 100644 index 2ea6c49..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/canonical_provider_request.bin and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/envelope_invocation.mp b/crates/model-connector/tests/fixtures/wire_v2/envelope_invocation.mp deleted file mode 100644 index 3f95738..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/envelope_invocation.mp +++ /dev/null @@ -1,6 +0,0 @@ -–Ù$gamecult.codex.transport_envelope.v2­parity-caller©request-1ªInvocationœÌ£VÌÁḩ̃̌xÌ©Y̽Ü­hÌ·ÌýÌâÌ—Ì…3ÌÕ ÌÇÌþÌ‘ÌÜḩ̨Ìé[̪ÌÙ!AÌë̉ÌðÌúÌÛ;ÌëÌú| ̪ÌÉ`!ÌúÌú̧̚Ì� -Ì�kÌÞ'vCZÌà̖̌̈ 8J̧ÌÀḍ̗NÌ¿FÌ¿zm6Ìÿ -Ì÷ÌíÌð\\NMqÌ–Ì×Ì— Ìù1ÌæÌ¦Ì¯Ìè 4*{ÌË̥̱ -ÌÖ̦eÌÇ̨Ì� -̰̆ḭG*SÌ�̳̼ÌÒ̥̮ÌÜ!NÌÀÌÑ̠̫̙̂7Ì�ÌÇ̰Ìì̃ÌÀ̬c̦ÌË ÌÒ̲1kÌá~hÌß3$ÌÚÌ KÌß̰ÌùÌÜ4{ÌÓÌß̼̩U.)ÌÌ̭̤rÌ ÌýÌìÌÆ^bbÏy^̳ÌßÌÌÌ�ÌÉ:Ì Ìš-ÌåYXoÌÓÌÒ[Qy̘̫ -XÌÓI:3̽ÌÔ̰D&V'-ÌòufÌŒX1ÌøÌÒ.Ì�|4cÌãÌ‹EÌåAÌßÌæÌŸÌÍQÌÝLÌ‚-Ìáw̰uÌ´3̹>Ìï$QzÌÀk m'+ÌÐÌ¢G Ì´sÌ®00 f)Ì·C̯̙*̆Ì’ÌÛy~ÌùHzÌøÌåÌý"ÌÇÌ¢*%ÌôoÌÉ̯ÌÙxÌŽ}Ì‹ÌÏÌÝYÌÈCÌîÌ´Ì¿uÌü̸x/gÌëÌñ̘X-ÌÙÌÂ̮̆NÌìRI):HÌñÌÉÌ’ÌÀ̗̉fÌÛÌ '\s̨ Ì�s̉ÌÄGVaÌÓ̶̲C\\`=p ÌžwÌŽHÌÖ4ÌÆÌØ>lfLÌ£ÌþÌäÌÖvÌ¿ÌÞJÌë \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/envelope_result_failed.mp b/crates/model-connector/tests/fixtures/wire_v2/envelope_result_failed.mp deleted file mode 100644 index 4b94559..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/envelope_result_failed.mp +++ /dev/null @@ -1,7 +0,0 @@ -–Ù$gamecult.codex.transport_envelope.v2­parity-caller©request-1¦ResultœÌ…Ì¢ÌÇ"̇Ì�GÌ©ÜCÌôÌË Ì�ÌéHÌßÌ—ÌÿÌÐÌ´ÌÝÌá\Ìö]2/ÌÎe"̘ -Ì¿ÌáÌìÌü{GÌÚṴ̧^b3Ìûj̢̗̟ÌÃÌ’sÌ•*Ì» ÌøÌä= ̸̄<ÌÁ{ÌýÌã.ÌØ8~̫̓CÌâ -̱̘ÌË -[Ì‚ÌÉoÌ–(47ÌÌBML̲Ìó̢̳Ì�hp,ÌîÌ®wÌê6DHÌðbÌÏÌÌb̹@a̧ÌÑ̵̎Ì´Ì�kÌäÌ’ÌáÌóÌ€ÌÑN+ÌüMÌÀjG %Ìß/Ìô -ÌÁÌò̸%Ì»Ì�@sT`ÌâÌ’}P̈ÌÒ ÌëÌÊÌÞ Ì«Ìâ:ÌÚ̟̖̔Ìû^Ìô>ÌûX.x -r]F8Ì�ÌÛÌ‹Ì÷Ì�5ÌÚGÌÆÌºÌÃÌ®C@(ÌóÌÓ̾{̾ÌÙMÌÓ~)Ìà 7ÌÐÌòI+'v ÌøUnP̈$U(NÌêÌçÌüsÌ¢T^[ÌÊYÌæÌ�zÌâ.wÌÆeÌ™C̦̿̄"U^trÌöÌ�ÌÙ̦Ìï̯̬ÌçÌÜÌž+ÌÑ/b̯̭̼Ìî*$Ì× ÌŠÌ²̘ÌÕ\K5̧f -Ìò̃b}̦̬o.Ẁ̧&Ìå̶̑[ \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/envelope_result_refused_replay_conflict.mp b/crates/model-connector/tests/fixtures/wire_v2/envelope_result_refused_replay_conflict.mp deleted file mode 100644 index 10e3726..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/envelope_result_refused_replay_conflict.mp and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/envelope_result_transported.mp b/crates/model-connector/tests/fixtures/wire_v2/envelope_result_transported.mp deleted file mode 100644 index 793bc54..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/envelope_result_transported.mp and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/generator.rs b/crates/model-connector/tests/fixtures/wire_v2/generator.rs deleted file mode 100644 index baf36cc..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/generator.rs +++ /dev/null @@ -1,171 +0,0 @@ -//! Generator of the golden v2 wire fixtures beside it. It is not compiled by this -//! workspace: it was run once, as an example of CodexConnector at commit -//! fd7cec4176f4e3f9a5aaa75e77ba10ce5e1522f8 (see README.md here for the command). -//! It prints one `FIXTURE ` line per file. - -use codex_connector as v2; -use serde::Serialize; - -const KEY: &str = "parity-distinct-test-key"; -const CALLER: &str = "parity-caller"; - -fn bytes(value: &T) -> Vec { - rmp_serde::to_vec(value).unwrap() -} - -fn emit(name: &str, data: &[u8]) { - let hex: String = data.iter().map(|byte| format!("{byte:02x}")).collect(); - println!("FIXTURE {name} {hex}"); -} - -fn request(choice: v2::CodexToolChoice) -> v2::CodexProviderRequest { - let mut request = - v2::CodexProviderRequest::new("request-1", "conversation-1", "gpt-5.4", "Be exact."); - request.input = vec![ - v2::CodexInputItem::UserText { - text: "state".to_string(), - }, - v2::CodexInputItem::AssistantText { - text: "reply".to_string(), - }, - v2::CodexInputItem::ToolCall { - call_id: "call-1".to_string(), - name: "read_source".to_string(), - arguments: "{}".to_string(), - }, - v2::CodexInputItem::ToolResult { - call_id: "call-1".to_string(), - output: "ok".to_string(), - }, - ]; - request.tools = vec![v2::CodexToolDefinition { - name: "read_source".to_string(), - description: "Read one admitted source.".to_string(), - parameters_json: r#"{"type":"object"}"#.to_string(), - }]; - request.tool_choice = choice; - request.reasoning_effort = Some("high".to_string()); - request.parallel_tool_calls = true; - request.max_output_tokens = Some(512); - request.prompt_cache_key = Some("cache-1".to_string()); - request -} - -fn invocation(choice: v2::CodexToolChoice) -> v2::CodexTransportInvocation { - v2::CodexTransportInvocation::new(CALLER, 2_000, [7; 32], request(choice)).unwrap() -} - -fn receipt( - invocation: &v2::CodexTransportInvocation, - outcome: v2::CodexTransportOutcome, -) -> v2::CodexTransportReceipt { - v2::CodexTransportReceipt { - schema_id: v2::RECEIPT_SCHEMA_ID.to_string(), - request_id: invocation.request_id().to_string(), - caller_runtime_id: invocation.caller_runtime_id.clone(), - native_request_sha256: invocation.native_request_sha256, - provider_request_sha256: invocation.provider_request_sha256, - model: invocation.request.model.clone(), - transport: "parity-sse".to_string(), - outcome, - } -} - -fn main() { - let key = v2::CodexTransportKey::from_connection_secret(KEY).unwrap(); - let auto = invocation(v2::CodexToolChoice::Auto); - let required = invocation(v2::CodexToolChoice::Required); - emit("invocation_auto.mp", &bytes(&auto)); - emit("invocation_required.mp", &bytes(&required)); - emit( - "canonical_invocation.bin", - &v2::canonical_invocation_bytes(&required).unwrap(), - ); - emit( - "canonical_provider_request.bin", - &v2::canonical_provider_request_bytes(&required.request).unwrap(), - ); - emit( - "provider_request_sha256.bin", - &v2::provider_request_sha256(&required.request).unwrap(), - ); - emit( - "envelope_invocation.mp", - &bytes(&v2::encrypt_invocation(&required, &key).unwrap()), - ); - - let completed = v2::CodexTransportResult::transported( - &required, - vec![ - v2::CodexTransportEvent { - sequence: 0, - payload: v2::CodexTransportEventPayload::TextDelta { - text: "hello".to_string(), - }, - }, - v2::CodexTransportEvent { - sequence: 1, - payload: v2::CodexTransportEventPayload::ToolCall { - call_id: "call-2".to_string(), - name: "read_source".to_string(), - arguments: "{}".to_string(), - }, - }, - ], - receipt( - &required, - v2::CodexTransportOutcome::Completed { - provider_response_id: Some("response-1".to_string()), - input_tokens: Some(10), - output_tokens: Some(3), - reasoning_output_tokens: Some(1), - cached_input_tokens: Some(4), - }, - ), - ); - emit("result_transported.mp", &bytes(&completed)); - emit( - "envelope_result_transported.mp", - &bytes(&v2::encrypt_result(&completed, &key).unwrap()), - ); - - let failed = v2::CodexTransportResult::transported( - &required, - Vec::new(), - receipt( - &required, - v2::CodexTransportOutcome::Failed { - failure_kind: "result_size".to_string(), - message: "provider result exceeded its byte bound".to_string(), - }, - ), - ); - emit("result_failed.mp", &bytes(&failed)); - emit( - "envelope_result_failed.mp", - &bytes(&v2::encrypt_result(&failed, &key).unwrap()), - ); - - use v2::CodexRefusal as R; - let refusals = [ - ("expired", R::Expired), - ("identity_substitution", R::IdentitySubstitution), - ("provider_digest_substitution", R::ProviderDigestSubstitution), - ("policy", R::Policy), - ("capacity", R::Capacity), - ("in_flight", R::InFlight), - ("indeterminate", R::Indeterminate), - ("replay_conflict", R::ReplayConflict), - ("malformed", R::Malformed), - ]; - for (name, refusal) in refusals { - let refused = v2::CodexTransportResult::refused(&required, refusal); - emit(&format!("result_refused_{name}.mp"), &bytes(&refused)); - if name == "replay_conflict" { - emit( - "envelope_result_refused_replay_conflict.mp", - &bytes(&v2::encrypt_result(&refused, &key).unwrap()), - ); - } - } -} diff --git a/crates/model-connector/tests/fixtures/wire_v2/invocation_auto.mp b/crates/model-connector/tests/fixtures/wire_v2/invocation_auto.mp deleted file mode 100644 index e505ca2..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/invocation_auto.mp and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/invocation_required.mp b/crates/model-connector/tests/fixtures/wire_v2/invocation_required.mp deleted file mode 100644 index 727edf6..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/invocation_required.mp and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/provider_request_sha256.bin b/crates/model-connector/tests/fixtures/wire_v2/provider_request_sha256.bin deleted file mode 100644 index f6003f3..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/provider_request_sha256.bin and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_failed.mp b/crates/model-connector/tests/fixtures/wire_v2/result_failed.mp deleted file mode 100644 index 1fe38b9..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/result_failed.mp and /dev/null differ diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_capacity.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_capacity.mp deleted file mode 100644 index 4425e6a..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_capacity.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused¨Capacity \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_expired.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_expired.mp deleted file mode 100644 index 47fff91..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_expired.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused§Expired \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_identity_substitution.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_identity_substitution.mp deleted file mode 100644 index 8da919c..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_identity_substitution.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused´IdentitySubstitution \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_in_flight.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_in_flight.mp deleted file mode 100644 index 0c9f9d3..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_in_flight.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused¨InFlight \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_indeterminate.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_indeterminate.mp deleted file mode 100644 index 068bed3..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_indeterminate.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused­Indeterminate \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_malformed.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_malformed.mp deleted file mode 100644 index f106b9f..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_malformed.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused©Malformed \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_policy.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_policy.mp deleted file mode 100644 index 28712db..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_policy.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused¦Policy \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_provider_digest_substitution.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_provider_digest_substitution.mp deleted file mode 100644 index 76b2169..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_provider_digest_substitution.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§RefusedºProviderDigestSubstitution \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_refused_replay_conflict.mp b/crates/model-connector/tests/fixtures/wire_v2/result_refused_replay_conflict.mp deleted file mode 100644 index 9f621de..0000000 --- a/crates/model-connector/tests/fixtures/wire_v2/result_refused_replay_conflict.mp +++ /dev/null @@ -1 +0,0 @@ -”Ù"gamecult.codex.transport_result.v2©request-1­parity-caller�§Refused®ReplayConflict \ No newline at end of file diff --git a/crates/model-connector/tests/fixtures/wire_v2/result_transported.mp b/crates/model-connector/tests/fixtures/wire_v2/result_transported.mp deleted file mode 100644 index f4fedf8..0000000 Binary files a/crates/model-connector/tests/fixtures/wire_v2/result_transported.mp and /dev/null differ diff --git a/crates/model-connector/tests/wire_golden_v2.rs b/crates/model-connector/tests/wire_golden_v2.rs deleted file mode 100644 index 198b731..0000000 --- a/crates/model-connector/tests/wire_golden_v2.rs +++ /dev/null @@ -1,301 +0,0 @@ -//! The kit speaks the v2 wire of CodexConnector fd7cec4, the library Ghostlight pins. -//! The golden bytes in `fixtures/wire_v2` were produced by that library (see its README); -//! nothing of it is linked here. Deleted with the fixtures by cut connector-contract-v3, -//! which changes the wire. - -use model_connector as kit; -use serde::Serialize; -use serde::de::DeserializeOwned; - -const KEY: &str = "parity-distinct-test-key"; -const CALLER: &str = "parity-caller"; - -macro_rules! golden { - ($name:literal) => { - include_bytes!(concat!("fixtures/wire_v2/", $name)) as &[u8] - }; -} - -fn bytes(value: &T) -> Vec { - rmp_serde::to_vec(value).unwrap() -} - -/// The value serializes to the golden bytes and the golden bytes decode back to it. -fn assert_wire( - name: &str, - value: &T, - golden: &[u8], -) { - assert_eq!(bytes(value), golden, "{name}: serialized bytes"); - let decoded: T = rmp_serde::from_slice(golden).unwrap(); - assert_eq!(&decoded, value, "{name}: decoded value"); -} - -fn request(choice: kit::ToolChoice) -> kit::ProviderRequest { - let mut request = - kit::ProviderRequest::new("request-1", "conversation-1", "gpt-5.4", "Be exact."); - request.input = vec![ - kit::InputItem::UserText { - text: "state".to_string(), - }, - kit::InputItem::AssistantText { - text: "reply".to_string(), - }, - kit::InputItem::ToolCall { - call_id: "call-1".to_string(), - name: "read_source".to_string(), - arguments: "{}".to_string(), - }, - kit::InputItem::ToolResult { - call_id: "call-1".to_string(), - output: "ok".to_string(), - }, - ]; - request.tools = vec![kit::ToolDefinition { - name: "read_source".to_string(), - description: "Read one admitted source.".to_string(), - parameters_json: r#"{"type":"object"}"#.to_string(), - }]; - request.tool_choice = choice; - request.reasoning_effort = Some("high".to_string()); - request.parallel_tool_calls = true; - request.max_output_tokens = Some(512); - request.prompt_cache_key = Some("cache-1".to_string()); - request -} - -fn invocation(choice: kit::ToolChoice) -> kit::TransportInvocation { - kit::TransportInvocation::new(CALLER, 2_000, [7; 32], request(choice)).unwrap() -} - -fn receipt( - invocation: &kit::TransportInvocation, - outcome: kit::TransportOutcome, -) -> kit::TransportReceipt { - kit::TransportReceipt { - schema_id: kit::RECEIPT_SCHEMA_ID.to_string(), - request_id: invocation.request_id().to_string(), - caller_runtime_id: invocation.caller_runtime_id.clone(), - native_request_sha256: invocation.native_request_sha256, - provider_request_sha256: invocation.provider_request_sha256, - model: invocation.request.model.clone(), - transport: "parity-sse".to_string(), - outcome, - } -} - -fn completed(invocation: &kit::TransportInvocation) -> kit::TransportResult { - kit::TransportResult::transported( - invocation, - vec![ - kit::TransportEvent { - sequence: 0, - payload: kit::TransportEventPayload::TextDelta { - text: "hello".to_string(), - }, - }, - kit::TransportEvent { - sequence: 1, - payload: kit::TransportEventPayload::ToolCall { - call_id: "call-2".to_string(), - name: "read_source".to_string(), - arguments: "{}".to_string(), - }, - }, - ], - receipt( - invocation, - kit::TransportOutcome::Completed { - provider_response_id: Some("response-1".to_string()), - input_tokens: Some(10), - output_tokens: Some(3), - reasoning_output_tokens: Some(1), - cached_input_tokens: Some(4), - }, - ), - ) -} - -fn failed(invocation: &kit::TransportInvocation) -> kit::TransportResult { - kit::TransportResult::transported( - invocation, - Vec::new(), - receipt( - invocation, - kit::TransportOutcome::Failed { - failure_kind: "result_size".to_string(), - message: "provider result exceeded its byte bound".to_string(), - }, - ), - ) -} - -fn key() -> kit::TransportKey { - kit::TransportKey::from_connection_secret(KEY).unwrap() -} - -fn refusals() -> [(&'static str, kit::Refusal, &'static [u8]); 9] { - use kit::Refusal as R; - [ - ("expired", R::Expired, golden!("result_refused_expired.mp")), - ( - "identity_substitution", - R::IdentitySubstitution, - golden!("result_refused_identity_substitution.mp"), - ), - ( - "provider_digest_substitution", - R::ProviderDigestSubstitution, - golden!("result_refused_provider_digest_substitution.mp"), - ), - ("policy", R::Policy, golden!("result_refused_policy.mp")), - ( - "capacity", - R::Capacity, - golden!("result_refused_capacity.mp"), - ), - ( - "in_flight", - R::InFlight, - golden!("result_refused_in_flight.mp"), - ), - ( - "indeterminate", - R::Indeterminate, - golden!("result_refused_indeterminate.mp"), - ), - ( - "replay_conflict", - R::ReplayConflict, - golden!("result_refused_replay_conflict.mp"), - ), - ( - "malformed", - R::Malformed, - golden!("result_refused_malformed.mp"), - ), - ] -} - -#[test] -fn schema_ids_are_the_v2_ids() { - assert_eq!( - kit::PROVIDER_REQUEST_SCHEMA_ID, - "gamecult.codex.provider_request.v2" - ); - assert_eq!( - kit::INVOCATION_SCHEMA_ID, - "gamecult.codex.transport_invocation.v2" - ); - assert_eq!(kit::RESULT_SCHEMA_ID, "gamecult.codex.transport_result.v2"); - assert_eq!( - kit::RECEIPT_SCHEMA_ID, - "gamecult.codex.transport_receipt.v2" - ); - assert_eq!( - kit::ENVELOPE_SCHEMA_ID, - "gamecult.codex.transport_envelope.v2" - ); -} - -#[test] -fn invocations_carry_the_v2_bytes_for_each_tool_choice() { - assert_wire( - "auto", - &invocation(kit::ToolChoice::Auto), - golden!("invocation_auto.mp"), - ); - assert_wire( - "required", - &invocation(kit::ToolChoice::Required), - golden!("invocation_required.mp"), - ); -} - -#[test] -fn results_carry_the_v2_bytes_for_success_and_failure() { - let invocation = invocation(kit::ToolChoice::Required); - assert_wire( - "transported", - &completed(&invocation), - golden!("result_transported.mp"), - ); - assert_wire("failed", &failed(&invocation), golden!("result_failed.mp")); -} - -#[test] -fn every_refusal_carries_its_v2_bytes() { - let invocation = invocation(kit::ToolChoice::Required); - for (name, refusal, golden) in refusals() { - assert_wire( - name, - &kit::TransportResult::refused(&invocation, refusal), - golden, - ); - } -} - -#[test] -fn canonical_bytes_and_provider_digest_are_the_v2_bytes() { - let invocation = invocation(kit::ToolChoice::Required); - assert_eq!( - kit::canonical_invocation_bytes(&invocation).unwrap(), - golden!("canonical_invocation.bin") - ); - assert_eq!( - kit::canonical_provider_request_bytes(&invocation.request).unwrap(), - golden!("canonical_provider_request.bin") - ); - assert_eq!( - kit::provider_request_sha256(&invocation.request) - .unwrap() - .as_slice(), - golden!("provider_request_sha256.bin") - ); -} - -#[test] -fn v2_sealed_envelopes_decrypt_and_validate_under_the_kit() { - let invocation = invocation(kit::ToolChoice::Required); - let envelope: kit::TransportEnvelope = - rmp_serde::from_slice(golden!("envelope_invocation.mp")).unwrap(); - let received = kit::decrypt_invocation(&envelope, &key()).unwrap(); - assert_eq!(bytes(&received), bytes(&invocation)); - - let results = [ - ( - golden!("envelope_result_transported.mp"), - completed(&invocation), - ), - (golden!("envelope_result_failed.mp"), failed(&invocation)), - ( - golden!("envelope_result_refused_replay_conflict.mp"), - kit::TransportResult::refused(&invocation, kit::Refusal::ReplayConflict), - ), - ]; - for (sealed, expected) in results { - let envelope: kit::TransportEnvelope = rmp_serde::from_slice(sealed).unwrap(); - let received = kit::decrypt_result(&envelope, &key(), &invocation).unwrap(); - assert_eq!(bytes(&received), bytes(&expected)); - } -} - -#[test] -fn kit_sealed_envelopes_have_the_v2_shape() { - let invocation = invocation(kit::ToolChoice::Required); - let golden: kit::TransportEnvelope = - rmp_serde::from_slice(golden!("envelope_invocation.mp")).unwrap(); - let sealed = kit::encrypt_invocation(&invocation, &key()).unwrap(); - assert_eq!(sealed.schema_id, golden.schema_id); - assert_eq!(sealed.caller_runtime_id, golden.caller_runtime_id); - assert_eq!(sealed.request_id, golden.request_id); - assert_eq!(sealed.message_kind, golden.message_kind); - assert_eq!(sealed.ciphertext.len(), golden.ciphertext.len()); - assert_ne!(sealed.nonce, golden.nonce, "nonces are fresh per seal"); - - let golden: kit::TransportEnvelope = - rmp_serde::from_slice(golden!("envelope_result_transported.mp")).unwrap(); - let sealed = kit::encrypt_result(&completed(&invocation), &key()).unwrap(); - assert_eq!(sealed.message_kind, golden.message_kind); - assert_eq!(sealed.ciphertext.len(), golden.ciphertext.len()); -}