feat(TASK-043): Responses usage parsing, failure hardening, responses default for stock openai
Parse Responses-API token usage on both wires: non-streaming responses fill ChatCompletionsOutput.usage and response.completed events feed the SseHandler accumulator, with cached input mapped from input_tokens_details.cached_tokens. Harden failure paths: bail with the payload message on response.failed and error stream events, and surface incomplete_details.reason when a non-streaming response comes back incomplete and empty. Replay hardening: id-only Reasoning blocks (no encrypted_content) are dropped at replay time since the API 400s on them under store:false, which would permanently wedge a persisted session; a null summary is normalized to [] at the same site. Claude's replay guards flip to a positive Thinking/RedactedThinking allow-list. Flip the default wire for stock openai (api.openai.com, no custom api_base) to Responses. The resolver call site now passes a genuine stock-openai predicate: api-key clients or stock oauth without api_base qualify, config-oauth gateways never do. Custom api_base and openai-compatible clients keep defaulting to chat; explicit wire_api still always wins. Also reject a non-map responses section in RequestPatch via test.
This commit is contained in:
3 files changed
+395
-26
No files matched your search
@@ -1640,6 +1640,15 @@ mod tests {
|
||||
assert!(patch.chat_completions.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_map_request_patch_responses_section_is_rejected() {
|
||||
let err = serde_json::from_value::<RequestPatch>(json!({"responses": "bogus"}))
|
||||
.unwrap_err()
|
||||
.to_string();
|
||||
|
||||
assert!(err.contains("expected a map"), "unexpected error: {err}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chat_client_patch_never_touches_the_responses_wire() {
|
||||
let client = patch_probe(
|
||||
|
||||
Reference in new issue
Block a user