@dudousxd/nestjs-agent-telescope 0.4.0 → 0.5.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/index.cjs +36 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -13
- package/dist/index.d.ts +13 -13
- package/dist/index.js +37 -32
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -153,7 +153,7 @@ function agentDashboard(opts = {}) {
|
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
title: "Run trends",
|
|
156
|
-
cols:
|
|
156
|
+
cols: 4,
|
|
157
157
|
panels: [
|
|
158
158
|
{
|
|
159
159
|
kind: "timeseries",
|
|
@@ -167,16 +167,28 @@ function agentDashboard(opts = {}) {
|
|
|
167
167
|
],
|
|
168
168
|
style: "stacked"
|
|
169
169
|
},
|
|
170
|
+
// Two duration stats, not a `distribution` panel: RunMetrics carries only p50/p95 (no
|
|
171
|
+
// raw samples to bucket), so a histogram here would be a permanently-empty box.
|
|
170
172
|
{
|
|
171
|
-
kind: "
|
|
172
|
-
title: "
|
|
173
|
+
kind: "stat",
|
|
174
|
+
title: "Duration p50",
|
|
173
175
|
data: {
|
|
174
|
-
provider: "agent.runs.duration"
|
|
176
|
+
provider: "agent.runs.duration",
|
|
177
|
+
query: {
|
|
178
|
+
metric: "p50"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
format: "duration"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
kind: "stat",
|
|
185
|
+
title: "Duration p95",
|
|
186
|
+
data: {
|
|
187
|
+
provider: "agent.runs.duration",
|
|
188
|
+
query: {
|
|
189
|
+
metric: "p95"
|
|
190
|
+
}
|
|
175
191
|
},
|
|
176
|
-
markers: [
|
|
177
|
-
"p50",
|
|
178
|
-
"p95"
|
|
179
|
-
],
|
|
180
192
|
format: "duration"
|
|
181
193
|
},
|
|
182
194
|
{
|
|
@@ -223,17 +235,15 @@ function agentDashboard(opts = {}) {
|
|
|
223
235
|
data: {
|
|
224
236
|
provider: "agent.runs.recent"
|
|
225
237
|
},
|
|
238
|
+
// A deliberate SUBSET of the provider's row shape: the full 11-field row overflows the
|
|
239
|
+
// card horizontally. Thread/actor/retries/errorCode detail lives in the standalone
|
|
240
|
+
// agent dashboard; the provider keeps returning the full row for other consumers.
|
|
226
241
|
columns: [
|
|
227
242
|
{
|
|
228
243
|
key: "startedAt",
|
|
229
244
|
label: "Started"
|
|
230
245
|
},
|
|
231
246
|
col("runId", "Run", opts.runHref),
|
|
232
|
-
col("threadId", "Thread", opts.threadHref),
|
|
233
|
-
{
|
|
234
|
-
key: "actorRef",
|
|
235
|
-
label: "Actor"
|
|
236
|
-
},
|
|
237
247
|
{
|
|
238
248
|
key: "agentName",
|
|
239
249
|
label: "Agent"
|
|
@@ -246,14 +256,6 @@ function agentDashboard(opts = {}) {
|
|
|
246
256
|
key: "durationMs",
|
|
247
257
|
label: "Duration (ms)"
|
|
248
258
|
},
|
|
249
|
-
{
|
|
250
|
-
key: "retries",
|
|
251
|
-
label: "Retries"
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
key: "errorCode",
|
|
255
|
-
label: "Error code"
|
|
256
|
-
},
|
|
257
259
|
{
|
|
258
260
|
key: "errorMessage",
|
|
259
261
|
label: "Error"
|
|
@@ -947,15 +949,17 @@ function agentRunsRetriesProvider() {
|
|
|
947
949
|
}
|
|
948
950
|
__name(agentRunsRetriesProvider, "agentRunsRetriesProvider");
|
|
949
951
|
function agentRunsDurationProvider() {
|
|
950
|
-
return
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
952
|
+
return {
|
|
953
|
+
name: "agent.runs.duration",
|
|
954
|
+
async resolve(query, ctx) {
|
|
955
|
+
const queries = resolveGovernanceQueries(ctx);
|
|
956
|
+
const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;
|
|
957
|
+
const value = query?.metric === "p95" ? metrics.durationP95Ms : metrics.durationP50Ms;
|
|
958
|
+
return {
|
|
959
|
+
value: value ?? 0
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
};
|
|
959
963
|
}
|
|
960
964
|
__name(agentRunsDurationProvider, "agentRunsDurationProvider");
|
|
961
965
|
function agentRunsByAgentTableProvider() {
|
|
@@ -1051,6 +1055,7 @@ var AgentTelescopeWatcher = class {
|
|
|
1051
1055
|
type = "agent";
|
|
1052
1056
|
disposers = [];
|
|
1053
1057
|
register(ctx) {
|
|
1058
|
+
this.disposers.push((0, import_nestjs_diagnostics.claimDiagnostics)("agent", import_nestjs_agent_core2.AGENT_DIAGNOSTIC_EVENTS));
|
|
1054
1059
|
for (const event of import_nestjs_agent_core2.AGENT_DIAGNOSTIC_EVENTS) {
|
|
1055
1060
|
const channel = (0, import_nestjs_diagnostics.channelName)("agent", event);
|
|
1056
1061
|
const onMessage = /* @__PURE__ */ __name((message) => {
|
|
@@ -1070,7 +1075,7 @@ var AgentTelescopeWatcher = class {
|
|
|
1070
1075
|
this.disposers.push(() => (0, import_node_diagnostics_channel.unsubscribe)(channel, onMessage));
|
|
1071
1076
|
}
|
|
1072
1077
|
}
|
|
1073
|
-
/** Detach all channel subscriptions (e.g. on module destroy). */
|
|
1078
|
+
/** Detach all channel subscriptions and release the diagnostics claim (e.g. on module destroy). */
|
|
1074
1079
|
dispose() {
|
|
1075
1080
|
while (this.disposers.length) this.disposers.pop()?.();
|
|
1076
1081
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/agent-telescope.extension.ts","../src/agent-dashboard.spec-data.ts","../src/agent-data-providers.ts","../src/agent-governance-providers.ts","../src/agent-telescope.watcher.ts"],"sourcesContent":["export { agentTelescopeExtension } from './agent-telescope.extension.js';\nexport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\nexport { agentDashboard } from './agent-dashboard.spec-data.js';\nexport {\n agentRunsProvider,\n agentTokensProvider,\n agentToolsProvider,\n agentToolStatusProvider,\n} from './agent-data-providers.js';\nexport {\n agentActorSpendTableProvider,\n agentModelSpendTableProvider,\n agentPendingApprovalsCountProvider,\n agentPendingApprovalsTableProvider,\n agentRecentRunsTableProvider,\n agentRecentThreadsTableProvider,\n agentRecentToolCallsTableProvider,\n agentRunErrorsProvider,\n agentRunsByAgentTableProvider,\n agentRunsDurationProvider,\n agentRunsFailedProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentTokensTotalProvider,\n agentToolStatsTableProvider,\n agentTopThreadsTableProvider,\n agentUsageTrendProvider,\n capErrorMessage,\n resolveRange,\n shiftUtcDay,\n shortPromptHash,\n toActorSpendRows,\n toActorSpendSegments,\n toModelSpendRows,\n toModelSpendSegments,\n toPendingApprovalTableRows,\n toRecentRunTableRows,\n toRecentThreadTableRows,\n toRecentToolCallRows,\n toRunAgentTableRows,\n toRunErrorSegments,\n toRunTrendRows,\n toThreadSpendRows,\n toToolStatTableRows,\n totalCostUsd,\n totalTokens,\n toUsageTrendRows,\n} from './agent-governance-providers.js';\n","import { defineTelescopeExtension } from '@dudousxd/nestjs-telescope';\nimport { agentDashboard } from './agent-dashboard.spec-data.js';\nimport {\n agentRunsProvider,\n agentTokensProvider,\n agentToolStatusProvider,\n} from './agent-data-providers.js';\nimport {\n agentActorSpendTableProvider,\n agentModelSpendTableProvider,\n agentPendingApprovalsCountProvider,\n agentPendingApprovalsTableProvider,\n agentRecentRunsTableProvider,\n agentRecentThreadsTableProvider,\n agentRecentToolCallsTableProvider,\n agentRunErrorsProvider,\n agentRunsByAgentTableProvider,\n agentRunsDurationProvider,\n agentRunsFailedProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentTokensTotalProvider,\n agentToolStatsTableProvider,\n agentTopThreadsTableProvider,\n agentUsageTrendProvider,\n} from './agent-governance-providers.js';\nimport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\n\n/**\n * The first-class Telescope extension for nestjs-agent: an \"Agent\" tab fed by two sources —\n * the `aviary:agent:*` diagnostics channel (live runs, tool calls) via the watcher, and the\n * authoritative `AGENT_GOVERNANCE_QUERIES` read-model (historical spend/usage, run reliability,\n * tool activity, the approvals inbox) via the governance providers. The extension `name`,\n * entry-type id, dashboard id, and every provider name share the `agent` prefix so the registry's\n * global-uniqueness namespaces never collide with sibling extensions.\n *\n * `threadHref`/`runHref` deep-link a table row's `threadId`/`runId` cell out to the host's own\n * thread/run viewer — passed straight through to {@link agentDashboard}, mirroring\n * `durableTelescopeExtension`'s `runHref` option.\n *\n * Host wiring: the governance panels (Spend/Models/Actors/Reliability/Runs/Threads/Approvals/Tool\n * stats/Recent tool calls) resolve `AGENT_GOVERNANCE_QUERIES` from the host DI container at\n * request time (via `ctx.moduleRef`). The host must bind that token — from its store adapter\n * (e.g. `store-mikro-orm` / `store-drizzle` / `testing`) — in the same module that registers\n * `TelescopeModule.forRoot({ extensions: [agentTelescopeExtension()] })`. If the binding is\n * absent, those panels render an empty state; the live watcher-fed panels (Runs/Tokens stats and\n * the Tool-call status breakdown) keep working regardless.\n */\nexport function agentTelescopeExtension(opts: { threadHref?: string; runHref?: string } = {}) {\n return defineTelescopeExtension({\n name: 'agent',\n watchers: () => [new AgentTelescopeWatcher()],\n entryTypes: () => [{ id: 'agent', label: 'Agent', dot: 'bg-violet-400' }],\n dashboards: () => [agentDashboard(opts)],\n dataProviders: () => [\n agentRunsProvider(),\n agentTokensProvider(),\n agentToolStatusProvider(),\n agentSpendTotalProvider(),\n agentTokensTotalProvider(),\n agentSpendByModelProvider(),\n agentModelSpendTableProvider(),\n agentUsageTrendProvider(),\n agentActorSpendTableProvider(),\n agentSpendByActorProvider(),\n agentTopThreadsTableProvider(),\n agentRunsTotalProvider(),\n agentRunsSuccessRateProvider(),\n agentRunsFailedProvider(),\n agentRunsRetriesProvider(),\n agentRunsDurationProvider(),\n agentRunsByAgentTableProvider(),\n agentRunErrorsProvider(),\n agentRunsTrendProvider(),\n agentRecentRunsTableProvider(),\n agentRecentToolCallsTableProvider(),\n agentRecentThreadsTableProvider(),\n agentPendingApprovalsCountProvider(),\n agentPendingApprovalsTableProvider(),\n agentToolStatsTableProvider(),\n ],\n });\n}\n","import type { Column, DashboardSpec } from '@dudousxd/nestjs-telescope';\n\n/** A plain column, or one carrying a `Column.link` to `href` when `href` is given. */\nfunction col(key: string, label: string, href?: string): Column {\n return href !== undefined ? { key, label, link: { href } } : { key, label };\n}\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref`/`runHref` are URL templates for deep-linking a `{threadId}`/`{runId}` cell out to\n * the host's own thread/run viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA),\n * mirroring `durableTelescopeExtension`'s `runHref` option. Every table whose rows carry a\n * `threadId`/`runId` gets a `Column.link` for it (via {@link col}); omit an option to leave that\n * column plain text.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n title: 'Overview',\n cols: 2,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n ],\n },\n {\n title: 'Reliability',\n cols: 4,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs.total' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n { kind: 'stat', title: 'Failed', data: { provider: 'agent.runs.failed' } },\n { kind: 'stat', title: 'Retries', data: { provider: 'agent.runs.retries' } },\n ],\n },\n {\n title: 'Run trends',\n cols: 3,\n panels: [\n {\n kind: 'timeseries',\n title: 'Runs & failures',\n data: { provider: 'agent.runs.trend' },\n series: ['runs', 'failed'],\n style: 'stacked',\n },\n {\n kind: 'distribution',\n title: 'Run duration',\n data: { provider: 'agent.runs.duration' },\n markers: ['p50', 'p95'],\n format: 'duration',\n },\n {\n kind: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\n ],\n },\n {\n title: 'Runs',\n panels: [\n {\n kind: 'table',\n title: 'Runs by agent',\n data: { provider: 'agent.runs.byAgent' },\n columns: [\n { key: 'agentName', label: 'Agent' },\n { key: 'runs', label: 'Runs' },\n { key: 'failed', label: 'Failed' },\n { key: 'retries', label: 'Retries' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent runs',\n data: { provider: 'agent.runs.recent' },\n columns: [\n { key: 'startedAt', label: 'Started' },\n col('runId', 'Run', opts.runHref),\n col('threadId', 'Thread', opts.threadHref),\n { key: 'actorRef', label: 'Actor' },\n { key: 'agentName', label: 'Agent' },\n { key: 'status', label: 'Status' },\n { key: 'durationMs', label: 'Duration (ms)' },\n { key: 'retries', label: 'Retries' },\n { key: 'errorCode', label: 'Error code' },\n { key: 'errorMessage', label: 'Error' },\n { key: 'promptHash', label: 'Prompt' },\n ],\n },\n ],\n },\n {\n title: 'Spend',\n cols: 2,\n panels: [\n {\n kind: 'stat',\n title: 'Total spend (USD)',\n data: { provider: 'agent.spend.totalCost' },\n format: 'number',\n },\n {\n kind: 'stat',\n title: 'Total tokens',\n data: { provider: 'agent.spend.totalTokens' },\n format: 'number',\n },\n {\n kind: 'breakdown',\n title: 'Spend by model',\n data: { provider: 'agent.spend.byModel' },\n style: 'donut',\n },\n {\n kind: 'timeseries',\n title: 'Daily spend & tokens',\n data: { provider: 'agent.usage.trend' },\n series: ['costUsd', 'totalTokens'],\n style: 'area',\n },\n ],\n },\n {\n title: 'Models',\n panels: [\n {\n kind: 'table',\n title: 'Usage & cost by model',\n data: { provider: 'agent.spend.byModelTable' },\n columns: [\n { key: 'modelId', label: 'Model' },\n { key: 'requests', label: 'Requests' },\n { key: 'inputTokens', label: 'Input tokens' },\n { key: 'outputTokens', label: 'Output tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Actors',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Spend share by actor',\n data: { provider: 'agent.spend.byActorShare' },\n style: 'bar',\n },\n {\n kind: 'table',\n title: 'Spend by actor',\n data: { provider: 'agent.spend.byActor' },\n columns: [\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Threads',\n cols: 2,\n panels: [\n {\n kind: 'table',\n title: 'Top threads by cost',\n data: { provider: 'agent.threads.topSpend' },\n columns: [\n { key: 'title', label: 'Thread' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n data: { provider: 'agent.threads.recent' },\n columns: [\n col('threadId', 'Thread', opts.threadHref),\n { key: 'title', label: 'Title' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'messageCount', label: 'Messages' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'lastActivityAt', label: 'Last activity' },\n ],\n },\n ],\n },\n {\n title: 'Approvals',\n cols: 3,\n panels: [\n {\n kind: 'stat',\n title: 'Pending approvals',\n data: { provider: 'agent.approvals.pending' },\n },\n {\n kind: 'table',\n title: 'Approvals inbox',\n data: { provider: 'agent.approvals.recent' },\n columns: [\n { key: 'requestedAt', label: 'Requested' },\n { key: 'toolName', label: 'Tool' },\n { key: 'threadTitle', label: 'Thread' },\n col('threadId', 'Thread id', opts.threadHref),\n { key: 'actorRef', label: 'Actor' },\n { key: 'agentName', label: 'Agent' },\n ],\n },\n ],\n },\n {\n title: 'Tools',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Tool-call status',\n data: { provider: 'agent.toolStatus' },\n style: 'donut',\n },\n {\n kind: 'table',\n title: 'Tool stats',\n data: { provider: 'agent.tools.stats' },\n columns: [\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'calls', label: 'Calls' },\n { key: 'failed', label: 'Failed' },\n { key: 'rejected', label: 'Rejected' },\n { key: 'p95ExecutionMs', label: 'p95 (ms)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent tool calls',\n data: { provider: 'agent.tools.recent' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n ],\n },\n ],\n };\n}\n","import type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\nimport { TELESCOPE_STORAGE } from '@dudousxd/nestjs-telescope';\n\ninterface AgentEntryContent {\n event: string;\n runId?: string;\n threadId?: string;\n toolName?: string;\n toolType?: string;\n status?: string;\n steps?: number;\n inputTokens?: number;\n outputTokens?: number;\n}\n\ninterface StorageEntry {\n content?: AgentEntryContent;\n createdAt?: Date;\n}\n\nasync function fetchEntries(ctx: ExtensionContext): Promise<StorageEntry[]> {\n const storage = ctx.moduleRef.get(TELESCOPE_STORAGE, { strict: false }) as {\n get(query: { type?: string; limit?: number }): Promise<{ data: StorageEntry[] }>;\n };\n const page = await storage.get({ type: 'agent', limit: 5_000 });\n return page.data;\n}\n\nfunction ofEvent(entries: StorageEntry[], event: string): StorageEntry[] {\n return entries.filter((entry) => entry.content?.event === event);\n}\n\n/** stat → total agent runs (run.finished entries). */\nexport function agentRunsProvider(): DataProvider {\n return {\n name: 'agent.runs',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n return { value: finished.length };\n },\n };\n}\n\n/** stat → total tokens across all finished runs. */\nexport function agentTokensProvider(): DataProvider {\n return {\n name: 'agent.tokens',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n const value = finished.reduce(\n (sum, entry) =>\n sum + (entry.content?.inputTokens ?? 0) + (entry.content?.outputTokens ?? 0),\n 0,\n );\n return { value };\n },\n };\n}\n\n/**\n * table → recent tool calls, from Telescope's own ephemeral event storage.\n *\n * @deprecated Superseded in the shipped dashboard by `agentRecentToolCallsTableProvider`\n * (`agent.tools.recent`, in `agent-governance-providers.ts`), which reads the durable,\n * restart-surviving `AGENT_GOVERNANCE_QUERIES.recentToolCalls` read-model. That durable route is\n * never behind this ephemeral one: `agent-loop.ts` always awaits `store.recordToolCall` /\n * `store.updateToolCall` (the durable write) BEFORE calling `publishAgentToolCall` (the event this\n * provider reads), so a row is durably queryable strictly before the ephemeral entry exists. The\n * durable route also captures the `pending_approval` state this ephemeral channel never emits at\n * all (no `publishAgentToolCall` call sits between `recordToolCall(status: 'pending_approval')`\n * and the eventual terminal transition) — so there's no in-flight state left for this table to\n * uniquely show. Kept exported (not removed — that would be a breaking export change) for hosts\n * that use `agentTelescopeExtension()` without wiring `AGENT_GOVERNANCE_QUERIES`, or that compose\n * a custom extension from these lower-level provider functions directly.\n */\nexport function agentToolsProvider(): DataProvider {\n return {\n name: 'agent.tools',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call')\n .slice(-50)\n .reverse()\n .map((entry) => ({\n toolName: entry.content?.toolName ?? '',\n toolType: entry.content?.toolType ?? '',\n status: entry.content?.status ?? '',\n runId: entry.content?.runId ?? '',\n }));\n return { rows: calls };\n },\n };\n}\n\n/** breakdown → tool-call status distribution. */\nexport function agentToolStatusProvider(): DataProvider {\n return {\n name: 'agent.toolStatus',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call');\n const counts = new Map<string, number>();\n for (const call of calls) {\n const status = call.content?.status ?? 'unknown';\n counts.set(status, (counts.get(status) ?? 0) + 1);\n }\n return { segments: [...counts.entries()].map(([label, value]) => ({ label, value })) };\n },\n };\n}\n","import type {\n ActorSpendRow,\n AgentGovernanceQueries,\n GovernanceRange,\n ModelSpendRow,\n PendingApprovalRow,\n RecentRunRow,\n RunAgentBreakdownRow,\n RunErrorBreakdownRow,\n RunMetrics,\n RunTrendPoint,\n ThreadActivityRow,\n ThreadSpendRow,\n ToolCallActivityRow,\n ToolStatRow,\n UsageTrendPoint,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_GOVERNANCE_QUERIES } from '@dudousxd/nestjs-agent-core';\nimport type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\n\n/**\n * Governance data providers for the \"Agent\" Telescope tab: spend/usage, run reliability, tool\n * activity, and the cross-thread approvals inbox. Unlike the live watcher-fed providers in\n * `agent-data-providers.ts` (which read the ephemeral Telescope event storage), these read the\n * authoritative, restart-surviving read-model: `AGENT_GOVERNANCE_QUERIES` (usage ⋈ pricing, plus\n * run/tool-call/thread history).\n *\n * The read-model is resolved from the host's DI container via `ctx.moduleRef` — the exact same\n * mechanism the existing providers use for `TELESCOPE_STORAGE`. The host must bind\n * `AGENT_GOVERNANCE_QUERIES` (from its store adapter) in the same module that registers Telescope;\n * when the binding is absent every provider degrades to an empty-but-valid shape rather than throwing.\n */\n\n/** Default trailing window (in days, inclusive) when a panel query omits an explicit range. */\nconst DEFAULT_TREND_WINDOW_DAYS = 30;\n\nconst ISO_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** A breakdown-panel segment (Telescope core: `{ segments: Array<{ label, value, color? }> }`). */\ninterface BreakdownSegment {\n label: string;\n value: number;\n}\n\n/** One row of the per-model usage/cost table. */\ninterface ModelSpendTableRow {\n modelId: string;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\n/** One row of the per-actor spend table. */\ninterface ActorSpendTableRow {\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** One row of the top-threads-by-cost table. */\ninterface ThreadSpendTableRow {\n title: string;\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** Top threads by cost within the range, capped to this count. */\nconst TOP_THREADS_LIMIT = 10;\n\n/** One point of the timeseries trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface UsageTrendTableRow {\n label: string;\n costUsd: number;\n totalTokens: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Structural guard so the DI-resolved binding is narrowed without an `as`/`any` cast. */\nfunction isGovernanceQueries(value: unknown): value is AgentGovernanceQueries {\n return (\n isRecord(value) &&\n typeof value.spendByModel === 'function' &&\n typeof value.spendByActor === 'function' &&\n typeof value.spendByThread === 'function' &&\n typeof value.usageTrend === 'function' &&\n typeof value.recentToolCalls === 'function' &&\n typeof value.recentThreads === 'function' &&\n typeof value.runMetrics === 'function' &&\n typeof value.runsByAgent === 'function' &&\n typeof value.runErrors === 'function' &&\n typeof value.runTrend === 'function' &&\n typeof value.recentRuns === 'function' &&\n typeof value.pendingApprovals === 'function' &&\n typeof value.toolStats === 'function'\n );\n}\n\n/**\n * Resolve the governance read-model from the host container. Returns `null` when the host has not\n * bound `AGENT_GOVERNANCE_QUERIES` (missing token throws inside `moduleRef.get`) so panels can render\n * an empty state instead of erroring.\n */\nfunction resolveGovernanceQueries(ctx: ExtensionContext): AgentGovernanceQueries | null {\n let resolved: unknown;\n try {\n resolved = ctx.moduleRef.get(AGENT_GOVERNANCE_QUERIES, { strict: false });\n } catch {\n return null;\n }\n return isGovernanceQueries(resolved) ? resolved : null;\n}\n\nfunction isIsoDay(value: unknown): value is string {\n return typeof value === 'string' && ISO_DAY_PATTERN.test(value);\n}\n\nfunction todayUtcDay(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Shift a `YYYY-MM-DD` UTC day by `deltaDays` (negative goes back in time). */\nexport function shiftUtcDay(day: string, deltaDays: number): string {\n const shifted = new Date(`${day}T00:00:00.000Z`);\n shifted.setUTCDate(shifted.getUTCDate() + deltaDays);\n return shifted.toISOString().slice(0, 10);\n}\n\n/**\n * Derive the query range: honour explicit `fromDay`/`toDay` (validated ISO days), otherwise default\n * to the trailing {@link DEFAULT_TREND_WINDOW_DAYS}-day window ending today (UTC).\n */\nexport function resolveRange(query: Record<string, unknown> | undefined): GovernanceRange {\n const toDay = query && isIsoDay(query.toDay) ? query.toDay : todayUtcDay();\n const fromDay =\n query && isIsoDay(query.fromDay)\n ? query.fromDay\n : shiftUtcDay(toDay, -(DEFAULT_TREND_WINDOW_DAYS - 1));\n return { fromDay, toDay };\n}\n\nfunction roundCents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/** Sum authoritative spend across every model row. */\nexport function totalCostUsd(rows: ModelSpendRow[]): number {\n return roundCents(rows.reduce((sum, row) => sum + row.costUsd, 0));\n}\n\n/** Sum input + output tokens across every model row. */\nexport function totalTokens(rows: ModelSpendRow[]): number {\n return rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);\n}\n\n/** Spend-by-model as breakdown segments (models with zero cost are dropped from the donut). */\nexport function toModelSpendSegments(rows: ModelSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.modelId, value: roundCents(row.costUsd) }));\n}\n\n/** Spend-by-model as table rows (cost rounded to cents; usage kept exact). */\nexport function toModelSpendRows(rows: ModelSpendRow[]): ModelSpendTableRow[] {\n return rows.map((row) => ({\n modelId: row.modelId,\n requests: row.requests,\n inputTokens: row.inputTokens,\n outputTokens: row.outputTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as table rows. */\nexport function toActorSpendRows(rows: ActorSpendRow[]): ActorSpendTableRow[] {\n return rows.map((row) => ({\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Top-threads-by-cost as table rows. */\nexport function toThreadSpendRows(rows: ThreadSpendRow[]): ThreadSpendTableRow[] {\n return rows.map((row) => ({\n title: row.title || row.threadId,\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as breakdown segments (actors with zero cost are dropped). */\nexport function toActorSpendSegments(rows: ActorSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.actorRef, value: roundCents(row.costUsd) }));\n}\n\n/** Daily usage trend as timeseries rows keyed by `label` (the day). */\nexport function toUsageTrendRows(points: UsageTrendPoint[]): UsageTrendTableRow[] {\n return points.map((point) => ({\n label: point.day,\n costUsd: roundCents(point.costUsd),\n totalTokens: point.totalTokens,\n }));\n}\n\n// ─── Run reliability + tools + approvals shaping ─────────────────────────────\n\n/** Placeholder shown for a table cell whose source value is `null`/unmeasured — matches the\n * convention `@dudousxd/nestjs-durable-telescope` uses for the same case (e.g. `fmtNum`). */\nconst NO_VALUE = '—';\n\n/** Run/failure/retry rollup as table rows — `RunAgentBreakdownRow` is already table-shaped. */\nexport function toRunAgentTableRows(\n rows: RunAgentBreakdownRow[],\n): Array<{ agentName: string; runs: number; failed: number; retries: number }> {\n return rows.map((row) => ({\n agentName: row.agentName,\n runs: row.runs,\n failed: row.failed,\n retries: row.retries,\n }));\n}\n\n/** Failed-run counts by error code as breakdown segments. */\nexport function toRunErrorSegments(rows: RunErrorBreakdownRow[]): BreakdownSegment[] {\n return rows.map((row) => ({ label: row.errorCode, value: row.count }));\n}\n\n/** One point of the run/failure trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface RunTrendTableRow {\n label: string;\n runs: number;\n failed: number;\n}\n\n/** Daily run/failure trend as timeseries rows keyed by `label` (the day). */\nexport function toRunTrendRows(points: RunTrendPoint[]): RunTrendTableRow[] {\n return points.map((point) => ({ label: point.day, runs: point.runs, failed: point.failed }));\n}\n\n/** Cap this many characters before a byte length; matches the DB column's practical display width. */\nconst ERROR_MESSAGE_CAP = 500;\n\n/**\n * Cap a run's error message to {@link ERROR_MESSAGE_CAP} characters before it leaves the provider.\n * `DataProvider.resolve` output bypasses Telescope core's `redact()` pipeline — that only runs on\n * entries a `Watcher` records via `ctx.record`, not on values a provider computes and returns\n * directly to a panel — so an unbounded stack trace or secret-laden failure message would ride\n * straight into a table cell with no truncation/redaction safety net. This cap is a stopgap\n * mitigation, not a substitute for the (out-of-scope this wave) telescope-core redaction hook for\n * DataProvider output.\n */\nexport function capErrorMessage(message: string | null): string | null {\n if (message === null) return null;\n return message.length > ERROR_MESSAGE_CAP ? `${message.slice(0, ERROR_MESSAGE_CAP)}…` : message;\n}\n\n/** How many leading hex characters of a promptHash the table shows as a short chip. */\nconst PROMPT_HASH_CHIP_LENGTH = 10;\n\n/** Shorten a full sha256 promptHash to a compact chip for the table column. */\nexport function shortPromptHash(promptHash: string | null): string | null {\n return promptHash === null ? null : promptHash.slice(0, PROMPT_HASH_CHIP_LENGTH);\n}\n\n/** One row of the recent-runs table — every nullable field falls back to {@link NO_VALUE}. */\ninterface RecentRunTableRow {\n startedAt: string;\n runId: string;\n threadId: string;\n actorRef: string;\n agentName: string;\n status: string;\n durationMs: number | string;\n retries: number;\n errorCode: string;\n errorMessage: string;\n promptHash: string;\n}\n\n/** Recent runs as table rows: errorMessage capped, promptHash shortened to a chip. */\nexport function toRecentRunTableRows(rows: RecentRunRow[]): RecentRunTableRow[] {\n return rows.map((row) => ({\n startedAt: row.startedAt,\n runId: row.runId,\n threadId: row.threadId,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n status: row.status,\n durationMs: row.durationMs ?? NO_VALUE,\n retries: row.retries,\n errorCode: row.errorCode ?? NO_VALUE,\n errorMessage: capErrorMessage(row.errorMessage) ?? NO_VALUE,\n promptHash: shortPromptHash(row.promptHash) ?? NO_VALUE,\n }));\n}\n\n/** Recent tool calls as table rows — `ToolCallActivityRow` is already table-shaped. */\nexport function toRecentToolCallRows(rows: ToolCallActivityRow[]): ToolCallActivityRow[] {\n return rows;\n}\n\n/** Recent threads as table rows — `ThreadActivityRow` is already table-shaped. */\nexport function toRecentThreadTableRows(rows: ThreadActivityRow[]): ThreadActivityRow[] {\n return rows;\n}\n\n/** One row of the pending-approvals inbox table, `input` stringified for display. */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n}\n\n/** Pending-approvals rows as table rows (drops the raw `input` — not renderable in a table cell). */\nexport function toPendingApprovalTableRows(rows: PendingApprovalRow[]): PendingApprovalTableRow[] {\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n requestedAt: row.requestedAt,\n }));\n}\n\n/** One row of the per-tool stats table, `p95ExecutionMs` falling back to {@link NO_VALUE}. */\ninterface ToolStatTableRow {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n p95ExecutionMs: number | string;\n}\n\n/** Per-tool call/failure/rejection/latency rollup as table rows. */\nexport function toToolStatTableRows(rows: ToolStatRow[]): ToolStatTableRow[] {\n return rows.map((row) => ({\n toolName: row.toolName,\n toolType: row.toolType,\n calls: row.calls,\n failed: row.failed,\n rejected: row.rejected,\n p95ExecutionMs: row.p95ExecutionMs ?? NO_VALUE,\n }));\n}\n\n/** Zero-valued `RunMetrics`, returned when the read-model isn't bound. */\nconst EMPTY_RUN_METRICS: RunMetrics = {\n runs: 0,\n completed: 0,\n failed: 0,\n successRate: 0,\n retries: 0,\n durationP50Ms: null,\n durationP95Ms: null,\n};\n\n/**\n * Build a governance `DataProvider` from a fetch + a format step. Every provider follows the same\n * shape: resolve the read-model, run ONE query over the panel's range, then format the rows into the\n * panel's result shape. When the host hasn't bound the read-model, `fetch` is skipped and `format`\n * runs over `[]` — which is exactly the empty-but-valid shape each formatter already yields (0 for\n * totals, `[]` for segments/rows), so the degraded case needs no special-casing.\n */\nfunction governanceStatProvider<TRow>(\n name: string,\n fetch: (queries: AgentGovernanceQueries, range: GovernanceRange) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveRange(query)) : [];\n return format(rows);\n },\n };\n}\n\n/** stat → authoritative total spend (USD) over the range. */\nexport function agentSpendTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalCost',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalCostUsd(rows) }),\n );\n}\n\n/** stat → authoritative total tokens (input + output) over the range. */\nexport function agentTokensTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalTokens',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalTokens(rows) }),\n );\n}\n\n/** breakdown → spend share per model. */\nexport function agentSpendByModelProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModel',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ segments: toModelSpendSegments(rows) }),\n );\n}\n\n/** table → per-model requests / in+out tokens / cost. */\nexport function agentModelSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModelTable',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ rows: toModelSpendRows(rows) }),\n );\n}\n\n/** timeseries → daily spend + tokens trend. */\nexport function agentUsageTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.usage.trend',\n (queries, range) => queries.usageTrend(range),\n (points) => ({ rows: toUsageTrendRows(points) }),\n );\n}\n\n/** table → spend per acting ref (user/tenant). */\nexport function agentActorSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActor',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ rows: toActorSpendRows(rows) }),\n );\n}\n\n/** breakdown → spend share per actor. */\nexport function agentSpendByActorProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActorShare',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ segments: toActorSpendSegments(rows) }),\n );\n}\n\n/** table → top threads by cost (title, actor, requests, tokens, cost). */\nexport function agentTopThreadsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.threads.topSpend',\n (queries, range) => queries.spendByThread(range, TOP_THREADS_LIMIT),\n (rows) => ({ rows: toThreadSpendRows(rows) }),\n );\n}\n\n// ─── Reliability providers ────────────────────────────────────────────────────\n\n/**\n * Build a `DataProvider` from ONE range-scoped `runMetrics` call + a format step — the\n * `governanceStatProvider` pattern specialized for the single-object `RunMetrics` shape (the five\n * reliability stats all reuse the same underlying query, exactly like the spend stats above reuse\n * `spendByModel`). Degrades to {@link EMPTY_RUN_METRICS} when the read-model isn't bound.\n */\nfunction governanceRunMetricsProvider(\n name: string,\n format: (metrics: RunMetrics) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;\n return format(metrics);\n },\n };\n}\n\n/** stat → total runs over the range. */\nexport function agentRunsTotalProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.total', (metrics) => ({ value: metrics.runs }));\n}\n\n/** stat → completed/total success rate over the range. */\nexport function agentRunsSuccessRateProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.successRate', (metrics) => ({\n value: metrics.successRate,\n }));\n}\n\n/** stat → failed run count over the range. */\nexport function agentRunsFailedProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.failed', (metrics) => ({\n value: metrics.failed,\n }));\n}\n\n/** stat → total llm-step retries across the range's runs. */\nexport function agentRunsRetriesProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.retries', (metrics) => ({\n value: metrics.retries,\n }));\n}\n\n/**\n * distribution → run duration. `RunMetrics` exposes only the two percentiles (no raw per-run\n * samples), so there is nothing to bucket into a histogram — the panel renders its `p50`/`p95`\n * markers over an empty bucket series. `exactOptionalPropertyTypes` means a `null` percentile is\n * omitted from the result rather than carried as an explicit `undefined`.\n */\nexport function agentRunsDurationProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.duration', (metrics) => ({\n buckets: [],\n ...(metrics.durationP50Ms !== null ? { p50: metrics.durationP50Ms } : {}),\n ...(metrics.durationP95Ms !== null ? { p95: metrics.durationP95Ms } : {}),\n }));\n}\n\n/** table → run/failure/retry rollup per agent. */\nexport function agentRunsByAgentTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.byAgent',\n (queries, range) => queries.runsByAgent(range),\n (rows) => ({ rows: toRunAgentTableRows(rows) }),\n );\n}\n\n/** breakdown → failed runs by error code. */\nexport function agentRunErrorsProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.errors',\n (queries, range) => queries.runErrors(range),\n (rows) => ({ segments: toRunErrorSegments(rows) }),\n );\n}\n\n/** timeseries → daily runs + failures trend. */\nexport function agentRunsTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.trend',\n (queries, range) => queries.runTrend(range),\n (points) => ({ rows: toRunTrendRows(points) }),\n );\n}\n\n// ─── Limit-scoped providers (recent-activity feeds + the approvals inbox) ────\n\n/** Default row count for a \"recent …\" feed when a panel's query omits `limit`. */\nconst DEFAULT_RECENT_LIMIT = 50;\n/** Hard ceiling on `limit`, regardless of what a panel's query requests. */\nconst MAX_RECENT_LIMIT = 500;\n\n/** Clamp a panel-supplied `limit` into `[1, MAX_RECENT_LIMIT]`, defaulting when absent/invalid. */\nfunction resolveLimit(query: Record<string, unknown> | undefined, fallback: number): number {\n const raw = query?.limit;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : fallback;\n return Math.min(MAX_RECENT_LIMIT, Math.max(1, Math.trunc(value)));\n}\n\n/**\n * Build a governance `DataProvider` from a `limit`-scoped fetch + a format step — the sibling of\n * {@link governanceStatProvider} for the read-model's \"recent N\" queries, which take a row cap\n * instead of a day range. Degrades to `[]` when the read-model isn't bound.\n */\nfunction governanceLimitProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, limit: number) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveLimit(query, defaultLimit)) : [];\n return format(rows);\n },\n };\n}\n\n/**\n * table → most recent runs (newest first), errorMessage capped and promptHash shortened to a chip\n * — see {@link capErrorMessage} for why the cap happens here rather than downstream.\n */\nexport function agentRecentRunsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.runs.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentRuns(limit),\n (rows) => ({ rows: toRecentRunTableRows(rows) }),\n );\n}\n\n/**\n * table → most recent tool calls (newest first), from the durable read-model. Replaces the\n * ephemeral, watcher-fed `agent.tools` provider in `agent-data-providers.ts` for the shipped\n * dashboard — see that file's header comment for why.\n */\nexport function agentRecentToolCallsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.tools.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentToolCalls(limit),\n (rows) => ({ rows: toRecentToolCallRows(rows) }),\n );\n}\n\n/** table → most recently active threads, with rolled-up message/token counts. */\nexport function agentRecentThreadsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.threads.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentThreads(limit),\n (rows) => ({ rows: toRecentThreadTableRows(rows) }),\n );\n}\n\n/** Row cap used to approximate a \"pending approvals\" COUNT (the SPI only exposes a capped list —\n * see {@link agentPendingApprovalsCountProvider}). */\nconst PENDING_APPROVALS_COUNT_LIMIT = 500;\n\n/**\n * stat → count of tool calls sitting `pending_approval` across every thread. The SPI's\n * `pendingApprovals` only returns a capped list, not a true count, so this undercounts a backlog\n * larger than {@link PENDING_APPROVALS_COUNT_LIMIT} — a backlog that size signals a bigger\n * operational problem than an off-by-N stat, so the approximation is an acceptable tradeoff.\n */\nexport function agentPendingApprovalsCountProvider(): DataProvider {\n return {\n name: 'agent.approvals.pending',\n async resolve(_query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await queries.pendingApprovals(PENDING_APPROVALS_COUNT_LIMIT) : [];\n return { value: rows.length };\n },\n };\n}\n\n/** table → the pending-approvals inbox, oldest request first. */\nexport function agentPendingApprovalsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.approvals.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.pendingApprovals(limit),\n (rows) => ({ rows: toPendingApprovalTableRows(rows) }),\n );\n}\n\n/** table → per-tool call/failure/rejection/latency rollup over the range. */\nexport function agentToolStatsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.tools.stats',\n (queries, range) => queries.toolStats(range),\n (rows) => ({ rows: toToolStatTableRows(rows) }),\n );\n}\n","import { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport { AGENT_DIAGNOSTIC_EVENTS } from '@dudousxd/nestjs-agent-core';\nimport { channelName } from '@dudousxd/nestjs-diagnostics';\nimport type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';\n\ninterface DiagnosticEnvelope {\n event: string;\n payload: Record<string, unknown>;\n}\n\n/**\n * Records `aviary:agent:*` diagnostics events as Telescope entries of type `agent`. It depends\n * only on the diagnostics channel — not on the agent runtime — so it stays fully decoupled.\n *\n * Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 events on `ChannelRegistry['agent']`) rather\n * than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and tagged —\n * filterable in the Telescope UI — like every other agent event.\n *\n * **Superseded by `@dudousxd/nestjs-diagnostics-telescope`'s generic watcher,** which\n * auto-captures every `aviary:agent:*` channel registered in the diagnostics registry — prefer\n * that when the generic bridge is already in use; pass `agentDiagnosticKey(event)` keys to its\n * `exclude` option to mute a noisy one. This watcher is kept for standalone use without the\n * diagnostics telescope bridge.\n *\n * Register it with the telescope module's watcher list.\n */\nexport class AgentTelescopeWatcher implements Watcher {\n readonly type = 'agent';\n private readonly disposers: Array<() => void> = [];\n\n register(ctx: WatcherContext): void {\n for (const event of AGENT_DIAGNOSTIC_EVENTS) {\n const channel = channelName('agent', event);\n const onMessage = (message: unknown) => {\n const envelope = message as DiagnosticEnvelope;\n ctx.record({\n type: 'agent',\n content: { event: envelope.event, ...envelope.payload },\n tags: [envelope.event],\n });\n };\n subscribe(channel, onMessage);\n this.disposers.push(() => unsubscribe(channel, onMessage));\n }\n }\n\n /** Detach all channel subscriptions (e.g. on module destroy). */\n dispose(): void {\n while (this.disposers.length) this.disposers.pop()?.();\n }\n}\n"],"mappings":"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","names":["import_nestjs_telescope","col","key","label","href","undefined","link","agentDashboard","opts","id","panels","sections","title","cols","kind","data","provider","format","series","style","markers","columns","runHref","threadHref","fetchEntries","ctx","storage","moduleRef","get","TELESCOPE_STORAGE","strict","page","type","limit","data","ofEvent","entries","event","filter","entry","content","agentRunsProvider","name","resolve","_query","finished","value","length","agentTokensProvider","reduce","sum","inputTokens","outputTokens","agentToolsProvider","calls","slice","reverse","map","toolName","toolType","status","runId","rows","agentToolStatusProvider","counts","Map","call","set","segments","label","DEFAULT_TREND_WINDOW_DAYS","ISO_DAY_PATTERN","TOP_THREADS_LIMIT","isRecord","value","isGovernanceQueries","spendByModel","spendByActor","spendByThread","usageTrend","recentToolCalls","recentThreads","runMetrics","runsByAgent","runErrors","runTrend","recentRuns","pendingApprovals","toolStats","resolveGovernanceQueries","ctx","resolved","moduleRef","get","AGENT_GOVERNANCE_QUERIES","strict","isIsoDay","test","todayUtcDay","Date","toISOString","slice","shiftUtcDay","day","deltaDays","shifted","setUTCDate","getUTCDate","resolveRange","query","toDay","fromDay","roundCents","Math","round","totalCostUsd","rows","reduce","sum","row","costUsd","totalTokens","inputTokens","outputTokens","toModelSpendSegments","filter","map","label","modelId","toModelSpendRows","requests","toActorSpendRows","actorRef","toThreadSpendRows","title","threadId","toActorSpendSegments","toUsageTrendRows","points","point","NO_VALUE","toRunAgentTableRows","agentName","runs","failed","retries","toRunErrorSegments","errorCode","count","toRunTrendRows","ERROR_MESSAGE_CAP","capErrorMessage","message","length","PROMPT_HASH_CHIP_LENGTH","shortPromptHash","promptHash","toRecentRunTableRows","startedAt","runId","status","durationMs","errorMessage","toRecentToolCallRows","toRecentThreadTableRows","toPendingApprovalTableRows","toolCallId","toolName","threadTitle","requestedAt","toToolStatTableRows","toolType","calls","rejected","p95ExecutionMs","EMPTY_RUN_METRICS","completed","successRate","durationP50Ms","durationP95Ms","governanceStatProvider","name","fetch","format","resolve","queries","agentSpendTotalProvider","range","agentTokensTotalProvider","agentSpendByModelProvider","segments","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","governanceRunMetricsProvider","metrics","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","buckets","p50","p95","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","DEFAULT_RECENT_LIMIT","MAX_RECENT_LIMIT","resolveLimit","fallback","raw","limit","Number","isFinite","min","max","trunc","governanceLimitProvider","defaultLimit","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","PENDING_APPROVALS_COUNT_LIMIT","agentPendingApprovalsCountProvider","_query","agentPendingApprovalsTableProvider","agentToolStatsTableProvider","import_nestjs_agent_core","AgentTelescopeWatcher","type","disposers","register","ctx","event","AGENT_DIAGNOSTIC_EVENTS","channel","channelName","onMessage","message","envelope","record","content","payload","tags","subscribe","push","unsubscribe","dispose","length","pop","agentTelescopeExtension","opts","defineTelescopeExtension","name","watchers","AgentTelescopeWatcher","entryTypes","id","label","dot","dashboards","agentDashboard","dataProviders","agentRunsProvider","agentTokensProvider","agentToolStatusProvider","agentSpendTotalProvider","agentTokensTotalProvider","agentSpendByModelProvider","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentPendingApprovalsCountProvider","agentPendingApprovalsTableProvider","agentToolStatsTableProvider"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/agent-telescope.extension.ts","../src/agent-dashboard.spec-data.ts","../src/agent-data-providers.ts","../src/agent-governance-providers.ts","../src/agent-telescope.watcher.ts"],"sourcesContent":["export { agentTelescopeExtension } from './agent-telescope.extension.js';\nexport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\nexport { agentDashboard } from './agent-dashboard.spec-data.js';\nexport {\n agentRunsProvider,\n agentTokensProvider,\n agentToolsProvider,\n agentToolStatusProvider,\n} from './agent-data-providers.js';\nexport {\n agentActorSpendTableProvider,\n agentModelSpendTableProvider,\n agentPendingApprovalsCountProvider,\n agentPendingApprovalsTableProvider,\n agentRecentRunsTableProvider,\n agentRecentThreadsTableProvider,\n agentRecentToolCallsTableProvider,\n agentRunErrorsProvider,\n agentRunsByAgentTableProvider,\n agentRunsDurationProvider,\n agentRunsFailedProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentTokensTotalProvider,\n agentToolStatsTableProvider,\n agentTopThreadsTableProvider,\n agentUsageTrendProvider,\n capErrorMessage,\n resolveRange,\n shiftUtcDay,\n shortPromptHash,\n toActorSpendRows,\n toActorSpendSegments,\n toModelSpendRows,\n toModelSpendSegments,\n toPendingApprovalTableRows,\n toRecentRunTableRows,\n toRecentThreadTableRows,\n toRecentToolCallRows,\n toRunAgentTableRows,\n toRunErrorSegments,\n toRunTrendRows,\n toThreadSpendRows,\n toToolStatTableRows,\n totalCostUsd,\n totalTokens,\n toUsageTrendRows,\n} from './agent-governance-providers.js';\n","import { defineTelescopeExtension } from '@dudousxd/nestjs-telescope';\nimport { agentDashboard } from './agent-dashboard.spec-data.js';\nimport {\n agentRunsProvider,\n agentTokensProvider,\n agentToolStatusProvider,\n} from './agent-data-providers.js';\nimport {\n agentActorSpendTableProvider,\n agentModelSpendTableProvider,\n agentPendingApprovalsCountProvider,\n agentPendingApprovalsTableProvider,\n agentRecentRunsTableProvider,\n agentRecentThreadsTableProvider,\n agentRecentToolCallsTableProvider,\n agentRunErrorsProvider,\n agentRunsByAgentTableProvider,\n agentRunsDurationProvider,\n agentRunsFailedProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentTokensTotalProvider,\n agentToolStatsTableProvider,\n agentTopThreadsTableProvider,\n agentUsageTrendProvider,\n} from './agent-governance-providers.js';\nimport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\n\n/**\n * The first-class Telescope extension for nestjs-agent: an \"Agent\" tab fed by two sources —\n * the `aviary:agent:*` diagnostics channel (live runs, tool calls) via the watcher, and the\n * authoritative `AGENT_GOVERNANCE_QUERIES` read-model (historical spend/usage, run reliability,\n * tool activity, the approvals inbox) via the governance providers. The extension `name`,\n * entry-type id, dashboard id, and every provider name share the `agent` prefix so the registry's\n * global-uniqueness namespaces never collide with sibling extensions.\n *\n * `threadHref`/`runHref` deep-link a table row's `threadId`/`runId` cell out to the host's own\n * thread/run viewer — passed straight through to {@link agentDashboard}, mirroring\n * `durableTelescopeExtension`'s `runHref` option.\n *\n * Host wiring: the governance panels (Spend/Models/Actors/Reliability/Runs/Threads/Approvals/Tool\n * stats/Recent tool calls) resolve `AGENT_GOVERNANCE_QUERIES` from the host DI container at\n * request time (via `ctx.moduleRef`). The host must bind that token — from its store adapter\n * (e.g. `store-mikro-orm` / `store-drizzle` / `testing`) — in the same module that registers\n * `TelescopeModule.forRoot({ extensions: [agentTelescopeExtension()] })`. If the binding is\n * absent, those panels render an empty state; the live watcher-fed panels (Runs/Tokens stats and\n * the Tool-call status breakdown) keep working regardless.\n */\nexport function agentTelescopeExtension(opts: { threadHref?: string; runHref?: string } = {}) {\n return defineTelescopeExtension({\n name: 'agent',\n watchers: () => [new AgentTelescopeWatcher()],\n entryTypes: () => [{ id: 'agent', label: 'Agent', dot: 'bg-violet-400' }],\n dashboards: () => [agentDashboard(opts)],\n dataProviders: () => [\n agentRunsProvider(),\n agentTokensProvider(),\n agentToolStatusProvider(),\n agentSpendTotalProvider(),\n agentTokensTotalProvider(),\n agentSpendByModelProvider(),\n agentModelSpendTableProvider(),\n agentUsageTrendProvider(),\n agentActorSpendTableProvider(),\n agentSpendByActorProvider(),\n agentTopThreadsTableProvider(),\n agentRunsTotalProvider(),\n agentRunsSuccessRateProvider(),\n agentRunsFailedProvider(),\n agentRunsRetriesProvider(),\n agentRunsDurationProvider(),\n agentRunsByAgentTableProvider(),\n agentRunErrorsProvider(),\n agentRunsTrendProvider(),\n agentRecentRunsTableProvider(),\n agentRecentToolCallsTableProvider(),\n agentRecentThreadsTableProvider(),\n agentPendingApprovalsCountProvider(),\n agentPendingApprovalsTableProvider(),\n agentToolStatsTableProvider(),\n ],\n });\n}\n","import type { Column, DashboardSpec } from '@dudousxd/nestjs-telescope';\n\n/** A plain column, or one carrying a `Column.link` to `href` when `href` is given. */\nfunction col(key: string, label: string, href?: string): Column {\n return href !== undefined ? { key, label, link: { href } } : { key, label };\n}\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref`/`runHref` are URL templates for deep-linking a `{threadId}`/`{runId}` cell out to\n * the host's own thread/run viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA),\n * mirroring `durableTelescopeExtension`'s `runHref` option. Every table whose rows carry a\n * `threadId`/`runId` gets a `Column.link` for it (via {@link col}); omit an option to leave that\n * column plain text.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n title: 'Overview',\n cols: 2,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n ],\n },\n {\n title: 'Reliability',\n cols: 4,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs.total' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n { kind: 'stat', title: 'Failed', data: { provider: 'agent.runs.failed' } },\n { kind: 'stat', title: 'Retries', data: { provider: 'agent.runs.retries' } },\n ],\n },\n {\n title: 'Run trends',\n cols: 4,\n panels: [\n {\n kind: 'timeseries',\n title: 'Runs & failures',\n data: { provider: 'agent.runs.trend' },\n series: ['runs', 'failed'],\n style: 'stacked',\n },\n // Two duration stats, not a `distribution` panel: RunMetrics carries only p50/p95 (no\n // raw samples to bucket), so a histogram here would be a permanently-empty box.\n {\n kind: 'stat',\n title: 'Duration p50',\n data: { provider: 'agent.runs.duration', query: { metric: 'p50' } },\n format: 'duration',\n },\n {\n kind: 'stat',\n title: 'Duration p95',\n data: { provider: 'agent.runs.duration', query: { metric: 'p95' } },\n format: 'duration',\n },\n {\n kind: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\n ],\n },\n {\n title: 'Runs',\n panels: [\n {\n kind: 'table',\n title: 'Runs by agent',\n data: { provider: 'agent.runs.byAgent' },\n columns: [\n { key: 'agentName', label: 'Agent' },\n { key: 'runs', label: 'Runs' },\n { key: 'failed', label: 'Failed' },\n { key: 'retries', label: 'Retries' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent runs',\n data: { provider: 'agent.runs.recent' },\n // A deliberate SUBSET of the provider's row shape: the full 11-field row overflows the\n // card horizontally. Thread/actor/retries/errorCode detail lives in the standalone\n // agent dashboard; the provider keeps returning the full row for other consumers.\n columns: [\n { key: 'startedAt', label: 'Started' },\n col('runId', 'Run', opts.runHref),\n { key: 'agentName', label: 'Agent' },\n { key: 'status', label: 'Status' },\n { key: 'durationMs', label: 'Duration (ms)' },\n { key: 'errorMessage', label: 'Error' },\n { key: 'promptHash', label: 'Prompt' },\n ],\n },\n ],\n },\n {\n title: 'Spend',\n cols: 2,\n panels: [\n {\n kind: 'stat',\n title: 'Total spend (USD)',\n data: { provider: 'agent.spend.totalCost' },\n format: 'number',\n },\n {\n kind: 'stat',\n title: 'Total tokens',\n data: { provider: 'agent.spend.totalTokens' },\n format: 'number',\n },\n {\n kind: 'breakdown',\n title: 'Spend by model',\n data: { provider: 'agent.spend.byModel' },\n style: 'donut',\n },\n {\n kind: 'timeseries',\n title: 'Daily spend & tokens',\n data: { provider: 'agent.usage.trend' },\n series: ['costUsd', 'totalTokens'],\n style: 'area',\n },\n ],\n },\n {\n title: 'Models',\n panels: [\n {\n kind: 'table',\n title: 'Usage & cost by model',\n data: { provider: 'agent.spend.byModelTable' },\n columns: [\n { key: 'modelId', label: 'Model' },\n { key: 'requests', label: 'Requests' },\n { key: 'inputTokens', label: 'Input tokens' },\n { key: 'outputTokens', label: 'Output tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Actors',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Spend share by actor',\n data: { provider: 'agent.spend.byActorShare' },\n style: 'bar',\n },\n {\n kind: 'table',\n title: 'Spend by actor',\n data: { provider: 'agent.spend.byActor' },\n columns: [\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Threads',\n cols: 2,\n panels: [\n {\n kind: 'table',\n title: 'Top threads by cost',\n data: { provider: 'agent.threads.topSpend' },\n columns: [\n { key: 'title', label: 'Thread' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n data: { provider: 'agent.threads.recent' },\n columns: [\n col('threadId', 'Thread', opts.threadHref),\n { key: 'title', label: 'Title' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'messageCount', label: 'Messages' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'lastActivityAt', label: 'Last activity' },\n ],\n },\n ],\n },\n {\n title: 'Approvals',\n cols: 3,\n panels: [\n {\n kind: 'stat',\n title: 'Pending approvals',\n data: { provider: 'agent.approvals.pending' },\n },\n {\n kind: 'table',\n title: 'Approvals inbox',\n data: { provider: 'agent.approvals.recent' },\n columns: [\n { key: 'requestedAt', label: 'Requested' },\n { key: 'toolName', label: 'Tool' },\n { key: 'threadTitle', label: 'Thread' },\n col('threadId', 'Thread id', opts.threadHref),\n { key: 'actorRef', label: 'Actor' },\n { key: 'agentName', label: 'Agent' },\n ],\n },\n ],\n },\n {\n title: 'Tools',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Tool-call status',\n data: { provider: 'agent.toolStatus' },\n style: 'donut',\n },\n {\n kind: 'table',\n title: 'Tool stats',\n data: { provider: 'agent.tools.stats' },\n columns: [\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'calls', label: 'Calls' },\n { key: 'failed', label: 'Failed' },\n { key: 'rejected', label: 'Rejected' },\n { key: 'p95ExecutionMs', label: 'p95 (ms)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent tool calls',\n data: { provider: 'agent.tools.recent' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n ],\n },\n ],\n };\n}\n","import type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\nimport { TELESCOPE_STORAGE } from '@dudousxd/nestjs-telescope';\n\ninterface AgentEntryContent {\n event: string;\n runId?: string;\n threadId?: string;\n toolName?: string;\n toolType?: string;\n status?: string;\n steps?: number;\n inputTokens?: number;\n outputTokens?: number;\n}\n\ninterface StorageEntry {\n content?: AgentEntryContent;\n createdAt?: Date;\n}\n\nasync function fetchEntries(ctx: ExtensionContext): Promise<StorageEntry[]> {\n const storage = ctx.moduleRef.get(TELESCOPE_STORAGE, { strict: false }) as {\n get(query: { type?: string; limit?: number }): Promise<{ data: StorageEntry[] }>;\n };\n const page = await storage.get({ type: 'agent', limit: 5_000 });\n return page.data;\n}\n\nfunction ofEvent(entries: StorageEntry[], event: string): StorageEntry[] {\n return entries.filter((entry) => entry.content?.event === event);\n}\n\n/** stat → total agent runs (run.finished entries). */\nexport function agentRunsProvider(): DataProvider {\n return {\n name: 'agent.runs',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n return { value: finished.length };\n },\n };\n}\n\n/** stat → total tokens across all finished runs. */\nexport function agentTokensProvider(): DataProvider {\n return {\n name: 'agent.tokens',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n const value = finished.reduce(\n (sum, entry) =>\n sum + (entry.content?.inputTokens ?? 0) + (entry.content?.outputTokens ?? 0),\n 0,\n );\n return { value };\n },\n };\n}\n\n/**\n * table → recent tool calls, from Telescope's own ephemeral event storage.\n *\n * @deprecated Superseded in the shipped dashboard by `agentRecentToolCallsTableProvider`\n * (`agent.tools.recent`, in `agent-governance-providers.ts`), which reads the durable,\n * restart-surviving `AGENT_GOVERNANCE_QUERIES.recentToolCalls` read-model. That durable route is\n * never behind this ephemeral one: `agent-loop.ts` always awaits `store.recordToolCall` /\n * `store.updateToolCall` (the durable write) BEFORE calling `publishAgentToolCall` (the event this\n * provider reads), so a row is durably queryable strictly before the ephemeral entry exists. The\n * durable route also captures the `pending_approval` state this ephemeral channel never emits at\n * all (no `publishAgentToolCall` call sits between `recordToolCall(status: 'pending_approval')`\n * and the eventual terminal transition) — so there's no in-flight state left for this table to\n * uniquely show. Kept exported (not removed — that would be a breaking export change) for hosts\n * that use `agentTelescopeExtension()` without wiring `AGENT_GOVERNANCE_QUERIES`, or that compose\n * a custom extension from these lower-level provider functions directly.\n */\nexport function agentToolsProvider(): DataProvider {\n return {\n name: 'agent.tools',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call')\n .slice(-50)\n .reverse()\n .map((entry) => ({\n toolName: entry.content?.toolName ?? '',\n toolType: entry.content?.toolType ?? '',\n status: entry.content?.status ?? '',\n runId: entry.content?.runId ?? '',\n }));\n return { rows: calls };\n },\n };\n}\n\n/** breakdown → tool-call status distribution. */\nexport function agentToolStatusProvider(): DataProvider {\n return {\n name: 'agent.toolStatus',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call');\n const counts = new Map<string, number>();\n for (const call of calls) {\n const status = call.content?.status ?? 'unknown';\n counts.set(status, (counts.get(status) ?? 0) + 1);\n }\n return { segments: [...counts.entries()].map(([label, value]) => ({ label, value })) };\n },\n };\n}\n","import type {\n ActorSpendRow,\n AgentGovernanceQueries,\n GovernanceRange,\n ModelSpendRow,\n PendingApprovalRow,\n RecentRunRow,\n RunAgentBreakdownRow,\n RunErrorBreakdownRow,\n RunMetrics,\n RunTrendPoint,\n ThreadActivityRow,\n ThreadSpendRow,\n ToolCallActivityRow,\n ToolStatRow,\n UsageTrendPoint,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_GOVERNANCE_QUERIES } from '@dudousxd/nestjs-agent-core';\nimport type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\n\n/**\n * Governance data providers for the \"Agent\" Telescope tab: spend/usage, run reliability, tool\n * activity, and the cross-thread approvals inbox. Unlike the live watcher-fed providers in\n * `agent-data-providers.ts` (which read the ephemeral Telescope event storage), these read the\n * authoritative, restart-surviving read-model: `AGENT_GOVERNANCE_QUERIES` (usage ⋈ pricing, plus\n * run/tool-call/thread history).\n *\n * The read-model is resolved from the host's DI container via `ctx.moduleRef` — the exact same\n * mechanism the existing providers use for `TELESCOPE_STORAGE`. The host must bind\n * `AGENT_GOVERNANCE_QUERIES` (from its store adapter) in the same module that registers Telescope;\n * when the binding is absent every provider degrades to an empty-but-valid shape rather than throwing.\n */\n\n/** Default trailing window (in days, inclusive) when a panel query omits an explicit range. */\nconst DEFAULT_TREND_WINDOW_DAYS = 30;\n\nconst ISO_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** A breakdown-panel segment (Telescope core: `{ segments: Array<{ label, value, color? }> }`). */\ninterface BreakdownSegment {\n label: string;\n value: number;\n}\n\n/** One row of the per-model usage/cost table. */\ninterface ModelSpendTableRow {\n modelId: string;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\n/** One row of the per-actor spend table. */\ninterface ActorSpendTableRow {\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** One row of the top-threads-by-cost table. */\ninterface ThreadSpendTableRow {\n title: string;\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** Top threads by cost within the range, capped to this count. */\nconst TOP_THREADS_LIMIT = 10;\n\n/** One point of the timeseries trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface UsageTrendTableRow {\n label: string;\n costUsd: number;\n totalTokens: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Structural guard so the DI-resolved binding is narrowed without an `as`/`any` cast. */\nfunction isGovernanceQueries(value: unknown): value is AgentGovernanceQueries {\n return (\n isRecord(value) &&\n typeof value.spendByModel === 'function' &&\n typeof value.spendByActor === 'function' &&\n typeof value.spendByThread === 'function' &&\n typeof value.usageTrend === 'function' &&\n typeof value.recentToolCalls === 'function' &&\n typeof value.recentThreads === 'function' &&\n typeof value.runMetrics === 'function' &&\n typeof value.runsByAgent === 'function' &&\n typeof value.runErrors === 'function' &&\n typeof value.runTrend === 'function' &&\n typeof value.recentRuns === 'function' &&\n typeof value.pendingApprovals === 'function' &&\n typeof value.toolStats === 'function'\n );\n}\n\n/**\n * Resolve the governance read-model from the host container. Returns `null` when the host has not\n * bound `AGENT_GOVERNANCE_QUERIES` (missing token throws inside `moduleRef.get`) so panels can render\n * an empty state instead of erroring.\n */\nfunction resolveGovernanceQueries(ctx: ExtensionContext): AgentGovernanceQueries | null {\n let resolved: unknown;\n try {\n resolved = ctx.moduleRef.get(AGENT_GOVERNANCE_QUERIES, { strict: false });\n } catch {\n return null;\n }\n return isGovernanceQueries(resolved) ? resolved : null;\n}\n\nfunction isIsoDay(value: unknown): value is string {\n return typeof value === 'string' && ISO_DAY_PATTERN.test(value);\n}\n\nfunction todayUtcDay(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Shift a `YYYY-MM-DD` UTC day by `deltaDays` (negative goes back in time). */\nexport function shiftUtcDay(day: string, deltaDays: number): string {\n const shifted = new Date(`${day}T00:00:00.000Z`);\n shifted.setUTCDate(shifted.getUTCDate() + deltaDays);\n return shifted.toISOString().slice(0, 10);\n}\n\n/**\n * Derive the query range: honour explicit `fromDay`/`toDay` (validated ISO days), otherwise default\n * to the trailing {@link DEFAULT_TREND_WINDOW_DAYS}-day window ending today (UTC).\n */\nexport function resolveRange(query: Record<string, unknown> | undefined): GovernanceRange {\n const toDay = query && isIsoDay(query.toDay) ? query.toDay : todayUtcDay();\n const fromDay =\n query && isIsoDay(query.fromDay)\n ? query.fromDay\n : shiftUtcDay(toDay, -(DEFAULT_TREND_WINDOW_DAYS - 1));\n return { fromDay, toDay };\n}\n\nfunction roundCents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/** Sum authoritative spend across every model row. */\nexport function totalCostUsd(rows: ModelSpendRow[]): number {\n return roundCents(rows.reduce((sum, row) => sum + row.costUsd, 0));\n}\n\n/** Sum input + output tokens across every model row. */\nexport function totalTokens(rows: ModelSpendRow[]): number {\n return rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);\n}\n\n/** Spend-by-model as breakdown segments (models with zero cost are dropped from the donut). */\nexport function toModelSpendSegments(rows: ModelSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.modelId, value: roundCents(row.costUsd) }));\n}\n\n/** Spend-by-model as table rows (cost rounded to cents; usage kept exact). */\nexport function toModelSpendRows(rows: ModelSpendRow[]): ModelSpendTableRow[] {\n return rows.map((row) => ({\n modelId: row.modelId,\n requests: row.requests,\n inputTokens: row.inputTokens,\n outputTokens: row.outputTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as table rows. */\nexport function toActorSpendRows(rows: ActorSpendRow[]): ActorSpendTableRow[] {\n return rows.map((row) => ({\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Top-threads-by-cost as table rows. */\nexport function toThreadSpendRows(rows: ThreadSpendRow[]): ThreadSpendTableRow[] {\n return rows.map((row) => ({\n title: row.title || row.threadId,\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as breakdown segments (actors with zero cost are dropped). */\nexport function toActorSpendSegments(rows: ActorSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.actorRef, value: roundCents(row.costUsd) }));\n}\n\n/** Daily usage trend as timeseries rows keyed by `label` (the day). */\nexport function toUsageTrendRows(points: UsageTrendPoint[]): UsageTrendTableRow[] {\n return points.map((point) => ({\n label: point.day,\n costUsd: roundCents(point.costUsd),\n totalTokens: point.totalTokens,\n }));\n}\n\n// ─── Run reliability + tools + approvals shaping ─────────────────────────────\n\n/** Placeholder shown for a table cell whose source value is `null`/unmeasured — matches the\n * convention `@dudousxd/nestjs-durable-telescope` uses for the same case (e.g. `fmtNum`). */\nconst NO_VALUE = '—';\n\n/** Run/failure/retry rollup as table rows — `RunAgentBreakdownRow` is already table-shaped. */\nexport function toRunAgentTableRows(\n rows: RunAgentBreakdownRow[],\n): Array<{ agentName: string; runs: number; failed: number; retries: number }> {\n return rows.map((row) => ({\n agentName: row.agentName,\n runs: row.runs,\n failed: row.failed,\n retries: row.retries,\n }));\n}\n\n/** Failed-run counts by error code as breakdown segments. */\nexport function toRunErrorSegments(rows: RunErrorBreakdownRow[]): BreakdownSegment[] {\n return rows.map((row) => ({ label: row.errorCode, value: row.count }));\n}\n\n/** One point of the run/failure trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface RunTrendTableRow {\n label: string;\n runs: number;\n failed: number;\n}\n\n/** Daily run/failure trend as timeseries rows keyed by `label` (the day). */\nexport function toRunTrendRows(points: RunTrendPoint[]): RunTrendTableRow[] {\n return points.map((point) => ({ label: point.day, runs: point.runs, failed: point.failed }));\n}\n\n/** Cap this many characters before a byte length; matches the DB column's practical display width. */\nconst ERROR_MESSAGE_CAP = 500;\n\n/**\n * Cap a run's error message to {@link ERROR_MESSAGE_CAP} characters before it leaves the provider.\n * `DataProvider.resolve` output bypasses Telescope core's `redact()` pipeline — that only runs on\n * entries a `Watcher` records via `ctx.record`, not on values a provider computes and returns\n * directly to a panel — so an unbounded stack trace or secret-laden failure message would ride\n * straight into a table cell with no truncation/redaction safety net. This cap is a stopgap\n * mitigation, not a substitute for the (out-of-scope this wave) telescope-core redaction hook for\n * DataProvider output.\n */\nexport function capErrorMessage(message: string | null): string | null {\n if (message === null) return null;\n return message.length > ERROR_MESSAGE_CAP ? `${message.slice(0, ERROR_MESSAGE_CAP)}…` : message;\n}\n\n/** How many leading hex characters of a promptHash the table shows as a short chip. */\nconst PROMPT_HASH_CHIP_LENGTH = 10;\n\n/** Shorten a full sha256 promptHash to a compact chip for the table column. */\nexport function shortPromptHash(promptHash: string | null): string | null {\n return promptHash === null ? null : promptHash.slice(0, PROMPT_HASH_CHIP_LENGTH);\n}\n\n/** One row of the recent-runs table — every nullable field falls back to {@link NO_VALUE}. */\ninterface RecentRunTableRow {\n startedAt: string;\n runId: string;\n threadId: string;\n actorRef: string;\n agentName: string;\n status: string;\n durationMs: number | string;\n retries: number;\n errorCode: string;\n errorMessage: string;\n promptHash: string;\n}\n\n/** Recent runs as table rows: errorMessage capped, promptHash shortened to a chip. */\nexport function toRecentRunTableRows(rows: RecentRunRow[]): RecentRunTableRow[] {\n return rows.map((row) => ({\n startedAt: row.startedAt,\n runId: row.runId,\n threadId: row.threadId,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n status: row.status,\n durationMs: row.durationMs ?? NO_VALUE,\n retries: row.retries,\n errorCode: row.errorCode ?? NO_VALUE,\n errorMessage: capErrorMessage(row.errorMessage) ?? NO_VALUE,\n promptHash: shortPromptHash(row.promptHash) ?? NO_VALUE,\n }));\n}\n\n/** Recent tool calls as table rows — `ToolCallActivityRow` is already table-shaped. */\nexport function toRecentToolCallRows(rows: ToolCallActivityRow[]): ToolCallActivityRow[] {\n return rows;\n}\n\n/** Recent threads as table rows — `ThreadActivityRow` is already table-shaped. */\nexport function toRecentThreadTableRows(rows: ThreadActivityRow[]): ThreadActivityRow[] {\n return rows;\n}\n\n/** One row of the pending-approvals inbox table, `input` stringified for display. */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n}\n\n/** Pending-approvals rows as table rows (drops the raw `input` — not renderable in a table cell). */\nexport function toPendingApprovalTableRows(rows: PendingApprovalRow[]): PendingApprovalTableRow[] {\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n requestedAt: row.requestedAt,\n }));\n}\n\n/** One row of the per-tool stats table, `p95ExecutionMs` falling back to {@link NO_VALUE}. */\ninterface ToolStatTableRow {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n p95ExecutionMs: number | string;\n}\n\n/** Per-tool call/failure/rejection/latency rollup as table rows. */\nexport function toToolStatTableRows(rows: ToolStatRow[]): ToolStatTableRow[] {\n return rows.map((row) => ({\n toolName: row.toolName,\n toolType: row.toolType,\n calls: row.calls,\n failed: row.failed,\n rejected: row.rejected,\n p95ExecutionMs: row.p95ExecutionMs ?? NO_VALUE,\n }));\n}\n\n/** Zero-valued `RunMetrics`, returned when the read-model isn't bound. */\nconst EMPTY_RUN_METRICS: RunMetrics = {\n runs: 0,\n completed: 0,\n failed: 0,\n successRate: 0,\n retries: 0,\n durationP50Ms: null,\n durationP95Ms: null,\n};\n\n/**\n * Build a governance `DataProvider` from a fetch + a format step. Every provider follows the same\n * shape: resolve the read-model, run ONE query over the panel's range, then format the rows into the\n * panel's result shape. When the host hasn't bound the read-model, `fetch` is skipped and `format`\n * runs over `[]` — which is exactly the empty-but-valid shape each formatter already yields (0 for\n * totals, `[]` for segments/rows), so the degraded case needs no special-casing.\n */\nfunction governanceStatProvider<TRow>(\n name: string,\n fetch: (queries: AgentGovernanceQueries, range: GovernanceRange) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveRange(query)) : [];\n return format(rows);\n },\n };\n}\n\n/** stat → authoritative total spend (USD) over the range. */\nexport function agentSpendTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalCost',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalCostUsd(rows) }),\n );\n}\n\n/** stat → authoritative total tokens (input + output) over the range. */\nexport function agentTokensTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalTokens',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalTokens(rows) }),\n );\n}\n\n/** breakdown → spend share per model. */\nexport function agentSpendByModelProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModel',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ segments: toModelSpendSegments(rows) }),\n );\n}\n\n/** table → per-model requests / in+out tokens / cost. */\nexport function agentModelSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModelTable',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ rows: toModelSpendRows(rows) }),\n );\n}\n\n/** timeseries → daily spend + tokens trend. */\nexport function agentUsageTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.usage.trend',\n (queries, range) => queries.usageTrend(range),\n (points) => ({ rows: toUsageTrendRows(points) }),\n );\n}\n\n/** table → spend per acting ref (user/tenant). */\nexport function agentActorSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActor',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ rows: toActorSpendRows(rows) }),\n );\n}\n\n/** breakdown → spend share per actor. */\nexport function agentSpendByActorProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActorShare',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ segments: toActorSpendSegments(rows) }),\n );\n}\n\n/** table → top threads by cost (title, actor, requests, tokens, cost). */\nexport function agentTopThreadsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.threads.topSpend',\n (queries, range) => queries.spendByThread(range, TOP_THREADS_LIMIT),\n (rows) => ({ rows: toThreadSpendRows(rows) }),\n );\n}\n\n// ─── Reliability providers ────────────────────────────────────────────────────\n\n/**\n * Build a `DataProvider` from ONE range-scoped `runMetrics` call + a format step — the\n * `governanceStatProvider` pattern specialized for the single-object `RunMetrics` shape (the five\n * reliability stats all reuse the same underlying query, exactly like the spend stats above reuse\n * `spendByModel`). Degrades to {@link EMPTY_RUN_METRICS} when the read-model isn't bound.\n */\nfunction governanceRunMetricsProvider(\n name: string,\n format: (metrics: RunMetrics) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;\n return format(metrics);\n },\n };\n}\n\n/** stat → total runs over the range. */\nexport function agentRunsTotalProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.total', (metrics) => ({ value: metrics.runs }));\n}\n\n/** stat → completed/total success rate over the range. */\nexport function agentRunsSuccessRateProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.successRate', (metrics) => ({\n value: metrics.successRate,\n }));\n}\n\n/** stat → failed run count over the range. */\nexport function agentRunsFailedProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.failed', (metrics) => ({\n value: metrics.failed,\n }));\n}\n\n/** stat → total llm-step retries across the range's runs. */\nexport function agentRunsRetriesProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.retries', (metrics) => ({\n value: metrics.retries,\n }));\n}\n\n/**\n * stat → run duration percentile, selected by `query.metric` (`'p95'` for p95, anything else —\n * including omitted — for p50), mirroring `durable.duration`'s stat shortcut. NOT a\n * `distribution` panel: `RunMetrics` exposes only the two percentiles (no raw per-run samples to\n * bucket into a histogram), so a distribution here would render as a permanently-empty box. A\n * `null` percentile (no settled runs in range) resolves to 0.\n */\nexport function agentRunsDurationProvider(): DataProvider {\n return {\n name: 'agent.runs.duration',\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;\n const value = query?.metric === 'p95' ? metrics.durationP95Ms : metrics.durationP50Ms;\n return { value: value ?? 0 };\n },\n };\n}\n\n/** table → run/failure/retry rollup per agent. */\nexport function agentRunsByAgentTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.byAgent',\n (queries, range) => queries.runsByAgent(range),\n (rows) => ({ rows: toRunAgentTableRows(rows) }),\n );\n}\n\n/** breakdown → failed runs by error code. */\nexport function agentRunErrorsProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.errors',\n (queries, range) => queries.runErrors(range),\n (rows) => ({ segments: toRunErrorSegments(rows) }),\n );\n}\n\n/** timeseries → daily runs + failures trend. */\nexport function agentRunsTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.trend',\n (queries, range) => queries.runTrend(range),\n (points) => ({ rows: toRunTrendRows(points) }),\n );\n}\n\n// ─── Limit-scoped providers (recent-activity feeds + the approvals inbox) ────\n\n/** Default row count for a \"recent …\" feed when a panel's query omits `limit`. */\nconst DEFAULT_RECENT_LIMIT = 50;\n/** Hard ceiling on `limit`, regardless of what a panel's query requests. */\nconst MAX_RECENT_LIMIT = 500;\n\n/** Clamp a panel-supplied `limit` into `[1, MAX_RECENT_LIMIT]`, defaulting when absent/invalid. */\nfunction resolveLimit(query: Record<string, unknown> | undefined, fallback: number): number {\n const raw = query?.limit;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : fallback;\n return Math.min(MAX_RECENT_LIMIT, Math.max(1, Math.trunc(value)));\n}\n\n/**\n * Build a governance `DataProvider` from a `limit`-scoped fetch + a format step — the sibling of\n * {@link governanceStatProvider} for the read-model's \"recent N\" queries, which take a row cap\n * instead of a day range. Degrades to `[]` when the read-model isn't bound.\n */\nfunction governanceLimitProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, limit: number) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveLimit(query, defaultLimit)) : [];\n return format(rows);\n },\n };\n}\n\n/**\n * table → most recent runs (newest first), errorMessage capped and promptHash shortened to a chip\n * — see {@link capErrorMessage} for why the cap happens here rather than downstream.\n */\nexport function agentRecentRunsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.runs.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentRuns(limit),\n (rows) => ({ rows: toRecentRunTableRows(rows) }),\n );\n}\n\n/**\n * table → most recent tool calls (newest first), from the durable read-model. Replaces the\n * ephemeral, watcher-fed `agent.tools` provider in `agent-data-providers.ts` for the shipped\n * dashboard — see that file's header comment for why.\n */\nexport function agentRecentToolCallsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.tools.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentToolCalls(limit),\n (rows) => ({ rows: toRecentToolCallRows(rows) }),\n );\n}\n\n/** table → most recently active threads, with rolled-up message/token counts. */\nexport function agentRecentThreadsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.threads.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentThreads(limit),\n (rows) => ({ rows: toRecentThreadTableRows(rows) }),\n );\n}\n\n/** Row cap used to approximate a \"pending approvals\" COUNT (the SPI only exposes a capped list —\n * see {@link agentPendingApprovalsCountProvider}). */\nconst PENDING_APPROVALS_COUNT_LIMIT = 500;\n\n/**\n * stat → count of tool calls sitting `pending_approval` across every thread. The SPI's\n * `pendingApprovals` only returns a capped list, not a true count, so this undercounts a backlog\n * larger than {@link PENDING_APPROVALS_COUNT_LIMIT} — a backlog that size signals a bigger\n * operational problem than an off-by-N stat, so the approximation is an acceptable tradeoff.\n */\nexport function agentPendingApprovalsCountProvider(): DataProvider {\n return {\n name: 'agent.approvals.pending',\n async resolve(_query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await queries.pendingApprovals(PENDING_APPROVALS_COUNT_LIMIT) : [];\n return { value: rows.length };\n },\n };\n}\n\n/** table → the pending-approvals inbox, oldest request first. */\nexport function agentPendingApprovalsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.approvals.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.pendingApprovals(limit),\n (rows) => ({ rows: toPendingApprovalTableRows(rows) }),\n );\n}\n\n/** table → per-tool call/failure/rejection/latency rollup over the range. */\nexport function agentToolStatsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.tools.stats',\n (queries, range) => queries.toolStats(range),\n (rows) => ({ rows: toToolStatTableRows(rows) }),\n );\n}\n","import { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport { AGENT_DIAGNOSTIC_EVENTS } from '@dudousxd/nestjs-agent-core';\nimport { channelName, claimDiagnostics } from '@dudousxd/nestjs-diagnostics';\nimport type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';\n\ninterface DiagnosticEnvelope {\n event: string;\n payload: Record<string, unknown>;\n}\n\n/**\n * Records `aviary:agent:*` diagnostics events as Telescope entries of type `agent`. It depends\n * only on the diagnostics channel — not on the agent runtime — so it stays fully decoupled.\n *\n * Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 point events on `ChannelRegistry['agent']`)\n * rather than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and\n * tagged — filterable in the Telescope UI — like every other agent event.\n *\n * Coexists with `@dudousxd/nestjs-diagnostics-telescope`'s generic watcher: `register()` CLAIMS\n * every recorded key via `claimDiagnostics('agent', ...)` (diagnostics 0.7+), so the generic\n * bridge skips them at record time instead of duplicating each event as a `diagnostic` entry —\n * no `exclude` wiring needed anymore. `dispose()` releases the claim.\n *\n * Register it with the telescope module's watcher list.\n */\nexport class AgentTelescopeWatcher implements Watcher {\n readonly type = 'agent';\n private readonly disposers: Array<() => void> = [];\n\n register(ctx: WatcherContext): void {\n // Tell the generic diagnostics bridge these keys are recorded here as typed `agent` entries,\n // so it skips them (refcounted; released in dispose()).\n this.disposers.push(claimDiagnostics('agent', AGENT_DIAGNOSTIC_EVENTS));\n for (const event of AGENT_DIAGNOSTIC_EVENTS) {\n const channel = channelName('agent', event);\n const onMessage = (message: unknown) => {\n const envelope = message as DiagnosticEnvelope;\n ctx.record({\n type: 'agent',\n content: { event: envelope.event, ...envelope.payload },\n tags: [envelope.event],\n });\n };\n subscribe(channel, onMessage);\n this.disposers.push(() => unsubscribe(channel, onMessage));\n }\n }\n\n /** Detach all channel subscriptions and release the diagnostics claim (e.g. on module destroy). */\n dispose(): void {\n while (this.disposers.length) this.disposers.pop()?.();\n }\n}\n"],"mappings":"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","names":["import_nestjs_telescope","col","key","label","href","undefined","link","agentDashboard","opts","id","panels","sections","title","cols","kind","data","provider","format","series","style","query","metric","columns","runHref","threadHref","fetchEntries","ctx","storage","moduleRef","get","TELESCOPE_STORAGE","strict","page","type","limit","data","ofEvent","entries","event","filter","entry","content","agentRunsProvider","name","resolve","_query","finished","value","length","agentTokensProvider","reduce","sum","inputTokens","outputTokens","agentToolsProvider","calls","slice","reverse","map","toolName","toolType","status","runId","rows","agentToolStatusProvider","counts","Map","call","set","segments","label","DEFAULT_TREND_WINDOW_DAYS","ISO_DAY_PATTERN","TOP_THREADS_LIMIT","isRecord","value","isGovernanceQueries","spendByModel","spendByActor","spendByThread","usageTrend","recentToolCalls","recentThreads","runMetrics","runsByAgent","runErrors","runTrend","recentRuns","pendingApprovals","toolStats","resolveGovernanceQueries","ctx","resolved","moduleRef","get","AGENT_GOVERNANCE_QUERIES","strict","isIsoDay","test","todayUtcDay","Date","toISOString","slice","shiftUtcDay","day","deltaDays","shifted","setUTCDate","getUTCDate","resolveRange","query","toDay","fromDay","roundCents","Math","round","totalCostUsd","rows","reduce","sum","row","costUsd","totalTokens","inputTokens","outputTokens","toModelSpendSegments","filter","map","label","modelId","toModelSpendRows","requests","toActorSpendRows","actorRef","toThreadSpendRows","title","threadId","toActorSpendSegments","toUsageTrendRows","points","point","NO_VALUE","toRunAgentTableRows","agentName","runs","failed","retries","toRunErrorSegments","errorCode","count","toRunTrendRows","ERROR_MESSAGE_CAP","capErrorMessage","message","length","PROMPT_HASH_CHIP_LENGTH","shortPromptHash","promptHash","toRecentRunTableRows","startedAt","runId","status","durationMs","errorMessage","toRecentToolCallRows","toRecentThreadTableRows","toPendingApprovalTableRows","toolCallId","toolName","threadTitle","requestedAt","toToolStatTableRows","toolType","calls","rejected","p95ExecutionMs","EMPTY_RUN_METRICS","completed","successRate","durationP50Ms","durationP95Ms","governanceStatProvider","name","fetch","format","resolve","queries","agentSpendTotalProvider","range","agentTokensTotalProvider","agentSpendByModelProvider","segments","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","governanceRunMetricsProvider","metrics","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","metric","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","DEFAULT_RECENT_LIMIT","MAX_RECENT_LIMIT","resolveLimit","fallback","raw","limit","Number","isFinite","min","max","trunc","governanceLimitProvider","defaultLimit","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","PENDING_APPROVALS_COUNT_LIMIT","agentPendingApprovalsCountProvider","_query","agentPendingApprovalsTableProvider","agentToolStatsTableProvider","import_nestjs_agent_core","AgentTelescopeWatcher","type","disposers","register","ctx","push","claimDiagnostics","AGENT_DIAGNOSTIC_EVENTS","event","channel","channelName","onMessage","message","envelope","record","content","payload","tags","subscribe","unsubscribe","dispose","length","pop","agentTelescopeExtension","opts","defineTelescopeExtension","name","watchers","AgentTelescopeWatcher","entryTypes","id","label","dot","dashboards","agentDashboard","dataProviders","agentRunsProvider","agentTokensProvider","agentToolStatusProvider","agentSpendTotalProvider","agentTokensTotalProvider","agentSpendByModelProvider","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentPendingApprovalsCountProvider","agentPendingApprovalsTableProvider","agentToolStatsTableProvider"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -31,15 +31,14 @@ declare function agentTelescopeExtension(opts?: {
|
|
|
31
31
|
* Records `aviary:agent:*` diagnostics events as Telescope entries of type `agent`. It depends
|
|
32
32
|
* only on the diagnostics channel — not on the agent runtime — so it stays fully decoupled.
|
|
33
33
|
*
|
|
34
|
-
* Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 events on `ChannelRegistry['agent']`)
|
|
35
|
-
* than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and
|
|
36
|
-
* filterable in the Telescope UI — like every other agent event.
|
|
34
|
+
* Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 point events on `ChannelRegistry['agent']`)
|
|
35
|
+
* rather than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and
|
|
36
|
+
* tagged — filterable in the Telescope UI — like every other agent event.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* `exclude`
|
|
42
|
-
* diagnostics telescope bridge.
|
|
38
|
+
* Coexists with `@dudousxd/nestjs-diagnostics-telescope`'s generic watcher: `register()` CLAIMS
|
|
39
|
+
* every recorded key via `claimDiagnostics('agent', ...)` (diagnostics 0.7+), so the generic
|
|
40
|
+
* bridge skips them at record time instead of duplicating each event as a `diagnostic` entry —
|
|
41
|
+
* no `exclude` wiring needed anymore. `dispose()` releases the claim.
|
|
43
42
|
*
|
|
44
43
|
* Register it with the telescope module's watcher list.
|
|
45
44
|
*/
|
|
@@ -47,7 +46,7 @@ declare class AgentTelescopeWatcher implements Watcher {
|
|
|
47
46
|
readonly type = "agent";
|
|
48
47
|
private readonly disposers;
|
|
49
48
|
register(ctx: WatcherContext): void;
|
|
50
|
-
/** Detach all channel subscriptions (e.g. on module destroy). */
|
|
49
|
+
/** Detach all channel subscriptions and release the diagnostics claim (e.g. on module destroy). */
|
|
51
50
|
dispose(): void;
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -243,10 +242,11 @@ declare function agentRunsFailedProvider(): DataProvider;
|
|
|
243
242
|
/** stat → total llm-step retries across the range's runs. */
|
|
244
243
|
declare function agentRunsRetriesProvider(): DataProvider;
|
|
245
244
|
/**
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
245
|
+
* stat → run duration percentile, selected by `query.metric` (`'p95'` for p95, anything else —
|
|
246
|
+
* including omitted — for p50), mirroring `durable.duration`'s stat shortcut. NOT a
|
|
247
|
+
* `distribution` panel: `RunMetrics` exposes only the two percentiles (no raw per-run samples to
|
|
248
|
+
* bucket into a histogram), so a distribution here would render as a permanently-empty box. A
|
|
249
|
+
* `null` percentile (no settled runs in range) resolves to 0.
|
|
250
250
|
*/
|
|
251
251
|
declare function agentRunsDurationProvider(): DataProvider;
|
|
252
252
|
/** table → run/failure/retry rollup per agent. */
|
package/dist/index.d.ts
CHANGED
|
@@ -31,15 +31,14 @@ declare function agentTelescopeExtension(opts?: {
|
|
|
31
31
|
* Records `aviary:agent:*` diagnostics events as Telescope entries of type `agent`. It depends
|
|
32
32
|
* only on the diagnostics channel — not on the agent runtime — so it stays fully decoupled.
|
|
33
33
|
*
|
|
34
|
-
* Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 events on `ChannelRegistry['agent']`)
|
|
35
|
-
* than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and
|
|
36
|
-
* filterable in the Telescope UI — like every other agent event.
|
|
34
|
+
* Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 point events on `ChannelRegistry['agent']`)
|
|
35
|
+
* rather than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and
|
|
36
|
+
* tagged — filterable in the Telescope UI — like every other agent event.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* `exclude`
|
|
42
|
-
* diagnostics telescope bridge.
|
|
38
|
+
* Coexists with `@dudousxd/nestjs-diagnostics-telescope`'s generic watcher: `register()` CLAIMS
|
|
39
|
+
* every recorded key via `claimDiagnostics('agent', ...)` (diagnostics 0.7+), so the generic
|
|
40
|
+
* bridge skips them at record time instead of duplicating each event as a `diagnostic` entry —
|
|
41
|
+
* no `exclude` wiring needed anymore. `dispose()` releases the claim.
|
|
43
42
|
*
|
|
44
43
|
* Register it with the telescope module's watcher list.
|
|
45
44
|
*/
|
|
@@ -47,7 +46,7 @@ declare class AgentTelescopeWatcher implements Watcher {
|
|
|
47
46
|
readonly type = "agent";
|
|
48
47
|
private readonly disposers;
|
|
49
48
|
register(ctx: WatcherContext): void;
|
|
50
|
-
/** Detach all channel subscriptions (e.g. on module destroy). */
|
|
49
|
+
/** Detach all channel subscriptions and release the diagnostics claim (e.g. on module destroy). */
|
|
51
50
|
dispose(): void;
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -243,10 +242,11 @@ declare function agentRunsFailedProvider(): DataProvider;
|
|
|
243
242
|
/** stat → total llm-step retries across the range's runs. */
|
|
244
243
|
declare function agentRunsRetriesProvider(): DataProvider;
|
|
245
244
|
/**
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
245
|
+
* stat → run duration percentile, selected by `query.metric` (`'p95'` for p95, anything else —
|
|
246
|
+
* including omitted — for p50), mirroring `durable.duration`'s stat shortcut. NOT a
|
|
247
|
+
* `distribution` panel: `RunMetrics` exposes only the two percentiles (no raw per-run samples to
|
|
248
|
+
* bucket into a histogram), so a distribution here would render as a permanently-empty box. A
|
|
249
|
+
* `null` percentile (no settled runs in range) resolves to 0.
|
|
250
250
|
*/
|
|
251
251
|
declare function agentRunsDurationProvider(): DataProvider;
|
|
252
252
|
/** table → run/failure/retry rollup per agent. */
|
package/dist/index.js
CHANGED
|
@@ -81,7 +81,7 @@ function agentDashboard(opts = {}) {
|
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
title: "Run trends",
|
|
84
|
-
cols:
|
|
84
|
+
cols: 4,
|
|
85
85
|
panels: [
|
|
86
86
|
{
|
|
87
87
|
kind: "timeseries",
|
|
@@ -95,16 +95,28 @@ function agentDashboard(opts = {}) {
|
|
|
95
95
|
],
|
|
96
96
|
style: "stacked"
|
|
97
97
|
},
|
|
98
|
+
// Two duration stats, not a `distribution` panel: RunMetrics carries only p50/p95 (no
|
|
99
|
+
// raw samples to bucket), so a histogram here would be a permanently-empty box.
|
|
98
100
|
{
|
|
99
|
-
kind: "
|
|
100
|
-
title: "
|
|
101
|
+
kind: "stat",
|
|
102
|
+
title: "Duration p50",
|
|
101
103
|
data: {
|
|
102
|
-
provider: "agent.runs.duration"
|
|
104
|
+
provider: "agent.runs.duration",
|
|
105
|
+
query: {
|
|
106
|
+
metric: "p50"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
format: "duration"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
kind: "stat",
|
|
113
|
+
title: "Duration p95",
|
|
114
|
+
data: {
|
|
115
|
+
provider: "agent.runs.duration",
|
|
116
|
+
query: {
|
|
117
|
+
metric: "p95"
|
|
118
|
+
}
|
|
103
119
|
},
|
|
104
|
-
markers: [
|
|
105
|
-
"p50",
|
|
106
|
-
"p95"
|
|
107
|
-
],
|
|
108
120
|
format: "duration"
|
|
109
121
|
},
|
|
110
122
|
{
|
|
@@ -151,17 +163,15 @@ function agentDashboard(opts = {}) {
|
|
|
151
163
|
data: {
|
|
152
164
|
provider: "agent.runs.recent"
|
|
153
165
|
},
|
|
166
|
+
// A deliberate SUBSET of the provider's row shape: the full 11-field row overflows the
|
|
167
|
+
// card horizontally. Thread/actor/retries/errorCode detail lives in the standalone
|
|
168
|
+
// agent dashboard; the provider keeps returning the full row for other consumers.
|
|
154
169
|
columns: [
|
|
155
170
|
{
|
|
156
171
|
key: "startedAt",
|
|
157
172
|
label: "Started"
|
|
158
173
|
},
|
|
159
174
|
col("runId", "Run", opts.runHref),
|
|
160
|
-
col("threadId", "Thread", opts.threadHref),
|
|
161
|
-
{
|
|
162
|
-
key: "actorRef",
|
|
163
|
-
label: "Actor"
|
|
164
|
-
},
|
|
165
175
|
{
|
|
166
176
|
key: "agentName",
|
|
167
177
|
label: "Agent"
|
|
@@ -174,14 +184,6 @@ function agentDashboard(opts = {}) {
|
|
|
174
184
|
key: "durationMs",
|
|
175
185
|
label: "Duration (ms)"
|
|
176
186
|
},
|
|
177
|
-
{
|
|
178
|
-
key: "retries",
|
|
179
|
-
label: "Retries"
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
key: "errorCode",
|
|
183
|
-
label: "Error code"
|
|
184
|
-
},
|
|
185
187
|
{
|
|
186
188
|
key: "errorMessage",
|
|
187
189
|
label: "Error"
|
|
@@ -875,15 +877,17 @@ function agentRunsRetriesProvider() {
|
|
|
875
877
|
}
|
|
876
878
|
__name(agentRunsRetriesProvider, "agentRunsRetriesProvider");
|
|
877
879
|
function agentRunsDurationProvider() {
|
|
878
|
-
return
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
880
|
+
return {
|
|
881
|
+
name: "agent.runs.duration",
|
|
882
|
+
async resolve(query, ctx) {
|
|
883
|
+
const queries = resolveGovernanceQueries(ctx);
|
|
884
|
+
const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;
|
|
885
|
+
const value = query?.metric === "p95" ? metrics.durationP95Ms : metrics.durationP50Ms;
|
|
886
|
+
return {
|
|
887
|
+
value: value ?? 0
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
};
|
|
887
891
|
}
|
|
888
892
|
__name(agentRunsDurationProvider, "agentRunsDurationProvider");
|
|
889
893
|
function agentRunsByAgentTableProvider() {
|
|
@@ -971,7 +975,7 @@ __name(agentToolStatsTableProvider, "agentToolStatsTableProvider");
|
|
|
971
975
|
// src/agent-telescope.watcher.ts
|
|
972
976
|
import { subscribe, unsubscribe } from "node:diagnostics_channel";
|
|
973
977
|
import { AGENT_DIAGNOSTIC_EVENTS } from "@dudousxd/nestjs-agent-core";
|
|
974
|
-
import { channelName } from "@dudousxd/nestjs-diagnostics";
|
|
978
|
+
import { channelName, claimDiagnostics } from "@dudousxd/nestjs-diagnostics";
|
|
975
979
|
var AgentTelescopeWatcher = class {
|
|
976
980
|
static {
|
|
977
981
|
__name(this, "AgentTelescopeWatcher");
|
|
@@ -979,6 +983,7 @@ var AgentTelescopeWatcher = class {
|
|
|
979
983
|
type = "agent";
|
|
980
984
|
disposers = [];
|
|
981
985
|
register(ctx) {
|
|
986
|
+
this.disposers.push(claimDiagnostics("agent", AGENT_DIAGNOSTIC_EVENTS));
|
|
982
987
|
for (const event of AGENT_DIAGNOSTIC_EVENTS) {
|
|
983
988
|
const channel = channelName("agent", event);
|
|
984
989
|
const onMessage = /* @__PURE__ */ __name((message) => {
|
|
@@ -998,7 +1003,7 @@ var AgentTelescopeWatcher = class {
|
|
|
998
1003
|
this.disposers.push(() => unsubscribe(channel, onMessage));
|
|
999
1004
|
}
|
|
1000
1005
|
}
|
|
1001
|
-
/** Detach all channel subscriptions (e.g. on module destroy). */
|
|
1006
|
+
/** Detach all channel subscriptions and release the diagnostics claim (e.g. on module destroy). */
|
|
1002
1007
|
dispose() {
|
|
1003
1008
|
while (this.disposers.length) this.disposers.pop()?.();
|
|
1004
1009
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent-telescope.extension.ts","../src/agent-dashboard.spec-data.ts","../src/agent-data-providers.ts","../src/agent-governance-providers.ts","../src/agent-telescope.watcher.ts"],"sourcesContent":["import { defineTelescopeExtension } from '@dudousxd/nestjs-telescope';\nimport { agentDashboard } from './agent-dashboard.spec-data.js';\nimport {\n agentRunsProvider,\n agentTokensProvider,\n agentToolStatusProvider,\n} from './agent-data-providers.js';\nimport {\n agentActorSpendTableProvider,\n agentModelSpendTableProvider,\n agentPendingApprovalsCountProvider,\n agentPendingApprovalsTableProvider,\n agentRecentRunsTableProvider,\n agentRecentThreadsTableProvider,\n agentRecentToolCallsTableProvider,\n agentRunErrorsProvider,\n agentRunsByAgentTableProvider,\n agentRunsDurationProvider,\n agentRunsFailedProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentTokensTotalProvider,\n agentToolStatsTableProvider,\n agentTopThreadsTableProvider,\n agentUsageTrendProvider,\n} from './agent-governance-providers.js';\nimport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\n\n/**\n * The first-class Telescope extension for nestjs-agent: an \"Agent\" tab fed by two sources —\n * the `aviary:agent:*` diagnostics channel (live runs, tool calls) via the watcher, and the\n * authoritative `AGENT_GOVERNANCE_QUERIES` read-model (historical spend/usage, run reliability,\n * tool activity, the approvals inbox) via the governance providers. The extension `name`,\n * entry-type id, dashboard id, and every provider name share the `agent` prefix so the registry's\n * global-uniqueness namespaces never collide with sibling extensions.\n *\n * `threadHref`/`runHref` deep-link a table row's `threadId`/`runId` cell out to the host's own\n * thread/run viewer — passed straight through to {@link agentDashboard}, mirroring\n * `durableTelescopeExtension`'s `runHref` option.\n *\n * Host wiring: the governance panels (Spend/Models/Actors/Reliability/Runs/Threads/Approvals/Tool\n * stats/Recent tool calls) resolve `AGENT_GOVERNANCE_QUERIES` from the host DI container at\n * request time (via `ctx.moduleRef`). The host must bind that token — from its store adapter\n * (e.g. `store-mikro-orm` / `store-drizzle` / `testing`) — in the same module that registers\n * `TelescopeModule.forRoot({ extensions: [agentTelescopeExtension()] })`. If the binding is\n * absent, those panels render an empty state; the live watcher-fed panels (Runs/Tokens stats and\n * the Tool-call status breakdown) keep working regardless.\n */\nexport function agentTelescopeExtension(opts: { threadHref?: string; runHref?: string } = {}) {\n return defineTelescopeExtension({\n name: 'agent',\n watchers: () => [new AgentTelescopeWatcher()],\n entryTypes: () => [{ id: 'agent', label: 'Agent', dot: 'bg-violet-400' }],\n dashboards: () => [agentDashboard(opts)],\n dataProviders: () => [\n agentRunsProvider(),\n agentTokensProvider(),\n agentToolStatusProvider(),\n agentSpendTotalProvider(),\n agentTokensTotalProvider(),\n agentSpendByModelProvider(),\n agentModelSpendTableProvider(),\n agentUsageTrendProvider(),\n agentActorSpendTableProvider(),\n agentSpendByActorProvider(),\n agentTopThreadsTableProvider(),\n agentRunsTotalProvider(),\n agentRunsSuccessRateProvider(),\n agentRunsFailedProvider(),\n agentRunsRetriesProvider(),\n agentRunsDurationProvider(),\n agentRunsByAgentTableProvider(),\n agentRunErrorsProvider(),\n agentRunsTrendProvider(),\n agentRecentRunsTableProvider(),\n agentRecentToolCallsTableProvider(),\n agentRecentThreadsTableProvider(),\n agentPendingApprovalsCountProvider(),\n agentPendingApprovalsTableProvider(),\n agentToolStatsTableProvider(),\n ],\n });\n}\n","import type { Column, DashboardSpec } from '@dudousxd/nestjs-telescope';\n\n/** A plain column, or one carrying a `Column.link` to `href` when `href` is given. */\nfunction col(key: string, label: string, href?: string): Column {\n return href !== undefined ? { key, label, link: { href } } : { key, label };\n}\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref`/`runHref` are URL templates for deep-linking a `{threadId}`/`{runId}` cell out to\n * the host's own thread/run viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA),\n * mirroring `durableTelescopeExtension`'s `runHref` option. Every table whose rows carry a\n * `threadId`/`runId` gets a `Column.link` for it (via {@link col}); omit an option to leave that\n * column plain text.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n title: 'Overview',\n cols: 2,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n ],\n },\n {\n title: 'Reliability',\n cols: 4,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs.total' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n { kind: 'stat', title: 'Failed', data: { provider: 'agent.runs.failed' } },\n { kind: 'stat', title: 'Retries', data: { provider: 'agent.runs.retries' } },\n ],\n },\n {\n title: 'Run trends',\n cols: 3,\n panels: [\n {\n kind: 'timeseries',\n title: 'Runs & failures',\n data: { provider: 'agent.runs.trend' },\n series: ['runs', 'failed'],\n style: 'stacked',\n },\n {\n kind: 'distribution',\n title: 'Run duration',\n data: { provider: 'agent.runs.duration' },\n markers: ['p50', 'p95'],\n format: 'duration',\n },\n {\n kind: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\n ],\n },\n {\n title: 'Runs',\n panels: [\n {\n kind: 'table',\n title: 'Runs by agent',\n data: { provider: 'agent.runs.byAgent' },\n columns: [\n { key: 'agentName', label: 'Agent' },\n { key: 'runs', label: 'Runs' },\n { key: 'failed', label: 'Failed' },\n { key: 'retries', label: 'Retries' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent runs',\n data: { provider: 'agent.runs.recent' },\n columns: [\n { key: 'startedAt', label: 'Started' },\n col('runId', 'Run', opts.runHref),\n col('threadId', 'Thread', opts.threadHref),\n { key: 'actorRef', label: 'Actor' },\n { key: 'agentName', label: 'Agent' },\n { key: 'status', label: 'Status' },\n { key: 'durationMs', label: 'Duration (ms)' },\n { key: 'retries', label: 'Retries' },\n { key: 'errorCode', label: 'Error code' },\n { key: 'errorMessage', label: 'Error' },\n { key: 'promptHash', label: 'Prompt' },\n ],\n },\n ],\n },\n {\n title: 'Spend',\n cols: 2,\n panels: [\n {\n kind: 'stat',\n title: 'Total spend (USD)',\n data: { provider: 'agent.spend.totalCost' },\n format: 'number',\n },\n {\n kind: 'stat',\n title: 'Total tokens',\n data: { provider: 'agent.spend.totalTokens' },\n format: 'number',\n },\n {\n kind: 'breakdown',\n title: 'Spend by model',\n data: { provider: 'agent.spend.byModel' },\n style: 'donut',\n },\n {\n kind: 'timeseries',\n title: 'Daily spend & tokens',\n data: { provider: 'agent.usage.trend' },\n series: ['costUsd', 'totalTokens'],\n style: 'area',\n },\n ],\n },\n {\n title: 'Models',\n panels: [\n {\n kind: 'table',\n title: 'Usage & cost by model',\n data: { provider: 'agent.spend.byModelTable' },\n columns: [\n { key: 'modelId', label: 'Model' },\n { key: 'requests', label: 'Requests' },\n { key: 'inputTokens', label: 'Input tokens' },\n { key: 'outputTokens', label: 'Output tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Actors',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Spend share by actor',\n data: { provider: 'agent.spend.byActorShare' },\n style: 'bar',\n },\n {\n kind: 'table',\n title: 'Spend by actor',\n data: { provider: 'agent.spend.byActor' },\n columns: [\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Threads',\n cols: 2,\n panels: [\n {\n kind: 'table',\n title: 'Top threads by cost',\n data: { provider: 'agent.threads.topSpend' },\n columns: [\n { key: 'title', label: 'Thread' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n data: { provider: 'agent.threads.recent' },\n columns: [\n col('threadId', 'Thread', opts.threadHref),\n { key: 'title', label: 'Title' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'messageCount', label: 'Messages' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'lastActivityAt', label: 'Last activity' },\n ],\n },\n ],\n },\n {\n title: 'Approvals',\n cols: 3,\n panels: [\n {\n kind: 'stat',\n title: 'Pending approvals',\n data: { provider: 'agent.approvals.pending' },\n },\n {\n kind: 'table',\n title: 'Approvals inbox',\n data: { provider: 'agent.approvals.recent' },\n columns: [\n { key: 'requestedAt', label: 'Requested' },\n { key: 'toolName', label: 'Tool' },\n { key: 'threadTitle', label: 'Thread' },\n col('threadId', 'Thread id', opts.threadHref),\n { key: 'actorRef', label: 'Actor' },\n { key: 'agentName', label: 'Agent' },\n ],\n },\n ],\n },\n {\n title: 'Tools',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Tool-call status',\n data: { provider: 'agent.toolStatus' },\n style: 'donut',\n },\n {\n kind: 'table',\n title: 'Tool stats',\n data: { provider: 'agent.tools.stats' },\n columns: [\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'calls', label: 'Calls' },\n { key: 'failed', label: 'Failed' },\n { key: 'rejected', label: 'Rejected' },\n { key: 'p95ExecutionMs', label: 'p95 (ms)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent tool calls',\n data: { provider: 'agent.tools.recent' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n ],\n },\n ],\n };\n}\n","import type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\nimport { TELESCOPE_STORAGE } from '@dudousxd/nestjs-telescope';\n\ninterface AgentEntryContent {\n event: string;\n runId?: string;\n threadId?: string;\n toolName?: string;\n toolType?: string;\n status?: string;\n steps?: number;\n inputTokens?: number;\n outputTokens?: number;\n}\n\ninterface StorageEntry {\n content?: AgentEntryContent;\n createdAt?: Date;\n}\n\nasync function fetchEntries(ctx: ExtensionContext): Promise<StorageEntry[]> {\n const storage = ctx.moduleRef.get(TELESCOPE_STORAGE, { strict: false }) as {\n get(query: { type?: string; limit?: number }): Promise<{ data: StorageEntry[] }>;\n };\n const page = await storage.get({ type: 'agent', limit: 5_000 });\n return page.data;\n}\n\nfunction ofEvent(entries: StorageEntry[], event: string): StorageEntry[] {\n return entries.filter((entry) => entry.content?.event === event);\n}\n\n/** stat → total agent runs (run.finished entries). */\nexport function agentRunsProvider(): DataProvider {\n return {\n name: 'agent.runs',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n return { value: finished.length };\n },\n };\n}\n\n/** stat → total tokens across all finished runs. */\nexport function agentTokensProvider(): DataProvider {\n return {\n name: 'agent.tokens',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n const value = finished.reduce(\n (sum, entry) =>\n sum + (entry.content?.inputTokens ?? 0) + (entry.content?.outputTokens ?? 0),\n 0,\n );\n return { value };\n },\n };\n}\n\n/**\n * table → recent tool calls, from Telescope's own ephemeral event storage.\n *\n * @deprecated Superseded in the shipped dashboard by `agentRecentToolCallsTableProvider`\n * (`agent.tools.recent`, in `agent-governance-providers.ts`), which reads the durable,\n * restart-surviving `AGENT_GOVERNANCE_QUERIES.recentToolCalls` read-model. That durable route is\n * never behind this ephemeral one: `agent-loop.ts` always awaits `store.recordToolCall` /\n * `store.updateToolCall` (the durable write) BEFORE calling `publishAgentToolCall` (the event this\n * provider reads), so a row is durably queryable strictly before the ephemeral entry exists. The\n * durable route also captures the `pending_approval` state this ephemeral channel never emits at\n * all (no `publishAgentToolCall` call sits between `recordToolCall(status: 'pending_approval')`\n * and the eventual terminal transition) — so there's no in-flight state left for this table to\n * uniquely show. Kept exported (not removed — that would be a breaking export change) for hosts\n * that use `agentTelescopeExtension()` without wiring `AGENT_GOVERNANCE_QUERIES`, or that compose\n * a custom extension from these lower-level provider functions directly.\n */\nexport function agentToolsProvider(): DataProvider {\n return {\n name: 'agent.tools',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call')\n .slice(-50)\n .reverse()\n .map((entry) => ({\n toolName: entry.content?.toolName ?? '',\n toolType: entry.content?.toolType ?? '',\n status: entry.content?.status ?? '',\n runId: entry.content?.runId ?? '',\n }));\n return { rows: calls };\n },\n };\n}\n\n/** breakdown → tool-call status distribution. */\nexport function agentToolStatusProvider(): DataProvider {\n return {\n name: 'agent.toolStatus',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call');\n const counts = new Map<string, number>();\n for (const call of calls) {\n const status = call.content?.status ?? 'unknown';\n counts.set(status, (counts.get(status) ?? 0) + 1);\n }\n return { segments: [...counts.entries()].map(([label, value]) => ({ label, value })) };\n },\n };\n}\n","import type {\n ActorSpendRow,\n AgentGovernanceQueries,\n GovernanceRange,\n ModelSpendRow,\n PendingApprovalRow,\n RecentRunRow,\n RunAgentBreakdownRow,\n RunErrorBreakdownRow,\n RunMetrics,\n RunTrendPoint,\n ThreadActivityRow,\n ThreadSpendRow,\n ToolCallActivityRow,\n ToolStatRow,\n UsageTrendPoint,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_GOVERNANCE_QUERIES } from '@dudousxd/nestjs-agent-core';\nimport type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\n\n/**\n * Governance data providers for the \"Agent\" Telescope tab: spend/usage, run reliability, tool\n * activity, and the cross-thread approvals inbox. Unlike the live watcher-fed providers in\n * `agent-data-providers.ts` (which read the ephemeral Telescope event storage), these read the\n * authoritative, restart-surviving read-model: `AGENT_GOVERNANCE_QUERIES` (usage ⋈ pricing, plus\n * run/tool-call/thread history).\n *\n * The read-model is resolved from the host's DI container via `ctx.moduleRef` — the exact same\n * mechanism the existing providers use for `TELESCOPE_STORAGE`. The host must bind\n * `AGENT_GOVERNANCE_QUERIES` (from its store adapter) in the same module that registers Telescope;\n * when the binding is absent every provider degrades to an empty-but-valid shape rather than throwing.\n */\n\n/** Default trailing window (in days, inclusive) when a panel query omits an explicit range. */\nconst DEFAULT_TREND_WINDOW_DAYS = 30;\n\nconst ISO_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** A breakdown-panel segment (Telescope core: `{ segments: Array<{ label, value, color? }> }`). */\ninterface BreakdownSegment {\n label: string;\n value: number;\n}\n\n/** One row of the per-model usage/cost table. */\ninterface ModelSpendTableRow {\n modelId: string;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\n/** One row of the per-actor spend table. */\ninterface ActorSpendTableRow {\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** One row of the top-threads-by-cost table. */\ninterface ThreadSpendTableRow {\n title: string;\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** Top threads by cost within the range, capped to this count. */\nconst TOP_THREADS_LIMIT = 10;\n\n/** One point of the timeseries trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface UsageTrendTableRow {\n label: string;\n costUsd: number;\n totalTokens: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Structural guard so the DI-resolved binding is narrowed without an `as`/`any` cast. */\nfunction isGovernanceQueries(value: unknown): value is AgentGovernanceQueries {\n return (\n isRecord(value) &&\n typeof value.spendByModel === 'function' &&\n typeof value.spendByActor === 'function' &&\n typeof value.spendByThread === 'function' &&\n typeof value.usageTrend === 'function' &&\n typeof value.recentToolCalls === 'function' &&\n typeof value.recentThreads === 'function' &&\n typeof value.runMetrics === 'function' &&\n typeof value.runsByAgent === 'function' &&\n typeof value.runErrors === 'function' &&\n typeof value.runTrend === 'function' &&\n typeof value.recentRuns === 'function' &&\n typeof value.pendingApprovals === 'function' &&\n typeof value.toolStats === 'function'\n );\n}\n\n/**\n * Resolve the governance read-model from the host container. Returns `null` when the host has not\n * bound `AGENT_GOVERNANCE_QUERIES` (missing token throws inside `moduleRef.get`) so panels can render\n * an empty state instead of erroring.\n */\nfunction resolveGovernanceQueries(ctx: ExtensionContext): AgentGovernanceQueries | null {\n let resolved: unknown;\n try {\n resolved = ctx.moduleRef.get(AGENT_GOVERNANCE_QUERIES, { strict: false });\n } catch {\n return null;\n }\n return isGovernanceQueries(resolved) ? resolved : null;\n}\n\nfunction isIsoDay(value: unknown): value is string {\n return typeof value === 'string' && ISO_DAY_PATTERN.test(value);\n}\n\nfunction todayUtcDay(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Shift a `YYYY-MM-DD` UTC day by `deltaDays` (negative goes back in time). */\nexport function shiftUtcDay(day: string, deltaDays: number): string {\n const shifted = new Date(`${day}T00:00:00.000Z`);\n shifted.setUTCDate(shifted.getUTCDate() + deltaDays);\n return shifted.toISOString().slice(0, 10);\n}\n\n/**\n * Derive the query range: honour explicit `fromDay`/`toDay` (validated ISO days), otherwise default\n * to the trailing {@link DEFAULT_TREND_WINDOW_DAYS}-day window ending today (UTC).\n */\nexport function resolveRange(query: Record<string, unknown> | undefined): GovernanceRange {\n const toDay = query && isIsoDay(query.toDay) ? query.toDay : todayUtcDay();\n const fromDay =\n query && isIsoDay(query.fromDay)\n ? query.fromDay\n : shiftUtcDay(toDay, -(DEFAULT_TREND_WINDOW_DAYS - 1));\n return { fromDay, toDay };\n}\n\nfunction roundCents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/** Sum authoritative spend across every model row. */\nexport function totalCostUsd(rows: ModelSpendRow[]): number {\n return roundCents(rows.reduce((sum, row) => sum + row.costUsd, 0));\n}\n\n/** Sum input + output tokens across every model row. */\nexport function totalTokens(rows: ModelSpendRow[]): number {\n return rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);\n}\n\n/** Spend-by-model as breakdown segments (models with zero cost are dropped from the donut). */\nexport function toModelSpendSegments(rows: ModelSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.modelId, value: roundCents(row.costUsd) }));\n}\n\n/** Spend-by-model as table rows (cost rounded to cents; usage kept exact). */\nexport function toModelSpendRows(rows: ModelSpendRow[]): ModelSpendTableRow[] {\n return rows.map((row) => ({\n modelId: row.modelId,\n requests: row.requests,\n inputTokens: row.inputTokens,\n outputTokens: row.outputTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as table rows. */\nexport function toActorSpendRows(rows: ActorSpendRow[]): ActorSpendTableRow[] {\n return rows.map((row) => ({\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Top-threads-by-cost as table rows. */\nexport function toThreadSpendRows(rows: ThreadSpendRow[]): ThreadSpendTableRow[] {\n return rows.map((row) => ({\n title: row.title || row.threadId,\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as breakdown segments (actors with zero cost are dropped). */\nexport function toActorSpendSegments(rows: ActorSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.actorRef, value: roundCents(row.costUsd) }));\n}\n\n/** Daily usage trend as timeseries rows keyed by `label` (the day). */\nexport function toUsageTrendRows(points: UsageTrendPoint[]): UsageTrendTableRow[] {\n return points.map((point) => ({\n label: point.day,\n costUsd: roundCents(point.costUsd),\n totalTokens: point.totalTokens,\n }));\n}\n\n// ─── Run reliability + tools + approvals shaping ─────────────────────────────\n\n/** Placeholder shown for a table cell whose source value is `null`/unmeasured — matches the\n * convention `@dudousxd/nestjs-durable-telescope` uses for the same case (e.g. `fmtNum`). */\nconst NO_VALUE = '—';\n\n/** Run/failure/retry rollup as table rows — `RunAgentBreakdownRow` is already table-shaped. */\nexport function toRunAgentTableRows(\n rows: RunAgentBreakdownRow[],\n): Array<{ agentName: string; runs: number; failed: number; retries: number }> {\n return rows.map((row) => ({\n agentName: row.agentName,\n runs: row.runs,\n failed: row.failed,\n retries: row.retries,\n }));\n}\n\n/** Failed-run counts by error code as breakdown segments. */\nexport function toRunErrorSegments(rows: RunErrorBreakdownRow[]): BreakdownSegment[] {\n return rows.map((row) => ({ label: row.errorCode, value: row.count }));\n}\n\n/** One point of the run/failure trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface RunTrendTableRow {\n label: string;\n runs: number;\n failed: number;\n}\n\n/** Daily run/failure trend as timeseries rows keyed by `label` (the day). */\nexport function toRunTrendRows(points: RunTrendPoint[]): RunTrendTableRow[] {\n return points.map((point) => ({ label: point.day, runs: point.runs, failed: point.failed }));\n}\n\n/** Cap this many characters before a byte length; matches the DB column's practical display width. */\nconst ERROR_MESSAGE_CAP = 500;\n\n/**\n * Cap a run's error message to {@link ERROR_MESSAGE_CAP} characters before it leaves the provider.\n * `DataProvider.resolve` output bypasses Telescope core's `redact()` pipeline — that only runs on\n * entries a `Watcher` records via `ctx.record`, not on values a provider computes and returns\n * directly to a panel — so an unbounded stack trace or secret-laden failure message would ride\n * straight into a table cell with no truncation/redaction safety net. This cap is a stopgap\n * mitigation, not a substitute for the (out-of-scope this wave) telescope-core redaction hook for\n * DataProvider output.\n */\nexport function capErrorMessage(message: string | null): string | null {\n if (message === null) return null;\n return message.length > ERROR_MESSAGE_CAP ? `${message.slice(0, ERROR_MESSAGE_CAP)}…` : message;\n}\n\n/** How many leading hex characters of a promptHash the table shows as a short chip. */\nconst PROMPT_HASH_CHIP_LENGTH = 10;\n\n/** Shorten a full sha256 promptHash to a compact chip for the table column. */\nexport function shortPromptHash(promptHash: string | null): string | null {\n return promptHash === null ? null : promptHash.slice(0, PROMPT_HASH_CHIP_LENGTH);\n}\n\n/** One row of the recent-runs table — every nullable field falls back to {@link NO_VALUE}. */\ninterface RecentRunTableRow {\n startedAt: string;\n runId: string;\n threadId: string;\n actorRef: string;\n agentName: string;\n status: string;\n durationMs: number | string;\n retries: number;\n errorCode: string;\n errorMessage: string;\n promptHash: string;\n}\n\n/** Recent runs as table rows: errorMessage capped, promptHash shortened to a chip. */\nexport function toRecentRunTableRows(rows: RecentRunRow[]): RecentRunTableRow[] {\n return rows.map((row) => ({\n startedAt: row.startedAt,\n runId: row.runId,\n threadId: row.threadId,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n status: row.status,\n durationMs: row.durationMs ?? NO_VALUE,\n retries: row.retries,\n errorCode: row.errorCode ?? NO_VALUE,\n errorMessage: capErrorMessage(row.errorMessage) ?? NO_VALUE,\n promptHash: shortPromptHash(row.promptHash) ?? NO_VALUE,\n }));\n}\n\n/** Recent tool calls as table rows — `ToolCallActivityRow` is already table-shaped. */\nexport function toRecentToolCallRows(rows: ToolCallActivityRow[]): ToolCallActivityRow[] {\n return rows;\n}\n\n/** Recent threads as table rows — `ThreadActivityRow` is already table-shaped. */\nexport function toRecentThreadTableRows(rows: ThreadActivityRow[]): ThreadActivityRow[] {\n return rows;\n}\n\n/** One row of the pending-approvals inbox table, `input` stringified for display. */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n}\n\n/** Pending-approvals rows as table rows (drops the raw `input` — not renderable in a table cell). */\nexport function toPendingApprovalTableRows(rows: PendingApprovalRow[]): PendingApprovalTableRow[] {\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n requestedAt: row.requestedAt,\n }));\n}\n\n/** One row of the per-tool stats table, `p95ExecutionMs` falling back to {@link NO_VALUE}. */\ninterface ToolStatTableRow {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n p95ExecutionMs: number | string;\n}\n\n/** Per-tool call/failure/rejection/latency rollup as table rows. */\nexport function toToolStatTableRows(rows: ToolStatRow[]): ToolStatTableRow[] {\n return rows.map((row) => ({\n toolName: row.toolName,\n toolType: row.toolType,\n calls: row.calls,\n failed: row.failed,\n rejected: row.rejected,\n p95ExecutionMs: row.p95ExecutionMs ?? NO_VALUE,\n }));\n}\n\n/** Zero-valued `RunMetrics`, returned when the read-model isn't bound. */\nconst EMPTY_RUN_METRICS: RunMetrics = {\n runs: 0,\n completed: 0,\n failed: 0,\n successRate: 0,\n retries: 0,\n durationP50Ms: null,\n durationP95Ms: null,\n};\n\n/**\n * Build a governance `DataProvider` from a fetch + a format step. Every provider follows the same\n * shape: resolve the read-model, run ONE query over the panel's range, then format the rows into the\n * panel's result shape. When the host hasn't bound the read-model, `fetch` is skipped and `format`\n * runs over `[]` — which is exactly the empty-but-valid shape each formatter already yields (0 for\n * totals, `[]` for segments/rows), so the degraded case needs no special-casing.\n */\nfunction governanceStatProvider<TRow>(\n name: string,\n fetch: (queries: AgentGovernanceQueries, range: GovernanceRange) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveRange(query)) : [];\n return format(rows);\n },\n };\n}\n\n/** stat → authoritative total spend (USD) over the range. */\nexport function agentSpendTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalCost',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalCostUsd(rows) }),\n );\n}\n\n/** stat → authoritative total tokens (input + output) over the range. */\nexport function agentTokensTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalTokens',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalTokens(rows) }),\n );\n}\n\n/** breakdown → spend share per model. */\nexport function agentSpendByModelProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModel',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ segments: toModelSpendSegments(rows) }),\n );\n}\n\n/** table → per-model requests / in+out tokens / cost. */\nexport function agentModelSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModelTable',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ rows: toModelSpendRows(rows) }),\n );\n}\n\n/** timeseries → daily spend + tokens trend. */\nexport function agentUsageTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.usage.trend',\n (queries, range) => queries.usageTrend(range),\n (points) => ({ rows: toUsageTrendRows(points) }),\n );\n}\n\n/** table → spend per acting ref (user/tenant). */\nexport function agentActorSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActor',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ rows: toActorSpendRows(rows) }),\n );\n}\n\n/** breakdown → spend share per actor. */\nexport function agentSpendByActorProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActorShare',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ segments: toActorSpendSegments(rows) }),\n );\n}\n\n/** table → top threads by cost (title, actor, requests, tokens, cost). */\nexport function agentTopThreadsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.threads.topSpend',\n (queries, range) => queries.spendByThread(range, TOP_THREADS_LIMIT),\n (rows) => ({ rows: toThreadSpendRows(rows) }),\n );\n}\n\n// ─── Reliability providers ────────────────────────────────────────────────────\n\n/**\n * Build a `DataProvider` from ONE range-scoped `runMetrics` call + a format step — the\n * `governanceStatProvider` pattern specialized for the single-object `RunMetrics` shape (the five\n * reliability stats all reuse the same underlying query, exactly like the spend stats above reuse\n * `spendByModel`). Degrades to {@link EMPTY_RUN_METRICS} when the read-model isn't bound.\n */\nfunction governanceRunMetricsProvider(\n name: string,\n format: (metrics: RunMetrics) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;\n return format(metrics);\n },\n };\n}\n\n/** stat → total runs over the range. */\nexport function agentRunsTotalProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.total', (metrics) => ({ value: metrics.runs }));\n}\n\n/** stat → completed/total success rate over the range. */\nexport function agentRunsSuccessRateProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.successRate', (metrics) => ({\n value: metrics.successRate,\n }));\n}\n\n/** stat → failed run count over the range. */\nexport function agentRunsFailedProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.failed', (metrics) => ({\n value: metrics.failed,\n }));\n}\n\n/** stat → total llm-step retries across the range's runs. */\nexport function agentRunsRetriesProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.retries', (metrics) => ({\n value: metrics.retries,\n }));\n}\n\n/**\n * distribution → run duration. `RunMetrics` exposes only the two percentiles (no raw per-run\n * samples), so there is nothing to bucket into a histogram — the panel renders its `p50`/`p95`\n * markers over an empty bucket series. `exactOptionalPropertyTypes` means a `null` percentile is\n * omitted from the result rather than carried as an explicit `undefined`.\n */\nexport function agentRunsDurationProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.duration', (metrics) => ({\n buckets: [],\n ...(metrics.durationP50Ms !== null ? { p50: metrics.durationP50Ms } : {}),\n ...(metrics.durationP95Ms !== null ? { p95: metrics.durationP95Ms } : {}),\n }));\n}\n\n/** table → run/failure/retry rollup per agent. */\nexport function agentRunsByAgentTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.byAgent',\n (queries, range) => queries.runsByAgent(range),\n (rows) => ({ rows: toRunAgentTableRows(rows) }),\n );\n}\n\n/** breakdown → failed runs by error code. */\nexport function agentRunErrorsProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.errors',\n (queries, range) => queries.runErrors(range),\n (rows) => ({ segments: toRunErrorSegments(rows) }),\n );\n}\n\n/** timeseries → daily runs + failures trend. */\nexport function agentRunsTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.trend',\n (queries, range) => queries.runTrend(range),\n (points) => ({ rows: toRunTrendRows(points) }),\n );\n}\n\n// ─── Limit-scoped providers (recent-activity feeds + the approvals inbox) ────\n\n/** Default row count for a \"recent …\" feed when a panel's query omits `limit`. */\nconst DEFAULT_RECENT_LIMIT = 50;\n/** Hard ceiling on `limit`, regardless of what a panel's query requests. */\nconst MAX_RECENT_LIMIT = 500;\n\n/** Clamp a panel-supplied `limit` into `[1, MAX_RECENT_LIMIT]`, defaulting when absent/invalid. */\nfunction resolveLimit(query: Record<string, unknown> | undefined, fallback: number): number {\n const raw = query?.limit;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : fallback;\n return Math.min(MAX_RECENT_LIMIT, Math.max(1, Math.trunc(value)));\n}\n\n/**\n * Build a governance `DataProvider` from a `limit`-scoped fetch + a format step — the sibling of\n * {@link governanceStatProvider} for the read-model's \"recent N\" queries, which take a row cap\n * instead of a day range. Degrades to `[]` when the read-model isn't bound.\n */\nfunction governanceLimitProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, limit: number) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveLimit(query, defaultLimit)) : [];\n return format(rows);\n },\n };\n}\n\n/**\n * table → most recent runs (newest first), errorMessage capped and promptHash shortened to a chip\n * — see {@link capErrorMessage} for why the cap happens here rather than downstream.\n */\nexport function agentRecentRunsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.runs.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentRuns(limit),\n (rows) => ({ rows: toRecentRunTableRows(rows) }),\n );\n}\n\n/**\n * table → most recent tool calls (newest first), from the durable read-model. Replaces the\n * ephemeral, watcher-fed `agent.tools` provider in `agent-data-providers.ts` for the shipped\n * dashboard — see that file's header comment for why.\n */\nexport function agentRecentToolCallsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.tools.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentToolCalls(limit),\n (rows) => ({ rows: toRecentToolCallRows(rows) }),\n );\n}\n\n/** table → most recently active threads, with rolled-up message/token counts. */\nexport function agentRecentThreadsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.threads.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentThreads(limit),\n (rows) => ({ rows: toRecentThreadTableRows(rows) }),\n );\n}\n\n/** Row cap used to approximate a \"pending approvals\" COUNT (the SPI only exposes a capped list —\n * see {@link agentPendingApprovalsCountProvider}). */\nconst PENDING_APPROVALS_COUNT_LIMIT = 500;\n\n/**\n * stat → count of tool calls sitting `pending_approval` across every thread. The SPI's\n * `pendingApprovals` only returns a capped list, not a true count, so this undercounts a backlog\n * larger than {@link PENDING_APPROVALS_COUNT_LIMIT} — a backlog that size signals a bigger\n * operational problem than an off-by-N stat, so the approximation is an acceptable tradeoff.\n */\nexport function agentPendingApprovalsCountProvider(): DataProvider {\n return {\n name: 'agent.approvals.pending',\n async resolve(_query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await queries.pendingApprovals(PENDING_APPROVALS_COUNT_LIMIT) : [];\n return { value: rows.length };\n },\n };\n}\n\n/** table → the pending-approvals inbox, oldest request first. */\nexport function agentPendingApprovalsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.approvals.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.pendingApprovals(limit),\n (rows) => ({ rows: toPendingApprovalTableRows(rows) }),\n );\n}\n\n/** table → per-tool call/failure/rejection/latency rollup over the range. */\nexport function agentToolStatsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.tools.stats',\n (queries, range) => queries.toolStats(range),\n (rows) => ({ rows: toToolStatTableRows(rows) }),\n );\n}\n","import { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport { AGENT_DIAGNOSTIC_EVENTS } from '@dudousxd/nestjs-agent-core';\nimport { channelName } from '@dudousxd/nestjs-diagnostics';\nimport type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';\n\ninterface DiagnosticEnvelope {\n event: string;\n payload: Record<string, unknown>;\n}\n\n/**\n * Records `aviary:agent:*` diagnostics events as Telescope entries of type `agent`. It depends\n * only on the diagnostics channel — not on the agent runtime — so it stays fully decoupled.\n *\n * Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 events on `ChannelRegistry['agent']`) rather\n * than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and tagged —\n * filterable in the Telescope UI — like every other agent event.\n *\n * **Superseded by `@dudousxd/nestjs-diagnostics-telescope`'s generic watcher,** which\n * auto-captures every `aviary:agent:*` channel registered in the diagnostics registry — prefer\n * that when the generic bridge is already in use; pass `agentDiagnosticKey(event)` keys to its\n * `exclude` option to mute a noisy one. This watcher is kept for standalone use without the\n * diagnostics telescope bridge.\n *\n * Register it with the telescope module's watcher list.\n */\nexport class AgentTelescopeWatcher implements Watcher {\n readonly type = 'agent';\n private readonly disposers: Array<() => void> = [];\n\n register(ctx: WatcherContext): void {\n for (const event of AGENT_DIAGNOSTIC_EVENTS) {\n const channel = channelName('agent', event);\n const onMessage = (message: unknown) => {\n const envelope = message as DiagnosticEnvelope;\n ctx.record({\n type: 'agent',\n content: { event: envelope.event, ...envelope.payload },\n tags: [envelope.event],\n });\n };\n subscribe(channel, onMessage);\n this.disposers.push(() => unsubscribe(channel, onMessage));\n }\n }\n\n /** Detach all channel subscriptions (e.g. on module destroy). */\n dispose(): void {\n while (this.disposers.length) this.disposers.pop()?.();\n }\n}\n"],"mappings":"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","names":["defineTelescopeExtension","col","key","label","href","undefined","link","agentDashboard","opts","id","panels","sections","title","cols","kind","data","provider","format","series","style","markers","columns","runHref","threadHref","TELESCOPE_STORAGE","fetchEntries","ctx","storage","moduleRef","get","TELESCOPE_STORAGE","strict","page","type","limit","data","ofEvent","entries","event","filter","entry","content","agentRunsProvider","name","resolve","_query","finished","value","length","agentTokensProvider","reduce","sum","inputTokens","outputTokens","agentToolsProvider","calls","slice","reverse","map","toolName","toolType","status","runId","rows","agentToolStatusProvider","counts","Map","call","set","segments","label","AGENT_GOVERNANCE_QUERIES","DEFAULT_TREND_WINDOW_DAYS","ISO_DAY_PATTERN","TOP_THREADS_LIMIT","isRecord","value","isGovernanceQueries","spendByModel","spendByActor","spendByThread","usageTrend","recentToolCalls","recentThreads","runMetrics","runsByAgent","runErrors","runTrend","recentRuns","pendingApprovals","toolStats","resolveGovernanceQueries","ctx","resolved","moduleRef","get","AGENT_GOVERNANCE_QUERIES","strict","isIsoDay","test","todayUtcDay","Date","toISOString","slice","shiftUtcDay","day","deltaDays","shifted","setUTCDate","getUTCDate","resolveRange","query","toDay","fromDay","roundCents","Math","round","totalCostUsd","rows","reduce","sum","row","costUsd","totalTokens","inputTokens","outputTokens","toModelSpendSegments","filter","map","label","modelId","toModelSpendRows","requests","toActorSpendRows","actorRef","toThreadSpendRows","title","threadId","toActorSpendSegments","toUsageTrendRows","points","point","NO_VALUE","toRunAgentTableRows","agentName","runs","failed","retries","toRunErrorSegments","errorCode","count","toRunTrendRows","ERROR_MESSAGE_CAP","capErrorMessage","message","length","PROMPT_HASH_CHIP_LENGTH","shortPromptHash","promptHash","toRecentRunTableRows","startedAt","runId","status","durationMs","errorMessage","toRecentToolCallRows","toRecentThreadTableRows","toPendingApprovalTableRows","toolCallId","toolName","threadTitle","requestedAt","toToolStatTableRows","toolType","calls","rejected","p95ExecutionMs","EMPTY_RUN_METRICS","completed","successRate","durationP50Ms","durationP95Ms","governanceStatProvider","name","fetch","format","resolve","queries","agentSpendTotalProvider","range","agentTokensTotalProvider","agentSpendByModelProvider","segments","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","governanceRunMetricsProvider","metrics","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","buckets","p50","p95","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","DEFAULT_RECENT_LIMIT","MAX_RECENT_LIMIT","resolveLimit","fallback","raw","limit","Number","isFinite","min","max","trunc","governanceLimitProvider","defaultLimit","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","PENDING_APPROVALS_COUNT_LIMIT","agentPendingApprovalsCountProvider","_query","agentPendingApprovalsTableProvider","agentToolStatsTableProvider","subscribe","unsubscribe","AGENT_DIAGNOSTIC_EVENTS","channelName","AgentTelescopeWatcher","type","disposers","register","ctx","event","AGENT_DIAGNOSTIC_EVENTS","channel","channelName","onMessage","message","envelope","record","content","payload","tags","subscribe","push","unsubscribe","dispose","length","pop","agentTelescopeExtension","opts","defineTelescopeExtension","name","watchers","AgentTelescopeWatcher","entryTypes","id","label","dot","dashboards","agentDashboard","dataProviders","agentRunsProvider","agentTokensProvider","agentToolStatusProvider","agentSpendTotalProvider","agentTokensTotalProvider","agentSpendByModelProvider","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentPendingApprovalsCountProvider","agentPendingApprovalsTableProvider","agentToolStatsTableProvider"]}
|
|
1
|
+
{"version":3,"sources":["../src/agent-telescope.extension.ts","../src/agent-dashboard.spec-data.ts","../src/agent-data-providers.ts","../src/agent-governance-providers.ts","../src/agent-telescope.watcher.ts"],"sourcesContent":["import { defineTelescopeExtension } from '@dudousxd/nestjs-telescope';\nimport { agentDashboard } from './agent-dashboard.spec-data.js';\nimport {\n agentRunsProvider,\n agentTokensProvider,\n agentToolStatusProvider,\n} from './agent-data-providers.js';\nimport {\n agentActorSpendTableProvider,\n agentModelSpendTableProvider,\n agentPendingApprovalsCountProvider,\n agentPendingApprovalsTableProvider,\n agentRecentRunsTableProvider,\n agentRecentThreadsTableProvider,\n agentRecentToolCallsTableProvider,\n agentRunErrorsProvider,\n agentRunsByAgentTableProvider,\n agentRunsDurationProvider,\n agentRunsFailedProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentTokensTotalProvider,\n agentToolStatsTableProvider,\n agentTopThreadsTableProvider,\n agentUsageTrendProvider,\n} from './agent-governance-providers.js';\nimport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\n\n/**\n * The first-class Telescope extension for nestjs-agent: an \"Agent\" tab fed by two sources —\n * the `aviary:agent:*` diagnostics channel (live runs, tool calls) via the watcher, and the\n * authoritative `AGENT_GOVERNANCE_QUERIES` read-model (historical spend/usage, run reliability,\n * tool activity, the approvals inbox) via the governance providers. The extension `name`,\n * entry-type id, dashboard id, and every provider name share the `agent` prefix so the registry's\n * global-uniqueness namespaces never collide with sibling extensions.\n *\n * `threadHref`/`runHref` deep-link a table row's `threadId`/`runId` cell out to the host's own\n * thread/run viewer — passed straight through to {@link agentDashboard}, mirroring\n * `durableTelescopeExtension`'s `runHref` option.\n *\n * Host wiring: the governance panels (Spend/Models/Actors/Reliability/Runs/Threads/Approvals/Tool\n * stats/Recent tool calls) resolve `AGENT_GOVERNANCE_QUERIES` from the host DI container at\n * request time (via `ctx.moduleRef`). The host must bind that token — from its store adapter\n * (e.g. `store-mikro-orm` / `store-drizzle` / `testing`) — in the same module that registers\n * `TelescopeModule.forRoot({ extensions: [agentTelescopeExtension()] })`. If the binding is\n * absent, those panels render an empty state; the live watcher-fed panels (Runs/Tokens stats and\n * the Tool-call status breakdown) keep working regardless.\n */\nexport function agentTelescopeExtension(opts: { threadHref?: string; runHref?: string } = {}) {\n return defineTelescopeExtension({\n name: 'agent',\n watchers: () => [new AgentTelescopeWatcher()],\n entryTypes: () => [{ id: 'agent', label: 'Agent', dot: 'bg-violet-400' }],\n dashboards: () => [agentDashboard(opts)],\n dataProviders: () => [\n agentRunsProvider(),\n agentTokensProvider(),\n agentToolStatusProvider(),\n agentSpendTotalProvider(),\n agentTokensTotalProvider(),\n agentSpendByModelProvider(),\n agentModelSpendTableProvider(),\n agentUsageTrendProvider(),\n agentActorSpendTableProvider(),\n agentSpendByActorProvider(),\n agentTopThreadsTableProvider(),\n agentRunsTotalProvider(),\n agentRunsSuccessRateProvider(),\n agentRunsFailedProvider(),\n agentRunsRetriesProvider(),\n agentRunsDurationProvider(),\n agentRunsByAgentTableProvider(),\n agentRunErrorsProvider(),\n agentRunsTrendProvider(),\n agentRecentRunsTableProvider(),\n agentRecentToolCallsTableProvider(),\n agentRecentThreadsTableProvider(),\n agentPendingApprovalsCountProvider(),\n agentPendingApprovalsTableProvider(),\n agentToolStatsTableProvider(),\n ],\n });\n}\n","import type { Column, DashboardSpec } from '@dudousxd/nestjs-telescope';\n\n/** A plain column, or one carrying a `Column.link` to `href` when `href` is given. */\nfunction col(key: string, label: string, href?: string): Column {\n return href !== undefined ? { key, label, link: { href } } : { key, label };\n}\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref`/`runHref` are URL templates for deep-linking a `{threadId}`/`{runId}` cell out to\n * the host's own thread/run viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA),\n * mirroring `durableTelescopeExtension`'s `runHref` option. Every table whose rows carry a\n * `threadId`/`runId` gets a `Column.link` for it (via {@link col}); omit an option to leave that\n * column plain text.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n title: 'Overview',\n cols: 2,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n ],\n },\n {\n title: 'Reliability',\n cols: 4,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs.total' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n { kind: 'stat', title: 'Failed', data: { provider: 'agent.runs.failed' } },\n { kind: 'stat', title: 'Retries', data: { provider: 'agent.runs.retries' } },\n ],\n },\n {\n title: 'Run trends',\n cols: 4,\n panels: [\n {\n kind: 'timeseries',\n title: 'Runs & failures',\n data: { provider: 'agent.runs.trend' },\n series: ['runs', 'failed'],\n style: 'stacked',\n },\n // Two duration stats, not a `distribution` panel: RunMetrics carries only p50/p95 (no\n // raw samples to bucket), so a histogram here would be a permanently-empty box.\n {\n kind: 'stat',\n title: 'Duration p50',\n data: { provider: 'agent.runs.duration', query: { metric: 'p50' } },\n format: 'duration',\n },\n {\n kind: 'stat',\n title: 'Duration p95',\n data: { provider: 'agent.runs.duration', query: { metric: 'p95' } },\n format: 'duration',\n },\n {\n kind: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\n ],\n },\n {\n title: 'Runs',\n panels: [\n {\n kind: 'table',\n title: 'Runs by agent',\n data: { provider: 'agent.runs.byAgent' },\n columns: [\n { key: 'agentName', label: 'Agent' },\n { key: 'runs', label: 'Runs' },\n { key: 'failed', label: 'Failed' },\n { key: 'retries', label: 'Retries' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent runs',\n data: { provider: 'agent.runs.recent' },\n // A deliberate SUBSET of the provider's row shape: the full 11-field row overflows the\n // card horizontally. Thread/actor/retries/errorCode detail lives in the standalone\n // agent dashboard; the provider keeps returning the full row for other consumers.\n columns: [\n { key: 'startedAt', label: 'Started' },\n col('runId', 'Run', opts.runHref),\n { key: 'agentName', label: 'Agent' },\n { key: 'status', label: 'Status' },\n { key: 'durationMs', label: 'Duration (ms)' },\n { key: 'errorMessage', label: 'Error' },\n { key: 'promptHash', label: 'Prompt' },\n ],\n },\n ],\n },\n {\n title: 'Spend',\n cols: 2,\n panels: [\n {\n kind: 'stat',\n title: 'Total spend (USD)',\n data: { provider: 'agent.spend.totalCost' },\n format: 'number',\n },\n {\n kind: 'stat',\n title: 'Total tokens',\n data: { provider: 'agent.spend.totalTokens' },\n format: 'number',\n },\n {\n kind: 'breakdown',\n title: 'Spend by model',\n data: { provider: 'agent.spend.byModel' },\n style: 'donut',\n },\n {\n kind: 'timeseries',\n title: 'Daily spend & tokens',\n data: { provider: 'agent.usage.trend' },\n series: ['costUsd', 'totalTokens'],\n style: 'area',\n },\n ],\n },\n {\n title: 'Models',\n panels: [\n {\n kind: 'table',\n title: 'Usage & cost by model',\n data: { provider: 'agent.spend.byModelTable' },\n columns: [\n { key: 'modelId', label: 'Model' },\n { key: 'requests', label: 'Requests' },\n { key: 'inputTokens', label: 'Input tokens' },\n { key: 'outputTokens', label: 'Output tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Actors',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Spend share by actor',\n data: { provider: 'agent.spend.byActorShare' },\n style: 'bar',\n },\n {\n kind: 'table',\n title: 'Spend by actor',\n data: { provider: 'agent.spend.byActor' },\n columns: [\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n ],\n },\n {\n title: 'Threads',\n cols: 2,\n panels: [\n {\n kind: 'table',\n title: 'Top threads by cost',\n data: { provider: 'agent.threads.topSpend' },\n columns: [\n { key: 'title', label: 'Thread' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'requests', label: 'Requests' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'costUsd', label: 'Cost (USD)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n data: { provider: 'agent.threads.recent' },\n columns: [\n col('threadId', 'Thread', opts.threadHref),\n { key: 'title', label: 'Title' },\n { key: 'actorRef', label: 'Actor' },\n { key: 'messageCount', label: 'Messages' },\n { key: 'totalTokens', label: 'Tokens' },\n { key: 'lastActivityAt', label: 'Last activity' },\n ],\n },\n ],\n },\n {\n title: 'Approvals',\n cols: 3,\n panels: [\n {\n kind: 'stat',\n title: 'Pending approvals',\n data: { provider: 'agent.approvals.pending' },\n },\n {\n kind: 'table',\n title: 'Approvals inbox',\n data: { provider: 'agent.approvals.recent' },\n columns: [\n { key: 'requestedAt', label: 'Requested' },\n { key: 'toolName', label: 'Tool' },\n { key: 'threadTitle', label: 'Thread' },\n col('threadId', 'Thread id', opts.threadHref),\n { key: 'actorRef', label: 'Actor' },\n { key: 'agentName', label: 'Agent' },\n ],\n },\n ],\n },\n {\n title: 'Tools',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Tool-call status',\n data: { provider: 'agent.toolStatus' },\n style: 'donut',\n },\n {\n kind: 'table',\n title: 'Tool stats',\n data: { provider: 'agent.tools.stats' },\n columns: [\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'calls', label: 'Calls' },\n { key: 'failed', label: 'Failed' },\n { key: 'rejected', label: 'Rejected' },\n { key: 'p95ExecutionMs', label: 'p95 (ms)' },\n ],\n },\n {\n kind: 'table',\n title: 'Recent tool calls',\n data: { provider: 'agent.tools.recent' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n ],\n },\n ],\n };\n}\n","import type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\nimport { TELESCOPE_STORAGE } from '@dudousxd/nestjs-telescope';\n\ninterface AgentEntryContent {\n event: string;\n runId?: string;\n threadId?: string;\n toolName?: string;\n toolType?: string;\n status?: string;\n steps?: number;\n inputTokens?: number;\n outputTokens?: number;\n}\n\ninterface StorageEntry {\n content?: AgentEntryContent;\n createdAt?: Date;\n}\n\nasync function fetchEntries(ctx: ExtensionContext): Promise<StorageEntry[]> {\n const storage = ctx.moduleRef.get(TELESCOPE_STORAGE, { strict: false }) as {\n get(query: { type?: string; limit?: number }): Promise<{ data: StorageEntry[] }>;\n };\n const page = await storage.get({ type: 'agent', limit: 5_000 });\n return page.data;\n}\n\nfunction ofEvent(entries: StorageEntry[], event: string): StorageEntry[] {\n return entries.filter((entry) => entry.content?.event === event);\n}\n\n/** stat → total agent runs (run.finished entries). */\nexport function agentRunsProvider(): DataProvider {\n return {\n name: 'agent.runs',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n return { value: finished.length };\n },\n };\n}\n\n/** stat → total tokens across all finished runs. */\nexport function agentTokensProvider(): DataProvider {\n return {\n name: 'agent.tokens',\n async resolve(_query, ctx) {\n const finished = ofEvent(await fetchEntries(ctx), 'run.finished');\n const value = finished.reduce(\n (sum, entry) =>\n sum + (entry.content?.inputTokens ?? 0) + (entry.content?.outputTokens ?? 0),\n 0,\n );\n return { value };\n },\n };\n}\n\n/**\n * table → recent tool calls, from Telescope's own ephemeral event storage.\n *\n * @deprecated Superseded in the shipped dashboard by `agentRecentToolCallsTableProvider`\n * (`agent.tools.recent`, in `agent-governance-providers.ts`), which reads the durable,\n * restart-surviving `AGENT_GOVERNANCE_QUERIES.recentToolCalls` read-model. That durable route is\n * never behind this ephemeral one: `agent-loop.ts` always awaits `store.recordToolCall` /\n * `store.updateToolCall` (the durable write) BEFORE calling `publishAgentToolCall` (the event this\n * provider reads), so a row is durably queryable strictly before the ephemeral entry exists. The\n * durable route also captures the `pending_approval` state this ephemeral channel never emits at\n * all (no `publishAgentToolCall` call sits between `recordToolCall(status: 'pending_approval')`\n * and the eventual terminal transition) — so there's no in-flight state left for this table to\n * uniquely show. Kept exported (not removed — that would be a breaking export change) for hosts\n * that use `agentTelescopeExtension()` without wiring `AGENT_GOVERNANCE_QUERIES`, or that compose\n * a custom extension from these lower-level provider functions directly.\n */\nexport function agentToolsProvider(): DataProvider {\n return {\n name: 'agent.tools',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call')\n .slice(-50)\n .reverse()\n .map((entry) => ({\n toolName: entry.content?.toolName ?? '',\n toolType: entry.content?.toolType ?? '',\n status: entry.content?.status ?? '',\n runId: entry.content?.runId ?? '',\n }));\n return { rows: calls };\n },\n };\n}\n\n/** breakdown → tool-call status distribution. */\nexport function agentToolStatusProvider(): DataProvider {\n return {\n name: 'agent.toolStatus',\n async resolve(_query, ctx) {\n const calls = ofEvent(await fetchEntries(ctx), 'tool-call');\n const counts = new Map<string, number>();\n for (const call of calls) {\n const status = call.content?.status ?? 'unknown';\n counts.set(status, (counts.get(status) ?? 0) + 1);\n }\n return { segments: [...counts.entries()].map(([label, value]) => ({ label, value })) };\n },\n };\n}\n","import type {\n ActorSpendRow,\n AgentGovernanceQueries,\n GovernanceRange,\n ModelSpendRow,\n PendingApprovalRow,\n RecentRunRow,\n RunAgentBreakdownRow,\n RunErrorBreakdownRow,\n RunMetrics,\n RunTrendPoint,\n ThreadActivityRow,\n ThreadSpendRow,\n ToolCallActivityRow,\n ToolStatRow,\n UsageTrendPoint,\n} from '@dudousxd/nestjs-agent-core';\nimport { AGENT_GOVERNANCE_QUERIES } from '@dudousxd/nestjs-agent-core';\nimport type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\n\n/**\n * Governance data providers for the \"Agent\" Telescope tab: spend/usage, run reliability, tool\n * activity, and the cross-thread approvals inbox. Unlike the live watcher-fed providers in\n * `agent-data-providers.ts` (which read the ephemeral Telescope event storage), these read the\n * authoritative, restart-surviving read-model: `AGENT_GOVERNANCE_QUERIES` (usage ⋈ pricing, plus\n * run/tool-call/thread history).\n *\n * The read-model is resolved from the host's DI container via `ctx.moduleRef` — the exact same\n * mechanism the existing providers use for `TELESCOPE_STORAGE`. The host must bind\n * `AGENT_GOVERNANCE_QUERIES` (from its store adapter) in the same module that registers Telescope;\n * when the binding is absent every provider degrades to an empty-but-valid shape rather than throwing.\n */\n\n/** Default trailing window (in days, inclusive) when a panel query omits an explicit range. */\nconst DEFAULT_TREND_WINDOW_DAYS = 30;\n\nconst ISO_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/** A breakdown-panel segment (Telescope core: `{ segments: Array<{ label, value, color? }> }`). */\ninterface BreakdownSegment {\n label: string;\n value: number;\n}\n\n/** One row of the per-model usage/cost table. */\ninterface ModelSpendTableRow {\n modelId: string;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\n/** One row of the per-actor spend table. */\ninterface ActorSpendTableRow {\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** One row of the top-threads-by-cost table. */\ninterface ThreadSpendTableRow {\n title: string;\n actorRef: string;\n requests: number;\n totalTokens: number;\n costUsd: number;\n}\n\n/** Top threads by cost within the range, capped to this count. */\nconst TOP_THREADS_LIMIT = 10;\n\n/** One point of the timeseries trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface UsageTrendTableRow {\n label: string;\n costUsd: number;\n totalTokens: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** Structural guard so the DI-resolved binding is narrowed without an `as`/`any` cast. */\nfunction isGovernanceQueries(value: unknown): value is AgentGovernanceQueries {\n return (\n isRecord(value) &&\n typeof value.spendByModel === 'function' &&\n typeof value.spendByActor === 'function' &&\n typeof value.spendByThread === 'function' &&\n typeof value.usageTrend === 'function' &&\n typeof value.recentToolCalls === 'function' &&\n typeof value.recentThreads === 'function' &&\n typeof value.runMetrics === 'function' &&\n typeof value.runsByAgent === 'function' &&\n typeof value.runErrors === 'function' &&\n typeof value.runTrend === 'function' &&\n typeof value.recentRuns === 'function' &&\n typeof value.pendingApprovals === 'function' &&\n typeof value.toolStats === 'function'\n );\n}\n\n/**\n * Resolve the governance read-model from the host container. Returns `null` when the host has not\n * bound `AGENT_GOVERNANCE_QUERIES` (missing token throws inside `moduleRef.get`) so panels can render\n * an empty state instead of erroring.\n */\nfunction resolveGovernanceQueries(ctx: ExtensionContext): AgentGovernanceQueries | null {\n let resolved: unknown;\n try {\n resolved = ctx.moduleRef.get(AGENT_GOVERNANCE_QUERIES, { strict: false });\n } catch {\n return null;\n }\n return isGovernanceQueries(resolved) ? resolved : null;\n}\n\nfunction isIsoDay(value: unknown): value is string {\n return typeof value === 'string' && ISO_DAY_PATTERN.test(value);\n}\n\nfunction todayUtcDay(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Shift a `YYYY-MM-DD` UTC day by `deltaDays` (negative goes back in time). */\nexport function shiftUtcDay(day: string, deltaDays: number): string {\n const shifted = new Date(`${day}T00:00:00.000Z`);\n shifted.setUTCDate(shifted.getUTCDate() + deltaDays);\n return shifted.toISOString().slice(0, 10);\n}\n\n/**\n * Derive the query range: honour explicit `fromDay`/`toDay` (validated ISO days), otherwise default\n * to the trailing {@link DEFAULT_TREND_WINDOW_DAYS}-day window ending today (UTC).\n */\nexport function resolveRange(query: Record<string, unknown> | undefined): GovernanceRange {\n const toDay = query && isIsoDay(query.toDay) ? query.toDay : todayUtcDay();\n const fromDay =\n query && isIsoDay(query.fromDay)\n ? query.fromDay\n : shiftUtcDay(toDay, -(DEFAULT_TREND_WINDOW_DAYS - 1));\n return { fromDay, toDay };\n}\n\nfunction roundCents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/** Sum authoritative spend across every model row. */\nexport function totalCostUsd(rows: ModelSpendRow[]): number {\n return roundCents(rows.reduce((sum, row) => sum + row.costUsd, 0));\n}\n\n/** Sum input + output tokens across every model row. */\nexport function totalTokens(rows: ModelSpendRow[]): number {\n return rows.reduce((sum, row) => sum + row.inputTokens + row.outputTokens, 0);\n}\n\n/** Spend-by-model as breakdown segments (models with zero cost are dropped from the donut). */\nexport function toModelSpendSegments(rows: ModelSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.modelId, value: roundCents(row.costUsd) }));\n}\n\n/** Spend-by-model as table rows (cost rounded to cents; usage kept exact). */\nexport function toModelSpendRows(rows: ModelSpendRow[]): ModelSpendTableRow[] {\n return rows.map((row) => ({\n modelId: row.modelId,\n requests: row.requests,\n inputTokens: row.inputTokens,\n outputTokens: row.outputTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as table rows. */\nexport function toActorSpendRows(rows: ActorSpendRow[]): ActorSpendTableRow[] {\n return rows.map((row) => ({\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Top-threads-by-cost as table rows. */\nexport function toThreadSpendRows(rows: ThreadSpendRow[]): ThreadSpendTableRow[] {\n return rows.map((row) => ({\n title: row.title || row.threadId,\n actorRef: row.actorRef,\n requests: row.requests,\n totalTokens: row.totalTokens,\n costUsd: roundCents(row.costUsd),\n }));\n}\n\n/** Spend-by-actor as breakdown segments (actors with zero cost are dropped). */\nexport function toActorSpendSegments(rows: ActorSpendRow[]): BreakdownSegment[] {\n return rows\n .filter((row) => row.costUsd > 0)\n .map((row) => ({ label: row.actorRef, value: roundCents(row.costUsd) }));\n}\n\n/** Daily usage trend as timeseries rows keyed by `label` (the day). */\nexport function toUsageTrendRows(points: UsageTrendPoint[]): UsageTrendTableRow[] {\n return points.map((point) => ({\n label: point.day,\n costUsd: roundCents(point.costUsd),\n totalTokens: point.totalTokens,\n }));\n}\n\n// ─── Run reliability + tools + approvals shaping ─────────────────────────────\n\n/** Placeholder shown for a table cell whose source value is `null`/unmeasured — matches the\n * convention `@dudousxd/nestjs-durable-telescope` uses for the same case (e.g. `fmtNum`). */\nconst NO_VALUE = '—';\n\n/** Run/failure/retry rollup as table rows — `RunAgentBreakdownRow` is already table-shaped. */\nexport function toRunAgentTableRows(\n rows: RunAgentBreakdownRow[],\n): Array<{ agentName: string; runs: number; failed: number; retries: number }> {\n return rows.map((row) => ({\n agentName: row.agentName,\n runs: row.runs,\n failed: row.failed,\n retries: row.retries,\n }));\n}\n\n/** Failed-run counts by error code as breakdown segments. */\nexport function toRunErrorSegments(rows: RunErrorBreakdownRow[]): BreakdownSegment[] {\n return rows.map((row) => ({ label: row.errorCode, value: row.count }));\n}\n\n/** One point of the run/failure trend (Telescope core: `{ label } & Record<string, number>`). */\ninterface RunTrendTableRow {\n label: string;\n runs: number;\n failed: number;\n}\n\n/** Daily run/failure trend as timeseries rows keyed by `label` (the day). */\nexport function toRunTrendRows(points: RunTrendPoint[]): RunTrendTableRow[] {\n return points.map((point) => ({ label: point.day, runs: point.runs, failed: point.failed }));\n}\n\n/** Cap this many characters before a byte length; matches the DB column's practical display width. */\nconst ERROR_MESSAGE_CAP = 500;\n\n/**\n * Cap a run's error message to {@link ERROR_MESSAGE_CAP} characters before it leaves the provider.\n * `DataProvider.resolve` output bypasses Telescope core's `redact()` pipeline — that only runs on\n * entries a `Watcher` records via `ctx.record`, not on values a provider computes and returns\n * directly to a panel — so an unbounded stack trace or secret-laden failure message would ride\n * straight into a table cell with no truncation/redaction safety net. This cap is a stopgap\n * mitigation, not a substitute for the (out-of-scope this wave) telescope-core redaction hook for\n * DataProvider output.\n */\nexport function capErrorMessage(message: string | null): string | null {\n if (message === null) return null;\n return message.length > ERROR_MESSAGE_CAP ? `${message.slice(0, ERROR_MESSAGE_CAP)}…` : message;\n}\n\n/** How many leading hex characters of a promptHash the table shows as a short chip. */\nconst PROMPT_HASH_CHIP_LENGTH = 10;\n\n/** Shorten a full sha256 promptHash to a compact chip for the table column. */\nexport function shortPromptHash(promptHash: string | null): string | null {\n return promptHash === null ? null : promptHash.slice(0, PROMPT_HASH_CHIP_LENGTH);\n}\n\n/** One row of the recent-runs table — every nullable field falls back to {@link NO_VALUE}. */\ninterface RecentRunTableRow {\n startedAt: string;\n runId: string;\n threadId: string;\n actorRef: string;\n agentName: string;\n status: string;\n durationMs: number | string;\n retries: number;\n errorCode: string;\n errorMessage: string;\n promptHash: string;\n}\n\n/** Recent runs as table rows: errorMessage capped, promptHash shortened to a chip. */\nexport function toRecentRunTableRows(rows: RecentRunRow[]): RecentRunTableRow[] {\n return rows.map((row) => ({\n startedAt: row.startedAt,\n runId: row.runId,\n threadId: row.threadId,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n status: row.status,\n durationMs: row.durationMs ?? NO_VALUE,\n retries: row.retries,\n errorCode: row.errorCode ?? NO_VALUE,\n errorMessage: capErrorMessage(row.errorMessage) ?? NO_VALUE,\n promptHash: shortPromptHash(row.promptHash) ?? NO_VALUE,\n }));\n}\n\n/** Recent tool calls as table rows — `ToolCallActivityRow` is already table-shaped. */\nexport function toRecentToolCallRows(rows: ToolCallActivityRow[]): ToolCallActivityRow[] {\n return rows;\n}\n\n/** Recent threads as table rows — `ThreadActivityRow` is already table-shaped. */\nexport function toRecentThreadTableRows(rows: ThreadActivityRow[]): ThreadActivityRow[] {\n return rows;\n}\n\n/** One row of the pending-approvals inbox table, `input` stringified for display. */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n}\n\n/** Pending-approvals rows as table rows (drops the raw `input` — not renderable in a table cell). */\nexport function toPendingApprovalTableRows(rows: PendingApprovalRow[]): PendingApprovalTableRow[] {\n return rows.map((row) => ({\n toolCallId: row.toolCallId,\n toolName: row.toolName,\n threadId: row.threadId,\n threadTitle: row.threadTitle,\n actorRef: row.actorRef,\n agentName: row.agentName ?? NO_VALUE,\n requestedAt: row.requestedAt,\n }));\n}\n\n/** One row of the per-tool stats table, `p95ExecutionMs` falling back to {@link NO_VALUE}. */\ninterface ToolStatTableRow {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n p95ExecutionMs: number | string;\n}\n\n/** Per-tool call/failure/rejection/latency rollup as table rows. */\nexport function toToolStatTableRows(rows: ToolStatRow[]): ToolStatTableRow[] {\n return rows.map((row) => ({\n toolName: row.toolName,\n toolType: row.toolType,\n calls: row.calls,\n failed: row.failed,\n rejected: row.rejected,\n p95ExecutionMs: row.p95ExecutionMs ?? NO_VALUE,\n }));\n}\n\n/** Zero-valued `RunMetrics`, returned when the read-model isn't bound. */\nconst EMPTY_RUN_METRICS: RunMetrics = {\n runs: 0,\n completed: 0,\n failed: 0,\n successRate: 0,\n retries: 0,\n durationP50Ms: null,\n durationP95Ms: null,\n};\n\n/**\n * Build a governance `DataProvider` from a fetch + a format step. Every provider follows the same\n * shape: resolve the read-model, run ONE query over the panel's range, then format the rows into the\n * panel's result shape. When the host hasn't bound the read-model, `fetch` is skipped and `format`\n * runs over `[]` — which is exactly the empty-but-valid shape each formatter already yields (0 for\n * totals, `[]` for segments/rows), so the degraded case needs no special-casing.\n */\nfunction governanceStatProvider<TRow>(\n name: string,\n fetch: (queries: AgentGovernanceQueries, range: GovernanceRange) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveRange(query)) : [];\n return format(rows);\n },\n };\n}\n\n/** stat → authoritative total spend (USD) over the range. */\nexport function agentSpendTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalCost',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalCostUsd(rows) }),\n );\n}\n\n/** stat → authoritative total tokens (input + output) over the range. */\nexport function agentTokensTotalProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.totalTokens',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ value: totalTokens(rows) }),\n );\n}\n\n/** breakdown → spend share per model. */\nexport function agentSpendByModelProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModel',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ segments: toModelSpendSegments(rows) }),\n );\n}\n\n/** table → per-model requests / in+out tokens / cost. */\nexport function agentModelSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byModelTable',\n (queries, range) => queries.spendByModel(range),\n (rows) => ({ rows: toModelSpendRows(rows) }),\n );\n}\n\n/** timeseries → daily spend + tokens trend. */\nexport function agentUsageTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.usage.trend',\n (queries, range) => queries.usageTrend(range),\n (points) => ({ rows: toUsageTrendRows(points) }),\n );\n}\n\n/** table → spend per acting ref (user/tenant). */\nexport function agentActorSpendTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActor',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ rows: toActorSpendRows(rows) }),\n );\n}\n\n/** breakdown → spend share per actor. */\nexport function agentSpendByActorProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.spend.byActorShare',\n (queries, range) => queries.spendByActor(range),\n (rows) => ({ segments: toActorSpendSegments(rows) }),\n );\n}\n\n/** table → top threads by cost (title, actor, requests, tokens, cost). */\nexport function agentTopThreadsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.threads.topSpend',\n (queries, range) => queries.spendByThread(range, TOP_THREADS_LIMIT),\n (rows) => ({ rows: toThreadSpendRows(rows) }),\n );\n}\n\n// ─── Reliability providers ────────────────────────────────────────────────────\n\n/**\n * Build a `DataProvider` from ONE range-scoped `runMetrics` call + a format step — the\n * `governanceStatProvider` pattern specialized for the single-object `RunMetrics` shape (the five\n * reliability stats all reuse the same underlying query, exactly like the spend stats above reuse\n * `spendByModel`). Degrades to {@link EMPTY_RUN_METRICS} when the read-model isn't bound.\n */\nfunction governanceRunMetricsProvider(\n name: string,\n format: (metrics: RunMetrics) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;\n return format(metrics);\n },\n };\n}\n\n/** stat → total runs over the range. */\nexport function agentRunsTotalProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.total', (metrics) => ({ value: metrics.runs }));\n}\n\n/** stat → completed/total success rate over the range. */\nexport function agentRunsSuccessRateProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.successRate', (metrics) => ({\n value: metrics.successRate,\n }));\n}\n\n/** stat → failed run count over the range. */\nexport function agentRunsFailedProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.failed', (metrics) => ({\n value: metrics.failed,\n }));\n}\n\n/** stat → total llm-step retries across the range's runs. */\nexport function agentRunsRetriesProvider(): DataProvider {\n return governanceRunMetricsProvider('agent.runs.retries', (metrics) => ({\n value: metrics.retries,\n }));\n}\n\n/**\n * stat → run duration percentile, selected by `query.metric` (`'p95'` for p95, anything else —\n * including omitted — for p50), mirroring `durable.duration`'s stat shortcut. NOT a\n * `distribution` panel: `RunMetrics` exposes only the two percentiles (no raw per-run samples to\n * bucket into a histogram), so a distribution here would render as a permanently-empty box. A\n * `null` percentile (no settled runs in range) resolves to 0.\n */\nexport function agentRunsDurationProvider(): DataProvider {\n return {\n name: 'agent.runs.duration',\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const metrics = queries ? await queries.runMetrics(resolveRange(query)) : EMPTY_RUN_METRICS;\n const value = query?.metric === 'p95' ? metrics.durationP95Ms : metrics.durationP50Ms;\n return { value: value ?? 0 };\n },\n };\n}\n\n/** table → run/failure/retry rollup per agent. */\nexport function agentRunsByAgentTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.byAgent',\n (queries, range) => queries.runsByAgent(range),\n (rows) => ({ rows: toRunAgentTableRows(rows) }),\n );\n}\n\n/** breakdown → failed runs by error code. */\nexport function agentRunErrorsProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.errors',\n (queries, range) => queries.runErrors(range),\n (rows) => ({ segments: toRunErrorSegments(rows) }),\n );\n}\n\n/** timeseries → daily runs + failures trend. */\nexport function agentRunsTrendProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.runs.trend',\n (queries, range) => queries.runTrend(range),\n (points) => ({ rows: toRunTrendRows(points) }),\n );\n}\n\n// ─── Limit-scoped providers (recent-activity feeds + the approvals inbox) ────\n\n/** Default row count for a \"recent …\" feed when a panel's query omits `limit`. */\nconst DEFAULT_RECENT_LIMIT = 50;\n/** Hard ceiling on `limit`, regardless of what a panel's query requests. */\nconst MAX_RECENT_LIMIT = 500;\n\n/** Clamp a panel-supplied `limit` into `[1, MAX_RECENT_LIMIT]`, defaulting when absent/invalid. */\nfunction resolveLimit(query: Record<string, unknown> | undefined, fallback: number): number {\n const raw = query?.limit;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : fallback;\n return Math.min(MAX_RECENT_LIMIT, Math.max(1, Math.trunc(value)));\n}\n\n/**\n * Build a governance `DataProvider` from a `limit`-scoped fetch + a format step — the sibling of\n * {@link governanceStatProvider} for the read-model's \"recent N\" queries, which take a row cap\n * instead of a day range. Degrades to `[]` when the read-model isn't bound.\n */\nfunction governanceLimitProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, limit: number) => Promise<TRow[]>,\n format: (rows: TRow[]) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await fetch(queries, resolveLimit(query, defaultLimit)) : [];\n return format(rows);\n },\n };\n}\n\n/**\n * table → most recent runs (newest first), errorMessage capped and promptHash shortened to a chip\n * — see {@link capErrorMessage} for why the cap happens here rather than downstream.\n */\nexport function agentRecentRunsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.runs.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentRuns(limit),\n (rows) => ({ rows: toRecentRunTableRows(rows) }),\n );\n}\n\n/**\n * table → most recent tool calls (newest first), from the durable read-model. Replaces the\n * ephemeral, watcher-fed `agent.tools` provider in `agent-data-providers.ts` for the shipped\n * dashboard — see that file's header comment for why.\n */\nexport function agentRecentToolCallsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.tools.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentToolCalls(limit),\n (rows) => ({ rows: toRecentToolCallRows(rows) }),\n );\n}\n\n/** table → most recently active threads, with rolled-up message/token counts. */\nexport function agentRecentThreadsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.threads.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.recentThreads(limit),\n (rows) => ({ rows: toRecentThreadTableRows(rows) }),\n );\n}\n\n/** Row cap used to approximate a \"pending approvals\" COUNT (the SPI only exposes a capped list —\n * see {@link agentPendingApprovalsCountProvider}). */\nconst PENDING_APPROVALS_COUNT_LIMIT = 500;\n\n/**\n * stat → count of tool calls sitting `pending_approval` across every thread. The SPI's\n * `pendingApprovals` only returns a capped list, not a true count, so this undercounts a backlog\n * larger than {@link PENDING_APPROVALS_COUNT_LIMIT} — a backlog that size signals a bigger\n * operational problem than an off-by-N stat, so the approximation is an acceptable tradeoff.\n */\nexport function agentPendingApprovalsCountProvider(): DataProvider {\n return {\n name: 'agent.approvals.pending',\n async resolve(_query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const rows = queries ? await queries.pendingApprovals(PENDING_APPROVALS_COUNT_LIMIT) : [];\n return { value: rows.length };\n },\n };\n}\n\n/** table → the pending-approvals inbox, oldest request first. */\nexport function agentPendingApprovalsTableProvider(): DataProvider {\n return governanceLimitProvider(\n 'agent.approvals.recent',\n DEFAULT_RECENT_LIMIT,\n (queries, limit) => queries.pendingApprovals(limit),\n (rows) => ({ rows: toPendingApprovalTableRows(rows) }),\n );\n}\n\n/** table → per-tool call/failure/rejection/latency rollup over the range. */\nexport function agentToolStatsTableProvider(): DataProvider {\n return governanceStatProvider(\n 'agent.tools.stats',\n (queries, range) => queries.toolStats(range),\n (rows) => ({ rows: toToolStatTableRows(rows) }),\n );\n}\n","import { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport { AGENT_DIAGNOSTIC_EVENTS } from '@dudousxd/nestjs-agent-core';\nimport { channelName, claimDiagnostics } from '@dudousxd/nestjs-diagnostics';\nimport type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';\n\ninterface DiagnosticEnvelope {\n event: string;\n payload: Record<string, unknown>;\n}\n\n/**\n * Records `aviary:agent:*` diagnostics events as Telescope entries of type `agent`. It depends\n * only on the diagnostics channel — not on the agent runtime — so it stays fully decoupled.\n *\n * Iterates {@link AGENT_DIAGNOSTIC_EVENTS} (all 8 point events on `ChannelRegistry['agent']`)\n * rather than a hand-written literal, so `run.failed`/`delegated`/`retrieved` are recorded and\n * tagged — filterable in the Telescope UI — like every other agent event.\n *\n * Coexists with `@dudousxd/nestjs-diagnostics-telescope`'s generic watcher: `register()` CLAIMS\n * every recorded key via `claimDiagnostics('agent', ...)` (diagnostics 0.7+), so the generic\n * bridge skips them at record time instead of duplicating each event as a `diagnostic` entry —\n * no `exclude` wiring needed anymore. `dispose()` releases the claim.\n *\n * Register it with the telescope module's watcher list.\n */\nexport class AgentTelescopeWatcher implements Watcher {\n readonly type = 'agent';\n private readonly disposers: Array<() => void> = [];\n\n register(ctx: WatcherContext): void {\n // Tell the generic diagnostics bridge these keys are recorded here as typed `agent` entries,\n // so it skips them (refcounted; released in dispose()).\n this.disposers.push(claimDiagnostics('agent', AGENT_DIAGNOSTIC_EVENTS));\n for (const event of AGENT_DIAGNOSTIC_EVENTS) {\n const channel = channelName('agent', event);\n const onMessage = (message: unknown) => {\n const envelope = message as DiagnosticEnvelope;\n ctx.record({\n type: 'agent',\n content: { event: envelope.event, ...envelope.payload },\n tags: [envelope.event],\n });\n };\n subscribe(channel, onMessage);\n this.disposers.push(() => unsubscribe(channel, onMessage));\n }\n }\n\n /** Detach all channel subscriptions and release the diagnostics claim (e.g. on module destroy). */\n dispose(): void {\n while (this.disposers.length) this.disposers.pop()?.();\n }\n}\n"],"mappings":"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","names":["defineTelescopeExtension","col","key","label","href","undefined","link","agentDashboard","opts","id","panels","sections","title","cols","kind","data","provider","format","series","style","query","metric","columns","runHref","threadHref","TELESCOPE_STORAGE","fetchEntries","ctx","storage","moduleRef","get","TELESCOPE_STORAGE","strict","page","type","limit","data","ofEvent","entries","event","filter","entry","content","agentRunsProvider","name","resolve","_query","finished","value","length","agentTokensProvider","reduce","sum","inputTokens","outputTokens","agentToolsProvider","calls","slice","reverse","map","toolName","toolType","status","runId","rows","agentToolStatusProvider","counts","Map","call","set","segments","label","AGENT_GOVERNANCE_QUERIES","DEFAULT_TREND_WINDOW_DAYS","ISO_DAY_PATTERN","TOP_THREADS_LIMIT","isRecord","value","isGovernanceQueries","spendByModel","spendByActor","spendByThread","usageTrend","recentToolCalls","recentThreads","runMetrics","runsByAgent","runErrors","runTrend","recentRuns","pendingApprovals","toolStats","resolveGovernanceQueries","ctx","resolved","moduleRef","get","AGENT_GOVERNANCE_QUERIES","strict","isIsoDay","test","todayUtcDay","Date","toISOString","slice","shiftUtcDay","day","deltaDays","shifted","setUTCDate","getUTCDate","resolveRange","query","toDay","fromDay","roundCents","Math","round","totalCostUsd","rows","reduce","sum","row","costUsd","totalTokens","inputTokens","outputTokens","toModelSpendSegments","filter","map","label","modelId","toModelSpendRows","requests","toActorSpendRows","actorRef","toThreadSpendRows","title","threadId","toActorSpendSegments","toUsageTrendRows","points","point","NO_VALUE","toRunAgentTableRows","agentName","runs","failed","retries","toRunErrorSegments","errorCode","count","toRunTrendRows","ERROR_MESSAGE_CAP","capErrorMessage","message","length","PROMPT_HASH_CHIP_LENGTH","shortPromptHash","promptHash","toRecentRunTableRows","startedAt","runId","status","durationMs","errorMessage","toRecentToolCallRows","toRecentThreadTableRows","toPendingApprovalTableRows","toolCallId","toolName","threadTitle","requestedAt","toToolStatTableRows","toolType","calls","rejected","p95ExecutionMs","EMPTY_RUN_METRICS","completed","successRate","durationP50Ms","durationP95Ms","governanceStatProvider","name","fetch","format","resolve","queries","agentSpendTotalProvider","range","agentTokensTotalProvider","agentSpendByModelProvider","segments","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","governanceRunMetricsProvider","metrics","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","metric","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","DEFAULT_RECENT_LIMIT","MAX_RECENT_LIMIT","resolveLimit","fallback","raw","limit","Number","isFinite","min","max","trunc","governanceLimitProvider","defaultLimit","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","PENDING_APPROVALS_COUNT_LIMIT","agentPendingApprovalsCountProvider","_query","agentPendingApprovalsTableProvider","agentToolStatsTableProvider","subscribe","unsubscribe","AGENT_DIAGNOSTIC_EVENTS","channelName","claimDiagnostics","AgentTelescopeWatcher","type","disposers","register","ctx","push","claimDiagnostics","AGENT_DIAGNOSTIC_EVENTS","event","channel","channelName","onMessage","message","envelope","record","content","payload","tags","subscribe","unsubscribe","dispose","length","pop","agentTelescopeExtension","opts","defineTelescopeExtension","name","watchers","AgentTelescopeWatcher","entryTypes","id","label","dot","dashboards","agentDashboard","dataProviders","agentRunsProvider","agentTokensProvider","agentToolStatusProvider","agentSpendTotalProvider","agentTokensTotalProvider","agentSpendByModelProvider","agentModelSpendTableProvider","agentUsageTrendProvider","agentActorSpendTableProvider","agentSpendByActorProvider","agentTopThreadsTableProvider","agentRunsTotalProvider","agentRunsSuccessRateProvider","agentRunsFailedProvider","agentRunsRetriesProvider","agentRunsDurationProvider","agentRunsByAgentTableProvider","agentRunErrorsProvider","agentRunsTrendProvider","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentPendingApprovalsCountProvider","agentPendingApprovalsTableProvider","agentToolStatsTableProvider"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-agent-telescope",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/DavideCarvalho/nestjs-agent.git",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@dudousxd/nestjs-diagnostics": "0.
|
|
33
|
-
"@dudousxd/nestjs-agent-core": "0.
|
|
32
|
+
"@dudousxd/nestjs-diagnostics": "0.7.0",
|
|
33
|
+
"@dudousxd/nestjs-agent-core": "0.7.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@dudousxd/nestjs-telescope": ">=1.15.0"
|