@dudousxd/nestjs-agent-dashboard 0.6.0 → 0.8.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/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 +324 -59
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +93 -17
- package/dist/server/index.d.ts +93 -17
- package/dist/server/index.js +274 -10
- 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 +3 -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.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActorSpendRow, AgentGovernanceQueries, ActorDirectory, AgentPricingStore, AgentApprovalPort, GovernanceRange, ModelSpendRow, UsageTrendPoint, ThreadSpendRow, RunMetrics, RunAgentBreakdownRow, RunErrorBreakdownRow, RunTrendPoint, RecentRunRow, ToolCallActivityRow, PendingApprovalRow, ToolStatRow, ThreadActivityRow, CurrentModelPrice, ModelPriceInput } from '@dudousxd/nestjs-agent-core';
|
|
1
|
+
import { ActorSpendRow, AgentGovernanceQueries, ActorDirectory, AgentPricingStore, AgentApprovalPort, GovernanceRange, ModelSpendRow, UsageTrendPoint, ThreadSpendRow, RunMetrics, RunAgentBreakdownRow, RunErrorBreakdownRow, RunTrendPoint, RecentRunRow, ToolCallActivityRow, GovernancePageQuery, ToolCallWhere, GovernancePage, RunWhere, PendingApprovalRow, ToolStatRow, ThreadActivityRow, ThreadWhere, CurrentModelPrice, ActorResolver, ModelPriceInput } from '@dudousxd/nestjs-agent-core';
|
|
2
2
|
export { ActorDirectory } from '@dudousxd/nestjs-agent-core';
|
|
3
3
|
import { Observable } from 'rxjs';
|
|
4
4
|
import { DynamicModule, Type, CanActivate, StreamableFile } from '@nestjs/common';
|
|
@@ -61,6 +61,10 @@ declare class DashboardService {
|
|
|
61
61
|
recentRuns(limit: number): Promise<RecentRunRow[]>;
|
|
62
62
|
/** Most recent tool calls (status/type/thread) for the Runs & tools activity feed. */
|
|
63
63
|
recentToolCalls(limit: number): Promise<ToolCallActivityRow[]>;
|
|
64
|
+
/** Paged, filterable tool calls for the Runs & tools activity table. */
|
|
65
|
+
toolCallsPage(query: GovernancePageQuery<ToolCallWhere>): Promise<GovernancePage<ToolCallActivityRow>>;
|
|
66
|
+
/** Paged, filterable runs for the Reliability recent-runs table. */
|
|
67
|
+
runsPage(query: GovernancePageQuery<RunWhere>): Promise<GovernancePage<RecentRunRow>>;
|
|
64
68
|
/** Tool calls sitting `pending_approval`, oldest first, for the cross-thread approvals inbox. */
|
|
65
69
|
pendingApprovals(limit: number): Promise<PendingApprovalRow[]>;
|
|
66
70
|
/** Per-tool call/failure/rejection/latency rollup for a day range, for the Tools section. */
|
|
@@ -76,6 +80,11 @@ declare class DashboardService {
|
|
|
76
80
|
decideApproval(toolCallId: string, body: unknown, executedByRef: string | undefined): Promise<void>;
|
|
77
81
|
/** Most recent threads with rolled-up message/token counts. */
|
|
78
82
|
recentThreads(limit: number): Promise<ThreadActivityRowWithLabel[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Paged, filterable threads for the Runs & tools threads table — actor-labeled the same way
|
|
85
|
+
* {@link recentThreads} is.
|
|
86
|
+
*/
|
|
87
|
+
threadsPage(query: GovernancePageQuery<ThreadWhere>): Promise<GovernancePage<ThreadActivityRowWithLabel>>;
|
|
79
88
|
/**
|
|
80
89
|
* Decorate actor-scoped rows with `actorLabel`, batching the distinct `actorRef`s into ONE
|
|
81
90
|
* {@link ActorDirectory.resolveDisplay} call per response. `null` for every row when no directory
|
|
@@ -107,7 +116,8 @@ declare class DashboardService {
|
|
|
107
116
|
declare class AgentApiController {
|
|
108
117
|
private readonly dashboard;
|
|
109
118
|
private readonly approvalActorRef;
|
|
110
|
-
|
|
119
|
+
private readonly actorResolver?;
|
|
120
|
+
constructor(dashboard: DashboardService, approvalActorRef: ((req: unknown) => string | undefined) | undefined, actorResolver?: ActorResolver | undefined);
|
|
111
121
|
/** `{ byModel, byActor, trend }` for a day range (defaults to the last 30 days). */
|
|
112
122
|
spend(from?: string, to?: string): Promise<SpendOverview>;
|
|
113
123
|
/** Top threads by cost (default 10, max 200) for a day range (defaults to the last 30 days). */
|
|
@@ -116,20 +126,46 @@ declare class AgentApiController {
|
|
|
116
126
|
reliability(from?: string, to?: string): Promise<ReliabilityOverview>;
|
|
117
127
|
/** Most recent runs (default 50, max 200) for the Reliability recent-runs table. */
|
|
118
128
|
runs(limit?: string): Promise<RecentRunRow[]>;
|
|
129
|
+
/**
|
|
130
|
+
* Paged, filterable runs for the Reliability recent-runs table. `page` (default 1), `limit`
|
|
131
|
+
* (default 25, max 200), and `where[agentName]`/`where[status]`/`where[errorCode]`/
|
|
132
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
133
|
+
*/
|
|
134
|
+
runsPage(page?: string, limit?: string, where?: Record<string, string>): Promise<GovernancePage<RecentRunRow>>;
|
|
119
135
|
/** Most recent tool calls (default 50, max 200) for the activity feed. */
|
|
120
136
|
toolCalls(limit?: string): Promise<ToolCallActivityRow[]>;
|
|
137
|
+
/**
|
|
138
|
+
* Paged, filterable tool calls for the Runs & tools activity table. `page` (default 1), `limit`
|
|
139
|
+
* (default 25, max 200), and `where[toolName]`/`where[toolType]`/`where[status]`/`where[threadId]`/
|
|
140
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
141
|
+
*/
|
|
142
|
+
toolCallsPage(page?: string, limit?: string, where?: Record<string, string>): Promise<GovernancePage<ToolCallActivityRow>>;
|
|
121
143
|
/** Tool calls sitting `pending_approval` (default 50, max 200), oldest first — the approvals inbox. */
|
|
122
144
|
approvals(limit?: string): Promise<PendingApprovalRow[]>;
|
|
123
145
|
/**
|
|
124
146
|
* Decide a pending HITL tool call. Body `{ approved: boolean; reason?: string }`. 501s (via
|
|
125
147
|
* `DashboardService.decideApproval`) when no `AGENT_APPROVAL_PORT` is bound. `executedByRef`
|
|
126
|
-
* comes from
|
|
148
|
+
* comes from {@link deciderRef} run against the live request.
|
|
127
149
|
*/
|
|
128
150
|
decideApproval(toolCallId: string, body: unknown, req: unknown): Promise<void>;
|
|
151
|
+
/**
|
|
152
|
+
* WHO decided, as an opaque ref: an explicit `approvalActorRef` override wins outright (no
|
|
153
|
+
* resolver fallback, even when it returns `undefined`); otherwise the AgentModule-configured
|
|
154
|
+
* actor resolver — the same identity seam chat requests use. A resolver that throws is an
|
|
155
|
+
* unauthenticated/unreadable request, not an error to surface: the decision itself was already
|
|
156
|
+
* authorized by the dashboard's guards, so the ref is simply omitted.
|
|
157
|
+
*/
|
|
158
|
+
private deciderRef;
|
|
129
159
|
/** Per-tool call/failure/rejection/latency rollup for a day range (defaults to the last 30 days). */
|
|
130
160
|
tools(from?: string, to?: string): Promise<ToolStatRow[]>;
|
|
131
161
|
/** Most recent threads (default 50, max 200) with rolled-up counts. */
|
|
132
162
|
threads(limit?: string): Promise<ThreadActivityRowWithLabel[]>;
|
|
163
|
+
/**
|
|
164
|
+
* Paged, filterable threads for the Runs & tools threads table. `page` (default 1), `limit`
|
|
165
|
+
* (default 25, max 200), and `where[actorRef]`/`where[title]` (case-insensitive substring)/
|
|
166
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
167
|
+
*/
|
|
168
|
+
threadsPage(page?: string, limit?: string, where?: Record<string, string>): Promise<GovernancePage<ThreadActivityRowWithLabel>>;
|
|
133
169
|
/**
|
|
134
170
|
* Current price row per model, for the pricing tab. 501s (via `DashboardService.listPrices`) when
|
|
135
171
|
* no `AGENT_PRICING_STORE` is bound.
|
|
@@ -178,7 +214,13 @@ interface AgentDashboardMountPathsOptions {
|
|
|
178
214
|
*/
|
|
179
215
|
declare function agentDashboardMountPaths(options?: AgentDashboardMountPathsOptions): string[];
|
|
180
216
|
|
|
181
|
-
|
|
217
|
+
/**
|
|
218
|
+
* `TReq` mirrors core's `ActorResolver<TReq>` convention: the transport request type
|
|
219
|
+
* {@link AgentDashboardOptions.approvalActorRef} receives. Defaults to `unknown` so untyped usage
|
|
220
|
+
* compiles unchanged; a host may narrow it (e.g. `forRoot<Request>({ approvalActorRef: ... })`)
|
|
221
|
+
* instead of writing its own `unknown`-narrowing type guard.
|
|
222
|
+
*/
|
|
223
|
+
interface AgentDashboardOptions<TReq = unknown> {
|
|
182
224
|
/**
|
|
183
225
|
* Where the SPA (UI) is served. Default `/ai-gateway`. This is a page route — keep it out of an
|
|
184
226
|
* `/api` prefix so it reads as a UI, not an endpoint.
|
|
@@ -208,13 +250,17 @@ interface AgentDashboardOptions {
|
|
|
208
250
|
*/
|
|
209
251
|
imports?: DynamicModule['imports'];
|
|
210
252
|
/**
|
|
211
|
-
*
|
|
253
|
+
* OVERRIDE for WHO is deciding a HITL approval — invoked on the incoming
|
|
212
254
|
* `POST <api>/approvals/:toolCallId` request to stamp `AgentApprovalPort`'s `opts.executedByRef`.
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
255
|
+
*
|
|
256
|
+
* DEFAULT (option omitted): the AgentModule-configured actor resolver (`AGENT_ACTOR_RESOLVER`) is
|
|
257
|
+
* consulted — the same identity seam chat requests use — and its actor id becomes the decider ref
|
|
258
|
+
* (a throwing resolver, i.e. an unauthenticated request, just omits the ref). Set this only when
|
|
259
|
+
* console auth differs from chat auth (e.g. the console sits behind a separate SSO whose principal
|
|
260
|
+
* the chat resolver can't read); returning `undefined` leaves `executedByRef` unset — the explicit
|
|
261
|
+
* override wins outright, with no resolver fallback.
|
|
216
262
|
*/
|
|
217
|
-
approvalActorRef?: (req:
|
|
263
|
+
approvalActorRef?: (req: TReq) => string | undefined;
|
|
218
264
|
}
|
|
219
265
|
/**
|
|
220
266
|
* Holds the JSON API + SSE controller and its read service, mounted on its own path by `forRoot`.
|
|
@@ -225,10 +271,10 @@ interface AgentDashboardOptions {
|
|
|
225
271
|
* the right `imports` to `forRoot`.
|
|
226
272
|
*/
|
|
227
273
|
declare class AgentApiModule {
|
|
228
|
-
static register(options: {
|
|
274
|
+
static register<TReq = unknown>(options: {
|
|
229
275
|
imports?: DynamicModule['imports'];
|
|
230
276
|
guards?: Type<CanActivate>[];
|
|
231
|
-
approvalActorRef?: (req:
|
|
277
|
+
approvalActorRef?: (req: TReq) => string | undefined;
|
|
232
278
|
}): DynamicModule;
|
|
233
279
|
}
|
|
234
280
|
/**
|
|
@@ -239,11 +285,31 @@ declare class AgentApiModule {
|
|
|
239
285
|
* (global), which must provide `AGENT_GOVERNANCE_QUERIES` (bound by a store adapter). Front the
|
|
240
286
|
* routes with the first-class `guards` option (plus `imports` for the guards' own dependencies) —
|
|
241
287
|
* see {@link AgentDashboardOptions.guards}.
|
|
288
|
+
*
|
|
289
|
+
* Inertia hosts: the console is a full-page app, not an Inertia page. An in-app `<Link>` visit to
|
|
290
|
+
* `basePath` (an XHR carrying `X-Inertia`) is bounced with the protocol's own external-redirect
|
|
291
|
+
* mechanism — `409 Conflict` + `X-Inertia-Location: <the visited URL>` — so the Inertia client
|
|
292
|
+
* performs a full `window.location` load and the console renders normally. In-app links to the
|
|
293
|
+
* console therefore just work; no host-side special-casing needed.
|
|
242
294
|
*/
|
|
243
295
|
declare class AgentDashboardModule {
|
|
244
|
-
static forRoot(options?: AgentDashboardOptions): DynamicModule;
|
|
296
|
+
static forRoot<TReq = unknown>(options?: AgentDashboardOptions<TReq>): DynamicModule;
|
|
245
297
|
}
|
|
246
298
|
|
|
299
|
+
/**
|
|
300
|
+
* The slice of the express request the Inertia bounce below reads — structural, so the package
|
|
301
|
+
* needs no express dependency (the API controller similarly takes `@Req() req: unknown`).
|
|
302
|
+
*/
|
|
303
|
+
interface UiPageRequest {
|
|
304
|
+
headers: Record<string, string | string[] | undefined>;
|
|
305
|
+
/** Path + query as received (express `originalUrl`) — what the full-page visit must reload. */
|
|
306
|
+
originalUrl: string;
|
|
307
|
+
}
|
|
308
|
+
/** The slice of the express response the Inertia bounce writes (passthrough mode — Nest still sends). */
|
|
309
|
+
interface UiPageResponse {
|
|
310
|
+
status(code: number): unknown;
|
|
311
|
+
setHeader(name: string, value: string): unknown;
|
|
312
|
+
}
|
|
247
313
|
/**
|
|
248
314
|
* Serves the bundled AI-gateway console SPA at the configured base (+ hashed assets at
|
|
249
315
|
* `<base>/assets`). The path comes from `RouterModule` (set by
|
|
@@ -254,7 +320,7 @@ declare class AgentUiController {
|
|
|
254
320
|
private readonly apiBasePath;
|
|
255
321
|
private readonly dir;
|
|
256
322
|
constructor(basePath: string, apiBasePath: string);
|
|
257
|
-
index(): string;
|
|
323
|
+
index(req: UiPageRequest, res: UiPageResponse): string;
|
|
258
324
|
asset(file: string): StreamableFile;
|
|
259
325
|
}
|
|
260
326
|
|
|
@@ -301,16 +367,26 @@ declare const AGENT_PRICING_STORE: unique symbol;
|
|
|
301
367
|
* absent, `POST <api>/approvals/:toolCallId` 501s and the approvals inbox renders read-only.
|
|
302
368
|
*/
|
|
303
369
|
declare const AGENT_APPROVAL_PORT: unique symbol;
|
|
370
|
+
/**
|
|
371
|
+
* The app's request-identity seam (`ActorResolver`), owned by `@dudousxd/nestjs-agent-core` and
|
|
372
|
+
* bound + exported by the (global) `AgentModule` from the host's `actorResolver` option. Re-declared
|
|
373
|
+
* here BY VALUE for the same reason as {@link AGENT_GOVERNANCE_QUERIES} above. Optional: the default
|
|
374
|
+
* decider attribution for `POST <api>/approvals/:toolCallId` — absent (or throwing, i.e.
|
|
375
|
+
* unauthenticated), `executedByRef` is simply omitted.
|
|
376
|
+
*/
|
|
377
|
+
declare const AGENT_ACTOR_RESOLVER: unique symbol;
|
|
304
378
|
/** DI token carrying the UI mount base (e.g. `/ai-gateway`). */
|
|
305
379
|
declare const DASHBOARD_BASE_PATH: unique symbol;
|
|
306
380
|
/** DI token carrying the JSON API base the SPA fetches from (e.g. `/ai-gateway/api`). */
|
|
307
381
|
declare const DASHBOARD_API_PATH: unique symbol;
|
|
308
382
|
/**
|
|
309
383
|
* DI token carrying the host-provided {@link AgentDashboardOptions.approvalActorRef} extractor (or
|
|
310
|
-
* `undefined` when the host didn't set one
|
|
311
|
-
*
|
|
312
|
-
*
|
|
384
|
+
* `undefined` when the host didn't set one — the controller then falls back to
|
|
385
|
+
* {@link AGENT_ACTOR_RESOLVER} for decider attribution). Threaded to `AgentApiModule` (where the API
|
|
386
|
+
* controller actually lives) same as the pattern above — `useValue` even when `undefined`, so
|
|
387
|
+
* injecting it needs no `@Optional()` (mirrors `AGENT_QUOTA_STORE`'s factory in
|
|
388
|
+
* `@dudousxd/nestjs-agent`).
|
|
313
389
|
*/
|
|
314
390
|
declare const DASHBOARD_APPROVAL_ACTOR_REF: unique symbol;
|
|
315
391
|
|
|
316
|
-
export { AGENT_ACTOR_DIRECTORY, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_BASE_PATH, DashboardService, type LiveAgentEvent, type ReliabilityOverview, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput };
|
|
392
|
+
export { AGENT_ACTOR_DIRECTORY, AGENT_ACTOR_RESOLVER, AGENT_APPROVAL_PORT, AGENT_GOVERNANCE_QUERIES, AGENT_PRICING_STORE, type ActorSpendRowWithLabel, AgentApiController, AgentApiModule, AgentDashboardModule, type AgentDashboardMountPathsOptions, type AgentDashboardOptions, AgentUiController, DASHBOARD_API_PATH, DASHBOARD_APPROVAL_ACTOR_REF, DASHBOARD_BASE_PATH, DashboardService, type LiveAgentEvent, type ReliabilityOverview, type SpendOverview, type ThreadActivityRowWithLabel, type ThreadSpendRowWithLabel, type WithActorLabel, agentDashboardMountPaths, parsePriceInput };
|
package/dist/server/index.js
CHANGED
|
@@ -2,7 +2,7 @@ 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 Inject2, Param, Post, Query, Req, Sse } from "@nestjs/common";
|
|
5
|
+
import { Body, Controller, Get, HttpCode, Inject as Inject2, Optional as Optional2, Param, Post, Query, Req, Sse } from "@nestjs/common";
|
|
6
6
|
|
|
7
7
|
// src/server/dashboard.service.ts
|
|
8
8
|
import { subscribe, unsubscribe } from "node:diagnostics_channel";
|
|
@@ -77,6 +77,7 @@ var AGENT_GOVERNANCE_QUERIES = Symbol.for("@dudousxd/nestjs-agent:governance-que
|
|
|
77
77
|
var AGENT_ACTOR_DIRECTORY = Symbol.for("@dudousxd/nestjs-agent:actor-directory");
|
|
78
78
|
var AGENT_PRICING_STORE = Symbol.for("@dudousxd/nestjs-agent:pricing-store");
|
|
79
79
|
var AGENT_APPROVAL_PORT = Symbol.for("@dudousxd/nestjs-agent:approval-port");
|
|
80
|
+
var AGENT_ACTOR_RESOLVER = Symbol.for("@dudousxd/nestjs-agent:actor-resolver");
|
|
80
81
|
var DASHBOARD_BASE_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:base-path");
|
|
81
82
|
var DASHBOARD_API_PATH = Symbol.for("@dudousxd/nestjs-agent-dashboard:api-path");
|
|
82
83
|
var DASHBOARD_APPROVAL_ACTOR_REF = Symbol.for("@dudousxd/nestjs-agent-dashboard:approval-actor-ref");
|
|
@@ -169,6 +170,14 @@ var DashboardService = class {
|
|
|
169
170
|
recentToolCalls(limit) {
|
|
170
171
|
return this.queries.recentToolCalls(limit);
|
|
171
172
|
}
|
|
173
|
+
/** Paged, filterable tool calls for the Runs & tools activity table. */
|
|
174
|
+
toolCallsPage(query) {
|
|
175
|
+
return this.queries.toolCallsPage(query);
|
|
176
|
+
}
|
|
177
|
+
/** Paged, filterable runs for the Reliability recent-runs table. */
|
|
178
|
+
runsPage(query) {
|
|
179
|
+
return this.queries.runsPage(query);
|
|
180
|
+
}
|
|
172
181
|
/** Tool calls sitting `pending_approval`, oldest first, for the cross-thread approvals inbox. */
|
|
173
182
|
pendingApprovals(limit) {
|
|
174
183
|
return this.queries.pendingApprovals(limit);
|
|
@@ -210,6 +219,18 @@ var DashboardService = class {
|
|
|
210
219
|
return this.withActorLabels(rows);
|
|
211
220
|
}
|
|
212
221
|
/**
|
|
222
|
+
* Paged, filterable threads for the Runs & tools threads table — actor-labeled the same way
|
|
223
|
+
* {@link recentThreads} is.
|
|
224
|
+
*/
|
|
225
|
+
async threadsPage(query) {
|
|
226
|
+
const page = await this.queries.threadsPage(query);
|
|
227
|
+
const rows = await this.withActorLabels(page.rows);
|
|
228
|
+
return {
|
|
229
|
+
...page,
|
|
230
|
+
rows
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
213
234
|
* Decorate actor-scoped rows with `actorLabel`, batching the distinct `actorRef`s into ONE
|
|
214
235
|
* {@link ActorDirectory.resolveDisplay} call per response. `null` for every row when no directory
|
|
215
236
|
* is bound, or for a ref the directory didn't resolve.
|
|
@@ -300,6 +321,127 @@ DashboardService = _ts_decorate([
|
|
|
300
321
|
])
|
|
301
322
|
], DashboardService);
|
|
302
323
|
|
|
324
|
+
// src/server/parse-page-query.ts
|
|
325
|
+
import { BadRequestException as BadRequestException3 } from "@nestjs/common";
|
|
326
|
+
var ISO_DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
327
|
+
function parsePageNumber(value) {
|
|
328
|
+
const parsed = value === void 0 ? Number.NaN : Number.parseInt(value, 10);
|
|
329
|
+
if (!Number.isFinite(parsed) || parsed < 1) return 1;
|
|
330
|
+
return parsed;
|
|
331
|
+
}
|
|
332
|
+
__name(parsePageNumber, "parsePageNumber");
|
|
333
|
+
function assertKnownFields(raw, allowed) {
|
|
334
|
+
for (const field of Object.keys(raw)) {
|
|
335
|
+
if (!allowed.includes(field)) {
|
|
336
|
+
throw new BadRequestException3(`Unknown where field "${field}".`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
__name(assertKnownFields, "assertKnownFields");
|
|
341
|
+
function assertDayFields(raw, dayFields) {
|
|
342
|
+
for (const field of dayFields) {
|
|
343
|
+
const value = raw[field];
|
|
344
|
+
if (value !== void 0 && !ISO_DAY.test(value)) {
|
|
345
|
+
throw new BadRequestException3(`"where[${field}]" must be YYYY-MM-DD.`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
__name(assertDayFields, "assertDayFields");
|
|
350
|
+
var DAY_FIELDS = [
|
|
351
|
+
"fromDay",
|
|
352
|
+
"toDay"
|
|
353
|
+
];
|
|
354
|
+
var TOOL_CALL_WHERE_FIELDS = [
|
|
355
|
+
"toolName",
|
|
356
|
+
"toolType",
|
|
357
|
+
"status",
|
|
358
|
+
"threadId",
|
|
359
|
+
"fromDay",
|
|
360
|
+
"toDay"
|
|
361
|
+
];
|
|
362
|
+
function parseToolCallWhere(raw) {
|
|
363
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
364
|
+
assertKnownFields(raw, TOOL_CALL_WHERE_FIELDS);
|
|
365
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
366
|
+
return {
|
|
367
|
+
...raw.toolName !== void 0 ? {
|
|
368
|
+
toolName: raw.toolName
|
|
369
|
+
} : {},
|
|
370
|
+
...raw.toolType !== void 0 ? {
|
|
371
|
+
toolType: raw.toolType
|
|
372
|
+
} : {},
|
|
373
|
+
...raw.status !== void 0 ? {
|
|
374
|
+
status: raw.status
|
|
375
|
+
} : {},
|
|
376
|
+
...raw.threadId !== void 0 ? {
|
|
377
|
+
threadId: raw.threadId
|
|
378
|
+
} : {},
|
|
379
|
+
...raw.fromDay !== void 0 ? {
|
|
380
|
+
fromDay: raw.fromDay
|
|
381
|
+
} : {},
|
|
382
|
+
...raw.toDay !== void 0 ? {
|
|
383
|
+
toDay: raw.toDay
|
|
384
|
+
} : {}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
__name(parseToolCallWhere, "parseToolCallWhere");
|
|
388
|
+
var THREAD_WHERE_FIELDS = [
|
|
389
|
+
"actorRef",
|
|
390
|
+
"title",
|
|
391
|
+
"fromDay",
|
|
392
|
+
"toDay"
|
|
393
|
+
];
|
|
394
|
+
function parseThreadWhere(raw) {
|
|
395
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
396
|
+
assertKnownFields(raw, THREAD_WHERE_FIELDS);
|
|
397
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
398
|
+
return {
|
|
399
|
+
...raw.actorRef !== void 0 ? {
|
|
400
|
+
actorRef: raw.actorRef
|
|
401
|
+
} : {},
|
|
402
|
+
...raw.title !== void 0 ? {
|
|
403
|
+
title: raw.title
|
|
404
|
+
} : {},
|
|
405
|
+
...raw.fromDay !== void 0 ? {
|
|
406
|
+
fromDay: raw.fromDay
|
|
407
|
+
} : {},
|
|
408
|
+
...raw.toDay !== void 0 ? {
|
|
409
|
+
toDay: raw.toDay
|
|
410
|
+
} : {}
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
__name(parseThreadWhere, "parseThreadWhere");
|
|
414
|
+
var RUN_WHERE_FIELDS = [
|
|
415
|
+
"agentName",
|
|
416
|
+
"status",
|
|
417
|
+
"errorCode",
|
|
418
|
+
"fromDay",
|
|
419
|
+
"toDay"
|
|
420
|
+
];
|
|
421
|
+
function parseRunWhere(raw) {
|
|
422
|
+
if (raw === void 0 || Object.keys(raw).length === 0) return void 0;
|
|
423
|
+
assertKnownFields(raw, RUN_WHERE_FIELDS);
|
|
424
|
+
assertDayFields(raw, DAY_FIELDS);
|
|
425
|
+
return {
|
|
426
|
+
...raw.agentName !== void 0 ? {
|
|
427
|
+
agentName: raw.agentName
|
|
428
|
+
} : {},
|
|
429
|
+
...raw.status !== void 0 ? {
|
|
430
|
+
status: raw.status
|
|
431
|
+
} : {},
|
|
432
|
+
...raw.errorCode !== void 0 ? {
|
|
433
|
+
errorCode: raw.errorCode
|
|
434
|
+
} : {},
|
|
435
|
+
...raw.fromDay !== void 0 ? {
|
|
436
|
+
fromDay: raw.fromDay
|
|
437
|
+
} : {},
|
|
438
|
+
...raw.toDay !== void 0 ? {
|
|
439
|
+
toDay: raw.toDay
|
|
440
|
+
} : {}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
__name(parseRunWhere, "parseRunWhere");
|
|
444
|
+
|
|
303
445
|
// src/server/agent-api.controller.ts
|
|
304
446
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
305
447
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -319,13 +461,13 @@ function _ts_param2(paramIndex, decorator) {
|
|
|
319
461
|
}
|
|
320
462
|
__name(_ts_param2, "_ts_param");
|
|
321
463
|
var DAY_MS = 864e5;
|
|
322
|
-
var
|
|
464
|
+
var ISO_DAY2 = /^\d{4}-\d{2}-\d{2}$/;
|
|
323
465
|
function utcDay(daysAgo) {
|
|
324
466
|
return new Date(Date.now() - daysAgo * DAY_MS).toISOString().slice(0, 10);
|
|
325
467
|
}
|
|
326
468
|
__name(utcDay, "utcDay");
|
|
327
469
|
function dayOr(value, fallback) {
|
|
328
|
-
return value !== void 0 &&
|
|
470
|
+
return value !== void 0 && ISO_DAY2.test(value) ? value : fallback;
|
|
329
471
|
}
|
|
330
472
|
__name(dayOr, "dayOr");
|
|
331
473
|
function resolveRange(from, to) {
|
|
@@ -347,9 +489,11 @@ var AgentApiController = class {
|
|
|
347
489
|
}
|
|
348
490
|
dashboard;
|
|
349
491
|
approvalActorRef;
|
|
350
|
-
|
|
492
|
+
actorResolver;
|
|
493
|
+
constructor(dashboard, approvalActorRef, actorResolver) {
|
|
351
494
|
this.dashboard = dashboard;
|
|
352
495
|
this.approvalActorRef = approvalActorRef;
|
|
496
|
+
this.actorResolver = actorResolver;
|
|
353
497
|
}
|
|
354
498
|
/** `{ byModel, byActor, trend }` for a day range (defaults to the last 30 days). */
|
|
355
499
|
spend(from, to) {
|
|
@@ -367,10 +511,40 @@ var AgentApiController = class {
|
|
|
367
511
|
runs(limit) {
|
|
368
512
|
return this.dashboard.recentRuns(parseLimit(limit, 50));
|
|
369
513
|
}
|
|
514
|
+
/**
|
|
515
|
+
* Paged, filterable runs for the Reliability recent-runs table. `page` (default 1), `limit`
|
|
516
|
+
* (default 25, max 200), and `where[agentName]`/`where[status]`/`where[errorCode]`/
|
|
517
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
518
|
+
*/
|
|
519
|
+
runsPage(page, limit, where) {
|
|
520
|
+
const parsedWhere = parseRunWhere(where);
|
|
521
|
+
return this.dashboard.runsPage({
|
|
522
|
+
page: parsePageNumber(page),
|
|
523
|
+
pageSize: parseLimit(limit, 25),
|
|
524
|
+
...parsedWhere !== void 0 ? {
|
|
525
|
+
where: parsedWhere
|
|
526
|
+
} : {}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
370
529
|
/** Most recent tool calls (default 50, max 200) for the activity feed. */
|
|
371
530
|
toolCalls(limit) {
|
|
372
531
|
return this.dashboard.recentToolCalls(parseLimit(limit, 50));
|
|
373
532
|
}
|
|
533
|
+
/**
|
|
534
|
+
* Paged, filterable tool calls for the Runs & tools activity table. `page` (default 1), `limit`
|
|
535
|
+
* (default 25, max 200), and `where[toolName]`/`where[toolType]`/`where[status]`/`where[threadId]`/
|
|
536
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
537
|
+
*/
|
|
538
|
+
toolCallsPage(page, limit, where) {
|
|
539
|
+
const parsedWhere = parseToolCallWhere(where);
|
|
540
|
+
return this.dashboard.toolCallsPage({
|
|
541
|
+
page: parsePageNumber(page),
|
|
542
|
+
pageSize: parseLimit(limit, 25),
|
|
543
|
+
...parsedWhere !== void 0 ? {
|
|
544
|
+
where: parsedWhere
|
|
545
|
+
} : {}
|
|
546
|
+
});
|
|
547
|
+
}
|
|
374
548
|
/** Tool calls sitting `pending_approval` (default 50, max 200), oldest first — the approvals inbox. */
|
|
375
549
|
approvals(limit) {
|
|
376
550
|
return this.dashboard.pendingApprovals(parseLimit(limit, 50));
|
|
@@ -378,10 +552,30 @@ var AgentApiController = class {
|
|
|
378
552
|
/**
|
|
379
553
|
* Decide a pending HITL tool call. Body `{ approved: boolean; reason?: string }`. 501s (via
|
|
380
554
|
* `DashboardService.decideApproval`) when no `AGENT_APPROVAL_PORT` is bound. `executedByRef`
|
|
381
|
-
* comes from
|
|
555
|
+
* comes from {@link deciderRef} run against the live request.
|
|
382
556
|
*/
|
|
383
557
|
async decideApproval(toolCallId, body, req) {
|
|
384
|
-
await this.dashboard.decideApproval(toolCallId, body, this.
|
|
558
|
+
await this.dashboard.decideApproval(toolCallId, body, await this.deciderRef(req));
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* WHO decided, as an opaque ref: an explicit `approvalActorRef` override wins outright (no
|
|
562
|
+
* resolver fallback, even when it returns `undefined`); otherwise the AgentModule-configured
|
|
563
|
+
* actor resolver — the same identity seam chat requests use. A resolver that throws is an
|
|
564
|
+
* unauthenticated/unreadable request, not an error to surface: the decision itself was already
|
|
565
|
+
* authorized by the dashboard's guards, so the ref is simply omitted.
|
|
566
|
+
*/
|
|
567
|
+
async deciderRef(req) {
|
|
568
|
+
if (this.approvalActorRef !== void 0) {
|
|
569
|
+
return this.approvalActorRef(req);
|
|
570
|
+
}
|
|
571
|
+
if (this.actorResolver === void 0) {
|
|
572
|
+
return void 0;
|
|
573
|
+
}
|
|
574
|
+
try {
|
|
575
|
+
return (await this.actorResolver.resolve(req)).id;
|
|
576
|
+
} catch {
|
|
577
|
+
return void 0;
|
|
578
|
+
}
|
|
385
579
|
}
|
|
386
580
|
/** Per-tool call/failure/rejection/latency rollup for a day range (defaults to the last 30 days). */
|
|
387
581
|
tools(from, to) {
|
|
@@ -392,6 +586,21 @@ var AgentApiController = class {
|
|
|
392
586
|
return this.dashboard.recentThreads(parseLimit(limit, 50));
|
|
393
587
|
}
|
|
394
588
|
/**
|
|
589
|
+
* Paged, filterable threads for the Runs & tools threads table. `page` (default 1), `limit`
|
|
590
|
+
* (default 25, max 200), and `where[actorRef]`/`where[title]` (case-insensitive substring)/
|
|
591
|
+
* `where[fromDay]`/`where[toDay]` (`YYYY-MM-DD`) — an unknown `where` field 400s naming it.
|
|
592
|
+
*/
|
|
593
|
+
threadsPage(page, limit, where) {
|
|
594
|
+
const parsedWhere = parseThreadWhere(where);
|
|
595
|
+
return this.dashboard.threadsPage({
|
|
596
|
+
page: parsePageNumber(page),
|
|
597
|
+
pageSize: parseLimit(limit, 25),
|
|
598
|
+
...parsedWhere !== void 0 ? {
|
|
599
|
+
where: parsedWhere
|
|
600
|
+
} : {}
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
395
604
|
* Current price row per model, for the pricing tab. 501s (via `DashboardService.listPrices`) when
|
|
396
605
|
* no `AGENT_PRICING_STORE` is bound.
|
|
397
606
|
*/
|
|
@@ -455,6 +664,19 @@ _ts_decorate2([
|
|
|
455
664
|
]),
|
|
456
665
|
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
457
666
|
], AgentApiController.prototype, "runs", null);
|
|
667
|
+
_ts_decorate2([
|
|
668
|
+
Get("runs-page"),
|
|
669
|
+
_ts_param2(0, Query("page")),
|
|
670
|
+
_ts_param2(1, Query("limit")),
|
|
671
|
+
_ts_param2(2, Query("where")),
|
|
672
|
+
_ts_metadata2("design:type", Function),
|
|
673
|
+
_ts_metadata2("design:paramtypes", [
|
|
674
|
+
String,
|
|
675
|
+
String,
|
|
676
|
+
typeof Record === "undefined" ? Object : Record
|
|
677
|
+
]),
|
|
678
|
+
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
679
|
+
], AgentApiController.prototype, "runsPage", null);
|
|
458
680
|
_ts_decorate2([
|
|
459
681
|
Get("tool-calls"),
|
|
460
682
|
_ts_param2(0, Query("limit")),
|
|
@@ -464,6 +686,19 @@ _ts_decorate2([
|
|
|
464
686
|
]),
|
|
465
687
|
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
466
688
|
], AgentApiController.prototype, "toolCalls", null);
|
|
689
|
+
_ts_decorate2([
|
|
690
|
+
Get("tool-calls-page"),
|
|
691
|
+
_ts_param2(0, Query("page")),
|
|
692
|
+
_ts_param2(1, Query("limit")),
|
|
693
|
+
_ts_param2(2, Query("where")),
|
|
694
|
+
_ts_metadata2("design:type", Function),
|
|
695
|
+
_ts_metadata2("design:paramtypes", [
|
|
696
|
+
String,
|
|
697
|
+
String,
|
|
698
|
+
typeof Record === "undefined" ? Object : Record
|
|
699
|
+
]),
|
|
700
|
+
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
701
|
+
], AgentApiController.prototype, "toolCallsPage", null);
|
|
467
702
|
_ts_decorate2([
|
|
468
703
|
Get("approvals"),
|
|
469
704
|
_ts_param2(0, Query("limit")),
|
|
@@ -507,6 +742,19 @@ _ts_decorate2([
|
|
|
507
742
|
]),
|
|
508
743
|
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
509
744
|
], AgentApiController.prototype, "threads", null);
|
|
745
|
+
_ts_decorate2([
|
|
746
|
+
Get("threads-page"),
|
|
747
|
+
_ts_param2(0, Query("page")),
|
|
748
|
+
_ts_param2(1, Query("limit")),
|
|
749
|
+
_ts_param2(2, Query("where")),
|
|
750
|
+
_ts_metadata2("design:type", Function),
|
|
751
|
+
_ts_metadata2("design:paramtypes", [
|
|
752
|
+
String,
|
|
753
|
+
String,
|
|
754
|
+
typeof Record === "undefined" ? Object : Record
|
|
755
|
+
]),
|
|
756
|
+
_ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
757
|
+
], AgentApiController.prototype, "threadsPage", null);
|
|
510
758
|
_ts_decorate2([
|
|
511
759
|
Get("pricing"),
|
|
512
760
|
_ts_metadata2("design:type", Function),
|
|
@@ -531,10 +779,13 @@ _ts_decorate2([
|
|
|
531
779
|
AgentApiController = _ts_decorate2([
|
|
532
780
|
Controller(),
|
|
533
781
|
_ts_param2(1, Inject2(DASHBOARD_APPROVAL_ACTOR_REF)),
|
|
782
|
+
_ts_param2(2, Optional2()),
|
|
783
|
+
_ts_param2(2, Inject2(AGENT_ACTOR_RESOLVER)),
|
|
534
784
|
_ts_metadata2("design:type", Function),
|
|
535
785
|
_ts_metadata2("design:paramtypes", [
|
|
536
786
|
typeof DashboardService === "undefined" ? Object : DashboardService,
|
|
537
|
-
Object
|
|
787
|
+
Object,
|
|
788
|
+
typeof ActorResolver === "undefined" ? Object : ActorResolver
|
|
538
789
|
])
|
|
539
790
|
], AgentApiController);
|
|
540
791
|
|
|
@@ -572,7 +823,7 @@ import { RouterModule } from "@nestjs/core";
|
|
|
572
823
|
import { existsSync, readFileSync } from "node:fs";
|
|
573
824
|
import { basename, extname, join, resolve, sep } from "node:path";
|
|
574
825
|
import { fileURLToPath } from "node:url";
|
|
575
|
-
import { Controller as Controller2, Get as Get2, Header, Inject as Inject3, NotFoundException, Param as Param2, StreamableFile } from "@nestjs/common";
|
|
826
|
+
import { Controller as Controller2, Get as Get2, Header, Inject as Inject3, NotFoundException, Param as Param2, Req as Req2, Res, StreamableFile } from "@nestjs/common";
|
|
576
827
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
577
828
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
578
829
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -617,7 +868,12 @@ var AgentUiController = class {
|
|
|
617
868
|
}
|
|
618
869
|
// index.html references hash-named bundles, so it MUST NOT be cached (stale bundle = the classic
|
|
619
870
|
// "stuck loading after a deploy"). The hashed assets below are immutable.
|
|
620
|
-
index() {
|
|
871
|
+
index(req, res) {
|
|
872
|
+
if (req.headers["x-inertia"] !== void 0) {
|
|
873
|
+
res.status(409);
|
|
874
|
+
res.setHeader("X-Inertia-Location", req.originalUrl);
|
|
875
|
+
return "";
|
|
876
|
+
}
|
|
621
877
|
const indexPath = join(this.dir, "index.html");
|
|
622
878
|
if (!existsSync(indexPath)) {
|
|
623
879
|
throw new NotFoundException("Dashboard is not built. Run the package build.");
|
|
@@ -644,8 +900,15 @@ _ts_decorate3([
|
|
|
644
900
|
Get2(),
|
|
645
901
|
Header("Content-Type", "text/html; charset=utf-8"),
|
|
646
902
|
Header("Cache-Control", "no-store, must-revalidate"),
|
|
903
|
+
_ts_param3(0, Req2()),
|
|
904
|
+
_ts_param3(1, Res({
|
|
905
|
+
passthrough: true
|
|
906
|
+
})),
|
|
647
907
|
_ts_metadata3("design:type", Function),
|
|
648
|
-
_ts_metadata3("design:paramtypes", [
|
|
908
|
+
_ts_metadata3("design:paramtypes", [
|
|
909
|
+
typeof UiPageRequest === "undefined" ? Object : UiPageRequest,
|
|
910
|
+
typeof UiPageResponse === "undefined" ? Object : UiPageResponse
|
|
911
|
+
]),
|
|
649
912
|
_ts_metadata3("design:returntype", String)
|
|
650
913
|
], AgentUiController.prototype, "index", null);
|
|
651
914
|
_ts_decorate3([
|
|
@@ -784,6 +1047,7 @@ AgentDashboardModule = _ts_decorate4([
|
|
|
784
1047
|
], AgentDashboardModule);
|
|
785
1048
|
export {
|
|
786
1049
|
AGENT_ACTOR_DIRECTORY,
|
|
1050
|
+
AGENT_ACTOR_RESOLVER,
|
|
787
1051
|
AGENT_APPROVAL_PORT,
|
|
788
1052
|
AGENT_GOVERNANCE_QUERIES,
|
|
789
1053
|
AGENT_PRICING_STORE,
|