@dudousxd/nestjs-agent-dashboard 0.21.0 → 0.23.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.
@@ -35,16 +35,24 @@ __export(index_exports, {
35
35
  AGENT_ACTOR_DIRECTORY: () => AGENT_ACTOR_DIRECTORY,
36
36
  AGENT_ACTOR_RESOLVER: () => AGENT_ACTOR_RESOLVER,
37
37
  AGENT_APPROVAL_PORT: () => AGENT_APPROVAL_PORT,
38
+ AGENT_CONSOLE_ID: () => AGENT_CONSOLE_ID,
39
+ AGENT_DASHBOARD_CONFIG_ID: () => AGENT_DASHBOARD_CONFIG_ID,
38
40
  AGENT_GOVERNANCE_QUERIES: () => AGENT_GOVERNANCE_QUERIES,
41
+ AGENT_OPTIONS: () => AGENT_OPTIONS,
39
42
  AGENT_PRICING_STORE: () => AGENT_PRICING_STORE,
43
+ AVIARY_CONSOLES_SLOT: () => AVIARY_CONSOLES_SLOT,
40
44
  AgentApiController: () => AgentApiController,
41
45
  AgentApiModule: () => AgentApiModule,
46
+ AgentConsoleRegistration: () => AgentConsoleRegistration,
47
+ AgentConsolesController: () => AgentConsolesController,
42
48
  AgentDashboardModule: () => AgentDashboardModule,
43
49
  AgentDevToolsRegistration: () => AgentDevToolsRegistration,
44
50
  AgentUiController: () => AgentUiController,
45
51
  CONSOLE_AUTHORIZE_MISSING_WARNING: () => CONSOLE_AUTHORIZE_MISSING_WARNING,
46
52
  CONSOLE_GATE: () => CONSOLE_GATE,
47
53
  CONSOLE_PAGE_METADATA: () => CONSOLE_PAGE_METADATA,
54
+ CONSOLE_PROBE_TIMEOUT_MS: () => CONSOLE_PROBE_TIMEOUT_MS,
55
+ CONTEXT_ACCESSOR: () => CONTEXT_ACCESSOR,
48
56
  ConsoleAccessDenied: () => ConsoleAccessDenied,
49
57
  ConsoleAuthorizeFilter: () => ConsoleAuthorizeFilter,
50
58
  ConsoleAuthorizeGuard: () => ConsoleAuthorizeGuard,
@@ -61,8 +69,10 @@ __export(index_exports, {
61
69
  agentDevTools: () => agentDevTools,
62
70
  anyAuthorize: () => anyAuthorize,
63
71
  authorizeByToken: () => authorizeByToken,
72
+ listVisibleConsoles: () => listVisibleConsoles,
64
73
  normalizeConsoleResult: () => normalizeConsoleResult,
65
74
  parsePriceInput: () => parsePriceInput,
75
+ registerAviaryConsole: () => registerAviaryConsole,
66
76
  resolveConsoleAuthorize: () => resolveConsoleAuthorize
67
77
  });
68
78
  module.exports = __toCommonJS(index_exports);
@@ -139,12 +149,37 @@ function isFiniteNonNegative(value) {
139
149
  }
140
150
  __name(isFiniteNonNegative, "isFiniteNonNegative");
141
151
 
152
+ // src/server/tenancy.ts
153
+ var SLOT = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-diagnostics:accessor");
154
+ function consoleTenantFilter(option = "inherit", accessor) {
155
+ const slot = globalThis[SLOT];
156
+ const a = accessor ?? slot?.current;
157
+ if (option === false || typeof a?.tenancy !== "function" || !a.tenantFilter) return void 0;
158
+ const own = typeof option === "object" ? option : {};
159
+ const inherit = own.enabled === void 0 || own.enabled === "inherit";
160
+ if (!(inherit ? a.tenancy().enabled : own.enabled)) return void 0;
161
+ const filter = a.tenantFilter(own.kinds ? {
162
+ kinds: own.kinds
163
+ } : void 0);
164
+ if (filter.mode === "system" || filter.mode === "all") return void 0;
165
+ if (filter.mode === "tenantless") return {
166
+ nulls: true
167
+ };
168
+ return {
169
+ tenant: filter.tenant.id,
170
+ nulls: own.nullRows === "shared"
171
+ };
172
+ }
173
+ __name(consoleTenantFilter, "consoleTenantFilter");
174
+
142
175
  // src/server/tokens.ts
143
176
  var AGENT_GOVERNANCE_QUERIES = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:governance-queries");
144
177
  var AGENT_ACTOR_DIRECTORY = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:actor-directory");
145
178
  var AGENT_PRICING_STORE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:pricing-store");
146
179
  var AGENT_APPROVAL_PORT = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:approval-port");
147
180
  var AGENT_ACTOR_RESOLVER = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
181
+ var AGENT_OPTIONS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:options");
182
+ var CONTEXT_ACCESSOR = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-context:accessor");
148
183
  var DASHBOARD_BASE_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
149
184
  var DASHBOARD_API_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
150
185
  var DASHBOARD_APPROVAL_ACTOR_REF = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
@@ -180,6 +215,7 @@ function _ts_param(paramIndex, decorator) {
180
215
  __name(_ts_param, "_ts_param");
181
216
  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.";
182
217
  var APPROVAL_PORT_UNBOUND_MESSAGE = "Approve/reject is unavailable: no AGENT_APPROVAL_PORT is bound. Import AgentModule from @dudousxd/nestjs-agent alongside this dashboard to enable it \u2014 the approvals inbox stays read-only until then.";
218
+ var TENANT_SCOPE_UNSUPPORTED_MESSAGE = "The agent console is tenant-scoped (AgentModule tenancy is on), and the bound AGENT_GOVERNANCE_QUERIES store does not implement forTenant. Use a store adapter that does (Drizzle, MikroORM, in-memory) or set AgentModule `tenancy: false`.";
183
219
  var GENUI_STATS_UNSUPPORTED_MESSAGE = "Generative UI telemetry is unavailable: the bound AGENT_GOVERNANCE_QUERIES store does not implement genuiStats. Use a store adapter that records generative-UI calls (recordGenuiCalls) to enable it.";
184
220
  var AGENT_EVENTS = [
185
221
  "run.started",
@@ -203,19 +239,37 @@ var DashboardService = class {
203
239
  actorDirectory;
204
240
  pricingStore;
205
241
  approvalPort;
206
- constructor(queries, actorDirectory, pricingStore, approvalPort) {
242
+ agentOptions;
243
+ contextAccessor;
244
+ constructor(queries, actorDirectory, pricingStore, approvalPort, agentOptions, contextAccessor) {
207
245
  this.queries = queries;
208
246
  this.actorDirectory = actorDirectory;
209
247
  this.pricingStore = pricingStore;
210
248
  this.approvalPort = approvalPort;
249
+ this.agentOptions = agentOptions;
250
+ this.contextAccessor = contextAccessor;
251
+ }
252
+ /**
253
+ * The read-model for this request: with the agent's tenancy on, narrowed to the viewer's context
254
+ * tenant (another tenant's thread or run is not found). A store without `forTenant` cannot be
255
+ * narrowed, so the console refuses (`501`) rather than show every tenant's rows.
256
+ */
257
+ scoped() {
258
+ const filter = consoleTenantFilter(this.agentOptions?.tenancy ?? "inherit", this.contextAccessor);
259
+ if (filter === void 0) return this.queries;
260
+ if (typeof this.queries.forTenant !== "function") {
261
+ throw new import_common3.NotImplementedException(TENANT_SCOPE_UNSUPPORTED_MESSAGE);
262
+ }
263
+ return this.queries.forTenant(filter);
211
264
  }
212
265
  /** Spend/usage overview for a day range: by-model + by-actor spend and the daily trend, in parallel. */
213
266
  async spend(range) {
267
+ const queries = this.scoped();
214
268
  const [byModel, byActorRaw, trend, byFeature] = await Promise.all([
215
- this.queries.spendByModel(range),
216
- this.queries.spendByActor(range),
217
- this.queries.usageTrend(range),
218
- this.queries.spendByFeature?.(range)
269
+ queries.spendByModel(range),
270
+ queries.spendByActor(range),
271
+ queries.usageTrend(range),
272
+ queries.spendByFeature?.(range)
219
273
  ]);
220
274
  const byActor = await this.withActorLabels(byActorRaw);
221
275
  return {
@@ -229,16 +283,17 @@ var DashboardService = class {
229
283
  }
230
284
  /** Top threads by cost for a day range (default 10, highest cost first). */
231
285
  async topThreads(range, limit2 = 10) {
232
- const rows = await this.queries.spendByThread(range, limit2);
286
+ const rows = await this.scoped().spendByThread(range, limit2);
233
287
  return this.withActorLabels(rows);
234
288
  }
235
289
  /** Run reliability for a day range: metrics, by-agent/by-error breakdowns and the trend, in parallel. */
236
290
  async reliability(range) {
291
+ const queries = this.scoped();
237
292
  const [metrics, byAgent, errors, trend] = await Promise.all([
238
- this.queries.runMetrics(range),
239
- this.queries.runsByAgent(range),
240
- this.queries.runErrors(range),
241
- this.queries.runTrend(range)
293
+ queries.runMetrics(range),
294
+ queries.runsByAgent(range),
295
+ queries.runErrors(range),
296
+ queries.runTrend(range)
242
297
  ]);
243
298
  return {
244
299
  metrics,
@@ -249,19 +304,19 @@ var DashboardService = class {
249
304
  }
250
305
  /** Most recent runs (status/agent/duration/error) for the Reliability recent-runs table. */
251
306
  recentRuns(limit2) {
252
- return this.queries.recentRuns(limit2);
307
+ return this.scoped().recentRuns(limit2);
253
308
  }
254
309
  /** Most recent tool calls (status/type/thread) for the Runs & tools activity feed. */
255
310
  recentToolCalls(limit2) {
256
- return this.queries.recentToolCalls(limit2);
311
+ return this.scoped().recentToolCalls(limit2);
257
312
  }
258
313
  /** Paged, filterable tool calls for the Runs & tools activity table. */
259
314
  toolCallsPage(query) {
260
- return this.queries.toolCallsPage(query);
315
+ return this.scoped().toolCallsPage(query);
261
316
  }
262
317
  /** Paged, filterable runs for the Reliability recent-runs table. */
263
318
  runsPage(query) {
264
- return this.queries.runsPage(query);
319
+ return this.scoped().runsPage(query);
265
320
  }
266
321
  /**
267
322
  * Tool calls sitting `pending_approval`, oldest first, for the cross-thread approvals inbox.
@@ -269,11 +324,11 @@ var DashboardService = class {
269
324
  * {@link approvalsPage}, which reports how much of the backlog the cap hid.
270
325
  */
271
326
  pendingApprovals(limit2) {
272
- return this.queries.pendingApprovals(limit2);
327
+ return this.scoped().pendingApprovals(limit2);
273
328
  }
274
329
  /** Paged, filterable approvals inbox with a total — the backlog-safe read of the HITL queue. */
275
330
  approvalsPage(query) {
276
- return this.queries.approvalsPage(query);
331
+ return this.scoped().approvalsPage(query);
277
332
  }
278
333
  /**
279
334
  * One run with its thread and its tool calls. 404s on an unknown id rather than returning an empty
@@ -281,7 +336,7 @@ var DashboardService = class {
281
336
  * that conflates them sends an operator looking for a bug that isn't there.
282
337
  */
283
338
  async runDetail(runId) {
284
- const detail = await this.queries.runDetail(runId);
339
+ const detail = await this.scoped().runDetail(runId);
285
340
  if (detail === null) {
286
341
  throw new import_common3.NotFoundException(`No run "${runId}".`);
287
342
  }
@@ -298,7 +353,7 @@ var DashboardService = class {
298
353
  }
299
354
  /** One thread with its usage rollup, runs and messages. 404s on an unknown id, like {@link runDetail}. */
300
355
  async threadDetail(query) {
301
- const detail = await this.queries.threadDetail(query);
356
+ const detail = await this.scoped().threadDetail(query);
302
357
  if (detail === null) {
303
358
  throw new import_common3.NotFoundException(`No thread "${query.threadId}".`);
304
359
  }
@@ -315,7 +370,7 @@ var DashboardService = class {
315
370
  }
316
371
  /** Per-tool call/failure/rejection/latency rollup for a day range, for the Tools section. */
317
372
  toolStats(range) {
318
- return this.queries.toolStats(range);
373
+ return this.scoped().toolStats(range);
319
374
  }
320
375
  /**
321
376
  * Generative-UI telemetry for a day range — first-try success per tool/model, common errors, UI
@@ -324,10 +379,11 @@ var DashboardService = class {
324
379
  * same posture as an unbound pricing store — the console renders that as its own state.
325
380
  */
326
381
  async genuiStats(range) {
327
- if (this.queries.genuiStats === void 0) {
382
+ const queries = this.scoped();
383
+ if (queries.genuiStats === void 0) {
328
384
  throw new import_common3.NotImplementedException(GENUI_STATS_UNSUPPORTED_MESSAGE);
329
385
  }
330
- return this.queries.genuiStats(range);
386
+ return queries.genuiStats(range);
331
387
  }
332
388
  /**
333
389
  * Decide a pending HITL tool call from the console. Routes through the OPTIONAL
@@ -358,7 +414,7 @@ var DashboardService = class {
358
414
  }
359
415
  /** Most recent threads with rolled-up message/token counts. */
360
416
  async recentThreads(limit2) {
361
- const rows = await this.queries.recentThreads(limit2);
417
+ const rows = await this.scoped().recentThreads(limit2);
362
418
  return this.withActorLabels(rows);
363
419
  }
364
420
  /**
@@ -366,7 +422,7 @@ var DashboardService = class {
366
422
  * {@link recentThreads} is.
367
423
  */
368
424
  async threadsPage(query) {
369
- const page2 = await this.queries.threadsPage(query);
425
+ const page2 = await this.scoped().threadsPage(query);
370
426
  const rows = await this.withActorLabels(page2.rows);
371
427
  return {
372
428
  ...page2,
@@ -455,12 +511,18 @@ DashboardService = _ts_decorate([
455
511
  _ts_param(2, (0, import_common3.Inject)(AGENT_PRICING_STORE)),
456
512
  _ts_param(3, (0, import_common3.Optional)()),
457
513
  _ts_param(3, (0, import_common3.Inject)(AGENT_APPROVAL_PORT)),
514
+ _ts_param(4, (0, import_common3.Optional)()),
515
+ _ts_param(4, (0, import_common3.Inject)(AGENT_OPTIONS)),
516
+ _ts_param(5, (0, import_common3.Optional)()),
517
+ _ts_param(5, (0, import_common3.Inject)(CONTEXT_ACCESSOR)),
458
518
  _ts_metadata("design:type", Function),
459
519
  _ts_metadata("design:paramtypes", [
460
520
  typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries,
461
521
  typeof ActorDirectory === "undefined" ? Object : ActorDirectory,
462
522
  typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
463
- typeof AgentApprovalPort === "undefined" ? Object : AgentApprovalPort
523
+ typeof AgentApprovalPort === "undefined" ? Object : AgentApprovalPort,
524
+ Object,
525
+ Object
464
526
  ])
465
527
  ], DashboardService);
466
528
 
@@ -1109,17 +1171,17 @@ function agentDashboardMountPaths(options) {
1109
1171
  __name(agentDashboardMountPaths, "agentDashboardMountPaths");
1110
1172
 
1111
1173
  // src/server/agent-dashboard.module.ts
1112
- var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
1174
+ var import_nestjs_agent_core4 = require("@dudousxd/nestjs-agent-core");
1113
1175
  var import_reflect_metadata = require("reflect-metadata");
1114
- var import_common10 = require("@nestjs/common");
1176
+ var import_common11 = require("@nestjs/common");
1115
1177
  var import_core3 = require("@nestjs/core");
1116
1178
 
1117
1179
  // src/server/agent-ui.controller.ts
1118
1180
  var import_node_fs = require("fs");
1119
1181
  var import_node_path = require("path");
1120
1182
  var import_node_url = require("url");
1121
- var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
1122
- var import_common8 = require("@nestjs/common");
1183
+ var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
1184
+ var import_common9 = require("@nestjs/common");
1123
1185
 
1124
1186
  // src/server/console-authorize.guard.ts
1125
1187
  var import_common7 = require("@nestjs/common");
@@ -1508,7 +1570,9 @@ function UseConsoleAuthorize() {
1508
1570
  }
1509
1571
  __name(UseConsoleAuthorize, "UseConsoleAuthorize");
1510
1572
 
1511
- // src/server/agent-ui.controller.ts
1573
+ // src/server/console-switcher.ts
1574
+ var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
1575
+ var import_common8 = require("@nestjs/common");
1512
1576
  function _ts_decorate4(decorators, target, key, desc) {
1513
1577
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1514
1578
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -1535,7 +1599,186 @@ function _ts_param4(paramIndex, decorator) {
1535
1599
  };
1536
1600
  }
1537
1601
  __name(_ts_param4, "_ts_param");
1602
+ var AVIARY_CONSOLES_SLOT = /* @__PURE__ */ Symbol.for("@dudousxd/aviary:consoles");
1603
+ var ID = /^[a-z][a-z0-9-]*$/;
1604
+ var ICONS = /* @__PURE__ */ new Set([
1605
+ "workflow",
1606
+ "telescope",
1607
+ "media",
1608
+ "payments",
1609
+ "agent",
1610
+ "identity",
1611
+ "generic"
1612
+ ]);
1613
+ var CONSOLE_PROBE_TIMEOUT_MS = 300;
1614
+ function isSameOriginPath(path) {
1615
+ return typeof path === "string" && path.startsWith("/") && !path.startsWith("//");
1616
+ }
1617
+ __name(isSameOriginPath, "isSameOriginPath");
1618
+ function readAviaryConsoles() {
1619
+ const value = globalThis[AVIARY_CONSOLES_SLOT];
1620
+ if (value?.version !== 1 || !Array.isArray(value.entries)) return void 0;
1621
+ return value;
1622
+ }
1623
+ __name(readAviaryConsoles, "readAviaryConsoles");
1624
+ function registerAviaryConsole(entry, logger4) {
1625
+ if (!ID.test(entry.id)) throw new Error(`console id ${JSON.stringify(entry.id)} is invalid`);
1626
+ if (!isSameOriginPath(entry.path)) {
1627
+ throw new Error(`console path ${JSON.stringify(entry.path)} must start with a single "/"`);
1628
+ }
1629
+ const holder = globalThis;
1630
+ if (holder[AVIARY_CONSOLES_SLOT] === void 0) {
1631
+ const fresh = {
1632
+ version: 1,
1633
+ entries: []
1634
+ };
1635
+ holder[AVIARY_CONSOLES_SLOT] = fresh;
1636
+ }
1637
+ const registry = readAviaryConsoles();
1638
+ if (registry === void 0) return void 0;
1639
+ if (registry.entries.some((existing) => existing.id === entry.id)) {
1640
+ logger4?.warn(`console id "${entry.id}" is already registered`);
1641
+ return void 0;
1642
+ }
1643
+ registry.entries.push(entry);
1644
+ return () => {
1645
+ const index = registry.entries.indexOf(entry);
1646
+ if (index !== -1) registry.entries.splice(index, 1);
1647
+ };
1648
+ }
1649
+ __name(registerAviaryConsole, "registerAviaryConsole");
1650
+ function consoleSwitcherConfig(selfId, endpoint) {
1651
+ const registry = readAviaryConsoles();
1652
+ if (!registry?.entries.some((entry) => entry.id === selfId)) return void 0;
1653
+ const others = registry.entries.filter((entry) => entry.id !== selfId).length;
1654
+ return others > 0 ? {
1655
+ endpoint,
1656
+ others
1657
+ } : void 0;
1658
+ }
1659
+ __name(consoleSwitcherConfig, "consoleSwitcherConfig");
1660
+ async function allows(entry, context, ms) {
1661
+ let timer;
1662
+ const timeout = new Promise((resolve2) => {
1663
+ timer = setTimeout(() => resolve2(false), ms);
1664
+ });
1665
+ try {
1666
+ return await Promise.race([
1667
+ Promise.resolve().then(() => entry.authorize(context)).then((decision) => decision?.allowed === true, () => false),
1668
+ timeout
1669
+ ]);
1670
+ } finally {
1671
+ clearTimeout(timer);
1672
+ }
1673
+ }
1674
+ __name(allows, "allows");
1675
+ async function listVisibleConsoles(registry, selfId, context, timeoutMs = CONSOLE_PROBE_TIMEOUT_MS) {
1676
+ const others = (registry?.entries ?? []).filter((entry) => entry.id !== selfId && isSameOriginPath(entry.path)).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
1677
+ const verdicts = await Promise.all(others.map((entry) => allows(entry, context, timeoutMs)));
1678
+ return {
1679
+ version: 1,
1680
+ current: selfId,
1681
+ consoles: others.filter((_, index) => verdicts[index]).map((entry) => ({
1682
+ id: entry.id,
1683
+ title: entry.title,
1684
+ icon: ICONS.has(entry.icon) ? entry.icon : "generic",
1685
+ href: entry.path
1686
+ }))
1687
+ };
1688
+ }
1689
+ __name(listVisibleConsoles, "listVisibleConsoles");
1690
+ var AGENT_CONSOLE_ID = "agent";
1691
+ var logger2 = new import_common8.Logger("AgentDashboardModule");
1692
+ var AgentConsoleRegistration = class {
1693
+ static {
1694
+ __name(this, "AgentConsoleRegistration");
1695
+ }
1696
+ basePath;
1697
+ access;
1698
+ #unregister;
1699
+ constructor(basePath, access) {
1700
+ this.basePath = basePath;
1701
+ this.access = access;
1702
+ }
1703
+ onModuleInit() {
1704
+ this.#unregister = registerAviaryConsole({
1705
+ id: AGENT_CONSOLE_ID,
1706
+ title: "Agents",
1707
+ icon: "agent",
1708
+ order: 30,
1709
+ path: this.basePath === "" ? "/" : this.basePath,
1710
+ authorize: /* @__PURE__ */ __name((context) => this.access.check(context), "authorize")
1711
+ }, logger2);
1712
+ }
1713
+ onModuleDestroy() {
1714
+ this.#unregister?.();
1715
+ this.#unregister = void 0;
1716
+ }
1717
+ };
1718
+ AgentConsoleRegistration = _ts_decorate4([
1719
+ (0, import_common8.Injectable)(),
1720
+ _ts_param4(0, (0, import_common8.Inject)(DASHBOARD_BASE_PATH)),
1721
+ _ts_metadata4("design:type", Function),
1722
+ _ts_metadata4("design:paramtypes", [
1723
+ String,
1724
+ typeof DashboardConsoleAccess === "undefined" ? Object : DashboardConsoleAccess
1725
+ ])
1726
+ ], AgentConsoleRegistration);
1727
+ var CurrentExecutionContext = (0, import_common8.createParamDecorator)((_data, context) => ({
1728
+ context
1729
+ }));
1730
+ var AgentConsolesController = class {
1731
+ static {
1732
+ __name(this, "AgentConsolesController");
1733
+ }
1734
+ consoles(current) {
1735
+ return listVisibleConsoles(readAviaryConsoles(), AGENT_CONSOLE_ID, current.context);
1736
+ }
1737
+ };
1738
+ _ts_decorate4([
1739
+ (0, import_common8.Get)("consoles"),
1740
+ (0, import_common8.Header)("Cache-Control", "private, no-store"),
1741
+ _ts_param4(0, CurrentExecutionContext()),
1742
+ _ts_metadata4("design:type", Function),
1743
+ _ts_metadata4("design:paramtypes", [
1744
+ typeof CurrentContext === "undefined" ? Object : CurrentContext
1745
+ ]),
1746
+ _ts_metadata4("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1747
+ ], AgentConsolesController.prototype, "consoles", null);
1748
+ AgentConsolesController = _ts_decorate4([
1749
+ (0, import_nestjs_agent_core2.CanAnyone)(),
1750
+ (0, import_common8.Controller)()
1751
+ ], AgentConsolesController);
1752
+
1753
+ // src/server/agent-ui.controller.ts
1754
+ function _ts_decorate5(decorators, target, key, desc) {
1755
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1756
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1757
+ r = Reflect.decorate(decorators, target, key, desc);
1758
+ } else {
1759
+ for (var i = decorators.length - 1; i >= 0; i--) {
1760
+ if (d = decorators[i]) {
1761
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1762
+ }
1763
+ }
1764
+ }
1765
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1766
+ }
1767
+ __name(_ts_decorate5, "_ts_decorate");
1768
+ function _ts_metadata5(metadataKey, metadataValue) {
1769
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1770
+ return Reflect.metadata(metadataKey, metadataValue);
1771
+ }
1772
+ }
1773
+ __name(_ts_metadata5, "_ts_metadata");
1774
+ function _ts_param5(paramIndex, decorator) {
1775
+ return function(target, key) {
1776
+ decorator(target, key, paramIndex);
1777
+ };
1778
+ }
1779
+ __name(_ts_param5, "_ts_param");
1538
1780
  var BUILD_BASE = "/ai-gateway";
1781
+ var AGENT_DASHBOARD_CONFIG_ID = "agent-dashboard-config";
1539
1782
  function spaDir() {
1540
1783
  return (0, import_node_url.fileURLToPath)(new URL("../spa", __importMetaUrl));
1541
1784
  }
@@ -1570,67 +1813,81 @@ var AgentUiController = class {
1570
1813
  }
1571
1814
  const indexPath = (0, import_node_path.join)(this.dir, "index.html");
1572
1815
  if (!(0, import_node_fs.existsSync)(indexPath)) {
1573
- throw new import_common8.NotFoundException("Dashboard is not built. Run the package build.");
1816
+ throw new import_common9.NotFoundException("Dashboard is not built. Run the package build.");
1574
1817
  }
1575
1818
  const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
1576
- const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>`;
1819
+ const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>${this.configBlock()}`;
1577
1820
  return html.includes("</head>") ? html.replace("</head>", `${inject}</head>`) : inject + html;
1578
1821
  }
1822
+ /**
1823
+ * The page's JSON config block (`agent-dashboard-config`, CSP-safe: data, not script). It carries
1824
+ * `switcher` only when another Aviary console is registered.
1825
+ */
1826
+ configBlock() {
1827
+ const switcher = consoleSwitcherConfig(AGENT_CONSOLE_ID, `${this.apiBasePath}/consoles`);
1828
+ const json = JSON.stringify({
1829
+ apiBase: this.apiBasePath,
1830
+ ...switcher !== void 0 ? {
1831
+ switcher
1832
+ } : {}
1833
+ }).replaceAll("<", "\\u003c");
1834
+ return `<script type="application/json" id="${AGENT_DASHBOARD_CONFIG_ID}">${json}</script>`;
1835
+ }
1579
1836
  asset(file) {
1580
1837
  const safe = (0, import_node_path.basename)(file);
1581
- if (safe !== file) throw new import_common8.NotFoundException();
1838
+ if (safe !== file) throw new import_common9.NotFoundException();
1582
1839
  const root = (0, import_node_path.resolve)(this.dir, "assets");
1583
1840
  const assetPath = (0, import_node_path.resolve)(root, safe);
1584
1841
  if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
1585
- throw new import_common8.NotFoundException();
1842
+ throw new import_common9.NotFoundException();
1586
1843
  }
1587
1844
  const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
1588
- return new import_common8.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
1845
+ return new import_common9.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
1589
1846
  type
1590
1847
  });
1591
1848
  }
1592
1849
  };
1593
- _ts_decorate4([
1594
- (0, import_common8.Get)(),
1850
+ _ts_decorate5([
1851
+ (0, import_common9.Get)(),
1595
1852
  ConsolePage(),
1596
- (0, import_common8.Header)("Content-Type", "text/html; charset=utf-8"),
1597
- (0, import_common8.Header)("Cache-Control", "no-store, must-revalidate"),
1598
- _ts_param4(0, (0, import_common8.Req)()),
1599
- _ts_param4(1, (0, import_common8.Res)({
1853
+ (0, import_common9.Header)("Content-Type", "text/html; charset=utf-8"),
1854
+ (0, import_common9.Header)("Cache-Control", "no-store, must-revalidate"),
1855
+ _ts_param5(0, (0, import_common9.Req)()),
1856
+ _ts_param5(1, (0, import_common9.Res)({
1600
1857
  passthrough: true
1601
1858
  })),
1602
- _ts_metadata4("design:type", Function),
1603
- _ts_metadata4("design:paramtypes", [
1859
+ _ts_metadata5("design:type", Function),
1860
+ _ts_metadata5("design:paramtypes", [
1604
1861
  typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
1605
1862
  typeof UiPageResponse === "undefined" ? Object : UiPageResponse
1606
1863
  ]),
1607
- _ts_metadata4("design:returntype", String)
1864
+ _ts_metadata5("design:returntype", String)
1608
1865
  ], AgentUiController.prototype, "index", null);
1609
- _ts_decorate4([
1610
- (0, import_common8.Get)("assets/:file"),
1611
- (0, import_common8.Header)("Cache-Control", "public, max-age=31536000, immutable"),
1612
- _ts_param4(0, (0, import_common8.Param)("file")),
1613
- _ts_metadata4("design:type", Function),
1614
- _ts_metadata4("design:paramtypes", [
1866
+ _ts_decorate5([
1867
+ (0, import_common9.Get)("assets/:file"),
1868
+ (0, import_common9.Header)("Cache-Control", "public, max-age=31536000, immutable"),
1869
+ _ts_param5(0, (0, import_common9.Param)("file")),
1870
+ _ts_metadata5("design:type", Function),
1871
+ _ts_metadata5("design:paramtypes", [
1615
1872
  String
1616
1873
  ]),
1617
- _ts_metadata4("design:returntype", typeof import_common8.StreamableFile === "undefined" ? Object : import_common8.StreamableFile)
1874
+ _ts_metadata5("design:returntype", typeof import_common9.StreamableFile === "undefined" ? Object : import_common9.StreamableFile)
1618
1875
  ], AgentUiController.prototype, "asset", null);
1619
- AgentUiController = _ts_decorate4([
1620
- (0, import_nestjs_agent_core2.CanAnyone)(),
1621
- (0, import_common8.Controller)(),
1622
- _ts_param4(0, (0, import_common8.Inject)(DASHBOARD_BASE_PATH)),
1623
- _ts_param4(1, (0, import_common8.Inject)(DASHBOARD_API_PATH)),
1624
- _ts_metadata4("design:type", Function),
1625
- _ts_metadata4("design:paramtypes", [
1876
+ AgentUiController = _ts_decorate5([
1877
+ (0, import_nestjs_agent_core3.CanAnyone)(),
1878
+ (0, import_common9.Controller)(),
1879
+ _ts_param5(0, (0, import_common9.Inject)(DASHBOARD_BASE_PATH)),
1880
+ _ts_param5(1, (0, import_common9.Inject)(DASHBOARD_API_PATH)),
1881
+ _ts_metadata5("design:type", Function),
1882
+ _ts_metadata5("design:paramtypes", [
1626
1883
  String,
1627
1884
  String
1628
1885
  ])
1629
1886
  ], AgentUiController);
1630
1887
 
1631
1888
  // src/server/dev-tools.ts
1632
- var import_common9 = require("@nestjs/common");
1633
- function _ts_decorate5(decorators, target, key, desc) {
1889
+ var import_common10 = require("@nestjs/common");
1890
+ function _ts_decorate6(decorators, target, key, desc) {
1634
1891
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1635
1892
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1636
1893
  r = Reflect.decorate(decorators, target, key, desc);
@@ -1643,19 +1900,19 @@ function _ts_decorate5(decorators, target, key, desc) {
1643
1900
  }
1644
1901
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1645
1902
  }
1646
- __name(_ts_decorate5, "_ts_decorate");
1647
- function _ts_metadata5(metadataKey, metadataValue) {
1903
+ __name(_ts_decorate6, "_ts_decorate");
1904
+ function _ts_metadata6(metadataKey, metadataValue) {
1648
1905
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1649
1906
  return Reflect.metadata(metadataKey, metadataValue);
1650
1907
  }
1651
1908
  }
1652
- __name(_ts_metadata5, "_ts_metadata");
1653
- function _ts_param5(paramIndex, decorator) {
1909
+ __name(_ts_metadata6, "_ts_metadata");
1910
+ function _ts_param6(paramIndex, decorator) {
1654
1911
  return function(target, key) {
1655
1912
  decorator(target, key, paramIndex);
1656
1913
  };
1657
1914
  }
1658
- __name(_ts_param5, "_ts_param");
1915
+ __name(_ts_param6, "_ts_param");
1659
1916
  var DEV_TOOLS_SLOT = /* @__PURE__ */ Symbol.for("@dudousxd/aviary:dev-tools");
1660
1917
  function devToolsSlot() {
1661
1918
  const holder = globalThis;
@@ -1821,7 +2078,7 @@ function agentDevTools(dashboard) {
1821
2078
  try {
1822
2079
  detail = await dashboard.runDetail(String(input.id));
1823
2080
  } catch (error) {
1824
- if (error instanceof import_common9.NotFoundException) throw new Error(`run ${String(input.id)} not found`);
2081
+ if (error instanceof import_common10.NotFoundException) throw new Error(`run ${String(input.id)} not found`);
1825
2082
  throw error;
1826
2083
  }
1827
2084
  if (input.includeMessages !== true) return detail;
@@ -1989,7 +2246,7 @@ function agentDevTools(dashboard) {
1989
2246
  ];
1990
2247
  }
1991
2248
  __name(agentDevTools, "agentDevTools");
1992
- var logger2 = new import_common9.Logger("AgentDashboardModule");
2249
+ var logger3 = new import_common10.Logger("AgentDashboardModule");
1993
2250
  var AgentDevToolsRegistration = class {
1994
2251
  static {
1995
2252
  __name(this, "AgentDevToolsRegistration");
@@ -2015,7 +2272,7 @@ var AgentDevToolsRegistration = class {
2015
2272
  tools: agentDevTools(this.dashboard)
2016
2273
  });
2017
2274
  } catch (error) {
2018
- logger2.warn(`agent dev tools not registered: ${error instanceof Error ? error.message : String(error)}`);
2275
+ logger3.warn(`agent dev tools not registered: ${error instanceof Error ? error.message : String(error)}`);
2019
2276
  }
2020
2277
  }
2021
2278
  onModuleDestroy() {
@@ -2023,11 +2280,11 @@ var AgentDevToolsRegistration = class {
2023
2280
  this.#unregister = void 0;
2024
2281
  }
2025
2282
  };
2026
- AgentDevToolsRegistration = _ts_decorate5([
2027
- (0, import_common9.Injectable)(),
2028
- _ts_param5(0, (0, import_common9.Inject)(DASHBOARD_DEV_TOOLS)),
2029
- _ts_metadata5("design:type", Function),
2030
- _ts_metadata5("design:paramtypes", [
2283
+ AgentDevToolsRegistration = _ts_decorate6([
2284
+ (0, import_common10.Injectable)(),
2285
+ _ts_param6(0, (0, import_common10.Inject)(DASHBOARD_DEV_TOOLS)),
2286
+ _ts_metadata6("design:type", Function),
2287
+ _ts_metadata6("design:paramtypes", [
2031
2288
  Boolean,
2032
2289
  typeof DashboardService === "undefined" ? Object : DashboardService,
2033
2290
  typeof DashboardConsoleAccess === "undefined" ? Object : DashboardConsoleAccess
@@ -2035,7 +2292,7 @@ AgentDevToolsRegistration = _ts_decorate5([
2035
2292
  ], AgentDevToolsRegistration);
2036
2293
 
2037
2294
  // src/server/agent-dashboard.module.ts
2038
- function _ts_decorate6(decorators, target, key, desc) {
2295
+ function _ts_decorate7(decorators, target, key, desc) {
2039
2296
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2040
2297
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
2041
2298
  r = Reflect.decorate(decorators, target, key, desc);
@@ -2048,7 +2305,7 @@ function _ts_decorate6(decorators, target, key, desc) {
2048
2305
  }
2049
2306
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2050
2307
  }
2051
- __name(_ts_decorate6, "_ts_decorate");
2308
+ __name(_ts_decorate7, "_ts_decorate");
2052
2309
  function normalize(path) {
2053
2310
  return normalizeDashboardPath(path);
2054
2311
  }
@@ -2056,8 +2313,8 @@ __name(normalize, "normalize");
2056
2313
  function consoleDecorators(decorators) {
2057
2314
  return [
2058
2315
  ...decorators ?? [],
2059
- (0, import_common10.UseGuards)(ConsoleAuthorizeGuard),
2060
- (0, import_common10.UseFilters)(ConsoleAuthorizeFilter)
2316
+ (0, import_common11.UseGuards)(ConsoleAuthorizeGuard),
2317
+ (0, import_common11.UseFilters)(ConsoleAuthorizeFilter)
2061
2318
  ];
2062
2319
  }
2063
2320
  __name(consoleDecorators, "consoleDecorators");
@@ -2076,8 +2333,9 @@ var AgentApiModule = class _AgentApiModule {
2076
2333
  imports: [
2077
2334
  ...options.imports ?? []
2078
2335
  ],
2079
- controllers: options.routes === false ? [] : (0, import_nestjs_agent_core3.withControllerDecorators)([
2080
- AgentApiController
2336
+ controllers: options.routes === false ? [] : (0, import_nestjs_agent_core4.withControllerDecorators)([
2337
+ AgentApiController,
2338
+ AgentConsolesController
2081
2339
  ], consoleDecorators(options.decorators)),
2082
2340
  providers: [
2083
2341
  DashboardService,
@@ -2108,8 +2366,8 @@ var AgentApiModule = class _AgentApiModule {
2108
2366
  };
2109
2367
  }
2110
2368
  };
2111
- AgentApiModule = _ts_decorate6([
2112
- (0, import_common10.Module)({})
2369
+ AgentApiModule = _ts_decorate7([
2370
+ (0, import_common11.Module)({})
2113
2371
  ], AgentApiModule);
2114
2372
  var AgentDashboardModule = class _AgentDashboardModule {
2115
2373
  static {
@@ -2156,7 +2414,7 @@ var AgentDashboardModule = class _AgentDashboardModule {
2156
2414
  ])
2157
2415
  ]
2158
2416
  ],
2159
- controllers: options.routes === false ? [] : (0, import_nestjs_agent_core3.withControllerDecorators)([
2417
+ controllers: options.routes === false ? [] : (0, import_nestjs_agent_core4.withControllerDecorators)([
2160
2418
  AgentUiController
2161
2419
  ], consoleDecorators(options.decorators)),
2162
2420
  providers: [
@@ -2167,7 +2425,11 @@ var AgentDashboardModule = class _AgentDashboardModule {
2167
2425
  {
2168
2426
  provide: DASHBOARD_API_PATH,
2169
2427
  useValue: apiBasePath
2170
- }
2428
+ },
2429
+ // The console switcher lists this console only where it serves its own page.
2430
+ ...options.routes === false ? [] : [
2431
+ AgentConsoleRegistration
2432
+ ]
2171
2433
  ],
2172
2434
  // Re-export the API module so its DashboardService reaches importers (e.g. the host's own
2173
2435
  // controllers), and the paths a self-mounted `AgentUiController` subclass injects.
@@ -2179,24 +2441,32 @@ var AgentDashboardModule = class _AgentDashboardModule {
2179
2441
  };
2180
2442
  }
2181
2443
  };
2182
- AgentDashboardModule = _ts_decorate6([
2183
- (0, import_common10.Module)({})
2444
+ AgentDashboardModule = _ts_decorate7([
2445
+ (0, import_common11.Module)({})
2184
2446
  ], AgentDashboardModule);
2185
2447
  // Annotate the CommonJS export names for ESM import in node:
2186
2448
  0 && (module.exports = {
2187
2449
  AGENT_ACTOR_DIRECTORY,
2188
2450
  AGENT_ACTOR_RESOLVER,
2189
2451
  AGENT_APPROVAL_PORT,
2452
+ AGENT_CONSOLE_ID,
2453
+ AGENT_DASHBOARD_CONFIG_ID,
2190
2454
  AGENT_GOVERNANCE_QUERIES,
2455
+ AGENT_OPTIONS,
2191
2456
  AGENT_PRICING_STORE,
2457
+ AVIARY_CONSOLES_SLOT,
2192
2458
  AgentApiController,
2193
2459
  AgentApiModule,
2460
+ AgentConsoleRegistration,
2461
+ AgentConsolesController,
2194
2462
  AgentDashboardModule,
2195
2463
  AgentDevToolsRegistration,
2196
2464
  AgentUiController,
2197
2465
  CONSOLE_AUTHORIZE_MISSING_WARNING,
2198
2466
  CONSOLE_GATE,
2199
2467
  CONSOLE_PAGE_METADATA,
2468
+ CONSOLE_PROBE_TIMEOUT_MS,
2469
+ CONTEXT_ACCESSOR,
2200
2470
  ConsoleAccessDenied,
2201
2471
  ConsoleAuthorizeFilter,
2202
2472
  ConsoleAuthorizeGuard,
@@ -2213,8 +2483,10 @@ AgentDashboardModule = _ts_decorate6([
2213
2483
  agentDevTools,
2214
2484
  anyAuthorize,
2215
2485
  authorizeByToken,
2486
+ listVisibleConsoles,
2216
2487
  normalizeConsoleResult,
2217
2488
  parsePriceInput,
2489
+ registerAviaryConsole,
2218
2490
  resolveConsoleAuthorize
2219
2491
  });
2220
2492
  //# sourceMappingURL=index.cjs.map