@prestyj/agent 5.27.0 → 5.28.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 +43 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +43 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -433,11 +433,14 @@ async function* agentLoop(messages, options) {
|
|
|
433
433
|
const OVERLOAD_BASE_DELAY_MS = 2e3;
|
|
434
434
|
const OVERLOAD_MAX_DELAY_MS = 3e4;
|
|
435
435
|
const STREAM_IDLE_TIMEOUT_MS = 9e4;
|
|
436
|
+
const STREAM_TOOL_INPUT_IDLE_TIMEOUT_MS = 3e5;
|
|
436
437
|
const STREAM_HARD_TIMEOUT_MS = 9e4;
|
|
437
438
|
const STREAM_OUTPUT_HARD_TIMEOUT_MS = 3e5;
|
|
438
|
-
const STREAM_THINKING_IDLE_TIMEOUT_MS =
|
|
439
|
-
const STREAM_THINKING_HARD_TIMEOUT_MS =
|
|
439
|
+
const STREAM_THINKING_IDLE_TIMEOUT_MS = 6e5;
|
|
440
|
+
const STREAM_THINKING_HARD_TIMEOUT_MS = 9e5;
|
|
440
441
|
const NON_STREAMING_HARD_TIMEOUT_MS = 3e5;
|
|
442
|
+
const nonStreamingHardTimeoutMs = options.thinking != null ? STREAM_THINKING_HARD_TIMEOUT_MS : NON_STREAMING_HARD_TIMEOUT_MS;
|
|
443
|
+
const VISIBLE_STALL_AFTER_MS = 6e4;
|
|
441
444
|
const usesSilentReasoningBudget = options.provider === "sakana" || options.provider === "openai" && options.thinking != null;
|
|
442
445
|
const localBackend = isLocalBackendUrl(options.baseUrl);
|
|
443
446
|
const baseFirstEventTimeoutMs = localBackend ? Number.POSITIVE_INFINITY : usesSilentReasoningBudget ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
|
|
@@ -539,10 +542,11 @@ async function* agentLoop(messages, options) {
|
|
|
539
542
|
options.signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
540
543
|
let hasReceivedEvent = false;
|
|
541
544
|
let hasReceivedThinking = false;
|
|
545
|
+
let toolInputOpen = false;
|
|
542
546
|
const resetIdleTimer = () => {
|
|
543
547
|
if (useNonStreamingFallback) return;
|
|
544
548
|
if (idleTimer) clearTimeout(idleTimer);
|
|
545
|
-
const timeoutMs = hasReceivedEvent ? STREAM_IDLE_TIMEOUT_MS : hasReceivedThinking ? STREAM_THINKING_IDLE_TIMEOUT_MS : firstEventTimeoutMs;
|
|
549
|
+
const timeoutMs = hasReceivedEvent ? toolInputOpen ? STREAM_TOOL_INPUT_IDLE_TIMEOUT_MS : STREAM_IDLE_TIMEOUT_MS : hasReceivedThinking ? STREAM_THINKING_IDLE_TIMEOUT_MS : firstEventTimeoutMs;
|
|
546
550
|
if (!Number.isFinite(timeoutMs)) return;
|
|
547
551
|
idleTimer = setTimeout(() => {
|
|
548
552
|
diag("idle_timeout_fired", {
|
|
@@ -550,14 +554,14 @@ async function* agentLoop(messages, options) {
|
|
|
550
554
|
sinceLastEventMs: Date.now() - lastEventTime,
|
|
551
555
|
lastEventType,
|
|
552
556
|
maxConsumerLagMs,
|
|
553
|
-
phase: hasReceivedEvent ? "mid_stream" : hasReceivedThinking ? "post_thinking" : "first_event",
|
|
557
|
+
phase: hasReceivedEvent ? toolInputOpen ? "mid_tool_input" : "mid_stream" : hasReceivedThinking ? "post_thinking" : "first_event",
|
|
554
558
|
eventTypes: eventTypeCounts
|
|
555
559
|
});
|
|
556
560
|
idleTimedOut = true;
|
|
557
561
|
streamController.abort();
|
|
558
562
|
}, timeoutMs);
|
|
559
563
|
};
|
|
560
|
-
let hardTimeoutMs = useNonStreamingFallback ?
|
|
564
|
+
let hardTimeoutMs = useNonStreamingFallback ? nonStreamingHardTimeoutMs : initialHardTimeoutMs;
|
|
561
565
|
hardTimer = setTimeout(() => {
|
|
562
566
|
diag("hard_timeout_fired", {
|
|
563
567
|
events: typeof streamEventCount !== "undefined" ? streamEventCount : 0,
|
|
@@ -652,6 +656,8 @@ async function* agentLoop(messages, options) {
|
|
|
652
656
|
if (firstProviderEventAt === void 0) firstProviderEventAt = pullTime;
|
|
653
657
|
eventTypeCounts[event.type] = (eventTypeCounts[event.type] ?? 0) + 1;
|
|
654
658
|
lastEventType = event.type;
|
|
659
|
+
if (event.type === "toolcall_delta") toolInputOpen = true;
|
|
660
|
+
else if (event.type === "toolcall_done") toolInputOpen = false;
|
|
655
661
|
if ((event.type === "text_delta" || event.type === "server_toolcall" || event.type === "toolcall_delta") && !hasReceivedEvent) {
|
|
656
662
|
hasReceivedEvent = true;
|
|
657
663
|
if (hardTimer && hardTimeoutMs < STREAM_OUTPUT_HARD_TIMEOUT_MS) {
|
|
@@ -986,7 +992,7 @@ async function* agentLoop(messages, options) {
|
|
|
986
992
|
attempt: stallRetries,
|
|
987
993
|
maxAttempts: MAX_STALL_RETRIES,
|
|
988
994
|
delayMs,
|
|
989
|
-
silent: stallRetries <= 2,
|
|
995
|
+
silent: stallRetries <= 2 && Date.now() - streamCallStart < VISIBLE_STALL_AFTER_MS,
|
|
990
996
|
...preservedChars > 0 ? { preservedChars } : {}
|
|
991
997
|
};
|
|
992
998
|
await abortableSleep(delayMs, options.signal);
|
|
@@ -1249,7 +1255,8 @@ async function* agentLoop(messages, options) {
|
|
|
1249
1255
|
maxTurnToolResultChars: options.maxTurnToolResultChars,
|
|
1250
1256
|
toolMap,
|
|
1251
1257
|
invalidToolArgumentCounts,
|
|
1252
|
-
markFatalToolArgumentError
|
|
1258
|
+
markFatalToolArgumentError,
|
|
1259
|
+
seenToolCalls: /* @__PURE__ */ new Set()
|
|
1253
1260
|
};
|
|
1254
1261
|
const hasSequentialToolCall = toolCalls.some(
|
|
1255
1262
|
(toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
|
|
@@ -1370,6 +1377,15 @@ async function* agentLoop(messages, options) {
|
|
|
1370
1377
|
totalUsage: { ...totalUsage }
|
|
1371
1378
|
};
|
|
1372
1379
|
}
|
|
1380
|
+
function canonicalToolArgs(value) {
|
|
1381
|
+
if (Array.isArray(value)) return value.map(canonicalToolArgs);
|
|
1382
|
+
if (value !== null && typeof value === "object") {
|
|
1383
|
+
return Object.fromEntries(
|
|
1384
|
+
Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => [k, canonicalToolArgs(v)])
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
return value;
|
|
1388
|
+
}
|
|
1373
1389
|
function pushToolEvent(eventStream, state, event) {
|
|
1374
1390
|
if (!state.finalized) eventStream.push(event);
|
|
1375
1391
|
}
|
|
@@ -1386,6 +1402,21 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
1386
1402
|
let isError = false;
|
|
1387
1403
|
let invalidArgAttempt;
|
|
1388
1404
|
const tool = options.toolMap.get(toolCall.name);
|
|
1405
|
+
if (tool) {
|
|
1406
|
+
const signature = JSON.stringify([toolCall.name, canonicalToolArgs(toolCall.args)]);
|
|
1407
|
+
if (options.seenToolCalls.has(signature)) {
|
|
1408
|
+
const content = "Tool call cancelled: an identical call already appeared in this response; this call was not executed.";
|
|
1409
|
+
pushEvent({
|
|
1410
|
+
type: "tool_call_end",
|
|
1411
|
+
toolCallId: toolCall.id,
|
|
1412
|
+
result: content,
|
|
1413
|
+
isError: true,
|
|
1414
|
+
durationMs: Date.now() - startTime
|
|
1415
|
+
});
|
|
1416
|
+
return { toolCallId: toolCall.id, content, isError: true };
|
|
1417
|
+
}
|
|
1418
|
+
options.seenToolCalls.add(signature);
|
|
1419
|
+
}
|
|
1389
1420
|
if (!tool) {
|
|
1390
1421
|
resultContent = `Unknown tool: ${toolCall.name}`;
|
|
1391
1422
|
isError = true;
|
|
@@ -1502,6 +1533,11 @@ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
|
|
|
1502
1533
|
for (const phase of phases) {
|
|
1503
1534
|
if (options.signal?.aborted) break;
|
|
1504
1535
|
if (phase.sequential) {
|
|
1536
|
+
const signature = JSON.stringify([
|
|
1537
|
+
phase.sequential.name,
|
|
1538
|
+
canonicalToolArgs(phase.sequential.args)
|
|
1539
|
+
]);
|
|
1540
|
+
if (!options.seenToolCalls.has(signature)) options.seenToolCalls.clear();
|
|
1505
1541
|
dispatchedIds.add(phase.sequential.id);
|
|
1506
1542
|
const record = await executeSingleToolCall(
|
|
1507
1543
|
phase.sequential,
|