assistant-stream 0.3.26 → 0.3.27

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.
Files changed (121) hide show
  1. package/dist/core/AssistantStream.d.ts.map +1 -1
  2. package/dist/core/AssistantStreamChunk.d.ts +3 -3
  3. package/dist/core/accumulators/AssistantMessageStream.d.ts.map +1 -1
  4. package/dist/core/accumulators/assistant-message-accumulator.d.ts.map +1 -1
  5. package/dist/core/accumulators/assistant-message-accumulator.js +65 -28
  6. package/dist/core/accumulators/assistant-message-accumulator.js.map +1 -1
  7. package/dist/core/converters/toGenericMessages.js.map +1 -1
  8. package/dist/core/gorp/GorpStreamAccumulator.d.ts +15 -0
  9. package/dist/core/gorp/GorpStreamAccumulator.d.ts.map +1 -0
  10. package/dist/core/{object/ObjectStreamAccumulator.js → gorp/GorpStreamAccumulator.js} +11 -9
  11. package/dist/core/gorp/GorpStreamAccumulator.js.map +1 -0
  12. package/dist/core/gorp/GorpStreamDeltaTracker.d.ts +17 -0
  13. package/dist/core/gorp/GorpStreamDeltaTracker.d.ts.map +1 -0
  14. package/dist/core/gorp/GorpStreamDeltaTracker.js +38 -0
  15. package/dist/core/gorp/GorpStreamDeltaTracker.js.map +1 -0
  16. package/dist/core/gorp/GorpStreamResponse.d.ts +16 -0
  17. package/dist/core/gorp/GorpStreamResponse.d.ts.map +1 -0
  18. package/dist/core/gorp/GorpStreamResponse.js +51 -0
  19. package/dist/core/gorp/GorpStreamResponse.js.map +1 -0
  20. package/dist/core/gorp/changeTree.d.ts +16 -0
  21. package/dist/core/gorp/changeTree.d.ts.map +1 -0
  22. package/dist/core/gorp/changeTree.js +77 -0
  23. package/dist/core/gorp/changeTree.js.map +1 -0
  24. package/dist/core/gorp/createGorpStream.d.ts +16 -0
  25. package/dist/core/gorp/createGorpStream.d.ts.map +1 -0
  26. package/dist/core/{object/createObjectStream.js → gorp/createGorpStream.js} +13 -8
  27. package/dist/core/gorp/createGorpStream.js.map +1 -0
  28. package/dist/core/{object → gorp}/types.d.ts +6 -5
  29. package/dist/core/gorp/types.d.ts.map +1 -0
  30. package/dist/core/modules/assistant-stream.d.ts +5 -4
  31. package/dist/core/modules/assistant-stream.d.ts.map +1 -1
  32. package/dist/core/modules/assistant-stream.js +10 -6
  33. package/dist/core/modules/assistant-stream.js.map +1 -1
  34. package/dist/core/modules/tool-call.js +2 -2
  35. package/dist/core/modules/tool-call.js.map +1 -1
  36. package/dist/core/serialization/assistant-transport/AssistantTransport.d.ts.map +1 -1
  37. package/dist/core/serialization/assistant-transport/AssistantTransport.js +91 -1
  38. package/dist/core/serialization/assistant-transport/AssistantTransport.js.map +1 -1
  39. package/dist/core/serialization/data-stream/chunk-types.d.ts +2 -2
  40. package/dist/core/serialization/data-stream/chunk-types.js.map +1 -1
  41. package/dist/core/serialization/ui-message-stream/UIMessageStream.d.ts.map +1 -1
  42. package/dist/core/serialization/ui-message-stream/UIMessageStream.js +11 -1
  43. package/dist/core/serialization/ui-message-stream/UIMessageStream.js.map +1 -1
  44. package/dist/core/tool/ToolCallReader.d.ts.map +1 -1
  45. package/dist/core/tool/ToolCallReader.js.map +1 -1
  46. package/dist/core/tool/ToolExecutionStream.d.ts.map +1 -1
  47. package/dist/core/tool/ToolExecutionStream.js +9 -1
  48. package/dist/core/tool/ToolExecutionStream.js.map +1 -1
  49. package/dist/core/tool/ToolResponse.d.ts.map +1 -1
  50. package/dist/core/tool/toolResultStream.d.ts.map +1 -1
  51. package/dist/core/tool/toolResultStream.js +7 -2
  52. package/dist/core/tool/toolResultStream.js.map +1 -1
  53. package/dist/core/utils/stream/AssistantTransformStream.d.ts.map +1 -1
  54. package/dist/core/utils/stream/PipeableTransformStream.d.ts.map +1 -1
  55. package/dist/core/utils/stream/SSEEventDecoder.d.ts.map +1 -1
  56. package/dist/core/utils/stream/merge.d.ts +2 -0
  57. package/dist/core/utils/stream/merge.d.ts.map +1 -1
  58. package/dist/core/utils/stream/merge.js +27 -8
  59. package/dist/core/utils/stream/merge.js.map +1 -1
  60. package/dist/core/utils/stream/path-utils.d.ts.map +1 -1
  61. package/dist/index.d.ts +25 -4
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +14 -3
  64. package/dist/index.js.map +1 -0
  65. package/dist/resumable/ResumableStreamContext.d.ts.map +1 -1
  66. package/dist/resumable/ResumableStreamContext.js +12 -5
  67. package/dist/resumable/ResumableStreamContext.js.map +1 -1
  68. package/dist/resumable/errors.d.ts.map +1 -1
  69. package/dist/resumable/stores/redis-impl.d.ts.map +1 -1
  70. package/dist/utils/AsyncIterableStream.d.ts.map +1 -1
  71. package/dist/utils/AsyncIterableStream.js +18 -3
  72. package/dist/utils/AsyncIterableStream.js.map +1 -1
  73. package/dist/utils/promiseWithResolvers.d.ts.map +1 -1
  74. package/package.json +2 -2
  75. package/src/core/AssistantStreamChunk.ts +3 -3
  76. package/src/core/accumulators/assistant-message-accumulator.test.ts +374 -1
  77. package/src/core/accumulators/assistant-message-accumulator.ts +75 -26
  78. package/src/core/{object/ObjectStream.test.ts → gorp/GorpStream.test.ts} +86 -25
  79. package/src/core/gorp/GorpStreamAccumulator.test.ts +28 -0
  80. package/src/core/{object/ObjectStreamAccumulator.ts → gorp/GorpStreamAccumulator.ts} +13 -15
  81. package/src/core/gorp/GorpStreamDeltaTracker.test.ts +182 -0
  82. package/src/core/gorp/GorpStreamDeltaTracker.ts +55 -0
  83. package/src/core/{object/ObjectStreamResponse.test.ts → gorp/GorpStreamResponse.test.ts} +6 -6
  84. package/src/core/gorp/GorpStreamResponse.ts +88 -0
  85. package/src/core/gorp/changeTree.test.ts +168 -0
  86. package/src/core/gorp/changeTree.ts +96 -0
  87. package/src/core/{object/createObjectStream.ts → gorp/createGorpStream.ts} +23 -17
  88. package/src/core/{object → gorp}/types.ts +5 -3
  89. package/src/core/modules/assistant-stream.test.ts +154 -2
  90. package/src/core/modules/assistant-stream.ts +16 -6
  91. package/src/core/modules/tool-call.test.ts +67 -0
  92. package/src/core/modules/tool-call.ts +3 -3
  93. package/src/core/serialization/assistant-transport/AssistantTransport.test.ts +174 -1
  94. package/src/core/serialization/assistant-transport/AssistantTransport.ts +77 -1
  95. package/src/core/serialization/data-stream/chunk-types.ts +2 -2
  96. package/src/core/serialization/ui-message-stream/UIMessageStream.test.ts +111 -0
  97. package/src/core/serialization/ui-message-stream/UIMessageStream.ts +20 -1
  98. package/src/core/tool/ToolExecutionStream.ts +10 -0
  99. package/src/core/tool/toolResultStream.test.ts +50 -0
  100. package/src/core/tool/toolResultStream.ts +7 -2
  101. package/src/core/utils/stream/merge.ts +31 -9
  102. package/src/gorp.test.ts +42 -0
  103. package/src/index.ts +21 -6
  104. package/src/resumable/ResumableStreamContext.test.ts +116 -1
  105. package/src/resumable/ResumableStreamContext.ts +32 -5
  106. package/src/resumable/createResumableAssistantStreamResponse.test.ts +1 -25
  107. package/src/utils/AsyncIterableStream.test.ts +61 -0
  108. package/src/utils/AsyncIterableStream.ts +18 -3
  109. package/dist/core/object/ObjectStreamAccumulator.d.ts +0 -15
  110. package/dist/core/object/ObjectStreamAccumulator.d.ts.map +0 -1
  111. package/dist/core/object/ObjectStreamAccumulator.js.map +0 -1
  112. package/dist/core/object/ObjectStreamResponse.d.ts +0 -16
  113. package/dist/core/object/ObjectStreamResponse.d.ts.map +0 -1
  114. package/dist/core/object/ObjectStreamResponse.js +0 -57
  115. package/dist/core/object/ObjectStreamResponse.js.map +0 -1
  116. package/dist/core/object/createObjectStream.d.ts +0 -16
  117. package/dist/core/object/createObjectStream.d.ts.map +0 -1
  118. package/dist/core/object/createObjectStream.js.map +0 -1
  119. package/dist/core/object/types.d.ts.map +0 -1
  120. package/src/core/object/ObjectStreamResponse.ts +0 -114
  121. /package/dist/core/{object → gorp}/types.js +0 -0
