@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.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 = [
|
|
@@ -170,6 +496,14 @@ var DashboardService = class {
|
|
|
170
496
|
recentToolCalls(limit) {
|
|
171
497
|
return this.queries.recentToolCalls(limit);
|
|
172
498
|
}
|
|
499
|
+
/** Paged, filterable tool calls for the Runs & tools activity table. */
|
|
500
|
+
toolCallsPage(query) {
|
|
501
|
+
return this.queries.toolCallsPage(query);
|
|
502
|
+
}
|
|
503
|
+
/** Paged, filterable runs for the Reliability recent-runs table. */
|
|
504
|
+
runsPage(query) {
|
|
505
|
+
return this.queries.runsPage(query);
|
|
506
|
+
}
|
|
173
507
|
/** Tool calls sitting `pending_approval`, oldest first, for the cross-thread approvals inbox. */
|
|
174
508
|
pendingApprovals(limit) {
|
|
175
509
|
return this.queries.pendingApprovals(limit);
|
|
@@ -211,6 +545,18 @@ var DashboardService = class {
|
|
|
211
545
|
return this.withActorLabels(rows);
|
|
212
546
|
}
|
|
213
547
|
/**
|
|
548
|
+
* Paged, filterable threads for the Runs & tools threads table — actor-labeled the same way
|
|
549
|
+
* {@link recentThreads} is.
|
|
550
|
+
*/
|
|
551
|
+
async threadsPage(query) {
|
|
552
|
+
const page = await this.queries.threadsPage(query);
|
|
553
|
+
const rows = await this.withActorLabels(page.rows);
|
|
554
|
+
return {
|
|
555
|
+
...page,
|
|
556
|
+
rows
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
214
560
|
* Decorate actor-scoped rows with `actorLabel`, batching the distinct `actorRef`s into ONE
|
|
215
561
|
* {@link ActorDirectory.resolveDisplay} call per response. `null` for every row when no directory
|
|
216
562
|
* is bound, or for a ref the directory didn't resolve.
|
|
@@ -283,17 +629,17 @@ var DashboardService = class {
|
|
|
283
629
|
});
|
|
284
630
|
}
|
|
285
631
|
};
|
|
286
|
-
DashboardService =
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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", [
|
|
297
643
|
typeof AgentGovernanceQueries === "undefined" ? Object : AgentGovernanceQueries,
|
|
298
644
|
typeof ActorDirectory === "undefined" ? Object : ActorDirectory,
|
|
299
645
|
typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
|
|
@@ -301,32 +647,153 @@ DashboardService = _ts_decorate([
|
|
|
301
647
|
])
|
|
302
648
|
], DashboardService);
|
|
303
649
|
|
|
650
|
+
// src/server/parse-page-query.ts
|
|
651
|
+
import { BadRequestException as BadRequestException3 } from "@nestjs/common";
|
|
652
|
+
var ISO_DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
653
|
+
function parsePageNumber(value) {
|
|
654
|
+
const parsed = value === void 0 ? Number.NaN : Number.parseInt(value, 10);
|
|
655
|
+
if (!Number.isFinite(parsed) || parsed < 1) return 1;
|
|
656
|
+
return parsed;
|
|
657
|
+
}
|
|
658
|
+
__name(parsePageNumber, "parsePageNumber");
|
|
659
|
+
function assertKnownFields(raw, allowed) {
|
|
660
|
+
for (const field of Object.keys(raw)) {
|
|
661
|
+
if (!allowed.includes(field)) {
|
|
662
|
+
throw new BadRequestException3(`Unknown where field "${field}".`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
__name(assertKnownFields, "assertKnownFields");
|
|
667
|
+
function assertDayFields(raw, dayFields) {
|
|
668
|
+
for (const field of dayFields) {
|
|
669
|
+
const value = raw[field];
|
|
670
|
+
if (value !== void 0 && !ISO_DAY.test(value)) {
|
|
671
|
+
throw new BadRequestException3(`"where[${field}]" must be YYYY-MM-DD.`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
__name(assertDayFields, "assertDayFields");
|
|
676
|
+
var DAY_FIELDS = [
|
|
677
|
+
"fromDay",
|
|
678
|
+
"toDay"
|
|
679
|
+
];
|
|
680
|
+
var TOOL_CALL_WHERE_FIELDS = [
|
|
681
|
+
"toolName",
|
|
682
|
+
"toolType",
|
|
683
|
+
"status",
|
|
684
|
+
"threadId",
|
|
685
|
+
"fromDay",
|
|
686
|
+
"toDay"
|
|
687
|
+
];
|
|
688
|
+
function parseToolCallWhere(raw) {
|
|
689
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
690
|
+
assertKnownFields(raw, TOOL_CALL_WHERE_FIELDS);
|
|
691
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
692
|
+
return {
|
|
693
|
+
...raw.toolName !== void 0 ? {
|
|
694
|
+
toolName: raw.toolName
|
|
695
|
+
} : {},
|
|
696
|
+
...raw.toolType !== void 0 ? {
|
|
697
|
+
toolType: raw.toolType
|
|
698
|
+
} : {},
|
|
699
|
+
...raw.status !== void 0 ? {
|
|
700
|
+
status: raw.status
|
|
701
|
+
} : {},
|
|
702
|
+
...raw.threadId !== void 0 ? {
|
|
703
|
+
threadId: raw.threadId
|
|
704
|
+
} : {},
|
|
705
|
+
...raw.fromDay !== void 0 ? {
|
|
706
|
+
fromDay: raw.fromDay
|
|
707
|
+
} : {},
|
|
708
|
+
...raw.toDay !== void 0 ? {
|
|
709
|
+
toDay: raw.toDay
|
|
710
|
+
} : {}
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
__name(parseToolCallWhere, "parseToolCallWhere");
|
|
714
|
+
var THREAD_WHERE_FIELDS = [
|
|
715
|
+
"actorRef",
|
|
716
|
+
"title",
|
|
717
|
+
"fromDay",
|
|
718
|
+
"toDay"
|
|
719
|
+
];
|
|
720
|
+
function parseThreadWhere(raw) {
|
|
721
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
722
|
+
assertKnownFields(raw, THREAD_WHERE_FIELDS);
|
|
723
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
724
|
+
return {
|
|
725
|
+
...raw.actorRef !== void 0 ? {
|
|
726
|
+
actorRef: raw.actorRef
|
|
727
|
+
} : {},
|
|
728
|
+
...raw.title !== void 0 ? {
|
|
729
|
+
title: raw.title
|
|
730
|
+
} : {},
|
|
731
|
+
...raw.fromDay !== void 0 ? {
|
|
732
|
+
fromDay: raw.fromDay
|
|
733
|
+
} : {},
|
|
734
|
+
...raw.toDay !== void 0 ? {
|
|
735
|
+
toDay: raw.toDay
|
|
736
|
+
} : {}
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
__name(parseThreadWhere, "parseThreadWhere");
|
|
740
|
+
var RUN_WHERE_FIELDS = [
|
|
741
|
+
"agentName",
|
|
742
|
+
"status",
|
|
743
|
+
"errorCode",
|
|
744
|
+
"fromDay",
|
|
745
|
+
"toDay"
|
|
746
|
+
];
|
|
747
|
+
function parseRunWhere(raw) {
|
|
748
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
749
|
+
assertKnownFields(raw, RUN_WHERE_FIELDS);
|
|
750
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
751
|
+
return {
|
|
752
|
+
...raw.agentName !== void 0 ? {
|
|
753
|
+
agentName: raw.agentName
|
|
754
|
+
} : {},
|
|
755
|
+
...raw.status !== void 0 ? {
|
|
756
|
+
status: raw.status
|
|
757
|
+
} : {},
|
|
758
|
+
...raw.errorCode !== void 0 ? {
|
|
759
|
+
errorCode: raw.errorCode
|
|
760
|
+
} : {},
|
|
761
|
+
...raw.fromDay !== void 0 ? {
|
|
762
|
+
fromDay: raw.fromDay
|
|
763
|
+
} : {},
|
|
764
|
+
...raw.toDay !== void 0 ? {
|
|
765
|
+
toDay: raw.toDay
|
|
766
|
+
} : {}
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
__name(parseRunWhere, "parseRunWhere");
|
|
770
|
+
|
|
304
771
|
// src/server/agent-api.controller.ts
|
|
305
|
-
function
|
|
772
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
306
773
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
307
774
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
308
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;
|
|
309
776
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
310
777
|
}
|
|
311
|
-
__name(
|
|
312
|
-
function
|
|
778
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
779
|
+
function _ts_metadata3(k, v) {
|
|
313
780
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
314
781
|
}
|
|
315
|
-
__name(
|
|
316
|
-
function
|
|
782
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
783
|
+
function _ts_param3(paramIndex, decorator) {
|
|
317
784
|
return function(target, key) {
|
|
318
785
|
decorator(target, key, paramIndex);
|
|
319
786
|
};
|
|
320
787
|
}
|
|
321
|
-
__name(
|
|
788
|
+
__name(_ts_param3, "_ts_param");
|
|
322
789
|
var DAY_MS = 864e5;
|
|
323
|
-
var
|
|
790
|
+
var ISO_DAY2 = /^\d{4}-\d{2}-\d{2}$/;
|
|
324
791
|
function utcDay(daysAgo) {
|
|
325
792
|
return new Date(Date.now() - daysAgo * DAY_MS).toISOString().slice(0, 10);
|
|
326
793
|
}
|
|
327
794
|
__name(utcDay, "utcDay");
|
|
328
795
|
function dayOr(value, fallback) {
|
|
329
|
-
return value !== void 0 &&
|
|
796
|
+
return value !== void 0 && ISO_DAY2.test(value) ? value : fallback;
|
|
330
797
|
}
|
|
331
798
|
__name(dayOr, "dayOr");
|
|
332
799
|
function resolveRange(from, to) {
|
|
@@ -370,10 +837,40 @@ var AgentApiController = class {
|
|
|
370
837
|
runs(limit) {
|
|
371
838
|
return this.dashboard.recentRuns(parseLimit(limit, 50));
|
|
372
839
|
}
|
|
840
|
+
/**
|
|
841
|
+
* Paged, filterable runs for the Reliability recent-runs table. `page` (default 1), `limit`
|
|
842
|
+
* (default 25, max 200), and `where[agentName]`/`where[status]`/`where[errorCode]`/
|
|
843
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
844
|
+
*/
|
|
845
|
+
runsPage(page, limit, where) {
|
|
846
|
+
const parsedWhere = parseRunWhere(where);
|
|
847
|
+
return this.dashboard.runsPage({
|
|
848
|
+
page: parsePageNumber(page),
|
|
849
|
+
pageSize: parseLimit(limit, 25),
|
|
850
|
+
...parsedWhere !== void 0 ? {
|
|
851
|
+
where: parsedWhere
|
|
852
|
+
} : {}
|
|
853
|
+
});
|
|
854
|
+
}
|
|
373
855
|
/** Most recent tool calls (default 50, max 200) for the activity feed. */
|
|
374
856
|
toolCalls(limit) {
|
|
375
857
|
return this.dashboard.recentToolCalls(parseLimit(limit, 50));
|
|
376
858
|
}
|
|
859
|
+
/**
|
|
860
|
+
* Paged, filterable tool calls for the Runs & tools activity table. `page` (default 1), `limit`
|
|
861
|
+
* (default 25, max 200), and `where[toolName]`/`where[toolType]`/`where[status]`/`where[threadId]`/
|
|
862
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
863
|
+
*/
|
|
864
|
+
toolCallsPage(page, limit, where) {
|
|
865
|
+
const parsedWhere = parseToolCallWhere(where);
|
|
866
|
+
return this.dashboard.toolCallsPage({
|
|
867
|
+
page: parsePageNumber(page),
|
|
868
|
+
pageSize: parseLimit(limit, 25),
|
|
869
|
+
...parsedWhere !== void 0 ? {
|
|
870
|
+
where: parsedWhere
|
|
871
|
+
} : {}
|
|
872
|
+
});
|
|
873
|
+
}
|
|
377
874
|
/** Tool calls sitting `pending_approval` (default 50, max 200), oldest first — the approvals inbox. */
|
|
378
875
|
approvals(limit) {
|
|
379
876
|
return this.dashboard.pendingApprovals(parseLimit(limit, 50));
|
|
@@ -415,6 +912,21 @@ var AgentApiController = class {
|
|
|
415
912
|
return this.dashboard.recentThreads(parseLimit(limit, 50));
|
|
416
913
|
}
|
|
417
914
|
/**
|
|
915
|
+
* Paged, filterable threads for the Runs & tools threads table. `page` (default 1), `limit`
|
|
916
|
+
* (default 25, max 200), and `where[actorRef]`/`where[title]` (case-insensitive substring)/
|
|
917
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
918
|
+
*/
|
|
919
|
+
threadsPage(page, limit, where) {
|
|
920
|
+
const parsedWhere = parseThreadWhere(where);
|
|
921
|
+
return this.dashboard.threadsPage({
|
|
922
|
+
page: parsePageNumber(page),
|
|
923
|
+
pageSize: parseLimit(limit, 25),
|
|
924
|
+
...parsedWhere !== void 0 ? {
|
|
925
|
+
where: parsedWhere
|
|
926
|
+
} : {}
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
418
930
|
* Current price row per model, for the pricing tab. 501s (via `DashboardService.listPrices`) when
|
|
419
931
|
* no `AGENT_PRICING_STORE` is bound.
|
|
420
932
|
*/
|
|
@@ -434,136 +946,469 @@ var AgentApiController = class {
|
|
|
434
946
|
return this.dashboard.streamEvents();
|
|
435
947
|
}
|
|
436
948
|
};
|
|
437
|
-
|
|
949
|
+
_ts_decorate3([
|
|
438
950
|
Get("spend"),
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
951
|
+
_ts_param3(0, Query("from")),
|
|
952
|
+
_ts_param3(1, Query("to")),
|
|
953
|
+
_ts_metadata3("design:type", Function),
|
|
954
|
+
_ts_metadata3("design:paramtypes", [
|
|
443
955
|
String,
|
|
444
956
|
String
|
|
445
957
|
]),
|
|
446
|
-
|
|
958
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
447
959
|
], AgentApiController.prototype, "spend", null);
|
|
448
|
-
|
|
960
|
+
_ts_decorate3([
|
|
449
961
|
Get("top-threads"),
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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", [
|
|
455
967
|
String,
|
|
456
968
|
String,
|
|
457
969
|
String
|
|
458
970
|
]),
|
|
459
|
-
|
|
971
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
460
972
|
], AgentApiController.prototype, "topThreads", null);
|
|
461
|
-
|
|
973
|
+
_ts_decorate3([
|
|
462
974
|
Get("reliability"),
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
975
|
+
_ts_param3(0, Query("from")),
|
|
976
|
+
_ts_param3(1, Query("to")),
|
|
977
|
+
_ts_metadata3("design:type", Function),
|
|
978
|
+
_ts_metadata3("design:paramtypes", [
|
|
467
979
|
String,
|
|
468
980
|
String
|
|
469
981
|
]),
|
|
470
|
-
|
|
982
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
471
983
|
], AgentApiController.prototype, "reliability", null);
|
|
472
|
-
|
|
984
|
+
_ts_decorate3([
|
|
473
985
|
Get("runs"),
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
986
|
+
_ts_param3(0, Query("limit")),
|
|
987
|
+
_ts_metadata3("design:type", Function),
|
|
988
|
+
_ts_metadata3("design:paramtypes", [
|
|
477
989
|
String
|
|
478
990
|
]),
|
|
479
|
-
|
|
991
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
480
992
|
], AgentApiController.prototype, "runs", null);
|
|
481
|
-
|
|
993
|
+
_ts_decorate3([
|
|
994
|
+
Get("runs-page"),
|
|
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", [
|
|
1000
|
+
String,
|
|
1001
|
+
String,
|
|
1002
|
+
typeof Record === "undefined" ? Object : Record
|
|
1003
|
+
]),
|
|
1004
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
1005
|
+
], AgentApiController.prototype, "runsPage", null);
|
|
1006
|
+
_ts_decorate3([
|
|
482
1007
|
Get("tool-calls"),
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
1008
|
+
_ts_param3(0, Query("limit")),
|
|
1009
|
+
_ts_metadata3("design:type", Function),
|
|
1010
|
+
_ts_metadata3("design:paramtypes", [
|
|
486
1011
|
String
|
|
487
1012
|
]),
|
|
488
|
-
|
|
1013
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
489
1014
|
], AgentApiController.prototype, "toolCalls", null);
|
|
490
|
-
|
|
1015
|
+
_ts_decorate3([
|
|
1016
|
+
Get("tool-calls-page"),
|
|
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", [
|
|
1022
|
+
String,
|
|
1023
|
+
String,
|
|
1024
|
+
typeof Record === "undefined" ? Object : Record
|
|
1025
|
+
]),
|
|
1026
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
1027
|
+
], AgentApiController.prototype, "toolCallsPage", null);
|
|
1028
|
+
_ts_decorate3([
|
|
491
1029
|
Get("approvals"),
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
1030
|
+
_ts_param3(0, Query("limit")),
|
|
1031
|
+
_ts_metadata3("design:type", Function),
|
|
1032
|
+
_ts_metadata3("design:paramtypes", [
|
|
495
1033
|
String
|
|
496
1034
|
]),
|
|
497
|
-
|
|
1035
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
498
1036
|
], AgentApiController.prototype, "approvals", null);
|
|
499
|
-
|
|
1037
|
+
_ts_decorate3([
|
|
500
1038
|
Post("approvals/:toolCallId"),
|
|
501
1039
|
HttpCode(204),
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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", [
|
|
507
1045
|
String,
|
|
508
1046
|
Object,
|
|
509
1047
|
Object
|
|
510
1048
|
]),
|
|
511
|
-
|
|
1049
|
+
_ts_metadata3("design:returntype", Promise)
|
|
512
1050
|
], AgentApiController.prototype, "decideApproval", null);
|
|
513
|
-
|
|
1051
|
+
_ts_decorate3([
|
|
514
1052
|
Get("tools"),
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
1053
|
+
_ts_param3(0, Query("from")),
|
|
1054
|
+
_ts_param3(1, Query("to")),
|
|
1055
|
+
_ts_metadata3("design:type", Function),
|
|
1056
|
+
_ts_metadata3("design:paramtypes", [
|
|
519
1057
|
String,
|
|
520
1058
|
String
|
|
521
1059
|
]),
|
|
522
|
-
|
|
1060
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
523
1061
|
], AgentApiController.prototype, "tools", null);
|
|
524
|
-
|
|
1062
|
+
_ts_decorate3([
|
|
525
1063
|
Get("threads"),
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
1064
|
+
_ts_param3(0, Query("limit")),
|
|
1065
|
+
_ts_metadata3("design:type", Function),
|
|
1066
|
+
_ts_metadata3("design:paramtypes", [
|
|
529
1067
|
String
|
|
530
1068
|
]),
|
|
531
|
-
|
|
1069
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
532
1070
|
], AgentApiController.prototype, "threads", null);
|
|
533
|
-
|
|
1071
|
+
_ts_decorate3([
|
|
1072
|
+
Get("threads-page"),
|
|
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", [
|
|
1078
|
+
String,
|
|
1079
|
+
String,
|
|
1080
|
+
typeof Record === "undefined" ? Object : Record
|
|
1081
|
+
]),
|
|
1082
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
1083
|
+
], AgentApiController.prototype, "threadsPage", null);
|
|
1084
|
+
_ts_decorate3([
|
|
534
1085
|
Get("pricing"),
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
1086
|
+
_ts_metadata3("design:type", Function),
|
|
1087
|
+
_ts_metadata3("design:paramtypes", []),
|
|
1088
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
538
1089
|
], AgentApiController.prototype, "listPrices", null);
|
|
539
|
-
|
|
1090
|
+
_ts_decorate3([
|
|
540
1091
|
Post("pricing"),
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
1092
|
+
_ts_param3(0, Body()),
|
|
1093
|
+
_ts_metadata3("design:type", Function),
|
|
1094
|
+
_ts_metadata3("design:paramtypes", [
|
|
544
1095
|
Object
|
|
545
1096
|
]),
|
|
546
|
-
|
|
1097
|
+
_ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
547
1098
|
], AgentApiController.prototype, "upsertPrice", null);
|
|
548
|
-
|
|
1099
|
+
_ts_decorate3([
|
|
549
1100
|
Sse("stream"),
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
1101
|
+
_ts_metadata3("design:type", Function),
|
|
1102
|
+
_ts_metadata3("design:paramtypes", []),
|
|
1103
|
+
_ts_metadata3("design:returntype", typeof Observable === "undefined" ? Object : Observable)
|
|
553
1104
|
], AgentApiController.prototype, "stream", null);
|
|
554
|
-
AgentApiController =
|
|
1105
|
+
AgentApiController = _ts_decorate3([
|
|
555
1106
|
Controller(),
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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", [
|
|
561
1113
|
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
562
1114
|
Object,
|
|
563
1115
|
typeof ActorResolver === "undefined" ? Object : ActorResolver
|
|
564
1116
|
])
|
|
565
1117
|
], AgentApiController);
|
|
566
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 !== "";
|
|
1257
|
+
}
|
|
1258
|
+
__name(isNonEmptyString, "isNonEmptyString");
|
|
1259
|
+
var AgentDashboardAuthController = class _AgentDashboardAuthController {
|
|
1260
|
+
static {
|
|
1261
|
+
__name(this, "AgentDashboardAuthController");
|
|
1262
|
+
}
|
|
1263
|
+
auth;
|
|
1264
|
+
basePath;
|
|
1265
|
+
logger = new Logger(_AgentDashboardAuthController.name);
|
|
1266
|
+
/** Warn once (not per request) so a broken hook can't be used to flood the logs. */
|
|
1267
|
+
warnedLoginHookThrow = false;
|
|
1268
|
+
constructor(auth, basePath) {
|
|
1269
|
+
this.auth = auth;
|
|
1270
|
+
this.basePath = basePath;
|
|
1271
|
+
}
|
|
1272
|
+
loginPage(req, res, returnToQuery, error) {
|
|
1273
|
+
this.requireAuth();
|
|
1274
|
+
const returnTo = sanitizeReturnTo(this.basePath, returnToQuery);
|
|
1275
|
+
if (this.currentSession(req)) {
|
|
1276
|
+
res.status(302);
|
|
1277
|
+
res.setHeader("Location", returnTo);
|
|
1278
|
+
return "";
|
|
1279
|
+
}
|
|
1280
|
+
return renderLoginPage({
|
|
1281
|
+
actionUrl: `${this.basePath}/auth/login`,
|
|
1282
|
+
returnTo,
|
|
1283
|
+
error: error !== void 0
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
async login(body, req, res) {
|
|
1287
|
+
const auth = this.requireAuth();
|
|
1288
|
+
const returnTo = sanitizeReturnTo(this.basePath, body?.returnTo);
|
|
1289
|
+
const username = body?.username;
|
|
1290
|
+
const password = body?.password;
|
|
1291
|
+
if (!isNonEmptyString(username) || !isNonEmptyString(password)) {
|
|
1292
|
+
this.redirectToLoginError(res, returnTo);
|
|
1293
|
+
return "";
|
|
1294
|
+
}
|
|
1295
|
+
const user = await this.runLoginHook(auth, username, password);
|
|
1296
|
+
if (!user) {
|
|
1297
|
+
this.redirectToLoginError(res, returnTo);
|
|
1298
|
+
return "";
|
|
1299
|
+
}
|
|
1300
|
+
issueSessionCookie(user, {
|
|
1301
|
+
auth,
|
|
1302
|
+
request: req,
|
|
1303
|
+
response: res
|
|
1304
|
+
});
|
|
1305
|
+
res.status(302);
|
|
1306
|
+
res.setHeader("Location", returnTo);
|
|
1307
|
+
return "";
|
|
1308
|
+
}
|
|
1309
|
+
logout(req, res) {
|
|
1310
|
+
clearSessionCookie({
|
|
1311
|
+
request: req,
|
|
1312
|
+
response: res
|
|
1313
|
+
});
|
|
1314
|
+
res.status(302);
|
|
1315
|
+
res.setHeader("Location", `${this.basePath}/auth/login`);
|
|
1316
|
+
return "";
|
|
1317
|
+
}
|
|
1318
|
+
/** Uniform failure: same redirect (generic error flag) whether the user is unknown or the password is wrong. */
|
|
1319
|
+
redirectToLoginError(res, returnTo) {
|
|
1320
|
+
res.status(303);
|
|
1321
|
+
res.setHeader("Location", `${this.basePath}/auth/login?error=1&returnTo=${encodeURIComponent(returnTo)}`);
|
|
1322
|
+
}
|
|
1323
|
+
currentSession(req) {
|
|
1324
|
+
const auth = this.auth;
|
|
1325
|
+
if (!auth) return false;
|
|
1326
|
+
const cookieValue = parseCookieHeader(readCookieHeader(req))[SESSION_COOKIE_NAME];
|
|
1327
|
+
if (cookieValue === void 0) return false;
|
|
1328
|
+
return verifySessionCookie(cookieValue, {
|
|
1329
|
+
secret: auth.secret
|
|
1330
|
+
}) !== null;
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Run the host's `login` hook defensively: a throw (sync or async) is treated as a denial
|
|
1334
|
+
* (`null`) and warn-logged ONCE, so a buggy/unreachable hook never 500s the endpoint into a
|
|
1335
|
+
* stack-trace leak nor floods the logs.
|
|
1336
|
+
*/
|
|
1337
|
+
async runLoginHook(auth, username, password) {
|
|
1338
|
+
try {
|
|
1339
|
+
return await auth.login(username, password) ?? null;
|
|
1340
|
+
} catch (error) {
|
|
1341
|
+
if (!this.warnedLoginHookThrow) {
|
|
1342
|
+
this.warnedLoginHookThrow = true;
|
|
1343
|
+
this.logger.warn(`AgentDashboardModule dashboardAuth login hook threw; treating as denial. ${error instanceof Error ? error.message : String(error)}`);
|
|
1344
|
+
}
|
|
1345
|
+
return null;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
requireAuth() {
|
|
1349
|
+
if (!this.auth) throw new NotFoundException();
|
|
1350
|
+
return this.auth;
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
_ts_decorate4([
|
|
1354
|
+
Get2("login"),
|
|
1355
|
+
Header("Content-Type", "text/html; charset=utf-8"),
|
|
1356
|
+
Header("Cache-Control", "no-store"),
|
|
1357
|
+
_ts_param4(0, Req2()),
|
|
1358
|
+
_ts_param4(1, Res({
|
|
1359
|
+
passthrough: true
|
|
1360
|
+
})),
|
|
1361
|
+
_ts_param4(2, Query2("returnTo")),
|
|
1362
|
+
_ts_param4(3, Query2("error")),
|
|
1363
|
+
_ts_metadata4("design:type", Function),
|
|
1364
|
+
_ts_metadata4("design:paramtypes", [
|
|
1365
|
+
typeof AuthPageRequest === "undefined" ? Object : AuthPageRequest,
|
|
1366
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse,
|
|
1367
|
+
String,
|
|
1368
|
+
String
|
|
1369
|
+
]),
|
|
1370
|
+
_ts_metadata4("design:returntype", String)
|
|
1371
|
+
], AgentDashboardAuthController.prototype, "loginPage", null);
|
|
1372
|
+
_ts_decorate4([
|
|
1373
|
+
Post2("login"),
|
|
1374
|
+
_ts_param4(0, Body2()),
|
|
1375
|
+
_ts_param4(1, Req2()),
|
|
1376
|
+
_ts_param4(2, Res({
|
|
1377
|
+
passthrough: true
|
|
1378
|
+
})),
|
|
1379
|
+
_ts_metadata4("design:type", Function),
|
|
1380
|
+
_ts_metadata4("design:paramtypes", [
|
|
1381
|
+
typeof LoginFormBody === "undefined" ? Object : LoginFormBody,
|
|
1382
|
+
Object,
|
|
1383
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
|
|
1384
|
+
]),
|
|
1385
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1386
|
+
], AgentDashboardAuthController.prototype, "login", null);
|
|
1387
|
+
_ts_decorate4([
|
|
1388
|
+
Post2("logout"),
|
|
1389
|
+
_ts_param4(0, Req2()),
|
|
1390
|
+
_ts_param4(1, Res({
|
|
1391
|
+
passthrough: true
|
|
1392
|
+
})),
|
|
1393
|
+
_ts_metadata4("design:type", Function),
|
|
1394
|
+
_ts_metadata4("design:paramtypes", [
|
|
1395
|
+
Object,
|
|
1396
|
+
typeof AuthPageResponse === "undefined" ? Object : AuthPageResponse
|
|
1397
|
+
]),
|
|
1398
|
+
_ts_metadata4("design:returntype", String)
|
|
1399
|
+
], AgentDashboardAuthController.prototype, "logout", null);
|
|
1400
|
+
AgentDashboardAuthController = _ts_decorate4([
|
|
1401
|
+
Controller2("auth"),
|
|
1402
|
+
_ts_param4(0, Optional4()),
|
|
1403
|
+
_ts_param4(0, Inject4(DASHBOARD_AUTH)),
|
|
1404
|
+
_ts_param4(1, Inject4(DASHBOARD_BASE_PATH)),
|
|
1405
|
+
_ts_metadata4("design:type", Function),
|
|
1406
|
+
_ts_metadata4("design:paramtypes", [
|
|
1407
|
+
Object,
|
|
1408
|
+
String
|
|
1409
|
+
])
|
|
1410
|
+
], AgentDashboardAuthController);
|
|
1411
|
+
|
|
567
1412
|
// src/server/normalize-path.ts
|
|
568
1413
|
function normalizeDashboardPath(path) {
|
|
569
1414
|
return `/${path.replace(/^\/+|\/+$/g, "")}`;
|
|
@@ -598,24 +1443,147 @@ import { RouterModule } from "@nestjs/core";
|
|
|
598
1443
|
import { existsSync, readFileSync } from "node:fs";
|
|
599
1444
|
import { basename, extname, join, resolve, sep } from "node:path";
|
|
600
1445
|
import { fileURLToPath } from "node:url";
|
|
601
|
-
import { Controller as
|
|
602
|
-
|
|
1446
|
+
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";
|
|
1447
|
+
|
|
1448
|
+
// src/server/auth/dashboard-auth-page.guard.ts
|
|
1449
|
+
import { Inject as Inject5, Injectable as Injectable4, Optional as Optional5 } from "@nestjs/common";
|
|
1450
|
+
|
|
1451
|
+
// src/server/auth/dashboard-auth-redirect.ts
|
|
1452
|
+
import { Catch, Injectable as Injectable3 } from "@nestjs/common";
|
|
1453
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
603
1454
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
604
1455
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
605
1456
|
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;
|
|
606
1457
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
607
1458
|
}
|
|
608
|
-
__name(
|
|
609
|
-
|
|
1459
|
+
__name(_ts_decorate5, "_ts_decorate");
|
|
1460
|
+
var DashboardAuthRedirect = class extends Error {
|
|
1461
|
+
static {
|
|
1462
|
+
__name(this, "DashboardAuthRedirect");
|
|
1463
|
+
}
|
|
1464
|
+
redirectTo;
|
|
1465
|
+
constructor(redirectTo) {
|
|
1466
|
+
super(`Redirect to ${redirectTo}`), this.redirectTo = redirectTo;
|
|
1467
|
+
this.name = "DashboardAuthRedirect";
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
var DashboardAuthRedirectFilter = class {
|
|
1471
|
+
static {
|
|
1472
|
+
__name(this, "DashboardAuthRedirectFilter");
|
|
1473
|
+
}
|
|
1474
|
+
catch(exception, host) {
|
|
1475
|
+
const response = host.switchToHttp().getResponse();
|
|
1476
|
+
sendRedirect(response, 302, exception.redirectTo);
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
DashboardAuthRedirectFilter = _ts_decorate5([
|
|
1480
|
+
Injectable3(),
|
|
1481
|
+
Catch(DashboardAuthRedirect)
|
|
1482
|
+
], DashboardAuthRedirectFilter);
|
|
1483
|
+
|
|
1484
|
+
// src/server/auth/dashboard-auth-page.guard.ts
|
|
1485
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
1486
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1487
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1488
|
+
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;
|
|
1489
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1490
|
+
}
|
|
1491
|
+
__name(_ts_decorate6, "_ts_decorate");
|
|
1492
|
+
function _ts_metadata5(k, v) {
|
|
610
1493
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
611
1494
|
}
|
|
612
|
-
__name(
|
|
613
|
-
function
|
|
1495
|
+
__name(_ts_metadata5, "_ts_metadata");
|
|
1496
|
+
function _ts_param5(paramIndex, decorator) {
|
|
614
1497
|
return function(target, key) {
|
|
615
1498
|
decorator(target, key, paramIndex);
|
|
616
1499
|
};
|
|
617
1500
|
}
|
|
618
|
-
__name(
|
|
1501
|
+
__name(_ts_param5, "_ts_param");
|
|
1502
|
+
var DashboardAuthPageGuard = class {
|
|
1503
|
+
static {
|
|
1504
|
+
__name(this, "DashboardAuthPageGuard");
|
|
1505
|
+
}
|
|
1506
|
+
auth;
|
|
1507
|
+
basePath;
|
|
1508
|
+
constructor(auth, basePath) {
|
|
1509
|
+
this.auth = auth;
|
|
1510
|
+
this.basePath = basePath;
|
|
1511
|
+
}
|
|
1512
|
+
canActivate(context) {
|
|
1513
|
+
if (!this.auth) return true;
|
|
1514
|
+
const http = context.switchToHttp();
|
|
1515
|
+
const request = http.getRequest();
|
|
1516
|
+
const session = this.verifyRequestSession(request);
|
|
1517
|
+
if (!session) {
|
|
1518
|
+
const returnTo = readOriginalUrl(request);
|
|
1519
|
+
throw new DashboardAuthRedirect(`${this.basePath}/auth/login?returnTo=${encodeURIComponent(returnTo)}`);
|
|
1520
|
+
}
|
|
1521
|
+
attachSession(request, session);
|
|
1522
|
+
this.maybeRenew(http.getResponse(), request, session);
|
|
1523
|
+
return true;
|
|
1524
|
+
}
|
|
1525
|
+
verifyRequestSession(request) {
|
|
1526
|
+
const auth = this.auth;
|
|
1527
|
+
if (!auth) return null;
|
|
1528
|
+
const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
|
|
1529
|
+
if (cookieValue === void 0) return null;
|
|
1530
|
+
return verifySessionCookie(cookieValue, {
|
|
1531
|
+
secret: auth.secret
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Sliding renewal: a valid cookie past 50% of its TTL is transparently re-issued on the
|
|
1536
|
+
* response, so an active user never gets logged out mid-session.
|
|
1537
|
+
*/
|
|
1538
|
+
maybeRenew(response, request, session) {
|
|
1539
|
+
const auth = this.auth;
|
|
1540
|
+
if (!auth) return;
|
|
1541
|
+
const now = Date.now();
|
|
1542
|
+
if (now - session.iat <= auth.ttlMs / 2) return;
|
|
1543
|
+
issueSessionCookie({
|
|
1544
|
+
id: session.sub,
|
|
1545
|
+
...session.name !== void 0 ? {
|
|
1546
|
+
name: session.name
|
|
1547
|
+
} : {},
|
|
1548
|
+
roles: session.roles
|
|
1549
|
+
}, {
|
|
1550
|
+
auth,
|
|
1551
|
+
request,
|
|
1552
|
+
response,
|
|
1553
|
+
now
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
DashboardAuthPageGuard = _ts_decorate6([
|
|
1558
|
+
Injectable4(),
|
|
1559
|
+
_ts_param5(0, Optional5()),
|
|
1560
|
+
_ts_param5(0, Inject5(DASHBOARD_AUTH)),
|
|
1561
|
+
_ts_param5(1, Inject5(DASHBOARD_BASE_PATH)),
|
|
1562
|
+
_ts_metadata5("design:type", Function),
|
|
1563
|
+
_ts_metadata5("design:paramtypes", [
|
|
1564
|
+
Object,
|
|
1565
|
+
String
|
|
1566
|
+
])
|
|
1567
|
+
], DashboardAuthPageGuard);
|
|
1568
|
+
|
|
1569
|
+
// src/server/agent-ui.controller.ts
|
|
1570
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
1571
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1572
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1573
|
+
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;
|
|
1574
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1575
|
+
}
|
|
1576
|
+
__name(_ts_decorate7, "_ts_decorate");
|
|
1577
|
+
function _ts_metadata6(k, v) {
|
|
1578
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1579
|
+
}
|
|
1580
|
+
__name(_ts_metadata6, "_ts_metadata");
|
|
1581
|
+
function _ts_param6(paramIndex, decorator) {
|
|
1582
|
+
return function(target, key) {
|
|
1583
|
+
decorator(target, key, paramIndex);
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
__name(_ts_param6, "_ts_param");
|
|
619
1587
|
var BUILD_BASE = "/ai-gateway";
|
|
620
1588
|
function spaDir() {
|
|
621
1589
|
return fileURLToPath(new URL("../spa", import.meta.url));
|
|
@@ -651,7 +1619,7 @@ var AgentUiController = class {
|
|
|
651
1619
|
}
|
|
652
1620
|
const indexPath = join(this.dir, "index.html");
|
|
653
1621
|
if (!existsSync(indexPath)) {
|
|
654
|
-
throw new
|
|
1622
|
+
throw new NotFoundException2("Dashboard is not built. Run the package build.");
|
|
655
1623
|
}
|
|
656
1624
|
const html = readFileSync(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
|
|
657
1625
|
const inject = `<script>window.__AGENT_BASE__='${this.basePath}';window.__AGENT_API__='${this.apiBasePath}';</script>`;
|
|
@@ -659,11 +1627,11 @@ var AgentUiController = class {
|
|
|
659
1627
|
}
|
|
660
1628
|
asset(file) {
|
|
661
1629
|
const safe = basename(file);
|
|
662
|
-
if (safe !== file) throw new
|
|
1630
|
+
if (safe !== file) throw new NotFoundException2();
|
|
663
1631
|
const root = resolve(this.dir, "assets");
|
|
664
1632
|
const assetPath = resolve(root, safe);
|
|
665
1633
|
if (!assetPath.startsWith(root + sep) || !existsSync(assetPath)) {
|
|
666
|
-
throw new
|
|
1634
|
+
throw new NotFoundException2();
|
|
667
1635
|
}
|
|
668
1636
|
const type = CONTENT_TYPES[extname(safe)] ?? "application/octet-stream";
|
|
669
1637
|
return new StreamableFile(readFileSync(assetPath), {
|
|
@@ -671,66 +1639,135 @@ var AgentUiController = class {
|
|
|
671
1639
|
});
|
|
672
1640
|
}
|
|
673
1641
|
};
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
1642
|
+
_ts_decorate7([
|
|
1643
|
+
Get3(),
|
|
1644
|
+
Header2("Content-Type", "text/html; charset=utf-8"),
|
|
1645
|
+
Header2("Cache-Control", "no-store, must-revalidate"),
|
|
1646
|
+
_ts_param6(0, Req3()),
|
|
1647
|
+
_ts_param6(1, Res2({
|
|
680
1648
|
passthrough: true
|
|
681
1649
|
})),
|
|
682
|
-
|
|
683
|
-
|
|
1650
|
+
_ts_metadata6("design:type", Function),
|
|
1651
|
+
_ts_metadata6("design:paramtypes", [
|
|
684
1652
|
typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
|
|
685
1653
|
typeof UiPageResponse === "undefined" ? Object : UiPageResponse
|
|
686
1654
|
]),
|
|
687
|
-
|
|
1655
|
+
_ts_metadata6("design:returntype", String)
|
|
688
1656
|
], AgentUiController.prototype, "index", null);
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1657
|
+
_ts_decorate7([
|
|
1658
|
+
Get3("assets/:file"),
|
|
1659
|
+
Header2("Cache-Control", "public, max-age=31536000, immutable"),
|
|
1660
|
+
_ts_param6(0, Param2("file")),
|
|
1661
|
+
_ts_metadata6("design:type", Function),
|
|
1662
|
+
_ts_metadata6("design:paramtypes", [
|
|
695
1663
|
String
|
|
696
1664
|
]),
|
|
697
|
-
|
|
1665
|
+
_ts_metadata6("design:returntype", typeof StreamableFile === "undefined" ? Object : StreamableFile)
|
|
698
1666
|
], AgentUiController.prototype, "asset", null);
|
|
699
|
-
AgentUiController =
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
1667
|
+
AgentUiController = _ts_decorate7([
|
|
1668
|
+
Controller3(),
|
|
1669
|
+
UseGuards2(DashboardAuthPageGuard),
|
|
1670
|
+
UseFilters(new DashboardAuthRedirectFilter()),
|
|
1671
|
+
_ts_param6(0, Inject6(DASHBOARD_BASE_PATH)),
|
|
1672
|
+
_ts_param6(1, Inject6(DASHBOARD_API_PATH)),
|
|
1673
|
+
_ts_metadata6("design:type", Function),
|
|
1674
|
+
_ts_metadata6("design:paramtypes", [
|
|
705
1675
|
String,
|
|
706
1676
|
String
|
|
707
1677
|
])
|
|
708
1678
|
], AgentUiController);
|
|
709
1679
|
|
|
1680
|
+
// src/server/auth/dashboard-auth-config.ts
|
|
1681
|
+
var DEFAULT_TTL = "8h";
|
|
1682
|
+
function unitToMs(unit) {
|
|
1683
|
+
switch (unit) {
|
|
1684
|
+
case "ms":
|
|
1685
|
+
return 1;
|
|
1686
|
+
case "s":
|
|
1687
|
+
return 1e3;
|
|
1688
|
+
case "m":
|
|
1689
|
+
return 6e4;
|
|
1690
|
+
case "h":
|
|
1691
|
+
return 36e5;
|
|
1692
|
+
case "d":
|
|
1693
|
+
return 864e5;
|
|
1694
|
+
default:
|
|
1695
|
+
return void 0;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
__name(unitToMs, "unitToMs");
|
|
1699
|
+
function durationToMs(duration) {
|
|
1700
|
+
const match = /^(\d+)(ms|s|m|h|d)$/.exec(duration.trim());
|
|
1701
|
+
const amount = match?.[1];
|
|
1702
|
+
const unit = match?.[2] !== void 0 ? unitToMs(match[2]) : void 0;
|
|
1703
|
+
if (amount === void 0 || unit === void 0) {
|
|
1704
|
+
throw new Error(`AgentDashboardModule dashboardAuth: invalid \`ttl\` duration: ${duration}`);
|
|
1705
|
+
}
|
|
1706
|
+
return Number(amount) * unit;
|
|
1707
|
+
}
|
|
1708
|
+
__name(durationToMs, "durationToMs");
|
|
1709
|
+
function resolveDashboardAuth(options) {
|
|
1710
|
+
if (options === void 0) return null;
|
|
1711
|
+
if (typeof options.secret !== "string" || options.secret === "") {
|
|
1712
|
+
throw new Error("AgentDashboardModule dashboardAuth: `secret` is required and must be a non-empty string (HMAC-SHA256 signing key, 32+ bytes recommended). Failing closed.");
|
|
1713
|
+
}
|
|
1714
|
+
if (typeof options.login !== "function") {
|
|
1715
|
+
throw new Error("AgentDashboardModule dashboardAuth: `login` is required (validates submitted credentials for the built-in login screen). Failing closed.");
|
|
1716
|
+
}
|
|
1717
|
+
return {
|
|
1718
|
+
secret: options.secret,
|
|
1719
|
+
ttlMs: durationToMs(options.ttl ?? DEFAULT_TTL),
|
|
1720
|
+
login: options.login
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
__name(resolveDashboardAuth, "resolveDashboardAuth");
|
|
1724
|
+
|
|
1725
|
+
// src/server/guards.ts
|
|
1726
|
+
import "reflect-metadata";
|
|
1727
|
+
var GUARDS_METADATA = "__guards__";
|
|
1728
|
+
function isGuardClass(guard) {
|
|
1729
|
+
return typeof guard === "function";
|
|
1730
|
+
}
|
|
1731
|
+
__name(isGuardClass, "isGuardClass");
|
|
1732
|
+
function baseGuards(controller) {
|
|
1733
|
+
return Reflect.getOwnMetadata(GUARDS_METADATA, controller) ?? [];
|
|
1734
|
+
}
|
|
1735
|
+
__name(baseGuards, "baseGuards");
|
|
1736
|
+
function stampGuards(guards, entries) {
|
|
1737
|
+
for (const [controller, base] of entries) {
|
|
1738
|
+
Reflect.defineMetadata(GUARDS_METADATA, [
|
|
1739
|
+
...base,
|
|
1740
|
+
...guards ?? []
|
|
1741
|
+
], controller);
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
__name(stampGuards, "stampGuards");
|
|
1745
|
+
|
|
710
1746
|
// src/server/agent-dashboard.module.ts
|
|
711
|
-
function
|
|
1747
|
+
function _ts_decorate8(decorators, target, key, desc) {
|
|
712
1748
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
713
1749
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
714
1750
|
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;
|
|
715
1751
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
716
1752
|
}
|
|
717
|
-
__name(
|
|
718
|
-
var
|
|
1753
|
+
__name(_ts_decorate8, "_ts_decorate");
|
|
1754
|
+
var API_BASE_GUARDS = baseGuards(AgentApiController);
|
|
1755
|
+
var UI_BASE_GUARDS = baseGuards(AgentUiController);
|
|
719
1756
|
function normalize(path) {
|
|
720
1757
|
return normalizeDashboardPath(path);
|
|
721
1758
|
}
|
|
722
1759
|
__name(normalize, "normalize");
|
|
723
|
-
function stampGuards(guards, ...controllers) {
|
|
724
|
-
for (const controller of controllers) {
|
|
725
|
-
Reflect.defineMetadata(GUARDS_METADATA, guards ?? [], controller);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
__name(stampGuards, "stampGuards");
|
|
729
1760
|
var AgentApiModule = class _AgentApiModule {
|
|
730
1761
|
static {
|
|
731
1762
|
__name(this, "AgentApiModule");
|
|
732
1763
|
}
|
|
733
1764
|
static register(options) {
|
|
1765
|
+
stampGuards(options.guards, [
|
|
1766
|
+
[
|
|
1767
|
+
AgentApiController,
|
|
1768
|
+
API_BASE_GUARDS
|
|
1769
|
+
]
|
|
1770
|
+
]);
|
|
734
1771
|
return {
|
|
735
1772
|
module: _AgentApiModule,
|
|
736
1773
|
imports: [
|
|
@@ -741,7 +1778,9 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
741
1778
|
],
|
|
742
1779
|
providers: [
|
|
743
1780
|
DashboardService,
|
|
744
|
-
|
|
1781
|
+
DashboardAuthGuard,
|
|
1782
|
+
options.dashboardAuth,
|
|
1783
|
+
...(options.guards ?? []).filter(isGuardClass),
|
|
745
1784
|
// `useValue` even when `options.approvalActorRef` is `undefined` — AgentApiController
|
|
746
1785
|
// injects this WITHOUT `@Optional()` (same pattern as `AGENT_QUOTA_STORE`'s factory).
|
|
747
1786
|
{
|
|
@@ -749,13 +1788,17 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
749
1788
|
useValue: options.approvalActorRef
|
|
750
1789
|
}
|
|
751
1790
|
],
|
|
1791
|
+
// DASHBOARD_AUTH re-exported so AgentUiController/AgentDashboardAuthController (hosted
|
|
1792
|
+
// directly by AgentDashboardModule, which imports this module) resolve the SAME instance
|
|
1793
|
+
// instead of re-running a host's async factory a second time.
|
|
752
1794
|
exports: [
|
|
753
|
-
DashboardService
|
|
1795
|
+
DashboardService,
|
|
1796
|
+
DASHBOARD_AUTH
|
|
754
1797
|
]
|
|
755
1798
|
};
|
|
756
1799
|
}
|
|
757
1800
|
};
|
|
758
|
-
AgentApiModule =
|
|
1801
|
+
AgentApiModule = _ts_decorate8([
|
|
759
1802
|
Module({})
|
|
760
1803
|
], AgentApiModule);
|
|
761
1804
|
var AgentDashboardModule = class _AgentDashboardModule {
|
|
@@ -765,7 +1808,16 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
765
1808
|
static forRoot(options = {}) {
|
|
766
1809
|
const basePath = normalize(options.basePath ?? "/ai-gateway");
|
|
767
1810
|
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
768
|
-
stampGuards(options.guards,
|
|
1811
|
+
stampGuards(options.guards, [
|
|
1812
|
+
[
|
|
1813
|
+
AgentUiController,
|
|
1814
|
+
UI_BASE_GUARDS
|
|
1815
|
+
]
|
|
1816
|
+
]);
|
|
1817
|
+
const dashboardAuthProvider = {
|
|
1818
|
+
provide: DASHBOARD_AUTH,
|
|
1819
|
+
useValue: resolveDashboardAuth(options.dashboardAuth)
|
|
1820
|
+
};
|
|
769
1821
|
return {
|
|
770
1822
|
module: _AgentDashboardModule,
|
|
771
1823
|
imports: [
|
|
@@ -782,7 +1834,8 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
782
1834
|
} : {},
|
|
783
1835
|
...options.approvalActorRef ? {
|
|
784
1836
|
approvalActorRef: options.approvalActorRef
|
|
785
|
-
} : {}
|
|
1837
|
+
} : {},
|
|
1838
|
+
dashboardAuth: dashboardAuthProvider
|
|
786
1839
|
}),
|
|
787
1840
|
RouterModule.register([
|
|
788
1841
|
{
|
|
@@ -796,7 +1849,8 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
796
1849
|
])
|
|
797
1850
|
],
|
|
798
1851
|
controllers: [
|
|
799
|
-
AgentUiController
|
|
1852
|
+
AgentUiController,
|
|
1853
|
+
AgentDashboardAuthController
|
|
800
1854
|
],
|
|
801
1855
|
providers: [
|
|
802
1856
|
{
|
|
@@ -807,8 +1861,9 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
807
1861
|
provide: DASHBOARD_API_PATH,
|
|
808
1862
|
useValue: apiBasePath
|
|
809
1863
|
},
|
|
1864
|
+
DashboardAuthPageGuard,
|
|
810
1865
|
// AgentUiController is hosted HERE, so its guards DI-instantiate from this module.
|
|
811
|
-
...options.guards ?? []
|
|
1866
|
+
...(options.guards ?? []).filter(isGuardClass)
|
|
812
1867
|
],
|
|
813
1868
|
// Re-export the API module so its DashboardService reaches importers (e.g. the host's own controllers).
|
|
814
1869
|
exports: [
|
|
@@ -816,8 +1871,70 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
816
1871
|
]
|
|
817
1872
|
};
|
|
818
1873
|
}
|
|
1874
|
+
static forRootAsync(options) {
|
|
1875
|
+
const basePath = normalize(options.basePath ?? "/ai-gateway");
|
|
1876
|
+
const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
|
|
1877
|
+
stampGuards(options.guards, [
|
|
1878
|
+
[
|
|
1879
|
+
AgentUiController,
|
|
1880
|
+
UI_BASE_GUARDS
|
|
1881
|
+
]
|
|
1882
|
+
]);
|
|
1883
|
+
const dashboardAuthProvider = {
|
|
1884
|
+
provide: DASHBOARD_AUTH,
|
|
1885
|
+
inject: options.inject ?? [],
|
|
1886
|
+
useFactory: /* @__PURE__ */ __name(async (...deps) => resolveDashboardAuth(await options.useDashboardAuth(...deps)), "useFactory")
|
|
1887
|
+
};
|
|
1888
|
+
return {
|
|
1889
|
+
module: _AgentDashboardModule,
|
|
1890
|
+
imports: [
|
|
1891
|
+
...options.imports ?? [],
|
|
1892
|
+
AgentApiModule.register({
|
|
1893
|
+
...options.imports ? {
|
|
1894
|
+
imports: options.imports
|
|
1895
|
+
} : {},
|
|
1896
|
+
...options.guards ? {
|
|
1897
|
+
guards: options.guards
|
|
1898
|
+
} : {},
|
|
1899
|
+
...options.approvalActorRef ? {
|
|
1900
|
+
approvalActorRef: options.approvalActorRef
|
|
1901
|
+
} : {},
|
|
1902
|
+
dashboardAuth: dashboardAuthProvider
|
|
1903
|
+
}),
|
|
1904
|
+
RouterModule.register([
|
|
1905
|
+
{
|
|
1906
|
+
path: basePath,
|
|
1907
|
+
module: _AgentDashboardModule
|
|
1908
|
+
},
|
|
1909
|
+
{
|
|
1910
|
+
path: apiBasePath,
|
|
1911
|
+
module: AgentApiModule
|
|
1912
|
+
}
|
|
1913
|
+
])
|
|
1914
|
+
],
|
|
1915
|
+
controllers: [
|
|
1916
|
+
AgentUiController,
|
|
1917
|
+
AgentDashboardAuthController
|
|
1918
|
+
],
|
|
1919
|
+
providers: [
|
|
1920
|
+
{
|
|
1921
|
+
provide: DASHBOARD_BASE_PATH,
|
|
1922
|
+
useValue: basePath
|
|
1923
|
+
},
|
|
1924
|
+
{
|
|
1925
|
+
provide: DASHBOARD_API_PATH,
|
|
1926
|
+
useValue: apiBasePath
|
|
1927
|
+
},
|
|
1928
|
+
DashboardAuthPageGuard,
|
|
1929
|
+
...(options.guards ?? []).filter(isGuardClass)
|
|
1930
|
+
],
|
|
1931
|
+
exports: [
|
|
1932
|
+
AgentApiModule
|
|
1933
|
+
]
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
819
1936
|
};
|
|
820
|
-
AgentDashboardModule =
|
|
1937
|
+
AgentDashboardModule = _ts_decorate8([
|
|
821
1938
|
Module({})
|
|
822
1939
|
], AgentDashboardModule);
|
|
823
1940
|
export {
|
|
@@ -828,13 +1945,16 @@ export {
|
|
|
828
1945
|
AGENT_PRICING_STORE,
|
|
829
1946
|
AgentApiController,
|
|
830
1947
|
AgentApiModule,
|
|
1948
|
+
AgentDashboardAuthController,
|
|
831
1949
|
AgentDashboardModule,
|
|
832
1950
|
AgentUiController,
|
|
833
1951
|
DASHBOARD_API_PATH,
|
|
834
1952
|
DASHBOARD_APPROVAL_ACTOR_REF,
|
|
1953
|
+
DASHBOARD_AUTH,
|
|
835
1954
|
DASHBOARD_BASE_PATH,
|
|
836
1955
|
DashboardService,
|
|
837
1956
|
agentDashboardMountPaths,
|
|
838
|
-
parsePriceInput
|
|
1957
|
+
parsePriceInput,
|
|
1958
|
+
resolveDashboardAuth
|
|
839
1959
|
};
|
|
840
1960
|
//# sourceMappingURL=index.js.map
|