@dudousxd/nestjs-agent 1.19.2 → 1.20.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.
@@ -3,7 +3,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3
3
 
4
4
  // src/durable/agent-run.workflow.ts
5
5
  import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE, RUN_ENDED_BEFORE_TOOL_CALL, RunCancelledError, agentFailureCode, encodeStreamEvent as encodeStreamEvent2, isReplayIntegrityError, publishAgentRunFailed, releaseThreadRun, runAgentLoop, settleAll, settleDeadRun, settleUnsettledDelegation, streamFailure } from "@dudousxd/nestjs-agent-core";
6
- import { RUN_GATEWAY, Workflow } from "@dudousxd/nestjs-durable";
6
+ import { RUN_GATEWAY, Workflow, WorkflowService } from "@dudousxd/nestjs-durable";
7
7
  import { isWorkflowControlFlowSignal } from "@dudousxd/nestjs-durable-core";
8
8
  import { Inject as Inject2, Injectable as Injectable2, Logger, Optional } from "@nestjs/common";
9
9
 
@@ -33,7 +33,7 @@ __name(childSinkWriter, "childSinkWriter");
33
33
  var AGENT_CHAT_QUEUE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:chat-queue");
34
34
 
35
35
  // src/durable/agent-run.steps.ts
36
- import { AGENT_DEPS_FACTORY, createFrameBuffer, createUiCollector, encodeStreamEvent, invokeWithTransientRetry, observeTurnFrames, publishAgentToolRetry, stampToolKinds, toolCallContext, traceLlmTurn, traceToolExecution, withAskTool, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
36
+ import { AGENT_DEPS_FACTORY, createFrameBuffer, createUiCollector, encodeStreamEvent, intersectAllowLists, invokeWithTransientRetry, observeTurnFrames, publishAgentToolRetry, stampToolKinds, toolCallContext, traceLlmTurn, traceToolExecution, withAskTool, withMemoryTool, withSkillTool, withToolTimeout, withTurnFrames, wrapToolStepOutput } from "@dudousxd/nestjs-agent-core";
37
37
  import { Step } from "@dudousxd/nestjs-durable";
38
38
  import { Inject, Injectable } from "@nestjs/common";
39
39
 
@@ -97,14 +97,21 @@ var AgentRunSteps = class {
97
97
  const tools = withMemoryTool({
98
98
  tools: withSkillTool({
99
99
  tools: withAskTool({
100
- tools: await deps.registry.definitionsFor(input.actor, deps.rolesPolicy, deps.toolAllowList, {
101
- ...input.threadId !== void 0 ? {
102
- threadId: input.threadId
103
- } : {},
104
- ...input.agentName !== void 0 ? {
105
- agentName: input.agentName
106
- } : {}
107
- }),
100
+ tools: await deps.registry.definitionsFor(
101
+ input.actor,
102
+ deps.rolesPolicy,
103
+ // The persona narrowing the loop journaled in `persona:resolve` rides the envelope:
104
+ // this worker's own persona config may already say something else.
105
+ intersectAllowLists(deps.toolAllowList, input.personaAllowedTools),
106
+ {
107
+ ...input.threadId !== void 0 ? {
108
+ threadId: input.threadId
109
+ } : {},
110
+ ...input.agentName !== void 0 ? {
111
+ agentName: input.agentName
112
+ } : {}
113
+ }
114
+ ),
108
115
  ask: deps.ask
109
116
  }),
110
117
  enabled: deps.skills !== void 0
@@ -177,7 +184,9 @@ var AgentRunSteps = class {
177
184
  toolType: input.toolType
178
185
  }, () => invokeWithTransientRetry(() => {
179
186
  ui.restart();
180
- const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy);
187
+ const invocation = deps.registry.invoke(input.toolName, input.input, ctx, deps.rolesPolicy, input.allowedTools !== void 0 ? {
188
+ allowedTools: input.allowedTools
189
+ } : {});
181
190
  return input.timeoutMs !== void 0 ? withToolTimeout(invocation, input.timeoutMs, input.toolName) : invocation;
182
191
  }, transientRetry, {
183
192
  onRetry: /* @__PURE__ */ __name((attempt, error) => {
@@ -254,12 +263,60 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
254
263
  store;
255
264
  runs;
256
265
  queue;
266
+ workflows;
257
267
  logger = new Logger(_AgentRunWorkflow.name);
258
- constructor(factory, store, runs, queue) {
268
+ constructor(factory, store, runs, queue, workflows) {
259
269
  this.factory = factory;
260
270
  this.store = store;
261
271
  this.runs = runs;
262
272
  this.queue = queue;
273
+ this.workflows = workflows;
274
+ }
275
+ /**
276
+ * Start a detached delegation as a TOP-LEVEL run, under an id derived from this run and the call.
277
+ *
278
+ * Not `ctx.startChild`, because the runtime treats a `spawn:` child as part of its parent: a Stop
279
+ * on the parent cascades to every run it spawned. A detached run is exactly the one the person did
280
+ * NOT ask to stop — they stopped the turn they were watching, and the work it handed off is meant
281
+ * to outlive that turn (it is meant to outlive it finishing, after all). Cascaded, it died parked
282
+ * on its approval, where its body never runs again, so nothing settled the delegation and the card
283
+ * said "started" for ever. The agent-level edge stays: the child's input still carries
284
+ * `parentRunId`, which is what the run rows record.
285
+ *
286
+ * Journaled as one `detach:<toolCallId>` localStep whose body runs outside the ambient workflow
287
+ * ctx (so the start goes to the engine and writes no position in this run). Its recorded result
288
+ * keeps a replay from starting it again, and a body re-run after a crash between the start and
289
+ * the checkpoint asks for the same id, which the runtime answers with the run it already has.
290
+ * The child is stamped with this run's namespace, as `ctx.startChild` would have stamped it, so an
291
+ * operator re-driving a tenant's turn does not move its delegate off that tenant's workers.
292
+ */
293
+ startDetached(ctx, toolCallId2, childInput) {
294
+ return stepOf(ctx)(`detach:${toolCallId2}`, async () => {
295
+ const workflows = this.workflows;
296
+ if (workflows === void 0) {
297
+ throw new Error("A detached delegation needs WorkflowService (DurableModule) to start its run, and none is bound.");
298
+ }
299
+ const childRunId = `${ctx.runId}.detached.${toolCallId2}`;
300
+ const namespace = await this.namespaceOf(ctx.runId);
301
+ try {
302
+ await workflows.start(_AgentRunWorkflow, childInput, childRunId, namespace !== void 0 ? {
303
+ namespace
304
+ } : void 0);
305
+ } catch (error) {
306
+ if (!isWorkflowControlFlowSignal(error)) {
307
+ throw error;
308
+ }
309
+ }
310
+ return childRunId;
311
+ });
312
+ }
313
+ /** The namespace this run is stamped with, where the runtime can say. */
314
+ async namespaceOf(runId) {
315
+ try {
316
+ return (await this.runs?.getRunDetail(runId))?.run.namespace;
317
+ } catch {
318
+ return void 0;
319
+ }
263
320
  }
264
321
  /**
265
322
  * Move the thread past this settling turn — to the next queued message, started here as a
@@ -460,6 +517,10 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
460
517
  // OWN runId, and that is what `runForToolCall` answers with.
461
518
  // - `deliverTo` instead. The parent's tool result is a receipt, so the answer needs an
462
519
  // address of its own, and by the time it exists nobody is holding one.
520
+ // - no runtime parent. A Stop on this turn must not reach the work it handed off, so the
521
+ // run is started on its own (`startDetached`), not as a `spawn:` child. A run that
522
+ // journaled the `spawn:` before this release replays it: `ctx.patched` answers false at a
523
+ // position that already holds one.
463
524
  startAgent: /* @__PURE__ */ __name(async ({ agentName, task, toolCallId: toolCallId2 }) => {
464
525
  const subThreadId = await stepOf(ctx)(`subthread:${agentName}`, async () => {
465
526
  const thread = await this.store.createThread({
@@ -468,7 +529,7 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
468
529
  });
469
530
  return thread.id;
470
531
  });
471
- const childRunId = await ctx.startChild(_AgentRunWorkflow, {
532
+ const childInput = {
472
533
  agentName,
473
534
  threadId: subThreadId,
474
535
  actor: input.actor,
@@ -481,9 +542,14 @@ var AgentRunWorkflow = class _AgentRunWorkflow {
481
542
  threadId: input.threadId,
482
543
  toolCallId: toolCallId2
483
544
  }
484
- });
545
+ };
546
+ if (!await ctx.patched("agent:detached-unlinked")) {
547
+ return {
548
+ runId: await ctx.startChild(_AgentRunWorkflow, childInput)
549
+ };
550
+ }
485
551
  return {
486
- runId: childRunId
552
+ runId: await this.startDetached(ctx, toolCallId2, childInput)
487
553
  };
488
554
  }, "startAgent"),
489
555
  // The two long steps as engine-dispatched `ctx.step`s, so a turn isn't pinned to this
@@ -596,12 +662,14 @@ AgentRunWorkflow = _ts_decorate2([
596
662
  _ts_param2(2, Inject2(RUN_GATEWAY)),
597
663
  _ts_param2(3, Optional()),
598
664
  _ts_param2(3, Inject2(AGENT_CHAT_QUEUE)),
665
+ _ts_param2(4, Optional()),
599
666
  _ts_metadata2("design:type", Function),
600
667
  _ts_metadata2("design:paramtypes", [
601
668
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
602
669
  typeof AgentStore === "undefined" ? Object : AgentStore,
603
670
  typeof RunGateway === "undefined" ? Object : RunGateway,
604
- typeof ChatQueueService === "undefined" ? Object : ChatQueueService
671
+ typeof ChatQueueService === "undefined" ? Object : ChatQueueService,
672
+ typeof WorkflowService === "undefined" ? Object : WorkflowService
605
673
  ])
606
674
  ], AgentRunWorkflow);
607
675
  function isSignalTimeout(error) {
@@ -611,8 +679,8 @@ __name(isSignalTimeout, "isSignalTimeout");
611
679
 
612
680
  // src/durable/durable-agent-runner.ts
613
681
  import { randomUUID } from "crypto";
614
- import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent3, releaseThreadRun as releaseThreadRun2 } from "@dudousxd/nestjs-agent-core";
615
- import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService } from "@dudousxd/nestjs-durable";
682
+ import { AGENT_SINK, AGENT_STORE as AGENT_STORE2, encodeStreamEvent as encodeStreamEvent3, releaseThreadRun as releaseThreadRun2, settleUnsettledDelegation as settleUnsettledDelegation2 } from "@dudousxd/nestjs-agent-core";
683
+ import { RUN_GATEWAY as RUN_GATEWAY2, WorkflowService as WorkflowService2 } from "@dudousxd/nestjs-durable";
616
684
  import { isWorkflowControlFlowSignal as isWorkflowControlFlowSignal2 } from "@dudousxd/nestjs-durable-core";
617
685
  import { Inject as Inject3, Injectable as Injectable3, Logger as Logger2, Optional as Optional2 } from "@nestjs/common";
618
686
 
@@ -722,6 +790,20 @@ function isThreadTurn(input) {
722
790
  return typeof input === "object" && input !== null && input.sinkRunId === void 0 && input.deliverTo === void 0;
723
791
  }
724
792
  __name(isThreadTurn, "isThreadTurn");
793
+ function deliveryOf(input) {
794
+ if (typeof input !== "object" || input === null) {
795
+ return void 0;
796
+ }
797
+ const { deliverTo, agentName } = input;
798
+ if (typeof deliverTo !== "object" || deliverTo === null || typeof deliverTo.threadId !== "string" || typeof deliverTo.toolCallId !== "string") {
799
+ return void 0;
800
+ }
801
+ return {
802
+ delivery: deliverTo,
803
+ agent: typeof agentName === "string" ? agentName : "default"
804
+ };
805
+ }
806
+ __name(deliveryOf, "deliveryOf");
725
807
  var DurableAgentRunner = class _DurableAgentRunner {
726
808
  static {
727
809
  __name(this, "DurableAgentRunner");
@@ -801,11 +883,16 @@ var DurableAgentRunner = class _DurableAgentRunner {
801
883
  */
802
884
  async cancel(runId) {
803
885
  this.logger.log(`cancelling agent run ${runId}`);
804
- const input = await this.inputOf(runId);
886
+ const detail = await this.detailOf(runId);
887
+ const input = detail?.run.input;
805
888
  const threadId = threadOfRun(input);
806
889
  await this.runs.cancel(runId, {
807
890
  compensate: true
808
891
  });
892
+ await this.settleCancelledDelegation(runId, input);
893
+ for (const childId of detail?.children ?? []) {
894
+ await this.settleCascadedDetached(childId);
895
+ }
809
896
  const writer = await this.sink.open(runId);
810
897
  if (threadId !== void 0) {
811
898
  if (this.queue?.supported === true && isThreadTurn(input)) {
@@ -836,7 +923,57 @@ var DurableAgentRunner = class _DurableAgentRunner {
836
923
  });
837
924
  }
838
925
  /**
839
- * The input a run was started with (which thread it was streaming), or `undefined` where the gateway cannot say.
926
+ * Settle the delegation a DETACHED run was started for, once it has been stopped. A run parked on
927
+ * a human never runs its body again — the runtime settles it from outside — so the body's own
928
+ * `deliver:detached:unsettled` is not reached, and without this the card in the calling thread says
929
+ * "started" for ever. Settles once (see `settleUnsettledDelegation`), so a body that did observe
930
+ * the Stop and a run that had already answered are both left as they are. A no-op for any run
931
+ * that does not deliver into another thread.
932
+ */
933
+ async settleCancelledDelegation(runId, input) {
934
+ const target = deliveryOf(input);
935
+ if (target === void 0) {
936
+ return;
937
+ }
938
+ try {
939
+ await settleUnsettledDelegation2({
940
+ store: this.store,
941
+ delivery: target.delivery,
942
+ agent: target.agent,
943
+ runId,
944
+ status: "cancelled"
945
+ });
946
+ } catch (error) {
947
+ this.logger.error(`could not settle the delegation of cancelled run ${runId}: ${error instanceof Error ? error.message : String(error)}`);
948
+ }
949
+ }
950
+ /**
951
+ * A detached child the runtime cancelled along with its parent (a `spawn:` journaled before
952
+ * detached runs were started on their own): end it the way a Stop on its own id would have.
953
+ */
954
+ async settleCascadedDetached(childId) {
955
+ const child = await this.detailOf(childId);
956
+ const status = child?.run.status;
957
+ if (child === void 0 || deliveryOf(child.run.input) === void 0 || status !== "cancelled" && status !== "cancelling") {
958
+ return;
959
+ }
960
+ const subThreadId = threadOfRun(child.run.input);
961
+ if (subThreadId !== void 0) {
962
+ await releaseThreadRun2(this.store, subThreadId, childId);
963
+ }
964
+ await this.settleCancelledDelegation(childId, child.run.input);
965
+ const writer = await this.sink.open(childId);
966
+ await writer.write(encodeStreamEvent3({
967
+ kind: "cancelled"
968
+ }));
969
+ await writer.end();
970
+ await this.store.recordRunEnd?.({
971
+ runId: childId,
972
+ status: "cancelled"
973
+ });
974
+ }
975
+ /**
976
+ * What the runtime recorded for a run — the input it was started with (which thread it was streaming), its status and the runs it spawned — or `undefined` where the gateway cannot say.
840
977
  *
841
978
  * A read failure answers `undefined` instead of propagating, the same posture `AgentRunWorkflow`
842
979
  * takes for its own cancel observation: failing to ask is not an answer worth failing a cancel
@@ -845,9 +982,9 @@ var DurableAgentRunner = class _DurableAgentRunner {
845
982
  * with a subscriber holding a stream that never settles, from the one call whose entire job is to
846
983
  * make a run stop.
847
984
  */
848
- async inputOf(runId) {
985
+ async detailOf(runId) {
849
986
  try {
850
- return (await this.runs.getRunDetail(runId))?.run.input;
987
+ return await this.runs.getRunDetail(runId) ?? void 0;
851
988
  } catch {
852
989
  return void 0;
853
990
  }
@@ -862,7 +999,7 @@ DurableAgentRunner = _ts_decorate3([
862
999
  _ts_param3(4, Inject3(AGENT_CHAT_QUEUE)),
863
1000
  _ts_metadata3("design:type", Function),
864
1001
  _ts_metadata3("design:paramtypes", [
865
- typeof WorkflowService === "undefined" ? Object : WorkflowService,
1002
+ typeof WorkflowService2 === "undefined" ? Object : WorkflowService2,
866
1003
  typeof RunGateway === "undefined" ? Object : RunGateway,
867
1004
  typeof AgentStore === "undefined" ? Object : AgentStore,
868
1005
  typeof TokenStreamSink === "undefined" ? Object : TokenStreamSink,
@@ -957,14 +1094,14 @@ AgentDurableModule = _ts_decorate4([
957
1094
  ], AgentDurableModule);
958
1095
 
959
1096
  // src/agent.module.ts
960
- import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER13, AGENT_APPROVAL_PORT, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY7, AGENT_DURABLE_RUNNER as AGENT_DURABLE_RUNNER2, AGENT_MEMORY as AGENT_MEMORY3, AGENT_MODEL as AGENT_MODEL2, AGENT_MODEL_CATALOG as AGENT_MODEL_CATALOG3, AGENT_OPTIONS as AGENT_OPTIONS7, AGENT_PROMPT_CONTRIBUTORS as AGENT_PROMPT_CONTRIBUTORS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER3, AGENT_REGISTRY as AGENT_REGISTRY6, AGENT_ROLES_POLICY as AGENT_ROLES_POLICY2, AGENT_RUNNER as AGENT_RUNNER2, AGENT_SINK as AGENT_SINK4, AGENT_SKILLS as AGENT_SKILLS3, AGENT_SKILL_SOURCES as AGENT_SKILL_SOURCES2, AGENT_STORE as AGENT_STORE7, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY3, AgentRegistry as AgentRegistry6, ClosedRolesPolicy, DefaultRolesPolicy, InMemoryAgentStore, ToolRegistry as ToolRegistry3 } from "@dudousxd/nestjs-agent-core";
1097
+ import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER13, AGENT_APPROVAL_PORT, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY8, AGENT_DURABLE_RUNNER as AGENT_DURABLE_RUNNER2, AGENT_MEMORY as AGENT_MEMORY3, AGENT_MODEL as AGENT_MODEL2, AGENT_MODEL_CATALOG as AGENT_MODEL_CATALOG3, AGENT_OPTIONS as AGENT_OPTIONS7, AGENT_PROMPT_CONTRIBUTORS as AGENT_PROMPT_CONTRIBUTORS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER3, AGENT_REGISTRY as AGENT_REGISTRY6, AGENT_ROLES_POLICY as AGENT_ROLES_POLICY2, AGENT_RUNNER as AGENT_RUNNER2, AGENT_SINK as AGENT_SINK4, AGENT_SKILLS as AGENT_SKILLS3, AGENT_SKILL_SOURCES as AGENT_SKILL_SOURCES2, AGENT_STORE as AGENT_STORE7, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY3, AgentRegistry as AgentRegistry6, ClosedRolesPolicy, DefaultRolesPolicy, InMemoryAgentStore, ToolRegistry as ToolRegistry3 } from "@dudousxd/nestjs-agent-core";
961
1098
  import { Global as Global2, Logger as Logger8, Module as Module2 } from "@nestjs/common";
962
1099
  import { DiscoveryModule, ModulesContainer, RouterModule } from "@nestjs/core";
963
1100
 
964
1101
  // src/agent-deps.factory.ts
965
- import { AGENT_MEMORY, AGENT_MODEL, AGENT_PRICING_STORE, AGENT_PROMPT_CONTRIBUTORS, AGENT_REGISTRY, AGENT_ROLES_POLICY, AGENT_SINK as AGENT_SINK2, AGENT_SKILLS, AGENT_STORE as AGENT_STORE3, AGENT_TOOL_REGISTRY, AgentRegistry as AgentRegistry2, ToolRegistry as ToolRegistry2, normalizeDelegation, summarizeWithModel, windowHistory } from "@dudousxd/nestjs-agent-core";
1102
+ import { AGENT_MEMORY, AGENT_MODEL, AGENT_PRICING_STORE, AGENT_PROMPT_CONTRIBUTORS, AGENT_REGISTRY, AGENT_ROLES_POLICY, AGENT_SINK as AGENT_SINK2, AGENT_SKILLS, AGENT_STORE as AGENT_STORE3, AGENT_TOOL_REGISTRY, AgentRegistry as AgentRegistry2, ToolRegistry as ToolRegistry2, findPersona, intersectAllowLists as intersectAllowLists2, normalizeDelegation, personaCatalogEntry, resolvePersonaAlias, summarizeWithModel, windowHistory } from "@dudousxd/nestjs-agent-core";
966
1103
  import { AGENT_OPTIONS } from "@dudousxd/nestjs-agent-core";
967
- import { Inject as Inject4, Injectable as Injectable4, Optional as Optional3 } from "@nestjs/common";
1104
+ import { BadRequestException, Inject as Inject4, Injectable as Injectable4, Optional as Optional3 } from "@nestjs/common";
968
1105
  function _ts_decorate5(decorators, target, key, desc) {
969
1106
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
970
1107
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -1062,8 +1199,64 @@ var AgentDepsFactory2 = class {
1062
1199
  ...delegated
1063
1200
  ];
1064
1201
  }
1202
+ /**
1203
+ * The agent a name stands for: itself when it is a registered agent (or unknown — the bare
1204
+ * assistant), else the agent whose persona took the name over (`Persona.aliases`) and that persona.
1205
+ */
1206
+ resolveAgent(name) {
1207
+ if (this.agents.has(name)) {
1208
+ return {
1209
+ agentName: name
1210
+ };
1211
+ }
1212
+ const alias = resolvePersonaAlias(this.agents.list(), name);
1213
+ return alias === void 0 ? {
1214
+ agentName: name
1215
+ } : {
1216
+ agentName: alias.agent,
1217
+ persona: alias.persona
1218
+ };
1219
+ }
1220
+ /** `agentName`'s personas as a picker reads them. Empty when it declares none. */
1221
+ personaCatalog(agentName) {
1222
+ return (this.agents.get(agentName)?.personas ?? []).map(personaCatalogEntry);
1223
+ }
1224
+ /** The persona `agentName` runs under when nothing names one. Undefined → none. */
1225
+ defaultPersona(agentName) {
1226
+ return this.agents.get(agentName)?.defaultPersona;
1227
+ }
1228
+ /**
1229
+ * The persona a turn of `agentName` runs under, most specific first: the one the send names
1230
+ * (refused with `400 persona_not_found` when the agent does not declare it), else the thread's
1231
+ * pinned one when this agent declares it, else the agent's default. Undefined → none.
1232
+ */
1233
+ resolvePersona(args) {
1234
+ const definition = this.agents.get(args.agentName);
1235
+ if (args.requested !== void 0) {
1236
+ if (findPersona(definition, args.requested) === void 0) {
1237
+ throw new BadRequestException({
1238
+ statusCode: 400,
1239
+ code: "persona_not_found",
1240
+ message: `agent "${args.agentName}" has no persona "${args.requested}"`
1241
+ });
1242
+ }
1243
+ return args.requested;
1244
+ }
1245
+ const pinned = args.threadPersona ?? void 0;
1246
+ if (pinned !== void 0 && findPersona(definition, pinned) !== void 0) {
1247
+ return pinned;
1248
+ }
1249
+ return definition?.defaultPersona;
1250
+ }
1065
1251
  forAgent(agentName) {
1066
1252
  const name = agentName ?? this.defaultAgentName();
1253
+ if (agentName !== void 0 && !this.agents.has(agentName)) {
1254
+ const alias = resolvePersonaAlias(this.agents.list(), agentName);
1255
+ const persona = alias === void 0 ? void 0 : findPersona(this.agents.get(alias.agent), alias.persona);
1256
+ if (alias !== void 0 && persona !== void 0) {
1257
+ return this.withPersona(this.forAgent(alias.agent), persona);
1258
+ }
1259
+ }
1067
1260
  const definition = this.agents.get(name);
1068
1261
  const toolAllowList = this.effectiveTools(definition);
1069
1262
  const followUpsCount = this.followUpsCount();
@@ -1128,6 +1321,9 @@ var AgentDepsFactory2 = class {
1128
1321
  ...toolAllowList !== void 0 ? {
1129
1322
  toolAllowList
1130
1323
  } : {},
1324
+ ...definition?.personas !== void 0 ? {
1325
+ personas: definition.personas
1326
+ } : {},
1131
1327
  ...this.options.toolTimeoutMs !== void 0 ? {
1132
1328
  toolTimeoutMs: this.options.toolTimeoutMs
1133
1329
  } : {},
@@ -1146,6 +1342,45 @@ var AgentDepsFactory2 = class {
1146
1342
  };
1147
1343
  }
1148
1344
  /**
1345
+ * A persona baked into an agent's deps — how a run journaled under an agent name that a persona
1346
+ * has since taken over (`Persona.aliases`) is served. That run names no persona of its own (it
1347
+ * predates them, and its input cannot change), so the persona applies the way the old agent's own
1348
+ * config did: as config, re-read on every replay, with no checkpoint of its own.
1349
+ */
1350
+ withPersona(deps, persona) {
1351
+ const base = deps.systemPrompt;
1352
+ const ref = {
1353
+ id: persona.id,
1354
+ label: persona.label
1355
+ };
1356
+ const resolve = /* @__PURE__ */ __name(async (prompt, ctx) => typeof prompt === "function" ? prompt(ctx) : prompt, "resolve");
1357
+ const own = persona.systemPrompt;
1358
+ const systemPrompt = /* @__PURE__ */ __name(async (ctx) => {
1359
+ const scoped = {
1360
+ ...ctx,
1361
+ persona: ref
1362
+ };
1363
+ if (own === void 0) {
1364
+ return resolve(base, scoped);
1365
+ }
1366
+ const basePrompt = typeof own === "function" ? await resolve(base, scoped) : void 0;
1367
+ return resolve(own, {
1368
+ ...scoped,
1369
+ ...basePrompt !== void 0 ? {
1370
+ basePrompt
1371
+ } : {}
1372
+ });
1373
+ }, "systemPrompt");
1374
+ const toolAllowList = intersectAllowLists2(deps.toolAllowList, persona.allowedTools);
1375
+ return {
1376
+ ...deps,
1377
+ systemPrompt,
1378
+ ...toolAllowList !== void 0 ? {
1379
+ toolAllowList
1380
+ } : {}
1381
+ };
1382
+ }
1383
+ /**
1149
1384
  * The ceiling on how much of a thread this agent's turns carry, most specific wins: the agent's
1150
1385
  * own `@Agent({ history })`, else a module-wide custom `historyPolicy`, else the module-wide
1151
1386
  * `history` window. Undefined → unbounded, the behaviour of a module that configures none.
@@ -1220,12 +1455,24 @@ AgentDepsFactory2 = _ts_decorate5([
1220
1455
  ], AgentDepsFactory2);
1221
1456
 
1222
1457
  // src/agent.service.ts
1223
- import { AGENT_ATTACHMENT_STAGING as AGENT_ATTACHMENT_STAGING2, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_MODEL_CATALOG, AGENT_OPTIONS as AGENT_OPTIONS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE5, REQUESTER_APPROVER, findCatalogModel, mayDecideApproval, readElicitationQuestions, settleDeadRun as settleDeadRun2, validateElicitationAnswer } from "@dudousxd/nestjs-agent-core";
1224
- import { BadRequestException, ConflictException as ConflictException2, ForbiddenException, GoneException, HttpException, HttpStatus, Inject as Inject6, Injectable as Injectable6, NotFoundException, NotImplementedException as NotImplementedException2, Optional as Optional5 } from "@nestjs/common";
1458
+ import { AGENT_ATTACHMENT_STAGING as AGENT_ATTACHMENT_STAGING2, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY4, AGENT_MODEL_CATALOG, AGENT_OPTIONS as AGENT_OPTIONS3, AGENT_QUOTA_PROVIDER as AGENT_QUOTA_PROVIDER2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE5, REQUESTER_APPROVER, findCatalogModel, mayDecideApproval, readElicitationQuestions, settleDeadRun as settleDeadRun2, validateElicitationAnswer } from "@dudousxd/nestjs-agent-core";
1459
+ import { BadRequestException as BadRequestException2, ConflictException as ConflictException2, ForbiddenException, GoneException, HttpException, HttpStatus, Inject as Inject6, Injectable as Injectable6, NotFoundException, NotImplementedException as NotImplementedException2, Optional as Optional5 } from "@nestjs/common";
1225
1460
 
1226
1461
  // src/queue/chat-queue.service.ts
1227
- import { AGENT_ATTACHMENT_STAGING, AGENT_OPTIONS as AGENT_OPTIONS2, AGENT_QUOTA_PROVIDER, AGENT_SINK as AGENT_SINK3, AGENT_STORE as AGENT_STORE4, encodeStreamEvent as encodeStreamEvent4, isChatQueueStore, queuedMessageView } from "@dudousxd/nestjs-agent-core";
1462
+ import { AGENT_ATTACHMENT_STAGING, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_OPTIONS as AGENT_OPTIONS2, AGENT_QUOTA_PROVIDER, AGENT_SINK as AGENT_SINK3, AGENT_STORE as AGENT_STORE4, encodeStreamEvent as encodeStreamEvent4, isChatQueueStore, queuedMessageView } from "@dudousxd/nestjs-agent-core";
1228
1463
  import { Inject as Inject5, Injectable as Injectable5, Logger as Logger3, NotImplementedException, Optional as Optional4 } from "@nestjs/common";
1464
+
1465
+ // src/thread-persona.ts
1466
+ async function threadPersona(store, threadId) {
1467
+ const projecting = store;
1468
+ if (typeof projecting.personaForThread === "function") {
1469
+ return projecting.personaForThread(threadId);
1470
+ }
1471
+ return (await store.getThread(threadId))?.persona ?? null;
1472
+ }
1473
+ __name(threadPersona, "threadPersona");
1474
+
1475
+ // src/queue/chat-queue.service.ts
1229
1476
  function _ts_decorate6(decorators, target, key, desc) {
1230
1477
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1231
1478
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -1262,18 +1509,20 @@ var ChatQueueService2 = class _ChatQueueService {
1262
1509
  quotaProvider;
1263
1510
  options;
1264
1511
  staging;
1512
+ deps;
1265
1513
  logger = new Logger3(_ChatQueueService.name);
1266
1514
  /**
1267
1515
  * Runs this process claimed a thread for and has not handed to a runner yet. A holder in here is
1268
1516
  * alive whatever the runner says — it simply has not registered the run yet.
1269
1517
  */
1270
1518
  starting = /* @__PURE__ */ new Set();
1271
- constructor(store, sink, quotaProvider, options, staging) {
1519
+ constructor(store, sink, quotaProvider, options, staging, deps) {
1272
1520
  this.store = store;
1273
1521
  this.sink = sink;
1274
1522
  this.quotaProvider = quotaProvider;
1275
1523
  this.options = options;
1276
1524
  this.staging = staging;
1525
+ this.deps = deps;
1277
1526
  }
1278
1527
  /** Whether the bound store can hold a queue. Without one, a busy thread is not queued. */
1279
1528
  get supported() {
@@ -1571,13 +1820,17 @@ var ChatQueueService2 = class _ChatQueueService {
1571
1820
  */
1572
1821
  async inputFor(message) {
1573
1822
  const attachments = await this.freshAttachments(message.actor, message.attachments ?? []);
1823
+ const { agentName, persona } = await this.targetFor(message);
1574
1824
  return {
1575
1825
  threadId: message.threadId,
1576
1826
  actor: message.actor,
1577
1827
  userText: message.content,
1578
1828
  day: utcDay(),
1579
- ...message.agentName !== void 0 ? {
1580
- agentName: message.agentName
1829
+ ...agentName !== void 0 ? {
1830
+ agentName
1831
+ } : {},
1832
+ ...persona !== void 0 ? {
1833
+ persona
1581
1834
  } : {},
1582
1835
  ...attachments.length > 0 ? {
1583
1836
  attachments
@@ -1590,6 +1843,37 @@ var ChatQueueService2 = class _ChatQueueService {
1590
1843
  } : {}
1591
1844
  };
1592
1845
  }
1846
+ /**
1847
+ * The agent and persona a queued message starts as. A message carries the persona its send
1848
+ * resolved; one that carries none — queued before personas existed, or by a host that sets none —
1849
+ * resolves it now, exactly as a send would: an agent name a persona took over, then the thread's
1850
+ * pinned persona, then the agent's default. Never refused here: nobody is waiting on a 400.
1851
+ */
1852
+ async targetFor(message) {
1853
+ const deps = this.deps;
1854
+ if (message.persona !== void 0 || deps === void 0 || message.agentName === void 0) {
1855
+ return {
1856
+ ...message.agentName !== void 0 ? {
1857
+ agentName: message.agentName
1858
+ } : {},
1859
+ ...message.persona !== void 0 ? {
1860
+ persona: message.persona
1861
+ } : {}
1862
+ };
1863
+ }
1864
+ const target = deps.resolveAgent(message.agentName);
1865
+ const hasPersonas = deps.personaCatalog(target.agentName).length > 0;
1866
+ const persona = target.persona ?? (hasPersonas ? deps.resolvePersona({
1867
+ agentName: target.agentName,
1868
+ threadPersona: await threadPersona(this.store, message.threadId)
1869
+ }) : void 0);
1870
+ return {
1871
+ agentName: target.agentName,
1872
+ ...persona !== void 0 ? {
1873
+ persona
1874
+ } : {}
1875
+ };
1876
+ }
1593
1877
  async freshAttachments(actor, attachments) {
1594
1878
  const staging = this.staging;
1595
1879
  if (attachments.length === 0 || staging === void 0 || typeof staging.resolve !== "function") {
@@ -1617,13 +1901,16 @@ ChatQueueService2 = _ts_decorate6([
1617
1901
  _ts_param5(3, Inject5(AGENT_OPTIONS2)),
1618
1902
  _ts_param5(4, Optional4()),
1619
1903
  _ts_param5(4, Inject5(AGENT_ATTACHMENT_STAGING)),
1904
+ _ts_param5(5, Optional4()),
1905
+ _ts_param5(5, Inject5(AGENT_DEPS_FACTORY3)),
1620
1906
  _ts_metadata5("design:type", Function),
1621
1907
  _ts_metadata5("design:paramtypes", [
1622
1908
  typeof AgentStore === "undefined" ? Object : AgentStore,
1623
1909
  typeof TokenStreamSink === "undefined" ? Object : TokenStreamSink,
1624
1910
  typeof QuotaProvider === "undefined" ? Object : QuotaProvider,
1625
1911
  typeof Pick === "undefined" ? Object : Pick,
1626
- typeof AttachmentStagingStore === "undefined" ? Object : AttachmentStagingStore
1912
+ typeof AttachmentStagingStore === "undefined" ? Object : AttachmentStagingStore,
1913
+ typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
1627
1914
  ])
1628
1915
  ], ChatQueueService2);
1629
1916
  function pauseReasonFor(outcome, head) {
@@ -1795,17 +2082,17 @@ var AgentService = class {
1795
2082
  */
1796
2083
  async assertModelAllowed(actor, agent, model) {
1797
2084
  if (this.models === void 0) {
1798
- throw new BadRequestException(`model "${model}" cannot be selected: no ModelCatalog is configured (AgentModule.forRoot({ models }))`);
2085
+ throw new BadRequestException2(`model "${model}" cannot be selected: no ModelCatalog is configured (AgentModule.forRoot({ models }))`);
1799
2086
  }
1800
2087
  const entry = findCatalogModel(await this.models.list({
1801
2088
  actor,
1802
2089
  agent
1803
2090
  }), model);
1804
2091
  if (entry === void 0) {
1805
- throw new BadRequestException(`model "${model}" is not offered`);
2092
+ throw new BadRequestException2(`model "${model}" is not offered`);
1806
2093
  }
1807
2094
  if (!entry.available) {
1808
- throw new BadRequestException(`model "${model}" is not available${entry.unavailableReason ? `: ${entry.unavailableReason}` : ""}`);
2095
+ throw new BadRequestException2(`model "${model}" is not available${entry.unavailableReason ? `: ${entry.unavailableReason}` : ""}`);
1809
2096
  }
1810
2097
  return entry.id;
1811
2098
  }
@@ -1821,7 +2108,7 @@ var AgentService = class {
1821
2108
  })).locked : void 0;
1822
2109
  if (locked !== void 0) {
1823
2110
  if (requested !== void 0 && requested !== locked.model) {
1824
- throw new BadRequestException(`model "${requested}" cannot be selected: ${locked.reason ?? `this agent always uses "${locked.model}"`}`);
2111
+ throw new BadRequestException2(`model "${requested}" cannot be selected: ${locked.reason ?? `this agent always uses "${locked.model}"`}`);
1825
2112
  }
1826
2113
  return locked.model;
1827
2114
  }
@@ -1877,13 +2164,15 @@ var AgentService = class {
1877
2164
  */
1878
2165
  async send(params) {
1879
2166
  await this.assertWithinQuota(params.actor);
1880
- const agentName = await this.resolveAgentName(params.agentName, params.threadId);
2167
+ const target = this.deps.resolveAgent(await this.resolveAgentName(params.agentName, params.threadId));
2168
+ const agentName = target.agentName;
2169
+ const persona = await this.resolvePersona(agentName, params.personaId ?? target.persona, params.threadId);
1881
2170
  const model = await this.resolveModel(params.actor, agentName, params.model, params.threadId);
1882
2171
  const attachments = await this.resolveAttachments(params.actor, params.attachments ?? []);
1883
2172
  let threadId = params.threadId;
1884
2173
  if (threadId === void 0) {
1885
2174
  if (params.regenerate === true) {
1886
- throw new BadRequestException("regenerate requires an existing threadId");
2175
+ throw new BadRequestException2("regenerate requires an existing threadId");
1887
2176
  }
1888
2177
  const created = await this.store.createThread({
1889
2178
  actor: params.actor,
@@ -1892,11 +2181,17 @@ var AgentService = class {
1892
2181
  } : {},
1893
2182
  ...params.newThreadId !== void 0 ? {
1894
2183
  id: params.newThreadId
2184
+ } : {},
2185
+ ...params.personaId !== void 0 ? {
2186
+ persona: params.personaId
1895
2187
  } : {}
1896
2188
  });
1897
2189
  threadId = created.id;
1898
2190
  } else {
1899
2191
  await this.assertOwnsThread(params.actor, threadId);
2192
+ if (params.personaId !== void 0) {
2193
+ await this.pinThreadPersona(threadId, params.personaId);
2194
+ }
1900
2195
  }
1901
2196
  const input = {
1902
2197
  threadId,
@@ -1904,6 +2199,9 @@ var AgentService = class {
1904
2199
  userText: params.message,
1905
2200
  day: utcDay(),
1906
2201
  agentName,
2202
+ ...persona !== void 0 ? {
2203
+ persona
2204
+ } : {},
1907
2205
  ...params.regenerate === true ? {
1908
2206
  regenerate: true
1909
2207
  } : {},
@@ -1990,6 +2288,9 @@ var AgentService = class {
1990
2288
  ...input.agentName !== void 0 ? {
1991
2289
  agentName: input.agentName
1992
2290
  } : {},
2291
+ ...input.persona !== void 0 ? {
2292
+ persona: input.persona
2293
+ } : {},
1993
2294
  ...input.model !== void 0 ? {
1994
2295
  model: input.model
1995
2296
  } : {},
@@ -2042,7 +2343,7 @@ var AgentService = class {
2042
2343
  const store = queue.queueStore();
2043
2344
  const threadId = await this.assertOwnsQueuedMessage(actor, messageId);
2044
2345
  if (patch.message !== void 0 && patch.message.trim().length === 0) {
2045
- throw new BadRequestException("message must not be empty");
2346
+ throw new BadRequestException2("message must not be empty");
2046
2347
  }
2047
2348
  const attachments = patch.attachments === void 0 || patch.attachments === null ? patch.attachments : await this.resolveAttachments(actor, patch.attachments);
2048
2349
  if (patch.message !== void 0 || attachments !== void 0) {
@@ -2060,7 +2361,7 @@ var AgentService = class {
2060
2361
  }
2061
2362
  if (patch.position !== void 0) {
2062
2363
  if (!Number.isInteger(patch.position) || patch.position < 0) {
2063
- throw new BadRequestException("position must be a non-negative integer");
2364
+ throw new BadRequestException2("position must be a non-negative integer");
2064
2365
  }
2065
2366
  if (!await store.moveQueuedMessage(messageId, patch.position)) {
2066
2367
  throw new GoneException(`queued message ${messageId} already started or was removed`);
@@ -2384,16 +2685,22 @@ var AgentService = class {
2384
2685
  async updateThread(actor, threadId, patch) {
2385
2686
  const title = patch.title !== void 0 ? this.validateTitle(patch.title) : void 0;
2386
2687
  await this.assertOwnsThread(actor, threadId);
2387
- if (patch.defaultAgent === void 0 && patch.model === void 0) {
2688
+ if (patch.defaultAgent === void 0 && patch.model === void 0 && patch.persona === void 0) {
2388
2689
  if (title !== void 0) {
2389
2690
  await this.store.setTitle(threadId, title);
2390
2691
  }
2391
2692
  return;
2392
2693
  }
2393
2694
  if (this.store.updateThread === void 0) {
2394
- throw new NotImplementedException2("Setting a thread's defaultAgent or model requires an AgentStore that implements updateThread(); the bound store does not support it.");
2695
+ throw new NotImplementedException2("Setting a thread's defaultAgent, model or persona requires an AgentStore that implements updateThread(); the bound store does not support it.");
2395
2696
  }
2396
2697
  const model = patch.model === void 0 || patch.model === null ? patch.model : await this.assertModelAllowed(actor, patch.defaultAgent ?? await this.resolveAgentName(void 0, threadId), patch.model);
2698
+ if (patch.persona !== void 0 && patch.persona !== null) {
2699
+ this.deps.resolvePersona({
2700
+ agentName: this.deps.resolveAgent(patch.defaultAgent ?? await this.resolveAgentName(void 0, threadId)).agentName,
2701
+ requested: patch.persona
2702
+ });
2703
+ }
2397
2704
  await this.store.updateThread(threadId, {
2398
2705
  ...title !== void 0 ? {
2399
2706
  title
@@ -2403,16 +2710,46 @@ var AgentService = class {
2403
2710
  } : {},
2404
2711
  ...model !== void 0 ? {
2405
2712
  model
2713
+ } : {},
2714
+ ...patch.persona !== void 0 ? {
2715
+ persona: patch.persona
2716
+ } : {}
2717
+ });
2718
+ }
2719
+ /**
2720
+ * The persona this send runs under — see {@link AgentDepsFactory.resolvePersona}. The thread's
2721
+ * pinned persona is read only when the send names none AND the agent has personas to pick from.
2722
+ */
2723
+ async resolvePersona(agentName, requested, threadId) {
2724
+ const needsThread = requested === void 0 && threadId !== void 0 && this.deps.personaCatalog(agentName).length > 0;
2725
+ return this.deps.resolvePersona({
2726
+ agentName,
2727
+ ...requested !== void 0 ? {
2728
+ requested
2729
+ } : {},
2730
+ ...needsThread ? {
2731
+ threadPersona: await threadPersona(this.store, threadId)
2406
2732
  } : {}
2407
2733
  });
2408
2734
  }
2735
+ /** Pin `persona` on the thread when it is not already — a no-op on a store that cannot. */
2736
+ async pinThreadPersona(threadId, persona) {
2737
+ if (this.store.updateThread === void 0) {
2738
+ return;
2739
+ }
2740
+ if (await threadPersona(this.store, threadId) !== persona) {
2741
+ await this.store.updateThread(threadId, {
2742
+ persona
2743
+ });
2744
+ }
2745
+ }
2409
2746
  validateTitle(title) {
2410
2747
  const trimmed = title.trim();
2411
2748
  if (trimmed.length === 0) {
2412
- throw new BadRequestException("title must not be empty");
2749
+ throw new BadRequestException2("title must not be empty");
2413
2750
  }
2414
2751
  if (trimmed.length > 200) {
2415
- throw new BadRequestException("title must be at most 200 characters");
2752
+ throw new BadRequestException2("title must be at most 200 characters");
2416
2753
  }
2417
2754
  return trimmed;
2418
2755
  }
@@ -2451,6 +2788,7 @@ var AgentService = class {
2451
2788
  ...thread,
2452
2789
  defaultAgent: thread.defaultAgent ?? null,
2453
2790
  model: thread.model ?? null,
2791
+ persona: thread.persona ?? null,
2454
2792
  activeRunId: await this.store.activeRunForThread?.(thread.id) ?? thread.activeRunId ?? null
2455
2793
  };
2456
2794
  }
@@ -2515,14 +2853,14 @@ var AgentService = class {
2515
2853
  */
2516
2854
  async setMessageFeedback(actor, messageId, input) {
2517
2855
  if (input.value !== null && input.value !== "up" && input.value !== "down") {
2518
- throw new BadRequestException("value must be 'up', 'down' or null");
2856
+ throw new BadRequestException2("value must be 'up', 'down' or null");
2519
2857
  }
2520
2858
  if (input.comment !== void 0 && typeof input.comment !== "string") {
2521
- throw new BadRequestException("comment must be a string");
2859
+ throw new BadRequestException2("comment must be a string");
2522
2860
  }
2523
2861
  const comment = input.comment?.trim();
2524
2862
  if (comment !== void 0 && comment.length > 2e3) {
2525
- throw new BadRequestException("comment must be at most 2000 characters");
2863
+ throw new BadRequestException2("comment must be at most 2000 characters");
2526
2864
  }
2527
2865
  if (this.store.threadOfMessage === void 0 || this.store.setMessageFeedback === void 0) {
2528
2866
  throw new NotImplementedException2("Message feedback requires an AgentStore that implements threadOfMessage() and setMessageFeedback(); the bound store does not support it.");
@@ -2647,7 +2985,7 @@ var AgentService = class {
2647
2985
  const submitted = Object.hasOwn(answers2, question.id) ? answers2[question.id] : void 0;
2648
2986
  const problem = validateElicitationAnswer(question, submitted ?? question.defaults ?? []);
2649
2987
  if (problem !== null) {
2650
- throw new BadRequestException(`answers["${question.id}"] ${problem}`);
2988
+ throw new BadRequestException2(`answers["${question.id}"] ${problem}`);
2651
2989
  }
2652
2990
  }
2653
2991
  }
@@ -2721,7 +3059,7 @@ AgentService = _ts_decorate7([
2721
3059
  Injectable6(),
2722
3060
  _ts_param6(0, Inject6(AGENT_RUNNER)),
2723
3061
  _ts_param6(1, Inject6(AGENT_STORE5)),
2724
- _ts_param6(2, Inject6(AGENT_DEPS_FACTORY3)),
3062
+ _ts_param6(2, Inject6(AGENT_DEPS_FACTORY4)),
2725
3063
  _ts_param6(3, Optional5()),
2726
3064
  _ts_param6(3, Inject6(AGENT_ATTACHMENT_STAGING2)),
2727
3065
  _ts_param6(4, Optional5()),
@@ -2812,7 +3150,7 @@ AgentApprovalPortAdapter = _ts_decorate8([
2812
3150
  ], AgentApprovalPortAdapter);
2813
3151
 
2814
3152
  // src/controller/agents.controller.ts
2815
- import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY4, AGENT_REGISTRY as AGENT_REGISTRY2, AgentRegistry as AgentRegistry3 } from "@dudousxd/nestjs-agent-core";
3153
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY5, AGENT_REGISTRY as AGENT_REGISTRY2, AgentRegistry as AgentRegistry3 } from "@dudousxd/nestjs-agent-core";
2816
3154
  import { Controller, Get, Inject as Inject7 } from "@nestjs/common";
2817
3155
  function _ts_decorate9(decorators, target, key, desc) {
2818
3156
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -2852,13 +3190,22 @@ var AgentsController = class {
2852
3190
  }
2853
3191
  list() {
2854
3192
  const defaultAgentName = this.depsFactory.defaultAgentName();
2855
- return this.agents.list().map((definition) => ({
2856
- name: definition.name,
2857
- description: definition.description ?? "",
2858
- ...definition.name === defaultAgentName ? {
2859
- isDefault: true
2860
- } : {}
2861
- }));
3193
+ return this.agents.list().map((definition) => {
3194
+ const personas = this.depsFactory.personaCatalog(definition.name);
3195
+ return {
3196
+ name: definition.name,
3197
+ description: definition.description ?? "",
3198
+ ...definition.name === defaultAgentName ? {
3199
+ isDefault: true
3200
+ } : {},
3201
+ ...personas.length > 0 ? {
3202
+ personas
3203
+ } : {},
3204
+ ...definition.defaultPersona !== void 0 ? {
3205
+ defaultPersona: definition.defaultPersona
3206
+ } : {}
3207
+ };
3208
+ });
2862
3209
  }
2863
3210
  };
2864
3211
  _ts_decorate9([
@@ -2870,7 +3217,7 @@ _ts_decorate9([
2870
3217
  AgentsController = _ts_decorate9([
2871
3218
  Controller("agents"),
2872
3219
  _ts_param7(0, Inject7(AGENT_REGISTRY2)),
2873
- _ts_param7(1, Inject7(AGENT_DEPS_FACTORY4)),
3220
+ _ts_param7(1, Inject7(AGENT_DEPS_FACTORY5)),
2874
3221
  _ts_metadata8("design:type", Function),
2875
3222
  _ts_metadata8("design:paramtypes", [
2876
3223
  typeof AgentRegistry3 === "undefined" ? Object : AgentRegistry3,
@@ -2880,7 +3227,7 @@ AgentsController = _ts_decorate9([
2880
3227
 
2881
3228
  // src/controller/attachments.controller.ts
2882
3229
  import { AGENT_ACTOR_RESOLVER, AGENT_ATTACHMENT_STAGING as AGENT_ATTACHMENT_STAGING3, AGENT_OPTIONS as AGENT_OPTIONS4 } from "@dudousxd/nestjs-agent-core";
2883
- import { BadRequestException as BadRequestException2, Controller as Controller2, Get as Get2, Inject as Inject8, NotImplementedException as NotImplementedException3, Optional as Optional6, PayloadTooLargeException, Post, Req, UnsupportedMediaTypeException, UploadedFile, UseInterceptors } from "@nestjs/common";
3230
+ import { BadRequestException as BadRequestException3, Controller as Controller2, Get as Get2, Inject as Inject8, NotImplementedException as NotImplementedException3, Optional as Optional6, PayloadTooLargeException, Post, Req, UnsupportedMediaTypeException, UploadedFile, UseInterceptors } from "@nestjs/common";
2884
3231
  import { FileInterceptor } from "@nestjs/platform-express";
2885
3232
 
2886
3233
  // src/attachment-limits.ts
@@ -2971,7 +3318,7 @@ var AttachmentsController = class {
2971
3318
  throw new NotImplementedException3("Attachment upload is not configured on this server: bind AGENT_ATTACHMENT_STAGING (e.g. import AgentMediaAttachmentsModule).");
2972
3319
  }
2973
3320
  if (file === void 0) {
2974
- throw new BadRequestException2('multipart field "file" is required');
3321
+ throw new BadRequestException3('multipart field "file" is required');
2975
3322
  }
2976
3323
  const { allowedContentTypes, maxBytes } = attachmentLimits(this.options, this.staging);
2977
3324
  if (!allowedContentTypes.includes(file.mimetype)) {
@@ -3032,7 +3379,7 @@ AttachmentsController = _ts_decorate10([
3032
3379
 
3033
3380
  // src/controller/chat.controller.ts
3034
3381
  import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER2, AgentStreamError as AgentStreamError2, streamFailure as streamFailure2 } from "@dudousxd/nestjs-agent-core";
3035
- import { BadRequestException as BadRequestException3, Body, Controller as Controller3, Get as Get3, Inject as Inject9, Param, Post as Post2, Query, Req as Req2, Res } from "@nestjs/common";
3382
+ import { BadRequestException as BadRequestException4, Body, Controller as Controller3, Get as Get3, Inject as Inject9, Param, Post as Post2, Query, Req as Req2, Res } from "@nestjs/common";
3036
3383
  function _ts_decorate11(decorators, target, key, desc) {
3037
3384
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3038
3385
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -3069,7 +3416,7 @@ function sendMode(body) {
3069
3416
  if (body.mode === "auto" || body.mode === "queue" || body.mode === "interrupt") {
3070
3417
  return body.mode;
3071
3418
  }
3072
- throw new BadRequestException3("mode must be 'auto', 'queue' or 'interrupt'");
3419
+ throw new BadRequestException4("mode must be 'auto', 'queue' or 'interrupt'");
3073
3420
  }
3074
3421
  __name(sendMode, "sendMode");
3075
3422
  function attachmentRefs(claimed) {
@@ -3077,21 +3424,21 @@ function attachmentRefs(claimed) {
3077
3424
  return [];
3078
3425
  }
3079
3426
  if (!Array.isArray(claimed)) {
3080
- throw new BadRequestException3("attachments must be an array of { mediaId }");
3427
+ throw new BadRequestException4("attachments must be an array of { mediaId }");
3081
3428
  }
3082
3429
  if (claimed.length > MAX_ATTACHMENTS_PER_MESSAGE) {
3083
- throw new BadRequestException3(`a message may carry at most ${MAX_ATTACHMENTS_PER_MESSAGE} attachments`);
3430
+ throw new BadRequestException4(`a message may carry at most ${MAX_ATTACHMENTS_PER_MESSAGE} attachments`);
3084
3431
  }
3085
3432
  return claimed.map((entry) => {
3086
3433
  if (typeof entry !== "object" || entry === null || !("mediaId" in entry)) {
3087
- throw new BadRequestException3("each attachment must be an object with a mediaId");
3434
+ throw new BadRequestException4("each attachment must be an object with a mediaId");
3088
3435
  }
3089
3436
  if (Object.keys(entry).some((key) => key !== "mediaId")) {
3090
- throw new BadRequestException3("attachments are { mediaId } refs \u2014 send nothing but the id");
3437
+ throw new BadRequestException4("attachments are { mediaId } refs \u2014 send nothing but the id");
3091
3438
  }
3092
3439
  const { mediaId } = entry;
3093
3440
  if (typeof mediaId !== "string" || mediaId.length === 0) {
3094
- throw new BadRequestException3("each attachment must carry a non-empty string mediaId");
3441
+ throw new BadRequestException4("each attachment must carry a non-empty string mediaId");
3095
3442
  }
3096
3443
  return {
3097
3444
  mediaId
@@ -3128,6 +3475,9 @@ var ChatController = class {
3128
3475
  ...body.agent !== void 0 ? {
3129
3476
  agentName: body.agent
3130
3477
  } : {},
3478
+ ...typeof body.persona === "string" && body.persona.length > 0 ? {
3479
+ personaId: body.persona
3480
+ } : {},
3131
3481
  ...attachments.length > 0 ? {
3132
3482
  attachments
3133
3483
  } : {},
@@ -3754,7 +4104,7 @@ ModelsController = _ts_decorate15([
3754
4104
 
3755
4105
  // src/controller/queue.controller.ts
3756
4106
  import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER7 } from "@dudousxd/nestjs-agent-core";
3757
- import { BadRequestException as BadRequestException4, Body as Body3, Controller as Controller8, Delete as Delete2, Get as Get7, Inject as Inject14, Param as Param4, Patch, Post as Post4, Req as Req7 } from "@nestjs/common";
4107
+ import { BadRequestException as BadRequestException5, Body as Body3, Controller as Controller8, Delete as Delete2, Get as Get7, Inject as Inject14, Param as Param4, Patch, Post as Post4, Req as Req7 } from "@nestjs/common";
3758
4108
  function _ts_decorate16(decorators, target, key, desc) {
3759
4109
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3760
4110
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -3804,10 +4154,10 @@ var QueueController = class {
3804
4154
  async update(req, messageId, body) {
3805
4155
  const actor = await this.actorResolver.resolve(req);
3806
4156
  if (body.message !== void 0 && typeof body.message !== "string") {
3807
- throw new BadRequestException4("message must be a string");
4157
+ throw new BadRequestException5("message must be a string");
3808
4158
  }
3809
4159
  if (body.position !== void 0 && typeof body.position !== "number") {
3810
- throw new BadRequestException4("position must be a number");
4160
+ throw new BadRequestException5("position must be a number");
3811
4161
  }
3812
4162
  const attachments = body.attachments === void 0 ? void 0 : body.attachments === null ? null : attachmentRefs(body.attachments);
3813
4163
  return this.agent.updateQueuedMessage(actor, messageId, {
@@ -4127,6 +4477,9 @@ var ThreadsController = class {
4127
4477
  } : {},
4128
4478
  ..."model" in body ? {
4129
4479
  model: body.model ?? null
4480
+ } : {},
4481
+ ..."persona" in body ? {
4482
+ persona: body.persona ?? null
4130
4483
  } : {}
4131
4484
  });
4132
4485
  return {
@@ -4241,7 +4594,7 @@ ThreadsController = _ts_decorate19([
4241
4594
 
4242
4595
  // src/controller/tool-call.controller.ts
4243
4596
  import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER11 } from "@dudousxd/nestjs-agent-core";
4244
- import { BadRequestException as BadRequestException5, Body as Body5, Controller as Controller12, Inject as Inject18, Post as Post6, Req as Req11 } from "@nestjs/common";
4597
+ import { BadRequestException as BadRequestException6, Body as Body5, Controller as Controller12, Inject as Inject18, Post as Post6, Req as Req11 } from "@nestjs/common";
4245
4598
  function _ts_decorate20(decorators, target, key, desc) {
4246
4599
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4247
4600
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -4276,7 +4629,7 @@ var MAX_VIA_LENGTH = 64;
4276
4629
  var DEFAULT_VIA = "web";
4277
4630
  function toolCallId(claimed) {
4278
4631
  if (typeof claimed !== "string" || claimed.length === 0) {
4279
- throw new BadRequestException5("toolCallId must be a non-empty string");
4632
+ throw new BadRequestException6("toolCallId must be a non-empty string");
4280
4633
  }
4281
4634
  return claimed;
4282
4635
  }
@@ -4286,10 +4639,10 @@ function rejectReason(claimed) {
4286
4639
  return void 0;
4287
4640
  }
4288
4641
  if (typeof claimed !== "string") {
4289
- throw new BadRequestException5("reason must be a string");
4642
+ throw new BadRequestException6("reason must be a string");
4290
4643
  }
4291
4644
  if (claimed.length > MAX_REJECT_REASON_LENGTH) {
4292
- throw new BadRequestException5(`reason must be at most ${MAX_REJECT_REASON_LENGTH} characters`);
4645
+ throw new BadRequestException6(`reason must be at most ${MAX_REJECT_REASON_LENGTH} characters`);
4293
4646
  }
4294
4647
  return claimed;
4295
4648
  }
@@ -4299,7 +4652,7 @@ function remember(claimed) {
4299
4652
  return false;
4300
4653
  }
4301
4654
  if (typeof claimed !== "boolean") {
4302
- throw new BadRequestException5("remember must be a boolean");
4655
+ throw new BadRequestException6("remember must be a boolean");
4303
4656
  }
4304
4657
  return claimed;
4305
4658
  }
@@ -4309,7 +4662,7 @@ function via(claimed) {
4309
4662
  return DEFAULT_VIA;
4310
4663
  }
4311
4664
  if (typeof claimed !== "string" || claimed.length === 0 || claimed.length > MAX_VIA_LENGTH) {
4312
- throw new BadRequestException5(`via must be a string of 1-${MAX_VIA_LENGTH} characters`);
4665
+ throw new BadRequestException6(`via must be a string of 1-${MAX_VIA_LENGTH} characters`);
4313
4666
  }
4314
4667
  return claimed;
4315
4668
  }
@@ -4319,26 +4672,26 @@ function answers(claimed) {
4319
4672
  return void 0;
4320
4673
  }
4321
4674
  if (typeof claimed !== "object" || claimed === null || Array.isArray(claimed)) {
4322
- throw new BadRequestException5("answers must be an object of questionId \u2192 chosen values");
4675
+ throw new BadRequestException6("answers must be an object of questionId \u2192 chosen values");
4323
4676
  }
4324
4677
  const entries = Object.entries(claimed);
4325
4678
  if (entries.length > MAX_ANSWERED_QUESTIONS) {
4326
- throw new BadRequestException5(`answers may cover at most ${MAX_ANSWERED_QUESTIONS} questions`);
4679
+ throw new BadRequestException6(`answers may cover at most ${MAX_ANSWERED_QUESTIONS} questions`);
4327
4680
  }
4328
4681
  const validated = /* @__PURE__ */ Object.create(null);
4329
4682
  for (const [questionId, values] of entries) {
4330
4683
  if (!Array.isArray(values)) {
4331
- throw new BadRequestException5(`answers["${questionId}"] must be an array of chosen values`);
4684
+ throw new BadRequestException6(`answers["${questionId}"] must be an array of chosen values`);
4332
4685
  }
4333
4686
  if (values.length > MAX_VALUES_PER_QUESTION) {
4334
- throw new BadRequestException5(`answers["${questionId}"] may carry at most ${MAX_VALUES_PER_QUESTION} values`);
4687
+ throw new BadRequestException6(`answers["${questionId}"] may carry at most ${MAX_VALUES_PER_QUESTION} values`);
4335
4688
  }
4336
4689
  for (const value of values) {
4337
4690
  if (typeof value !== "string") {
4338
- throw new BadRequestException5(`answers["${questionId}"] must contain only strings`);
4691
+ throw new BadRequestException6(`answers["${questionId}"] must contain only strings`);
4339
4692
  }
4340
4693
  if (value.length > MAX_ANSWER_VALUE_LENGTH) {
4341
- throw new BadRequestException5(`answers["${questionId}"] values must be at most ${MAX_ANSWER_VALUE_LENGTH} characters`);
4694
+ throw new BadRequestException6(`answers["${questionId}"] values must be at most ${MAX_ANSWER_VALUE_LENGTH} characters`);
4342
4695
  }
4343
4696
  }
4344
4697
  validated[questionId] = values;
@@ -4455,7 +4808,7 @@ ToolCallController = _ts_decorate20([
4455
4808
  ], ToolCallController);
4456
4809
 
4457
4810
  // src/controller/tools.controller.ts
4458
- import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER12, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY5, AGENT_REGISTRY as AGENT_REGISTRY3, ALL_AGENTS, AgentRegistry as AgentRegistry4 } from "@dudousxd/nestjs-agent-core";
4811
+ import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER12, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_REGISTRY as AGENT_REGISTRY3, ALL_AGENTS, AgentRegistry as AgentRegistry4 } from "@dudousxd/nestjs-agent-core";
4459
4812
  import { Controller as Controller13, Get as Get11, Inject as Inject19, NotFoundException as NotFoundException3, Query as Query5, Req as Req12 } from "@nestjs/common";
4460
4813
  function _ts_decorate21(decorators, target, key, desc) {
4461
4814
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -4540,7 +4893,7 @@ _ts_decorate21([
4540
4893
  ToolsController = _ts_decorate21([
4541
4894
  Controller13("tools"),
4542
4895
  _ts_param19(0, Inject19(AGENT_ACTOR_RESOLVER12)),
4543
- _ts_param19(1, Inject19(AGENT_DEPS_FACTORY5)),
4896
+ _ts_param19(1, Inject19(AGENT_DEPS_FACTORY6)),
4544
4897
  _ts_param19(2, Inject19(AGENT_REGISTRY3)),
4545
4898
  _ts_metadata20("design:type", Function),
4546
4899
  _ts_metadata20("design:paramtypes", [
@@ -4622,6 +4975,7 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
4622
4975
  }
4623
4976
  this.collectContributors(instance);
4624
4977
  }
4978
+ this.assertPersonas(this.registry.list());
4625
4979
  }
4626
4980
  /** Build the internal {@link AgentDefinition} from an `@Agent` instance and its options. */
4627
4981
  definitionFrom(instance, meta) {
@@ -4665,10 +5019,48 @@ var AgentDiscoveryService = class _AgentDiscoveryService {
4665
5019
  } : {},
4666
5020
  ...meta.handoff !== void 0 ? {
4667
5021
  delegatesTo: this.handoffEdges(meta)
5022
+ } : {},
5023
+ ...meta.personas !== void 0 ? {
5024
+ personas: meta.personas
5025
+ } : {},
5026
+ ...meta.defaultPersona !== void 0 ? {
5027
+ defaultPersona: meta.defaultPersona
4668
5028
  } : {}
4669
5029
  };
4670
5030
  }
4671
5031
  /**
5032
+ * Refuse to boot on a persona declaration that could only fail later, per request: a default that
5033
+ * names no persona, an id declared twice, an alias two personas claim, or an alias that is a real
5034
+ * agent's name (which would never be reached — a registered agent always wins).
5035
+ */
5036
+ assertPersonas(definitions) {
5037
+ const agentNames = new Set(definitions.map((definition) => definition.name));
5038
+ const aliasOwner = /* @__PURE__ */ new Map();
5039
+ for (const definition of definitions) {
5040
+ const ids = /* @__PURE__ */ new Set();
5041
+ for (const persona of definition.personas ?? []) {
5042
+ if (ids.has(persona.id)) {
5043
+ throw new Error(`Agent "${definition.name}" declares persona "${persona.id}" twice.`);
5044
+ }
5045
+ ids.add(persona.id);
5046
+ for (const alias of persona.aliases ?? []) {
5047
+ const owner = `${definition.name}/${persona.id}`;
5048
+ if (agentNames.has(alias)) {
5049
+ throw new Error(`Persona ${owner} claims the alias "${alias}", which is a registered agent's name.`);
5050
+ }
5051
+ const previous = aliasOwner.get(alias);
5052
+ if (previous !== void 0) {
5053
+ throw new Error(`Personas ${previous} and ${owner} both claim the alias "${alias}".`);
5054
+ }
5055
+ aliasOwner.set(alias, owner);
5056
+ }
5057
+ }
5058
+ if (definition.defaultPersona !== void 0 && !ids.has(definition.defaultPersona)) {
5059
+ throw new Error(`Agent "${definition.name}" names "${definition.defaultPersona}" as its default persona, but declares no persona with that id.`);
5060
+ }
5061
+ }
5062
+ }
5063
+ /**
4672
5064
  * Resolve each handoff entry to an {@link AgentDelegation} — its target's registered name, plus
4673
5065
  * whether that edge detaches (skipping non-agent classes). A bare name is kept for a plain edge
4674
5066
  * rather than an always-object form, so a definition an older host built by hand still reads.
@@ -5100,7 +5492,7 @@ var LedgerQuotaProvider = class {
5100
5492
  };
5101
5493
 
5102
5494
  // src/runner/inline-agent-runner.ts
5103
- import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY6, AGENT_STORE as AGENT_STORE6, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation2, streamFailure as streamFailure3 } from "@dudousxd/nestjs-agent-core";
5495
+ import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY7, AGENT_STORE as AGENT_STORE6, RUN_ENDED_BEFORE_TOOL_CALL as RUN_ENDED_BEFORE_TOOL_CALL2, RunCancelledError as RunCancelledError2, agentFailureCode as agentFailureCode2, encodeStreamEvent as encodeStreamEvent5, publishAgentRunFailed as publishAgentRunFailed2, releaseThreadRun as releaseThreadRun3, runAgentLoop as runAgentLoop2, settleAll as settleAll2, settleUnsettledDelegation as settleUnsettledDelegation3, streamFailure as streamFailure3 } from "@dudousxd/nestjs-agent-core";
5104
5496
  import { Inject as Inject23, Injectable as Injectable11, Logger as Logger7, Optional as Optional10 } from "@nestjs/common";
5105
5497
  function _ts_decorate25(decorators, target, key, desc) {
5106
5498
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -5485,7 +5877,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5485
5877
  }
5486
5878
  });
5487
5879
  await Promise.resolve(this.store.failUnsettledToolCalls?.(runId, RUN_ENDED_BEFORE_TOOL_CALL2)).catch(() => 0);
5488
- await settleUnsettledDelegation2({
5880
+ await settleUnsettledDelegation3({
5489
5881
  store: this.store,
5490
5882
  delivery: deliverTo,
5491
5883
  agent: agentName,
@@ -5580,7 +5972,7 @@ var InlineAgentRunner = class _InlineAgentRunner {
5580
5972
  };
5581
5973
  InlineAgentRunner = _ts_decorate25([
5582
5974
  Injectable11(),
5583
- _ts_param23(0, Inject23(AGENT_DEPS_FACTORY6)),
5975
+ _ts_param23(0, Inject23(AGENT_DEPS_FACTORY7)),
5584
5976
  _ts_param23(1, Inject23(AGENT_STORE6)),
5585
5977
  _ts_param23(2, Optional10()),
5586
5978
  _ts_metadata24("design:type", Function),
@@ -5792,7 +6184,7 @@ function sharedProviders(durable) {
5792
6184
  },
5793
6185
  AgentDepsFactory2,
5794
6186
  {
5795
- provide: AGENT_DEPS_FACTORY7,
6187
+ provide: AGENT_DEPS_FACTORY8,
5796
6188
  useExisting: AgentDepsFactory2
5797
6189
  },
5798
6190
  // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes
@@ -5865,7 +6257,7 @@ function exportsFor() {
5865
6257
  AGENT_PROMPT_CONTRIBUTORS3,
5866
6258
  AGENT_SKILLS3,
5867
6259
  AGENT_MEMORY3,
5868
- AGENT_DEPS_FACTORY7,
6260
+ AGENT_DEPS_FACTORY8,
5869
6261
  AgentDepsFactory2,
5870
6262
  AgentService,
5871
6263
  ChatQueueService2,