@dudousxd/nestjs-agent-core 0.4.0 → 0.6.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
@@ -23,8 +23,10 @@ var index_exports = {};
23
23
  __export(index_exports, {
24
24
  AGENT_ACTOR_DIRECTORY: () => AGENT_ACTOR_DIRECTORY,
25
25
  AGENT_ACTOR_RESOLVER: () => AGENT_ACTOR_RESOLVER,
26
+ AGENT_APPROVAL_PORT: () => AGENT_APPROVAL_PORT,
26
27
  AGENT_ATTACHMENT_STAGING: () => AGENT_ATTACHMENT_STAGING,
27
28
  AGENT_DEPS_FACTORY: () => AGENT_DEPS_FACTORY,
29
+ AGENT_DIAGNOSTIC_EVENTS: () => AGENT_DIAGNOSTIC_EVENTS,
28
30
  AGENT_DURABLE_RUNNER: () => AGENT_DURABLE_RUNNER,
29
31
  AGENT_EMBEDDING_PROVIDER: () => AGENT_EMBEDDING_PROVIDER,
30
32
  AGENT_GOVERNANCE_QUERIES: () => AGENT_GOVERNANCE_QUERIES,
@@ -48,6 +50,7 @@ __export(index_exports, {
48
50
  ToolInputInvalidError: () => ToolInputInvalidError,
49
51
  ToolNotFoundError: () => ToolNotFoundError,
50
52
  ToolRegistry: () => ToolRegistry,
53
+ agentDiagnosticKey: () => agentDiagnosticKey,
51
54
  bucketByActor: () => bucketByActor,
52
55
  bucketByModel: () => bucketByModel,
53
56
  bucketByThread: () => bucketByThread,
@@ -66,7 +69,8 @@ __export(index_exports, {
66
69
  publishAgentRunStarted: () => publishAgentRunStarted,
67
70
  publishAgentToolCall: () => publishAgentToolCall,
68
71
  runAgentLoop: () => runAgentLoop,
69
- seedModelPrices: () => seedModelPrices
72
+ seedModelPrices: () => seedModelPrices,
73
+ withToolTimeout: () => withToolTimeout
70
74
  });
71
75
  module.exports = __toCommonJS(index_exports);
72
76
 
@@ -90,6 +94,7 @@ var AGENT_DEPS_FACTORY = Symbol.for("@dudousxd/nestjs-agent:deps-factory");
90
94
  var AGENT_PROMPT_CONTRIBUTORS = Symbol.for("@dudousxd/nestjs-agent:prompt-contributors");
91
95
  var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
92
96
  var AGENT_ATTACHMENT_STAGING = Symbol.for("@dudousxd/nestjs-agent:attachment-staging");
97
+ var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
93
98
 
94
99
  // src/spi/token-stream-sink.ts
95
100
  var AgentStreamError = class extends Error {
@@ -393,6 +398,9 @@ var DefaultRolesPolicy = class {
393
398
  }
394
399
  };
395
400
 
401
+ // src/agent-loop.ts
402
+ var import_node_crypto = require("crypto");
403
+
396
404
  // src/diagnostics.ts
397
405
  var import_nestjs_diagnostics = require("@dudousxd/nestjs-diagnostics");
398
406
  function publishAgentRunStarted(payload) {
@@ -427,6 +435,20 @@ function publishAgentRetrieved(payload) {
427
435
  (0, import_nestjs_diagnostics.emit)("agent", "retrieved", payload);
428
436
  }
429
437
  __name(publishAgentRetrieved, "publishAgentRetrieved");
438
+ var AGENT_DIAGNOSTIC_EVENTS = [
439
+ "run.started",
440
+ "message",
441
+ "tool-call",
442
+ "quota.exceeded",
443
+ "run.finished",
444
+ "run.failed",
445
+ "delegated",
446
+ "retrieved"
447
+ ];
448
+ function agentDiagnosticKey(event) {
449
+ return `agent:${event}`;
450
+ }
451
+ __name(agentDiagnosticKey, "agentDiagnosticKey");
430
452
 
431
453
  // src/agent-loop.ts
432
454
  function resolveCostUsd(usage, reportedCostUsd, price) {
@@ -505,7 +527,7 @@ var ToolTimeoutError = class ToolTimeoutError2 extends Error {
505
527
  this.name = "ToolTimeoutError";
506
528
  }
507
529
  };
508
- function withTimeout(work, ms, toolName) {
530
+ function withToolTimeout(work, ms, toolName) {
509
531
  return new Promise((resolve, reject) => {
510
532
  const timer = setTimeout(() => reject(new ToolTimeoutError(toolName, ms)), ms);
511
533
  work.then((value) => {
@@ -517,7 +539,7 @@ function withTimeout(work, ms, toolName) {
517
539
  });
518
540
  });
519
541
  }
520
- __name(withTimeout, "withTimeout");
542
+ __name(withToolTimeout, "withToolTimeout");
521
543
  function parseFollowUps(text, count) {
522
544
  const source = text.match(/\[[\s\S]*\]/)?.[0] ?? text;
523
545
  try {
@@ -622,6 +644,19 @@ async function runAgentLoop(deps, input, hooks) {
622
644
  agentName: input.agentName
623
645
  } : {}
624
646
  });
647
+ const startedAt = await hooks.step("run:started-at", () => Promise.resolve(Date.now()));
648
+ await hooks.step("persist:run:start", async () => {
649
+ const promptHash = (0, import_node_crypto.createHash)("sha256").update(system).digest("hex");
650
+ await deps.store.recordRunStart?.({
651
+ runId: hooks.runId,
652
+ threadId: input.threadId,
653
+ actorRef: input.actor.id,
654
+ ...input.agentName !== void 0 ? {
655
+ agentName: input.agentName
656
+ } : {},
657
+ promptHash
658
+ });
659
+ });
625
660
  let injectedPassages;
626
661
  if (deps.retriever !== void 0) {
627
662
  const retriever = deps.retriever;
@@ -655,13 +690,25 @@ ${buildContextBlock(passages)}`;
655
690
  kind: "step-start"
656
691
  }));
657
692
  });
658
- const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
659
- const turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
660
- system,
661
- messages: modelMessages,
662
- tools,
663
- sink: writer
664
- }));
693
+ let turn;
694
+ if (hooks.dispatchLlm) {
695
+ turn = await hooks.dispatchLlm(i, {
696
+ ...input.agentName !== void 0 ? {
697
+ agentName: input.agentName
698
+ } : {},
699
+ system,
700
+ messages: modelMessages,
701
+ actor: input.actor
702
+ });
703
+ } else {
704
+ const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
705
+ turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
706
+ system,
707
+ messages: modelMessages,
708
+ tools,
709
+ sink: writer
710
+ }));
711
+ }
665
712
  const resolvedModelId = turn.modelId ?? deps.modelId ?? "unknown";
666
713
  const costUsd = resolveCostUsd(turn.usage, turn.costUsd, priceByModel.get(resolvedModelId));
667
714
  const toolCallsWithKind = turn.toolCalls.map((call) => ({
@@ -836,6 +883,7 @@ ${buildContextBlock(passages)}`;
836
883
  });
837
884
  continue;
838
885
  }
886
+ let deciderRef = input.actor.id;
839
887
  if (toolType === "action") {
840
888
  await hooks.step(`persist:toolcall:${call.id}`, () => deps.store.recordToolCall({
841
889
  toolCallId: call.id,
@@ -846,10 +894,12 @@ ${buildContextBlock(passages)}`;
846
894
  status: "pending_approval"
847
895
  }));
848
896
  const decision = await hooks.awaitApproval(call, ctx);
897
+ deciderRef = decision.executedByRef ?? input.actor.id;
849
898
  if (!decision.approved) {
850
899
  await hooks.step(`persist:toolreject:${call.id}`, () => deps.store.updateToolCall({
851
900
  toolCallId: call.id,
852
901
  status: "rejected",
902
+ executedByRef: deciderRef,
853
903
  ...decision.reason !== void 0 ? {
854
904
  error: decision.reason
855
905
  } : {}
@@ -881,18 +931,43 @@ ${buildContextBlock(passages)}`;
881
931
  status: "auto_executed"
882
932
  }));
883
933
  }
884
- const startedAt = Date.now();
934
+ const startedAt2 = Date.now();
885
935
  try {
886
- const invocation = hooks.step(`tool:${call.id}`, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy));
887
- const output = deps.toolTimeoutMs !== void 0 ? await withTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
888
- const executionMs = Date.now() - startedAt;
936
+ let output;
937
+ if (hooks.dispatchTool) {
938
+ const stepCtx = {
939
+ actor: input.actor,
940
+ threadId: input.threadId,
941
+ runId: hooks.runId,
942
+ requestId: hooks.runId,
943
+ ...input.agentName !== void 0 ? {
944
+ agentName: input.agentName
945
+ } : {},
946
+ ...input.pageContext !== void 0 ? {
947
+ pageContext: input.pageContext
948
+ } : {}
949
+ };
950
+ const envelope = {
951
+ toolName: call.name,
952
+ input: call.input,
953
+ ctx: stepCtx,
954
+ ...deps.toolTimeoutMs !== void 0 ? {
955
+ timeoutMs: deps.toolTimeoutMs
956
+ } : {}
957
+ };
958
+ output = await hooks.dispatchTool(call, envelope);
959
+ } else {
960
+ const invocation = hooks.step(`tool:${call.id}`, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy));
961
+ output = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
962
+ }
963
+ const executionMs = Date.now() - startedAt2;
889
964
  await hooks.step(`persist:toolexec:${call.id}`, () => deps.store.updateToolCall({
890
965
  toolCallId: call.id,
891
966
  status: "executed",
892
967
  output,
893
968
  executionMs,
894
969
  ...toolType === "action" ? {
895
- executedByRef: input.actor.id
970
+ executedByRef: deciderRef
896
971
  } : {}
897
972
  }));
898
973
  results.push({
@@ -908,7 +983,10 @@ ${buildContextBlock(passages)}`;
908
983
  durationMs: executionMs
909
984
  });
910
985
  } catch (error) {
911
- const executionMs = Date.now() - startedAt;
986
+ if (hooks.isControlFlowError?.(error) === true) {
987
+ throw error;
988
+ }
989
+ const executionMs = Date.now() - startedAt2;
912
990
  const message = error instanceof Error ? error.message : String(error);
913
991
  await hooks.step(`persist:toolfail:${call.id}`, () => deps.store.updateToolCall({
914
992
  toolCallId: call.id,
@@ -956,6 +1034,13 @@ ${buildContextBlock(passages)}`;
956
1034
  if (thread !== null && (thread.title === "" || thread.title === "New chat")) {
957
1035
  await hooks.step("persist:title", () => deps.store.setTitle(input.threadId, deriveTitle(input.userText)));
958
1036
  }
1037
+ await hooks.step("persist:run:end", async () => {
1038
+ await deps.store.recordRunEnd?.({
1039
+ runId: hooks.runId,
1040
+ status: "completed",
1041
+ durationMs: Date.now() - startedAt
1042
+ });
1043
+ });
959
1044
  await writer.end();
960
1045
  publishAgentRunFinished({
961
1046
  runId: hooks.runId,
@@ -973,8 +1058,10 @@ __name(runAgentLoop, "runAgentLoop");
973
1058
  0 && (module.exports = {
974
1059
  AGENT_ACTOR_DIRECTORY,
975
1060
  AGENT_ACTOR_RESOLVER,
1061
+ AGENT_APPROVAL_PORT,
976
1062
  AGENT_ATTACHMENT_STAGING,
977
1063
  AGENT_DEPS_FACTORY,
1064
+ AGENT_DIAGNOSTIC_EVENTS,
978
1065
  AGENT_DURABLE_RUNNER,
979
1066
  AGENT_EMBEDDING_PROVIDER,
980
1067
  AGENT_GOVERNANCE_QUERIES,
@@ -998,6 +1085,7 @@ __name(runAgentLoop, "runAgentLoop");
998
1085
  ToolInputInvalidError,
999
1086
  ToolNotFoundError,
1000
1087
  ToolRegistry,
1088
+ agentDiagnosticKey,
1001
1089
  bucketByActor,
1002
1090
  bucketByModel,
1003
1091
  bucketByThread,
@@ -1016,6 +1104,7 @@ __name(runAgentLoop, "runAgentLoop");
1016
1104
  publishAgentRunStarted,
1017
1105
  publishAgentToolCall,
1018
1106
  runAgentLoop,
1019
- seedModelPrices
1107
+ seedModelPrices,
1108
+ withToolTimeout
1020
1109
  });
1021
1110
  //# sourceMappingURL=index.cjs.map