@dudousxd/nestjs-agent-core 0.9.0 → 0.11.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
@@ -45,8 +45,11 @@ __export(index_exports, {
45
45
  AGENT_TOOL_REGISTRY: () => AGENT_TOOL_REGISTRY,
46
46
  AgentRegistry: () => AgentRegistry,
47
47
  AgentStreamError: () => AgentStreamError,
48
+ DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS: () => DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS,
49
+ DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS: () => DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS,
48
50
  DefaultRolesPolicy: () => DefaultRolesPolicy,
49
51
  QuotaExceededError: () => QuotaExceededError,
52
+ THREAD_DETAIL_CONTENT_CHARS: () => THREAD_DETAIL_CONTENT_CHARS,
50
53
  ToolForbiddenError: () => ToolForbiddenError,
51
54
  ToolInputInvalidError: () => ToolInputInvalidError,
52
55
  ToolNotFoundError: () => ToolNotFoundError,
@@ -61,6 +64,8 @@ __export(index_exports, {
61
64
  estimateCost: () => estimateCost,
62
65
  filterToolsByAllowList: () => filterToolsByAllowList,
63
66
  filterToolsByRole: () => filterToolsByRole,
67
+ invokeWithTransientRetry: () => invokeWithTransientRetry,
68
+ isTransientToolError: () => isTransientToolError,
64
69
  publishAgentDelegated: () => publishAgentDelegated,
65
70
  publishAgentMessage: () => publishAgentMessage,
66
71
  publishAgentQuotaExceeded: () => publishAgentQuotaExceeded,
@@ -69,10 +74,14 @@ __export(index_exports, {
69
74
  publishAgentRunFinished: () => publishAgentRunFinished,
70
75
  publishAgentRunStarted: () => publishAgentRunStarted,
71
76
  publishAgentToolCall: () => publishAgentToolCall,
77
+ publishAgentToolRetry: () => publishAgentToolRetry,
78
+ resolveToolTransientRetryNumbers: () => resolveToolTransientRetryNumbers,
79
+ rollupThreadUsage: () => rollupThreadUsage,
72
80
  runAgentLoop: () => runAgentLoop,
73
81
  seedModelPrices: () => seedModelPrices,
74
82
  traceLlmTurn: () => traceLlmTurn,
75
83
  traceToolExecution: () => traceToolExecution,
84
+ truncateDetailContent: () => truncateDetailContent,
76
85
  withToolTimeout: () => withToolTimeout
77
86
  });
78
87
  module.exports = __toCommonJS(index_exports);
@@ -128,6 +137,22 @@ async function seedModelPrices(store, prices) {
128
137
  }
129
138
  __name(seedModelPrices, "seedModelPrices");
130
139
 
140
+ // src/spi/governance-queries.ts
141
+ var THREAD_DETAIL_CONTENT_CHARS = 2e3;
142
+ function truncateDetailContent(content) {
143
+ if (content.length <= THREAD_DETAIL_CONTENT_CHARS) {
144
+ return {
145
+ content,
146
+ truncated: false
147
+ };
148
+ }
149
+ return {
150
+ content: content.slice(0, THREAD_DETAIL_CONTENT_CHARS),
151
+ truncated: true
152
+ };
153
+ }
154
+ __name(truncateDetailContent, "truncateDetailContent");
155
+
131
156
  // src/governance/compute.ts
132
157
  function estimateCost(usage, price) {
133
158
  if (price === void 0) {
@@ -233,6 +258,24 @@ function bucketByThread(rows, prices, threads, options) {
233
258
  return result.slice(0, options.limit);
234
259
  }
235
260
  __name(bucketByThread, "bucketByThread");
261
+ function rollupThreadUsage(rows, prices) {
262
+ const rollup = {
263
+ requests: 0,
264
+ inputTokens: 0,
265
+ outputTokens: 0,
266
+ totalTokens: 0,
267
+ costUsd: 0
268
+ };
269
+ for (const row of rows) {
270
+ rollup.requests += 1;
271
+ rollup.inputTokens += row.inputTokens;
272
+ rollup.outputTokens += row.outputTokens;
273
+ rollup.totalTokens += row.inputTokens + row.outputTokens;
274
+ rollup.costUsd += rowCost(row, prices);
275
+ }
276
+ return rollup;
277
+ }
278
+ __name(rollupThreadUsage, "rollupThreadUsage");
236
279
  function bucketUsageTrend(rows, prices) {
237
280
  const byDay = /* @__PURE__ */ new Map();
238
281
  for (const row of rows) {
@@ -439,6 +482,10 @@ function publishAgentRetrieved(payload) {
439
482
  (0, import_nestjs_diagnostics.emit)("agent", "retrieved", payload);
440
483
  }
441
484
  __name(publishAgentRetrieved, "publishAgentRetrieved");
485
+ function publishAgentToolRetry(payload) {
486
+ (0, import_nestjs_diagnostics.emit)("agent", "tool.retry", payload);
487
+ }
488
+ __name(publishAgentToolRetry, "publishAgentToolRetry");
442
489
  var AGENT_SPAN_EVENTS = [
443
490
  "llm.turn",
444
491
  "tool.execution",
@@ -453,13 +500,96 @@ var AGENT_DIAGNOSTIC_EVENTS = [
453
500
  "run.finished",
454
501
  "run.failed",
455
502
  "delegated",
456
- "retrieved"
503
+ "retrieved",
504
+ "tool.retry"
457
505
  ];
458
506
  function agentDiagnosticKey(event) {
459
507
  return `agent:${event}`;
460
508
  }
461
509
  __name(agentDiagnosticKey, "agentDiagnosticKey");
462
510
 
511
+ // src/tool-retry.ts
512
+ function hasTransientShape(error) {
513
+ if (typeof error !== "object" || error === null) {
514
+ return false;
515
+ }
516
+ const code = "code" in error ? error.code : void 0;
517
+ const errno = "errno" in error ? error.errno : void 0;
518
+ const sqlState = "sqlState" in error ? error.sqlState : void 0;
519
+ if (code === 1213 || code === 1205 || errno === 1213 || errno === 1205) {
520
+ return true;
521
+ }
522
+ if (code === "ER_LOCK_DEADLOCK" || code === "ER_LOCK_WAIT_TIMEOUT") {
523
+ return true;
524
+ }
525
+ if (code === "40001" || code === "40P01" || sqlState === "40001" || sqlState === "40P01") {
526
+ return true;
527
+ }
528
+ if (code === "SQLITE_BUSY") {
529
+ return true;
530
+ }
531
+ const message = "message" in error ? error.message : void 0;
532
+ return typeof message === "string" && /deadlock|lock wait timeout|serialization failure/i.test(message);
533
+ }
534
+ __name(hasTransientShape, "hasTransientShape");
535
+ function isTransientToolError(error) {
536
+ if (hasTransientShape(error)) {
537
+ return true;
538
+ }
539
+ if (typeof error === "object" && error !== null && "cause" in error) {
540
+ const cause = error.cause;
541
+ if (cause !== void 0 && cause !== error && hasTransientShape(cause)) {
542
+ return true;
543
+ }
544
+ }
545
+ return false;
546
+ }
547
+ __name(isTransientToolError, "isTransientToolError");
548
+ var DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS = 2;
549
+ var DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS = 150;
550
+ function resolveToolTransientRetryNumbers(setting) {
551
+ if (setting === false) {
552
+ return false;
553
+ }
554
+ return {
555
+ attempts: setting?.attempts ?? DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS,
556
+ backoffMs: setting?.backoffMs ?? DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS
557
+ };
558
+ }
559
+ __name(resolveToolTransientRetryNumbers, "resolveToolTransientRetryNumbers");
560
+ function delay(ms) {
561
+ return new Promise((resolve) => {
562
+ setTimeout(resolve, ms);
563
+ });
564
+ }
565
+ __name(delay, "delay");
566
+ async function invokeWithTransientRetry(fn, setting, options) {
567
+ if (setting === false) {
568
+ return fn();
569
+ }
570
+ const attempts = setting.attempts ?? DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS;
571
+ const backoffMs = setting.backoffMs ?? DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS;
572
+ const classify = setting.classify ?? isTransientToolError;
573
+ let attempt = 1;
574
+ for (; ; ) {
575
+ try {
576
+ return await fn();
577
+ } catch (error) {
578
+ if (options?.isControlFlowError?.(error) === true) {
579
+ throw error;
580
+ }
581
+ const attemptsRemain = attempt < attempts;
582
+ if (!attemptsRemain || !classify(error)) {
583
+ throw error;
584
+ }
585
+ options?.onRetry?.(attempt, error);
586
+ await delay(backoffMs * attempt);
587
+ attempt += 1;
588
+ }
589
+ }
590
+ }
591
+ __name(invokeWithTransientRetry, "invokeWithTransientRetry");
592
+
463
593
  // src/agent-loop.ts
464
594
  function resolveCostUsd(usage, reportedCostUsd, price) {
465
595
  if (reportedCostUsd !== void 0) {
@@ -1018,7 +1148,10 @@ ${buildContextBlock(passages)}`;
1018
1148
  ctx: stepCtx,
1019
1149
  ...deps.toolTimeoutMs !== void 0 ? {
1020
1150
  timeoutMs: deps.toolTimeoutMs
1021
- } : {}
1151
+ } : {},
1152
+ // Numeric-only: the handler applies withToolTimeout AND its own local `classify` — see
1153
+ // ToolStepEnvelope.transientRetry.
1154
+ transientRetry: resolveToolTransientRetryNumbers(deps.toolTransientRetry)
1022
1155
  };
1023
1156
  output = await hooks.dispatchTool(call, envelope);
1024
1157
  } else {
@@ -1026,7 +1159,19 @@ ${buildContextBlock(passages)}`;
1026
1159
  toolCallId: call.id,
1027
1160
  toolName: call.name,
1028
1161
  toolType
1029
- }, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy)));
1162
+ }, () => invokeWithTransientRetry(() => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy), deps.toolTransientRetry ?? {}, {
1163
+ ...hooks.isControlFlowError !== void 0 ? {
1164
+ isControlFlowError: hooks.isControlFlowError
1165
+ } : {},
1166
+ onRetry: /* @__PURE__ */ __name((attempt, retryError) => {
1167
+ publishAgentToolRetry({
1168
+ toolName: call.name,
1169
+ toolCallId: call.id,
1170
+ attempt,
1171
+ message: retryError instanceof Error ? retryError.message : String(retryError)
1172
+ });
1173
+ }, "onRetry")
1174
+ })));
1030
1175
  output = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
1031
1176
  }
1032
1177
  const executionMs = Date.now() - startedAt2;
@@ -1149,8 +1294,11 @@ __name(runAgentLoop, "runAgentLoop");
1149
1294
  AGENT_TOOL_REGISTRY,
1150
1295
  AgentRegistry,
1151
1296
  AgentStreamError,
1297
+ DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS,
1298
+ DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS,
1152
1299
  DefaultRolesPolicy,
1153
1300
  QuotaExceededError,
1301
+ THREAD_DETAIL_CONTENT_CHARS,
1154
1302
  ToolForbiddenError,
1155
1303
  ToolInputInvalidError,
1156
1304
  ToolNotFoundError,
@@ -1165,6 +1313,8 @@ __name(runAgentLoop, "runAgentLoop");
1165
1313
  estimateCost,
1166
1314
  filterToolsByAllowList,
1167
1315
  filterToolsByRole,
1316
+ invokeWithTransientRetry,
1317
+ isTransientToolError,
1168
1318
  publishAgentDelegated,
1169
1319
  publishAgentMessage,
1170
1320
  publishAgentQuotaExceeded,
@@ -1173,10 +1323,14 @@ __name(runAgentLoop, "runAgentLoop");
1173
1323
  publishAgentRunFinished,
1174
1324
  publishAgentRunStarted,
1175
1325
  publishAgentToolCall,
1326
+ publishAgentToolRetry,
1327
+ resolveToolTransientRetryNumbers,
1328
+ rollupThreadUsage,
1176
1329
  runAgentLoop,
1177
1330
  seedModelPrices,
1178
1331
  traceLlmTurn,
1179
1332
  traceToolExecution,
1333
+ truncateDetailContent,
1180
1334
  withToolTimeout
1181
1335
  });
1182
1336
  //# sourceMappingURL=index.cjs.map