Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: AI

AI

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: takes call:, input: and pieces:, required, and refused_when:, cut_off_when:, done_when: and usage:. call: is an operation that changes nothing, as generate:'s, its output type the shape of one event's data; its input is mapped as generate:'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, first a list's first item; cut_off_when: and done_when: are { path: equals: } on each event as sent. A stream is whole at data: [DONE] or an event done_when: marks; an error event, or one with an error member, 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: takes call:, input:, vectors:, vector:, batch: and usage:, required, and index:. Its input maps request.model, request.texts (onto a list of text, and required) and request.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 (a Vector or a list of numbers) and index: 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 is too_long before sending. The answer is decoded by the package's types, then kept in the built-in driver's form, usage.prompt_tokens from usage: { 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 no first (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"}}) or AiEnvelope.anthropic ({"type": "json_schema", "schema"} at output_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, so json_only with its envelope, and any envelope with none, is package.provider_invalid.
  • CredentialScheme.header sends the credential alone in the header credential_header: names (Anthropic's x-api-key), a new provider key required for it and only for it; and headers:, another new key, lists the fixed headers every request carries, each "Name: value" (Anthropic's anthropic-version: 2023-06-01). Neither may name a header the driver writes itself (Authorization, Content-Type, Accept, User-Agent, Host, Content-Length and AWS's own). The surface record lists both.
  • A sandbox's embeddings. A connection's development: { sandbox: } may name embed, the operation embeddings are logged as, when it is the ai: connection and its package maps embed:.
  • A provider package's types read its answers leniently (a T? member left out is none, a member the type doesn't declare ignored) whether or not a connection names the package, so jadpo package check decodes its recordings as an app does.
  • ai: { prices: } sets a price for a model by its name in models:, overriding its package's table: input: and output:, required, and cached: (the input's when left out), each a Money setting giving the price per million tokens, all three in one currency (misconfigured at the call otherwise). A price for a model models: doesn't name, or one that isn't money, is ai.settings_invalid.
  • The OpenAI package, packages/openai (OpenAi.v1), is written from OpenAI's API reference and model pages: Chat Completions, POST /chat/completions with model, messages (the instructions as the system message), max_completion_tokens (max_tokens is deprecated) and the strict response_format; the answer choices.0.message.content; refused for message.refusal or a content_filter finish, cut off for a length finish; usage prompt_tokens, completion_tokens and prompt_tokens_details.cached_tokens. It streams the same request with "stream": true (its own input type, so a request that doesn't stream sends no stream), each chunk's choices.0.delta.content a piece, ended by data: [DONE]; and embeds through POST /embeddings with model, input and dimensions, reading data[i].embedding by index, up to 2,048 texts a request. Its key is a bearer credential; the connection gives host:, 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 is misconfigured, and a 429 or 5xx is unavailable, as for every package's operation.
  • The Anthropic package, packages/anthropic (Anthropic.v1), is written from Anthropic's Messages reference and guides: POST /v1/messages with model, max_tokens, system (the instructions) and messages, the schema at output_config.format (its structured outputs, out of beta; output_format is deprecated); the answer every text block's text; refused for a refusal stop reason, cut off for max_tokens; usage input_tokens, output_tokens and cache_read_input_tokens. It streams the same request with "stream": true, each content_block_delta's delta.text a piece, a message_delta's delta.stop_reason marking a refusal or a cut-off, ended by message_stop. Its key goes in x-api-key and its version, 2023-06-01, in anthropic-version; errors are error.type. Anthropic has no embeddings endpoint, so the package maps no embed:, and an app embedding through it is ai.settings_invalid at the call. Its current models think by default, and their thinking counts against max_tokens, so against max_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-sol and gpt-6-luna, 8,192 tokens a text for text-embedding-3-small and -large, and 1M (taken as 1,000,000) for claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5 and claude-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 sets ai: { prices: }.
  • Recordings. Each package keeps a recording of each operation, recordings/<resource>.<operation>.json, made by jadpo package record from 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, and jadpo test decodes them.
  • The documentation used:

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.