james.maes
|
a731b5db6e
|
feat(04-01): AnthropicProvider with URLSession SSE decoder covering all six AGENT-03 edges + 1h cache TTL header wiring (AGENT-02, AGENT-03, AGENT-07)
- AnthropicProvider actor: hand-rolled URLSession + per-request apiKeyProvider closure (S-5 fetch-per-request) + nonisolated stream(...) returning AsyncThrowingStream<LLMEvent, Error>
- AGENT-02: every request carries anthropic-version: 2023-06-01 + anthropic-beta: extended-cache-ttl-2025-04-11 (unconditional) + x-api-key + Accept: text/event-stream + Content-Type: application/json
- SSELineReader: generic over AsyncSequence<UInt8> — same code path for URLSession.AsyncBytes + test fixtures; multi-line data: concat with \n; CRLF tolerant; flushes pending frame on EOF
- SSEDecoder: state machine covering all AGENT-03 edges
- message_stop (NOT message_delta) is canonical close
- ping events swallowed
- thinking_delta routes to its own LLMEvent case
- stop_reason: refusal first-class (not warning)
- input_json_delta chunks concatenated; one toolUseRequested on content_block_stop
- empty partial_json chunks skipped
- mid-stream EOF emits partialToolUseAtDisconnect, then streamTruncated, then messageStop
- RequestBody: Codable encoder shapes Anthropic JSON via typed JSONValue enum (no [String: Any]); cache_control attaches to first system block with ttl: 1h when CacheHints.extended1h; tools.input_schema embedded inline (NOT double-encoded as string); ToolChoice.none → {"type":"none"}
- Base64URL helper for Plan 04-04 turnNonce wrapping (SEC-06)
- 7 RequestBodyTests + 11 SSEDecoderTests passing
|
2026-04-24 17:21:04 -05:00 |
|