@dudousxd/nestjs-agent 1.16.0 → 1.17.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.
@@ -23,6 +23,7 @@ declare class AgentRunWorkflow {
23
23
  private readonly store;
24
24
  private readonly runs?;
25
25
  private readonly queue?;
26
+ private readonly logger;
26
27
  constructor(factory: AgentDepsFactory, store: AgentStore, runs?: RunGateway | undefined, queue?: ChatQueueService | undefined);
27
28
  /**
28
29
  * Move the thread past this settling turn — to the next queued message, started here as a
@@ -122,6 +123,7 @@ declare class AgentRunSteps {
122
123
  * across however many turns/retries it takes.
123
124
  */
124
125
  llm(input: DispatchedLlmInput): Promise<BufferedModelTurnResult>;
126
+ private runLlm;
125
127
  /**
126
128
  * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
127
129
  * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
@@ -133,6 +135,7 @@ declare class AgentRunSteps {
133
135
  * ATTEMPT, so a retried invocation gets its own fresh timeout window.
134
136
  */
135
137
  tool(input: DispatchedToolInput): Promise<unknown>;
138
+ private runTool;
136
139
  }
137
140
 
138
141
  /**
@@ -23,6 +23,7 @@ declare class AgentRunWorkflow {
23
23
  private readonly store;
24
24
  private readonly runs?;
25
25
  private readonly queue?;
26
+ private readonly logger;
26
27
  constructor(factory: AgentDepsFactory, store: AgentStore, runs?: RunGateway | undefined, queue?: ChatQueueService | undefined);
27
28
  /**
28
29
  * Move the thread past this settling turn — to the next queued message, started here as a
@@ -122,6 +123,7 @@ declare class AgentRunSteps {
122
123
  * across however many turns/retries it takes.
123
124
  */
124
125
  llm(input: DispatchedLlmInput): Promise<BufferedModelTurnResult>;
126
+ private runLlm;
125
127
  /**
126
128
  * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
127
129
  * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
@@ -133,6 +135,7 @@ declare class AgentRunSteps {
133
135
  * ATTEMPT, so a retried invocation gets its own fresh timeout window.
134
136
  */
135
137
  tool(input: DispatchedToolInput): Promise<unknown>;
138
+ private runTool;
136
139
  }
137
140
 
