@dudousxd/nestjs-agent-dashboard 0.19.1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -82,6 +82,7 @@ var AGENT_ACTOR_RESOLVER = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:ac
82
82
  var DASHBOARD_BASE_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
83
83
  var DASHBOARD_API_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
84
84
  var DASHBOARD_APPROVAL_ACTOR_REF = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
85
+ var DASHBOARD_CONSOLE_OPTIONS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:console-options");
85
86
 
86
87
  // src/server/dashboard.service.ts
87
88
  function _ts_decorate(decorators, target, key, desc) {
@@ -1043,7 +1044,7 @@ __name(agentDashboardMountPaths, "agentDashboardMountPaths");
1043
1044
  // src/server/agent-dashboard.module.ts
1044
1045
  import { withControllerDecorators } from "@dudousxd/nestjs-agent-core";
1045
1046
  import "reflect-metadata";
1046
- import { Module } from "@nestjs/common";
1047
+ import { Module, UseFilters as UseFilters2, UseGuards as UseGuards2 } from "@nestjs/common";
1047
1048
  import { RouterModule } from "@nestjs/core";
1048
1049
 
1049
1050
  // src/server/agent-ui.controller.ts
@@ -1051,7 +1052,187 @@ import { existsSync, readFileSync } from "fs";
1051
1052
  import { basename, extname, join, resolve, sep } from "path";
1052
1053
  import { fileURLToPath } from "url";
1053
1054
  import { CanAnyone as CanAnyone2 } from "@dudousxd/nestjs-agent-core";
1054
- import { Controller as Controller2, Get as Get2, Header, Inject as Inject3, NotFoundException as NotFoundException2, Param as Param2, Req as Req2, Res, StreamableFile } from "@nestjs/common";
1055
+ import { Controller as Controller2, Get as Get2, Header, Inject as Inject4, NotFoundException as NotFoundException2, Param as Param2, Req as Req2, Res, StreamableFile } from "@nestjs/common";
1056
+
1057
+ // src/server/console-authorize.guard.ts
1058
+ import { Catch, HttpException, Inject as Inject3, Injectable as Injectable2, SetMetadata, UseFilters, UseGuards, applyDecorators } from "@nestjs/common";
1059
+ import { HttpAdapterHost, ModuleRef } from "@nestjs/core";
1060
+
1061
+ // src/server/console-authorize.ts
1062
+ import { createHash, timingSafeEqual } from "crypto";
1063
+ import { Logger } from "@nestjs/common";
1064
+ var CONSOLE_GATE = /* @__PURE__ */ Symbol.for("@dudousxd/aviary:console-gate");
1065
+ var PACKAGE = "@dudousxd/nestjs-agent-dashboard";
1066
+ var MODULE = "AgentDashboardModule";
1067
+ var logger = new Logger(MODULE);
1068
+ var CONSOLE_AUTHORIZE_MISSING_WARNING = `[${PACKAGE}] console has no \`authorize\` configured: it is open outside production and denies every request in production. Set \`authorize\` in ${MODULE}.forRoot().`;
1069
+ var allow = /* @__PURE__ */ __name(() => ({
1070
+ allowed: true
1071
+ }), "allow");
1072
+ var forbidden = /* @__PURE__ */ __name(() => ({
1073
+ allowed: false,
1074
+ reason: "forbidden"
1075
+ }), "forbidden");
1076
+ var unauthenticated = /* @__PURE__ */ __name(() => ({
1077
+ allowed: false,
1078
+ reason: "unauthenticated"
1079
+ }), "unauthenticated");
1080
+ function isProduction() {
1081
+ return (process.env.NODE_ENV ?? "").trim().toLowerCase() === "production";
1082
+ }
1083
+ __name(isProduction, "isProduction");
1084
+ function normalizeConsoleResult(result) {
1085
+ if (result === true) return allow();
1086
+ if (result === null || typeof result !== "object") return forbidden();
1087
+ const value = result;
1088
+ if (typeof value.redirectTo === "string" && value.redirectTo !== "" && value.allowed !== true) {
1089
+ return {
1090
+ allowed: false,
1091
+ reason: "unauthenticated",
1092
+ redirectTo: value.redirectTo
1093
+ };
1094
+ }
1095
+ if (value.allowed === true) return allow();
1096
+ return value.reason === "unauthenticated" ? unauthenticated() : forbidden();
1097
+ }
1098
+ __name(normalizeConsoleResult, "normalizeConsoleResult");
1099
+ function isAuthorizerClass(value) {
1100
+ if (typeof value !== "function") return false;
1101
+ if (typeof value.prototype?.authorize === "function") {
1102
+ return true;
1103
+ }
1104
+ return /^class[\s{]/.test(Function.prototype.toString.call(value));
1105
+ }
1106
+ __name(isAuthorizerClass, "isAuthorizerClass");
1107
+ function isPolicyCheck(value) {
1108
+ return typeof value === "object" && value !== null && typeof value.policy === "function" && typeof value.ability === "string";
1109
+ }
1110
+ __name(isPolicyCheck, "isPolicyCheck");
1111
+ function lazyModuleClass(value) {
1112
+ if (typeof value !== "object" || value === null) return void 0;
1113
+ const candidate = value.default;
1114
+ return isAuthorizerClass(candidate) ? candidate : void 0;
1115
+ }
1116
+ __name(lazyModuleClass, "lazyModuleClass");
1117
+ function tryGet(moduleRef, token) {
1118
+ try {
1119
+ return moduleRef.get(token, {
1120
+ strict: false
1121
+ }) ?? void 0;
1122
+ } catch {
1123
+ return void 0;
1124
+ }
1125
+ }
1126
+ __name(tryGet, "tryGet");
1127
+ function classInstances(moduleRef) {
1128
+ const instances = /* @__PURE__ */ new Map();
1129
+ return (Class) => {
1130
+ let instance = instances.get(Class);
1131
+ if (instance === void 0) {
1132
+ const registered = tryGet(moduleRef, Class);
1133
+ instance = registered !== void 0 ? Promise.resolve(registered) : moduleRef.create(Class);
1134
+ instance.catch(() => instances.delete(Class));
1135
+ instances.set(Class, instance);
1136
+ }
1137
+ return instance;
1138
+ };
1139
+ }
1140
+ __name(classInstances, "classInstances");
1141
+ function hasUser(user) {
1142
+ return user !== null && user !== void 0 && user !== false;
1143
+ }
1144
+ __name(hasUser, "hasUser");
1145
+ async function policyDecider(check, moduleRef) {
1146
+ let mod;
1147
+ try {
1148
+ mod = await import("@nestjs/authorization");
1149
+ } catch {
1150
+ throw new Error(`${MODULE}: \`authorize: { policy, ability }\` needs @nestjs/authorization installed and AuthorizationModule imported; or pass a function, a class, or a gate name.`);
1151
+ }
1152
+ const service = tryGet(moduleRef, mod.AuthorizationService);
1153
+ if (service === void 0) {
1154
+ throw new Error(`${MODULE}: \`authorize: { policy, ability }\` needs AuthorizationModule.forRoot() from @nestjs/authorization imported in the app.`);
1155
+ }
1156
+ const options = tryGet(moduleRef, mod.AUTHORIZATION_MODULE_OPTIONS);
1157
+ const getUser = options?.getUser ?? mod.defaultGetUser;
1158
+ return async (context) => {
1159
+ const user = await getUser(context);
1160
+ const signedIn = hasUser(user);
1161
+ if (await service.can(check.policy, check.ability, signedIn ? user : null)) return allow();
1162
+ return signedIn ? forbidden() : unauthenticated();
1163
+ };
1164
+ }
1165
+ __name(policyDecider, "policyDecider");
1166
+ async function resolveConsoleAuthorize(authorize, moduleRef, options = {}) {
1167
+ const log = options.logger ?? logger;
1168
+ if (authorize === void 0) {
1169
+ if (options.warnIfMissing !== false) log.warn(CONSOLE_AUTHORIZE_MISSING_WARNING);
1170
+ const production = isProduction();
1171
+ return async () => production ? forbidden() : allow();
1172
+ }
1173
+ const instanceOf = classInstances(moduleRef);
1174
+ let decide;
1175
+ if (typeof authorize === "string") {
1176
+ const name = authorize;
1177
+ const gate = tryGet(moduleRef, CONSOLE_GATE);
1178
+ if (gate === void 0) {
1179
+ throw new Error(`${MODULE}: \`authorize: '${name}'\` needs @dudousxd/nestjs-authz's AuthzModule (it resolves gate names); or pass a function, a class, or { policy, ability }.`);
1180
+ }
1181
+ decide = /* @__PURE__ */ __name((context) => gate.allows(name, context), "decide");
1182
+ } else if (isPolicyCheck(authorize)) {
1183
+ decide = await policyDecider(authorize, moduleRef);
1184
+ } else if (isAuthorizerClass(authorize)) {
1185
+ const Class = authorize;
1186
+ decide = /* @__PURE__ */ __name(async (context) => (await instanceOf(Class)).authorize(context), "decide");
1187
+ } else if (typeof authorize === "function") {
1188
+ const fn = authorize;
1189
+ let lazyClass;
1190
+ decide = /* @__PURE__ */ __name(async (context) => {
1191
+ if (lazyClass !== void 0) return (await instanceOf(lazyClass)).authorize(context);
1192
+ const result = await fn(context);
1193
+ const Class = lazyModuleClass(result);
1194
+ if (Class === void 0) return result;
1195
+ lazyClass = Class;
1196
+ return (await instanceOf(Class)).authorize(context);
1197
+ }, "decide");
1198
+ } else {
1199
+ throw new Error(`${MODULE}: \`authorize\` must be a function, a class with authorize(), a lazy import, { policy, ability } or a gate name.`);
1200
+ }
1201
+ return async (context) => {
1202
+ try {
1203
+ return normalizeConsoleResult(await decide(context));
1204
+ } catch (error) {
1205
+ log.warn(`console \`authorize\` threw, denying the request: ${error instanceof Error ? error.message : String(error)}`);
1206
+ return forbidden();
1207
+ }
1208
+ };
1209
+ }
1210
+ __name(resolveConsoleAuthorize, "resolveConsoleAuthorize");
1211
+ function sha256(value) {
1212
+ return createHash("sha256").update(value).digest();
1213
+ }
1214
+ __name(sha256, "sha256");
1215
+ function authorizeByToken(options) {
1216
+ const token = options.token;
1217
+ if (typeof token !== "string" || token === "") {
1218
+ throw new Error("authorizeByToken: `token` is empty; set it (e.g. from an env var).");
1219
+ }
1220
+ const expected = sha256(token);
1221
+ return (context) => {
1222
+ const req = context.switchToHttp().getRequest();
1223
+ const header = req?.headers?.authorization;
1224
+ const value = Array.isArray(header) ? header[0] : header;
1225
+ const match = typeof value === "string" ? /^Bearer\s+(.+)$/i.exec(value.trim()) : null;
1226
+ if (match?.[1] !== void 0 && timingSafeEqual(sha256(match[1]), expected)) return true;
1227
+ return {
1228
+ allowed: false,
1229
+ reason: "unauthenticated"
1230
+ };
1231
+ };
1232
+ }
1233
+ __name(authorizeByToken, "authorizeByToken");
1234
+
1235
+ // src/server/console-authorize.guard.ts
1055
1236
  function _ts_decorate3(decorators, target, key, desc) {
1056
1237
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1057
1238
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -1078,6 +1259,161 @@ function _ts_param3(paramIndex, decorator) {
1078
1259
  };
1079
1260
  }
1080
1261
  __name(_ts_param3, "_ts_param");
1262
+ var DashboardConsoleAccess = class {
1263
+ static {
1264
+ __name(this, "DashboardConsoleAccess");
1265
+ }
1266
+ options;
1267
+ moduleRef;
1268
+ #decide;
1269
+ constructor(options, moduleRef) {
1270
+ this.options = options;
1271
+ this.moduleRef = moduleRef;
1272
+ }
1273
+ #resolving;
1274
+ /** Resolves `authorize` at boot: a configuration mistake fails the boot, and the warning logs once. */
1275
+ async onModuleInit() {
1276
+ this.#resolving ??= resolveConsoleAuthorize(this.options.authorize, this.moduleRef);
1277
+ this.#decide = await this.#resolving;
1278
+ }
1279
+ /** The decision for one request. */
1280
+ async check(context) {
1281
+ if (this.#decide === void 0) await this.onModuleInit();
1282
+ return this.#decide(context);
1283
+ }
1284
+ };
1285
+ DashboardConsoleAccess = _ts_decorate3([
1286
+ Injectable2(),
1287
+ _ts_param3(0, Inject3(DASHBOARD_CONSOLE_OPTIONS)),
1288
+ _ts_metadata3("design:type", Function),
1289
+ _ts_metadata3("design:paramtypes", [
1290
+ typeof DashboardConsoleOptions === "undefined" ? Object : DashboardConsoleOptions,
1291
+ typeof ModuleRef === "undefined" ? Object : ModuleRef
1292
+ ])
1293
+ ], DashboardConsoleAccess);
1294
+ var CONSOLE_PAGE_METADATA = "@dudousxd/nestjs-agent-dashboard:console-page";
1295
+ var ConsolePage = /* @__PURE__ */ __name(() => SetMetadata(CONSOLE_PAGE_METADATA, true), "ConsolePage");
1296
+ var ConsoleAccessDenied = class extends HttpException {
1297
+ static {
1298
+ __name(this, "ConsoleAccessDenied");
1299
+ }
1300
+ decision;
1301
+ page;
1302
+ constructor(decision, page) {
1303
+ super(decision.reason === "forbidden" ? {
1304
+ error: "forbidden"
1305
+ } : {
1306
+ error: "unauthenticated",
1307
+ ...decision.redirectTo !== void 0 ? {
1308
+ redirectTo: decision.redirectTo
1309
+ } : {}
1310
+ }, decision.reason === "forbidden" ? 403 : 401), this.decision = decision, this.page = page;
1311
+ }
1312
+ };
1313
+ function isPageNavigation(context) {
1314
+ if (context.getType() !== "http") return false;
1315
+ const page = Reflect.getMetadata(CONSOLE_PAGE_METADATA, context.getHandler()) === true || Reflect.getMetadata(CONSOLE_PAGE_METADATA, context.getClass()) === true;
1316
+ if (!page) return false;
1317
+ const req = context.switchToHttp().getRequest();
1318
+ if ((req.method ?? "GET").toUpperCase() !== "GET") return false;
1319
+ const accept = req.headers?.accept;
1320
+ const value = Array.isArray(accept) ? accept.join(",") : accept ?? "";
1321
+ return value.includes("text/html");
1322
+ }
1323
+ __name(isPageNavigation, "isPageNavigation");
1324
+ var ConsoleAuthorizeGuard = class {
1325
+ static {
1326
+ __name(this, "ConsoleAuthorizeGuard");
1327
+ }
1328
+ access;
1329
+ constructor(access) {
1330
+ this.access = access;
1331
+ }
1332
+ async canActivate(context) {
1333
+ const decision = await this.access.check(context);
1334
+ if (decision.allowed) return true;
1335
+ throw new ConsoleAccessDenied(decision, isPageNavigation(context));
1336
+ }
1337
+ };
1338
+ ConsoleAuthorizeGuard = _ts_decorate3([
1339
+ Injectable2(),
1340
+ _ts_metadata3("design:type", Function),
1341
+ _ts_metadata3("design:paramtypes", [
1342
+ typeof DashboardConsoleAccess === "undefined" ? Object : DashboardConsoleAccess
1343
+ ])
1344
+ ], ConsoleAuthorizeGuard);
1345
+ function deniedPage(title, message) {
1346
+ const body = "font-family:system-ui,sans-serif;display:grid;place-items:center;min-height:100vh;margin:0";
1347
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title}</title></head><body style="${body}"><main style="text-align:center"><h1>${title}</h1><p>${message}</p></main></body></html>`;
1348
+ }
1349
+ __name(deniedPage, "deniedPage");
1350
+ var FORBIDDEN_PAGE = deniedPage("Access denied", "You do not have access to this console.");
1351
+ var UNAUTHENTICATED_PAGE = deniedPage("Sign in required", "Sign in to open this console.");
1352
+ var ConsoleAuthorizeFilter = class {
1353
+ static {
1354
+ __name(this, "ConsoleAuthorizeFilter");
1355
+ }
1356
+ adapterHost;
1357
+ constructor(adapterHost) {
1358
+ this.adapterHost = adapterHost;
1359
+ }
1360
+ catch(exception, host) {
1361
+ const adapter = this.adapterHost.httpAdapter;
1362
+ const res = host.switchToHttp().getResponse();
1363
+ const { decision, page } = exception;
1364
+ if (page && decision.reason === "unauthenticated" && decision.redirectTo !== void 0) {
1365
+ adapter.redirect(res, 302, decision.redirectTo);
1366
+ return;
1367
+ }
1368
+ if (page) {
1369
+ const forbidden2 = decision.reason === "forbidden";
1370
+ adapter.setHeader(res, "Content-Type", "text/html; charset=utf-8");
1371
+ adapter.reply(res, forbidden2 ? FORBIDDEN_PAGE : UNAUTHENTICATED_PAGE, forbidden2 ? 403 : 401);
1372
+ return;
1373
+ }
1374
+ adapter.reply(res, exception.getResponse(), exception.getStatus());
1375
+ }
1376
+ };
1377
+ ConsoleAuthorizeFilter = _ts_decorate3([
1378
+ Catch(ConsoleAccessDenied),
1379
+ Injectable2(),
1380
+ _ts_metadata3("design:type", Function),
1381
+ _ts_metadata3("design:paramtypes", [
1382
+ typeof HttpAdapterHost === "undefined" ? Object : HttpAdapterHost
1383
+ ])
1384
+ ], ConsoleAuthorizeFilter);
1385
+ function UseConsoleAuthorize() {
1386
+ return applyDecorators(UseGuards(ConsoleAuthorizeGuard), UseFilters(ConsoleAuthorizeFilter));
1387
+ }
1388
+ __name(UseConsoleAuthorize, "UseConsoleAuthorize");
1389
+
1390
+ // src/server/agent-ui.controller.ts
1391
+ function _ts_decorate4(decorators, target, key, desc) {
1392
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1393
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1394
+ r = Reflect.decorate(decorators, target, key, desc);
1395
+ } else {
1396
+ for (var i = decorators.length - 1; i >= 0; i--) {
1397
+ if (d = decorators[i]) {
1398
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1399
+ }
1400
+ }
1401
+ }
1402
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1403
+ }
1404
+ __name(_ts_decorate4, "_ts_decorate");
1405
+ function _ts_metadata4(metadataKey, metadataValue) {
1406
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1407
+ return Reflect.metadata(metadataKey, metadataValue);
1408
+ }
1409
+ }
1410
+ __name(_ts_metadata4, "_ts_metadata");
1411
+ function _ts_param4(paramIndex, decorator) {
1412
+ return function(target, key) {
1413
+ decorator(target, key, paramIndex);
1414
+ };
1415
+ }
1416
+ __name(_ts_param4, "_ts_param");
1081
1417
  var BUILD_BASE = "/ai-gateway";
1082
1418
  function spaDir() {
1083
1419
  return fileURLToPath(new URL("../spa", import.meta.url));
@@ -1133,45 +1469,46 @@ var AgentUiController = class {
1133
1469
  });
1134
1470
  }
1135
1471
  };
1136
- _ts_decorate3([
1472
+ _ts_decorate4([
1137
1473
  Get2(),
1474
+ ConsolePage(),
1138
1475
  Header("Content-Type", "text/html; charset=utf-8"),
1139
1476
  Header("Cache-Control", "no-store, must-revalidate"),
1140
- _ts_param3(0, Req2()),
1141
- _ts_param3(1, Res({
1477
+ _ts_param4(0, Req2()),
1478
+ _ts_param4(1, Res({
1142
1479
  passthrough: true
1143
1480
  })),
1144
- _ts_metadata3("design:type", Function),
1145
- _ts_metadata3("design:paramtypes", [
1481
+ _ts_metadata4("design:type", Function),
1482
+ _ts_metadata4("design:paramtypes", [
1146
1483
  typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
1147
1484
  typeof UiPageResponse === "undefined" ? Object : UiPageResponse
1148
1485
  ]),
1149
- _ts_metadata3("design:returntype", String)
1486
+ _ts_metadata4("design:returntype", String)
1150
1487
  ], AgentUiController.prototype, "index", null);
1151
- _ts_decorate3([
1488
+ _ts_decorate4([
1152
1489
  Get2("assets/:file"),
1153
1490
  Header("Cache-Control", "public, max-age=31536000, immutable"),
1154
- _ts_param3(0, Param2("file")),
1155
- _ts_metadata3("design:type", Function),
1156
- _ts_metadata3("design:paramtypes", [
1491
+ _ts_param4(0, Param2("file")),
1492
+ _ts_metadata4("design:type", Function),
1493
+ _ts_metadata4("design:paramtypes", [
1157
1494
  String
1158
1495
  ]),
1159
- _ts_metadata3("design:returntype", typeof StreamableFile === "undefined" ? Object : StreamableFile)
1496
+ _ts_metadata4("design:returntype", typeof StreamableFile === "undefined" ? Object : StreamableFile)
1160
1497
  ], AgentUiController.prototype, "asset", null);
1161
- AgentUiController = _ts_decorate3([
1498
+ AgentUiController = _ts_decorate4([
1162
1499
  CanAnyone2(),
1163
1500
  Controller2(),
1164
- _ts_param3(0, Inject3(DASHBOARD_BASE_PATH)),
1165
- _ts_param3(1, Inject3(DASHBOARD_API_PATH)),
1166
- _ts_metadata3("design:type", Function),
1167
- _ts_metadata3("design:paramtypes", [
1501
+ _ts_param4(0, Inject4(DASHBOARD_BASE_PATH)),
1502
+ _ts_param4(1, Inject4(DASHBOARD_API_PATH)),
1503
+ _ts_metadata4("design:type", Function),
1504
+ _ts_metadata4("design:paramtypes", [
1168
1505
  String,
1169
1506
  String
1170
1507
  ])
1171
1508
  ], AgentUiController);
1172
1509
 
1173
1510
  // src/server/agent-dashboard.module.ts
1174
- function _ts_decorate4(decorators, target, key, desc) {
1511
+ function _ts_decorate5(decorators, target, key, desc) {
1175
1512
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1176
1513
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1177
1514
  r = Reflect.decorate(decorators, target, key, desc);
@@ -1184,23 +1521,29 @@ function _ts_decorate4(decorators, target, key, desc) {
1184
1521
  }
1185
1522
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1186
1523
  }
1187
- __name(_ts_decorate4, "_ts_decorate");
1524
+ __name(_ts_decorate5, "_ts_decorate");
1188
1525
  function normalize(path) {
1189
1526
  return normalizeDashboardPath(path);
1190
1527
  }
1191
1528
  __name(normalize, "normalize");
1192
- function assertProtected(options) {
1193
- if (process.env.NODE_ENV !== "production") return;
1194
- if (options.routes === false) return;
1195
- if ((options.decorators ?? []).length > 0) return;
1196
- throw new Error("AgentDashboardModule: the AI-gateway console would be served open in production. Say who reaches it, with `decorators: [UseGuards(AuthenticationGuard), Can(ConsolePolicy, 'view')]`, or mount its routes yourself with `routes: false` and extend `AgentApiController` / `AgentUiController` under your own guards.");
1529
+ function consoleDecorators(decorators) {
1530
+ return [
1531
+ ...decorators ?? [],
1532
+ UseGuards2(ConsoleAuthorizeGuard),
1533
+ UseFilters2(ConsoleAuthorizeFilter)
1534
+ ];
1197
1535
  }
1198
- __name(assertProtected, "assertProtected");
1536
+ __name(consoleDecorators, "consoleDecorators");
1199
1537
  var AgentApiModule = class _AgentApiModule {
1200
1538
  static {
1201
1539
  __name(this, "AgentApiModule");
1202
1540
  }
1203
1541
  static register(options) {
1542
+ const consoleOptions = {
1543
+ ...options.authorize !== void 0 ? {
1544
+ authorize: options.authorize
1545
+ } : {}
1546
+ };
1204
1547
  return {
1205
1548
  module: _AgentApiModule,
1206
1549
  imports: [
@@ -1208,7 +1551,7 @@ var AgentApiModule = class _AgentApiModule {
1208
1551
  ],
1209
1552
  controllers: options.routes === false ? [] : withControllerDecorators([
1210
1553
  AgentApiController
1211
- ], options.decorators),
1554
+ ], consoleDecorators(options.decorators)),
1212
1555
  providers: [
1213
1556
  DashboardService,
1214
1557
  // `useValue` even when `options.approvalActorRef` is `undefined` — AgentApiController
@@ -1216,17 +1559,24 @@ var AgentApiModule = class _AgentApiModule {
1216
1559
  {
1217
1560
  provide: DASHBOARD_APPROVAL_ACTOR_REF,
1218
1561
  useValue: options.approvalActorRef
1219
- }
1562
+ },
1563
+ {
1564
+ provide: DASHBOARD_CONSOLE_OPTIONS,
1565
+ useValue: consoleOptions
1566
+ },
1567
+ DashboardConsoleAccess
1220
1568
  ],
1221
- // What a self-mounted `AgentApiController` subclass injects, too (`routes: false`).
1569
+ // What a self-mounted `AgentApiController` subclass injects, too (`routes: false`), and the
1570
+ // access check `UseConsoleAuthorize()` runs.
1222
1571
  exports: [
1223
1572
  DashboardService,
1224
- DASHBOARD_APPROVAL_ACTOR_REF
1573
+ DASHBOARD_APPROVAL_ACTOR_REF,
1574
+ DashboardConsoleAccess
1225
1575
  ]
1226
1576
  };
1227
1577
  }
1228
1578
  };
1229
- AgentApiModule = _ts_decorate4([
1579
+ AgentApiModule = _ts_decorate5([
1230
1580
  Module({})
1231
1581
  ], AgentApiModule);
1232
1582
  var AgentDashboardModule = class _AgentDashboardModule {
@@ -1234,7 +1584,6 @@ var AgentDashboardModule = class _AgentDashboardModule {
1234
1584
  __name(this, "AgentDashboardModule");
1235
1585
  }
1236
1586
  static forRoot(options = {}) {
1237
- assertProtected(options);
1238
1587
  const basePath = normalize(options.basePath ?? "/ai-gateway");
1239
1588
  const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
1240
1589
  return {
@@ -1254,6 +1603,9 @@ var AgentDashboardModule = class _AgentDashboardModule {
1254
1603
  } : {},
1255
1604
  ...options.approvalActorRef ? {
1256
1605
  approvalActorRef: options.approvalActorRef
1606
+ } : {},
1607
+ ...options.authorize !== void 0 ? {
1608
+ authorize: options.authorize
1257
1609
  } : {}
1258
1610
  }),
1259
1611
  ...options.routes === false ? [] : [
@@ -1271,7 +1623,7 @@ var AgentDashboardModule = class _AgentDashboardModule {
1271
1623
  ],
1272
1624
  controllers: options.routes === false ? [] : withControllerDecorators([
1273
1625
  AgentUiController
1274
- ], options.decorators),
1626
+ ], consoleDecorators(options.decorators)),
1275
1627
  providers: [
1276
1628
  {
1277
1629
  provide: DASHBOARD_BASE_PATH,
@@ -1292,7 +1644,7 @@ var AgentDashboardModule = class _AgentDashboardModule {
1292
1644
  };
1293
1645
  }
1294
1646
  };
1295
- AgentDashboardModule = _ts_decorate4([
1647
+ AgentDashboardModule = _ts_decorate5([
1296
1648
  Module({})
1297
1649
  ], AgentDashboardModule);
1298
1650
  export {
@@ -1305,11 +1657,24 @@ export {
1305
1657
  AgentApiModule,
1306
1658
  AgentDashboardModule,
1307
1659
  AgentUiController,
1660
+ CONSOLE_AUTHORIZE_MISSING_WARNING,
1661
+ CONSOLE_GATE,
1662
+ CONSOLE_PAGE_METADATA,
1663
+ ConsoleAccessDenied,
1664
+ ConsoleAuthorizeFilter,
1665
+ ConsoleAuthorizeGuard,
1666
+ ConsolePage,
1308
1667
  DASHBOARD_API_PATH,
1309
1668
  DASHBOARD_APPROVAL_ACTOR_REF,
1310
1669
  DASHBOARD_BASE_PATH,
1670
+ DASHBOARD_CONSOLE_OPTIONS,
1671
+ DashboardConsoleAccess,
1311
1672
  DashboardService,
1673
+ UseConsoleAuthorize,
1312
1674
  agentDashboardMountPaths,
1313
- parsePriceInput
1675
+ authorizeByToken,
1676
+ normalizeConsoleResult,
1677
+ parsePriceInput,
1678
+ resolveConsoleAuthorize
1314
1679
  };
1315
1680
  //# sourceMappingURL=index.js.map