@dudousxd/nestjs-agent-dashboard 0.17.0 → 0.19.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.
Files changed (36) hide show
  1. package/README.md +28 -132
  2. package/dist/client/agent-client.d.ts +47 -1
  3. package/dist/client/agent-client.d.ts.map +1 -1
  4. package/dist/client/agent-client.js +0 -4
  5. package/dist/client/agent-client.js.map +1 -1
  6. package/dist/server/index.cjs +286 -1373
  7. package/dist/server/index.cjs.map +1 -1
  8. package/dist/server/index.d.cts +37 -287
  9. package/dist/server/index.d.ts +37 -287
  10. package/dist/server/index.js +239 -1323
  11. package/dist/server/index.js.map +1 -1
  12. package/dist/spa/assets/index-B1znMy6W.css +1 -0
  13. package/dist/spa/assets/{index-DKPuTuEx.js → index-DzukxAmy.js} +1 -1
  14. package/dist/spa/assets/index-eW1zMwDF.js +25 -0
  15. package/dist/spa/assets/{preview-BgeSHiwH.js → preview-Ch59R-LE.js} +1 -1
  16. package/dist/spa/index.html +3 -3
  17. package/dist/spa/preview.html +3 -3
  18. package/package.json +6 -20
  19. package/dist/client/console-session.d.ts +0 -63
  20. package/dist/client/console-session.d.ts.map +0 -1
  21. package/dist/client/console-session.js +0 -107
  22. package/dist/client/console-session.js.map +0 -1
  23. package/dist/react/index.d.ts +0 -4
  24. package/dist/react/index.d.ts.map +0 -1
  25. package/dist/react/index.js +0 -14
  26. package/dist/react/index.js.map +0 -1
  27. package/dist/react/open-console-button.d.ts +0 -26
  28. package/dist/react/open-console-button.d.ts.map +0 -1
  29. package/dist/react/open-console-button.js +0 -29
  30. package/dist/react/open-console-button.js.map +0 -1
  31. package/dist/react/use-open-console.d.ts +0 -34
  32. package/dist/react/use-open-console.d.ts.map +0 -1
  33. package/dist/react/use-open-console.js +0 -70
  34. package/dist/react/use-open-console.js.map +0 -1
  35. package/dist/spa/assets/index-B2rAzTPe.js +0 -25
  36. package/dist/spa/assets/index-P6B28Wyx.css +0 -1
@@ -2,401 +2,13 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/server/agent-api.controller.ts
5
- import { Body, Controller, Get, HttpCode, Inject as Inject3, Optional as Optional3, Param, Post, Query, Req, Sse, UseGuards } from "@nestjs/common";
6
-
7
- // src/server/auth/dashboard-auth.guard.ts
8
- import { Inject, Injectable, Optional, UnauthorizedException } from "@nestjs/common";
9
-
10
- // src/server/tokens.ts
11
- var AGENT_GOVERNANCE_QUERIES = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:governance-queries");
12
- var AGENT_ACTOR_DIRECTORY = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:actor-directory");
13
- var AGENT_PRICING_STORE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:pricing-store");
14
- var AGENT_APPROVAL_PORT = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:approval-port");
15
- var AGENT_ACTOR_RESOLVER = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
16
- var DASHBOARD_BASE_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
17
- var DASHBOARD_API_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
18
- var DASHBOARD_APPROVAL_ACTOR_REF = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
19
- var DASHBOARD_AUTH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:dashboard-auth");
20
-
21
- // src/server/auth/cookie-header.ts
22
- function parseCookieHeader(header) {
23
- const cookies = {};
24
- if (typeof header !== "string" || header === "") return cookies;
25
- for (const segment of header.split(";")) {
26
- const eq = segment.indexOf("=");
27
- if (eq <= 0) continue;
28
- const name = segment.slice(0, eq).trim();
29
- if (name === "") continue;
30
- let rawValue = segment.slice(eq + 1).trim();
31
- if (rawValue.length >= 2 && rawValue.startsWith('"') && rawValue.endsWith('"')) {
32
- rawValue = rawValue.slice(1, -1);
33
- }
34
- if (name in cookies) continue;
35
- try {
36
- cookies[name] = decodeURIComponent(rawValue);
37
- } catch {
38
- cookies[name] = rawValue;
39
- }
40
- }
41
- return cookies;
42
- }
43
- __name(parseCookieHeader, "parseCookieHeader");
44
- function serializeSetCookie(name, value, options) {
45
- const parts = [
46
- `${name}=${options.clear ? "" : encodeURIComponent(value)}`
47
- ];
48
- parts.push(`Path=${options.path}`);
49
- parts.push("HttpOnly");
50
- parts.push("SameSite=Lax");
51
- if (options.secure) parts.push("Secure");
52
- if (options.clear) {
53
- parts.push("Max-Age=0");
54
- parts.push("Expires=Thu, 01 Jan 1970 00:00:00 GMT");
55
- } else {
56
- parts.push(`Max-Age=${options.maxAgeSeconds}`);
57
- }
58
- return parts.join("; ");
59
- }
60
- __name(serializeSetCookie, "serializeSetCookie");
61
-
62
- // src/server/auth/http-request.ts
63
- function isRecord(value) {
64
- return typeof value === "object" && value !== null;
65
- }
66
- __name(isRecord, "isRecord");
67
- function readHeaders(request) {
68
- if (!isRecord(request)) return {};
69
- const headers = request.headers;
70
- return isRecord(headers) ? headers : {};
71
- }
72
- __name(readHeaders, "readHeaders");
73
- function headerToString(value) {
74
- if (typeof value === "string") return value;
75
- if (Array.isArray(value) && value.every((part) => typeof part === "string")) {
76
- return value.join(",");
77
- }
78
- return void 0;
79
- }
80
- __name(headerToString, "headerToString");
81
- function readCookieHeader(request) {
82
- return headerToString(readHeaders(request).cookie);
83
- }
84
- __name(readCookieHeader, "readCookieHeader");
85
- function isHttpsRequest(request) {
86
- if (isRecord(request) && request.protocol === "https") return true;
87
- const forwarded = headerToString(readHeaders(request)["x-forwarded-proto"]);
88
- if (forwarded === void 0) return false;
89
- return forwarded.split(",").map((proto) => proto.trim().toLowerCase()).includes("https");
90
- }
91
- __name(isHttpsRequest, "isHttpsRequest");
92
- function readOriginalUrl(request) {
93
- if (!isRecord(request)) return "/";
94
- const originalUrl = request.originalUrl;
95
- if (typeof originalUrl === "string" && originalUrl !== "") return originalUrl;
96
- const url = request.url;
97
- return typeof url === "string" && url !== "" ? url : "/";
98
- }
99
- __name(readOriginalUrl, "readOriginalUrl");
100
- function attachSession(request, session) {
101
- if (!isRecord(request)) return;
102
- const target = request;
103
- target.dashboardSession = session;
104
- }
105
- __name(attachSession, "attachSession");
106
-
107
- // src/server/auth/response.ts
108
- function isRecord2(value) {
109
- return typeof value === "object" && value !== null;
110
- }
111
- __name(isRecord2, "isRecord");
112
- function isHeaderCapableResponse(value) {
113
- return isRecord2(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function";
114
- }
115
- __name(isHeaderCapableResponse, "isHeaderCapableResponse");
116
- function resolveHeaderCapableResponse(response) {
117
- if (isHeaderCapableResponse(response)) return response;
118
- if (isRecord2(response) && isHeaderCapableResponse(response.raw)) return response.raw;
119
- return null;
120
- }
121
- __name(resolveHeaderCapableResponse, "resolveHeaderCapableResponse");
122
- function existingSetCookies(response) {
123
- const current = response.getHeader("set-cookie");
124
- if (Array.isArray(current)) return current;
125
- if (typeof current === "string") return [
126
- current
127
- ];
128
- return [];
129
- }
130
- __name(existingSetCookies, "existingSetCookies");
131
- function appendSetCookie(response, cookie) {
132
- const raw = resolveHeaderCapableResponse(response);
133
- if (!raw) return;
134
- raw.setHeader("set-cookie", [
135
- ...existingSetCookies(raw),
136
- cookie
137
- ]);
138
- }
139
- __name(appendSetCookie, "appendSetCookie");
140
- function isRawNodeResponse(value) {
141
- return isRecord2(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function" && typeof value.end === "function";
142
- }
143
- __name(isRawNodeResponse, "isRawNodeResponse");
144
- function resolveRawResponse(response) {
145
- if (isRawNodeResponse(response)) return response;
146
- if (isRecord2(response) && isRawNodeResponse(response.raw)) return response.raw;
147
- return null;
148
- }
149
- __name(resolveRawResponse, "resolveRawResponse");
150
- function responseAlreadyWritten(response) {
151
- const raw = resolveRawResponse(response);
152
- return raw?.headersSent === true;
153
- }
154
- __name(responseAlreadyWritten, "responseAlreadyWritten");
155
- function sendHtml(response, status, html) {
156
- const raw = resolveRawResponse(response);
157
- if (!raw) return;
158
- raw.statusCode = status;
159
- raw.setHeader("content-type", "text/html; charset=utf-8");
160
- raw.setHeader("cache-control", "no-store, must-revalidate");
161
- raw.end(html);
162
- }
163
- __name(sendHtml, "sendHtml");
164
- function sendRedirect(response, status, location) {
165
- const raw = resolveRawResponse(response);
166
- if (!raw) return;
167
- raw.statusCode = status;
168
- raw.setHeader("location", location);
169
- raw.end();
170
- }
171
- __name(sendRedirect, "sendRedirect");
172
-
173
- // src/server/auth/session-cookie.ts
174
- import { createHmac, timingSafeEqual } from "crypto";
175
- var EXP_GRACE_MS = 3e4;
176
- function base64urlEncode(value) {
177
- return Buffer.from(value, "utf8").toString("base64url");
178
- }
179
- __name(base64urlEncode, "base64urlEncode");
180
- function base64urlDecode(value) {
181
- return Buffer.from(value, "base64url").toString("utf8");
182
- }
183
- __name(base64urlDecode, "base64urlDecode");
184
- function hmac(secret, payload) {
185
- return createHmac("sha256", secret).update(payload).digest("base64url");
186
- }
187
- __name(hmac, "hmac");
188
- function signSessionCookie(user, options) {
189
- const issuedAt = options.now ?? Date.now();
190
- const session = {
191
- sub: user.id,
192
- ...user.name !== void 0 ? {
193
- name: user.name
194
- } : {},
195
- roles: user.roles ?? [],
196
- iat: issuedAt,
197
- exp: issuedAt + options.ttlMs
198
- };
199
- const encodedPayload = base64urlEncode(JSON.stringify(session));
200
- const signature = hmac(options.secret, encodedPayload);
201
- return `${encodedPayload}.${signature}`;
202
- }
203
- __name(signSessionCookie, "signSessionCookie");
204
- function isSessionPayload(value) {
205
- if (typeof value !== "object" || value === null) return false;
206
- const record = {
207
- ...value
208
- };
209
- if (typeof record.sub !== "string") return false;
210
- if (record.name !== void 0 && typeof record.name !== "string") return false;
211
- if (!Array.isArray(record.roles)) return false;
212
- if (!record.roles.every((role) => typeof role === "string")) return false;
213
- if (typeof record.iat !== "number" || !Number.isFinite(record.iat)) return false;
214
- if (typeof record.exp !== "number" || !Number.isFinite(record.exp)) return false;
215
- return true;
216
- }
217
- __name(isSessionPayload, "isSessionPayload");
218
- function verifySessionCookie(value, options) {
219
- try {
220
- const dot = value.indexOf(".");
221
- if (dot <= 0 || dot === value.length - 1) return null;
222
- const encodedPayload = value.slice(0, dot);
223
- const providedSignature = value.slice(dot + 1);
224
- const expectedSignature = hmac(options.secret, encodedPayload);
225
- const provided = Buffer.from(providedSignature, "base64url");
226
- const expected = Buffer.from(expectedSignature, "base64url");
227
- if (provided.length !== expected.length) return null;
228
- if (!timingSafeEqual(provided, expected)) return null;
229
- const decoded = JSON.parse(base64urlDecode(encodedPayload));
230
- if (!isSessionPayload(decoded)) return null;
231
- const now = options.now ?? Date.now();
232
- if (now > decoded.exp + EXP_GRACE_MS) return null;
233
- const session = {
234
- sub: decoded.sub,
235
- ...decoded.name !== void 0 ? {
236
- name: decoded.name
237
- } : {},
238
- roles: decoded.roles,
239
- iat: decoded.iat,
240
- exp: decoded.exp
241
- };
242
- return session;
243
- } catch {
244
- return null;
245
- }
246
- }
247
- __name(verifySessionCookie, "verifySessionCookie");
248
-
249
- // src/server/auth/session-cookie-io.ts
250
- var SESSION_COOKIE_NAME = "agent_dashboard_session";
251
- var COOKIE_PATH = "/";
252
- function issueSessionCookie(user, context) {
253
- const value = signSessionCookie(user, {
254
- secret: context.auth.secret,
255
- ttlMs: context.auth.ttlMs,
256
- ...context.now !== void 0 ? {
257
- now: context.now
258
- } : {}
259
- });
260
- const cookie = serializeSetCookie(SESSION_COOKIE_NAME, value, {
261
- path: COOKIE_PATH,
262
- maxAgeSeconds: Math.floor(context.auth.ttlMs / 1e3),
263
- secure: isHttpsRequest(context.request)
264
- });
265
- appendSetCookie(context.response, cookie);
266
- }
267
- __name(issueSessionCookie, "issueSessionCookie");
268
- function clearSessionCookie(context) {
269
- const cookie = serializeSetCookie(SESSION_COOKIE_NAME, "", {
270
- path: COOKIE_PATH,
271
- maxAgeSeconds: 0,
272
- secure: isHttpsRequest(context.request),
273
- clear: true
274
- });
275
- appendSetCookie(context.response, cookie);
276
- }
277
- __name(clearSessionCookie, "clearSessionCookie");
278
- var inFlightRevalidations = /* @__PURE__ */ new Map();
279
- function revalidationKey(session) {
280
- return `${session.sub}:${session.iat}`;
281
- }
282
- __name(revalidationKey, "revalidationKey");
283
- function getOrStartRevalidation(auth, session, user) {
284
- const hook = auth.revalidate;
285
- if (!hook) return Promise.resolve(true);
286
- const key = revalidationKey(session);
287
- const inFlight = inFlightRevalidations.get(key);
288
- if (inFlight) return inFlight;
289
- const outcome = (async () => {
290
- try {
291
- return await hook(user);
292
- } catch {
293
- return false;
294
- }
295
- })().finally(() => {
296
- inFlightRevalidations.delete(key);
297
- });
298
- inFlightRevalidations.set(key, outcome);
299
- return outcome;
300
- }
301
- __name(getOrStartRevalidation, "getOrStartRevalidation");
302
- async function maybeRenewSession(auth, session, request, response, now = Date.now()) {
303
- if (now - session.iat <= auth.ttlMs / 2) return true;
304
- const user = {
305
- id: session.sub,
306
- ...session.name !== void 0 ? {
307
- name: session.name
308
- } : {},
309
- roles: session.roles
310
- };
311
- const allowed = await getOrStartRevalidation(auth, session, user);
312
- if (!allowed) {
313
- clearSessionCookie({
314
- request,
315
- response
316
- });
317
- return false;
318
- }
319
- issueSessionCookie(user, {
320
- auth,
321
- request,
322
- response,
323
- now
324
- });
325
- return true;
326
- }
327
- __name(maybeRenewSession, "maybeRenewSession");
328
-
329
- // src/server/auth/dashboard-auth.guard.ts
330
- function _ts_decorate(decorators, target, key, desc) {
331
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
332
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
333
- r = Reflect.decorate(decorators, target, key, desc);
334
- } else {
335
- for (var i = decorators.length - 1; i >= 0; i--) {
336
- if (d = decorators[i]) {
337
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
338
- }
339
- }
340
- }
341
- return c > 3 && r && Object.defineProperty(target, key, r), r;
342
- }
343
- __name(_ts_decorate, "_ts_decorate");
344
- function _ts_metadata(metadataKey, metadataValue) {
345
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
346
- return Reflect.metadata(metadataKey, metadataValue);
347
- }
348
- }
349
- __name(_ts_metadata, "_ts_metadata");
350
- function _ts_param(paramIndex, decorator) {
351
- return function(target, key) {
352
- decorator(target, key, paramIndex);
353
- };
354
- }
355
- __name(_ts_param, "_ts_param");
356
- var DashboardAuthGuard = class {
357
- static {
358
- __name(this, "DashboardAuthGuard");
359
- }
360
- auth;
361
- constructor(auth) {
362
- this.auth = auth;
363
- }
364
- async canActivate(context) {
365
- if (!this.auth) return true;
366
- const http = context.switchToHttp();
367
- const request = http.getRequest();
368
- const session = this.verifyRequestSession(request);
369
- if (!session) throw new UnauthorizedException();
370
- attachSession(request, session);
371
- if (!await maybeRenewSession(this.auth, session, request, http.getResponse())) {
372
- throw new UnauthorizedException();
373
- }
374
- return true;
375
- }
376
- verifyRequestSession(request) {
377
- const auth = this.auth;
378
- if (!auth) return null;
379
- const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
380
- if (cookieValue === void 0) return null;
381
- return verifySessionCookie(cookieValue, {
382
- secret: auth.secret
383
- });
384
- }
385
- };
386
- DashboardAuthGuard = _ts_decorate([
387
- Injectable(),
388
- _ts_param(0, Optional()),
389
- _ts_param(0, Inject(DASHBOARD_AUTH)),
390
- _ts_metadata("design:type", Function),
391
- _ts_metadata("design:paramtypes", [
392
- Object
393
- ])
394
- ], DashboardAuthGuard);
5
+ import { CanAnyone } from "@dudousxd/nestjs-agent-core";
6
+ import { Body, Controller, Get, HttpCode, Inject as Inject2, Optional as Optional2, Param, Post, Query, Req, Sse } from "@nestjs/common";
395
7
 