@@ -1,4 +1,5 @@
1
1
  import { ResumableStreamError } from "./errors";
2
+ import { withPromiseOrValue } from "../core/utils/withPromiseOrValue";
2
3
  import type {
3
4
  ResumableStreamRole,
4
5
  ResumableStreamStatus,
@@ -42,6 +43,21 @@ export interface ResumableStreamContext {
42
43
  delete(streamId: string): Promise<void>;
43
44
  }
44
45
 
46
+ const invokeObservabilityHook = <TArgs extends unknown[]>(
47
+ name: string,
48
+ hook: ((...args: TArgs) => void) | undefined,
49
+ ...args: TArgs
50
+ ): void => {
51
+ if (!hook) return;
52
+ void withPromiseOrValue(
53
+ () => hook(...args),
54
+ () => {},
55
+ (error) => {
56
+ console.error(`resumable stream ${name} hook failed:`, error);
57
+ },
58
+ );
59
+ };
60
+
45
61
  export function createResumableStreamContext(
46
62
  options: ResumableStreamContextOptions,
47
63
  ): ResumableStreamContext {
@@ -53,7 +69,7 @@ export function createResumableStreamContext(
53
69
  return {
54
70
  async run(streamId, makeStream) {
55
71
  const role = await store.acquire(streamId, acquireOptions);
56
- onAcquire?.(streamId, role);
72
+ invokeObservabilityHook("onAcquire", onAcquire, streamId, role);
57
73
  if (role === "producer") {
58
74
  startProducerTask(store, streamId, makeStream, {
59
75
  waitUntil,
@@ -119,13 +135,18 @@ function startProducerTask(
119
135
  const { done, value } = await reader.read();
120
136
  if (done) break;
121
137
  await store.append(streamId, value);
122
- onAppend?.(streamId, value.byteLength);
138
+ invokeObservabilityHook(
139
+ "onAppend",
140
+ onAppend,
141
+ streamId,
142
+ value.byteLength,
143
+ );
123
144
  }
124
145
  await store.finalize(streamId, "done");
125
- onFinalize?.(streamId, "done");
146
+ invokeObservabilityHook("onFinalize", onFinalize, streamId, "done");
126
147
  } catch (err) {
127
148
  cancelled = true;
128
- onError?.(streamId, err);
149
+ invokeObservabilityHook("onError", onError, streamId, err);
129
150
  const message = err instanceof Error ? err.message : String(err);
130
151
  try {
131
152
  await reader?.cancel(err);
@@ -134,7 +155,13 @@ function startProducerTask(
134
155
  }
135
156
  try {
136
157
  await store.finalize(streamId, "error", message);
137
- onFinalize?.(streamId, "error", message);
158
+ invokeObservabilityHook(
159
+ "onFinalize",
160
+ onFinalize,
161
+ streamId,
162
+ "error",
163
+ message,
164
+ );
138
165
  } catch (finalizeErr) {
139
166
  console.error("resumable stream finalize failed:", finalizeErr);
140
167
  }
@@ -1,4 +1,4 @@
1
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
1
+ import { describe, expect, it } from "vitest";
2
2
  import {
3
3
  RESUMABLE_STREAM_ID_HEADER,
4
4
  createResumableAssistantStreamResponse,
@@ -140,25 +140,6 @@ describe("createResumableAssistantStreamResponse", () => {
140
140
  });
141
141
 
142
142
  describe("producer crash", () => {
143
- let suppressed: unknown[];
144
- let original: NodeJS.UnhandledRejectionListener[];
145
- const swallow: NodeJS.UnhandledRejectionListener = (reason) => {
146
- suppressed.push(reason);
147
- };
148
-
149
- beforeEach(() => {
150
- suppressed = [];
151
- original = process.listeners("unhandledRejection");
152
- for (const l of original) process.off("unhandledRejection", l);
153
- process.on("unhandledRejection", swallow);
154
- });
155
-
156
- afterEach(async () => {
157
- await new Promise((r) => setTimeout(r, 20));
158
- process.off("unhandledRejection", swallow);
159
- for (const l of original) process.on("unhandledRejection", l);
160
- });
161
-
162
143
  it("synchronous callback throw is encoded into the body and finalizes the stream", async () => {
163
144
  const ctx = createResumableStreamContext({
164
145
  store: createInMemoryResumableStreamStore(),
@@ -184,11 +165,6 @@ describe("createResumableAssistantStreamResponse", () => {
184
165
  expect(replay).not.toBeNull();
185
166
  const replayBytes = await new Response(replay).arrayBuffer();
186
167
  expect(new Uint8Array(replayBytes)).toEqual(new Uint8Array(firstBytes));
187
-
188
- while (suppressed.length === 0) {
189
- await new Promise((r) => setTimeout(r, 5));
190
- }
191
- expect(suppressed.map((e) => (e as Error).message)).toContain("boom");
192
168
  });
193
169
  });
194
170
 
@@ -0,0 +1,61 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { asAsyncIterableStream } from "./AsyncIterableStream";
3
+
4
+ const forcePolyfilledIterator = <T>(
5
+ stream: ReadableStream<T>,
6
+ ): AsyncIterable<T> & ReadableStream<T> => {
7
+ Object.defineProperty(stream, Symbol.asyncIterator, {
8
+ configurable: true,
9
+ value: undefined,
10
+ writable: true,
11
+ });
12
+ return asAsyncIterableStream(stream);
13
+ };
14
+
15
+ describe("asAsyncIterableStream", () => {
16
+ it("cancels the source when iteration stops early", async () => {
17
+ const cancel = vi.fn();
18
+ const stream = forcePolyfilledIterator(
19
+ new ReadableStream<string>({
20
+ start(controller) {
21
+ controller.enqueue("first");
22
+ controller.enqueue("second");
23
+ },
24
+ cancel,
25
+ }),
26
+ );
27
+
28
+ const values: string[] = [];
29
+ for await (const value of stream) {
30
+ values.push(value);
31
+ break;
32
+ }
33
+
34
+ expect(values).toEqual(["first"]);
35
+ expect(cancel).toHaveBeenCalledOnce();
36
+ expect(stream.locked).toBe(false);
37
+ });
38
+
39
+ it("does not cancel a fully consumed source", async () => {
40
+ const cancel = vi.fn();
41
+ const stream = forcePolyfilledIterator(
42
+ new ReadableStream<string>({
43
+ start(controller) {
44
+ controller.enqueue("first");
45
+ controller.enqueue("second");
46
+ controller.close();
47
+ },
48
+ cancel,
49
+ }),
50
+ );
51
+
52
+ const values: string[] = [];
53
+ for await (const value of stream) {
54
+ values.push(value);
55
+ }
56
+
57
+ expect(values).toEqual(["first", "second"]);
58
+ expect(cancel).not.toHaveBeenCalled();
59
+ expect(stream.locked).toBe(false);
60
+ });
61
+ });
@@ -4,14 +4,29 @@ async function* streamGeneratorPolyfill<T>(
4
4
  this: ReadableStream<T>,
5
5
  ): AsyncGenerator<T, undefined, unknown> {
6
6
  const reader = this.getReader();
7
+ let shouldCancel = true;
7
8
  try {
8
9
  while (true) {
9
- const { done, value } = await reader.read();
10
- if (done) break;
10
+ let result: ReadableStreamReadResult<T>;
11
+ try {
12
+ result = await reader.read();
13
+ } catch (error) {
14
+ shouldCancel = false;
15
+ throw error;
16
+ }
17
+ if (result.done) {
18
+ shouldCancel = false;
19
+ break;
20
+ }
21
+ const { value } = result;
11
22
  yield value;
12
23
  }
13
24
  } finally {
14
- reader.releaseLock();
25
+ try {
26
+ if (shouldCancel) await reader.cancel();
27
+ } finally {
28
+ reader.releaseLock();
29
+ }
15
30
  }
16
31
  }
17
32
 
@@ -1,15 +0,0 @@
1
- import { ReadonlyJSONValue } from "../../utils/json/json-value.js";
2
- import "../../utils.js";
3
- import { ObjectStreamOperation } from "./types.js";
4
- //#region src/core/object/ObjectStreamAccumulator.d.ts
5
- declare class ObjectStreamAccumulator {
6
- private _state;
7
- constructor(initialValue?: ReadonlyJSONValue);
8
- get state(): ReadonlyJSONValue;
9
- append(ops: readonly ObjectStreamOperation[]): void;
10
- private static apply;
11
- private static updatePath;
12
- }
13
- //#endregion
14
- export { ObjectStreamAccumulator };
15
- //# sourceMappingURL=ObjectStreamAccumulator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ObjectStreamAccumulator.d.ts","names":[],"sources":["../../../src/core/object/ObjectStreamAccumulator.ts"],"mappings":";;;;cAGa;UACH;cAEI,eAAc;MAItB,SAAK;EAIT,OAAO,cAAc;iBAON;iBAuBA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ObjectStreamAccumulator.js","names":["_exhaustiveCheck"],"sources":["../../../src/core/object/ObjectStreamAccumulator.ts"],"sourcesContent":["import type { ReadonlyJSONValue, ReadonlyJSONObject } from \"../../utils\";\nimport type { ObjectStreamOperation } from \"./types\";\n\nexport class ObjectStreamAccumulator {\n private _state: ReadonlyJSONValue;\n\n constructor(initialValue: ReadonlyJSONValue = null) {\n this._state = initialValue;\n }\n\n get state() {\n return this._state;\n }\n\n append(ops: readonly ObjectStreamOperation[]) {\n this._state = ops.reduce(\n (state, op) => ObjectStreamAccumulator.apply(state, op),\n this._state,\n );\n }\n\n private static apply(state: ReadonlyJSONValue, op: ObjectStreamOperation) {\n const type = op.type;\n switch (type) {\n case \"set\":\n return ObjectStreamAccumulator.updatePath(\n state,\n op.path,\n () => op.value,\n );\n case \"append-text\":\n return ObjectStreamAccumulator.updatePath(state, op.path, (current) => {\n if (typeof current !== \"string\")\n throw new Error(`Expected string at path [${op.path.join(\", \")}]`);\n return current + op.value;\n });\n\n default: {\n const _exhaustiveCheck: never = type;\n throw new Error(`Invalid operation type: ${_exhaustiveCheck}`);\n }\n }\n }\n\n private static updatePath(\n state: ReadonlyJSONValue | undefined,\n path: readonly string[],\n updater: (current: ReadonlyJSONValue | undefined) => ReadonlyJSONValue,\n ): ReadonlyJSONValue {\n if (path.length === 0) return updater(state);\n\n // Initialize state as empty object if it's null and we're trying to set a property\n state ??= {};\n\n if (typeof state !== \"object\") {\n throw new Error(`Invalid path: [${path.join(\", \")}]`);\n }\n\n const [key, ...rest] = path as [string, ...(readonly string[])];\n if (Array.isArray(state)) {\n const idx = Number(key);\n if (Number.isNaN(idx))\n throw new Error(`Expected array index at [${path.join(\", \")}]`);\n if (idx > state.length || idx < 0)\n throw new Error(`Insert array index out of bounds`);\n\n const nextState = [...state];\n nextState[idx] = ObjectStreamAccumulator.updatePath(\n nextState[idx],\n rest,\n updater,\n );\n\n return nextState;\n }\n\n const nextState = { ...(state as ReadonlyJSONObject) };\n nextState[key] = ObjectStreamAccumulator.updatePath(\n nextState[key],\n rest,\n updater,\n );\n\n return nextState;\n }\n}\n"],"mappings":";AAGA,IAAa,0BAAb,MAAa,wBAAwB;CACnC;CAEA,YAAY,eAAkC,MAAM;EAClD,KAAK,SAAS;CAChB;CAEA,IAAI,QAAQ;EACV,OAAO,KAAK;CACd;CAEA,OAAO,KAAuC;EAC5C,KAAK,SAAS,IAAI,QACf,OAAO,OAAO,wBAAwB,MAAM,OAAO,EAAE,GACtD,KAAK,MACP;CACF;CAEA,OAAe,MAAM,OAA0B,IAA2B;EACxE,MAAM,OAAO,GAAG;EAChB,QAAQ,MAAR;GACE,KAAK,OACH,OAAO,wBAAwB,WAC7B,OACA,GAAG,YACG,GAAG,KACX;GACF,KAAK,eACH,OAAO,wBAAwB,WAAW,OAAO,GAAG,OAAO,YAAY;IACrE,IAAI,OAAO,YAAY,UACrB,MAAM,IAAI,MAAM,4BAA4B,GAAG,KAAK,KAAK,IAAI,EAAE,EAAE;IACnE,OAAO,UAAU,GAAG;GACtB,CAAC;GAEH,SAEE,MAAM,IAAI,MAAM,2BAA2BA,MAAkB;EAEjE;CACF;CAEA,OAAe,WACb,OACA,MACA,SACmB;EACnB,IAAI,KAAK,WAAW,GAAG,OAAO,QAAQ,KAAK;EAG3C,UAAU,CAAC;EAEX,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,MAAM,kBAAkB,KAAK,KAAK,IAAI,EAAE,EAAE;EAGtD,MAAM,CAAC,KAAK,GAAG,QAAQ;EACvB,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,MAAM,MAAM,OAAO,GAAG;GACtB,IAAI,OAAO,MAAM,GAAG,GAClB,MAAM,IAAI,MAAM,4BAA4B,KAAK,KAAK,IAAI,EAAE,EAAE;GAChE,IAAI,MAAM,MAAM,UAAU,MAAM,GAC9B,MAAM,IAAI,MAAM,kCAAkC;GAEpD,MAAM,YAAY,CAAC,GAAG,KAAK;GAC3B,UAAU,OAAO,wBAAwB,WACvC,UAAU,MACV,MACA,OACF;GAEA,OAAO;EACT;EAEA,MAAM,YAAY,EAAE,GAAI,MAA6B;EACrD,UAAU,OAAO,wBAAwB,WACvC,UAAU,MACV,MACA,OACF;EAEA,OAAO;CACT;AACF"}
@@ -1,16 +0,0 @@
1
- import { ObjectStreamChunk } from "./types.js";
2
- import { PipeableTransformStream } from "../utils/stream/PipeableTransformStream.js";
3
- //#region src/core/object/ObjectStreamResponse.d.ts
4
- declare class ObjectStreamEncoder extends PipeableTransformStream<ObjectStreamChunk, Uint8Array> {
5
- constructor();
6
- }
7
- declare class ObjectStreamDecoder extends PipeableTransformStream<Uint8Array<ArrayBuffer>, ObjectStreamChunk> {
8
- constructor();
9
- }
10
- declare class ObjectStreamResponse extends Response {
11
- constructor(body: ReadableStream<ObjectStreamChunk>);
12
- }
13
- declare const fromObjectStreamResponse: (response: Response) => ReadableStream<ObjectStreamChunk>;
14
- //#endregion
15
- export { ObjectStreamDecoder, ObjectStreamEncoder, ObjectStreamResponse, fromObjectStreamResponse };
16
- //# sourceMappingURL=ObjectStreamResponse.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ObjectStreamResponse.d.ts","names":[],"sources":["../../../src/core/object/ObjectStreamResponse.ts"],"mappings":";;;cAKa,4BAA4B,wBACvC,mBACA;;;cAgDW,4BAA4B,wBACvC,WAAW,cACX;;;cAyBW,6BAA6B;cAC5B,MAAM,eAAe;;cAYtB,2BACX,UAAU,aACT,eAAe"}
@@ -1,57 +0,0 @@
1
- import { PipeableTransformStream } from "../utils/stream/PipeableTransformStream.js";
2
- import { ObjectStreamAccumulator } from "./ObjectStreamAccumulator.js";
3
- import { SSEDecoder, SSEEncoder } from "../utils/stream/SSE.js";
4
- //#region src/core/object/ObjectStreamResponse.ts
5
- var ObjectStreamEncoder = class extends PipeableTransformStream {
6
- constructor() {
7
- super((readable) => readable.pipeThrough((() => {
8
- class ObjectStreamTransformer {
9
- #isFirstChunk = true;
10
- start() {}
11
- transform(chunk, controller) {
12
- if (this.#isFirstChunk && chunk.snapshot && Object.keys(chunk.snapshot).length > 0) controller.enqueue([{
13
- type: "set",
14
- path: [],
15
- value: chunk.snapshot
16
- }, ...chunk.operations]);
17
- else controller.enqueue(chunk.operations);
18
- this.#isFirstChunk = false;
19
- }
20
- }
21
- return new TransformStream(new ObjectStreamTransformer());
22
- })()).pipeThrough(new SSEEncoder()));
23
- }
24
- };
25
- var ObjectStreamDecoder = class extends PipeableTransformStream {
26
- constructor() {
27
- const accumulator = new ObjectStreamAccumulator();
28
- super((readable) => readable.pipeThrough(new SSEDecoder()).pipeThrough(new TransformStream({ transform(operations, controller) {
29
- accumulator.append(operations);
30
- controller.enqueue({
31
- snapshot: accumulator.state,
32
- operations
33
- });
34
- } })));
35
- }
36
- };
37
- var ObjectStreamResponse = class extends Response {
38
- constructor(body) {
39
- super(body.pipeThrough(new ObjectStreamEncoder()), { headers: new Headers({
40
- "Content-Type": "text/event-stream",
41
- "Cache-Control": "no-cache",
42
- Connection: "keep-alive",
43
- "Assistant-Stream-Format": "object-stream/v0"
44
- }) });
45
- }
46
- };
47
- const fromObjectStreamResponse = (response) => {
48
- if (!response.ok) throw new Error(`Response failed, status ${response.status}`);
49
- if (!response.body) throw new Error("Response body is null");
50
- if (response.headers.get("Content-Type")?.split(";", 1)[0]?.trim().toLowerCase() !== "text/event-stream") throw new Error("Response is not an event stream");
51
- if (response.headers.get("Assistant-Stream-Format") !== "object-stream/v0") throw new Error("Unsupported Assistant-Stream-Format header");
52
- return response.body.pipeThrough(new ObjectStreamDecoder());
53
- };
54
- //#endregion
55
- export { ObjectStreamDecoder, ObjectStreamEncoder, ObjectStreamResponse, fromObjectStreamResponse };
56
-
57
- //# sourceMappingURL=ObjectStreamResponse.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ObjectStreamResponse.js","names":["#isFirstChunk"],"sources":["../../../src/core/object/ObjectStreamResponse.ts"],"sourcesContent":["import { PipeableTransformStream } from \"../utils/stream/PipeableTransformStream\";\nimport { ObjectStreamAccumulator } from \"./ObjectStreamAccumulator\";\nimport { SSEDecoder, SSEEncoder } from \"../utils/stream/SSE\";\nimport type { ObjectStreamChunk, ObjectStreamOperation } from \"./types\";\n\nexport class ObjectStreamEncoder extends PipeableTransformStream<\n ObjectStreamChunk,\n Uint8Array\n> {\n constructor() {\n super((readable) =>\n readable\n .pipeThrough(\n (() => {\n class ObjectStreamTransformer implements Transformer<\n ObjectStreamChunk,\n readonly ObjectStreamOperation[]\n > {\n #isFirstChunk = true;\n\n start() {\n // Nothing needed here since we initialize in the field declaration\n }\n\n transform(\n chunk: ObjectStreamChunk,\n controller: TransformStreamDefaultController<\n readonly ObjectStreamOperation[]\n >,\n ) {\n if (\n this.#isFirstChunk &&\n chunk.snapshot &&\n Object.keys(chunk.snapshot).length > 0\n ) {\n // For the first chunk, if there's an initial state that's not empty,\n // prepend a set operation for the initial state\n controller.enqueue([\n { type: \"set\", path: [], value: chunk.snapshot },\n ...chunk.operations,\n ]);\n } else {\n controller.enqueue(chunk.operations);\n }\n this.#isFirstChunk = false;\n }\n }\n return new TransformStream(new ObjectStreamTransformer());\n })(),\n )\n .pipeThrough(new SSEEncoder()),\n );\n }\n}\n\nexport class ObjectStreamDecoder extends PipeableTransformStream<\n Uint8Array<ArrayBuffer>,\n ObjectStreamChunk\n> {\n constructor() {\n const accumulator = new ObjectStreamAccumulator();\n super((readable) =>\n readable\n .pipeThrough(new SSEDecoder<readonly ObjectStreamOperation[]>())\n .pipeThrough(\n new TransformStream<\n readonly ObjectStreamOperation[],\n ObjectStreamChunk\n >({\n transform(operations, controller) {\n accumulator.append(operations);\n controller.enqueue({\n snapshot: accumulator.state,\n operations,\n });\n },\n }),\n ),\n );\n }\n}\n\nexport class ObjectStreamResponse extends Response {\n constructor(body: ReadableStream<ObjectStreamChunk>) {\n super(body.pipeThrough(new ObjectStreamEncoder()), {\n headers: new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Assistant-Stream-Format\": \"object-stream/v0\",\n }),\n });\n }\n}\n\nexport const fromObjectStreamResponse = (\n response: Response,\n): ReadableStream<ObjectStreamChunk> => {\n if (!response.ok)\n throw new Error(`Response failed, status ${response.status}`);\n if (!response.body) throw new Error(\"Response body is null\");\n const mediaType = response.headers\n .get(\"Content-Type\")\n ?.split(\";\", 1)[0]\n ?.trim()\n .toLowerCase();\n if (mediaType !== \"text/event-stream\") {\n throw new Error(\"Response is not an event stream\");\n }\n if (response.headers.get(\"Assistant-Stream-Format\") !== \"object-stream/v0\") {\n throw new Error(\"Unsupported Assistant-Stream-Format header\");\n }\n return response.body.pipeThrough(new ObjectStreamDecoder());\n};\n"],"mappings":";;;;AAKA,IAAa,sBAAb,cAAyC,wBAGvC;CACA,cAAc;EACZ,OAAO,aACL,SACG,mBACQ;GACL,MAAM,wBAGJ;IACA,gBAAgB;IAEhB,QAAQ,CAER;IAEA,UACE,OACA,YAGA;KACA,IACE,KAAKA,iBACL,MAAM,YACN,OAAO,KAAK,MAAM,QAAQ,CAAC,CAAC,SAAS,GAIrC,WAAW,QAAQ,CACjB;MAAE,MAAM;MAAO,MAAM,CAAC;MAAG,OAAO,MAAM;KAAS,GAC/C,GAAG,MAAM,UACX,CAAC;UAED,WAAW,QAAQ,MAAM,UAAU;KAErC,KAAKA,gBAAgB;IACvB;GACF;GACA,OAAO,IAAI,gBAAgB,IAAI,wBAAwB,CAAC;EAC1D,EAAA,CAAG,CACL,CAAC,CACA,YAAY,IAAI,WAAW,CAAC,CACjC;CACF;AACF;AAEA,IAAa,sBAAb,cAAyC,wBAGvC;CACA,cAAc;EACZ,MAAM,cAAc,IAAI,wBAAwB;EAChD,OAAO,aACL,SACG,YAAY,IAAI,WAA6C,CAAC,CAAC,CAC/D,YACC,IAAI,gBAGF,EACA,UAAU,YAAY,YAAY;GAChC,YAAY,OAAO,UAAU;GAC7B,WAAW,QAAQ;IACjB,UAAU,YAAY;IACtB;GACF,CAAC;EACH,EACF,CAAC,CACH,CACJ;CACF;AACF;AAEA,IAAa,uBAAb,cAA0C,SAAS;CACjD,YAAY,MAAyC;EACnD,MAAM,KAAK,YAAY,IAAI,oBAAoB,CAAC,GAAG,EACjD,SAAS,IAAI,QAAQ;GACnB,gBAAgB;GAChB,iBAAiB;GACjB,YAAY;GACZ,2BAA2B;EAC7B,CAAC,EACH,CAAC;CACH;AACF;AAEA,MAAa,4BACX,aACsC;CACtC,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,2BAA2B,SAAS,QAAQ;CAC9D,IAAI,CAAC,SAAS,MAAM,MAAM,IAAI,MAAM,uBAAuB;CAM3D,IALkB,SAAS,QACxB,IAAI,cAAc,CAAC,EAClB,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,EAChB,KAAK,CAAC,CACP,YAAY,MACG,qBAChB,MAAM,IAAI,MAAM,iCAAiC;CAEnD,IAAI,SAAS,QAAQ,IAAI,yBAAyB,MAAM,oBACtD,MAAM,IAAI,MAAM,4CAA4C;CAE9D,OAAO,SAAS,KAAK,YAAY,IAAI,oBAAoB,CAAC;AAC5D"}
@@ -1,16 +0,0 @@
1
- import { ReadonlyJSONValue } from "../../utils/json/json-value.js";
2
- import "../../utils.js";
3
- import { ObjectStreamChunk, ObjectStreamOperation } from "./types.js";
4
- //#region src/core/object/createObjectStream.d.ts
5
- type ObjectStreamController = {
6
- readonly abortSignal: AbortSignal;
7
- enqueue(operations: readonly ObjectStreamOperation[]): void;
8
- };
9
- type CreateObjectStreamOptions = {
10
- execute: (controller: ObjectStreamController) => void | PromiseLike<void>;
11
- defaultValue?: ReadonlyJSONValue;
12
- };
13
- declare const createObjectStream: ({ execute, defaultValue }: CreateObjectStreamOptions) => ReadableStream<ObjectStreamChunk>;
14
- //#endregion
15
- export { createObjectStream };
16
- //# sourceMappingURL=createObjectStream.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createObjectStream.d.ts","names":[],"sources":["../../../src/core/object/createObjectStream.ts"],"mappings":";;;;KAKK;WACM,aAAa;EAEtB,QAAQ,qBAAqB;;KAwD1B;EACH,UAAU,YAAY,kCAAkC;EACxD,eAAe;;cAGJ,uBAAsB,SAAA,gBAGhC,8BAAyB,eAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"createObjectStream.js","names":[],"sources":["../../../src/core/object/createObjectStream.ts"],"sourcesContent":["import type { ReadonlyJSONValue } from \"../../utils\";\nimport { withPromiseOrValue } from \"../utils/withPromiseOrValue\";\nimport { ObjectStreamAccumulator } from \"./ObjectStreamAccumulator\";\nimport type { ObjectStreamOperation, ObjectStreamChunk } from \"./types\";\n\ntype ObjectStreamController = {\n readonly abortSignal: AbortSignal;\n\n enqueue(operations: readonly ObjectStreamOperation[]): void;\n};\n\nclass ObjectStreamControllerImpl implements ObjectStreamController {\n private _controller: ReadableStreamDefaultController<ObjectStreamChunk>;\n private _abortController = new AbortController();\n private _accumulator: ObjectStreamAccumulator;\n\n get abortSignal() {\n return this._abortController.signal;\n }\n\n constructor(\n controller: ReadableStreamDefaultController<ObjectStreamChunk>,\n defaultValue: ReadonlyJSONValue,\n ) {\n this._controller = controller;\n this._accumulator = new ObjectStreamAccumulator(defaultValue);\n }\n\n enqueue(operations: readonly ObjectStreamOperation[]) {\n this._accumulator.append(operations);\n\n this._controller.enqueue({\n snapshot: this._accumulator.state,\n operations,\n });\n }\n\n __internalError(error: unknown) {\n this._controller.error(error);\n }\n\n __internalClose() {\n this._controller.close();\n }\n\n __internalCancel(reason?: unknown) {\n this._abortController.abort(reason);\n }\n}\n\nconst getStreamControllerPair = (defaultValue: ReadonlyJSONValue) => {\n let controller!: ObjectStreamControllerImpl;\n const stream = new ReadableStream<ObjectStreamChunk>({\n start(c) {\n controller = new ObjectStreamControllerImpl(c, defaultValue);\n },\n cancel(reason: unknown) {\n controller.__internalCancel(reason);\n },\n });\n\n return [stream, controller] as const;\n};\n\ntype CreateObjectStreamOptions = {\n execute: (controller: ObjectStreamController) => void | PromiseLike<void>;\n defaultValue?: ReadonlyJSONValue;\n};\n\nexport const createObjectStream = ({\n execute,\n defaultValue = {},\n}: CreateObjectStreamOptions) => {\n const [stream, controller] = getStreamControllerPair(defaultValue);\n\n withPromiseOrValue(\n () => execute(controller),\n () => {\n controller.__internalClose();\n },\n (e: unknown) => {\n controller.__internalError(e);\n },\n );\n\n return stream;\n};\n"],"mappings":";;;AAWA,IAAM,6BAAN,MAAmE;CACjE;CACA,mBAA2B,IAAI,gBAAgB;CAC/C;CAEA,IAAI,cAAc;EAChB,OAAO,KAAK,iBAAiB;CAC/B;CAEA,YACE,YACA,cACA;EACA,KAAK,cAAc;EACnB,KAAK,eAAe,IAAI,wBAAwB,YAAY;CAC9D;CAEA,QAAQ,YAA8C;EACpD,KAAK,aAAa,OAAO,UAAU;EAEnC,KAAK,YAAY,QAAQ;GACvB,UAAU,KAAK,aAAa;GAC5B;EACF,CAAC;CACH;CAEA,gBAAgB,OAAgB;EAC9B,KAAK,YAAY,MAAM,KAAK;CAC9B;CAEA,kBAAkB;EAChB,KAAK,YAAY,MAAM;CACzB;CAEA,iBAAiB,QAAkB;EACjC,KAAK,iBAAiB,MAAM,MAAM;CACpC;AACF;AAEA,MAAM,2BAA2B,iBAAoC;CACnE,IAAI;CAUJ,OAAO,CAAC,IATW,eAAkC;EACnD,MAAM,GAAG;GACP,aAAa,IAAI,2BAA2B,GAAG,YAAY;EAC7D;EACA,OAAO,QAAiB;GACtB,WAAW,iBAAiB,MAAM;EACpC;CACF,CAEa,GAAG,UAAU;AAC5B;AAOA,MAAa,sBAAsB,EACjC,SACA,eAAe,CAAC,QACe;CAC/B,MAAM,CAAC,QAAQ,cAAc,wBAAwB,YAAY;CAEjE,yBACQ,QAAQ,UAAU,SAClB;EACJ,WAAW,gBAAgB;CAC7B,IACC,MAAe;EACd,WAAW,gBAAgB,CAAC;CAC9B,CACF;CAEA,OAAO;AACT"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/core/object/types.ts"],"mappings":";;;KAEY;WAEG;WACA;WACA,OAAO;;WAGP;WACA;WACA;;KAGH;WACD,UAAU;WACV,qBAAqB"}
@@ -1,114 +0,0 @@
1
- import { PipeableTransformStream } from "../utils/stream/PipeableTransformStream";
2
- import { ObjectStreamAccumulator } from "./ObjectStreamAccumulator";
3
- import { SSEDecoder, SSEEncoder } from "../utils/stream/SSE";
4
- import type { ObjectStreamChunk, ObjectStreamOperation } from "./types";
5
-
6
- export class ObjectStreamEncoder extends PipeableTransformStream<
7
- ObjectStreamChunk,
8
- Uint8Array
9
- > {
10
- constructor() {
11
- super((readable) =>
12
- readable
13
- .pipeThrough(
14
- (() => {
15
- class ObjectStreamTransformer implements Transformer<
16
- ObjectStreamChunk,
17
- readonly ObjectStreamOperation[]
18
- > {
19
- #isFirstChunk = true;
20
-
21
- start() {
22
- // Nothing needed here since we initialize in the field declaration
23
- }
24
-
25
- transform(
26
- chunk: ObjectStreamChunk,
27
- controller: TransformStreamDefaultController<
28
- readonly ObjectStreamOperation[]
29
- >,
30
- ) {
31
- if (
32
- this.#isFirstChunk &&
33
- chunk.snapshot &&
34
- Object.keys(chunk.snapshot).length > 0
35
- ) {
36
- // For the first chunk, if there's an initial state that's not empty,
37
- // prepend a set operation for the initial state
38
- controller.enqueue([
39
- { type: "set", path: [], value: chunk.snapshot },
40
- ...chunk.operations,
41
- ]);
42
- } else {
43
- controller.enqueue(chunk.operations);
44
- }
45
- this.#isFirstChunk = false;
46
- }
47
- }
48
- return new TransformStream(new ObjectStreamTransformer());
49
- })(),
50
- )
51
- .pipeThrough(new SSEEncoder()),
52
- );
53
- }
54
- }
55
-
56
- export class ObjectStreamDecoder extends PipeableTransformStream<
57
- Uint8Array<ArrayBuffer>,
58
- ObjectStreamChunk
59
- > {
60
- constructor() {
61
- const accumulator = new ObjectStreamAccumulator();
62
- super((readable) =>
63
- readable
64
- .pipeThrough(new SSEDecoder<readonly ObjectStreamOperation[]>())
65
- .pipeThrough(
66
- new TransformStream<
67
- readonly ObjectStreamOperation[],
68
- ObjectStreamChunk
69
- >({
70
- transform(operations, controller) {
71
- accumulator.append(operations);
72
- controller.enqueue({
73
- snapshot: accumulator.state,
74
- operations,
75
- });
76
- },
77
- }),
78
- ),
79
- );
80
- }
81
- }
82
-
83
- export class ObjectStreamResponse extends Response {
84
- constructor(body: ReadableStream<ObjectStreamChunk>) {
85
- super(body.pipeThrough(new ObjectStreamEncoder()), {
86
- headers: new Headers({
87
- "Content-Type": "text/event-stream",
88
- "Cache-Control": "no-cache",
89
- Connection: "keep-alive",
90
- "Assistant-Stream-Format": "object-stream/v0",
91
- }),
92
- });
93
- }
94
- }
95
-
96
- export const fromObjectStreamResponse = (
97
- response: Response,
98
- ): ReadableStream<ObjectStreamChunk> => {
99
- if (!response.ok)
100
- throw new Error(`Response failed, status ${response.status}`);
101
- if (!response.body) throw new Error("Response body is null");
102
- const mediaType = response.headers
103
- .get("Content-Type")
104
- ?.split(";", 1)[0]
105
- ?.trim()
106
- .toLowerCase();
107
- if (mediaType !== "text/event-stream") {
108
- throw new Error("Response is not an event stream");
109
- }
110
- if (response.headers.get("Assistant-Stream-Format") !== "object-stream/v0") {
111
- throw new Error("Unsupported Assistant-Stream-Format header");
112
- }
113
- return response.body.pipeThrough(new ObjectStreamDecoder());
114
- };
File without changes