@prestyj/agent 5.26.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 +56 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +57 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -120,6 +120,11 @@ function clampOutputTokens(key, requested) {
|
|
|
120
120
|
// src/agent-loop.ts
|
|
121
121
|
var DEFAULT_MAX_TURNS = 300;
|
|
122
122
|
var DEFAULT_TOOL_TIMEOUT_MS = 3e5;
|
|
123
|
+
var _toolRedaction;
|
|
124
|
+
function toolRedactionOptions() {
|
|
125
|
+
_toolRedaction ??= { secrets: (0, import_ai.environmentSecrets)(process.env) };
|
|
126
|
+
return _toolRedaction;
|
|
127
|
+
}
|
|
123
128
|
var _diagFn = null;
|
|
124
129
|
function setStreamDiagnostic(fn) {
|
|
125
130
|
_diagFn = fn;
|
|
@@ -455,11 +460,14 @@ async function* agentLoop(messages, options) {
|
|
|
455
460
|
const OVERLOAD_BASE_DELAY_MS = 2e3;
|
|
456
461
|
const OVERLOAD_MAX_DELAY_MS = 3e4;
|
|
457
462
|
const STREAM_IDLE_TIMEOUT_MS = 9e4;
|
|
463
|
+
const STREAM_TOOL_INPUT_IDLE_TIMEOUT_MS = 3e5;
|
|
458
464
|
const STREAM_HARD_TIMEOUT_MS = 9e4;
|
|
459
465
|
const STREAM_OUTPUT_HARD_TIMEOUT_MS = 3e5;
|
|
460
|
-
const STREAM_THINKING_IDLE_TIMEOUT_MS =
|
|
461
|
-
const STREAM_THINKING_HARD_TIMEOUT_MS =
|
|
466
|
+
const STREAM_THINKING_IDLE_TIMEOUT_MS = 6e5;
|
|
467
|
+
const STREAM_THINKING_HARD_TIMEOUT_MS = 9e5;
|
|
462
468
|
const NON_STREAMING_HARD_TIMEOUT_MS = 3e5;
|
|
469
|
+
const nonStreamingHardTimeoutMs = options.thinking != null ? STREAM_THINKING_HARD_TIMEOUT_MS : NON_STREAMING_HARD_TIMEOUT_MS;
|
|
470
|
+
const VISIBLE_STALL_AFTER_MS = 6e4;
|
|
463
471
|
const usesSilentReasoningBudget = options.provider === "sakana" || options.provider === "openai" && options.thinking != null;
|
|
464
472
|
const localBackend = isLocalBackendUrl(options.baseUrl);
|
|
465
473
|
const baseFirstEventTimeoutMs = localBackend ? Number.POSITIVE_INFINITY : usesSilentReasoningBudget ? STREAM_THINKING_IDLE_TIMEOUT_MS : STREAM_FIRST_EVENT_TIMEOUT_MS;
|
|
@@ -561,10 +569,11 @@ async function* agentLoop(messages, options) {
|
|
|
561
569
|
options.signal?.addEventListener("abort", forwardAbort, { once: true });
|
|
562
570
|
let hasReceivedEvent = false;
|
|
563
571
|
let hasReceivedThinking = false;
|
|
572
|
+
let toolInputOpen = false;
|
|
564
573
|
const resetIdleTimer = () => {
|
|
565
574
|
if (useNonStreamingFallback) return;
|
|
566
575
|
if (idleTimer) clearTimeout(idleTimer);
|
|
567
|
-
const timeoutMs = hasReceivedEvent ? STREAM_IDLE_TIMEOUT_MS : hasReceivedThinking ? STREAM_THINKING_IDLE_TIMEOUT_MS : firstEventTimeoutMs;
|
|
576
|
+
const timeoutMs = hasReceivedEvent ? toolInputOpen ? STREAM_TOOL_INPUT_IDLE_TIMEOUT_MS : STREAM_IDLE_TIMEOUT_MS : hasReceivedThinking ? STREAM_THINKING_IDLE_TIMEOUT_MS : firstEventTimeoutMs;
|
|
568
577
|
if (!Number.isFinite(timeoutMs)) return;
|
|
569
578
|
idleTimer = setTimeout(() => {
|
|
570
579
|
diag("idle_timeout_fired", {
|
|
@@ -572,14 +581,14 @@ async function* agentLoop(messages, options) {
|
|
|
572
581
|
sinceLastEventMs: Date.now() - lastEventTime,
|
|
573
582
|
lastEventType,
|
|
574
583
|
maxConsumerLagMs,
|
|
575
|
-
phase: hasReceivedEvent ? "mid_stream" : hasReceivedThinking ? "post_thinking" : "first_event",
|
|
584
|
+
phase: hasReceivedEvent ? toolInputOpen ? "mid_tool_input" : "mid_stream" : hasReceivedThinking ? "post_thinking" : "first_event",
|
|
576
585
|
eventTypes: eventTypeCounts
|
|
577
586
|
});
|
|
578
587
|
idleTimedOut = true;
|
|
579
588
|
streamController.abort();
|
|
580
589
|
}, timeoutMs);
|
|
581
590
|
};
|
|
582
|
-
let hardTimeoutMs = useNonStreamingFallback ?
|
|
591
|
+
let hardTimeoutMs = useNonStreamingFallback ? nonStreamingHardTimeoutMs : initialHardTimeoutMs;
|
|
583
592
|
hardTimer = setTimeout(() => {
|
|
584
593
|
diag("hard_timeout_fired", {
|
|
585
594
|
events: typeof streamEventCount !== "undefined" ? streamEventCount : 0,
|
|
@@ -674,6 +683,8 @@ async function* agentLoop(messages, options) {
|
|
|
674
683
|
if (firstProviderEventAt === void 0) firstProviderEventAt = pullTime;
|
|
675
684
|
eventTypeCounts[event.type] = (eventTypeCounts[event.type] ?? 0) + 1;
|
|
676
685
|
lastEventType = event.type;
|
|
686
|
+
if (event.type === "toolcall_delta") toolInputOpen = true;
|
|
687
|
+
else if (event.type === "toolcall_done") toolInputOpen = false;
|
|
677
688
|
if ((event.type === "text_delta" || event.type === "server_toolcall" || event.type === "toolcall_delta") && !hasReceivedEvent) {
|
|
678
689
|
hasReceivedEvent = true;
|
|
679
690
|
if (hardTimer && hardTimeoutMs < STREAM_OUTPUT_HARD_TIMEOUT_MS) {
|
|
@@ -1008,7 +1019,7 @@ async function* agentLoop(messages, options) {
|
|
|
1008
1019
|
attempt: stallRetries,
|
|
1009
1020
|
maxAttempts: MAX_STALL_RETRIES,
|
|
1010
1021
|
delayMs,
|
|
1011
|
-
silent: stallRetries <= 2,
|
|
1022
|
+
silent: stallRetries <= 2 && Date.now() - streamCallStart < VISIBLE_STALL_AFTER_MS,
|
|
1012
1023
|
...preservedChars > 0 ? { preservedChars } : {}
|
|
1013
1024
|
};
|
|
1014
1025
|
await abortableSleep(delayMs, options.signal);
|
|
@@ -1271,7 +1282,8 @@ async function* agentLoop(messages, options) {
|
|
|
1271
1282
|
maxTurnToolResultChars: options.maxTurnToolResultChars,
|
|
1272
1283
|
toolMap,
|
|
1273
1284
|
invalidToolArgumentCounts,
|
|
1274
|
-
markFatalToolArgumentError
|
|
1285
|
+
markFatalToolArgumentError,
|
|
1286
|
+
seenToolCalls: /* @__PURE__ */ new Set()
|
|
1275
1287
|
};
|
|
1276
1288
|
const hasSequentialToolCall = toolCalls.some(
|
|
1277
1289
|
(toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
|
|
@@ -1392,6 +1404,15 @@ async function* agentLoop(messages, options) {
|
|
|
1392
1404
|
totalUsage: { ...totalUsage }
|
|
1393
1405
|
};
|
|
1394
1406
|
}
|
|
1407
|
+
function canonicalToolArgs(value) {
|
|
1408
|
+
if (Array.isArray(value)) return value.map(canonicalToolArgs);
|
|
1409
|
+
if (value !== null && typeof value === "object") {
|
|
1410
|
+
return Object.fromEntries(
|
|
1411
|
+
Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => [k, canonicalToolArgs(v)])
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
return value;
|
|
1415
|
+
}
|
|
1395
1416
|
function pushToolEvent(eventStream, state, event) {
|
|
1396
1417
|
if (!state.finalized) eventStream.push(event);
|
|
1397
1418
|
}
|
|
@@ -1408,6 +1429,21 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
1408
1429
|
let isError = false;
|
|
1409
1430
|
let invalidArgAttempt;
|
|
1410
1431
|
const tool = options.toolMap.get(toolCall.name);
|
|
1432
|
+
if (tool) {
|
|
1433
|
+
const signature = JSON.stringify([toolCall.name, canonicalToolArgs(toolCall.args)]);
|
|
1434
|
+
if (options.seenToolCalls.has(signature)) {
|
|
1435
|
+
const content = "Tool call cancelled: an identical call already appeared in this response; this call was not executed.";
|
|
1436
|
+
pushEvent({
|
|
1437
|
+
type: "tool_call_end",
|
|
1438
|
+
toolCallId: toolCall.id,
|
|
1439
|
+
result: content,
|
|
1440
|
+
isError: true,
|
|
1441
|
+
durationMs: Date.now() - startTime
|
|
1442
|
+
});
|
|
1443
|
+
return { toolCallId: toolCall.id, content, isError: true };
|
|
1444
|
+
}
|
|
1445
|
+
options.seenToolCalls.add(signature);
|
|
1446
|
+
}
|
|
1411
1447
|
if (!tool) {
|
|
1412
1448
|
resultContent = `Unknown tool: ${toolCall.name}`;
|
|
1413
1449
|
isError = true;
|
|
@@ -1442,8 +1478,8 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
1442
1478
|
ctx.signal
|
|
1443
1479
|
);
|
|
1444
1480
|
const normalized = normalizeToolResult(raw);
|
|
1445
|
-
resultContent = (0, import_ai.redactValue)(normalized.content);
|
|
1446
|
-
details = (0, import_ai.redactValue)(normalized.details);
|
|
1481
|
+
resultContent = (0, import_ai.redactValue)(normalized.content, toolRedactionOptions());
|
|
1482
|
+
details = (0, import_ai.redactValue)(normalized.details, toolRedactionOptions());
|
|
1447
1483
|
for (const key of options.invalidToolArgumentCounts.keys()) {
|
|
1448
1484
|
if (key.startsWith(`${toolCall.name}:`)) options.invalidToolArgumentCounts.delete(key);
|
|
1449
1485
|
}
|
|
@@ -1474,12 +1510,15 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
1474
1510
|
} else if (options.signal?.aborted && isAbortError(err)) {
|
|
1475
1511
|
resultContent = indeterminateOutcomeText(toolCall.name);
|
|
1476
1512
|
} else {
|
|
1477
|
-
resultContent = (0, import_ai.redactValue)(
|
|
1513
|
+
resultContent = (0, import_ai.redactValue)(
|
|
1514
|
+
err instanceof Error ? err.message : String(err),
|
|
1515
|
+
toolRedactionOptions()
|
|
1516
|
+
);
|
|
1478
1517
|
}
|
|
1479
1518
|
}
|
|
1480
1519
|
}
|
|
1481
|
-
resultContent = (0, import_ai.redactValue)(resultContent);
|
|
1482
|
-
details = (0, import_ai.redactValue)(details);
|
|
1520
|
+
resultContent = (0, import_ai.redactValue)(resultContent, toolRedactionOptions());
|
|
1521
|
+
details = (0, import_ai.redactValue)(details, toolRedactionOptions());
|
|
1483
1522
|
const durationMs = Date.now() - startTime;
|
|
1484
1523
|
pushEvent({
|
|
1485
1524
|
type: "tool_call_end",
|
|
@@ -1521,6 +1560,11 @@ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
|
|
|
1521
1560
|
for (const phase of phases) {
|
|
1522
1561
|
if (options.signal?.aborted) break;
|
|
1523
1562
|
if (phase.sequential) {
|
|
1563
|
+
const signature = JSON.stringify([
|
|
1564
|
+
phase.sequential.name,
|
|
1565
|
+
canonicalToolArgs(phase.sequential.args)
|
|
1566
|
+
]);
|
|
1567
|
+
if (!options.seenToolCalls.has(signature)) options.seenToolCalls.clear();
|
|
1524
1568
|
dispatchedIds.add(phase.sequential.id);
|
|
1525
1569
|
const record = await executeSingleToolCall(
|
|
1526
1570
|
phase.sequential,
|