396
8
  // src/server/dashboard.service.ts
397
9
  import { subscribe, unsubscribe } from "diagnostics_channel";
398
10
  import { channelName } from "@dudousxd/nestjs-diagnostics";
399
- import { Inject as Inject2, Injectable as Injectable2, NotFoundException, NotImplementedException, Optional as Optional2 } from "@nestjs/common";
11
+ import { Inject, Injectable, NotFoundException, NotImplementedException, Optional } from "@nestjs/common";
400
12
  import { Observable as Observable2 } from "rxjs";
401
13
 
402
14
  // src/server/parse-approval-decision.ts
@@ -461,8 +73,18 @@ function isFiniteNonNegative(value) {
461
73
  }
462
74
  __name(isFiniteNonNegative, "isFiniteNonNegative");
463
75
 
76
+ // src/server/tokens.ts
77
+ var AGENT_GOVERNANCE_QUERIES = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:governance-queries");
78
+ var AGENT_ACTOR_DIRECTORY = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:actor-directory");
79
+ var AGENT_PRICING_STORE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:pricing-store");
80
+ var AGENT_APPROVAL_PORT = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:approval-port");
81
+ var AGENT_ACTOR_RESOLVER = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
82
+ var DASHBOARD_BASE_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
83
+ var DASHBOARD_API_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
84
+ var DASHBOARD_APPROVAL_ACTOR_REF = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
85
+
464
86
  // src/server/dashboard.service.ts
