@prestyj/agent 5.6.0 → 5.8.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 +85 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -5
- package/dist/index.d.ts +34 -5
- package/dist/index.js +87 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -154,7 +154,7 @@ function classifyOverload(err) {
|
|
|
154
154
|
if (statusCode === 529 || msg.includes("overloaded") || msg.includes("529")) {
|
|
155
155
|
return "overloaded";
|
|
156
156
|
}
|
|
157
|
-
if (statusCode === 500 || statusCode === 502 || statusCode === 503 || statusCode === 504 || msg.includes("api_error") || msg.includes("server_error") || msg.includes("internal server error") || msg.includes("bad gateway") || msg.includes("service unavailable") || msg.includes("gateway timeout")) {
|
|
157
|
+
if (statusCode === 500 || statusCode === 502 || statusCode === 503 || statusCode === 504 || statusCode === 507 || msg.includes("api_error") || msg.includes("server_error") || msg.includes("internal server error") || msg.includes("bad gateway") || msg.includes("service unavailable") || msg.includes("gateway timeout") || msg.includes("exceeded request buffer limit while retrying upstream")) {
|
|
158
158
|
return "provider_error";
|
|
159
159
|
}
|
|
160
160
|
if (isOpaqueProviderMessage(err.message)) {
|
|
@@ -260,6 +260,8 @@ async function* agentLoop(messages, options) {
|
|
|
260
260
|
const maxContinuations = options.maxContinuations ?? 5;
|
|
261
261
|
let toolMap = new Map((options.tools ?? []).map((t) => [t.name, t]));
|
|
262
262
|
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
263
|
+
let latestProviderUsage;
|
|
264
|
+
let usageAnchorIndex;
|
|
263
265
|
let turn = 0;
|
|
264
266
|
let hitMaxTurns = false;
|
|
265
267
|
let firstTurn = true;
|
|
@@ -296,10 +298,14 @@ async function* agentLoop(messages, options) {
|
|
|
296
298
|
const initialHardTimeoutMs = isSakana ? STREAM_THINKING_HARD_TIMEOUT_MS : STREAM_HARD_TIMEOUT_MS;
|
|
297
299
|
const MAX_TOOLCALL_DELTA_CHARS = 1e6;
|
|
298
300
|
const MAX_TOOLCALL_DELTA_EVENTS = 2e4;
|
|
301
|
+
let logicalTurnStartedAt = 0;
|
|
302
|
+
let firstProviderEventAt;
|
|
303
|
+
let providerDurationMs = 0;
|
|
299
304
|
try {
|
|
300
305
|
while (turn < maxTurns) {
|
|
301
306
|
options.signal?.throwIfAborted();
|
|
302
307
|
turn++;
|
|
308
|
+
if (logicalTurnStartedAt === 0) logicalTurnStartedAt = Date.now();
|
|
303
309
|
toolMap = new Map((options.tools ?? []).map((t) => [t.name, t]));
|
|
304
310
|
if (_diagFn) {
|
|
305
311
|
let msgChars = 0;
|
|
@@ -332,7 +338,11 @@ async function* agentLoop(messages, options) {
|
|
|
332
338
|
firstTurn = false;
|
|
333
339
|
if (options.transformContext) {
|
|
334
340
|
diag("transform_start");
|
|
335
|
-
const
|
|
341
|
+
const pendingMessages = usageAnchorIndex === void 0 ? [] : messages.slice(usageAnchorIndex + 1);
|
|
342
|
+
const transformed = await options.transformContext(messages, {
|
|
343
|
+
usage: latestProviderUsage,
|
|
344
|
+
pendingMessages
|
|
345
|
+
});
|
|
336
346
|
if (transformed !== messages) {
|
|
337
347
|
diag("transform_compacted", {
|
|
338
348
|
before: messages.length,
|
|
@@ -340,6 +350,8 @@ async function* agentLoop(messages, options) {
|
|
|
340
350
|
});
|
|
341
351
|
messages.length = 0;
|
|
342
352
|
messages.push(...transformed);
|
|
353
|
+
latestProviderUsage = void 0;
|
|
354
|
+
usageAnchorIndex = void 0;
|
|
343
355
|
}
|
|
344
356
|
diag("transform_end");
|
|
345
357
|
}
|
|
@@ -349,6 +361,7 @@ async function* agentLoop(messages, options) {
|
|
|
349
361
|
let idleTimer = null;
|
|
350
362
|
let hardTimer = null;
|
|
351
363
|
let idleTimedOut = false;
|
|
364
|
+
let providerAttemptStartedAt;
|
|
352
365
|
let streamEventCount = 0;
|
|
353
366
|
let lastEventTime = Date.now();
|
|
354
367
|
let streamCallStart = Date.now();
|
|
@@ -394,12 +407,14 @@ async function* agentLoop(messages, options) {
|
|
|
394
407
|
try {
|
|
395
408
|
diag("stream_call", { nonStreaming: useNonStreamingFallback });
|
|
396
409
|
streamCallStart = Date.now();
|
|
410
|
+
providerAttemptStartedAt = streamCallStart;
|
|
397
411
|
const result = (0, import_ai.stream)({
|
|
398
412
|
provider: options.provider,
|
|
399
413
|
model: options.model,
|
|
400
414
|
messages,
|
|
401
415
|
tools: options.tools,
|
|
402
416
|
serverTools: options.serverTools,
|
|
417
|
+
toolChoice: options.toolChoice,
|
|
403
418
|
webSearch: options.webSearch,
|
|
404
419
|
maxTokens: options.maxTokens,
|
|
405
420
|
temperature: options.temperature,
|
|
@@ -442,6 +457,7 @@ async function* agentLoop(messages, options) {
|
|
|
442
457
|
maxConsumerLagMs = consumerLag;
|
|
443
458
|
}
|
|
444
459
|
streamEventCount++;
|
|
460
|
+
if (firstProviderEventAt === void 0) firstProviderEventAt = pullTime;
|
|
445
461
|
eventTypeCounts[event.type] = (eventTypeCounts[event.type] ?? 0) + 1;
|
|
446
462
|
lastEventType = event.type;
|
|
447
463
|
if ((event.type === "text_delta" || event.type === "server_toolcall" || event.type === "toolcall_delta") && !hasReceivedEvent) {
|
|
@@ -534,6 +550,7 @@ async function* agentLoop(messages, options) {
|
|
|
534
550
|
eventTypes: eventTypeCounts
|
|
535
551
|
});
|
|
536
552
|
response = await abortablePromise(result.response, streamController.signal);
|
|
553
|
+
if (firstProviderEventAt === void 0) firstProviderEventAt = Date.now();
|
|
537
554
|
} catch (err) {
|
|
538
555
|
if (streamController.signal.aborted) closeIterator(streamIterator);
|
|
539
556
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -595,10 +612,17 @@ async function* agentLoop(messages, options) {
|
|
|
595
612
|
...overflowDetails
|
|
596
613
|
});
|
|
597
614
|
try {
|
|
598
|
-
const
|
|
615
|
+
const pendingMessages = usageAnchorIndex === void 0 ? [] : messages.slice(usageAnchorIndex + 1);
|
|
616
|
+
const compacted = await options.transformContext(messages, {
|
|
617
|
+
force: true,
|
|
618
|
+
usage: latestProviderUsage,
|
|
619
|
+
pendingMessages
|
|
620
|
+
});
|
|
599
621
|
if (compacted !== messages && compacted.length < messages.length) {
|
|
600
622
|
messages.length = 0;
|
|
601
623
|
messages.push(...compacted);
|
|
624
|
+
latestProviderUsage = void 0;
|
|
625
|
+
usageAnchorIndex = void 0;
|
|
602
626
|
diag("overflow_compact_success", {
|
|
603
627
|
attempt: overflowCompactionAttempts,
|
|
604
628
|
messages: messages.length,
|
|
@@ -758,6 +782,9 @@ async function* agentLoop(messages, options) {
|
|
|
758
782
|
});
|
|
759
783
|
throw err;
|
|
760
784
|
} finally {
|
|
785
|
+
if (providerAttemptStartedAt !== void 0) {
|
|
786
|
+
providerDurationMs += Date.now() - providerAttemptStartedAt;
|
|
787
|
+
}
|
|
761
788
|
if (idleTimer) clearTimeout(idleTimer);
|
|
762
789
|
if (hardTimer) clearTimeout(hardTimer);
|
|
763
790
|
options.signal?.removeEventListener("abort", forwardAbort);
|
|
@@ -801,11 +828,29 @@ async function* agentLoop(messages, options) {
|
|
|
801
828
|
totalUsage.cacheWrite = (totalUsage.cacheWrite ?? 0) + response.usage.cacheWrite;
|
|
802
829
|
}
|
|
803
830
|
messages.push(response.message);
|
|
831
|
+
latestProviderUsage = response.usage;
|
|
832
|
+
usageAnchorIndex = messages.length - 1;
|
|
833
|
+
const completedAt = Date.now();
|
|
834
|
+
const outputTokensPerSecond = providerDurationMs > 0 && response.usage.outputTokens > 0 ? response.usage.outputTokens / (providerDurationMs / 1e3) : void 0;
|
|
835
|
+
const timing = {
|
|
836
|
+
startedAt: logicalTurnStartedAt,
|
|
837
|
+
...firstProviderEventAt !== void 0 ? {
|
|
838
|
+
firstProviderEventAt,
|
|
839
|
+
ttftMs: Math.max(0, firstProviderEventAt - logicalTurnStartedAt)
|
|
840
|
+
} : {},
|
|
841
|
+
completedAt,
|
|
842
|
+
providerDurationMs,
|
|
843
|
+
...outputTokensPerSecond !== void 0 ? { outputTokensPerSecond } : {}
|
|
844
|
+
};
|
|
845
|
+
logicalTurnStartedAt = 0;
|
|
846
|
+
firstProviderEventAt = void 0;
|
|
847
|
+
providerDurationMs = 0;
|
|
804
848
|
yield {
|
|
805
849
|
type: "turn_end",
|
|
806
850
|
turn,
|
|
807
851
|
stopReason: response.stopReason,
|
|
808
|
-
usage: response.usage
|
|
852
|
+
usage: response.usage,
|
|
853
|
+
timing
|
|
809
854
|
};
|
|
810
855
|
if (response.stopReason === "pause_turn") {
|
|
811
856
|
consecutivePauses++;
|
|
@@ -872,6 +917,7 @@ async function* agentLoop(messages, options) {
|
|
|
872
917
|
const executionOptions = {
|
|
873
918
|
signal: options.signal,
|
|
874
919
|
maxToolResultChars: options.maxToolResultChars,
|
|
920
|
+
maxTurnToolResultChars: options.maxTurnToolResultChars,
|
|
875
921
|
toolMap,
|
|
876
922
|
invalidToolArgumentCounts,
|
|
877
923
|
markFatalToolArgumentError
|
|
@@ -989,8 +1035,8 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
989
1035
|
ctx.signal
|
|
990
1036
|
);
|
|
991
1037
|
const normalized = normalizeToolResult(raw);
|
|
992
|
-
resultContent = normalized.content;
|
|
993
|
-
details = normalized.details;
|
|
1038
|
+
resultContent = (0, import_ai.redactValue)(normalized.content);
|
|
1039
|
+
details = (0, import_ai.redactValue)(normalized.details);
|
|
994
1040
|
for (const key of options.invalidToolArgumentCounts.keys()) {
|
|
995
1041
|
if (key.startsWith(`${toolCall.name}:`)) options.invalidToolArgumentCounts.delete(key);
|
|
996
1042
|
}
|
|
@@ -1018,10 +1064,12 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
1018
1064
|
);
|
|
1019
1065
|
}
|
|
1020
1066
|
} else {
|
|
1021
|
-
resultContent = err instanceof Error ? err.message : String(err);
|
|
1067
|
+
resultContent = (0, import_ai.redactValue)(err instanceof Error ? err.message : String(err));
|
|
1022
1068
|
}
|
|
1023
1069
|
}
|
|
1024
1070
|
}
|
|
1071
|
+
resultContent = (0, import_ai.redactValue)(resultContent);
|
|
1072
|
+
details = (0, import_ai.redactValue)(details);
|
|
1025
1073
|
const durationMs = Date.now() - startTime;
|
|
1026
1074
|
pushEvent({
|
|
1027
1075
|
type: "tool_call_end",
|
|
@@ -1109,6 +1157,7 @@ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
|
|
|
1109
1157
|
}
|
|
1110
1158
|
const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
|
|
1111
1159
|
capToolResults(toolResults, options.maxToolResultChars);
|
|
1160
|
+
capTurnToolResults(toolResults, options.maxTurnToolResultChars);
|
|
1112
1161
|
return { toolResults, aborted };
|
|
1113
1162
|
}
|
|
1114
1163
|
async function* executeToolCallsParallel(toolCalls, initialToolResults, options) {
|
|
@@ -1148,6 +1197,7 @@ async function* executeToolCallsParallel(toolCalls, initialToolResults, options)
|
|
|
1148
1197
|
}
|
|
1149
1198
|
const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
|
|
1150
1199
|
capToolResults(toolResults, options.maxToolResultChars);
|
|
1200
|
+
capTurnToolResults(toolResults, options.maxTurnToolResultChars);
|
|
1151
1201
|
return { toolResults, aborted };
|
|
1152
1202
|
}
|
|
1153
1203
|
function buildToolResults(initialToolResults, toolCalls, resultsById) {
|
|
@@ -1190,6 +1240,34 @@ function capToolResults(toolResults, maxToolResultChars) {
|
|
|
1190
1240
|
` + tail;
|
|
1191
1241
|
}
|
|
1192
1242
|
}
|
|
1243
|
+
function capTurnToolResults(toolResults, maxTurnToolResultChars) {
|
|
1244
|
+
if (!maxTurnToolResultChars) return;
|
|
1245
|
+
const textResults = toolResults.filter(
|
|
1246
|
+
(toolResult) => typeof toolResult.content === "string"
|
|
1247
|
+
);
|
|
1248
|
+
const total = textResults.reduce((sum, toolResult) => sum + toolResult.content.length, 0);
|
|
1249
|
+
if (total <= maxTurnToolResultChars) return;
|
|
1250
|
+
const bySize = [...textResults].sort((a, b) => a.content.length - b.content.length);
|
|
1251
|
+
let remaining = maxTurnToolResultChars;
|
|
1252
|
+
let left = bySize.length;
|
|
1253
|
+
for (const toolResult of bySize) {
|
|
1254
|
+
const fairShare = Math.floor(remaining / left);
|
|
1255
|
+
left--;
|
|
1256
|
+
if (toolResult.content.length <= fairShare) {
|
|
1257
|
+
remaining -= toolResult.content.length;
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1260
|
+
remaining -= fairShare;
|
|
1261
|
+
const headChars = Math.floor(fairShare * 0.7);
|
|
1262
|
+
const tailChars = fairShare - headChars;
|
|
1263
|
+
const omitted = toolResult.content.length - fairShare;
|
|
1264
|
+
toolResult.content = toolResult.content.slice(0, headChars) + `
|
|
1265
|
+
|
|
1266
|
+
[... ${omitted} characters trimmed: this turn's combined tool results exceeded the per-turn budget. Re-run this call alone with narrower filters or offset/limit if you need the omitted content ...]
|
|
1267
|
+
|
|
1268
|
+
` + (tailChars > 0 ? toolResult.content.slice(-tailChars) : "");
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1193
1271
|
function normalizeToolResult(raw) {
|
|
1194
1272
|
return typeof raw === "string" ? { content: raw } : raw;
|
|
1195
1273
|
}
|