@langchain/svelte 0.4.7 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -443
- package/dist/context.cjs +72 -0
- package/dist/context.cjs.map +1 -0
- package/dist/context.d.cts +72 -0
- package/dist/context.d.cts.map +1 -0
- package/dist/context.d.ts +72 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +70 -0
- package/dist/context.js.map +1 -0
- package/dist/index.cjs +32 -316
- package/dist/index.d.cts +11 -97
- package/dist/index.d.ts +11 -97
- package/dist/index.js +10 -290
- package/dist/selectors.svelte.cjs +214 -0
- package/dist/selectors.svelte.cjs.map +1 -0
- package/dist/selectors.svelte.d.cts +146 -0
- package/dist/selectors.svelte.d.cts.map +1 -0
- package/dist/selectors.svelte.d.ts +146 -0
- package/dist/selectors.svelte.d.ts.map +1 -0
- package/dist/selectors.svelte.js +204 -0
- package/dist/selectors.svelte.js.map +1 -0
- package/dist/use-audio-player.svelte.cjs +608 -0
- package/dist/use-audio-player.svelte.cjs.map +1 -0
- package/dist/use-audio-player.svelte.d.cts +70 -0
- package/dist/use-audio-player.svelte.d.cts.map +1 -0
- package/dist/use-audio-player.svelte.d.ts +70 -0
- package/dist/use-audio-player.svelte.d.ts.map +1 -0
- package/dist/use-audio-player.svelte.js +608 -0
- package/dist/use-audio-player.svelte.js.map +1 -0
- package/dist/use-media-url.svelte.cjs +54 -0
- package/dist/use-media-url.svelte.cjs.map +1 -0
- package/dist/use-media-url.svelte.d.cts +29 -0
- package/dist/use-media-url.svelte.d.cts.map +1 -0
- package/dist/use-media-url.svelte.d.ts +29 -0
- package/dist/use-media-url.svelte.d.ts.map +1 -0
- package/dist/use-media-url.svelte.js +54 -0
- package/dist/use-media-url.svelte.js.map +1 -0
- package/dist/use-projection.svelte.cjs +62 -0
- package/dist/use-projection.svelte.cjs.map +1 -0
- package/dist/use-projection.svelte.d.cts +65 -0
- package/dist/use-projection.svelte.d.cts.map +1 -0
- package/dist/use-projection.svelte.d.ts +65 -0
- package/dist/use-projection.svelte.d.ts.map +1 -0
- package/dist/use-projection.svelte.js +62 -0
- package/dist/use-projection.svelte.js.map +1 -0
- package/dist/use-stream.svelte.cjs +193 -0
- package/dist/use-stream.svelte.cjs.map +1 -0
- package/dist/use-stream.svelte.d.cts +116 -0
- package/dist/use-stream.svelte.d.cts.map +1 -0
- package/dist/use-stream.svelte.d.ts +116 -0
- package/dist/use-stream.svelte.d.ts.map +1 -0
- package/dist/use-stream.svelte.js +191 -0
- package/dist/use-stream.svelte.js.map +1 -0
- package/dist/use-video-player.svelte.cjs +233 -0
- package/dist/use-video-player.svelte.cjs.map +1 -0
- package/dist/use-video-player.svelte.d.cts +66 -0
- package/dist/use-video-player.svelte.d.cts.map +1 -0
- package/dist/use-video-player.svelte.d.ts +66 -0
- package/dist/use-video-player.svelte.d.ts.map +1 -0
- package/dist/use-video-player.svelte.js +233 -0
- package/dist/use-video-player.svelte.js.map +1 -0
- package/package.json +9 -8
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/stream.custom.cjs +0 -122
- package/dist/stream.custom.cjs.map +0 -1
- package/dist/stream.custom.js +0 -122
- package/dist/stream.custom.js.map +0 -1
- package/dist/subagents.cjs +0 -81
- package/dist/subagents.cjs.map +0 -1
- package/dist/subagents.js +0 -81
- package/dist/subagents.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @langchain/svelte
|
|
2
2
|
|
|
3
|
-
Svelte SDK for
|
|
3
|
+
Svelte 5 SDK for [Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview), [LangChain](https://docs.langchain.com/oss/javascript/langchain/overview) and [LangGraph](https://docs.langchain.com/oss/javascript/langgraph/overview).
|
|
4
|
+
|
|
5
|
+
`useStream` binds a LangGraph agent into a Svelte 5 component. Reactive fields are exposed as getters on a stable handle (`stream.messages`, `stream.isLoading`, …) so templates and `$derived` expressions track updates automatically — no stores, no `$` prefix, no destructuring.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -8,157 +10,9 @@ Svelte SDK for building AI-powered applications with [Deep Agents](https://docs.
|
|
|
8
10
|
npm install @langchain/svelte @langchain/core
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
**Peer dependencies:** `svelte`
|
|
12
|
-
|
|
13
|
-
## Quick Start
|
|
14
|
-
|
|
15
|
-
```svelte
|
|
16
|
-
<script lang="ts">
|
|
17
|
-
import { useStream } from "@langchain/svelte";
|
|
18
|
-
|
|
19
|
-
const stream = useStream({
|
|
20
|
-
assistantId: "agent",
|
|
21
|
-
apiUrl: "http://localhost:2024",
|
|
22
|
-
});
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<div>
|
|
26
|
-
{#each stream.messages as msg, i (msg.id ?? i)}
|
|
27
|
-
<div>{msg.content}</div>
|
|
28
|
-
{/each}
|
|
29
|
-
|
|
30
|
-
<button
|
|
31
|
-
disabled={stream.isLoading}
|
|
32
|
-
onclick={() =>
|
|
33
|
-
void stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
|
|
34
|
-
>
|
|
35
|
-
Send
|
|
36
|
-
</button>
|
|
37
|
-
</div>
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
All reactive properties (`messages`, `isLoading`, `values`, etc.) are accessed directly on the returned object — no `$` prefix needed. Avoid destructuring reactive properties; use `stream.messages` instead of `const { messages } = stream` to keep reactivity intact.
|
|
41
|
-
|
|
42
|
-
## `useStream` Options
|
|
43
|
-
|
|
44
|
-
| Option | Type | Description |
|
|
45
|
-
|---|---|---|
|
|
46
|
-
| `assistantId` | `string` | **Required.** The assistant/graph ID to stream from. |
|
|
47
|
-
| `apiUrl` | `string` | Base URL of the LangGraph API. |
|
|
48
|
-
| `client` | `Client` | Pre-configured `Client` instance (alternative to `apiUrl`). |
|
|
49
|
-
| `messagesKey` | `string` | State key containing messages. Defaults to `"messages"`. |
|
|
50
|
-
| `initialValues` | `StateType` | Initial state values before any stream data arrives. |
|
|
51
|
-
| `fetchStateHistory` | `boolean \| { limit: number }` | Fetch thread history on stream completion. Enables branching. |
|
|
52
|
-
| `throttle` | `boolean \| number` | Throttle state updates for performance. |
|
|
53
|
-
| `onFinish` | `(state, error?) => void` | Called when the stream completes. |
|
|
54
|
-
| `onError` | `(error, state?) => void` | Called on stream errors. |
|
|
55
|
-
| `onThreadId` | `(threadId) => void` | Called when a new thread is created. |
|
|
56
|
-
| `onUpdateEvent` | `(event) => void` | Receive update events from the stream. |
|
|
57
|
-
| `onCustomEvent` | `(event) => void` | Receive custom events from the stream. |
|
|
58
|
-
| `onStop` | `() => void` | Called when the stream is stopped by the user. |
|
|
59
|
-
|
|
60
|
-
## Return Values
|
|
61
|
-
|
|
62
|
-
All reactive properties are exposed as getters on the returned object. They update automatically and can be read directly in Svelte 5 templates without the `$` prefix.
|
|
63
|
-
|
|
64
|
-
| Property | Type | Description |
|
|
65
|
-
|---|---|---|
|
|
66
|
-
| `values` | `StateType` | Current graph state. |
|
|
67
|
-
| `messages` | `BaseMessage[]` | Messages from the current state. |
|
|
68
|
-
| `isLoading` | `boolean` | Whether a stream is currently active. |
|
|
69
|
-
| `error` | `unknown` | The most recent error, if any. |
|
|
70
|
-
| `interrupt` | `Interrupt \| undefined` | Current interrupt requiring user input. |
|
|
71
|
-
| `branch` | `string` | Active branch identifier. |
|
|
72
|
-
| `submit(values, options?)` | `function` | Submit new input to the graph. When called while a stream is active, the run is created on the server with `multitaskStrategy: "enqueue"` and queued automatically. |
|
|
73
|
-
| `stop()` | `function` | Cancel the active stream. |
|
|
74
|
-
| `setBranch(branch)` | `function` | Switch to a different conversation branch. |
|
|
75
|
-
| `getMessagesMetadata(msg, index?)` | `function` | Get branching and checkpoint metadata for a message. |
|
|
76
|
-
| `switchThread(id)` | `(id: string \| null) => void` | Switch to a different thread. Pass `null` to start a new thread on next submit. |
|
|
77
|
-
| `queue.entries` | `ReadonlyArray<QueueEntry>` | Pending server-side runs. Each entry has `id` (server run ID), `values`, `options`, and `createdAt`. |
|
|
78
|
-
| `queue.size` | `number` | Number of pending runs on the server. |
|
|
79
|
-
| `queue.cancel(id)` | `(id: string) => Promise<boolean>` | Cancel a pending run on the server by its run ID. |
|
|
80
|
-
| `queue.clear()` | `() => Promise<void>` | Cancel all pending runs on the server. |
|
|
81
|
-
|
|
82
|
-
## Type Safety
|
|
83
|
-
|
|
84
|
-
Provide your state type as a generic parameter:
|
|
85
|
-
|
|
86
|
-
```svelte
|
|
87
|
-
<script lang="ts">
|
|
88
|
-
import { useStream } from "@langchain/svelte";
|
|
89
|
-
import type { BaseMessage } from "langchain";
|
|
90
|
-
|
|
91
|
-
interface MyState {
|
|
92
|
-
messages: BaseMessage[];
|
|
93
|
-
context?: string;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const stream = useStream<MyState>({
|
|
97
|
-
assistantId: "my-graph",
|
|
98
|
-
apiUrl: "http://localhost:2024",
|
|
99
|
-
});
|
|
100
|
-
</script>
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### Typed Interrupts
|
|
104
|
-
|
|
105
|
-
```svelte
|
|
106
|
-
<script lang="ts">
|
|
107
|
-
import { useStream } from "@langchain/svelte";
|
|
108
|
-
import type { BaseMessage } from "langchain";
|
|
109
|
-
|
|
110
|
-
const stream = useStream<
|
|
111
|
-
{ messages: BaseMessage[] },
|
|
112
|
-
{ InterruptType: { question: string } }
|
|
113
|
-
>({
|
|
114
|
-
assistantId: "my-graph",
|
|
115
|
-
apiUrl: "http://localhost:2024",
|
|
116
|
-
});
|
|
117
|
-
</script>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Handling Interrupts
|
|
121
|
-
|
|
122
|
-
```svelte
|
|
123
|
-
<script lang="ts">
|
|
124
|
-
import { useStream } from "@langchain/svelte";
|
|
125
|
-
import type { BaseMessage } from "langchain";
|
|
126
|
-
|
|
127
|
-
const stream = useStream<
|
|
128
|
-
{ messages: BaseMessage[] },
|
|
129
|
-
{ InterruptType: { question: string } }
|
|
130
|
-
>({
|
|
131
|
-
assistantId: "agent",
|
|
132
|
-
apiUrl: "http://localhost:2024",
|
|
133
|
-
});
|
|
134
|
-
</script>
|
|
135
|
-
|
|
136
|
-
<div>
|
|
137
|
-
{#each stream.messages as msg, i (msg.id ?? i)}
|
|
138
|
-
<div>{msg.content}</div>
|
|
139
|
-
{/each}
|
|
140
|
-
|
|
141
|
-
{#if stream.interrupt}
|
|
142
|
-
<div>
|
|
143
|
-
<p>{stream.interrupt.value.question}</p>
|
|
144
|
-
<button onclick={() => void stream.submit(null, { command: { resume: "Approved" } })}>
|
|
145
|
-
Approve
|
|
146
|
-
</button>
|
|
147
|
-
</div>
|
|
148
|
-
{/if}
|
|
149
|
-
|
|
150
|
-
<button
|
|
151
|
-
onclick={() =>
|
|
152
|
-
void stream.submit({ messages: [{ type: "human", content: "Hello" }] })}
|
|
153
|
-
>
|
|
154
|
-
Send
|
|
155
|
-
</button>
|
|
156
|
-
</div>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## Branching
|
|
13
|
+
**Peer dependencies:** `svelte` ^5.0.0, `@langchain/core` ^1.0.1
|
|
160
14
|
|
|
161
|
-
|
|
15
|
+
## Quick start
|
|
162
16
|
|
|
163
17
|
```svelte
|
|
164
18
|
<script lang="ts">
|
|
@@ -167,316 +21,56 @@ Enable conversation branching with `fetchStateHistory: true`:
|
|
|
167
21
|
const stream = useStream({
|
|
168
22
|
assistantId: "agent",
|
|
169
23
|
apiUrl: "http://localhost:2024",
|
|
170
|
-
fetchStateHistory: true,
|
|
171
24
|
});
|
|
172
25
|
</script>
|
|
173
26
|
|
|
174
|
-
<div>
|
|
175
|
-
{#each stream.messages as msg, i (msg.id ?? i)}
|
|
176
|
-
{@const metadata = stream.getMessagesMetadata(msg, i)}
|
|
177
|
-
{@const branchOptions = metadata?.branchOptions}
|
|
178
|
-
{@const currentBranch = metadata?.branch}
|
|
179
|
-
|
|
180
|
-
<div>
|
|
181
|
-
<p>{msg.content}</p>
|
|
182
|
-
|
|
183
|
-
{#if branchOptions && currentBranch}
|
|
184
|
-
<button onclick={() => {
|
|
185
|
-
const prev = branchOptions[branchOptions.indexOf(currentBranch) - 1];
|
|
186
|
-
if (prev) stream.setBranch(prev);
|
|
187
|
-
}}>
|
|
188
|
-
Previous
|
|
189
|
-
</button>
|
|
190
|
-
<span>
|
|
191
|
-
{branchOptions.indexOf(currentBranch) + 1} / {branchOptions.length}
|
|
192
|
-
</span>
|
|
193
|
-
<button onclick={() => {
|
|
194
|
-
const next = branchOptions[branchOptions.indexOf(currentBranch) + 1];
|
|
195
|
-
if (next) stream.setBranch(next);
|
|
196
|
-
}}>
|
|
197
|
-
Next
|
|
198
|
-
</button>
|
|
199
|
-
{/if}
|
|
200
|
-
</div>
|
|
201
|
-
{/each}
|
|
202
|
-
|
|
203
|
-
<button
|
|
204
|
-
onclick={() =>
|
|
205
|
-
void stream.submit({ messages: [{ type: "human", content: "Hello" }] })}
|
|
206
|
-
>
|
|
207
|
-
Send
|
|
208
|
-
</button>
|
|
209
|
-
</div>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## Server-Side Queuing
|
|
213
|
-
|
|
214
|
-
When `submit()` is called while a stream is already active, the SDK automatically creates the run on the server with `multitaskStrategy: "enqueue"`. The pending runs are tracked in `queue` and processed in order as each finishes:
|
|
215
|
-
|
|
216
|
-
```svelte
|
|
217
|
-
<script lang="ts">
|
|
218
|
-
import { useStream } from "@langchain/svelte";
|
|
219
|
-
|
|
220
|
-
const stream = useStream({
|
|
221
|
-
assistantId: "agent",
|
|
222
|
-
apiUrl: "http://localhost:2024",
|
|
223
|
-
});
|
|
224
|
-
</script>
|
|
225
|
-
|
|
226
|
-
<div>
|
|
227
|
-
{#each stream.messages as msg, i (msg.id ?? i)}
|
|
228
|
-
<div>{msg.content}</div>
|
|
229
|
-
{/each}
|
|
230
|
-
|
|
231
|
-
{#if stream.queue.size > 0}
|
|
232
|
-
<div>
|
|
233
|
-
<p>{stream.queue.size} message(s) queued</p>
|
|
234
|
-
<button onclick={() => void stream.queue.clear()}>Clear Queue</button>
|
|
235
|
-
</div>
|
|
236
|
-
{/if}
|
|
237
|
-
|
|
238
|
-
<button
|
|
239
|
-
disabled={stream.isLoading}
|
|
240
|
-
onclick={() =>
|
|
241
|
-
void stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
|
|
242
|
-
>
|
|
243
|
-
Send
|
|
244
|
-
</button>
|
|
245
|
-
<button onclick={() => stream.switchThread(null)}>New Thread</button>
|
|
246
|
-
</div>
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Switching threads via `switchThread()` cancels all pending runs and clears the queue.
|
|
250
|
-
|
|
251
|
-
## Stream Context
|
|
252
|
-
|
|
253
|
-
Use `setStreamContext` and `getStreamContext` to share a single `useStream` instance across a component tree without prop drilling. This uses Svelte's built-in `setContext` / `getContext` under the hood.
|
|
254
|
-
|
|
255
|
-
### Setting context in a parent
|
|
256
|
-
|
|
257
|
-
Call `setStreamContext` during component initialisation to provide the stream to all descendants:
|
|
258
|
-
|
|
259
|
-
```svelte
|
|
260
|
-
<script lang="ts">
|
|
261
|
-
import { useStream, setStreamContext } from "@langchain/svelte";
|
|
262
|
-
import ChatMessages from "./ChatMessages.svelte";
|
|
263
|
-
import ChatInput from "./ChatInput.svelte";
|
|
264
|
-
|
|
265
|
-
const stream = useStream({
|
|
266
|
-
assistantId: "agent",
|
|
267
|
-
apiUrl: "http://localhost:2024",
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
setStreamContext(stream);
|
|
271
|
-
</script>
|
|
272
|
-
|
|
273
|
-
<ChatMessages />
|
|
274
|
-
<ChatInput />
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Consuming context in a child
|
|
278
|
-
|
|
279
|
-
Call `getStreamContext` in any descendant to retrieve the stream. The returned value has the same shape and types as the `useStream` return value:
|
|
280
|
-
|
|
281
|
-
```svelte
|
|
282
|
-
<script lang="ts">
|
|
283
|
-
import { getStreamContext } from "@langchain/svelte";
|
|
284
|
-
|
|
285
|
-
const stream = getStreamContext();
|
|
286
|
-
</script>
|
|
287
|
-
|
|
288
|
-
{#each stream.messages as msg, i (msg.id ?? i)}
|
|
289
|
-
<div>{msg.content}</div>
|
|
290
|
-
{/each}
|
|
291
|
-
|
|
292
|
-
{#if stream.isLoading}
|
|
293
|
-
<p>Thinking…</p>
|
|
294
|
-
{/if}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
```svelte
|
|
298
|
-
<script lang="ts">
|
|
299
|
-
import { getStreamContext } from "@langchain/svelte";
|
|
300
|
-
|
|
301
|
-
const stream = getStreamContext();
|
|
302
|
-
|
|
303
|
-
let input = $state("");
|
|
304
|
-
</script>
|
|
305
|
-
|
|
306
|
-
<form onsubmit={(e) => { e.preventDefault(); void stream.submit({ messages: [{ type: "human", content: input }] }); input = ""; }}>
|
|
307
|
-
<input bind:value={input} />
|
|
308
|
-
<button type="submit">Send</button>
|
|
309
|
-
</form>
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### Type safety
|
|
313
|
-
|
|
314
|
-
`getStreamContext` accepts the same generic parameters as `useStream` so child components can be fully typed:
|
|
315
|
-
|
|
316
|
-
```svelte
|
|
317
|
-
<script lang="ts">
|
|
318
|
-
import { getStreamContext } from "@langchain/svelte";
|
|
319
|
-
import type { BaseMessage } from "@langchain/core/messages";
|
|
320
|
-
|
|
321
|
-
interface MyState {
|
|
322
|
-
messages: BaseMessage[];
|
|
323
|
-
context?: string;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
const stream = getStreamContext<MyState>();
|
|
327
|
-
</script>
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
`setStreamContext` returns the stream it was given, so you can inline both calls:
|
|
331
|
-
|
|
332
|
-
```svelte
|
|
333
|
-
<script lang="ts">
|
|
334
|
-
import { useStream, setStreamContext } from "@langchain/svelte";
|
|
335
|
-
|
|
336
|
-
const stream = setStreamContext(
|
|
337
|
-
useStream({ assistantId: "agent", apiUrl: "http://localhost:2024" }),
|
|
338
|
-
);
|
|
339
|
-
</script>
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
> **Note:** Both functions must be called during component initialisation (i.e. at the top level of a `<script>` block), just like Svelte's own `setContext` / `getContext`. Calling `getStreamContext` without a parent `setStreamContext` throws an error.
|
|
343
|
-
|
|
344
|
-
## Custom Transport
|
|
345
|
-
|
|
346
|
-
Instead of connecting to a LangGraph API, you can provide your own streaming transport. Pass a `transport` object instead of `assistantId` to use a custom backend:
|
|
347
|
-
|
|
348
|
-
```svelte
|
|
349
|
-
<script lang="ts">
|
|
350
|
-
import { useStream, FetchStreamTransport } from "@langchain/svelte";
|
|
351
|
-
import type { BaseMessage } from "langchain";
|
|
352
|
-
|
|
353
|
-
const stream = useStream<{ messages: BaseMessage[] }>({
|
|
354
|
-
transport: new FetchStreamTransport({
|
|
355
|
-
url: "https://my-api.example.com/stream",
|
|
356
|
-
}),
|
|
357
|
-
threadId: null,
|
|
358
|
-
onThreadId: (id) => console.log("Thread created:", id),
|
|
359
|
-
});
|
|
360
|
-
</script>
|
|
361
|
-
|
|
362
|
-
<div>
|
|
363
|
-
{#each stream.messages as msg, i (msg.id ?? i)}
|
|
364
|
-
{@const metadata = stream.getMessagesMetadata(msg, i)}
|
|
365
|
-
<div>
|
|
366
|
-
<p>{msg.content}</p>
|
|
367
|
-
{#if metadata?.streamMetadata}
|
|
368
|
-
<span>Node: {metadata.streamMetadata.langgraph_node}</span>
|
|
369
|
-
{/if}
|
|
370
|
-
</div>
|
|
371
|
-
{/each}
|
|
372
|
-
|
|
373
|
-
<p>Current branch: {stream.branch}</p>
|
|
374
|
-
|
|
375
|
-
<button
|
|
376
|
-
disabled={stream.isLoading}
|
|
377
|
-
onclick={() =>
|
|
378
|
-
void stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
|
|
379
|
-
>
|
|
380
|
-
Send
|
|
381
|
-
</button>
|
|
382
|
-
</div>
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
The custom transport interface returns the same properties as the standard `useStream` function, including `getMessagesMetadata`, `branch`, `setBranch`, `switchThread`, and all message/interrupt/subagent helpers. When using a custom transport, `getMessagesMetadata` returns stream metadata sent alongside messages during streaming; `branch` and `setBranch` provide local branch state management. `onFinish` is also supported and receives a synthetic `ThreadState` built from the final locally streamed values; the run metadata argument is `undefined`.
|
|
386
|
-
|
|
387
|
-
## Sharing State with `provideStream`
|
|
388
|
-
|
|
389
|
-
When multiple components need access to the same stream (a message list, a header, an input bar), use `provideStream` and `getStream` to share a single stream instance via Svelte's context API:
|
|
390
|
-
|
|
391
|
-
```svelte
|
|
392
|
-
<!-- ChatContainer.svelte -->
|
|
393
|
-
<script lang="ts">
|
|
394
|
-
import { provideStream } from "@langchain/svelte";
|
|
395
|
-
import ChatHeader from "./ChatHeader.svelte";
|
|
396
|
-
import MessageList from "./MessageList.svelte";
|
|
397
|
-
import MessageInput from "./MessageInput.svelte";
|
|
398
|
-
|
|
399
|
-
provideStream({
|
|
400
|
-
assistantId: "agent",
|
|
401
|
-
apiUrl: "http://localhost:2024",
|
|
402
|
-
});
|
|
403
|
-
</script>
|
|
404
|
-
|
|
405
|
-
<ChatHeader />
|
|
406
|
-
<MessageList />
|
|
407
|
-
<MessageInput />
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
```svelte
|
|
411
|
-
<!-- MessageList.svelte -->
|
|
412
|
-
<script lang="ts">
|
|
413
|
-
import { getStream } from "@langchain/svelte";
|
|
414
|
-
|
|
415
|
-
const stream = getStream();
|
|
416
|
-
</script>
|
|
417
|
-
|
|
418
27
|
{#each stream.messages as msg (msg.id)}
|
|
419
28
|
<div>{msg.content}</div>
|
|
420
29
|
{/each}
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
```svelte
|
|
424
|
-
<!-- MessageInput.svelte -->
|
|
425
|
-
<script lang="ts">
|
|
426
|
-
import { getStream } from "@langchain/svelte";
|
|
427
|
-
|
|
428
|
-
const stream = getStream();
|
|
429
|
-
let input = $state("");
|
|
430
30
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
<textarea bind:value={input}></textarea>
|
|
439
|
-
<button disabled={stream.isLoading} type="submit">Send</button>
|
|
440
|
-
</form>
|
|
31
|
+
<button
|
|
32
|
+
disabled={stream.isLoading}
|
|
33
|
+
onclick={() =>
|
|
34
|
+
stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
|
|
35
|
+
>
|
|
36
|
+
Send
|
|
37
|
+
</button>
|
|
441
38
|
```
|
|
442
39
|
|
|
443
|
-
|
|
444
|
-
<!-- ChatHeader.svelte -->
|
|
445
|
-
<script lang="ts">
|
|
446
|
-
import { getStream } from "@langchain/svelte";
|
|
40
|
+
> **Note:** Access fields through the live `stream` handle. Destructuring (`const { messages } = stream`) freezes the values at that moment — use `stream.messages` in templates instead.
|
|
447
41
|
|
|
448
|
-
|
|
449
|
-
</script>
|
|
42
|
+
## Highlights
|
|
450
43
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
</header>
|
|
460
|
-
```
|
|
44
|
+
- **v2-native streaming protocol.** Session-based transport with automatic re-attach on remount; no more `reconnectOnMount` / `joinStream` dance.
|
|
45
|
+
- **Always-on root projections.** `values`, `messages`, `toolCalls`, and `interrupts` are reactive at the root with zero extra subscription cost.
|
|
46
|
+
- **Selector composables for scoped data.** Per-subagent / per-subgraph messages, tool calls, and media stream only when a component actually mounts the matching composable, and release on unmount.
|
|
47
|
+
- **Discriminated option bag.** The hosted Agent Server path and the custom-adapter path are two arms of a single typed union — mixing them is a compile-time error.
|
|
48
|
+
- **Reactive `threadId`.** Pass `threadId: () => active` to drive in-place thread swaps without remounting.
|
|
49
|
+
- **Agent-brand type inference.** `useStream<typeof agent>()` unwraps state, tool calls, and subagent state maps from an agent brand.
|
|
50
|
+
- **Multimodal media streams.** Built-in assembly for audio, images, video, and files — plus opinionated playback helpers.
|
|
51
|
+
- **Headless tools.** Register local tool implementations that auto-resolve server-emitted tool-call interrupts without a round-trip through the UI.
|
|
461
52
|
|
|
462
|
-
|
|
53
|
+
## Documentation
|
|
463
54
|
|
|
464
|
-
|
|
55
|
+
In-depth guides live in [`docs/`](./docs/):
|
|
465
56
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
57
|
+
- [`useStream` — options, return shape, reactive `threadId`](./docs/use-stream.md)
|
|
58
|
+
- [Selector composables (`useMessages`, `useToolCalls`, `useValues`, …)](./docs/selector-composables.md)
|
|
59
|
+
- [Interrupts, `respond()`, `stop()`, `hydrationPromise`](./docs/interrupts.md)
|
|
60
|
+
- [Submission queue](./docs/submission-queue.md)
|
|
61
|
+
- [Stream context (`provideStream` / `getStream`)](./docs/stream-context.md)
|
|
62
|
+
- [Headless tools](./docs/headless-tools.md)
|
|
63
|
+
- [Custom transport (`AgentServerAdapter`, `HttpAgentServerAdapter`)](./docs/custom-transport.md)
|
|
64
|
+
- [Media (images, audio, video, files) & playback helpers](./docs/media.md)
|
|
65
|
+
- [Type safety](./docs/type-safety.md)
|
|
472
66
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
67
|
+
## Migrating from v0
|
|
68
|
+
|
|
69
|
+
`@langchain/svelte` **v1** targets the v2 streaming protocol. The `useStream` import stays the same, but the option bag, return shape, and how you subscribe to scoped data all change. Most chat apps migrate in well under an hour — the full guide with line-by-line diffs lives in [`docs/v1-migration.md`](./docs/v1-migration.md).
|
|
476
70
|
|
|
477
71
|
## Playground
|
|
478
72
|
|
|
479
|
-
For
|
|
73
|
+
For full end-to-end examples, see the [LangChain UI Playground](https://docs.langchain.com/playground).
|
|
480
74
|
|
|
481
75
|
## License
|
|
482
76
|
|
package/dist/context.cjs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const require_use_stream_svelte = require("./use-stream.svelte.cjs");
|
|
2
|
+
let svelte = require("svelte");
|
|
3
|
+
//#region src/context.ts
|
|
4
|
+
/**
|
|
5
|
+
* Context key used for the shared stream handle exposed via
|
|
6
|
+
* {@link provideStream}. Exported so advanced callers can drive
|
|
7
|
+
* Svelte's context API directly (e.g. a shared context in a
|
|
8
|
+
* microfrontend shell).
|
|
9
|
+
*/
|
|
10
|
+
const STREAM_CONTEXT_KEY = Symbol.for("@langchain/svelte/stream-context");
|
|
11
|
+
/**
|
|
12
|
+
* Creates a shared {@link useStream} handle and publishes it via
|
|
13
|
+
* Svelte's `setContext`. Descendant components read it via
|
|
14
|
+
* {@link getStream}.
|
|
15
|
+
*
|
|
16
|
+
* Must be called during component initialisation (the top level of a
|
|
17
|
+
* `<script>` block or `<script module>` that runs at mount), same
|
|
18
|
+
* lifecycle constraint as `setContext`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```svelte
|
|
22
|
+
* <!-- ChatContainer.svelte -->
|
|
23
|
+
* <script lang="ts">
|
|
24
|
+
* import { provideStream } from "@langchain/svelte";
|
|
25
|
+
*
|
|
26
|
+
* provideStream({
|
|
27
|
+
* assistantId: "agent",
|
|
28
|
+
* apiUrl: "http://localhost:2024",
|
|
29
|
+
* });
|
|
30
|
+
* <\/script>
|
|
31
|
+
*
|
|
32
|
+
* <ChatHeader />
|
|
33
|
+
* <MessageList />
|
|
34
|
+
* <MessageInput />
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function provideStream(options) {
|
|
38
|
+
const stream = require_use_stream_svelte.useStream(options);
|
|
39
|
+
(0, svelte.setContext)(STREAM_CONTEXT_KEY, stream);
|
|
40
|
+
return stream;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Reads the shared stream handle exposed by the nearest ancestor
|
|
44
|
+
* {@link provideStream} call. Throws when no ancestor has provided
|
|
45
|
+
* one.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```svelte
|
|
49
|
+
* <!-- MessageList.svelte -->
|
|
50
|
+
* <script lang="ts">
|
|
51
|
+
* import { getStream } from "@langchain/svelte";
|
|
52
|
+
* import type { agent } from "./agent";
|
|
53
|
+
*
|
|
54
|
+
* const stream = getStream<typeof agent>();
|
|
55
|
+
* <\/script>
|
|
56
|
+
*
|
|
57
|
+
* {#each stream.messages as msg (msg.id)}
|
|
58
|
+
* <div>{msg.content}</div>
|
|
59
|
+
* {/each}
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
function getStream() {
|
|
63
|
+
const context = (0, svelte.getContext)(STREAM_CONTEXT_KEY);
|
|
64
|
+
if (context == null) throw new Error("getStream() requires a parent component to call provideStream(). Add provideStream({ assistantId: '...' }) in an ancestor component.");
|
|
65
|
+
return context;
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
exports.STREAM_CONTEXT_KEY = STREAM_CONTEXT_KEY;
|
|
69
|
+
exports.getStream = getStream;
|
|
70
|
+
exports.provideStream = provideStream;
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=context.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.cjs","names":["useStream"],"sources":["../src/context.ts"],"sourcesContent":["import { getContext, setContext } from \"svelte\";\nimport type { InferStateType } from \"@langchain/langgraph-sdk/stream\";\nimport {\n useStream,\n type AgentServerOptions,\n type CustomAdapterOptions,\n type UseStreamOptions,\n type UseStreamReturn,\n} from \"./use-stream.svelte.js\";\n\n/**\n * Context key used for the shared stream handle exposed via\n * {@link provideStream}. Exported so advanced callers can drive\n * Svelte's context API directly (e.g. a shared context in a\n * microfrontend shell).\n */\nexport const STREAM_CONTEXT_KEY: unique symbol = Symbol.for(\n \"@langchain/svelte/stream-context\"\n);\n\n/**\n * Props for {@link provideStream} when talking to the default\n * LangGraph-Platform agent server.\n */\nexport type ProvideStreamProps<T = Record<string, unknown>> =\n AgentServerOptions<InferStateType<T>>;\n\n/**\n * Props for {@link provideStream} when wiring a custom\n * {@link AgentServerAdapter}.\n */\nexport type ProvideStreamCustomProps<T = Record<string, unknown>> =\n CustomAdapterOptions<InferStateType<T>>;\n\n/**\n * Creates a shared {@link useStream} handle and publishes it via\n * Svelte's `setContext`. Descendant components read it via\n * {@link getStream}.\n *\n * Must be called during component initialisation (the top level of a\n * `<script>` block or `<script module>` that runs at mount), same\n * lifecycle constraint as `setContext`.\n *\n * @example\n * ```svelte\n * <!-- ChatContainer.svelte -->\n * <script lang=\"ts\">\n * import { provideStream } from \"@langchain/svelte\";\n *\n * provideStream({\n * assistantId: \"agent\",\n * apiUrl: \"http://localhost:2024\",\n * });\n * </script>\n *\n * <ChatHeader />\n * <MessageList />\n * <MessageInput />\n * ```\n */\nexport function provideStream<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n>(\n options: ProvideStreamProps<T> | ProvideStreamCustomProps<T>\n): UseStreamReturn<T, InterruptType, ConfigurableType> {\n const stream = useStream<T, InterruptType, ConfigurableType>(\n options as UseStreamOptions<InferStateType<T>>\n );\n setContext(STREAM_CONTEXT_KEY, stream);\n return stream;\n}\n\n/**\n * Reads the shared stream handle exposed by the nearest ancestor\n * {@link provideStream} call. Throws when no ancestor has provided\n * one.\n *\n * @example\n * ```svelte\n * <!-- MessageList.svelte -->\n * <script lang=\"ts\">\n * import { getStream } from \"@langchain/svelte\";\n * import type { agent } from \"./agent\";\n *\n * const stream = getStream<typeof agent>();\n * </script>\n *\n * {#each stream.messages as msg (msg.id)}\n * <div>{msg.content}</div>\n * {/each}\n * ```\n */\nexport function getStream<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n>(): UseStreamReturn<T, InterruptType, ConfigurableType> {\n const context = getContext<\n UseStreamReturn<T, InterruptType, ConfigurableType> | undefined\n >(STREAM_CONTEXT_KEY);\n if (context == null) {\n throw new Error(\n \"getStream() requires a parent component to call provideStream(). \" +\n \"Add provideStream({ assistantId: '...' }) in an ancestor component.\"\n );\n }\n return context;\n}\n"],"mappings":";;;;;;;;;AAgBA,MAAa,qBAAoC,OAAO,IACtD,mCACD;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CD,SAAgB,cAKd,SACqD;CACrD,MAAM,SAASA,0BAAAA,UACb,QACD;AACD,EAAA,GAAA,OAAA,YAAW,oBAAoB,OAAO;AACtC,QAAO;;;;;;;;;;;;;;;;;;;;;;AAuBT,SAAgB,YAIyC;CACvD,MAAM,WAAA,GAAA,OAAA,YAEJ,mBAAmB;AACrB,KAAI,WAAW,KACb,OAAM,IAAI,MACR,uIAED;AAEH,QAAO"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AgentServerOptions as AgentServerOptions$1, CustomAdapterOptions as CustomAdapterOptions$1, UseStreamReturn } from "./use-stream.svelte.cjs";
|
|
2
|
+
import { InferStateType } from "@langchain/langgraph-sdk/stream";
|
|
3
|
+
|
|
4
|
+
//#region src/context.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Context key used for the shared stream handle exposed via
|
|
7
|
+
* {@link provideStream}. Exported so advanced callers can drive
|
|
8
|
+
* Svelte's context API directly (e.g. a shared context in a
|
|
9
|
+
* microfrontend shell).
|
|
10
|
+
*/
|
|
11
|
+
declare const STREAM_CONTEXT_KEY: unique symbol;
|
|
12
|
+
/**
|
|
13
|
+
* Props for {@link provideStream} when talking to the default
|
|
14
|
+
* LangGraph-Platform agent server.
|
|
15
|
+
*/
|
|
16
|
+
type ProvideStreamProps<T = Record<string, unknown>> = AgentServerOptions$1<InferStateType<T>>;
|
|
17
|
+
/**
|
|
18
|
+
* Props for {@link provideStream} when wiring a custom
|
|
19
|
+
* {@link AgentServerAdapter}.
|
|
20
|
+
*/
|
|
21
|
+
type ProvideStreamCustomProps<T = Record<string, unknown>> = CustomAdapterOptions$1<InferStateType<T>>;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a shared {@link useStream} handle and publishes it via
|
|
24
|
+
* Svelte's `setContext`. Descendant components read it via
|
|
25
|
+
* {@link getStream}.
|
|
26
|
+
*
|
|
27
|
+
* Must be called during component initialisation (the top level of a
|
|
28
|
+
* `<script>` block or `<script module>` that runs at mount), same
|
|
29
|
+
* lifecycle constraint as `setContext`.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```svelte
|
|
33
|
+
* <!-- ChatContainer.svelte -->
|
|
34
|
+
* <script lang="ts">
|
|
35
|
+
* import { provideStream } from "@langchain/svelte";
|
|
36
|
+
*
|
|
37
|
+
* provideStream({
|
|
38
|
+
* assistantId: "agent",
|
|
39
|
+
* apiUrl: "http://localhost:2024",
|
|
40
|
+
* });
|
|
41
|
+
* </script>
|
|
42
|
+
*
|
|
43
|
+
* <ChatHeader />
|
|
44
|
+
* <MessageList />
|
|
45
|
+
* <MessageInput />
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function provideStream<T = Record<string, unknown>, InterruptType = unknown, ConfigurableType extends object = Record<string, unknown>>(options: ProvideStreamProps<T> | ProvideStreamCustomProps<T>): UseStreamReturn<T, InterruptType, ConfigurableType>;
|
|
49
|
+
/**
|
|
50
|
+
* Reads the shared stream handle exposed by the nearest ancestor
|
|
51
|
+
* {@link provideStream} call. Throws when no ancestor has provided
|
|
52
|
+
* one.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```svelte
|
|
56
|
+
* <!-- MessageList.svelte -->
|
|
57
|
+
* <script lang="ts">
|
|
58
|
+
* import { getStream } from "@langchain/svelte";
|
|
59
|
+
* import type { agent } from "./agent";
|
|
60
|
+
*
|
|
61
|
+
* const stream = getStream<typeof agent>();
|
|
62
|
+
* </script>
|
|
63
|
+
*
|
|
64
|
+
* {#each stream.messages as msg (msg.id)}
|
|
65
|
+
* <div>{msg.content}</div>
|
|
66
|
+
* {/each}
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function getStream<T = Record<string, unknown>, InterruptType = unknown, ConfigurableType extends object = Record<string, unknown>>(): UseStreamReturn<T, InterruptType, ConfigurableType>;
|
|
70
|
+
//#endregion
|
|
71
|
+
export { ProvideStreamCustomProps, ProvideStreamProps, STREAM_CONTEXT_KEY, getStream, provideStream };
|
|
72
|
+
//# sourceMappingURL=context.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.cts","names":[],"sources":["../src/context.ts"],"mappings":";;;;;;AAgBA;;;;cAAa,kBAAA;AAQb;;;;AAAA,KAAY,kBAAA,KAAuB,MAAA,qBACjC,oBAAA,CAAmB,cAAA,CAAe,CAAA;;;;;KAMxB,wBAAA,KAA6B,MAAA,qBACvC,sBAAA,CAAqB,cAAA,CAAe,CAAA;;;;;;;AADtC;;;;;;;;;;;;;;;;AA6BA;;;;iBAAgB,aAAA,KACV,MAAA,8EAE8B,MAAA,kBAAA,CAElC,OAAA,EAAS,kBAAA,CAAmB,CAAA,IAAK,wBAAA,CAAyB,CAAA,IACzD,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;;;;;;;;;;;;;;;;;;;;;iBA4BrB,SAAA,KACV,MAAA,8EAE8B,MAAA,kBAAA,CAAA,GAC/B,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA"}
|