@dudousxd/nestjs-agent-dashboard 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,28 +22,74 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  // src/server/index.ts
23
23
  var index_exports = {};
24
24
  __export(index_exports, {
25
+ AGENT_ACTOR_DIRECTORY: () => AGENT_ACTOR_DIRECTORY,
25
26
  AGENT_GOVERNANCE_QUERIES: () => AGENT_GOVERNANCE_QUERIES,
27
+ AGENT_PRICING_STORE: () => AGENT_PRICING_STORE,
26
28
  AgentApiController: () => AgentApiController,
27
29
  AgentApiModule: () => AgentApiModule,
28
30
  AgentDashboardModule: () => AgentDashboardModule,
29
31
  AgentUiController: () => AgentUiController,
30
32
  DASHBOARD_API_PATH: () => DASHBOARD_API_PATH,
31
33
  DASHBOARD_BASE_PATH: () => DASHBOARD_BASE_PATH,
32
- DashboardService: () => DashboardService
34
+ DashboardService: () => DashboardService,
35
+ agentDashboardMountPaths: () => agentDashboardMountPaths,
36
+ parsePriceInput: () => parsePriceInput
33
37
  });
34
38
  module.exports = __toCommonJS(index_exports);
35
39
 
36
40
  // src/server/agent-api.controller.ts
37
- var import_common2 = require("@nestjs/common");
41
+ var import_common3 = require("@nestjs/common");
38
42
 
39
43
  // src/server/dashboard.service.ts
40
44
  var import_node_diagnostics_channel = require("diagnostics_channel");
41
45
  var import_nestjs_diagnostics = require("@dudousxd/nestjs-diagnostics");
42
- var import_common = require("@nestjs/common");
46
+ var import_common2 = require("@nestjs/common");
43
47
  var import_rxjs = require("rxjs");
44
48
 
49
+ // src/server/parse-price-input.ts
50
+ var import_common = require("@nestjs/common");
51
+ function parsePriceInput(body) {
52
+ if (typeof body !== "object" || body === null) {
53
+ throw new import_common.BadRequestException("Expected a JSON object body.");
54
+ }
55
+ const { modelId, inputPricePer1m, outputPricePer1m, cacheWritePricePer1m, cacheReadPricePer1m } = body;
56
+ if (typeof modelId !== "string" || modelId.trim().length === 0) {
57
+ throw new import_common.BadRequestException('"modelId" must be a non-empty string.');
58
+ }
59
+ if (!isFiniteNonNegative(inputPricePer1m)) {
60
+ throw new import_common.BadRequestException('"inputPricePer1m" must be a non-negative number.');
61
+ }
62
+ if (!isFiniteNonNegative(outputPricePer1m)) {
63
+ throw new import_common.BadRequestException('"outputPricePer1m" must be a non-negative number.');
64
+ }
65
+ if (cacheWritePricePer1m !== void 0 && !isFiniteNonNegative(cacheWritePricePer1m)) {
66
+ throw new import_common.BadRequestException('"cacheWritePricePer1m" must be a non-negative number when present.');
67
+ }
68
+ if (cacheReadPricePer1m !== void 0 && !isFiniteNonNegative(cacheReadPricePer1m)) {
69
+ throw new import_common.BadRequestException('"cacheReadPricePer1m" must be a non-negative number when present.');
70
+ }
71
+ return {
72
+ modelId,
73
+ inputPricePer1m,
74
+ outputPricePer1m,
75
+ ...cacheWritePricePer1m !== void 0 ? {
76
+ cacheWritePricePer1m
77
+ } : {},
78
+ ...cacheReadPricePer1m !== void 0 ? {
79
+ cacheReadPricePer1m
80
+ } : {}
81
+ };
82
+ }
83
+ __name(parsePriceInput, "parsePriceInput");
84
+ function isFiniteNonNegative(value) {
85
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
86
+ }
87
+ __name(isFiniteNonNegative, "isFiniteNonNegative");
88
+
45
89
  // src/server/tokens.ts
46
90
  var AGENT_GOVERNANCE_QUERIES = Symbol.for("@dudousxd/nestjs-agent:governance-queries");
91
+ var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
92
+ var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
47
93
  var DASHBOARD_BASE_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
48
94
  var DASHBOARD_API_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
49
95
 
