ai-stream-utils 1.5.0 → 2.0.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.
@@ -0,0 +1,165 @@
1
+ import { JsonToSseTransformStream, parseJsonEventStream, uiMessageChunkSchema } from "ai";
2
+
3
+ //#region src/utils/convert-async-iterable-to-stream.ts
4
+ /**
5
+ * Converts an AsyncIterable to a ReadableStream.
6
+ * Copied from https://github.com/vercel/ai/blob/main/packages/provider-utils/src/convert-async-iterator-to-readable-stream.ts
7
+ */
8
+ function convertAsyncIterableToStream(iterable) {
9
+ const iterator = iterable[Symbol.asyncIterator]();
10
+ let cancelled = false;
11
+ return new ReadableStream({
12
+ async pull(controller) {
13
+ if (cancelled) return;
14
+ try {
15
+ const { value, done } = await iterator.next();
16
+ if (done) controller.close();
17
+ else controller.enqueue(value);
18
+ } catch (error) {
19
+ controller.error(error);
20
+ }
21
+ },
22
+ async cancel(reason) {
23
+ cancelled = true;
24
+ try {
25
+ await iterator.return?.(reason);
26
+ } catch {}
27
+ }
28
+ });
29
+ }
30
+
31
+ //#endregion
32
+ //#region src/utils/create-async-iterable-stream.ts
33
+ /**
34
+ * Converts a ReadableStream to an AsyncIterableStream.
35
+ * Copied from https://github.com/vercel/ai/blob/main/packages/ai/src/util/async-iterable-stream.ts
36
+ */
37
+ function createAsyncIterableStream(source) {
38
+ /** Pipe through a TransformStream to ensure a fresh, unlocked stream. */
39
+ const stream = source.pipeThrough(new TransformStream());
40
+ /** Implements the async iterator protocol for the stream. */
41
+ return Object.assign(stream, { [Symbol.asyncIterator]() {
42
+ const reader = stream.getReader();
43
+ let finished = false;
44
+ /** Cleans up the reader by cancelling and releasing the lock. */
45
+ async function cleanup(cancelStream) {
46
+ finished = true;
47
+ try {
48
+ if (cancelStream) await reader.cancel?.();
49
+ } finally {
50
+ try {
51
+ reader.releaseLock();
52
+ } catch {}
53
+ }
54
+ }
55
+ return {
56
+ async next() {
57
+ if (finished) return {
58
+ done: true,
59
+ value: void 0
60
+ };
61
+ const { done, value } = await reader.read();
62
+ if (done) {
63
+ await cleanup(true);
64
+ return {
65
+ done: true,
66
+ value: void 0
67
+ };
68
+ }
69
+ return {
70
+ done: false,
71
+ value
72
+ };
73
+ },
74
+ async return() {
75
+ await cleanup(true);
76
+ return {
77
+ done: true,
78
+ value: void 0
79
+ };
80
+ },
81
+ async throw(err) {
82
+ await cleanup(true);
83
+ throw err;
84
+ }
85
+ };
86
+ } });
87
+ }
88
+
89
+ //#endregion
90
+ //#region src/utils/convert-array-to-async-iterable.ts
91
+ /**
92
+ * Converts an array to an AsyncIterable.
93
+ */
94
+ async function* convertArrayToAsyncIterable(array) {
95
+ for (const item of array) yield item;
96
+ }
97
+
98
+ //#endregion
99
+ //#region src/utils/convert-array-to-stream.ts
100
+ /**
101
+ * Converts an array to a ReadableStream.
102
+ */
103
+ function convertArrayToStream(array) {
104
+ return new ReadableStream({ start(controller) {
105
+ for (const item of array) controller.enqueue(item);
106
+ controller.close();
107
+ } });
108
+ }
109
+
110
+ //#endregion
111
+ //#region src/utils/convert-async-iterable-to-array.ts
112
+ /**
113
+ * Converts an AsyncIterable to an array.
114
+ */
115
+ async function convertAsyncIterableToArray(iterable) {
116
+ const result = [];
117
+ for await (const item of iterable) result.push(item);
118
+ return result;
119
+ }
120
+
121
+ //#endregion
122
+ //#region src/utils/convert-sse-stream-to-ui-message-stream.ts
123
+ /**
124
+ * Converts an SSE stream to a UI message stream.
125
+ */
126
+ function convertSSEToUIMessageStream(stream) {
127
+ return parseJsonEventStream({
128
+ stream: stream.pipeThrough(new TextEncoderStream()),
129
+ schema: uiMessageChunkSchema
130
+ }).pipeThrough(new TransformStream({ transform(result, controller) {
131
+ if (result.success) controller.enqueue(result.value);
132
+ } }));
133
+ }
134
+
135
+ //#endregion
136
+ //#region src/utils/convert-stream-to-array.ts
137
+ /**
138
+ * Converts a ReadableStream to an array.
139
+ */
140
+ async function convertStreamToArray(stream) {
141
+ const reader = stream.getReader();
142
+ const result = [];
143
+ try {
144
+ while (true) {
145
+ const { done, value } = await reader.read();
146
+ if (done) break;
147
+ result.push(value);
148
+ }
149
+ } finally {
150
+ reader.releaseLock();
151
+ }
152
+ return result;
153
+ }
154
+
155
+ //#endregion
156
+ //#region src/utils/convert-ui-message-stream-to-sse-stream.ts
157
+ /**
158
+ * Converts a UI message stream to an SSE stream.
159
+ */
160
+ function convertUIMessageToSSEStream(stream) {
161
+ return stream.pipeThrough(new JsonToSseTransformStream());
162
+ }
163
+
164
+ //#endregion
165
+ export { convertArrayToStream as a, convertAsyncIterableToStream as c, convertAsyncIterableToArray as i, convertStreamToArray as n, convertArrayToAsyncIterable as o, convertSSEToUIMessageStream as r, createAsyncIterableStream as s, convertUIMessageToSSEStream as t };