@kenkaiiii/gg-agent 5.63.0 → 5.64.1

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
@@ -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_gg_ai.environmentSecrets)(process.env) };
126
+ return _toolRedaction;
127
+ }
123
128
  var _diagFn = null;
124
129
  function setStreamDiagnostic(fn) {
125
130
  _diagFn = fn;
@@ -1210,7 +1215,8 @@ async function* agentLoop(messages, options) {
1210
1215
  maxTurnToolResultChars: options.maxTurnToolResultChars,
1211
1216
  toolMap,
1212
1217
  invalidToolArgumentCounts,
1213
- markFatalToolArgumentError
1218
+ markFatalToolArgumentError,
1219
+ seenToolCalls: /* @__PURE__ */ new Set()
1214
1220
  };
1215
1221
  const hasSequentialToolCall = toolCalls.some(
1216
1222
  (toolCall) => toolMap.get(toolCall.name)?.executionMode === "sequential"
@@ -1331,6 +1337,15 @@ async function* agentLoop(messages, options) {
1331
1337
  totalUsage: { ...totalUsage }
1332
1338
  };
1333
1339
  }
1340
+ function canonicalToolArgs(value) {
1341
+ if (Array.isArray(value)) return value.map(canonicalToolArgs);
1342
+ if (value !== null && typeof value === "object") {
1343
+ return Object.fromEntries(
1344
+ Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => [k, canonicalToolArgs(v)])
1345
+ );
1346
+ }
1347
+ return value;
1348
+ }
1334
1349
  function pushToolEvent(eventStream, state, event) {
1335
1350
  if (!state.finalized) eventStream.push(event);
1336
1351
  }
@@ -1347,6 +1362,21 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
1347
1362
  let isError = false;
1348
1363
  let invalidArgAttempt;
1349
1364
  const tool = options.toolMap.get(toolCall.name);
1365
+ if (tool) {
1366
+ const signature = JSON.stringify([toolCall.name, canonicalToolArgs(toolCall.args)]);
1367
+ if (options.seenToolCalls.has(signature)) {
1368
+ const content = "Tool call cancelled: an identical call already appeared in this response; this call was not executed.";
1369
+ pushEvent({
1370
+ type: "tool_call_end",
1371
+ toolCallId: toolCall.id,
1372
+ result: content,
1373
+ isError: true,
1374
+ durationMs: Date.now() - startTime
1375
+ });
1376
+ return { toolCallId: toolCall.id, content, isError: true };
1377
+ }
1378
+ options.seenToolCalls.add(signature);
1379
+ }
1350
1380
  if (!tool) {
1351
1381
  resultContent = `Unknown tool: ${toolCall.name}`;
1352
1382
  isError = true;
@@ -1378,8 +1408,8 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
1378
1408
  };
1379
1409
  const raw = await tool.execute(parsed, ctx);
1380
1410
  const normalized = normalizeToolResult(raw);
1381
- resultContent = (0, import_gg_ai.redactValue)(normalized.content);
1382
- details = (0, import_gg_ai.redactValue)(normalized.details);
1411
+ resultContent = (0, import_gg_ai.redactValue)(normalized.content, toolRedactionOptions());
1412
+ details = (0, import_gg_ai.redactValue)(normalized.details, toolRedactionOptions());
1383
1413
  for (const key of options.invalidToolArgumentCounts.keys()) {
1384
1414
  if (key.startsWith(`${toolCall.name}:`)) options.invalidToolArgumentCounts.delete(key);
1385
1415
  }
@@ -1408,12 +1438,15 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
1408
1438
  );
1409
1439
  }
1410
1440
  } else {
1411
- resultContent = (0, import_gg_ai.redactValue)(err instanceof Error ? err.message : String(err));
1441
+ resultContent = (0, import_gg_ai.redactValue)(
1442
+ err instanceof Error ? err.message : String(err),
1443
+ toolRedactionOptions()
1444
+ );
1412
1445
  }
1413
1446
  }
1414
1447
  }
1415
- resultContent = (0, import_gg_ai.redactValue)(resultContent);
1416
- details = (0, import_gg_ai.redactValue)(details);
1448
+ resultContent = (0, import_gg_ai.redactValue)(resultContent, toolRedactionOptions());
1449
+ details = (0, import_gg_ai.redactValue)(details, toolRedactionOptions());
1417
1450
  const durationMs = Date.now() - startTime;
1418
1451
  pushEvent({
1419
1452
  type: "tool_call_end",
@@ -1455,6 +1488,11 @@ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
1455
1488
  for (const phase of phases) {
1456
1489
  if (options.signal?.aborted) break;
1457
1490
  if (phase.sequential) {
1491
+ const signature = JSON.stringify([
1492
+ phase.sequential.name,
1493
+ canonicalToolArgs(phase.sequential.args)
1494
+ ]);
1495
+ if (!options.seenToolCalls.has(signature)) options.seenToolCalls.clear();
1458
1496
  dispatchedIds.add(phase.sequential.id);
1459
1497
  const record = await executeSingleToolCall(
1460
1498
  phase.sequential,