@dudousxd/nestjs-agent 0.8.1 → 0.9.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.
@@ -1,6 +1,6 @@
1
1
  import { LlmStepEnvelope, ModelTurnResult, ToolStepEnvelope, AgentStore, AgentRunInput, AgentRunner, Decision } from '@dudousxd/nestjs-agent-core';
2
2
  import { WorkflowCtx } from '@dudousxd/nestjs-durable-core';
3
- import { A as AgentDepsFactory, a as AgentModuleOptions } from '../agent-deps.factory-BlC9tumI.cjs';
3
+ import { A as AgentDepsFactory, a as AgentModuleOptions } from '../agent-deps.factory-DNslT7_J.cjs';
4
4
  import { WorkflowService } from '@dudousxd/nestjs-durable';
5
5
  import { DynamicModule } from '@nestjs/common';
6
6
 
@@ -56,9 +56,14 @@ declare class AgentRunSteps {
56
56
  */
57
57
  llm(input: DispatchedLlmInput): Promise<ModelTurnResult>;
58
58
  /**
59
- * No retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm` above).
60
- * The timeout is applied HERE, handler-side, via `withToolTimeout` — never as a durable dispatch
61
- * `timeoutMs`, which bounds engine liveness (retryable) rather than the tool's own business outcome.
59
+ * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
60
+ * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
61
+ * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
62
+ * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
63
+ * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
64
+ * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
65
+ * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
66
+ * ATTEMPT, so a retried invocation gets its own fresh timeout window.
62
67
  */
63
68
  tool(input: DispatchedToolInput): Promise<unknown>;
64
69
  }
@@ -1,6 +1,6 @@
1
1
  import { LlmStepEnvelope, ModelTurnResult, ToolStepEnvelope, AgentStore, AgentRunInput, AgentRunner, Decision } from '@dudousxd/nestjs-agent-core';
2
2
  import { WorkflowCtx } from '@dudousxd/nestjs-durable-core';
3
- import { A as AgentDepsFactory, a as AgentModuleOptions } from '../agent-deps.factory-BlC9tumI.js';
3
+ import { A as AgentDepsFactory, a as AgentModuleOptions } from '../agent-deps.factory-DNslT7_J.js';
4
4
  import { WorkflowService } from '@dudousxd/nestjs-durable';
5
5
  import { DynamicModule } from '@nestjs/common';
6
6
 
@@ -56,9 +56,14 @@ declare class AgentRunSteps {
56
56
  */
57
57
  llm(input: DispatchedLlmInput): Promise<ModelTurnResult>;
58
58
  /**
59
- * No retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm` above).
60
- * The timeout is applied HERE, handler-side, via `withToolTimeout` — never as a durable dispatch
61
- * `timeoutMs`, which bounds engine liveness (retryable) rather than the tool's own business outcome.
59
+ * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
60
+ * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
61
+ * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
62
+ * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
63
+ * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
64
+ * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
65
+ * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
66
+ * ATTEMPT, so a retried invocation gets its own fresh timeout window.
62
67
  */
63
68
  tool(input: DispatchedToolInput): Promise<unknown>;
64
69
  }
@@ -24,7 +24,7 @@ function childSinkWriter(writer) {
24
24
  __name(childSinkWriter, "childSinkWriter");
25
25
 
26
26
  // src/durable/agent-run.steps.ts
27
- import { AGENT_DEPS_FACTORY, traceLlmTurn, traceToolExecution, withToolTimeout } from "@dudousxd/nestjs-agent-core";
27
+ import { AGENT_DEPS_FACTORY, invokeWithTransientRetry, publishAgentToolRetry, traceLlmTurn, traceToolExecution, withToolTimeout } from "@dudousxd/nestjs-agent-core";
28
28
  import { Step } from "@dudousxd/nestjs-durable";
29
29
  import { Inject, Injectable } from "@nestjs/common";
30
30
  function _ts_decorate(decorators, target, key, desc) {
@@ -71,23 +71,45 @@ var AgentRunSteps = class {
71
71
  }));
72
72
  }
73
73
  /**
74
- * No retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm` above).
75
- * The timeout is applied HERE, handler-side, via `withToolTimeout` — never as a durable dispatch
76
- * `timeoutMs`, which bounds engine liveness (retryable) rather than the tool's own business outcome.
74
+ * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
75
+ * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
76
+ * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
77
+ * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
78
+ * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
79
+ * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
80
+ * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
81
+ * ATTEMPT, so a retried invocation gets its own fresh timeout window.
77
82
  */
78
83
  async tool(input) {
79
84
  const deps = this.factory.forAgent(input.ctx.agentName);
80
85
  const ctx = {
81
86
  ...input.ctx
82
87
  };
88
+ const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
89
+ const transientRetry = input.transientRetry === false ? false : {
90
+ attempts: input.transientRetry.attempts,
91
+ backoffMs: input.transientRetry.backoffMs,
92
+ ...localClassify !== void 0 ? {
93
+ classify: localClassify
94
+ } : {}
95
+ };
83
96
  return traceToolExecution(input.ctx.runId, {
84
97
  toolCallId: input.toolCallId,
85
98
  toolName: input.toolName,
86
99
  toolType: input.toolType
87
- }, () => {
100
+ }, () => invokeWithTransientRetry(() => {
88
101
  const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
89
102
  return input.timeoutMs !== void 0 ? withToolTimeout(invocation, input.timeoutMs, input.toolName) : invocation;
90
- });
103
+ }, transientRetry, {
104
+ onRetry: /* @__PURE__ */ __name((attempt, error) => {
105
+ publishAgentToolRetry({
106
+ toolName: input.toolName,
107
+ toolCallId: input.toolCallId,
108
+ attempt,
109
+ message: error instanceof Error ? error.message : String(error)
110
+ });
111
+ }, "onRetry")
112
+ }));
91
113
  }
92
114
  };
93
115
  _ts_decorate([
@@ -562,6 +584,9 @@ var AgentDepsFactory2 = class {
562
584
  ...this.options.toolTimeoutMs !== void 0 ? {
563
585
  toolTimeoutMs: this.options.toolTimeoutMs
564
586
  } : {},
587
+ ...this.options.toolTransientRetry !== void 0 ? {
588
+ toolTransientRetry: this.options.toolTransientRetry
589
+ } : {},
565
590
  ...followUpsCount !== void 0 ? {
566
591
  followUpsCount
567
592
  } : {},