
Company News
Socket Joins New OpenJS Program to Fund Node.js Security Work
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.
@aibind/sveltekit
Advanced tools
AI SDK bindings for SvelteKit — streaming, structured output, agents, server handlers, and remote functions
AI SDK bindings for SvelteKit. Reactive Svelte 5 classes, server handlers, remote functions, and agents — all wired up with sensible defaults.
🤏 Tiny — Ships only what you use. Tree-shakes per entry point.
🐇 Simple — Three classes: Stream, StructuredStream, Agent. Instantiate and .send().
🧙♀️ Elegant — Svelte 5 runes ($state) on every field. No stores, no boilerplate.
🗃️ Highly customizable — Custom endpoints, custom fetch, per-request system overrides, named model registries.
⚛️ Reactive — Text, loading, error, done — all reactive. Just bind and go.
🔌 Batteries included — Server handler, remote functions, and default endpoints out of the box.
npm install @aibind/sveltekit ai svelte
Peer dependencies: svelte ^5.53, ai ^6.0, @sveltejs/kit ^2.53.
StructuredStream works with any Standard Schema-compatible library. Install one:
# Zod (v4 recommended — has built-in JSON Schema support)
npm install zod
# Valibot (requires JSON Schema converter)
npm install valibot @valibot/to-json-schema
# ArkType (built-in JSON Schema via .toJsonSchema())
npm install arktype
// src/hooks.server.ts
import { createStreamHandler } from "@aibind/sveltekit/server";
import { anthropic } from "@ai-sdk/anthropic";
export const handle = createStreamHandler({
model: anthropic("claude-sonnet-4-20250514"),
});
This handles /api/__aibind__/stream and /api/__aibind__/structured automatically.
<script lang="ts">
import { Stream } from '@aibind/sveltekit';
const stream = new Stream({
system: 'You are a helpful assistant.'
});
let prompt = $state('');
</script>
<form onsubmit={(e) => { e.preventDefault(); stream.send(prompt); }}>
<input bind:value={prompt} />
<button disabled={stream.loading}>Send</button>
</form>
{#if stream.text}
<p>{stream.text}</p>
{/if}
@aibind/sveltekit — Client Classesimport { Stream, StructuredStream, defineModels } from "@aibind/sveltekit";
defineModels(models)Define named AI models for type-safe model selection across client and server.
// src/lib/models.server.ts
import { defineModels } from "@aibind/sveltekit";
import { anthropic } from "@ai-sdk/anthropic";
export const models = defineModels({
default: anthropic("claude-sonnet-4-20250514"),
fast: anthropic("claude-haiku-20250514"),
});
export type Models = typeof models.$infer; // 'default' | 'fast'
Pass models to the server handler:
// src/hooks.server.ts
import { createStreamHandler } from "@aibind/sveltekit/server";
import { models } from "$lib/models.server";
export const handle = createStreamHandler({ models });
new Stream(options?)Reactive streaming text. All properties are Svelte 5 $state fields. Endpoint defaults to /api/__aibind__/stream.
const stream = new Stream({
model: "fast", // optional model key
system: "You are a poet.",
endpoint: "/api/custom/stream", // override default
fetch: customFetch, // optional custom fetch
onFinish: (text) => console.log(text),
onError: (err) => console.error(err),
});
stream.send("Write a haiku");
stream.send("Now a limerick", { system: "Override system prompt" });
stream.text; // reactive accumulated text
stream.loading; // true while streaming
stream.error; // Error | null
stream.done; // true when complete
stream.abort(); // cancel in-flight request
stream.retry(); // re-send last prompt
new StructuredStream(options)Streams JSON and parses partial objects as they arrive. Validates the final result with any Standard Schema-compatible library. Endpoint defaults to /api/__aibind__/structured.
import { StructuredStream } from "@aibind/sveltekit";
import { z } from "zod";
const analysis = new StructuredStream({
schema: z.object({
sentiment: z.enum(["positive", "negative", "neutral"]),
score: z.number(),
topics: z.array(z.string()),
}),
system: "Analyze sentiment. Return JSON matching the schema.",
});
analysis.send("I love this product!");
analysis.partial; // Partial<T> — updates as JSON streams in
analysis.data; // T | null — fully validated after completion
analysis.raw; // raw JSON string
@aibind/sveltekit/server — Stream Handlerimport { createStreamHandler, ServerAgent } from "@aibind/sveltekit/server";
createStreamHandler(config)SvelteKit handle hook that serves streaming endpoints.
// Single model
export const handle = createStreamHandler({
model: anthropic("claude-sonnet-4-20250514"),
prefix: "/api/__aibind__", // default
});
// Multi-model
export const handle = createStreamHandler({ models });
Handles two routes:
POST {prefix}/stream — text streamingPOST {prefix}/structured — JSON streamingServerAgentServer-side agent with tools, system prompt, and multi-step tool loops.
import { ServerAgent } from "@aibind/sveltekit/server";
import { tool, stepCountIs } from "ai";
import { z } from "zod";
const agent = new ServerAgent({
model: anthropic("claude-sonnet-4-20250514"),
system: "You are a helpful assistant with access to tools.",
tools: {
get_weather: tool({
description: "Get weather for a city",
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({
city,
temperature: "72°F",
condition: "sunny",
}),
}),
},
stopWhen: stepCountIs(5),
});
// In a SvelteKit endpoint:
export async function POST({ request }) {
const { messages } = await request.json();
const lastMessage = messages[messages.length - 1];
const result = agent.stream(lastMessage.content, {
messages: messages.slice(0, -1),
});
return result.toTextStreamResponse();
}
@aibind/sveltekit/remote — SvelteKit Remote Functionsimport { AIRemote } from "@aibind/sveltekit/remote";
Requires
@sveltejs/kit ^2.53.
new AIRemote(model)Wraps SvelteKit's remote functions with AI SDK.
// src/lib/ai.server.ts
import { AIRemote } from "@aibind/sveltekit/remote";
export const ai = new AIRemote(anthropic("claude-sonnet-4-20250514"));
ai.query(schema, promptFn) — Text response// src/routes/api/summarize.remote.ts
import { ai } from "$lib/ai.server";
import { z } from "zod";
export const summarize = ai.query(
z.string(),
(text) => `Summarize this: ${text}`,
);
ai.structuredQuery({ input, output, prompt }) — Typed responseexport const analyze = ai.structuredQuery({
input: z.string(),
output: z.object({
sentiment: z.enum(["positive", "negative", "neutral"]),
confidence: z.number(),
}),
prompt: (text) => `Analyze: ${text}`,
system: "Return JSON matching the output schema.",
});
ai.command(schema, handler) — Mutationsexport const generatePost = ai.command(
z.object({ topic: z.string() }),
async (input, { model }) => {
const result = await generateText({
model,
prompt: `Write about ${input.topic}`,
});
await db.posts.create({ content: result.text });
return { id: post.id };
},
);
@aibind/sveltekit/agent — Client Agentimport { Agent } from "@aibind/sveltekit/agent";
new Agent(options?)Reactive agent state. Endpoint defaults to /api/__aibind__/agent.
<script lang="ts">
import { Agent } from '@aibind/sveltekit/agent';
const agent = new Agent();
let prompt = $state('');
</script>
<form onsubmit={(e) => { e.preventDefault(); agent.send(prompt); prompt = ''; }}>
<input bind:value={prompt} />
<button disabled={agent.status === 'running'}>Send</button>
</form>
{#each agent.messages as message (message.id)}
<div class={message.role}>{message.content}</div>
{/each}
{#if agent.status === 'running'}
<button onclick={() => agent.stop()}>Stop</button>
{/if}
Reactive properties:
messages — array of { id, role, content, type } messagesstatus — 'idle' | 'running' | 'awaiting-approval' | 'error'error — Error | nullpendingApproval — { id, toolName, args } | nullMethods:
send(prompt) — send a message, streams response incrementallystop() — abort the current requestapprove(id) / deny(id) — respond to tool approval requests@aibind/sveltekit/markdown — Streaming Markdownimport { StreamMarkdown } from "@aibind/sveltekit/markdown";
Renders streaming markdown with recovery for unterminated syntax. Uses @aibind/markdown under the hood.
<script lang="ts">
import { Stream } from '@aibind/sveltekit';
import { StreamMarkdown } from '@aibind/sveltekit/markdown';
const stream = new Stream({ system: 'You are a helpful assistant.' });
</script>
<StreamMarkdown text={stream.text} streaming={stream.loading} />
Props:
text — markdown string to renderstreaming — when true, applies markdown recovery (closes unterminated bold, code blocks, etc.)class — optional CSS class@aibind/sveltekit/history — Branching Conversation Historyimport {
ReactiveChatHistory,
ReactiveMessageTree,
ChatHistory,
MessageTree,
} from "@aibind/sveltekit/history";
Tree-structured conversation history with branching support. Edit messages, regenerate responses, and navigate alternatives (ChatGPT-style).
<script lang="ts">
import { ReactiveChatHistory } from '@aibind/sveltekit/history';
const chat = new ReactiveChatHistory<{ role: string; content: string }>();
chat.append({ role: 'user', content: 'Hello' });
chat.append({ role: 'assistant', content: 'Hi!' });
</script>
{#each chat.messages as msg, i}
<div>{msg.role}: {msg.content}</div>
{#if chat.hasAlternatives(chat.nodeIds[i])}
<button onclick={() => chat.prevAlternative(chat.nodeIds[i])}>←</button>
{chat.alternativeIndex(chat.nodeIds[i]) + 1}/{chat.alternativeCount(chat.nodeIds[i])}
<button onclick={() => chat.nextAlternative(chat.nodeIds[i])}>→</button>
{/if}
{/each}
See @aibind/core README for full API documentation.
MIT
FAQs
AI SDK bindings for SvelteKit — streaming, structured output, agents, server handlers, and remote functions
The npm package @aibind/sveltekit receives a total of 0 weekly downloads. As such, @aibind/sveltekit popularity was classified as not popular.
We found that @aibind/sveltekit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Company News
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.

Research
/Security News
A malicious Firefox extension fetches its payload after installation to evade detection, steal Google session cookies, and automate account takeover.