138
141
  /**
@@ -2,10 +2,10 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/durable/agent-run.workflow.ts
5
- import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE as AGENT_STORE2, RunCancelledError, agentFailureCode, encodeStreamEvent as encodeStreamEvent3, isReplayIntegrityError, publishAgentRunFailed, releaseThreadRun, runAgentLoop, settleAll, settleUnsettledDelegation } from "@dudousxd/nestjs-agent-core";
5
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE as AGENT_STORE2, RUN_ENDED_BEFORE_TOOL_CALL, RunCancelledError, agentFailureCode, encodeStreamEvent as encodeStreamEvent3, isReplayIntegrityError, publishAgentRunFailed, releaseThreadRun, runAgentLoop, settleAll, settleDeadRun, settleUnsettledDelegation, streamFailure } from "@dudousxd/nestjs-agent-core";
6
6
  import { RUN_GATEWAY, Workflow } from "@dudousxd/nestjs-durable";
7
7
  import { isWorkflowControlFlowSignal } from "@dudousxd/nestjs-durable-core";
8
- import { Inject as Inject3, Injectable as Injectable3, Optional as Optional2 } from "@nestjs/common";
8
+ import { Inject as Inject3, Injectable as Injectable3, Logger as Logger2, Optional as Optional2 } from "@nestjs/common";
9
9
 
10
10
  // src/agent-deps.ts
11
11
  function utcDay(date = /* @__PURE__ */ new Date()) {
@@ -451,9 +451,22 @@ function queueFrame(items, paused, started) {
451
451
  __name(queueFrame, "queueFrame");
452
452
 
453
453
  // src/durable/agent-run.steps.ts
454
- import { AGENT_DEPS_FACTORY, createFrameBuffer, createUiCollector, encodeStreamEvent as encodeStreamEvent2, invokeWithTransientRetry, observeTurnFrames, publishAgentToolRetry, stampToolKinds, traceLlmTurn, traceToolExecution, withAskTool, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
454
+ import { AGENT_DEPS_FACTORY, createFrameBuffer, createUiCollector, encodeStreamEvent as encodeStreamEvent2, invokeWithTransientRetry, observeTurnFrames, publishAgentToolRetry, stampToolKinds, toolCallContext, traceLlmTurn, traceToolExecution, withAskTool, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
455
455
  import { Step } from "@dudousxd/nestjs-durable";
456
456
  import { Inject as Inject2, Injectable as Injectable2 } from "@nestjs/common";
457
+
458
+ // src/durable/outside-workflow-ctx.ts
459
+ import { runInWorkflowCtx } from "@dudousxd/nestjs-durable-core";
460
+ function outsideWorkflowCtx(fn) {
461
+ return runInWorkflowCtx(void 0, fn);
462
+ }
463
+ __name(outsideWorkflowCtx, "outsideWorkflowCtx");
464
+ function stepOf(ctx) {
465
+ return (name, fn, ...rest) => ctx.localStep(name, (...args) => outsideWorkflowCtx(() => fn(...args)), ...rest);
466
+ }
467
+ __name(stepOf, "stepOf");
468
+
469
+ // src/durable/agent-run.steps.ts
457
470
  function _ts_decorate2(decorators, target, key, desc) {
458
471
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
459
472
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -494,7 +507,10 @@ var AgentRunSteps = class {
494
507
  * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
495
508
  * across however many turns/retries it takes.
496
509
  */
497
- async llm(input) {
510
+ llm(input) {
511
+ return outsideWorkflowCtx(() => this.runLlm(input));
512
+ }
513
+ async runLlm(input) {
498
514
  const deps = this.factory.forAgent(input.agentName);
499
515
  const tools = withMemoryTool({
500
516
  tools: withSkillTool({
@@ -547,7 +563,10 @@ var AgentRunSteps = class {
547
563
  * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
548
564
  * ATTEMPT, so a retried invocation gets its own fresh timeout window.
549
565
  */
550
- async tool(input) {
566
+ tool(input) {
567
+ return outsideWorkflowCtx(() => this.runTool(input));
568
+ }
569
+ async runTool(input) {
551
570
  const deps = this.factory.forAgent(input.ctx.agentName);
552
571
  if (deps.registry.spec(input.toolName)?.kind === "action" && input.toolType !== "action") {
553
572
  throw new Error(`tool "${input.toolName}" is an action tool but was dispatched without approval: the dispatching process resolved its kind against a registry that does not have it`);
@@ -559,7 +578,7 @@ var AgentRunSteps = class {
559
578
  await (await opened).write(encodeStreamEvent2(event));
560
579
  });
561
580
  const ctx = {
562
- ...input.ctx,
581
+ ...toolCallContext(input.ctx, input.toolCallId),
563
582
  emitUi: ui.emit
564
583
  };
565
584
  const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
@@ -599,7 +618,7 @@ _ts_decorate2([
599
618
  _ts_metadata2("design:paramtypes", [
600
619
  typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
601
620
  ]),
602
- _ts_metadata2("design:returntype", Promise)
621
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
603
622
  ], AgentRunSteps.prototype, "llm", null);
604
623
  _ts_decorate2([
605
624
  Step(),
@@ -607,7 +626,7 @@ _ts_decorate2([
607
626
  _ts_metadata2("design:paramtypes", [
608
627
  typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
609
628
  ]),
610
- _ts_metadata2("design:returntype", Promise)
629
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
611
630
  ], AgentRunSteps.prototype, "tool", null);
612
631
  AgentRunSteps = _ts_decorate2([
613
632
  Injectable2(),
@@ -653,6 +672,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
653
672
  store;
654
673
  runs;
655
674
  queue;
675
+ logger = new Logger2(_AgentRunWorkflow.name);
656
676
  constructor(factory, store, runs, queue) {
657
677
  this.factory = factory;
658
678
  this.store = store;
@@ -677,7 +697,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
677
697
  if (!await ctx.patched("agent:chat-queue")) {
678
698
  return void 0;
679
699
  }
680
- const plan = await ctx.localStep(`queue:${outcome}`, async () => {
700
+ const plan = await stepOf(ctx)(`queue:${outcome}`, async () => {
681
701
  try {
682
702
  const settled = outcome === "completed" && await this.isCancelled(ctx.runId) ? "cancelled" : outcome;
683
703
  return await queue.plan({
@@ -704,7 +724,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
704
724
  throw failure;
705
725
  }
706
726
  const reason = failure instanceof Error ? failure.message : String(failure);
707
- return ctx.localStep("queue:restore", async () => {
727
+ return stepOf(ctx)("queue:restore", async () => {
708
728
  await queue.restore(input.threadId, next, "start_failed", reason);
709
729
  return queue.pausedFrame(input.threadId);
710
730
  });
@@ -746,7 +766,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
746
766
  if (delivery === void 0) {
747
767
  return;
748
768
  }
749
- await ctx.localStep("deliver:detached:unsettled", () => settleUnsettledDelegation({
769
+ await stepOf(ctx)("deliver:detached:unsettled", () => settleUnsettledDelegation({
750
770
  store: this.store,
751
771
  delivery,
752
772
  agent: input.agentName ?? "default",
@@ -762,7 +782,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
762
782
  const deps = this.factory.forAgent(input.agentName);
763
783
  const dispatchSteps = await ctx.patched("agent:dispatched-steps");
764
784
  if (input.sinkRunId !== void 0 || input.deliverTo !== void 0) {
765
- await ctx.localStep("activate", () => this.store.setActiveStream(input.threadId, ctx.runId));
785
+ await stepOf(ctx)("activate", () => this.store.setActiveStream(input.threadId, ctx.runId));
766
786
  }
767
787
  const sinkRunId = input.sinkRunId ?? ctx.runId;
768
788
  const chainBelow = [
@@ -812,7 +832,9 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
812
832
  // question set and an approval reach a parked run through one path, and the HTTP surface that
813
833
  // settles either one is the same `POST /agent/tool-call/*` family.
814
834
  awaitAnswers: /* @__PURE__ */ __name((request) => ctx.waitForSignal(`tool:${ctx.runId}:${request.id}`), "awaitAnswers"),
815
- step: /* @__PURE__ */ __name((name, fn) => ctx.localStep(name, fn), "step"),
835
+ // Bodies run outside the ambient workflow ctx, so nothing the application does in there can
836
+ // take a position in this run's journal (see `outsideWorkflowCtx`).
837
+ step: /* @__PURE__ */ __name((name, fn) => stepOf(ctx)(name, fn), "step"),
816
838
  // Both durable step primitives take their checkpoint position on the CALL, before their first
817
839
  // await, so launching a batch in one tick — what `settleAll` does — fixes the block of
818
840
  // positions in call order however the tools then settle. `ctx.patched` keeps a run that
@@ -826,7 +848,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
826
848
  // worker throws durable-worker's own Suspend), so only the Symbol.for marker is reliable.
827
849
  isControlFlowError: /* @__PURE__ */ __name((error) => isWorkflowControlFlowSignal(error), "isControlFlowError"),
828
850
  runAgent: /* @__PURE__ */ __name(async (agentName, task) => {
829
- const subThreadId = await ctx.localStep(`subthread:${agentName}`, async () => {
851
+ const subThreadId = await stepOf(ctx)(`subthread:${agentName}`, async () => {
830
852
  const thread = await this.store.createThread({
831
853
  actor: input.actor,
832
854
  transient: true
@@ -857,7 +879,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
857
879
  // - `deliverTo` instead. The parent's tool result is a receipt, so the answer needs an
858
880
  // address of its own, and by the time it exists nobody is holding one.
859
881
  startAgent: /* @__PURE__ */ __name(async ({ agentName, task, toolCallId: toolCallId2 }) => {
860
- const subThreadId = await ctx.localStep(`subthread:${agentName}`, async () => {
882
+ const subThreadId = await stepOf(ctx)(`subthread:${agentName}`, async () => {
861
883
  const thread = await this.store.createThread({
862
884
  actor: input.actor,
863
885
  transient: true
@@ -915,46 +937,58 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
915
937
  ...deps,
916
938
  day
917
939
  }, input, hooks);
918
- await ctx.localStep("deactivate", () => releaseThreadRun(this.store, input.threadId, ctx.runId));
940
+ await stepOf(ctx)("deactivate", () => releaseThreadRun(this.store, input.threadId, ctx.runId));
919
941
  return result;
920
942
  } catch (error) {
921
943
  if (isWorkflowControlFlowSignal(error)) {
922
944
  throw error;
923
945
  }
924
946
  if (error instanceof RunCancelledError) {
925
- await ctx.localStep("deactivate", () => releaseThreadRun(this.store, input.threadId, ctx.runId));
947
+ await stepOf(ctx)("deactivate", () => releaseThreadRun(this.store, input.threadId, ctx.runId));
926
948
  await this.settleDetachedParent(ctx, input, {
927
949
  status: "cancelled"
928
950
  });
929
951
  throw error;
930
952
  }
931
953
  if (isReplayIntegrityError(error)) {
932
- const failure = {
933
- code: "run_failed",
934
- message: error.message
935
- };
954
+ const detail = error.message;
955
+ const code2 = agentFailureCode(error);
956
+ this.logger.error(`agent run ${ctx.runId} failed (${code2}): ${detail}`);
936
957
  publishAgentRunFailed({
937
958
  runId: ctx.runId,
938
- ...failure
959
+ code: code2,
960
+ message: detail
939
961
  });
940
- await (await hooks.openSink()).fail(failure);
962
+ await settleDeadRun(this.store, {
963
+ runId: ctx.runId,
964
+ threadId: input.threadId,
965
+ failure: {
966
+ code: code2,
967
+ message: detail
968
+ }
969
+ });
970
+ await (await hooks.openSink()).fail(streamFailure(error));
941
971
  throw error;
942
972
  }
943
973
  const message = error instanceof Error ? error.message : String(error);
944
974
  const code = agentFailureCode(error);
975
+ this.logger.error(`agent run ${ctx.runId} failed (${code}): ${message}`);
945
976
  publishAgentRunFailed({
946
977
  runId: ctx.runId,
947
978
  code,
948
979
  message
949
980
  });
950
- await ctx.localStep("persist:run:fail", () => this.store.recordRunEnd?.({
951
- runId: ctx.runId,
952
- status: "failed",
953
- errorCode: code,
954
- errorMessage: message
955
- }) ?? Promise.resolve());
981
+ await stepOf(ctx)("persist:run:fail", async () => {
982
+ await this.store.recordRunEnd?.({
983
+ runId: ctx.runId,
984
+ status: "failed",
985
+ errorCode: code,
986
+ errorMessage: message
987
+ });
988
+ await Promise.resolve(this.store.failUnsettledToolCalls?.(ctx.runId, RUN_ENDED_BEFORE_TOOL_CALL)).catch(() => 0);
989
+ });
956
990
  const queueFrame2 = await this.advanceQueue(ctx, input, "failed", message);
957
- await ctx.localStep("deactivate", () => releaseThreadRun(this.store, input.threadId, ctx.runId));
991
+ await stepOf(ctx)("deactivate", () => releaseThreadRun(this.store, input.threadId, ctx.runId));
958
992
  await this.settleDetachedParent(ctx, input, {
959
993
  status: "failed",
960
994
  error: message
@@ -963,10 +997,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
963
997
  if (queueFrame2 !== void 0) {
964
998
  await writer.write(encodeStreamEvent3(queueFrame2));
965
999
  }
966
- await writer.fail({
967
- code,
968
- message
969
- });
1000
+ await writer.fail(streamFailure(error));
970
1001
  throw error;
971
1002
  }
972
1003
  }
@@ -1000,7 +1031,7 @@ import { randomUUID } from "crypto";
1000
1031
  import { AGENT_SINK as AGENT_SINK2, AGENT_STORE as AGENT_STORE3, encodeStreamEvent as encodeStreamEvent4, releaseThreadRun as releaseThreadRun2 } from "@dudousxd/nestjs-agent-core";
1001
1032
  import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService } from "@dudousxd/nestjs-durable";
1002
1033
  import { isWorkflowControlFlowSignal as isWorkflowControlFlowSignal2 } from "@dudousxd/nestjs-durable-core";
1003
- import { Inject as Inject4, Injectable as Injectable4, Logger as Logger2, Optional as Optional3 } from "@nestjs/common";
1034
+ import { Inject as Inject4, Injectable as Injectable4, Logger as Logger3, Optional as Optional3 } from "@nestjs/common";
1004
1035
 
1005
1036
  // src/in-process-sink.ts
1006
1037
  import { AgentStreamError } from "@dudousxd/nestjs-agent-core";
@@ -1117,7 +1148,7 @@ var DurableAgentRunner = class _DurableAgentRunner {
1117
1148
  store;
1118
1149
  sink;
1119
1150
  queue;
1120
- logger = new Logger2(_DurableAgentRunner.name);
1151
+ logger = new Logger3(_DurableAgentRunner.name);
1121
1152
  constructor(workflows, runs, store, sink, queue) {
1122
1153
  this.workflows = workflows;
1123
1154
  this.runs = runs;
@@ -1343,7 +1374,7 @@ AgentDurableModule = _ts_decorate5([
1343
1374
 
1344
1375
  // src/agent.module.ts
1345
1376
  import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER13, AGENT_APPROVAL_PORT, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY7, AGENT_DURABLE_RUNNER as AGENT_DURABLE_RUNNER2, AGENT_MEMORY as AGENT_MEMORY3, AGENT_MODEL as AGENT_MODEL2, AGENT_MODEL_CATALOG as AGENT_MODEL_CATALOG3, AGENT_OPTIONS as AGENT_OPTIONS7, AGENT_PROMPT_CONTRIBUTORS as AGENT_PROMPT_CONTRIBUTORS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER3, AGENT_REGISTRY as AGENT_REGISTRY6, AGENT_ROLES_POLICY as AGENT_ROLES_POLICY2, AGENT_RUNNER as AGENT_RUNNER2, AGENT_SINK as AGENT_SINK4, AGENT_SKILLS as AGENT_SKILLS3, AGENT_SKILL_SOURCES as AGENT_SKILL_SOURCES2, AGENT_STORE as AGENT_STORE7, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY3, AgentRegistry as AgentRegistry6, DefaultRolesPolicy, InMemoryAgentStore, ToolRegistry as ToolRegistry3 } from "@dudousxd/nestjs-agent-core";
1346
- import { Global as Global2, Logger as Logger7, Module as Module2 } from "@nestjs/common";
1377
+ import { Global as Global2, Logger as Logger8, Module as Module2 } from "@nestjs/common";
1347
1378
  import { DiscoveryModule, ModulesContainer, RouterModule } from "@nestjs/core";
1348
1379
 
1349
1380
  // src/agent-deps.factory.ts
@@ -1605,8 +1636,28 @@ AgentDepsFactory2 = _ts_decorate6([
1605
1636
  ], AgentDepsFactory2);
1606
1637
 
1607
1638
  // src/agent.service.ts
1608
- import { AGENT_ATTACHMENT_STAGING as AGENT_ATTACHMENT_STAGING2, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_MODEL_CATALOG, AGENT_OPTIONS as AGENT_OPTIONS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE5, REQUESTER_APPROVER, findCatalogModel, mayDecideApproval, readElicitationQuestions, validateElicitationAnswer } from "@dudousxd/nestjs-agent-core";
1609
- import { BadRequestException, ConflictException, ForbiddenException, GoneException, HttpException, HttpStatus, Inject as Inject6, Injectable as Injectable6, NotFoundException, NotImplementedException as NotImplementedException2, Optional as Optional5 } from "@nestjs/common";
1639
+ import { AGENT_ATTACHMENT_STAGING as AGENT_ATTACHMENT_STAGING2, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_MODEL_CATALOG, AGENT_OPTIONS as AGENT_OPTIONS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE5, REQUESTER_APPROVER, findCatalogModel, mayDecideApproval, readElicitationQuestions, settleDeadRun as settleDeadRun2, validateElicitationAnswer } from "@dudousxd/nestjs-agent-core";
1640
+ import { BadRequestException, ConflictException as ConflictException2, ForbiddenException, GoneException, HttpException, HttpStatus, Inject as Inject6, Injectable as Injectable6, NotFoundException, NotImplementedException as NotImplementedException2, Optional as Optional5 } from "@nestjs/common";
1641
+
1642
+ // src/run-not-active.exception.ts
1643
+ import { RUN_NOT_ACTIVE_CODE, RUN_NOT_ACTIVE_MESSAGE } from "@dudousxd/nestjs-agent-core";
1644
+ import { ConflictException } from "@nestjs/common";
1645
+ var RunNotActiveException = class extends ConflictException {
1646
+ static {
1647
+ __name(this, "RunNotActiveException");
1648
+ }
1649
+ runId;
1650
+ code = RUN_NOT_ACTIVE_CODE;
1651
+ constructor(runId) {
1652
+ super({
1653
+ statusCode: 409,
1654
+ code: RUN_NOT_ACTIVE_CODE,
1655
+ message: RUN_NOT_ACTIVE_MESSAGE
1656
+ }), this.runId = runId;
1657
+ }
1658
+ };
1659
+
1660
+ // src/agent.service.ts
1610
1661
  function _ts_decorate7(decorators, target, key, desc) {
1611
1662
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1612
1663
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -1803,7 +1854,7 @@ var AgentService = class {
1803
1854
  };
1804
1855
  }
1805
1856
  await this.requireQueue().publish(result.threadId);
1806
- throw new ConflictException({
1857
+ throw new ConflictException2({
1807
1858
  statusCode: 409,
1808
1859
  code: "run_active",
1809
1860
  message: `thread ${result.threadId} already has a turn running`
@@ -1863,6 +1914,11 @@ var AgentService = class {
1863
1914
  }
1864
1915
  const mode = params.mode ?? "auto";
1865
1916
  const { live, stale } = await queue.holder(threadId, this.runner);
1917
+ if (stale !== null) {
1918
+ await settleDeadRun2(this.store, {
1919
+ runId: stale
1920
+ });
1921
+ }
1866
1922
  if (live === null && mode !== "queue") {
1867
1923
  const runId = crypto.randomUUID();
1868
1924
  if (await queue.queueStore().claimActiveStream(threadId, runId, stale !== null ? {
@@ -1875,7 +1931,7 @@ var AgentService = class {
1875
1931
  }
1876
1932
  }
1877
1933
  if (params.regenerate === true) {
1878
- throw new ConflictException({
1934
+ throw new ConflictException2({
1879
1935
  statusCode: 409,
1880
1936
  code: "run_active",
1881
1937
  message: "cannot regenerate while a turn is running on this thread"
@@ -2223,8 +2279,29 @@ var AgentService = class {
2223
2279
  async signalToolCall(toolCallId2, reply) {
2224
2280
  await this.assertNotExpired(toolCallId2);
2225
2281
  const runId = await this.resolveRunForToolCall(toolCallId2);
2282
+ await this.assertRunWaiting(runId);
2226
2283
  return this.runner.signal(runId, toolCallId2, reply);
2227
2284
  }
2285
+ /**
2286
+ * Refuse a decision addressed at a run that is over (`409 run_not_active`). The runtime would take
2287
+ * the signal and buffer it for a run that never comes back — the person's "yes" is accepted, the
2288
+ * card says so, and nothing runs. Settles the calls the dead run left awaiting a decision on the
2289
+ * way out, so the card stops asking. A runner that cannot say whether a run is alive is taken at
2290
+ * its word that it is, and so is one that fails to answer.
2291
+ */
2292
+ async assertRunWaiting(runId) {
2293
+ if (typeof this.runner.isRunActive !== "function") {
2294
+ return;
2295
+ }
2296
+ const active = await this.runner.isRunActive(runId).catch(() => true);
2297
+ if (active) {
2298
+ return;
2299
+ }
2300
+ await settleDeadRun2(this.store, {
2301
+ runId
2302
+ });
2303
+ throw new RunNotActiveException(runId);
2304
+ }
2228
2305
  async cancel(actor, runId) {
2229
2306
  await this.assertOwnsActiveStream(actor, runId);
2230
2307
  return this.runner.cancel(runId);
@@ -2908,7 +2985,7 @@ AttachmentsController = _ts_decorate10([
2908
2985
  ], AttachmentsController);
2909
2986
 
2910
2987
  // src/controller/chat.controller.ts
2911
- import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER2, AgentStreamError as AgentStreamError2 } from "@dudousxd/nestjs-agent-core";
2988
+ import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER2, AgentStreamError as AgentStreamError2, streamFailure as streamFailure2 } from "@dudousxd/nestjs-agent-core";
2912
2989
  import { BadRequestException as BadRequestException3, Body, Controller as Controller3, Get as Get3, Inject as Inject9, Param, Post as Post2, Query, Req as Req2, Res } from "@nestjs/common";
2913
2990
  function _ts_decorate11(decorators, target, key, desc) {
2914
2991
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -3104,10 +3181,7 @@ data: ${line}
3104
3181
  const payload = error instanceof AgentStreamError2 ? {
3105
3182
  code: error.code,
3106
3183
  message: error.message
3107
- } : {
3108
- code: "run_failed",
3109
- message: error instanceof Error ? error.message : "stream error"
3110
- };
3184
+ } : streamFailure2(error);
3111
3185
  res.write(`event: error
3112
3186
  data: ${JSON.stringify(payload)}
3113
3187
 
@@ -4432,7 +4506,7 @@ ToolsController = _ts_decorate21([
4432
4506
 
4433
4507
  // src/discovery/agent-discovery.service.ts
4434
4508
  import { AGENT_PROMPT_CONTRIBUTORS as AGENT_PROMPT_CONTRIBUTORS2, AGENT_REGISTRY as AGENT_REGISTRY4, AgentRegistry as AgentRegistry5 } from "@dudousxd/nestjs-agent-core";
4435
- import { Inject as Inject20, Injectable as Injectable8, Logger as Logger3 } from "@nestjs/common";
4509
+ import { Inject as Inject20, Injectable as Injectable8, Logger as Logger4 } from "@nestjs/common";
4436
4510
  import { DiscoveryService, MetadataScanner } from "@nestjs/core";
4437
4511
 
4438
4512
  // src/decorator/agent.decorator.ts
@@ -4483,7 +4557,7 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
4483
4557
  scanner;
4484
4558
  registry;
4485
4559
  contributors;
4486
- logger = new Logger3(_AgentDiscoveryService.name);
4560
+ logger = new Logger4(_AgentDiscoveryService.name);
4487
4561
  constructor(discovery, scanner, registry, contributors) {
4488
4562
  this.discovery = discovery;
4489
4563
  this.scanner = scanner;
@@ -4616,7 +4690,7 @@ AgentDiscoveryService = _ts_decorate22([
4616
4690
 
4617
4691
  // src/discovery/ai-tool-discovery.service.ts
4618
4692
  import { AGENT_OPTIONS as AGENT_OPTIONS6, AGENT_REGISTRY as AGENT_REGISTRY5, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY2, normalizeDelegation as normalizeDelegation2 } from "@dudousxd/nestjs-agent-core";
4619
- import { Inject as Inject21, Injectable as Injectable9, Logger as Logger4 } from "@nestjs/common";
4693
+ import { Inject as Inject21, Injectable as Injectable9, Logger as Logger5 } from "@nestjs/common";
4620
4694
  import { DiscoveryService as DiscoveryService2 } from "@nestjs/core";
4621
4695
  import { z } from "zod";
4622
4696
 
@@ -4670,7 +4744,7 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
4670
4744
  registry;
4671
4745
  agents;
4672
4746
  options;
4673
- logger = new Logger4(_AiToolDiscoveryService.name);
4747
+ logger = new Logger5(_AiToolDiscoveryService.name);
4674
4748
  constructor(discovery, registry, agents, options) {
4675
4749
  this.discovery = discovery;
4676
4750
  this.registry = registry;
@@ -4821,7 +4895,7 @@ AiToolDiscoveryService = _ts_decorate23([
4821
4895
 
4822
4896
  // src/discovery/skill-discovery.service.ts
4823
4897
  import { AGENT_SKILL_SOURCES } from "@dudousxd/nestjs-agent-core";
4824
- import { Inject as Inject22, Injectable as Injectable10, Logger as Logger5 } from "@nestjs/common";
4898
+ import { Inject as Inject22, Injectable as Injectable10, Logger as Logger6 } from "@nestjs/common";
4825
4899
  import { DiscoveryService as DiscoveryService3 } from "@nestjs/core";
4826
4900
 
4827
4901
  // src/decorator/skill.decorator.ts
@@ -4870,7 +4944,7 @@ var SkillDiscoveryService = class _SkillDiscoveryService {
4870
4944
  }
4871
4945
  discovery;
4872
4946
  declared;
4873
- logger = new Logger5(_SkillDiscoveryService.name);
4947
+ logger = new Logger6(_SkillDiscoveryService.name);
4874
4948
  constructor(discovery, declared) {
4875
4949
  this.discovery = discovery;
4876
4950
  this.declared = declared;
@@ -4980,8 +5054,8 @@ var LedgerQuotaProvider = class {
4980
5054
  };
4981
5055
 
4982
5056
  // src/runner/inline-agent-runner.ts
4983
- import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE6, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation2 } from "@dudousxd/nestjs-agent-core";
4984
- import { Inject as Inject23, Injectable as Injectable11, Logger as Logger6, Optional as Optional10 } from "@nestjs/common";
5057
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE6, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation2, streamFailure as streamFailure3 } from "@dudousxd/nestjs-agent-core";
5058
+ import { Inject as Inject23, Injectable as Injectable11, Logger as Logger7, Optional as Optional10 } from "@nestjs/common";
4985
5059
  function _ts_decorate25(decorators, target, key, desc) {
4986
5060
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4987
5061
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -5015,7 +5089,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5015
5089
  factory;
5016
5090
  store;
5017
5091
  queue;
5018
- logger = new Logger6(_InlineAgentRunner.name);
5092
+ logger = new Logger7(_InlineAgentRunner.name);
5019
5093
  pending = /* @__PURE__ */ new Map();
5020
5094
  /**
5021
5095
  * Runs someone has asked to stop. In-process, like `pending`, and for the same reason: this runner
@@ -5035,7 +5109,15 @@ var InlineAgentRunner = class _InlineAgentRunner {
5035
5109
  * that was running it is gone (a restart), and a thread it still holds is a stale claim.
5036
5110
  */
5037
5111
  async isRunActive(runId) {
5038
- return this.live.has(runId);
5112
+ if (this.live.has(runId)) {
5113
+ return true;
5114
+ }
5115
+ for (const key of this.pending.keys()) {
5116
+ if (key.startsWith(`${runId}:`)) {
5117
+ return true;
5118
+ }
5119
+ }
5120
+ return false;
5039
5121
  }
5040
5122
  async start(input, options = {}) {
5041
5123
  const runId = options.runId ?? crypto.randomUUID();
@@ -5078,13 +5160,11 @@ var InlineAgentRunner = class _InlineAgentRunner {
5078
5160
  errorCode: code,
5079
5161
  errorMessage: message
5080
5162
  });
5163
+ await Promise.resolve(this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL2)).catch(() => 0);
5081
5164
  const writer = await deps.sink.open(runId);
5082
5165
  await this.settleQueue(writer, input, runId, "failed", message);
5083
5166
  await releaseThreadRun3(this.store, input.threadId, runId);
5084
- await writer.fail({
5085
- code,
5086
- message
5087
- });
5167
+ await writer.fail(streamFailure3(error));
5088
5168
  }).finally(() => {
5089
5169
  this.cancelled.delete(runId);
5090
5170
  this.live.delete(runId);
@@ -5358,6 +5438,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5358
5438
  errorMessage: message
5359
5439
  }
5360
5440
  });
5441
+ await Promise.resolve(this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL2)).catch(() => 0);
5361
5442
  await settleUnsettledDelegation2({
5362
5443
  store: this.store,
5363
5444
  delivery: deliverTo,
@@ -5522,7 +5603,7 @@ function _ts_decorate26(decorators, target, key, desc) {
5522
5603
  }
5523
5604
  __name(_ts_decorate26, "_ts_decorate");
5524
5605
  var DEFAULT_PATH = "agent";
5525
- var logger = new Logger7("AgentModule");
5606
+ var logger = new Logger8("AgentModule");
5526
5607
  function externalStoreWrapper(modules) {
5527
5608
  for (const module of modules.values()) {
5528
5609
  if (module.metatype === AgentModule) continue;