@agentica/core 0.32.3 → 0.32.4

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.
@@ -55,6 +55,10 @@ export interface MicroAgenticaContext<Model extends ILlmSchema.Model> {
55
55
  * {@link Agentica.conversate} function.
56
56
  */
57
57
  prompt: AgenticaUserMessageHistory;
58
+ /**
59
+ * Abort signal.
60
+ */
61
+ abortSignal?: AbortSignal;
58
62
  /**
59
63
  * Dispatch event.
60
64
  *
package/lib/index.mjs CHANGED
@@ -1160,12 +1160,12 @@ class MPSC {
1160
1160
  }
1161
1161
  }
1162
1162
 
1163
- async function readAll(stream) {
1163
+ async function readAll(stream, abortSignal) {
1164
1164
  const reader = stream.getReader();
1165
1165
  const result = [];
1166
1166
  while (true) {
1167
1167
  const {done, value} = await reader.read();
1168
- if (done) {
1168
+ if (done || abortSignal?.aborted === true) {
1169
1169
  break;
1170
1170
  }
1171
1171
  result.push(value);
@@ -1173,11 +1173,14 @@ async function readAll(stream) {
1173
1173
  return result;
1174
1174
  }
1175
1175
 
1176
- async function reduce(stream, reducer, initial) {
1176
+ async function reduce(stream, reducer, options) {
1177
1177
  const reader = stream.getReader();
1178
1178
  const iterator = streamDefaultReaderToAsyncGenerator(reader);
1179
- let acc = initial ?? null;
1179
+ let acc = options.initial ?? null;
1180
1180
  for await (const value of iterator) {
1181
+ if (options.abortSignal?.aborted === true) {
1182
+ break;
1183
+ }
1181
1184
  if (acc === null) {
1182
1185
  acc = value;
1183
1186
  continue;
@@ -1201,26 +1204,26 @@ async function* toAsyncGenerator(value) {
1201
1204
  yield value;
1202
1205
  }
1203
1206
 
1204
- async function* streamDefaultReaderToAsyncGenerator(reader) {
1207
+ async function* streamDefaultReaderToAsyncGenerator(reader, abortSignal) {
1205
1208
  while (true) {
1206
1209
  const {done, value} = await reader.read();
1207
- if (done) {
1210
+ if (done || abortSignal?.aborted === true) {
1208
1211
  break;
1209
1212
  }
1210
1213
  yield value;
1211
1214
  }
1212
1215
  }
1213
1216
 
1214
- function transform(stream, transformer) {
1217
+ function transform(stream, transformer, abortSignal) {
1215
1218
  const reader = stream.getReader();
1216
1219
  return new ReadableStream({
1217
1220
  pull: async controller => {
1218
1221
  const {done, value} = await reader.read();
1219
- if (!done) {
1220
- controller.enqueue(transformer(value));
1221
- } else {
1222
+ if (done === true || abortSignal?.aborted === true) {
1222
1223
  controller.close();
1224
+ return;
1223
1225
  }
1226
+ controller.enqueue(transformer(value));
1224
1227
  }
1225
1228
  });
1226
1229
  }
@@ -1243,7 +1246,7 @@ var index$2 = Object.freeze({
1243
1246
  toAsyncGenerator
1244
1247
  });
1245
1248
 
1246
- async function reduceStreamingWithDispatch(stream, eventProcessor) {
1249
+ async function reduceStreamingWithDispatch(stream, eventProcessor, abortSignal) {
1247
1250
  const streamContext = new Map;
1248
1251
  const nullableCompletion = await StreamUtil.reduce(stream, (async (accPromise, chunk) => {
1249
1252
  const acc = await accPromise;
@@ -1286,7 +1289,9 @@ async function reduceStreamingWithDispatch(stream, eventProcessor) {
1286
1289
  }
1287
1290
  registerContext(chunk.choices);
1288
1291
  return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
1289
- }));
1292
+ }), {
1293
+ abortSignal
1294
+ });
1290
1295
  if (nullableCompletion == null) {
1291
1296
  throw new Error("StreamUtil.reduce did not produce a ChatCompletion. Possible causes: the input stream was empty, invalid, or closed prematurely. " + "To debug: check that the stream is properly initialized and contains valid ChatCompletionChunk data. " + "You may also enable verbose logging upstream to inspect the stream contents. " + `Stream locked: ${stream.locked}.`);
1292
1297
  }
@@ -1376,6 +1381,7 @@ async function call(ctx, operations) {
1376
1381
  const completion = await reduceStreamingWithDispatch(stream, (props => {
1377
1382
  const event = createAssistantMessageEvent(props);
1378
1383
  void ctx.dispatch(event).catch((() => {}));
1384
+ ctx.abortSignal;
1379
1385
  }));
1380
1386
  const allAssistantMessagesEmpty = completion.choices.every((v => v.message.tool_calls == null && v.message.content === ""));
1381
1387
  if (allAssistantMessagesEmpty) {
@@ -1799,7 +1805,7 @@ async function step$1(ctx, operations, retry, failures) {
1799
1805
  } ],
1800
1806
  tool_choice: retry === 0 ? "auto" : "required"
1801
1807
  });
1802
- const chunks = await StreamUtil.readAll(completionStream);
1808
+ const chunks = await StreamUtil.readAll(completionStream, ctx.abortSignal);
1803
1809
  const completion = ChatGptCompletionMessageUtil.merge(chunks);
1804
1810
  if (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)) {
1805
1811
  const failures = [];
@@ -1951,7 +1957,7 @@ async function describe(ctx, histories) {
1951
1957
  ...props
1952
1958
  });
1953
1959
  ctx.dispatch(event);
1954
- }));
1960
+ }), ctx.abortSignal);
1955
1961
  }
1956
1962
 
1957
1963
  const ChatGptDescribeFunctionAgent = {
@@ -2618,7 +2624,7 @@ async function initialize(ctx) {
2618
2624
  const completion = await reduceStreamingWithDispatch(completionStream, (props => {
2619
2625
  const event = createAssistantMessageEvent(props);
2620
2626
  ctx.dispatch(event);
2621
- }));
2627
+ }), ctx.abortSignal);
2622
2628
  if (completion === null) {
2623
2629
  throw new Error("No completion received");
2624
2630
  }
@@ -2823,7 +2829,7 @@ async function step(ctx, operations, retry, failures) {
2823
2829
  const completion = await reduceStreamingWithDispatch(stream, (props => {
2824
2830
  const event = createAssistantMessageEvent(props);
2825
2831
  void ctx.dispatch(event).catch((() => {}));
2826
- }));
2832
+ }), ctx.abortSignal);
2827
2833
  const allAssistantMessagesEmpty = completion.choices.every((v => v.message.tool_calls == null && v.message.content === ""));
2828
2834
  if (allAssistantMessagesEmpty) {
2829
2835
  const firstChoice = completion.choices.at(0);
@@ -3176,13 +3182,13 @@ const getChatCompletionWithStreamingFunction = props => async (source, body) =>
3176
3182
  }
3177
3183
  }
3178
3184
  })();
3179
- const [streamForEvent, temporaryStream] = StreamUtil.transform(completion.toReadableStream(), (value => ChatGptCompletionMessageUtil.transformCompletionChunk(value))).tee();
3185
+ const [streamForEvent, temporaryStream] = StreamUtil.transform(completion.toReadableStream(), (value => ChatGptCompletionMessageUtil.transformCompletionChunk(value)), props.abortSignal).tee();
3180
3186
  const [streamForAggregate, streamForReturn] = temporaryStream.tee();
3181
3187
  (async () => {
3182
3188
  const reader = streamForAggregate.getReader();
3183
3189
  while (true) {
3184
3190
  const chunk = await reader.read();
3185
- if (chunk.done) {
3191
+ if (chunk.done || props.abortSignal?.aborted === true) {
3186
3192
  break;
3187
3193
  }
3188
3194
  if (chunk.value.usage != null) {
@@ -3199,11 +3205,11 @@ const getChatCompletionWithStreamingFunction = props => async (source, body) =>
3199
3205
  id: v4(),
3200
3206
  type: "response",
3201
3207
  source,
3202
- stream: streamDefaultReaderToAsyncGenerator(streamForStream.getReader()),
3208
+ stream: streamDefaultReaderToAsyncGenerator(streamForStream.getReader(), props.abortSignal),
3203
3209
  body: event.body,
3204
3210
  options: event.options,
3205
3211
  join: async () => {
3206
- const chunks = await StreamUtil.readAll(streamForJoin);
3212
+ const chunks = await StreamUtil.readAll(streamForJoin, props.abortSignal);
3207
3213
  return ChatGptCompletionMessageUtil.merge(chunks);
3208
3214
  },
3209
3215
  created_at: (new Date).toISOString()