@dudousxd/nestjs-agent 0.11.0 → 0.12.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.
package/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  AGENT_METADATA: () => AGENT_METADATA,
26
26
  AGENT_TOOL_BRAND: () => AGENT_TOOL_BRAND,
27
27
  AI_TOOL_METADATA: () => AI_TOOL_METADATA,
28
+ ATTACHMENT_PAGE_SIZE: () => ATTACHMENT_PAGE_SIZE,
28
29
  Agent: () => Agent,
29
30
  AgentApprovalPortAdapter: () => AgentApprovalPortAdapter,
30
31
  AgentDepsFactory: () => AgentDepsFactory2,
@@ -40,22 +41,31 @@ __export(index_exports, {
40
41
  InProcessTokenStreamSink: () => InProcessTokenStreamSink,
41
42
  InlineAgentRunner: () => InlineAgentRunner,
42
43
  LedgerQuotaStore: () => LedgerQuotaStore,
44
+ MemoriesController: () => MemoriesController,
45
+ SKILL_METADATA: () => SKILL_METADATA,
43
46
  SYSTEM_PROMPT_CONTRIBUTOR_METADATA: () => SYSTEM_PROMPT_CONTRIBUTOR_METADATA,
44
47
  SYSTEM_PROMPT_METADATA: () => SYSTEM_PROMPT_METADATA,
48
+ Skill: () => Skill,
49
+ SkillDiscoveryService: () => SkillDiscoveryService,
50
+ SkillsController: () => SkillsController,
45
51
  SystemPrompt: () => SystemPrompt,
46
52
  SystemPromptContributor: () => SystemPromptContributor,
53
+ declaredSkillProvider: () => declaredSkillProvider,
47
54
  delegateToolName: () => delegateToolName,
48
55
  provideAgentTool: () => provideAgentTool,
49
56
  readAgentMetadata: () => readAgentMetadata,
50
57
  readAiToolMetadata: () => readAiToolMetadata,
58
+ readSkillMetadata: () => readSkillMetadata,
59
+ resolveSkillsConfig: () => resolveSkillsConfig,
60
+ skillScope: () => skillScope,
51
61
  utcDay: () => utcDay
52
62
  });
53
63
  module.exports = __toCommonJS(index_exports);
54
64
 
55
65
  // src/agent.module.ts
56
- var import_nestjs_agent_core14 = require("@dudousxd/nestjs-agent-core");
57
- var import_common13 = require("@nestjs/common");
58
- var import_core3 = require("@nestjs/core");
66
+ var import_nestjs_agent_core19 = require("@dudousxd/nestjs-agent-core");
67
+ var import_common16 = require("@nestjs/common");
68
+ var import_core4 = require("@nestjs/core");
59
69
 
60
70
  // src/agent-deps.factory.ts
61
71
  var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
@@ -78,8 +88,9 @@ function _ts_param(paramIndex, decorator) {
78
88
  };
79
89
  }
80
90
  __name(_ts_param, "_ts_param");
