@dudousxd/nestjs-agent 0.1.0 → 0.3.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.js CHANGED
@@ -2,12 +2,12 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/agent.module.ts
5
- import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER5, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_DURABLE_RUNNER, AGENT_MODEL as AGENT_MODEL2, AGENT_OPTIONS as AGENT_OPTIONS3, AGENT_QUOTA_STORE as AGENT_QUOTA_STORE2, AGENT_REGISTRY as AGENT_REGISTRY3, AGENT_ROLES_POLICY as AGENT_ROLES_POLICY2, AGENT_RUNNER as AGENT_RUNNER2, AGENT_SINK as AGENT_SINK2, AGENT_STORE as AGENT_STORE4, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY3, AgentRegistry as AgentRegistry3, DefaultRolesPolicy, ToolRegistry as ToolRegistry3 } from "@dudousxd/nestjs-agent-core";
5
+ import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER5, AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY3, AGENT_DURABLE_RUNNER, AGENT_MODEL as AGENT_MODEL2, AGENT_OPTIONS as AGENT_OPTIONS3, AGENT_PROMPT_CONTRIBUTORS as AGENT_PROMPT_CONTRIBUTORS3, AGENT_QUOTA_STORE as AGENT_QUOTA_STORE3, AGENT_REGISTRY as AGENT_REGISTRY4, AGENT_ROLES_POLICY as AGENT_ROLES_POLICY2, AGENT_RUNNER as AGENT_RUNNER2, AGENT_SINK as AGENT_SINK2, AGENT_STORE as AGENT_STORE4, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY3, AgentRegistry as AgentRegistry4, DefaultRolesPolicy, ToolRegistry as ToolRegistry3 } from "@dudousxd/nestjs-agent-core";
6
6
  import { Global, Module } from "@nestjs/common";
7
7
  import { DiscoveryModule, RouterModule } from "@nestjs/core";
8
8
 
9
9
  // src/agent-deps.factory.ts
10
- import { AGENT_MODEL, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_ROLES_POLICY, AGENT_SINK, AGENT_STORE, AGENT_TOOL_REGISTRY, AgentRegistry as AgentRegistry2, ToolRegistry as ToolRegistry2 } from "@dudousxd/nestjs-agent-core";
10
+ import { AGENT_MODEL, AGENT_PROMPT_CONTRIBUTORS, AGENT_QUOTA_STORE, AGENT_REGISTRY, AGENT_ROLES_POLICY, AGENT_SINK, AGENT_STORE, AGENT_TOOL_REGISTRY, AgentRegistry as AgentRegistry2, ToolRegistry as ToolRegistry2 } from "@dudousxd/nestjs-agent-core";
11
11
  import { AGENT_OPTIONS } from "@dudousxd/nestjs-agent-core";
12
12
  import { Inject, Injectable } from "@nestjs/common";
