@agentica/core 0.32.9 → 0.33.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.
Files changed (65) hide show
  1. package/lib/events/AgenticaCallEvent.d.ts +0 -4
  2. package/lib/events/AgenticaExecuteEvent.d.ts +1 -1
  3. package/lib/events/AgenticaJsonParseErrorEvent.d.ts +4 -0
  4. package/lib/events/AgenticaResponseEvent.d.ts +1 -0
  5. package/lib/events/AgenticaValidateEvent.d.ts +1 -1
  6. package/lib/factory/events.d.ts +4 -2
  7. package/lib/factory/events.js +11 -3
  8. package/lib/factory/events.js.map +1 -1
  9. package/lib/index.mjs +100 -85
  10. package/lib/index.mjs.map +1 -1
  11. package/lib/json/IAgenticaEventJson.d.ts +9 -5
  12. package/lib/orchestrate/call.js +9 -5
  13. package/lib/orchestrate/call.js.map +1 -1
  14. package/lib/orchestrate/cancel.js +1 -1
  15. package/lib/orchestrate/cancel.js.map +1 -1
  16. package/lib/orchestrate/describe.js +1 -1
  17. package/lib/orchestrate/describe.js.map +1 -1
  18. package/lib/orchestrate/initialize.js +1 -1
  19. package/lib/orchestrate/initialize.js.map +1 -1
  20. package/lib/orchestrate/internal/cancelFunctionFromContext.js +1 -1
  21. package/lib/orchestrate/internal/cancelFunctionFromContext.js.map +1 -1
  22. package/lib/orchestrate/internal/selectFunctionFromContext.js +1 -1
  23. package/lib/orchestrate/internal/selectFunctionFromContext.js.map +1 -1
  24. package/lib/orchestrate/select.js +1 -1
  25. package/lib/orchestrate/select.js.map +1 -1
  26. package/lib/utils/ChatGptCompletionMessageUtil.d.ts +2 -2
  27. package/lib/utils/ChatGptCompletionMessageUtil.js +3 -3
  28. package/lib/utils/ChatGptCompletionMessageUtil.js.map +1 -1
  29. package/lib/utils/ChatGptCompletionMessageUtil.spec.js +4 -4
  30. package/lib/utils/ChatGptCompletionMessageUtil.spec.js.map +1 -1
  31. package/lib/utils/ChatGptCompletionStreamingUtil.js.map +1 -1
  32. package/lib/utils/ChatGptCompletionStreamingUtil.spec.js +2 -1
  33. package/lib/utils/ChatGptCompletionStreamingUtil.spec.js.map +1 -1
  34. package/lib/utils/JsonUtil.js +1 -1
  35. package/lib/utils/JsonUtil.js.map +1 -1
  36. package/lib/utils/JsonUtil.spec.js +38 -38
  37. package/lib/utils/JsonUtil.spec.js.map +1 -1
  38. package/lib/utils/StreamUtil.spec.js.map +1 -1
  39. package/lib/utils/request.d.ts +7 -7
  40. package/lib/utils/request.js +67 -65
  41. package/lib/utils/request.js.map +1 -1
  42. package/package.json +7 -7
  43. package/src/events/AgenticaCallEvent.ts +0 -5
  44. package/src/events/AgenticaExecuteEvent.ts +1 -1
  45. package/src/events/AgenticaJsonParseErrorEvent.ts +4 -0
  46. package/src/events/AgenticaResponseEvent.ts +2 -0
  47. package/src/events/AgenticaValidateEvent.ts +1 -1
  48. package/src/factory/events.ts +15 -5
  49. package/src/json/IAgenticaEventJson.ts +11 -6
  50. package/src/orchestrate/call.ts +14 -7
  51. package/src/orchestrate/cancel.ts +1 -1
  52. package/src/orchestrate/describe.ts +1 -1
  53. package/src/orchestrate/initialize.ts +1 -1
  54. package/src/orchestrate/internal/cancelFunctionFromContext.ts +1 -1
  55. package/src/orchestrate/internal/selectFunctionFromContext.ts +1 -1
  56. package/src/orchestrate/select.ts +1 -1
  57. package/src/utils/ChatGptCompletionMessageUtil.spec.ts +4 -4
  58. package/src/utils/ChatGptCompletionMessageUtil.ts +5 -4
  59. package/src/utils/ChatGptCompletionStreamingUtil.spec.ts +437 -435
  60. package/src/utils/ChatGptCompletionStreamingUtil.ts +5 -4
  61. package/src/utils/JsonUtil.spec.ts +58 -60
  62. package/src/utils/JsonUtil.ts +1 -3
  63. package/src/utils/StreamUtil.spec.ts +1 -1
  64. package/src/utils/StreamUtil.ts +2 -2
  65. package/src/utils/request.ts +92 -85
