@langchain/svelte 0.1.3 → 0.2.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @langchain/svelte
2
2
 
3
- Svelte SDK for building AI-powered applications with [LangChain](https://js.langchain.com/) and [LangGraph](https://langchain-ai.github.io/langgraphjs/). Provides a `useStream` function that manages streaming, state, branching, and interrupts using Svelte stores.
3
+ Svelte SDK for building AI-powered applications with [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). It provides a `useStream` function that manages streaming, state, branching, and interrupts with a Svelte 5 runes-compatible reactive API.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,7 +8,7 @@ Svelte SDK for building AI-powered applications with [LangChain](https://js.lang
8
8
  npm install @langchain/svelte @langchain/core
9
9
  ```
10
10
 
11
- **Peer dependencies:** `svelte` (^4.0.0 || ^5.0.0), `@langchain/core` (^1.0.1)
11
+ **Peer dependencies:** `svelte` (^5.0.0), `@langchain/core` (^1.0.1)
12
12
 
13
13
  ## Quick Start
14
14
 
@@ -16,27 +16,29 @@ npm install @langchain/svelte @langchain/core
16
16
  <script lang="ts">
17
17
  import { useStream } from "@langchain/svelte";
18
18
 
19
- const { messages, submit, isLoading } = useStream({
19
+ const stream = useStream({
20
20
  assistantId: "agent",
21
21
  apiUrl: "http://localhost:2024",
22
22
  });
23
23
  </script>
24
24
 
25
25
  <div>
26
- {#each $messages as msg, i (msg.id ?? i)}
26
+ {#each stream.messages as msg, i (msg.id ?? i)}
27
27
  <div>{msg.content}</div>
28
28
  {/each}
29
29
 
30
30
  <button
31
- disabled={$isLoading}
31
+ disabled={stream.isLoading}
32
32
  onclick={() =>
33
- void submit({ messages: [{ type: "human", content: "Hello!" }] })}
33
+ void stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
34
34
  >
35
35
  Send
36
36
  </button>
37
37
  </div>
38
38
  ```
39
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
+
40
42
  ## `useStream` Options
41
43
 
42
44
  | Option | Type | Description |
@@ -57,23 +59,23 @@ npm install @langchain/svelte @langchain/core
57
59
 
58
60
  ## Return Values
59
61
 
60
- Reactive properties are Svelte `writable` or `derived` stores. Access their values in templates with the `$` prefix.
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.
61
63
 
62
64
  | Property | Type | Description |
63
65
  |---|---|---|
64
- | `values` | `Readable<StateType>` | Current graph state. |
65
- | `messages` | `Readable<Message[]>` | Messages from the current state. |
66
- | `isLoading` | `Writable<boolean>` | Whether a stream is currently active. |
67
- | `error` | `Readable<unknown>` | The most recent error, if any. |
68
- | `interrupt` | `Readable<Interrupt \| undefined>` | Current interrupt requiring user input. |
69
- | `branch` | `Writable<string>` | Active branch identifier. |
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. |
70
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. |
71
73
  | `stop()` | `function` | Cancel the active stream. |
72
74
  | `setBranch(branch)` | `function` | Switch to a different conversation branch. |
73
75
  | `getMessagesMetadata(msg, index?)` | `function` | Get branching and checkpoint metadata for a message. |
74
76
  | `switchThread(id)` | `(id: string \| null) => void` | Switch to a different thread. Pass `null` to start a new thread on next submit. |
75
- | `queue.entries` | `Readable<ReadonlyArray<QueueEntry>>` | Pending server-side runs. Each entry has `id` (server run ID), `values`, `options`, and `createdAt`. |
76
- | `queue.size` | `Writable<number>` | Number of pending runs on the server. |
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. |
77
79
  | `queue.cancel(id)` | `(id: string) => Promise<boolean>` | Cancel a pending run on the server by its run ID. |
78
80
  | `queue.clear()` | `() => Promise<void>` | Cancel all pending runs on the server. |
79
81
 
@@ -91,7 +93,7 @@ Provide your state type as a generic parameter:
91
93
  context?: string;
92
94
  }
93
95
 
94
- const { messages, submit } = useStream<MyState>({
96
+ const stream = useStream<MyState>({
95
97
  assistantId: "my-graph",
96
98
  apiUrl: "http://localhost:2024",
97
99
  });
@@ -105,7 +107,7 @@ Provide your state type as a generic parameter:
105
107
  import { useStream } from "@langchain/svelte";
106
108
  import type { BaseMessage } from "langchain";
107
109
 
108
- const { interrupt, submit } = useStream<
110
+ const stream = useStream<
109
111
  { messages: BaseMessage[] },
110
112
  { InterruptType: { question: string } }
111
113
  >({
@@ -122,7 +124,7 @@ Provide your state type as a generic parameter:
122
124
  import { useStream } from "@langchain/svelte";
123
125
  import type { BaseMessage } from "langchain";
124
126
 
125
- const { messages, interrupt, submit } = useStream<
127
+ const stream = useStream<
126
128
  { messages: BaseMessage[] },
127
129
  { InterruptType: { question: string } }
128
130
  >({
@@ -132,14 +134,14 @@ Provide your state type as a generic parameter:
132
134
  </script>
133
135
 
134
136
  <div>
135
- {#each $messages as msg, i (msg.id ?? i)}
137
+ {#each stream.messages as msg, i (msg.id ?? i)}
136
138
  <div>{msg.content}</div>
137
139
  {/each}
138
140
 
139
- {#if $interrupt}
141
+ {#if stream.interrupt}
140
142
  <div>
141
- <p>{$interrupt.value.question}</p>
142
- <button onclick={() => void submit(null, { command: { resume: "Approved" } })}>
143
+ <p>{stream.interrupt.value.question}</p>
144
+ <button onclick={() => void stream.submit(null, { command: { resume: "Approved" } })}>
143
145
  Approve
144
146
  </button>
145
147
  </div>
@@ -147,7 +149,7 @@ Provide your state type as a generic parameter:
147
149
 
148
150
  <button
149
151
  onclick={() =>
150
- void submit({ messages: [{ type: "human", content: "Hello" }] })}
152
+ void stream.submit({ messages: [{ type: "human", content: "Hello" }] })}
151
153
  >
152
154
  Send
153
155
  </button>
@@ -162,7 +164,7 @@ Enable conversation branching with `fetchStateHistory: true`:
162
164
  <script lang="ts">
163
165
  import { useStream } from "@langchain/svelte";
164
166
 
165
- const { messages, submit, getMessagesMetadata, setBranch } = useStream({
167
+ const stream = useStream({
166
168
  assistantId: "agent",
167
169
  apiUrl: "http://localhost:2024",
168
170
  fetchStateHistory: true,
@@ -170,27 +172,27 @@ Enable conversation branching with `fetchStateHistory: true`:
170
172
  </script>
171
173
 
172
174
  <div>
173
- {#each $messages as msg, i (msg.id ?? i)}
174
- {@const metadata = getMessagesMetadata(msg, i)}
175
+ {#each stream.messages as msg, i (msg.id ?? i)}
176
+ {@const metadata = stream.getMessagesMetadata(msg, i)}
175
177
  {@const branchOptions = metadata?.branchOptions}
176
- {@const branch = metadata?.branch}
178
+ {@const currentBranch = metadata?.branch}
177
179
 
178
180
  <div>
179
181
  <p>{msg.content}</p>
180
182
 
181
- {#if branchOptions && branch}
183
+ {#if branchOptions && currentBranch}
182
184
  <button onclick={() => {
183
- const prev = branchOptions[branchOptions.indexOf(branch) - 1];
184
- if (prev) setBranch(prev);
185
+ const prev = branchOptions[branchOptions.indexOf(currentBranch) - 1];
186
+ if (prev) stream.setBranch(prev);
185
187
  }}>
186
188
  Previous
187
189
  </button>
188
190
  <span>
189
- {branchOptions.indexOf(branch) + 1} / {branchOptions.length}
191
+ {branchOptions.indexOf(currentBranch) + 1} / {branchOptions.length}
190
192
  </span>
191
193
  <button onclick={() => {
192
- const next = branchOptions[branchOptions.indexOf(branch) + 1];
193
- if (next) setBranch(next);
194
+ const next = branchOptions[branchOptions.indexOf(currentBranch) + 1];
195
+ if (next) stream.setBranch(next);
194
196
  }}>
195
197
  Next
196
198
  </button>
@@ -200,7 +202,7 @@ Enable conversation branching with `fetchStateHistory: true`:
200
202
 
201
203
  <button
202
204
  onclick={() =>
203
- void submit({ messages: [{ type: "human", content: "Hello" }] })}
205
+ void stream.submit({ messages: [{ type: "human", content: "Hello" }] })}
204
206
  >
205
207
  Send
206
208
  </button>
@@ -215,40 +217,130 @@ When `submit()` is called while a stream is already active, the SDK automaticall
215
217
  <script lang="ts">
216
218
  import { useStream } from "@langchain/svelte";
217
219
 
218
- const { messages, submit, isLoading, queue, switchThread } = useStream({
220
+ const stream = useStream({
219
221
  assistantId: "agent",
220
222
  apiUrl: "http://localhost:2024",
221
223
  });
222
-
223
- const queueSize = queue.size;
224
- const queueEntries = queue.entries;
225
224
  </script>
226
225
 
227
226
  <div>
228
- {#each $messages as msg, i (msg.id ?? i)}
227
+ {#each stream.messages as msg, i (msg.id ?? i)}
229
228
  <div>{msg.content}</div>
230
229
  {/each}
231
230
 
232
- {#if $queueSize > 0}
231
+ {#if stream.queue.size > 0}
233
232
  <div>
234
- <p>{$queueSize} message(s) queued</p>
235
- <button onclick={() => void queue.clear()}>Clear Queue</button>
233
+ <p>{stream.queue.size} message(s) queued</p>
234
+ <button onclick={() => void stream.queue.clear()}>Clear Queue</button>
236
235
  </div>
237
236
  {/if}
238
237
 
239
238
  <button
240
- disabled={$isLoading}
239
+ disabled={stream.isLoading}
241
240
  onclick={() =>
242
- void submit({ messages: [{ type: "human", content: "Hello!" }] })}
241
+ void stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
243
242
  >
244
243
  Send
245
244
  </button>
246
- <button onclick={() => switchThread(null)}>New Thread</button>
245
+ <button onclick={() => stream.switchThread(null)}>New Thread</button>
247
246
  </div>
248
247
  ```
249
248
 
250
249
  Switching threads via `switchThread()` cancels all pending runs and clears the queue.
251
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
+
252
344
  ## Custom Transport
253
345
 
254
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:
@@ -258,14 +350,7 @@ Instead of connecting to a LangGraph API, you can provide your own streaming tra
258
350
  import { useStream, FetchStreamTransport } from "@langchain/svelte";
259
351
  import type { BaseMessage } from "langchain";
260
352
 
261
- const {
262
- messages,
263
- submit,
264
- isLoading,
265
- branch,
266
- setBranch,
267
- getMessagesMetadata,
268
- } = useStream<{ messages: BaseMessage[] }>({
353
+ const stream = useStream<{ messages: BaseMessage[] }>({
269
354
  transport: new FetchStreamTransport({
270
355
  url: "https://my-api.example.com/stream",
271
356
  }),
@@ -275,8 +360,8 @@ Instead of connecting to a LangGraph API, you can provide your own streaming tra
275
360
  </script>
276
361
 
277
362
  <div>
278
- {#each $messages as msg, i (msg.id ?? i)}
279
- {@const metadata = getMessagesMetadata(msg, i)}
363
+ {#each stream.messages as msg, i (msg.id ?? i)}
364
+ {@const metadata = stream.getMessagesMetadata(msg, i)}
280
365
  <div>
281
366
  <p>{msg.content}</p>
282
367
  {#if metadata?.streamMetadata}
@@ -285,23 +370,113 @@ Instead of connecting to a LangGraph API, you can provide your own streaming tra
285
370
  </div>
286
371
  {/each}
287
372
 
288
- <p>Current branch: {$branch}</p>
373
+ <p>Current branch: {stream.branch}</p>
289
374
 
290
375
  <button
291
- disabled={$isLoading}
376
+ disabled={stream.isLoading}
292
377
  onclick={() =>
293
- void submit({ messages: [{ type: "human", content: "Hello!" }] })}
378
+ void stream.submit({ messages: [{ type: "human", content: "Hello!" }] })}
294
379
  >
295
380
  Send
296
381
  </button>
297
382
  </div>
298
383
  ```
299
384
 
300
- 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.
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
+ {#each stream.messages as msg (msg.id)}
419
+ <div>{msg.content}</div>
420
+ {/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
+
431
+ function send() {
432
+ stream.submit({ messages: [{ type: "human", content: input }] });
433
+ input = "";
434
+ }
435
+ </script>
436
+
437
+ <form onsubmit={send}>
438
+ <textarea bind:value={input}></textarea>
439
+ <button disabled={stream.isLoading} type="submit">Send</button>
440
+ </form>
441
+ ```
442
+
443
+ ```svelte
444
+ <!-- ChatHeader.svelte -->
445
+ <script lang="ts">
446
+ import { getStream } from "@langchain/svelte";
447
+
448
+ const stream = getStream();
449
+ </script>
450
+
451
+ <header>
452
+ <h1>Chat</h1>
453
+ {#if stream.isLoading}
454
+ <span>Thinking...</span>
455
+ {/if}
456
+ {#if stream.error}
457
+ <span>Error occurred</span>
458
+ {/if}
459
+ </header>
460
+ ```
461
+
462
+ ### Multiple Agents
463
+
464
+ Nest `provideStream` calls for multi-agent scenarios — Svelte's context scoping ensures each subtree gets its own stream:
465
+
466
+ ```svelte
467
+ <!-- ResearchPanel.svelte -->
468
+ <script lang="ts">
469
+ import { provideStream } from "@langchain/svelte";
470
+ provideStream({ assistantId: "researcher", apiUrl: "http://localhost:2024" });
471
+ </script>
472
+
473
+ <MessageList />
474
+ <MessageInput />
475
+ ```
301
476
 
302
477
  ## Playground
303
478
 
304
- For complete end-to-end examples with full agentic UIs, visit the [LangGraph Playground](https://github.com/langchain-ai/langgraphjs).
479
+ For complete end-to-end examples with full agentic UIs, visit the [LangChain UI Playground](https://docs.langchain.com/playground).
305
480
 
306
481
  ## License
307
482
 
@@ -0,0 +1,86 @@
1
+ const require_index = require("./index.cjs");
2
+ let svelte = require("svelte");
3
+ //#region src/context.ts
4
+ const STREAM_CONTEXT_KEY = Symbol("langchain-stream");
5
+ /**
6
+ * Creates a shared `useStream` instance and makes it available to all
7
+ * descendant components via Svelte's `setContext`/`getContext`.
8
+ *
9
+ * Call this in a parent component's `<script>` block. Children access
10
+ * the shared stream via `getStream()`.
11
+ *
12
+ * @example
13
+ * ```svelte
14
+ * <!-- ChatContainer.svelte -->
15
+ * <script lang="ts">
16
+ * import { provideStream } from "@langchain/svelte";
17
+ *
18
+ * provideStream({
19
+ * assistantId: "agent",
20
+ * apiUrl: "http://localhost:2024",
21
+ * });
22
+ * <\/script>
23
+ *
24
+ * <ChatHeader />
25
+ * <MessageList />
26
+ * <MessageInput />
27
+ * ```
28
+ *
29
+ * @returns The stream instance (same as calling `useStream` directly).
30
+ */
31
+ function provideStream(options) {
32
+ const stream = require_index.useStream(options);
33
+ (0, svelte.setContext)(STREAM_CONTEXT_KEY, stream);
34
+ return stream;
35
+ }
36
+ /**
37
+ * Retrieves the shared stream instance from the nearest ancestor that
38
+ * called `provideStream()`.
39
+ *
40
+ * Throws if no ancestor has provided a stream.
41
+ *
42
+ * @example
43
+ * ```svelte
44
+ * <!-- MessageList.svelte -->
45
+ * <script lang="ts">
46
+ * import { getStream } from "@langchain/svelte";
47
+ *
48
+ * const stream = getStream();
49
+ * <\/script>
50
+ *
51
+ * {#each stream.messages as msg (msg.id)}
52
+ * <div>{msg.content}</div>
53
+ * {/each}
54
+ * ```
55
+ *
56
+ * @example
57
+ * ```svelte
58
+ * <!-- MessageInput.svelte -->
59
+ * <script lang="ts">
60
+ * import { getStream } from "@langchain/svelte";
61
+ *
62
+ * const stream = getStream();
63
+ * let input = $state("");
64
+ *
65
+ * function send() {
66
+ * stream.submit({ messages: [{ type: "human", content: input }] });
67
+ * input = "";
68
+ * }
69
+ * <\/script>
70
+ *
71
+ * <form onsubmit={send}>
72
+ * <textarea bind:value={input}></textarea>
73
+ * <button disabled={stream.isLoading} type="submit">Send</button>
74
+ * </form>
75
+ * ```
76
+ */
77
+ function getStream() {
78
+ const context = (0, svelte.getContext)(STREAM_CONTEXT_KEY);
79
+ if (context == null) throw new Error("getStream() requires a parent component to call provideStream(). Add provideStream({ assistantId: '...' }) in an ancestor component.");
80
+ return context;
81
+ }
82
+ //#endregion
83
+ exports.getStream = getStream;
84
+ exports.provideStream = provideStream;
85
+
86
+ //# sourceMappingURL=context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.cjs","names":["useStream"],"sources":["../src/context.ts"],"sourcesContent":["import { setContext, getContext } from \"svelte\";\nimport type { BagTemplate } from \"@langchain/langgraph-sdk\";\nimport type {\n ResolveStreamOptions,\n InferBag,\n InferStateType,\n UseStreamCustomOptions,\n} from \"@langchain/langgraph-sdk/ui\";\nimport { useStream } from \"./index.js\";\n\nconst STREAM_CONTEXT_KEY = Symbol(\"langchain-stream\");\n\n/**\n * Creates a shared `useStream` instance and makes it available to all\n * descendant components via Svelte's `setContext`/`getContext`.\n *\n * Call this in a parent component's `<script>` block. Children access\n * the shared stream via `getStream()`.\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 *\n * @returns The stream instance (same as calling `useStream` directly).\n */\nexport function provideStream<\n T = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n>(\n options:\n | ResolveStreamOptions<T, InferBag<T, Bag>>\n | UseStreamCustomOptions<InferStateType<T>, InferBag<T, Bag>>,\n): ReturnType<typeof useStream<T, Bag>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = useStream<T, Bag>(options as any);\n setContext(STREAM_CONTEXT_KEY, stream);\n return stream;\n}\n\n/**\n * Retrieves the shared stream instance from the nearest ancestor that\n * called `provideStream()`.\n *\n * Throws if no ancestor has provided a stream.\n *\n * @example\n * ```svelte\n * <!-- MessageList.svelte -->\n * <script lang=\"ts\">\n * import { getStream } from \"@langchain/svelte\";\n *\n * const stream = getStream();\n * </script>\n *\n * {#each stream.messages as msg (msg.id)}\n * <div>{msg.content}</div>\n * {/each}\n * ```\n *\n * @example\n * ```svelte\n * <!-- MessageInput.svelte -->\n * <script lang=\"ts\">\n * import { getStream } from \"@langchain/svelte\";\n *\n * const stream = getStream();\n * let input = $state(\"\");\n *\n * function send() {\n * stream.submit({ messages: [{ type: \"human\", content: input }] });\n * input = \"\";\n * }\n * </script>\n *\n * <form onsubmit={send}>\n * <textarea bind:value={input}></textarea>\n * <button disabled={stream.isLoading} type=\"submit\">Send</button>\n * </form>\n * ```\n */\nexport function getStream<\n T = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n>(): ReturnType<typeof useStream<T, Bag>> {\n const context = getContext(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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return context as any;\n}\n"],"mappings":";;;AAUA,MAAM,qBAAqB,OAAO,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BrD,SAAgB,cAId,SAGsC;CAEtC,MAAM,SAASA,cAAAA,UAAkB,QAAe;AAChD,EAAA,GAAA,OAAA,YAAW,oBAAoB,OAAO;AACtC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,SAAgB,YAG0B;CACxC,MAAM,WAAA,GAAA,OAAA,YAAqB,mBAAmB;AAC9C,KAAI,WAAW,KACb,OAAM,IAAI,MACR,uIAED;AAGH,QAAO"}
@@ -0,0 +1,77 @@
1
+ import { useStream } from "./index.cjs";
2
+ import { InferBag, InferStateType, ResolveStreamOptions, UseStreamCustomOptions } from "@langchain/langgraph-sdk/ui";
3
+ import { BagTemplate } from "@langchain/langgraph-sdk";
4
+
5
+ //#region src/context.d.ts
6
+ /**
7
+ * Creates a shared `useStream` instance and makes it available to all
8
+ * descendant components via Svelte's `setContext`/`getContext`.
9
+ *
10
+ * Call this in a parent component's `<script>` block. Children access
11
+ * the shared stream via `getStream()`.
12
+ *
13
+ * @example
14
+ * ```svelte
15
+ * <!-- ChatContainer.svelte -->
16
+ * <script lang="ts">
17
+ * import { provideStream } from "@langchain/svelte";
18
+ *
19
+ * provideStream({
20
+ * assistantId: "agent",
21
+ * apiUrl: "http://localhost:2024",
22
+ * });
23
+ * </script>
24
+ *
25
+ * <ChatHeader />
26
+ * <MessageList />
27
+ * <MessageInput />
28
+ * ```
29
+ *
30
+ * @returns The stream instance (same as calling `useStream` directly).
31
+ */
32
+ declare function provideStream<T = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: ResolveStreamOptions<T, InferBag<T, Bag>> | UseStreamCustomOptions<InferStateType<T>, InferBag<T, Bag>>): ReturnType<typeof useStream<T, Bag>>;
33
+ /**
34
+ * Retrieves the shared stream instance from the nearest ancestor that
35
+ * called `provideStream()`.
36
+ *
37
+ * Throws if no ancestor has provided a stream.
38
+ *
39
+ * @example
40
+ * ```svelte
41
+ * <!-- MessageList.svelte -->
42
+ * <script lang="ts">
43
+ * import { getStream } from "@langchain/svelte";
44
+ *
45
+ * const stream = getStream();
46
+ * </script>
47
+ *
48
+ * {#each stream.messages as msg (msg.id)}
49
+ * <div>{msg.content}</div>
50
+ * {/each}
51
+ * ```
52
+ *
53
+ * @example
54
+ * ```svelte
55
+ * <!-- MessageInput.svelte -->
56
+ * <script lang="ts">
57
+ * import { getStream } from "@langchain/svelte";
58
+ *
59
+ * const stream = getStream();
60
+ * let input = $state("");
61
+ *
62
+ * function send() {
63
+ * stream.submit({ messages: [{ type: "human", content: input }] });
64
+ * input = "";
65
+ * }
66
+ * </script>
67
+ *
68
+ * <form onsubmit={send}>
69
+ * <textarea bind:value={input}></textarea>
70
+ * <button disabled={stream.isLoading} type="submit">Send</button>
71
+ * </form>
72
+ * ```
73
+ */
74
+ declare function getStream<T = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(): ReturnType<typeof useStream<T, Bag>>;
75
+ //#endregion
76
+ export { getStream, provideStream };
77
+ //# sourceMappingURL=context.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.cts","names":[],"sources":["../src/context.ts"],"mappings":";;;;;;;AAsCA;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,aAAA,KACV,MAAA,+BACQ,WAAA,GAAc,WAAA,CAAA,CAE1B,OAAA,EACI,oBAAA,CAAqB,CAAA,EAAG,QAAA,CAAS,CAAA,EAAG,GAAA,KACpC,sBAAA,CAAuB,cAAA,CAAe,CAAA,GAAI,QAAA,CAAS,CAAA,EAAG,GAAA,KACzD,UAAA,QAAkB,SAAA,CAAU,CAAA,EAAG,GAAA;;;;;;;;;;;;;;;;;;;;;;AAgDlC;;;;;;;;;;;;;;;;;;;;iBAAgB,SAAA,KACV,MAAA,+BACQ,WAAA,GAAc,WAAA,CAAA,CAAA,GACvB,UAAA,QAAkB,SAAA,CAAU,CAAA,EAAG,GAAA"}