@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.js CHANGED
@@ -21,6 +21,7 @@ var AGENT_DEPS_FACTORY = Symbol.for("@dudousxd/nestjs-agent:deps-factory");
21
21
  var AGENT_PROMPT_CONTRIBUTORS = Symbol.for("@dudousxd/nestjs-agent:prompt-contributors");
22
22
  var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
23
23
  var AGENT_ATTACHMENT_STAGING = Symbol.for("@dudousxd/nestjs-agent:attachment-staging");
24
+ var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
24
25
 
25
26
  // src/spi/token-stream-sink.ts
26
27
  var AgentStreamError = class extends Error {
@@ -324,6 +325,9 @@ var DefaultRolesPolicy = class {
324
325
  }
325
326
  };
326
327
 
328
+ // src/agent-loop.ts
329
+ import { createHash } from "node:crypto";
330
+
327
331
  // src/diagnostics.ts
328
332
  import { emit } from "@dudousxd/nestjs-diagnostics";
329
333
  function publishAgentRunStarted(payload) {
@@ -358,6 +362,20 @@ function publishAgentRetrieved(payload) {
358
362
  emit("agent", "retrieved", payload);
359
363
  }
360
364
  __name(publishAgentRetrieved, "publishAgentRetrieved");
365
+ var AGENT_DIAGNOSTIC_EVENTS = [
366
+ "run.started",
367
+ "message",
368
+ "tool-call",
369
+ "quota.exceeded",
370
+ "run.finished",
371
+ "run.failed",
372
+ "delegated",
373
+ "retrieved"
374
+ ];
375
+ function agentDiagnosticKey(event) {
376
+ return `agent:${event}`;
377
+ }
378
+ __name(agentDiagnosticKey, "agentDiagnosticKey");
361
379
 
362
380
  // src/agent-loop.ts
363
381
  function resolveCostUsd(usage, reportedCostUsd, price) {
@@ -436,7 +454,7 @@ var ToolTimeoutError = class ToolTimeoutError2 extends Error {
436
454
  this.name = "ToolTimeoutError";
437
455
  }
438
456
  };
439
- function withTimeout(work, ms, toolName) {
457
+ function withToolTimeout(work, ms, toolName) {
440
458
  return new Promise((resolve, reject) => {
441
459
  const timer = setTimeout(() => reject(new ToolTimeoutError(toolName, ms)), ms);
442
460
  work.then((value) => {
@@ -448,7 +466,7 @@ function withTimeout(work, ms, toolName) {
448
466
  });
449
467
  });
450
468
  }
451
- __name(withTimeout, "withTimeout");
469
+ __name(withToolTimeout, "withToolTimeout");
452
470
  function parseFollowUps(text, count) {
453
471
  const source = text.match(/\[[\s\S]*\]/)?.[0] ?? text;
454
472
  try {
@@ -553,6 +571,19 @@ async function runAgentLoop(deps, input, hooks) {
553
571
  agentName: input.agentName
554
572
  } : {}
555
573
  });
574
+ const startedAt = await hooks.step("run:started-at", () => Promise.resolve(Date.now()));
575
+ await hooks.step("persist:run:start", async () => {
576
+ const promptHash = createHash("sha256").update(system).digest("hex");
577
+ await deps.store.recordRunStart?.({
578
+ runId: hooks.runId,
579
+ threadId: input.threadId,
580
+ actorRef: input.actor.id,
581
+ ...input.agentName !== void 0 ? {
582
+ agentName: input.agentName
583
+ } : {},
584
+ promptHash
585
+ });
586
+ });
556
587
  let injectedPassages;
557
588
  if (deps.retriever !== void 0) {
558
589
  const retriever = deps.retriever;
@@ -586,13 +617,25 @@ ${buildContextBlock(passages)}`;
586
617
  kind: "step-start"
587
618
  }));
588
619
  });
589
- const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
590
- const turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
591
- system,
592
- messages: modelMessages,
593
- tools,
594
- sink: writer
595
- }));
620
+ let turn;
621
+ if (hooks.dispatchLlm) {
622
+ turn = await hooks.dispatchLlm(i, {
623
+ ...input.agentName !== void 0 ? {
624
+ agentName: input.agentName
625
+ } : {},
626
+ system,
627
+ messages: modelMessages,
628
+ actor: input.actor
629
+ });
630
+ } else {
631
+ const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
632
+ turn = await hooks.step(`llm:${i}`, () => deps.model.runTurn({
633
+ system,
634
+ messages: modelMessages,
635
+ tools,
636
+ sink: writer
637
+ }));
638
+ }
596
639
  const resolvedModelId = turn.modelId ?? deps.modelId ?? "unknown";
597
640
  const costUsd = resolveCostUsd(turn.usage, turn.costUsd, priceByModel.get(resolvedModelId));
598
641
  const toolCallsWithKind = turn.toolCalls.map((call) => ({
@@ -767,6 +810,7 @@ ${buildContextBlock(passages)}`;
767
810
  });
768
811
  continue;
769
812
  }
813
+ let deciderRef = input.actor.id;
770
814
  if (toolType === "action") {
771
815
  await hooks.step(`persist:toolcall:${call.id}`, () => deps.store.recordToolCall({
772
816
  toolCallId: call.id,
@@ -777,10 +821,12 @@ ${buildContextBlock(passages)}`;
777
821
  status: "pending_approval"
778
822
  }));
779
823
  const decision = await hooks.awaitApproval(call, ctx);
824
+ deciderRef = decision.executedByRef ?? input.actor.id;
780
825
  if (!decision.approved) {
781
826
  await hooks.step(`persist:toolreject:${call.id}`, () => deps.store.updateToolCall({
782
827
  toolCallId: call.id,
783
828
  status: "rejected",
829
+ executedByRef: deciderRef,
784
830
  ...decision.reason !== void 0 ? {
785
831
  error: decision.reason
786
832
  } : {}
@@ -812,18 +858,43 @@ ${buildContextBlock(passages)}`;
812
858
  status: "auto_executed"
813
859
  }));
814
860
  }
815
- const startedAt = Date.now();
861
+ const startedAt2 = Date.now();
816
862
  try {
817
- const invocation = hooks.step(`tool:${call.id}`, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy));
818
- const output = deps.toolTimeoutMs !== void 0 ? await withTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
819
- const executionMs = Date.now() - startedAt;
863
+ let output;
864
+ if (hooks.dispatchTool) {
865
+ const stepCtx = {
866
+ actor: input.actor,
867
+ threadId: input.threadId,
868
+ runId: hooks.runId,
869
+ requestId: hooks.runId,
870
+ ...input.agentName !== void 0 ? {
871
+ agentName: input.agentName
872
+ } : {},
873
+ ...input.pageContext !== void 0 ? {
874
+ pageContext: input.pageContext
875
+ } : {}
876
+ };
877
+ const envelope = {
878
+ toolName: call.name,
879
+ input: call.input,
880
+ ctx: stepCtx,
881
+ ...deps.toolTimeoutMs !== void 0 ? {
882
+ timeoutMs: deps.toolTimeoutMs
883
+ } : {}
884
+ };
885
+ output = await hooks.dispatchTool(call, envelope);
886
+ } else {
887
+ const invocation = hooks.step(`tool:${call.id}`, () => deps.registry.invoke(call.name, call.input, ctx, deps.rolesPolicy));
888
+ output = deps.toolTimeoutMs !== void 0 ? await withToolTimeout(invocation, deps.toolTimeoutMs, call.name) : await invocation;
889
+ }
890
+ const executionMs = Date.now() - startedAt2;
820
891
  await hooks.step(`persist:toolexec:${call.id}`, () => deps.store.updateToolCall({
821
892
  toolCallId: call.id,
822
893
  status: "executed",
823
894
  output,
824
895
  executionMs,
825
896
  ...toolType === "action" ? {
826
- executedByRef: input.actor.id
897
+ executedByRef: deciderRef
827
898
  } : {}
828
899
  }));
829
900
  results.push({
@@ -839,7 +910,10 @@ ${buildContextBlock(passages)}`;
839
910
  durationMs: executionMs
840
911
  });
841
912
  } catch (error) {
842
- const executionMs = Date.now() - startedAt;
913
+ if (hooks.isControlFlowError?.(error) === true) {
914
+ throw error;
915
+ }
916
+ const executionMs = Date.now() - startedAt2;
843
917
  const message = error instanceof Error ? error.message : String(error);
844
918
  await hooks.step(`persist:toolfail:${call.id}`, () => deps.store.updateToolCall({
845
919
  toolCallId: call.id,
@@ -887,6 +961,13 @@ ${buildContextBlock(passages)}`;
887
961
  if (thread !== null && (thread.title === "" || thread.title === "New chat")) {
888
962
  await hooks.step("persist:title", () => deps.store.setTitle(input.threadId, deriveTitle(input.userText)));
889
963
  }
964
+ await hooks.step("persist:run:end", async () => {
965
+ await deps.store.recordRunEnd?.({
966
+ runId: hooks.runId,
967
+ status: "completed",
968
+ durationMs: Date.now() - startedAt
969
+ });
970
+ });
890
971
  await writer.end();
891
972
  publishAgentRunFinished({
892
973
  runId: hooks.runId,
@@ -903,8 +984,10 @@ __name(runAgentLoop, "runAgentLoop");
903
984
  export {
904
985
  AGENT_ACTOR_DIRECTORY,
905
986
  AGENT_ACTOR_RESOLVER,
987
+ AGENT_APPROVAL_PORT,
906
988
  AGENT_ATTACHMENT_STAGING,
907
989
  AGENT_DEPS_FACTORY,
990
+ AGENT_DIAGNOSTIC_EVENTS,
908
991
  AGENT_DURABLE_RUNNER,
909
992
  AGENT_EMBEDDING_PROVIDER,
910
993
  AGENT_GOVERNANCE_QUERIES,
@@ -928,6 +1011,7 @@ export {
928
1011
  ToolInputInvalidError,
929
1012
  ToolNotFoundError,
930
1013
  ToolRegistry,
1014
+ agentDiagnosticKey,
931
1015
  bucketByActor,
932
1016
  bucketByModel,
933
1017
  bucketByThread,
@@ -946,6 +1030,7 @@ export {
946
1030
  publishAgentRunStarted,
947
1031
  publishAgentToolCall,
948
1032
  runAgentLoop,
949
- seedModelPrices
1033
+ seedModelPrices,
1034
+ withToolTimeout
950
1035
  };
951
1036
  //# sourceMappingURL=index.js.map