@@ -23,7 +23,8 @@ async function reduceStreamingWithDispatch(stream: ReadableStream<ChatCompletion
23
23
  const context = streamContext.get(choice.index)!;
24
24
  context.content += choice.delta.content;
25
25
  context.mpsc.produce(choice.delta.content);
26
- } else {
26
+ }
27
+ else {
27
28
  const mpsc = new MPSC<string>();
28
29
 
29
30
  streamContext.set(choice.index, {
@@ -43,7 +44,7 @@ async function reduceStreamingWithDispatch(stream: ReadableStream<ChatCompletion
43
44
  });
44
45
  }
45
46
  }
46
-
47
+
47
48
  // Handle finish_reason after content processing
48
49
  if (choice.finish_reason != null) {
49
50
  const context = streamContext.get(choice.index);
@@ -70,10 +71,10 @@ async function reduceStreamingWithDispatch(stream: ReadableStream<ChatCompletion
70
71
  );
71
72
  }
72
73
 
73
- if((nullableCompletion.object as string) === "chat.completion.chunk") {
74
+ if ((nullableCompletion.object as string) === "chat.completion.chunk") {
74
75
  const completion = ChatGptCompletionMessageUtil.merge([nullableCompletion as unknown as ChatCompletionChunk]);
75
76
  completion.choices.forEach((choice) => {
76
- if(choice.message.content != null && choice.message.content !== "") {
77
+ if (choice.message.content != null && choice.message.content !== "") {
77
78
  eventProcessor({
78
79
  stream: toAsyncGenerator(choice.message.content),
79
80
  done: () => true,
@@ -1,185 +1,184 @@
1
1
  import { JsonUtil } from "./JsonUtil";
2
2
 
3
- describe("JsonUtil", () => {
3
+ describe("jsonUtil", () => {
4
4
  describe("parse", () => {
5
-
6
- describe("Normal Operations", () => {
5
+ describe("normal Operations", () => {
7
6
  it("should parse standard valid JSON", () => {
8
- const jsonString = '{"normal": "json"}';
7
+ const jsonString = "{\"normal\": \"json\"}";
9
8
  const result = JsonUtil.parse(jsonString);
10
-
9
+
11
10
  expect(result).toEqual({ normal: "json" });
12
11
  });
13
12
 
14
13
  it("should handle object with '{}' prefix", () => {
15
- const jsonString = '{}{"name": "test", "value": 42}';
14
+ const jsonString = "{}{\"name\": \"test\", \"value\": 42}";
16
15
  const result = JsonUtil.parse(jsonString);
17
-
16
+
18
17
  expect(result).toEqual({ name: "test", value: 42 });
19
18
  });
20
19
 
21
20
  it("should handle array with '{}' prefix", () => {
22
- const jsonString = '{}[1, 2, 3, "test"]';
21
+ const jsonString = "{}[1, 2, 3, \"test\"]";
23
22
  const result = JsonUtil.parse(jsonString);
24
-
23
+
25
24
  expect(result).toEqual([1, 2, 3, "test"]);
26
25
  });
27
26
 
28
27
  it("should handle primitive values with '{}' prefix", () => {
29
- expect(JsonUtil.parse('{}42')).toBe(42);
30
- expect(JsonUtil.parse('{}"hello"')).toBe("hello");
31
- expect(JsonUtil.parse('{}true')).toBe(true);
32
- expect(JsonUtil.parse('{}null')).toBeNull();
28
+ expect(JsonUtil.parse("{}42")).toBe(42);
29
+ expect(JsonUtil.parse("{}\"hello\"")).toBe("hello");
30
+ expect(JsonUtil.parse("{}true")).toBe(true);
31
+ expect(JsonUtil.parse("{}null")).toBeNull();
33
32
  });
34
33
 
35
34
  it("should remove trailing comma in object", () => {
36
- const jsonString = '{"name": "test", "value": 42,}';
35
+ const jsonString = "{\"name\": \"test\", \"value\": 42,}";
37
36
  const result = JsonUtil.parse(jsonString);
38
-
37
+
39
38
  expect(result).toEqual({ name: "test", value: 42 });
40
39
  });
41
40
 
42
41
  it("should remove trailing comma in array", () => {
43
- const jsonString = '[1, 2, 3, "test",]';
42
+ const jsonString = "[1, 2, 3, \"test\",]";
44
43
  const result = JsonUtil.parse(jsonString);
45
-
44
+
46
45
  expect(result).toEqual([1, 2, 3, "test"]);
47
46
  });
48
47
 
49
48
  it("should add missing closing brace in object", () => {
50
- const jsonString = '{"name": "test", "value": 42';
49
+ const jsonString = "{\"name\": \"test\", \"value\": 42";
51
50
  const result = JsonUtil.parse(jsonString);
52
-
51
+
53
52
  expect(result).toEqual({ name: "test", value: 42 });
54
53
  });
55
54
 
56
55
  it("should add missing closing bracket in array", () => {
57
- const jsonString = '[1, 2, 3, "test"';
56
+ const jsonString = "[1, 2, 3, \"test\"";
58
57
  const result = JsonUtil.parse(jsonString);
59
-
58
+
60
59
  expect(result).toEqual([1, 2, 3, "test"]);
61
60
  });
62
61
  });
63
62
 
64
- describe("Combined Features", () => {
63
+ describe("combined Features", () => {
65
64
  it("should handle '{}' prefix and missing closing brace together", () => {
66
- const jsonString = '{}{"name": "test", "value": 42';
65
+ const jsonString = "{}{\"name\": \"test\", \"value\": 42";
67
66
  const result = JsonUtil.parse(jsonString);
68
-
67
+
69
68
  expect(result).toEqual({ name: "test", value: 42 });
70
69
  });
71
70
 
72
71
  it("should handle '{}' prefix and missing closing bracket together", () => {
73
- const jsonString = '{}[1, 2, 3, "test"';
72
+ const jsonString = "{}[1, 2, 3, \"test\"";
74
73
  const result = JsonUtil.parse(jsonString);
75
-
74
+
76
75
  expect(result).toEqual([1, 2, 3, "test"]);
77
76
  });
78
77
 
79
78
  it("should handle trailing comma in nested objects", () => {
80
- const jsonString = '{"user": {"id": 1, "name": "John",}, "active": true,}';
79
+ const jsonString = "{\"user\": {\"id\": 1, \"name\": \"John\",}, \"active\": true,}";
81
80
  const result = JsonUtil.parse(jsonString);
82
-
81
+
83
82
  expect(result).toEqual({
84
83
  user: { id: 1, name: "John" },
85
- active: true
84
+ active: true,
86
85
  });
87
86
  });
88
87
 
89
88
  it("should handle missing closing brace in nested objects", () => {
90
- const jsonString = '{"user": {"id": 1, "name": "John"}';
89
+ const jsonString = "{\"user\": {\"id\": 1, \"name\": \"John\"}";
91
90
  const result = JsonUtil.parse(jsonString);
92
-
91
+
93
92
  expect(result).toEqual({
94
- user: { id: 1, name: "John" }
93
+ user: { id: 1, name: "John" },
95
94
  });
96
95
  });
97
96
 
98
97
  it("should handle missing closing brace in complex nested structure", () => {
99
- const jsonString = '{"users": [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}], "count": 2';
98
+ const jsonString = "{\"users\": [{\"id\": 1, \"name\": \"John\"}, {\"id\": 2, \"name\": \"Jane\"}], \"count\": 2";
100
99
  const result = JsonUtil.parse(jsonString);
101
-
100
+
102
101
  expect(result).toEqual({
103
102
  users: [
104
103
  { id: 1, name: "John" },
105
- { id: 2, name: "Jane" }
104
+ { id: 2, name: "Jane" },
106
105
  ],
107
- count: 2
106
+ count: 2,
108
107
  });
109
108
  });
110
109
 
111
110
  it("should apply all correction features together", () => {
112
- const jsonString = '{}{"name": "test", "items": [1, 2, 3,], "user": {"id": 1, "name": "John",}';
111
+ const jsonString = "{}{\"name\": \"test\", \"items\": [1, 2, 3,], \"user\": {\"id\": 1, \"name\": \"John\",}";
113
112
  const result = JsonUtil.parse(jsonString);
114
-
113
+
115
114
  expect(result).toEqual({
116
115
  name: "test",
117
116
  items: [1, 2, 3],
118
- user: { id: 1, name: "John" }
117
+ user: { id: 1, name: "John" },
119
118
  });
120
119
  });
121
120
 
122
121
  it("should handle all issues simultaneously in complex nested structure", () => {
123
- const jsonString = '{}{"data": {"users": [{"id": 1, "name": "John",}, {"id": 2, "name": "Jane",}], "meta": {"total": 2, "page": 1,}}, "status": "ok",';
122
+ const jsonString = "{}{\"data\": {\"users\": [{\"id\": 1, \"name\": \"John\",}, {\"id\": 2, \"name\": \"Jane\",}], \"meta\": {\"total\": 2, \"page\": 1,}}, \"status\": \"ok\",";
124
123
  const result = JsonUtil.parse(jsonString);
125
-
124
+
126
125
  expect(result).toEqual({
127
126
  data: {
128
127
  users: [
129
128
  { id: 1, name: "John" },
130
- { id: 2, name: "Jane" }
129
+ { id: 2, name: "Jane" },
131
130
  ],
132
- meta: { total: 2, page: 1 }
131
+ meta: { total: 2, page: 1 },
133
132
  },
134
- status: "ok"
133
+ status: "ok",
135
134
  });
136
135
  });
137
136
  });
138
137
 
139
- describe("Edge Cases", () => {
138
+ describe("edge Cases", () => {
140
139
  it("should handle empty object with '{}' prefix", () => {
141
- const jsonString = '{}{}';
140
+ const jsonString = "{}{}";
142
141
  const result = JsonUtil.parse(jsonString);
143
-
142
+
144
143
  expect(result).toEqual({});
145
144
  });
146
145
 
147
146
  it("should handle empty array with '{}' prefix", () => {
148
- const jsonString = '{}[]';
147
+ const jsonString = "{}[]";
149
148
  const result = JsonUtil.parse(jsonString);
150
-
149
+
151
150
  expect(result).toEqual([]);
152
151
  });
153
152
 
154
153
  it("should handle nested object with '{}' prefix", () => {
155
- const jsonString = '{}{"user": {"id": 1, "name": "John"}}';
154
+ const jsonString = "{}{\"user\": {\"id\": 1, \"name\": \"John\"}}";
156
155
  const result = JsonUtil.parse(jsonString);
157
-
156
+
158
157
  expect(result).toEqual({
159
- user: { id: 1, name: "John" }
158
+ user: { id: 1, name: "John" },
160
159
  });
161
160
  });
162
161
 
163
162
  it("should handle multiple trailing commas", () => {
164
- const jsonString = '{"items": [1, 2, 3,,,], "count": 3,,,}';
163
+ const jsonString = "{\"items\": [1, 2, 3,,,], \"count\": 3,,,}";
165
164
  const result = JsonUtil.parse(jsonString);
166
-
165
+
167
166
  expect(result).toEqual({
168
167
  items: [1, 2, 3],
169
- count: 3
168
+ count: 3,
170
169
  });
171
170
  });
172
171
 
173
172
  it("should handle JSON with whitespace and formatting issues", () => {
174
- const jsonString = '{} { "name" : "test" , "value" : 42 , } ';
173
+ const jsonString = "{} { \"name\" : \"test\" , \"value\" : 42 , } ";
175
174
  const result = JsonUtil.parse(jsonString);
176
-
175
+
177
176
  expect(result).toEqual({ name: "test", value: 42 });
178
177
  });
179
178
 
180
179
  it("should throw error for completely invalid JSON", () => {
181
- const invalidJson = '{invalid: json without quotes}';
182
-
180
+ const invalidJson = "{invalid: json without quotes}";
181
+
183
182
  expect(() => JsonUtil.parse(invalidJson)).toThrow();
184
183
  });
185
184
 
@@ -187,6 +186,5 @@ describe("JsonUtil", () => {
187
186
  expect(() => JsonUtil.parse("")).toThrow();
188
187
  });
189
188
  });
190
-
191
189
  });
192
190
  });
@@ -4,10 +4,8 @@ export const JsonUtil = {
4
4
  parse,
5
5
  };
6
6
 
7
+ const pipe = (...fns: ((str: string) => string)[]) => (str: string) => fns.reduce((acc, fn) => fn(acc), str);
7
8
  function parse(str: string) {
8
9
  const corrected = pipe(removeEmptyObjectPrefix, addMissingBraces, removeTrailingCommas)(str);
9
10
  return JSON.parse(corrected);
10
11
  }
11
-
12
- const pipe = (...fns: ((str: string) => string)[]) => (str: string) => fns.reduce((acc, fn) => fn(acc), str);
13
-
@@ -149,7 +149,7 @@ describe("streamUtil", () => {
149
149
  const stringResult = await StreamUtil.reduce<number, string>(
150
150
  stringStream,
151
151
  (acc, cur) => acc + cur.toString(),
152
- { initial: ""},
152
+ { initial: "" },
153
153
  );
154
154
 
155
155
  expect(stringResult).toBe("123");
@@ -17,7 +17,7 @@ async function readAll<T>(stream: ReadableStream<T>, abortSignal?: AbortSignal):
17
17
  return result;
18
18
  }
19
19
 
20
- async function reduce<T, R = T>(stream: ReadableStream<T>, reducer: (acc: T | R, cur: T) => R, options: { initial?: R, abortSignal?: AbortSignal }): Promise<R | null> {
20
+ async function reduce<T, R = T>(stream: ReadableStream<T>, reducer: (acc: T | R, cur: T) => R, options: { initial?: R; abortSignal?: AbortSignal }): Promise<R | null> {
21
21
  const reader = stream.getReader();
22
22
  const iterator = streamDefaultReaderToAsyncGenerator(reader);
23
23
  let acc = (options.initial ?? null) as R | null | T;
@@ -73,7 +73,7 @@ function transform<T, R>(stream: ReadableStream<T>, transformer: (value: T) => R
73
73
  controller.close();
74
74
  return;
75
75
  }
76
-
76
+
77
77
  controller.enqueue(transformer(value));
78
78
  },
79
79
  });
@@ -1,101 +1,108 @@
1
- import OpenAI from "openai";
2
- import { AgenticaEventSource, AgenticaRequestEvent, AgenticaResponseEvent } from "../events";
1
+ import type { ILlmSchema } from "@samchon/openapi";
2
+ import type OpenAI from "openai";
3
+
4
+ import { v4 } from "uuid";
5
+
6
+ import type { AgenticaTokenUsage } from "../context/AgenticaTokenUsage";
7
+ import type { AgenticaEventSource, AgenticaRequestEvent, AgenticaResponseEvent } from "../events";
8
+ import type { IAgenticaConfig, IAgenticaVendor, IMicroAgenticaConfig } from "../structures";
9
+
10
+ import { AgenticaTokenUsageAggregator } from "../context/internal/AgenticaTokenUsageAggregator";
11
+ import { createRequestEvent } from "../factory";
12
+
3
13
  import { ChatGptCompletionMessageUtil } from "./ChatGptCompletionMessageUtil";
4
14
  import { streamDefaultReaderToAsyncGenerator, StreamUtil } from "./StreamUtil";
5
- import { createRequestEvent } from "../factory";
6
- import { IAgenticaConfig, IAgenticaVendor, IMicroAgenticaConfig } from "../structures";
7
- import { ILlmSchema } from "@samchon/openapi";
8
- import { AgenticaTokenUsageAggregator } from "../context/internal/AgenticaTokenUsageAggregator";
9
- import { AgenticaTokenUsage } from "../context/AgenticaTokenUsage";
10
- import { v4 } from "uuid";
11
15
 
12
- export const getChatCompletionWithStreamingFunction = <Model extends ILlmSchema.Model>(props: {
16
+ export function getChatCompletionWithStreamingFunction<Model extends ILlmSchema.Model>(props: {
13
17
  vendor: IAgenticaVendor;
14
18
  config?: IAgenticaConfig<Model> | IMicroAgenticaConfig<Model>;
15
19
  dispatch: (event: AgenticaRequestEvent | AgenticaResponseEvent) => Promise<void>;
16
20
  abortSignal?: AbortSignal;
17
21
  usage: AgenticaTokenUsage;
18
- }) => async (
19
- source: AgenticaEventSource,
20
- body: Omit<OpenAI.ChatCompletionCreateParamsStreaming, "model" | "stream">,
21
- ) => {
22
- const event: AgenticaRequestEvent = createRequestEvent({
23
- source,
24
- body: {
25
- ...body,
26
- model: props.vendor.model,
27
- stream: true,
28
- stream_options: {
29
- include_usage: true,
22
+ }) {
23
+ return async (
24
+ source: AgenticaEventSource,
25
+ body: Omit<OpenAI.ChatCompletionCreateParamsStreaming, "model" | "stream">,
26
+ ) => {
27
+ const event: AgenticaRequestEvent = createRequestEvent({
28
+ source,
29
+ body: {
30
+ ...body,
31
+ model: props.vendor.model,
32
+ stream: true,
33
+ stream_options: {
34
+ include_usage: true,
35
+ },
36
+ },
37
+ options: {
38
+ ...props.vendor.options,
39
+ signal: props.abortSignal,
30
40
  },
31
- },
32
- options: {
33
- ...props.vendor.options,
34
- signal: props.abortSignal,
35
- },
36
- });
37
- await props.dispatch(event);
41
+ });
42
+ await props.dispatch(event);
38
43
 
39
- // completion
40
- const backoffStrategy = props.config?.backoffStrategy ?? ((props) => {
41
- throw props.error;
42
- });
43
- const completion = await (async () => {
44
- let count = 0;
45
- while (true) {
46
- try {
47
- return await props.vendor.api.chat.completions.create(
48
- event.body,
49
- event.options,
50
- );
44
+ // completion
45
+ const backoffStrategy = props.config?.backoffStrategy ?? ((props) => {
46
+ throw props.error;
47
+ });
48
+ const completion = await (async () => {
49
+ let count = 0;
50
+ while (true) {
51
+ try {
52
+ return await props.vendor.api.chat.completions.create(
53
+ event.body,
54
+ event.options,
55
+ );
56
+ }
57
+ catch (error) {
58
+ const waiting = backoffStrategy({ count, error });
59
+ await new Promise(resolve => setTimeout(resolve, waiting));
60
+ count++;
61
+ }
51
62
  }
52
- catch (error) {
53
- const waiting = backoffStrategy({ count, error });
54
- await new Promise(resolve => setTimeout(resolve, waiting));
55
- count++;
56
- }
57
- }
58
- })();
63
+ })();
59
64
 
60
- const [streamForEvent, temporaryStream] = StreamUtil.transform(
61
- completion.toReadableStream() as ReadableStream<Uint8Array>,
62
- value =>
63
- ChatGptCompletionMessageUtil.transformCompletionChunk(value),
64
- props.abortSignal,
65
- ).tee();
65
+ const [streamForEvent, temporaryStream] = StreamUtil.transform(
66
+ completion.toReadableStream() as ReadableStream<Uint8Array>,
67
+ value =>
68
+ ChatGptCompletionMessageUtil.transformCompletionChunk(value),
69
+ props.abortSignal,
70
+ ).tee();
66
71
 
67
- const [streamForAggregate, streamForReturn] = temporaryStream.tee();
72
+ const [streamForAggregate, streamForReturn] = temporaryStream.tee();
68
73
 
69
- (async () => {
70
- const reader = streamForAggregate.getReader();
71
- while (true) {
72
- const chunk = await reader.read();
73
- if (chunk.done || props.abortSignal?.aborted === true) {
74
- break;
75
- }
76
- if (chunk.value.usage != null) {
77
- AgenticaTokenUsageAggregator.aggregate({
78
- kind: source,
79
- completionUsage: chunk.value.usage,
80
- usage: props.usage,
81
- });
74
+ (async () => {
75
+ const reader = streamForAggregate.getReader();
76
+ while (true) {
77
+ const chunk = await reader.read();
78
+ if (chunk.done || props.abortSignal?.aborted === true) {
79
+ break;
80
+ }
81
+ if (chunk.value.usage != null) {
82
+ AgenticaTokenUsageAggregator.aggregate({
83
+ kind: source,
84
+ completionUsage: chunk.value.usage,
85
+ usage: props.usage,
86
+ });
87
+ }
82
88
  }
83
- }
84
- })().catch(() => {});
89
+ })().catch(() => {});
85
90
 
86
- const [streamForStream, streamForJoin] = streamForEvent.tee();
87
- void props.dispatch({
88
- id: v4(),
89
- type: "response",
90
- source,
91
- stream: streamDefaultReaderToAsyncGenerator(streamForStream.getReader(), props.abortSignal),
92
- body: event.body,
93
- options: event.options,
94
- join: async () => {
95
- const chunks = await StreamUtil.readAll(streamForJoin, props.abortSignal);
96
- return ChatGptCompletionMessageUtil.merge(chunks);
97
- },
98
- created_at: new Date().toISOString(),
99
- }).catch(() => {});
100
- return streamForReturn;
101
- };
91
+ const [streamForStream, streamForJoin] = streamForEvent.tee();
92
+ void props.dispatch({
93
+ id: v4(),
94
+ type: "response",
95
+ request_id: event.id,
96
+ source,
97
+ stream: streamDefaultReaderToAsyncGenerator(streamForStream.getReader(), props.abortSignal),
98
+ body: event.body,
99
+ options: event.options,
100
+ join: async () => {
101
+ const chunks = await StreamUtil.readAll(streamForJoin, props.abortSignal);
102
+ return ChatGptCompletionMessageUtil.merge(chunks);
103
+ },
104
+ created_at: new Date().toISOString(),
105
+ }).catch(() => {});
106
+ return streamForReturn;
107
+ };
108
+ }