@kortyx/stream 0.6.1 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @chatbot-core/types
2
2
 
3
+ ## [0.8.0](https://github.com/kortyx-io/kortyx/compare/stream-v0.7.0...stream-v0.8.0) (2026-05-25)
4
+
5
+
6
+ ### Features
7
+
8
+ * add MCP tool support to useReason ([8352721](https://github.com/kortyx-io/kortyx/commit/83527215fd2fa6362348d842f8f3b9e9d9d03704))
9
+
10
+ ## [0.7.0](https://github.com/kortyx-io/kortyx/compare/stream-v0.6.1...stream-v0.7.0) (2026-05-20)
11
+
12
+
13
+ ### Features
14
+
15
+ * **react:** tighten useChat lifecycle controls ([1672c72](https://github.com/kortyx-io/kortyx/commit/1672c72a524d16fae2f23dcbec1b91191747dc25))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * expand test coverage and source cleanups ([f1d89ae](https://github.com/kortyx-io/kortyx/commit/f1d89ae61b3655d41450c66cf850e0e00972f54e))
21
+ * expand test coverage and source cleanups ([4831a25](https://github.com/kortyx-io/kortyx/commit/4831a25e9517f56b99610bddd4b48a10eff72047))
22
+
3
23
  ## [0.6.1](https://github.com/kortyx-io/kortyx/compare/stream-v0.6.0...stream-v0.6.1) (2026-04-22)
4
24
 
5
25
 
package/README.md CHANGED
@@ -1,20 +1,54 @@
1
1
  # @kortyx/stream
2
2
 
3
- Streaming primitives for Kortyx.
3
+ [![npm version](https://img.shields.io/npm/v/@kortyx/stream.svg)](https://www.npmjs.com/package/@kortyx/stream)
4
+ [![CI](https://github.com/kortyx-io/kortyx/actions/workflows/ci.yml/badge.svg)](https://github.com/kortyx-io/kortyx/actions/workflows/ci.yml)
5
+ [![License](https://img.shields.io/npm/l/@kortyx/stream.svg)](https://github.com/kortyx-io/kortyx/blob/main/LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-ready-3178c6.svg)](https://www.typescriptlang.org/)
7
+
8
+ Streaming primitives, SSE helpers, readers, collectors, and structured-data reducers for Kortyx.
9
+
10
+ Most application code should import server/runtime stream helpers from `kortyx` and browser-safe stream helpers from `kortyx/browser`. Use `@kortyx/stream` directly when you need the lower-level protocol package.
4
11
 
5
12
  ## Install
6
13
 
14
+ ```bash
15
+ pnpm add @kortyx/stream
16
+ ```
17
+
7
18
  ```bash
8
19
  npm install @kortyx/stream
9
20
  ```
10
21
 
11
- ## Documentation
22
+ ## Key APIs
12
23
 
13
- This repo is under active development. For the latest package list and links, see the monorepo README:
24
+ - `StreamChunk`
25
+ - `createStreamResponse(...)`
26
+ - `toSSE(...)`
27
+ - `readStream(...)`
28
+ - `consumeStream(...)`
29
+ - `collectStream(...)`
30
+ - `collectBufferedStream(...)`
31
+ - `createStructuredStreamAccumulator(...)`
32
+ - `applyStructuredChunk(...)`
14
33
 
15
- - `README.md`
34
+ ## Example
16
35
 
17
- ## License
36
+ ```ts
37
+ import { collectBufferedStream } from "@kortyx/stream";
18
38
 
19
- Apache-2.0
39
+ const result = await collectBufferedStream(agent.streamChat(messages));
40
+
41
+ console.log(result.text);
42
+ console.log(result.structured);
43
+ ```
44
+
45
+ ## Documentation
46
+
47
+ - [Documentation](https://kortyx.io/docs)
48
+ - [Stream protocol](https://kortyx.io/docs/reference/stream-protocol)
49
+ - [SSE guide](https://kortyx.io/docs/guides/sse)
50
+ - [React client](https://kortyx.io/docs/reference/react-client)
51
+
52
+ ## License
20
53
 
54
+ Apache-2.0. See [LICENSE](https://github.com/kortyx-io/kortyx/blob/main/LICENSE).
@@ -0,0 +1,256 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const StreamChunkSchema: z.ZodUnion<readonly [z.ZodObject<{
4
+ type: z.ZodLiteral<"session">;
5
+ sessionId: z.ZodString;
6
+ }, z.core.$strip>, z.ZodObject<{
7
+ type: z.ZodLiteral<"status">;
8
+ message: z.ZodString;
9
+ node: z.ZodOptional<z.ZodString>;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ type: z.ZodLiteral<"message">;
12
+ content: z.ZodString;
13
+ node: z.ZodOptional<z.ZodString>;
14
+ }, z.core.$strip>, z.ZodObject<{
15
+ type: z.ZodLiteral<"text-start">;
16
+ node: z.ZodOptional<z.ZodString>;
17
+ id: z.ZodOptional<z.ZodString>;
18
+ opId: z.ZodOptional<z.ZodString>;
19
+ segmentId: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>, z.ZodObject<{
21
+ type: z.ZodLiteral<"text-delta">;
22
+ delta: z.ZodString;
23
+ node: z.ZodOptional<z.ZodString>;
24
+ id: z.ZodOptional<z.ZodString>;
25
+ opId: z.ZodOptional<z.ZodString>;
26
+ segmentId: z.ZodOptional<z.ZodString>;
27
+ }, z.core.$strip>, z.ZodObject<{
28
+ type: z.ZodLiteral<"text-end">;
29
+ node: z.ZodOptional<z.ZodString>;
30
+ id: z.ZodOptional<z.ZodString>;
31
+ opId: z.ZodOptional<z.ZodString>;
32
+ segmentId: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strip>, z.ZodObject<{
34
+ type: z.ZodLiteral<"tool-result">;
35
+ tool: z.ZodOptional<z.ZodString>;
36
+ node: z.ZodOptional<z.ZodString>;
37
+ content: z.ZodUnknown;
38
+ }, z.core.$strip>, z.ZodObject<{
39
+ type: z.ZodLiteral<"tool-call-start">;
40
+ tool: z.ZodString;
41
+ toolCallId: z.ZodString;
42
+ node: z.ZodOptional<z.ZodString>;
43
+ id: z.ZodOptional<z.ZodString>;
44
+ opId: z.ZodOptional<z.ZodString>;
45
+ input: z.ZodOptional<z.ZodUnknown>;
46
+ }, z.core.$strip>, z.ZodObject<{
47
+ type: z.ZodLiteral<"tool-call-result">;
48
+ tool: z.ZodString;
49
+ toolCallId: z.ZodString;
50
+ node: z.ZodOptional<z.ZodString>;
51
+ id: z.ZodOptional<z.ZodString>;
52
+ opId: z.ZodOptional<z.ZodString>;
53
+ content: z.ZodUnknown;
54
+ structuredContent: z.ZodOptional<z.ZodUnknown>;
55
+ isError: z.ZodOptional<z.ZodBoolean>;
56
+ }, z.core.$strip>, z.ZodObject<{
57
+ type: z.ZodLiteral<"tool-call-error">;
58
+ tool: z.ZodString;
59
+ toolCallId: z.ZodString;
60
+ node: z.ZodOptional<z.ZodString>;
61
+ id: z.ZodOptional<z.ZodString>;
62
+ opId: z.ZodOptional<z.ZodString>;
63
+ message: z.ZodString;
64
+ }, z.core.$strip>, z.ZodObject<{
65
+ type: z.ZodLiteral<"interrupt">;
66
+ requestId: z.ZodString;
67
+ resumeToken: z.ZodString;
68
+ workflow: z.ZodOptional<z.ZodString>;
69
+ node: z.ZodOptional<z.ZodString>;
70
+ id: z.ZodOptional<z.ZodString>;
71
+ opId: z.ZodOptional<z.ZodString>;
72
+ schemaId: z.ZodOptional<z.ZodString>;
73
+ schemaVersion: z.ZodOptional<z.ZodString>;
74
+ input: z.ZodDiscriminatedUnion<[z.ZodObject<{
75
+ kind: z.ZodLiteral<"text">;
76
+ multiple: z.ZodBoolean;
77
+ question: z.ZodOptional<z.ZodString>;
78
+ id: z.ZodOptional<z.ZodString>;
79
+ schemaId: z.ZodOptional<z.ZodString>;
80
+ schemaVersion: z.ZodOptional<z.ZodString>;
81
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
82
+ options: z.ZodOptional<z.ZodArray<z.ZodNever>>;
83
+ }, z.core.$strip>, z.ZodObject<{
84
+ kind: z.ZodEnum<{
85
+ choice: "choice";
86
+ "multi-choice": "multi-choice";
87
+ }>;
88
+ multiple: z.ZodBoolean;
89
+ question: z.ZodString;
90
+ id: z.ZodOptional<z.ZodString>;
91
+ schemaId: z.ZodOptional<z.ZodString>;
92
+ schemaVersion: z.ZodOptional<z.ZodString>;
93
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
94
+ options: z.ZodArray<z.ZodObject<{
95
+ id: z.ZodString;
96
+ label: z.ZodString;
97
+ description: z.ZodOptional<z.ZodString>;
98
+ }, z.core.$strip>>;
99
+ }, z.core.$strip>], "kind">;
100
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
101
+ }, z.core.$strip>, z.ZodUnion<readonly [z.ZodObject<{
102
+ type: z.ZodLiteral<"structured-data">;
103
+ streamId: z.ZodString;
104
+ dataType: z.ZodString;
105
+ schemaId: z.ZodOptional<z.ZodString>;
106
+ schemaVersion: z.ZodOptional<z.ZodString>;
107
+ id: z.ZodOptional<z.ZodString>;
108
+ node: z.ZodOptional<z.ZodString>;
109
+ kind: z.ZodLiteral<"set">;
110
+ path: z.ZodString;
111
+ value: z.ZodUnknown;
112
+ }, z.core.$strip>, z.ZodObject<{
113
+ type: z.ZodLiteral<"structured-data">;
114
+ streamId: z.ZodString;
115
+ dataType: z.ZodString;
116
+ schemaId: z.ZodOptional<z.ZodString>;
117
+ schemaVersion: z.ZodOptional<z.ZodString>;
118
+ id: z.ZodOptional<z.ZodString>;
119
+ node: z.ZodOptional<z.ZodString>;
120
+ kind: z.ZodLiteral<"append">;
121
+ path: z.ZodString;
122
+ items: z.ZodArray<z.ZodUnknown>;
123
+ }, z.core.$strip>, z.ZodObject<{
124
+ type: z.ZodLiteral<"structured-data">;
125
+ streamId: z.ZodString;
126
+ dataType: z.ZodString;
127
+ schemaId: z.ZodOptional<z.ZodString>;
128
+ schemaVersion: z.ZodOptional<z.ZodString>;
129
+ id: z.ZodOptional<z.ZodString>;
130
+ node: z.ZodOptional<z.ZodString>;
131
+ kind: z.ZodLiteral<"text-delta">;
132
+ path: z.ZodString;
133
+ delta: z.ZodString;
134
+ }, z.core.$strip>, z.ZodObject<{
135
+ type: z.ZodLiteral<"structured-data">;
136
+ streamId: z.ZodString;
137
+ dataType: z.ZodString;
138
+ schemaId: z.ZodOptional<z.ZodString>;
139
+ schemaVersion: z.ZodOptional<z.ZodString>;
140
+ id: z.ZodOptional<z.ZodString>;
141
+ node: z.ZodOptional<z.ZodString>;
142
+ kind: z.ZodLiteral<"final">;
143
+ data: z.ZodUnknown;
144
+ }, z.core.$strip>]>, z.ZodObject<{
145
+ type: z.ZodLiteral<"transition">;
146
+ transitionTo: z.ZodString;
147
+ payload: z.ZodOptional<z.ZodAny>;
148
+ }, z.core.$strip>, z.ZodObject<{
149
+ type: z.ZodLiteral<"done">;
150
+ data: z.ZodOptional<z.ZodAny>;
151
+ }, z.core.$strip>, z.ZodObject<{
152
+ type: z.ZodLiteral<"error">;
153
+ message: z.ZodString;
154
+ }, z.core.$strip>]>;
155
+ type StreamChunk = z.infer<typeof StreamChunkSchema>;
156
+
157
+ interface ConsumeStreamHandlers {
158
+ onChunk?: (chunk: StreamChunk) => undefined | boolean | Promise<boolean | undefined>;
159
+ onDone?: () => void | Promise<void>;
160
+ onError?: (error: Error, chunk?: StreamChunk) => void | Promise<void>;
161
+ }
162
+ /**
163
+ * Consume a stream of StreamChunk events with callback handlers.
164
+ * Returns when a `done` chunk is seen, the stream ends, or `onChunk` returns `false`.
165
+ */
166
+ declare function consumeStream(stream: AsyncIterable<StreamChunk>, handlers?: ConsumeStreamHandlers): Promise<void>;
167
+
168
+ /**
169
+ * Reads a server-sent event (SSE) Response body and yields StreamChunk objects.
170
+ */
171
+ declare function readStream(body: ReadableStream<Uint8Array> | null): AsyncGenerator<StreamChunk, void, void>;
172
+
173
+ interface StreamFromRouteArgs<TBody = unknown> {
174
+ endpoint: string;
175
+ body: TBody;
176
+ method?: string | undefined;
177
+ fetchImpl?: typeof fetch;
178
+ headers?: Record<string, string> | undefined;
179
+ signal?: AbortSignal | undefined;
180
+ }
181
+ declare function streamFromRoute<TBody = unknown>(args: StreamFromRouteArgs<TBody>): AsyncGenerator<StreamChunk, void, void>;
182
+
183
+ declare const StructuredDataChunkSchema: z.ZodUnion<readonly [z.ZodObject<{
184
+ type: z.ZodLiteral<"structured-data">;
185
+ streamId: z.ZodString;
186
+ dataType: z.ZodString;
187
+ schemaId: z.ZodOptional<z.ZodString>;
188
+ schemaVersion: z.ZodOptional<z.ZodString>;
189
+ id: z.ZodOptional<z.ZodString>;
190
+ node: z.ZodOptional<z.ZodString>;
191
+ kind: z.ZodLiteral<"set">;
192
+ path: z.ZodString;
193
+ value: z.ZodUnknown;
194
+ }, z.core.$strip>, z.ZodObject<{
195
+ type: z.ZodLiteral<"structured-data">;
196
+ streamId: z.ZodString;
197
+ dataType: z.ZodString;
198
+ schemaId: z.ZodOptional<z.ZodString>;
199
+ schemaVersion: z.ZodOptional<z.ZodString>;
200
+ id: z.ZodOptional<z.ZodString>;
201
+ node: z.ZodOptional<z.ZodString>;
202
+ kind: z.ZodLiteral<"append">;
203
+ path: z.ZodString;
204
+ items: z.ZodArray<z.ZodUnknown>;
205
+ }, z.core.$strip>, z.ZodObject<{
206
+ type: z.ZodLiteral<"structured-data">;
207
+ streamId: z.ZodString;
208
+ dataType: z.ZodString;
209
+ schemaId: z.ZodOptional<z.ZodString>;
210
+ schemaVersion: z.ZodOptional<z.ZodString>;
211
+ id: z.ZodOptional<z.ZodString>;
212
+ node: z.ZodOptional<z.ZodString>;
213
+ kind: z.ZodLiteral<"text-delta">;
214
+ path: z.ZodString;
215
+ delta: z.ZodString;
216
+ }, z.core.$strip>, z.ZodObject<{
217
+ type: z.ZodLiteral<"structured-data">;
218
+ streamId: z.ZodString;
219
+ dataType: z.ZodString;
220
+ schemaId: z.ZodOptional<z.ZodString>;
221
+ schemaVersion: z.ZodOptional<z.ZodString>;
222
+ id: z.ZodOptional<z.ZodString>;
223
+ node: z.ZodOptional<z.ZodString>;
224
+ kind: z.ZodLiteral<"final">;
225
+ data: z.ZodUnknown;
226
+ }, z.core.$strip>]>;
227
+ type StructuredDataChunk = z.infer<typeof StructuredDataChunkSchema>;
228
+
229
+ type StructuredStreamState<TData = unknown> = {
230
+ streamId: string;
231
+ dataType: string;
232
+ status: "streaming" | "done";
233
+ data: TData;
234
+ node?: string;
235
+ id?: string;
236
+ schemaId?: string;
237
+ schemaVersion?: string;
238
+ };
239
+ declare function applyStructuredChunk<TData = unknown>(current: StructuredStreamState<TData> | undefined, chunk: StructuredDataChunk): StructuredStreamState<TData>;
240
+ declare function reduceStructuredChunks<TData = unknown>(chunks: StructuredDataChunk[]): Record<string, StructuredStreamState<TData>>;
241
+
242
+ type StructuredStreamAccumulator<TData = unknown> = {
243
+ apply: (chunk: StructuredDataChunk) => StructuredStreamState<TData>;
244
+ applyStreamChunk: (chunk: StreamChunk) => StructuredStreamState<TData> | undefined;
245
+ get: (streamId: string) => StructuredStreamState<TData> | undefined;
246
+ has: (streamId: string) => boolean;
247
+ delete: (streamId: string) => boolean;
248
+ clear: () => void;
249
+ size: () => number;
250
+ entries: () => Array<[string, StructuredStreamState<TData>]>;
251
+ values: () => StructuredStreamState<TData>[];
252
+ toRecord: () => Record<string, StructuredStreamState<TData>>;
253
+ };
254
+ declare function createStructuredStreamAccumulator<TData = unknown>(initialChunks?: Iterable<StructuredDataChunk>): StructuredStreamAccumulator<TData>;
255
+
256
+ export { type ConsumeStreamHandlers as C, type StreamChunk as S, type StructuredDataChunk as a, StreamChunkSchema as b, type StreamFromRouteArgs as c, StructuredDataChunkSchema as d, type StructuredStreamAccumulator as e, type StructuredStreamState as f, applyStructuredChunk as g, consumeStream as h, createStructuredStreamAccumulator as i, reduceStructuredChunks as j, readStream as r, streamFromRoute as s };
package/dist/browser.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { C as ConsumeStreamHandlers, S as StreamChunk, c as StreamFromRouteArgs, a as StructuredDataChunk, e as StructuredStreamAccumulator, f as StructuredStreamState, g as applyStructuredChunk, h as consumeStream, i as createStructuredStreamAccumulator, r as readStream, j as reduceStructuredChunks, s as streamFromRoute } from './browser-DBfCMmkm.js';
1
+ export { C as ConsumeStreamHandlers, S as StreamChunk, c as StreamFromRouteArgs, a as StructuredDataChunk, e as StructuredStreamAccumulator, f as StructuredStreamState, g as applyStructuredChunk, h as consumeStream, i as createStructuredStreamAccumulator, r as readStream, j as reduceStructuredChunks, s as streamFromRoute } from './browser-BLO5Ge4b.js';
2
2
  import 'zod';
package/dist/browser.js CHANGED
@@ -31,10 +31,7 @@ module.exports = __toCommonJS(browser_exports);
31
31
  // src/client/consume-stream.ts
32
32
  var toError = (value) => value instanceof Error ? value : new Error(String(value));
33
33
  async function consumeStream(stream, handlers = {}) {
34
- let doneCalled = false;
35
34
  const callDone = async () => {
36
- if (doneCalled) return;
37
- doneCalled = true;
38
35
  await handlers.onDone?.();
39
36
  };
40
37
  try {
@@ -70,7 +67,7 @@ async function* readStream(body) {
70
67
  if (done) break;
71
68
  buffer += decoder.decode(value, { stream: true });
72
69
  const parts = buffer.split("\n\n");
73
- buffer = parts.pop() ?? "";
70
+ buffer = parts.pop();
74
71
  for (const part of parts) {
75
72
  if (!part.startsWith("data: ")) continue;
76
73
  const payload = part.slice(6);
@@ -113,7 +110,8 @@ async function* streamFromRoute(args) {
113
110
  "content-type": "application/json",
114
111
  ...args.headers ?? {}
115
112
  },
116
- body: JSON.stringify(args.body)
113
+ body: JSON.stringify(args.body),
114
+ ...args.signal ? { signal: args.signal } : {}
117
115
  });
118
116
  } catch (error) {
119
117
  yield { type: "error", message: toErrorMessage(error) };
@@ -170,9 +168,6 @@ var cloneContainerForPart = (args) => {
170
168
  var updateByParts = (args) => {
171
169
  const traversed = args.traversed ?? [];
172
170
  const [part, ...rest] = args.parts;
173
- if (part === void 0) {
174
- return args.updateLeaf(args.input);
175
- }
176
171
  const container = cloneContainerForPart({
177
172
  current: args.input,
178
173
  part,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/browser.ts","../src/client/consume-stream.ts","../src/client/read-stream.ts","../src/client/stream-from-route.ts","../src/structured/apply-structured-chunk.ts","../src/structured/structured-stream-accumulator.ts"],"sourcesContent":["// Browser-safe exports for client bundles.\n// Keep this file free of Node-only imports (fs, path, etc).\n\nexport type { ConsumeStreamHandlers } from \"./client/consume-stream\";\nexport { consumeStream } from \"./client/consume-stream\";\nexport { readStream } from \"./client/read-stream\";\nexport type { StreamFromRouteArgs } from \"./client/stream-from-route\";\nexport { streamFromRoute } from \"./client/stream-from-route\";\nexport * from \"./structured/apply-structured-chunk\";\nexport * from \"./structured/structured-stream-accumulator\";\nexport type { StreamChunk } from \"./types/stream-chunk\";\nexport type { StructuredDataChunk } from \"./types/structured-data\";\n","import type { StreamChunk } from \"../types/stream-chunk\";\n\nexport interface ConsumeStreamHandlers {\n onChunk?: (\n chunk: StreamChunk,\n ) => undefined | boolean | Promise<boolean | undefined>;\n onDone?: () => void | Promise<void>;\n onError?: (error: Error, chunk?: StreamChunk) => void | Promise<void>;\n}\n\nconst toError = (value: unknown): Error =>\n value instanceof Error ? value : new Error(String(value));\n\n/**\n * Consume a stream of StreamChunk events with callback handlers.\n * Returns when a `done` chunk is seen, the stream ends, or `onChunk` returns `false`.\n */\nexport async function consumeStream(\n stream: AsyncIterable<StreamChunk>,\n handlers: ConsumeStreamHandlers = {},\n): Promise<void> {\n let doneCalled = false;\n\n const callDone = async () => {\n if (doneCalled) return;\n doneCalled = true;\n await handlers.onDone?.();\n };\n\n try {\n for await (const chunk of stream) {\n const shouldContinue = await handlers.onChunk?.(chunk);\n\n if (chunk.type === \"error\") {\n await handlers.onError?.(\n new Error(chunk.message || \"Stream error.\"),\n chunk,\n );\n }\n\n if (chunk.type === \"done\" || shouldContinue === false) {\n await callDone();\n return;\n }\n }\n\n await callDone();\n } catch (error) {\n const normalized = toError(error);\n await handlers.onError?.(normalized);\n throw normalized;\n }\n}\n","// packages/stream/src/client/read-stream.ts\nimport type { StreamChunk } from \"../types/stream-chunk\";\n\n/**\n * Reads a server-sent event (SSE) Response body and yields StreamChunk objects.\n */\nexport async function* readStream(\n body: ReadableStream<Uint8Array> | null,\n): AsyncGenerator<StreamChunk, void, void> {\n if (!body) return;\n\n const reader = body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n if (!part.startsWith(\"data: \")) continue;\n const payload = part.slice(6);\n if (payload.trim() === \"[DONE]\") return;\n try {\n yield JSON.parse(payload) as StreamChunk;\n } catch (err: any) {\n console.warn(\"Invalid JSON in stream chunk:\", payload);\n console.error(err);\n }\n }\n }\n}\n","import type { StreamChunk } from \"../types/stream-chunk\";\nimport { readStream } from \"./read-stream\";\n\nexport interface StreamFromRouteArgs<TBody = unknown> {\n endpoint: string;\n body: TBody;\n method?: string | undefined;\n fetchImpl?: typeof fetch;\n headers?: Record<string, string> | undefined;\n}\n\nconst toErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst readErrorMessage = async (response: Response): Promise<string> => {\n let message = `Request failed (${response.status})`;\n try {\n const payload = (await response.json()) as unknown;\n if (\n payload &&\n typeof payload === \"object\" &&\n \"error\" in payload &&\n typeof (payload as { error?: unknown }).error === \"string\"\n ) {\n message = (payload as { error: string }).error;\n }\n } catch {}\n return message;\n};\n\nexport async function* streamFromRoute<TBody = unknown>(\n args: StreamFromRouteArgs<TBody>,\n): AsyncGenerator<StreamChunk, void, void> {\n const fetchFn = args.fetchImpl ?? globalThis.fetch;\n if (!fetchFn) {\n yield { type: \"error\", message: \"No fetch implementation available.\" };\n yield { type: \"done\" };\n return;\n }\n\n let response: Response;\n try {\n response = await fetchFn(args.endpoint, {\n method: args.method ?? \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...(args.headers ?? {}),\n },\n body: JSON.stringify(args.body),\n });\n } catch (error) {\n yield { type: \"error\", message: toErrorMessage(error) };\n yield { type: \"done\" };\n return;\n }\n\n if (!response.ok) {\n yield { type: \"error\", message: await readErrorMessage(response) };\n yield { type: \"done\" };\n return;\n }\n\n yield* readStream(response.body);\n}\n","import type { StructuredDataChunk } from \"../types/structured-data\";\n\nexport type StructuredStreamState<TData = unknown> = {\n streamId: string;\n dataType: string;\n status: \"streaming\" | \"done\";\n data: TData;\n node?: string;\n id?: string;\n schemaId?: string;\n schemaVersion?: string;\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isArrayIndex = (value: string): boolean => /^\\d+$/.test(value);\n\nconst describeValue = (value: unknown): string => {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"array\";\n return typeof value;\n};\n\nconst parsePath = (path: string): string[] => {\n if (path.length === 0) {\n throw new Error(\n \"Structured chunk path must be a non-empty dot-separated string.\",\n );\n }\n\n const parts = path.split(\".\");\n if (parts.some((part) => part.length === 0)) {\n throw new Error(\n `Structured chunk path \"${path}\" must not contain empty segments.`,\n );\n }\n\n return parts;\n};\n\nconst cloneContainerForPart = (args: {\n current: unknown;\n part: string;\n path: string;\n traversed: string[];\n}): Record<string, unknown> | unknown[] => {\n const expected = isArrayIndex(args.part) ? \"array\" : \"object\";\n const location =\n args.traversed.length === 0 ? \"<root>\" : args.traversed.join(\".\");\n\n if (args.current === undefined) {\n return expected === \"array\" ? [] : {};\n }\n\n if (expected === \"array\") {\n if (Array.isArray(args.current)) return [...args.current];\n throw new Error(\n `Structured path conflict at ${location} for \"${args.path}\": expected array container, received ${describeValue(args.current)}.`,\n );\n }\n\n if (isPlainObject(args.current)) return { ...args.current };\n\n throw new Error(\n `Structured path conflict at ${location} for \"${args.path}\": expected object container, received ${describeValue(args.current)}.`,\n );\n};\n\nconst updateByParts = (args: {\n input: unknown;\n parts: string[];\n path: string;\n updateLeaf: (current: unknown) => unknown;\n traversed?: string[];\n}): unknown => {\n const traversed = args.traversed ?? [];\n const [part, ...rest] = args.parts;\n if (part === undefined) {\n return args.updateLeaf(args.input);\n }\n\n const container = cloneContainerForPart({\n current: args.input,\n part,\n path: args.path,\n traversed,\n });\n\n const currentChild = Array.isArray(container)\n ? container[Number(part)]\n : container[part];\n const nextChild =\n rest.length === 0\n ? args.updateLeaf(currentChild)\n : updateByParts({\n input: currentChild,\n parts: rest,\n path: args.path,\n updateLeaf: args.updateLeaf,\n traversed: [...traversed, part],\n });\n\n if (Array.isArray(container)) {\n container[Number(part)] = nextChild;\n } else {\n container[part] = nextChild;\n }\n\n return container;\n};\n\nexport function applyStructuredChunk<TData = unknown>(\n current: StructuredStreamState<TData> | undefined,\n chunk: StructuredDataChunk,\n): StructuredStreamState<TData> {\n if (current && current.streamId !== chunk.streamId) {\n throw new Error(\n `Structured chunk streamId mismatch: expected ${current.streamId}, received ${chunk.streamId}.`,\n );\n }\n\n if (current?.status === \"done\") {\n throw new Error(\n `Structured stream ${chunk.streamId} already completed with a final chunk.`,\n );\n }\n\n const nextBase = {\n streamId: chunk.streamId,\n dataType: chunk.dataType,\n status: chunk.kind === \"final\" ? (\"done\" as const) : (\"streaming\" as const),\n ...(chunk.node ? { node: chunk.node } : {}),\n ...(chunk.id ? { id: chunk.id } : {}),\n ...(chunk.schemaId ? { schemaId: chunk.schemaId } : {}),\n ...(chunk.schemaVersion ? { schemaVersion: chunk.schemaVersion } : {}),\n };\n\n if (chunk.kind === \"final\") {\n return {\n ...nextBase,\n data: chunk.data as TData,\n };\n }\n\n const path = chunk.path;\n const pathParts = parsePath(path);\n const previousData = current?.data;\n\n if (chunk.kind === \"set\") {\n return {\n ...nextBase,\n data: updateByParts({\n input: previousData,\n parts: pathParts,\n path,\n updateLeaf: () => chunk.value,\n }) as TData,\n };\n }\n\n if (chunk.kind === \"append\") {\n return {\n ...nextBase,\n data: updateByParts({\n input: previousData,\n parts: pathParts,\n path,\n updateLeaf: (existing) => {\n if (existing === undefined) return [...chunk.items];\n if (!Array.isArray(existing)) {\n throw new Error(\n `Structured append requires path \"${path}\" to target an array, received ${describeValue(existing)}.`,\n );\n }\n return [...existing, ...chunk.items];\n },\n }) as TData,\n };\n }\n\n return {\n ...nextBase,\n data: updateByParts({\n input: previousData,\n parts: pathParts,\n path,\n updateLeaf: (existing) => {\n if (existing === undefined) return chunk.delta;\n if (typeof existing !== \"string\") {\n throw new Error(\n `Structured text-delta requires path \"${path}\" to target a string, received ${describeValue(existing)}.`,\n );\n }\n return existing + chunk.delta;\n },\n }) as TData,\n };\n}\n\nexport function reduceStructuredChunks<TData = unknown>(\n chunks: StructuredDataChunk[],\n): Record<string, StructuredStreamState<TData>> {\n return chunks.reduce<Record<string, StructuredStreamState<TData>>>(\n (acc, chunk) => {\n acc[chunk.streamId] = applyStructuredChunk(acc[chunk.streamId], chunk);\n return acc;\n },\n {},\n );\n}\n","import type { StreamChunk } from \"../types/stream-chunk\";\nimport type { StructuredDataChunk } from \"../types/structured-data\";\nimport {\n applyStructuredChunk,\n type StructuredStreamState,\n} from \"./apply-structured-chunk\";\n\nexport type StructuredStreamAccumulator<TData = unknown> = {\n apply: (chunk: StructuredDataChunk) => StructuredStreamState<TData>;\n applyStreamChunk: (\n chunk: StreamChunk,\n ) => StructuredStreamState<TData> | undefined;\n get: (streamId: string) => StructuredStreamState<TData> | undefined;\n has: (streamId: string) => boolean;\n delete: (streamId: string) => boolean;\n clear: () => void;\n size: () => number;\n entries: () => Array<[string, StructuredStreamState<TData>]>;\n values: () => StructuredStreamState<TData>[];\n toRecord: () => Record<string, StructuredStreamState<TData>>;\n};\n\nconst isStructuredDataChunk = (\n chunk: StreamChunk,\n): chunk is StructuredDataChunk => chunk.type === \"structured-data\";\n\nexport function createStructuredStreamAccumulator<TData = unknown>(\n initialChunks: Iterable<StructuredDataChunk> = [],\n): StructuredStreamAccumulator<TData> {\n const states = new Map<string, StructuredStreamState<TData>>();\n\n const apply = (chunk: StructuredDataChunk): StructuredStreamState<TData> => {\n const nextState = applyStructuredChunk(states.get(chunk.streamId), chunk);\n states.set(chunk.streamId, nextState);\n return nextState;\n };\n\n for (const chunk of initialChunks) {\n apply(chunk);\n }\n\n return {\n apply,\n applyStreamChunk: (chunk) => {\n if (!isStructuredDataChunk(chunk)) return undefined;\n return apply(chunk);\n },\n get: (streamId) => states.get(streamId),\n has: (streamId) => states.has(streamId),\n delete: (streamId) => states.delete(streamId),\n clear: () => {\n states.clear();\n },\n size: () => states.size,\n entries: () => Array.from(states.entries()),\n values: () => Array.from(states.values()),\n toRecord: () => Object.fromEntries(states.entries()),\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/browser.ts","../src/client/consume-stream.ts","../src/client/read-stream.ts","../src/client/stream-from-route.ts","../src/structured/apply-structured-chunk.ts","../src/structured/structured-stream-accumulator.ts"],"sourcesContent":["// Browser-safe exports for client bundles.\n// Keep this file free of Node-only imports (fs, path, etc).\n\nexport type { ConsumeStreamHandlers } from \"./client/consume-stream\";\nexport { consumeStream } from \"./client/consume-stream\";\nexport { readStream } from \"./client/read-stream\";\nexport type { StreamFromRouteArgs } from \"./client/stream-from-route\";\nexport { streamFromRoute } from \"./client/stream-from-route\";\nexport * from \"./structured/apply-structured-chunk\";\nexport * from \"./structured/structured-stream-accumulator\";\nexport type { StreamChunk } from \"./types/stream-chunk\";\nexport type { StructuredDataChunk } from \"./types/structured-data\";\n","import type { StreamChunk } from \"../types/stream-chunk\";\n\nexport interface ConsumeStreamHandlers {\n onChunk?: (\n chunk: StreamChunk,\n ) => undefined | boolean | Promise<boolean | undefined>;\n onDone?: () => void | Promise<void>;\n onError?: (error: Error, chunk?: StreamChunk) => void | Promise<void>;\n}\n\nconst toError = (value: unknown): Error =>\n value instanceof Error ? value : new Error(String(value));\n\n/**\n * Consume a stream of StreamChunk events with callback handlers.\n * Returns when a `done` chunk is seen, the stream ends, or `onChunk` returns `false`.\n */\nexport async function consumeStream(\n stream: AsyncIterable<StreamChunk>,\n handlers: ConsumeStreamHandlers = {},\n): Promise<void> {\n const callDone = async () => {\n await handlers.onDone?.();\n };\n\n try {\n for await (const chunk of stream) {\n const shouldContinue = await handlers.onChunk?.(chunk);\n\n if (chunk.type === \"error\") {\n await handlers.onError?.(\n new Error(chunk.message || \"Stream error.\"),\n chunk,\n );\n }\n\n if (chunk.type === \"done\" || shouldContinue === false) {\n await callDone();\n return;\n }\n }\n\n await callDone();\n } catch (error) {\n const normalized = toError(error);\n await handlers.onError?.(normalized);\n throw normalized;\n }\n}\n","// packages/stream/src/client/read-stream.ts\nimport type { StreamChunk } from \"../types/stream-chunk\";\n\n/**\n * Reads a server-sent event (SSE) Response body and yields StreamChunk objects.\n */\nexport async function* readStream(\n body: ReadableStream<Uint8Array> | null,\n): AsyncGenerator<StreamChunk, void, void> {\n if (!body) return;\n\n const reader = body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() as string;\n\n for (const part of parts) {\n if (!part.startsWith(\"data: \")) continue;\n const payload = part.slice(6);\n if (payload.trim() === \"[DONE]\") return;\n try {\n yield JSON.parse(payload) as StreamChunk;\n } catch (err) {\n console.warn(\"Invalid JSON in stream chunk:\", payload);\n console.error(err);\n }\n }\n }\n}\n","import type { StreamChunk } from \"../types/stream-chunk\";\nimport { readStream } from \"./read-stream\";\n\nexport interface StreamFromRouteArgs<TBody = unknown> {\n endpoint: string;\n body: TBody;\n method?: string | undefined;\n fetchImpl?: typeof fetch;\n headers?: Record<string, string> | undefined;\n signal?: AbortSignal | undefined;\n}\n\nconst toErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst readErrorMessage = async (response: Response): Promise<string> => {\n let message = `Request failed (${response.status})`;\n try {\n const payload = (await response.json()) as unknown;\n if (\n payload &&\n typeof payload === \"object\" &&\n \"error\" in payload &&\n typeof (payload as { error?: unknown }).error === \"string\"\n ) {\n message = (payload as { error: string }).error;\n }\n } catch {}\n return message;\n};\n\nexport async function* streamFromRoute<TBody = unknown>(\n args: StreamFromRouteArgs<TBody>,\n): AsyncGenerator<StreamChunk, void, void> {\n const fetchFn = args.fetchImpl ?? globalThis.fetch;\n if (!fetchFn) {\n yield { type: \"error\", message: \"No fetch implementation available.\" };\n yield { type: \"done\" };\n return;\n }\n\n let response: Response;\n try {\n response = await fetchFn(args.endpoint, {\n method: args.method ?? \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...(args.headers ?? {}),\n },\n body: JSON.stringify(args.body),\n ...(args.signal ? { signal: args.signal } : {}),\n });\n } catch (error) {\n yield { type: \"error\", message: toErrorMessage(error) };\n yield { type: \"done\" };\n return;\n }\n\n if (!response.ok) {\n yield { type: \"error\", message: await readErrorMessage(response) };\n yield { type: \"done\" };\n return;\n }\n\n yield* readStream(response.body);\n}\n","import type { StructuredDataChunk } from \"../types/structured-data\";\n\nexport type StructuredStreamState<TData = unknown> = {\n streamId: string;\n dataType: string;\n status: \"streaming\" | \"done\";\n data: TData;\n node?: string;\n id?: string;\n schemaId?: string;\n schemaVersion?: string;\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isArrayIndex = (value: string): boolean => /^\\d+$/.test(value);\n\nconst describeValue = (value: unknown): string => {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"array\";\n return typeof value;\n};\n\nconst parsePath = (path: string): string[] => {\n if (path.length === 0) {\n throw new Error(\n \"Structured chunk path must be a non-empty dot-separated string.\",\n );\n }\n\n const parts = path.split(\".\");\n if (parts.some((part) => part.length === 0)) {\n throw new Error(\n `Structured chunk path \"${path}\" must not contain empty segments.`,\n );\n }\n\n return parts;\n};\n\nconst cloneContainerForPart = (args: {\n current: unknown;\n part: string;\n path: string;\n traversed: string[];\n}): Record<string, unknown> | unknown[] => {\n const expected = isArrayIndex(args.part) ? \"array\" : \"object\";\n const location =\n args.traversed.length === 0 ? \"<root>\" : args.traversed.join(\".\");\n\n if (args.current === undefined) {\n return expected === \"array\" ? [] : {};\n }\n\n if (expected === \"array\") {\n if (Array.isArray(args.current)) return [...args.current];\n throw new Error(\n `Structured path conflict at ${location} for \"${args.path}\": expected array container, received ${describeValue(args.current)}.`,\n );\n }\n\n if (isPlainObject(args.current)) return { ...args.current };\n\n throw new Error(\n `Structured path conflict at ${location} for \"${args.path}\": expected object container, received ${describeValue(args.current)}.`,\n );\n};\n\nconst updateByParts = (args: {\n input: unknown;\n parts: string[];\n path: string;\n updateLeaf: (current: unknown) => unknown;\n traversed?: string[];\n}): unknown => {\n const traversed = args.traversed ?? [];\n const [part, ...rest] = args.parts as [string, ...string[]];\n\n const container = cloneContainerForPart({\n current: args.input,\n part,\n path: args.path,\n traversed,\n });\n\n const currentChild = Array.isArray(container)\n ? container[Number(part)]\n : container[part];\n const nextChild =\n rest.length === 0\n ? args.updateLeaf(currentChild)\n : updateByParts({\n input: currentChild,\n parts: rest,\n path: args.path,\n updateLeaf: args.updateLeaf,\n traversed: [...traversed, part],\n });\n\n if (Array.isArray(container)) {\n container[Number(part)] = nextChild;\n } else {\n container[part] = nextChild;\n }\n\n return container;\n};\n\nexport function applyStructuredChunk<TData = unknown>(\n current: StructuredStreamState<TData> | undefined,\n chunk: StructuredDataChunk,\n): StructuredStreamState<TData> {\n if (current && current.streamId !== chunk.streamId) {\n throw new Error(\n `Structured chunk streamId mismatch: expected ${current.streamId}, received ${chunk.streamId}.`,\n );\n }\n\n if (current?.status === \"done\") {\n throw new Error(\n `Structured stream ${chunk.streamId} already completed with a final chunk.`,\n );\n }\n\n const nextBase = {\n streamId: chunk.streamId,\n dataType: chunk.dataType,\n status: chunk.kind === \"final\" ? (\"done\" as const) : (\"streaming\" as const),\n ...(chunk.node ? { node: chunk.node } : {}),\n ...(chunk.id ? { id: chunk.id } : {}),\n ...(chunk.schemaId ? { schemaId: chunk.schemaId } : {}),\n ...(chunk.schemaVersion ? { schemaVersion: chunk.schemaVersion } : {}),\n };\n\n if (chunk.kind === \"final\") {\n return {\n ...nextBase,\n data: chunk.data as TData,\n };\n }\n\n const path = chunk.path;\n const pathParts = parsePath(path);\n const previousData = current?.data;\n\n if (chunk.kind === \"set\") {\n return {\n ...nextBase,\n data: updateByParts({\n input: previousData,\n parts: pathParts,\n path,\n updateLeaf: () => chunk.value,\n }) as TData,\n };\n }\n\n if (chunk.kind === \"append\") {\n return {\n ...nextBase,\n data: updateByParts({\n input: previousData,\n parts: pathParts,\n path,\n updateLeaf: (existing) => {\n if (existing === undefined) return [...chunk.items];\n if (!Array.isArray(existing)) {\n throw new Error(\n `Structured append requires path \"${path}\" to target an array, received ${describeValue(existing)}.`,\n );\n }\n return [...existing, ...chunk.items];\n },\n }) as TData,\n };\n }\n\n return {\n ...nextBase,\n data: updateByParts({\n input: previousData,\n parts: pathParts,\n path,\n updateLeaf: (existing) => {\n if (existing === undefined) return chunk.delta;\n if (typeof existing !== \"string\") {\n throw new Error(\n `Structured text-delta requires path \"${path}\" to target a string, received ${describeValue(existing)}.`,\n );\n }\n return existing + chunk.delta;\n },\n }) as TData,\n };\n}\n\nexport function reduceStructuredChunks<TData = unknown>(\n chunks: StructuredDataChunk[],\n): Record<string, StructuredStreamState<TData>> {\n return chunks.reduce<Record<string, StructuredStreamState<TData>>>(\n (acc, chunk) => {\n acc[chunk.streamId] = applyStructuredChunk(acc[chunk.streamId], chunk);\n return acc;\n },\n {},\n );\n}\n","import type { StreamChunk } from \"../types/stream-chunk\";\nimport type { StructuredDataChunk } from \"../types/structured-data\";\nimport {\n applyStructuredChunk,\n type StructuredStreamState,\n} from \"./apply-structured-chunk\";\n\nexport type StructuredStreamAccumulator<TData = unknown> = {\n apply: (chunk: StructuredDataChunk) => StructuredStreamState<TData>;\n applyStreamChunk: (\n chunk: StreamChunk,\n ) => StructuredStreamState<TData> | undefined;\n get: (streamId: string) => StructuredStreamState<TData> | undefined;\n has: (streamId: string) => boolean;\n delete: (streamId: string) => boolean;\n clear: () => void;\n size: () => number;\n entries: () => Array<[string, StructuredStreamState<TData>]>;\n values: () => StructuredStreamState<TData>[];\n toRecord: () => Record<string, StructuredStreamState<TData>>;\n};\n\nconst isStructuredDataChunk = (\n chunk: StreamChunk,\n): chunk is StructuredDataChunk => chunk.type === \"structured-data\";\n\nexport function createStructuredStreamAccumulator<TData = unknown>(\n initialChunks: Iterable<StructuredDataChunk> = [],\n): StructuredStreamAccumulator<TData> {\n const states = new Map<string, StructuredStreamState<TData>>();\n\n const apply = (chunk: StructuredDataChunk): StructuredStreamState<TData> => {\n const nextState = applyStructuredChunk(states.get(chunk.streamId), chunk);\n states.set(chunk.streamId, nextState);\n return nextState;\n };\n\n for (const chunk of initialChunks) {\n apply(chunk);\n }\n\n return {\n apply,\n applyStreamChunk: (chunk) => {\n if (!isStructuredDataChunk(chunk)) return undefined;\n return apply(chunk);\n },\n get: (streamId) => states.get(streamId),\n has: (streamId) => states.has(streamId),\n delete: (streamId) => states.delete(streamId),\n clear: () => {\n states.clear();\n },\n size: () => states.size,\n entries: () => Array.from(states.entries()),\n values: () => Array.from(states.values()),\n toRecord: () => Object.fromEntries(states.entries()),\n };\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as StreamChunk, a as StructuredDataChunk } from './browser-DBfCMmkm.js';
2
- export { C as ConsumeStreamHandlers, b as StreamChunkSchema, c as StreamFromRouteArgs, d as StructuredDataChunkSchema, e as StructuredStreamAccumulator, f as StructuredStreamState, g as applyStructuredChunk, h as consumeStream, i as createStructuredStreamAccumulator, r as readStream, j as reduceStructuredChunks, s as streamFromRoute } from './browser-DBfCMmkm.js';
1
+ import { S as StreamChunk, a as StructuredDataChunk } from './browser-BLO5Ge4b.js';
2
+ export { C as ConsumeStreamHandlers, b as StreamChunkSchema, c as StreamFromRouteArgs, d as StructuredDataChunkSchema, e as StructuredStreamAccumulator, f as StructuredStreamState, g as applyStructuredChunk, h as consumeStream, i as createStructuredStreamAccumulator, r as readStream, j as reduceStructuredChunks, s as streamFromRoute } from './browser-BLO5Ge4b.js';
3
3
  import 'zod';
4
4
 
5
5
  interface BufferedStreamResult {
package/dist/index.js CHANGED
@@ -39,10 +39,7 @@ module.exports = __toCommonJS(index_exports);
39
39
  // src/client/consume-stream.ts
40
40
  var toError = (value) => value instanceof Error ? value : new Error(String(value));
41
41
  async function consumeStream(stream, handlers = {}) {
42
- let doneCalled = false;
43
42
  const callDone = async () => {
44
- if (doneCalled) return;
45
- doneCalled = true;
46
43
  await handlers.onDone?.();
47
44
  };
48
45
  try {
@@ -78,7 +75,7 @@ async function* readStream(body) {
78
75
  if (done) break;
79
76
  buffer += decoder.decode(value, { stream: true });
80
77
  const parts = buffer.split("\n\n");
81
- buffer = parts.pop() ?? "";
78
+ buffer = parts.pop();
82
79
  for (const part of parts) {
83
80
  if (!part.startsWith("data: ")) continue;
84
81
  const payload = part.slice(6);
@@ -121,7 +118,8 @@ async function* streamFromRoute(args) {
121
118
  "content-type": "application/json",
122
119
  ...args.headers ?? {}
123
120
  },
124
- body: JSON.stringify(args.body)
121
+ body: JSON.stringify(args.body),
122
+ ...args.signal ? { signal: args.signal } : {}
125
123
  });
126
124
  } catch (error) {
127
125
  yield { type: "error", message: toErrorMessage(error) };
@@ -178,13 +176,7 @@ async function collectBufferedStream(stream) {
178
176
  };
179
177
  }
180
178
 
181
- // src/server/create-stream-response.ts
182
- var STREAM_HEADERS = {
183
- "content-type": "text/event-stream",
184
- "cache-control": "no-cache",
185
- connection: "keep-alive",
186
- "x-accel-buffering": "no"
187
- };
179
+ // src/server/json-to-sse.ts
188
180
  var JsonToSseTransformStream = class extends TransformStream {
189
181
  constructor() {
190
182
  super({
@@ -199,6 +191,14 @@ var JsonToSseTransformStream = class extends TransformStream {
199
191
  });
200
192
  }
201
193
  };
194
+
195
+ // src/server/create-stream-response.ts
196
+ var STREAM_HEADERS = {
197
+ "content-type": "text/event-stream",
198
+ "cache-control": "no-cache",
199
+ connection: "keep-alive",
200
+ "x-accel-buffering": "no"
201
+ };
202
202
  function createStreamResponse(stream) {
203
203
  const readable = new ReadableStream({
204
204
  async start(controller) {
@@ -209,7 +209,7 @@ function createStreamResponse(stream) {
209
209
  } catch (err) {
210
210
  controller.enqueue({
211
211
  type: "error",
212
- message: String(err?.message ?? err)
212
+ message: err instanceof Error ? err.message : String(err)
213
213
  });
214
214
  } finally {
215
215
  controller.close();
@@ -269,9 +269,6 @@ var cloneContainerForPart = (args) => {
269
269
  var updateByParts = (args) => {
270
270
  const traversed = args.traversed ?? [];
271
271
  const [part, ...rest] = args.parts;
272
- if (part === void 0) {
273
- return args.updateLeaf(args.input);
274
- }
275
272
  const container = cloneContainerForPart({
276
273
  current: args.input,
277
274
  part,
@@ -496,6 +493,35 @@ var StreamChunkSchema = import_zod2.z.union([
496
493
  node: import_zod2.z.string().optional(),
497
494
  content: import_zod2.z.unknown()
498
495
  }),
496
+ import_zod2.z.object({
497
+ type: import_zod2.z.literal("tool-call-start"),
498
+ tool: import_zod2.z.string(),
499
+ toolCallId: import_zod2.z.string(),
500
+ node: import_zod2.z.string().optional(),
501
+ id: import_zod2.z.string().optional(),
502
+ opId: import_zod2.z.string().optional(),
503
+ input: import_zod2.z.unknown().optional()
504
+ }),
505
+ import_zod2.z.object({
506
+ type: import_zod2.z.literal("tool-call-result"),
507
+ tool: import_zod2.z.string(),
508
+ toolCallId: import_zod2.z.string(),
509
+ node: import_zod2.z.string().optional(),
510
+ id: import_zod2.z.string().optional(),
511
+ opId: import_zod2.z.string().optional(),
512
+ content: import_zod2.z.unknown(),
513
+ structuredContent: import_zod2.z.unknown().optional(),
514
+ isError: import_zod2.z.boolean().optional()
515
+ }),
516
+ import_zod2.z.object({
517
+ type: import_zod2.z.literal("tool-call-error"),
518
+ tool: import_zod2.z.string(),
519
+ toolCallId: import_zod2.z.string(),
520
+ node: import_zod2.z.string().optional(),
521
+ id: import_zod2.z.string().optional(),
522
+ opId: import_zod2.z.string().optional(),
523
+ message: import_zod2.z.string()
524
+ }),
499
525
  // Interrupt request chunk (used to render interactive options in UI)
500
526
  import_zod2.z.object({
501
527
  type: import_zod2.z.literal("interrupt"),
@@ -516,7 +542,7 @@ var StreamChunkSchema = import_zod2.z.union([
516
542
  id: import_zod2.z.string().optional(),
517
543
  schemaId: import_zod2.z.string().optional(),
518
544
  schemaVersion: import_zod2.z.string().optional(),
519
- meta: import_zod2.z.record(import_zod2.z.unknown()).optional(),
545
+ meta: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
520
546
  options: import_zod2.z.array(import_zod2.z.never()).optional()
521
547
  }),
522
548
  // Choice/multi-choice: question + options required
@@ -527,7 +553,7 @@ var StreamChunkSchema = import_zod2.z.union([
527
553
  id: import_zod2.z.string().optional(),
528
554
  schemaId: import_zod2.z.string().optional(),
529
555
  schemaVersion: import_zod2.z.string().optional(),
530
- meta: import_zod2.z.record(import_zod2.z.unknown()).optional(),
556
+ meta: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
531
557
  options: import_zod2.z.array(
532
558
  import_zod2.z.object({
533
559
  id: import_zod2.z.string(),
@@ -537,7 +563,7 @@ var StreamChunkSchema = import_zod2.z.union([
537
563
  )
538
564
  })
539
565
  ]),
540
- meta: import_zod2.z.record(import_zod2.z.unknown()).optional()
566
+ meta: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional()
541
567
  }),
542
568
  StructuredDataChunkSchema,
543
569
  import_zod2.z.object({