@dudousxd/nestjs-agent-dashboard 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -2
- package/dist/server/index.cjs +1119 -217
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +149 -8
- package/dist/server/index.d.ts +149 -8
- package/dist/server/index.js +1076 -177
- package/dist/server/index.js.map +1 -1
- package/package.json +6 -2
package/dist/server/index.js
CHANGED
|
@@ -2,12 +2,348 @@ 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
|
|
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 = Symbol.for("@dudousxd/nestjs-agent:governance-queries");
|
|
12
|
+
var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
|
|
13
|
+
var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
|
|
14
|
+
var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
|
|
15
|
+
var AGENT_ACTOR_RESOLVER = Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
|
|
16
|
+
var DASHBOARD_BASE_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
|
|
17
|
+
var DASHBOARD_API_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
|
|
18
|
+
var DASHBOARD_APPROVAL_ACTOR_REF = Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
|
|
19
|
+
var DASHBOARD_AUTH = 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 sendRedirect(response, status, location) {
|
|
151
|
+
const raw = resolveRawResponse(response);
|
|
152
|
+
if (!raw) return;
|
|
153
|
+
raw.statusCode = status;
|
|
154
|
+
raw.setHeader("location", location);
|
|
155
|
+
raw.end();
|
|
156
|
+
}
|
|
157
|
+
__name(sendRedirect, "sendRedirect");
|
|
158
|
+
|
|
159
|
+
// src/server/auth/session-cookie.ts
|
|
160
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
161
|
+
var EXP_GRACE_MS = 3e4;
|
|
162
|
+
function base64urlEncode(value) {
|
|
163
|
+
return Buffer.from(value, "utf8").toString("base64url");
|
|
164
|
+
}
|
|
165
|
+
__name(base64urlEncode, "base64urlEncode");
|
|
166
|
+
function base64urlDecode(value) {
|
|
167
|
+
return Buffer.from(value, "base64url").toString("utf8");
|
|
168
|
+
}
|
|
169
|
+
__name(base64urlDecode, "base64urlDecode");
|
|
170
|
+
function hmac(secret, payload) {
|
|
171
|
+
return createHmac("sha256", secret).update(payload).digest("base64url");
|
|
172
|
+
}
|
|
173
|
+
__name(hmac, "hmac");
|
|
174
|
+
function signSessionCookie(user, options) {
|
|
175
|
+
const issuedAt = options.now ?? Date.now();
|
|
176
|
+
const session = {
|
|
177
|
+
sub: user.id,
|
|
178
|
+
...user.name !== void 0 ? {
|
|
179
|
+
name: user.name
|
|
180
|
+
} : {},
|
|
181
|
+
roles: user.roles ?? [],
|
|
182
|
+
iat: issuedAt,
|
|
183
|
+
exp: issuedAt + options.ttlMs
|
|
184
|
+
};
|
|
185
|
+
const encodedPayload = base64urlEncode(JSON.stringify(session));
|
|
186
|
+
const signature = hmac(options.secret, encodedPayload);
|
|
187
|
+
return `${encodedPayload}.${signature}`;
|
|
188
|
+
}
|
|
189
|
+
__name(signSessionCookie, "signSessionCookie");
|
|
190
|
+
function isSessionPayload(value) {
|
|
191
|
+
if (typeof value !== "object" || value === null) return false;
|
|
192
|
+
const record = {
|
|
193
|
+
...value
|
|
194
|
+
};
|
|
195
|
+
if (typeof record.sub !== "string") return false;
|
|
196
|
+
if (record.name !== void 0 && typeof record.name !== "string") return false;
|
|
197
|
+
if (!Array.isArray(record.roles)) return false;
|
|
198
|
+
if (!record.roles.every((role) => typeof role === "string")) return false;
|
|
199
|
+
if (typeof record.iat !== "number" || !Number.isFinite(record.iat)) return false;
|
|
200
|
+
if (typeof record.exp !== "number" || !Number.isFinite(record.exp)) return false;
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
__name(isSessionPayload, "isSessionPayload");
|
|
204
|
+
function verifySessionCookie(value, options) {
|
|
205
|
+
try {
|
|
206
|
+
const dot = value.indexOf(".");
|
|
207
|
+
if (dot <= 0 || dot === value.length - 1) return null;
|
|
208
|
+
const encodedPayload = value.slice(0, dot);
|
|
209
|
+
const providedSignature = value.slice(dot + 1);
|
|
210
|
+
const expectedSignature = hmac(options.secret, encodedPayload);
|
|
211
|
+
const provided = Buffer.from(providedSignature, "base64url");
|
|
212
|
+
const expected = Buffer.from(expectedSignature, "base64url");
|
|
213
|
+
if (provided.length !== expected.length) return null;
|
|
214
|
+
if (!timingSafeEqual(provided, expected)) return null;
|
|
215
|
+
const decoded = JSON.parse(base64urlDecode(encodedPayload));
|
|
216
|
+
if (!isSessionPayload(decoded)) return null;
|
|
217
|
+
const now = options.now ?? Date.now();
|
|
218
|
+
if (now > decoded.exp + EXP_GRACE_MS) return null;
|
|
219
|
+
const session = {
|
|
220
|
+
sub: decoded.sub,
|
|
221
|
+
...decoded.name !== void 0 ? {
|
|
222
|
+
name: decoded.name
|
|
223
|
+
} : {},
|
|
224
|
+
roles: decoded.roles,
|
|
225
|
+
iat: decoded.iat,
|
|
226
|
+
exp: decoded.exp
|
|
227
|
+
};
|
|
228
|
+
return session;
|
|
229
|
+
} catch {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
__name(verifySessionCookie, "verifySessionCookie");
|
|
234
|
+
|
|
235
|
+
// src/server/auth/session-cookie-io.ts
|
|
236
|
+
var SESSION_COOKIE_NAME = "agent_dashboard_session";
|
|
237
|
+
var COOKIE_PATH = "/";
|
|
238
|
+
function issueSessionCookie(user, context) {
|
|
239
|
+
const value = signSessionCookie(user, {
|
|
240
|
+
secret: context.auth.secret,
|
|
241
|
+
ttlMs: context.auth.ttlMs,
|
|
242
|
+
...context.now !== void 0 ? {
|
|
243
|
+
now: context.now
|
|
244
|
+
} : {}
|
|
245
|
+
});
|
|
246
|
+
const cookie = serializeSetCookie(SESSION_COOKIE_NAME, value, {
|
|
247
|
+
path: COOKIE_PATH,
|
|
248
|
+
maxAgeSeconds: Math.floor(context.auth.ttlMs / 1e3),
|
|
249
|
+
secure: isHttpsRequest(context.request)
|
|
250
|
+
});
|
|
251
|
+
appendSetCookie(context.response, cookie);
|
|
252
|
+
}
|
|
253
|
+
__name(issueSessionCookie, "issueSessionCookie");
|
|
254
|
+
function clearSessionCookie(context) {
|
|
255
|
+
const cookie = serializeSetCookie(SESSION_COOKIE_NAME, "", {
|
|
256
|
+
path: COOKIE_PATH,
|
|
257
|
+
maxAgeSeconds: 0,
|
|
258
|
+
secure: isHttpsRequest(context.request),
|
|
259
|
+
clear: true
|
|
260
|
+
});
|
|
261
|
+
appendSetCookie(context.response, cookie);
|
|
262
|
+
}
|
|
263
|
+
__name(clearSessionCookie, "clearSessionCookie");
|
|
264
|
+
|
|
265
|
+
// src/server/auth/dashboard-auth.guard.ts
|
|
266
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
267
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
268
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
269
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
270
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
271
|
+
}
|
|
272
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
273
|
+
function _ts_metadata(k, v) {
|
|
274
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
275
|
+
}
|
|
276
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
277
|
+
function _ts_param(paramIndex, decorator) {
|
|
278
|
+
return function(target, key) {
|
|
279
|
+
decorator(target, key, paramIndex);
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
__name(_ts_param, "_ts_param");
|
|
283
|
+
var DashboardAuthGuard = class {
|
|
284
|
+
static {
|
|
285
|
+
__name(this, "DashboardAuthGuard");
|
|
286
|
+
}
|
|
287
|
+
auth;
|
|
288
|
+
constructor(auth) {
|
|
289
|
+
this.auth = auth;
|
|
290
|
+
}
|
|
291
|
+
canActivate(context) {
|
|
292
|
+
if (!this.auth) return true;
|
|
293
|
+
const http = context.switchToHttp();
|
|
294
|
+
const request = http.getRequest();
|
|
295
|
+
const session = this.verifyRequestSession(request);
|
|
296
|
+
if (!session) throw new UnauthorizedException();
|
|
297
|
+
attachSession(request, session);
|
|
298
|
+
this.maybeRenew(http.getResponse(), request, session);
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
verifyRequestSession(request) {
|
|
302
|
+
const auth = this.auth;
|
|
303
|
+
if (!auth) return null;
|
|
304
|
+
const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
|
|
305
|
+
if (cookieValue === void 0) return null;
|
|
306
|
+
return verifySessionCookie(cookieValue, {
|
|
307
|
+
secret: auth.secret
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Sliding renewal: a valid cookie past 50% of its TTL is transparently re-issued on the
|
|
312
|
+
* response, so an active user never gets logged out mid-session.
|
|
313
|
+
*/
|
|
314
|
+
maybeRenew(response, request, session) {
|
|
315
|
+
const auth = this.auth;
|
|
316
|
+
if (!auth) return;
|
|
317
|
+
const now = Date.now();
|
|
318
|
+
if (now - session.iat <= auth.ttlMs / 2) return;
|
|
319
|
+
issueSessionCookie({
|
|
320
|
+
id: session.sub,
|
|
321
|
+
...session.name !== void 0 ? {
|
|
322
|
+
name: session.name
|
|
323
|
+
} : {},
|
|
324
|
+
roles: session.roles
|
|
325
|
+
}, {
|
|
326
|
+
auth,
|
|
327
|
+
request,
|
|
328
|
+
response,
|
|
329
|
+
now
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
DashboardAuthGuard = _ts_decorate([
|
|
334
|
+
Injectable(),
|
|
335
|
+
_ts_param(0, Optional()),
|
|
336
|
+
_ts_param(0, Inject(DASHBOARD_AUTH)),
|
|
337
|
+
_ts_metadata("design:type", Function),
|
|
338
|
+
_ts_metadata("design:paramtypes", [
|
|
339
|
+
Object
|
|
340
|
+
])
|
|
341
|
+
], DashboardAuthGuard);
|
|
6
342
|
|
|
7
343
|
// src/server/dashboard.service.ts
|
|
8
344
|
import { subscribe, unsubscribe } from "node:diagnostics_channel";
|
|
9
345
|
import { channelName } from "@dudousxd/nestjs-diagnostics";
|
|
10
|
-
import { Inject, Injectable, NotImplementedException, Optional } from "@nestjs/common";
|
|
346
|
+
import { Inject as Inject2, Injectable as Injectable2, NotImplementedException, Optional as Optional2 } from "@nestjs/common";
|
|
11
347
|
import { Observable as Observable2 } from "rxjs";
|
|
12
348
|
|
|
13
349
|
// src/server/parse-approval-decision.ts
|
|
@@ -72,34 +408,24 @@ function isFiniteNonNegative(value) {
|
|
|
72
408
|
}
|
|
73
409
|
__name(isFiniteNonNegative, "isFiniteNonNegative");
|
|
74
410
|
|
|
75
|
-
// src/server/tokens.ts
|
|
76
|
-
var AGENT_GOVERNANCE_QUERIES = Symbol.for("@dudousxd/nestjs-agent:governance-queries");
|
|
77
|
-
var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
|
|
78
|
-
var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
|
|
79
|
-
var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
|
|
80
|
-
var AGENT_ACTOR_RESOLVER = Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
|
|
81
|
-
var DASHBOARD_BASE_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
|
|
82
|
-
var DASHBOARD_API_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
|
|
83
|
-
var DASHBOARD_APPROVAL_ACTOR_REF = Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
|
|
84
|
-
|
|
85
411
|
// src/server/dashboard.service.ts
|
|
86
|
-
function
|
|
412
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
87
413
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
88
414
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
89
415
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
90
416
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
91
417
|
}
|
|
92
|
-
__name(
|
|
93
|
-
function
|
|
418
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
419
|
+
function _ts_metadata2(k, v) {
|
|
94
420
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
95
421
|
}
|
|
96
|
-
__name(
|
|
97
|
-
function
|
|
422
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
423
|
+
function _ts_param2(paramIndex, decorator) {
|
|
98
424
|
return function(target, key) {
|
|
99
425
|
decorator(target, key, paramIndex);
|
|
100
426
|
};
|
|
101
427
|
}
|
|
102
|
-
__name(
|
|
428
|
+
__name(_ts_param2, "_ts_param");
|
|
103
429
|
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.";
|
|
104
430
|
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.";
|
|
105
431
|
var AGENT_EVENTS = [
|
|
@@ -303,17 +629,17 @@ var DashboardService = class {
|
|
|
303
629
|
});
|
|
304
630
|
}
|
|
305
631
|
};
|
|
306
|
-
DashboardService =
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
632
|
+
DashboardService = _ts_decorate2([
|
|
633
|
+
Injectable2(),
|
|
634
|
+
_ts_param2(0, Inject2(AGENT_GOVERNANCE_QUERIES)),
|
|
635
|
+
_ts_param2(1, Optional2()),
|
|
636
|
+
_ts_param2(1, Inject2(AGENT_ACTOR_DIRECTORY)),
|
|
637
|
+
_ts_param2(2, Optional2()),
|
|
638
|
+
_ts_param2(2, Inject2(AGENT_PRICING_STORE)),
|
|
639
|
+
_ts_param2(3, Optional2()),
|
|
640
|
+
_ts_param2(3, Inject2(AGENT_APPROVAL_PORT)),
|
|
641
|
+
_ts_metadata2("design:type", Function),
|
|
642
|
+
_ts_metadata2("design:paramtypes", [
|
|
317
643
|
typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries,
|
|
318
644
|
typeof ActorDirectory === "undefined" ? Object : ActorDirectory,
|
|
319
645
|
typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
|
|
@@ -443,23 +769,23 @@ function parseRunWhere(raw) {
|
|
|
443
769
|
__name(parseRunWhere, "parseRunWhere");
|
|
444
770
|
|
|
445
771
|
// src/server/agent-api.controller.ts
|
|
446
|
-
function
|
|
772
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
447
773
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
448
774
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
449
775
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
450
776
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
451
777
|
}
|
|
452
|
-
__name(
|
|
453
|
-
function
|
|
778
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
779
|
+
function _ts_metadata3(k, v) {
|
|
454
780
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
455
781
|
}
|
|
456
|
-
__name(
|
|
457
|
-
function
|
|
782
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
783
|
+
function _ts_param3(paramIndex, decorator) {
|
|
458
784
|
return function(target, key) {
|
|
459
785
|
decorator(target, key, paramIndex);
|
|
460
786
|
};
|
|
461
787
|
}
|
|
462
|
-
__name(
|
|
788
|
+
__name(_ts_param3, "_ts_param");
|
|
463
789
|
var DAY_MS = 864e5;
|
|
464
790
|
var ISO_DAY2 = /^\d{4}-\d{2}-\d{2}$/;
|
|
465
791
|
function utcDay(daysAgo) {
|
|
@@ -620,175 +946,473 @@ var AgentApiController = class {
|
|
|
620
946
|
return this.dashboard.streamEvents();
|
|
621
947
|
}
|
|
622
948
|
};
|
|
623
|
-
|
|
949
|
+
_ts_decorate3([
|
|
624
950
|
Get("spend"),
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
951
|
+
_ts_param3(0, Query("from")),
|
|
952
|
+
_ts_param3(1, Query("to")),
|
|
953
|
+
_ts_metadata3("design:type", Function),
|
|
954
|
+
_ts_metadata3("design:paramtypes", [
|
|
629
955
|
String,
|
|
630
956
|
String
|
|
631
957
|
]),
|
|
632
|
-
|
|
958
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
633
959
|
], AgentApiController.prototype, "spend", null);
|
|
634
|
-
|
|
960
|
+
_ts_decorate3([
|
|
635
961
|
Get("top-threads"),
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
962
|
+
_ts_param3(0, Query("from")),
|
|
963
|
+
_ts_param3(1, Query("to")),
|
|
964
|
+
_ts_param3(2, Query("limit")),
|
|
965
|
+
_ts_metadata3("design:type", Function),
|
|
966
|
+
_ts_metadata3("design:paramtypes", [
|
|
641
967
|
String,
|
|
642
968
|
String,
|
|
643
969
|
String
|
|
644
970
|
]),
|
|
645
|
-
|
|
971
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
646
972
|
], AgentApiController.prototype, "topThreads", null);
|
|
647
|
-
|
|
973
|
+
_ts_decorate3([
|
|
648
974
|
Get("reliability"),
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
975
|
+
_ts_param3(0, Query("from")),
|
|
976
|
+
_ts_param3(1, Query("to")),
|
|
977
|
+
_ts_metadata3("design:type", Function),
|
|
978
|
+
_ts_metadata3("design:paramtypes", [
|
|
653
979
|
String,
|
|
654
980
|
String
|
|
655
981
|
]),
|
|
656
|
-
|
|
982
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
657
983
|
], AgentApiController.prototype, "reliability", null);
|
|
658
|
-
|
|
984
|
+
_ts_decorate3([
|
|
659
985
|
Get("runs"),
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
986
|
+
_ts_param3(0, Query("limit")),
|
|
987
|
+
_ts_metadata3("design:type", Function),
|
|
988
|
+
_ts_metadata3("design:paramtypes", [
|
|
663
989
|
String
|
|
664
990
|
]),
|
|
665
|
-
|
|
991
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
666
992
|
], AgentApiController.prototype, "runs", null);
|
|
667
|
-
|
|
993
|
+
_ts_decorate3([
|
|
668
994
|
Get("runs-page"),
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
995
|
+
_ts_param3(0, Query("page")),
|
|
996
|
+
_ts_param3(1, Query("limit")),
|
|
997
|
+
_ts_param3(2, Query("where")),
|
|
998
|
+
_ts_metadata3("design:type", Function),
|
|
999
|
+
_ts_metadata3("design:paramtypes", [
|
|
674
1000
|
String,
|
|
675
1001
|
String,
|
|
676
1002
|
typeof Record === "undefined" ? Object : Record
|
|
677
1003
|
]),
|
|
678
|
-
|
|
1004
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
679
1005
|
], AgentApiController.prototype, "runsPage", null);
|
|
680
|
-
|
|
1006
|
+
_ts_decorate3([
|
|
681
1007
|
Get("tool-calls"),
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
1008
|
+
_ts_param3(0, Query("limit")),
|
|
1009
|
+
_ts_metadata3("design:type", Function),
|
|
1010
|
+
_ts_metadata3("design:paramtypes", [
|
|
685
1011
|
String
|
|
686
1012
|
]),
|
|
687
|
-
|
|
1013
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
688
1014
|
], AgentApiController.prototype, "toolCalls", null);
|
|
689
|
-
|
|
1015
|
+
_ts_decorate3([
|
|
690
1016
|
Get("tool-calls-page"),
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
1017
|
+
_ts_param3(0, Query("page")),
|
|
1018
|
+
_ts_param3(1, Query("limit")),
|
|
1019
|
+
_ts_param3(2, Query("where")),
|
|
1020
|
+
_ts_metadata3("design:type", Function),
|
|
1021
|
+
_ts_metadata3("design:paramtypes", [
|
|
696
1022
|
String,
|
|
697
1023
|
String,
|
|
698
1024
|
typeof Record === "undefined" ? Object : Record
|
|
699
1025
|
]),
|
|
700
|
-
|
|
1026
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
701
1027
|
], AgentApiController.prototype, "toolCallsPage", null);
|
|
702
|
-
|
|
1028
|
+
_ts_decorate3([
|
|
703
1029
|
Get("approvals"),
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1030
|
+
_ts_param3(0, Query("limit")),
|
|
1031
|
+
_ts_metadata3("design:type", Function),
|
|
1032
|
+
_ts_metadata3("design:paramtypes", [
|
|
707
1033
|
String
|
|
708
1034
|
]),
|
|
709
|
-
|
|
1035
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
710
1036
|
], AgentApiController.prototype, "approvals", null);
|
|
711
|
-
|
|
1037
|
+
_ts_decorate3([
|
|
712
1038
|
Post("approvals/:toolCallId"),
|
|
713
1039
|
HttpCode(204),
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
1040
|
+
_ts_param3(0, Param("toolCallId")),
|
|
1041
|
+
_ts_param3(1, Body()),
|
|
1042
|
+
_ts_param3(2, Req()),
|
|
1043
|
+
_ts_metadata3("design:type", Function),
|
|
1044
|
+
_ts_metadata3("design:paramtypes", [
|
|
719
1045
|
String,
|
|
720
1046
|
Object,
|
|
721
1047
|
Object
|
|
722
1048
|
]),
|
|
723
|
-
|
|
1049
|
+
_ts_metadata3("design:returntype", Promise)
|
|
724
1050
|
], AgentApiController.prototype, "decideApproval", null);
|
|
725
|
-
|
|
1051
|
+
_ts_decorate3([
|
|
726
1052
|
Get("tools"),
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
1053
|
+
_ts_param3(0, Query("from")),
|
|
1054
|
+
_ts_param3(1, Query("to")),
|
|
1055
|
+
_ts_metadata3("design:type", Function),
|
|
1056
|
+
_ts_metadata3("design:paramtypes", [
|
|
731
1057
|
String,
|
|
732
1058
|
String
|
|
733
1059
|
]),
|
|
734
|
-
|
|
1060
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
735
1061
|
], AgentApiController.prototype, "tools", null);
|
|
736
|
-
|
|
1062
|
+
_ts_decorate3([
|
|
737
1063
|
Get("threads"),
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
1064
|
+
_ts_param3(0, Query("limit")),
|
|
1065
|
+
_ts_metadata3("design:type", Function),
|
|
1066
|
+
_ts_metadata3("design:paramtypes", [
|
|
741
1067
|
String
|
|
742
1068
|
]),
|
|
743
|
-
|
|
1069
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
744
1070
|
], AgentApiController.prototype, "threads", null);
|
|
745
|
-
|
|
1071
|
+
_ts_decorate3([
|
|
746
1072
|
Get("threads-page"),
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1073
|
+
_ts_param3(0, Query("page")),
|
|
1074
|
+
_ts_param3(1, Query("limit")),
|
|
1075
|
+
_ts_param3(2, Query("where")),
|
|
1076
|
+
_ts_metadata3("design:type", Function),
|
|
1077
|
+
_ts_metadata3("design:paramtypes", [
|
|
752
1078
|
String,
|
|
753
1079
|
String,
|
|
754
1080
|
typeof Record === "undefined" ? Object : Record
|
|
755
1081
|
]),
|
|
756
|
-
|
|
1082
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
757
1083
|
], AgentApiController.prototype, "threadsPage", null);
|
|
758
|
-
|
|
1084
|
+
_ts_decorate3([
|
|
759
1085
|
Get("pricing"),
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1086
|
+
_ts_metadata3("design:type", Function),
|
|
1087
|
+
_ts_metadata3("design:paramtypes", []),
|
|
1088
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
763
1089
|
], AgentApiController.prototype, "listPrices", null);
|
|
764
|
-
|
|
1090
|
+
_ts_decorate3([
|
|
765
1091
|
Post("pricing"),
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
1092
|
+
_ts_param3(0, Body()),
|
|
1093
|
+
_ts_metadata3("design:type", Function),
|
|
1094
|
+
_ts_metadata3("design:paramtypes", [
|
|
769
1095
|
Object
|
|
770
1096
|
]),
|
|
771
|
-
|
|
1097
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
772
1098
|
], AgentApiController.prototype, "upsertPrice", null);
|
|
773
|
-
|
|
1099
|
+
_ts_decorate3([
|
|
774
1100
|
Sse("stream"),
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1101
|
+
_ts_metadata3("design:type", Function),
|
|
1102
|
+
_ts_metadata3("design:paramtypes", []),
|
|
1103
|
+
_ts_metadata3("design:returntype", typeof Observable === "undefined" ? Object : Observable)
|
|
778
1104
|
], AgentApiController.prototype, "stream", null);
|
|
779
|
-
AgentApiController =
|
|
1105
|
+
AgentApiController = _ts_decorate3([
|
|
780
1106
|
Controller(),
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1107
|
+
UseGuards(DashboardAuthGuard),
|
|
1108
|
+
_ts_param3(1, Inject3(DASHBOARD_APPROVAL_ACTOR_REF)),
|
|
1109
|
+
_ts_param3(2, Optional3()),
|
|
1110
|
+
_ts_param3(2, Inject3(AGENT_ACTOR_RESOLVER)),
|
|
1111
|
+
_ts_metadata3("design:type", Function),
|
|
1112
|
+
_ts_metadata3("design:paramtypes", [
|
|
786
1113
|
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
787
1114
|
Object,
|
|
788
1115
|
typeof ActorResolver === "undefined" ? Object : ActorResolver
|
|
789
1116
|
])
|
|
790
1117
|
], AgentApiController);
|
|
791
1118
|
|
|
1119
|
+
// src/server/agent-dashboard-auth.controller.ts
|
|
1120
|
+
import { Body as Body2, Controller as Controller2, Get as Get2, Header, Inject as Inject4, Logger, NotFoundException, Optional as Optional4, Post as Post2, Query as Query2, Req as Req2, Res } from "@nestjs/common";
|
|
1121
|
+
|
|
1122
|
+
// src/server/auth/login-page.ts
|
|
1123
|
+
function escapeHtml(value) {
|
|
1124
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1125
|
+
}
|
|
1126
|
+
__name(escapeHtml, "escapeHtml");
|
|
1127
|
+
function renderLoginPage(options) {
|
|
1128
|
+
const action = escapeHtml(options.actionUrl);
|
|
1129
|
+
const returnTo = escapeHtml(options.returnTo);
|
|
1130
|
+
const errorBanner = options.error === true ? '<p role="alert" class="error">Invalid username or password.</p>' : "";
|
|
1131
|
+
return `<!doctype html>
|
|
1132
|
+
<html lang="en">
|
|
1133
|
+
<head>
|
|
1134
|
+
<meta charset="utf-8" />
|
|
1135
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1136
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
1137
|
+
<title>Sign in \u2014 AI Gateway</title>
|
|
1138
|
+
<style>
|
|
1139
|
+
:root { color-scheme: dark; }
|
|
1140
|
+
* { box-sizing: border-box; }
|
|
1141
|
+
body {
|
|
1142
|
+
margin: 0;
|
|
1143
|
+
min-height: 100vh;
|
|
1144
|
+
display: flex;
|
|
1145
|
+
align-items: center;
|
|
1146
|
+
justify-content: center;
|
|
1147
|
+
background: #09090b;
|
|
1148
|
+
color: #e4e4e7;
|
|
1149
|
+
font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1150
|
+
padding: 16px;
|
|
1151
|
+
}
|
|
1152
|
+
.card {
|
|
1153
|
+
width: 100%;
|
|
1154
|
+
max-width: 384px;
|
|
1155
|
+
border: 1px solid #27272a;
|
|
1156
|
+
background: #18181b;
|
|
1157
|
+
border-radius: 8px;
|
|
1158
|
+
padding: 32px;
|
|
1159
|
+
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
|
|
1160
|
+
}
|
|
1161
|
+
.brand {
|
|
1162
|
+
margin: 0 0 24px;
|
|
1163
|
+
text-align: center;
|
|
1164
|
+
font-size: 18px;
|
|
1165
|
+
font-weight: 600;
|
|
1166
|
+
color: #34d399;
|
|
1167
|
+
}
|
|
1168
|
+
form { display: flex; flex-direction: column; gap: 16px; }
|
|
1169
|
+
label { display: flex; flex-direction: column; gap: 6px; }
|
|
1170
|
+
.field-label {
|
|
1171
|
+
font-size: 11px;
|
|
1172
|
+
text-transform: uppercase;
|
|
1173
|
+
letter-spacing: 0.05em;
|
|
1174
|
+
color: #71717a;
|
|
1175
|
+
}
|
|
1176
|
+
input {
|
|
1177
|
+
border-radius: 4px;
|
|
1178
|
+
border: 1px solid #3f3f46;
|
|
1179
|
+
background: #09090b;
|
|
1180
|
+
color: #f4f4f5;
|
|
1181
|
+
padding: 8px 12px;
|
|
1182
|
+
font: inherit;
|
|
1183
|
+
outline: none;
|
|
1184
|
+
}
|
|
1185
|
+
input:focus { border-color: rgb(52 211 153 / 0.6); }
|
|
1186
|
+
.error { margin: 0; font-size: 12px; color: #fb7185; }
|
|
1187
|
+
button {
|
|
1188
|
+
margin-top: 8px;
|
|
1189
|
+
border-radius: 4px;
|
|
1190
|
+
border: 1px solid rgb(52 211 153 / 0.4);
|
|
1191
|
+
background: rgb(52 211 153 / 0.1);
|
|
1192
|
+
color: #6ee7b7;
|
|
1193
|
+
padding: 8px 12px;
|
|
1194
|
+
font: inherit;
|
|
1195
|
+
font-size: 12px;
|
|
1196
|
+
font-weight: 500;
|
|
1197
|
+
text-transform: uppercase;
|
|
1198
|
+
letter-spacing: 0.05em;
|
|
1199
|
+
cursor: pointer;
|
|
1200
|
+
}
|
|
1201
|
+
button:hover { background: rgb(52 211 153 / 0.2); }
|
|
1202
|
+
</style>
|
|
1203
|
+
</head>
|
|
1204
|
+
<body>
|
|
1205
|
+
<div class="card">
|
|
1206
|
+
<p class="brand">AI Gateway</p>
|
|
1207
|
+
<form method="post" action="${action}">
|
|
1208
|
+
<input type="hidden" name="returnTo" value="${returnTo}" />
|
|
1209
|
+
<label>
|
|
1210
|
+
<span class="field-label">Username</span>
|
|
1211
|
+
<input type="text" name="username" autocomplete="username" autofocus />
|
|
1212
|
+
</label>
|
|
1213
|
+
<label>
|
|
1214
|
+
<span class="field-label">Password</span>
|
|
1215
|
+
<input type="password" name="password" autocomplete="current-password" />
|
|
1216
|
+
</label>
|
|
1217
|
+
${errorBanner}
|
|
1218
|
+
<button type="submit">Sign in</button>
|
|
1219
|
+
</form>
|
|
1220
|
+
</div>
|
|
1221
|
+
</body>
|
|
1222
|
+
</html>`;
|
|
1223
|
+
}
|
|
1224
|
+
__name(renderLoginPage, "renderLoginPage");
|
|
1225
|
+
|
|
1226
|
+
// src/server/auth/sanitize-return-to.ts
|
|
1227
|
+
function sanitizeReturnTo(basePath, returnTo) {
|
|
1228
|
+
if (typeof returnTo !== "string" || returnTo === "") return basePath;
|
|
1229
|
+
if (!returnTo.startsWith("/") || returnTo.startsWith("//")) return basePath;
|
|
1230
|
+
if (returnTo !== basePath && !returnTo.startsWith(`${basePath}/`) && !returnTo.startsWith(`${basePath}?`)) {
|
|
1231
|
+
return basePath;
|
|
1232
|
+
}
|
|
1233
|
+
return returnTo;
|
|
1234
|
+
}
|
|
1235
|
+
__name(sanitizeReturnTo, "sanitizeReturnTo");
|
|
1236
|
+
|
|
1237
|
+
// src/server/agent-dashboard-auth.controller.ts
|
|
1238
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
1239
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1240
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1241
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1242
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1243
|
+
}
|
|
1244
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
1245
|
+
function _ts_metadata4(k, v) {
|
|
1246
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1247
|
+
}
|
|
1248
|
+
__name(_ts_metadata4, "_ts_metadata");
|
|
1249
|
+
function _ts_param4(paramIndex, decorator) {
|
|
1250
|
+
return function(target, key) {
|
|
1251
|
+
decorator(target, key, paramIndex);
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
__name(_ts_param4, "_ts_param");
|
|
1255
|
+
function isNonEmptyString(value) {
|
|
1256
|
+
return typeof value === "string" && value.trim() !== "";
|
|
1257
|
+
}
|
|
1258
|
+
__name(isNonEmptyString, "isNonEmptyString");
|
|
1259
|
+
function isString(value) {
|
|
1260
|
+
return typeof value === "string";
|
|
1261
|
+
}
|
|
1262
|
+
__name(isString, "isString");
|
|
1263
|
+
var AgentDashboardAuthController = class _AgentDashboardAuthController {
|
|
1264
|
+
static {
|
|
1265
|
+
__name(this, "AgentDashboardAuthController");
|
|
1266
|
+
}
|
|
1267
|
+
auth;
|
|
1268
|
+
basePath;
|
|
1269
|
+
logger = new Logger(_AgentDashboardAuthController.name);
|
|
1270
|
+
/** Warn once (not per request) so a broken hook can't be used to flood the logs. */
|
|
1271
|
+
warnedLoginHookThrow = false;
|
|
1272
|
+
constructor(auth, basePath) {
|
|
1273
|
+
this.auth = auth;
|
|
1274
|
+
this.basePath = basePath;
|
|
1275
|
+
}
|
|
1276
|
+
loginPage(req, res, returnToQuery, error) {
|
|
1277
|
+
this.requireAuth();
|
|
1278
|
+
const returnTo = sanitizeReturnTo(this.basePath, returnToQuery);
|
|
1279
|
+
if (this.currentSession(req)) {
|
|
1280
|
+
res.status(302);
|
|
1281
|
+
res.setHeader("Location", returnTo);
|
|
1282
|
+
return "";
|
|
1283
|
+
}
|
|
1284
|
+
return renderLoginPage({
|
|
1285
|
+
actionUrl: `${this.basePath}/auth/login`,
|
|
1286
|
+
returnTo,
|
|
1287
|
+
error: error !== void 0
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
async login(body, req, res) {
|
|
1291
|
+
const auth = this.requireAuth();
|
|
1292
|
+
const returnTo = sanitizeReturnTo(this.basePath, body?.returnTo);
|
|
1293
|
+
const username = body?.username;
|
|
1294
|
+
const password = body?.password;
|
|
1295
|
+
if (!isNonEmptyString(username) || password !== void 0 && !isString(password)) {
|
|
1296
|
+
this.redirectToLoginError(res, returnTo);
|
|
1297
|
+
return "";
|
|
1298
|
+
}
|
|
1299
|
+
const user = await this.runLoginHook(auth, username.trim(), isString(password) ? password : "");
|
|
1300
|
+
if (!user) {
|
|
1301
|
+
this.redirectToLoginError(res, returnTo);
|
|
1302
|
+
return "";
|
|
1303
|
+
}
|
|
1304
|
+
issueSessionCookie(user, {
|
|
1305
|
+
auth,
|
|
1306
|
+
request: req,
|
|
1307
|
+
response: res
|
|
1308
|
+
});
|
|
1309
|
+
res.status(302);
|
|
1310
|
+
res.setHeader("Location", returnTo);
|
|
1311
|
+
return "";
|
|
1312
|
+
}
|
|
1313
|
+
logout(req, res) {
|
|
1314
|
+
clearSessionCookie({
|
|
1315
|
+
request: req,
|
|
1316
|
+
response: res
|
|
1317
|
+
});
|
|
1318
|
+
res.status(302);
|
|
1319
|
+
res.setHeader("Location", `${this.basePath}/auth/login`);
|
|
1320
|
+
return "";
|
|
1321
|
+
}
|
|
1322
|
+
/** Uniform failure: same redirect (generic error flag) whether the user is unknown or the password is wrong. */
|
|
1323
|
+
redirectToLoginError(res, returnTo) {
|
|
1324
|
+
res.status(303);
|
|
1325
|
+
res.setHeader("Location", `${this.basePath}/auth/login?error=1&returnTo=${encodeURIComponent(returnTo)}`);
|
|
1326
|
+
}
|
|
1327
|
+
currentSession(req) {
|
|
1328
|
+
const auth = this.auth;
|
|
1329
|
+
if (!auth) return false;
|
|
1330
|
+
const cookieValue = parseCookieHeader(readCookieHeader(req))[SESSION_COOKIE_NAME];
|
|
1331
|
+
if (cookieValue === void 0) return false;
|
|
1332
|
+
return verifySessionCookie(cookieValue, {
|
|
1333
|
+
secret: auth.secret
|
|
1334
|
+
}) !== null;
|
|
1335
|
+
}
|
|
1336
|
+
/**
|
|
1337
|
+
* Run the host's `login` hook defensively: a throw (sync or async) is treated as a denial
|
|
1338
|
+
* (`null`) and warn-logged ONCE, so a buggy/unreachable hook never 500s the endpoint into a
|
|
1339
|
+
* stack-trace leak nor floods the logs.
|
|
1340
|
+
*/
|
|
1341
|
+
async runLoginHook(auth, username, password) {
|
|
1342
|
+
try {
|
|
1343
|
+
return await auth.login(username, password) ?? null;
|
|
1344
|
+
} catch (error) {
|
|
1345
|
+
if (!this.warnedLoginHookThrow) {
|
|
1346
|
+
this.warnedLoginHookThrow = true;
|
|
1347
|
+
this.logger.warn(`AgentDashboardModule dashboardAuth login hook threw; treating as denial. ${error instanceof Error ? error.message : String(error)}`);
|
|
1348
|
+
}
|
|
1349
|
+
return null;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
requireAuth() {
|
|
1353
|
+
if (!this.auth) throw new NotFoundException();
|
|
1354
|
+
return this.auth;
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
_ts_decorate4([
|
|
1358
|
+
Get2("login"),
|
|
1359
|
+
Header("Content-Type", "text/html; charset=utf-8"),
|
|
1360
|
+
Header("Cache-Control", "no-store"),
|
|
1361
|
+
_ts_param4(0, Req2()),
|
|
1362
|
+
_ts_param4(1, Res({
|
|
1363
|
+
passthrough: true
|
|
1364
|
+
})),
|
|
1365
|
+
_ts_param4(2, Query2("returnTo")),
|
|
1366
|
+
_ts_param4(3, Query2("error")),
|
|
1367
|
+
_ts_metadata4("design:type", Function),
|
|
1368
|
+
_ts_metadata4("design:paramtypes", [
|
|
1369
|
+
typeof AuthPageRequest === "undefined" ? Object : AuthPageRequest,
|
|
1370
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse,
|
|
1371
|
+
String,
|
|
1372
|
+
String
|
|
1373
|
+
]),
|
|
1374
|
+
_ts_metadata4("design:returntype", String)
|
|
1375
|
+
], AgentDashboardAuthController.prototype, "loginPage", null);
|
|
1376
|
+
_ts_decorate4([
|
|
1377
|
+
Post2("login"),
|
|
1378
|
+
_ts_param4(0, Body2()),
|
|
1379
|
+
_ts_param4(1, Req2()),
|
|
1380
|
+
_ts_param4(2, Res({
|
|
1381
|
+
passthrough: true
|
|
1382
|
+
})),
|
|
1383
|
+
_ts_metadata4("design:type", Function),
|
|
1384
|
+
_ts_metadata4("design:paramtypes", [
|
|
1385
|
+
typeof LoginFormBody === "undefined" ? Object : LoginFormBody,
|
|
1386
|
+
Object,
|
|
1387
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
|
|
1388
|
+
]),
|
|
1389
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1390
|
+
], AgentDashboardAuthController.prototype, "login", null);
|
|
1391
|
+
_ts_decorate4([
|
|
1392
|
+
Post2("logout"),
|
|
1393
|
+
_ts_param4(0, Req2()),
|
|
1394
|
+
_ts_param4(1, Res({
|
|
1395
|
+
passthrough: true
|
|
1396
|
+
})),
|
|
1397
|
+
_ts_metadata4("design:type", Function),
|
|
1398
|
+
_ts_metadata4("design:paramtypes", [
|
|
1399
|
+
Object,
|
|
1400
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
|
|
1401
|
+
]),
|
|
1402
|
+
_ts_metadata4("design:returntype", String)
|
|
1403
|
+
], AgentDashboardAuthController.prototype, "logout", null);
|
|
1404
|
+
AgentDashboardAuthController = _ts_decorate4([
|
|
1405
|
+
Controller2("auth"),
|
|
1406
|
+
_ts_param4(0, Optional4()),
|
|
1407
|
+
_ts_param4(0, Inject4(DASHBOARD_AUTH)),
|
|
1408
|
+
_ts_param4(1, Inject4(DASHBOARD_BASE_PATH)),
|
|
1409
|
+
_ts_metadata4("design:type", Function),
|
|
1410
|
+
_ts_metadata4("design:paramtypes", [
|
|
1411
|
+
Object,
|
|
1412
|
+
String
|
|
1413
|
+
])
|
|
1414
|
+
], AgentDashboardAuthController);
|
|
1415
|
+
|
|
792
1416
|
// src/server/normalize-path.ts
|
|
793
1417
|
function normalizeDashboardPath(path) {
|
|
794
1418
|
return `/${path.replace(/^\/+|\/+$/g, "")}`;
|
|
@@ -823,24 +1447,147 @@ import { RouterModule } from "@nestjs/core";
|
|
|
823
1447
|
import { existsSync, readFileSync } from "node:fs";
|
|
824
1448
|
import { basename, extname, join, resolve, sep } from "node:path";
|
|
825
1449
|
import { fileURLToPath } from "node:url";
|
|
826
|
-
import { Controller as
|
|
827
|
-
|
|
1450
|
+
import { Controller as Controller3, Get as Get3, Header as Header2, Inject as Inject6, NotFoundException as NotFoundException2, Param as Param2, Req as Req3, Res as Res2, StreamableFile, UseFilters, UseGuards as UseGuards2 } from "@nestjs/common";
|
|
1451
|
+
|
|
1452
|
+
// src/server/auth/dashboard-auth-page.guard.ts
|
|
1453
|
+
import { Inject as Inject5, Injectable as Injectable4, Optional as Optional5 } from "@nestjs/common";
|
|
1454
|
+
|
|
1455
|
+
// src/server/auth/dashboard-auth-redirect.ts
|
|
1456
|
+
import { Catch, Injectable as Injectable3 } from "@nestjs/common";
|
|
1457
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
828
1458
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
829
1459
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
830
1460
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
831
1461
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
832
1462
|
}
|
|
833
|
-
__name(
|
|
834
|
-
|
|
1463
|
+
__name(_ts_decorate5, "_ts_decorate");
|
|
1464
|
+
var DashboardAuthRedirect = class extends Error {
|
|
1465
|
+
static {
|
|
1466
|
+
__name(this, "DashboardAuthRedirect");
|
|
1467
|
+
}
|
|
1468
|
+
redirectTo;
|
|
1469
|
+
constructor(redirectTo) {
|
|
1470
|
+
super(`Redirect to ${redirectTo}`), this.redirectTo = redirectTo;
|
|
1471
|
+
this.name = "DashboardAuthRedirect";
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
var DashboardAuthRedirectFilter = class {
|
|
1475
|
+
static {
|
|
1476
|
+
__name(this, "DashboardAuthRedirectFilter");
|
|
1477
|
+
}
|
|
1478
|
+
catch(exception, host) {
|
|
1479
|
+
const response = host.switchToHttp().getResponse();
|
|
1480
|
+
sendRedirect(response, 302, exception.redirectTo);
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
DashboardAuthRedirectFilter = _ts_decorate5([
|
|
1484
|
+
Injectable3(),
|
|
1485
|
+
Catch(DashboardAuthRedirect)
|
|
1486
|
+
], DashboardAuthRedirectFilter);
|
|
1487
|
+
|
|
1488
|
+
// src/server/auth/dashboard-auth-page.guard.ts
|
|
1489
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
1490
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1491
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1492
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1493
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1494
|
+
}
|
|
1495
|
+
__name(_ts_decorate6, "_ts_decorate");
|
|
1496
|
+
function _ts_metadata5(k, v) {
|
|
835
1497
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
836
1498
|
}
|
|
837
|
-
__name(
|
|
838
|
-
function
|
|
1499
|
+
__name(_ts_metadata5, "_ts_metadata");
|
|
1500
|
+
function _ts_param5(paramIndex, decorator) {
|
|
839
1501
|
return function(target, key) {
|
|
840
1502
|
decorator(target, key, paramIndex);
|
|
841
1503
|
};
|
|
842
1504
|
}
|
|
843
|
-
__name(
|
|
1505
|
+
__name(_ts_param5, "_ts_param");
|
|
1506
|
+
var DashboardAuthPageGuard = class {
|
|
1507
|
+
static {
|
|
1508
|
+
__name(this, "DashboardAuthPageGuard");
|
|
1509
|
+
}
|
|
1510
|
+
auth;
|
|
1511
|
+
basePath;
|
|
1512
|
+
constructor(auth, basePath) {
|
|
1513
|
+
this.auth = auth;
|
|
1514
|
+
this.basePath = basePath;
|
|
1515
|
+
}
|
|
1516
|
+
canActivate(context) {
|
|
1517
|
+
if (!this.auth) return true;
|
|
1518
|
+
const http = context.switchToHttp();
|
|
1519
|
+
const request = http.getRequest();
|
|
1520
|
+
const session = this.verifyRequestSession(request);
|
|
1521
|
+
if (!session) {
|
|
1522
|
+
const returnTo = readOriginalUrl(request);
|
|
1523
|
+
throw new DashboardAuthRedirect(`${this.basePath}/auth/login?returnTo=${encodeURIComponent(returnTo)}`);
|
|
1524
|
+
}
|
|
1525
|
+
attachSession(request, session);
|
|
1526
|
+
this.maybeRenew(http.getResponse(), request, session);
|
|
1527
|
+
return true;
|
|
1528
|
+
}
|
|
1529
|
+
verifyRequestSession(request) {
|
|
1530
|
+
const auth = this.auth;
|
|
1531
|
+
if (!auth) return null;
|
|
1532
|
+
const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
|
|
1533
|
+
if (cookieValue === void 0) return null;
|
|
1534
|
+
return verifySessionCookie(cookieValue, {
|
|
1535
|
+
secret: auth.secret
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Sliding renewal: a valid cookie past 50% of its TTL is transparently re-issued on the
|
|
1540
|
+
* response, so an active user never gets logged out mid-session.
|
|
1541
|
+
*/
|
|
1542
|
+
maybeRenew(response, request, session) {
|
|
1543
|
+
const auth = this.auth;
|
|
1544
|
+
if (!auth) return;
|
|
1545
|
+
const now = Date.now();
|
|
1546
|
+
if (now - session.iat <= auth.ttlMs / 2) return;
|
|
1547
|
+
issueSessionCookie({
|
|
1548
|
+
id: session.sub,
|
|
1549
|
+
...session.name !== void 0 ? {
|
|
1550
|
+
name: session.name
|
|
1551
|
+
} : {},
|
|
1552
|
+
roles: session.roles
|
|
1553
|
+
}, {
|
|
1554
|
+
auth,
|
|
1555
|
+
request,
|
|
1556
|
+
response,
|
|
1557
|
+
now
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1561
|
+
DashboardAuthPageGuard = _ts_decorate6([
|
|
1562
|
+
Injectable4(),
|
|
1563
|
+
_ts_param5(0, Optional5()),
|
|
1564
|
+
_ts_param5(0, Inject5(DASHBOARD_AUTH)),
|
|
1565
|
+
_ts_param5(1, Inject5(DASHBOARD_BASE_PATH)),
|
|
1566
|
+
_ts_metadata5("design:type", Function),
|
|
1567
|
+
_ts_metadata5("design:paramtypes", [
|
|
1568
|
+
Object,
|
|
1569
|
+
String
|
|
1570
|
+
])
|
|
1571
|
+
], DashboardAuthPageGuard);
|
|
1572
|
+
|
|
1573
|
+
// src/server/agent-ui.controller.ts
|
|
1574
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
1575
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1576
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1577
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1578
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1579
|
+
}
|
|
1580
|
+
__name(_ts_decorate7, "_ts_decorate");
|
|
1581
|
+
function _ts_metadata6(k, v) {
|
|
1582
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1583
|
+
}
|
|
1584
|
+
__name(_ts_metadata6, "_ts_metadata");
|
|
1585
|
+
function _ts_param6(paramIndex, decorator) {
|
|
1586
|
+
return function(target, key) {
|
|
1587
|
+
decorator(target, key, paramIndex);
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
__name(_ts_param6, "_ts_param");
|
|
844
1591
|
var BUILD_BASE = "/ai-gateway";
|
|
845
1592
|
function spaDir() {
|
|
846
1593
|
return fileURLToPath(new URL("../spa", import.meta.url));
|
|
@@ -876,7 +1623,7 @@ var AgentUiController = class {
|
|
|
876
1623
|
}
|
|
877
1624
|
const indexPath = join(this.dir, "index.html");
|
|
878
1625
|
if (!existsSync(indexPath)) {
|
|
879
|
-
throw new
|
|
1626
|
+
throw new NotFoundException2("Dashboard is not built. Run the package build.");
|
|
880
1627
|
}
|
|
881
1628
|
const html = readFileSync(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
|
|
882
1629
|
const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>`;
|
|
@@ -884,11 +1631,11 @@ var AgentUiController = class {
|
|
|
884
1631
|
}
|
|
885
1632
|
asset(file) {
|
|
886
1633
|
const safe = basename(file);
|
|
887
|
-
if (safe !== file) throw new
|
|
1634
|
+
if (safe !== file) throw new NotFoundException2();
|
|
888
1635
|
const root = resolve(this.dir, "assets");
|
|
889
1636
|
const assetPath = resolve(root, safe);
|
|
890
1637
|
if (!assetPath.startsWith(root + sep) || !existsSync(assetPath)) {
|
|
891
|
-
throw new
|
|
1638
|
+
throw new NotFoundException2();
|
|
892
1639
|
}
|
|
893
1640
|
const type = CONTENT_TYPES[extname(safe)] ?? "application/octet-stream";
|
|
894
1641
|
return new StreamableFile(readFileSync(assetPath), {
|
|
@@ -896,66 +1643,135 @@ var AgentUiController = class {
|
|
|
896
1643
|
});
|
|
897
1644
|
}
|
|
898
1645
|
};
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1646
|
+
_ts_decorate7([
|
|
1647
|
+
Get3(),
|
|
1648
|
+
Header2("Content-Type", "text/html; charset=utf-8"),
|
|
1649
|
+
Header2("Cache-Control", "no-store, must-revalidate"),
|
|
1650
|
+
_ts_param6(0, Req3()),
|
|
1651
|
+
_ts_param6(1, Res2({
|
|
905
1652
|
passthrough: true
|
|
906
1653
|
})),
|
|
907
|
-
|
|
908
|
-
|
|
1654
|
+
_ts_metadata6("design:type", Function),
|
|
1655
|
+
_ts_metadata6("design:paramtypes", [
|
|
909
1656
|
typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
|
|
910
1657
|
typeof UiPageResponse === "undefined" ? Object : UiPageResponse
|
|
911
1658
|
]),
|
|
912
|
-
|
|
1659
|
+
_ts_metadata6("design:returntype", String)
|
|
913
1660
|
], AgentUiController.prototype, "index", null);
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
1661
|
+
_ts_decorate7([
|
|
1662
|
+
Get3("assets/:file"),
|
|
1663
|
+
Header2("Cache-Control", "public, max-age=31536000, immutable"),
|
|
1664
|
+
_ts_param6(0, Param2("file")),
|
|
1665
|
+
_ts_metadata6("design:type", Function),
|
|
1666
|
+
_ts_metadata6("design:paramtypes", [
|
|
920
1667
|
String
|
|
921
1668
|
]),
|
|
922
|
-
|
|
1669
|
+
_ts_metadata6("design:returntype", typeof StreamableFile === "undefined" ? Object : StreamableFile)
|
|
923
1670
|
], AgentUiController.prototype, "asset", null);
|
|
924
|
-
AgentUiController =
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1671
|
+
AgentUiController = _ts_decorate7([
|
|
1672
|
+
Controller3(),
|
|
1673
|
+
UseGuards2(DashboardAuthPageGuard),
|
|
1674
|
+
UseFilters(new DashboardAuthRedirectFilter()),
|
|
1675
|
+
_ts_param6(0, Inject6(DASHBOARD_BASE_PATH)),
|
|
1676
|
+
_ts_param6(1, Inject6(DASHBOARD_API_PATH)),
|
|
1677
|
+
_ts_metadata6("design:type", Function),
|
|
1678
|
+
_ts_metadata6("design:paramtypes", [
|
|
930
1679
|
String,
|
|
931
1680
|
String
|
|
932
1681
|
])
|
|
933
1682
|
], AgentUiController);
|
|
934
1683
|
|
|
1684
|
+
// src/server/auth/dashboard-auth-config.ts
|
|
1685
|
+
var DEFAULT_TTL = "8h";
|
|
1686
|
+
function unitToMs(unit) {
|
|
1687
|
+
switch (unit) {
|
|
1688
|
+
case "ms":
|
|
1689
|
+
return 1;
|
|
1690
|
+
case "s":
|
|
1691
|
+
return 1e3;
|
|
1692
|
+
case "m":
|
|
1693
|
+
return 6e4;
|
|
1694
|
+
case "h":
|
|
1695
|
+
return 36e5;
|
|
1696
|
+
case "d":
|
|
1697
|
+
return 864e5;
|
|
1698
|
+
default:
|
|
1699
|
+
return void 0;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
__name(unitToMs, "unitToMs");
|
|
1703
|
+
function durationToMs(duration) {
|
|
1704
|
+
const match = /^(\d+)(ms|s|m|h|d)$/.exec(duration.trim());
|
|
1705
|
+
const amount = match?.[1];
|
|
1706
|
+
const unit = match?.[2] !== void 0 ? unitToMs(match[2]) : void 0;
|
|
1707
|
+
if (amount === void 0 || unit === void 0) {
|
|
1708
|
+
throw new Error(`AgentDashboardModule dashboardAuth: invalid \`ttl\` duration: ${duration}`);
|
|
1709
|
+
}
|
|
1710
|
+
return Number(amount) * unit;
|
|
1711
|
+
}
|
|
1712
|
+
__name(durationToMs, "durationToMs");
|
|
1713
|
+
function resolveDashboardAuth(options) {
|
|
1714
|
+
if (options === void 0) return null;
|
|
1715
|
+
if (typeof options.secret !== "string" || options.secret === "") {
|
|
1716
|
+
throw new Error("AgentDashboardModule dashboardAuth: `secret` is required and must be a non-empty string (HMAC-SHA256 signing key, 32+ bytes recommended). Failing closed.");
|
|
1717
|
+
}
|
|
1718
|
+
if (typeof options.login !== "function") {
|
|
1719
|
+
throw new Error("AgentDashboardModule dashboardAuth: `login` is required (validates submitted credentials for the built-in login screen). Failing closed.");
|
|
1720
|
+
}
|
|
1721
|
+
return {
|
|
1722
|
+
secret: options.secret,
|
|
1723
|
+
ttlMs: durationToMs(options.ttl ?? DEFAULT_TTL),
|
|
1724
|
+
login: options.login
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
__name(resolveDashboardAuth, "resolveDashboardAuth");
|
|
1728
|
+
|
|
1729
|
+
// src/server/guards.ts
|
|
1730
|
+
import "reflect-metadata";
|
|
1731
|
+
var GUARDS_METADATA = "__guards__";
|
|
1732
|
+
function isGuardClass(guard) {
|
|
1733
|
+
return typeof guard === "function";
|
|
1734
|
+
}
|
|
1735
|
+
__name(isGuardClass, "isGuardClass");
|
|
1736
|
+
function baseGuards(controller) {
|
|
1737
|
+
return Reflect.getOwnMetadata(GUARDS_METADATA, controller) ?? [];
|
|
1738
|
+
}
|
|
1739
|
+
__name(baseGuards, "baseGuards");
|
|
1740
|
+
function stampGuards(guards, entries) {
|
|
1741
|
+
for (const [controller, base] of entries) {
|
|
1742
|
+
Reflect.defineMetadata(GUARDS_METADATA, [
|
|
1743
|
+
...base,
|
|
1744
|
+
...guards ?? []
|
|
1745
|
+
], controller);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
__name(stampGuards, "stampGuards");
|
|
1749
|
+
|
|
935
1750
|
// src/server/agent-dashboard.module.ts
|
|
936
|
-
function
|
|
1751
|
+
function _ts_decorate8(decorators, target, key, desc) {
|
|
937
1752
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
938
1753
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
939
1754
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
940
1755
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
941
1756
|
}
|
|
942
|
-
__name(
|
|
943
|
-
var
|
|
1757
|
+
__name(_ts_decorate8, "_ts_decorate");
|
|
1758
|
+
var API_BASE_GUARDS = baseGuards(AgentApiController);
|
|
1759
|
+
var UI_BASE_GUARDS = baseGuards(AgentUiController);
|
|
944
1760
|
function normalize(path) {
|
|
945
1761
|
return normalizeDashboardPath(path);
|
|
946
1762
|
}
|
|
947
1763
|
__name(normalize, "normalize");
|
|
948
|
-
function stampGuards(guards, ...controllers) {
|
|
949
|
-
for (const controller of controllers) {
|
|
950
|
-
Reflect.defineMetadata(GUARDS_METADATA, guards ?? [], controller);
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
__name(stampGuards, "stampGuards");
|
|
954
1764
|
var AgentApiModule = class _AgentApiModule {
|
|
955
1765
|
static {
|
|
956
1766
|
__name(this, "AgentApiModule");
|
|
957
1767
|
}
|
|
958
1768
|
static register(options) {
|
|
1769
|
+
stampGuards(options.guards, [
|
|
1770
|
+
[
|
|
1771
|
+
AgentApiController,
|
|
1772
|
+
API_BASE_GUARDS
|
|
1773
|
+
]
|
|
1774
|
+
]);
|
|
959
1775
|
return {
|
|
960
1776
|
module: _AgentApiModule,
|
|
961
1777
|
imports: [
|
|
@@ -966,7 +1782,9 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
966
1782
|
],
|
|
967
1783
|
providers: [
|
|
968
1784
|
DashboardService,
|
|
969
|
-
|
|
1785
|
+
DashboardAuthGuard,
|
|
1786
|
+
options.dashboardAuth,
|
|
1787
|
+
...(options.guards ?? []).filter(isGuardClass),
|
|
970
1788
|
// `useValue` even when `options.approvalActorRef` is `undefined` — AgentApiController
|
|
971
1789
|
// injects this WITHOUT `@Optional()` (same pattern as `AGENT_QUOTA_STORE`'s factory).
|
|
972
1790
|
{
|
|
@@ -974,13 +1792,17 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
974
1792
|
useValue: options.approvalActorRef
|
|
975
1793
|
}
|
|
976
1794
|
],
|
|
1795
|
+
// DASHBOARD_AUTH re-exported so AgentUiController/AgentDashboardAuthController (hosted
|
|
1796
|
+
// directly by AgentDashboardModule, which imports this module) resolve the SAME instance
|
|
1797
|
+
// instead of re-running a host's async factory a second time.
|
|
977
1798
|
exports: [
|
|
978
|
-
DashboardService
|
|
1799
|
+
DashboardService,
|
|
1800
|
+
DASHBOARD_AUTH
|
|
979
1801
|
]
|
|
980
1802
|
};
|
|
981
1803
|
}
|
|
982
1804
|
};
|
|
983
|
-
AgentApiModule =
|
|
1805
|
+
AgentApiModule = _ts_decorate8([
|
|
984
1806
|
Module({})
|
|
985
1807
|
], AgentApiModule);
|
|
986
1808
|
var AgentDashboardModule = class _AgentDashboardModule {
|
|
@@ -990,7 +1812,16 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
990
1812
|
static forRoot(options = {}) {
|
|
991
1813
|
const basePath = normalize(options.basePath ?? "/ai-gateway");
|
|
992
1814
|
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
993
|
-
stampGuards(options.guards,
|
|
1815
|
+
stampGuards(options.guards, [
|
|
1816
|
+
[
|
|
1817
|
+
AgentUiController,
|
|
1818
|
+
UI_BASE_GUARDS
|
|
1819
|
+
]
|
|
1820
|
+
]);
|
|
1821
|
+
const dashboardAuthProvider = {
|
|
1822
|
+
provide: DASHBOARD_AUTH,
|
|
1823
|
+
useValue: resolveDashboardAuth(options.dashboardAuth)
|
|
1824
|
+
};
|
|
994
1825
|
return {
|
|
995
1826
|
module: _AgentDashboardModule,
|
|
996
1827
|
imports: [
|
|
@@ -1007,7 +1838,8 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
1007
1838
|
} : {},
|
|
1008
1839
|
...options.approvalActorRef ? {
|
|
1009
1840
|
approvalActorRef: options.approvalActorRef
|
|
1010
|
-
} : {}
|
|
1841
|
+
} : {},
|
|
1842
|
+
dashboardAuth: dashboardAuthProvider
|
|
1011
1843
|
}),
|
|
1012
1844
|
RouterModule.register([
|
|
1013
1845
|
{
|
|
@@ -1021,7 +1853,8 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
1021
1853
|
])
|
|
1022
1854
|
],
|
|
1023
1855
|
controllers: [
|
|
1024
|
-
AgentUiController
|
|
1856
|
+
AgentUiController,
|
|
1857
|
+
AgentDashboardAuthController
|
|
1025
1858
|
],
|
|
1026
1859
|
providers: [
|
|
1027
1860
|
{
|
|
@@ -1032,8 +1865,9 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
1032
1865
|
provide: DASHBOARD_API_PATH,
|
|
1033
1866
|
useValue: apiBasePath
|
|
1034
1867
|
},
|
|
1868
|
+
DashboardAuthPageGuard,
|
|
1035
1869
|
// AgentUiController is hosted HERE, so its guards DI-instantiate from this module.
|
|
1036
|
-
...options.guards ?? []
|
|
1870
|
+
...(options.guards ?? []).filter(isGuardClass)
|
|
1037
1871
|
],
|
|
1038
1872
|
// Re-export the API module so its DashboardService reaches importers (e.g. the host's own controllers).
|
|
1039
1873
|
exports: [
|
|
@@ -1041,8 +1875,70 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
1041
1875
|
]
|
|
1042
1876
|
};
|
|
1043
1877
|
}
|
|
1878
|
+
static forRootAsync(options) {
|
|
1879
|
+
const basePath = normalize(options.basePath ?? "/ai-gateway");
|
|
1880
|
+
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
1881
|
+
stampGuards(options.guards, [
|
|
1882
|
+
[
|
|
1883
|
+
AgentUiController,
|
|
1884
|
+
UI_BASE_GUARDS
|
|
1885
|
+
]
|
|
1886
|
+
]);
|
|
1887
|
+
const dashboardAuthProvider = {
|
|
1888
|
+
provide: DASHBOARD_AUTH,
|
|
1889
|
+
inject: options.inject ?? [],
|
|
1890
|
+
useFactory: /* @__PURE__ */ __name(async (...deps) => resolveDashboardAuth(await options.useDashboardAuth(...deps)), "useFactory")
|
|
1891
|
+
};
|
|
1892
|
+
return {
|
|
1893
|
+
module: _AgentDashboardModule,
|
|
1894
|
+
imports: [
|
|
1895
|
+
...options.imports ?? [],
|
|
1896
|
+
AgentApiModule.register({
|
|
1897
|
+
...options.imports ? {
|
|
1898
|
+
imports: options.imports
|
|
1899
|
+
} : {},
|
|
1900
|
+
...options.guards ? {
|
|
1901
|
+
guards: options.guards
|
|
1902
|
+
} : {},
|
|
1903
|
+
...options.approvalActorRef ? {
|
|
1904
|
+
approvalActorRef: options.approvalActorRef
|
|
1905
|
+
} : {},
|
|
1906
|
+
dashboardAuth: dashboardAuthProvider
|
|
1907
|
+
}),
|
|
1908
|
+
RouterModule.register([
|
|
1909
|
+
{
|
|
1910
|
+
path: basePath,
|
|
1911
|
+
module: _AgentDashboardModule
|
|
1912
|
+
},
|
|
1913
|
+
{
|
|
1914
|
+
path: apiBasePath,
|
|
1915
|
+
module: AgentApiModule
|
|
1916
|
+
}
|
|
1917
|
+
])
|
|
1918
|
+
],
|
|
1919
|
+
controllers: [
|
|
1920
|
+
AgentUiController,
|
|
1921
|
+
AgentDashboardAuthController
|
|
1922
|
+
],
|
|
1923
|
+
providers: [
|
|
1924
|
+
{
|
|
1925
|
+
provide: DASHBOARD_BASE_PATH,
|
|
1926
|
+
useValue: basePath
|
|
1927
|
+
},
|
|
1928
|
+
{
|
|
1929
|
+
provide: DASHBOARD_API_PATH,
|
|
1930
|
+
useValue: apiBasePath
|
|
1931
|
+
},
|
|
1932
|
+
DashboardAuthPageGuard,
|
|
1933
|
+
...(options.guards ?? []).filter(isGuardClass)
|
|
1934
|
+
],
|
|
1935
|
+
exports: [
|
|
1936
|
+
AgentApiModule
|
|
1937
|
+
]
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1044
1940
|
};
|
|
1045
|
-
AgentDashboardModule =
|
|
1941
|
+
AgentDashboardModule = _ts_decorate8([
|
|
1046
1942
|
Module({})
|
|
1047
1943
|
], AgentDashboardModule);
|
|
1048
1944
|
export {
|
|
@@ -1053,13 +1949,16 @@ export {
|
|
|
1053
1949
|
AGENT_PRICING_STORE,
|
|
1054
1950
|
AgentApiController,
|
|
1055
1951
|
AgentApiModule,
|
|
1952
|
+
AgentDashboardAuthController,
|
|
1056
1953
|
AgentDashboardModule,
|
|
1057
1954
|
AgentUiController,
|
|
1058
1955
|
DASHBOARD_API_PATH,
|
|
1059
1956
|
DASHBOARD_APPROVAL_ACTOR_REF,
|
|
1957
|
+
DASHBOARD_AUTH,
|
|
1060
1958
|
DASHBOARD_BASE_PATH,
|
|
1061
1959
|
DashboardService,
|
|
1062
1960
|
agentDashboardMountPaths,
|
|
1063
|
-
parsePriceInput
|
|
1961
|
+
parsePriceInput,
|
|
1962
|
+
resolveDashboardAuth
|
|
1064
1963
|
};
|
|
1065
1964
|
//# sourceMappingURL=index.js.map
|