@prestyj/agent 4.12.1 → 4.14.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.
package/dist/index.cjs CHANGED
@@ -287,29 +287,34 @@ async function* agentLoop(messages, options) {
287
287
  const STREAM_THINKING_IDLE_TIMEOUT_MS = 3e5;
288
288
  const STREAM_THINKING_HARD_TIMEOUT_MS = 6e5;
289
289
  const NON_STREAMING_HARD_TIMEOUT_MS = 3e5;
290
+ const isSakana = options.provider === "sakana";
291
+ const firstEventTimeoutMs = isSakana ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
292
+ const initialHardTimeoutMs = isSakana ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
290
293
  const MAX_TOOLCALL_DELTA_CHARS = 1e6;
291
294
  const MAX_TOOLCALL_DELTA_EVENTS = 2e4;
292
295
  try {
293
296
  while (turn < maxTurns) {
294
297
  options.signal?.throwIfAborted();
295
298
  turn++;
296
- let msgChars = 0;
297
- for (const m of messages) {
298
- if (typeof m.content === "string") msgChars += m.content.length;
299
- else if (Array.isArray(m.content)) {
300
- for (const p of m.content) {
301
- if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
302
- if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
299
+ if (_diagFn) {
300
+ let msgChars = 0;
301
+ for (const m of messages) {
302
+ if (typeof m.content === "string") msgChars += m.content.length;
303
+ else if (Array.isArray(m.content)) {
304
+ for (const p of m.content) {
305
+ if ("text" in p && typeof p.text === "string") msgChars += p.text.length;
306
+ if ("content" in p && typeof p.content === "string") msgChars += p.content.length;
307
+ }
303
308
  }
304
309
  }
310
+ diag("turn_start", {
311
+ turn,
312
+ messages: messages.length,
313
+ chars: msgChars,
314
+ provider: options.provider,
315
+ model: options.model
316
+ });
305
317
  }
306
- diag("turn_start", {
307
- turn,
308
- messages: messages.length,
309
- chars: msgChars,
310
- provider: options.provider,
311
- model: options.model
312
- });
313
318
  if (firstTurn && options.getSteeringMessages) {
314
319
  const steering = await options.getSteeringMessages();
315
320
  if (steering && steering.length > 0) {
@@ -356,7 +361,7 @@ async function* agentLoop(messages, options) {
356
361
  const resetIdleTimer = () => {
357
362
  if (useNonStreamingFallback) return;
358
363
  if (idleTimer) clearTimeout(idleTimer);
359
- const timeoutMs = hasReceivedEvent ? STREAM_IDLE_TIMEOUT_MS : hasReceivedThinking ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
364
+ const timeoutMs = hasReceivedEvent ? STREAM_IDLE_TIMEOUT_MS : hasReceivedThinking ? STREAM_THINKING_IDLE_TIMEOUT_MS : firstEventTimeoutMs;
360
365
  idleTimer = setTimeout(() => {
361
366
  diag("idle_timeout_fired", {
362
367
  events: streamEventCount,
@@ -370,7 +375,7 @@ async function* agentLoop(messages, options) {
370
375
  streamController.abort();
371
376
  }, timeoutMs);
372
377
  };
373
- let hardTimeoutMs = useNonStreamingFallback ? NON_STREAMING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
378
+ let hardTimeoutMs = useNonStreamingFallback ? NON_STREAMING_HARD_TIMEOUT_MS : initialHardTimeoutMs;
374
379
  hardTimer = setTimeout(() => {
375
380
  diag("hard_timeout_fired", {
376
381
  events: typeof streamEventCount !== "undefined" ? streamEventCount : 0,
@@ -851,7 +856,7 @@ async function* agentLoop(messages, options) {
851
856
  const hasSequentialToolCall = toolCalls.some(
852
857
  (toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
853
858
  );
854
- const executionResult = hasSequentialToolCall ? yield* executeToolCallsSequential(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
859
+ const executionResult = hasSequentialToolCall ? yield* executeToolCallsMixed(toolCalls, toolResults, executionOptions) : yield* executeToolCallsParallel(toolCalls, toolResults, executionOptions);
855
860
  messages.push({ role: "tool", content: executionResult.toolResults });
856
861
  const toolsAborted = executionResult.aborted;
857
862
  if (fatalToolArgumentError) {
@@ -911,8 +916,10 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
911
916
  } else {
912
917
  try {
913
918
  const parsed = tool.parameters.parse(toolCall.args);
919
+ const callerSignal = options.signal;
920
+ const toolTimeout = AbortSignal.timeout(3e5);
914
921
  const ctx = {
915
- signal: options.signal ?? AbortSignal.timeout(3e5),
922
+ signal: callerSignal ? AbortSignal.any([callerSignal, toolTimeout]) : toolTimeout,
916
923
  toolCallId: toolCall.id,
917
924
  onUpdate: (update) => {
918
925
  pushEvent({
@@ -964,22 +971,59 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
964
971
  });
965
972
  return { toolCallId: toolCall.id, content: resultContent, isError };
966
973
  }
967
- async function* executeToolCallsSequential(toolCalls, initialToolResults, options) {
974
+ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
968
975
  const eventStream = new import_ai.EventStream();
969
976
  const state = { finalized: false };
970
977
  const resultsById = /* @__PURE__ */ new Map();
971
978
  const abortHandler = () => eventStream.abort(new Error("aborted"));
972
979
  options.signal?.addEventListener("abort", abortHandler, { once: true });
980
+ const phases = [];
981
+ let currentParallel = [];
982
+ for (const toolCall of toolCalls) {
983
+ const isSequential = options.toolMap.get(toolCall.name)?.executionMode === "sequential";
984
+ if (isSequential) {
985
+ if (currentParallel.length > 0) {
986
+ phases.push({ parallel: currentParallel, sequential: null });
987
+ currentParallel = [];
988
+ }
989
+ phases.push({ parallel: [], sequential: toolCall });
990
+ } else {
991
+ currentParallel.push(toolCall);
992
+ }
993
+ }
994
+ if (currentParallel.length > 0) {
995
+ phases.push({ parallel: currentParallel, sequential: null });
996
+ }
973
997
  void (async () => {
974
998
  try {
975
- for (const toolCall of toolCalls) {
999
+ for (const phase of phases) {
976
1000
  if (options.signal?.aborted) break;
977
- const record = await executeSingleToolCall(
978
- toolCall,
979
- options,
980
- (event) => pushToolEvent(eventStream, state, event)
981
- );
982
- resultsById.set(record.toolCallId, record);
1001
+ if (phase.sequential) {
1002
+ const record = await executeSingleToolCall(
1003
+ phase.sequential,
1004
+ options,
1005
+ (event) => pushToolEvent(eventStream, state, event)
1006
+ );
1007
+ resultsById.set(record.toolCallId, record);
1008
+ } else if (phase.parallel.length === 1) {
1009
+ const record = await executeSingleToolCall(
1010
+ phase.parallel[0],
1011
+ options,
1012
+ (event) => pushToolEvent(eventStream, state, event)
1013
+ );
1014
+ resultsById.set(record.toolCallId, record);
1015
+ } else {
1016
+ await Promise.all(
1017
+ phase.parallel.map(async (toolCall) => {
1018
+ const record = await executeSingleToolCall(
1019
+ toolCall,
1020
+ options,
1021
+ (event) => pushToolEvent(eventStream, state, event)
1022
+ );
1023
+ resultsById.set(record.toolCallId, record);
1024
+ })
1025
+ );
1026
+ }
983
1027
  }
984
1028
  if (!state.finalized) eventStream.close();
985
1029
  } catch (err) {