@dudousxd/nestjs-agent-dashboard 0.7.0 → 0.9.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.
- package/README.md +85 -2
- package/dist/client/agent-client.d.ts +48 -0
- package/dist/client/agent-client.d.ts.map +1 -1
- package/dist/client/agent-client.js +23 -0
- package/dist/client/agent-client.js.map +1 -1
- package/dist/server/index.cjs +1315 -192
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +177 -9
- package/dist/server/index.d.ts +177 -9
- package/dist/server/index.js +1278 -158
- package/dist/server/index.js.map +1 -1
- package/dist/spa/assets/index-C42SW8IV.js +1 -0
- package/dist/spa/assets/index-DMBWMAsE.css +1 -0
- package/dist/spa/assets/index-DZVPxvtJ.js +49 -0
- package/dist/spa/assets/{preview-A3jHlGra.js → preview-DhDnTjWH.js} +1 -1
- package/dist/spa/index.html +3 -3
- package/dist/spa/preview.html +3 -3
- package/package.json +7 -3
- package/dist/spa/assets/index-BjIcXlBO.js +0 -1
- package/dist/spa/assets/index-CES4RqI4.js +0 -49
- package/dist/spa/assets/index-CVcgbps5.css +0 -1
package/dist/server/index.cjs
CHANGED
|
@@ -29,38 +29,377 @@ __export(index_exports, {
|
|
|
29
29
|
AGENT_PRICING_STORE: () => AGENT_PRICING_STORE,
|
|
30
30
|
AgentApiController: () => AgentApiController,
|
|
31
31
|
AgentApiModule: () => AgentApiModule,
|
|
32
|
+
AgentDashboardAuthController: () => AgentDashboardAuthController,
|
|
32
33
|
AgentDashboardModule: () => AgentDashboardModule,
|
|
33
34
|
AgentUiController: () => AgentUiController,
|
|
34
35
|
DASHBOARD_API_PATH: () => DASHBOARD_API_PATH,
|
|
35
36
|
DASHBOARD_APPROVAL_ACTOR_REF: () => DASHBOARD_APPROVAL_ACTOR_REF,
|
|
37
|
+
DASHBOARD_AUTH: () => DASHBOARD_AUTH,
|
|
36
38
|
DASHBOARD_BASE_PATH: () => DASHBOARD_BASE_PATH,
|
|
37
39
|
DashboardService: () => DashboardService,
|
|
38
40
|
agentDashboardMountPaths: () => agentDashboardMountPaths,
|
|
39
|
-
parsePriceInput: () => parsePriceInput
|
|
41
|
+
parsePriceInput: () => parsePriceInput,
|
|
42
|
+
resolveDashboardAuth: () => resolveDashboardAuth
|
|
40
43
|
});
|
|
41
44
|
module.exports = __toCommonJS(index_exports);
|
|
42
45
|
|
|
43
46
|
// src/server/agent-api.controller.ts
|
|
44
|
-
var
|
|
47
|
+
var import_common6 = require("@nestjs/common");
|
|
48
|
+
|
|
49
|
+
// src/server/auth/dashboard-auth.guard.ts
|
|
50
|
+
var import_common = require("@nestjs/common");
|
|
51
|
+
|
|
52
|
+
// src/server/tokens.ts
|
|
53
|
+
var AGENT_GOVERNANCE_QUERIES = Symbol.for("@dudousxd/nestjs-agent:governance-queries");
|
|
54
|
+
var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
|
|
55
|
+
var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
|
|
56
|
+
var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
|
|
57
|
+
var AGENT_ACTOR_RESOLVER = Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
|
|
58
|
+
var DASHBOARD_BASE_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
|
|
59
|
+
var DASHBOARD_API_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
|
|
60
|
+
var DASHBOARD_APPROVAL_ACTOR_REF = Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
|
|
61
|
+
var DASHBOARD_AUTH = Symbol.for("@dudousxd/nestjs-agent-dashboard:dashboard-auth");
|
|
62
|
+
|
|
63
|
+
// src/server/auth/cookie-header.ts
|
|
64
|
+
function parseCookieHeader(header) {
|
|
65
|
+
const cookies = {};
|
|
66
|
+
if (typeof header !== "string" || header === "") return cookies;
|
|
67
|
+
for (const segment of header.split(";")) {
|
|
68
|
+
const eq = segment.indexOf("=");
|
|
69
|
+
if (eq <= 0) continue;
|
|
70
|
+
const name = segment.slice(0, eq).trim();
|
|
71
|
+
if (name === "") continue;
|
|
72
|
+
let rawValue = segment.slice(eq + 1).trim();
|
|
73
|
+
if (rawValue.length >= 2 && rawValue.startsWith('"') && rawValue.endsWith('"')) {
|
|
74
|
+
rawValue = rawValue.slice(1, -1);
|
|
75
|
+
}
|
|
76
|
+
if (name in cookies) continue;
|
|
77
|
+
try {
|
|
78
|
+
cookies[name] = decodeURIComponent(rawValue);
|
|
79
|
+
} catch {
|
|
80
|
+
cookies[name] = rawValue;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return cookies;
|
|
84
|
+
}
|
|
85
|
+
__name(parseCookieHeader, "parseCookieHeader");
|
|
86
|
+
function serializeSetCookie(name, value, options) {
|
|
87
|
+
const parts = [
|
|
88
|
+
`${name}=${options.clear ? "" : encodeURIComponent(value)}`
|
|
89
|
+
];
|
|
90
|
+
parts.push(`Path=${options.path}`);
|
|
91
|
+
parts.push("HttpOnly");
|
|
92
|
+
parts.push("SameSite=Lax");
|
|
93
|
+
if (options.secure) parts.push("Secure");
|
|
94
|
+
if (options.clear) {
|
|
95
|
+
parts.push("Max-Age=0");
|
|
96
|
+
parts.push("Expires=Thu, 01 Jan 1970 00:00:00 GMT");
|
|
97
|
+
} else {
|
|
98
|
+
parts.push(`Max-Age=${options.maxAgeSeconds}`);
|
|
99
|
+
}
|
|
100
|
+
return parts.join("; ");
|
|
101
|
+
}
|
|
102
|
+
__name(serializeSetCookie, "serializeSetCookie");
|
|
103
|
+
|
|
104
|
+
// src/server/auth/http-request.ts
|
|
105
|
+
function isRecord(value) {
|
|
106
|
+
return typeof value === "object" && value !== null;
|
|
107
|
+
}
|
|
108
|
+
__name(isRecord, "isRecord");
|
|
109
|
+
function readHeaders(request) {
|
|
110
|
+
if (!isRecord(request)) return {};
|
|
111
|
+
const headers = request.headers;
|
|
112
|
+
return isRecord(headers) ? headers : {};
|
|
113
|
+
}
|
|
114
|
+
__name(readHeaders, "readHeaders");
|
|
115
|
+
function headerToString(value) {
|
|
116
|
+
if (typeof value === "string") return value;
|
|
117
|
+
if (Array.isArray(value) && value.every((part) => typeof part === "string")) {
|
|
118
|
+
return value.join(",");
|
|
119
|
+
}
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
__name(headerToString, "headerToString");
|
|
123
|
+
function readCookieHeader(request) {
|
|
124
|
+
return headerToString(readHeaders(request).cookie);
|
|
125
|
+
}
|
|
126
|
+
__name(readCookieHeader, "readCookieHeader");
|
|
127
|
+
function isHttpsRequest(request) {
|
|
128
|
+
if (isRecord(request) && request.protocol === "https") return true;
|
|
129
|
+
const forwarded = headerToString(readHeaders(request)["x-forwarded-proto"]);
|
|
130
|
+
if (forwarded === void 0) return false;
|
|
131
|
+
return forwarded.split(",").map((proto) => proto.trim().toLowerCase()).includes("https");
|
|
132
|
+
}
|
|
133
|
+
__name(isHttpsRequest, "isHttpsRequest");
|
|
134
|
+
function readOriginalUrl(request) {
|
|
135
|
+
if (!isRecord(request)) return "/";
|
|
136
|
+
const originalUrl = request.originalUrl;
|
|
137
|
+
if (typeof originalUrl === "string" && originalUrl !== "") return originalUrl;
|
|
138
|
+
const url = request.url;
|
|
139
|
+
return typeof url === "string" && url !== "" ? url : "/";
|
|
140
|
+
}
|
|
141
|
+
__name(readOriginalUrl, "readOriginalUrl");
|
|
142
|
+
function attachSession(request, session) {
|
|
143
|
+
if (!isRecord(request)) return;
|
|
144
|
+
const target = request;
|
|
145
|
+
target.dashboardSession = session;
|
|
146
|
+
}
|
|
147
|
+
__name(attachSession, "attachSession");
|
|
148
|
+
|
|
149
|
+
// src/server/auth/response.ts
|
|
150
|
+
function isRecord2(value) {
|
|
151
|
+
return typeof value === "object" && value !== null;
|
|
152
|
+
}
|
|
153
|
+
__name(isRecord2, "isRecord");
|
|
154
|
+
function isHeaderCapableResponse(value) {
|
|
155
|
+
return isRecord2(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function";
|
|
156
|
+
}
|
|
157
|
+
__name(isHeaderCapableResponse, "isHeaderCapableResponse");
|
|
158
|
+
function resolveHeaderCapableResponse(response) {
|
|
159
|
+
if (isHeaderCapableResponse(response)) return response;
|
|
160
|
+
if (isRecord2(response) && isHeaderCapableResponse(response.raw)) return response.raw;
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
__name(resolveHeaderCapableResponse, "resolveHeaderCapableResponse");
|
|
164
|
+
function existingSetCookies(response) {
|
|
165
|
+
const current = response.getHeader("set-cookie");
|
|
166
|
+
if (Array.isArray(current)) return current;
|
|
167
|
+
if (typeof current === "string") return [
|
|
168
|
+
current
|
|
169
|
+
];
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
__name(existingSetCookies, "existingSetCookies");
|
|
173
|
+
function appendSetCookie(response, cookie) {
|
|
174
|
+
const raw = resolveHeaderCapableResponse(response);
|
|
175
|
+
if (!raw) return;
|
|
176
|
+
raw.setHeader("set-cookie", [
|
|
177
|
+
...existingSetCookies(raw),
|
|
178
|
+
cookie
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
__name(appendSetCookie, "appendSetCookie");
|
|
182
|
+
function isRawNodeResponse(value) {
|
|
183
|
+
return isRecord2(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function" && typeof value.end === "function";
|
|
184
|
+
}
|
|
185
|
+
__name(isRawNodeResponse, "isRawNodeResponse");
|
|
186
|
+
function resolveRawResponse(response) {
|
|
187
|
+
if (isRawNodeResponse(response)) return response;
|
|
188
|
+
if (isRecord2(response) && isRawNodeResponse(response.raw)) return response.raw;
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
__name(resolveRawResponse, "resolveRawResponse");
|
|
192
|
+
function sendRedirect(response, status, location) {
|
|
193
|
+
const raw = resolveRawResponse(response);
|
|
194
|
+
if (!raw) return;
|
|
195
|
+
raw.statusCode = status;
|
|
196
|
+
raw.setHeader("location", location);
|
|
197
|
+
raw.end();
|
|
198
|
+
}
|
|
199
|
+
__name(sendRedirect, "sendRedirect");
|
|
200
|
+
|
|
201
|
+
// src/server/auth/session-cookie.ts
|
|
202
|
+
var import_node_crypto = require("crypto");
|
|
203
|
+
var EXP_GRACE_MS = 3e4;
|
|
204
|
+
function base64urlEncode(value) {
|
|
205
|
+
return Buffer.from(value, "utf8").toString("base64url");
|
|
206
|
+
}
|
|
207
|
+
__name(base64urlEncode, "base64urlEncode");
|
|
208
|
+
function base64urlDecode(value) {
|
|
209
|
+
return Buffer.from(value, "base64url").toString("utf8");
|
|
210
|
+
}
|
|
211
|
+
__name(base64urlDecode, "base64urlDecode");
|
|
212
|
+
function hmac(secret, payload) {
|
|
213
|
+
return (0, import_node_crypto.createHmac)("sha256", secret).update(payload).digest("base64url");
|
|
214
|
+
}
|
|
215
|
+
__name(hmac, "hmac");
|
|
216
|
+
function signSessionCookie(user, options) {
|
|
217
|
+
const issuedAt = options.now ?? Date.now();
|
|
218
|
+
const session = {
|
|
219
|
+
sub: user.id,
|
|
220
|
+
...user.name !== void 0 ? {
|
|
221
|
+
name: user.name
|
|
222
|
+
} : {},
|
|
223
|
+
roles: user.roles ?? [],
|
|
224
|
+
iat: issuedAt,
|
|
225
|
+
exp: issuedAt + options.ttlMs
|
|
226
|
+
};
|
|
227
|
+
const encodedPayload = base64urlEncode(JSON.stringify(session));
|
|
228
|
+
const signature = hmac(options.secret, encodedPayload);
|
|
229
|
+
return `${encodedPayload}.${signature}`;
|
|
230
|
+
}
|
|
231
|
+
__name(signSessionCookie, "signSessionCookie");
|
|
232
|
+
function isSessionPayload(value) {
|
|
233
|
+
if (typeof value !== "object" || value === null) return false;
|
|
234
|
+
const record = {
|
|
235
|
+
...value
|
|
236
|
+
};
|
|
237
|
+
if (typeof record.sub !== "string") return false;
|
|
238
|
+
if (record.name !== void 0 && typeof record.name !== "string") return false;
|
|
239
|
+
if (!Array.isArray(record.roles)) return false;
|
|
240
|
+
if (!record.roles.every((role) => typeof role === "string")) return false;
|
|
241
|
+
if (typeof record.iat !== "number" || !Number.isFinite(record.iat)) return false;
|
|
242
|
+
if (typeof record.exp !== "number" || !Number.isFinite(record.exp)) return false;
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
__name(isSessionPayload, "isSessionPayload");
|
|
246
|
+
function verifySessionCookie(value, options) {
|
|
247
|
+
try {
|
|
248
|
+
const dot = value.indexOf(".");
|
|
249
|
+
if (dot <= 0 || dot === value.length - 1) return null;
|
|
250
|
+
const encodedPayload = value.slice(0, dot);
|
|
251
|
+
const providedSignature = value.slice(dot + 1);
|
|
252
|
+
const expectedSignature = hmac(options.secret, encodedPayload);
|
|
253
|
+
const provided = Buffer.from(providedSignature, "base64url");
|
|
254
|
+
const expected = Buffer.from(expectedSignature, "base64url");
|
|
255
|
+
if (provided.length !== expected.length) return null;
|
|
256
|
+
if (!(0, import_node_crypto.timingSafeEqual)(provided, expected)) return null;
|
|
257
|
+
const decoded = JSON.parse(base64urlDecode(encodedPayload));
|
|
258
|
+
if (!isSessionPayload(decoded)) return null;
|
|
259
|
+
const now = options.now ?? Date.now();
|
|
260
|
+
if (now > decoded.exp + EXP_GRACE_MS) return null;
|
|
261
|
+
const session = {
|
|
262
|
+
sub: decoded.sub,
|
|
263
|
+
...decoded.name !== void 0 ? {
|
|
264
|
+
name: decoded.name
|
|
265
|
+
} : {},
|
|
266
|
+
roles: decoded.roles,
|
|
267
|
+
iat: decoded.iat,
|
|
268
|
+
exp: decoded.exp
|
|
269
|
+
};
|
|
270
|
+
return session;
|
|
271
|
+
} catch {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
__name(verifySessionCookie, "verifySessionCookie");
|
|
276
|
+
|
|
277
|
+
// src/server/auth/session-cookie-io.ts
|
|
278
|
+
var SESSION_COOKIE_NAME = "agent_dashboard_session";
|
|
279
|
+
var COOKIE_PATH = "/";
|
|
280
|
+
function issueSessionCookie(user, context) {
|
|
281
|
+
const value = signSessionCookie(user, {
|
|
282
|
+
secret: context.auth.secret,
|
|
283
|
+
ttlMs: context.auth.ttlMs,
|
|
284
|
+
...context.now !== void 0 ? {
|
|
285
|
+
now: context.now
|
|
286
|
+
} : {}
|
|
287
|
+
});
|
|
288
|
+
const cookie = serializeSetCookie(SESSION_COOKIE_NAME, value, {
|
|
289
|
+
path: COOKIE_PATH,
|
|
290
|
+
maxAgeSeconds: Math.floor(context.auth.ttlMs / 1e3),
|
|
291
|
+
secure: isHttpsRequest(context.request)
|
|
292
|
+
});
|
|
293
|
+
appendSetCookie(context.response, cookie);
|
|
294
|
+
}
|
|
295
|
+
__name(issueSessionCookie, "issueSessionCookie");
|
|
296
|
+
function clearSessionCookie(context) {
|
|
297
|
+
const cookie = serializeSetCookie(SESSION_COOKIE_NAME, "", {
|
|
298
|
+
path: COOKIE_PATH,
|
|
299
|
+
maxAgeSeconds: 0,
|
|
300
|
+
secure: isHttpsRequest(context.request),
|
|
301
|
+
clear: true
|
|
302
|
+
});
|
|
303
|
+
appendSetCookie(context.response, cookie);
|
|
304
|
+
}
|
|
305
|
+
__name(clearSessionCookie, "clearSessionCookie");
|
|
306
|
+
|
|
307
|
+
// src/server/auth/dashboard-auth.guard.ts
|
|
308
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
309
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
310
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
311
|
+
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;
|
|
312
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
313
|
+
}
|
|
314
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
315
|
+
function _ts_metadata(k, v) {
|
|
316
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
317
|
+
}
|
|
318
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
319
|
+
function _ts_param(paramIndex, decorator) {
|
|
320
|
+
return function(target, key) {
|
|
321
|
+
decorator(target, key, paramIndex);
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
__name(_ts_param, "_ts_param");
|
|
325
|
+
var DashboardAuthGuard = class {
|
|
326
|
+
static {
|
|
327
|
+
__name(this, "DashboardAuthGuard");
|
|
328
|
+
}
|
|
329
|
+
auth;
|
|
330
|
+
constructor(auth) {
|
|
331
|
+
this.auth = auth;
|
|
332
|
+
}
|
|
333
|
+
canActivate(context) {
|
|
334
|
+
if (!this.auth) return true;
|
|
335
|
+
const http = context.switchToHttp();
|
|
336
|
+
const request = http.getRequest();
|
|
337
|
+
const session = this.verifyRequestSession(request);
|
|
338
|
+
if (!session) throw new import_common.UnauthorizedException();
|
|
339
|
+
attachSession(request, session);
|
|
340
|
+
this.maybeRenew(http.getResponse(), request, session);
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
verifyRequestSession(request) {
|
|
344
|
+
const auth = this.auth;
|
|
345
|
+
if (!auth) return null;
|
|
346
|
+
const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
|
|
347
|
+
if (cookieValue === void 0) return null;
|
|
348
|
+
return verifySessionCookie(cookieValue, {
|
|
349
|
+
secret: auth.secret
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Sliding renewal: a valid cookie past 50% of its TTL is transparently re-issued on the
|
|
354
|
+
* response, so an active user never gets logged out mid-session.
|
|
355
|
+
*/
|
|
356
|
+
maybeRenew(response, request, session) {
|
|
357
|
+
const auth = this.auth;
|
|
358
|
+
if (!auth) return;
|
|
359
|
+
const now = Date.now();
|
|
360
|
+
if (now - session.iat <= auth.ttlMs / 2) return;
|
|
361
|
+
issueSessionCookie({
|
|
362
|
+
id: session.sub,
|
|
363
|
+
...session.name !== void 0 ? {
|
|
364
|
+
name: session.name
|
|
365
|
+
} : {},
|
|
366
|
+
roles: session.roles
|
|
367
|
+
}, {
|
|
368
|
+
auth,
|
|
369
|
+
request,
|
|
370
|
+
response,
|
|
371
|
+
now
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
DashboardAuthGuard = _ts_decorate([
|
|
376
|
+
(0, import_common.Injectable)(),
|
|
377
|
+
_ts_param(0, (0, import_common.Optional)()),
|
|
378
|
+
_ts_param(0, (0, import_common.Inject)(DASHBOARD_AUTH)),
|
|
379
|
+
_ts_metadata("design:type", Function),
|
|
380
|
+
_ts_metadata("design:paramtypes", [
|
|
381
|
+
Object
|
|
382
|
+
])
|
|
383
|
+
], DashboardAuthGuard);
|
|
45
384
|
|
|
46
385
|
// src/server/dashboard.service.ts
|
|
47
386
|
var import_node_diagnostics_channel = require("diagnostics_channel");
|
|
48
387
|
var import_nestjs_diagnostics = require("@dudousxd/nestjs-diagnostics");
|
|
49
|
-
var
|
|
388
|
+
var import_common4 = require("@nestjs/common");
|
|
50
389
|
var import_rxjs = require("rxjs");
|
|
51
390
|
|
|
52
391
|
// src/server/parse-approval-decision.ts
|
|
53
|
-
var
|
|
392
|
+
var import_common2 = require("@nestjs/common");
|
|
54
393
|
function parseApprovalDecision(body) {
|
|
55
394
|
if (typeof body !== "object" || body === null) {
|
|
56
|
-
throw new
|
|
395
|
+
throw new import_common2.BadRequestException("Expected a JSON object body.");
|
|
57
396
|
}
|
|
58
397
|
const { approved, reason } = body;
|
|
59
398
|
if (typeof approved !== "boolean") {
|
|
60
|
-
throw new
|
|
399
|
+
throw new import_common2.BadRequestException('"approved" must be a boolean.');
|
|
61
400
|
}
|
|
62
401
|
if (reason !== void 0 && typeof reason !== "string") {
|
|
63
|
-
throw new
|
|
402
|
+
throw new import_common2.BadRequestException('"reason" must be a string when present.');
|
|
64
403
|
}
|
|
65
404
|
return {
|
|
66
405
|
approved,
|
|
@@ -72,26 +411,26 @@ function parseApprovalDecision(body) {
|
|
|
72
411
|
__name(parseApprovalDecision, "parseApprovalDecision");
|
|
73
412
|
|
|
74
413
|
// src/server/parse-price-input.ts
|
|
75
|
-
var
|
|
414
|
+
var import_common3 = require("@nestjs/common");
|
|
76
415
|
function parsePriceInput(body) {
|
|
77
416
|
if (typeof body !== "object" || body === null) {
|
|
78
|
-
throw new
|
|
417
|
+
throw new import_common3.BadRequestException("Expected a JSON object body.");
|
|
79
418
|
}
|
|
80
419
|
const { modelId, inputPricePer1m, outputPricePer1m, cacheWritePricePer1m, cacheReadPricePer1m } = body;
|
|
81
420
|
if (typeof modelId !== "string" || modelId.trim().length === 0) {
|
|
82
|
-
throw new
|
|
421
|
+
throw new import_common3.BadRequestException('"modelId" must be a non-empty string.');
|
|
83
422
|
}
|
|
84
423
|
if (!isFiniteNonNegative(inputPricePer1m)) {
|
|
85
|
-
throw new
|
|
424
|
+
throw new import_common3.BadRequestException('"inputPricePer1m" must be a non-negative number.');
|
|
86
425
|
}
|
|
87
426
|
if (!isFiniteNonNegative(outputPricePer1m)) {
|
|
88
|
-
throw new
|
|
427
|
+
throw new import_common3.BadRequestException('"outputPricePer1m" must be a non-negative number.');
|
|
89
428
|
}
|
|
90
429
|
if (cacheWritePricePer1m !== void 0 && !isFiniteNonNegative(cacheWritePricePer1m)) {
|
|
91
|
-
throw new
|
|
430
|
+
throw new import_common3.BadRequestException('"cacheWritePricePer1m" must be a non-negative number when present.');
|
|
92
431
|
}
|
|
93
432
|
if (cacheReadPricePer1m !== void 0 && !isFiniteNonNegative(cacheReadPricePer1m)) {
|
|
94
|
-
throw new
|
|
433
|
+
throw new import_common3.BadRequestException('"cacheReadPricePer1m" must be a non-negative number when present.');
|
|
95
434
|
}
|
|
96
435
|
return {
|
|
97
436
|
modelId,
|
|
@@ -111,34 +450,24 @@ function isFiniteNonNegative(value) {
|
|
|
111
450
|
}
|
|
112
451
|
__name(isFiniteNonNegative, "isFiniteNonNegative");
|
|
113
452
|
|
|
114
|
-
// src/server/tokens.ts
|
|
115
|
-
var AGENT_GOVERNANCE_QUERIES = Symbol.for("@dudousxd/nestjs-agent:governance-queries");
|
|
116
|
-
var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
|
|
117
|
-
var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
|
|
118
|
-
var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
|
|
119
|
-
var AGENT_ACTOR_RESOLVER = Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
|
|
120
|
-
var DASHBOARD_BASE_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
|
|
121
|
-
var DASHBOARD_API_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
|
|
122
|
-
var DASHBOARD_APPROVAL_ACTOR_REF = Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
|
|
123
|
-
|
|
124
453
|
// src/server/dashboard.service.ts
|
|
125
|
-
function
|
|
454
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
126
455
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
127
456
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
128
457
|
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;
|
|
129
458
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
130
459
|
}
|
|
131
|
-
__name(
|
|
132
|
-
function
|
|
460
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
461
|
+
function _ts_metadata2(k, v) {
|
|
133
462
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
134
463
|
}
|
|
135
|
-
__name(
|
|
136
|
-
function
|
|
464
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
465
|
+
function _ts_param2(paramIndex, decorator) {
|
|
137
466
|
return function(target, key) {
|
|
138
467
|
decorator(target, key, paramIndex);
|
|
139
468
|
};
|
|
140
469
|
}
|
|
141
|
-
__name(
|
|
470
|
+
__name(_ts_param2, "_ts_param");
|
|
142
471
|
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.";
|
|
143
472
|
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.";
|
|
144
473
|
var AGENT_EVENTS = [
|
|
@@ -209,6 +538,14 @@ var DashboardService = class {
|
|
|
209
538
|
recentToolCalls(limit) {
|
|
210
539
|
return this.queries.recentToolCalls(limit);
|
|
211
540
|
}
|
|
541
|
+
/** Paged, filterable tool calls for the Runs & tools activity table. */
|
|
542
|
+
toolCallsPage(query) {
|
|
543
|
+
return this.queries.toolCallsPage(query);
|
|
544
|
+
}
|
|
545
|
+
/** Paged, filterable runs for the Reliability recent-runs table. */
|
|
546
|
+
runsPage(query) {
|
|
547
|
+
return this.queries.runsPage(query);
|
|
548
|
+
}
|
|
212
549
|
/** Tool calls sitting `pending_approval`, oldest first, for the cross-thread approvals inbox. */
|
|
213
550
|
pendingApprovals(limit) {
|
|
214
551
|
return this.queries.pendingApprovals(limit);
|
|
@@ -227,7 +564,7 @@ var DashboardService = class {
|
|
|
227
564
|
*/
|
|
228
565
|
async decideApproval(toolCallId, body, executedByRef) {
|
|
229
566
|
if (this.approvalPort === void 0) {
|
|
230
|
-
throw new
|
|
567
|
+
throw new import_common4.NotImplementedException(APPROVAL_PORT_UNBOUND_MESSAGE);
|
|
231
568
|
}
|
|
232
569
|
const decision = parseApprovalDecision(body);
|
|
233
570
|
const opts = executedByRef !== void 0 ? {
|
|
@@ -250,6 +587,18 @@ var DashboardService = class {
|
|
|
250
587
|
return this.withActorLabels(rows);
|
|
251
588
|
}
|
|
252
589
|
/**
|
|
590
|
+
* Paged, filterable threads for the Runs & tools threads table — actor-labeled the same way
|
|
591
|
+
* {@link recentThreads} is.
|
|
592
|
+
*/
|
|
593
|
+
async threadsPage(query) {
|
|
594
|
+
const page = await this.queries.threadsPage(query);
|
|
595
|
+
const rows = await this.withActorLabels(page.rows);
|
|
596
|
+
return {
|
|
597
|
+
...page,
|
|
598
|
+
rows
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
253
602
|
* Decorate actor-scoped rows with `actorLabel`, batching the distinct `actorRef`s into ONE
|
|
254
603
|
* {@link ActorDirectory.resolveDisplay} call per response. `null` for every row when no directory
|
|
255
604
|
* is bound, or for a ref the directory didn't resolve.
|
|
@@ -276,7 +625,7 @@ var DashboardService = class {
|
|
|
276
625
|
/** Current price row per model, for the pricing tab. 501s when no `AGENT_PRICING_STORE` is bound. */
|
|
277
626
|
async listPrices() {
|
|
278
627
|
if (this.pricingStore === void 0) {
|
|
279
|
-
throw new
|
|
628
|
+
throw new import_common4.NotImplementedException(PRICING_STORE_UNBOUND_MESSAGE);
|
|
280
629
|
}
|
|
281
630
|
return this.pricingStore.listCurrentPrices();
|
|
282
631
|
}
|
|
@@ -287,7 +636,7 @@ var DashboardService = class {
|
|
|
287
636
|
*/
|
|
288
637
|
async upsertPrice(body) {
|
|
289
638
|
if (this.pricingStore === void 0) {
|
|
290
|
-
throw new
|
|
639
|
+
throw new import_common4.NotImplementedException(PRICING_STORE_UNBOUND_MESSAGE);
|
|
291
640
|
}
|
|
292
641
|
await this.pricingStore.upsertModelPrice(parsePriceInput(body));
|
|
293
642
|
}
|
|
@@ -322,17 +671,17 @@ var DashboardService = class {
|
|
|
322
671
|
});
|
|
323
672
|
}
|
|
324
673
|
};
|
|
325
|
-
DashboardService =
|
|
326
|
-
(0,
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
674
|
+
DashboardService = _ts_decorate2([
|
|
675
|
+
(0, import_common4.Injectable)(),
|
|
676
|
+
_ts_param2(0, (0, import_common4.Inject)(AGENT_GOVERNANCE_QUERIES)),
|
|
677
|
+
_ts_param2(1, (0, import_common4.Optional)()),
|
|
678
|
+
_ts_param2(1, (0, import_common4.Inject)(AGENT_ACTOR_DIRECTORY)),
|
|
679
|
+
_ts_param2(2, (0, import_common4.Optional)()),
|
|
680
|
+
_ts_param2(2, (0, import_common4.Inject)(AGENT_PRICING_STORE)),
|
|
681
|
+
_ts_param2(3, (0, import_common4.Optional)()),
|
|
682
|
+
_ts_param2(3, (0, import_common4.Inject)(AGENT_APPROVAL_PORT)),
|
|
683
|
+
_ts_metadata2("design:type", Function),
|
|
684
|
+
_ts_metadata2("design:paramtypes", [
|
|
336
685
|
typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries,
|
|
337
686
|
typeof ActorDirectory === "undefined" ? Object : ActorDirectory,
|
|
338
687
|
typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
|
|
@@ -340,32 +689,153 @@ DashboardService = _ts_decorate([
|
|
|
340
689
|
])
|
|
341
690
|
], DashboardService);
|
|
342
691
|
|
|
692
|
+
// src/server/parse-page-query.ts
|
|
693
|
+
var import_common5 = require("@nestjs/common");
|
|
694
|
+
var ISO_DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
695
|
+
function parsePageNumber(value) {
|
|
696
|
+
const parsed = value === void 0 ? Number.NaN : Number.parseInt(value, 10);
|
|
697
|
+
if (!Number.isFinite(parsed) || parsed < 1) return 1;
|
|
698
|
+
return parsed;
|
|
699
|
+
}
|
|
700
|
+
__name(parsePageNumber, "parsePageNumber");
|
|
701
|
+
function assertKnownFields(raw, allowed) {
|
|
702
|
+
for (const field of Object.keys(raw)) {
|
|
703
|
+
if (!allowed.includes(field)) {
|
|
704
|
+
throw new import_common5.BadRequestException(`Unknown where field "${field}".`);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
__name(assertKnownFields, "assertKnownFields");
|
|
709
|
+
function assertDayFields(raw, dayFields) {
|
|
710
|
+
for (const field of dayFields) {
|
|
711
|
+
const value = raw[field];
|
|
712
|
+
if (value !== void 0 && !ISO_DAY.test(value)) {
|
|
713
|
+
throw new import_common5.BadRequestException(`"where[${field}]" must be YYYY-MM-DD.`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
__name(assertDayFields, "assertDayFields");
|
|
718
|
+
var DAY_FIELDS = [
|
|
719
|
+
"fromDay",
|
|
720
|
+
"toDay"
|
|
721
|
+
];
|
|
722
|
+
var TOOL_CALL_WHERE_FIELDS = [
|
|
723
|
+
"toolName",
|
|
724
|
+
"toolType",
|
|
725
|
+
"status",
|
|
726
|
+
"threadId",
|
|
727
|
+
"fromDay",
|
|
728
|
+
"toDay"
|
|
729
|
+
];
|
|
730
|
+
function parseToolCallWhere(raw) {
|
|
731
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
732
|
+
assertKnownFields(raw, TOOL_CALL_WHERE_FIELDS);
|
|
733
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
734
|
+
return {
|
|
735
|
+
...raw.toolName !== void 0 ? {
|
|
736
|
+
toolName: raw.toolName
|
|
737
|
+
} : {},
|
|
738
|
+
...raw.toolType !== void 0 ? {
|
|
739
|
+
toolType: raw.toolType
|
|
740
|
+
} : {},
|
|
741
|
+
...raw.status !== void 0 ? {
|
|
742
|
+
status: raw.status
|
|
743
|
+
} : {},
|
|
744
|
+
...raw.threadId !== void 0 ? {
|
|
745
|
+
threadId: raw.threadId
|
|
746
|
+
} : {},
|
|
747
|
+
...raw.fromDay !== void 0 ? {
|
|
748
|
+
fromDay: raw.fromDay
|
|
749
|
+
} : {},
|
|
750
|
+
...raw.toDay !== void 0 ? {
|
|
751
|
+
toDay: raw.toDay
|
|
752
|
+
} : {}
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
__name(parseToolCallWhere, "parseToolCallWhere");
|
|
756
|
+
var THREAD_WHERE_FIELDS = [
|
|
757
|
+
"actorRef",
|
|
758
|
+
"title",
|
|
759
|
+
"fromDay",
|
|
760
|
+
"toDay"
|
|
761
|
+
];
|
|
762
|
+
function parseThreadWhere(raw) {
|
|
763
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
764
|
+
assertKnownFields(raw, THREAD_WHERE_FIELDS);
|
|
765
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
766
|
+
return {
|
|
767
|
+
...raw.actorRef !== void 0 ? {
|
|
768
|
+
actorRef: raw.actorRef
|
|
769
|
+
} : {},
|
|
770
|
+
...raw.title !== void 0 ? {
|
|
771
|
+
title: raw.title
|
|
772
|
+
} : {},
|
|
773
|
+
...raw.fromDay !== void 0 ? {
|
|
774
|
+
fromDay: raw.fromDay
|
|
775
|
+
} : {},
|
|
776
|
+
...raw.toDay !== void 0 ? {
|
|
777
|
+
toDay: raw.toDay
|
|
778
|
+
} : {}
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
__name(parseThreadWhere, "parseThreadWhere");
|
|
782
|
+
var RUN_WHERE_FIELDS = [
|
|
783
|
+
"agentName",
|
|
784
|
+
"status",
|
|
785
|
+
"errorCode",
|
|
786
|
+
"fromDay",
|
|
787
|
+
"toDay"
|
|
788
|
+
];
|
|
789
|
+
function parseRunWhere(raw) {
|
|
790
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
791
|
+
assertKnownFields(raw, RUN_WHERE_FIELDS);
|
|
792
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
793
|
+
return {
|
|
794
|
+
...raw.agentName !== void 0 ? {
|
|
795
|
+
agentName: raw.agentName
|
|
796
|
+
} : {},
|
|
797
|
+
...raw.status !== void 0 ? {
|
|
798
|
+
status: raw.status
|
|
799
|
+
} : {},
|
|
800
|
+
...raw.errorCode !== void 0 ? {
|
|
801
|
+
errorCode: raw.errorCode
|
|
802
|
+
} : {},
|
|
803
|
+
...raw.fromDay !== void 0 ? {
|
|
804
|
+
fromDay: raw.fromDay
|
|
805
|
+
} : {},
|
|
806
|
+
...raw.toDay !== void 0 ? {
|
|
807
|
+
toDay: raw.toDay
|
|
808
|
+
} : {}
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
__name(parseRunWhere, "parseRunWhere");
|
|
812
|
+
|
|
343
813
|
// src/server/agent-api.controller.ts
|
|
344
|
-
function
|
|
814
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
345
815
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
346
816
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
347
817
|
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;
|
|
348
818
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
349
819
|
}
|
|
350
|
-
__name(
|
|
351
|
-
function
|
|
820
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
821
|
+
function _ts_metadata3(k, v) {
|
|
352
822
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
353
823
|
}
|
|
354
|
-
__name(
|
|
355
|
-
function
|
|
824
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
825
|
+
function _ts_param3(paramIndex, decorator) {
|
|
356
826
|
return function(target, key) {
|
|
357
827
|
decorator(target, key, paramIndex);
|
|
358
828
|
};
|
|
359
829
|
}
|
|
360
|
-
__name(
|
|
830
|
+
__name(_ts_param3, "_ts_param");
|
|
361
831
|
var DAY_MS = 864e5;
|
|
362
|
-
var
|
|
832
|
+
var ISO_DAY2 = /^\d{4}-\d{2}-\d{2}$/;
|
|
363
833
|
function utcDay(daysAgo) {
|
|
364
834
|
return new Date(Date.now() - daysAgo * DAY_MS).toISOString().slice(0, 10);
|
|
365
835
|
}
|
|
366
836
|
__name(utcDay, "utcDay");
|
|
367
837
|
function dayOr(value, fallback) {
|
|
368
|
-
return value !== void 0 &&
|
|
838
|
+
return value !== void 0 && ISO_DAY2.test(value) ? value : fallback;
|
|
369
839
|
}
|
|
370
840
|
__name(dayOr, "dayOr");
|
|
371
841
|
function resolveRange(from, to) {
|
|
@@ -409,10 +879,40 @@ var AgentApiController = class {
|
|
|
409
879
|
runs(limit) {
|
|
410
880
|
return this.dashboard.recentRuns(parseLimit(limit, 50));
|
|
411
881
|
}
|
|
882
|
+
/**
|
|
883
|
+
* Paged, filterable runs for the Reliability recent-runs table. `page` (default 1), `limit`
|
|
884
|
+
* (default 25, max 200), and `where[agentName]`/`where[status]`/`where[errorCode]`/
|
|
885
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
886
|
+
*/
|
|
887
|
+
runsPage(page, limit, where) {
|
|
888
|
+
const parsedWhere = parseRunWhere(where);
|
|
889
|
+
return this.dashboard.runsPage({
|
|
890
|
+
page: parsePageNumber(page),
|
|
891
|
+
pageSize: parseLimit(limit, 25),
|
|
892
|
+
...parsedWhere !== void 0 ? {
|
|
893
|
+
where: parsedWhere
|
|
894
|
+
} : {}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
412
897
|
/** Most recent tool calls (default 50, max 200) for the activity feed. */
|
|
413
898
|
toolCalls(limit) {
|
|
414
899
|
return this.dashboard.recentToolCalls(parseLimit(limit, 50));
|
|
415
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* Paged, filterable tool calls for the Runs & tools activity table. `page` (default 1), `limit`
|
|
903
|
+
* (default 25, max 200), and `where[toolName]`/`where[toolType]`/`where[status]`/`where[threadId]`/
|
|
904
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
905
|
+
*/
|
|
906
|
+
toolCallsPage(page, limit, where) {
|
|
907
|
+
const parsedWhere = parseToolCallWhere(where);
|
|
908
|
+
return this.dashboard.toolCallsPage({
|
|
909
|
+
page: parsePageNumber(page),
|
|
910
|
+
pageSize: parseLimit(limit, 25),
|
|
911
|
+
...parsedWhere !== void 0 ? {
|
|
912
|
+
where: parsedWhere
|
|
913
|
+
} : {}
|
|
914
|
+
});
|
|
915
|
+
}
|
|
416
916
|
/** Tool calls sitting `pending_approval` (default 50, max 200), oldest first — the approvals inbox. */
|
|
417
917
|
approvals(limit) {
|
|
418
918
|
return this.dashboard.pendingApprovals(parseLimit(limit, 50));
|
|
@@ -454,6 +954,21 @@ var AgentApiController = class {
|
|
|
454
954
|
return this.dashboard.recentThreads(parseLimit(limit, 50));
|
|
455
955
|
}
|
|
456
956
|
/**
|
|
957
|
+
* Paged, filterable threads for the Runs & tools threads table. `page` (default 1), `limit`
|
|
958
|
+
* (default 25, max 200), and `where[actorRef]`/`where[title]` (case-insensitive substring)/
|
|
959
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
960
|
+
*/
|
|
961
|
+
threadsPage(page, limit, where) {
|
|
962
|
+
const parsedWhere = parseThreadWhere(where);
|
|
963
|
+
return this.dashboard.threadsPage({
|
|
964
|
+
page: parsePageNumber(page),
|
|
965
|
+
pageSize: parseLimit(limit, 25),
|
|
966
|
+
...parsedWhere !== void 0 ? {
|
|
967
|
+
where: parsedWhere
|
|
968
|
+
} : {}
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
457
972
|
* Current price row per model, for the pricing tab. 501s (via `DashboardService.listPrices`) when
|
|
458
973
|
* no `AGENT_PRICING_STORE` is bound.
|
|
459
974
|
*/
|
|
@@ -473,136 +988,469 @@ var AgentApiController = class {
|
|
|
473
988
|
return this.dashboard.streamEvents();
|
|
474
989
|
}
|
|
475
990
|
};
|
|
476
|
-
|
|
477
|
-
(0,
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
991
|
+
_ts_decorate3([
|
|
992
|
+
(0, import_common6.Get)("spend"),
|
|
993
|
+
_ts_param3(0, (0, import_common6.Query)("from")),
|
|
994
|
+
_ts_param3(1, (0, import_common6.Query)("to")),
|
|
995
|
+
_ts_metadata3("design:type", Function),
|
|
996
|
+
_ts_metadata3("design:paramtypes", [
|
|
482
997
|
String,
|
|
483
998
|
String
|
|
484
999
|
]),
|
|
485
|
-
|
|
1000
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
486
1001
|
], AgentApiController.prototype, "spend", null);
|
|
487
|
-
|
|
488
|
-
(0,
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
1002
|
+
_ts_decorate3([
|
|
1003
|
+
(0, import_common6.Get)("top-threads"),
|
|
1004
|
+
_ts_param3(0, (0, import_common6.Query)("from")),
|
|
1005
|
+
_ts_param3(1, (0, import_common6.Query)("to")),
|
|
1006
|
+
_ts_param3(2, (0, import_common6.Query)("limit")),
|
|
1007
|
+
_ts_metadata3("design:type", Function),
|
|
1008
|
+
_ts_metadata3("design:paramtypes", [
|
|
494
1009
|
String,
|
|
495
1010
|
String,
|
|
496
1011
|
String
|
|
497
1012
|
]),
|
|
498
|
-
|
|
1013
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
499
1014
|
], AgentApiController.prototype, "topThreads", null);
|
|
500
|
-
|
|
501
|
-
(0,
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
1015
|
+
_ts_decorate3([
|
|
1016
|
+
(0, import_common6.Get)("reliability"),
|
|
1017
|
+
_ts_param3(0, (0, import_common6.Query)("from")),
|
|
1018
|
+
_ts_param3(1, (0, import_common6.Query)("to")),
|
|
1019
|
+
_ts_metadata3("design:type", Function),
|
|
1020
|
+
_ts_metadata3("design:paramtypes", [
|
|
506
1021
|
String,
|
|
507
1022
|
String
|
|
508
1023
|
]),
|
|
509
|
-
|
|
1024
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
510
1025
|
], AgentApiController.prototype, "reliability", null);
|
|
511
|
-
|
|
512
|
-
(0,
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
1026
|
+
_ts_decorate3([
|
|
1027
|
+
(0, import_common6.Get)("runs"),
|
|
1028
|
+
_ts_param3(0, (0, import_common6.Query)("limit")),
|
|
1029
|
+
_ts_metadata3("design:type", Function),
|
|
1030
|
+
_ts_metadata3("design:paramtypes", [
|
|
516
1031
|
String
|
|
517
1032
|
]),
|
|
518
|
-
|
|
1033
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
519
1034
|
], AgentApiController.prototype, "runs", null);
|
|
520
|
-
|
|
521
|
-
(0,
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
1035
|
+
_ts_decorate3([
|
|
1036
|
+
(0, import_common6.Get)("runs-page"),
|
|
1037
|
+
_ts_param3(0, (0, import_common6.Query)("page")),
|
|
1038
|
+
_ts_param3(1, (0, import_common6.Query)("limit")),
|
|
1039
|
+
_ts_param3(2, (0, import_common6.Query)("where")),
|
|
1040
|
+
_ts_metadata3("design:type", Function),
|
|
1041
|
+
_ts_metadata3("design:paramtypes", [
|
|
1042
|
+
String,
|
|
1043
|
+
String,
|
|
1044
|
+
typeof Record === "undefined" ? Object : Record
|
|
1045
|
+
]),
|
|
1046
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
1047
|
+
], AgentApiController.prototype, "runsPage", null);
|
|
1048
|
+
_ts_decorate3([
|
|
1049
|
+
(0, import_common6.Get)("tool-calls"),
|
|
1050
|
+
_ts_param3(0, (0, import_common6.Query)("limit")),
|
|
1051
|
+
_ts_metadata3("design:type", Function),
|
|
1052
|
+
_ts_metadata3("design:paramtypes", [
|
|
525
1053
|
String
|
|
526
1054
|
]),
|
|
527
|
-
|
|
1055
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
528
1056
|
], AgentApiController.prototype, "toolCalls", null);
|
|
529
|
-
|
|
530
|
-
(0,
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
1057
|
+
_ts_decorate3([
|
|
1058
|
+
(0, import_common6.Get)("tool-calls-page"),
|
|
1059
|
+
_ts_param3(0, (0, import_common6.Query)("page")),
|
|
1060
|
+
_ts_param3(1, (0, import_common6.Query)("limit")),
|
|
1061
|
+
_ts_param3(2, (0, import_common6.Query)("where")),
|
|
1062
|
+
_ts_metadata3("design:type", Function),
|
|
1063
|
+
_ts_metadata3("design:paramtypes", [
|
|
1064
|
+
String,
|
|
1065
|
+
String,
|
|
1066
|
+
typeof Record === "undefined" ? Object : Record
|
|
1067
|
+
]),
|
|
1068
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
1069
|
+
], AgentApiController.prototype, "toolCallsPage", null);
|
|
1070
|
+
_ts_decorate3([
|
|
1071
|
+
(0, import_common6.Get)("approvals"),
|
|
1072
|
+
_ts_param3(0, (0, import_common6.Query)("limit")),
|
|
1073
|
+
_ts_metadata3("design:type", Function),
|
|
1074
|
+
_ts_metadata3("design:paramtypes", [
|
|
534
1075
|
String
|
|
535
1076
|
]),
|
|
536
|
-
|
|
1077
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
537
1078
|
], AgentApiController.prototype, "approvals", null);
|
|
538
|
-
|
|
539
|
-
(0,
|
|
540
|
-
(0,
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
1079
|
+
_ts_decorate3([
|
|
1080
|
+
(0, import_common6.Post)("approvals/:toolCallId"),
|
|
1081
|
+
(0, import_common6.HttpCode)(204),
|
|
1082
|
+
_ts_param3(0, (0, import_common6.Param)("toolCallId")),
|
|
1083
|
+
_ts_param3(1, (0, import_common6.Body)()),
|
|
1084
|
+
_ts_param3(2, (0, import_common6.Req)()),
|
|
1085
|
+
_ts_metadata3("design:type", Function),
|
|
1086
|
+
_ts_metadata3("design:paramtypes", [
|
|
546
1087
|
String,
|
|
547
1088
|
Object,
|
|
548
1089
|
Object
|
|
549
1090
|
]),
|
|
550
|
-
|
|
1091
|
+
_ts_metadata3("design:returntype", Promise)
|
|
551
1092
|
], AgentApiController.prototype, "decideApproval", null);
|
|
552
|
-
|
|
553
|
-
(0,
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
1093
|
+
_ts_decorate3([
|
|
1094
|
+
(0, import_common6.Get)("tools"),
|
|
1095
|
+
_ts_param3(0, (0, import_common6.Query)("from")),
|
|
1096
|
+
_ts_param3(1, (0, import_common6.Query)("to")),
|
|
1097
|
+
_ts_metadata3("design:type", Function),
|
|
1098
|
+
_ts_metadata3("design:paramtypes", [
|
|
558
1099
|
String,
|
|
559
1100
|
String
|
|
560
1101
|
]),
|
|
561
|
-
|
|
1102
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
562
1103
|
], AgentApiController.prototype, "tools", null);
|
|
563
|
-
|
|
564
|
-
(0,
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
1104
|
+
_ts_decorate3([
|
|
1105
|
+
(0, import_common6.Get)("threads"),
|
|
1106
|
+
_ts_param3(0, (0, import_common6.Query)("limit")),
|
|
1107
|
+
_ts_metadata3("design:type", Function),
|
|
1108
|
+
_ts_metadata3("design:paramtypes", [
|
|
568
1109
|
String
|
|
569
1110
|
]),
|
|
570
|
-
|
|
1111
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
571
1112
|
], AgentApiController.prototype, "threads", null);
|
|
572
|
-
|
|
573
|
-
(0,
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
1113
|
+
_ts_decorate3([
|
|
1114
|
+
(0, import_common6.Get)("threads-page"),
|
|
1115
|
+
_ts_param3(0, (0, import_common6.Query)("page")),
|
|
1116
|
+
_ts_param3(1, (0, import_common6.Query)("limit")),
|
|
1117
|
+
_ts_param3(2, (0, import_common6.Query)("where")),
|
|
1118
|
+
_ts_metadata3("design:type", Function),
|
|
1119
|
+
_ts_metadata3("design:paramtypes", [
|
|
1120
|
+
String,
|
|
1121
|
+
String,
|
|
1122
|
+
typeof Record === "undefined" ? Object : Record
|
|
1123
|
+
]),
|
|
1124
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
1125
|
+
], AgentApiController.prototype, "threadsPage", null);
|
|
1126
|
+
_ts_decorate3([
|
|
1127
|
+
(0, import_common6.Get)("pricing"),
|
|
1128
|
+
_ts_metadata3("design:type", Function),
|
|
1129
|
+
_ts_metadata3("design:paramtypes", []),
|
|
1130
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
577
1131
|
], AgentApiController.prototype, "listPrices", null);
|
|
578
|
-
|
|
579
|
-
(0,
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
1132
|
+
_ts_decorate3([
|
|
1133
|
+
(0, import_common6.Post)("pricing"),
|
|
1134
|
+
_ts_param3(0, (0, import_common6.Body)()),
|
|
1135
|
+
_ts_metadata3("design:type", Function),
|
|
1136
|
+
_ts_metadata3("design:paramtypes", [
|
|
583
1137
|
Object
|
|
584
1138
|
]),
|
|
585
|
-
|
|
1139
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
586
1140
|
], AgentApiController.prototype, "upsertPrice", null);
|
|
587
|
-
|
|
588
|
-
(0,
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
1141
|
+
_ts_decorate3([
|
|
1142
|
+
(0, import_common6.Sse)("stream"),
|
|
1143
|
+
_ts_metadata3("design:type", Function),
|
|
1144
|
+
_ts_metadata3("design:paramtypes", []),
|
|
1145
|
+
_ts_metadata3("design:returntype", typeof Observable === "undefined" ? Object : Observable)
|
|
592
1146
|
], AgentApiController.prototype, "stream", null);
|
|
593
|
-
AgentApiController =
|
|
594
|
-
(0,
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
1147
|
+
AgentApiController = _ts_decorate3([
|
|
1148
|
+
(0, import_common6.Controller)(),
|
|
1149
|
+
(0, import_common6.UseGuards)(DashboardAuthGuard),
|
|
1150
|
+
_ts_param3(1, (0, import_common6.Inject)(DASHBOARD_APPROVAL_ACTOR_REF)),
|
|
1151
|
+
_ts_param3(2, (0, import_common6.Optional)()),
|
|
1152
|
+
_ts_param3(2, (0, import_common6.Inject)(AGENT_ACTOR_RESOLVER)),
|
|
1153
|
+
_ts_metadata3("design:type", Function),
|
|
1154
|
+
_ts_metadata3("design:paramtypes", [
|
|
600
1155
|
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
601
1156
|
Object,
|
|
602
1157
|
typeof ActorResolver === "undefined" ? Object : ActorResolver
|
|
603
1158
|
])
|
|
604
1159
|
], AgentApiController);
|
|
605
1160
|
|
|
1161
|
+
// src/server/agent-dashboard-auth.controller.ts
|
|
1162
|
+
var import_common7 = require("@nestjs/common");
|
|
1163
|
+
|
|
1164
|
+
// src/server/auth/login-page.ts
|
|
1165
|
+
function escapeHtml(value) {
|
|
1166
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1167
|
+
}
|
|
1168
|
+
__name(escapeHtml, "escapeHtml");
|
|
1169
|
+
function renderLoginPage(options) {
|
|
1170
|
+
const action = escapeHtml(options.actionUrl);
|
|
1171
|
+
const returnTo = escapeHtml(options.returnTo);
|
|
1172
|
+
const errorBanner = options.error === true ? '<p role="alert" class="error">Invalid username or password.</p>' : "";
|
|
1173
|
+
return `<!doctype html>
|
|
1174
|
+
<html lang="en">
|
|
1175
|
+
<head>
|
|
1176
|
+
<meta charset="utf-8" />
|
|
1177
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1178
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
1179
|
+
<title>Sign in \u2014 AI Gateway</title>
|
|
1180
|
+
<style>
|
|
1181
|
+
:root { color-scheme: dark; }
|
|
1182
|
+
* { box-sizing: border-box; }
|
|
1183
|
+
body {
|
|
1184
|
+
margin: 0;
|
|
1185
|
+
min-height: 100vh;
|
|
1186
|
+
display: flex;
|
|
1187
|
+
align-items: center;
|
|
1188
|
+
justify-content: center;
|
|
1189
|
+
background: #09090b;
|
|
1190
|
+
color: #e4e4e7;
|
|
1191
|
+
font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1192
|
+
padding: 16px;
|
|
1193
|
+
}
|
|
1194
|
+
.card {
|
|
1195
|
+
width: 100%;
|
|
1196
|
+
max-width: 384px;
|
|
1197
|
+
border: 1px solid #27272a;
|
|
1198
|
+
background: #18181b;
|
|
1199
|
+
border-radius: 8px;
|
|
1200
|
+
padding: 32px;
|
|
1201
|
+
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
|
|
1202
|
+
}
|
|
1203
|
+
.brand {
|
|
1204
|
+
margin: 0 0 24px;
|
|
1205
|
+
text-align: center;
|
|
1206
|
+
font-size: 18px;
|
|
1207
|
+
font-weight: 600;
|
|
1208
|
+
color: #34d399;
|
|
1209
|
+
}
|
|
1210
|
+
form { display: flex; flex-direction: column; gap: 16px; }
|
|
1211
|
+
label { display: flex; flex-direction: column; gap: 6px; }
|
|
1212
|
+
.field-label {
|
|
1213
|
+
font-size: 11px;
|
|
1214
|
+
text-transform: uppercase;
|
|
1215
|
+
letter-spacing: 0.05em;
|
|
1216
|
+
color: #71717a;
|
|
1217
|
+
}
|
|
1218
|
+
input {
|
|
1219
|
+
border-radius: 4px;
|
|
1220
|
+
border: 1px solid #3f3f46;
|
|
1221
|
+
background: #09090b;
|
|
1222
|
+
color: #f4f4f5;
|
|
1223
|
+
padding: 8px 12px;
|
|
1224
|
+
font: inherit;
|
|
1225
|
+
outline: none;
|
|
1226
|
+
}
|
|
1227
|
+
input:focus { border-color: rgb(52 211 153 / 0.6); }
|
|
1228
|
+
.error { margin: 0; font-size: 12px; color: #fb7185; }
|
|
1229
|
+
button {
|
|
1230
|
+
margin-top: 8px;
|
|
1231
|
+
border-radius: 4px;
|
|
1232
|
+
border: 1px solid rgb(52 211 153 / 0.4);
|
|
1233
|
+
background: rgb(52 211 153 / 0.1);
|
|
1234
|
+
color: #6ee7b7;
|
|
1235
|
+
padding: 8px 12px;
|
|
1236
|
+
font: inherit;
|
|
1237
|
+
font-size: 12px;
|
|
1238
|
+
font-weight: 500;
|
|
1239
|
+
text-transform: uppercase;
|
|
1240
|
+
letter-spacing: 0.05em;
|
|
1241
|
+
cursor: pointer;
|
|
1242
|
+
}
|
|
1243
|
+
button:hover { background: rgb(52 211 153 / 0.2); }
|
|
1244
|
+
</style>
|
|
1245
|
+
</head>
|
|
1246
|
+
<body>
|
|
1247
|
+
<div class="card">
|
|
1248
|
+
<p class="brand">AI Gateway</p>
|
|
1249
|
+
<form method="post" action="${action}">
|
|
1250
|
+
<input type="hidden" name="returnTo" value="${returnTo}" />
|
|
1251
|
+
<label>
|
|
1252
|
+
<span class="field-label">Username</span>
|
|
1253
|
+
<input type="text" name="username" autocomplete="username" autofocus />
|
|
1254
|
+
</label>
|
|
1255
|
+
<label>
|
|
1256
|
+
<span class="field-label">Password</span>
|
|
1257
|
+
<input type="password" name="password" autocomplete="current-password" />
|
|
1258
|
+
</label>
|
|
1259
|
+
${errorBanner}
|
|
1260
|
+
<button type="submit">Sign in</button>
|
|
1261
|
+
</form>
|
|
1262
|
+
</div>
|
|
1263
|
+
</body>
|
|
1264
|
+
</html>`;
|
|
1265
|
+
}
|
|
1266
|
+
__name(renderLoginPage, "renderLoginPage");
|
|
1267
|
+
|
|
1268
|
+
// src/server/auth/sanitize-return-to.ts
|
|
1269
|
+
function sanitizeReturnTo(basePath, returnTo) {
|
|
1270
|
+
if (typeof returnTo !== "string" || returnTo === "") return basePath;
|
|
1271
|
+
if (!returnTo.startsWith("/") || returnTo.startsWith("//")) return basePath;
|
|
1272
|
+
if (returnTo !== basePath && !returnTo.startsWith(`${basePath}/`) && !returnTo.startsWith(`${basePath}?`)) {
|
|
1273
|
+
return basePath;
|
|
1274
|
+
}
|
|
1275
|
+
return returnTo;
|
|
1276
|
+
}
|
|
1277
|
+
__name(sanitizeReturnTo, "sanitizeReturnTo");
|
|
1278
|
+
|
|
1279
|
+
// src/server/agent-dashboard-auth.controller.ts
|
|
1280
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
1281
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1282
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1283
|
+
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;
|
|
1284
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1285
|
+
}
|
|
1286
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
1287
|
+
function _ts_metadata4(k, v) {
|
|
1288
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1289
|
+
}
|
|
1290
|
+
__name(_ts_metadata4, "_ts_metadata");
|
|
1291
|
+
function _ts_param4(paramIndex, decorator) {
|
|
1292
|
+
return function(target, key) {
|
|
1293
|
+
decorator(target, key, paramIndex);
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
__name(_ts_param4, "_ts_param");
|
|
1297
|
+
function isNonEmptyString(value) {
|
|
1298
|
+
return typeof value === "string" && value !== "";
|
|
1299
|
+
}
|
|
1300
|
+
__name(isNonEmptyString, "isNonEmptyString");
|
|
1301
|
+
var AgentDashboardAuthController = class _AgentDashboardAuthController {
|
|
1302
|
+
static {
|
|
1303
|
+
__name(this, "AgentDashboardAuthController");
|
|
1304
|
+
}
|
|
1305
|
+
auth;
|
|
1306
|
+
basePath;
|
|
1307
|
+
logger = new import_common7.Logger(_AgentDashboardAuthController.name);
|
|
1308
|
+
/** Warn once (not per request) so a broken hook can't be used to flood the logs. */
|
|
1309
|
+
warnedLoginHookThrow = false;
|
|
1310
|
+
constructor(auth, basePath) {
|
|
1311
|
+
this.auth = auth;
|
|
1312
|
+
this.basePath = basePath;
|
|
1313
|
+
}
|
|
1314
|
+
loginPage(req, res, returnToQuery, error) {
|
|
1315
|
+
this.requireAuth();
|
|
1316
|
+
const returnTo = sanitizeReturnTo(this.basePath, returnToQuery);
|
|
1317
|
+
if (this.currentSession(req)) {
|
|
1318
|
+
res.status(302);
|
|
1319
|
+
res.setHeader("Location", returnTo);
|
|
1320
|
+
return "";
|
|
1321
|
+
}
|
|
1322
|
+
return renderLoginPage({
|
|
1323
|
+
actionUrl: `${this.basePath}/auth/login`,
|
|
1324
|
+
returnTo,
|
|
1325
|
+
error: error !== void 0
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
async login(body, req, res) {
|
|
1329
|
+
const auth = this.requireAuth();
|
|
1330
|
+
const returnTo = sanitizeReturnTo(this.basePath, body?.returnTo);
|
|
1331
|
+
const username = body?.username;
|
|
1332
|
+
const password = body?.password;
|
|
1333
|
+
if (!isNonEmptyString(username) || !isNonEmptyString(password)) {
|
|
1334
|
+
this.redirectToLoginError(res, returnTo);
|
|
1335
|
+
return "";
|
|
1336
|
+
}
|
|
1337
|
+
const user = await this.runLoginHook(auth, username, password);
|
|
1338
|
+
if (!user) {
|
|
1339
|
+
this.redirectToLoginError(res, returnTo);
|
|
1340
|
+
return "";
|
|
1341
|
+
}
|
|
1342
|
+
issueSessionCookie(user, {
|
|
1343
|
+
auth,
|
|
1344
|
+
request: req,
|
|
1345
|
+
response: res
|
|
1346
|
+
});
|
|
1347
|
+
res.status(302);
|
|
1348
|
+
res.setHeader("Location", returnTo);
|
|
1349
|
+
return "";
|
|
1350
|
+
}
|
|
1351
|
+
logout(req, res) {
|
|
1352
|
+
clearSessionCookie({
|
|
1353
|
+
request: req,
|
|
1354
|
+
response: res
|
|
1355
|
+
});
|
|
1356
|
+
res.status(302);
|
|
1357
|
+
res.setHeader("Location", `${this.basePath}/auth/login`);
|
|
1358
|
+
return "";
|
|
1359
|
+
}
|
|
1360
|
+
/** Uniform failure: same redirect (generic error flag) whether the user is unknown or the password is wrong. */
|
|
1361
|
+
redirectToLoginError(res, returnTo) {
|
|
1362
|
+
res.status(303);
|
|
1363
|
+
res.setHeader("Location", `${this.basePath}/auth/login?error=1&returnTo=${encodeURIComponent(returnTo)}`);
|
|
1364
|
+
}
|
|
1365
|
+
currentSession(req) {
|
|
1366
|
+
const auth = this.auth;
|
|
1367
|
+
if (!auth) return false;
|
|
1368
|
+
const cookieValue = parseCookieHeader(readCookieHeader(req))[SESSION_COOKIE_NAME];
|
|
1369
|
+
if (cookieValue === void 0) return false;
|
|
1370
|
+
return verifySessionCookie(cookieValue, {
|
|
1371
|
+
secret: auth.secret
|
|
1372
|
+
}) !== null;
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Run the host's `login` hook defensively: a throw (sync or async) is treated as a denial
|
|
1376
|
+
* (`null`) and warn-logged ONCE, so a buggy/unreachable hook never 500s the endpoint into a
|
|
1377
|
+
* stack-trace leak nor floods the logs.
|
|
1378
|
+
*/
|
|
1379
|
+
async runLoginHook(auth, username, password) {
|
|
1380
|
+
try {
|
|
1381
|
+
return await auth.login(username, password) ?? null;
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
if (!this.warnedLoginHookThrow) {
|
|
1384
|
+
this.warnedLoginHookThrow = true;
|
|
1385
|
+
this.logger.warn(`AgentDashboardModule dashboardAuth login hook threw; treating as denial. ${error instanceof Error ? error.message : String(error)}`);
|
|
1386
|
+
}
|
|
1387
|
+
return null;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
requireAuth() {
|
|
1391
|
+
if (!this.auth) throw new import_common7.NotFoundException();
|
|
1392
|
+
return this.auth;
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
_ts_decorate4([
|
|
1396
|
+
(0, import_common7.Get)("login"),
|
|
1397
|
+
(0, import_common7.Header)("Content-Type", "text/html; charset=utf-8"),
|
|
1398
|
+
(0, import_common7.Header)("Cache-Control", "no-store"),
|
|
1399
|
+
_ts_param4(0, (0, import_common7.Req)()),
|
|
1400
|
+
_ts_param4(1, (0, import_common7.Res)({
|
|
1401
|
+
passthrough: true
|
|
1402
|
+
})),
|
|
1403
|
+
_ts_param4(2, (0, import_common7.Query)("returnTo")),
|
|
1404
|
+
_ts_param4(3, (0, import_common7.Query)("error")),
|
|
1405
|
+
_ts_metadata4("design:type", Function),
|
|
1406
|
+
_ts_metadata4("design:paramtypes", [
|
|
1407
|
+
typeof AuthPageRequest === "undefined" ? Object : AuthPageRequest,
|
|
1408
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse,
|
|
1409
|
+
String,
|
|
1410
|
+
String
|
|
1411
|
+
]),
|
|
1412
|
+
_ts_metadata4("design:returntype", String)
|
|
1413
|
+
], AgentDashboardAuthController.prototype, "loginPage", null);
|
|
1414
|
+
_ts_decorate4([
|
|
1415
|
+
(0, import_common7.Post)("login"),
|
|
1416
|
+
_ts_param4(0, (0, import_common7.Body)()),
|
|
1417
|
+
_ts_param4(1, (0, import_common7.Req)()),
|
|
1418
|
+
_ts_param4(2, (0, import_common7.Res)({
|
|
1419
|
+
passthrough: true
|
|
1420
|
+
})),
|
|
1421
|
+
_ts_metadata4("design:type", Function),
|
|
1422
|
+
_ts_metadata4("design:paramtypes", [
|
|
1423
|
+
typeof LoginFormBody === "undefined" ? Object : LoginFormBody,
|
|
1424
|
+
Object,
|
|
1425
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
|
|
1426
|
+
]),
|
|
1427
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1428
|
+
], AgentDashboardAuthController.prototype, "login", null);
|
|
1429
|
+
_ts_decorate4([
|
|
1430
|
+
(0, import_common7.Post)("logout"),
|
|
1431
|
+
_ts_param4(0, (0, import_common7.Req)()),
|
|
1432
|
+
_ts_param4(1, (0, import_common7.Res)({
|
|
1433
|
+
passthrough: true
|
|
1434
|
+
})),
|
|
1435
|
+
_ts_metadata4("design:type", Function),
|
|
1436
|
+
_ts_metadata4("design:paramtypes", [
|
|
1437
|
+
Object,
|
|
1438
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
|
|
1439
|
+
]),
|
|
1440
|
+
_ts_metadata4("design:returntype", String)
|
|
1441
|
+
], AgentDashboardAuthController.prototype, "logout", null);
|
|
1442
|
+
AgentDashboardAuthController = _ts_decorate4([
|
|
1443
|
+
(0, import_common7.Controller)("auth"),
|
|
1444
|
+
_ts_param4(0, (0, import_common7.Optional)()),
|
|
1445
|
+
_ts_param4(0, (0, import_common7.Inject)(DASHBOARD_AUTH)),
|
|
1446
|
+
_ts_param4(1, (0, import_common7.Inject)(DASHBOARD_BASE_PATH)),
|
|
1447
|
+
_ts_metadata4("design:type", Function),
|
|
1448
|
+
_ts_metadata4("design:paramtypes", [
|
|
1449
|
+
Object,
|
|
1450
|
+
String
|
|
1451
|
+
])
|
|
1452
|
+
], AgentDashboardAuthController);
|
|
1453
|
+
|
|
606
1454
|
// src/server/normalize-path.ts
|
|
607
1455
|
function normalizeDashboardPath(path) {
|
|
608
1456
|
return `/${path.replace(/^\/+|\/+$/g, "")}`;
|
|
@@ -629,32 +1477,155 @@ function agentDashboardMountPaths(options) {
|
|
|
629
1477
|
__name(agentDashboardMountPaths, "agentDashboardMountPaths");
|
|
630
1478
|
|
|
631
1479
|
// src/server/agent-dashboard.module.ts
|
|
632
|
-
var
|
|
633
|
-
var
|
|
1480
|
+
var import_reflect_metadata2 = require("reflect-metadata");
|
|
1481
|
+
var import_common11 = require("@nestjs/common");
|
|
634
1482
|
var import_core = require("@nestjs/core");
|
|
635
1483
|
|
|
636
1484
|
// src/server/agent-ui.controller.ts
|
|
637
1485
|
var import_node_fs = require("fs");
|
|
638
1486
|
var import_node_path = require("path");
|
|
639
1487
|
var import_node_url = require("url");
|
|
640
|
-
var
|
|
641
|
-
|
|
1488
|
+
var import_common10 = require("@nestjs/common");
|
|
1489
|
+
|
|
1490
|
+
// src/server/auth/dashboard-auth-page.guard.ts
|
|
1491
|
+
var import_common9 = require("@nestjs/common");
|
|
1492
|
+
|
|
1493
|
+
// src/server/auth/dashboard-auth-redirect.ts
|
|
1494
|
+
var import_common8 = require("@nestjs/common");
|
|
1495
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
642
1496
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
643
1497
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
644
1498
|
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;
|
|
645
1499
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
646
1500
|
}
|
|
647
|
-
__name(
|
|
648
|
-
|
|
1501
|
+
__name(_ts_decorate5, "_ts_decorate");
|
|
1502
|
+
var DashboardAuthRedirect = class extends Error {
|
|
1503
|
+
static {
|
|
1504
|
+
__name(this, "DashboardAuthRedirect");
|
|
1505
|
+
}
|
|
1506
|
+
redirectTo;
|
|
1507
|
+
constructor(redirectTo) {
|
|
1508
|
+
super(`Redirect to ${redirectTo}`), this.redirectTo = redirectTo;
|
|
1509
|
+
this.name = "DashboardAuthRedirect";
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
var DashboardAuthRedirectFilter = class {
|
|
1513
|
+
static {
|
|
1514
|
+
__name(this, "DashboardAuthRedirectFilter");
|
|
1515
|
+
}
|
|
1516
|
+
catch(exception, host) {
|
|
1517
|
+
const response = host.switchToHttp().getResponse();
|
|
1518
|
+
sendRedirect(response, 302, exception.redirectTo);
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
DashboardAuthRedirectFilter = _ts_decorate5([
|
|
1522
|
+
(0, import_common8.Injectable)(),
|
|
1523
|
+
(0, import_common8.Catch)(DashboardAuthRedirect)
|
|
1524
|
+
], DashboardAuthRedirectFilter);
|
|
1525
|
+
|
|
1526
|
+
// src/server/auth/dashboard-auth-page.guard.ts
|
|
1527
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
1528
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1529
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1530
|
+
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;
|
|
1531
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1532
|
+
}
|
|
1533
|
+
__name(_ts_decorate6, "_ts_decorate");
|
|
1534
|
+
function _ts_metadata5(k, v) {
|
|
649
1535
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
650
1536
|
}
|
|
651
|
-
__name(
|
|
652
|
-
function
|
|
1537
|
+
__name(_ts_metadata5, "_ts_metadata");
|
|
1538
|
+
function _ts_param5(paramIndex, decorator) {
|
|
653
1539
|
return function(target, key) {
|
|
654
1540
|
decorator(target, key, paramIndex);
|
|
655
1541
|
};
|
|
656
1542
|
}
|
|
657
|
-
__name(
|
|
1543
|
+
__name(_ts_param5, "_ts_param");
|
|
1544
|
+
var DashboardAuthPageGuard = class {
|
|
1545
|
+
static {
|
|
1546
|
+
__name(this, "DashboardAuthPageGuard");
|
|
1547
|
+
}
|
|
1548
|
+
auth;
|
|
1549
|
+
basePath;
|
|
1550
|
+
constructor(auth, basePath) {
|
|
1551
|
+
this.auth = auth;
|
|
1552
|
+
this.basePath = basePath;
|
|
1553
|
+
}
|
|
1554
|
+
canActivate(context) {
|
|
1555
|
+
if (!this.auth) return true;
|
|
1556
|
+
const http = context.switchToHttp();
|
|
1557
|
+
const request = http.getRequest();
|
|
1558
|
+
const session = this.verifyRequestSession(request);
|
|
1559
|
+
if (!session) {
|
|
1560
|
+
const returnTo = readOriginalUrl(request);
|
|
1561
|
+
throw new DashboardAuthRedirect(`${this.basePath}/auth/login?returnTo=${encodeURIComponent(returnTo)}`);
|
|
1562
|
+
}
|
|
1563
|
+
attachSession(request, session);
|
|
1564
|
+
this.maybeRenew(http.getResponse(), request, session);
|
|
1565
|
+
return true;
|
|
1566
|
+
}
|
|
1567
|
+
verifyRequestSession(request) {
|
|
1568
|
+
const auth = this.auth;
|
|
1569
|
+
if (!auth) return null;
|
|
1570
|
+
const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
|
|
1571
|
+
if (cookieValue === void 0) return null;
|
|
1572
|
+
return verifySessionCookie(cookieValue, {
|
|
1573
|
+
secret: auth.secret
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Sliding renewal: a valid cookie past 50% of its TTL is transparently re-issued on the
|
|
1578
|
+
* response, so an active user never gets logged out mid-session.
|
|
1579
|
+
*/
|
|
1580
|
+
maybeRenew(response, request, session) {
|
|
1581
|
+
const auth = this.auth;
|
|
1582
|
+
if (!auth) return;
|
|
1583
|
+
const now = Date.now();
|
|
1584
|
+
if (now - session.iat <= auth.ttlMs / 2) return;
|
|
1585
|
+
issueSessionCookie({
|
|
1586
|
+
id: session.sub,
|
|
1587
|
+
...session.name !== void 0 ? {
|
|
1588
|
+
name: session.name
|
|
1589
|
+
} : {},
|
|
1590
|
+
roles: session.roles
|
|
1591
|
+
}, {
|
|
1592
|
+
auth,
|
|
1593
|
+
request,
|
|
1594
|
+
response,
|
|
1595
|
+
now
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
DashboardAuthPageGuard = _ts_decorate6([
|
|
1600
|
+
(0, import_common9.Injectable)(),
|
|
1601
|
+
_ts_param5(0, (0, import_common9.Optional)()),
|
|
1602
|
+
_ts_param5(0, (0, import_common9.Inject)(DASHBOARD_AUTH)),
|
|
1603
|
+
_ts_param5(1, (0, import_common9.Inject)(DASHBOARD_BASE_PATH)),
|
|
1604
|
+
_ts_metadata5("design:type", Function),
|
|
1605
|
+
_ts_metadata5("design:paramtypes", [
|
|
1606
|
+
Object,
|
|
1607
|
+
String
|
|
1608
|
+
])
|
|
1609
|
+
], DashboardAuthPageGuard);
|
|
1610
|
+
|
|
1611
|
+
// src/server/agent-ui.controller.ts
|
|
1612
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
1613
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1614
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1615
|
+
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;
|
|
1616
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1617
|
+
}
|
|
1618
|
+
__name(_ts_decorate7, "_ts_decorate");
|
|
1619
|
+
function _ts_metadata6(k, v) {
|
|
1620
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1621
|
+
}
|
|
1622
|
+
__name(_ts_metadata6, "_ts_metadata");
|
|
1623
|
+
function _ts_param6(paramIndex, decorator) {
|
|
1624
|
+
return function(target, key) {
|
|
1625
|
+
decorator(target, key, paramIndex);
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
__name(_ts_param6, "_ts_param");
|
|
658
1629
|
var BUILD_BASE = "/ai-gateway";
|
|
659
1630
|
function spaDir() {
|
|
660
1631
|
return (0, import_node_url.fileURLToPath)(new URL("../spa", __importMetaUrl));
|
|
@@ -690,7 +1661,7 @@ var AgentUiController = class {
|
|
|
690
1661
|
}
|
|
691
1662
|
const indexPath = (0, import_node_path.join)(this.dir, "index.html");
|
|
692
1663
|
if (!(0, import_node_fs.existsSync)(indexPath)) {
|
|
693
|
-
throw new
|
|
1664
|
+
throw new import_common10.NotFoundException("Dashboard is not built. Run the package build.");
|
|
694
1665
|
}
|
|
695
1666
|
const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
|
|
696
1667
|
const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>`;
|
|
@@ -698,78 +1669,147 @@ var AgentUiController = class {
|
|
|
698
1669
|
}
|
|
699
1670
|
asset(file) {
|
|
700
1671
|
const safe = (0, import_node_path.basename)(file);
|
|
701
|
-
if (safe !== file) throw new
|
|
1672
|
+
if (safe !== file) throw new import_common10.NotFoundException();
|
|
702
1673
|
const root = (0, import_node_path.resolve)(this.dir, "assets");
|
|
703
1674
|
const assetPath = (0, import_node_path.resolve)(root, safe);
|
|
704
1675
|
if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
|
|
705
|
-
throw new
|
|
1676
|
+
throw new import_common10.NotFoundException();
|
|
706
1677
|
}
|
|
707
1678
|
const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
|
|
708
|
-
return new
|
|
1679
|
+
return new import_common10.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
|
|
709
1680
|
type
|
|
710
1681
|
});
|
|
711
1682
|
}
|
|
712
1683
|
};
|
|
713
|
-
|
|
714
|
-
(0,
|
|
715
|
-
(0,
|
|
716
|
-
(0,
|
|
717
|
-
|
|
718
|
-
|
|
1684
|
+
_ts_decorate7([
|
|
1685
|
+
(0, import_common10.Get)(),
|
|
1686
|
+
(0, import_common10.Header)("Content-Type", "text/html; charset=utf-8"),
|
|
1687
|
+
(0, import_common10.Header)("Cache-Control", "no-store, must-revalidate"),
|
|
1688
|
+
_ts_param6(0, (0, import_common10.Req)()),
|
|
1689
|
+
_ts_param6(1, (0, import_common10.Res)({
|
|
719
1690
|
passthrough: true
|
|
720
1691
|
})),
|
|
721
|
-
|
|
722
|
-
|
|
1692
|
+
_ts_metadata6("design:type", Function),
|
|
1693
|
+
_ts_metadata6("design:paramtypes", [
|
|
723
1694
|
typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
|
|
724
1695
|
typeof UiPageResponse === "undefined" ? Object : UiPageResponse
|
|
725
1696
|
]),
|
|
726
|
-
|
|
1697
|
+
_ts_metadata6("design:returntype", String)
|
|
727
1698
|
], AgentUiController.prototype, "index", null);
|
|
728
|
-
|
|
729
|
-
(0,
|
|
730
|
-
(0,
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
1699
|
+
_ts_decorate7([
|
|
1700
|
+
(0, import_common10.Get)("assets/:file"),
|
|
1701
|
+
(0, import_common10.Header)("Cache-Control", "public, max-age=31536000, immutable"),
|
|
1702
|
+
_ts_param6(0, (0, import_common10.Param)("file")),
|
|
1703
|
+
_ts_metadata6("design:type", Function),
|
|
1704
|
+
_ts_metadata6("design:paramtypes", [
|
|
734
1705
|
String
|
|
735
1706
|
]),
|
|
736
|
-
|
|
1707
|
+
_ts_metadata6("design:returntype", typeof import_common10.StreamableFile === "undefined" ? Object : import_common10.StreamableFile)
|
|
737
1708
|
], AgentUiController.prototype, "asset", null);
|
|
738
|
-
AgentUiController =
|
|
739
|
-
(0,
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1709
|
+
AgentUiController = _ts_decorate7([
|
|
1710
|
+
(0, import_common10.Controller)(),
|
|
1711
|
+
(0, import_common10.UseGuards)(DashboardAuthPageGuard),
|
|
1712
|
+
(0, import_common10.UseFilters)(new DashboardAuthRedirectFilter()),
|
|
1713
|
+
_ts_param6(0, (0, import_common10.Inject)(DASHBOARD_BASE_PATH)),
|
|
1714
|
+
_ts_param6(1, (0, import_common10.Inject)(DASHBOARD_API_PATH)),
|
|
1715
|
+
_ts_metadata6("design:type", Function),
|
|
1716
|
+
_ts_metadata6("design:paramtypes", [
|
|
744
1717
|
String,
|
|
745
1718
|
String
|
|
746
1719
|
])
|
|
747
1720
|
], AgentUiController);
|
|
748
1721
|
|
|
1722
|
+
// src/server/auth/dashboard-auth-config.ts
|
|
1723
|
+
var DEFAULT_TTL = "8h";
|
|
1724
|
+
function unitToMs(unit) {
|
|
1725
|
+
switch (unit) {
|
|
1726
|
+
case "ms":
|
|
1727
|
+
return 1;
|
|
1728
|
+
case "s":
|
|
1729
|
+
return 1e3;
|
|
1730
|
+
case "m":
|
|
1731
|
+
return 6e4;
|
|
1732
|
+
case "h":
|
|
1733
|
+
return 36e5;
|
|
1734
|
+
case "d":
|
|
1735
|
+
return 864e5;
|
|
1736
|
+
default:
|
|
1737
|
+
return void 0;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
__name(unitToMs, "unitToMs");
|
|
1741
|
+
function durationToMs(duration) {
|
|
1742
|
+
const match = /^(\d+)(ms|s|m|h|d)$/.exec(duration.trim());
|
|
1743
|
+
const amount = match?.[1];
|
|
1744
|
+
const unit = match?.[2] !== void 0 ? unitToMs(match[2]) : void 0;
|
|
1745
|
+
if (amount === void 0 || unit === void 0) {
|
|
1746
|
+
throw new Error(`AgentDashboardModule dashboardAuth: invalid \`ttl\` duration: ${duration}`);
|
|
1747
|
+
}
|
|
1748
|
+
return Number(amount) * unit;
|
|
1749
|
+
}
|
|
1750
|
+
__name(durationToMs, "durationToMs");
|
|
1751
|
+
function resolveDashboardAuth(options) {
|
|
1752
|
+
if (options === void 0) return null;
|
|
1753
|
+
if (typeof options.secret !== "string" || options.secret === "") {
|
|
1754
|
+
throw new Error("AgentDashboardModule dashboardAuth: `secret` is required and must be a non-empty string (HMAC-SHA256 signing key, 32+ bytes recommended). Failing closed.");
|
|
1755
|
+
}
|
|
1756
|
+
if (typeof options.login !== "function") {
|
|
1757
|
+
throw new Error("AgentDashboardModule dashboardAuth: `login` is required (validates submitted credentials for the built-in login screen). Failing closed.");
|
|
1758
|
+
}
|
|
1759
|
+
return {
|
|
1760
|
+
secret: options.secret,
|
|
1761
|
+
ttlMs: durationToMs(options.ttl ?? DEFAULT_TTL),
|
|
1762
|
+
login: options.login
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
__name(resolveDashboardAuth, "resolveDashboardAuth");
|
|
1766
|
+
|
|
1767
|
+
// src/server/guards.ts
|
|
1768
|
+
var import_reflect_metadata = require("reflect-metadata");
|
|
1769
|
+
var GUARDS_METADATA = "__guards__";
|
|
1770
|
+
function isGuardClass(guard) {
|
|
1771
|
+
return typeof guard === "function";
|
|
1772
|
+
}
|
|
1773
|
+
__name(isGuardClass, "isGuardClass");
|
|
1774
|
+
function baseGuards(controller) {
|
|
1775
|
+
return Reflect.getOwnMetadata(GUARDS_METADATA, controller) ?? [];
|
|
1776
|
+
}
|
|
1777
|
+
__name(baseGuards, "baseGuards");
|
|
1778
|
+
function stampGuards(guards, entries) {
|
|
1779
|
+
for (const [controller, base] of entries) {
|
|
1780
|
+
Reflect.defineMetadata(GUARDS_METADATA, [
|
|
1781
|
+
...base,
|
|
1782
|
+
...guards ?? []
|
|
1783
|
+
], controller);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
__name(stampGuards, "stampGuards");
|
|
1787
|
+
|
|
749
1788
|
// src/server/agent-dashboard.module.ts
|
|
750
|
-
function
|
|
1789
|
+
function _ts_decorate8(decorators, target, key, desc) {
|
|
751
1790
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
752
1791
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
753
1792
|
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;
|
|
754
1793
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
755
1794
|
}
|
|
756
|
-
__name(
|
|
757
|
-
var
|
|
1795
|
+
__name(_ts_decorate8, "_ts_decorate");
|
|
1796
|
+
var API_BASE_GUARDS = baseGuards(AgentApiController);
|
|
1797
|
+
var UI_BASE_GUARDS = baseGuards(AgentUiController);
|
|
758
1798
|
function normalize(path) {
|
|
759
1799
|
return normalizeDashboardPath(path);
|
|
760
1800
|
}
|
|
761
1801
|
__name(normalize, "normalize");
|
|
762
|
-
function stampGuards(guards, ...controllers) {
|
|
763
|
-
for (const controller of controllers) {
|
|
764
|
-
Reflect.defineMetadata(GUARDS_METADATA, guards ?? [], controller);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
__name(stampGuards, "stampGuards");
|
|
768
1802
|
var AgentApiModule = class _AgentApiModule {
|
|
769
1803
|
static {
|
|
770
1804
|
__name(this, "AgentApiModule");
|
|
771
1805
|
}
|
|
772
1806
|
static register(options) {
|
|
1807
|
+
stampGuards(options.guards, [
|
|
1808
|
+
[
|
|
1809
|
+
AgentApiController,
|
|
1810
|
+
API_BASE_GUARDS
|
|
1811
|
+
]
|
|
1812
|
+
]);
|
|
773
1813
|
return {
|
|
774
1814
|
module: _AgentApiModule,
|
|
775
1815
|
imports: [
|
|
@@ -780,7 +1820,9 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
780
1820
|
],
|
|
781
1821
|
providers: [
|
|
782
1822
|
DashboardService,
|
|
783
|
-
|
|
1823
|
+
DashboardAuthGuard,
|
|
1824
|
+
options.dashboardAuth,
|
|
1825
|
+
...(options.guards ?? []).filter(isGuardClass),
|
|
784
1826
|
// `useValue` even when `options.approvalActorRef` is `undefined` — AgentApiController
|
|
785
1827
|
// injects this WITHOUT `@Optional()` (same pattern as `AGENT_QUOTA_STORE`'s factory).
|
|
786
1828
|
{
|
|
@@ -788,14 +1830,18 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
788
1830
|
useValue: options.approvalActorRef
|
|
789
1831
|
}
|
|
790
1832
|
],
|
|
1833
|
+
// DASHBOARD_AUTH re-exported so AgentUiController/AgentDashboardAuthController (hosted
|
|
1834
|
+
// directly by AgentDashboardModule, which imports this module) resolve the SAME instance
|
|
1835
|
+
// instead of re-running a host's async factory a second time.
|
|
791
1836
|
exports: [
|
|
792
|
-
DashboardService
|
|
1837
|
+
DashboardService,
|
|
1838
|
+
DASHBOARD_AUTH
|
|
793
1839
|
]
|
|
794
1840
|
};
|
|
795
1841
|
}
|
|
796
1842
|
};
|
|
797
|
-
AgentApiModule =
|
|
798
|
-
(0,
|
|
1843
|
+
AgentApiModule = _ts_decorate8([
|
|
1844
|
+
(0, import_common11.Module)({})
|
|
799
1845
|
], AgentApiModule);
|
|
800
1846
|
var AgentDashboardModule = class _AgentDashboardModule {
|
|
801
1847
|
static {
|
|
@@ -804,7 +1850,16 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
804
1850
|
static forRoot(options = {}) {
|
|
805
1851
|
const basePath = normalize(options.basePath ?? "/ai-gateway");
|
|
806
1852
|
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
807
|
-
stampGuards(options.guards,
|
|
1853
|
+
stampGuards(options.guards, [
|
|
1854
|
+
[
|
|
1855
|
+
AgentUiController,
|
|
1856
|
+
UI_BASE_GUARDS
|
|
1857
|
+
]
|
|
1858
|
+
]);
|
|
1859
|
+
const dashboardAuthProvider = {
|
|
1860
|
+
provide: DASHBOARD_AUTH,
|
|
1861
|
+
useValue: resolveDashboardAuth(options.dashboardAuth)
|
|
1862
|
+
};
|
|
808
1863
|
return {
|
|
809
1864
|
module: _AgentDashboardModule,
|
|
810
1865
|
imports: [
|
|
@@ -821,7 +1876,8 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
821
1876
|
} : {},
|
|
822
1877
|
...options.approvalActorRef ? {
|
|
823
1878
|
approvalActorRef: options.approvalActorRef
|
|
824
|
-
} : {}
|
|
1879
|
+
} : {},
|
|
1880
|
+
dashboardAuth: dashboardAuthProvider
|
|
825
1881
|
}),
|
|
826
1882
|
import_core.RouterModule.register([
|
|
827
1883
|
{
|
|
@@ -835,7 +1891,8 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
835
1891
|
])
|
|
836
1892
|
],
|
|
837
1893
|
controllers: [
|
|
838
|
-
AgentUiController
|
|
1894
|
+
AgentUiController,
|
|
1895
|
+
AgentDashboardAuthController
|
|
839
1896
|
],
|
|
840
1897
|
providers: [
|
|
841
1898
|
{
|
|
@@ -846,8 +1903,9 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
846
1903
|
provide: DASHBOARD_API_PATH,
|
|
847
1904
|
useValue: apiBasePath
|
|
848
1905
|
},
|
|
1906
|
+
DashboardAuthPageGuard,
|
|
849
1907
|
// AgentUiController is hosted HERE, so its guards DI-instantiate from this module.
|
|
850
|
-
...options.guards ?? []
|
|
1908
|
+
...(options.guards ?? []).filter(isGuardClass)
|
|
851
1909
|
],
|
|
852
1910
|
// Re-export the API module so its DashboardService reaches importers (e.g. the host's own controllers).
|
|
853
1911
|
exports: [
|
|
@@ -855,9 +1913,71 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
855
1913
|
]
|
|
856
1914
|
};
|
|
857
1915
|
}
|
|
1916
|
+
static forRootAsync(options) {
|
|
1917
|
+
const basePath = normalize(options.basePath ?? "/ai-gateway");
|
|
1918
|
+
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
1919
|
+
stampGuards(options.guards, [
|
|
1920
|
+
[
|
|
1921
|
+
AgentUiController,
|
|
1922
|
+
UI_BASE_GUARDS
|
|
1923
|
+
]
|
|
1924
|
+
]);
|
|
1925
|
+
const dashboardAuthProvider = {
|
|
1926
|
+
provide: DASHBOARD_AUTH,
|
|
1927
|
+
inject: options.inject ?? [],
|
|
1928
|
+
useFactory: /* @__PURE__ */ __name(async (...deps) => resolveDashboardAuth(await options.useDashboardAuth(...deps)), "useFactory")
|
|
1929
|
+
};
|
|
1930
|
+
return {
|
|
1931
|
+
module: _AgentDashboardModule,
|
|
1932
|
+
imports: [
|
|
1933
|
+
...options.imports ?? [],
|
|
1934
|
+
AgentApiModule.register({
|
|
1935
|
+
...options.imports ? {
|
|
1936
|
+
imports: options.imports
|
|
1937
|
+
} : {},
|
|
1938
|
+
...options.guards ? {
|
|
1939
|
+
guards: options.guards
|
|
1940
|
+
} : {},
|
|
1941
|
+
...options.approvalActorRef ? {
|
|
1942
|
+
approvalActorRef: options.approvalActorRef
|
|
1943
|
+
} : {},
|
|
1944
|
+
dashboardAuth: dashboardAuthProvider
|
|
1945
|
+
}),
|
|
1946
|
+
import_core.RouterModule.register([
|
|
1947
|
+
{
|
|
1948
|
+
path: basePath,
|
|
1949
|
+
module: _AgentDashboardModule
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
path: apiBasePath,
|
|
1953
|
+
module: AgentApiModule
|
|
1954
|
+
}
|
|
1955
|
+
])
|
|
1956
|
+
],
|
|
1957
|
+
controllers: [
|
|
1958
|
+
AgentUiController,
|
|
1959
|
+
AgentDashboardAuthController
|
|
1960
|
+
],
|
|
1961
|
+
providers: [
|
|
1962
|
+
{
|
|
1963
|
+
provide: DASHBOARD_BASE_PATH,
|
|
1964
|
+
useValue: basePath
|
|
1965
|
+
},
|
|
1966
|
+
{
|
|
1967
|
+
provide: DASHBOARD_API_PATH,
|
|
1968
|
+
useValue: apiBasePath
|
|
1969
|
+
},
|
|
1970
|
+
DashboardAuthPageGuard,
|
|
1971
|
+
...(options.guards ?? []).filter(isGuardClass)
|
|
1972
|
+
],
|
|
1973
|
+
exports: [
|
|
1974
|
+
AgentApiModule
|
|
1975
|
+
]
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
858
1978
|
};
|
|
859
|
-
AgentDashboardModule =
|
|
860
|
-
(0,
|
|
1979
|
+
AgentDashboardModule = _ts_decorate8([
|
|
1980
|
+
(0, import_common11.Module)({})
|
|
861
1981
|
], AgentDashboardModule);
|
|
862
1982
|
// Annotate the CommonJS export names for ESM import in node:
|
|
863
1983
|
0 && (module.exports = {
|
|
@@ -868,13 +1988,16 @@ AgentDashboardModule = _ts_decorate4([
|
|
|
868
1988
|
AGENT_PRICING_STORE,
|
|
869
1989
|
AgentApiController,
|
|
870
1990
|
AgentApiModule,
|
|
1991
|
+
AgentDashboardAuthController,
|
|
871
1992
|
AgentDashboardModule,
|
|
872
1993
|
AgentUiController,
|
|
873
1994
|
DASHBOARD_API_PATH,
|
|
874
1995
|
DASHBOARD_APPROVAL_ACTOR_REF,
|
|
1996
|
+
DASHBOARD_AUTH,
|
|
875
1997
|
DASHBOARD_BASE_PATH,
|
|
876
1998
|
DashboardService,
|
|
877
1999
|
agentDashboardMountPaths,
|
|
878
|
-
parsePriceInput
|
|
2000
|
+
parsePriceInput,
|
|
2001
|
+
resolveDashboardAuth
|
|
879
2002
|
});
|
|
880
2003
|
//# sourceMappingURL=index.cjs.map
|