Streams, embeddings and the OpenAI and Anthropic packages
How a provider package maps streams and embeddings, and what Jadpo's own OpenAI and Anthropic packages send. You need the mapping rules only to write a package; an app picks a package and connects it (Connecting a provider).
stream:takescall:,input:andpieces:, required, andrefused_when:,cut_off_when:,done_when:andusage:.call:is an operation that changes nothing, asgenerate:'s, its output type the shape of one event's data; its input is mapped asgenerate:'s, and a value written there (stream: true) asks the provider to stream.pieces: event.<field>...is where an event's piece of text is,firsta list's first item;cut_off_when:anddone_when:are{ path: equals: }on each event as sent. A stream is whole atdata: [DONE]or an eventdone_when:marks; anerrorevent, or one with anerrormember, breaks it; an event that marks nothing and has no text (a ping, a thinking block's) is passed over. Its events are read on the answer as sent, not decoded, since a provider's events differ in shape; their type checks the mapping and the stream's recording.usage:is read and checked but not counted, since a stream is charged the whole of the most it could use.embed:takescall:,input:,vectors:,vector:,batch:andusage:, required, andindex:. Its input mapsrequest.model,request.texts(onto a list of text, and required) andrequest.dimensions,ai: { embedding_dimensions: }, besides settings and values;vectors: response.<field>is the answer's list of objects,vector: item.<field>each item's vector (aVectoror a list of numbers) andindex: item.<field>its place among the texts.batch:is the most texts the provider takes at once (see the note at the end of this topic). A text longer than the model's context in the package's table istoo_longbefore sending. The answer is decoded by the package's types, then kept in the built-in driver's form,usage.prompt_tokensfromusage: { input: }, so a rerun, a record and the budget read it as theirs.refused_when:is a place that holds anything, or{ holds: <place> path: "<member>" equals: <value> }, any of them saying so, since OpenAI marks a refusal with a field and its content filter with a finish reason.answer:reads every item of a list where a field follows the list with nofirst(response.content.text), their texts joined in order and the items with none left out, as Anthropic answers in content blocks, a thinking block among them with no text.schema: { envelope: }names the envelope's shape:AiEnvelope.openai(the default,{"type": "json_schema", "json_schema": {"name", "strict", "schema"}}) orAiEnvelope.anthropic({"type": "json_schema", "schema"}atoutput_config.format), with the schema cut as Generating, its fake and the local driver says, which Anthropic's structured outputs also take. Anthropic has no JSON-only mode, sojson_onlywith its envelope, and any envelope withnone, ispackage.provider_invalid.CredentialScheme.headersends the credential alone in the headercredential_header:names (Anthropic'sx-api-key), a new provider key required for it and only for it; andheaders:, another new key, lists the fixed headers every request carries, each"Name: value"(Anthropic'santhropic-version: 2023-06-01). Neither may name a header the driver writes itself (Authorization,Content-Type,Accept,User-Agent,Host,Content-Lengthand AWS's own). The surface record lists both.- A sandbox's embeddings. A connection's
development: { sandbox: }may nameembed, the operation embeddings are logged as, when it is theai:connection and its package mapsembed:. - A provider package's types read its answers leniently (a
T?member left out isnone, a member the type doesn't declare ignored) whether or not a connection names the package, sojadpo package checkdecodes its recordings as an app does. ai: { prices: }sets a price for a model by its name inmodels:, overriding its package's table:input:andoutput:, required, andcached:(the input's when left out), each aMoneysetting giving the price per million tokens, all three in one currency (misconfiguredat the call otherwise). A price for a modelmodels:doesn't name, or one that isn't money, isai.settings_invalid.- The OpenAI package,
packages/openai(OpenAi.v1), is written from OpenAI's API reference and model pages: Chat Completions,POST /chat/completionswithmodel,messages(the instructions as thesystemmessage),max_completion_tokens(max_tokensis deprecated) and the strictresponse_format; the answerchoices.0.message.content; refused formessage.refusalor acontent_filterfinish, cut off for alengthfinish; usageprompt_tokens,completion_tokensandprompt_tokens_details.cached_tokens. It streams the same request with"stream": true(its own input type, so a request that doesn't stream sends nostream), each chunk'schoices.0.delta.contenta piece, ended bydata: [DONE]; and embeds throughPOST /embeddingswithmodel,inputanddimensions, readingdata[i].embeddingbyindex, up to 2,048 texts a request. Its key is a bearer credential; the connection giveshost:,https://api.openai.com/v1, so a compatible gateway or a test's server can stand in. Its failures are its operations' (error.code), and none is mapped. So a refusal of the request ismisconfigured, and a429or5xxisunavailable, as for every package's operation. - The Anthropic package,
packages/anthropic(Anthropic.v1), is written from Anthropic's Messages reference and guides:POST /v1/messageswithmodel,max_tokens,system(the instructions) andmessages, the schema atoutput_config.format(its structured outputs, out of beta;output_formatis deprecated); the answer everytextblock's text; refused for arefusalstop reason, cut off formax_tokens; usageinput_tokens,output_tokensandcache_read_input_tokens. It streams the same request with"stream": true, eachcontent_block_delta'sdelta.texta piece, amessage_delta'sdelta.stop_reasonmarking a refusal or a cut-off, ended bymessage_stop. Its key goes inx-api-keyand its version,2023-06-01, inanthropic-version; errors areerror.type. Anthropic has no embeddings endpoint, so the package maps noembed:, and an app embedding through it isai.settings_invalidat the call. Its current models think by default, and their thinking counts againstmax_tokens, so againstmax_output:; the package leaves thinking as each model sets it, since the setting that turns it down differs by model and a mapping writes no nested object. - The tables come from the providers' own pages, and are refreshed
whenever those change. They hold context windows of 1,050,000
tokens for
gpt-6-astra,gpt-6.1-solandgpt-6-luna, 8,192 tokens a text fortext-embedding-3-smalland-large, and 1M (taken as 1,000,000) forclaude-fable-5-1,claude-opus-5-5,claude-sonnet-5-5andclaude-haiku-5-5; standard prices per million input, cached and output tokens in US dollars, from 2026-10-20: OpenAI's 10.00, 1.00 and 50.00 (Astra), 2.00, 0.10 and 10.00 (Sol), and 0.10, 0.01 and 0.50 (Luna), its embedding models' 0.02 and 0.13 input (no output; cached repeating input, which OpenAI doesn't publish); Anthropic's 10.00, 0.25 and 50.00 (Fable 5.1), 4.00, 0.20 and 20.00 (Opus 5.5), 2.00, 0.10 and 10.00 (Sonnet 5.5), and 0.10, 0.01 and 0.50 (Haiku 5.5, for prompts up to 100,000 tokens). Long-prompt prices (OpenAI's past 272,000 input tokens, Haiku 5.5's past 100,000), batch, fast and regional prices and cache writes aren't held; an app that needs them setsai: { prices: }. - Recordings. Each package keeps a recording of each operation,
recordings/<resource>.<operation>.json, made byjadpo package recordfrom the answer each provider's documentation shows, sent by a server in the test, never a live call: a stream's is one event, a piece of text. A test records them again from the same answers and compares them with the files, andjadpo testdecodes them. - The documentation used:
- OpenAI: https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create,
https://developers.openai.com/api/reference/resources/chat/subresources/completions/streaming-events,
https://developers.openai.com/api/reference/resources/embeddings/methods/create,
https://developers.openai.com/api/docs/guides/structured-outputs,
https://developers.openai.com/api/docs/guides/error-codes,
https://developers.openai.com/api/docs/models, each model's page
under https://developers.openai.com/api/docs/models/ (
gpt-6-astra,gpt-6.1-sol,gpt-6-luna,text-embedding-3-small,text-embedding-3-large), and https://developers.openai.com/api/docs/pricing. - Anthropic: https://platform.claude.com/docs/en/api/messages/create, https://platform.claude.com/docs/en/build-with-claude/streaming, https://platform.claude.com/docs/en/build-with-claude/structured-outputs, https://platform.claude.com/docs/en/build-with-claude/thinking, https://platform.claude.com/docs/en/api/errors, https://platform.claude.com/docs/en/api/versioning, https://platform.claude.com/docs/en/about-claude/models/overview, https://platform.claude.com/docs/en/build-with-claude/context-windows and https://platform.claude.com/docs/en/about-claude/pricing.
- OpenAI: https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create,
https://developers.openai.com/api/reference/resources/chat/subresources/completions/streaming-events,
https://developers.openai.com/api/reference/resources/embeddings/methods/create,
https://developers.openai.com/api/docs/guides/structured-outputs,
https://developers.openai.com/api/docs/guides/error-codes,
https://developers.openai.com/api/docs/models, each model's page
under https://developers.openai.com/api/docs/models/ (
Not built yet: a batch: below 100, the most ai.embed_all sends, is
toolchain.not_built_yet, since every text goes in one request.
Markdown for agents: /docs/streams-embeddings-and-the-openai-and-anthropic-packages.md.Built from Jadpo main at a707efb.