Repository navigation
@tanstack/ai@0.67.0
Minor Changes
-
#1685
7dbfaf6- Text adapters can now giveinputModalitiesat run time: the input kinds that the model reads, for example['text', 'image', 'document'].undefinedmeans that the adapter does not know.TextAdapterhas the new optionalinputModalitiesproperty. ABaseTextAdaptersubclass sets it from its model metadata.- The text adapters of OpenAI, Anthropic, Gemini, Mistral, Groq, BytePlus, Grok, OpenRouter, and LLM Gateway set it. A known model gives its input kinds. An unknown model gives
undefined.
-
#1683
88fd67c- A middlewareonAfterToolCallhook can now replace the result of a tool call. Return{ type: 'replaceResult', result }from the hook.- The model and the stream (
TOOL_CALL_RESULT) get the new result. - Middleware run in order. Each hook gets the result of the hook before it as
info.result. - An error result stays an error.
- A hook that returns
undefined, or any value that is not areplaceResultdecision, keeps the result. onAfterToolCallafter anonBeforeToolCallskip now gets the parsed skip result, the same value that goes to the model.- The new
AfterToolCallDecisiontype is exported from@tanstack/ai.
- The model and the stream (
-
#1682
3aa2e3d- AddfakeText()at the new@tanstack/ai/testingsubpath. It is a text adapter that answers from a script. Use it to testchat(), tools, and middleware with no network and no API key.- Queue answers with
setResponsesandappendResponses. An answer is{ text?, thinking?, toolCalls?, finishReason?, error? }, or a function that gets{ request, state }. An empty queue fails with "No more fake responses queued". - Token usage is an estimate:
ceil(characters / 4). Withcache: true, the part of a request that matches the previous request of the same thread counts as cached tokens. - Options:
model,contextWindow, andtokensPerSecondfor stream pacing. The stream stops when the request aborts. RUN_STARTEDcarriesparentRunIdwhen the call has one.- The default tool call id is
fake-call-<fake>-<call>-<index>. It is unique acrossfakeText()instances.
- Queue answers with
-
#1684
c5ae415- AddkeyedAdapter(provider, create)andisKeyedAdapter(value). Import them from@tanstack/aior@tanstack/ai/byok.keyedAdapterwraps an adapter factory that needs a provider key.provideris a BYOK descriptor (for exampleopenaiByok) or a provider id. It throws when the provider id is not valid.- A host finds the key, for example with
getByokKey(request, keyed.provider), and callskeyed.create(key)just before the call. The key is not in your code. isKeyedAdaptertells a keyed adapter apart from a plain adapter.- It works for every adapter kind: text, image, speech, audio, video, and the rest.
For several providers, use
keyedAdapters({ openai: (key) => ..., anthropic: keyedAdapter(anthropicByok, ...) }). The map key is the provider id, so a key goes only to its own provider. An entry that is a keyed adapter for another provider throws at startup. In a route,keyedAdapterFromRequest(request, models)from@tanstack/ai/byok/serverbuilds the adapter of the provider that has a key. The user'sx-byok-<id>header wins, then the env names of descriptor entries, in map order. It givesnullwhen no provider has a key. -
#1678
13ba1b0- ARUN_ERRORnow tells you how long the provider asks you to wait before a retry.@tanstack/ai:RunErrorEventhas a newretryAfterMsfield, in milliseconds.chat()moves it tometadata.tanstack.retryAfterMs. The newtoRetryAfterMs(error)helper on@tanstack/ai/adapter-internalsreads theretry-after-msheader first, then theretry-afterheader in seconds or as an HTTP date.@tanstack/openai-baseand@tanstack/ai-anthropic: the text adapters setretryAfterMson aRUN_ERRORwhen the error response has one of these headers. This includes every adapter that uses@tanstack/openai-base.
-
#1680
377262c- AddwrapFetchtochat(), to the middlewareonConfigconfig, and toTextOptions. A wrapper gets the next fetch and gives back a new fetch. Use it to change the URL, the headers, the request, or the response of a model call. The newFetchWrappertype names the wrapper.The engine chains the
chat()wrapper and the middleware wrappers into one function. A middleware wrapper runs inside thechat()wrapper and applies to one model call only.These text adapters send their requests through the wrapper: every adapter on
@tanstack/openai-base(OpenAI, the OpenAI-compatible adapters, Grok, Groq, BytePlus, LLM Gateway, Lovable, Vercel AI Gateway, Cloudflare, and the Bedrock Chat Completions and Responses APIs), Anthropic, Mistral, Ollama, and OpenRouter. The wrapper wraps the fetch of the adapter config, not the global fetch. An Anthropic or Ollama adapter with an injected client ignoreswrapFetch. In Cloudflare binding mode, the wrapper runs, but the binding does not send the URL or the headers. WithoutwrapFetch, the requests do not change.