assistant-stream 0.2.20 → 0.2.21

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.
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-stream.d.ts","sourceRoot":"","sources":["../../../src/core/modules/assistant-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAY,MAAM,yBAAyB,CAAC;AAEzE,OAAO,EAA8B,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC1E,OAAO,EAEL,wBAAwB,EACzB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,KAAK,gBAAgB,GAAG;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,CAAC,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IACxC,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACpC,WAAW,IAAI,oBAAoB,CAAC;IACpC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,wBAAwB,CAAC;IAC3D,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,wBAAwB,CAAC;IACrE,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,KAAK,IAAI,IAAI,CAAC;IACd,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,yBAAyB,CAAC;CAC3D,CAAC;AAiKF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,CAAC,UAAU,EAAE,yBAAyB,KAAK,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,GAC5E,eAAe,CA6CjB;AAED,wBAAgB,+BAA+B,0DAa9C;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,CAAC,UAAU,EAAE,yBAAyB,KAAK,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,YAM9E"}
1
+ {"version":3,"file":"assistant-stream.d.ts","sourceRoot":"","sources":["../../../src/core/modules/assistant-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAY,MAAM,yBAAyB,CAAC;AAEzE,OAAO,EAA8B,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC1E,OAAO,EAEL,wBAAwB,EACzB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,KAAK,gBAAgB,GAAG;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,CAAC,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IACxC,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACpC,WAAW,IAAI,oBAAoB,CAAC;IACpC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,wBAAwB,CAAC;IAC3D,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,wBAAwB,CAAC;IACrE,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,KAAK,IAAI,IAAI,CAAC;IACd,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,yBAAyB,CAAC;CAC3D,CAAC;AAmLF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,CAAC,UAAU,EAAE,yBAAyB,KAAK,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,GAC5E,eAAe,CA6CjB;AAED,wBAAgB,+BAA+B,0DAa9C;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,CAAC,UAAU,EAAE,yBAAyB,KAAK,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,YAM9E"}
@@ -14,56 +14,61 @@ import { DataStreamEncoder } from "../serialization/data-stream/DataStream.js";
14
14
  import { generateId } from "../utils/generateId.js";
15
15
  import { promiseWithResolvers } from "../../utils/promiseWithResolvers.js";
16
16
  var AssistantStreamControllerImpl = class _AssistantStreamControllerImpl {
17
- _merger = createMergeStream();
18
- _append;
19
- _contentCounter = new Counter();
17
+ _state;
20
18
  _parentId;
19
+ constructor(state) {
20
+ this._state = state || {
21
+ merger: createMergeStream(),
22
+ contentCounter: new Counter()
23
+ };
24
+ }
21
25
  get __internal_isClosed() {
22
- return this._merger.isSealed();
26
+ return this._state.merger.isSealed();
23
27
  }
24
28
  __internal_getReadable() {
25
- return this._merger.readable;
29
+ return this._state.merger.readable;
26
30
  }
27
- _closeSubscriber;
28
31
  __internal_subscribeToClose(callback) {
29
- this._closeSubscriber = callback;
32
+ this._state.closeSubscriber = callback;
30
33
  }
31
34
  _addPart(part, stream) {
32
- if (this._append) {
33
- this._append.controller.close();
34
- this._append = void 0;
35
+ if (this._state.append) {
36
+ this._state.append.controller.close();
37
+ this._state.append = void 0;
35
38
  }
36
39
  this.enqueue({
37
40
  type: "part-start",
38
41
  part,
39
42
  path: []
40
43
  });
41
- this._merger.addStream(
42
- stream.pipeThrough(new PathAppendEncoder(this._contentCounter.value))
44
+ this._state.merger.addStream(
45
+ stream.pipeThrough(
46
+ new PathAppendEncoder(this._state.contentCounter.value)
47
+ )
43
48
  );
44
49
  }
45
50
  merge(stream) {
46
- this._merger.addStream(
47
- stream.pipeThrough(new PathMergeEncoder(this._contentCounter))
51
+ this._state.merger.addStream(
52
+ stream.pipeThrough(new PathMergeEncoder(this._state.contentCounter))
48
53
  );
49
54
  }
50
55
  appendText(textDelta) {
51
- if (this._append?.kind !== "text") {
52
- this._append = {
56
+ if (this._state.append?.kind !== "text") {
57
+ this._state.append = {
53
58
  kind: "text",
54
59
  controller: this.addTextPart()
55
60
  };
56
61
  }
57
- this._append.controller.append(textDelta);
62
+ this._state.append.controller.append(textDelta);
58
63
  }
59
64
  appendReasoning(textDelta) {
60
- if (this._append?.kind !== "reasoning") {
61
- this._append = {
65
+ if (this._state.append?.kind !== "reasoning") {
66
+ this._state.append = {
62
67
  kind: "reasoning",
63
68
  controller: this.addReasoningPart()
64
69
  };
65
70
  }
66
- this._append.controller.append(textDelta);
71
+ this._state.append.controller.append(textDelta);
67
72
  }
68
73
  addTextPart() {
69
74
  const [stream, controller] = createTextStreamController();
@@ -80,7 +85,15 @@ var AssistantStreamControllerImpl = class _AssistantStreamControllerImpl {
80
85
  const toolName = opt.toolName;
81
86
  const toolCallId = opt.toolCallId ?? generateId();
82
87
  const [stream, controller] = createToolCallStreamController();
83
- this._addPart({ type: "tool-call", toolName, toolCallId }, stream);
88
+ this._addPart(
89
+ {
90
+ type: "tool-call",
91
+ toolName,
92
+ toolCallId,
93
+ ...this._parentId && { parentId: this._parentId }
94
+ },
95
+ stream
96
+ );
84
97
  if (opt.argsText !== void 0) {
85
98
  controller.argsText.append(opt.argsText);
86
99
  controller.argsText.close();
@@ -123,24 +136,20 @@ var AssistantStreamControllerImpl = class _AssistantStreamControllerImpl {
123
136
  );
124
137
  }
125
138
  enqueue(chunk) {
126
- this._merger.enqueue(chunk);
139
+ this._state.merger.enqueue(chunk);
127
140
  if (chunk.type === "part-start" && chunk.path.length === 0) {
128
- this._contentCounter.up();
141
+ this._state.contentCounter.up();
129
142
  }
130
143
  }
131
144
  withParentId(parentId) {
132
- const controller = new _AssistantStreamControllerImpl();
133
- controller._merger = this._merger;
134
- controller._append = this._append;
135
- controller._contentCounter = this._contentCounter;
136
- controller._closeSubscriber = this._closeSubscriber;
145
+ const controller = new _AssistantStreamControllerImpl(this._state);
137
146
  controller._parentId = parentId;
138
147
  return controller;
139
148
  }
140
149
  close() {
141
- this._merger.seal();
142
- this._append?.controller?.close();
143
- this._closeSubscriber?.();
150
+ this._state.merger.seal();
151
+ this._state.append?.controller?.close();
152
+ this._state.closeSubscriber?.();
144
153
  }
145
154
  };
146
155
  function createAssistantStream(callback) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/modules/assistant-stream.ts"],"sourcesContent":["import { AssistantStream } from \"../AssistantStream\";\nimport { AssistantStreamChunk, PartInit } from \"../AssistantStreamChunk\";\nimport { createMergeStream } from \"../utils/stream/merge\";\nimport { createTextStreamController, TextStreamController } from \"./text\";\nimport {\n createToolCallStreamController,\n ToolCallStreamController,\n} from \"./tool-call\";\nimport { Counter } from \"../utils/Counter\";\nimport {\n PathAppendEncoder,\n PathMergeEncoder,\n} from \"../utils/stream/path-utils\";\nimport { DataStreamEncoder } from \"../serialization/data-stream/DataStream\";\nimport { FilePart, SourcePart } from \"../utils/types\";\nimport { generateId } from \"../utils/generateId\";\nimport {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"../../utils/json/json-value\";\nimport { ToolResponseLike } from \"../tool/ToolResponse\";\nimport { promiseWithResolvers } from \"../../utils/promiseWithResolvers\";\n\ntype ToolCallPartInit = {\n toolCallId?: string;\n toolName: string;\n argsText?: string;\n args?: ReadonlyJSONObject;\n response?: ToolResponseLike<ReadonlyJSONValue>;\n};\n\nexport type AssistantStreamController = {\n appendText(textDelta: string): void;\n appendReasoning(reasoningDelta: string): void;\n appendSource(options: SourcePart): void;\n appendFile(options: FilePart): void;\n addTextPart(): TextStreamController;\n addToolCallPart(options: string): ToolCallStreamController;\n addToolCallPart(options: ToolCallPartInit): ToolCallStreamController;\n enqueue(chunk: AssistantStreamChunk): void;\n merge(stream: AssistantStream): void;\n close(): void;\n withParentId(parentId: string): AssistantStreamController;\n};\n\nclass AssistantStreamControllerImpl implements AssistantStreamController {\n private _merger = createMergeStream();\n private _append:\n | {\n controller: TextStreamController;\n kind: \"text\" | \"reasoning\";\n }\n | undefined;\n private _contentCounter = new Counter();\n private _parentId?: string;\n\n get __internal_isClosed() {\n return this._merger.isSealed();\n }\n\n __internal_getReadable() {\n return this._merger.readable;\n }\n\n private _closeSubscriber: undefined | (() => void);\n __internal_subscribeToClose(callback: () => void) {\n this._closeSubscriber = callback;\n }\n\n private _addPart(part: PartInit, stream: AssistantStream) {\n if (this._append) {\n this._append.controller.close();\n this._append = undefined;\n }\n\n this.enqueue({\n type: \"part-start\",\n part,\n path: [],\n });\n this._merger.addStream(\n stream.pipeThrough(new PathAppendEncoder(this._contentCounter.value)),\n );\n }\n\n merge(stream: AssistantStream) {\n this._merger.addStream(\n stream.pipeThrough(new PathMergeEncoder(this._contentCounter)),\n );\n }\n\n appendText(textDelta: string) {\n if (this._append?.kind !== \"text\") {\n this._append = {\n kind: \"text\",\n controller: this.addTextPart(),\n };\n }\n this._append.controller.append(textDelta);\n }\n\n appendReasoning(textDelta: string) {\n if (this._append?.kind !== \"reasoning\") {\n this._append = {\n kind: \"reasoning\",\n controller: this.addReasoningPart(),\n };\n }\n this._append.controller.append(textDelta);\n }\n\n addTextPart() {\n const [stream, controller] = createTextStreamController();\n this._addPart({ type: \"text\" }, stream);\n return controller;\n }\n\n addReasoningPart() {\n const [stream, controller] = createTextStreamController();\n this._addPart({ type: \"reasoning\" }, stream);\n return controller;\n }\n\n addToolCallPart(\n options: string | ToolCallPartInit,\n ): ToolCallStreamController {\n const opt = typeof options === \"string\" ? { toolName: options } : options;\n const toolName = opt.toolName;\n const toolCallId = opt.toolCallId ?? generateId();\n\n const [stream, controller] = createToolCallStreamController();\n this._addPart({ type: \"tool-call\", toolName, toolCallId }, stream);\n\n if (opt.argsText !== undefined) {\n controller.argsText.append(opt.argsText);\n controller.argsText.close();\n }\n if (opt.args !== undefined) {\n controller.argsText.append(JSON.stringify(opt.args));\n controller.argsText.close();\n }\n if (opt.response !== undefined) {\n controller.setResponse(opt.response);\n }\n\n return controller;\n }\n\n appendSource(options: SourcePart) {\n this._addPart(\n { ...options, ...(this._parentId && { parentId: this._parentId }) },\n new ReadableStream({\n start(controller) {\n controller.enqueue({\n type: \"part-finish\",\n path: [],\n });\n controller.close();\n },\n }),\n );\n }\n\n appendFile(options: FilePart) {\n this._addPart(\n options,\n new ReadableStream({\n start(controller) {\n controller.enqueue({\n type: \"part-finish\",\n path: [],\n });\n controller.close();\n },\n }),\n );\n }\n\n enqueue(chunk: AssistantStreamChunk) {\n this._merger.enqueue(chunk);\n\n if (chunk.type === \"part-start\" && chunk.path.length === 0) {\n this._contentCounter.up();\n }\n }\n\n withParentId(parentId: string): AssistantStreamController {\n const controller = new AssistantStreamControllerImpl();\n controller._merger = this._merger;\n controller._append = this._append;\n controller._contentCounter = this._contentCounter;\n controller._closeSubscriber = this._closeSubscriber;\n controller._parentId = parentId;\n return controller;\n }\n\n close() {\n this._merger.seal();\n this._append?.controller?.close();\n\n this._closeSubscriber?.();\n }\n}\n\nexport function createAssistantStream(\n callback: (controller: AssistantStreamController) => PromiseLike<void> | void,\n): AssistantStream {\n const controller = new AssistantStreamControllerImpl();\n\n let promiseOrVoid: PromiseLike<void> | void;\n try {\n promiseOrVoid = callback(controller);\n } catch (e) {\n if (!controller.__internal_isClosed) {\n controller.enqueue({\n type: \"error\",\n path: [],\n error: String(e),\n });\n controller.close();\n }\n throw e;\n }\n\n if (promiseOrVoid instanceof Promise) {\n const runTask = async () => {\n try {\n await promiseOrVoid;\n } catch (e) {\n if (!controller.__internal_isClosed) {\n controller.enqueue({\n type: \"error\",\n path: [],\n error: String(e),\n });\n }\n throw e;\n } finally {\n if (!controller.__internal_isClosed) {\n controller.close();\n }\n }\n };\n runTask();\n } else {\n if (!controller.__internal_isClosed) {\n controller.close();\n }\n }\n\n return controller.__internal_getReadable();\n}\n\nexport function createAssistantStreamController() {\n const { resolve, promise } = promiseWithResolvers<void>();\n let controller!: AssistantStreamController;\n const stream = createAssistantStream((c) => {\n controller = c;\n\n (controller as AssistantStreamControllerImpl).__internal_subscribeToClose(\n resolve,\n );\n\n return promise;\n });\n return [stream, controller] as const;\n}\n\nexport function createAssistantStreamResponse(\n callback: (controller: AssistantStreamController) => PromiseLike<void> | void,\n) {\n return AssistantStream.toResponse(\n createAssistantStream(callback),\n new DataStreamEncoder(),\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/core/modules/assistant-stream.ts"],"sourcesContent":["import { AssistantStream } from \"../AssistantStream\";\nimport { AssistantStreamChunk, PartInit } from \"../AssistantStreamChunk\";\nimport { createMergeStream } from \"../utils/stream/merge\";\nimport { createTextStreamController, TextStreamController } from \"./text\";\nimport {\n createToolCallStreamController,\n ToolCallStreamController,\n} from \"./tool-call\";\nimport { Counter } from \"../utils/Counter\";\nimport {\n PathAppendEncoder,\n PathMergeEncoder,\n} from \"../utils/stream/path-utils\";\nimport { DataStreamEncoder } from \"../serialization/data-stream/DataStream\";\nimport { FilePart, SourcePart } from \"../utils/types\";\nimport { generateId } from \"../utils/generateId\";\nimport {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"../../utils/json/json-value\";\nimport { ToolResponseLike } from \"../tool/ToolResponse\";\nimport { promiseWithResolvers } from \"../../utils/promiseWithResolvers\";\n\ntype ToolCallPartInit = {\n toolCallId?: string;\n toolName: string;\n argsText?: string;\n args?: ReadonlyJSONObject;\n response?: ToolResponseLike<ReadonlyJSONValue>;\n};\n\nexport type AssistantStreamController = {\n appendText(textDelta: string): void;\n appendReasoning(reasoningDelta: string): void;\n appendSource(options: SourcePart): void;\n appendFile(options: FilePart): void;\n addTextPart(): TextStreamController;\n addToolCallPart(options: string): ToolCallStreamController;\n addToolCallPart(options: ToolCallPartInit): ToolCallStreamController;\n enqueue(chunk: AssistantStreamChunk): void;\n merge(stream: AssistantStream): void;\n close(): void;\n withParentId(parentId: string): AssistantStreamController;\n};\n\n// Shared state between controller instances\ntype AssistantStreamControllerState = {\n merger: ReturnType<typeof createMergeStream>;\n append?:\n | {\n controller: TextStreamController;\n kind: \"text\" | \"reasoning\";\n }\n | undefined;\n contentCounter: Counter;\n closeSubscriber?: () => void;\n};\n\nclass AssistantStreamControllerImpl implements AssistantStreamController {\n private readonly _state: AssistantStreamControllerState;\n private _parentId?: string;\n\n constructor(state?: AssistantStreamControllerState) {\n this._state = state || {\n merger: createMergeStream(),\n contentCounter: new Counter(),\n };\n }\n\n get __internal_isClosed() {\n return this._state.merger.isSealed();\n }\n\n __internal_getReadable() {\n return this._state.merger.readable;\n }\n\n __internal_subscribeToClose(callback: () => void) {\n this._state.closeSubscriber = callback;\n }\n\n private _addPart(part: PartInit, stream: AssistantStream) {\n if (this._state.append) {\n this._state.append.controller.close();\n this._state.append = undefined;\n }\n\n this.enqueue({\n type: \"part-start\",\n part,\n path: [],\n });\n this._state.merger.addStream(\n stream.pipeThrough(\n new PathAppendEncoder(this._state.contentCounter.value),\n ),\n );\n }\n\n merge(stream: AssistantStream) {\n this._state.merger.addStream(\n stream.pipeThrough(new PathMergeEncoder(this._state.contentCounter)),\n );\n }\n\n appendText(textDelta: string) {\n if (this._state.append?.kind !== \"text\") {\n this._state.append = {\n kind: \"text\",\n controller: this.addTextPart(),\n };\n }\n this._state.append.controller.append(textDelta);\n }\n\n appendReasoning(textDelta: string) {\n if (this._state.append?.kind !== \"reasoning\") {\n this._state.append = {\n kind: \"reasoning\",\n controller: this.addReasoningPart(),\n };\n }\n this._state.append.controller.append(textDelta);\n }\n\n addTextPart() {\n const [stream, controller] = createTextStreamController();\n this._addPart({ type: \"text\" }, stream);\n return controller;\n }\n\n addReasoningPart() {\n const [stream, controller] = createTextStreamController();\n this._addPart({ type: \"reasoning\" }, stream);\n return controller;\n }\n\n addToolCallPart(\n options: string | ToolCallPartInit,\n ): ToolCallStreamController {\n const opt = typeof options === \"string\" ? { toolName: options } : options;\n const toolName = opt.toolName;\n const toolCallId = opt.toolCallId ?? generateId();\n\n const [stream, controller] = createToolCallStreamController();\n this._addPart(\n {\n type: \"tool-call\",\n toolName,\n toolCallId,\n ...(this._parentId && { parentId: this._parentId }),\n },\n stream,\n );\n\n if (opt.argsText !== undefined) {\n controller.argsText.append(opt.argsText);\n controller.argsText.close();\n }\n if (opt.args !== undefined) {\n controller.argsText.append(JSON.stringify(opt.args));\n controller.argsText.close();\n }\n if (opt.response !== undefined) {\n controller.setResponse(opt.response);\n }\n\n return controller;\n }\n\n appendSource(options: SourcePart) {\n this._addPart(\n { ...options, ...(this._parentId && { parentId: this._parentId }) },\n new ReadableStream({\n start(controller) {\n controller.enqueue({\n type: \"part-finish\",\n path: [],\n });\n controller.close();\n },\n }),\n );\n }\n\n appendFile(options: FilePart) {\n this._addPart(\n options,\n new ReadableStream({\n start(controller) {\n controller.enqueue({\n type: \"part-finish\",\n path: [],\n });\n controller.close();\n },\n }),\n );\n }\n\n enqueue(chunk: AssistantStreamChunk) {\n this._state.merger.enqueue(chunk);\n\n if (chunk.type === \"part-start\" && chunk.path.length === 0) {\n this._state.contentCounter.up();\n }\n }\n\n withParentId(parentId: string): AssistantStreamController {\n const controller = new AssistantStreamControllerImpl(this._state);\n controller._parentId = parentId;\n return controller;\n }\n\n close() {\n this._state.merger.seal();\n this._state.append?.controller?.close();\n\n this._state.closeSubscriber?.();\n }\n}\n\nexport function createAssistantStream(\n callback: (controller: AssistantStreamController) => PromiseLike<void> | void,\n): AssistantStream {\n const controller = new AssistantStreamControllerImpl();\n\n let promiseOrVoid: PromiseLike<void> | void;\n try {\n promiseOrVoid = callback(controller);\n } catch (e) {\n if (!controller.__internal_isClosed) {\n controller.enqueue({\n type: \"error\",\n path: [],\n error: String(e),\n });\n controller.close();\n }\n throw e;\n }\n\n if (promiseOrVoid instanceof Promise) {\n const runTask = async () => {\n try {\n await promiseOrVoid;\n } catch (e) {\n if (!controller.__internal_isClosed) {\n controller.enqueue({\n type: \"error\",\n path: [],\n error: String(e),\n });\n }\n throw e;\n } finally {\n if (!controller.__internal_isClosed) {\n controller.close();\n }\n }\n };\n runTask();\n } else {\n if (!controller.__internal_isClosed) {\n controller.close();\n }\n }\n\n return controller.__internal_getReadable();\n}\n\nexport function createAssistantStreamController() {\n const { resolve, promise } = promiseWithResolvers<void>();\n let controller!: AssistantStreamController;\n const stream = createAssistantStream((c) => {\n controller = c;\n\n (controller as AssistantStreamControllerImpl).__internal_subscribeToClose(\n resolve,\n );\n\n return promise;\n });\n return [stream, controller] as const;\n}\n\nexport function createAssistantStreamResponse(\n callback: (controller: AssistantStreamController) => PromiseLike<void> | void,\n) {\n return AssistantStream.toResponse(\n createAssistantStream(callback),\n new DataStreamEncoder(),\n );\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assistant-stream",
3
- "version": "0.2.20",
3
+ "version": "0.2.21",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -43,34 +43,46 @@ export type AssistantStreamController = {
43
43
  withParentId(parentId: string): AssistantStreamController;
44
44
  };
45
45
 
46
- class AssistantStreamControllerImpl implements AssistantStreamController {
47
- private _merger = createMergeStream();
48
- private _append:
46
+ // Shared state between controller instances
47
+ type AssistantStreamControllerState = {
48
+ merger: ReturnType<typeof createMergeStream>;
49
+ append?:
49
50
  | {
50
51
  controller: TextStreamController;
51
52
  kind: "text" | "reasoning";
52
53
  }
53
54
  | undefined;
54
- private _contentCounter = new Counter();
55
+ contentCounter: Counter;
56
+ closeSubscriber?: () => void;
57
+ };
58
+
59
+ class AssistantStreamControllerImpl implements AssistantStreamController {
60
+ private readonly _state: AssistantStreamControllerState;
55
61
  private _parentId?: string;
56
62
 
63
+ constructor(state?: AssistantStreamControllerState) {
64
+ this._state = state || {
65
+ merger: createMergeStream(),
66
+ contentCounter: new Counter(),
67
+ };
68
+ }
69
+
57
70
  get __internal_isClosed() {
58
- return this._merger.isSealed();
71
+ return this._state.merger.isSealed();
59
72
  }
60
73
 
61
74
  __internal_getReadable() {
62
- return this._merger.readable;
75
+ return this._state.merger.readable;
63
76
  }
64
77
 
65
- private _closeSubscriber: undefined | (() => void);
66
78
  __internal_subscribeToClose(callback: () => void) {
67
- this._closeSubscriber = callback;
79
+ this._state.closeSubscriber = callback;
68
80
  }
69
81
 
70
82
  private _addPart(part: PartInit, stream: AssistantStream) {
71
- if (this._append) {
72
- this._append.controller.close();
73
- this._append = undefined;
83
+ if (this._state.append) {
84
+ this._state.append.controller.close();
85
+ this._state.append = undefined;
74
86
  }
75
87
 
76
88
  this.enqueue({
@@ -78,35 +90,37 @@ class AssistantStreamControllerImpl implements AssistantStreamController {
78
90
  part,
79
91
  path: [],
80
92
  });
81
- this._merger.addStream(
82
- stream.pipeThrough(new PathAppendEncoder(this._contentCounter.value)),
93
+ this._state.merger.addStream(
94
+ stream.pipeThrough(
95
+ new PathAppendEncoder(this._state.contentCounter.value),
96
+ ),
83
97
  );
84
98
  }
85
99
 
86
100
  merge(stream: AssistantStream) {
87
- this._merger.addStream(
88
- stream.pipeThrough(new PathMergeEncoder(this._contentCounter)),
101
+ this._state.merger.addStream(
102
+ stream.pipeThrough(new PathMergeEncoder(this._state.contentCounter)),
89
103
  );
90
104
  }
91
105
 
92
106
  appendText(textDelta: string) {
93
- if (this._append?.kind !== "text") {
94
- this._append = {
107
+ if (this._state.append?.kind !== "text") {
108
+ this._state.append = {
95
109
  kind: "text",
96
110
  controller: this.addTextPart(),
97
111
  };
98
112
  }
99
- this._append.controller.append(textDelta);
113
+ this._state.append.controller.append(textDelta);
100
114
  }
101
115
 
102
116
  appendReasoning(textDelta: string) {
103
- if (this._append?.kind !== "reasoning") {
104
- this._append = {
117
+ if (this._state.append?.kind !== "reasoning") {
118
+ this._state.append = {
105
119
  kind: "reasoning",
106
120
  controller: this.addReasoningPart(),
107
121
  };
108
122
  }
109
- this._append.controller.append(textDelta);
123
+ this._state.append.controller.append(textDelta);
110
124
  }
111
125
 
112
126
  addTextPart() {
@@ -129,7 +143,15 @@ class AssistantStreamControllerImpl implements AssistantStreamController {
129
143
  const toolCallId = opt.toolCallId ?? generateId();
130
144
 
131
145
  const [stream, controller] = createToolCallStreamController();
132
- this._addPart({ type: "tool-call", toolName, toolCallId }, stream);
146
+ this._addPart(
147
+ {
148
+ type: "tool-call",
149
+ toolName,
150
+ toolCallId,
151
+ ...(this._parentId && { parentId: this._parentId }),
152
+ },
153
+ stream,
154
+ );
133
155
 
134
156
  if (opt.argsText !== undefined) {
135
157
  controller.argsText.append(opt.argsText);
@@ -177,28 +199,24 @@ class AssistantStreamControllerImpl implements AssistantStreamController {
177
199
  }
178
200
 
179
201
  enqueue(chunk: AssistantStreamChunk) {
180
- this._merger.enqueue(chunk);
202
+ this._state.merger.enqueue(chunk);
181
203
 
182
204
  if (chunk.type === "part-start" && chunk.path.length === 0) {
183
- this._contentCounter.up();
205
+ this._state.contentCounter.up();
184
206
  }
185
207
  }
186
208
 
187
209
  withParentId(parentId: string): AssistantStreamController {
188
- const controller = new AssistantStreamControllerImpl();
189
- controller._merger = this._merger;
190
- controller._append = this._append;
191
- controller._contentCounter = this._contentCounter;
192
- controller._closeSubscriber = this._closeSubscriber;
210
+ const controller = new AssistantStreamControllerImpl(this._state);
193
211
  controller._parentId = parentId;
194
212
  return controller;
195
213
  }
196
214
 
197
215
  close() {
198
- this._merger.seal();
199
- this._append?.controller?.close();
216
+ this._state.merger.seal();
217
+ this._state.append?.controller?.close();
200
218
 
201
- this._closeSubscriber?.();
219
+ this._state.closeSubscriber?.();
202
220
  }
203
221
  }
204
222