@prestyj/agent 5.7.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 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;
@@ -336,7 +338,11 @@ async function* agentLoop(messages, options) {
336
338
  firstTurn = false;
337
339
  if (options.transformContext) {
338
340
  diag("transform_start");
339
- const transformed = await options.transformContext(messages);
341
+ const pendingMessages = usageAnchorIndex === void 0 ? [] : messages.slice(usageAnchorIndex + 1);
342
+ const transformed = await options.transformContext(messages, {
343
+ usage: latestProviderUsage,
344
+ pendingMessages
345
+ });
340
346
  if (transformed !== messages) {
341
347
  diag("transform_compacted", {
342
348
  before: messages.length,
@@ -344,6 +350,8 @@ async function* agentLoop(messages, options) {
344
350
  });
345
351
  messages.length = 0;
346
352
  messages.push(...transformed);
353
+ latestProviderUsage = void 0;
354
+ usageAnchorIndex = void 0;
347
355
  }
348
356
  diag("transform_end");
349
357
  }
@@ -604,10 +612,17 @@ async function* agentLoop(messages, options) {
604
612
  ...overflowDetails
605
613
  });
606
614
  try {
607
- const compacted = await options.transformContext(messages, { force: true });
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
+ });
608
621
  if (compacted !== messages && compacted.length < messages.length) {
609
622
  messages.length = 0;
610
623
  messages.push(...compacted);
624
+ latestProviderUsage = void 0;
625
+ usageAnchorIndex = void 0;
611
626
  diag("overflow_compact_success", {
612
627
  attempt: overflowCompactionAttempts,
613
628
  messages: messages.length,
@@ -813,6 +828,8 @@ async function* agentLoop(messages, options) {
813
828
  totalUsage.cacheWrite = (totalUsage.cacheWrite ?? 0) + response.usage.cacheWrite;
814
829
  }
815
830
  messages.push(response.message);
831
+ latestProviderUsage = response.usage;
832
+ usageAnchorIndex = messages.length - 1;
816
833
  const completedAt = Date.now();
817
834
  const outputTokensPerSecond = providerDurationMs > 0 && response.usage.outputTokens > 0 ? response.usage.outputTokens / (providerDurationMs / 1e3) : void 0;
818
835
  const timing = {
@@ -900,6 +917,7 @@ async function* agentLoop(messages, options) {
900
917
  const executionOptions = {
901
918
  signal: options.signal,
902
919
  maxToolResultChars: options.maxToolResultChars,
920
+ maxTurnToolResultChars: options.maxTurnToolResultChars,
903
921
  toolMap,
904
922
  invalidToolArgumentCounts,
905
923
  markFatalToolArgumentError
@@ -1139,6 +1157,7 @@ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
1139
1157
  }
1140
1158
  const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
1141
1159
  capToolResults(toolResults, options.maxToolResultChars);
1160
+ capTurnToolResults(toolResults, options.maxTurnToolResultChars);
1142
1161
  return { toolResults, aborted };
1143
1162
  }
1144
1163
  async function* executeToolCallsParallel(toolCalls, initialToolResults, options) {
@@ -1178,6 +1197,7 @@ async function* executeToolCallsParallel(toolCalls, initialToolResults, options)
1178
1197
  }
1179
1198
  const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
1180
1199
  capToolResults(toolResults, options.maxToolResultChars);
1200
+ capTurnToolResults(toolResults, options.maxTurnToolResultChars);
1181
1201
  return { toolResults, aborted };
1182
1202
  }
1183
1203
  function buildToolResults(initialToolResults, toolCalls, resultsById) {
@@ -1220,6 +1240,34 @@ function capToolResults(toolResults, maxToolResultChars) {
1220
1240
  ` + tail;
1221
1241
  }
1222
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
+ }
1223
1271
  function normalizeToolResult(raw) {
1224
1272
  return typeof raw === "string" ? { content: raw } : raw;
1225
1273
  }