@prestyj/agent 5.12.0 → 5.13.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
@@ -951,6 +951,7 @@ async function* agentLoop(messages, options) {
951
951
  continue;
952
952
  }
953
953
  }
954
+ const emptyExhausted = !hasActionableContent;
954
955
  emptyResponseRetries = 0;
955
956
  useNonStreamingFallback = false;
956
957
  totalUsage.inputTokens += response.usage.inputTokens;
@@ -964,9 +965,11 @@ async function* agentLoop(messages, options) {
964
965
  if (response.usage.cacheWrite) {
965
966
  totalUsage.cacheWrite = (totalUsage.cacheWrite ?? 0) + response.usage.cacheWrite;
966
967
  }
967
- messages.push(response.message);
968
- latestProviderUsage = response.usage;
969
- usageAnchorIndex = messages.length - 1;
968
+ if (!emptyExhausted) {
969
+ messages.push(response.message);
970
+ latestProviderUsage = response.usage;
971
+ usageAnchorIndex = messages.length - 1;
972
+ }
970
973
  const completedAt = Date.now();
971
974
  const outputTokensPerSecond = providerDurationMs > 0 && response.usage.outputTokens > 0 ? response.usage.outputTokens / (providerDurationMs / 1e3) : void 0;
972
975
  const timing = {
@@ -998,8 +1001,15 @@ async function* agentLoop(messages, options) {
998
1001
  }
999
1002
  consecutivePauses = 0;
1000
1003
  const allToolCalls = extractToolCalls(response.message.content);
1001
- if (response.stopReason !== "tool_use" && allToolCalls.length === 0) {
1002
- if (response.stopReason === "max_tokens") {
1004
+ if (emptyExhausted || response.stopReason !== "tool_use" && allToolCalls.length === 0) {
1005
+ if (emptyExhausted) {
1006
+ diag("empty_response_exhausted", {
1007
+ provider: options.provider,
1008
+ model: options.model,
1009
+ stopReason: response.stopReason
1010
+ });
1011
+ yield { type: "truncated", reason: "empty_response", continued: false };
1012
+ } else if (response.stopReason === "max_tokens") {
1003
1013
  if (maxTokensContinuations < MAX_OUTPUT_CONTINUATIONS) {
1004
1014
  maxTokensContinuations++;
1005
1015
  diag("max_tokens_continuation", {
@@ -1221,6 +1231,7 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
1221
1231
  let resultContent;
1222
1232
  let details;
1223
1233
  let isError = false;
1234
+ let invalidArgAttempt;
1224
1235
  const tool = options.toolMap.get(toolCall.name);
1225
1236
  if (!tool) {
1226
1237
  resultContent = `Unknown tool: ${toolCall.name}`;
@@ -1258,6 +1269,7 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
1258
1269
  const failureKey = `${toolCall.name}:${prettyError}`;
1259
1270
  const failureCount = (options.invalidToolArgumentCounts.get(failureKey) ?? 0) + 1;
1260
1271
  options.invalidToolArgumentCounts.set(failureKey, failureCount);
1272
+ invalidArgAttempt = failureCount;
1261
1273
  resultContent = `Invalid arguments for tool \`${toolCall.name}\`:
1262
1274
  ` + prettyError + "\nRe-issue the call with each field as the correct type.";
1263
1275
  if (failureCount >= 3) {
@@ -1288,7 +1300,8 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
1288
1300
  result: toolResultPreview(resultContent),
1289
1301
  details,
1290
1302
  isError,
1291
- durationMs
1303
+ durationMs,
1304
+ ...invalidArgAttempt === void 0 ? {} : { invalidArgAttempt }
1292
1305
  });
1293
1306
  return { toolCallId: toolCall.id, content: resultContent, isError };
1294
1307
  }