13
13
  function _ts_decorate(decorators, target, key, desc) {
@@ -42,8 +42,9 @@ var AgentDepsFactory2 = class {
42
42
  rolesPolicy;
43
43
  registry;
44
44
  agents;
45
+ promptContributors;
45
46
  quota;
46
- constructor(options, model, store, sink, rolesPolicy, registry, agents, quota) {
47
+ constructor(options, model, store, sink, rolesPolicy, registry, agents, promptContributors, quota) {
47
48
  this.options = options;
48
49
  this.model = model;
49
50
  this.store = store;
@@ -51,10 +52,19 @@ var AgentDepsFactory2 = class {
51
52
  this.rolesPolicy = rolesPolicy;
52
53
  this.registry = registry;
53
54
  this.agents = agents;
55
+ this.promptContributors = promptContributors;
54
56
  this.quota = quota;
55
57
  }
58
+ /**
59
+ * The agent a turn uses when the caller names none: the explicit `defaultAgent` option, else the
60
+ * sole registered `@Agent` when there is exactly one, else `'default'` (a bare assistant).
61
+ */
56
62
  defaultAgentName() {
57
- return this.options.defaultAgent?.name ?? "default";
63
+ if (this.options.defaultAgent !== void 0) {
64
+ return this.options.defaultAgent;
65
+ }
66
+ const registered = this.agents.list();
67
+ return registered.length === 1 ? registered[0]?.name ?? "default" : "default";
58
68
  }
59
69
  effectiveTools(definition) {
60
70
  if (definition === void 0) {
@@ -72,10 +82,6 @@ var AgentDepsFactory2 = class {
72
82
  forAgent(agentName) {
73
83
  const name = agentName ?? this.defaultAgentName();
74
84
  const definition = this.agents.get(name);
75
- const personas = /* @__PURE__ */ new Map();
76
- for (const persona of definition?.personas ?? []) {
77
- personas.set(persona.id, persona);
78
- }
79
85
  const toolAllowList = this.effectiveTools(definition);
80
86
  const followUpsCount = this.followUpsCount();
81
87
  const retrieval = this.options.retrieval;
@@ -85,10 +91,9 @@ var AgentDepsFactory2 = class {
85
91
  sink: this.sink,
86
92
  rolesPolicy: this.rolesPolicy,
87
93
  registry: this.registry,
94
+ promptContributors: this.promptContributors,
88
95
  systemPrompt: definition?.systemPrompt ?? "You are a helpful assistant.",
89
96
  maxSteps: definition?.maxSteps ?? 8,
90
- personas,
91
- defaultPersona: definition?.defaultPersona ?? "default",
92
97
  ...definition?.modelId !== void 0 ? {
93
98
  modelId: definition.modelId
94
99
  } : {},
@@ -133,7 +138,8 @@ AgentDepsFactory2 = _ts_decorate([
133
138
  _ts_param(4, Inject(AGENT_ROLES_POLICY)),
134
139
  _ts_param(5, Inject(AGENT_TOOL_REGISTRY)),
135
140
  _ts_param(6, Inject(AGENT_REGISTRY)),
136
- _ts_param(7, Inject(AGENT_QUOTA_STORE)),
141
+ _ts_param(7, Inject(AGENT_PROMPT_CONTRIBUTORS)),
142
+ _ts_param(8, Inject(AGENT_QUOTA_STORE)),
137
143
  _ts_metadata("design:type", Function),
138
144
  _ts_metadata("design:paramtypes", [
139
145
  typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions,
@@ -143,12 +149,13 @@ AgentDepsFactory2 = _ts_decorate([
143
149
  typeof RolesPolicy === "undefined" ? Object : RolesPolicy,
144
150
  typeof ToolRegistry2 === "undefined" ? Object : ToolRegistry2,
145
151
  typeof AgentRegistry2 === "undefined" ? Object : AgentRegistry2,
152
+ Array,
146
153
  Object
147
154
  ])
148
155
  ], AgentDepsFactory2);
149
156
 
150
157
  // src/agent.service.ts
151
- import { AGENT_DEPS_FACTORY, AGENT_RUNNER, AGENT_STORE as AGENT_STORE2 } from "@dudousxd/nestjs-agent-core";
158
+ import { AGENT_DEPS_FACTORY, AGENT_QUOTA_STORE as AGENT_QUOTA_STORE2, AGENT_RUNNER, AGENT_STORE as AGENT_STORE2 } from "@dudousxd/nestjs-agent-core";
152
159
  import { BadRequestException, ForbiddenException, Inject as Inject2, Injectable as Injectable2, NotFoundException } from "@nestjs/common";
153
160
 
154
161
  // src/agent-deps.ts
@@ -192,10 +199,12 @@ var AgentService = class {
192
199
  runner;
193
200
  store;
194
201
  deps;
195
- constructor(runner, store, deps) {
202
+ quota;
203
+ constructor(runner, store, deps, quota) {
196
204
  this.runner = runner;
197
205
  this.store = store;
198
206
  this.deps = deps;
207
+ this.quota = quota;
199
208
  }
200
209
  async chat(params) {
201
210
  const agentName = params.agentName ?? this.deps.defaultAgentName();
@@ -206,13 +215,14 @@ var AgentService = class {
206
215
  }
207
216
  const created = await this.store.createThread({
208
217
  actor: params.actor,
209
- persona: params.personaId ?? this.deps.forAgent(agentName).defaultPersona
218
+ ...params.transient === true ? {
219
+ transient: true
220
+ } : {}
210
221
  });
211
222
  threadId = created.id;
212
223
  } else if (params.regenerate === true) {
213
224
  await this.assertOwnsThread(params.actor, threadId);
214
225
  }
215
- const persona = this.resolvePersona(agentName, params.personaId);
216
226
  const input = {
217
227
  threadId,
218
228
  actor: params.actor,
@@ -222,9 +232,6 @@ var AgentService = class {
222
232
  ...params.regenerate === true ? {
223
233
  regenerate: true
224
234
  } : {},
225
- ...persona !== void 0 ? {
226
- persona
227
- } : {},
228
235
  ...params.pageContext !== void 0 ? {
229
236
  pageContext: params.pageContext
230
237
  } : {}
@@ -258,18 +265,6 @@ var AgentService = class {
258
265
  await this.assertOwnsActiveStream(actor, runId);
259
266
  return this.runner.cancel(runId);
260
267
  }
261
- resolvePersona(agentName, id) {
262
- const deps = this.deps.forAgent(agentName);
263
- return deps.personas.get(id ?? deps.defaultPersona);
264
- }
265
- personaCatalog(agentName) {
266
- return [
267
- ...this.deps.forAgent(agentName).personas.values()
268
- ].map((persona) => ({
269
- id: persona.id,
270
- label: persona.label
271
- }));
272
- }
273
268
  listThreads(actorRef) {
274
269
  return this.store.listThreads(actorRef);
275
270
  }
@@ -285,8 +280,53 @@ var AgentService = class {
285
280
  await this.assertOwnsThread(actor, threadId);
286
281
  return this.store.forkThread(threadId, fromMessageId);
287
282
  }
283
+ async renameThread(actor, threadId, title) {
284
+ const trimmed = title.trim();
285
+ if (trimmed.length === 0) {
286
+ throw new BadRequestException("title must not be empty");
287
+ }
288
+ if (trimmed.length > 200) {
289
+ throw new BadRequestException("title must be at most 200 characters");
290
+ }
291
+ await this.assertOwnsThread(actor, threadId);
292
+ return this.store.setTitle(threadId, trimmed);
293
+ }
294
+ async promoteThread(actor, threadId) {
295
+ await this.assertOwnsThread(actor, threadId);
296
+ return this.store.promoteThread(threadId);
297
+ }
298
+ /**
299
+ * Drop a message and everything after it — the "edit and resend" / "delete from here" primitive.
300
+ * The client then sends a fresh turn on the truncated thread. Ownership-gated like the other
301
+ * thread-scoped mutations.
302
+ */
303
+ async truncateThreadFrom(actor, threadId, messageId) {
304
+ await this.assertOwnsThread(actor, threadId);
305
+ return this.store.truncateFrom(threadId, messageId);
306
+ }
307
+ /**
308
+ * The day's usage for the badge: tokens + summed USD cost from the store, and the configured
309
+ * limit from the quota store (null → unlimited). `withinLimit` comes from the quota store so it
310
+ * can never drift from what enforcement uses.
311
+ */
288
312
  async quotaToday(actorRef) {
289
- return this.store.quotaToday(actorRef, utcDay());
313
+ const day = utcDay();
314
+ const { usedTokens, costUsd } = await this.store.quotaToday(actorRef, day);
315
+ if (this.quota === void 0) {
316
+ return {
317
+ usedTokens,
318
+ costUsd,
319
+ limitTokens: null,
320
+ withinLimit: true
321
+ };
322
+ }
323
+ const state = await this.quota.check(actorRef, day);
324
+ return {
325
+ usedTokens: state.usedTokens,
326
+ costUsd,
327
+ limitTokens: state.limitTokens,
328
+ withinLimit: state.withinLimit
329
+ };
290
330
  }
291
331
  /**
292
332
  * Authorization seam for thread-scoped endpoints: the caller must own the thread. A missing
@@ -337,11 +377,13 @@ AgentService = _ts_decorate2([
337
377
  _ts_param2(0, Inject2(AGENT_RUNNER)),
338
378
  _ts_param2(1, Inject2(AGENT_STORE2)),
339
379
  _ts_param2(2, Inject2(AGENT_DEPS_FACTORY)),
380
+ _ts_param2(3, Inject2(AGENT_QUOTA_STORE2)),
340
381
  _ts_metadata2("design:type", Function),
341
382
  _ts_metadata2("design:paramtypes", [
342
383
  typeof AgentRunner === "undefined" ? Object : AgentRunner,
343
384
  typeof AgentStore === "undefined" ? Object : AgentStore,
344
- typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory
385
+ typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
386
+ Object
345
387
  ])
346
388
  ], AgentService);
347
389
 
@@ -386,14 +428,14 @@ var ChatController = class {
386
428
  ...body.agent !== void 0 ? {
387
429
  agentName: body.agent
388
430
  } : {},
389
- ...body.persona !== void 0 ? {
390
- personaId: body.persona
391
- } : {},
392
431
  ...body.pageContext !== void 0 ? {
393
432
  pageContext: body.pageContext
394
433
  } : {},
395
434
  ...body.regenerate === true ? {
396
435
  regenerate: true
436
+ } : {},
437
+ ...body.transient === true ? {
438
+ transient: true
397
439
  } : {}
398
440
  });
399
441
  await this.pipe(res, runId, threadId);
@@ -550,7 +592,7 @@ QuotaController = _ts_decorate4([
550
592
 
551
593
  // src/controller/threads.controller.ts
552
594
  import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER3 } from "@dudousxd/nestjs-agent-core";
553
- import { Controller as Controller3, Delete, Get as Get3, Inject as Inject5, Param as Param2, Post as Post2, Req as Req3 } from "@nestjs/common";
595
+ import { Body as Body2, Controller as Controller3, Delete, Get as Get3, Inject as Inject5, Param as Param2, Patch, Post as Post2, Req as Req3 } from "@nestjs/common";
554
596
  function _ts_decorate5(decorators, target, key, desc) {
555
597
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
556
598
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -582,9 +624,6 @@ var ThreadsController = class {
582
624
  const actor = await this.actorResolver.resolve(req);
583
625
  return this.agent.listThreads(actor.id);
584
626
  }
585
- personas() {
586
- return this.agent.personaCatalog();
587
- }
588
627
  async detail(req, id) {
589
628
  const actor = await this.actorResolver.resolve(req);
590
629
  return this.agent.getThread(actor, id);
@@ -600,6 +639,27 @@ var ThreadsController = class {
600
639
  const actor = await this.actorResolver.resolve(req);
601
640
  return this.agent.forkThread(actor, id, messageId);
602
641
  }
642
+ async rename(req, id, body) {
643
+ const actor = await this.actorResolver.resolve(req);
644
+ await this.agent.renameThread(actor, id, body.title);
645
+ return {
646
+ ok: true
647
+ };
648
+ }
649
+ async promote(req, id) {
650
+ const actor = await this.actorResolver.resolve(req);
651
+ await this.agent.promoteThread(actor, id);
652
+ return {
653
+ ok: true
654
+ };
655
+ }
656
+ async truncateFrom(req, id, messageId) {
657
+ const actor = await this.actorResolver.resolve(req);
658
+ await this.agent.truncateThreadFrom(actor, id, messageId);
659
+ return {
660
+ ok: true
661
+ };
662
+ }
603
663
  };
604
664
  _ts_decorate5([
605
665
  Get3(),
@@ -610,12 +670,6 @@ _ts_decorate5([
610
670
  ]),
611
671
  _ts_metadata5("design:returntype", Promise)
612
672
  ], ThreadsController.prototype, "list", null);
613
- _ts_decorate5([
614
- Get3("personas/catalog"),
615
- _ts_metadata5("design:type", Function),
616
- _ts_metadata5("design:paramtypes", []),
617
- _ts_metadata5("design:returntype", void 0)
618
- ], ThreadsController.prototype, "personas", null);
619
673
  _ts_decorate5([
620
674
  Get3(":id"),
621
675
  _ts_param5(0, Req3()),
@@ -651,6 +705,43 @@ _ts_decorate5([
651
705
  ]),
652
706
  _ts_metadata5("design:returntype", Promise)
653
707
  ], ThreadsController.prototype, "fork", null);
708
+ _ts_decorate5([
709
+ Patch(":id"),
710
+ _ts_param5(0, Req3()),
711
+ _ts_param5(1, Param2("id")),
712
+ _ts_param5(2, Body2()),
713
+ _ts_metadata5("design:type", Function),
714
+ _ts_metadata5("design:paramtypes", [
715
+ typeof Request === "undefined" ? Object : Request,
716
+ String,
717
+ typeof RenameThreadBody === "undefined" ? Object : RenameThreadBody
718
+ ]),
719
+ _ts_metadata5("design:returntype", Promise)
720
+ ], ThreadsController.prototype, "rename", null);
721
+ _ts_decorate5([
722
+ Post2(":id/promote"),
723
+ _ts_param5(0, Req3()),
724
+ _ts_param5(1, Param2("id")),
725
+ _ts_metadata5("design:type", Function),
726
+ _ts_metadata5("design:paramtypes", [
727
+ typeof Request === "undefined" ? Object : Request,
728
+ String
729
+ ]),
730
+ _ts_metadata5("design:returntype", Promise)
731
+ ], ThreadsController.prototype, "promote", null);
732
+ _ts_decorate5([
733
+ Delete(":id/from/:messageId"),
734
+ _ts_param5(0, Req3()),
735
+ _ts_param5(1, Param2("id")),
736
+ _ts_param5(2, Param2("messageId")),
737
+ _ts_metadata5("design:type", Function),
738
+ _ts_metadata5("design:paramtypes", [
739
+ typeof Request === "undefined" ? Object : Request,
740
+ String,
741
+ String
742
+ ]),
743
+ _ts_metadata5("design:returntype", Promise)
744
+ ], ThreadsController.prototype, "truncateFrom", null);
654
745
  ThreadsController = _ts_decorate5([
655
746
  Controller3("threads"),
656
747
  _ts_param5(1, Inject5(AGENT_ACTOR_RESOLVER3)),
@@ -663,7 +754,7 @@ ThreadsController = _ts_decorate5([
663
754
 
664
755
  // src/controller/tool-call.controller.ts
665
756
  import { AGENT_ACTOR_RESOLVER as AGENT_ACTOR_RESOLVER4 } from "@dudousxd/nestjs-agent-core";
666
- import { Body as Body2, Controller as Controller4, Inject as Inject6, Post as Post3, Req as Req4 } from "@nestjs/common";
757
+ import { Body as Body3, Controller as Controller4, Inject as Inject6, Post as Post3, Req as Req4 } from "@nestjs/common";
667
758
  function _ts_decorate6(decorators, target, key, desc) {
668
759
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
669
760
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -709,7 +800,7 @@ var ToolCallController = class {
709
800
  _ts_decorate6([
710
801
  Post3("approve"),
711
802
  _ts_param6(0, Req4()),
712
- _ts_param6(1, Body2()),
803
+ _ts_param6(1, Body3()),
713
804
  _ts_metadata6("design:type", Function),
714
805
  _ts_metadata6("design:paramtypes", [
715
806
  typeof Request === "undefined" ? Object : Request,
@@ -720,7 +811,7 @@ _ts_decorate6([
720
811
  _ts_decorate6([
721
812
  Post3("reject"),
722
813
  _ts_param6(0, Req4()),
723
- _ts_param6(1, Body2()),
814
+ _ts_param6(1, Body3()),
724
815
  _ts_metadata6("design:type", Function),
725
816
  _ts_metadata6("design:paramtypes", [
726
817
  typeof Request === "undefined" ? Object : Request,
@@ -738,10 +829,170 @@ ToolCallController = _ts_decorate6([
738
829
  ])
739
830
  ], ToolCallController);
740
831
 
741
- // src/discovery/ai-tool-discovery.service.ts
742
- import { AGENT_OPTIONS as AGENT_OPTIONS2, AGENT_REGISTRY as AGENT_REGISTRY2, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY2 } from "@dudousxd/nestjs-agent-core";
832
+ // src/discovery/agent-discovery.service.ts
833
+ import { AGENT_PROMPT_CONTRIBUTORS as AGENT_PROMPT_CONTRIBUTORS2, AGENT_REGISTRY as AGENT_REGISTRY2, AgentRegistry as AgentRegistry3 } from "@dudousxd/nestjs-agent-core";
743
834
  import { Inject as Inject7, Injectable as Injectable3, Logger } from "@nestjs/common";
744
- import { DiscoveryService } from "@nestjs/core";
835
+ import { DiscoveryService, MetadataScanner } from "@nestjs/core";
836
+
837
+ // src/decorator/agent.decorator.ts
838
+ import "reflect-metadata";
839
+ var AGENT_METADATA = Symbol.for("@dudousxd/nestjs-agent:agent-metadata");
840
+ function Agent(options) {
841
+ return (target) => {
842
+ Reflect.defineMetadata(AGENT_METADATA, options, target);
843
+ };
844
+ }
845
+ __name(Agent, "Agent");
846
+ function readAgentMetadata(target) {
847
+ return Reflect.getMetadata(AGENT_METADATA, target);
848
+ }
849
+ __name(readAgentMetadata, "readAgentMetadata");
850
+
851
+ // src/decorator/system-prompt.decorator.ts
852
+ import "reflect-metadata";
853
+ var SYSTEM_PROMPT_METADATA = Symbol.for("@dudousxd/nestjs-agent:system-prompt");
854
+ var SYSTEM_PROMPT_CONTRIBUTOR_METADATA = Symbol.for("@dudousxd/nestjs-agent:system-prompt-contributor");
855
+ function SystemPrompt() {
856
+ return (target, key) => {
857
+ Reflect.defineMetadata(SYSTEM_PROMPT_METADATA, true, target, key);
858
+ };
859
+ }
860
+ __name(SystemPrompt, "SystemPrompt");
861
+ function SystemPromptContributor() {
862
+ return (target, key) => {
863
+ Reflect.defineMetadata(SYSTEM_PROMPT_CONTRIBUTOR_METADATA, true, target, key);
864
+ };
865
+ }
866
+ __name(SystemPromptContributor, "SystemPromptContributor");
867
+
868
+ // src/discovery/agent-discovery.service.ts
869
+ function _ts_decorate7(decorators, target, key, desc) {
870
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
871
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
872
+ 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;
873
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
874
+ }
875
+ __name(_ts_decorate7, "_ts_decorate");
876
+ function _ts_metadata7(k, v) {
877
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
878
+ }
879
+ __name(_ts_metadata7, "_ts_metadata");
880
+ function _ts_param7(paramIndex, decorator) {
881
+ return function(target, key) {
882
+ decorator(target, key, paramIndex);
883
+ };
884
+ }
885
+ __name(_ts_param7, "_ts_param");
886
+ var AgentDiscoveryService = class _AgentDiscoveryService {
887
+ static {
888
+ __name(this, "AgentDiscoveryService");
889
+ }
890
+ discovery;
891
+ scanner;
892
+ registry;
893
+ contributors;
894
+ logger = new Logger(_AgentDiscoveryService.name);
895
+ constructor(discovery, scanner, registry, contributors) {
896
+ this.discovery = discovery;
897
+ this.scanner = scanner;
898
+ this.registry = registry;
899
+ this.contributors = contributors;
900
+ }
901
+ onModuleInit() {
902
+ for (const wrapper of this.discovery.getProviders()) {
903
+ const instance = wrapper.instance;
904
+ if (instance === null || typeof instance !== "object") {
905
+ continue;
906
+ }
907
+ const meta = readAgentMetadata(instance.constructor);
908
+ if (meta !== void 0) {
909
+ this.registry.register(this.definitionFrom(instance, meta));
910
+ }
911
+ this.collectContributors(instance);
912
+ }
913
+ }
914
+ /** Build the internal {@link AgentDefinition} from an `@Agent` instance and its options. */
915
+ definitionFrom(instance, meta) {
916
+ const promptMethod = this.methodWith(instance, SYSTEM_PROMPT_METADATA);
917
+ const systemPrompt = promptMethod !== void 0 ? (ctx) => promptMethod(ctx) : meta.systemPrompt ?? "You are a helpful assistant.";
918
+ return {
919
+ name: meta.name,
920
+ systemPrompt,
921
+ ...meta.tools !== void 0 ? {
922
+ tools: meta.tools
923
+ } : {},
924
+ ...meta.model !== void 0 ? {
925
+ modelId: meta.model
926
+ } : {},
927
+ ...meta.maxSteps !== void 0 ? {
928
+ maxSteps: meta.maxSteps
929
+ } : {},
930
+ ...meta.handoff !== void 0 ? {
931
+ delegatesTo: this.handoffNames(meta)
932
+ } : {}
933
+ };
934
+ }
935
+ /** Resolve each handoff `@Agent` class to its registered name (skipping non-agent classes). */
936
+ handoffNames(meta) {
937
+ const names = [];
938
+ for (const target of meta.handoff ?? []) {
939
+ const targetMeta = readAgentMetadata(target);
940
+ if (targetMeta === void 0) {
941
+ this.logger.warn(`Agent "${meta.name}" hands off to ${target.name}, which is not an @Agent \u2014 skipped.`);
942
+ continue;
943
+ }
944
+ names.push(targetMeta.name);
945
+ }
946
+ return names;
947
+ }
948
+ /** Push every `@SystemPromptContributor()` method on `instance` (bound) into the contributor list. */
949
+ collectContributors(instance) {
950
+ const prototype = Object.getPrototypeOf(instance);
951
+ for (const name of this.scanner.getAllMethodNames(prototype)) {
952
+ if (Reflect.getMetadata(SYSTEM_PROMPT_CONTRIBUTOR_METADATA, prototype, name) === true) {
953
+ const method = this.boundMethod(instance, name);
954
+ if (method !== void 0) {
955
+ this.contributors.push((ctx) => method(ctx));
956
+ }
957
+ }
958
+ }
959
+ }
960
+ /** The single method on `instance` carrying `metadataKey`, bound to the instance, or undefined. */
961
+ methodWith(instance, metadataKey) {
962
+ const prototype = Object.getPrototypeOf(instance);
963
+ for (const name of this.scanner.getAllMethodNames(prototype)) {
964
+ if (Reflect.getMetadata(metadataKey, prototype, name) === true) {
965
+ return this.boundMethod(instance, name);
966
+ }
967
+ }
968
+ return void 0;
969
+ }
970
+ /** Bind a named method to its instance, guarding that it is actually a function. */
971
+ boundMethod(instance, name) {
972
+ const candidate = instance[name];
973
+ if (typeof candidate !== "function") {
974
+ return void 0;
975
+ }
976
+ return (ctx) => candidate.call(instance, ctx);
977
+ }
978
+ };
979
+ AgentDiscoveryService = _ts_decorate7([
980
+ Injectable3(),
981
+ _ts_param7(2, Inject7(AGENT_REGISTRY2)),
982
+ _ts_param7(3, Inject7(AGENT_PROMPT_CONTRIBUTORS2)),
983
+ _ts_metadata7("design:type", Function),
984
+ _ts_metadata7("design:paramtypes", [
985
+ typeof DiscoveryService === "undefined" ? Object : DiscoveryService,
986
+ typeof MetadataScanner === "undefined" ? Object : MetadataScanner,
987
+ typeof AgentRegistry3 === "undefined" ? Object : AgentRegistry3,
988
+ Array
989
+ ])
990
+ ], AgentDiscoveryService);
991
+
992
+ // src/discovery/ai-tool-discovery.service.ts
993
+ import { AGENT_OPTIONS as AGENT_OPTIONS2, AGENT_REGISTRY as AGENT_REGISTRY3, AGENT_TOOL_REGISTRY as AGENT_TOOL_REGISTRY2 } from "@dudousxd/nestjs-agent-core";
994
+ import { Inject as Inject8, Injectable as Injectable4, Logger as Logger2 } from "@nestjs/common";
995
+ import { DiscoveryService as DiscoveryService2 } from "@nestjs/core";
745
996
  import { z } from "zod";
746
997
 
747
998
  // src/decorator/ai-tool.decorator.ts
@@ -789,23 +1040,23 @@ function provideAgentTool(factoryOrTool, inject) {
789
1040
  __name(provideAgentTool, "provideAgentTool");
790
1041
 
791
1042
  // src/discovery/ai-tool-discovery.service.ts
792
- function _ts_decorate7(decorators, target, key, desc) {
1043
+ function _ts_decorate8(decorators, target, key, desc) {
793
1044
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
794
1045
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
795
1046
  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;
796
1047
  return c > 3 && r && Object.defineProperty(target, key, r), r;
797
1048
  }
798
- __name(_ts_decorate7, "_ts_decorate");
799
- function _ts_metadata7(k, v) {
1049
+ __name(_ts_decorate8, "_ts_decorate");
1050
+ function _ts_metadata8(k, v) {
800
1051
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
801
1052
  }
802
- __name(_ts_metadata7, "_ts_metadata");
803
- function _ts_param7(paramIndex, decorator) {
1053
+ __name(_ts_metadata8, "_ts_metadata");
1054
+ function _ts_param8(paramIndex, decorator) {
804
1055
  return function(target, key) {
805
1056
  decorator(target, key, paramIndex);
806
1057
  };
807
1058
  }
808
- __name(_ts_param7, "_ts_param");
1059
+ __name(_ts_param8, "_ts_param");
809
1060
  var AiToolDiscoveryService = class _AiToolDiscoveryService {
810
1061
  static {
811
1062
  __name(this, "AiToolDiscoveryService");
@@ -814,7 +1065,7 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
814
1065
  registry;
815
1066
  agents;
816
1067
  options;
817
- logger = new Logger(_AiToolDiscoveryService.name);
1068
+ logger = new Logger2(_AiToolDiscoveryService.name);
818
1069
  constructor(discovery, registry, agents, options) {
819
1070
  this.discovery = discovery;
820
1071
  this.registry = registry;
@@ -872,7 +1123,7 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
872
1123
  for (const target of definition.delegatesTo ?? []) {
873
1124
  const targetDefinition = this.agents.get(target);
874
1125
  if (targetDefinition === void 0) {
875
- throw new Error(`Agent "${definition.name}" delegatesTo "${target}", which is not a registered agent. Register it via AgentModule.forFeature([...]) or fix the name.`);
1126
+ 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.`);
876
1127
  }
877
1128
  const name = delegateToolName(target);
878
1129
  if (this.registry.has(name)) {
@@ -912,14 +1163,14 @@ var AiToolDiscoveryService = class _AiToolDiscoveryService {
912
1163
  return true;
913
1164
  }
914
1165
  };
915
- AiToolDiscoveryService = _ts_decorate7([
916
- Injectable3(),
917
- _ts_param7(1, Inject7(AGENT_TOOL_REGISTRY2)),
918
- _ts_param7(2, Inject7(AGENT_REGISTRY2)),
919
- _ts_param7(3, Inject7(AGENT_OPTIONS2)),
920
- _ts_metadata7("design:type", Function),
921
- _ts_metadata7("design:paramtypes", [
922
- typeof DiscoveryService === "undefined" ? Object : DiscoveryService,
1166
+ AiToolDiscoveryService = _ts_decorate8([
1167
+ Injectable4(),
1168
+ _ts_param8(1, Inject8(AGENT_TOOL_REGISTRY2)),
1169
+ _ts_param8(2, Inject8(AGENT_REGISTRY3)),
1170
+ _ts_param8(3, Inject8(AGENT_OPTIONS2)),
1171
+ _ts_metadata8("design:type", Function),
1172
+ _ts_metadata8("design:paramtypes", [
1173
+ typeof DiscoveryService2 === "undefined" ? Object : DiscoveryService2,
923
1174
  typeof ToolRegistry === "undefined" ? Object : ToolRegistry,
924
1175
  typeof AgentRegistry === "undefined" ? Object : AgentRegistry,
925
1176
  typeof AgentModuleOptions === "undefined" ? Object : AgentModuleOptions
@@ -1019,31 +1270,31 @@ var LedgerQuotaStore = class {
1019
1270
 
1020
1271
  // src/runner/inline-agent-runner.ts
1021
1272
  import { AGENT_DEPS_FACTORY as AGENT_DEPS_FACTORY2, AGENT_STORE as AGENT_STORE3, QuotaExceededError, publishAgentRunFailed, runAgentLoop } from "@dudousxd/nestjs-agent-core";
1022
- import { Inject as Inject8, Injectable as Injectable4, Logger as Logger2 } from "@nestjs/common";
1023
- function _ts_decorate8(decorators, target, key, desc) {
1273
+ import { Inject as Inject9, Injectable as Injectable5, Logger as Logger3 } from "@nestjs/common";
1274
+ function _ts_decorate9(decorators, target, key, desc) {
1024
1275
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1025
1276
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1026
1277
  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;
1027
1278
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1028
1279
  }
1029
- __name(_ts_decorate8, "_ts_decorate");
1030
- function _ts_metadata8(k, v) {
1280
+ __name(_ts_decorate9, "_ts_decorate");
1281
+ function _ts_metadata9(k, v) {
1031
1282
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1032
1283
  }
1033
- __name(_ts_metadata8, "_ts_metadata");
1034
- function _ts_param8(paramIndex, decorator) {
1284
+ __name(_ts_metadata9, "_ts_metadata");
1285
+ function _ts_param9(paramIndex, decorator) {
1035
1286
  return function(target, key) {
1036
1287
  decorator(target, key, paramIndex);
1037
1288
  };
1038
1289
  }
1039
- __name(_ts_param8, "_ts_param");
1290
+ __name(_ts_param9, "_ts_param");
1040
1291
  var InlineAgentRunner = class _InlineAgentRunner {
1041
1292
  static {
1042
1293
  __name(this, "InlineAgentRunner");
1043
1294
  }
1044
1295
  factory;
1045
1296
  store;
1046
- logger = new Logger2(_InlineAgentRunner.name);
1297
+ logger = new Logger3(_InlineAgentRunner.name);
1047
1298
  pending = /* @__PURE__ */ new Map();
1048
1299
  constructor(factory, store) {
1049
1300
  this.factory = factory;
@@ -1108,7 +1359,6 @@ var InlineAgentRunner = class _InlineAgentRunner {
1108
1359
  async runNested(agentName, task, actor, day, depth, sinkRunId) {
1109
1360
  const subThread = await this.store.createThread({
1110
1361
  actor,
1111
- persona: "default",
1112
1362
  transient: true
1113
1363
  });
1114
1364
  const runId = crypto.randomUUID();
@@ -1138,50 +1388,41 @@ var InlineAgentRunner = class _InlineAgentRunner {
1138
1388
  }, hooks);
1139
1389
  }
1140
1390
  };
1141
- InlineAgentRunner = _ts_decorate8([
1142
- Injectable4(),
1143
- _ts_param8(0, Inject8(AGENT_DEPS_FACTORY2)),
1144
- _ts_param8(1, Inject8(AGENT_STORE3)),
1145
- _ts_metadata8("design:type", Function),
1146
- _ts_metadata8("design:paramtypes", [
1391
+ InlineAgentRunner = _ts_decorate9([
1392
+ Injectable5(),
1393
+ _ts_param9(0, Inject9(AGENT_DEPS_FACTORY2)),
1394
+ _ts_param9(1, Inject9(AGENT_STORE3)),
1395
+ _ts_metadata9("design:type", Function),
1396
+ _ts_metadata9("design:paramtypes", [
1147
1397
  typeof AgentDepsFactory === "undefined" ? Object : AgentDepsFactory,
1148
1398
  typeof AgentStore === "undefined" ? Object : AgentStore
1149
1399
  ])
1150
1400
  ], InlineAgentRunner);
1151
1401
 
1152
1402
  // src/agent.module.ts
1153
- function _ts_decorate9(decorators, target, key, desc) {
1403
+ function _ts_decorate10(decorators, target, key, desc) {
1154
1404
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1155
1405
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1156
1406
  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;
1157
1407
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1158
1408
  }
1159
- __name(_ts_decorate9, "_ts_decorate");
1160
- var FEATURE_INIT = Symbol("nestjs-agent:feature-init");
1409
+ __name(_ts_decorate10, "_ts_decorate");
1161
1410
  var DEFAULT_PATH = "agent";
1162
- function defaultDefinition(options) {
1163
- return {
1164
- name: "default",
1165
- ...options.defaultAgent
1166
- };
1167
- }
1168
- __name(defaultDefinition, "defaultDefinition");
1169
1411
  function sharedProviders(durable, includeStore) {
1170
1412
  const providers = [
1171
1413
  {
1172
1414
  provide: AGENT_TOOL_REGISTRY3,
1173
1415
  useFactory: /* @__PURE__ */ __name(() => new ToolRegistry3(), "useFactory")
1174
1416
  },
1417
+ // Starts empty; AgentDiscoveryService populates it from `@Agent`-decorated providers at boot.
1175
1418
  {
1176
- provide: AGENT_REGISTRY3,
1177
- useFactory: /* @__PURE__ */ __name((options) => {
1178
- const registry = new AgentRegistry3();
1179
- registry.register(defaultDefinition(options));
1180
- return registry;
1181
- }, "useFactory"),
1182
- inject: [
1183
- AGENT_OPTIONS3
1184
- ]
1419
+ provide: AGENT_REGISTRY4,
1420
+ useFactory: /* @__PURE__ */ __name(() => new AgentRegistry4(), "useFactory")
1421
+ },
1422
+ // A shared, mutable list AgentDiscoveryService fills with `@SystemPromptContributor()` methods.
1423
+ {
1424
+ provide: AGENT_PROMPT_CONTRIBUTORS3,
1425
+ useFactory: /* @__PURE__ */ __name(() => [], "useFactory")
1185
1426
  },
1186
1427
  {
1187
1428
  provide: AGENT_SINK2,
@@ -1215,7 +1456,7 @@ function sharedProviders(durable, includeStore) {
1215
1456
  // An explicit `quota` wins; otherwise `quotaLimitTokens` binds the built-in ledger-backed
1216
1457
  // store; otherwise quotas are off (undefined). The ledger store reads the same usage rows
1217
1458
  // the loop already writes, so enforcement needs no extra shared state across replicas.
1218
- provide: AGENT_QUOTA_STORE2,
1459
+ provide: AGENT_QUOTA_STORE3,
1219
1460
  useFactory: /* @__PURE__ */ __name((o, store) => o.quota ?? (o.quotaLimitTokens !== void 0 ? new LedgerQuotaStore(store, o.quotaLimitTokens) : void 0), "useFactory"),
1220
1461
  inject: [
1221
1462
  AGENT_OPTIONS3,
@@ -1227,6 +1468,9 @@ function sharedProviders(durable, includeStore) {
1227
1468
  provide: AGENT_DEPS_FACTORY3,
1228
1469
  useExisting: AgentDepsFactory2
1229
1470
  },
1471
+ // Populates the registry + contributors (onModuleInit) BEFORE AiToolDiscoveryService synthesizes
1472
+ // handoff tools (onApplicationBootstrap) reads the registry.
1473
+ AgentDiscoveryService,
1230
1474
  AiToolDiscoveryService,
1231
1475
  InlineAgentRunner,
1232
1476
  AgentService
@@ -1269,7 +1513,7 @@ function exportsFor(includeStore) {
1269
1513
  return [
1270
1514
  AGENT_OPTIONS3,
1271
1515
  AGENT_TOOL_REGISTRY3,
1272
- AGENT_REGISTRY3,
1516
+ AGENT_REGISTRY4,
1273
1517
  AGENT_SINK2,
1274
1518
  AGENT_ROLES_POLICY2,
1275
1519
  AGENT_ACTOR_RESOLVER5,
@@ -1277,7 +1521,8 @@ function exportsFor(includeStore) {
1277
1521
  ...includeStore ? [
1278
1522
  AGENT_STORE4
1279
1523
  ] : [],
1280
- AGENT_QUOTA_STORE2,
1524
+ AGENT_QUOTA_STORE3,
1525
+ AGENT_PROMPT_CONTRIBUTORS3,
1281
1526
  AGENT_DEPS_FACTORY3,
1282
1527
  AgentDepsFactory2,
1283
1528
  AgentService,
@@ -1349,28 +1594,8 @@ var AgentModule = class _AgentModule {
1349
1594
  exports: exportsFor(true)
1350
1595
  };
1351
1596
  }
1352
- /** Register additional named agents (an orchestrator + its sub-agents). */
1353
- static forFeature(definitions) {
1354
- return {
1355
- module: _AgentModule,
1356
- providers: [
1357
- {
1358
- provide: FEATURE_INIT,
1359
- useFactory: /* @__PURE__ */ __name((registry) => {
1360
- for (const definition of definitions) {
1361
- registry.register(definition);
1362
- }
1363
- return true;
1364
- }, "useFactory"),
1365
- inject: [
1366
- AGENT_REGISTRY3
1367
- ]
1368
- }
1369
- ]
1370
- };
1371
- }
1372
1597
  };
1373
- AgentModule = _ts_decorate9([
1598
+ AgentModule = _ts_decorate10([
1374
1599
  Global(),
1375
1600
  Module({})
1376
1601
  ], AgentModule);
@@ -1408,9 +1633,12 @@ var HeaderActorResolver = class {
1408
1633
  // src/index.ts
1409
1634
  export * from "@dudousxd/nestjs-agent-core";
1410
1635
  export {
1636
+ AGENT_METADATA,
1411
1637
  AGENT_TOOL_BRAND,
1412
1638
  AI_TOOL_METADATA,
1639
+ Agent,
1413
1640
  AgentDepsFactory2 as AgentDepsFactory,
1641
+ AgentDiscoveryService,
1414
1642
  AgentModule,
1415
1643
  AgentService,
1416
1644
  AiTool,
@@ -1419,8 +1647,13 @@ export {
1419
1647
  InProcessTokenStreamSink,
1420
1648
  InlineAgentRunner,
1421
1649
  LedgerQuotaStore,
1650
+ SYSTEM_PROMPT_CONTRIBUTOR_METADATA,
1651
+ SYSTEM_PROMPT_METADATA,
1652
+ SystemPrompt,
1653
+ SystemPromptContributor,
1422
1654
  delegateToolName,
1423
1655
  provideAgentTool,
1656
+ readAgentMetadata,
1424
1657
  readAiToolMetadata,
1425
1658
  utcDay
1426
1659
  };