@dudousxd/nestjs-agent 0.8.2 → 0.10.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.
@@ -31,10 +31,10 @@ __export(durable_exports, {
31
31
  module.exports = __toCommonJS(durable_exports);
32
32
 
33
33
  // src/durable/agent-run.workflow.ts
34
- var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
35
- var import_nestjs_durable2 = require("@dudousxd/nestjs-durable");
34
+ var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
35
+ var import_nestjs_durable = require("@dudousxd/nestjs-durable");
36
36
  var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
37
- var import_common2 = require("@nestjs/common");
37
+ var import_common = require("@nestjs/common");
38
38
 
39
39
  // src/agent-deps.ts
40
40
  function utcDay(date = /* @__PURE__ */ new Date()) {
@@ -52,10 +52,10 @@ function childSinkWriter(writer) {
52
52
  }
53
53
  __name(childSinkWriter, "childSinkWriter");
54
54
 
55
- // src/durable/agent-run.steps.ts
56
- var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
57
- var import_nestjs_durable = require("@dudousxd/nestjs-durable");
58
- var import_common = require("@nestjs/common");
55
+ // src/durable/dispatched-steps.token.ts
56
+ var AGENT_DISPATCHED_STEPS = Symbol.for("@dudousxd/nestjs-agent:dispatched-steps");
57
+
58
+ // src/durable/agent-run.workflow.ts
59
59
  function _ts_decorate(decorators, target, key, desc) {
60
60
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
61
61
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -73,100 +73,6 @@ function _ts_param(paramIndex, decorator) {
73
73
  };
74
74
  }
75
75
  __name(_ts_param, "_ts_param");
76
- var AgentRunSteps = class {
77
- static {
78
- __name(this, "AgentRunSteps");
79
- }
80
- factory;
81
- constructor(factory) {
82
- this.factory = factory;
83
- }
84
- /**
85
- * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
86
- * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
87
- * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
88
- * across however many turns/retries it takes.
89
- */
90
- async llm(input) {
91
- const deps = this.factory.forAgent(input.agentName);
92
- const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
93
- const opened = await deps.sink.open(input.sinkRunId);
94
- const writer = input.childSink ? childSinkWriter(opened) : opened;
95
- return (0, import_nestjs_agent_core.traceLlmTurn)(input.runId, input.step, () => deps.model.runTurn({
96
- system: input.system,
97
- messages: input.messages,
98
- tools,
99
- sink: writer
100
- }));
101
- }
102
- /**
103
- * No retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm` above).
104
- * The timeout is applied HERE, handler-side, via `withToolTimeout` — never as a durable dispatch
105
- * `timeoutMs`, which bounds engine liveness (retryable) rather than the tool's own business outcome.
106
- */
107
- async tool(input) {
108
- const deps = this.factory.forAgent(input.ctx.agentName);
109
- const ctx = {
110
- ...input.ctx
111
- };
112
- return (0, import_nestjs_agent_core.traceToolExecution)(input.ctx.runId, {
113
- toolCallId: input.toolCallId,
114
- toolName: input.toolName,
115
- toolType: input.toolType
116
- }, () => {
117
- const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
118
- return input.timeoutMs !== void 0 ? (0, import_nestjs_agent_core.withToolTimeout)(invocation, input.timeoutMs, input.toolName) : invocation;
119
- });
120
- }
121
- };
122
- _ts_decorate([
123
- (0, import_nestjs_durable.Step)({
124
- retries: 3
125
- }),
126
- _ts_metadata("design:type", Function),
127
- _ts_metadata("design:paramtypes", [
128
- typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
129
- ]),
130
- _ts_metadata("design:returntype", Promise)
131
- ], AgentRunSteps.prototype, "llm", null);
132
- _ts_decorate([
133
- (0, import_nestjs_durable.Step)(),
134
- _ts_metadata("design:type", Function),
135
- _ts_metadata("design:paramtypes", [
136
- typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
137
- ]),
138
- _ts_metadata("design:returntype", Promise)
139
- ], AgentRunSteps.prototype, "tool", null);
140
- AgentRunSteps = _ts_decorate([
141
- (0, import_common.Injectable)(),
142
- _ts_param(0, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_DEPS_FACTORY)),
143
- _ts_metadata("design:type", Function),
144
- _ts_metadata("design:paramtypes", [
145
- typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
146
- ])
147
- ], AgentRunSteps);
148
-
149
- // src/durable/dispatched-steps.token.ts
150
- var AGENT_DISPATCHED_STEPS = Symbol.for("@dudousxd/nestjs-agent:dispatched-steps");
151
-
152
- // src/durable/agent-run.workflow.ts
153
- function _ts_decorate2(decorators, target, key, desc) {
154
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
155
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
156
- 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;
157
- return c > 3 && r && Object.defineProperty(target, key, r), r;
158
- }
159
- __name(_ts_decorate2, "_ts_decorate");
160
- function _ts_metadata2(k, v) {
161
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
162
- }
163
- __name(_ts_metadata2, "_ts_metadata");
164
- function _ts_param2(paramIndex, decorator) {
165
- return function(target, key) {
166
- decorator(target, key, paramIndex);
167
- };
168
- }
169
- __name(_ts_param2, "_ts_param");
170
76
  var AgentRunWorkflow = class _AgentRunWorkflow {
171
77
  static {
172
78
  __name(this, "AgentRunWorkflow");
@@ -184,6 +90,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
184
90
  async run(ctx, input) {
185
91
  const day = input.day ?? utcDay();
186
92
  const deps = this.factory.forAgent(input.agentName);
93
+ const dispatchSteps = this.dispatchedSteps ? this.steps : void 0;
187
94
  if (input.sinkRunId !== void 0) {
188
95
  await ctx.localStep("activate", () => this.store.setActiveStream(input.threadId, ctx.runId));
189
96
  }
@@ -221,8 +128,8 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
221
128
  // `ctx.localStep`s, so a turn isn't pinned to this workflow worker for the model call or a tool
222
129
  // execution. `sinkRunId`/`childSink` are sink routing this workflow already resolved above —
223
130
  // core's dispatchLlm signature stays sink-topology-agnostic, so we add them here, not in core.
224
- ...this.dispatchedSteps ? {
225
- dispatchLlm: /* @__PURE__ */ __name((index, envelope) => ctx.step(this.steps.llm, {
131
+ ...dispatchSteps !== void 0 ? {
132
+ dispatchLlm: /* @__PURE__ */ __name((index, envelope) => ctx.step(dispatchSteps.llm, {
226
133
  ...envelope,
227
134
  runId: ctx.runId,
228
135
  step: index,
@@ -234,7 +141,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
234
141
  // ('agent'-kind delegations branch to runAgent earlier in the loop), so anything that
235
142
  // isn't 'action' is defensively 'read' — the same posture core takes for an
236
143
  // unresolvable `kind`.
237
- dispatchTool: /* @__PURE__ */ __name((call, envelope) => ctx.step(this.steps.tool, {
144
+ dispatchTool: /* @__PURE__ */ __name((call, envelope) => ctx.step(dispatchSteps.tool, {
238
145
  ...envelope,
239
146
  toolCallId: call.id,
240
147
  toolType: call.kind === "action" ? "action" : "read"
@@ -242,7 +149,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
242
149
  } : {}
243
150
  };
244
151
  try {
245
- const result = await (0, import_nestjs_agent_core2.runAgentLoop)({
152
+ const result = await (0, import_nestjs_agent_core.runAgentLoop)({
246
153
  ...deps,
247
154
  day
248
155
  }, input, hooks);
@@ -253,8 +160,8 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
253
160
  throw error;
254
161
  }
255
162
  const message = error instanceof Error ? error.message : String(error);
256
- const code = error instanceof import_nestjs_agent_core2.QuotaExceededError ? "quota_exceeded" : "run_failed";
257
- (0, import_nestjs_agent_core2.publishAgentRunFailed)({
163
+ const code = error instanceof import_nestjs_agent_core.QuotaExceededError ? "quota_exceeded" : "run_failed";
164
+ (0, import_nestjs_agent_core.publishAgentRunFailed)({
258
165
  runId: ctx.runId,
259
166
  code,
260
167
  message
@@ -275,24 +182,141 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
275
182
  }
276
183
  }
277
184
  };
278
- AgentRunWorkflow = _ts_decorate2([
279
- (0, import_common2.Injectable)(),
280
- (0, import_nestjs_durable2.Workflow)({
185
+ AgentRunWorkflow = _ts_decorate([
186
+ (0, import_common.Injectable)(),
187
+ (0, import_nestjs_durable.Workflow)({
281
188
  name: "agent.run",
282
189
  version: "1"
283
190
  }),
284
- _ts_param2(0, (0, import_common2.Inject)(import_nestjs_agent_core2.AGENT_DEPS_FACTORY)),
285
- _ts_param2(1, (0, import_common2.Inject)(import_nestjs_agent_core2.AGENT_STORE)),
286
- _ts_param2(3, (0, import_common2.Inject)(AGENT_DISPATCHED_STEPS)),
287
- _ts_metadata2("design:type", Function),
288
- _ts_metadata2("design:paramtypes", [
191
+ _ts_param(0, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_DEPS_FACTORY)),
192
+ _ts_param(1, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_STORE)),
193
+ _ts_param(2, (0, import_common.Optional)()),
194
+ _ts_param(3, (0, import_common.Inject)(AGENT_DISPATCHED_STEPS)),
195
+ _ts_metadata("design:type", Function),
196
+ _ts_metadata("design:paramtypes", [
289
197
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
290
198
  typeof AgentStore === "undefined" ? Object : AgentStore,
291
- typeof AgentRunSteps === "undefined" ? Object : AgentRunSteps,
199
+ Object,
292
200
  Boolean
293
201
  ])
294
202
  ], AgentRunWorkflow);
295
203
 
204
+ // src/durable/agent-run.steps.ts
205
+ var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
206
+ var import_nestjs_durable2 = require("@dudousxd/nestjs-durable");
207
+ var import_common2 = require("@nestjs/common");
208
+ function _ts_decorate2(decorators, target, key, desc) {
209
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
210
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
211
+ 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;
212
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
213
+ }
214
+ __name(_ts_decorate2, "_ts_decorate");
215
+ function _ts_metadata2(k, v) {
216
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
217
+ }
218
+ __name(_ts_metadata2, "_ts_metadata");
219
+ function _ts_param2(paramIndex, decorator) {
220
+ return function(target, key) {
221
+ decorator(target, key, paramIndex);
222
+ };
223
+ }
224
+ __name(_ts_param2, "_ts_param");
225
+ var AgentRunSteps = class {
226
+ static {
227
+ __name(this, "AgentRunSteps");
228
+ }
229
+ factory;
230
+ constructor(factory) {
231
+ this.factory = factory;
232
+ }
233
+ /**
234
+ * Retryable: every side effect (persist/quota/stream markers) happens loop-side under
235
+ * `hooks.step`, so a durable retry only re-runs the model call and re-streams its tokens — never
236
+ * double-writes. NEVER call `writer.end()`/`fail()` here: the workflow owns the stream's lifecycle,
237
+ * across however many turns/retries it takes.
238
+ */
239
+ async llm(input) {
240
+ const deps = this.factory.forAgent(input.agentName);
241
+ const tools = await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList);
242
+ const opened = await deps.sink.open(input.sinkRunId);
243
+ const writer = input.childSink ? childSinkWriter(opened) : opened;
244
+ return (0, import_nestjs_agent_core2.traceLlmTurn)(input.runId, input.step, () => deps.model.runTurn({
245
+ system: input.system,
246
+ messages: input.messages,
247
+ tools,
248
+ sink: writer
249
+ }));
250
+ }
251
+ /**
252
+ * NO DURABLE retries — a tool may not be idempotent (a bare `@Step()` carries none, unlike `llm`
253
+ * above). What it does retry, in place, is a CLASSIFIED-TRANSIENT error from the tool's own
254
+ * invocation (a DB deadlock, a lock-wait timeout — see `isTransientToolError`): the server rolled
255
+ * that work back, so re-invoking it is safe, and doing it here (inside this one step, never a new
256
+ * checkpoint) is exactly how the non-dispatched loop path handles it too. The timeout is applied
257
+ * HERE, handler-side, via `withToolTimeout` — never as a durable dispatch `timeoutMs`, which
258
+ * bounds engine liveness (retryable) rather than the tool's own business outcome — and per
259
+ * ATTEMPT, so a retried invocation gets its own fresh timeout window.
260
+ */
261
+ async tool(input) {
262
+ const deps = this.factory.forAgent(input.ctx.agentName);
263
+ const ctx = {
264
+ ...input.ctx
265
+ };
266
+ const localClassify = deps.toolTransientRetry !== false ? deps.toolTransientRetry?.classify : void 0;
267
+ const transientRetry = input.transientRetry === false ? false : {
268
+ attempts: input.transientRetry.attempts,
269
+ backoffMs: input.transientRetry.backoffMs,
270
+ ...localClassify !== void 0 ? {
271
+ classify: localClassify
272
+ } : {}
273
+ };
274
+ return (0, import_nestjs_agent_core2.traceToolExecution)(input.ctx.runId, {
275
+ toolCallId: input.toolCallId,
276
+ toolName: input.toolName,
277
+ toolType: input.toolType
278
+ }, () => (0, import_nestjs_agent_core2.invokeWithTransientRetry)(() => {
279
+ const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
280
+ return input.timeoutMs !== void 0 ? (0, import_nestjs_agent_core2.withToolTimeout)(invocation, input.timeoutMs, input.toolName) : invocation;
281
+ }, transientRetry, {
282
+ onRetry: /* @__PURE__ */ __name((attempt, error) => {
283
+ (0, import_nestjs_agent_core2.publishAgentToolRetry)({
284
+ toolName: input.toolName,
285
+ toolCallId: input.toolCallId,
286
+ attempt,
287
+ message: error instanceof Error ? error.message : String(error)
288
+ });
289
+ }, "onRetry")
290
+ }));
291
+ }
292
+ };
293
+ _ts_decorate2([
294
+ (0, import_nestjs_durable2.Step)({
295
+ retries: 3
296
+ }),
297
+ _ts_metadata2("design:type", Function),
298
+ _ts_metadata2("design:paramtypes", [
299
+ typeof DispatchedLlmInput === "undefined" ? Object : DispatchedLlmInput
300
+ ]),
301
+ _ts_metadata2("design:returntype", Promise)
302
+ ], AgentRunSteps.prototype, "llm", null);
303
+ _ts_decorate2([
304
+ (0, import_nestjs_durable2.Step)(),
305
+ _ts_metadata2("design:type", Function),
306
+ _ts_metadata2("design:paramtypes", [
307
+ typeof DispatchedToolInput === "undefined" ? Object : DispatchedToolInput
308
+ ]),
309
+ _ts_metadata2("design:returntype", Promise)
310
+ ], AgentRunSteps.prototype, "tool", null);
311
+ AgentRunSteps = _ts_decorate2([
312
+ (0, import_common2.Injectable)(),
313
+ _ts_param2(0, (0, import_common2.Inject)(import_nestjs_agent_core2.AGENT_DEPS_FACTORY)),
314
+ _ts_metadata2("design:type", Function),
315
+ _ts_metadata2("design:paramtypes", [
316
+ typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
317
+ ])
318
+ ], AgentRunSteps);
319
+
296
320
  // src/durable/durable-agent-runner.ts
297
321
  var import_node_crypto = require("crypto");
298
322
  var import_nestjs_durable3 = require("@dudousxd/nestjs-durable");
@@ -430,16 +454,68 @@ function _ts_decorate4(decorators, target, key, desc) {
430
454
  }
431
455
  __name(_ts_decorate4, "_ts_decorate");
432
456
  var logger = new import_common4.Logger("AgentDurableModule");
457
+ function runnerProviders() {
458
+ return [
459
+ DurableAgentRunner,
460
+ {
461
+ provide: import_nestjs_agent_core4.AGENT_DURABLE_RUNNER,
462
+ useExisting: DurableAgentRunner
463
+ },
464
+ {
465
+ provide: AGENT_DISPATCHED_STEPS,
466
+ useFactory: /* @__PURE__ */ __name((options, sink) => {
467
+ const enabled = options.durable === true && options.dispatchedSteps !== false;
468
+ if (enabled && sink instanceof InProcessTokenStreamSink) {
469
+ 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.");
470
+ }
471
+ return enabled;
472
+ }, "useFactory"),
473
+ inject: [
474
+ import_nestjs_agent_core4.AGENT_OPTIONS,
475
+ import_nestjs_agent_core4.AGENT_SINK
476
+ ]
477
+ }
478
+ ];
479
+ }
480
+ __name(runnerProviders, "runnerProviders");
481
+ var AgentDurableHttpModule = class AgentDurableHttpModule2 {
482
+ static {
483
+ __name(this, "AgentDurableHttpModule");
484
+ }
485
+ };
486
+ AgentDurableHttpModule = _ts_decorate4([
487
+ (0, import_common4.Global)(),
488
+ (0, import_common4.Module)({
489
+ providers: [
490
+ AgentRunWorkflow,
491
+ ...runnerProviders()
492
+ ],
493
+ exports: [
494
+ import_nestjs_agent_core4.AGENT_DURABLE_RUNNER,
495
+ AgentRunWorkflow,
496
+ AGENT_DISPATCHED_STEPS
497
+ ]
498
+ })
499
+ ], AgentDurableHttpModule);
433
500
  var AgentDurableModule = class _AgentDurableModule {
434
501
  static {
435
502
  __name(this, "AgentDurableModule");
436
503
  }
437
504
  /**
438
- * The dynamic form used by the `agentDurable` helper. The module needs no configuration of its
439
- * own (its providers come from the decorator above), so this just yields the module reference —
440
- * importing `AgentDurableModule` directly stays equivalent.
505
+ * `surface: 'http'` returns the reduced `AgentDurableHttpModule` wiring (no `AgentRunSteps`);
506
+ * everything else (omitted, `'engine'`, `'both'`) returns this module's own full wiring — the
507
+ * class's `@Module` providers above merge in regardless of which DynamicModule shape a caller
508
+ * imports (Nest merges a class's static provider list with whatever a self-referencing
509
+ * `DynamicModule` adds), which is exactly why the reduced case has to be a DIFFERENT module class
510
+ * rather than a conditional subset of this one's own decorator.
441
511
  */
442
- static forRoot() {
512
+ static forRoot(options) {
513
+ if (options?.surface === "http") {
514
+ return {
515
+ module: AgentDurableHttpModule,
516
+ global: true
517
+ };
518
+ }
443
519
  return {
444
520
  module: _AgentDurableModule,
445
521
  global: true
@@ -452,25 +528,7 @@ AgentDurableModule = _ts_decorate4([
452
528
  providers: [
453
529
  AgentRunWorkflow,
454
530
  AgentRunSteps,
455
- DurableAgentRunner,
456
- {
457
- provide: import_nestjs_agent_core4.AGENT_DURABLE_RUNNER,
458
- useExisting: DurableAgentRunner
459
- },
460
- {
461
- provide: AGENT_DISPATCHED_STEPS,
462
- useFactory: /* @__PURE__ */ __name((options, sink) => {
463
- const enabled = options.durable === true && options.dispatchedSteps !== false;
464
- if (enabled && sink instanceof InProcessTokenStreamSink) {
465
- 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.");
466
- }
467
- return enabled;
468
- }, "useFactory"),
469
- inject: [
470
- import_nestjs_agent_core4.AGENT_OPTIONS,
471
- import_nestjs_agent_core4.AGENT_SINK
472
- ]
473
- }
531
+ ...runnerProviders()
474
532
  ],
475
533
  exports: [
476
534
  import_nestjs_agent_core4.AGENT_DURABLE_RUNNER,
@@ -591,6 +649,9 @@ var AgentDepsFactory2 = class {
591
649
  ...this.options.toolTimeoutMs !== void 0 ? {
592
650
  toolTimeoutMs: this.options.toolTimeoutMs
593
651
  } : {},
652
+ ...this.options.toolTransientRetry !== void 0 ? {
653
+ toolTransientRetry: this.options.toolTransientRetry
654
+ } : {},
594
655
  ...followUpsCount !== void 0 ? {
595
656
  followUpsCount
596
657
  } : {},
@@ -2254,6 +2315,10 @@ function controllersFor(mountAttachments) {
2254
2315
  ] : BASE_CONTROLLERS;
2255
2316
  }
2256
2317
  __name(controllersFor, "controllersFor");
2318
+ function controllersForSurface(surface, mountAttachments) {
2319
+ return surface === "engine" ? [] : controllersFor(mountAttachments);
2320
+ }
2321
+ __name(controllersForSurface, "controllersForSurface");
2257
2322
  var GUARDS_METADATA = "__guards__";
2258
2323
  function applyGuards(guards) {
2259
2324
  const resolved = guards ?? [];
@@ -2299,7 +2364,7 @@ var AgentModule = class _AgentModule {
2299
2364
  import_core3.DiscoveryModule,
2300
2365
  routerFor(path)
2301
2366
  ],
2302
- controllers: controllersFor(options.attachments?.upload === true),
2367
+ controllers: controllersForSurface(options.surface, options.attachments?.upload === true),
2303
2368
  providers: [
2304
2369
  {
2305
2370
  provide: import_nestjs_agent_core17.AGENT_OPTIONS,
@@ -2324,17 +2389,21 @@ var AgentModule = class _AgentModule {
2324
2389
  routerFor(path),
2325
2390
  ...options.imports ?? []
2326
2391
  ],
2327
- controllers: controllersFor(options.attachmentsUpload === true),
2392
+ controllers: controllersForSurface(options.surface, options.attachmentsUpload === true),
2328
2393
  providers: [
2329
2394
  {
2330
2395
  provide: import_nestjs_agent_core17.AGENT_OPTIONS,
2331
- // Stamp the STATIC wiring flags onto the factory result: `durable`/`dispatchedSteps` are
2332
- // authoritative on the async config object (they decided the actual wiring above), and
2333
- // `AgentDurableModule` derives the effective dispatched-steps value from AGENT_OPTIONS —
2334
- // without this stamp, an async host would get in-process localSteps despite durable: true.
2396
+ // Stamp the STATIC wiring flags onto the factory result: `durable`/`dispatchedSteps`/
2397
+ // `surface` are authoritative on the async config object (they decided the actual wiring
2398
+ // above), and `AgentDurableModule` derives the effective dispatched-steps value from
2399
+ // AGENT_OPTIONS — without this stamp, an async host would get in-process localSteps
2400
+ // despite durable: true. `surface` isn't read back by anything today (AgentDurableModule
2401
+ // takes its own mirror option — see its doc for why), but it's stamped here too so the
2402
+ // EFFECTIVE value is always observable off AGENT_OPTIONS, sync or async alike.
2335
2403
  useFactory: /* @__PURE__ */ __name(async (...args) => ({
2336
2404
  ...await options.useFactory(...args),
2337
2405
  durable: options.durable ?? false,
2406
+ surface: options.surface ?? "both",
2338
2407
  ...options.dispatchedSteps !== void 0 ? {
2339
2408
  dispatchedSteps: options.dispatchedSteps
2340
2409
  } : {}
@@ -2360,7 +2429,9 @@ function agentDurable(options) {
2360
2429
  ...options,
2361
2430
  durable: true
2362
2431
  }),
2363
- AgentDurableModule.forRoot()
2432
+ AgentDurableModule.forRoot(options.surface !== void 0 ? {
2433
+ surface: options.surface
2434
+ } : {})
2364
2435
  ];
2365
2436
  }
2366
2437
  __name(agentDurable, "agentDurable");