@dudousxd/nestjs-agent 0.9.0 → 0.10.1

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.
@@ -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, QuotaExceededError, publishAgentRunFailed, runAgentLoop } from "@dudousxd/nestjs-agent-core";
5
+ import { AGENT_DEPS_FACTORY, AGENT_STORE, QuotaExceededError, publishAgentRunFailed, runAgentLoop } from "@dudousxd/nestjs-agent-core";
6
6
  import { Workflow } from "@dudousxd/nestjs-durable";
7
7
  import { isWorkflowControlFlowSignal } from "@dudousxd/nestjs-durable-core";
8
- import { Inject as Inject2, Injectable as Injectable2 } from "@nestjs/common";
8
+ import { Inject, Injectable, Optional } from "@nestjs/common";
9
9
 
10
10
  // src/agent-deps.ts
11
11
  function utcDay(date = /* @__PURE__ */ new Date()) {
@@ -23,10 +23,10 @@ function childSinkWriter(writer) {
23
23
  }
24
24
  __name(childSinkWriter, "childSinkWriter");
25
25
 
26
- // src/durable/agent-run.steps.ts
27
- import { AGENT_DEPS_FACTORY, invokeWithTransientRetry, publishAgentToolRetry, traceLlmTurn, traceToolExecution, withToolTimeout } from "@dudousxd/nestjs-agent-core";
28
- import { Step } from "@dudousxd/nestjs-durable";
29
- import { Inject, Injectable } from "@nestjs/common";
26
+ // src/durable/dispatched-steps.token.ts
27
+ var AGENT_DISPATCHED_STEPS = Symbol.for("@dudousxd/nestjs-agent:dispatched-steps");
28
+
29
+ // src/durable/agent-run.workflow.ts
30
30
  function _ts_decorate(decorators, target, key, desc) {
31
31
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
32
32
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -44,122 +44,6 @@ function _ts_param(paramIndex, decorator) {
44
44
  };
45
45
  }
46
46
  __name(_ts_param, "_ts_param");
47
- var AgentRunSteps = class {
48
- static {
49
- __name(this, "AgentRunSteps");
50
- }
51
- factory;
52
- constructor(factory) {
53
- this.factory = factory;
54
- }
55
- /**
56
- * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
57
- * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
58
- * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
59
- * across however many turns/retries it takes.
60
- */
61
- async llm(input) {
62
- const deps = this.factory.forAgent(input.agentName);
63
- const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
64
- const opened = await deps.sink.open(input.sinkRunId);
65
- const writer = input.childSink ? childSinkWriter(opened) : opened;
66
- return traceLlmTurn(input.runId, input.step, () => deps.model.runTurn({
67
- system: input.system,
68
- messages: input.messages,
69
- tools,
70
- sink: writer
71
- }));
72
- }
73
- /**
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.
82
- */
83
- async tool(input) {
84
- const deps = this.factory.forAgent(input.ctx.agentName);
85
- const ctx = {
86
- ...input.ctx
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
- };
96
- return traceToolExecution(input.ctx.runId, {
97
- toolCallId: input.toolCallId,
98
- toolName: input.toolName,
99
- toolType: input.toolType
100
- }, () => invokeWithTransientRetry(() => {
101
- const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
102
- return input.timeoutMs !== void 0 ? withToolTimeout(invocation, input.timeoutMs, input.toolName) : invocation;
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
- }));
113
- }
114
- };
115
- _ts_decorate([
116
- Step({
117
- retries: 3
118
- }),
119
- _ts_metadata("design:type", Function),
120
- _ts_metadata("design:paramtypes", [
121
- typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
122
- ]),
123
- _ts_metadata("design:returntype", Promise)
124
- ], AgentRunSteps.prototype, "llm", null);
125
- _ts_decorate([
126
- Step(),
127
- _ts_metadata("design:type", Function),
128
- _ts_metadata("design:paramtypes", [
129
- typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
130
- ]),
131
- _ts_metadata("design:returntype", Promise)
132
- ], AgentRunSteps.prototype, "tool", null);
133
- AgentRunSteps = _ts_decorate([
134
- Injectable(),
135
- _ts_param(0, Inject(AGENT_DEPS_FACTORY)),
136
- _ts_metadata("design:type", Function),
137
- _ts_metadata("design:paramtypes", [
138
- typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
139
- ])
140
- ], AgentRunSteps);
141
-
142
- // src/durable/dispatched-steps.token.ts
143
- var AGENT_DISPATCHED_STEPS = Symbol.for("@dudousxd/nestjs-agent:dispatched-steps");
144
-
145
- // src/durable/agent-run.workflow.ts
146
- function _ts_decorate2(decorators, target, key, desc) {
147
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
148
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
149
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
150
- return c > 3 && r && Object.defineProperty(target, key, r), r;
151
- }
152
- __name(_ts_decorate2, "_ts_decorate");
153
- function _ts_metadata2(k, v) {
154
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
155
- }
156
- __name(_ts_metadata2, "_ts_metadata");
157
- function _ts_param2(paramIndex, decorator) {
158
- return function(target, key) {
159
- decorator(target, key, paramIndex);
160
- };
161
- }
162
- __name(_ts_param2, "_ts_param");
163
47
  var AgentRunWorkflow = class _AgentRunWorkflow {
164
48
  static {
165
49
  __name(this, "AgentRunWorkflow");
@@ -177,6 +61,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
177
61
  async run(ctx, input) {
178
62
  const day = input.day ?? utcDay();
179
63
  const deps = this.factory.forAgent(input.agentName);
64
+ const dispatchSteps = this.dispatchedSteps ? this.steps : void 0;
180
65
  if (input.sinkRunId !== void 0) {
181
66
  await ctx.localStep("activate", () => this.store.setActiveStream(input.threadId, ctx.runId));
182
67
  }
@@ -214,8 +99,8 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
214
99
  // `ctx.localStep`s, so a turn isn't pinned to this workflow worker for the model call or a tool
215
100
  // execution. `sinkRunId`/`childSink` are sink routing this workflow already resolved above —
216
101
  // core's dispatchLlm signature stays sink-topology-agnostic, so we add them here, not in core.
217
- ...this.dispatchedSteps ? {
218
- dispatchLlm: /* @__PURE__ */ __name((index, envelope) => ctx.step(this.steps.llm, {
102
+ ...dispatchSteps !== void 0 ? {
103
+ dispatchLlm: /* @__PURE__ */ __name((index, envelope) => ctx.step(dispatchSteps.llm, {
219
104
  ...envelope,
220
105
  runId: ctx.runId,
221
106
  step: index,
@@ -227,7 +112,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
227
112
  // ('agent'-kind delegations branch to runAgent earlier in the loop), so anything that
228
113
  // isn't 'action' is defensively 'read' — the same posture core takes for an
229
114
  // unresolvable `kind`.
230
- dispatchTool: /* @__PURE__ */ __name((call, envelope) => ctx.step(this.steps.tool, {
115
+ dispatchTool: /* @__PURE__ */ __name((call, envelope) => ctx.step(dispatchSteps.tool, {
231
116
  ...envelope,
232
117
  toolCallId: call.id,
233
118
  toolType: call.kind === "action" ? "action" : "read"
@@ -268,24 +153,141 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
268
153
  }
269
154
  }
270
155
  };
271
- AgentRunWorkflow = _ts_decorate2([
272
- Injectable2(),
156
+ AgentRunWorkflow = _ts_decorate([
157
+ Injectable(),
273
158
  Workflow({
274
159
  name: "agent.run",
275
160
  version: "1"
276
161
  }),
277
- _ts_param2(0, Inject2(AGENT_DEPS_FACTORY2)),
278
- _ts_param2(1, Inject2(AGENT_STORE)),
279
- _ts_param2(3, Inject2(AGENT_DISPATCHED_STEPS)),
280
- _ts_metadata2("design:type", Function),
281
- _ts_metadata2("design:paramtypes", [
162
+ _ts_param(0, Inject(AGENT_DEPS_FACTORY)),
163
+ _ts_param(1, Inject(AGENT_STORE)),
164
+ _ts_param(2, Optional()),
165
+ _ts_param(3, Inject(AGENT_DISPATCHED_STEPS)),
166
+ _ts_metadata("design:type", Function),
167
+ _ts_metadata("design:paramtypes", [
282
168
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
283
169
  typeof AgentStore === "undefined" ? Object : AgentStore,
284
- typeof AgentRunSteps === "undefined" ? Object : AgentRunSteps,
170
+ Object,
285
171
  Boolean
286
172
  ])
287
173
  ], AgentRunWorkflow);
288
174
 
175
+ // src/durable/agent-run.steps.ts
176
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, invokeWithTransientRetry, publishAgentToolRetry, traceLlmTurn, traceToolExecution, withToolTimeout } from "@dudousxd/nestjs-agent-core";
177
+ import { Step } from "@dudousxd/nestjs-durable";
178
+ import { Inject as Inject2, Injectable as Injectable2 } from "@nestjs/common";
179
+ function _ts_decorate2(decorators, target, key, desc) {
180
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
181
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
182
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
183
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
184
+ }
185
+ __name(_ts_decorate2, "_ts_decorate");
186
+ function _ts_metadata2(k, v) {
187
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
188
+ }
189
+ __name(_ts_metadata2, "_ts_metadata");
190
+ function _ts_param2(paramIndex, decorator) {
191
+ return function(target, key) {
192
+ decorator(target, key, paramIndex);
193
+ };
194
+ }
195
+ __name(_ts_param2, "_ts_param");
196
+ var AgentRunSteps = class {
197
+ static {
198
+ __name(this, "AgentRunSteps");
199
+ }
200
+ factory;
201
+ constructor(factory) {
202
+ this.factory = factory;
203
+ }
204
+ /**
205
+ * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
206
+ * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
207
+ * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
208
+ * across however many turns/retries it takes.
209
+ */
210
+ async llm(input) {
211
+ const deps = this.factory.forAgent(input.agentName);
212
+ const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
213
+ const opened = await deps.sink.open(input.sinkRunId);
214
+ const writer = input.childSink ? childSinkWriter(opened) : opened;
215
+ return traceLlmTurn(input.runId, input.step, () => deps.model.runTurn({
216
+ system: input.system,
217
+ messages: input.messages,
218
+ tools,
219
+ sink: writer
220
+ }));
221
+ }
222
+ /**
223
+ * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
224
+ * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
225
+ * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
226
+ * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
227
+ * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
228
+ * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
229
+ * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
230
+ * ATTEMPT, so a retried invocation gets its own fresh timeout window.
231
+ */
232
+ async tool(input) {
233
+ const deps = this.factory.forAgent(input.ctx.agentName);
234
+ const ctx = {
235
+ ...input.ctx
236
+ };
237
+ const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
238
+ const transientRetry = input.transientRetry === false ? false : {
239
+ attempts: input.transientRetry.attempts,
240
+ backoffMs: input.transientRetry.backoffMs,
241
+ ...localClassify !== void 0 ? {
242
+ classify: localClassify
243
+ } : {}
244
+ };
245
+ return traceToolExecution(input.ctx.runId, {
246
+ toolCallId: input.toolCallId,
247
+ toolName: input.toolName,
248
+ toolType: input.toolType
249
+ }, () => invokeWithTransientRetry(() => {
250
+ const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
251
+ return input.timeoutMs !== void 0 ? withToolTimeout(invocation, input.timeoutMs, input.toolName) : invocation;
252
+ }, transientRetry, {
253
+ onRetry: /* @__PURE__ */ __name((attempt, error) => {
254
+ publishAgentToolRetry({
255
+ toolName: input.toolName,
256
+ toolCallId: input.toolCallId,
257
+ attempt,
258
+ message: error instanceof Error ? error.message : String(error)
259
+ });
260
+ }, "onRetry")
261
+ }));
262
+ }
263
+ };
264
+ _ts_decorate2([
265
+ Step({
266
+ retries: 3
267
+ }),
268
+ _ts_metadata2("design:type", Function),
269
+ _ts_metadata2("design:paramtypes", [
270
+ typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
271
+ ]),
272
+ _ts_metadata2("design:returntype", Promise)
273
+ ], AgentRunSteps.prototype, "llm", null);
274
+ _ts_decorate2([
275
+ Step(),
276
+ _ts_metadata2("design:type", Function),
277
+ _ts_metadata2("design:paramtypes", [
278
+ typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
279
+ ]),
280
+ _ts_metadata2("design:returntype", Promise)
281
+ ], AgentRunSteps.prototype, "tool", null);
282
+ AgentRunSteps = _ts_decorate2([
283
+ Injectable2(),
284
+ _ts_param2(0, Inject2(AGENT_DEPS_FACTORY2)),
285
+ _ts_metadata2("design:type", Function),
286
+ _ts_metadata2("design:paramtypes", [
287
+ typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
288
+ ])
289
+ ], AgentRunSteps);
290
+
289
291
  // src/durable/durable-agent-runner.ts
290
292
  import { randomUUID } from "node:crypto";
291
293
  import { WorkflowService } from "@dudousxd/nestjs-durable";
@@ -423,16 +425,68 @@ function _ts_decorate4(decorators, target, key, desc) {
423
425
  }
424
426
  __name(_ts_decorate4, "_ts_decorate");
425
427
  var logger = new Logger("AgentDurableModule");
428
+ function runnerProviders() {
429
+ return [
430
+ DurableAgentRunner,
431
+ {
432
+ provide: AGENT_DURABLE_RUNNER,
433
+ useExisting: DurableAgentRunner
434
+ },
435
+ {
436
+ provide: AGENT_DISPATCHED_STEPS,
437
+ useFactory: /* @__PURE__ */ __name((options, sink) => {
438
+ const enabled = options.durable === true && options.dispatchedSteps !== false;
439
+ if (enabled && sink instanceof InProcessTokenStreamSink) {
440
+ logger.warn("Dispatched steps are active (the default under durable: true) with the default InProcessTokenStreamSink, which only buffers tokens in-process. A dispatched `llm` step served by a different worker cannot stream into this buffer. Wire a cross-process TokenStreamSink (e.g. a Redis pub/sub sink) via AgentModule.forRoot({ sink }) before running multi-pod, or set dispatchedSteps: false to keep the turn in-process localSteps.");
441
+ }
442
+ return enabled;
443
+ }, "useFactory"),
444
+ inject: [
445
+ AGENT_OPTIONS,
446
+ AGENT_SINK
447
+ ]
448
+ }
449
+ ];
450
+ }
451
+ __name(runnerProviders, "runnerProviders");
452
+ var AgentDurableHttpModule = class AgentDurableHttpModule2 {
453
+ static {
454
+ __name(this, "AgentDurableHttpModule");
455
+ }
456
+ };
457
+ AgentDurableHttpModule = _ts_decorate4([
458
+ Global(),
459
+ Module({
460
+ providers: [
461
+ AgentRunWorkflow,
462
+ ...runnerProviders()
463
+ ],
464
+ exports: [
465
+ AGENT_DURABLE_RUNNER,
466
+ AgentRunWorkflow,
467
+ AGENT_DISPATCHED_STEPS
468
+ ]
469
+ })
470
+ ], AgentDurableHttpModule);
426
471
  var AgentDurableModule = class _AgentDurableModule {
427
472
  static {
428
473
  __name(this, "AgentDurableModule");
429
474
  }
430
475
  /**
431
- * The dynamic form used by the `agentDurable` helper. The module needs no configuration of its
432
- * own (its providers come from the decorator above), so this just yields the module reference —
433
- * importing `AgentDurableModule` directly stays equivalent.
476
+ * `surface: 'http'` returns the reduced `AgentDurableHttpModule` wiring (no `AgentRunSteps`);
477
+ * everything else (omitted, `'engine'`, `'both'`) returns this module's own full wiring — the
478
+ * class's `@Module` providers above merge in regardless of which DynamicModule shape a caller
479
+ * imports (Nest merges a class's static provider list with whatever a self-referencing
480
+ * `DynamicModule` adds), which is exactly why the reduced case has to be a DIFFERENT module class
481
+ * rather than a conditional subset of this one's own decorator.
434
482
  */
435
- static forRoot() {
483
+ static forRoot(options) {
484
+ if (options?.surface === "http") {
485
+ return {
486
+ module: AgentDurableHttpModule,
487
+ global: true
488
+ };
489
+ }
436
490
  return {
437
491
  module: _AgentDurableModule,
438
492
  global: true
@@ -445,25 +499,7 @@ AgentDurableModule = _ts_decorate4([
445
499
  providers: [
446
500
  AgentRunWorkflow,
447
501
  AgentRunSteps,
448
- DurableAgentRunner,
449
- {
450
- provide: AGENT_DURABLE_RUNNER,
451
- useExisting: DurableAgentRunner
452
- },
453
- {
454
- provide: AGENT_DISPATCHED_STEPS,
455
- useFactory: /* @__PURE__ */ __name((options, sink) => {
456
- const enabled = options.durable === true && options.dispatchedSteps !== false;
457
- if (enabled && sink instanceof InProcessTokenStreamSink) {
458
- logger.warn("Dispatched steps are active (the default under durable: true) with the default InProcessTokenStreamSink, which only buffers tokens in-process. A dispatched `llm` step served by a different worker cannot stream into this buffer. Wire a cross-process TokenStreamSink (e.g. a Redis pub/sub sink) via AgentModule.forRoot({ sink }) before running multi-pod, or set dispatchedSteps: false to keep the turn in-process localSteps.");
459
- }
460
- return enabled;
461
- }, "useFactory"),
462
- inject: [
463
- AGENT_OPTIONS,
464
- AGENT_SINK
465
- ]
466
- }
502
+ ...runnerProviders()
467
503
  ],
468
504
  exports: [
469
505
  AGENT_DURABLE_RUNNER,
@@ -482,7 +518,7 @@ import { DiscoveryModule, RouterModule } from "@nestjs/core";
482
518
  // src/agent-deps.factory.ts
483
519
  import { AGENT_MODEL, AGENT_PRICING_STORE, AGENT_PROMPT_CONTRIBUTORS, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_ROLES_POLICY, AGENT_SINK as AGENT_SINK2, AGENT_STORE as AGENT_STORE2, AGENT_TOOL_REGISTRY, AgentRegistry as AgentRegistry2, ToolRegistry as ToolRegistry2 } from "@dudousxd/nestjs-agent-core";
484
520
  import { AGENT_OPTIONS as AGENT_OPTIONS2 } from "@dudousxd/nestjs-agent-core";
485
- import { Inject as Inject3, Injectable as Injectable4, Optional } from "@nestjs/common";
521
+ import { Inject as Inject3, Injectable as Injectable4, Optional as Optional2 } from "@nestjs/common";
486
522
  function _ts_decorate5(decorators, target, key, desc) {
487
523
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
488
524
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -621,7 +657,7 @@ AgentDepsFactory2 = _ts_decorate5([
621
657
  _ts_param3(6, Inject3(AGENT_REGISTRY)),
622
658
  _ts_param3(7, Inject3(AGENT_PROMPT_CONTRIBUTORS)),
623
659
  _ts_param3(8, Inject3(AGENT_QUOTA_STORE)),
624
- _ts_param3(9, Optional()),
660
+ _ts_param3(9, Optional2()),
625
661
  _ts_param3(9, Inject3(AGENT_PRICING_STORE)),
626
662
  _ts_metadata4("design:type", Function),
627
663
  _ts_metadata4("design:paramtypes", [
@@ -1049,7 +1085,7 @@ AgentsController = _ts_decorate8([
1049
1085
 
1050
1086
  // src/controller/attachments.controller.ts
1051
1087
  import { AGENT_ACTOR_RESOLVER, AGENT_ATTACHMENT_STAGING, AGENT_OPTIONS as AGENT_OPTIONS3 } from "@dudousxd/nestjs-agent-core";
1052
- import { BadRequestException as BadRequestException2, Controller as Controller2, Inject as Inject6, NotImplementedException as NotImplementedException2, Optional as Optional2, PayloadTooLargeException, Post, Req, UnsupportedMediaTypeException, UploadedFile, UseInterceptors } from "@nestjs/common";
1088
+ import { BadRequestException as BadRequestException2, Controller as Controller2, Inject as Inject6, NotImplementedException as NotImplementedException2, Optional as Optional3, PayloadTooLargeException, Post, Req, UnsupportedMediaTypeException, UploadedFile, UseInterceptors } from "@nestjs/common";
1053
1089
  import { FileInterceptor } from "@nestjs/platform-express";
1054
1090
  function _ts_decorate9(decorators, target, key, desc) {
1055
1091
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -1142,7 +1178,7 @@ AttachmentsController = _ts_decorate9([
1142
1178
  Controller2("attachments"),
1143
1179
  _ts_param6(0, Inject6(AGENT_OPTIONS3)),
1144
1180
  _ts_param6(1, Inject6(AGENT_ACTOR_RESOLVER)),
1145
- _ts_param6(2, Optional2()),
1181
+ _ts_param6(2, Optional3()),
1146
1182
  _ts_param6(2, Inject6(AGENT_ATTACHMENT_STAGING)),
1147
1183
  _ts_metadata8("design:type", Function),
1148
1184
  _ts_metadata8("design:paramtypes", [
@@ -2250,6 +2286,10 @@ function controllersFor(mountAttachments) {
2250
2286
  ] : BASE_CONTROLLERS;
2251
2287
  }
2252
2288
  __name(controllersFor, "controllersFor");
2289
+ function controllersForSurface(surface, mountAttachments) {
2290
+ return surface === "engine" ? [] : controllersFor(mountAttachments);
2291
+ }
2292
+ __name(controllersForSurface, "controllersForSurface");
2253
2293
  var GUARDS_METADATA = "__guards__";
2254
2294
  function applyGuards(guards) {
2255
2295
  const resolved = guards ?? [];
@@ -2295,7 +2335,7 @@ var AgentModule = class _AgentModule {
2295
2335
  DiscoveryModule,
2296
2336
  routerFor(path)
2297
2337
  ],
2298
- controllers: controllersFor(options.attachments?.upload === true),
2338
+ controllers: controllersForSurface(options.surface, options.attachments?.upload === true),
2299
2339
  providers: [
2300
2340
  {
2301
2341
  provide: AGENT_OPTIONS5,
@@ -2320,17 +2360,21 @@ var AgentModule = class _AgentModule {
2320
2360
  routerFor(path),
2321
2361
  ...options.imports ?? []
2322
2362
  ],
2323
- controllers: controllersFor(options.attachmentsUpload === true),
2363
+ controllers: controllersForSurface(options.surface, options.attachmentsUpload === true),
2324
2364
  providers: [
2325
2365
  {
2326
2366
  provide: AGENT_OPTIONS5,
2327
- // Stamp the STATIC wiring flags onto the factory result: `durable`/`dispatchedSteps` are
2328
- // authoritative on the async config object (they decided the actual wiring above), and
2329
- // `AgentDurableModule` derives the effective dispatched-steps value from AGENT_OPTIONS —
2330
- // without this stamp, an async host would get in-process localSteps despite durable: true.
2367
+ // Stamp the STATIC wiring flags onto the factory result: `durable`/`dispatchedSteps`/
2368
+ // `surface` are authoritative on the async config object (they decided the actual wiring
2369
+ // above), and `AgentDurableModule` derives the effective dispatched-steps value from
2370
+ // AGENT_OPTIONS — without this stamp, an async host would get in-process localSteps
2371
+ // despite durable: true. `surface` isn't read back by anything today (AgentDurableModule
2372
+ // takes its own mirror option — see its doc for why), but it's stamped here too so the
2373
+ // EFFECTIVE value is always observable off AGENT_OPTIONS, sync or async alike.
2331
2374
  useFactory: /* @__PURE__ */ __name(async (...args) => ({
2332
2375
  ...await options.useFactory(...args),
2333
2376
  durable: options.durable ?? false,
2377
+ surface: options.surface ?? "both",
2334
2378
  ...options.dispatchedSteps !== void 0 ? {
2335
2379
  dispatchedSteps: options.dispatchedSteps
2336
2380
  } : {}
@@ -2356,7 +2400,9 @@ function agentDurable(options) {
2356
2400
  ...options,
2357
2401
  durable: true
2358
2402
  }),
2359
- AgentDurableModule.forRoot()
2403
+ AgentDurableModule.forRoot(options.surface !== void 0 ? {
2404
+ surface: options.surface
2405
+ } : {})
2360
2406
  ];
2361
2407
  }
2362
2408
  __name(agentDurable, "agentDurable");