465
- function _ts_decorate2(decorators, target, key, desc) {
87
+ function _ts_decorate(decorators, target, key, desc) {
466
88
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
467
89
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
468
90
  r = Reflect.decorate(decorators, target, key, desc);
@@ -475,19 +97,19 @@ function _ts_decorate2(decorators, target, key, desc) {
475
97
  }
476
98
  return c > 3 && r && Object.defineProperty(target, key, r), r;
477
99
  }
478
- __name(_ts_decorate2, "_ts_decorate");
479
- function _ts_metadata2(metadataKey, metadataValue) {
100
+ __name(_ts_decorate, "_ts_decorate");
101
+ function _ts_metadata(metadataKey, metadataValue) {
480
102
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
481
103
  return Reflect.metadata(metadataKey, metadataValue);
482
104
  }
483
105
  }
484
- __name(_ts_metadata2, "_ts_metadata");
485
- function _ts_param2(paramIndex, decorator) {
106
+ __name(_ts_metadata, "_ts_metadata");
107
+ function _ts_param(paramIndex, decorator) {
486
108
  return function(target, key) {
487
109
  decorator(target, key, paramIndex);
488
110
  };
489
111
  }
490
- __name(_ts_param2, "_ts_param");
112
+ __name(_ts_param, "_ts_param");
491
113
  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.";
492
114
  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.";
493
115
  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.";
@@ -521,16 +143,20 @@ var DashboardService = class {
521
143
  }
522
144
  /** Spend/usage overview for a day range: by-model + by-actor spend and the daily trend, in parallel. */
523
145
  async spend(range) {
524
- const [byModel, byActorRaw, trend] = await Promise.all([
146
+ const [byModel, byActorRaw, trend, byFeature] = await Promise.all([
525
147
  this.queries.spendByModel(range),
526
148
  this.queries.spendByActor(range),
527
- this.queries.usageTrend(range)
149
+ this.queries.usageTrend(range),
150
+ this.queries.spendByFeature?.(range)
528
151
  ]);
529
152
  const byActor = await this.withActorLabels(byActorRaw);
530
153
  return {
531
154
  byModel,
532
155
  byActor,
533
- trend
156
+ trend,
157
+ ...byFeature !== void 0 ? {
158
+ byFeature
159
+ } : {}
534
160
  };
535
161
  }
536
162
  /** Top threads by cost for a day range (default 10, highest cost first). */
@@ -752,17 +378,17 @@ var DashboardService = class {
752
378
  });
753
379
  }
754
380
  };
755
- DashboardService = _ts_decorate2([
756
- Injectable2(),
757
- _ts_param2(0, Inject2(AGENT_GOVERNANCE_QUERIES)),
758
- _ts_param2(1, Optional2()),
759
- _ts_param2(1, Inject2(AGENT_ACTOR_DIRECTORY)),
760
- _ts_param2(2, Optional2()),
761
- _ts_param2(2, Inject2(AGENT_PRICING_STORE)),
762
- _ts_param2(3, Optional2()),
763
- _ts_param2(3, Inject2(AGENT_APPROVAL_PORT)),
764
- _ts_metadata2("design:type", Function),
765
- _ts_metadata2("design:paramtypes", [
381
+ DashboardService = _ts_decorate([
382
+ Injectable(),
383
+ _ts_param(0, Inject(AGENT_GOVERNANCE_QUERIES)),
384
+ _ts_param(1, Optional()),
385
+ _ts_param(1, Inject(AGENT_ACTOR_DIRECTORY)),
386
+ _ts_param(2, Optional()),
387
+ _ts_param(2, Inject(AGENT_PRICING_STORE)),
388
+ _ts_param(3, Optional()),
389
+ _ts_param(3, Inject(AGENT_APPROVAL_PORT)),
390
+ _ts_metadata("design:type", Function),
391
+ _ts_metadata("design:paramtypes", [
766
392
  typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries,
767
393
  typeof ActorDirectory === "undefined" ? Object : ActorDirectory,
768
394
  typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
@@ -930,7 +556,7 @@ function parseApprovalWhere(raw) {
930
556
  __name(parseApprovalWhere, "parseApprovalWhere");
931
557
 
932
558
  // src/server/agent-api.controller.ts
933
- function _ts_decorate3(decorators, target, key, desc) {
559
+ function _ts_decorate2(decorators, target, key, desc) {
934
560
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
935
561
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
936
562
  r = Reflect.decorate(decorators, target, key, desc);
@@ -943,19 +569,19 @@ function _ts_decorate3(decorators, target, key, desc) {
943
569
  }
944
570
  return c > 3 && r && Object.defineProperty(target, key, r), r;
945
571
  }
946
- __name(_ts_decorate3, "_ts_decorate");
947
- function _ts_metadata3(metadataKey, metadataValue) {
572
+ __name(_ts_decorate2, "_ts_decorate");
573
+ function _ts_metadata2(metadataKey, metadataValue) {
948
574
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
949
575
  return Reflect.metadata(metadataKey, metadataValue);
950
576
  }
951
577
  }
952
- __name(_ts_metadata3, "_ts_metadata");
953
- function _ts_param3(paramIndex, decorator) {
578
+ __name(_ts_metadata2, "_ts_metadata");
579
+ function _ts_param2(paramIndex, decorator) {
954
580
  return function(target, key) {
955
581
  decorator(target, key, paramIndex);
956
582
  };
957
583
  }
958
- __name(_ts_param3, "_ts_param");
584
+ __name(_ts_param2, "_ts_param");
959
585
  var DAY_MS = 864e5;
960
586
  var ISO_DAY2 = /^\d{4}-\d{2}-\d{2}$/;
961
587
  function utcDay(daysAgo) {
@@ -1173,620 +799,222 @@ var AgentApiController = class {
1173
799
  return this.dashboard.streamEvents();
1174
800
  }
1175
801
  };
1176
- _ts_decorate3([
802
+ _ts_decorate2([
1177
803
  Get("spend"),
1178
- _ts_param3(0, Query("from")),
1179
- _ts_param3(1, Query("to")),
1180
- _ts_metadata3("design:type", Function),
1181
- _ts_metadata3("design:paramtypes", [
804
+ _ts_param2(0, Query("from")),
805
+ _ts_param2(1, Query("to")),
806
+ _ts_metadata2("design:type", Function),
807
+ _ts_metadata2("design:paramtypes", [
1182
808
  String,
1183
809
  String
1184
810
  ]),
1185
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
811
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1186
812
  ], AgentApiController.prototype, "spend", null);
1187
- _ts_decorate3([
813
+ _ts_decorate2([
1188
814
  Get("top-threads"),
1189
- _ts_param3(0, Query("from")),
1190
- _ts_param3(1, Query("to")),
1191
- _ts_param3(2, Query("limit")),
1192
- _ts_metadata3("design:type", Function),
1193
- _ts_metadata3("design:paramtypes", [
815
+ _ts_param2(0, Query("from")),
816
+ _ts_param2(1, Query("to")),
817
+ _ts_param2(2, Query("limit")),
818
+ _ts_metadata2("design:type", Function),
819
+ _ts_metadata2("design:paramtypes", [
1194
820
  String,
1195
821
  String,
1196
822
  String
1197
823
  ]),
1198
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
824
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1199
825
  ], AgentApiController.prototype, "topThreads", null);
1200
- _ts_decorate3([
826
+ _ts_decorate2([
1201
827
  Get("reliability"),
1202
- _ts_param3(0, Query("from")),
1203
- _ts_param3(1, Query("to")),
1204
- _ts_metadata3("design:type", Function),
1205
- _ts_metadata3("design:paramtypes", [
828
+ _ts_param2(0, Query("from")),
829
+ _ts_param2(1, Query("to")),
830
+ _ts_metadata2("design:type", Function),
831
+ _ts_metadata2("design:paramtypes", [
1206
832
  String,
1207
833
  String
1208
834
  ]),
1209
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
835
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1210
836
  ], AgentApiController.prototype, "reliability", null);
1211
- _ts_decorate3([
837
+ _ts_decorate2([
1212
838
  Get("runs"),
1213
- _ts_param3(0, Query("limit")),
1214
- _ts_metadata3("design:type", Function),
1215
- _ts_metadata3("design:paramtypes", [
839
+ _ts_param2(0, Query("limit")),
840
+ _ts_metadata2("design:type", Function),
841
+ _ts_metadata2("design:paramtypes", [
1216
842
  String
1217
843
  ]),
1218
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
844
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1219
845
  ], AgentApiController.prototype, "runs", null);
1220
- _ts_decorate3([
846
+ _ts_decorate2([
1221
847
  Get("runs-page"),
1222
- _ts_param3(0, Query("page")),
1223
- _ts_param3(1, Query("limit")),
1224
- _ts_param3(2, Query("where")),
1225
- _ts_metadata3("design:type", Function),
1226
- _ts_metadata3("design:paramtypes", [
848
+ _ts_param2(0, Query("page")),
849
+ _ts_param2(1, Query("limit")),
850
+ _ts_param2(2, Query("where")),
851
+ _ts_metadata2("design:type", Function),
852
+ _ts_metadata2("design:paramtypes", [
1227
853
  String,
1228
854
  String,
1229
855
  typeof Record === "undefined" ? Object : Record
1230
856
  ]),
1231
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
857
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1232
858
  ], AgentApiController.prototype, "runsPage", null);
1233
- _ts_decorate3([
859
+ _ts_decorate2([
1234
860
  Get("runs/:runId"),
1235
- _ts_param3(0, Param("runId")),
1236
- _ts_metadata3("design:type", Function),
1237
- _ts_metadata3("design:paramtypes", [
861
+ _ts_param2(0, Param("runId")),
862
+ _ts_metadata2("design:type", Function),
863
+ _ts_metadata2("design:paramtypes", [
1238
864
  String
1239
865
  ]),
1240
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
866
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1241
867
  ], AgentApiController.prototype, "runDetail", null);
1242
- _ts_decorate3([
868
+ _ts_decorate2([
1243
869
  Get("tool-calls"),
1244
- _ts_param3(0, Query("limit")),
1245
- _ts_metadata3("design:type", Function),
1246
- _ts_metadata3("design:paramtypes", [
870
+ _ts_param2(0, Query("limit")),
871
+ _ts_metadata2("design:type", Function),
872
+ _ts_metadata2("design:paramtypes", [
1247
873
  String
1248
874
  ]),
1249
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
875
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1250
876
  ], AgentApiController.prototype, "toolCalls", null);
1251
- _ts_decorate3([
877
+ _ts_decorate2([
1252
878
  Get("tool-calls-page"),
1253
- _ts_param3(0, Query("page")),
1254
- _ts_param3(1, Query("limit")),
1255
- _ts_param3(2, Query("where")),
1256
- _ts_metadata3("design:type", Function),
1257
- _ts_metadata3("design:paramtypes", [
879
+ _ts_param2(0, Query("page")),
880
+ _ts_param2(1, Query("limit")),
881
+ _ts_param2(2, Query("where")),
882
+ _ts_metadata2("design:type", Function),
883
+ _ts_metadata2("design:paramtypes", [
1258
884
  String,
1259
885
  String,
1260
886
  typeof Record === "undefined" ? Object : Record
1261
887
  ]),
1262
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
888
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1263
889
  ], AgentApiController.prototype, "toolCallsPage", null);
1264
- _ts_decorate3([
890
+ _ts_decorate2([
1265
891
  Get("approvals"),
1266
- _ts_param3(0, Query("limit")),
1267
- _ts_metadata3("design:type", Function),
1268
- _ts_metadata3("design:paramtypes", [
892
+ _ts_param2(0, Query("limit")),
893
+ _ts_metadata2("design:type", Function),
894
+ _ts_metadata2("design:paramtypes", [
1269
895
  String
1270
896
  ]),
1271
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
897
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1272
898
  ], AgentApiController.prototype, "approvals", null);
1273
- _ts_decorate3([
899
+ _ts_decorate2([
1274
900
  Get("approvals-page"),
1275
- _ts_param3(0, Query("page")),
1276
- _ts_param3(1, Query("limit")),
1277
- _ts_param3(2, Query("where")),
1278
- _ts_metadata3("design:type", Function),
1279
- _ts_metadata3("design:paramtypes", [
901
+ _ts_param2(0, Query("page")),
902
+ _ts_param2(1, Query("limit")),
903
+ _ts_param2(2, Query("where")),
904
+ _ts_metadata2("design:type", Function),
905
+ _ts_metadata2("design:paramtypes", [
1280
906
  String,
1281
907
  String,
1282
908
  typeof Record === "undefined" ? Object : Record
1283
909
  ]),
1284
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
910
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1285
911
  ], AgentApiController.prototype, "approvalsPage", null);
1286
- _ts_decorate3([
912
+ _ts_decorate2([
1287
913
  Post("approvals/:toolCallId"),
1288
914
  HttpCode(204),
1289
- _ts_param3(0, Param("toolCallId")),
1290
- _ts_param3(1, Body()),
1291
- _ts_param3(2, Req()),
1292
- _ts_metadata3("design:type", Function),
1293
- _ts_metadata3("design:paramtypes", [
915
+ _ts_param2(0, Param("toolCallId")),
916
+ _ts_param2(1, Body()),
917
+ _ts_param2(2, Req()),
918
+ _ts_metadata2("design:type", Function),
919
+ _ts_metadata2("design:paramtypes", [
1294
920
  String,
1295
921
  Object,
1296
922
  Object
1297
923
  ]),
1298
- _ts_metadata3("design:returntype", Promise)
924
+ _ts_metadata2("design:returntype", Promise)
1299
925
  ], AgentApiController.prototype, "decideApproval", null);
1300
- _ts_decorate3([
926
+ _ts_decorate2([
1301
927
  Get("tools"),
1302
- _ts_param3(0, Query("from")),
1303
- _ts_param3(1, Query("to")),
1304
- _ts_metadata3("design:type", Function),
1305
- _ts_metadata3("design:paramtypes", [
928
+ _ts_param2(0, Query("from")),
929
+ _ts_param2(1, Query("to")),
930
+ _ts_metadata2("design:type", Function),
931
+ _ts_metadata2("design:paramtypes", [
1306
932
  String,
1307
933
  String
1308
934
  ]),
1309
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
935
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1310
936
  ], AgentApiController.prototype, "tools", null);
1311
- _ts_decorate3([
937
+ _ts_decorate2([
1312
938
  Get("genui"),
1313
- _ts_param3(0, Query("from")),
1314
- _ts_param3(1, Query("to")),
1315
- _ts_metadata3("design:type", Function),
1316
- _ts_metadata3("design:paramtypes", [
939
+ _ts_param2(0, Query("from")),
940
+ _ts_param2(1, Query("to")),
941
+ _ts_metadata2("design:type", Function),
942
+ _ts_metadata2("design:paramtypes", [
1317
943
  String,
1318
944
  String
1319
945
  ]),
1320
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
946
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1321
947
  ], AgentApiController.prototype, "genui", null);
1322
- _ts_decorate3([
948
+ _ts_decorate2([
1323
949
  Get("threads"),
1324
- _ts_param3(0, Query("limit")),
1325
- _ts_metadata3("design:type", Function),
1326
- _ts_metadata3("design:paramtypes", [
950
+ _ts_param2(0, Query("limit")),
951
+ _ts_metadata2("design:type", Function),
952
+ _ts_metadata2("design:paramtypes", [
1327
953
  String
1328
954
  ]),
1329
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
955
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1330
956
  ], AgentApiController.prototype, "threads", null);
1331
- _ts_decorate3([
957
+ _ts_decorate2([
1332
958
  Get("threads-page"),
1333
- _ts_param3(0, Query("page")),
1334
- _ts_param3(1, Query("limit")),
1335
- _ts_param3(2, Query("where")),
1336
- _ts_metadata3("design:type", Function),
1337
- _ts_metadata3("design:paramtypes", [
959
+ _ts_param2(0, Query("page")),
960
+ _ts_param2(1, Query("limit")),
961
+ _ts_param2(2, Query("where")),
962
+ _ts_metadata2("design:type", Function),
963
+ _ts_metadata2("design:paramtypes", [
1338
964
  String,
1339
965
  String,
1340
966
  typeof Record === "undefined" ? Object : Record
1341
967
  ]),
1342
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
968
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1343
969
  ], AgentApiController.prototype, "threadsPage", null);
1344
- _ts_decorate3([
970
+ _ts_decorate2([
1345
971
  Get("threads/:threadId"),
1346
- _ts_param3(0, Param("threadId")),
1347
- _ts_param3(1, Query("messages")),
1348
- _ts_param3(2, Query("runs")),
1349
- _ts_metadata3("design:type", Function),
1350
- _ts_metadata3("design:paramtypes", [
972
+ _ts_param2(0, Param("threadId")),
973
+ _ts_param2(1, Query("messages")),
974
+ _ts_param2(2, Query("runs")),
975
+ _ts_metadata2("design:type", Function),
976
+ _ts_metadata2("design:paramtypes", [
1351
977
  String,
1352
978
  String,
1353
979
  String
1354
980
  ]),
1355
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
981
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1356
982
  ], AgentApiController.prototype, "threadDetail", null);
1357
- _ts_decorate3([
983
+ _ts_decorate2([
1358
984
  Get("pricing"),
1359
- _ts_metadata3("design:type", Function),
1360
- _ts_metadata3("design:paramtypes", []),
1361
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
985
+ _ts_metadata2("design:type", Function),
986
+ _ts_metadata2("design:paramtypes", []),
987
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1362
988
  ], AgentApiController.prototype, "listPrices", null);
1363
- _ts_decorate3([
989
+ _ts_decorate2([
1364
990
  Post("pricing"),
1365
- _ts_param3(0, Body()),
1366
- _ts_metadata3("design:type", Function),
1367
- _ts_metadata3("design:paramtypes", [
991
+ _ts_param2(0, Body()),
992
+ _ts_metadata2("design:type", Function),
993
+ _ts_metadata2("design:paramtypes", [
1368
994
  Object
1369
995
  ]),
1370
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
996
+ _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1371
997
  ], AgentApiController.prototype, "upsertPrice", null);
1372
- _ts_decorate3([
998
+ _ts_decorate2([
1373
999
  Sse("stream"),
1374
- _ts_metadata3("design:type", Function),
1375
- _ts_metadata3("design:paramtypes", []),
1376
- _ts_metadata3("design:returntype", typeof Observable === "undefined" ? Object : Observable)
1000
+ _ts_metadata2("design:type", Function),
1001
+ _ts_metadata2("design:paramtypes", []),
1002
+ _ts_metadata2("design:returntype", typeof Observable === "undefined" ? Object : Observable)
1377
1003
  ], AgentApiController.prototype, "stream", null);
1378
- AgentApiController = _ts_decorate3([
1004
+ AgentApiController = _ts_decorate2([
1005
+ CanAnyone(),
1379
1006
  Controller(),
1380
- UseGuards(DashboardAuthGuard),
1381
- _ts_param3(1, Inject3(DASHBOARD_APPROVAL_ACTOR_REF)),
1382
- _ts_param3(2, Optional3()),
1383
- _ts_param3(2, Inject3(AGENT_ACTOR_RESOLVER)),
1384
- _ts_metadata3("design:type", Function),
1385
- _ts_metadata3("design:paramtypes", [
1007
+ _ts_param2(1, Inject2(DASHBOARD_APPROVAL_ACTOR_REF)),
1008
+ _ts_param2(2, Optional2()),
1009
+ _ts_param2(2, Inject2(AGENT_ACTOR_RESOLVER)),
1010
+ _ts_metadata2("design:type", Function),
1011
+ _ts_metadata2("design:paramtypes", [
1386
1012
  typeof DashboardService === "undefined" ? Object : DashboardService,
1387
1013
  Object,
1388
1014
  typeof ActorResolver === "undefined" ? Object : ActorResolver
1389
1015
  ])
1390
1016
  ], AgentApiController);
1391
1017
 
1392
- // src/server/agent-dashboard-auth.controller.ts
1393
- import { Body as Body2, Controller as Controller2, Get as Get2, Header, HttpCode as HttpCode2, Inject as Inject4, Logger, NotFoundException as NotFoundException2, Optional as Optional4, Post as Post2, Query as Query2, Req as Req2, Res, UnauthorizedException as UnauthorizedException2 } from "@nestjs/common";
1394
-
1395
- // src/server/auth/login-page.ts
1396
- function escapeHtml(value) {
1397
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1398
- }
1399
- __name(escapeHtml, "escapeHtml");
1400
- function pageShell(content, title) {
1401
- return `<!doctype html>
1402
- <html lang="en">
1403
- <head>
1404
- <meta charset="utf-8" />
1405
- <meta name="viewport" content="width=device-width, initial-scale=1" />
1406
- <meta name="robots" content="noindex, nofollow" />
1407
- <title>${title}</title>
1408
- <style>
1409
- :root { color-scheme: dark; }
1410
- * { box-sizing: border-box; }
1411
- body {
1412
- margin: 0;
1413
- min-height: 100vh;
1414
- display: flex;
1415
- align-items: center;
1416
- justify-content: center;
1417
- background: #09090b;
1418
- color: #e4e4e7;
1419
- font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1420
- padding: 16px;
1421
- }
1422
- .card {
1423
- width: 100%;
1424
- max-width: 384px;
1425
- border: 1px solid #27272a;
1426
- background: #18181b;
1427
- border-radius: 8px;
1428
- padding: 32px;
1429
- box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
1430
- }
1431
- .brand {
1432
- margin: 0 0 24px;
1433
- text-align: center;
1434
- font-size: 18px;
1435
- font-weight: 600;
1436
- color: #34d399;
1437
- }
1438
- h1 {
1439
- margin: 0 0 12px;
1440
- font-size: 16px;
1441
- font-weight: 600;
1442
- color: #f4f4f5;
1443
- }
1444
- p { margin: 0 0 16px; color: #a1a1aa; }
1445
- form { display: flex; flex-direction: column; gap: 16px; }
1446
- label { display: flex; flex-direction: column; gap: 6px; }
1447
- .field-label {
1448
- font-size: 11px;
1449
- text-transform: uppercase;
1450
- letter-spacing: 0.05em;
1451
- color: #71717a;
1452
- }
1453
- input {
1454
- border-radius: 4px;
1455
- border: 1px solid #3f3f46;
1456
- background: #09090b;
1457
- color: #f4f4f5;
1458
- padding: 8px 12px;
1459
- font: inherit;
1460
- outline: none;
1461
- }
1462
- input:focus { border-color: rgb(52 211 153 / 0.6); }
1463
- .error { margin: 0; font-size: 12px; color: #fb7185; }
1464
- button {
1465
- margin-top: 8px;
1466
- border-radius: 4px;
1467
- border: 1px solid rgb(52 211 153 / 0.4);
1468
- background: rgb(52 211 153 / 0.1);
1469
- color: #6ee7b7;
1470
- padding: 8px 12px;
1471
- font: inherit;
1472
- font-size: 12px;
1473
- font-weight: 500;
1474
- text-transform: uppercase;
1475
- letter-spacing: 0.05em;
1476
- cursor: pointer;
1477
- }
1478
- button:hover { background: rgb(52 211 153 / 0.2); }
1479
- </style>
1480
- </head>
1481
- <body>
1482
- <div class="card">
1483
- ${content}
1484
- </div>
1485
- </body>
1486
- </html>`;
1487
- }
1488
- __name(pageShell, "pageShell");
1489
- function renderLoginPage(options) {
1490
- const action = escapeHtml(options.actionUrl);
1491
- const returnTo = escapeHtml(options.returnTo);
1492
- const errorBanner = options.error === true ? '<p role="alert" class="error">Invalid username or password.</p>' : "";
1493
- return pageShell(`<p class="brand">AI Gateway</p>
1494
- <form method="post" action="${action}">
1495
- <input type="hidden" name="returnTo" value="${returnTo}" />
1496
- <label>
1497
- <span class="field-label">Username</span>
1498
- <input type="text" name="username" autocomplete="username" autofocus />
1499
- </label>
1500
- <label>
1501
- <span class="field-label">Password</span>
1502
- <input type="password" name="password" autocomplete="current-password" />
1503
- </label>
1504
- ${errorBanner}
1505
- <button type="submit">Sign in</button>
1506
- </form>`, "Sign in \u2014 AI Gateway");
1507
- }
1508
- __name(renderLoginPage, "renderLoginPage");
1509
- function renderSessionRequiredPage() {
1510
- return pageShell(`<p class="brand">AI Gateway</p>
1511
- <h1>Open this console from your application</h1>
1512
- <p>Your session is minted by the host app. Use its console launcher to sign in, then reload.</p>`, "Sign in \u2014 AI Gateway");
1513
- }
1514
- __name(renderSessionRequiredPage, "renderSessionRequiredPage");
1515
-
1516
- // src/server/auth/sanitize-return-to.ts
1517
- function sanitizeReturnTo(basePath, returnTo) {
1518
- if (typeof returnTo !== "string" || returnTo === "") return basePath;
1519
- if (!returnTo.startsWith("/") || returnTo.startsWith("//")) return basePath;
1520
- if (returnTo !== basePath && !returnTo.startsWith(`${basePath}/`) && !returnTo.startsWith(`${basePath}?`)) {
1521
- return basePath;
1522
- }
1523
- return returnTo;
1524
- }
1525
- __name(sanitizeReturnTo, "sanitizeReturnTo");
1526
-
1527
- // src/server/agent-dashboard-auth.controller.ts
1528
- function _ts_decorate4(decorators, target, key, desc) {
1529
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1530
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1531
- r = Reflect.decorate(decorators, target, key, desc);
1532
- } else {
1533
- for (var i = decorators.length - 1; i >= 0; i--) {
1534
- if (d = decorators[i]) {
1535
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1536
- }
1537
- }
1538
- }
1539
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1540
- }
1541
- __name(_ts_decorate4, "_ts_decorate");
1542
- function _ts_metadata4(metadataKey, metadataValue) {
1543
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1544
- return Reflect.metadata(metadataKey, metadataValue);
1545
- }
1546
- }
1547
- __name(_ts_metadata4, "_ts_metadata");
1548
- function _ts_param4(paramIndex, decorator) {
1549
- return function(target, key) {
1550
- decorator(target, key, paramIndex);
1551
- };
1552
- }
1553
- __name(_ts_param4, "_ts_param");
1554
- function isNonEmptyString(value) {
1555
- return typeof value === "string" && value.trim() !== "";
1556
- }
1557
- __name(isNonEmptyString, "isNonEmptyString");
1558
- function isString(value) {
1559
- return typeof value === "string";
1560
- }
1561
- __name(isString, "isString");
1562
- var AgentDashboardAuthController = class _AgentDashboardAuthController {
1563
- static {
1564
- __name(this, "AgentDashboardAuthController");
1565
- }
1566
- auth;
1567
- basePath;
1568
- logger = new Logger(_AgentDashboardAuthController.name);
1569
- /** Warn once PER HOOK KIND (not per request) so a broken hook can't be used to flood the logs. */
1570
- warnedHooks = /* @__PURE__ */ new Set();
1571
- constructor(auth, basePath) {
1572
- this.auth = auth;
1573
- this.basePath = basePath;
1574
- }
1575
- loginPage(req, res, returnToQuery, error) {
1576
- const auth = this.requireAuth();
1577
- if (!auth.modes.includes("login")) throw new NotFoundException2();
1578
- const returnTo = sanitizeReturnTo(this.basePath, returnToQuery);
1579
- if (this.currentSession(req)) {
1580
- res.status(302);
1581
- res.setHeader("Location", returnTo);
1582
- return "";
1583
- }
1584
- return renderLoginPage({
1585
- actionUrl: `${this.basePath}/auth/login`,
1586
- returnTo,
1587
- error: error !== void 0
1588
- });
1589
- }
1590
- async login(body, req, res) {
1591
- const auth = this.requireAuth();
1592
- if (!auth.modes.includes("login")) throw new NotFoundException2();
1593
- const returnTo = sanitizeReturnTo(this.basePath, body?.returnTo);
1594
- const username = body?.username;
1595
- const password = body?.password;
1596
- if (!isNonEmptyString(username) || password !== void 0 && !isString(password)) {
1597
- this.redirectToLoginError(res, returnTo);
1598
- return "";
1599
- }
1600
- const user = await this.runHook("login", () => auth.login?.(username.trim(), isString(password) ? password : "") ?? null);
1601
- if (!user) {
1602
- this.redirectToLoginError(res, returnTo);
1603
- return "";
1604
- }
1605
- issueSessionCookie(user, {
1606
- auth,
1607
- request: req,
1608
- response: res
1609
- });
1610
- res.status(302);
1611
- res.setHeader("Location", returnTo);
1612
- return "";
1613
- }
1614
- logout(req, res) {
1615
- clearSessionCookie({
1616
- request: req,
1617
- response: res
1618
- });
1619
- res.status(302);
1620
- res.setHeader("Location", this.auth && !this.auth.modes.includes("login") ? `${this.basePath}/auth/session-required` : `${this.basePath}/auth/login`);
1621
- return "";
1622
- }
1623
- // Mode A: the host frontend (carrying its own auth) POSTs here; the host hook validates the raw
1624
- // request and returns the session user, or `null` to deny. No credential reaches this library.
1625
- async session(request, response) {
1626
- const auth = this.requireAuth();
1627
- if (!auth.modes.includes("session")) throw new NotFoundException2();
1628
- const user = await this.runHook("session", () => auth.session?.(request) ?? null);
1629
- if (!user) throw new UnauthorizedException2();
1630
- issueSessionCookie(user, {
1631
- auth,
1632
- request,
1633
- response
1634
- });
1635
- }
1636
- // Mode-A-only landing: the host mints the session, so there is nothing to submit here. Serves
1637
- // as the redirect target `DashboardAuthPageGuard` bounces to instead of `/auth/login`, which
1638
- // 404s under Mode A (see `loginPage` above).
1639
- //
1640
- // Non-passthrough `@Res()` (unlike its sibling routes) because `dashboardAuth.unauthenticatedPage`
1641
- // hands the response to the HOST, which writes and ends it itself — there is no return value for
1642
- // Nest to send, and letting Nest also send one would double-write. The `Content-Type` /
1643
- // `Cache-Control` this route used to carry as decorators move into `sendHtml` for the built-in
1644
- // path; the host owns its own headers on the hook path.
1645
- async sessionRequiredPage(req, res) {
1646
- const auth = this.requireAuth();
1647
- if (auth.modes.includes("login")) throw new NotFoundException2();
1648
- const hook = auth.unauthenticatedPage;
1649
- if (hook) {
1650
- try {
1651
- await hook({
1652
- request: req,
1653
- response: res,
1654
- basePath: this.basePath
1655
- });
1656
- if (responseAlreadyWritten(res)) return;
1657
- this.warnHookOnce("unauthenticatedPage", "dashboardAuth.unauthenticatedPage returned without writing a response; falling back to the built-in page. The hook must write AND end the response it is given.");
1658
- } catch (error) {
1659
- this.warnHookOnce("unauthenticatedPage", `dashboardAuth.unauthenticatedPage threw; falling back to the built-in page. ${String(error)}`);
1660
- if (responseAlreadyWritten(res)) return;
1661
- }
1662
- }
1663
- sendHtml(res, 200, renderSessionRequiredPage());
1664
- }
1665
- /** Uniform failure: same redirect (generic error flag) whether the user is unknown or the password is wrong. */
1666
- redirectToLoginError(res, returnTo) {
1667
- res.status(303);
1668
- res.setHeader("Location", `${this.basePath}/auth/login?error=1&returnTo=${encodeURIComponent(returnTo)}`);
1669
- }
1670
- currentSession(req) {
1671
- const auth = this.auth;
1672
- if (!auth) return false;
1673
- const cookieValue = parseCookieHeader(readCookieHeader(req))[SESSION_COOKIE_NAME];
1674
- if (cookieValue === void 0) return false;
1675
- return verifySessionCookie(cookieValue, {
1676
- secret: auth.secret
1677
- }) !== null;
1678
- }
1679
- /**
1680
- * Run a host hook (`login` or `session`) defensively: a throw (sync or async) is treated as a
1681
- * denial (`null`) and warn-logged ONCE PER KIND, so a buggy/unreachable hook never 500s the
1682
- * endpoint into a stack-trace leak nor floods the logs on repeated bad attempts.
1683
- */
1684
- async runHook(kind, run) {
1685
- try {
1686
- return await run() ?? null;
1687
- } catch (error) {
1688
- this.warnHookOnce(kind, `AgentDashboardModule dashboardAuth ${kind} hook threw; treating as denial. ${error instanceof Error ? error.message : String(error)}`);
1689
- return null;
1690
- }
1691
- }
1692
- /**
1693
- * Warn once per hook kind for the life of the process, not once per request: a broken hook fires
1694
- * on every denied navigation and would otherwise flood the logs.
1695
- */
1696
- warnHookOnce(kind, message) {
1697
- if (this.warnedHooks.has(kind)) return;
1698
- this.warnedHooks.add(kind);
1699
- this.logger.warn(message);
1700
- }
1701
- requireAuth() {
1702
- if (!this.auth) throw new NotFoundException2();
1703
- return this.auth;
1704
- }
1705
- };
1706
- _ts_decorate4([
1707
- Get2("login"),
1708
- Header("Content-Type", "text/html; charset=utf-8"),
1709
- Header("Cache-Control", "no-store"),
1710
- _ts_param4(0, Req2()),
1711
- _ts_param4(1, Res({
1712
- passthrough: true
1713
- })),
1714
- _ts_param4(2, Query2("returnTo")),
1715
- _ts_param4(3, Query2("error")),
1716
- _ts_metadata4("design:type", Function),
1717
- _ts_metadata4("design:paramtypes", [
1718
- typeof AuthPageRequest === "undefined" ? Object : AuthPageRequest,
1719
- typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse,
1720
- String,
1721
- String
1722
- ]),
1723
- _ts_metadata4("design:returntype", String)
1724
- ], AgentDashboardAuthController.prototype, "loginPage", null);
1725
- _ts_decorate4([
1726
- Post2("login"),
1727
- _ts_param4(0, Body2()),
1728
- _ts_param4(1, Req2()),
1729
- _ts_param4(2, Res({
1730
- passthrough: true
1731
- })),
1732
- _ts_metadata4("design:type", Function),
1733
- _ts_metadata4("design:paramtypes", [
1734
- typeof LoginFormBody === "undefined" ? Object : LoginFormBody,
1735
- Object,
1736
- typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
1737
- ]),
1738
- _ts_metadata4("design:returntype", Promise)
1739
- ], AgentDashboardAuthController.prototype, "login", null);
1740
- _ts_decorate4([
1741
- Post2("logout"),
1742
- _ts_param4(0, Req2()),
1743
- _ts_param4(1, Res({
1744
- passthrough: true
1745
- })),
1746
- _ts_metadata4("design:type", Function),
1747
- _ts_metadata4("design:paramtypes", [
1748
- Object,
1749
- typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
1750
- ]),
1751
- _ts_metadata4("design:returntype", String)
1752
- ], AgentDashboardAuthController.prototype, "logout", null);
1753
- _ts_decorate4([
1754
- Post2("session"),
1755
- HttpCode2(204),
1756
- _ts_param4(0, Req2()),
1757
- _ts_param4(1, Res({
1758
- passthrough: true
1759
- })),
1760
- _ts_metadata4("design:type", Function),
1761
- _ts_metadata4("design:paramtypes", [
1762
- Object,
1763
- Object
1764
- ]),
1765
- _ts_metadata4("design:returntype", Promise)
1766
- ], AgentDashboardAuthController.prototype, "session", null);
1767
- _ts_decorate4([
1768
- Get2("session-required"),
1769
- _ts_param4(0, Req2()),
1770
- _ts_param4(1, Res()),
1771
- _ts_metadata4("design:type", Function),
1772
- _ts_metadata4("design:paramtypes", [
1773
- typeof AuthPageRequest === "undefined" ? Object : AuthPageRequest,
1774
- Object
1775
- ]),
1776
- _ts_metadata4("design:returntype", Promise)
1777
- ], AgentDashboardAuthController.prototype, "sessionRequiredPage", null);
1778
- AgentDashboardAuthController = _ts_decorate4([
1779
- Controller2("auth"),
1780
- _ts_param4(0, Optional4()),
1781
- _ts_param4(0, Inject4(DASHBOARD_AUTH)),
1782
- _ts_param4(1, Inject4(DASHBOARD_BASE_PATH)),
1783
- _ts_metadata4("design:type", Function),
1784
- _ts_metadata4("design:paramtypes", [
1785
- Object,
1786
- String
1787
- ])
1788
- ], AgentDashboardAuthController);
1789
-
1790
1018
  // src/server/normalize-path.ts
1791
1019
  function normalizeDashboardPath(path) {
1792
1020
  return `/${path.replace(/^\/+|\/+$/g, "")}`;
@@ -1813,6 +1041,7 @@ function agentDashboardMountPaths(options) {
1813
1041
  __name(agentDashboardMountPaths, "agentDashboardMountPaths");
1814
1042
 
1815
1043
  // src/server/agent-dashboard.module.ts
1044
+ import { withControllerDecorators } from "@dudousxd/nestjs-agent-core";
1816
1045
  import "reflect-metadata";
1817
1046
  import { Module } from "@nestjs/common";
1818
1047
  import { RouterModule } from "@nestjs/core";
@@ -1821,145 +1050,9 @@ import { RouterModule } from "@nestjs/core";
1821
1050
  import { existsSync, readFileSync } from "fs";
1822
1051
  import { basename, extname, join, resolve, sep } from "path";
1823
1052
  import { fileURLToPath } from "url";
1824
- import { Controller as Controller3, Get as Get3, Header as Header2, Inject as Inject6, NotFoundException as NotFoundException3, Param as Param2, Req as Req3, Res as Res2, StreamableFile, UseFilters, UseGuards as UseGuards2 } from "@nestjs/common";
1825
-
1826
- // src/server/auth/dashboard-auth-page.guard.ts
1827
- import { Inject as Inject5, Injectable as Injectable4, Optional as Optional5 } from "@nestjs/common";
1828
-
1829
- // src/server/auth/dashboard-auth-redirect.ts
1830
- import { Catch, Injectable as Injectable3 } from "@nestjs/common";
1831
- function _ts_decorate5(decorators, target, key, desc) {
1832
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1833
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1834
- r = Reflect.decorate(decorators, target, key, desc);
1835
- } else {
1836
- for (var i = decorators.length - 1; i >= 0; i--) {
1837
- if (d = decorators[i]) {
1838
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1839
- }
1840
- }
1841
- }
1842
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1843
- }
1844
- __name(_ts_decorate5, "_ts_decorate");
1845
- var DashboardAuthRedirect = class extends Error {
1846
- static {
1847
- __name(this, "DashboardAuthRedirect");
1848
- }
1849
- redirectTo;
1850
- constructor(redirectTo) {
1851
- super(`Redirect to ${redirectTo}`), this.redirectTo = redirectTo;
1852
- this.name = "DashboardAuthRedirect";
1853
- }
1854
- };
1855
- var DashboardAuthRedirectFilter = class {
1856
- static {
1857
- __name(this, "DashboardAuthRedirectFilter");
1858
- }
1859
- catch(exception, host) {
1860
- const response = host.switchToHttp().getResponse();
1861
- sendRedirect(response, 302, exception.redirectTo);
1862
- }
1863
- };
1864
- DashboardAuthRedirectFilter = _ts_decorate5([
1865
- Injectable3(),
1866
- Catch(DashboardAuthRedirect)
1867
- ], DashboardAuthRedirectFilter);
1868
-
1869
- // src/server/auth/dashboard-auth-page.guard.ts
1870
- function _ts_decorate6(decorators, target, key, desc) {
1871
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1872
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1873
- r = Reflect.decorate(decorators, target, key, desc);
1874
- } else {
1875
- for (var i = decorators.length - 1; i >= 0; i--) {
1876
- if (d = decorators[i]) {
1877
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1878
- }
1879
- }
1880
- }
1881
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1882
- }
1883
- __name(_ts_decorate6, "_ts_decorate");
1884
- function _ts_metadata5(metadataKey, metadataValue) {
1885
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1886
- return Reflect.metadata(metadataKey, metadataValue);
1887
- }
1888
- }
1889
- __name(_ts_metadata5, "_ts_metadata");
1890
- function _ts_param5(paramIndex, decorator) {
1891
- return function(target, key) {
1892
- decorator(target, key, paramIndex);
1893
- };
1894
- }
1895
- __name(_ts_param5, "_ts_param");
1896
- var DashboardAuthPageGuard = class {
1897
- static {
1898
- __name(this, "DashboardAuthPageGuard");
1899
- }
1900
- auth;
1901
- basePath;
1902
- constructor(auth, basePath) {
1903
- this.auth = auth;
1904
- this.basePath = basePath;
1905
- }
1906
- async canActivate(context) {
1907
- if (!this.auth) return true;
1908
- const auth = this.auth;
1909
- const http = context.switchToHttp();
1910
- const request = http.getRequest();
1911
- const session = this.verifyRequestSession(request);
1912
- if (!session) this.deny(auth, request);
1913
- attachSession(request, session);
1914
- if (!await maybeRenewSession(auth, session, request, http.getResponse())) {
1915
- this.deny(auth, request);
1916
- }
1917
- return true;
1918
- }
1919
- /**
1920
- * No valid session: bounce the browser navigation onward. Under Mode B (`login` configured)
1921
- * that's the built-in login screen, carrying `returnTo` back to the page that was requested.
1922
- * Under Mode-A-only there is no login screen to redirect to — the host mints the session
1923
- * itself — so this instead serves the instruction page rather than redirecting into a 404.
1924
- * Pulled out of `canActivate` so both the "no session at all" and the "revalidate revoked a
1925
- * renewable session" paths reuse the exact same mode-aware deny logic.
1926
- *
1927
- * Takes `auth` explicitly rather than reading `this.auth`: `canActivate`'s `!this.auth` early
1928
- * return narrows the field within that method only — TS doesn't carry it across a method call —
1929
- * so the caller passes the already-narrowed value instead of this method re-deriving (or
1930
- * asserting away) the nullability.
1931
- */
1932
- deny(auth, request) {
1933
- if (!auth.modes.includes("login")) {
1934
- throw new DashboardAuthRedirect(`${this.basePath}/auth/session-required`);
1935
- }
1936
- const returnTo = readOriginalUrl(request);
1937
- throw new DashboardAuthRedirect(`${this.basePath}/auth/login?returnTo=${encodeURIComponent(returnTo)}`);
1938
- }
1939
- verifyRequestSession(request) {
1940
- const auth = this.auth;
1941
- if (!auth) return null;
1942
- const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
1943
- if (cookieValue === void 0) return null;
1944
- return verifySessionCookie(cookieValue, {
1945
- secret: auth.secret
1946
- });
1947
- }
1948
- };
1949
- DashboardAuthPageGuard = _ts_decorate6([
1950
- Injectable4(),
1951
- _ts_param5(0, Optional5()),
1952
- _ts_param5(0, Inject5(DASHBOARD_AUTH)),
1953
- _ts_param5(1, Inject5(DASHBOARD_BASE_PATH)),
1954
- _ts_metadata5("design:type", Function),
1955
- _ts_metadata5("design:paramtypes", [
1956
- Object,
1957
- String
1958
- ])
1959
- ], DashboardAuthPageGuard);
1960
-
1961
- // src/server/agent-ui.controller.ts
1962
- function _ts_decorate7(decorators, target, key, desc) {
1053
+ 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
+ function _ts_decorate3(decorators, target, key, desc) {
1963
1056
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1964
1057
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
1965
1058
  r = Reflect.decorate(decorators, target, key, desc);
@@ -1972,19 +1065,19 @@ function _ts_decorate7(decorators, target, key, desc) {
1972
1065
  }
1973
1066
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1974
1067
  }
1975
- __name(_ts_decorate7, "_ts_decorate");
1976
- function _ts_metadata6(metadataKey, metadataValue) {
1068
+ __name(_ts_decorate3, "_ts_decorate");
1069
+ function _ts_metadata3(metadataKey, metadataValue) {
1977
1070
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
1978
1071
  return Reflect.metadata(metadataKey, metadataValue);
1979
1072
  }
1980
1073
  }
1981
- __name(_ts_metadata6, "_ts_metadata");
1982
- function _ts_param6(paramIndex, decorator) {
1074
+ __name(_ts_metadata3, "_ts_metadata");
1075
+ function _ts_param3(paramIndex, decorator) {
1983
1076
  return function(target, key) {
1984
1077
  decorator(target, key, paramIndex);
1985
1078
  };
1986
1079
  }
1987
- __name(_ts_param6, "_ts_param");
1080
+ __name(_ts_param3, "_ts_param");
1988
1081
  var BUILD_BASE = "/ai-gateway";
1989
1082
  function spaDir() {
1990
1083
  return fileURLToPath(new URL("../spa", import.meta.url));
@@ -2020,7 +1113,7 @@ var AgentUiController = class {
2020
1113
  }
2021
1114
  const indexPath = join(this.dir, "index.html");
2022
1115
  if (!existsSync(indexPath)) {
2023
- throw new NotFoundException3("Dashboard is not built. Run the package build.");
1116
+ throw new NotFoundException2("Dashboard is not built. Run the package build.");
2024
1117
  }
2025
1118
  const html = readFileSync(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
2026
1119
  const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>`;
@@ -2028,11 +1121,11 @@ var AgentUiController = class {
2028
1121
  }
2029
1122
  asset(file) {
2030
1123
  const safe = basename(file);
2031
- if (safe !== file) throw new NotFoundException3();
1124
+ if (safe !== file) throw new NotFoundException2();
2032
1125
  const root = resolve(this.dir, "assets");
2033
1126
  const assetPath = resolve(root, safe);
2034
1127
  if (!assetPath.startsWith(root + sep) || !existsSync(assetPath)) {
2035
- throw new NotFoundException3();
1128
+ throw new NotFoundException2();
2036
1129
  }
2037
1130
  const type = CONTENT_TYPES[extname(safe)] ?? "application/octet-stream";
2038
1131
  return new StreamableFile(readFileSync(assetPath), {
@@ -2040,143 +1133,45 @@ var AgentUiController = class {
2040
1133
  });
2041
1134
  }
2042
1135
  };
2043
- _ts_decorate7([
2044
- Get3(),
2045
- Header2("Content-Type", "text/html; charset=utf-8"),
2046
- Header2("Cache-Control", "no-store, must-revalidate"),
2047
- _ts_param6(0, Req3()),
2048
- _ts_param6(1, Res2({
1136
+ _ts_decorate3([
1137
+ Get2(),
1138
+ Header("Content-Type", "text/html; charset=utf-8"),
1139
+ Header("Cache-Control", "no-store, must-revalidate"),
1140
+ _ts_param3(0, Req2()),
1141
+ _ts_param3(1, Res({
2049
1142
  passthrough: true
2050
1143
  })),
2051
- _ts_metadata6("design:type", Function),
2052
- _ts_metadata6("design:paramtypes", [
1144
+ _ts_metadata3("design:type", Function),
1145
+ _ts_metadata3("design:paramtypes", [
2053
1146
  typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
2054
1147
  typeof UiPageResponse === "undefined" ? Object : UiPageResponse
2055
1148
  ]),
2056
- _ts_metadata6("design:returntype", String)
1149
+ _ts_metadata3("design:returntype", String)
2057
1150
  ], AgentUiController.prototype, "index", null);
2058
- _ts_decorate7([
2059
- Get3("assets/:file"),
2060
- Header2("Cache-Control", "public, max-age=31536000, immutable"),
2061
- _ts_param6(0, Param2("file")),
2062
- _ts_metadata6("design:type", Function),
2063
- _ts_metadata6("design:paramtypes", [
1151
+ _ts_decorate3([
1152
+ Get2("assets/:file"),
1153
+ 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", [
2064
1157
  String
2065
1158
  ]),
2066
- _ts_metadata6("design:returntype", typeof StreamableFile === "undefined" ? Object : StreamableFile)
1159
+ _ts_metadata3("design:returntype", typeof StreamableFile === "undefined" ? Object : StreamableFile)
2067
1160
  ], AgentUiController.prototype, "asset", null);
2068
- AgentUiController = _ts_decorate7([
2069
- Controller3(),
2070
- UseGuards2(DashboardAuthPageGuard),
2071
- UseFilters(new DashboardAuthRedirectFilter()),
2072
- _ts_param6(0, Inject6(DASHBOARD_BASE_PATH)),
2073
- _ts_param6(1, Inject6(DASHBOARD_API_PATH)),
2074
- _ts_metadata6("design:type", Function),
2075
- _ts_metadata6("design:paramtypes", [
1161
+ AgentUiController = _ts_decorate3([
1162
+ CanAnyone2(),
1163
+ 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", [
2076
1168
  String,
2077
1169
  String
2078
1170
  ])
2079
1171
  ], AgentUiController);
2080
1172
 
2081
- // src/server/auth/dashboard-auth-config.ts
2082
- var DEFAULT_TTL = "8h";
2083
- function unitToMs(unit) {
2084
- switch (unit) {
2085
- case "ms":
2086
- return 1;
2087
- case "s":
2088
- return 1e3;
2089
- case "m":
2090
- return 6e4;
2091
- case "h":
2092
- return 36e5;
2093
- case "d":
2094
- return 864e5;
2095
- default:
2096
- return void 0;
2097
- }
2098
- }
2099
- __name(unitToMs, "unitToMs");
2100
- function durationToMs(duration) {
2101
- const match = /^(\d+)(ms|s|m|h|d)$/.exec(duration.trim());
2102
- const amount = match?.[1];
2103
- const unit = match?.[2] !== void 0 ? unitToMs(match[2]) : void 0;
2104
- if (amount === void 0 || unit === void 0) {
2105
- throw new Error(`AgentDashboardModule dashboardAuth: invalid \`ttl\` duration: ${duration}`);
2106
- }
2107
- return Number(amount) * unit;
2108
- }
2109
- __name(durationToMs, "durationToMs");
2110
- function resolveDashboardAuth(options) {
2111
- if (options === void 0) return null;
2112
- if (typeof options.secret !== "string" || options.secret === "") {
2113
- throw new Error("AgentDashboardModule dashboardAuth: `secret` is required and must be a non-empty string (HMAC-SHA256 signing key, 32+ bytes recommended). Failing closed.");
2114
- }
2115
- const modes = [];
2116
- if (options.session !== void 0) {
2117
- if (typeof options.session !== "function") {
2118
- throw new Error("AgentDashboardModule dashboardAuth: `session` must be a function.");
2119
- }
2120
- modes.push("session");
2121
- }
2122
- if (options.login !== void 0) {
2123
- if (typeof options.login !== "function") {
2124
- throw new Error("AgentDashboardModule dashboardAuth: `login` must be a function.");
2125
- }
2126
- modes.push("login");
2127
- }
2128
- if (options.revalidate !== void 0 && typeof options.revalidate !== "function") {
2129
- throw new Error("AgentDashboardModule dashboardAuth: `revalidate` must be a function.");
2130
- }
2131
- if (options.unauthenticatedPage !== void 0 && typeof options.unauthenticatedPage !== "function") {
2132
- throw new Error("AgentDashboardModule dashboardAuth: `unauthenticatedPage` must be a function.");
2133
- }
2134
- if (modes.length === 0) {
2135
- throw new Error("AgentDashboardModule dashboardAuth: at least one of `session` (the host mints the session from its own auth) or `login` (the built-in login screen) is required \u2014 otherwise the cookie can never be minted. Failing closed.");
2136
- }
2137
- return {
2138
- secret: options.secret,
2139
- ttlMs: durationToMs(options.ttl ?? DEFAULT_TTL),
2140
- modes,
2141
- ...options.session !== void 0 ? {
2142
- session: options.session
2143
- } : {},
2144
- ...options.login !== void 0 ? {
2145
- login: options.login
2146
- } : {},
2147
- ...options.revalidate !== void 0 ? {
2148
- revalidate: options.revalidate
2149
- } : {},
2150
- ...options.unauthenticatedPage !== void 0 ? {
2151
- unauthenticatedPage: options.unauthenticatedPage
2152
- } : {}
2153
- };
2154
- }
2155
- __name(resolveDashboardAuth, "resolveDashboardAuth");
2156
-
2157
- // src/server/guards.ts
2158
- import "reflect-metadata";
2159
- var GUARDS_METADATA = "__guards__";
2160
- function isGuardClass(guard) {
2161
- return typeof guard === "function";
2162
- }
2163
- __name(isGuardClass, "isGuardClass");
2164
- function baseGuards(controller) {
2165
- return Reflect.getOwnMetadata(GUARDS_METADATA, controller) ?? [];
2166
- }
2167
- __name(baseGuards, "baseGuards");
2168
- function stampGuards(guards, entries) {
2169
- for (const [controller, base] of entries) {
2170
- Reflect.defineMetadata(GUARDS_METADATA, [
2171
- ...base,
2172
- ...guards ?? []
2173
- ], controller);
2174
- }
2175
- }
2176
- __name(stampGuards, "stampGuards");
2177
-
2178
1173
  // src/server/agent-dashboard.module.ts
2179
- function _ts_decorate8(decorators, target, key, desc) {
1174
+ function _ts_decorate4(decorators, target, key, desc) {
2180
1175
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2181
1176
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
2182
1177
  r = Reflect.decorate(decorators, target, key, desc);
@@ -2189,37 +1184,33 @@ function _ts_decorate8(decorators, target, key, desc) {
2189
1184
  }
2190
1185
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2191
1186
  }
2192
- __name(_ts_decorate8, "_ts_decorate");
2193
- var API_BASE_GUARDS = baseGuards(AgentApiController);
2194
- var UI_BASE_GUARDS = baseGuards(AgentUiController);
1187
+ __name(_ts_decorate4, "_ts_decorate");
2195
1188
  function normalize(path) {
2196
1189
  return normalizeDashboardPath(path);
2197
1190
  }
2198
1191
  __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.");
1197
+ }
1198
+ __name(assertProtected, "assertProtected");
2199
1199
  var AgentApiModule = class _AgentApiModule {
2200
1200
  static {
2201
1201
  __name(this, "AgentApiModule");
2202
1202
  }
2203
1203
  static register(options) {
2204
- stampGuards(options.guards, [
2205
- [
2206
- AgentApiController,
2207
- API_BASE_GUARDS
2208
- ]
2209
- ]);
2210
1204
  return {
2211
1205
  module: _AgentApiModule,
2212
1206
  imports: [
2213
1207
  ...options.imports ?? []
2214
1208
  ],
2215
- controllers: [
1209
+ controllers: options.routes === false ? [] : withControllerDecorators([
2216
1210
  AgentApiController
2217
- ],
1211
+ ], options.decorators),
2218
1212
  providers: [
2219
1213
  DashboardService,
2220
- DashboardAuthGuard,
2221
- options.dashboardAuth,
2222
- ...(options.guards ?? []).filter(isGuardClass),
2223
1214
  // `useValue` even when `options.approvalActorRef` is `undefined` — AgentApiController
2224
1215
  // injects this WITHOUT `@Optional()`.
2225
1216
  {
@@ -2227,17 +1218,15 @@ var AgentApiModule = class _AgentApiModule {
2227
1218
  useValue: options.approvalActorRef
2228
1219
  }
2229
1220
  ],
2230
- // DASHBOARD_AUTH re-exported so AgentUiController/AgentDashboardAuthController (hosted
2231
- // directly by AgentDashboardModule, which imports this module) resolve the SAME instance
2232
- // instead of re-running a host's async factory a second time.
1221
+ // What a self-mounted `AgentApiController` subclass injects, too (`routes: false`).
2233
1222
  exports: [
2234
1223
  DashboardService,
2235
- DASHBOARD_AUTH
1224
+ DASHBOARD_APPROVAL_ACTOR_REF
2236
1225
  ]
2237
1226
  };
2238
1227
  }
2239
1228
  };
2240
- AgentApiModule = _ts_decorate8([
1229
+ AgentApiModule = _ts_decorate4([
2241
1230
  Module({})
2242
1231
  ], AgentApiModule);
2243
1232
  var AgentDashboardModule = class _AgentDashboardModule {
@@ -2245,116 +1234,44 @@ var AgentDashboardModule = class _AgentDashboardModule {
2245
1234
  __name(this, "AgentDashboardModule");
2246
1235
  }
2247
1236
  static forRoot(options = {}) {
1237
+ assertProtected(options);
2248
1238
  const basePath = normalize(options.basePath ?? "/ai-gateway");
2249
1239
  const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
2250
- stampGuards(options.guards, [
2251
- [
2252
- AgentUiController,
2253
- UI_BASE_GUARDS
2254
- ]
2255
- ]);
2256
- const dashboardAuthProvider = {
2257
- provide: DASHBOARD_AUTH,
2258
- useValue: resolveDashboardAuth(options.dashboardAuth)
2259
- };
2260
1240
  return {
2261
1241
  module: _AgentDashboardModule,
2262
1242
  imports: [
2263
1243
  ...options.imports ?? [],
2264
- // Guards + host imports must reach the API controller's HOST module — enhancers resolve
2265
- // from their controller's own module, never from a parent (see AgentApiModule.register).
2266
1244
  // Spread-only-when-set: exactOptionalPropertyTypes rejects an explicit `undefined`.
2267
1245
  AgentApiModule.register({
2268
1246
  ...options.imports ? {
2269
1247
  imports: options.imports
2270
1248
  } : {},
2271
- ...options.guards ? {
2272
- guards: options.guards
1249
+ ...options.decorators ? {
1250
+ decorators: options.decorators
2273
1251
  } : {},
2274
- ...options.approvalActorRef ? {
2275
- approvalActorRef: options.approvalActorRef
2276
- } : {},
2277
- dashboardAuth: dashboardAuthProvider
2278
- }),
2279
- RouterModule.register([
2280
- {
2281
- path: basePath,
2282
- module: _AgentDashboardModule
2283
- },
2284
- {
2285
- path: apiBasePath,
2286
- module: AgentApiModule
2287
- }
2288
- ])
2289
- ],
2290
- controllers: [
2291
- AgentUiController,
2292
- AgentDashboardAuthController
2293
- ],
2294
- providers: [
2295
- {
2296
- provide: DASHBOARD_BASE_PATH,
2297
- useValue: basePath
2298
- },
2299
- {
2300
- provide: DASHBOARD_API_PATH,
2301
- useValue: apiBasePath
2302
- },
2303
- DashboardAuthPageGuard,
2304
- // AgentUiController is hosted HERE, so its guards DI-instantiate from this module.
2305
- ...(options.guards ?? []).filter(isGuardClass)
2306
- ],
2307
- // Re-export the API module so its DashboardService reaches importers (e.g. the host's own controllers).
2308
- exports: [
2309
- AgentApiModule
2310
- ]
2311
- };
2312
- }
2313
- static forRootAsync(options) {
2314
- const basePath = normalize(options.basePath ?? "/ai-gateway");
2315
- const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
2316
- stampGuards(options.guards, [
2317
- [
2318
- AgentUiController,
2319
- UI_BASE_GUARDS
2320
- ]
2321
- ]);
2322
- const dashboardAuthProvider = {
2323
- provide: DASHBOARD_AUTH,
2324
- inject: options.inject ?? [],
2325
- useFactory: /* @__PURE__ */ __name(async (...deps) => resolveDashboardAuth(await options.useDashboardAuth(...deps)), "useFactory")
2326
- };
2327
- return {
2328
- module: _AgentDashboardModule,
2329
- imports: [
2330
- ...options.imports ?? [],
2331
- AgentApiModule.register({
2332
- ...options.imports ? {
2333
- imports: options.imports
2334
- } : {},
2335
- ...options.guards ? {
2336
- guards: options.guards
1252
+ ...options.routes === false ? {
1253
+ routes: false
2337
1254
  } : {},
2338
1255
  ...options.approvalActorRef ? {
2339
1256
  approvalActorRef: options.approvalActorRef
2340
- } : {},
2341
- dashboardAuth: dashboardAuthProvider
1257
+ } : {}
2342
1258
  }),
2343
- RouterModule.register([
2344
- {
2345
- path: basePath,
2346
- module: _AgentDashboardModule
2347
- },
2348
- {
2349
- path: apiBasePath,
2350
- module: AgentApiModule
2351
- }
2352
- ])
2353
- ],
2354
- controllers: [
2355
- AgentUiController,
2356
- AgentDashboardAuthController
1259
+ ...options.routes === false ? [] : [
1260
+ RouterModule.register([
1261
+ {
1262
+ path: basePath,
1263
+ module: _AgentDashboardModule
1264
+ },
1265
+ {
1266
+ path: apiBasePath,
1267
+ module: AgentApiModule
1268
+ }
1269
+ ])
1270
+ ]
2357
1271
  ],
1272
+ controllers: options.routes === false ? [] : withControllerDecorators([
1273
+ AgentUiController
1274
+ ], options.decorators),
2358
1275
  providers: [
2359
1276
  {
2360
1277
  provide: DASHBOARD_BASE_PATH,
@@ -2363,17 +1280,19 @@ var AgentDashboardModule = class _AgentDashboardModule {
2363
1280
  {
2364
1281
  provide: DASHBOARD_API_PATH,
2365
1282
  useValue: apiBasePath
2366
- },
2367
- DashboardAuthPageGuard,
2368
- ...(options.guards ?? []).filter(isGuardClass)
1283
+ }
2369
1284
  ],
1285
+ // Re-export the API module so its DashboardService reaches importers (e.g. the host's own
1286
+ // controllers), and the paths a self-mounted `AgentUiController` subclass injects.
2370
1287
  exports: [
2371
- AgentApiModule
1288
+ AgentApiModule,
1289
+ DASHBOARD_BASE_PATH,
1290
+ DASHBOARD_API_PATH
2372
1291
  ]
2373
1292
  };
2374
1293
  }
2375
1294
  };
2376
- AgentDashboardModule = _ts_decorate8([
1295
+ AgentDashboardModule = _ts_decorate4([
2377
1296
  Module({})
2378
1297
  ], AgentDashboardModule);
2379
1298
  export {
@@ -2384,16 +1303,13 @@ export {
2384
1303
  AGENT_PRICING_STORE,
2385
1304
  AgentApiController,
2386
1305
  AgentApiModule,
2387
- AgentDashboardAuthController,
2388
1306
  AgentDashboardModule,
2389
1307
  AgentUiController,
2390
1308
  DASHBOARD_API_PATH,
2391
1309
  DASHBOARD_APPROVAL_ACTOR_REF,
2392
- DASHBOARD_AUTH,
2393
1310
  DASHBOARD_BASE_PATH,
2394
1311
  DashboardService,
2395
1312
  agentDashboardMountPaths,
2396
- parsePriceInput,
2397
- resolveDashboardAuth
1313
+ parsePriceInput
2398
1314
  };
2399
1315
  //# sourceMappingURL=index.js.map