feat(llm): halkyon_llm, language models' APIs streamed over plain HTTP (ADR 0021, step 2)
A pure Dart package, no SDKs, one interface (LlmClient) over Anthropic's Messages API, OpenAI's chat completions, in each known host's dialect and the local servers' (D45), and OpenAI's Responses API, stateless (D46). A model's turn keeps what its provider wants back with the tools' results: Anthropic's thinking blocks, the Responses API's reasoning items and message phase, Gemini's thought signatures. Failures come by kind, the provider's words cut and without keys. Tested on replies written from the providers' documentation, replayed in pieces of 1, 7 and 4,096 bytes; tool/record_llm.dart records real ones with a key of one's own, which the tests then run on too (D36). FakeLlmClient for the code that uses it. BSD-3-Clause, as halkyon_oidc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
e4c7259df3
commit
038aca5439
8 changed files with 4841 additions and 0 deletions
15
packages/halkyon_llm/test/fixtures/documented/anthropic/overloaded_midstream.http
vendored
Normal file
15
packages/halkyon_llm/test/fixtures/documented/anthropic/overloaded_midstream.http
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
HTTP 200
|
||||
content-type: text/event-stream; charset=utf-8
|
||||
|
||||
event: message_start
|
||||
data: {"type":"message_start","message":{"id":"msg_01Qm2vYB8xkN4cH6sGtRpL3J","type":"message","role":"assistant","model":"claude-sonnet-5-5","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":412,"output_tokens":1}}}
|
||||
|
||||
event: content_block_start
|
||||
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"„Hund“"}}
|
||||
|
||||
event: error
|
||||
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}
|
||||
|
||||
4
packages/halkyon_llm/test/fixtures/documented/anthropic/status_400.http
vendored
Normal file
4
packages/halkyon_llm/test/fixtures/documented/anthropic/status_400.http
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
HTTP 400
|
||||
content-type: application/json
|
||||
|
||||
{"type":"error","error":{"type":"invalid_request_error","message":"model: claude-sonet-5-5 is not a valid model"},"request_id":"req_011CSHoEeqs5C35K2UUqR7G0"}
|
||||
5
packages/halkyon_llm/test/fixtures/documented/anthropic/status_401.http
vendored
Normal file
5
packages/halkyon_llm/test/fixtures/documented/anthropic/status_401.http
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
HTTP 401
|
||||
content-type: application/json
|
||||
request-id: req_018EeWyXxfu5pfWkrYcMdjWG
|
||||
|
||||
{"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"},"request_id":"req_018EeWyXxfu5pfWkrYcMdjWG"}
|
||||
4
packages/halkyon_llm/test/fixtures/documented/anthropic/status_402.http
vendored
Normal file
4
packages/halkyon_llm/test/fixtures/documented/anthropic/status_402.http
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
HTTP 402
|
||||
content-type: application/json
|
||||
|
||||
{"type":"error","error":{"type":"billing_error","message":"Your credit balance is too low to access the Claude API."},"request_id":"req_011CSHoEeqs5C35K2UUqR7G1"}
|
||||
5
packages/halkyon_llm/test/fixtures/documented/anthropic/status_429.http
vendored
Normal file
5
packages/halkyon_llm/test/fixtures/documented/anthropic/status_429.http
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
HTTP 429
|
||||
content-type: application/json
|
||||
retry-after: 30
|
||||
|
||||
{"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed the rate limit for your organization of 50 requests per minute."},"request_id":"req_011CSHoEeqs5C35K2UUqR7Fy"}
|
||||
4
packages/halkyon_llm/test/fixtures/documented/anthropic/status_529.http
vendored
Normal file
4
packages/halkyon_llm/test/fixtures/documented/anthropic/status_529.http
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
HTTP 529
|
||||
content-type: application/json
|
||||
|
||||
{"type":"error","error":{"type":"overloaded_error","message":"Overloaded"},"request_id":"req_011CSHoEeqs5C35K2UUqR7Fz"}
|
||||
39
packages/halkyon_llm/test/fixtures/documented/anthropic/text.http
vendored
Normal file
39
packages/halkyon_llm/test/fixtures/documented/anthropic/text.http
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
HTTP 200
|
||||
content-type: text/event-stream; charset=utf-8
|
||||
|
||||
event: message_start
|
||||
data: {"type":"message_start","message":{"id":"msg_01Xq7aVbN3T9kd2LwPZr5HcE","type":"message","role":"assistant","model":"claude-sonnet-5-5","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":412,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":1}}}
|
||||
|
||||
event: content_block_start
|
||||
data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":"","signature":""}}
|
||||
|
||||
event: ping
|
||||
data: {"type": "ping"}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":""}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":0,"delta":{"type":"signature_delta","signature":"EqQBCgIYAhIMxk3Lr9vQm2HbW7pTGgy1d2nXo8Rf4KsJ0eQiMNp6"}}
|
||||
|
||||
event: content_block_stop
|
||||
data: {"type":"content_block_stop","index":0}
|
||||
|
||||
event: content_block_start
|
||||
data: {"type":"content_block_start","index":1,"content_block":{"type":"text","text":""}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":1,"delta":{"type":"text_delta","text":"„Hund“ heißt auf Japanisch"}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":1,"delta":{"type":"text_delta","text":" 犬 (いぬ, inu)."}}
|
||||
|
||||
event: content_block_stop
|
||||
data: {"type":"content_block_stop","index":1}
|
||||
|
||||
event: message_delta
|
||||
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":38}}
|
||||
|
||||
event: message_stop
|
||||
data: {"type":"message_stop"}
|
||||
|
||||
45
packages/halkyon_llm/test/fixtures/documented/anthropic/tool.http
vendored
Normal file
45
packages/halkyon_llm/test/fixtures/documented/anthropic/tool.http
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
HTTP 200
|
||||
content-type: text/event-stream; charset=utf-8
|
||||
|
||||
event: message_start
|
||||
data: {"type":"message_start","message":{"id":"msg_014p7gG3wDgGV9EUtLvnow3U","type":"message","role":"assistant","model":"claude-sonnet-5-5","stop_sequence":null,"usage":{"input_tokens":472,"output_tokens":2},"content":[],"stop_reason":null}}
|
||||
|
||||
event: content_block_start
|
||||
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
|
||||
|
||||
event: ping
|
||||
data: {"type": "ping"}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Ich sehe"}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" im Studienset nach."}}
|
||||
|
||||
event: content_block_stop
|
||||
data: {"type":"content_block_stop","index":0}
|
||||
|
||||
event: content_block_start
|
||||
data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01T1x1fJ34qAmk2tNTrN7Up6","name":"find_cards","input":{}}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"query\":"}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"Hu"}}
|
||||
|
||||
event: content_block_delta
|
||||
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"nd\", \"limit\": 5}"}}
|
||||
|
||||
event: content_block_stop
|
||||
data: {"type":"content_block_stop","index":1}
|
||||
|
||||
event: message_delta
|
||||
data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":89}}
|
||||
|
||||
event: message_stop
|
||||
data: {"type":"message_stop"}
|
||||
|
||||
Loading…
Reference in a new issue