Skip to content

Latest commit

 

History

History
383 lines (239 loc) · 27.3 KB

File metadata and controls

383 lines (239 loc) · 27.3 KB

@tanstack/ai-openai

0.9.3

Patch Changes

  • Update model metadata from OpenRouter API (#581)

0.9.2

Patch Changes

  • Updated dependencies [2e0e2eb]:
    • @tanstack/ai@0.19.0
    • @tanstack/ai-client@0.11.0
    • @tanstack/openai-base@0.3.2

0.9.1

Patch Changes

  • Updated dependencies [a9d1916, e810153]:
    • @tanstack/ai@0.18.0
    • @tanstack/ai-client@0.10.0
    • @tanstack/openai-base@0.3.1

0.9.0

Minor Changes

  • Streaming structured output across the OpenAI-compatible providers, an OpenAI Chat Completions sibling adapter, a summarize-subsystem unification, and the decoupling of @tanstack/ai-openrouter from the shared OpenAI base. (#527)

    Core — @tanstack/ai

    • New chat({ outputSchema, stream: true }) overload returning StructuredOutputStream<InferSchemaType<TSchema>>. The stream yields raw JSON deltas via TEXT_MESSAGE_CONTENT plus a terminal CUSTOM structured-output.complete event whose value.object is typed against the caller's schema with no helper or cast required.
    • StructuredOutputStream<T> is a discriminated union over three tagged CUSTOM variants — structured-output.complete<T>, approval-requested, and tool-input-available (new ApprovalRequestedEvent / ToolInputAvailableEvent interfaces exported from @tanstack/ai). Narrowing on chunk.type === 'CUSTOM' && chunk.name === '<literal>' resolves chunk.value to the exact shape per variant. The bare CustomEvent (with value: any) is deliberately excluded to keep the narrow from collapsing to any; user-emitted events via the emitCustomEvent context API still flow at runtime and are documented as a small residual gap.
    • Activity-layer hardening: always-finalise after the stream loop (no silent hangs on missing finishReason), typed RUN_ERROR on empty content, mid-stream provider errors terminate cleanly, schema-validation failures carry runId / model / timestamp.
    • fallbackStructuredOutputStream in the activity layer is the single source of truth for adapters that don't implement structuredOutputStream natively; BaseTextAdapter no longer ships a default.
    • ChatStreamSummarizeAdapter.summarizeStream accumulates summary text and emits a terminal CUSTOM generation:result event before the final RUN_FINISHED. Fixes useSummarize never populating result over streaming connections (the client only sets result on that specific CUSTOM event).
    • SummarizationOptions is now generic in TProviderOptions and modelOptions is plumbed through end-to-end (previously silently dropped by runSummarize / runStreamingSummarize).

    Framework hooks — @tanstack/ai-react, @tanstack/ai-vue, @tanstack/ai-solid, @tanstack/ai-svelte

    useChat (React/Vue/Solid) and createChat (Svelte) now accept an outputSchema option mirroring chat({ outputSchema }) on the server. When supplied, the hook's return adds two managed reactive fields:

    • partial — the live progressive object, typed DeepPartial<InferSchemaType<typeof outputSchema>>. Updated from TEXT_MESSAGE_CONTENT deltas via parsePartialJSON. Resets on every new run.
    • final — the validated terminal payload from the structured-output.complete event, typed InferSchemaType<typeof outputSchema> | null. null until the run completes.

    Both fields are typed against the schema with no helper or cast — each hook is generic on TSchema and conditionally adds the fields to the return type. Without outputSchema, the return type is unchanged. Works the same for streaming and non-streaming endpoints — for non-streaming, partial stays {} and final snaps when the single terminal event arrives. Reasoning text and tool calls aren't surfaced as separate hook fields — they're already on messages[…].parts (as ThinkingPart, ToolCallPart, ToolResultPart), same as a normal chat. When outputSchema is set, the assistant's TextPart contains the raw JSON the model produced; filter text parts out of your message renderer and let the structured view (driven by partial / final) replace it.

    Reactivity primitive per framework:

    Framework partial type final type
    React (@tanstack/ai-react) DeepPartial<T> (plain state) T | null (plain state)
    Vue (@tanstack/ai-vue) Readonly<ShallowRef<DeepPartial<T>>> Readonly<ShallowRef<T | null>>
    Solid (@tanstack/ai-solid) Accessor<DeepPartial<T>> Accessor<T | null>
    Svelte (@tanstack/ai-svelte) readonly partial: DeepPartial<T> (rune-backed getter) readonly final: T | null (rune-backed getter)

    DeepPartial<T> is exported from each framework package for callers who want to annotate handlers explicitly.

    Base — @tanstack/openai-base

    • Package renamed from @tanstack/ai-openai-compatible (which remains published for pinned lockfiles but receives no further updates). Imports change:

      - import { OpenAICompatibleChatCompletionsTextAdapter } from '@tanstack/ai-openai-compatible'
      + import { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'
      - import { OpenAICompatibleResponsesTextAdapter } from '@tanstack/ai-openai-compatible'
      + import { OpenAIBaseResponsesTextAdapter } from '@tanstack/openai-base'
    • Centralised structuredOutputStream on both bases. Chat Completions uses response_format: { type: 'json_schema', strict: true } + stream: true; Responses uses text.format: { type: 'json_schema', strict: true } + stream: true. Subclasses (ai-openai, ai-grok, ai-groq) inherit it; OpenRouter implements its own (see below).

    • Base now adopts the openai SDK directly and imports types from openai/resources/.... The previously-vendored ~720 LOC of wire-format types (ChatCompletion, ResponseStreamEvent, etc.) is removed; consumers that imported wire types from the package should import them from the openai SDK instead. The abstract callChatCompletion* / callResponse* hooks are gone — the base constructor now takes a pre-built OpenAI client (new OpenAIBaseChatCompletionsTextAdapter(model, name, openaiClient)) and calls client.chat.completions.create / client.responses.create itself.

    • New protected isAbortError(error) hook duck-types abort detection so RUN_ERROR { code: 'aborted' } is emitted consistently across SDK error types — subclasses with proprietary error classes (e.g. @openrouter/sdk's RequestAbortedError) override.

    • Per-chunk logger.provider(...) debug logging now fires inside structuredOutputStream loops, matching the existing pattern in chatStream for end-to-end introspection in debug mode.

    The other extension hooks (extractReasoning, extractTextFromResponse, processStreamChunks, makeStructuredOutputCompatible, transformStructuredOutput, mapOptionsToRequest, convertMessage) remain. Groq's processStreamChunks and makeStructuredOutputCompatible overrides (for x_groq.usage promotion and Groq's structured-output schema quirks) are unchanged.

    Provider adapters

    Adapter API Reasoning surface
    @tanstack/ai-openai openaiText Responses response.reasoning_text.delta + response.reasoning_summary_text.delta (requires reasoning.summary: 'auto')
    @tanstack/ai-openai openaiChatCompletions (new) Chat Completions reasoning emitted silently — Chat Completions has no reasoning.summary opt-in
    @tanstack/ai-grok grokText Chat Completions delta.reasoning_content (DeepSeek convention; not typed by OpenAI SDK)
    @tanstack/ai-groq groqText Chat Completions delta.reasoning (requires reasoning_format: 'parsed'; not typed by groq-sdk)
    @tanstack/ai-openrouter openRouterText Chat Completions delta.reasoningDetails (camelCase)
    @tanstack/ai-openrouter openRouterResponsesText (beta) Responses (beta) response.reasoning_text.delta + response.reasoning_summary_text.delta via normalizeStreamEvent

    All six emit the contractual REASONING_* lifecycle (REASONING_STARTREASONING_MESSAGE_STARTREASONING_MESSAGE_CONTENT deltas → REASONING_MESSAGE_ENDREASONING_END) and close it before TEXT_MESSAGE_START. Accumulated reasoning is also surfaced on structured-output.complete.value.reasoning for consumers that only subscribe to the terminal event. OpenRouter SDK's proprietary RequestAbortedError is mapped (alongside DOM AbortError) to code: 'aborted' in the two openrouter adapters.

    @tanstack/ai-openai also exports a new OpenAIChatCompletionsTextAdapter / openaiChatCompletions / createOpenaiChatCompletions factory — a sibling to the existing Responses adapter for callers who want the older /v1/chat/completions wire format against the OpenAI SDK.

    Decouple @tanstack/ai-openrouter from the OpenAI base

    OpenRouter ships its own SDK (@openrouter/sdk) with a camelCase shape, so inheriting from the OpenAI-shaped base forced a snake_case ↔ camelCase round-trip on every request and stream event. ai-openrouter now extends BaseTextAdapter directly and inlines its own stream processors (OpenRouterTextAdapter for chat-completions, OpenRouterResponsesTextAdapter for the Responses beta), reading OpenRouter's camelCase types natively. The @tanstack/openai-base and openai dependencies are removed from ai-openrouter; only @openrouter/sdk, @tanstack/ai, and @tanstack/ai-utils remain. The ~300 LOC of inbound/outbound shape converters (toOpenRouterRequest, toChatCompletion, adaptOpenRouterStreamChunks, toSnakeResponseResult, …) are gone. Internal: duck-typed as { ... } casts on stream chunks in OpenRouterResponsesTextAdapter are replaced with direct narrowing via the SDK's discriminated unions.

    Public OpenRouter API is unchanged: openRouterText, openRouterResponsesText, createOpenRouterText, createOpenRouterResponsesText, the OpenRouter tool factories, provider routing surface (provider, models, plugins, variant, transforms), app attribution headers (httpReferer, appTitle), :variant model suffixing, RequestAbortedError propagation, and the OpenRouter-specific structured-output null-preservation all behave the same.

    ai-ollama remains on BaseTextAdapter directly — its native API uses a different wire format from Chat Completions and was never on the shared base.

    Summarize subsystem

    Anthropic, Gemini, Ollama, and OpenRouter previously each shipped a bespoke 200–300 LOC summarize adapter. They now construct a ChatStreamSummarizeAdapter (formerly ChatStreamWrapperAdapter, renamed and exported from @tanstack/ai/activities) wrapping their own text adapter, matching the existing OpenAI/Grok pattern. Removes ~600 LOC of duplicated logic across the six providers and ensures behavioural parity.

    Bespoke *SummarizeProviderOptions interfaces (e.g. OpenAISummarizeProviderOptions, AnthropicSummarizeProviderOptions, GeminiSummarizeProviderOptions, OllamaSummarizeProviderOptions, OpenRouterSummarizeProviderOptions) are removed from the provider packages' public exports. Consumers who imported them should switch to inferring the type from the adapter (InferTextProviderOptions<typeof adapter>) or remove the explicit annotation (it'll be inferred from the adapter argument).

    SummarizeAdapter interface methods are now generic in TProviderOptions. summarize and summarizeStream previously took SummarizationOptions (defaulted, so modelOptions was effectively Record<string, any> regardless of the adapter's typed shape). They now take SummarizationOptions<TProviderOptions>. Source-compatible for callers that didn't specify the generic; type-tighter for implementers and downstream consumers. SummarizationOptions, SummarizeAdapter, BaseSummarizeAdapter, and ChatStreamSummarizeAdapter previously had a mixed Record<string, any> / Record<string, unknown> / object set of defaults for TProviderOptions; they now uniformly default to Record<string, unknown>.

Patch Changes

  • Updated dependencies [98979f7, 02527c2]:
    • @tanstack/ai@0.17.0
    • @tanstack/openai-base@0.3.0
    • @tanstack/ai-client@0.9.2

0.8.5

Patch Changes

  • Updated dependencies [87f305c]:
    • @tanstack/ai@0.16.0
    • @tanstack/ai-client@0.9.1
    • @tanstack/openai-base@0.2.1

0.8.4

Patch Changes

  • Internal refactor: every provider now delegates getApiKeyFromEnv / generateId / transformNullsToUndefined / ModelMeta helpers to the new @tanstack/ai-utils package. ai-openai and ai-grok additionally inherit OpenAI-compatible adapter base classes (Chat Completions / Responses text, image, summarize, transcription, TTS, video) from the new @tanstack/openai-base package; ai-groq keeps its own BaseTextAdapter-derived text adapter (Groq uses the groq-sdk, not the OpenAI SDK) but consumes @tanstack/openai-base's schema converter and tool converters. The remaining providers (ai-anthropic, ai-gemini, ai-ollama, ai-openrouter, ai-fal, ai-elevenlabs) only consume @tanstack/ai-utils because they speak provider-native protocols, not OpenAI-compatible ones. No breaking changes — all public APIs remain identical. (#409)

  • Updated dependencies [27c9aeb, 27c9aeb]:

    • @tanstack/ai-utils@0.2.0
    • @tanstack/openai-base@0.2.0

0.8.3

Patch Changes

0.8.2

Patch Changes

  • refactor(ai, ai-openai): narrow error handling before logging (#465)

    catch (error: any) sites in stream-to-response.ts, activities/stream-generation-result.ts, and activities/generateVideo/index.ts are now narrowed to unknown and funnel through a shared toRunErrorPayload(error, fallback) helper that extracts message / code without leaking the original error object (which can carry request state from an SDK).

    Replaced four console.error calls in the OpenAI text adapter's chatStream catch block that dumped the full error object to stdout. SDK errors can carry the original request including auth headers, so the library now logs only the narrowed { message, code } payload via the internal logger — any user-supplied logger receives the sanitized shape, not the raw SDK error.

  • Tighten GeneratedImage and GeneratedAudio to enforce exactly one of url or b64Json via a mutually-exclusive GeneratedMediaSource union. (#463)

    Both types previously declared url? and b64Json? as independently optional, which allowed meaningless {} values and objects that set both fields. They now require exactly one:

    type GeneratedMediaSource =
      | { url: string; b64Json?: never }
      | { b64Json: string; url?: never }

    Existing read patterns like img.url || \data:image/png;base64,${img.b64Json}`continue to work unchanged. The only runtime-visible change is that the@tanstack/ai-openrouterand@tanstack/ai-falimage adapters no longer populateurlwith a synthesizeddata:image/png;base64,...URI when the provider returns base64 — they return{ b64Json }only. Consumers that want a data URI should build it fromb64Json` at render time.

  • Updated dependencies [54523f5, 54523f5, af9eb7b, 008f015, 54523f5]:

    • @tanstack/ai@0.14.0
    • @tanstack/ai-client@0.8.0

0.8.1

Patch Changes

  • Wire each adapter's text, summarize, image, speech, transcription, and video paths through the new InternalLogger from @tanstack/ai/adapter-internals: logger.request(...) before each SDK call, logger.provider(...) for every chunk received, and logger.errors(...) in catch blocks. Migrates all pre-existing ad-hoc console.* calls in adapter catch blocks (including the OpenAI and ElevenLabs realtime adapters) onto the structured logger. No adapter factory or config-shape changes. (#467)

  • Updated dependencies [c1fd96f]:

    • @tanstack/ai@0.13.0
    • @tanstack/ai-client@0.7.14

0.8.0

Minor Changes

  • Expose provider-tool factories (webSearchTool, webSearchPreviewTool, fileSearchTool, imageGenerationTool, codeInterpreterTool, mcpTool, computerUseTool, localShellTool, shellTool, applyPatchTool, customTool) on a new /tools subpath. Each factory returns a branded type (e.g. OpenAIWebSearchTool) gated against the selected model's supports.tools list. supports.tools was expanded to include web_search_preview, local_shell, shell, apply_patch. Existing factory signatures and runtime behavior are unchanged. (#466)

Patch Changes

  • Updated dependencies [e32583e]:
    • @tanstack/ai@0.12.0
    • @tanstack/ai-client@0.7.13

0.7.6

Patch Changes

  • Align stream output with @tanstack/ai's AG-UI-compliant event shapes: emit REASONING_* events alongside STEP_*, thread threadId/runId through RUN_STARTED/RUN_FINISHED, and return flat RunErrorEvent shape. Cast raw events through an internal asChunk helper so they line up with the re-exported @ag-ui/core EventType enum. No changes to adapter factory signatures or config shapes. (#474)

  • Updated dependencies [12d43e5, 12d43e5, 1d6f3be]:

    • @tanstack/ai@0.11.0
    • @tanstack/ai-client@0.7.11

0.7.5

Patch Changes

  • fix(ai, ai-openai, ai-gemini, ai-ollama): normalize null tool input to empty object (#430)

    When a model produces a tool_use block with no input, JSON.parse('null') returns null which fails Zod schema validation and silently kills the agent loop. Normalize null/non-object parsed tool input to {} in executeToolCalls, ToolCallManager.completeToolCall, ToolCallManager.executeTools, and the OpenAI/Gemini/Ollama adapter TOOL_CALL_END emissions. The Anthropic adapter already had this fix.

  • Updated dependencies [c780bc1]:

    • @tanstack/ai@0.10.3
    • @tanstack/ai-client@0.7.10

0.7.4

Patch Changes

  • Update model metadata from OpenRouter API (#433)

0.7.3

Patch Changes

  • Add code mode and isolate packages for secure AI code execution (#362)

    Also includes fixes for Ollama tool call argument streaming and usage reporting, OpenAI realtime adapter handling of missing call_id/item_id, realtime client guards for missing toolCallId, and new DevtoolsChatMiddleware type export from ai-event-client.

  • Updated dependencies [54abae0]:

    • @tanstack/ai@0.10.0
    • @tanstack/ai-client@0.7.7

0.7.2

Patch Changes

  • Updated dependencies [842e119]:
    • @tanstack/ai@0.9.0
    • @tanstack/ai-client@0.7.3

0.7.1

Patch Changes

  • Updated dependencies [f62eeb0]:
    • @tanstack/ai@0.8.0
    • @tanstack/ai-client@0.7.1

0.7.0

Minor Changes

  • feat: add realtime voice chat with OpenAI and ElevenLabs adapters (#300)

    Adds realtime voice/text chat capabilities:

    • @tanstack/ai: realtimeToken() function and shared realtime types (RealtimeToken, RealtimeMessage, RealtimeSessionConfig, RealtimeStatus, RealtimeMode, AudioVisualization, events, and error types)
    • @tanstack/ai-client: Framework-agnostic RealtimeClient class with connection lifecycle, audio I/O, message state management, tool execution, and RealtimeAdapter/RealtimeConnection interfaces
    • @tanstack/ai-openai: openaiRealtime() client adapter (WebRTC) and openaiRealtimeToken() server token adapter with support for semantic VAD, multiple voices, and all realtime models
    • @tanstack/ai-elevenlabs: elevenlabsRealtime() client adapter (WebSocket) and elevenlabsRealtimeToken() server token adapter for ElevenLabs conversational AI agents
    • @tanstack/ai-react: useRealtimeChat() hook with reactive state for status, mode, messages, pending transcripts, audio visualization levels, VAD control, text/image input, and interruptions
    • Docs: Realtime Voice Chat guide and full API reference for all realtime classes, interfaces, functions, and type aliases

Patch Changes

  • Updated dependencies [86be1c8]:
    • @tanstack/ai@0.7.0
    • @tanstack/ai-client@0.7.0

0.6.0

Patch Changes

0.5.0

Patch Changes

0.4.0

Patch Changes

  • re-release adapter packages (#263)

  • add multiple modalities support to the client (#263)

  • Updated dependencies [0158d14]:

    • @tanstack/ai@0.4.0

0.3.0

Minor Changes

  • feat: Add AG-UI protocol events to streaming system (#244)

    All text adapters now emit AG-UI protocol events only:

    • RUN_STARTED / RUN_FINISHED - Run lifecycle events
    • TEXT_MESSAGE_START / TEXT_MESSAGE_CONTENT / TEXT_MESSAGE_END - Text message streaming
    • TOOL_CALL_START / TOOL_CALL_ARGS / TOOL_CALL_END - Tool call streaming

    Only AG-UI event types are supported; previous legacy chunk formats (content, tool_call, done, etc.) are no longer accepted.

Patch Changes

  • Updated dependencies [e52135f]:
    • @tanstack/ai@0.3.0

0.3.0

Minor Changes

  • allows additional configuration options when creating an openAI client (#245)

0.2.1

Patch Changes

  • Fix up model names for OpenAI and release the new response APIs (#188)

  • fix up readmes (#188)

  • Updated dependencies [181e0ac, 181e0ac]:

    • @tanstack/ai@0.2.1

0.2.0

Patch Changes

  • Updated dependencies [c5df33c]:
    • @tanstack/ai@0.2.0

0.1.1

Patch Changes

  • add support for gpt 5.2 models (#166)

0.1.0

Minor Changes

  • Split up adapters for better tree shaking into separate functionalities (#137)

Patch Changes

  • Updated dependencies [8d77614]:
    • @tanstack/ai@0.1.0

0.0.3

Patch Changes

  • Fix reasoning token streaming for gpt-5-mini and gpt-5-nano models (#94)

    • Added OpenAIReasoningOptions to type definitions for gpt-5-mini and gpt-5-nano models
    • Fixed summary option placement in OpenAIReasoningOptions (moved inside reasoning object to match OpenAI SDK)
    • Added handler for response.reasoning_summary_text.delta events to stream reasoning summaries
    • Added model-specific reasoning.summary types: concise only available for computer-use-preview
    • Added OpenAIReasoningOptionsWithConcise for computer-use-preview model
  • Updated dependencies [52c3172]:

    • @tanstack/ai@0.0.3

0.0.2

Patch Changes

  • added text metadata support for message inputs (#95)

  • Updated dependencies [64fda55]:

    • @tanstack/ai@0.0.2

0.0.1

Patch Changes

  • Initial release of TanStack AI (#72)

  • Updated dependencies [a9b54c2]:

    • @tanstack/ai@0.0.1