@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 +157 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +252 -3
- package/dist/index.d.ts +252 -3
- package/dist/index.js +148 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|