@@ -65,6 +111,7 @@ function _ts_param(paramIndex, decorator) {
65
111
  };
66
112
  }
67
113
  __name(_ts_param, "_ts_param");
114
+ var PRICING_STORE_UNBOUND_MESSAGE = "Pricing CRUD is unavailable: no AGENT_PRICING_STORE is bound. Bind a pricing store (e.g. MikroOrmPricingStore from @dudousxd/nestjs-agent-store-mikro-orm) to enable it.";
68
115
  var AGENT_EVENTS = [
69
116
  "run.started",
70
117
  "message",
@@ -82,16 +129,21 @@ var DashboardService = class {
82
129
  __name(this, "DashboardService");
83
130
  }
84
131
  queries;
85
- constructor(queries) {
132
+ actorDirectory;
133
+ pricingStore;
134
+ constructor(queries, actorDirectory, pricingStore) {
86
135
  this.queries = queries;
136
+ this.actorDirectory = actorDirectory;
137
+ this.pricingStore = pricingStore;
87
138
  }
88
139
  /** Spend/usage overview for a day range: by-model + by-actor spend and the daily trend, in parallel. */
89
140
  async spend(range) {
90
- const [byModel, byActor, trend] = await Promise.all([
141
+ const [byModel, byActorRaw, trend] = await Promise.all([
91
142
  this.queries.spendByModel(range),
92
143
  this.queries.spendByActor(range),
93
144
  this.queries.usageTrend(range)
94
145
  ]);
146
+ const byActor = await this.withActorLabels(byActorRaw);
95
147
  return {
96
148
  byModel,
97
149
  byActor,
@@ -99,16 +151,60 @@ var DashboardService = class {
99
151
  };
100
152
  }
101
153
  /** Top threads by cost for a day range (default 10, highest cost first). */
102
- topThreads(range, limit = 10) {
103
- return this.queries.spendByThread(range, limit);
154
+ async topThreads(range, limit = 10) {
155
+ const rows = await this.queries.spendByThread(range, limit);
156
+ return this.withActorLabels(rows);
104
157
  }
105
158
  /** Most recent tool calls (status/type/thread) for the Runs & tools activity feed. */
106
159
  recentToolCalls(limit) {
107
160
  return this.queries.recentToolCalls(limit);
108
161
  }
109
162
  /** Most recent threads with rolled-up message/token counts. */
110
- recentThreads(limit) {
111
- return this.queries.recentThreads(limit);
163
+ async recentThreads(limit) {
164
+ const rows = await this.queries.recentThreads(limit);
165
+ return this.withActorLabels(rows);
166
+ }
167
+ /**
168
+ * Decorate actor-scoped rows with `actorLabel`, batching the distinct `actorRef`s into ONE
169
+ * {@link ActorDirectory.resolveDisplay} call per response. `null` for every row when no directory
170
+ * is bound, or for a ref the directory didn't resolve.
171
+ */
172
+ async withActorLabels(rows) {
173
+ if (rows.length === 0) {
174
+ return [];
175
+ }
176
+ if (this.actorDirectory === void 0) {
177
+ return rows.map((row) => ({
178
+ ...row,
179
+ actorLabel: null
180
+ }));
181
+ }
182
+ const refs = [
183
+ ...new Set(rows.map((row) => row.actorRef))
184
+ ];
185
+ const resolved = await this.actorDirectory.resolveDisplay(refs);
186
+ return rows.map((row) => ({
187
+ ...row,
188
+ actorLabel: resolved[row.actorRef] ?? null
189
+ }));
190
+ }
191
+ /** Current price row per model, for the pricing tab. 501s when no `AGENT_PRICING_STORE` is bound. */
192
+ async listPrices() {
193
+ if (this.pricingStore === void 0) {
194
+ throw new import_common2.NotImplementedException(PRICING_STORE_UNBOUND_MESSAGE);
195
+ }
196
+ return this.pricingStore.listCurrentPrices();
197
+ }
198
+ /**
199
+ * Set a model's current price (`POST <api>/pricing` body). 501s when no `AGENT_PRICING_STORE` is
200
+ * bound (checked BEFORE body validation, so an unbound store always reports as unimplemented rather
201
+ * than as a validation error); otherwise the body is minimally validated via {@link parsePriceInput}.
202
+ */
203
+ async upsertPrice(body) {
204
+ if (this.pricingStore === void 0) {
205
+ throw new import_common2.NotImplementedException(PRICING_STORE_UNBOUND_MESSAGE);
206
+ }
207
+ await this.pricingStore.upsertModelPrice(parsePriceInput(body));
112
208
  }
113
209
  /**
114
210
  * Live SSE stream of `aviary:agent:*` diagnostics events. One subscription per SSE client:
@@ -142,11 +238,17 @@ var DashboardService = class {
142
238
  }
143
239
  };
144
240
  DashboardService = _ts_decorate([
145
- (0, import_common.Injectable)(),
146
- _ts_param(0, (0, import_common.Inject)(AGENT_GOVERNANCE_QUERIES)),
241
+ (0, import_common2.Injectable)(),
242
+ _ts_param(0, (0, import_common2.Inject)(AGENT_GOVERNANCE_QUERIES)),
243
+ _ts_param(1, (0, import_common2.Optional)()),
244
+ _ts_param(1, (0, import_common2.Inject)(AGENT_ACTOR_DIRECTORY)),
245
+ _ts_param(2, (0, import_common2.Optional)()),
246
+ _ts_param(2, (0, import_common2.Inject)(AGENT_PRICING_STORE)),
147
247
  _ts_metadata("design:type", Function),
148
248
  _ts_metadata("design:paramtypes", [
149
- typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries
249
+ typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries,
250
+ typeof ActorDirectory === "undefined" ? Object : ActorDirectory,
251
+ typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore
150
252
  ])
151
253
  ], DashboardService);
152
254
 
@@ -215,15 +317,30 @@ var AgentApiController = class {
215
317
  threads(limit) {
216
318
  return this.dashboard.recentThreads(parseLimit(limit, 50));
217
319
  }
320
+ /**
321
+ * Current price row per model, for the pricing tab. 501s (via `DashboardService.listPrices`) when
322
+ * no `AGENT_PRICING_STORE` is bound.
323
+ */
324
+ listPrices() {
325
+ return this.dashboard.listPrices();
326
+ }
327
+ /**
328
+ * Set a model's current price. Body shape mirrors core's `ModelPriceInput`
329
+ * (`{ modelId, inputPricePer1m, outputPricePer1m, cacheWritePricePer1m?, cacheReadPricePer1m? }`).
330
+ * 501s when no `AGENT_PRICING_STORE` is bound; 400s on a malformed body.
331
+ */
332
+ upsertPrice(body) {
333
+ return this.dashboard.upsertPrice(body);
334
+ }
218
335
  /** Server-Sent Events stream of live `aviary:agent:*` events — the Live feed tails it. */
219
336
  stream() {
220
337
  return this.dashboard.streamEvents();
221
338
  }
222
339
  };
223
340
  _ts_decorate2([
224
- (0, import_common2.Get)("spend"),
225
- _ts_param2(0, (0, import_common2.Query)("from")),
226
- _ts_param2(1, (0, import_common2.Query)("to")),
341
+ (0, import_common3.Get)("spend"),
342
+ _ts_param2(0, (0, import_common3.Query)("from")),
343
+ _ts_param2(1, (0, import_common3.Query)("to")),
227
344
  _ts_metadata2("design:type", Function),
228
345
  _ts_metadata2("design:paramtypes", [
229
346
  String,
@@ -232,10 +349,10 @@ _ts_decorate2([
232
349
  _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
233
350
  ], AgentApiController.prototype, "spend", null);
234
351
  _ts_decorate2([
235
- (0, import_common2.Get)("top-threads"),
236
- _ts_param2(0, (0, import_common2.Query)("from")),
237
- _ts_param2(1, (0, import_common2.Query)("to")),
238
- _ts_param2(2, (0, import_common2.Query)("limit")),
352
+ (0, import_common3.Get)("top-threads"),
353
+ _ts_param2(0, (0, import_common3.Query)("from")),
354
+ _ts_param2(1, (0, import_common3.Query)("to")),
355
+ _ts_param2(2, (0, import_common3.Query)("limit")),
239
356
  _ts_metadata2("design:type", Function),
240
357
  _ts_metadata2("design:paramtypes", [
241
358
  String,
@@ -245,8 +362,8 @@ _ts_decorate2([
245
362
  _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
246
363
  ], AgentApiController.prototype, "topThreads", null);
247
364
  _ts_decorate2([
248
- (0, import_common2.Get)("tool-calls"),
249
- _ts_param2(0, (0, import_common2.Query)("limit")),
365
+ (0, import_common3.Get)("tool-calls"),
366
+ _ts_param2(0, (0, import_common3.Query)("limit")),
250
367
  _ts_metadata2("design:type", Function),
251
368
  _ts_metadata2("design:paramtypes", [
252
369
  String
@@ -254,8 +371,8 @@ _ts_decorate2([
254
371
  _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
255
372
  ], AgentApiController.prototype, "toolCalls", null);
256
373
  _ts_decorate2([
257
- (0, import_common2.Get)("threads"),
258
- _ts_param2(0, (0, import_common2.Query)("limit")),
374
+ (0, import_common3.Get)("threads"),
375
+ _ts_param2(0, (0, import_common3.Query)("limit")),
259
376
  _ts_metadata2("design:type", Function),
260
377
  _ts_metadata2("design:paramtypes", [
261
378
  String
@@ -263,28 +380,69 @@ _ts_decorate2([
263
380
  _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
264
381
  ], AgentApiController.prototype, "threads", null);
265
382
  _ts_decorate2([
266
- (0, import_common2.Sse)("stream"),
383
+ (0, import_common3.Get)("pricing"),
384
+ _ts_metadata2("design:type", Function),
385
+ _ts_metadata2("design:paramtypes", []),
386
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
387
+ ], AgentApiController.prototype, "listPrices", null);
388
+ _ts_decorate2([
389
+ (0, import_common3.Post)("pricing"),
390
+ _ts_param2(0, (0, import_common3.Body)()),
391
+ _ts_metadata2("design:type", Function),
392
+ _ts_metadata2("design:paramtypes", [
393
+ Object
394
+ ]),
395
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
396
+ ], AgentApiController.prototype, "upsertPrice", null);
397
+ _ts_decorate2([
398
+ (0, import_common3.Sse)("stream"),
267
399
  _ts_metadata2("design:type", Function),
268
400
  _ts_metadata2("design:paramtypes", []),
269
401
  _ts_metadata2("design:returntype", typeof Observable === "undefined" ? Object : Observable)
270
402
  ], AgentApiController.prototype, "stream", null);
271
403
  AgentApiController = _ts_decorate2([
272
- (0, import_common2.Controller)(),
404
+ (0, import_common3.Controller)(),
273
405
  _ts_metadata2("design:type", Function),
274
406
  _ts_metadata2("design:paramtypes", [
275
407
  typeof DashboardService === "undefined" ? Object : DashboardService
276
408
  ])
277
409
  ], AgentApiController);
278
410
 
411
+ // src/server/normalize-path.ts
412
+ function normalizeDashboardPath(path) {
413
+ return `/${path.replace(/^\/+|\/+$/g, "")}`;
414
+ }
415
+ __name(normalizeDashboardPath, "normalizeDashboardPath");
416
+
417
+ // src/server/agent-dashboard-mount-paths.ts
418
+ function unprefixed(path) {
419
+ return path.replace(/^\/+/, "");
420
+ }
421
+ __name(unprefixed, "unprefixed");
422
+ function agentDashboardMountPaths(options) {
423
+ const basePath = normalizeDashboardPath(options?.basePath ?? "/ai-gateway");
424
+ const apiBasePath = normalizeDashboardPath(options?.apiBasePath ?? `${basePath}/api`);
425
+ const base = unprefixed(basePath);
426
+ const api = unprefixed(apiBasePath);
427
+ return [
428
+ base,
429
+ `${base}/{*splat}`,
430
+ api,
431
+ `${api}/{*splat}`
432
+ ];
433
+ }
434
+ __name(agentDashboardMountPaths, "agentDashboardMountPaths");
435
+
279
436
  // src/server/agent-dashboard.module.ts
280
- var import_common4 = require("@nestjs/common");
437
+ var import_reflect_metadata = require("reflect-metadata");
438
+ var import_common5 = require("@nestjs/common");
281
439
  var import_core = require("@nestjs/core");
282
440
 
283
441
  // src/server/agent-ui.controller.ts
284
442
  var import_node_fs = require("fs");
285
443
  var import_node_path = require("path");
286
444
  var import_node_url = require("url");
287
- var import_common3 = require("@nestjs/common");
445
+ var import_common4 = require("@nestjs/common");
288
446
  function _ts_decorate3(decorators, target, key, desc) {
289
447
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
290
448
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -332,7 +490,7 @@ var AgentUiController = class {
332
490
  index() {
333
491
  const indexPath = (0, import_node_path.join)(this.dir, "index.html");
334
492
  if (!(0, import_node_fs.existsSync)(indexPath)) {
335
- throw new import_common3.NotFoundException("Dashboard is not built. Run the package build.");
493
+ throw new import_common4.NotFoundException("Dashboard is not built. Run the package build.");
336
494
  }
337
495
  const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
338
496
  const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>`;
@@ -340,40 +498,40 @@ var AgentUiController = class {
340
498
  }
341
499
  asset(file) {
342
500
  const safe = (0, import_node_path.basename)(file);
343
- if (safe !== file) throw new import_common3.NotFoundException();
501
+ if (safe !== file) throw new import_common4.NotFoundException();
344
502
  const root = (0, import_node_path.resolve)(this.dir, "assets");
345
503
  const assetPath = (0, import_node_path.resolve)(root, safe);
346
504
  if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
347
- throw new import_common3.NotFoundException();
505
+ throw new import_common4.NotFoundException();
348
506
  }
349
507
  const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
350
- return new import_common3.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
508
+ return new import_common4.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
351
509
  type
352
510
  });
353
511
  }
354
512
  };
355
513
  _ts_decorate3([
356
- (0, import_common3.Get)(),
357
- (0, import_common3.Header)("Content-Type", "text/html; charset=utf-8"),
358
- (0, import_common3.Header)("Cache-Control", "no-store, must-revalidate"),
514
+ (0, import_common4.Get)(),
515
+ (0, import_common4.Header)("Content-Type", "text/html; charset=utf-8"),
516
+ (0, import_common4.Header)("Cache-Control", "no-store, must-revalidate"),
359
517
  _ts_metadata3("design:type", Function),
360
518
  _ts_metadata3("design:paramtypes", []),
361
519
  _ts_metadata3("design:returntype", String)
362
520
  ], AgentUiController.prototype, "index", null);
363
521
  _ts_decorate3([
364
- (0, import_common3.Get)("assets/:file"),
365
- (0, import_common3.Header)("Cache-Control", "public, max-age=31536000, immutable"),
366
- _ts_param3(0, (0, import_common3.Param)("file")),
522
+ (0, import_common4.Get)("assets/:file"),
523
+ (0, import_common4.Header)("Cache-Control", "public, max-age=31536000, immutable"),
524
+ _ts_param3(0, (0, import_common4.Param)("file")),
367
525
  _ts_metadata3("design:type", Function),
368
526
  _ts_metadata3("design:paramtypes", [
369
527
  String
370
528
  ]),
371
- _ts_metadata3("design:returntype", typeof import_common3.StreamableFile === "undefined" ? Object : import_common3.StreamableFile)
529
+ _ts_metadata3("design:returntype", typeof import_common4.StreamableFile === "undefined" ? Object : import_common4.StreamableFile)
372
530
  ], AgentUiController.prototype, "asset", null);
373
531
  AgentUiController = _ts_decorate3([
374
- (0, import_common3.Controller)(),
375
- _ts_param3(0, (0, import_common3.Inject)(DASHBOARD_BASE_PATH)),
376
- _ts_param3(1, (0, import_common3.Inject)(DASHBOARD_API_PATH)),
532
+ (0, import_common4.Controller)(),
533
+ _ts_param3(0, (0, import_common4.Inject)(DASHBOARD_BASE_PATH)),
534
+ _ts_param3(1, (0, import_common4.Inject)(DASHBOARD_API_PATH)),
377
535
  _ts_metadata3("design:type", Function),
378
536
  _ts_metadata3("design:paramtypes", [
379
537
  String,
@@ -389,27 +547,42 @@ function _ts_decorate4(decorators, target, key, desc) {
389
547
  return c > 3 && r && Object.defineProperty(target, key, r), r;
390
548
  }
391
549
  __name(_ts_decorate4, "_ts_decorate");
550
+ var GUARDS_METADATA = "__guards__";
392
551
  function normalize(path) {
393
- return `/${path.replace(/^\/+|\/+$/g, "")}`;
552
+ return normalizeDashboardPath(path);
394
553
  }
395
554
  __name(normalize, "normalize");
396
- var AgentApiModule = class {
555
+ function stampGuards(guards, ...controllers) {
556
+ for (const controller of controllers) {
557
+ Reflect.defineMetadata(GUARDS_METADATA, guards ?? [], controller);
558
+ }
559
+ }
560
+ __name(stampGuards, "stampGuards");
561
+ var AgentApiModule = class _AgentApiModule {
397
562
  static {
398
563
  __name(this, "AgentApiModule");
399
564
  }
565
+ static register(options) {
566
+ return {
567
+ module: _AgentApiModule,
568
+ imports: [
569
+ ...options.imports ?? []
570
+ ],
571
+ controllers: [
572
+ AgentApiController
573
+ ],
574
+ providers: [
575
+ DashboardService,
576
+ ...options.guards ?? []
577
+ ],
578
+ exports: [
579
+ DashboardService
580
+ ]
581
+ };
582
+ }
400
583
  };
401
584
  AgentApiModule = _ts_decorate4([
402
- (0, import_common4.Module)({
403
- controllers: [
404
- AgentApiController
405
- ],
406
- providers: [
407
- DashboardService
408
- ],
409
- exports: [
410
- DashboardService
411
- ]
412
- })
585
+ (0, import_common5.Module)({})
413
586
  ], AgentApiModule);
414
587
  var AgentDashboardModule = class _AgentDashboardModule {
415
588
  static {
@@ -418,10 +591,22 @@ var AgentDashboardModule = class _AgentDashboardModule {
418
591
  static forRoot(options = {}) {
419
592
  const basePath = normalize(options.basePath ?? "/ai-gateway");
420
593
  const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
594
+ stampGuards(options.guards, AgentApiController, AgentUiController);
421
595
  return {
422
596
  module: _AgentDashboardModule,
423
597
  imports: [
424
- AgentApiModule,
598
+ ...options.imports ?? [],
599
+ // Guards + host imports must reach the API controller's HOST module — enhancers resolve
600
+ // from their controller's own module, never from a parent (see AgentApiModule.register).
601
+ // Spread-only-when-set: exactOptionalPropertyTypes rejects an explicit `undefined`.
602
+ AgentApiModule.register({
603
+ ...options.imports ? {
604
+ imports: options.imports
605
+ } : {},
606
+ ...options.guards ? {
607
+ guards: options.guards
608
+ } : {}
609
+ }),
425
610
  import_core.RouterModule.register([
426
611
  {
427
612
  path: basePath,
@@ -444,7 +629,9 @@ var AgentDashboardModule = class _AgentDashboardModule {
444
629
  {
445
630
  provide: DASHBOARD_API_PATH,
446
631
  useValue: apiBasePath
447
- }
632
+ },
633
+ // AgentUiController is hosted HERE, so its guards DI-instantiate from this module.
634
+ ...options.guards ?? []
448
635
  ],
449
636
  // Re-export the API module so its DashboardService reaches importers (e.g. the host's own controllers).
450
637
  exports: [
@@ -454,17 +641,21 @@ var AgentDashboardModule = class _AgentDashboardModule {
454
641
  }
455
642
  };
456
643
  AgentDashboardModule = _ts_decorate4([
457
- (0, import_common4.Module)({})
644
+ (0, import_common5.Module)({})
458
645
  ], AgentDashboardModule);
459
646
  // Annotate the CommonJS export names for ESM import in node:
460
647
  0 && (module.exports = {
648
+ AGENT_ACTOR_DIRECTORY,
461
649
  AGENT_GOVERNANCE_QUERIES,
650
+ AGENT_PRICING_STORE,
462
651
  AgentApiController,
463
652
  AgentApiModule,
464
653
  AgentDashboardModule,
465
654
  AgentUiController,
466
655
  DASHBOARD_API_PATH,
467
656
  DASHBOARD_BASE_PATH,
468
- DashboardService
657
+ DashboardService,
658
+ agentDashboardMountPaths,
659
+ parsePriceInput
469
660
  });
470
661
  //# sourceMappingURL=index.cjs.map