Skip to content

AI

@delightstack/ai adds AI to SvelteKit apps on Cloudflare Workers — chat completions, resumable streaming, vector embeddings, and tool calling, routed through Cloudflare AI Gateway and integrated with the database and realtime layers.

  • Chat completions — streaming and non-streaming via AI Gateway (Workers AI @cf/ models, OpenAI, Anthropic, or any provider behind the gateway).
  • Resumable streaming — chunks buffer in the DO and broadcast over WebSocket; clients resume from their last offset after reconnect, with no lost tokens.
  • Vector embeddings — alarm-based async pipeline with change detection; embeddings generate automatically on create/update.
  • Tool calling — OpenAI-compatible function calling with streaming delta merging.
  • Reactive AiClient — Svelte 5 runes for streaming content, usage, errors, and tool calls.
Terminal window
pnpm add @delightstack/ai
ImportUse
@delightstack/ai/serveraiProcessing, createAiHandle, createAiMessageHandler
@delightstack/ai/clientAiClient — reactive Svelte 5 client
@delightstack/ai/schemadefineAiTable, defineAiConversationTable

It builds on database and websocket, and needs an AI binding (Cloudflare AI Gateway) in wrangler.toml.

import { defineAiTable } from '@delightstack/ai/schema';
// extends a database table with embedding + embedding_status fields
const articleTable = defineAiTable('article', (schema) => ({
title: schema.string().searchable(),
body: schema.string(),
}), { dimensions: 1024 });
hooks.server.ts
import { createAiHandle } from '@delightstack/ai/server';
export const aiHandle = createAiHandle({
getAi: (event) => event.platform.env.AI,
// exposes /api/ai/complete, /api/ai/stream, /api/ai/embed, /api/ai/cancel
});

createAiMessageHandler() wires resume/cancel messages into your WebSocket server so streams survive page transitions and network drops.

<script>
import { AiClient } from '@delightstack/ai/client';
const ai = new AiClient();
async function ask() {
await ai.chat({ messages: [{ role: 'user', content: 'Hello!' }] });
}
</script>
<button onclick={ask}>Ask</button>
<p>{ai.content}</p>

ai.chat() streams over WebSocket (resumable); ai.complete() returns a full result over HTTP.