@dudousxd/nestjs-agent-dashboard 0.20.0 → 0.21.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/dist/server/index.cjs +542 -65
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +73 -3
- package/dist/server/index.d.ts +73 -3
- package/dist/server/index.js +530 -57
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -83,6 +83,7 @@ var DASHBOARD_BASE_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-das
|
|
|
83
83
|
var DASHBOARD_API_PATH = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
|
|
84
84
|
var DASHBOARD_APPROVAL_ACTOR_REF = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
|
|
85
85
|
var DASHBOARD_CONSOLE_OPTIONS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:console-options");
|
|
86
|
+
var DASHBOARD_DEV_TOOLS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-dashboard:dev-tools");
|
|
86
87
|
|
|
87
88
|
// src/server/dashboard.service.ts
|
|
88
89
|
function _ts_decorate(decorators, target, key, desc) {
|
|
@@ -161,8 +162,8 @@ var DashboardService = class {
|
|
|
161
162
|
};
|
|
162
163
|
}
|
|
163
164
|
/** Top threads by cost for a day range (default 10, highest cost first). */
|
|
164
|
-
async topThreads(range,
|
|
165
|
-
const rows = await this.queries.spendByThread(range,
|
|
165
|
+
async topThreads(range, limit2 = 10) {
|
|
166
|
+
const rows = await this.queries.spendByThread(range, limit2);
|
|
166
167
|
return this.withActorLabels(rows);
|
|
167
168
|
}
|
|
168
169
|
/** Run reliability for a day range: metrics, by-agent/by-error breakdowns and the trend, in parallel. */
|
|
@@ -181,12 +182,12 @@ var DashboardService = class {
|
|
|
181
182
|
};
|
|
182
183
|
}
|
|
183
184
|
/** Most recent runs (status/agent/duration/error) for the Reliability recent-runs table. */
|
|
184
|
-
recentRuns(
|
|
185
|
-
return this.queries.recentRuns(
|
|
185
|
+
recentRuns(limit2) {
|
|
186
|
+
return this.queries.recentRuns(limit2);
|
|
186
187
|
}
|
|
187
188
|
/** Most recent tool calls (status/type/thread) for the Runs & tools activity feed. */
|
|
188
|
-
recentToolCalls(
|
|
189
|
-
return this.queries.recentToolCalls(
|
|
189
|
+
recentToolCalls(limit2) {
|
|
190
|
+
return this.queries.recentToolCalls(limit2);
|
|
190
191
|
}
|
|
191
192
|
/** Paged, filterable tool calls for the Runs & tools activity table. */
|
|
192
193
|
toolCallsPage(query) {
|
|
@@ -201,8 +202,8 @@ var DashboardService = class {
|
|
|
201
202
|
* Capped and totalless — kept because the SPA still calls `GET approvals`; new callers want
|
|
202
203
|
* {@link approvalsPage}, which reports how much of the backlog the cap hid.
|
|
203
204
|
*/
|
|
204
|
-
pendingApprovals(
|
|
205
|
-
return this.queries.pendingApprovals(
|
|
205
|
+
pendingApprovals(limit2) {
|
|
206
|
+
return this.queries.pendingApprovals(limit2);
|
|
206
207
|
}
|
|
207
208
|
/** Paged, filterable approvals inbox with a total — the backlog-safe read of the HITL queue. */
|
|
208
209
|
approvalsPage(query) {
|
|
@@ -290,8 +291,8 @@ var DashboardService = class {
|
|
|
290
291
|
});
|
|
291
292
|
}
|
|
292
293
|
/** Most recent threads with rolled-up message/token counts. */
|
|
293
|
-
async recentThreads(
|
|
294
|
-
const rows = await this.queries.recentThreads(
|
|
294
|
+
async recentThreads(limit2) {
|
|
295
|
+
const rows = await this.queries.recentThreads(limit2);
|
|
295
296
|
return this.withActorLabels(rows);
|
|
296
297
|
}
|
|
297
298
|
/**
|
|
@@ -299,10 +300,10 @@ var DashboardService = class {
|
|
|
299
300
|
* {@link recentThreads} is.
|
|
300
301
|
*/
|
|
301
302
|
async threadsPage(query) {
|
|
302
|
-
const
|
|
303
|
-
const rows = await this.withActorLabels(
|
|
303
|
+
const page2 = await this.queries.threadsPage(query);
|
|
304
|
+
const rows = await this.withActorLabels(page2.rows);
|
|
304
305
|
return {
|
|
305
|
-
...
|
|
306
|
+
...page2,
|
|
306
307
|
rows
|
|
307
308
|
};
|
|
308
309
|
}
|
|
@@ -623,27 +624,27 @@ var AgentApiController = class {
|
|
|
623
624
|
return this.dashboard.spend(resolveRange(from, to));
|
|
624
625
|
}
|
|
625
626
|
/** Top threads by cost (default 10, max 200) for a day range (defaults to the last 30 days). */
|
|
626
|
-
topThreads(from, to,
|
|
627
|
-
return this.dashboard.topThreads(resolveRange(from, to), parseLimit(
|
|
627
|
+
topThreads(from, to, limit2) {
|
|
628
|
+
return this.dashboard.topThreads(resolveRange(from, to), parseLimit(limit2, 10));
|
|
628
629
|
}
|
|
629
630
|
/** `{ metrics, byAgent, errors, trend }` for a day range (defaults to the last 30 days). */
|
|
630
631
|
reliability(from, to) {
|
|
631
632
|
return this.dashboard.reliability(resolveRange(from, to));
|
|
632
633
|
}
|
|
633
634
|
/** Most recent runs (default 50, max 200) for the Reliability recent-runs table. */
|
|
634
|
-
runs(
|
|
635
|
-
return this.dashboard.recentRuns(parseLimit(
|
|
635
|
+
runs(limit2) {
|
|
636
|
+
return this.dashboard.recentRuns(parseLimit(limit2, 50));
|
|
636
637
|
}
|
|
637
638
|
/**
|
|
638
639
|
* Paged, filterable runs for the Reliability recent-runs table. `page` (default 1), `limit`
|
|
639
640
|
* (default 25, max 200), and `where[agentName]`/`where[status]`/`where[errorCode]`/
|
|
640
641
|
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
641
642
|
*/
|
|
642
|
-
runsPage(
|
|
643
|
-
const parsedWhere = parseRunWhere(
|
|
643
|
+
runsPage(page2, limit2, where2) {
|
|
644
|
+
const parsedWhere = parseRunWhere(where2);
|
|
644
645
|
return this.dashboard.runsPage({
|
|
645
|
-
page: parsePageNumber(
|
|
646
|
-
pageSize: parseLimit(
|
|
646
|
+
page: parsePageNumber(page2),
|
|
647
|
+
pageSize: parseLimit(limit2, 25),
|
|
647
648
|
...parsedWhere !== void 0 ? {
|
|
648
649
|
where: parsedWhere
|
|
649
650
|
} : {}
|
|
@@ -660,19 +661,19 @@ var AgentApiController = class {
|
|
|
660
661
|
return this.dashboard.runDetail(runId);
|
|
661
662
|
}
|
|
662
663
|
/** Most recent tool calls (default 50, max 200) for the activity feed. */
|
|
663
|
-
toolCalls(
|
|
664
|
-
return this.dashboard.recentToolCalls(parseLimit(
|
|
664
|
+
toolCalls(limit2) {
|
|
665
|
+
return this.dashboard.recentToolCalls(parseLimit(limit2, 50));
|
|
665
666
|
}
|
|
666
667
|
/**
|
|
667
668
|
* Paged, filterable tool calls for the Runs & tools activity table. `page` (default 1), `limit`
|
|
668
669
|
* (default 25, max 200), and `where[toolName]`/`where[toolType]`/`where[status]`/`where[threadId]`/
|
|
669
670
|
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
670
671
|
*/
|
|
671
|
-
toolCallsPage(
|
|
672
|
-
const parsedWhere = parseToolCallWhere(
|
|
672
|
+
toolCallsPage(page2, limit2, where2) {
|
|
673
|
+
const parsedWhere = parseToolCallWhere(where2);
|
|
673
674
|
return this.dashboard.toolCallsPage({
|
|
674
|
-
page: parsePageNumber(
|
|
675
|
-
pageSize: parseLimit(
|
|
675
|
+
page: parsePageNumber(page2),
|
|
676
|
+
pageSize: parseLimit(limit2, 25),
|
|
676
677
|
...parsedWhere !== void 0 ? {
|
|
677
678
|
where: parsedWhere
|
|
678
679
|
} : {}
|
|
@@ -684,8 +685,8 @@ var AgentApiController = class {
|
|
|
684
685
|
* Capped with NO total, so a backlog past `limit` is invisible from the response alone. Kept
|
|
685
686
|
* because the SPA still calls it; anything new should call `approvals-page` instead.
|
|
686
687
|
*/
|
|
687
|
-
approvals(
|
|
688
|
-
return this.dashboard.pendingApprovals(parseLimit(
|
|
688
|
+
approvals(limit2) {
|
|
689
|
+
return this.dashboard.pendingApprovals(parseLimit(limit2, 50));
|
|
689
690
|
}
|
|
690
691
|
/**
|
|
691
692
|
* Paged, filterable approvals inbox, oldest first. `page` (default 1), `limit` (default 25, max
|
|
@@ -695,11 +696,11 @@ var AgentApiController = class {
|
|
|
695
696
|
* Unlike `GET approvals` this reports `total`, so the console can say "showing N of M" instead of
|
|
696
697
|
* silently hiding pending decisions behind a row cap.
|
|
697
698
|
*/
|
|
698
|
-
approvalsPage(
|
|
699
|
-
const parsedWhere = parseApprovalWhere(
|
|
699
|
+
approvalsPage(page2, limit2, where2) {
|
|
700
|
+
const parsedWhere = parseApprovalWhere(where2);
|
|
700
701
|
return this.dashboard.approvalsPage({
|
|
701
|
-
page: parsePageNumber(
|
|
702
|
-
pageSize: parseLimit(
|
|
702
|
+
page: parsePageNumber(page2),
|
|
703
|
+
pageSize: parseLimit(limit2, 25),
|
|
703
704
|
...parsedWhere !== void 0 ? {
|
|
704
705
|
where: parsedWhere
|
|
705
706
|
} : {}
|
|
@@ -746,19 +747,19 @@ var AgentApiController = class {
|
|
|
746
747
|
return this.dashboard.genuiStats(resolveRange(from, to));
|
|
747
748
|
}
|
|
748
749
|
/** Most recent threads (default 50, max 200) with rolled-up counts. */
|
|
749
|
-
threads(
|
|
750
|
-
return this.dashboard.recentThreads(parseLimit(
|
|
750
|
+
threads(limit2) {
|
|
751
|
+
return this.dashboard.recentThreads(parseLimit(limit2, 50));
|
|
751
752
|
}
|
|
752
753
|
/**
|
|
753
754
|
* Paged, filterable threads for the Runs & tools threads table. `page` (default 1), `limit`
|
|
754
755
|
* (default 25, max 200), and `where[actorRef]`/`where[title]` (case-insensitive substring)/
|
|
755
756
|
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
756
757
|
*/
|
|
757
|
-
threadsPage(
|
|
758
|
-
const parsedWhere = parseThreadWhere(
|
|
758
|
+
threadsPage(page2, limit2, where2) {
|
|
759
|
+
const parsedWhere = parseThreadWhere(where2);
|
|
759
760
|
return this.dashboard.threadsPage({
|
|
760
|
-
page: parsePageNumber(
|
|
761
|
-
pageSize: parseLimit(
|
|
761
|
+
page: parsePageNumber(page2),
|
|
762
|
+
pageSize: parseLimit(limit2, 25),
|
|
762
763
|
...parsedWhere !== void 0 ? {
|
|
763
764
|
where: parsedWhere
|
|
764
765
|
} : {}
|
|
@@ -1056,19 +1057,23 @@ import { Controller as Controller2, Get as Get2, Header, Inject as Inject4, NotF
|
|
|
1056
1057
|
|
|
1057
1058
|
// src/server/console-authorize.guard.ts
|
|
1058
1059
|
import { Catch, HttpException, Inject as Inject3, Injectable as Injectable2, SetMetadata, UseFilters, UseGuards, applyDecorators } from "@nestjs/common";
|
|
1059
|
-
import { HttpAdapterHost, ModuleRef } from "@nestjs/core";
|
|
1060
|
+
import { HttpAdapterHost, ModuleRef as ModuleRef2 } from "@nestjs/core";
|
|
1060
1061
|
|
|
1061
1062
|
// src/server/console-authorize.ts
|
|
1062
1063
|
import { createHash, timingSafeEqual } from "crypto";
|
|
1063
1064
|
import { Logger } from "@nestjs/common";
|
|
1065
|
+
import { ModuleRef } from "@nestjs/core";
|
|
1064
1066
|
var CONSOLE_GATE = /* @__PURE__ */ Symbol.for("@dudousxd/aviary:console-gate");
|
|
1065
1067
|
var PACKAGE = "@dudousxd/nestjs-agent-dashboard";
|
|
1066
1068
|
var MODULE = "AgentDashboardModule";
|
|
1067
1069
|
var logger = new Logger(MODULE);
|
|
1068
1070
|
var CONSOLE_AUTHORIZE_MISSING_WARNING = `[${PACKAGE}] console has no \`authorize\` configured: it is open outside production and denies every request in production. Set \`authorize\` in ${MODULE}.forRoot().`;
|
|
1069
|
-
var allow = /* @__PURE__ */ __name(() =>
|
|
1071
|
+
var allow = /* @__PURE__ */ __name((caller) => caller !== void 0 && caller !== "" ? {
|
|
1072
|
+
allowed: true,
|
|
1073
|
+
caller
|
|
1074
|
+
} : {
|
|
1070
1075
|
allowed: true
|
|
1071
|
-
}
|
|
1076
|
+
}, "allow");
|
|
1072
1077
|
var forbidden = /* @__PURE__ */ __name(() => ({
|
|
1073
1078
|
allowed: false,
|
|
1074
1079
|
reason: "forbidden"
|
|
@@ -1092,7 +1097,9 @@ function normalizeConsoleResult(result) {
|
|
|
1092
1097
|
redirectTo: value.redirectTo
|
|
1093
1098
|
};
|
|
1094
1099
|
}
|
|
1095
|
-
if (value.allowed === true)
|
|
1100
|
+
if (value.allowed === true) {
|
|
1101
|
+
return allow(typeof value.caller === "string" ? value.caller : void 0);
|
|
1102
|
+
}
|
|
1096
1103
|
return value.reason === "unauthenticated" ? unauthenticated() : forbidden();
|
|
1097
1104
|
}
|
|
1098
1105
|
__name(normalizeConsoleResult, "normalizeConsoleResult");
|
|
@@ -1168,7 +1175,7 @@ async function resolveConsoleAuthorize(authorize, moduleRef, options = {}) {
|
|
|
1168
1175
|
if (authorize === void 0) {
|
|
1169
1176
|
if (options.warnIfMissing !== false) log.warn(CONSOLE_AUTHORIZE_MISSING_WARNING);
|
|
1170
1177
|
const production = isProduction();
|
|
1171
|
-
return async () => production ? forbidden() : allow();
|
|
1178
|
+
return async () => production ? forbidden() : allow("dev-open");
|
|
1172
1179
|
}
|
|
1173
1180
|
const instanceOf = classInstances(moduleRef);
|
|
1174
1181
|
let decide;
|
|
@@ -1218,12 +1225,18 @@ function authorizeByToken(options) {
|
|
|
1218
1225
|
throw new Error("authorizeByToken: `token` is empty; set it (e.g. from an env var).");
|
|
1219
1226
|
}
|
|
1220
1227
|
const expected = sha256(token);
|
|
1228
|
+
const caller = `token:${expected.toString("hex").slice(0, 12)}`;
|
|
1221
1229
|
return (context) => {
|
|
1222
1230
|
const req = context.switchToHttp().getRequest();
|
|
1223
1231
|
const header = req?.headers?.authorization;
|
|
1224
1232
|
const value = Array.isArray(header) ? header[0] : header;
|
|
1225
1233
|
const match = typeof value === "string" ? /^Bearer\s+(.+)$/i.exec(value.trim()) : null;
|
|
1226
|
-
if (match?.[1] !== void 0 && timingSafeEqual(sha256(match[1]), expected))
|
|
1234
|
+
if (match?.[1] !== void 0 && timingSafeEqual(sha256(match[1]), expected)) {
|
|
1235
|
+
return {
|
|
1236
|
+
allowed: true,
|
|
1237
|
+
caller
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1227
1240
|
return {
|
|
1228
1241
|
allowed: false,
|
|
1229
1242
|
reason: "unauthenticated"
|
|
@@ -1231,6 +1244,48 @@ function authorizeByToken(options) {
|
|
|
1231
1244
|
};
|
|
1232
1245
|
}
|
|
1233
1246
|
__name(authorizeByToken, "authorizeByToken");
|
|
1247
|
+
function anyAuthorize(...forms) {
|
|
1248
|
+
if (forms.length === 0) throw new Error("anyAuthorize: pass at least one authorize form.");
|
|
1249
|
+
let AnyConsoleAuthorizer = class AnyConsoleAuthorizer {
|
|
1250
|
+
static {
|
|
1251
|
+
__name(this, "AnyConsoleAuthorizer");
|
|
1252
|
+
}
|
|
1253
|
+
moduleRef;
|
|
1254
|
+
#decides;
|
|
1255
|
+
constructor(moduleRef) {
|
|
1256
|
+
this.moduleRef = moduleRef;
|
|
1257
|
+
}
|
|
1258
|
+
async authorize(context) {
|
|
1259
|
+
this.#decides ??= Promise.all(forms.map((form) => resolveConsoleAuthorize(form, this.moduleRef, {
|
|
1260
|
+
warnIfMissing: false
|
|
1261
|
+
})));
|
|
1262
|
+
this.#decides.catch(() => {
|
|
1263
|
+
this.#decides = void 0;
|
|
1264
|
+
});
|
|
1265
|
+
let unauthenticated2;
|
|
1266
|
+
for (const decide of await this.#decides) {
|
|
1267
|
+
const decision = await decide(context);
|
|
1268
|
+
if (decision.allowed) return decision;
|
|
1269
|
+
if (decision.reason === "unauthenticated") unauthenticated2 ??= decision;
|
|
1270
|
+
}
|
|
1271
|
+
if (unauthenticated2 === void 0) return {
|
|
1272
|
+
allowed: false,
|
|
1273
|
+
reason: "forbidden"
|
|
1274
|
+
};
|
|
1275
|
+
return "redirectTo" in unauthenticated2 && unauthenticated2.redirectTo !== void 0 ? {
|
|
1276
|
+
redirectTo: unauthenticated2.redirectTo
|
|
1277
|
+
} : {
|
|
1278
|
+
allowed: false,
|
|
1279
|
+
reason: "unauthenticated"
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
Reflect.defineMetadata("design:paramtypes", [
|
|
1284
|
+
ModuleRef
|
|
1285
|
+
], AnyConsoleAuthorizer);
|
|
1286
|
+
return AnyConsoleAuthorizer;
|
|
1287
|
+
}
|
|
1288
|
+
__name(anyAuthorize, "anyAuthorize");
|
|
1234
1289
|
|
|
1235
1290
|
// src/server/console-authorize.guard.ts
|
|
1236
1291
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
@@ -1288,7 +1343,7 @@ DashboardConsoleAccess = _ts_decorate3([
|
|
|
1288
1343
|
_ts_metadata3("design:type", Function),
|
|
1289
1344
|
_ts_metadata3("design:paramtypes", [
|
|
1290
1345
|
typeof DashboardConsoleOptions === "undefined" ? Object : DashboardConsoleOptions,
|
|
1291
|
-
typeof
|
|
1346
|
+
typeof ModuleRef2 === "undefined" ? Object : ModuleRef2
|
|
1292
1347
|
])
|
|
1293
1348
|
], DashboardConsoleAccess);
|
|
1294
1349
|
var CONSOLE_PAGE_METADATA = "@dudousxd/nestjs-agent-dashboard:console-page";
|
|
@@ -1299,7 +1354,7 @@ var ConsoleAccessDenied = class extends HttpException {
|
|
|
1299
1354
|
}
|
|
1300
1355
|
decision;
|
|
1301
1356
|
page;
|
|
1302
|
-
constructor(decision,
|
|
1357
|
+
constructor(decision, page2) {
|
|
1303
1358
|
super(decision.reason === "forbidden" ? {
|
|
1304
1359
|
error: "forbidden"
|
|
1305
1360
|
} : {
|
|
@@ -1307,13 +1362,13 @@ var ConsoleAccessDenied = class extends HttpException {
|
|
|
1307
1362
|
...decision.redirectTo !== void 0 ? {
|
|
1308
1363
|
redirectTo: decision.redirectTo
|
|
1309
1364
|
} : {}
|
|
1310
|
-
}, decision.reason === "forbidden" ? 403 : 401), this.decision = decision, this.page =
|
|
1365
|
+
}, decision.reason === "forbidden" ? 403 : 401), this.decision = decision, this.page = page2;
|
|
1311
1366
|
}
|
|
1312
1367
|
};
|
|
1313
1368
|
function isPageNavigation(context) {
|
|
1314
1369
|
if (context.getType() !== "http") return false;
|
|
1315
|
-
const
|
|
1316
|
-
if (!
|
|
1370
|
+
const page2 = Reflect.getMetadata(CONSOLE_PAGE_METADATA, context.getHandler()) === true || Reflect.getMetadata(CONSOLE_PAGE_METADATA, context.getClass()) === true;
|
|
1371
|
+
if (!page2) return false;
|
|
1317
1372
|
const req = context.switchToHttp().getRequest();
|
|
1318
1373
|
if ((req.method ?? "GET").toUpperCase() !== "GET") return false;
|
|
1319
1374
|
const accept = req.headers?.accept;
|
|
@@ -1360,12 +1415,12 @@ var ConsoleAuthorizeFilter = class {
|
|
|
1360
1415
|
catch(exception, host) {
|
|
1361
1416
|
const adapter = this.adapterHost.httpAdapter;
|
|
1362
1417
|
const res = host.switchToHttp().getResponse();
|
|
1363
|
-
const { decision, page } = exception;
|
|
1364
|
-
if (
|
|
1418
|
+
const { decision, page: page2 } = exception;
|
|
1419
|
+
if (page2 && decision.reason === "unauthenticated" && decision.redirectTo !== void 0) {
|
|
1365
1420
|
adapter.redirect(res, 302, decision.redirectTo);
|
|
1366
1421
|
return;
|
|
1367
1422
|
}
|
|
1368
|
-
if (
|
|
1423
|
+
if (page2) {
|
|
1369
1424
|
const forbidden2 = decision.reason === "forbidden";
|
|
1370
1425
|
adapter.setHeader(res, "Content-Type", "text/html; charset=utf-8");
|
|
1371
1426
|
adapter.reply(res, forbidden2 ? FORBIDDEN_PAGE : UNAUTHENTICATED_PAGE, forbidden2 ? 403 : 401);
|
|
@@ -1507,7 +1562,8 @@ AgentUiController = _ts_decorate4([
|
|
|
1507
1562
|
])
|
|
1508
1563
|
], AgentUiController);
|
|
1509
1564
|
|
|
1510
|
-
// src/server/
|
|
1565
|
+
// src/server/dev-tools.ts
|
|
1566
|
+
import { Inject as Inject5, Injectable as Injectable3, Logger as Logger2, NotFoundException as NotFoundException3 } from "@nestjs/common";
|
|
1511
1567
|
function _ts_decorate5(decorators, target, key, desc) {
|
|
1512
1568
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1513
1569
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -1522,6 +1578,411 @@ function _ts_decorate5(decorators, target, key, desc) {
|
|
|
1522
1578
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1523
1579
|
}
|
|
1524
1580
|
__name(_ts_decorate5, "_ts_decorate");
|
|
1581
|
+
function _ts_metadata5(metadataKey, metadataValue) {
|
|
1582
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
1583
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
__name(_ts_metadata5, "_ts_metadata");
|
|
1587
|
+
function _ts_param5(paramIndex, decorator) {
|
|
1588
|
+
return function(target, key) {
|
|
1589
|
+
decorator(target, key, paramIndex);
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
__name(_ts_param5, "_ts_param");
|
|
1593
|
+
var DEV_TOOLS_SLOT = /* @__PURE__ */ Symbol.for("@dudousxd/aviary:dev-tools");
|
|
1594
|
+
function devToolsSlot() {
|
|
1595
|
+
const holder = globalThis;
|
|
1596
|
+
const existing = holder[DEV_TOOLS_SLOT];
|
|
1597
|
+
if (existing !== void 0) return existing;
|
|
1598
|
+
const libs = [];
|
|
1599
|
+
const slot = {
|
|
1600
|
+
version: 1,
|
|
1601
|
+
libs,
|
|
1602
|
+
register(lib) {
|
|
1603
|
+
if (libs.some((entry) => entry.lib === lib.lib)) {
|
|
1604
|
+
throw new Error(`dev tools: the lib "${lib.lib}" is already registered`);
|
|
1605
|
+
}
|
|
1606
|
+
libs.push(lib);
|
|
1607
|
+
return () => {
|
|
1608
|
+
const index = libs.indexOf(lib);
|
|
1609
|
+
if (index !== -1) libs.splice(index, 1);
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
holder[DEV_TOOLS_SLOT] = slot;
|
|
1614
|
+
return slot;
|
|
1615
|
+
}
|
|
1616
|
+
__name(devToolsSlot, "devToolsSlot");
|
|
1617
|
+
var DEFAULT_LIMIT = 20;
|
|
1618
|
+
var MAX_LIMIT = 100;
|
|
1619
|
+
var MESSAGE_LIMIT = 50;
|
|
1620
|
+
var MESSAGE_BYTES = 2 * 1024;
|
|
1621
|
+
var DAY_MS2 = 864e5;
|
|
1622
|
+
var ISO_DAY3 = /^\d{4}-\d{2}-\d{2}$/;
|
|
1623
|
+
var day = {
|
|
1624
|
+
type: "string",
|
|
1625
|
+
description: "UTC day, YYYY-MM-DD."
|
|
1626
|
+
};
|
|
1627
|
+
var page = {
|
|
1628
|
+
type: "integer",
|
|
1629
|
+
description: "Page, from 1. Pass the `next` of the previous page.",
|
|
1630
|
+
minimum: 1
|
|
1631
|
+
};
|
|
1632
|
+
var limit = {
|
|
1633
|
+
type: "integer",
|
|
1634
|
+
description: `Rows per page (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT}).`,
|
|
1635
|
+
minimum: 1,
|
|
1636
|
+
maximum: MAX_LIMIT
|
|
1637
|
+
};
|
|
1638
|
+
var str = /* @__PURE__ */ __name((value) => typeof value === "string" && value !== "" ? value : void 0, "str");
|
|
1639
|
+
function dayOf(input, key) {
|
|
1640
|
+
const value = str(input[key]);
|
|
1641
|
+
if (value !== void 0 && !ISO_DAY3.test(value)) throw new Error(`"${key}" must be YYYY-MM-DD`);
|
|
1642
|
+
return value;
|
|
1643
|
+
}
|
|
1644
|
+
__name(dayOf, "dayOf");
|
|
1645
|
+
function rangeOf(input) {
|
|
1646
|
+
const utcDay2 = /* @__PURE__ */ __name((daysAgo) => new Date(Date.now() - daysAgo * DAY_MS2).toISOString().slice(0, 10), "utcDay");
|
|
1647
|
+
return {
|
|
1648
|
+
fromDay: dayOf(input, "from") ?? utcDay2(29),
|
|
1649
|
+
toDay: dayOf(input, "to") ?? utcDay2(0)
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
__name(rangeOf, "rangeOf");
|
|
1653
|
+
function pageOf(input) {
|
|
1654
|
+
return {
|
|
1655
|
+
page: typeof input.page === "number" ? input.page : 1,
|
|
1656
|
+
pageSize: typeof input.limit === "number" ? input.limit : DEFAULT_LIMIT
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
__name(pageOf, "pageOf");
|
|
1660
|
+
function where(fields) {
|
|
1661
|
+
const set = Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== void 0));
|
|
1662
|
+
return Object.keys(set).length > 0 ? {
|
|
1663
|
+
where: set
|
|
1664
|
+
} : {};
|
|
1665
|
+
}
|
|
1666
|
+
__name(where, "where");
|
|
1667
|
+
function listOf(result) {
|
|
1668
|
+
return {
|
|
1669
|
+
items: result.rows,
|
|
1670
|
+
next: result.page * result.pageSize < result.total ? result.page + 1 : null,
|
|
1671
|
+
total: result.total
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
__name(listOf, "listOf");
|
|
1675
|
+
function cut(text, maxBytes) {
|
|
1676
|
+
const size = Buffer.byteLength(text, "utf8");
|
|
1677
|
+
if (size <= maxBytes) return text;
|
|
1678
|
+
const suffix = `\u2026(truncated, ${size} bytes)`;
|
|
1679
|
+
const keep = Math.max(0, maxBytes - Buffer.byteLength(suffix, "utf8"));
|
|
1680
|
+
let head = Buffer.from(text, "utf8").subarray(0, keep).toString("utf8");
|
|
1681
|
+
if (head.endsWith("\uFFFD")) head = head.slice(0, -1);
|
|
1682
|
+
return `${head}${suffix}`;
|
|
1683
|
+
}
|
|
1684
|
+
__name(cut, "cut");
|
|
1685
|
+
function agentDevTools(dashboard) {
|
|
1686
|
+
return [
|
|
1687
|
+
{
|
|
1688
|
+
name: "agent_list_runs",
|
|
1689
|
+
kind: "read",
|
|
1690
|
+
description: "Agent runs, newest first: agent, actor, status, duration, cost, error. Filters: agent, status, errorCode, threadId, from/to (UTC days). Returns { items, next, total }; pass next as page.",
|
|
1691
|
+
input: {
|
|
1692
|
+
type: "object",
|
|
1693
|
+
properties: {
|
|
1694
|
+
agent: {
|
|
1695
|
+
type: "string",
|
|
1696
|
+
description: "Agent name."
|
|
1697
|
+
},
|
|
1698
|
+
status: {
|
|
1699
|
+
type: "string",
|
|
1700
|
+
enum: [
|
|
1701
|
+
"running",
|
|
1702
|
+
"completed",
|
|
1703
|
+
"failed",
|
|
1704
|
+
"cancelled"
|
|
1705
|
+
]
|
|
1706
|
+
},
|
|
1707
|
+
errorCode: {
|
|
1708
|
+
type: "string"
|
|
1709
|
+
},
|
|
1710
|
+
threadId: {
|
|
1711
|
+
type: "string"
|
|
1712
|
+
},
|
|
1713
|
+
from: day,
|
|
1714
|
+
to: day,
|
|
1715
|
+
page,
|
|
1716
|
+
limit
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
async run(input) {
|
|
1720
|
+
return listOf(await dashboard.runsPage({
|
|
1721
|
+
...pageOf(input),
|
|
1722
|
+
...where({
|
|
1723
|
+
agentName: str(input.agent),
|
|
1724
|
+
status: str(input.status),
|
|
1725
|
+
errorCode: str(input.errorCode),
|
|
1726
|
+
threadId: str(input.threadId),
|
|
1727
|
+
fromDay: dayOf(input, "from"),
|
|
1728
|
+
toDay: dayOf(input, "to")
|
|
1729
|
+
})
|
|
1730
|
+
}));
|
|
1731
|
+
}
|
|
1732
|
+
},
|
|
1733
|
+
{
|
|
1734
|
+
name: "agent_get_run",
|
|
1735
|
+
kind: "read",
|
|
1736
|
+
description: "One run: the run, its thread, its tool calls and timings. With includeMessages: true, the thread's latest 50 messages, each cut to 2 KB. An error when no run has that id.",
|
|
1737
|
+
input: {
|
|
1738
|
+
type: "object",
|
|
1739
|
+
properties: {
|
|
1740
|
+
id: {
|
|
1741
|
+
type: "string",
|
|
1742
|
+
description: "Run id."
|
|
1743
|
+
},
|
|
1744
|
+
includeMessages: {
|
|
1745
|
+
type: "boolean",
|
|
1746
|
+
description: "Include messages (default false)."
|
|
1747
|
+
}
|
|
1748
|
+
},
|
|
1749
|
+
required: [
|
|
1750
|
+
"id"
|
|
1751
|
+
]
|
|
1752
|
+
},
|
|
1753
|
+
async run(input) {
|
|
1754
|
+
let detail;
|
|
1755
|
+
try {
|
|
1756
|
+
detail = await dashboard.runDetail(String(input.id));
|
|
1757
|
+
} catch (error) {
|
|
1758
|
+
if (error instanceof NotFoundException3) throw new Error(`run ${String(input.id)} not found`);
|
|
1759
|
+
throw error;
|
|
1760
|
+
}
|
|
1761
|
+
if (input.includeMessages !== true) return detail;
|
|
1762
|
+
const thread = await dashboard.threadDetail({
|
|
1763
|
+
threadId: detail.run.threadId,
|
|
1764
|
+
messageLimit: MESSAGE_LIMIT,
|
|
1765
|
+
runLimit: 1
|
|
1766
|
+
});
|
|
1767
|
+
return {
|
|
1768
|
+
...detail,
|
|
1769
|
+
messages: thread.messages.map((message) => ({
|
|
1770
|
+
...message,
|
|
1771
|
+
content: cut(message.content, MESSAGE_BYTES)
|
|
1772
|
+
}))
|
|
1773
|
+
};
|
|
1774
|
+
}
|
|
1775
|
+
},
|
|
1776
|
+
{
|
|
1777
|
+
name: "agent_get_spend",
|
|
1778
|
+
kind: "read",
|
|
1779
|
+
description: "Tokens and cost over UTC days from/to (default the last 30 days): by model, by actor, by feature and the daily trend. `by` returns one of them.",
|
|
1780
|
+
input: {
|
|
1781
|
+
type: "object",
|
|
1782
|
+
properties: {
|
|
1783
|
+
by: {
|
|
1784
|
+
type: "string",
|
|
1785
|
+
enum: [
|
|
1786
|
+
"model",
|
|
1787
|
+
"actor",
|
|
1788
|
+
"feature"
|
|
1789
|
+
]
|
|
1790
|
+
},
|
|
1791
|
+
from: day,
|
|
1792
|
+
to: day
|
|
1793
|
+
}
|
|
1794
|
+
},
|
|
1795
|
+
async run(input) {
|
|
1796
|
+
const spend = await dashboard.spend(rangeOf(input));
|
|
1797
|
+
switch (input.by) {
|
|
1798
|
+
case "model":
|
|
1799
|
+
return {
|
|
1800
|
+
items: spend.byModel
|
|
1801
|
+
};
|
|
1802
|
+
case "actor":
|
|
1803
|
+
return {
|
|
1804
|
+
items: spend.byActor
|
|
1805
|
+
};
|
|
1806
|
+
case "feature":
|
|
1807
|
+
return {
|
|
1808
|
+
items: spend.byFeature ?? []
|
|
1809
|
+
};
|
|
1810
|
+
default:
|
|
1811
|
+
return spend;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
},
|
|
1815
|
+
{
|
|
1816
|
+
name: "agent_get_tool_stats",
|
|
1817
|
+
kind: "read",
|
|
1818
|
+
description: "Per tool: calls, failures, rejections and latency, over UTC days from/to (default the last 30 days).",
|
|
1819
|
+
input: {
|
|
1820
|
+
type: "object",
|
|
1821
|
+
properties: {
|
|
1822
|
+
from: day,
|
|
1823
|
+
to: day
|
|
1824
|
+
}
|
|
1825
|
+
},
|
|
1826
|
+
async run(input) {
|
|
1827
|
+
return {
|
|
1828
|
+
items: await dashboard.toolStats(rangeOf(input))
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
},
|
|
1832
|
+
{
|
|
1833
|
+
name: "agent_get_reliability",
|
|
1834
|
+
kind: "read",
|
|
1835
|
+
description: "Run metrics, by-agent and by-error breakdowns and the trend, over UTC days from/to (default the last 30 days).",
|
|
1836
|
+
input: {
|
|
1837
|
+
type: "object",
|
|
1838
|
+
properties: {
|
|
1839
|
+
from: day,
|
|
1840
|
+
to: day
|
|
1841
|
+
}
|
|
1842
|
+
},
|
|
1843
|
+
async run(input) {
|
|
1844
|
+
return dashboard.reliability(rangeOf(input));
|
|
1845
|
+
}
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
name: "agent_list_pending_approvals",
|
|
1849
|
+
kind: "read",
|
|
1850
|
+
description: "Tool calls waiting for a human approval, oldest first. Read-only: approve them in the app. Returns { items, next, total }.",
|
|
1851
|
+
input: {
|
|
1852
|
+
type: "object",
|
|
1853
|
+
properties: {
|
|
1854
|
+
toolName: {
|
|
1855
|
+
type: "string"
|
|
1856
|
+
},
|
|
1857
|
+
agent: {
|
|
1858
|
+
type: "string",
|
|
1859
|
+
description: "Agent name."
|
|
1860
|
+
},
|
|
1861
|
+
actor: {
|
|
1862
|
+
type: "string",
|
|
1863
|
+
description: "Actor ref of the thread owner."
|
|
1864
|
+
},
|
|
1865
|
+
threadId: {
|
|
1866
|
+
type: "string"
|
|
1867
|
+
},
|
|
1868
|
+
from: day,
|
|
1869
|
+
to: day,
|
|
1870
|
+
page,
|
|
1871
|
+
limit
|
|
1872
|
+
}
|
|
1873
|
+
},
|
|
1874
|
+
async run(input) {
|
|
1875
|
+
return listOf(await dashboard.approvalsPage({
|
|
1876
|
+
...pageOf(input),
|
|
1877
|
+
...where({
|
|
1878
|
+
toolName: str(input.toolName),
|
|
1879
|
+
agentName: str(input.agent),
|
|
1880
|
+
actorRef: str(input.actor),
|
|
1881
|
+
threadId: str(input.threadId),
|
|
1882
|
+
fromDay: dayOf(input, "from"),
|
|
1883
|
+
toDay: dayOf(input, "to")
|
|
1884
|
+
})
|
|
1885
|
+
}));
|
|
1886
|
+
}
|
|
1887
|
+
},
|
|
1888
|
+
{
|
|
1889
|
+
name: "agent_list_recent_tool_calls",
|
|
1890
|
+
kind: "read",
|
|
1891
|
+
description: "Tool calls of every agent, newest first. Filters: toolName, status, threadId, from/to (UTC days). Returns { items, next, total }.",
|
|
1892
|
+
input: {
|
|
1893
|
+
type: "object",
|
|
1894
|
+
properties: {
|
|
1895
|
+
toolName: {
|
|
1896
|
+
type: "string"
|
|
1897
|
+
},
|
|
1898
|
+
status: {
|
|
1899
|
+
type: "string"
|
|
1900
|
+
},
|
|
1901
|
+
threadId: {
|
|
1902
|
+
type: "string"
|
|
1903
|
+
},
|
|
1904
|
+
from: day,
|
|
1905
|
+
to: day,
|
|
1906
|
+
page,
|
|
1907
|
+
limit
|
|
1908
|
+
}
|
|
1909
|
+
},
|
|
1910
|
+
async run(input) {
|
|
1911
|
+
return listOf(await dashboard.toolCallsPage({
|
|
1912
|
+
...pageOf(input),
|
|
1913
|
+
...where({
|
|
1914
|
+
toolName: str(input.toolName),
|
|
1915
|
+
status: str(input.status),
|
|
1916
|
+
threadId: str(input.threadId),
|
|
1917
|
+
fromDay: dayOf(input, "from"),
|
|
1918
|
+
toDay: dayOf(input, "to")
|
|
1919
|
+
})
|
|
1920
|
+
}));
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
];
|
|
1924
|
+
}
|
|
1925
|
+
__name(agentDevTools, "agentDevTools");
|
|
1926
|
+
var logger2 = new Logger2("AgentDashboardModule");
|
|
1927
|
+
var AgentDevToolsRegistration = class {
|
|
1928
|
+
static {
|
|
1929
|
+
__name(this, "AgentDevToolsRegistration");
|
|
1930
|
+
}
|
|
1931
|
+
enabled;
|
|
1932
|
+
dashboard;
|
|
1933
|
+
access;
|
|
1934
|
+
#unregister;
|
|
1935
|
+
constructor(enabled, dashboard, access) {
|
|
1936
|
+
this.enabled = enabled;
|
|
1937
|
+
this.dashboard = dashboard;
|
|
1938
|
+
this.access = access;
|
|
1939
|
+
}
|
|
1940
|
+
onModuleInit() {
|
|
1941
|
+
if (!this.enabled) return;
|
|
1942
|
+
const slot = devToolsSlot();
|
|
1943
|
+
if (slot.version !== 1 || typeof slot.register !== "function") return;
|
|
1944
|
+
try {
|
|
1945
|
+
this.#unregister = slot.register({
|
|
1946
|
+
lib: "agent",
|
|
1947
|
+
title: "Agent governance",
|
|
1948
|
+
authorize: /* @__PURE__ */ __name((context) => this.access.check(context), "authorize"),
|
|
1949
|
+
tools: agentDevTools(this.dashboard)
|
|
1950
|
+
});
|
|
1951
|
+
} catch (error) {
|
|
1952
|
+
logger2.warn(`agent dev tools not registered: ${error instanceof Error ? error.message : String(error)}`);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
onModuleDestroy() {
|
|
1956
|
+
this.#unregister?.();
|
|
1957
|
+
this.#unregister = void 0;
|
|
1958
|
+
}
|
|
1959
|
+
};
|
|
1960
|
+
AgentDevToolsRegistration = _ts_decorate5([
|
|
1961
|
+
Injectable3(),
|
|
1962
|
+
_ts_param5(0, Inject5(DASHBOARD_DEV_TOOLS)),
|
|
1963
|
+
_ts_metadata5("design:type", Function),
|
|
1964
|
+
_ts_metadata5("design:paramtypes", [
|
|
1965
|
+
Boolean,
|
|
1966
|
+
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
1967
|
+
typeof DashboardConsoleAccess === "undefined" ? Object : DashboardConsoleAccess
|
|
1968
|
+
])
|
|
1969
|
+
], AgentDevToolsRegistration);
|
|
1970
|
+
|
|
1971
|
+
// src/server/agent-dashboard.module.ts
|
|
1972
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
1973
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1974
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
1975
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
1976
|
+
} else {
|
|
1977
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
1978
|
+
if (d = decorators[i]) {
|
|
1979
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1984
|
+
}
|
|
1985
|
+
__name(_ts_decorate6, "_ts_decorate");
|
|
1525
1986
|
function normalize(path) {
|
|
1526
1987
|
return normalizeDashboardPath(path);
|
|
1527
1988
|
}
|
|
@@ -1564,7 +2025,12 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
1564
2025
|
provide: DASHBOARD_CONSOLE_OPTIONS,
|
|
1565
2026
|
useValue: consoleOptions
|
|
1566
2027
|
},
|
|
1567
|
-
DashboardConsoleAccess
|
|
2028
|
+
DashboardConsoleAccess,
|
|
2029
|
+
{
|
|
2030
|
+
provide: DASHBOARD_DEV_TOOLS,
|
|
2031
|
+
useValue: options.devTools ?? options.routes !== false
|
|
2032
|
+
},
|
|
2033
|
+
AgentDevToolsRegistration
|
|
1568
2034
|
],
|
|
1569
2035
|
// What a self-mounted `AgentApiController` subclass injects, too (`routes: false`), and the
|
|
1570
2036
|
// access check `UseConsoleAuthorize()` runs.
|
|
@@ -1576,7 +2042,7 @@ var AgentApiModule = class _AgentApiModule {
|
|
|
1576
2042
|
};
|
|
1577
2043
|
}
|
|
1578
2044
|
};
|
|
1579
|
-
AgentApiModule =
|
|
2045
|
+
AgentApiModule = _ts_decorate6([
|
|
1580
2046
|
Module({})
|
|
1581
2047
|
], AgentApiModule);
|
|
1582
2048
|
var AgentDashboardModule = class _AgentDashboardModule {
|
|
@@ -1606,6 +2072,9 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
1606
2072
|
} : {},
|
|
1607
2073
|
...options.authorize !== void 0 ? {
|
|
1608
2074
|
authorize: options.authorize
|
|
2075
|
+
} : {},
|
|
2076
|
+
...options.devTools !== void 0 ? {
|
|
2077
|
+
devTools: options.devTools
|
|
1609
2078
|
} : {}
|
|
1610
2079
|
}),
|
|
1611
2080
|
...options.routes === false ? [] : [
|
|
@@ -1644,7 +2113,7 @@ var AgentDashboardModule = class _AgentDashboardModule {
|
|
|
1644
2113
|
};
|
|
1645
2114
|
}
|
|
1646
2115
|
};
|
|
1647
|
-
AgentDashboardModule =
|
|
2116
|
+
AgentDashboardModule = _ts_decorate6([
|
|
1648
2117
|
Module({})
|
|
1649
2118
|
], AgentDashboardModule);
|
|
1650
2119
|
export {
|
|
@@ -1656,6 +2125,7 @@ export {
|
|
|
1656
2125
|
AgentApiController,
|
|
1657
2126
|
AgentApiModule,
|
|
1658
2127
|
AgentDashboardModule,
|
|
2128
|
+
AgentDevToolsRegistration,
|
|
1659
2129
|
AgentUiController,
|
|
1660
2130
|
CONSOLE_AUTHORIZE_MISSING_WARNING,
|
|
1661
2131
|
CONSOLE_GATE,
|
|
@@ -1668,10 +2138,13 @@ export {
|
|
|
1668
2138
|
DASHBOARD_APPROVAL_ACTOR_REF,
|
|
1669
2139
|
DASHBOARD_BASE_PATH,
|
|
1670
2140
|
DASHBOARD_CONSOLE_OPTIONS,
|
|
2141
|
+
DASHBOARD_DEV_TOOLS,
|
|
1671
2142
|
DashboardConsoleAccess,
|
|
1672
2143
|
DashboardService,
|
|
1673
2144
|
UseConsoleAuthorize,
|
|
1674
2145
|
agentDashboardMountPaths,
|
|
2146
|
+
agentDevTools,
|
|
2147
|
+
anyAuthorize,
|
|
1675
2148
|
authorizeByToken,
|
|
1676
2149
|
normalizeConsoleResult,
|
|
1677
2150
|
parsePriceInput,
|