fix: harden protocol handling and rate-limit recovery - #269
fix: harden protocol handling and rate-limit recovery#269angelarose210 wants to merge 5 commits into
Conversation
- Downgrade unknown content block types to text instead of 422 errors - Accept free-form message roles (Claude Code sends non-standard roles) - Add first-token timeout to prevent indefinite hangs on stalled upstream - Improve truncation recovery with distinct small/transient vs large/size messaging - Add usage logger for dashboard tracking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tics Improve robustness for GPT models proxied through the gateway while keeping Claude request/response behavior byte-identical: - parsers: classify malformed/truncated tool-call arguments as non-executable protocol failures and record metadata-only anomalies - streaming_core: warning-only detection of raw transport-text leaks in content (never mutates the response) - debug_logger: add record_anomaly()/anomaly_info.json, gated behind DEBUG_MODE (off by default); persisted on both success and error paths, scalars only - protocol_anomalies: new pure classifier for high-confidence transport leaks - carry forward prior-session converter/streaming/truncation-recovery changes - update stale tests to match intcentional role-normalization and the small/large truncation message split; document anomaly_info.json in .env.example - gitignore .venv/ Full suite: 1728 passed.
… path collect_stream_response() flattened every tool_calls delta with `tool_calls.extend(...)`, ignoring the `index` field. That is correct only when a provider emits each tool call in exactly one chunk. Per the OpenAI streaming protocol a tool call may be split — identity (id + function.name) in one delta, argument fragments in later deltas keyed by the same index — so any split emission produced multiple half-formed tool calls: one with a name and no arguments, another with arguments and no name. Accumulate by index the way a streaming client does (see the Vercel AI SDK StreamingToolCallTracker), taking identity from the first delta for an index and concatenating argument fragments, then emit in index order. Latent today: the gateway currently emits one chunk per tool call, verified end to end against a live gateway (direct curl, tool-result round trip, and parallel multi-tool turns). This hardens the path against split emission rather than fixing an observed failure. Tests: reassembly for single and parallel tool calls, non-streaming collection, and the existing None-protection cases retargeted at the reassembled call instead of individual fragments.
|
Thanks for the PR! 🎉 Before merge, we need a one-time CLA confirmation. Full CLA text: Please reply once with: You need to write once, all further messages from me can be ignored. |
|
I have read the CLA and I accept its terms |
|
Thanks for the PR! 🎉 Before merge, we need a one-time CLA confirmation. Full CLA text: Please reply once with: You need to write once, all further messages from me can be ignored. |
|
@angelarose210 could you give a try to this gateway: https://github.com/ankitcharolia/kiro-gateway It works quite well with All AI harness and actively being developed. The most important thing is that it is ACP compliant |
Summary