@dudousxd/nestjs-agent 0.4.1 → 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.
@@ -1,23 +1,73 @@
1
- import { AgentStore, AgentRunInput, AgentRunner, Decision } from '@dudousxd/nestjs-agent-core';
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-BM_RB6br.cjs';
3
+ import { A as AgentDepsFactory, a as AgentModuleOptions } from '../agent-deps.factory-BlC9tumI.cjs';
4
4
  import { WorkflowService } from '@dudousxd/nestjs-durable';
5
5
  import { DynamicModule } from '@nestjs/common';
6
6
 
7
7
  /**
8
- * The agent turn AS a durable workflow. Each model/tool call is a checkpointed `ctx.localStep` — the
9
- * in-process primitive, NOT the always-dispatched `ctx.step`: the loop's deps (model provider, store,
10
- * sink) live in THIS workflow worker's DI, and the step names are dynamic checkpoint identities
11
- * (`llm:0`, `persist:toolcall:<id>`), not routable worker groups. HITL is
12
- * `ctx.waitForSignal`, and sub-agent delegation is `ctx.child(AgentRunWorkflow)` — a replay-safe,
13
- * observable child run (it shows up as a node in the durable dashboard). A child streams into its
14
- * top-level ancestor's sink (`sinkRunId`) so the human watching the parent sees it and can approve
15
- * its action tools; the approval routes to the child's own run via `runForToolCall`.
8
+ * Serializable input for the dispatched `llm` step: a {@link LlmStepEnvelope} plus the sink routing
9
+ * only the durable runner knows (`sinkRunId`/`childSink`) — core's `AgentLoopHooks.dispatchLlm` stays
10
+ * sink-topology-agnostic, so the workflow adds these two fields when it builds the envelope.
11
+ */
12
+ interface DispatchedLlmInput extends LlmStepEnvelope {
13
+ /**
14
+ * The dispatching workflow's own `ctx.runId` — the run this step's outcome accrues to for
15
+ * reliability metrics (`bumpRunRetries`). Carried even though the handler cannot bump retries
16
+ * today: the durable handler boundary (`runStepHandler`) hands a `@Step` method only
17
+ * `(input, StepLogger)` — the wire task's `attempt` is not exposed — so there is no clean way to
18
+ * detect a retry from inside the handler. Kept on the envelope so the bump can be wired without a
19
+ * wire-contract change once the durable runtime exposes the attempt.
20
+ */
21
+ runId: string;
22
+ /** The stream target: `input.sinkRunId ?? ctx.runId` of the dispatching workflow. */
23
+ sinkRunId: string;
24
+ /** True for a sub-agent run — wrap the writer with {@link childSinkWriter} (no end/fail). */
25
+ childSink: boolean;
26
+ }
27
+ /**
28
+ * The two long steps `AgentRunWorkflow` dispatches as routed remote steps (`AgentRunSteps.llm` /
29
+ * `AgentRunSteps.tool`) — the default under `durable: true`; `dispatchedSteps: false` runs them
30
+ * in-process under `ctx.localStep` instead. Both re-resolve their deps from THIS worker's own DI via
31
+ * `AGENT_DEPS_FACTORY.forAgent` — a step can be served by any worker in the fleet, not just the one
32
+ * that started the run. Always provided by `AgentDurableModule` regardless of `dispatchedSteps`, so
33
+ * the worker group is never orphaned.
34
+ */
35
+ declare class AgentRunSteps {
36
+ private readonly factory;
37
+ constructor(factory: AgentDepsFactory);
38
+ /**
39
+ * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
40
+ * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
41
+ * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
42
+ * across however many turns/retries it takes.
43
+ */
44
+ llm(input: DispatchedLlmInput): Promise<ModelTurnResult>;
45
+ /**
46
+ * No retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm` above).
47
+ * The timeout is applied HERE, handler-side, via `withToolTimeout` — never as a durable dispatch
48
+ * `timeoutMs`, which bounds engine liveness (retryable) rather than the tool's own business outcome.
49
+ */
50
+ tool(input: ToolStepEnvelope): Promise<unknown>;
51
+ }
52
+
53
+ /**
54
+ * The agent turn AS a durable workflow. Persist/stream checkpoints are `ctx.localStep`s — the
55
+ * in-process primitive, NOT the always-dispatched `ctx.step`: their names are dynamic checkpoint
56
+ * identities (`persist:toolcall:<id>`), not routable worker groups, and their deps (store, sink)
57
+ * live in THIS workflow worker's DI. The two LONG steps (model call, tool execution) are dispatched
58
+ * through `AgentRunSteps` by default (`AGENT_DISPATCHED_STEPS`, ON under `durable: true`) so the
59
+ * run isn't pinned to this pod while they execute; `dispatchedSteps: false` keeps them localSteps
60
+ * too. HITL is `ctx.waitForSignal`, and sub-agent delegation is `ctx.child(AgentRunWorkflow)` — a
61
+ * replay-safe, observable child run (it shows up as a node in the durable dashboard). A child
62
+ * streams into its top-level ancestor's sink (`sinkRunId`) so the human watching the parent sees it
63
+ * and can approve its action tools; the approval routes to the child's own run via `runForToolCall`.
16
64
  */
