@dudousxd/nestjs-agent-core 0.8.0 → 0.10.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 +125 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +114 -2
- package/dist/index.d.ts +114 -2
- package/dist/index.js +119 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,8 @@ __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,
|
|
50
52
|
ToolForbiddenError: () => ToolForbiddenError,
|
|
@@ -61,6 +63,8 @@ __export(index_exports, {
|
|
|
61
63
|
estimateCost: () => estimateCost,
|
|
62
64
|
filterToolsByAllowList: () => filterToolsByAllowList,
|
|
63
65
|
filterToolsByRole: () => filterToolsByRole,
|
|
66
|
+
invokeWithTransientRetry: () => invokeWithTransientRetry,
|
|
67
|
+
isTransientToolError: () => isTransientToolError,
|
|
64
68
|
publishAgentDelegated: () => publishAgentDelegated,
|
|
65
69
|
publishAgentMessage: () => publishAgentMessage,
|
|
66
70
|
publishAgentQuotaExceeded: () => publishAgentQuotaExceeded,
|
|
@@ -69,6 +73,8 @@ __export(index_exports, {
|
|
|
69
73
|
publishAgentRunFinished: () => publishAgentRunFinished,
|
|
70
74
|
publishAgentRunStarted: () => publishAgentRunStarted,
|
|
71
75
|
publishAgentToolCall: () => publishAgentToolCall,
|
|
76
|
+
publishAgentToolRetry: () => publishAgentToolRetry,
|
|
77
|
+
resolveToolTransientRetryNumbers: () => resolveToolTransientRetryNumbers,
|
|
72
78
|
runAgentLoop: () => runAgentLoop,
|
|
73
79
|
seedModelPrices: () => seedModelPrices,
|
|
74
80
|
traceLlmTurn: () => traceLlmTurn,
|
|
@@ -439,6 +445,10 @@ function publishAgentRetrieved(payload) {
|
|
|
439
445
|
(0, import_nestjs_diagnostics.emit)("agent", "retrieved", payload);
|
|
440
446
|
}
|
|
441
447
|
__name(publishAgentRetrieved, "publishAgentRetrieved");
|
|
448
|
+
function publishAgentToolRetry(payload) {
|
|
449
|
+
(0, import_nestjs_diagnostics.emit)("agent", "tool.retry", payload);
|
|
450
|
+
}
|
|
451
|
+
__name(publishAgentToolRetry, "publishAgentToolRetry");
|
|
442
452
|
var AGENT_SPAN_EVENTS = [
|
|
443
453
|
"llm.turn",
|
|
444
454
|
"tool.execution",
|
|
@@ -453,13 +463,96 @@ var AGENT_DIAGNOSTIC_EVENTS = [
|
|
|
453
463
|
"run.finished",
|
|
454
464
|
"run.failed",
|
|
455
465
|
"delegated",
|
|
456
|
-
"retrieved"
|
|
466
|
+
"retrieved",
|
|
467
|
+
"tool.retry"
|
|
457
468
|
];
|
|
458
469
|
function agentDiagnosticKey(event) {
|
|
459
470
|
return `agent:${event}`;
|
|
460
471
|
}
|
|
461
472
|
__name(agentDiagnosticKey, "agentDiagnosticKey");
|
|
462
473
|
|
|
474
|
+
// src/tool-retry.ts
|
|
475
|
+
function hasTransientShape(error) {
|
|
476
|
+
if (typeof error !== "object" || error === null) {
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
const code = "code" in error ? error.code : void 0;
|
|
480
|
+
const errno = "errno" in error ? error.errno : void 0;
|
|
481
|
+
const sqlState = "sqlState" in error ? error.sqlState : void 0;
|
|
482
|
+
if (code === 1213 || code === 1205 || errno === 1213 || errno === 1205) {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
if (code === "ER_LOCK_DEADLOCK" || code === "ER_LOCK_WAIT_TIMEOUT") {
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
if (code === "40001" || code === "40P01" || sqlState === "40001" || sqlState === "40P01") {
|
|
489
|
+
return true;
|
|
490
|
+
}
|
|
491
|
+
if (code === "SQLITE_BUSY") {
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
const message = "message" in error ? error.message : void 0;
|
|
495
|
+
return typeof message === "string" && /deadlock|lock wait timeout|serialization failure/i.test(message);
|
|
496
|
+
}
|
|
497
|
+
__name(hasTransientShape, "hasTransientShape");
|
|
498
|
+
function isTransientToolError(error) {
|
|
499
|
+
if (hasTransientShape(error)) {
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
if (typeof error === "object" && error !== null && "cause" in error) {
|
|
503
|
+
const cause = error.cause;
|
|
504
|
+
if (cause !== void 0 && cause !== error && hasTransientShape(cause)) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
__name(isTransientToolError, "isTransientToolError");
|
|
511
|
+
var DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS = 2;
|
|
512
|
+
var DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS = 150;
|
|
513
|
+
function resolveToolTransientRetryNumbers(setting) {
|
|
514
|
+
if (setting === false) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
attempts: setting?.attempts ?? DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS,
|
|
519
|
+
backoffMs: setting?.backoffMs ?? DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
__name(resolveToolTransientRetryNumbers, "resolveToolTransientRetryNumbers");
|
|
523
|
+
function delay(ms) {
|
|
524
|
+
return new Promise((resolve) => {
|
|
525
|
+
setTimeout(resolve, ms);
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
__name(delay, "delay");
|
|
529
|
+
async function invokeWithTransientRetry(fn, setting, options) {
|
|
530
|
+
if (setting === false) {
|
|
531
|
+
return fn();
|
|
532
|
+
}
|
|
533
|
+
const attempts = setting.attempts ?? DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS;
|
|
534
|
+
const backoffMs = setting.backoffMs ?? DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS;
|
|
535
|
+
const classify = setting.classify ?? isTransientToolError;
|
|
536
|
+
let attempt = 1;
|
|
537
|
+
for (; ; ) {
|
|
538
|
+
try {
|
|
539
|
+
return await fn();
|
|
540
|
+
} catch (error) {
|
|
541
|
+
if (options?.isControlFlowError?.(error) === true) {
|
|
542
|
+
throw error;
|
|
543
|
+
}
|
|
544
|
+
const attemptsRemain = attempt < attempts;
|
|
545
|
+
if (!attemptsRemain || !classify(error)) {
|
|
546
|
+
throw error;
|
|
547
|
+
}
|
|
548
|
+
options?.onRetry?.(attempt, error);
|
|
549
|
+
await delay(backoffMs * attempt);
|
|
550
|
+
attempt += 1;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
__name(invokeWithTransientRetry, "invokeWithTransientRetry");
|
|
555
|
+
|
|
463
556
|
// src/agent-loop.ts
|
|
464
557
|
function resolveCostUsd(usage, reportedCostUsd, price) {
|
|
465
558
|
if (reportedCostUsd !== void 0) {
|
|
@@ -861,7 +954,8 @@ ${buildContextBlock(passages)}`;
|
|
|
861
954
|
input: {
|
|
862
955
|
query: input.userText
|
|
863
956
|
},
|
|
864
|
-
status: "auto_executed"
|
|
957
|
+
status: "auto_executed",
|
|
958
|
+
runId: hooks.runId
|
|
865
959
|
});
|
|
866
960
|
await deps.store.updateToolCall({
|
|
867
961
|
toolCallId,
|
|
@@ -910,7 +1004,8 @@ ${buildContextBlock(passages)}`;
|
|
|
910
1004
|
toolName: call.name,
|
|
911
1005
|
toolType: "read",
|
|
912
1006
|
input: call.input,
|
|
913
|
-
status: "auto_executed"
|
|
1007
|
+
status: "auto_executed",
|
|
1008
|
+
runId: hooks.runId
|
|
914
1009
|
}));
|
|
915
1010
|
const overDepth = (input.delegationDepth ?? 0) >= MAX_DELEGATION_DEPTH;
|
|
916
1011
|
publishAgentDelegated({
|
|
@@ -952,7 +1047,8 @@ ${buildContextBlock(passages)}`;
|
|
|
952
1047
|
toolName: call.name,
|
|
953
1048
|
toolType: "action",
|
|
954
1049
|
input: call.input,
|
|
955
|
-
status: "pending_approval"
|
|
1050
|
+
status: "pending_approval",
|
|
1051
|
+
runId: hooks.runId
|
|
956
1052
|
}));
|
|
957
1053
|
const decision = await hooks.awaitApproval(call, ctx);
|
|
958
1054
|
deciderRef = decision.executedByRef ?? input.actor.id;
|
|
@@ -989,7 +1085,8 @@ ${buildContextBlock(passages)}`;
|
|
|
989
1085
|
toolName: call.name,
|
|
990
1086
|
toolType: "read",
|
|
991
1087
|
input: call.input,
|
|
992
|
-
status: "auto_executed"
|
|
1088
|
+
status: "auto_executed",
|
|
1089
|
+
runId: hooks.runId
|
|
993
1090
|
}));
|
|
994
1091
|
}
|
|
995
1092
|
const startedAt2 = Date.now();
|
|
@@ -1014,7 +1111,10 @@ ${buildContextBlock(passages)}`;
|
|
|
1014
1111
|
ctx: stepCtx,
|
|
1015
1112
|
...deps.toolTimeoutMs !== void 0 ? {
|
|
1016
1113
|
timeoutMs: deps.toolTimeoutMs
|
|
1017
|
-
} : {}
|
|
1114
|
+
} : {},
|
|
1115
|
+
// Numeric-only: the handler applies withToolTimeout AND its own local `classify` — see
|
|
1116
|
+
// ToolStepEnvelope.transientRetry.
|
|
1117
|
+
transientRetry: resolveToolTransientRetryNumbers(deps.toolTransientRetry)
|
|
1018
1118
|
};
|
|
1019
1119
|
output = await hooks.dispatchTool(call, envelope);
|
|
1020
1120
|
} else {
|
|
@@ -1022,7 +1122,19 @@ ${buildContextBlock(passages)}`;
|
|
|
1022
1122
|
toolCallId: call.id,
|
|
1023
1123
|
toolName: call.name,
|
|
1024
1124
|
toolType
|
|
1025
|
-
}, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy)
|
|
1125
|
+
}, () => invokeWithTransientRetry(() => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy), deps.toolTransientRetry ?? {}, {
|
|
1126
|
+
...hooks.isControlFlowError !== void 0 ? {
|
|
1127
|
+
isControlFlowError: hooks.isControlFlowError
|
|
1128
|
+
} : {},
|
|
1129
|
+
onRetry: /* @__PURE__ */ __name((attempt, retryError) => {
|
|
1130
|
+
publishAgentToolRetry({
|
|
1131
|
+
toolName: call.name,
|
|
1132
|
+
toolCallId: call.id,
|
|
1133
|
+
attempt,
|
|
1134
|
+
message: retryError instanceof Error ? retryError.message : String(retryError)
|
|
1135
|
+
});
|
|
1136
|
+
}, "onRetry")
|
|
1137
|
+
})));
|
|
1026
1138
|
output = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
|
|
1027
1139
|
}
|
|
1028
1140
|
const executionMs = Date.now() - startedAt2;
|
|
@@ -1145,6 +1257,8 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
1145
1257
|
AGENT_TOOL_REGISTRY,
|
|
1146
1258
|
AgentRegistry,
|
|
1147
1259
|
AgentStreamError,
|
|
1260
|
+
DEFAULT_TOOL_TRANSIENT_RETRY_ATTEMPTS,
|
|
1261
|
+
DEFAULT_TOOL_TRANSIENT_RETRY_BACKOFF_MS,
|
|
1148
1262
|
DefaultRolesPolicy,
|
|
1149
1263
|
QuotaExceededError,
|
|
1150
1264
|
ToolForbiddenError,
|
|
@@ -1161,6 +1275,8 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
1161
1275
|
estimateCost,
|
|
1162
1276
|
filterToolsByAllowList,
|
|
1163
1277
|
filterToolsByRole,
|
|
1278
|
+
invokeWithTransientRetry,
|
|
1279
|
+
isTransientToolError,
|
|
1164
1280
|
publishAgentDelegated,
|
|
1165
1281
|
publishAgentMessage,
|
|
1166
1282
|
publishAgentQuotaExceeded,
|
|
@@ -1169,6 +1285,8 @@ __name(runAgentLoop, "runAgentLoop");
|
|
|
1169
1285
|
publishAgentRunFinished,
|
|
1170
1286
|
publishAgentRunStarted,
|
|
1171
1287
|
publishAgentToolCall,
|
|
1288
|
+
publishAgentToolRetry,
|
|
1289
|
+
resolveToolTransientRetryNumbers,
|
|
1172
1290
|
runAgentLoop,
|
|
1173
1291
|
seedModelPrices,
|
|
1174
1292
|
traceLlmTurn,
|