81
- function delegateToolName(target) {
82
- return `ask_${target.replace(/[^a-zA-Z0-9]+/g, "_")}`;
91
+ function delegateToolName(args) {
92
+ const slug = args.target.replace(/[^a-zA-Z0-9]+/g, "_");
93
+ return args.detached === true ? `start_${slug}` : `ask_${slug}`;
83
94
  }
84
95
  __name(delegateToolName, "delegateToolName");
85
96
  var AgentDepsFactory2 = class {
@@ -96,7 +107,9 @@ var AgentDepsFactory2 = class {
96
107
  promptContributors;
97
108
  quota;
98
109
  pricingStore;
99
- constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, quota, pricingStore) {
110
+ skills;
111
+ memory;
112
+ constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, quota, pricingStore, skills, memory) {
100
113
  this.options = options;
101
114
  this.model = model;
102
115
  this.store = store;
@@ -107,6 +120,16 @@ var AgentDepsFactory2 = class {
107
120
  this.promptContributors = promptContributors;
108
121
  this.quota = quota;
109
122
  this.pricingStore = pricingStore;
123
+ this.skills = skills;
124
+ this.memory = memory;
125
+ }
126
+ /** The turn's memory seam, shared with the read-back endpoint. Undefined → memory is not configured. */
127
+ memoryConfig() {
128
+ return this.memory;
129
+ }
130
+ /** The turn's skills seam, shared with the listing endpoint. Undefined → skills are not configured. */
131
+ skillsConfig() {
132
+ return this.skills;
110
133
  }
111
134
  /**
112
135
  * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the
@@ -123,7 +146,13 @@ var AgentDepsFactory2 = class {
123
146
  if (definition === void 0) {
124
147
  return void 0;
125
148
  }
126
- const delegated = (definition.delegatesTo ?? []).map(delegateToolName);
149
+ const delegated = (definition.delegatesTo ?? []).map((edge) => {
150
+ const { agent, detached } = (0, import_nestjs_agent_core.normalizeDelegation)(edge);
151
+ return delegateToolName({
152
+ target: agent,
153
+ detached
154
+ });
155
+ });
127
156
  if (definition.tools === void 0 && delegated.length === 0) {
128
157
  return void 0;
129
158
  }
@@ -138,6 +167,8 @@ var AgentDepsFactory2 = class {
138
167
  const toolAllowList = this.effectiveTools(definition);
139
168
  const followUpsCount = this.followUpsCount();
140
169
  const retrieval = this.options.retrieval;
170
+ const historyPolicy = this.historyPolicy(definition);
171
+ const ask = definition?.ask ?? this.options.ask;
141
172
  return {
142
173
  model: this.model,
143
174
  store: this.store,
@@ -147,6 +178,12 @@ var AgentDepsFactory2 = class {
147
178
  promptContributors: this.promptContributors,
148
179
  systemPrompt: definition?.systemPrompt ?? "You are a helpful assistant.",
149
180
  maxSteps: definition?.maxSteps ?? 8,
181
+ ...definition?.maxDelegationDepth !== void 0 ? {
182
+ maxDelegationDepth: definition.maxDelegationDepth
183
+ } : {},
184
+ ...definition?.maxAgentAppearances !== void 0 ? {
185
+ maxAgentAppearances: definition.maxAgentAppearances
186
+ } : {},
150
187
  ...definition?.modelId !== void 0 ? {
151
188
  modelId: definition.modelId
152
189
  } : {},
@@ -156,6 +193,37 @@ var AgentDepsFactory2 = class {
156
193
  ...this.pricingStore !== void 0 ? {
157
194
  pricingStore: this.pricingStore
158
195
  } : {},
196
+ ...historyPolicy !== void 0 ? {
197
+ historyPolicy
198
+ } : {},
199
+ inputProcessors: this.options.inputProcessors ?? [],
200
+ outputProcessors: this.options.outputProcessors ?? [],
201
+ ...definition?.outputSchema !== void 0 ? {
202
+ outputSchema: definition.outputSchema
203
+ } : {},
204
+ ...definition?.outputRepairAttempts !== void 0 ? {
205
+ outputRepairAttempts: definition.outputRepairAttempts
206
+ } : {},
207
+ ...definition?.intake !== void 0 ? {
208
+ intake: definition.intake
209
+ } : {},
210
+ // Most specific wins, exactly as `historyPolicy` resolves: the agent's own `@Agent({ ask })`,
211
+ // else the module-wide flag. Both are module config, so every process of a deployment agrees.
212
+ ...ask === true ? {
213
+ ask: true
214
+ } : {},
215
+ // Module-wide, never per-agent: a skill is a procedure, not a persona, and an agent that could
216
+ // opt out of one would make the catalog depend on which agent a turn happened to select — a
217
+ // per-turn fact the worker re-deriving the tool list cannot see.
218
+ ...this.skills !== void 0 ? {
219
+ skills: this.skills
220
+ } : {},
221
+ // Module-wide, never per-agent, for the same reason skills are: which memories a turn carries
222
+ // cannot depend on which persona answered it, or the worker re-deriving a dispatched turn's
223
+ // tool list would disagree with the loop about whether `remember` was offered.
224
+ ...this.memory !== void 0 ? {
225
+ memory: this.memory
226
+ } : {},
159
227
  ...toolAllowList !== void 0 ? {
160
228
  toolAllowList
161
229
  } : {},
@@ -176,6 +244,36 @@ var AgentDepsFactory2 = class {
176
244
  } : {}
177
245
  };
178
246
  }
247
+ /**
248
+ * The ceiling on how much of a thread this agent's turns carry, most specific wins: the agent's
249
+ * own `@Agent({ history })`, else a module-wide custom `historyPolicy`, else the module-wide
250
+ * `history` window. Undefined → unbounded, the behaviour of a module that configures none.
251
+ */
252
+ historyPolicy(definition) {
253
+ if (definition?.history !== void 0) {
254
+ return this.window(definition.history);
255
+ }
256
+ if (this.options.historyPolicy !== void 0) {
257
+ return this.options.historyPolicy;
258
+ }
259
+ return this.options.history === void 0 ? void 0 : this.window(this.options.history);
260
+ }
261
+ /** Build the built-in window policy from the declarative `{ maxMessages, maxTokens, summarize }`. */
262
+ window(config) {
263
+ return (0, import_nestjs_agent_core.windowHistory)({
264
+ ...config.maxMessages !== void 0 ? {
265
+ maxMessages: config.maxMessages
266
+ } : {},
267
+ ...config.maxTokens !== void 0 ? {
268
+ maxTokens: config.maxTokens
269
+ } : {},
270
+ // The shared module model, not a per-agent one: an agent's `modelId` is an accounting label,
271
+ // and only one provider is ever bound.
272
+ ...config.summarize === true ? {
273
+ summarize: (0, import_nestjs_agent_core.summarizeWithModel)(this.model)
274
+ } : {}
275
+ });
276
+ }
179
277
  /** Normalize the `followUps` option (`true` → 3, `{ count }` → count) to a number, or undefined. */
180
278
  followUpsCount() {
181
279
  const followUps = this.options.followUps;
@@ -201,6 +299,10 @@ AgentDepsFactory2 = _ts_decorate([
201
299
  _ts_param(8, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_QUOTA_STORE)),
202
300
  _ts_param(9, (0, import_common.Optional)()),
203
301
  _ts_param(9, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_PRICING_STORE)),
302
+ _ts_param(10, (0, import_common.Optional)()),
303
+ _ts_param(10, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_SKILLS)),
304
+ _ts_param(11, (0, import_common.Optional)()),
305
+ _ts_param(11, (0, import_common.Inject)(import_nestjs_agent_core.AGENT_MEMORY)),
204
306
  _ts_metadata("design:type", Function),
205
307
  _ts_metadata("design:paramtypes", [
206
308
  typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions,
@@ -212,6 +314,8 @@ AgentDepsFactory2 = _ts_decorate([
212
314
  typeof import_nestjs_agent_core.AgentRegistry === "undefined" ? Object : import_nestjs_agent_core.AgentRegistry,
213
315
  Array,
214
316
  Object,
317
+ Object,
318
+ Object,
215
319
  Object
216
320
  ])
217
321
  ], AgentDepsFactory2);
@@ -262,14 +366,17 @@ var AgentService = class {
262
366
  store;
263
367
  deps;
264
368
  quota;
265
- constructor(runner, store, deps, quota) {
369
+ staging;
370
+ constructor(runner, store, deps, quota, staging) {
266
371
  this.runner = runner;
267
372
  this.store = store;
268
373
  this.deps = deps;
269
374
  this.quota = quota;
375
+ this.staging = staging;
270
376
  }
271
377
  async chat(params) {
272
378
  const agentName = await this.resolveAgentName(params.agentName, params.threadId);
379
+ const attachments = await this.resolveAttachments(params.actor, params.attachments ?? []);
273
380
  let threadId = params.threadId;
274
381
  if (threadId === void 0) {
275
382
  if (params.regenerate === true) {
@@ -294,8 +401,8 @@ var AgentService = class {
294
401
  ...params.regenerate === true ? {
295
402
  regenerate: true
296
403
  } : {},
297
- ...params.attachments !== void 0 ? {
298
- attachments: params.attachments
404
+ ...attachments.length > 0 ? {
405
+ attachments
299
406
  } : {},
300
407
  ...params.pageContext !== void 0 ? {
301
408
  pageContext: params.pageContext
@@ -308,18 +415,66 @@ var AgentService = class {
308
415
  threadId
309
416
  };
310
417
  }
418
+ /**
419
+ * Rebuild this turn's attachments from the staging store, keyed by the ids the caller claimed.
420
+ * The model provider fetches {@link MessageAttachment.url} verbatim, so that url is only ever
421
+ * allowed to come from the host's own store — a caller that could name it could point the server
422
+ * at anything it can reach (cloud metadata, internal services) and read the response back out of
423
+ * the model's answer.
424
+ *
425
+ * No store bound means no way to tell an id the actor owns from one they don't, so a turn simply
426
+ * cannot carry attachments: 501 rather than trusting the request.
427
+ */
428
+ async resolveAttachments(actor, refs) {
429
+ if (refs.length === 0) {
430
+ return [];
431
+ }
432
+ const staging = this.staging;
433
+ if (staging === void 0 || typeof staging.resolve !== "function") {
434
+ throw new import_common2.NotImplementedException("Message attachments require an AGENT_ATTACHMENT_STAGING provider implementing resolve(); attachment urls are never taken from the request.");
435
+ }
436
+ const resolved = [];
437
+ for (const ref of refs) {
438
+ const attachment = await staging.resolve({
439
+ mediaId: ref.mediaId,
440
+ actor
441
+ });
442
+ if (attachment === null) {
443
+ throw new import_common2.ForbiddenException(`attachment ${ref.mediaId} is not available to this actor`);
444
+ }
445
+ resolved.push(attachment);
446
+ }
447
+ return resolved;
448
+ }
449
+ /**
450
+ * The run's live token stream, WITHOUT an ownership check — for in-process callers that are
451
+ * already authorized (the MCP bridge, a host's own job code), the same split as
452
+ * {@link signalToolCall} vs {@link approve}. Anything reachable from a request must go through
453
+ * {@link subscribeAs} instead: a runId is the only thing standing between a caller and another
454
+ * actor's answer, tool arguments and tool results.
455
+ */
311
456
  subscribe(runId) {
312
457
  return this.deps.forAgent().sink.subscribe(runId);
313
458
  }
314
- async approve(actor, toolCallId) {
315
- await this.assertOwnsToolCall(actor, toolCallId);
316
- return this.signalToolCall(toolCallId, {
459
+ /**
460
+ * {@link subscribe}, gated the way {@link cancel} is: only the actor whose thread is currently
461
+ * streaming this run may read it. A run that has already finished is reported missing rather than
462
+ * replayed — the runner clears the thread's active stream as the run ends, and that field is what
463
+ * ownership is derived from.
464
+ */
465
+ async subscribeAs(actor, runId) {
466
+ await this.assertOwnsActiveStream(actor, runId);
467
+ return this.subscribe(runId);
468
+ }
469
+ async approve(actor, toolCallId2) {
470
+ await this.assertOwnsToolCall(actor, toolCallId2);
471
+ return this.signalToolCall(toolCallId2, {
317
472
  approved: true
318
473
  });
319
474
  }
320
- async reject(actor, toolCallId, reason) {
321
- await this.assertOwnsToolCall(actor, toolCallId);
322
- return this.signalToolCall(toolCallId, {
475
+ async reject(actor, toolCallId2, reason) {
476
+ await this.assertOwnsToolCall(actor, toolCallId2);
477
+ return this.signalToolCall(toolCallId2, {
323
478
  approved: false,
324
479
  ...reason !== void 0 ? {
325
480
  reason
@@ -327,6 +482,34 @@ var AgentService = class {
327
482
  });
328
483
  }
329
484
  /**
485
+ * Answer a parked question set. An omitted question takes the request's own pre-picked default —
486
+ * resolved by the LOOP against the request it already holds, so "the user just submitted" and
487
+ * "the user picked exactly the defaults" persist as the same answers, and no client has to
488
+ * re-send what it was shown.
489
+ */
490
+ async answer(actor, toolCallId2, answers2 = {}) {
491
+ await this.assertOwnsToolCall(actor, toolCallId2);
492
+ const reply = {
493
+ answers: answers2,
494
+ answeredByRef: actor.id
495
+ };
496
+ return this.signalToolCall(toolCallId2, reply);
497
+ }
498
+ /**
499
+ * Decline to answer and let the agent proceed on its own assumptions. NOT the same as confirming
500
+ * them: the run records this as a rejection, so a reader auditing what the agent was told can
501
+ * tell a choice the user made from one they refused to make.
502
+ */
503
+ async skip(actor, toolCallId2) {
504
+ await this.assertOwnsToolCall(actor, toolCallId2);
505
+ const reply = {
506
+ answers: {},
507
+ skipped: true,
508
+ answeredByRef: actor.id
509
+ };
510
+ return this.signalToolCall(toolCallId2, reply);
511
+ }
512
+ /**
330
513
  * The decision core behind approve/reject, WITHOUT an ownership check: resolves the run
331
514
  * currently awaiting `toolCallId` and signals it. `approve`/`reject` above call this after their
332
515
  * own `assertOwnsToolCall` gate; the console `AgentApprovalPort` adapter (bound by `AgentModule`)
@@ -334,9 +517,9 @@ var AgentService = class {
334
517
  * re-deriving thread ownership here would reject a legitimate operator decision (an operator is
335
518
  * not the thread's own actor).
336
519
  */
337
- async signalToolCall(toolCallId, decision) {
338
- const runId = await this.resolveRunForToolCall(toolCallId);
339
- return this.runner.signal(runId, toolCallId, decision);
520
+ async signalToolCall(toolCallId2, reply) {
521
+ const runId = await this.resolveRunForToolCall(toolCallId2);
522
+ return this.runner.signal(runId, toolCallId2, reply);
340
523
  }
341
524
  async cancel(actor, runId) {
342
525
  await this.assertOwnsActiveStream(actor, runId);
@@ -403,20 +586,33 @@ var AgentService = class {
403
586
  /**
404
587
  * Agent-selection precedence for a `chat()` call with no explicit `agentName`: the thread's own
405
588
  * `defaultAgent` (if the thread exists and one is set) wins over the module's configured default.
406
- * Skips the thread lookup entirely when the caller already named an agent or there's no thread yet.
589
+ * Skips the store entirely when the caller already named an agent or there's no thread yet.
590
+ *
591
+ * What this needs is one nullable scalar, so it asks for one. `getThread` returns the entire
592
+ * transcript — every message, every persisted tool output — and this discards all of it; on a
593
+ * long thread with large tool results that is hundreds of kilobytes read per turn, outside the
594
+ * workflow, for a string. A store predating {@link ThreadDefaultAgentReader} still answers, via
595
+ * the full read.
407
596
  */
408
597
  async resolveAgentName(agentName, threadId) {
409
598
  if (agentName !== void 0) {
410
599
  return agentName;
411
600
  }
412
601
  if (threadId !== void 0) {
413
- const thread = await this.store.getThread(threadId);
414
- if (thread?.defaultAgent !== void 0 && thread.defaultAgent !== null) {
415
- return thread.defaultAgent;
602
+ const threadDefault = await this.threadDefaultAgent(threadId);
603
+ if (threadDefault !== null) {
604
+ return threadDefault;
416
605
  }
417
606
  }
418
607
  return this.deps.defaultAgentName();
419
608
  }
609
+ async threadDefaultAgent(threadId) {
610
+ const projecting = this.store;
611
+ if (typeof projecting.defaultAgentForThread === "function") {
612
+ return projecting.defaultAgentForThread(threadId);
613
+ }
614
+ return (await this.store.getThread(threadId))?.defaultAgent ?? null;
615
+ }
420
616
  async toSummaryView(thread) {
421
617
  return {
422
618
  ...thread,
@@ -448,6 +644,67 @@ var AgentService = class {
448
644
  return this.store.truncateFrom(threadId, messageId);
449
645
  }
450
646
  /**
647
+ * Every file this actor has staged, newest first — across threads, including uploads that were
648
+ * never sent, which nothing else on this surface can see.
649
+ *
650
+ * Metadata only. A url is minted per turn by `resolve` so it can be short-lived, and handing one
651
+ * back per entry would undo that for the price of rendering a list.
652
+ */
653
+ async listAttachments(actor, options = {}) {
654
+ const list = this.attachmentInventory();
655
+ return list({
656
+ actor,
657
+ ...options.limit !== void 0 ? {
658
+ limit: options.limit
659
+ } : {}
660
+ });
661
+ }
662
+ /**
663
+ * This actor's staged media that no live message references and that is old enough not to be an
664
+ * upload in flight — the candidate set for a sweep. Returns them; never deletes them. The bytes
665
+ * are the host's, and so is the decision.
666
+ *
667
+ * `olderThan` is required and has no default. How long a composer may sit open with a file
668
+ * attached is the host's knowledge, and a library-chosen grace period would eventually delete a
669
+ * file someone was about to send. The staging store is asked to apply it, and the result is
670
+ * filtered again here: a store that ignores the hint would otherwise turn this into exactly that
671
+ * bug, silently.
672
+ *
673
+ * Both halves must be answerable or this refuses. An unanswerable reference query means "cannot
674
+ * tell", and treating it as "nothing is referenced" would hand back every attachment the actor
675
+ * ever sent, marked safe to delete.
676
+ */
677
+ async collectableAttachments(actor, options) {
678
+ const list = this.attachmentInventory();
679
+ const referencedMediaIds = this.store.referencedMediaIds?.bind(this.store);
680
+ if (referencedMediaIds === void 0) {
681
+ throw new import_common2.NotImplementedException("Collecting attachments requires an AgentStore that implements referencedMediaIds(); the bound store cannot say which media a message still references, and guessing would delete files that are in use.");
682
+ }
683
+ const stagedBefore = options.olderThan.toISOString();
684
+ const inventory = await list({
685
+ actor,
686
+ stagedBefore,
687
+ ...options.limit !== void 0 ? {
688
+ limit: options.limit
689
+ } : {}
690
+ });
691
+ const aged = inventory.filter((entry) => entry.createdAt < stagedBefore);
692
+ const referenced = new Set(await referencedMediaIds(actor.id, aged.map((entry) => entry.mediaId)));
693
+ return aged.filter((entry) => !referenced.has(entry.mediaId));
694
+ }
695
+ /**
696
+ * The bound staging store's `list`, or a refusal. Absence is never answered with an empty list:
697
+ * "this host keeps no inventory" and "this actor has no files" are opposite facts that would
698
+ * otherwise render identically — as a clean file list, and as a sweep that collects nothing.
699
+ */
700
+ attachmentInventory() {
701
+ const list = this.staging?.list?.bind(this.staging);
702
+ if (list === void 0) {
703
+ throw new import_common2.NotImplementedException("Listing attachments requires an AGENT_ATTACHMENT_STAGING provider implementing list(); the host owns the staged bytes, so only it can enumerate them.");
704
+ }
705
+ return list;
706
+ }
707
+ /**
451
708
  * The day's usage for the badge: tokens + summed USD cost from the store, and the configured
452
709
  * limit from the quota store (null → unlimited). `withinLimit` comes from the quota store so it
453
710
  * can never drift from what enforcement uses.
@@ -489,24 +746,26 @@ var AgentService = class {
489
746
  * out from run resolution (see {@link resolveRunForToolCall}) so the console `AgentApprovalPort`
490
747
  * adapter can resolve+signal a decision WITHOUT this check — it is authorized upstream instead.
491
748
  */
492
- async assertOwnsToolCall(actor, toolCallId) {
493
- const owner = await this.store.ownerOfToolCall(toolCallId);
749
+ async assertOwnsToolCall(actor, toolCallId2) {
750
+ const owner = await this.store.ownerOfToolCall(toolCallId2);
494
751
  if (owner === null) {
495
- throw new import_common2.NotFoundException(`tool call ${toolCallId} not found`);
752
+ throw new import_common2.NotFoundException(`tool call ${toolCallId2} not found`);
496
753
  }
497
754
  if (owner !== actor.id) {
498
755
  throw new import_common2.ForbiddenException("tool call belongs to another actor");
499
756
  }
500
757
  }
501
758
  /**
502
- * Resolve the run currently awaiting `toolCallId` (its thread's active stream). That run is the
503
- * sub-agent's own child run when the pending call belongs to a delegated agent — the client never
504
- * knows or supplies a runId; it is derived here from the tool call alone.
759
+ * Resolve the run awaiting `toolCallId`. Derived server-side from the tool call alone — the client
760
+ * never knows or supplies a runId, and that run is the sub-agent's own child run when the pending
761
+ * call belongs to a delegated agent. The store answers from the CALL'S OWN `runId` where it has
762
+ * one; see `AgentStore.runForToolCall` for why that matters once a thread can hold more than one
763
+ * live run.
505
764
  */
506
- async resolveRunForToolCall(toolCallId) {
507
- const runId = await this.store.runForToolCall(toolCallId);
765
+ async resolveRunForToolCall(toolCallId2) {
766
+ const runId = await this.store.runForToolCall(toolCallId2);
508
767
  if (runId === null) {
509
- throw new import_common2.NotFoundException(`tool call ${toolCallId} has no active run to signal`);
768
+ throw new import_common2.NotFoundException(`tool call ${toolCallId2} has no active run to signal`);
510
769
  }
511
770
  return runId;
512
771
  }
@@ -527,12 +786,15 @@ AgentService = _ts_decorate2([
527
786
  _ts_param2(1, (0, import_common2.Inject)(import_nestjs_agent_core3.AGENT_STORE)),
528
787
  _ts_param2(2, (0, import_common2.Inject)(import_nestjs_agent_core3.AGENT_DEPS_FACTORY)),
529
788
  _ts_param2(3, (0, import_common2.Inject)(import_nestjs_agent_core3.AGENT_QUOTA_STORE)),
789
+ _ts_param2(4, (0, import_common2.Optional)()),
790
+ _ts_param2(4, (0, import_common2.Inject)(import_nestjs_agent_core3.AGENT_ATTACHMENT_STAGING)),
530
791
  _ts_metadata2("design:type", Function),
531
792
  _ts_metadata2("design:paramtypes", [
532
793
  typeof AgentRunner === "undefined" ? Object : AgentRunner,
533
794
  typeof AgentStore === "undefined" ? Object : AgentStore,
534
795
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
535
- Object
796
+ Object,
797
+ typeof AttachmentStagingStore === "undefined" ? Object : AttachmentStagingStore
536
798
  ])
537
799
  ], AgentService);
538
800
 
@@ -557,16 +819,16 @@ var AgentApprovalPortAdapter = class {
557
819
  constructor(agent) {
558
820
  this.agent = agent;
559
821
  }
560
- async approve(toolCallId, opts) {
561
- await this.agent.signalToolCall(toolCallId, {
822
+ async approve(toolCallId2, opts) {
823
+ await this.agent.signalToolCall(toolCallId2, {
562
824
  approved: true,
563
825
  ...opts?.executedByRef !== void 0 ? {
564
826
  executedByRef: opts.executedByRef
565
827
  } : {}
566
828
  });
567
829
  }
568
- async reject(toolCallId, opts) {
569
- await this.agent.signalToolCall(toolCallId, {
830
+ async reject(toolCallId2, opts) {
831
+ await this.agent.signalToolCall(toolCallId2, {
570
832
  approved: false,
571
833
  ...opts?.executedByRef !== void 0 ? {
572
834
  executedByRef: opts.executedByRef
@@ -665,6 +927,8 @@ function _ts_param4(paramIndex, decorator) {
665
927
  }
666
928
  __name(_ts_param4, "_ts_param");
667
929
  var DEFAULT_MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024;
930
+ var HARD_MAX_ATTACHMENT_BYTES = 32 * 1024 * 1024;
931
+ var ATTACHMENT_PAGE_SIZE = 50;
668
932
  var DEFAULT_ALLOWED_ATTACHMENT_CONTENT_TYPES = [
669
933
  "image/png",
670
934
  "image/jpeg",
@@ -680,10 +944,12 @@ var AttachmentsController = class {
680
944
  }
681
945
  options;
682
946
  actorResolver;
947
+ agents;
683
948
  staging;
684
- constructor(options, actorResolver, staging) {
949
+ constructor(options, actorResolver, agents, staging) {
685
950
  this.options = options;
686
951
  this.actorResolver = actorResolver;
952
+ this.agents = agents;
687
953
  this.staging = staging;
688
954
  }
689
955
  /**
@@ -697,6 +963,21 @@ var AttachmentsController = class {
697
963
  throw new Error("AgentModule: attachments.upload is true but no AGENT_ATTACHMENT_STAGING provider is bound. Bind one (e.g. `{ provide: AGENT_ATTACHMENT_STAGING, useClass: MyStagingStore }`) in a module imported alongside AgentModule, or set attachments.upload to false.");
698
964
  }
699
965
  }
966
+ /**
967
+ * The caller's own staged files, newest first — the one question `GET /agent/threads/:id` cannot
968
+ * answer, since an upload that was never sent belongs to no thread.
969
+ *
970
+ * Scoped by the RESOLVED actor and nothing else. There is deliberately no `threadId` filter: a
971
+ * thread's attachments already ride on its messages in the thread payload, and re-serving them
972
+ * from here would add a second ownership path to get wrong for information the client already
973
+ * holds. Metadata only — see {@link StagedAttachment}.
974
+ */
975
+ async list(req) {
976
+ const actor = await this.actorResolver.resolve(req);
977
+ return this.agents.listAttachments(actor, {
978
+ limit: ATTACHMENT_PAGE_SIZE
979
+ });
980
+ }
700
981
  async upload(req, file) {
701
982
  if (this.staging === void 0) {
702
983
  throw new import_common5.NotImplementedException("Attachment upload is not configured on this server.");
@@ -722,9 +1003,22 @@ var AttachmentsController = class {
722
1003
  });
723
1004
  }
724
1005
  };
1006
+ _ts_decorate5([
1007
+ (0, import_common5.Get)(),
1008
+ _ts_param4(0, (0, import_common5.Req)()),
1009
+ _ts_metadata5("design:type", Function),
1010
+ _ts_metadata5("design:paramtypes", [
1011
+ typeof Request === "undefined" ? Object : Request
1012
+ ]),
1013
+ _ts_metadata5("design:returntype", Promise)
1014
+ ], AttachmentsController.prototype, "list", null);
725
1015
  _ts_decorate5([
726
1016
  (0, import_common5.Post)(),
727
- (0, import_common5.UseInterceptors)((0, import_platform_express.FileInterceptor)("file")),
1017
+ (0, import_common5.UseInterceptors)((0, import_platform_express.FileInterceptor)("file", {
1018
+ limits: {
1019
+ fileSize: HARD_MAX_ATTACHMENT_BYTES
1020
+ }
1021
+ })),
728
1022
  _ts_param4(0, (0, import_common5.Req)()),
729
1023
  _ts_param4(1, (0, import_common5.UploadedFile)()),
730
1024
  _ts_metadata5("design:type", Function),
@@ -738,12 +1032,13 @@ AttachmentsController = _ts_decorate5([
738
1032
  (0, import_common5.Controller)("attachments"),
739
1033
  _ts_param4(0, (0, import_common5.Inject)(import_nestjs_agent_core5.AGENT_OPTIONS)),
740
1034
  _ts_param4(1, (0, import_common5.Inject)(import_nestjs_agent_core5.AGENT_ACTOR_RESOLVER)),
741
- _ts_param4(2, (0, import_common5.Optional)()),
742
- _ts_param4(2, (0, import_common5.Inject)(import_nestjs_agent_core5.AGENT_ATTACHMENT_STAGING)),
1035
+ _ts_param4(3, (0, import_common5.Optional)()),
1036
+ _ts_param4(3, (0, import_common5.Inject)(import_nestjs_agent_core5.AGENT_ATTACHMENT_STAGING)),
743
1037
  _ts_metadata5("design:type", Function),
744
1038
  _ts_metadata5("design:paramtypes", [
745
1039
  typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions,
746
1040
  typeof ActorResolver === "undefined" ? Object : ActorResolver,
1041
+ typeof AgentService === "undefined" ? Object : AgentService,
747
1042
  Object
748
1043
  ])
749
1044
  ], AttachmentsController);
@@ -768,6 +1063,31 @@ function _ts_param5(paramIndex, decorator) {
768
1063
  };
769
1064
  }
770
1065
  __name(_ts_param5, "_ts_param");
1066
+ var MAX_ATTACHMENTS_PER_MESSAGE = 10;
1067
+ function attachmentRefs(claimed) {
1068
+ if (claimed === void 0) {
1069
+ return [];
1070
+ }
1071
+ if (!Array.isArray(claimed)) {
1072
+ throw new import_common6.BadRequestException("attachments must be an array of { mediaId }");
1073
+ }
1074
+ if (claimed.length > MAX_ATTACHMENTS_PER_MESSAGE) {
1075
+ throw new import_common6.BadRequestException(`a message may carry at most ${MAX_ATTACHMENTS_PER_MESSAGE} attachments`);
1076
+ }
1077
+ return claimed.map((entry) => {
1078
+ if (typeof entry !== "object" || entry === null || !("mediaId" in entry)) {
1079
+ throw new import_common6.BadRequestException("each attachment must be an object with a mediaId");
1080
+ }
1081
+ const { mediaId } = entry;
1082
+ if (typeof mediaId !== "string" || mediaId.length === 0) {
1083
+ throw new import_common6.BadRequestException("each attachment must carry a non-empty string mediaId");
1084
+ }
1085
+ return {
1086
+ mediaId
1087
+ };
1088
+ });
1089
+ }
1090
+ __name(attachmentRefs, "attachmentRefs");
771
1091
  var ChatController = class {
772
1092
  static {
773
1093
  __name(this, "ChatController");
@@ -780,6 +1100,7 @@ var ChatController = class {
780
1100
  }
781
1101
  async chat(req, res, body) {
782
1102
  const actor = await this.actorResolver.resolve(req);
1103
+ const attachments = attachmentRefs(body.attachments);
783
1104
  const { runId, threadId } = await this.agent.chat({
784
1105
  actor,
785
1106
  message: body.message,
@@ -789,8 +1110,8 @@ var ChatController = class {
789
1110
  ...body.agent !== void 0 ? {
790
1111
  agentName: body.agent
791
1112
  } : {},
792
- ...body.attachments !== void 0 ? {
793
- attachments: body.attachments
1113
+ ...attachments.length > 0 ? {
1114
+ attachments
794
1115
  } : {},
795
1116
  ...body.pageContext !== void 0 ? {
796
1117
  pageContext: body.pageContext
@@ -802,10 +1123,11 @@ var ChatController = class {
802
1123
  transient: true
803
1124
  } : {}
804
1125
  });
805
- await this.pipe(res, runId, threadId);
1126
+ await this.pipe(res, runId, this.agent.subscribe(runId), threadId);
806
1127
  }
807
- async stream(runId, res) {
808
- await this.pipe(res, runId);
1128
+ async stream(req, runId, res) {
1129
+ const actor = await this.actorResolver.resolve(req);
1130
+ await this.pipe(res, runId, await this.agent.subscribeAs(actor, runId));
809
1131
  }
810
1132
  async cancel(req, runId) {
811
1133
  const actor = await this.actorResolver.resolve(req);
@@ -814,7 +1136,7 @@ var ChatController = class {
814
1136
  aborted: true
815
1137
  };
816
1138
  }
817
- async pipe(res, runId, threadId) {
1139
+ async pipe(res, runId, events, threadId) {
818
1140
  res.setHeader("Content-Type", "text/event-stream");
819
1141
  res.setHeader("Cache-Control", "no-cache");
820
1142
  res.setHeader("Connection", "keep-alive");
@@ -832,7 +1154,7 @@ data: ${JSON.stringify({
832
1154
  const decoder = new TextDecoder();
833
1155
  let buffer = "";
834
1156
  try {
835
- for await (const chunk of this.agent.subscribe(runId)) {
1157
+ for await (const chunk of events) {
836
1158
  buffer += decoder.decode(chunk, {
837
1159
  stream: true
838
1160
  });
@@ -885,10 +1207,12 @@ _ts_decorate6([
885
1207
  ], ChatController.prototype, "chat", null);
886
1208
  _ts_decorate6([
887
1209
  (0, import_common6.Get)("chat/:runId/stream"),
888
- _ts_param5(0, (0, import_common6.Param)("runId")),
889
- _ts_param5(1, (0, import_common6.Res)()),
1210
+ _ts_param5(0, (0, import_common6.Req)()),
1211
+ _ts_param5(1, (0, import_common6.Param)("runId")),
1212
+ _ts_param5(2, (0, import_common6.Res)()),
890
1213
  _ts_metadata6("design:type", Function),
891
1214
  _ts_metadata6("design:paramtypes", [
1215
+ typeof Request === "undefined" ? Object : Request,
892
1216
  String,
893
1217
  typeof Response === "undefined" ? Object : Response
894
1218
  ]),
@@ -915,7 +1239,7 @@ ChatController = _ts_decorate6([
915
1239
  ])
916
1240
  ], ChatController);
917
1241
 
918
- // src/controller/quota.controller.ts
1242
+ // src/controller/memories.controller.ts
919
1243
  var import_nestjs_agent_core7 = require("@dudousxd/nestjs-agent-core");
920
1244
  var import_common7 = require("@nestjs/common");
921
1245
  function _ts_decorate7(decorators, target, key, desc) {
@@ -935,41 +1259,113 @@ function _ts_param6(paramIndex, decorator) {
935
1259
  };
936
1260
  }
937
1261
  __name(_ts_param6, "_ts_param");
938
- var QuotaController = class {
1262
+ var MemoriesController = class {
939
1263
  static {
940
- __name(this, "QuotaController");
1264
+ __name(this, "MemoriesController");
941
1265
  }
942
- agent;
943
1266
  actorResolver;
944
- constructor(agent, actorResolver) {
945
- this.agent = agent;
1267
+ memory;
1268
+ constructor(actorResolver, memory) {
946
1269
  this.actorResolver = actorResolver;
1270
+ this.memory = memory;
947
1271
  }
948
- async today(req) {
1272
+ /**
1273
+ * Every memory this actor can reach, most specific first, each carrying its origin and whatever
1274
+ * wider value it outranks.
1275
+ *
1276
+ * DELIBERATELY IGNORES `maxMemories`. That ceiling is a budget on what one TURN carries; applying
1277
+ * it here would mean a person could not see — and so could not delete — a belief the assistant is
1278
+ * one write away from acting on again. Showing someone more than the model sees is harmless;
1279
+ * showing them less is the failure this endpoint exists to prevent.
1280
+ */
1281
+ async list(req, threadId) {
1282
+ if (this.memory === void 0) {
1283
+ return [];
1284
+ }
949
1285
  const actor = await this.actorResolver.resolve(req);
950
- return this.agent.quotaToday(actor.id);
1286
+ return (await this.unbounded(threadId ?? "", actor)).entries;
1287
+ }
1288
+ /**
1289
+ * Forget one. Authorized against the actor's OWN resolved list, the same way a `skill` load is
1290
+ * authorized against the turn's catalog: an id this actor cannot see is answered as missing rather
1291
+ * than refused, so the endpoint cannot be used to find out which memories exist about other people.
1292
+ */
1293
+ async forget(req, id) {
1294
+ if (this.memory === void 0) {
1295
+ throw new import_common7.NotFoundException("No memory is configured in this deployment.");
1296
+ }
1297
+ const actor = await this.actorResolver.resolve(req);
1298
+ const digest = await this.unbounded("", actor);
1299
+ const entry = digest.entries.find((candidate) => candidate.id === id);
1300
+ if (entry === void 0) {
1301
+ throw new import_common7.NotFoundException(`No memory with id "${id}".`);
1302
+ }
1303
+ const verdict = (0, import_nestjs_agent_core7.memoryForgetVerdict)({
1304
+ record: entry,
1305
+ actor
1306
+ });
1307
+ if (!verdict.allowed) {
1308
+ throw new import_common7.ForbiddenException(verdict.reason);
1309
+ }
1310
+ return {
1311
+ forgotten: await this.memory.provider.forget({
1312
+ id: entry.id,
1313
+ ctx: {
1314
+ actor,
1315
+ threadId: ""
1316
+ }
1317
+ })
1318
+ };
1319
+ }
1320
+ async unbounded(threadId, actor) {
1321
+ const config = this.memory;
1322
+ return await (0, import_nestjs_agent_core7.offerMemories)({
1323
+ config: {
1324
+ ...config,
1325
+ maxMemories: Number.POSITIVE_INFINITY
1326
+ },
1327
+ ctx: {
1328
+ actor,
1329
+ threadId
1330
+ }
1331
+ });
951
1332
  }
952
1333
  };
953
1334
  _ts_decorate7([
954
- (0, import_common7.Get)("today"),
1335
+ (0, import_common7.Get)(),
955
1336
  _ts_param6(0, (0, import_common7.Req)()),
1337
+ _ts_param6(1, (0, import_common7.Query)("threadId")),
956
1338
  _ts_metadata7("design:type", Function),
957
1339
  _ts_metadata7("design:paramtypes", [
958
- typeof Request === "undefined" ? Object : Request
1340
+ typeof Request === "undefined" ? Object : Request,
1341
+ String
959
1342
  ]),
960
1343
  _ts_metadata7("design:returntype", Promise)
961
- ], QuotaController.prototype, "today", null);
962
- QuotaController = _ts_decorate7([
963
- (0, import_common7.Controller)("quota"),
964
- _ts_param6(1, (0, import_common7.Inject)(import_nestjs_agent_core7.AGENT_ACTOR_RESOLVER)),
1344
+ ], MemoriesController.prototype, "list", null);
1345
+ _ts_decorate7([
1346
+ (0, import_common7.Delete)(":id"),
1347
+ _ts_param6(0, (0, import_common7.Req)()),
1348
+ _ts_param6(1, (0, import_common7.Param)("id")),
965
1349
  _ts_metadata7("design:type", Function),
966
1350
  _ts_metadata7("design:paramtypes", [
967
- typeof AgentService === "undefined" ? Object : AgentService,
968
- typeof ActorResolver === "undefined" ? Object : ActorResolver
1351
+ typeof Request === "undefined" ? Object : Request,
1352
+ String
1353
+ ]),
1354
+ _ts_metadata7("design:returntype", Promise)
1355
+ ], MemoriesController.prototype, "forget", null);
1356
+ MemoriesController = _ts_decorate7([
1357
+ (0, import_common7.Controller)("memories"),
1358
+ _ts_param6(0, (0, import_common7.Inject)(import_nestjs_agent_core7.AGENT_ACTOR_RESOLVER)),
1359
+ _ts_param6(1, (0, import_common7.Optional)()),
1360
+ _ts_param6(1, (0, import_common7.Inject)(import_nestjs_agent_core7.AGENT_MEMORY)),
1361
+ _ts_metadata7("design:type", Function),
1362
+ _ts_metadata7("design:paramtypes", [
1363
+ typeof ActorResolver === "undefined" ? Object : ActorResolver,
1364
+ Object
969
1365
  ])
970
- ], QuotaController);
1366
+ ], MemoriesController);
971
1367
 
972
- // src/controller/threads.controller.ts
1368
+ // src/controller/quota.controller.ts
973
1369
  var import_nestjs_agent_core8 = require("@dudousxd/nestjs-agent-core");
974
1370
  var import_common8 = require("@nestjs/common");
975
1371
  function _ts_decorate8(decorators, target, key, desc) {
@@ -989,6 +1385,125 @@ function _ts_param7(paramIndex, decorator) {
989
1385
  };
990
1386
  }
991
1387
  __name(_ts_param7, "_ts_param");
1388
+ var QuotaController = class {
1389
+ static {
1390
+ __name(this, "QuotaController");
1391
+ }
1392
+ agent;
1393
+ actorResolver;
1394
+ constructor(agent, actorResolver) {
1395
+ this.agent = agent;
1396
+ this.actorResolver = actorResolver;
1397
+ }
1398
+ async today(req) {
1399
+ const actor = await this.actorResolver.resolve(req);
1400
+ return this.agent.quotaToday(actor.id);
1401
+ }
1402
+ };
1403
+ _ts_decorate8([
1404
+ (0, import_common8.Get)("today"),
1405
+ _ts_param7(0, (0, import_common8.Req)()),
1406
+ _ts_metadata8("design:type", Function),
1407
+ _ts_metadata8("design:paramtypes", [
1408
+ typeof Request === "undefined" ? Object : Request
1409
+ ]),
1410
+ _ts_metadata8("design:returntype", Promise)
1411
+ ], QuotaController.prototype, "today", null);
1412
+ QuotaController = _ts_decorate8([
1413
+ (0, import_common8.Controller)("quota"),
1414
+ _ts_param7(1, (0, import_common8.Inject)(import_nestjs_agent_core8.AGENT_ACTOR_RESOLVER)),
1415
+ _ts_metadata8("design:type", Function),
1416
+ _ts_metadata8("design:paramtypes", [
1417
+ typeof AgentService === "undefined" ? Object : AgentService,
1418
+ typeof ActorResolver === "undefined" ? Object : ActorResolver
1419
+ ])
1420
+ ], QuotaController);
1421
+
1422
+ // src/controller/skills.controller.ts
1423
+ var import_nestjs_agent_core9 = require("@dudousxd/nestjs-agent-core");
1424
+ var import_common9 = require("@nestjs/common");
1425
+ function _ts_decorate9(decorators, target, key, desc) {
1426
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1427
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1428
+ 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;
1429
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1430
+ }
1431
+ __name(_ts_decorate9, "_ts_decorate");
1432
+ function _ts_metadata9(k, v) {
1433
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1434
+ }
1435
+ __name(_ts_metadata9, "_ts_metadata");
1436
+ function _ts_param8(paramIndex, decorator) {
1437
+ return function(target, key) {
1438
+ decorator(target, key, paramIndex);
1439
+ };
1440
+ }
1441
+ __name(_ts_param8, "_ts_param");
1442
+ var SkillsController = class {
1443
+ static {
1444
+ __name(this, "SkillsController");
1445
+ }
1446
+ actorResolver;
1447
+ skills;
1448
+ constructor(actorResolver, skills) {
1449
+ this.actorResolver = actorResolver;
1450
+ this.skills = skills;
1451
+ }
1452
+ async list(req, threadId) {
1453
+ if (this.skills === void 0) {
1454
+ return [];
1455
+ }
1456
+ const actor = await this.actorResolver.resolve(req);
1457
+ const offer = await (0, import_nestjs_agent_core9.offerSkills)(this.skills, {
1458
+ actor,
1459
+ threadId: threadId ?? ""
1460
+ });
1461
+ return offer.entries;
1462
+ }
1463
+ };
1464
+ _ts_decorate9([
1465
+ (0, import_common9.Get)(),
1466
+ _ts_param8(0, (0, import_common9.Req)()),
1467
+ _ts_param8(1, (0, import_common9.Query)("threadId")),
1468
+ _ts_metadata9("design:type", Function),
1469
+ _ts_metadata9("design:paramtypes", [
1470
+ typeof Request === "undefined" ? Object : Request,
1471
+ String
1472
+ ]),
1473
+ _ts_metadata9("design:returntype", Promise)
1474
+ ], SkillsController.prototype, "list", null);
1475
+ SkillsController = _ts_decorate9([
1476
+ (0, import_common9.Controller)("skills"),
1477
+ _ts_param8(0, (0, import_common9.Inject)(import_nestjs_agent_core9.AGENT_ACTOR_RESOLVER)),
1478
+ _ts_param8(1, (0, import_common9.Optional)()),
1479
+ _ts_param8(1, (0, import_common9.Inject)(import_nestjs_agent_core9.AGENT_SKILLS)),
1480
+ _ts_metadata9("design:type", Function),
1481
+ _ts_metadata9("design:paramtypes", [
1482
+ typeof ActorResolver === "undefined" ? Object : ActorResolver,
1483
+ Object
1484
+ ])
1485
+ ], SkillsController);
1486
+
1487
+ // src/controller/threads.controller.ts
1488
+ var import_nestjs_agent_core10 = require("@dudousxd/nestjs-agent-core");
1489
+ var import_common10 = require("@nestjs/common");
1490
+ function _ts_decorate10(decorators, target, key, desc) {
1491
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1492
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1493
+ 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;
1494
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1495
+ }
1496
+ __name(_ts_decorate10, "_ts_decorate");
1497
+ function _ts_metadata10(k, v) {
1498
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1499
+ }
1500
+ __name(_ts_metadata10, "_ts_metadata");
1501
+ function _ts_param9(paramIndex, decorator) {
1502
+ return function(target, key) {
1503
+ decorator(target, key, paramIndex);
1504
+ };
1505
+ }
1506
+ __name(_ts_param9, "_ts_param");
992
1507
  var ThreadsController = class {
993
1508
  static {
994
1509
  __name(this, "ThreadsController");
@@ -1052,117 +1567,173 @@ var ThreadsController = class {
1052
1567
  };
1053
1568
  }
1054
1569
  };
1055
- _ts_decorate8([
1056
- (0, import_common8.Get)(),
1057
- _ts_param7(0, (0, import_common8.Req)()),
1058
- _ts_metadata8("design:type", Function),
1059
- _ts_metadata8("design:paramtypes", [
1570
+ _ts_decorate10([
1571
+ (0, import_common10.Get)(),
1572
+ _ts_param9(0, (0, import_common10.Req)()),
1573
+ _ts_metadata10("design:type", Function),
1574
+ _ts_metadata10("design:paramtypes", [
1060
1575
  typeof Request === "undefined" ? Object : Request
1061
1576
  ]),
1062
- _ts_metadata8("design:returntype", Promise)
1577
+ _ts_metadata10("design:returntype", Promise)
1063
1578
  ], ThreadsController.prototype, "list", null);
1064
- _ts_decorate8([
1065
- (0, import_common8.Get)(":id"),
1066
- _ts_param7(0, (0, import_common8.Req)()),
1067
- _ts_param7(1, (0, import_common8.Param)("id")),
1068
- _ts_metadata8("design:type", Function),
1069
- _ts_metadata8("design:paramtypes", [
1070
- typeof Request === "undefined" ? Object : Request,
1579
+ _ts_decorate10([
1580
+ (0, import_common10.Get)(":id"),
1581
+ _ts_param9(0, (0, import_common10.Req)()),
1582
+ _ts_param9(1, (0, import_common10.Param)("id")),
1583
+ _ts_metadata10("design:type", Function),
1584
+ _ts_metadata10("design:paramtypes", [
1585
+ typeof Request === "undefined" ? Object : Request,
1071
1586
  String
1072
1587
  ]),
1073
- _ts_metadata8("design:returntype", Promise)
1588
+ _ts_metadata10("design:returntype", Promise)
1074
1589
  ], ThreadsController.prototype, "detail", null);
1075
- _ts_decorate8([
1076
- (0, import_common8.Delete)(":id"),
1077
- _ts_param7(0, (0, import_common8.Req)()),
1078
- _ts_param7(1, (0, import_common8.Param)("id")),
1079
- _ts_metadata8("design:type", Function),
1080
- _ts_metadata8("design:paramtypes", [
1590
+ _ts_decorate10([
1591
+ (0, import_common10.Delete)(":id"),
1592
+ _ts_param9(0, (0, import_common10.Req)()),
1593
+ _ts_param9(1, (0, import_common10.Param)("id")),
1594
+ _ts_metadata10("design:type", Function),
1595
+ _ts_metadata10("design:paramtypes", [
1081
1596
  typeof Request === "undefined" ? Object : Request,
1082
1597
  String
1083
1598
  ]),
1084
- _ts_metadata8("design:returntype", Promise)
1599
+ _ts_metadata10("design:returntype", Promise)
1085
1600
  ], ThreadsController.prototype, "remove", null);
1086
- _ts_decorate8([
1087
- (0, import_common8.Post)(":id/fork-from/:messageId"),
1088
- _ts_param7(0, (0, import_common8.Req)()),
1089
- _ts_param7(1, (0, import_common8.Param)("id")),
1090
- _ts_param7(2, (0, import_common8.Param)("messageId")),
1091
- _ts_metadata8("design:type", Function),
1092
- _ts_metadata8("design:paramtypes", [
1601
+ _ts_decorate10([
1602
+ (0, import_common10.Post)(":id/fork-from/:messageId"),
1603
+ _ts_param9(0, (0, import_common10.Req)()),
1604
+ _ts_param9(1, (0, import_common10.Param)("id")),
1605
+ _ts_param9(2, (0, import_common10.Param)("messageId")),
1606
+ _ts_metadata10("design:type", Function),
1607
+ _ts_metadata10("design:paramtypes", [
1093
1608
  typeof Request === "undefined" ? Object : Request,
1094
1609
  String,
1095
1610
  String
1096
1611
  ]),
1097
- _ts_metadata8("design:returntype", Promise)
1612
+ _ts_metadata10("design:returntype", Promise)
1098
1613
  ], ThreadsController.prototype, "fork", null);
1099
- _ts_decorate8([
1100
- (0, import_common8.Patch)(":id"),
1101
- _ts_param7(0, (0, import_common8.Req)()),
1102
- _ts_param7(1, (0, import_common8.Param)("id")),
1103
- _ts_param7(2, (0, import_common8.Body)()),
1104
- _ts_metadata8("design:type", Function),
1105
- _ts_metadata8("design:paramtypes", [
1614
+ _ts_decorate10([
1615
+ (0, import_common10.Patch)(":id"),
1616
+ _ts_param9(0, (0, import_common10.Req)()),
1617
+ _ts_param9(1, (0, import_common10.Param)("id")),
1618
+ _ts_param9(2, (0, import_common10.Body)()),
1619
+ _ts_metadata10("design:type", Function),
1620
+ _ts_metadata10("design:paramtypes", [
1106
1621
  typeof Request === "undefined" ? Object : Request,
1107
1622
  String,
1108
1623
  typeof UpdateThreadBody === "undefined" ? Object : UpdateThreadBody
1109
1624
  ]),
1110
- _ts_metadata8("design:returntype", Promise)
1625
+ _ts_metadata10("design:returntype", Promise)
1111
1626
  ], ThreadsController.prototype, "update", null);
1112
- _ts_decorate8([
1113
- (0, import_common8.Post)(":id/promote"),
1114
- _ts_param7(0, (0, import_common8.Req)()),
1115
- _ts_param7(1, (0, import_common8.Param)("id")),
1116
- _ts_metadata8("design:type", Function),
1117
- _ts_metadata8("design:paramtypes", [
1627
+ _ts_decorate10([
1628
+ (0, import_common10.Post)(":id/promote"),
1629
+ _ts_param9(0, (0, import_common10.Req)()),
1630
+ _ts_param9(1, (0, import_common10.Param)("id")),
1631
+ _ts_metadata10("design:type", Function),
1632
+ _ts_metadata10("design:paramtypes", [
1118
1633
  typeof Request === "undefined" ? Object : Request,
1119
1634
  String
1120
1635
  ]),
1121
- _ts_metadata8("design:returntype", Promise)
1636
+ _ts_metadata10("design:returntype", Promise)
1122
1637
  ], ThreadsController.prototype, "promote", null);
1123
- _ts_decorate8([
1124
- (0, import_common8.Delete)(":id/from/:messageId"),
1125
- _ts_param7(0, (0, import_common8.Req)()),
1126
- _ts_param7(1, (0, import_common8.Param)("id")),
1127
- _ts_param7(2, (0, import_common8.Param)("messageId")),
1128
- _ts_metadata8("design:type", Function),
1129
- _ts_metadata8("design:paramtypes", [
1638
+ _ts_decorate10([
1639
+ (0, import_common10.Delete)(":id/from/:messageId"),
1640
+ _ts_param9(0, (0, import_common10.Req)()),
1641
+ _ts_param9(1, (0, import_common10.Param)("id")),
1642
+ _ts_param9(2, (0, import_common10.Param)("messageId")),
1643
+ _ts_metadata10("design:type", Function),
1644
+ _ts_metadata10("design:paramtypes", [
1130
1645
  typeof Request === "undefined" ? Object : Request,
1131
1646
  String,
1132
1647
  String
1133
1648
  ]),
1134
- _ts_metadata8("design:returntype", Promise)
1649
+ _ts_metadata10("design:returntype", Promise)
1135
1650
  ], ThreadsController.prototype, "truncateFrom", null);
1136
- ThreadsController = _ts_decorate8([
1137
- (0, import_common8.Controller)("threads"),
1138
- _ts_param7(1, (0, import_common8.Inject)(import_nestjs_agent_core8.AGENT_ACTOR_RESOLVER)),
1139
- _ts_metadata8("design:type", Function),
1140
- _ts_metadata8("design:paramtypes", [
1651
+ ThreadsController = _ts_decorate10([
1652
+ (0, import_common10.Controller)("threads"),
1653
+ _ts_param9(1, (0, import_common10.Inject)(import_nestjs_agent_core10.AGENT_ACTOR_RESOLVER)),
1654
+ _ts_metadata10("design:type", Function),
1655
+ _ts_metadata10("design:paramtypes", [
1141
1656
  typeof AgentService === "undefined" ? Object : AgentService,
1142
1657
  typeof ActorResolver === "undefined" ? Object : ActorResolver
1143
1658
  ])
1144
1659
  ], ThreadsController);
1145
1660
 
1146
1661
  // src/controller/tool-call.controller.ts
1147
- var import_nestjs_agent_core9 = require("@dudousxd/nestjs-agent-core");
1148
- var import_common9 = require("@nestjs/common");
1149
- function _ts_decorate9(decorators, target, key, desc) {
1662
+ var import_nestjs_agent_core11 = require("@dudousxd/nestjs-agent-core");
1663
+ var import_common11 = require("@nestjs/common");
1664
+ function _ts_decorate11(decorators, target, key, desc) {
1150
1665
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1151
1666
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1152
1667
  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;
1153
1668
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1154
1669
  }
1155
- __name(_ts_decorate9, "_ts_decorate");
1156
- function _ts_metadata9(k, v) {
1670
+ __name(_ts_decorate11, "_ts_decorate");
1671
+ function _ts_metadata11(k, v) {
1157
1672
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1158
1673
  }
1159
- __name(_ts_metadata9, "_ts_metadata");
1160
- function _ts_param8(paramIndex, decorator) {
1674
+ __name(_ts_metadata11, "_ts_metadata");
1675
+ function _ts_param10(paramIndex, decorator) {
1161
1676
  return function(target, key) {
1162
1677
  decorator(target, key, paramIndex);
1163
1678
  };
1164
1679
  }
1165
- __name(_ts_param8, "_ts_param");
1680
+ __name(_ts_param10, "_ts_param");
1681
+ var MAX_ANSWERED_QUESTIONS = 100;
1682
+ var MAX_VALUES_PER_QUESTION = 100;
1683
+ var MAX_ANSWER_VALUE_LENGTH = 4096;
1684
+ var MAX_REJECT_REASON_LENGTH = 4096;
1685
+ function toolCallId(claimed) {
1686
+ if (typeof claimed !== "string" || claimed.length === 0) {
1687
+ throw new import_common11.BadRequestException("toolCallId must be a non-empty string");
1688
+ }
1689
+ return claimed;
1690
+ }
1691
+ __name(toolCallId, "toolCallId");
1692
+ function rejectReason(claimed) {
1693
+ if (claimed === void 0) {
1694
+ return void 0;
1695
+ }
1696
+ if (typeof claimed !== "string") {
1697
+ throw new import_common11.BadRequestException("reason must be a string");
1698
+ }
1699
+ if (claimed.length > MAX_REJECT_REASON_LENGTH) {
1700
+ throw new import_common11.BadRequestException(`reason must be at most ${MAX_REJECT_REASON_LENGTH} characters`);
1701
+ }
1702
+ return claimed;
1703
+ }
1704
+ __name(rejectReason, "rejectReason");
1705
+ function answers(claimed) {
1706
+ if (claimed === void 0) {
1707
+ return void 0;
1708
+ }
1709
+ if (typeof claimed !== "object" || claimed === null || Array.isArray(claimed)) {
1710
+ throw new import_common11.BadRequestException("answers must be an object of questionId \u2192 chosen values");
1711
+ }
1712
+ const entries = Object.entries(claimed);
1713
+ if (entries.length > MAX_ANSWERED_QUESTIONS) {
1714
+ throw new import_common11.BadRequestException(`answers may cover at most ${MAX_ANSWERED_QUESTIONS} questions`);
1715
+ }
1716
+ const validated = /* @__PURE__ */ Object.create(null);
1717
+ for (const [questionId, values] of entries) {
1718
+ if (!Array.isArray(values)) {
1719
+ throw new import_common11.BadRequestException(`answers["${questionId}"] must be an array of chosen values`);
1720
+ }
1721
+ if (values.length > MAX_VALUES_PER_QUESTION) {
1722
+ throw new import_common11.BadRequestException(`answers["${questionId}"] may carry at most ${MAX_VALUES_PER_QUESTION} values`);
1723
+ }
1724
+ for (const value of values) {
1725
+ if (typeof value !== "string") {
1726
+ throw new import_common11.BadRequestException(`answers["${questionId}"] must contain only strings`);
1727
+ }
1728
+ if (value.length > MAX_ANSWER_VALUE_LENGTH) {
1729
+ throw new import_common11.BadRequestException(`answers["${questionId}"] values must be at most ${MAX_ANSWER_VALUE_LENGTH} characters`);
1730
+ }
1731
+ }
1732
+ validated[questionId] = values;
1733
+ }
1734
+ return validated;
1735
+ }
1736
+ __name(answers, "answers");
1166
1737
  var ToolCallController = class {
1167
1738
  static {
1168
1739
  __name(this, "ToolCallController");
@@ -1175,54 +1746,96 @@ var ToolCallController = class {
1175
1746
  }
1176
1747
  async approve(req, body) {
1177
1748
  const actor = await this.actorResolver.resolve(req);
1178
- await this.agent.approve(actor, body.toolCallId);
1749
+ await this.agent.approve(actor, toolCallId(body.toolCallId));
1179
1750
  return {
1180
1751
  ok: true
1181
1752
  };
1182
1753
  }
1183
1754
  async reject(req, body) {
1184
1755
  const actor = await this.actorResolver.resolve(req);
1185
- await this.agent.reject(actor, body.toolCallId, body.reason);
1756
+ await this.agent.reject(actor, toolCallId(body.toolCallId), rejectReason(body.reason));
1757
+ return {
1758
+ ok: true
1759
+ };
1760
+ }
1761
+ /**
1762
+ * Settle a parked question set. Alongside `approve`/`reject` rather than under a surface of its
1763
+ * own: an elicitation IS a parked tool call, gated by the same ownership check and delivered
1764
+ * through the same signal.
1765
+ */
1766
+ async answer(req, body) {
1767
+ const actor = await this.actorResolver.resolve(req);
1768
+ await this.agent.answer(actor, toolCallId(body.toolCallId), answers(body.answers));
1769
+ return {
1770
+ ok: true
1771
+ };
1772
+ }
1773
+ /** Decline to answer and let the agent proceed on the answers it pre-picked. */
1774
+ async skip(req, body) {
1775
+ const actor = await this.actorResolver.resolve(req);
1776
+ await this.agent.skip(actor, toolCallId(body.toolCallId));
1186
1777
  return {
1187
1778
  ok: true
1188
1779
  };
1189
1780
  }
1190
1781
  };
1191
- _ts_decorate9([
1192
- (0, import_common9.Post)("approve"),
1193
- _ts_param8(0, (0, import_common9.Req)()),
1194
- _ts_param8(1, (0, import_common9.Body)()),
1195
- _ts_metadata9("design:type", Function),
1196
- _ts_metadata9("design:paramtypes", [
1782
+ _ts_decorate11([
1783
+ (0, import_common11.Post)("approve"),
1784
+ _ts_param10(0, (0, import_common11.Req)()),
1785
+ _ts_param10(1, (0, import_common11.Body)()),
1786
+ _ts_metadata11("design:type", Function),
1787
+ _ts_metadata11("design:paramtypes", [
1197
1788
  typeof Request === "undefined" ? Object : Request,
1198
1789
  typeof ApproveBody === "undefined" ? Object : ApproveBody
1199
1790
  ]),
1200
- _ts_metadata9("design:returntype", Promise)
1791
+ _ts_metadata11("design:returntype", Promise)
1201
1792
  ], ToolCallController.prototype, "approve", null);
1202
- _ts_decorate9([
1203
- (0, import_common9.Post)("reject"),
1204
- _ts_param8(0, (0, import_common9.Req)()),
1205
- _ts_param8(1, (0, import_common9.Body)()),
1206
- _ts_metadata9("design:type", Function),
1207
- _ts_metadata9("design:paramtypes", [
1793
+ _ts_decorate11([
1794
+ (0, import_common11.Post)("reject"),
1795
+ _ts_param10(0, (0, import_common11.Req)()),
1796
+ _ts_param10(1, (0, import_common11.Body)()),
1797
+ _ts_metadata11("design:type", Function),
1798
+ _ts_metadata11("design:paramtypes", [
1208
1799
  typeof Request === "undefined" ? Object : Request,
1209
1800
  typeof RejectBody === "undefined" ? Object : RejectBody
1210
1801
  ]),
1211
- _ts_metadata9("design:returntype", Promise)
1802
+ _ts_metadata11("design:returntype", Promise)
1212
1803
  ], ToolCallController.prototype, "reject", null);
1213
- ToolCallController = _ts_decorate9([
1214
- (0, import_common9.Controller)("tool-call"),
1215
- _ts_param8(1, (0, import_common9.Inject)(import_nestjs_agent_core9.AGENT_ACTOR_RESOLVER)),
1216
- _ts_metadata9("design:type", Function),
1217
- _ts_metadata9("design:paramtypes", [
1804
+ _ts_decorate11([
1805
+ (0, import_common11.Post)("answer"),
1806
+ _ts_param10(0, (0, import_common11.Req)()),
1807
+ _ts_param10(1, (0, import_common11.Body)()),
1808
+ _ts_metadata11("design:type", Function),
1809
+ _ts_metadata11("design:paramtypes", [
1810
+ typeof Request === "undefined" ? Object : Request,
1811
+ typeof AnswerBody === "undefined" ? Object : AnswerBody
1812
+ ]),
1813
+ _ts_metadata11("design:returntype", Promise)
1814
+ ], ToolCallController.prototype, "answer", null);
1815
+ _ts_decorate11([
1816
+ (0, import_common11.Post)("skip"),
1817
+ _ts_param10(0, (0, import_common11.Req)()),
1818
+ _ts_param10(1, (0, import_common11.Body)()),
1819
+ _ts_metadata11("design:type", Function),
1820
+ _ts_metadata11("design:paramtypes", [
1821
+ typeof Request === "undefined" ? Object : Request,
1822
+ typeof ApproveBody === "undefined" ? Object : ApproveBody
1823
+ ]),
1824
+ _ts_metadata11("design:returntype", Promise)
1825
+ ], ToolCallController.prototype, "skip", null);
1826
+ ToolCallController = _ts_decorate11([
1827
+ (0, import_common11.Controller)("tool-call"),
1828
+ _ts_param10(1, (0, import_common11.Inject)(import_nestjs_agent_core11.AGENT_ACTOR_RESOLVER)),
1829
+ _ts_metadata11("design:type", Function),
1830
+ _ts_metadata11("design:paramtypes", [
1218
1831
  typeof AgentService === "undefined" ? Object : AgentService,
1219
1832
  typeof ActorResolver === "undefined" ? Object : ActorResolver
1220
1833
  ])
1221
1834
  ], ToolCallController);
1222
1835
 
1223
1836
  // src/discovery/agent-discovery.service.ts
1224
- var import_nestjs_agent_core10 = require("@dudousxd/nestjs-agent-core");
1225
- var import_common10 = require("@nestjs/common");
1837
+ var import_nestjs_agent_core12 = require("@dudousxd/nestjs-agent-core");
1838
+ var import_common12 = require("@nestjs/common");
1226
1839
  var import_core = require("@nestjs/core");
1227
1840
 
1228
1841
  // src/decorator/agent.decorator.ts
@@ -1257,23 +1870,23 @@ function SystemPromptContributor() {
1257
1870
  __name(SystemPromptContributor, "SystemPromptContributor");
1258
1871
 
1259
1872
  // src/discovery/agent-discovery.service.ts
1260
- function _ts_decorate10(decorators, target, key, desc) {
1873
+ function _ts_decorate12(decorators, target, key, desc) {
1261
1874
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1262
1875
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1263
1876
  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;
1264
1877
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1265
1878
  }
1266
- __name(_ts_decorate10, "_ts_decorate");
1267
- function _ts_metadata10(k, v) {
1879
+ __name(_ts_decorate12, "_ts_decorate");
1880
+ function _ts_metadata12(k, v) {
1268
1881
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1269
1882
  }
1270
- __name(_ts_metadata10, "_ts_metadata");
1271
- function _ts_param9(paramIndex, decorator) {
1883
+ __name(_ts_metadata12, "_ts_metadata");
1884
+ function _ts_param11(paramIndex, decorator) {
1272
1885
  return function(target, key) {
1273
1886
  decorator(target, key, paramIndex);
1274
1887
  };
1275
1888
  }
1276
- __name(_ts_param9, "_ts_param");
1889
+ __name(_ts_param11, "_ts_param");
1277
1890
  var AgentDiscoveryService = class _AgentDiscoveryService {
1278
1891
  static {
1279
1892
  __name(this, "AgentDiscoveryService");
@@ -1282,7 +1895,7 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
1282
1895
  scanner;
1283
1896
  registry;
1284
1897
  contributors;
1285
- logger = new import_common10.Logger(_AgentDiscoveryService.name);
1898
+ logger = new import_common12.Logger(_AgentDiscoveryService.name);
1286
1899
  constructor(discovery, scanner, registry, contributors) {
1287
1900
  this.discovery = discovery;
1288
1901
  this.scanner = scanner;
@@ -1321,23 +1934,53 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
1321
1934
  ...meta.maxSteps !== void 0 ? {
1322
1935
  maxSteps: meta.maxSteps
1323
1936
  } : {},
1937
+ ...meta.maxDelegationDepth !== void 0 ? {
1938
+ maxDelegationDepth: meta.maxDelegationDepth
1939
+ } : {},
1940
+ ...meta.maxAgentAppearances !== void 0 ? {
1941
+ maxAgentAppearances: meta.maxAgentAppearances
1942
+ } : {},
1943
+ ...meta.history !== void 0 ? {
1944
+ history: meta.history
1945
+ } : {},
1946
+ ...meta.outputSchema !== void 0 ? {
1947
+ outputSchema: meta.outputSchema
1948
+ } : {},
1949
+ ...meta.intake !== void 0 ? {
1950
+ intake: meta.intake
1951
+ } : {},
1952
+ ...meta.ask !== void 0 ? {
1953
+ ask: meta.ask
1954
+ } : {},
1955
+ ...meta.outputRepairAttempts !== void 0 ? {
1956
+ outputRepairAttempts: meta.outputRepairAttempts
1957
+ } : {},
1324
1958
  ...meta.handoff !== void 0 ? {
1325
- delegatesTo: this.handoffNames(meta)
1959
+ delegatesTo: this.handoffEdges(meta)
1326
1960
  } : {}
1327
1961
  };
1328
1962
  }
1329
- /** Resolve each handoff `@Agent` class to its registered name (skipping non-agent classes). */
1330
- handoffNames(meta) {
1331
- const names = [];
1332
- for (const target of meta.handoff ?? []) {
1963
+ /**
1964
+ * Resolve each handoff entry to an {@link AgentDelegation} — its target's registered name, plus
1965
+ * whether that edge detaches (skipping non-agent classes). A bare name is kept for a plain edge
1966
+ * rather than an always-object form, so a definition an older host built by hand still reads.
1967
+ */
1968
+ handoffEdges(meta) {
1969
+ const edges = [];
1970
+ for (const entry of meta.handoff ?? []) {
1971
+ const target = typeof entry === "function" ? entry : entry.agent;
1972
+ const detached = typeof entry === "function" ? false : entry.detached === true;
1333
1973
  const targetMeta = readAgentMetadata(target);
1334
1974
  if (targetMeta === void 0) {
1335
1975
  this.logger.warn(`Agent "${meta.name}" hands off to ${target.name}, which is not an @Agent \u2014 skipped.`);
1336
1976
  continue;
1337
1977
  }
1338
- names.push(targetMeta.name);
1978
+ edges.push(detached ? {
1979
+ agent: targetMeta.name,
1980
+ detached: true
1981
+ } : targetMeta.name);
1339
1982
  }
1340
- return names;
1983
+ return edges;
1341
1984
  }
1342
1985
  /** Push every `@SystemPromptContributor()` method on `instance` (bound) into the contributor list. */
1343
1986
  collectContributors(instance) {
@@ -1370,22 +2013,22 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
1370
2013
  return (ctx) => candidate.call(instance, ctx);
1371
2014
  }
1372
2015
  };
1373
- AgentDiscoveryService = _ts_decorate10([
1374
- (0, import_common10.Injectable)(),
1375
- _ts_param9(2, (0, import_common10.Inject)(import_nestjs_agent_core10.AGENT_REGISTRY)),
1376
- _ts_param9(3, (0, import_common10.Inject)(import_nestjs_agent_core10.AGENT_PROMPT_CONTRIBUTORS)),
1377
- _ts_metadata10("design:type", Function),
1378
- _ts_metadata10("design:paramtypes", [
2016
+ AgentDiscoveryService = _ts_decorate12([
2017
+ (0, import_common12.Injectable)(),
2018
+ _ts_param11(2, (0, import_common12.Inject)(import_nestjs_agent_core12.AGENT_REGISTRY)),
2019
+ _ts_param11(3, (0, import_common12.Inject)(import_nestjs_agent_core12.AGENT_PROMPT_CONTRIBUTORS)),
2020
+ _ts_metadata12("design:type", Function),
2021
+ _ts_metadata12("design:paramtypes", [
1379
2022
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
1380
2023
  typeof import_core.MetadataScanner === "undefined" ? Object : import_core.MetadataScanner,
1381
- typeof import_nestjs_agent_core10.AgentRegistry === "undefined" ? Object : import_nestjs_agent_core10.AgentRegistry,
2024
+ typeof import_nestjs_agent_core12.AgentRegistry === "undefined" ? Object : import_nestjs_agent_core12.AgentRegistry,
1382
2025
  Array
1383
2026
  ])
1384
2027
  ], AgentDiscoveryService);
1385
2028
 
1386
2029
  // src/discovery/ai-tool-discovery.service.ts
1387
- var import_nestjs_agent_core11 = require("@dudousxd/nestjs-agent-core");
1388
- var import_common11 = require("@nestjs/common");
2030
+ var import_nestjs_agent_core13 = require("@dudousxd/nestjs-agent-core");
2031
+ var import_common13 = require("@nestjs/common");
1389
2032
  var import_core2 = require("@nestjs/core");
1390
2033
  var import_zod = require("zod");
1391
2034
 
@@ -1434,23 +2077,23 @@ function provideAgentTool(factoryOrTool, inject) {
1434
2077
  __name(provideAgentTool, "provideAgentTool");
1435
2078
 
1436
2079
  // src/discovery/ai-tool-discovery.service.ts
1437
- function _ts_decorate11(decorators, target, key, desc) {
2080
+ function _ts_decorate13(decorators, target, key, desc) {
1438
2081
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1439
2082
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1440
2083
  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;
1441
2084
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1442
2085
  }
1443
- __name(_ts_decorate11, "_ts_decorate");
1444
- function _ts_metadata11(k, v) {
2086
+ __name(_ts_decorate13, "_ts_decorate");
2087
+ function _ts_metadata13(k, v) {
1445
2088
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1446
2089
  }
1447
- __name(_ts_metadata11, "_ts_metadata");
1448
- function _ts_param10(paramIndex, decorator) {
2090
+ __name(_ts_metadata13, "_ts_metadata");
2091
+ function _ts_param12(paramIndex, decorator) {
1449
2092
  return function(target, key) {
1450
2093
  decorator(target, key, paramIndex);
1451
2094
  };
1452
2095
  }
1453
- __name(_ts_param10, "_ts_param");
2096
+ __name(_ts_param12, "_ts_param");
1454
2097
  var AiToolDiscoveryService = class _AiToolDiscoveryService {
1455
2098
  static {
1456
2099
  __name(this, "AiToolDiscoveryService");
@@ -1459,7 +2102,7 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
1459
2102
  registry;
1460
2103
  agents;
1461
2104
  options;
1462
- logger = new import_common11.Logger(_AiToolDiscoveryService.name);
2105
+ logger = new import_common13.Logger(_AiToolDiscoveryService.name);
1463
2106
  constructor(discovery, registry, agents, options) {
1464
2107
  this.discovery = discovery;
1465
2108
  this.registry = registry;
@@ -1526,22 +2169,30 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
1526
2169
  }
1527
2170
  let delegates = 0;
1528
2171
  for (const definition of this.agents.list()) {
1529
- for (const target of definition.delegatesTo ?? []) {
2172
+ for (const edge of definition.delegatesTo ?? []) {
2173
+ const { agent: target, detached } = (0, import_nestjs_agent_core13.normalizeDelegation)(edge);
1530
2174
  const targetDefinition = this.agents.get(target);
1531
2175
  if (targetDefinition === void 0) {
1532
2176
  throw new Error(`Agent "${definition.name}" hands off to "${target}", which is not a registered @Agent. Declare it as an @Agent provider or fix the reference.`);
1533
2177
  }
1534
- const name = delegateToolName(target);
2178
+ const name = delegateToolName({
2179
+ target,
2180
+ detached
2181
+ });
1535
2182
  if (this.registry.has(name)) {
1536
2183
  continue;
1537
2184
  }
1538
2185
  const targetBlurb = typeof targetDefinition.systemPrompt === "string" ? ` It is: ${targetDefinition.systemPrompt}` : "";
2186
+ const description = detached ? `Start the "${target}" agent working on a task in the BACKGROUND. Returns immediately with a receipt, NOT an answer \u2014 the answer is delivered to this conversation as a separate message later. Use it for work the user does not need to sit and wait for.${targetBlurb}` : `Delegate a task to the "${target}" agent and get its answer.${targetBlurb}`;
1539
2187
  this.registry.register(
1540
2188
  {
1541
2189
  name,
1542
2190
  kind: "agent",
1543
2191
  targetAgent: target,
1544
- description: `Delegate a task to the "${target}" agent and get its answer.${targetBlurb}`,
2192
+ ...detached ? {
2193
+ detached: true
2194
+ } : {},
2195
+ description,
1545
2196
  inputSchema: import_zod.z.object({
1546
2197
  task: import_zod.z.string()
1547
2198
  })
@@ -1569,13 +2220,13 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
1569
2220
  return true;
1570
2221
  }
1571
2222
  };
1572
- AiToolDiscoveryService = _ts_decorate11([
1573
- (0, import_common11.Injectable)(),
1574
- _ts_param10(1, (0, import_common11.Inject)(import_nestjs_agent_core11.AGENT_TOOL_REGISTRY)),
1575
- _ts_param10(2, (0, import_common11.Inject)(import_nestjs_agent_core11.AGENT_REGISTRY)),
1576
- _ts_param10(3, (0, import_common11.Inject)(import_nestjs_agent_core11.AGENT_OPTIONS)),
1577
- _ts_metadata11("design:type", Function),
1578
- _ts_metadata11("design:paramtypes", [
2223
+ AiToolDiscoveryService = _ts_decorate13([
2224
+ (0, import_common13.Injectable)(),
2225
+ _ts_param12(1, (0, import_common13.Inject)(import_nestjs_agent_core13.AGENT_TOOL_REGISTRY)),
2226
+ _ts_param12(2, (0, import_common13.Inject)(import_nestjs_agent_core13.AGENT_REGISTRY)),
2227
+ _ts_param12(3, (0, import_common13.Inject)(import_nestjs_agent_core13.AGENT_OPTIONS)),
2228
+ _ts_metadata13("design:type", Function),
2229
+ _ts_metadata13("design:paramtypes", [
1579
2230
  typeof import_core2.DiscoveryService === "undefined" ? Object : import_core2.DiscoveryService,
1580
2231
  typeof ToolRegistry === "undefined" ? Object : ToolRegistry,
1581
2232
  typeof AgentRegistry === "undefined" ? Object : AgentRegistry,
@@ -1583,8 +2234,103 @@ AiToolDiscoveryService = _ts_decorate11([
1583
2234
  ])
1584
2235
  ], AiToolDiscoveryService);
1585
2236
 
2237
+ // src/discovery/skill-discovery.service.ts
2238
+ var import_nestjs_agent_core15 = require("@dudousxd/nestjs-agent-core");
2239
+ var import_common14 = require("@nestjs/common");
2240
+ var import_core3 = require("@nestjs/core");
2241
+
2242
+ // src/decorator/skill.decorator.ts
2243
+ var import_reflect_metadata4 = require("reflect-metadata");
2244
+ var import_nestjs_agent_core14 = require("@dudousxd/nestjs-agent-core");
2245
+ var SKILL_METADATA = Symbol.for("@dudousxd/nestjs-agent:skill-metadata");
2246
+ function Skill(options) {
2247
+ return (target) => {
2248
+ Reflect.defineMetadata(SKILL_METADATA, options, target);
2249
+ };
2250
+ }
2251
+ __name(Skill, "Skill");
2252
+ function readSkillMetadata(target) {
2253
+ return Reflect.getMetadata(SKILL_METADATA, target);
2254
+ }
2255
+ __name(readSkillMetadata, "readSkillMetadata");
2256
+ function skillScope(options) {
2257
+ return options.scope ?? import_nestjs_agent_core14.GLOBAL_SCOPE;
2258
+ }
2259
+ __name(skillScope, "skillScope");
2260
+
2261
+ // src/discovery/skill-discovery.service.ts
2262
+ function _ts_decorate14(decorators, target, key, desc) {
2263
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2264
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2265
+ 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;
2266
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2267
+ }
2268
+ __name(_ts_decorate14, "_ts_decorate");
2269
+ function _ts_metadata14(k, v) {
2270
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2271
+ }
2272
+ __name(_ts_metadata14, "_ts_metadata");
2273
+ function _ts_param13(paramIndex, decorator) {
2274
+ return function(target, key) {
2275
+ decorator(target, key, paramIndex);
2276
+ };
2277
+ }
2278
+ __name(_ts_param13, "_ts_param");
2279
+ var SkillDiscoveryService = class _SkillDiscoveryService {
2280
+ static {
2281
+ __name(this, "SkillDiscoveryService");
2282
+ }
2283
+ discovery;
2284
+ declared;
2285
+ logger = new import_common14.Logger(_SkillDiscoveryService.name);
2286
+ constructor(discovery, declared) {
2287
+ this.discovery = discovery;
2288
+ this.declared = declared;
2289
+ }
2290
+ onModuleInit() {
2291
+ for (const wrapper of this.discovery.getProviders()) {
2292
+ const instance = wrapper.instance;
2293
+ if (instance === null || typeof instance !== "object") {
2294
+ continue;
2295
+ }
2296
+ const meta = readSkillMetadata(instance.constructor);
2297
+ if (meta === void 0) {
2298
+ continue;
2299
+ }
2300
+ const body = this.bodyOf(instance, meta.body);
2301
+ if (body === void 0) {
2302
+ this.logger.warn(`Skill "${meta.name}" declares no body \u2014 add a \`body()\` method or \`@Skill({ body })\`. Skipped.`);
2303
+ continue;
2304
+ }
2305
+ this.declared.push({
2306
+ name: meta.name,
2307
+ description: meta.description,
2308
+ scope: skillScope(meta),
2309
+ body
2310
+ });
2311
+ }
2312
+ }
2313
+ /** The instance's `body()` method (bound), else the flat string, else nothing to offer. */
2314
+ bodyOf(instance, flat) {
2315
+ const candidate = instance.body;
2316
+ if (typeof candidate === "function") {
2317
+ return (ctx) => candidate.call(instance, ctx);
2318
+ }
2319
+ return flat === void 0 ? void 0 : () => flat;
2320
+ }
2321
+ };
2322
+ SkillDiscoveryService = _ts_decorate14([
2323
+ (0, import_common14.Injectable)(),
2324
+ _ts_param13(1, (0, import_common14.Inject)(import_nestjs_agent_core15.AGENT_SKILL_SOURCES)),
2325
+ _ts_metadata14("design:type", Function),
2326
+ _ts_metadata14("design:paramtypes", [
2327
+ typeof import_core3.DiscoveryService === "undefined" ? Object : import_core3.DiscoveryService,
2328
+ Array
2329
+ ])
2330
+ ], SkillDiscoveryService);
2331
+
1586
2332
  // src/in-process-sink.ts
1587
- var import_nestjs_agent_core12 = require("@dudousxd/nestjs-agent-core");
2333
+ var import_nestjs_agent_core16 = require("@dudousxd/nestjs-agent-core");
1588
2334
  var InProcessTokenStreamSink = class {
1589
2335
  static {
1590
2336
  __name(this, "InProcessTokenStreamSink");
@@ -1639,7 +2385,7 @@ var InProcessTokenStreamSink = class {
1639
2385
  }
1640
2386
  if (buf.ended) {
1641
2387
  if (buf.failure !== void 0) {
1642
- throw new import_nestjs_agent_core12.AgentStreamError(buf.failure);
2388
+ throw new import_nestjs_agent_core16.AgentStreamError(buf.failure);
1643
2389
  }
1644
2390
  return;
1645
2391
  }
@@ -1670,38 +2416,44 @@ var LedgerQuotaStore = class {
1670
2416
  withinLimit: usedTokens < this.limitTokens
1671
2417
  };
1672
2418
  }
1673
- async bump() {
2419
+ async bump(_actorRef, _day, _tokens) {
1674
2420
  }
1675
2421
  };
1676
2422
 
1677
2423
  // src/runner/inline-agent-runner.ts
1678
- var import_nestjs_agent_core13 = require("@dudousxd/nestjs-agent-core");
1679
- var import_common12 = require("@nestjs/common");
1680
- function _ts_decorate12(decorators, target, key, desc) {
2424
+ var import_nestjs_agent_core17 = require("@dudousxd/nestjs-agent-core");
2425
+ var import_common15 = require("@nestjs/common");
2426
+ function _ts_decorate15(decorators, target, key, desc) {
1681
2427
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1682
2428
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1683
2429
  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;
1684
2430
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1685
2431
  }
1686
- __name(_ts_decorate12, "_ts_decorate");
1687
- function _ts_metadata12(k, v) {
2432
+ __name(_ts_decorate15, "_ts_decorate");
2433
+ function _ts_metadata15(k, v) {
1688
2434
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1689
2435
  }
1690
- __name(_ts_metadata12, "_ts_metadata");
1691
- function _ts_param11(paramIndex, decorator) {
2436
+ __name(_ts_metadata15, "_ts_metadata");
2437
+ function _ts_param14(paramIndex, decorator) {
1692
2438
  return function(target, key) {
1693
2439
  decorator(target, key, paramIndex);
1694
2440
  };
1695
2441
  }
1696
- __name(_ts_param11, "_ts_param");
2442
+ __name(_ts_param14, "_ts_param");
1697
2443
  var InlineAgentRunner = class _InlineAgentRunner {
1698
2444
  static {
1699
2445
  __name(this, "InlineAgentRunner");
1700
2446
  }
1701
2447
  factory;
1702
2448
  store;
1703
- logger = new import_common12.Logger(_InlineAgentRunner.name);
2449
+ logger = new import_common15.Logger(_InlineAgentRunner.name);
1704
2450
  pending = /* @__PURE__ */ new Map();
2451
+ /**
2452
+ * Runs someone has asked to stop. In-process, like `pending`, and for the same reason: this runner
2453
+ * is single-replica by construction, so the request is readable by the only loop that could be
2454
+ * running it. A cancelled id is dropped once the run settles, so the set tracks live runs only.
2455
+ */
2456
+ cancelled = /* @__PURE__ */ new Set();
1705
2457
  constructor(factory, store) {
1706
2458
  this.factory = factory;
1707
2459
  this.store = store;
@@ -1710,15 +2462,31 @@ var InlineAgentRunner = class _InlineAgentRunner {
1710
2462
  const runId = crypto.randomUUID();
1711
2463
  const day = input.day ?? utcDay();
1712
2464
  const deps = this.factory.forAgent(input.agentName);
1713
- const hooks = this.topLevelHooks(runId, deps, input.actor, day);
1714
- void (0, import_nestjs_agent_core13.runAgentLoop)({
2465
+ const hooks = this.topLevelHooks({
2466
+ runId,
2467
+ deps,
2468
+ actor: input.actor,
2469
+ day,
2470
+ threadId: input.threadId,
2471
+ chainBelow: [
2472
+ ...input.delegationPath ?? [],
2473
+ ...input.agentName !== void 0 ? [
2474
+ input.agentName
2475
+ ] : []
2476
+ ]
2477
+ });
2478
+ void (0, import_nestjs_agent_core17.runAgentLoop)({
1715
2479
  ...deps,
1716
2480
  day
1717
2481
  }, input, hooks).then(() => this.store.setActiveStream(input.threadId, null)).catch(async (error) => {
2482
+ if (error instanceof import_nestjs_agent_core17.RunCancelledError) {
2483
+ await this.settleCancelled(runId, input.threadId, deps);
2484
+ return;
2485
+ }
1718
2486
  const message = error instanceof Error ? error.message : String(error);
1719
- const code = error instanceof import_nestjs_agent_core13.QuotaExceededError ? "quota_exceeded" : "run_failed";
2487
+ const code = (0, import_nestjs_agent_core17.agentFailureCode)(error);
1720
2488
  this.logger.error(`agent run ${runId} failed (${code}): ${message}`);
1721
- (0, import_nestjs_agent_core13.publishAgentRunFailed)({
2489
+ (0, import_nestjs_agent_core17.publishAgentRunFailed)({
1722
2490
  runId,
1723
2491
  code,
1724
2492
  message
@@ -1735,33 +2503,216 @@ var InlineAgentRunner = class _InlineAgentRunner {
1735
2503
  code,
1736
2504
  message
1737
2505
  });
1738
- });
2506
+ }).finally(() => this.cancelled.delete(runId));
1739
2507
  return {
1740
2508
  runId
1741
2509
  };
1742
2510
  }
1743
- async signal(runId, toolCallId, decision) {
1744
- const key = `${runId}:${toolCallId}`;
1745
- const resolve = this.pending.get(key);
1746
- if (resolve !== void 0) {
2511
+ async signal(runId, toolCallId2, reply) {
2512
+ const key = `${runId}:${toolCallId2}`;
2513
+ const waiter = this.pending.get(key);
2514
+ if (waiter !== void 0) {
1747
2515
  this.pending.delete(key);
1748
- resolve(decision);
2516
+ waiter.resolve(reply);
1749
2517
  }
1750
2518
  }
2519
+ /**
2520
+ * Ask a run to stop, and settle whatever it was parked on.
2521
+ *
2522
+ * The loop observes the request at its next safe point (between steps, before the turn's tools) and
2523
+ * unwinds from there — so a tool already executing is left to finish, and its result is recorded
2524
+ * exactly as it would have been. What this cannot wait for is a turn parked on a human: that wait
2525
+ * is a promise nobody is going to resolve, so it is REJECTED here with the same
2526
+ * {@link RunCancelledError} the loop would have thrown, and the run unwinds through the identical
2527
+ * path.
2528
+ *
2529
+ * Settlement — the run row, the thread's active stream, the stream's terminal — belongs to the
2530
+ * `RunCancelledError` catch in `start`, so a cancel and an ordinary failure settle in one place
2531
+ * each and can never both write.
2532
+ */
1751
2533
  async cancel(runId) {
1752
- const deps = this.factory.forAgent();
2534
+ this.cancelled.add(runId);
2535
+ for (const [key, waiter] of this.pending) {
2536
+ if (key.startsWith(`${runId}:`)) {
2537
+ this.pending.delete(key);
2538
+ waiter.reject(new import_nestjs_agent_core17.RunCancelledError());
2539
+ }
2540
+ }
2541
+ await Promise.resolve();
2542
+ }
2543
+ /**
2544
+ * The single place a cancelled run's state is settled: recorded as its own terminal (never
2545
+ * `failed` — a user pressing Stop must not land in someone's error rate), the thread released, and
2546
+ * the stream ENDED after a `cancelled` frame rather than failed, so a client that retries failed
2547
+ * streams does not retry this one.
2548
+ */
2549
+ async settleCancelled(runId, threadId, deps) {
2550
+ this.logger.log(`agent run ${runId} cancelled`);
2551
+ await this.store.setActiveStream(threadId, null);
1753
2552
  const writer = await deps.sink.open(runId);
2553
+ await writer.write((0, import_nestjs_agent_core17.encodeStreamEvent)({
2554
+ kind: "cancelled"
2555
+ }));
1754
2556
  await writer.end();
2557
+ await this.store.recordRunEnd?.({
2558
+ runId,
2559
+ status: "cancelled"
2560
+ });
2561
+ }
2562
+ /**
2563
+ * Park a run on a human, keyed by run + tool call. One map for approvals and for question-set
2564
+ * answers alike: both wait on the same key, and `signal` cannot tell (or need to tell) which
2565
+ * shape it is delivering — the loop asked for one and only ever gets what the caller sent. A
2566
+ * cancel settles the wait too, by rejecting it.
2567
+ */
2568
+ park(runId, toolCallId2) {
2569
+ return new Promise((resolve, reject) => {
2570
+ this.pending.set(`${runId}:${toolCallId2}`, {
2571
+ resolve,
2572
+ reject
2573
+ });
2574
+ });
1755
2575
  }
1756
- topLevelHooks(runId, deps, actor, day) {
2576
+ topLevelHooks(args) {
2577
+ const { runId, deps, actor, day, threadId, chainBelow } = args;
1757
2578
  return {
1758
2579
  runId,
1759
2580
  openSink: /* @__PURE__ */ __name(() => deps.sink.open(runId), "openSink"),
1760
- awaitApproval: /* @__PURE__ */ __name((call) => new Promise((resolve) => {
1761
- this.pending.set(`${runId}:${call.id}`, resolve);
1762
- }), "awaitApproval"),
2581
+ awaitApproval: /* @__PURE__ */ __name((call) => this.park(runId, call.id), "awaitApproval"),
2582
+ awaitAnswers: /* @__PURE__ */ __name((request) => this.park(runId, request.id), "awaitAnswers"),
1763
2583
  step: /* @__PURE__ */ __name((_name, fn) => fn(), "step"),
1764
- runAgent: /* @__PURE__ */ __name((agentName, task) => this.runNested(agentName, task, actor, day, 1, runId), "runAgent")
2584
+ parallel: import_nestjs_agent_core17.settleAll,
2585
+ cancelled: /* @__PURE__ */ __name(async () => this.cancelled.has(runId), "cancelled"),
2586
+ runAgent: /* @__PURE__ */ __name((agentName, task) => this.runNested({
2587
+ agentName,
2588
+ task,
2589
+ actor,
2590
+ day,
2591
+ depth: 1,
2592
+ path: chainBelow,
2593
+ sinkRunId: runId,
2594
+ parentRunId: runId
2595
+ }), "runAgent"),
2596
+ startAgent: /* @__PURE__ */ __name(({ agentName, task, toolCallId: toolCallId2 }) => this.startDetached({
2597
+ agentName,
2598
+ task,
2599
+ actor,
2600
+ day,
2601
+ depth: 1,
2602
+ path: chainBelow,
2603
+ parentRunId: runId,
2604
+ deliverTo: {
2605
+ threadId,
2606
+ toolCallId: toolCallId2
2607
+ }
2608
+ }), "startAgent")
2609
+ };
2610
+ }
2611
+ /**
2612
+ * Delegate WITHOUT waiting: a nested loop nobody awaits, on its own thread and its own sink, which
2613
+ * posts its answer back into the delegating thread when it lands (`deliverTo`, settled by the
2614
+ * loop). The calling turn gets the run id straight back and finishes.
2615
+ *
2616
+ * No `sinkRunId`, unlike {@link runNested}: forwarding into the stream the human is watching would
2617
+ * write into a turn that has already ended. Its own approvals resolve through the shared pending
2618
+ * map keyed by its own runId — which is what the pending-approvals surface routes to.
2619
+ */
2620
+ async startDetached(args) {
2621
+ const { agentName, task, actor, day, depth, path, parentRunId, deliverTo } = args;
2622
+ const subThread = await this.store.createThread({
2623
+ actor,
2624
+ transient: true
2625
+ });
2626
+ const runId = crypto.randomUUID();
2627
+ await this.store.setActiveStream(subThread.id, runId);
2628
+ const deps = this.factory.forAgent(agentName);
2629
+ const hooks = {
2630
+ runId,
2631
+ openSink: /* @__PURE__ */ __name(() => deps.sink.open(runId), "openSink"),
2632
+ awaitApproval: /* @__PURE__ */ __name((call) => this.park(runId, call.id), "awaitApproval"),
2633
+ awaitAnswers: /* @__PURE__ */ __name((request) => this.park(runId, request.id), "awaitAnswers"),
2634
+ step: /* @__PURE__ */ __name((_name, fn) => fn(), "step"),
2635
+ parallel: import_nestjs_agent_core17.settleAll,
2636
+ cancelled: /* @__PURE__ */ __name(async () => this.cancelled.has(runId), "cancelled"),
2637
+ runAgent: /* @__PURE__ */ __name((childName, childTask) => this.runNested({
2638
+ agentName: childName,
2639
+ task: childTask,
2640
+ actor,
2641
+ day,
2642
+ depth: depth + 1,
2643
+ path: [
2644
+ ...path,
2645
+ agentName
2646
+ ],
2647
+ // A detached run owns a stream of its own, so ITS sub-agents forward into that one.
2648
+ sinkRunId: runId,
2649
+ parentRunId: runId
2650
+ }), "runAgent"),
2651
+ startAgent: /* @__PURE__ */ __name(({ agentName: childName, task: childTask, toolCallId: toolCallId2 }) => this.startDetached({
2652
+ agentName: childName,
2653
+ task: childTask,
2654
+ actor,
2655
+ day,
2656
+ depth: depth + 1,
2657
+ path: [
2658
+ ...path,
2659
+ agentName
2660
+ ],
2661
+ parentRunId: runId,
2662
+ deliverTo: {
2663
+ threadId: subThread.id,
2664
+ toolCallId: toolCallId2
2665
+ }
2666
+ }), "startAgent")
2667
+ };
2668
+ void (0, import_nestjs_agent_core17.runAgentLoop)({
2669
+ ...deps,
2670
+ day
2671
+ }, {
2672
+ threadId: subThread.id,
2673
+ actor,
2674
+ userText: task,
2675
+ agentName,
2676
+ day,
2677
+ delegationDepth: depth,
2678
+ delegationPath: path,
2679
+ parentRunId,
2680
+ deliverTo
2681
+ }, hooks).catch(async (error) => {
2682
+ const cancelled = error instanceof import_nestjs_agent_core17.RunCancelledError;
2683
+ const message = error instanceof Error ? error.message : String(error);
2684
+ if (!cancelled) {
2685
+ this.logger.error(`detached agent run ${runId} failed: ${message}`);
2686
+ (0, import_nestjs_agent_core17.publishAgentRunFailed)({
2687
+ runId,
2688
+ code: (0, import_nestjs_agent_core17.agentFailureCode)(error),
2689
+ message
2690
+ });
2691
+ }
2692
+ await this.store.recordRunEnd?.({
2693
+ runId,
2694
+ status: cancelled ? "cancelled" : "failed",
2695
+ ...cancelled ? {} : {
2696
+ errorCode: (0, import_nestjs_agent_core17.agentFailureCode)(error),
2697
+ errorMessage: message
2698
+ }
2699
+ });
2700
+ await (0, import_nestjs_agent_core17.settleUnsettledDelegation)({
2701
+ store: this.store,
2702
+ delivery: deliverTo,
2703
+ agent: agentName,
2704
+ runId,
2705
+ status: cancelled ? "cancelled" : "failed",
2706
+ ...cancelled ? {} : {
2707
+ error: message
2708
+ }
2709
+ });
2710
+ }).finally(async () => {
2711
+ this.cancelled.delete(runId);
2712
+ await this.store.setActiveStream(subThread.id, null);
2713
+ });
2714
+ return {
2715
+ runId
1765
2716
  };
1766
2717
  }
1767
2718
  /**
@@ -1769,7 +2720,8 @@ var InlineAgentRunner = class _InlineAgentRunner {
1769
2720
  * (the top-level run the human is watching) so its output and any pending action tool are visible,
1770
2721
  * and its own approvals resolve through the shared pending map keyed by its own runId.
1771
2722
  */
1772
- async runNested(agentName, task, actor, day, depth, sinkRunId) {
2723
+ async runNested(args) {
2724
+ const { agentName, task, actor, day, depth, path, sinkRunId, parentRunId } = args;
1773
2725
  const subThread = await this.store.createThread({
1774
2726
  actor,
1775
2727
  transient: true
@@ -1781,14 +2733,45 @@ var InlineAgentRunner = class _InlineAgentRunner {
1781
2733
  runId,
1782
2734
  // Forward into the top-level stream; the top-level run owns end/fail on that shared sink.
1783
2735
  openSink: /* @__PURE__ */ __name(async () => childSinkWriter(await deps.sink.open(sinkRunId)), "openSink"),
1784
- awaitApproval: /* @__PURE__ */ __name((call) => new Promise((resolve) => {
1785
- this.pending.set(`${runId}:${call.id}`, resolve);
1786
- }), "awaitApproval"),
2736
+ awaitApproval: /* @__PURE__ */ __name((call) => this.park(runId, call.id), "awaitApproval"),
2737
+ awaitAnswers: /* @__PURE__ */ __name((request) => this.park(runId, request.id), "awaitAnswers"),
1787
2738
  step: /* @__PURE__ */ __name((_name, fn) => fn(), "step"),
1788
- runAgent: /* @__PURE__ */ __name((childName, childTask) => this.runNested(childName, childTask, actor, day, depth + 1, sinkRunId), "runAgent")
2739
+ parallel: import_nestjs_agent_core17.settleAll,
2740
+ // A child stops when it is cancelled OR when the run a human is actually watching is: the
2741
+ // canceller names the top-level run, which is the only id that ever left the server.
2742
+ cancelled: /* @__PURE__ */ __name(async () => this.cancelled.has(runId) || this.cancelled.has(sinkRunId), "cancelled"),
2743
+ runAgent: /* @__PURE__ */ __name((childName, childTask) => this.runNested({
2744
+ agentName: childName,
2745
+ task: childTask,
2746
+ actor,
2747
+ day,
2748
+ depth: depth + 1,
2749
+ path: [
2750
+ ...path,
2751
+ agentName
2752
+ ],
2753
+ sinkRunId,
2754
+ parentRunId: runId
2755
+ }), "runAgent"),
2756
+ startAgent: /* @__PURE__ */ __name(({ agentName: childName, task: childTask, toolCallId: toolCallId2 }) => this.startDetached({
2757
+ agentName: childName,
2758
+ task: childTask,
2759
+ actor,
2760
+ day,
2761
+ depth: depth + 1,
2762
+ path: [
2763
+ ...path,
2764
+ agentName
2765
+ ],
2766
+ parentRunId: runId,
2767
+ deliverTo: {
2768
+ threadId: subThread.id,
2769
+ toolCallId: toolCallId2
2770
+ }
2771
+ }), "startAgent")
1789
2772
  };
1790
2773
  try {
1791
- return await (0, import_nestjs_agent_core13.runAgentLoop)({
2774
+ return await (0, import_nestjs_agent_core17.runAgentLoop)({
1792
2775
  ...deps,
1793
2776
  day
1794
2777
  }, {
@@ -1798,6 +2781,8 @@ var InlineAgentRunner = class _InlineAgentRunner {
1798
2781
  agentName,
1799
2782
  day,
1800
2783
  delegationDepth: depth,
2784
+ delegationPath: path,
2785
+ parentRunId,
1801
2786
  sinkRunId
1802
2787
  }, hooks);
1803
2788
  } finally {
@@ -1805,112 +2790,177 @@ var InlineAgentRunner = class _InlineAgentRunner {
1805
2790
  }
1806
2791
  }
1807
2792
  };
1808
- InlineAgentRunner = _ts_decorate12([
1809
- (0, import_common12.Injectable)(),
1810
- _ts_param11(0, (0, import_common12.Inject)(import_nestjs_agent_core13.AGENT_DEPS_FACTORY)),
1811
- _ts_param11(1, (0, import_common12.Inject)(import_nestjs_agent_core13.AGENT_STORE)),
1812
- _ts_metadata12("design:type", Function),
1813
- _ts_metadata12("design:paramtypes", [
2793
+ InlineAgentRunner = _ts_decorate15([
2794
+ (0, import_common15.Injectable)(),
2795
+ _ts_param14(0, (0, import_common15.Inject)(import_nestjs_agent_core17.AGENT_DEPS_FACTORY)),
2796
+ _ts_param14(1, (0, import_common15.Inject)(import_nestjs_agent_core17.AGENT_STORE)),
2797
+ _ts_metadata15("design:type", Function),
2798
+ _ts_metadata15("design:paramtypes", [
1814
2799
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
1815
2800
  typeof AgentStore === "undefined" ? Object : AgentStore
1816
2801
  ])
1817
2802
  ], InlineAgentRunner);
1818
2803
 
2804
+ // src/skills-config.ts
2805
+ var import_nestjs_agent_core18 = require("@dudousxd/nestjs-agent-core");
2806
+ function declaredSkillProvider(declared) {
2807
+ return {
2808
+ list: /* @__PURE__ */ __name(({ scopes }) => declared.filter((skill) => scopes.includes(skill.scope)).map(({ name, description, scope }) => ({
2809
+ name,
2810
+ description,
2811
+ scope
2812
+ })), "list"),
2813
+ load: /* @__PURE__ */ __name(async ({ name, scope, ctx }) => {
2814
+ const match = declared.find((skill) => skill.name === name && skill.scope === scope);
2815
+ return match === void 0 ? null : await match.body(ctx);
2816
+ }, "load")
2817
+ };
2818
+ }
2819
+ __name(declaredSkillProvider, "declaredSkillProvider");
2820
+ function resolveSkillsConfig(options, declared) {
2821
+ if (options === void 0) {
2822
+ return void 0;
2823
+ }
2824
+ const providers = options.provider === void 0 ? [
2825
+ declaredSkillProvider(declared)
2826
+ ] : [
2827
+ options.provider,
2828
+ declaredSkillProvider(declared)
2829
+ ];
2830
+ return {
2831
+ provider: providers.length === 1 ? providers[0] : (0, import_nestjs_agent_core18.compositeSkillProvider)(providers),
2832
+ ...options.scopes !== void 0 ? {
2833
+ scopes: options.scopes
2834
+ } : {},
2835
+ ...options.maxSkills !== void 0 ? {
2836
+ maxSkills: options.maxSkills
2837
+ } : {}
2838
+ };
2839
+ }
2840
+ __name(resolveSkillsConfig, "resolveSkillsConfig");
2841
+
1819
2842
  // src/agent.module.ts
1820
- function _ts_decorate13(decorators, target, key, desc) {
2843
+ function _ts_decorate16(decorators, target, key, desc) {
1821
2844
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1822
2845
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1823
2846
  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;
1824
2847
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1825
2848
  }
1826
- __name(_ts_decorate13, "_ts_decorate");
2849
+ __name(_ts_decorate16, "_ts_decorate");
1827
2850
  var DEFAULT_PATH = "agent";
1828
2851
  function sharedProviders(durable, includeStore) {
1829
2852
  const providers = [
1830
2853
  {
1831
- provide: import_nestjs_agent_core14.AGENT_TOOL_REGISTRY,
1832
- useFactory: /* @__PURE__ */ __name(() => new import_nestjs_agent_core14.ToolRegistry(), "useFactory")
2854
+ provide: import_nestjs_agent_core19.AGENT_TOOL_REGISTRY,
2855
+ useFactory: /* @__PURE__ */ __name(() => new import_nestjs_agent_core19.ToolRegistry(), "useFactory")
1833
2856
  },
1834
2857
  // Starts empty; AgentDiscoveryService populates it from `@Agent`-decorated providers at boot.
1835
2858
  {
1836
- provide: import_nestjs_agent_core14.AGENT_REGISTRY,
1837
- useFactory: /* @__PURE__ */ __name(() => new import_nestjs_agent_core14.AgentRegistry(), "useFactory")
2859
+ provide: import_nestjs_agent_core19.AGENT_REGISTRY,
2860
+ useFactory: /* @__PURE__ */ __name(() => new import_nestjs_agent_core19.AgentRegistry(), "useFactory")
1838
2861
  },
1839
2862
  // A shared, mutable list AgentDiscoveryService fills with `@SystemPromptContributor()` methods.
1840
2863
  {
1841
- provide: import_nestjs_agent_core14.AGENT_PROMPT_CONTRIBUTORS,
2864
+ provide: import_nestjs_agent_core19.AGENT_PROMPT_CONTRIBUTORS,
1842
2865
  useFactory: /* @__PURE__ */ __name(() => [], "useFactory")
1843
2866
  },
2867
+ // Likewise for `@Skill`-decorated providers — filled by SkillDiscoveryService at onModuleInit,
2868
+ // read lazily by the AGENT_SKILLS provider below (which DI builds before discovery has run).
2869
+ {
2870
+ provide: import_nestjs_agent_core19.AGENT_SKILL_SOURCES,
2871
+ useFactory: /* @__PURE__ */ __name(() => [], "useFactory")
2872
+ },
2873
+ {
2874
+ // One resolution, shared by the loop's deps and the listing endpoint: a second one would
2875
+ // drift, and a user would be offered a skill the agent cannot reach. `undefined` when the
2876
+ // host configured none — which is what keeps the turn's checkpoint sequence unchanged.
2877
+ provide: import_nestjs_agent_core19.AGENT_SKILLS,
2878
+ useFactory: /* @__PURE__ */ __name((options, declared) => resolveSkillsConfig(options.skills, declared), "useFactory"),
2879
+ inject: [
2880
+ import_nestjs_agent_core19.AGENT_OPTIONS,
2881
+ import_nestjs_agent_core19.AGENT_SKILL_SOURCES
2882
+ ]
2883
+ },
2884
+ {
2885
+ // One resolution, shared by the loop's deps and the read-back endpoint: a person has to be
2886
+ // shown what the model was shown, and two resolutions would eventually disagree about that.
2887
+ provide: import_nestjs_agent_core19.AGENT_MEMORY,
2888
+ useFactory: /* @__PURE__ */ __name((options) => options.memory, "useFactory"),
2889
+ inject: [
2890
+ import_nestjs_agent_core19.AGENT_OPTIONS
2891
+ ]
2892
+ },
1844
2893
  {
1845
- provide: import_nestjs_agent_core14.AGENT_SINK,
2894
+ provide: import_nestjs_agent_core19.AGENT_SINK,
1846
2895
  useFactory: /* @__PURE__ */ __name((options) => options.sink ?? new InProcessTokenStreamSink(), "useFactory"),
1847
2896
  inject: [
1848
- import_nestjs_agent_core14.AGENT_OPTIONS
2897
+ import_nestjs_agent_core19.AGENT_OPTIONS
1849
2898
  ]
1850
2899
  },
1851
2900
  {
1852
- provide: import_nestjs_agent_core14.AGENT_ROLES_POLICY,
1853
- useFactory: /* @__PURE__ */ __name((options) => options.rolesPolicy ?? new import_nestjs_agent_core14.DefaultRolesPolicy(options.defaultRoles), "useFactory"),
2901
+ provide: import_nestjs_agent_core19.AGENT_ROLES_POLICY,
2902
+ useFactory: /* @__PURE__ */ __name((options) => options.rolesPolicy ?? new import_nestjs_agent_core19.DefaultRolesPolicy(options.defaultRoles), "useFactory"),
1854
2903
  inject: [
1855
- import_nestjs_agent_core14.AGENT_OPTIONS
2904
+ import_nestjs_agent_core19.AGENT_OPTIONS
1856
2905
  ]
1857
2906
  },
1858
2907
  {
1859
- provide: import_nestjs_agent_core14.AGENT_ACTOR_RESOLVER,
2908
+ provide: import_nestjs_agent_core19.AGENT_ACTOR_RESOLVER,
1860
2909
  useFactory: /* @__PURE__ */ __name((options) => options.actorResolver, "useFactory"),
1861
2910
  inject: [
1862
- import_nestjs_agent_core14.AGENT_OPTIONS
2911
+ import_nestjs_agent_core19.AGENT_OPTIONS
1863
2912
  ]
1864
2913
  },
1865
2914
  {
1866
- provide: import_nestjs_agent_core14.AGENT_MODEL,
2915
+ provide: import_nestjs_agent_core19.AGENT_MODEL,
1867
2916
  useFactory: /* @__PURE__ */ __name((o) => o.model, "useFactory"),
1868
2917
  inject: [
1869
- import_nestjs_agent_core14.AGENT_OPTIONS
2918
+ import_nestjs_agent_core19.AGENT_OPTIONS
1870
2919
  ]
1871
2920
  },
1872
2921
  {
1873
2922
  // An explicit `quota` wins; otherwise `quotaLimitTokens` binds the built-in ledger-backed
1874
2923
  // store; otherwise quotas are off (undefined). The ledger store reads the same usage rows
1875
2924
  // the loop already writes, so enforcement needs no extra shared state across replicas.
1876
- provide: import_nestjs_agent_core14.AGENT_QUOTA_STORE,
2925
+ provide: import_nestjs_agent_core19.AGENT_QUOTA_STORE,
1877
2926
  useFactory: /* @__PURE__ */ __name((o, store) => o.quota ?? (o.quotaLimitTokens !== void 0 ? new LedgerQuotaStore(store, o.quotaLimitTokens) : void 0), "useFactory"),
1878
2927
  inject: [
1879
- import_nestjs_agent_core14.AGENT_OPTIONS,
1880
- import_nestjs_agent_core14.AGENT_STORE
2928
+ import_nestjs_agent_core19.AGENT_OPTIONS,
2929
+ import_nestjs_agent_core19.AGENT_STORE
1881
2930
  ]
1882
2931
  },
1883
2932
  AgentDepsFactory2,
1884
2933
  {
1885
- provide: import_nestjs_agent_core14.AGENT_DEPS_FACTORY,
2934
+ provide: import_nestjs_agent_core19.AGENT_DEPS_FACTORY,
1886
2935
  useExisting: AgentDepsFactory2
1887
2936
  },
1888
2937
  // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes
1889
2938
  // handoff tools (onApplicationBootstrap) reads the registry.
1890
2939
  AgentDiscoveryService,
1891
2940
  AiToolDiscoveryService,
2941
+ SkillDiscoveryService,
1892
2942
  InlineAgentRunner,
1893
2943
  AgentService,
1894
2944
  // Bound ALWAYS (durable or inline) — the console's cross-thread approvals inbox routes decisions
1895
2945
  // through AgentService.signalToolCall, which reaches whichever AGENT_RUNNER is bound above.
1896
2946
  AgentApprovalPortAdapter,
1897
2947
  {
1898
- provide: import_nestjs_agent_core14.AGENT_APPROVAL_PORT,
2948
+ provide: import_nestjs_agent_core19.AGENT_APPROVAL_PORT,
1899
2949
  useExisting: AgentApprovalPortAdapter
1900
2950
  }
1901
2951
  ];
1902
2952
  if (includeStore) {
1903
2953
  providers.push({
1904
- provide: import_nestjs_agent_core14.AGENT_STORE,
2954
+ provide: import_nestjs_agent_core19.AGENT_STORE,
1905
2955
  useFactory: /* @__PURE__ */ __name((o) => o.store, "useFactory"),
1906
2956
  inject: [
1907
- import_nestjs_agent_core14.AGENT_OPTIONS
2957
+ import_nestjs_agent_core19.AGENT_OPTIONS
1908
2958
  ]
1909
2959
  });
1910
2960
  }
1911
2961
  if (durable) {
1912
2962
  providers.push({
1913
- provide: import_nestjs_agent_core14.AGENT_RUNNER,
2963
+ provide: import_nestjs_agent_core19.AGENT_RUNNER,
1914
2964
  useFactory: /* @__PURE__ */ __name((durableRunner) => {
1915
2965
  if (durableRunner === void 0) {
1916
2966
  throw new Error("AgentModule.forRoot({ durable: true }) requires importing AgentDurableModule from '@dudousxd/nestjs-agent/durable' (alongside a configured DurableModule). It was not found.");
@@ -1919,14 +2969,14 @@ function sharedProviders(durable, includeStore) {
1919
2969
  }, "useFactory"),
1920
2970
  inject: [
1921
2971
  {
1922
- token: import_nestjs_agent_core14.AGENT_DURABLE_RUNNER,
2972
+ token: import_nestjs_agent_core19.AGENT_DURABLE_RUNNER,
1923
2973
  optional: true
1924
2974
  }
1925
2975
  ]
1926
2976
  });
1927
2977
  } else {
1928
2978
  providers.push({
1929
- provide: import_nestjs_agent_core14.AGENT_RUNNER,
2979
+ provide: import_nestjs_agent_core19.AGENT_RUNNER,
1930
2980
  useExisting: InlineAgentRunner
1931
2981
  });
1932
2982
  }
@@ -1935,23 +2985,25 @@ function sharedProviders(durable, includeStore) {
1935
2985
  __name(sharedProviders, "sharedProviders");
1936
2986
  function exportsFor(includeStore) {
1937
2987
  return [
1938
- import_nestjs_agent_core14.AGENT_OPTIONS,
1939
- import_nestjs_agent_core14.AGENT_TOOL_REGISTRY,
1940
- import_nestjs_agent_core14.AGENT_REGISTRY,
1941
- import_nestjs_agent_core14.AGENT_SINK,
1942
- import_nestjs_agent_core14.AGENT_ROLES_POLICY,
1943
- import_nestjs_agent_core14.AGENT_ACTOR_RESOLVER,
1944
- import_nestjs_agent_core14.AGENT_MODEL,
2988
+ import_nestjs_agent_core19.AGENT_OPTIONS,
2989
+ import_nestjs_agent_core19.AGENT_TOOL_REGISTRY,
2990
+ import_nestjs_agent_core19.AGENT_REGISTRY,
2991
+ import_nestjs_agent_core19.AGENT_SINK,
2992
+ import_nestjs_agent_core19.AGENT_ROLES_POLICY,
2993
+ import_nestjs_agent_core19.AGENT_ACTOR_RESOLVER,
2994
+ import_nestjs_agent_core19.AGENT_MODEL,
1945
2995
  ...includeStore ? [
1946
- import_nestjs_agent_core14.AGENT_STORE
2996
+ import_nestjs_agent_core19.AGENT_STORE
1947
2997
  ] : [],
1948
- import_nestjs_agent_core14.AGENT_QUOTA_STORE,
1949
- import_nestjs_agent_core14.AGENT_PROMPT_CONTRIBUTORS,
1950
- import_nestjs_agent_core14.AGENT_DEPS_FACTORY,
2998
+ import_nestjs_agent_core19.AGENT_QUOTA_STORE,
2999
+ import_nestjs_agent_core19.AGENT_PROMPT_CONTRIBUTORS,
3000
+ import_nestjs_agent_core19.AGENT_SKILLS,
3001
+ import_nestjs_agent_core19.AGENT_MEMORY,
3002
+ import_nestjs_agent_core19.AGENT_DEPS_FACTORY,
1951
3003
  AgentDepsFactory2,
1952
3004
  AgentService,
1953
3005
  InlineAgentRunner,
1954
- import_nestjs_agent_core14.AGENT_APPROVAL_PORT
3006
+ import_nestjs_agent_core19.AGENT_APPROVAL_PORT
1955
3007
  ];
1956
3008
  }
1957
3009
  __name(exportsFor, "exportsFor");
@@ -1960,7 +3012,9 @@ var BASE_CONTROLLERS = [
1960
3012
  ThreadsController,
1961
3013
  ToolCallController,
1962
3014
  QuotaController,
1963
- AgentsController
3015
+ AgentsController,
3016
+ SkillsController,
3017
+ MemoriesController
1964
3018
  ];
1965
3019
  var GUARDABLE_CONTROLLERS = [
1966
3020
  ...BASE_CONTROLLERS,
@@ -1992,7 +3046,7 @@ function guardProviders(guards) {
1992
3046
  }
1993
3047
  __name(guardProviders, "guardProviders");
1994
3048
  function routerFor(path) {
1995
- return import_core3.RouterModule.register([
3049
+ return import_core4.RouterModule.register([
1996
3050
  {
1997
3051
  path,
1998
3052
  module: AgentModule
@@ -2019,13 +3073,13 @@ var AgentModule = class _AgentModule {
2019
3073
  module: _AgentModule,
2020
3074
  global: true,
2021
3075
  imports: [
2022
- import_core3.DiscoveryModule,
3076
+ import_core4.DiscoveryModule,
2023
3077
  routerFor(path)
2024
3078
  ],
2025
3079
  controllers: controllersForSurface(options.surface, options.attachments?.upload === true),
2026
3080
  providers: [
2027
3081
  {
2028
- provide: import_nestjs_agent_core14.AGENT_OPTIONS,
3082
+ provide: import_nestjs_agent_core19.AGENT_OPTIONS,
2029
3083
  useValue: options
2030
3084
  },
2031
3085
  ...sharedProviders(options.durable ?? false, includeStore),
@@ -2043,14 +3097,14 @@ var AgentModule = class _AgentModule {
2043
3097
  module: _AgentModule,
2044
3098
  global: true,
2045
3099
  imports: [
2046
- import_core3.DiscoveryModule,
3100
+ import_core4.DiscoveryModule,
2047
3101
  routerFor(path),
2048
3102
  ...options.imports ?? []
2049
3103
  ],
2050
3104
  controllers: controllersForSurface(options.surface, options.attachmentsUpload === true),
2051
3105
  providers: [
2052
3106
  {
2053
- provide: import_nestjs_agent_core14.AGENT_OPTIONS,
3107
+ provide: import_nestjs_agent_core19.AGENT_OPTIONS,
2054
3108
  // Stamp the STATIC wiring flags onto the factory result: `durable`/`dispatchedSteps`/
2055
3109
  // `surface` are authoritative on the async config object (they decided the actual wiring
2056
3110
  // above), and `AgentDurableModule` derives the effective dispatched-steps value from
@@ -2075,12 +3129,13 @@ var AgentModule = class _AgentModule {
2075
3129
  };
2076
3130
  }
2077
3131
  };
2078
- AgentModule = _ts_decorate13([
2079
- (0, import_common13.Global)(),
2080
- (0, import_common13.Module)({})
3132
+ AgentModule = _ts_decorate16([
3133
+ (0, import_common16.Global)(),
3134
+ (0, import_common16.Module)({})
2081
3135
  ], AgentModule);
2082
3136
 
2083
3137
  // src/resolver/header-actor-resolver.ts
3138
+ var import_common17 = require("@nestjs/common");
2084
3139
  function readHeader(req, name) {
2085
3140
  if (typeof req !== "object" || req === null || !("headers" in req)) return void 0;
2086
3141
  const { headers } = req;
@@ -2096,7 +3151,7 @@ var HeaderActorResolver = class {
2096
3151
  resolve(req) {
2097
3152
  const id = readHeader(req, "x-actor-id");
2098
3153
  if (id === void 0 || id.length === 0) {
2099
- throw new Error("HeaderActorResolver: missing x-actor-id header. No default actor is fabricated. Send x-actor-id from a trusted gateway, or configure AgentModule.forRoot({ actorResolver }) with a resolver that reads your authenticated principal.");
3154
+ throw new import_common17.UnauthorizedException("HeaderActorResolver: missing x-actor-id header. No default actor is fabricated. Send x-actor-id from a trusted gateway, or configure AgentModule.forRoot({ actorResolver }) with a resolver that reads your authenticated principal.");
2100
3155
  }
2101
3156
  const roles = (readHeader(req, "x-actor-role") ?? "").split(",").map((role) => role.trim()).filter((role) => role.length > 0);
2102
3157
  const tenantRef = readHeader(req, "x-tenant-ref");
@@ -2117,6 +3172,7 @@ __reExport(index_exports, require("@dudousxd/nestjs-agent-core"), module.exports
2117
3172
  AGENT_METADATA,
2118
3173
  AGENT_TOOL_BRAND,
2119
3174
  AI_TOOL_METADATA,
3175
+ ATTACHMENT_PAGE_SIZE,
2120
3176
  Agent,
2121
3177
  AgentApprovalPortAdapter,
2122
3178
  AgentDepsFactory,
@@ -2132,14 +3188,23 @@ __reExport(index_exports, require("@dudousxd/nestjs-agent-core"), module.exports
2132
3188
  InProcessTokenStreamSink,
2133
3189
  InlineAgentRunner,
2134
3190
  LedgerQuotaStore,
3191
+ MemoriesController,
3192
+ SKILL_METADATA,
2135
3193
  SYSTEM_PROMPT_CONTRIBUTOR_METADATA,
2136
3194
  SYSTEM_PROMPT_METADATA,
3195
+ Skill,
3196
+ SkillDiscoveryService,
3197
+ SkillsController,
2137
3198
  SystemPrompt,
2138
3199
  SystemPromptContributor,
3200
+ declaredSkillProvider,
2139
3201
  delegateToolName,
2140
3202
  provideAgentTool,
2141
3203
  readAgentMetadata,
2142
3204
  readAiToolMetadata,
3205
+ readSkillMetadata,
3206
+ resolveSkillsConfig,
3207
+ skillScope,
2143
3208
  utcDay,
2144
3209
  ...require("@dudousxd/nestjs-agent-core")
2145
3210
  });