17
65
  declare class AgentRunWorkflow {
18
66
  private readonly factory;
19
67
  private readonly store;
20
- constructor(factory: AgentDepsFactory, store: AgentStore);
68
+ private readonly steps;
69
+ private readonly dispatchedSteps;
70
+ constructor(factory: AgentDepsFactory, store: AgentStore, steps: AgentRunSteps, dispatchedSteps: boolean);
21
71
  run(ctx: WorkflowCtx, input: AgentRunInput): Promise<{
22
72
  text: string;
23
73
  }>;
@@ -43,6 +93,10 @@ declare class DurableAgentRunner implements AgentRunner {
43
93
  * configured `DurableModule`. It registers the `agent.run` workflow (discovered by DurableModule)
44
94
  * and exposes the durable runner via `AGENT_DURABLE_RUNNER`, which AgentModule binds to
45
95
  * `AGENT_RUNNER`. Forgetting this import makes AgentModule throw a clear error at boot.
96
+ *
97
+ * Always provides `AgentRunSteps` regardless of `dispatchedSteps` — the worker group it serves
98
+ * (`AgentRunSteps.llm`/`.tool`) must never be orphaned by a config flag the durable step registrar
99
+ * can't see ahead of time.
46
100
  */
47
101
  declare class AgentDurableModule {
48
102
  /**
@@ -66,4 +120,14 @@ declare class AgentDurableModule {
66
120
  */
67
121
  declare function agentDurable(options: AgentModuleOptions): DynamicModule[];
68
122
 
69
- export { AgentDurableModule, AgentRunWorkflow, DurableAgentRunner, agentDurable };
123
+ /**
124
+ * DI flag carrying the EFFECTIVE `dispatchedSteps` value: whether `AgentRunWorkflow` dispatches its
125
+ * `llm`/`tool` steps as routed remote steps (`AgentRunSteps`) instead of in-process `ctx.localStep`s.
126
+ * `AgentDurableModule` derives it from `AGENT_OPTIONS` (`durable === true && dispatchedSteps !==
127
+ * false` — default ON under durable); `AgentRunWorkflow` injects it. Kept in its own file —
128
+ * `AgentDurableModule` provides `AgentRunWorkflow` and `AgentRunWorkflow` injects this token, so
129
+ * declaring it in either of those two files would make them import each other.
130
+ */
131
+ declare const AGENT_DISPATCHED_STEPS: unique symbol;
132
+
133
+ export { AGENT_DISPATCHED_STEPS, AgentDurableModule, AgentRunSteps, AgentRunWorkflow, type DispatchedLlmInput, DurableAgentRunner, agentDurable };
@@ -1,23 +1,73 @@
1
- import { AgentStore, AgentRunInput, AgentRunner, Decision } from '@dudousxd/nestjs-agent-core';
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-BM_RB6br.js';
3
+ import { A as AgentDepsFactory, a as AgentModuleOptions } from '../agent-deps.factory-BlC9tumI.js';
4
4
  import { WorkflowService } from '@dudousxd/nestjs-durable';
5
5
  import { DynamicModule } from '@nestjs/common';
6
6
 
7
7
  /**
8
- * The agent turn AS a durable workflow. Each model/tool call is a checkpointed `ctx.localStep` — the
9
- * in-process primitive, NOT the always-dispatched `ctx.step`: the loop's deps (model provider, store,
10
- * sink) live in THIS workflow worker's DI, and the step names are dynamic checkpoint identities
11
- * (`llm:0`, `persist:toolcall:<id>`), not routable worker groups. HITL is
12
- * `ctx.waitForSignal`, and sub-agent delegation is `ctx.child(AgentRunWorkflow)` — a replay-safe,
13
- * observable child run (it shows up as a node in the durable dashboard). A child streams into its
14
- * top-level ancestor's sink (`sinkRunId`) so the human watching the parent sees it and can approve
15
- * its action tools; the approval routes to the child's own run via `runForToolCall`.
8
+ * Serializable input for the dispatched `llm` step: a {@link LlmStepEnvelope} plus the sink routing
9
+ * only the durable runner knows (`sinkRunId`/`childSink`) — core's `AgentLoopHooks.dispatchLlm` stays
10
+ * sink-topology-agnostic, so the workflow adds these two fields when it builds the envelope.
11
+ */
12
+ interface DispatchedLlmInput extends LlmStepEnvelope {
13
+ /**
14
+ * The dispatching workflow's own `ctx.runId` — the run this step's outcome accrues to for
15
+ * reliability metrics (`bumpRunRetries`). Carried even though the handler cannot bump retries
16
+ * today: the durable handler boundary (`runStepHandler`) hands a `@Step` method only
17
+ * `(input, StepLogger)` — the wire task's `attempt` is not exposed — so there is no clean way to
18
+ * detect a retry from inside the handler. Kept on the envelope so the bump can be wired without a
19
+ * wire-contract change once the durable runtime exposes the attempt.
20
+ */
21
+ runId: string;
22
+ /** The stream target: `input.sinkRunId ?? ctx.runId` of the dispatching workflow. */
23
+ sinkRunId: string;
24
+ /** True for a sub-agent run — wrap the writer with {@link childSinkWriter} (no end/fail). */
25
+ childSink: boolean;
26
+ }
27
+ /**
28
+ * The two long steps `AgentRunWorkflow` dispatches as routed remote steps (`AgentRunSteps.llm` /
29
+ * `AgentRunSteps.tool`) — the default under `durable: true`; `dispatchedSteps: false` runs them
30
+ * in-process under `ctx.localStep` instead. Both re-resolve their deps from THIS worker's own DI via
31
+ * `AGENT_DEPS_FACTORY.forAgent` — a step can be served by any worker in the fleet, not just the one
32
+ * that started the run. Always provided by `AgentDurableModule` regardless of `dispatchedSteps`, so
33
+ * the worker group is never orphaned.
34
+ */
35
+ declare class AgentRunSteps {
36
+ private readonly factory;
37
+ constructor(factory: AgentDepsFactory);
38
+ /**
39
+ * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
40
+ * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
41
+ * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
42
+ * across however many turns/retries it takes.
43
+ */
44
+ llm(input: DispatchedLlmInput): Promise<ModelTurnResult>;
45
+ /**
46
+ * No retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm` above).
47
+ * The timeout is applied HERE, handler-side, via `withToolTimeout` — never as a durable dispatch
48
+ * `timeoutMs`, which bounds engine liveness (retryable) rather than the tool's own business outcome.
49
+ */
50
+ tool(input: ToolStepEnvelope): Promise<unknown>;
51
+ }
52
+
53
+ /**
54
+ * The agent turn AS a durable workflow. Persist/stream checkpoints are `ctx.localStep`s — the
55
+ * in-process primitive, NOT the always-dispatched `ctx.step`: their names are dynamic checkpoint
56
+ * identities (`persist:toolcall:<id>`), not routable worker groups, and their deps (store, sink)
57
+ * live in THIS workflow worker's DI. The two LONG steps (model call, tool execution) are dispatched
58
+ * through `AgentRunSteps` by default (`AGENT_DISPATCHED_STEPS`, ON under `durable: true`) so the
59
+ * run isn't pinned to this pod while they execute; `dispatchedSteps: false` keeps them localSteps
60
+ * too. HITL is `ctx.waitForSignal`, and sub-agent delegation is `ctx.child(AgentRunWorkflow)` — a
61
+ * replay-safe, observable child run (it shows up as a node in the durable dashboard). A child
62
+ * streams into its top-level ancestor's sink (`sinkRunId`) so the human watching the parent sees it
63
+ * and can approve its action tools; the approval routes to the child's own run via `runForToolCall`.
16
64
  */
17
65
  declare class AgentRunWorkflow {
18
66
  private readonly factory;
19
67
  private readonly store;
20
- constructor(factory: AgentDepsFactory, store: AgentStore);
68
+ private readonly steps;
69
+ private readonly dispatchedSteps;
70
+ constructor(factory: AgentDepsFactory, store: AgentStore, steps: AgentRunSteps, dispatchedSteps: boolean);
21
71
  run(ctx: WorkflowCtx, input: AgentRunInput): Promise<{
22
72
  text: string;
23
73
  }>;
@@ -43,6 +93,10 @@ declare class DurableAgentRunner implements AgentRunner {
43
93
  * configured `DurableModule`. It registers the `agent.run` workflow (discovered by DurableModule)
44
94
  * and exposes the durable runner via `AGENT_DURABLE_RUNNER`, which AgentModule binds to
45
95
  * `AGENT_RUNNER`. Forgetting this import makes AgentModule throw a clear error at boot.
96
+ *
97
+ * Always provides `AgentRunSteps` regardless of `dispatchedSteps` — the worker group it serves
98
+ * (`AgentRunSteps.llm`/`.tool`) must never be orphaned by a config flag the durable step registrar
99
+ * can't see ahead of time.
46
100
  */
47
101
  declare class AgentDurableModule {
48
102
  /**
@@ -66,4 +120,14 @@ declare class AgentDurableModule {
66
120
  */
67
121
  declare function agentDurable(options: AgentModuleOptions): DynamicModule[];
68
122
 
69
- export { AgentDurableModule, AgentRunWorkflow, DurableAgentRunner, agentDurable };
123
+ /**
124
+ * DI flag carrying the EFFECTIVE `dispatchedSteps` value: whether `AgentRunWorkflow` dispatches its
125
+ * `llm`/`tool` steps as routed remote steps (`AgentRunSteps`) instead of in-process `ctx.localStep`s.
126
+ * `AgentDurableModule` derives it from `AGENT_OPTIONS` (`durable === true && dispatchedSteps !==
127
+ * false` — default ON under durable); `AgentRunWorkflow` injects it. Kept in its own file —
128
+ * `AgentDurableModule` provides `AgentRunWorkflow` and `AgentRunWorkflow` injects this token, so
129
+ * declaring it in either of those two files would make them import each other.
130
+ */
131
+ declare const AGENT_DISPATCHED_STEPS: unique symbol;
132
+
133
+ export { AGENT_DISPATCHED_STEPS, AgentDurableModule, AgentRunSteps, AgentRunWorkflow, type DispatchedLlmInput, DurableAgentRunner, agentDurable };