本页还没有译文
本页 61 段还没译成Русский,下面显示的是英文原文。@tanstack/ai-svelte
还没翻译译自英文(tanstack.com)本页 61 段都还没译
Svelte 5 bindings for TanStack AI, providing reactive factory functions for the headless client using Svelte runes.
For a typed headless chat UI, see Svelte Chat UI.
Installation
createRegisterWebMCPTools(tools, options?)
Register executable client tools during Svelte component initialization. Svelte removes them when the component is destroyed.
For a complete setup and behavior guide, see WebMCP Tools.
<script lang="ts">
import {
createRegisterWebMCPTools,
type CreateRegisterWebMCPToolsOptions,
} from "@tanstack/ai-svelte";
import { searchProducts } from "./tools";
const tools = [searchProducts];
const options: CreateRegisterWebMCPToolsOptions<typeof tools> = {
onError(error) {
console.error(error);
},
};
createRegisterWebMCPTools(tools, options);
</script>CreateRegisterWebMCPToolsOptions<TTools, TContext> contains toolOptions, context, and onError. The factory owns the registration signal.
The context field is required when a tool declares a required runtime context.
createPageWebMCPTools(options?)
Read the WebMCP tools on the page as client tools. The tools field starts empty and updates when the page adds or removes a tool. Read it in a get tools() getter on createChat.
<script lang="ts">
import { createPageWebMCPTools } from "@tanstack/ai-svelte";
const page = createPageWebMCPTools({
filter: (tool) => tool.origin === location.origin,
});
</script>
<p>{page.tools.length} page tools</p>filter skips a tool when it returns false. onError gets a failed WebMCP read. For a complete guide, see Page WebMCP Tools in Chat.
createChatHook(options)
Bind chatOptions once at module scope. Call createChat() to create the instance. Per-call overrides may set threadId, initialMessages, live, and forwardedProps. They must not change tools, interrupts, or outputSchema.
import { createChatHook, fetchServerSentEvents } from "@tanstack/ai-svelte";
const chatOptions = {
connection: fetchServerSentEvents("/api/chat"),
};
const { createChat } = createChatHook(chatOptions);
const chat = createChat({ threadId: "support-1" });createChat(chatOptions) from this package still works when you want to pass the full object at the call site. Rename the bound factory if both are in one file: const { createChat: createSupportChat } = createChatHook(chatOptions).
createChat(options)
Factory function for managing chat state in Svelte 5 with full type safety.
import { createChat, fetchServerSentEvents } from "@tanstack/ai-svelte";
import {
createChatClientOptions,
type InferChatMessages,
} from "@tanstack/ai-client";
import { toolDefinition } from "@tanstack/ai";
import { z } from "zod";
const updateUIDef = toolDefinition({
name: "updateUI",
description: "Update the UI with a notification",
inputSchema: z.object({
message: z.string(),
}),
outputSchema: z.object({ success: z.boolean() }),
});
// In <script> block
let notification = "";
const updateUI = updateUIDef.client((input) => {
notification = input.message;
return { success: true };
});
const tools = [updateUI];
const chatOptions = createChatClientOptions({
connection: fetchServerSentEvents("/api/chat"),
tools,
});
// Fully typed messages!
type ChatMessages = InferChatMessages<typeof chatOptions>;
const chat = createChat(chatOptions);
// Access: chat.messages, chat.sendMessage, chat.isLoading, chat.errorOptions
Extends ChatClientOptions from @tanstack/ai-client (minus internal state callbacks):
connection- Connection adapter (required)tools?- Array of client tool implementations (with.client()method). In a component, read reactive state in aget tools()getter to change the tools after the chat is created.initialMessages?- Initial messages arraythreadId?- The only identity for this chat. Required when persistence is on. If omitted, minted after mount.forwardedProps?- Arbitrary client-controlled JSON forwarded to the server in the AG-UIRunAgentInput.forwardedPropsfield (e.g.,{ provider: 'openai', model: 'gpt-5.5' })body?- Deprecated. UseforwardedPropsinstead. Still works for backward compatibility; values are merged intoforwardedPropson the wirebyok?- Optional BYOK keyring fromdefineByok. On each send the client prepares the resolved provider and stampsx-byok-*request headers. Keys never go in the bodybyokProvider?- Optional function that returns the provider slug for this chat. If it returns a slug, only that key is prepared and sent. Otherwise the mergedproviderfromforwardedProps,body, and per-callsendMessagebodyis used. Later sources win. If no slug resolves, the send throws instead of attaching every stored keycontext?- Typed client-local runtime context passed to client tool implementations. This value is not serialized to the serverlive?- Enable live subscription mode (subscribes on creation)onResponse?- Callback when response is receivedonChunk?- Callback when stream chunk is receivedonFinish?- Callback when response finishesonError?- Callback when error occursonInterruptStateChange?- Callback when interrupt state changes; context source ishydratefor restored state andlivefor streamed or client-initiated updatesonCustomEvent?- Callback for custom stream eventsstreamProcessor?- Stream processing configuration
Note: Client tools are now automatically executed - no onToolCall callback needed!
Returns
import type {
UIMessage,
MultimodalContent,
ChatClientState,
ConnectionStatus,
SendMessageOptions,
} from "@tanstack/ai-client";
import type { ModelMessage } from "@tanstack/ai";
interface CreateChatReturn<TContext = unknown> {
readonly messages: UIMessage[];
sendMessage: (
content: string | MultimodalContent,
options?: SendMessageOptions,
) => Promise<void>;
append: (message: ModelMessage | UIMessage) => Promise<void>;
addToolResult: (result: {
toolCallId: string;
tool: string;
output: any;
state?: "output-available" | "output-error";
errorText?: string;
}) => Promise<void>;
addToolApprovalResponse: (response: {
id: string;
approved: boolean;
}) => Promise<void>;
reload: () => Promise<void>;
stop: () => void;
readonly isLoading: boolean;
readonly error: Error | undefined;
readonly status: ChatClientState;
readonly isSubscribed: boolean;
readonly connectionStatus: ConnectionStatus;
readonly sessionGenerating: boolean;
readonly isHydrating: boolean;
setMessages: (messages: UIMessage[]) => void;
clear: () => void;
/** @deprecated Use `updateForwardedProps` instead. */
updateBody: (body: Record<string, any>) => void;
updateForwardedProps: (forwardedProps: Record<string, any>) => void;
updateContext: (context: TContext) => void;
}Key differences from React/Vue:
create*naming -- factory functions, not hooks. Call outside of any lifecycle.- Reactive getters -- state properties (
messages,isLoading,error,status,isSubscribed,connectionStatus,sessionGenerating,isHydrating) are Svelte 5$statevia getters. Access directly (e.g.,chat.messages, notchat.messages.value). - No automatic cleanup -- unlike React/Vue/Solid,
createChatdoes not auto-dispose. Callchat.stop()manually when the component unmounts (e.g., inonDestroyor an$effectreturn). updateForwardedProps()-- update AG-UIforwardedPropsdynamically (e.g., for model selection). In Vue, changes to theforwardedPropsoption are synced viawatch; in Svelte, call this method explicitly. The legacyupdateBody()is still available but deprecated..svelte.tsfiles -- source files use the.svelte.tsextension for Svelte 5 rune support.
createByok(client)
Subscribe to a ByokClient snapshot in Svelte 5. Call it during component init.
import { createByok } from "@tanstack/ai-svelte";
import { byok } from "./byok";
const byokState = createByok(byok);Keep the object. byokState.snapshot is a reactive getter (status, locked, prompt). Destructuring snapshot freezes the first value. Read it in markup or $derived. Call byok.update(provider, value) from your own UI to save a key. See Bring Your Own Key.
Connection Adapters
Re-exported from @tanstack/ai-client for convenience:
import {
fetchServerSentEvents,
fetchHttpStream,
fetchJson,
stream,
type ConnectionAdapter,
} from "@tanstack/ai-svelte";Example: Basic Chat
<script lang="ts">
import { createChat, fetchServerSentEvents } from "@tanstack/ai-svelte";
let input = $state("");
const chat = createChat({
connection: fetchServerSentEvents("/api/chat"),
});
const handleSubmit = (e: Event) => {
e.preventDefault();
if (input.trim() && !chat.isLoading) {
chat.sendMessage(input);
input = "";
}
};
</script>
<div>
<div>
{#each chat.messages as message (message.id)}
<div>
<strong>{message.role}:</strong>
{#each message.parts as part, idx}
{#if part.type === "thinking"}
<div class="text-sm text-gray-500 italic">
Thinking: {part.content}
</div>
{:else if part.type === "text"}
<span>{part.content}</span>
{/if}
{/each}
</div>
{/each}
</div>
<form onsubmit={handleSubmit}>
<input bind:value={input} disabled={chat.isLoading} />
<button type="submit" disabled={chat.isLoading}>Send</button>
</form>
</div>
Example: Tool Approval
<script lang="ts">
import { createChat, fetchServerSentEvents } from "@tanstack/ai-svelte";
const chat = createChat({
connection: fetchServerSentEvents("/api/chat"),
});
</script>
<div>
{#each chat.messages as message (message.id)}
{#each message.parts as part}
{#if part.type === "tool-call" && part.state === "approval-requested" && part.approval}
<div>
<p>Approve: {part.name}</p>
<button
onclick={() =>
chat.addToolApprovalResponse({
id: part.approval.id,
approved: true,
})}
>
Approve
</button>
<button
onclick={() =>
chat.addToolApprovalResponse({
id: part.approval.id,
approved: false,
})}
>
Deny
</button>
</div>
{/if}
{/each}
{/each}
</div>
Example: Client Tools with Type Safety
<script lang="ts">
import { createChat, fetchServerSentEvents } from "@tanstack/ai-svelte";
import {
createChatClientOptions,
type InferChatMessages,
} from "@tanstack/ai-client";
import { updateUIDef, saveToStorageDef } from "./tool-definitions";
let notification = $state(null);
// Create client implementations
const updateUI = updateUIDef.client((input) => {
// input is fully typed!
notification = { message: input.message, type: input.type };
return { success: true };
});
const saveToStorage = saveToStorageDef.client((input) => {
localStorage.setItem(input.key, input.value);
return { saved: true };
});
// Create typed tools array (no 'as const' needed!)
const tools = [updateUI, saveToStorage];
const chat = createChat({
connection: fetchServerSentEvents("/api/chat"),
tools, // Automatic execution, full type safety
});
</script>
<div>
{#each chat.messages as message (message.id)}
{#each message.parts as part}
{#if part.type === "tool-call" && part.name === "updateUI"}
<div>Tool executed: {part.name}</div>
{/if}
{/each}
{/each}
</div>
Generation Functions
Factory functions for one-shot generation tasks (images, speech, transcription, summarization, video). All share the same pattern: provide a connection or fetcher, call generate(), and read reactive state.
createGeneration(options)
Base factory for custom generation types. All specialized functions below are built on this.
import { createGeneration, fetchServerSentEvents } from "@tanstack/ai-svelte";
const gen = createGeneration({
connection: fetchServerSentEvents("/api/generate/custom"),
});
// gen.generate({ prompt: 'Hello' })
// gen.result, gen.isLoading, gen.error, gen.statusOptions: connection?, fetcher?, threadId?, body?, onResult?, onError?, onProgress?, onChunk?
Returns: generate, result, isLoading, error, status, stop, reset, runId, updateBody -- all state properties are reactive getters.
createGenerateImage(options)
Image generation factory. generate() accepts ImageGenerateInput, result is ImageGenerationResult.
createGenerateSpeech(options)
Text-to-speech factory. generate() accepts SpeechGenerateInput, result is TTSResult.
createTranscription(options)
Audio transcription factory. generate() accepts TranscriptionGenerateInput, result is TranscriptionResult.
createSummarize(options)
Text summarization factory. generate() accepts SummarizeGenerateInput, result is SummarizationResult.
createGenerateVideo(options)
Video generation factory with job polling. Returns additional jobId and videoStatus reactive getters. Accepts extra onJobCreated? and onStatusUpdate? callbacks.
No generation function includes automatic cleanup. Call .stop() manually when done.
createChatClientOptions(options)
Helper to create typed chat options (re-exported from @tanstack/ai-client).
import {
createChatClientOptions,
fetchServerSentEvents,
type InferChatMessages,
} from "@tanstack/ai-client";
import { tool1, tool2 } from "./tools";
// Create typed tools array (no 'as const' needed!)
const tools = [tool1, tool2];
const chatOptions = createChatClientOptions({
connection: fetchServerSentEvents("/api/chat"),
tools,
});
type Messages = InferChatMessages<typeof chatOptions>;Types
Re-exported from @tanstack/ai-client:
UIMessage<TTools>- Message type with tool type parameterMessagePart<TTools>- Message part with tool type parameterTextPart- Text content partThinkingPart- Thinking content partToolCallPart<TTools>- Tool call part (discriminated union)ToolResultPart- Tool result partChatClientOptions<TTools, TContext>- Chat client options with typed client runtime contextConnectionAdapter- Connection adapter interfaceInferChatMessages<T>- Extract message type from optionsChatRequestBody- Request body typeGenerationClientState- Generation lifecycle stateImageGenerateInput- Image generation input typeSpeechGenerateInput- Speech generation input typeTranscriptionGenerateInput- Transcription input typeSummarizeGenerateInput- Summarization input typeVideoGenerateInput- Video generation input typeVideoGenerateResult- Video generation result typeVideoStatusInfo- Video job status info
Re-exported from @tanstack/ai:
toolDefinition()- Create isomorphic tool definitionToolDefinitionInstance- Tool definition typeClientTool- Client tool typeServerTool- Server tool type
Next Steps
- Getting Started - Learn the basics
- Tools Guide - Learn about the isomorphic tool system
- Client Tools - Learn about client-side tools