@dudousxd/nestjs-agent-telescope 0.6.1 → 0.7.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 CHANGED
@@ -553,6 +553,10 @@ function agentDashboard(opts = {}) {
553
553
  key: "rejected",
554
554
  label: "Rejected"
555
555
  },
556
+ {
557
+ key: "p50ExecutionMs",
558
+ label: "p50 (ms)"
559
+ },
556
560
  {
557
561
  key: "p95ExecutionMs",
558
562
  label: "p95 (ms)"
@@ -658,7 +662,7 @@ function isRecord(value) {
658
662
  }
659
663
  __name(isRecord, "isRecord");
660
664
  function isGovernanceQueries(value) {
661
- return isRecord(value) && typeof value.spendByModel === "function" && typeof value.spendByActor === "function" && typeof value.spendByThread === "function" && typeof value.usageTrend === "function" && typeof value.recentToolCalls === "function" && typeof value.recentThreads === "function" && typeof value.runMetrics === "function" && typeof value.runsByAgent === "function" && typeof value.runErrors === "function" && typeof value.runTrend === "function" && typeof value.recentRuns === "function" && typeof value.pendingApprovals === "function" && typeof value.toolStats === "function" && typeof value.toolCallsPage === "function" && typeof value.threadsPage === "function" && typeof value.runsPage === "function";
665
+ return isRecord(value) && typeof value.spendByModel === "function" && typeof value.spendByActor === "function" && typeof value.spendByThread === "function" && typeof value.usageTrend === "function" && typeof value.recentToolCalls === "function" && typeof value.recentThreads === "function" && typeof value.runMetrics === "function" && typeof value.runsByAgent === "function" && typeof value.runErrors === "function" && typeof value.runTrend === "function" && typeof value.recentRuns === "function" && typeof value.pendingApprovals === "function" && typeof value.approvalsPage === "function" && typeof value.toolStats === "function" && typeof value.toolCallsPage === "function" && typeof value.threadsPage === "function" && typeof value.runsPage === "function" && typeof value.runDetail === "function" && typeof value.threadDetail === "function";
662
666
  }
663
667
  __name(isGovernanceQueries, "isGovernanceQueries");
664
668
  function resolveGovernanceQueries(ctx) {
@@ -839,6 +843,7 @@ function toToolStatTableRows(rows) {
839
843
  calls: row.calls,
840
844
  failed: row.failed,
841
845
  rejected: row.rejected,
846
+ p50ExecutionMs: row.p50ExecutionMs ?? NO_VALUE,
842
847
  p95ExecutionMs: row.p95ExecutionMs ?? NO_VALUE
843
848
  }));
844
849
  }
@@ -1062,15 +1067,22 @@ function agentRunsPagedTableProvider() {
1062
1067
  return governancePagedTableProvider("agent.runs.paged", DEFAULT_RECENT_LIMIT, (queries, query) => queries.runsPage(query), toRecentRunTableRows);
1063
1068
  }
1064
1069
  __name(agentRunsPagedTableProvider, "agentRunsPagedTableProvider");
1065
- var PENDING_APPROVALS_COUNT_LIMIT = 500;
1066
1070
  function agentPendingApprovalsCountProvider() {
1067
1071
  return {
1068
1072
  name: "agent.approvals.pending",
1069
1073
  async resolve(_query, ctx) {
1070
1074
  const queries = resolveGovernanceQueries(ctx);
1071
- const rows = queries ? await queries.pendingApprovals(PENDING_APPROVALS_COUNT_LIMIT) : [];
1075
+ if (queries === null) {
1076
+ return {
1077
+ value: 0
1078
+ };
1079
+ }
1080
+ const page = await queries.approvalsPage({
1081
+ page: 1,
1082
+ pageSize: 1
1083
+ });
1072
1084
  return {
1073
- value: rows.length
1085
+ value: page.total
1074
1086
  };
1075
1087
  }
1076
1088
  };
@@ -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 agentRunsPagedTableProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentThreadsPagedTableProvider,\n agentTokensTotalProvider,\n agentToolCallsPagedTableProvider,\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` deep-links a table row's `threadId` cell out to the HOST's own thread viewer —\n * passed straight through to {@link agentDashboard}, mirroring `durableTelescopeExtension`'s\n * `runHref` option. A row's `runId` cell instead defaults to the IN-APP trace waterfall\n * (`#/traces/{runId}`, per wave-polish-CONTRACTS.md §A2) — no host wiring needed; `runHref`\n * overrides that default for a host that wants its own run viewer instead.\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 agentRunsPagedTableProvider(),\n agentToolCallsPagedTableProvider(),\n agentThreadsPagedTableProvider(),\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 default in-app trace-waterfall route a `runId` cell deep-links to — the TRACE view's\n * confirmed URL shape (wave-polish-CONTRACTS.md §A2 / `@dudousxd/nestjs-telescope`'s `LinkSpec`\n * doc): an in-app hash route rendered as a plain anchor, no host wiring required. `opts.runHref`\n * overrides this for a host that wants its own run viewer instead — mirrors how\n * `durableDashboard`'s own `runHref` defaults to an internal route (`'/durable/runs/{runId}'`)\n * unless the host supplies one.\n */\nconst DEFAULT_TRACE_HREF = '#/traces/{runId}';\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref` is a URL template for deep-linking a `{threadId}` cell out to the HOST's own thread\n * viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA) — omitted by default (no\n * internal thread view exists), passed straight through when the host supplies one. `runHref` deep-\n * links a `{runId}` cell to the trace waterfall — defaults to {@link DEFAULT_TRACE_HREF} (the\n * in-app route), so a `runId` column works out of the box with no host option needed; a host may\n * still override it. Every table whose rows carry a `threadId`/`runId` gets a `Column.link` for it\n * (via {@link col}); `threadHref` left unset leaves that column plain text.\n *\n * Layout: six sections (Overview lean; Spend; Reliability; Activity; Approvals; Tools), each sized\n * so its panel count is an exact multiple of its `cols` — no half-empty row. `nestjs-telescope`'s\n * `ExtensionDashboardPage` renders a section as a `grid-cols-N` grid with one panel per cell and no\n * `colSpan`, so a lone table in an otherwise-empty row would leave a visible gap next to it.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n const runHref = opts.runHref ?? DEFAULT_TRACE_HREF;\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n // Lean: the headline runs/tokens/success numbers only — Reliability below has the detail.\n title: 'Overview',\n cols: 3,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n ],\n },\n {\n title: 'Spend',\n cols: 4,\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 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 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 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 },\n {\n title: 'Reliability',\n cols: 3,\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 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 // Two duration stats above, not a `distribution` panel: RunMetrics carries only p50/p95\n // (no raw samples to bucket), so a histogram here would be a permanently-empty box.\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: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\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 },\n {\n // The paged list tables: tool calls, threads, runs — each reads the paged SPI\n // (toolCallsPage/threadsPage/runsPage via `agent.*.paged`) and opts into the renderer's\n // pagination (`paged: true`, telescope >= 1.18): prev/next + \"Page X of Y\".\n title: 'Activity',\n cols: 3,\n panels: [\n {\n kind: 'table',\n title: 'Recent runs',\n paged: true,\n data: { provider: 'agent.runs.paged' },\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', 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 kind: 'table',\n title: 'Recent tool calls',\n paged: true,\n data: { provider: 'agent.tools.paged' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('runId', 'Run', runHref),\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n paged: true,\n data: { provider: 'agent.threads.paged' },\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: 2,\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 col('runId', 'Run', runHref),\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 },\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 GovernancePage,\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 typeof value.toolCallsPage === 'function' &&\n typeof value.threadsPage === 'function' &&\n typeof value.runsPage === '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/**\n * One row of the pending-approvals inbox table, `input` stringified for display. `runId` is kept\n * raw (not NO_VALUE-substituted, unlike `agentName`) so the trace-link column's `{runId}` template\n * substitutes a real value when present; a `null` row (recorded before this shipped) renders an\n * empty, inert link cell instead — the `Column.link` primitive has no per-row conditional.\n */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n runId: string | null;\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 runId: row.runId,\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// ─── Paged-table providers (tool calls / threads / runs) ─────────────────────\n//\n// Pinned against wave-polish-CONTRACTS.md §A1 (the ext-dashboard paged-table convention: a table\n// panel opts in with `paged: true`, the UI then re-resolves with `query.page`/`query.limit` and\n// expects `{ rows, total, page, limit }` back instead of a bare rows array). The convention is\n// implemented here at the DATA layer — these three providers already read `query.page`/`query.limit`\n// and return the paged shape — but the three list-table panels in `agent-dashboard.spec-data.ts`\n// don't yet set `paged: true`: the installed `@dudousxd/nestjs-telescope` (1.15.0) predates that\n// field on the table `Panel` variant, so setting it would fail typecheck (excess-property error on\n// the discriminated union). Once nestjs-agent bumps its `@dudousxd/nestjs-telescope` dependency to a\n// version that publishes `paged`, flip the three panels below to `paged: true` — no other change\n// needed, the provider side is already ready.\n\n/** Clamp a panel-supplied `page` to `[1, Infinity)`, defaulting to 1 when absent/invalid. */\nfunction resolvePage(query: Record<string, unknown> | undefined): number {\n const raw = query?.page;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : 1;\n return Math.max(1, Math.trunc(value));\n}\n\n/** The page/limit shape the paged-table providers below build — none of these panels filter by `where`. */\ninterface PagedQuery {\n page: number;\n pageSize: number;\n}\n\n/**\n * Build a governance `DataProvider` for a PAGED list table (A1's convention): reads `query.page`/\n * `query.limit` (clamped, mirroring {@link governanceLimitProvider}'s `limit` handling) and returns\n * `{ rows, total, page, limit }` instead of a bare rows array. Degrades to an empty page (`total: 0`)\n * when the read-model isn't bound.\n */\nfunction governancePagedTableProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, query: PagedQuery) => Promise<GovernancePage<TRow>>,\n format: (rows: TRow[]) => unknown[],\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const page = resolvePage(query);\n const limit = resolveLimit(query, defaultLimit);\n if (!queries) {\n return { rows: [], total: 0, page, limit };\n }\n const resolved = await fetch(queries, { page, pageSize: limit });\n return {\n rows: format(resolved.rows),\n total: resolved.total,\n page: resolved.page,\n limit: resolved.pageSize,\n };\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/**\n * table (paged, A1) → tool-call activity, newest first, via {@link AgentGovernanceQueries.toolCallsPage}\n * rather than the capped `recentToolCalls`. See the \"Paged-table providers\" section above for why\n * the panel wiring can't set `paged: true` yet.\n */\nexport function agentToolCallsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.tools.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.toolCallsPage(query),\n toRecentToolCallRows,\n );\n}\n\n/**\n * table (paged, A1) → thread activity, newest first, via {@link AgentGovernanceQueries.threadsPage}\n * rather than the capped `recentThreads`.\n */\nexport function agentThreadsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.threads.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.threadsPage(query),\n toRecentThreadTableRows,\n );\n}\n\n/**\n * table (paged, A1) → run activity, newest first, via {@link AgentGovernanceQueries.runsPage} rather\n * than the capped `recentRuns`. Rows are shaped identically to {@link agentRecentRunsTableProvider}\n * (errorMessage capped, promptHash shortened).\n */\nexport function agentRunsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.runs.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.runsPage(query),\n toRecentRunTableRows,\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 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","DEFAULT_TRACE_HREF","agentDashboard","opts","runHref","id","panels","sections","title","cols","kind","data","provider","format","style","series","columns","query","metric","paged","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","toolCallsPage","threadsPage","runsPage","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","resolvePage","page","governancePagedTableProvider","total","pageSize","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","agentRunsPagedTableProvider","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","agentRunsPagedTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","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 agentRunsPagedTableProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentThreadsPagedTableProvider,\n agentTokensTotalProvider,\n agentToolCallsPagedTableProvider,\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` deep-links a table row's `threadId` cell out to the HOST's own thread viewer —\n * passed straight through to {@link agentDashboard}, mirroring `durableTelescopeExtension`'s\n * `runHref` option. A row's `runId` cell instead defaults to the IN-APP trace waterfall\n * (`#/traces/{runId}`, per wave-polish-CONTRACTS.md §A2) — no host wiring needed; `runHref`\n * overrides that default for a host that wants its own run viewer instead.\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 agentRunsPagedTableProvider(),\n agentToolCallsPagedTableProvider(),\n agentThreadsPagedTableProvider(),\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 default in-app trace-waterfall route a `runId` cell deep-links to — the TRACE view's\n * confirmed URL shape (wave-polish-CONTRACTS.md §A2 / `@dudousxd/nestjs-telescope`'s `LinkSpec`\n * doc): an in-app hash route rendered as a plain anchor, no host wiring required. `opts.runHref`\n * overrides this for a host that wants its own run viewer instead — mirrors how\n * `durableDashboard`'s own `runHref` defaults to an internal route (`'/durable/runs/{runId}'`)\n * unless the host supplies one.\n */\nconst DEFAULT_TRACE_HREF = '#/traces/{runId}';\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref` is a URL template for deep-linking a `{threadId}` cell out to the HOST's own thread\n * viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA) — omitted by default (no\n * internal thread view exists), passed straight through when the host supplies one. `runHref` deep-\n * links a `{runId}` cell to the trace waterfall — defaults to {@link DEFAULT_TRACE_HREF} (the\n * in-app route), so a `runId` column works out of the box with no host option needed; a host may\n * still override it. Every table whose rows carry a `threadId`/`runId` gets a `Column.link` for it\n * (via {@link col}); `threadHref` left unset leaves that column plain text.\n *\n * Layout: six sections (Overview lean; Spend; Reliability; Activity; Approvals; Tools), each sized\n * so its panel count is an exact multiple of its `cols` — no half-empty row. `nestjs-telescope`'s\n * `ExtensionDashboardPage` renders a section as a `grid-cols-N` grid with one panel per cell and no\n * `colSpan`, so a lone table in an otherwise-empty row would leave a visible gap next to it.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n const runHref = opts.runHref ?? DEFAULT_TRACE_HREF;\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n // Lean: the headline runs/tokens/success numbers only — Reliability below has the detail.\n title: 'Overview',\n cols: 3,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n ],\n },\n {\n title: 'Spend',\n cols: 4,\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 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 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 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 },\n {\n title: 'Reliability',\n cols: 3,\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 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 // Two duration stats above, not a `distribution` panel: RunMetrics carries only p50/p95\n // (no raw samples to bucket), so a histogram here would be a permanently-empty box.\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: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\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 },\n {\n // The paged list tables: tool calls, threads, runs — each reads the paged SPI\n // (toolCallsPage/threadsPage/runsPage via `agent.*.paged`) and opts into the renderer's\n // pagination (`paged: true`, telescope >= 1.18): prev/next + \"Page X of Y\".\n title: 'Activity',\n cols: 3,\n panels: [\n {\n kind: 'table',\n title: 'Recent runs',\n paged: true,\n data: { provider: 'agent.runs.paged' },\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', 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 kind: 'table',\n title: 'Recent tool calls',\n paged: true,\n data: { provider: 'agent.tools.paged' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('runId', 'Run', runHref),\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n paged: true,\n data: { provider: 'agent.threads.paged' },\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: 2,\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 col('runId', 'Run', runHref),\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: 'p50ExecutionMs', label: 'p50 (ms)' },\n { key: 'p95ExecutionMs', label: 'p95 (ms)' },\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 GovernancePage,\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.approvalsPage === 'function' &&\n typeof value.toolStats === 'function' &&\n typeof value.toolCallsPage === 'function' &&\n typeof value.threadsPage === 'function' &&\n typeof value.runsPage === 'function' &&\n typeof value.runDetail === 'function' &&\n typeof value.threadDetail === '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/**\n * One row of the pending-approvals inbox table, `input` stringified for display. `runId` is kept\n * raw (not NO_VALUE-substituted, unlike `agentName`) so the trace-link column's `{runId}` template\n * substitutes a real value when present; a `null` row (recorded before this shipped) renders an\n * empty, inert link cell instead — the `Column.link` primitive has no per-row conditional.\n */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n runId: string | null;\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 runId: row.runId,\n }));\n}\n\n/** One row of the per-tool stats table, each latency falling back to {@link NO_VALUE}. */\ninterface ToolStatTableRow {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n p50ExecutionMs: number | string;\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 p50ExecutionMs: row.p50ExecutionMs ?? NO_VALUE,\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// ─── Paged-table providers (tool calls / threads / runs) ─────────────────────\n//\n// Pinned against wave-polish-CONTRACTS.md §A1 (the ext-dashboard paged-table convention: a table\n// panel opts in with `paged: true`, the UI then re-resolves with `query.page`/`query.limit` and\n// expects `{ rows, total, page, limit }` back instead of a bare rows array). The convention is\n// implemented here at the DATA layer — these three providers already read `query.page`/`query.limit`\n// and return the paged shape — but the three list-table panels in `agent-dashboard.spec-data.ts`\n// don't yet set `paged: true`: the installed `@dudousxd/nestjs-telescope` (1.15.0) predates that\n// field on the table `Panel` variant, so setting it would fail typecheck (excess-property error on\n// the discriminated union). Once nestjs-agent bumps its `@dudousxd/nestjs-telescope` dependency to a\n// version that publishes `paged`, flip the three panels below to `paged: true` — no other change\n// needed, the provider side is already ready.\n\n/** Clamp a panel-supplied `page` to `[1, Infinity)`, defaulting to 1 when absent/invalid. */\nfunction resolvePage(query: Record<string, unknown> | undefined): number {\n const raw = query?.page;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : 1;\n return Math.max(1, Math.trunc(value));\n}\n\n/** The page/limit shape the paged-table providers below build — none of these panels filter by `where`. */\ninterface PagedQuery {\n page: number;\n pageSize: number;\n}\n\n/**\n * Build a governance `DataProvider` for a PAGED list table (A1's convention): reads `query.page`/\n * `query.limit` (clamped, mirroring {@link governanceLimitProvider}'s `limit` handling) and returns\n * `{ rows, total, page, limit }` instead of a bare rows array. Degrades to an empty page (`total: 0`)\n * when the read-model isn't bound.\n */\nfunction governancePagedTableProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, query: PagedQuery) => Promise<GovernancePage<TRow>>,\n format: (rows: TRow[]) => unknown[],\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const page = resolvePage(query);\n const limit = resolveLimit(query, defaultLimit);\n if (!queries) {\n return { rows: [], total: 0, page, limit };\n }\n const resolved = await fetch(queries, { page, pageSize: limit });\n return {\n rows: format(resolved.rows),\n total: resolved.total,\n page: resolved.page,\n limit: resolved.pageSize,\n };\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/**\n * table (paged, A1) → tool-call activity, newest first, via {@link AgentGovernanceQueries.toolCallsPage}\n * rather than the capped `recentToolCalls`. See the \"Paged-table providers\" section above for why\n * the panel wiring can't set `paged: true` yet.\n */\nexport function agentToolCallsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.tools.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.toolCallsPage(query),\n toRecentToolCallRows,\n );\n}\n\n/**\n * table (paged, A1) → thread activity, newest first, via {@link AgentGovernanceQueries.threadsPage}\n * rather than the capped `recentThreads`.\n */\nexport function agentThreadsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.threads.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.threadsPage(query),\n toRecentThreadTableRows,\n );\n}\n\n/**\n * table (paged, A1) → run activity, newest first, via {@link AgentGovernanceQueries.runsPage} rather\n * than the capped `recentRuns`. Rows are shaped identically to {@link agentRecentRunsTableProvider}\n * (errorMessage capped, promptHash shortened).\n */\nexport function agentRunsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.runs.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.runsPage(query),\n toRecentRunTableRows,\n );\n}\n\n/**\n * stat → count of tool calls sitting `pending_approval` across every thread. Reads `approvalsPage`\n * for the smallest possible page and takes its `total`: an EXACT count, where the previous\n * `pendingApprovals(500).length` silently undercounted any backlog past its row cap — precisely the\n * backlog an operator most needs the stat to be right about.\n */\nexport function agentPendingApprovalsCountProvider(): DataProvider {\n return {\n name: 'agent.approvals.pending',\n async resolve(_query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n if (queries === null) {\n return { value: 0 };\n }\n const page = await queries.approvalsPage({ page: 1, pageSize: 1 });\n return { value: page.total };\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 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","DEFAULT_TRACE_HREF","agentDashboard","opts","runHref","id","panels","sections","title","cols","kind","data","provider","format","style","series","columns","query","metric","paged","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","approvalsPage","toolStats","toolCallsPage","threadsPage","runsPage","runDetail","threadDetail","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","p50ExecutionMs","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","resolvePage","page","governancePagedTableProvider","total","pageSize","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","agentRunsPagedTableProvider","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","agentRunsPagedTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","agentPendingApprovalsCountProvider","agentPendingApprovalsTableProvider","agentToolStatsTableProvider"]}
package/dist/index.d.cts CHANGED
@@ -221,13 +221,14 @@ interface PendingApprovalTableRow {
221
221
  }
222
222
  /** Pending-approvals rows as table rows (drops the raw `input` — not renderable in a table cell). */
223
223
  declare function toPendingApprovalTableRows(rows: PendingApprovalRow[]): PendingApprovalTableRow[];
224
- /** One row of the per-tool stats table, `p95ExecutionMs` falling back to {@link NO_VALUE}. */
224
+ /** One row of the per-tool stats table, each latency falling back to {@link NO_VALUE}. */
225
225
  interface ToolStatTableRow {
226
226
  toolName: string;
227
227
  toolType: string;
228
228
  calls: number;
229
229
  failed: number;
230
230
  rejected: number;
231
+ p50ExecutionMs: number | string;
231
232
  p95ExecutionMs: number | string;
232
233
  }
233
234
  /** Per-tool call/failure/rejection/latency rollup as table rows. */
@@ -284,10 +285,10 @@ declare function agentRecentToolCallsTableProvider(): DataProvider;
284
285
  /** table → most recently active threads, with rolled-up message/token counts. */
285
286
  declare function agentRecentThreadsTableProvider(): DataProvider;
286
287
  /**
287
- * stat → count of tool calls sitting `pending_approval` across every thread. The SPI's
288
- * `pendingApprovals` only returns a capped list, not a true count, so this undercounts a backlog
289
- * larger than {@link PENDING_APPROVALS_COUNT_LIMIT} a backlog that size signals a bigger
290
- * operational problem than an off-by-N stat, so the approximation is an acceptable tradeoff.
288
+ * stat → count of tool calls sitting `pending_approval` across every thread. Reads `approvalsPage`
289
+ * for the smallest possible page and takes its `total`: an EXACT count, where the previous
290
+ * `pendingApprovals(500).length` silently undercounted any backlog past its row cap precisely the
291
+ * backlog an operator most needs the stat to be right about.
291
292
  */
292
293
  declare function agentPendingApprovalsCountProvider(): DataProvider;
293
294
  /** table → the pending-approvals inbox, oldest request first. */
package/dist/index.d.ts CHANGED
@@ -221,13 +221,14 @@ interface PendingApprovalTableRow {
221
221
  }
222
222
  /** Pending-approvals rows as table rows (drops the raw `input` — not renderable in a table cell). */
223
223
  declare function toPendingApprovalTableRows(rows: PendingApprovalRow[]): PendingApprovalTableRow[];
224
- /** One row of the per-tool stats table, `p95ExecutionMs` falling back to {@link NO_VALUE}. */
224
+ /** One row of the per-tool stats table, each latency falling back to {@link NO_VALUE}. */
225
225
  interface ToolStatTableRow {
226
226
  toolName: string;
227
227
  toolType: string;
228
228
  calls: number;
229
229
  failed: number;
230
230
  rejected: number;
231
+ p50ExecutionMs: number | string;
231
232
  p95ExecutionMs: number | string;
232
233
  }
233
234
  /** Per-tool call/failure/rejection/latency rollup as table rows. */
@@ -284,10 +285,10 @@ declare function agentRecentToolCallsTableProvider(): DataProvider;
284
285
  /** table → most recently active threads, with rolled-up message/token counts. */
285
286
  declare function agentRecentThreadsTableProvider(): DataProvider;
286
287
  /**
287
- * stat → count of tool calls sitting `pending_approval` across every thread. The SPI's
288
- * `pendingApprovals` only returns a capped list, not a true count, so this undercounts a backlog
289
- * larger than {@link PENDING_APPROVALS_COUNT_LIMIT} a backlog that size signals a bigger
290
- * operational problem than an off-by-N stat, so the approximation is an acceptable tradeoff.
288
+ * stat → count of tool calls sitting `pending_approval` across every thread. Reads `approvalsPage`
289
+ * for the smallest possible page and takes its `total`: an EXACT count, where the previous
290
+ * `pendingApprovals(500).length` silently undercounted any backlog past its row cap precisely the
291
+ * backlog an operator most needs the stat to be right about.
291
292
  */
292
293
  declare function agentPendingApprovalsCountProvider(): DataProvider;
293
294
  /** table → the pending-approvals inbox, oldest request first. */
package/dist/index.js CHANGED
@@ -481,6 +481,10 @@ function agentDashboard(opts = {}) {
481
481
  key: "rejected",
482
482
  label: "Rejected"
483
483
  },
484
+ {
485
+ key: "p50ExecutionMs",
486
+ label: "p50 (ms)"
487
+ },
484
488
  {
485
489
  key: "p95ExecutionMs",
486
490
  label: "p95 (ms)"
@@ -586,7 +590,7 @@ function isRecord(value) {
586
590
  }
587
591
  __name(isRecord, "isRecord");
588
592
  function isGovernanceQueries(value) {
589
- return isRecord(value) && typeof value.spendByModel === "function" && typeof value.spendByActor === "function" && typeof value.spendByThread === "function" && typeof value.usageTrend === "function" && typeof value.recentToolCalls === "function" && typeof value.recentThreads === "function" && typeof value.runMetrics === "function" && typeof value.runsByAgent === "function" && typeof value.runErrors === "function" && typeof value.runTrend === "function" && typeof value.recentRuns === "function" && typeof value.pendingApprovals === "function" && typeof value.toolStats === "function" && typeof value.toolCallsPage === "function" && typeof value.threadsPage === "function" && typeof value.runsPage === "function";
593
+ return isRecord(value) && typeof value.spendByModel === "function" && typeof value.spendByActor === "function" && typeof value.spendByThread === "function" && typeof value.usageTrend === "function" && typeof value.recentToolCalls === "function" && typeof value.recentThreads === "function" && typeof value.runMetrics === "function" && typeof value.runsByAgent === "function" && typeof value.runErrors === "function" && typeof value.runTrend === "function" && typeof value.recentRuns === "function" && typeof value.pendingApprovals === "function" && typeof value.approvalsPage === "function" && typeof value.toolStats === "function" && typeof value.toolCallsPage === "function" && typeof value.threadsPage === "function" && typeof value.runsPage === "function" && typeof value.runDetail === "function" && typeof value.threadDetail === "function";
590
594
  }
591
595
  __name(isGovernanceQueries, "isGovernanceQueries");
592
596
  function resolveGovernanceQueries(ctx) {
@@ -767,6 +771,7 @@ function toToolStatTableRows(rows) {
767
771
  calls: row.calls,
768
772
  failed: row.failed,
769
773
  rejected: row.rejected,
774
+ p50ExecutionMs: row.p50ExecutionMs ?? NO_VALUE,
770
775
  p95ExecutionMs: row.p95ExecutionMs ?? NO_VALUE
771
776
  }));
772
777
  }
@@ -990,15 +995,22 @@ function agentRunsPagedTableProvider() {
990
995
  return governancePagedTableProvider("agent.runs.paged", DEFAULT_RECENT_LIMIT, (queries, query) => queries.runsPage(query), toRecentRunTableRows);
991
996
  }
992
997
  __name(agentRunsPagedTableProvider, "agentRunsPagedTableProvider");
993
- var PENDING_APPROVALS_COUNT_LIMIT = 500;
994
998
  function agentPendingApprovalsCountProvider() {
995
999
  return {
996
1000
  name: "agent.approvals.pending",
997
1001
  async resolve(_query, ctx) {
998
1002
  const queries = resolveGovernanceQueries(ctx);
999
- const rows = queries ? await queries.pendingApprovals(PENDING_APPROVALS_COUNT_LIMIT) : [];
1003
+ if (queries === null) {
1004
+ return {
1005
+ value: 0
1006
+ };
1007
+ }
1008
+ const page = await queries.approvalsPage({
1009
+ page: 1,
1010
+ pageSize: 1
1011
+ });
1000
1012
  return {
1001
- value: rows.length
1013
+ value: page.total
1002
1014
  };
1003
1015
  }
1004
1016
  };
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 agentRunsPagedTableProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentThreadsPagedTableProvider,\n agentTokensTotalProvider,\n agentToolCallsPagedTableProvider,\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` deep-links a table row's `threadId` cell out to the HOST's own thread viewer —\n * passed straight through to {@link agentDashboard}, mirroring `durableTelescopeExtension`'s\n * `runHref` option. A row's `runId` cell instead defaults to the IN-APP trace waterfall\n * (`#/traces/{runId}`, per wave-polish-CONTRACTS.md §A2) — no host wiring needed; `runHref`\n * overrides that default for a host that wants its own run viewer instead.\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 agentRunsPagedTableProvider(),\n agentToolCallsPagedTableProvider(),\n agentThreadsPagedTableProvider(),\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 default in-app trace-waterfall route a `runId` cell deep-links to — the TRACE view's\n * confirmed URL shape (wave-polish-CONTRACTS.md §A2 / `@dudousxd/nestjs-telescope`'s `LinkSpec`\n * doc): an in-app hash route rendered as a plain anchor, no host wiring required. `opts.runHref`\n * overrides this for a host that wants its own run viewer instead — mirrors how\n * `durableDashboard`'s own `runHref` defaults to an internal route (`'/durable/runs/{runId}'`)\n * unless the host supplies one.\n */\nconst DEFAULT_TRACE_HREF = '#/traces/{runId}';\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref` is a URL template for deep-linking a `{threadId}` cell out to the HOST's own thread\n * viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA) — omitted by default (no\n * internal thread view exists), passed straight through when the host supplies one. `runHref` deep-\n * links a `{runId}` cell to the trace waterfall — defaults to {@link DEFAULT_TRACE_HREF} (the\n * in-app route), so a `runId` column works out of the box with no host option needed; a host may\n * still override it. Every table whose rows carry a `threadId`/`runId` gets a `Column.link` for it\n * (via {@link col}); `threadHref` left unset leaves that column plain text.\n *\n * Layout: six sections (Overview lean; Spend; Reliability; Activity; Approvals; Tools), each sized\n * so its panel count is an exact multiple of its `cols` — no half-empty row. `nestjs-telescope`'s\n * `ExtensionDashboardPage` renders a section as a `grid-cols-N` grid with one panel per cell and no\n * `colSpan`, so a lone table in an otherwise-empty row would leave a visible gap next to it.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n const runHref = opts.runHref ?? DEFAULT_TRACE_HREF;\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n // Lean: the headline runs/tokens/success numbers only — Reliability below has the detail.\n title: 'Overview',\n cols: 3,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n ],\n },\n {\n title: 'Spend',\n cols: 4,\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 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 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 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 },\n {\n title: 'Reliability',\n cols: 3,\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 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 // Two duration stats above, not a `distribution` panel: RunMetrics carries only p50/p95\n // (no raw samples to bucket), so a histogram here would be a permanently-empty box.\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: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\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 },\n {\n // The paged list tables: tool calls, threads, runs — each reads the paged SPI\n // (toolCallsPage/threadsPage/runsPage via `agent.*.paged`) and opts into the renderer's\n // pagination (`paged: true`, telescope >= 1.18): prev/next + \"Page X of Y\".\n title: 'Activity',\n cols: 3,\n panels: [\n {\n kind: 'table',\n title: 'Recent runs',\n paged: true,\n data: { provider: 'agent.runs.paged' },\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', 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 kind: 'table',\n title: 'Recent tool calls',\n paged: true,\n data: { provider: 'agent.tools.paged' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('runId', 'Run', runHref),\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n paged: true,\n data: { provider: 'agent.threads.paged' },\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: 2,\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 col('runId', 'Run', runHref),\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 },\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 GovernancePage,\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 typeof value.toolCallsPage === 'function' &&\n typeof value.threadsPage === 'function' &&\n typeof value.runsPage === '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/**\n * One row of the pending-approvals inbox table, `input` stringified for display. `runId` is kept\n * raw (not NO_VALUE-substituted, unlike `agentName`) so the trace-link column's `{runId}` template\n * substitutes a real value when present; a `null` row (recorded before this shipped) renders an\n * empty, inert link cell instead — the `Column.link` primitive has no per-row conditional.\n */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n runId: string | null;\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 runId: row.runId,\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// ─── Paged-table providers (tool calls / threads / runs) ─────────────────────\n//\n// Pinned against wave-polish-CONTRACTS.md §A1 (the ext-dashboard paged-table convention: a table\n// panel opts in with `paged: true`, the UI then re-resolves with `query.page`/`query.limit` and\n// expects `{ rows, total, page, limit }` back instead of a bare rows array). The convention is\n// implemented here at the DATA layer — these three providers already read `query.page`/`query.limit`\n// and return the paged shape — but the three list-table panels in `agent-dashboard.spec-data.ts`\n// don't yet set `paged: true`: the installed `@dudousxd/nestjs-telescope` (1.15.0) predates that\n// field on the table `Panel` variant, so setting it would fail typecheck (excess-property error on\n// the discriminated union). Once nestjs-agent bumps its `@dudousxd/nestjs-telescope` dependency to a\n// version that publishes `paged`, flip the three panels below to `paged: true` — no other change\n// needed, the provider side is already ready.\n\n/** Clamp a panel-supplied `page` to `[1, Infinity)`, defaulting to 1 when absent/invalid. */\nfunction resolvePage(query: Record<string, unknown> | undefined): number {\n const raw = query?.page;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : 1;\n return Math.max(1, Math.trunc(value));\n}\n\n/** The page/limit shape the paged-table providers below build — none of these panels filter by `where`. */\ninterface PagedQuery {\n page: number;\n pageSize: number;\n}\n\n/**\n * Build a governance `DataProvider` for a PAGED list table (A1's convention): reads `query.page`/\n * `query.limit` (clamped, mirroring {@link governanceLimitProvider}'s `limit` handling) and returns\n * `{ rows, total, page, limit }` instead of a bare rows array. Degrades to an empty page (`total: 0`)\n * when the read-model isn't bound.\n */\nfunction governancePagedTableProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, query: PagedQuery) => Promise<GovernancePage<TRow>>,\n format: (rows: TRow[]) => unknown[],\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const page = resolvePage(query);\n const limit = resolveLimit(query, defaultLimit);\n if (!queries) {\n return { rows: [], total: 0, page, limit };\n }\n const resolved = await fetch(queries, { page, pageSize: limit });\n return {\n rows: format(resolved.rows),\n total: resolved.total,\n page: resolved.page,\n limit: resolved.pageSize,\n };\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/**\n * table (paged, A1) → tool-call activity, newest first, via {@link AgentGovernanceQueries.toolCallsPage}\n * rather than the capped `recentToolCalls`. See the \"Paged-table providers\" section above for why\n * the panel wiring can't set `paged: true` yet.\n */\nexport function agentToolCallsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.tools.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.toolCallsPage(query),\n toRecentToolCallRows,\n );\n}\n\n/**\n * table (paged, A1) → thread activity, newest first, via {@link AgentGovernanceQueries.threadsPage}\n * rather than the capped `recentThreads`.\n */\nexport function agentThreadsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.threads.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.threadsPage(query),\n toRecentThreadTableRows,\n );\n}\n\n/**\n * table (paged, A1) → run activity, newest first, via {@link AgentGovernanceQueries.runsPage} rather\n * than the capped `recentRuns`. Rows are shaped identically to {@link agentRecentRunsTableProvider}\n * (errorMessage capped, promptHash shortened).\n */\nexport function agentRunsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.runs.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.runsPage(query),\n toRecentRunTableRows,\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 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","DEFAULT_TRACE_HREF","agentDashboard","opts","runHref","id","panels","sections","title","cols","kind","data","provider","format","style","series","columns","query","metric","paged","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","toolCallsPage","threadsPage","runsPage","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","resolvePage","page","governancePagedTableProvider","total","pageSize","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","agentRunsPagedTableProvider","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","agentRunsPagedTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","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 agentRunsPagedTableProvider,\n agentRunsRetriesProvider,\n agentRunsSuccessRateProvider,\n agentRunsTotalProvider,\n agentRunsTrendProvider,\n agentSpendByActorProvider,\n agentSpendByModelProvider,\n agentSpendTotalProvider,\n agentThreadsPagedTableProvider,\n agentTokensTotalProvider,\n agentToolCallsPagedTableProvider,\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` deep-links a table row's `threadId` cell out to the HOST's own thread viewer —\n * passed straight through to {@link agentDashboard}, mirroring `durableTelescopeExtension`'s\n * `runHref` option. A row's `runId` cell instead defaults to the IN-APP trace waterfall\n * (`#/traces/{runId}`, per wave-polish-CONTRACTS.md §A2) — no host wiring needed; `runHref`\n * overrides that default for a host that wants its own run viewer instead.\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 agentRunsPagedTableProvider(),\n agentToolCallsPagedTableProvider(),\n agentThreadsPagedTableProvider(),\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 default in-app trace-waterfall route a `runId` cell deep-links to — the TRACE view's\n * confirmed URL shape (wave-polish-CONTRACTS.md §A2 / `@dudousxd/nestjs-telescope`'s `LinkSpec`\n * doc): an in-app hash route rendered as a plain anchor, no host wiring required. `opts.runHref`\n * overrides this for a host that wants its own run viewer instead — mirrors how\n * `durableDashboard`'s own `runHref` defaults to an internal route (`'/durable/runs/{runId}'`)\n * unless the host supplies one.\n */\nconst DEFAULT_TRACE_HREF = '#/traces/{runId}';\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref` is a URL template for deep-linking a `{threadId}` cell out to the HOST's own thread\n * viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA) — omitted by default (no\n * internal thread view exists), passed straight through when the host supplies one. `runHref` deep-\n * links a `{runId}` cell to the trace waterfall — defaults to {@link DEFAULT_TRACE_HREF} (the\n * in-app route), so a `runId` column works out of the box with no host option needed; a host may\n * still override it. Every table whose rows carry a `threadId`/`runId` gets a `Column.link` for it\n * (via {@link col}); `threadHref` left unset leaves that column plain text.\n *\n * Layout: six sections (Overview lean; Spend; Reliability; Activity; Approvals; Tools), each sized\n * so its panel count is an exact multiple of its `cols` — no half-empty row. `nestjs-telescope`'s\n * `ExtensionDashboardPage` renders a section as a `grid-cols-N` grid with one panel per cell and no\n * `colSpan`, so a lone table in an otherwise-empty row would leave a visible gap next to it.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string } = {},\n): DashboardSpec {\n const runHref = opts.runHref ?? DEFAULT_TRACE_HREF;\n return {\n id: 'agent.overview',\n label: 'Agent',\n panels: [],\n sections: [\n {\n // Lean: the headline runs/tokens/success numbers only — Reliability below has the detail.\n title: 'Overview',\n cols: 3,\n panels: [\n { kind: 'stat', title: 'Runs', data: { provider: 'agent.runs' } },\n { kind: 'stat', title: 'Tokens', data: { provider: 'agent.tokens' } },\n {\n kind: 'stat',\n title: 'Success rate',\n data: { provider: 'agent.runs.successRate' },\n format: 'percent',\n },\n ],\n },\n {\n title: 'Spend',\n cols: 4,\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 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 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 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 },\n {\n title: 'Reliability',\n cols: 3,\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 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 // Two duration stats above, not a `distribution` panel: RunMetrics carries only p50/p95\n // (no raw samples to bucket), so a histogram here would be a permanently-empty box.\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: 'breakdown',\n title: 'Run errors',\n data: { provider: 'agent.runs.errors' },\n style: 'donut',\n },\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 },\n {\n // The paged list tables: tool calls, threads, runs — each reads the paged SPI\n // (toolCallsPage/threadsPage/runsPage via `agent.*.paged`) and opts into the renderer's\n // pagination (`paged: true`, telescope >= 1.18): prev/next + \"Page X of Y\".\n title: 'Activity',\n cols: 3,\n panels: [\n {\n kind: 'table',\n title: 'Recent runs',\n paged: true,\n data: { provider: 'agent.runs.paged' },\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', 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 kind: 'table',\n title: 'Recent tool calls',\n paged: true,\n data: { provider: 'agent.tools.paged' },\n columns: [\n { key: 'createdAt', label: 'When' },\n { key: 'toolName', label: 'Tool' },\n { key: 'toolType', label: 'Type' },\n { key: 'status', label: 'Status' },\n col('runId', 'Run', runHref),\n col('threadId', 'Thread', opts.threadHref),\n ],\n },\n {\n kind: 'table',\n title: 'Recently active threads',\n paged: true,\n data: { provider: 'agent.threads.paged' },\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: 2,\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 col('runId', 'Run', runHref),\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: 'p50ExecutionMs', label: 'p50 (ms)' },\n { key: 'p95ExecutionMs', label: 'p95 (ms)' },\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 GovernancePage,\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.approvalsPage === 'function' &&\n typeof value.toolStats === 'function' &&\n typeof value.toolCallsPage === 'function' &&\n typeof value.threadsPage === 'function' &&\n typeof value.runsPage === 'function' &&\n typeof value.runDetail === 'function' &&\n typeof value.threadDetail === '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/**\n * One row of the pending-approvals inbox table, `input` stringified for display. `runId` is kept\n * raw (not NO_VALUE-substituted, unlike `agentName`) so the trace-link column's `{runId}` template\n * substitutes a real value when present; a `null` row (recorded before this shipped) renders an\n * empty, inert link cell instead — the `Column.link` primitive has no per-row conditional.\n */\ninterface PendingApprovalTableRow {\n toolCallId: string;\n toolName: string;\n threadId: string;\n threadTitle: string;\n actorRef: string;\n agentName: string;\n requestedAt: string;\n runId: string | null;\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 runId: row.runId,\n }));\n}\n\n/** One row of the per-tool stats table, each latency falling back to {@link NO_VALUE}. */\ninterface ToolStatTableRow {\n toolName: string;\n toolType: string;\n calls: number;\n failed: number;\n rejected: number;\n p50ExecutionMs: number | string;\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 p50ExecutionMs: row.p50ExecutionMs ?? NO_VALUE,\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// ─── Paged-table providers (tool calls / threads / runs) ─────────────────────\n//\n// Pinned against wave-polish-CONTRACTS.md §A1 (the ext-dashboard paged-table convention: a table\n// panel opts in with `paged: true`, the UI then re-resolves with `query.page`/`query.limit` and\n// expects `{ rows, total, page, limit }` back instead of a bare rows array). The convention is\n// implemented here at the DATA layer — these three providers already read `query.page`/`query.limit`\n// and return the paged shape — but the three list-table panels in `agent-dashboard.spec-data.ts`\n// don't yet set `paged: true`: the installed `@dudousxd/nestjs-telescope` (1.15.0) predates that\n// field on the table `Panel` variant, so setting it would fail typecheck (excess-property error on\n// the discriminated union). Once nestjs-agent bumps its `@dudousxd/nestjs-telescope` dependency to a\n// version that publishes `paged`, flip the three panels below to `paged: true` — no other change\n// needed, the provider side is already ready.\n\n/** Clamp a panel-supplied `page` to `[1, Infinity)`, defaulting to 1 when absent/invalid. */\nfunction resolvePage(query: Record<string, unknown> | undefined): number {\n const raw = query?.page;\n const value = typeof raw === 'number' && Number.isFinite(raw) ? raw : 1;\n return Math.max(1, Math.trunc(value));\n}\n\n/** The page/limit shape the paged-table providers below build — none of these panels filter by `where`. */\ninterface PagedQuery {\n page: number;\n pageSize: number;\n}\n\n/**\n * Build a governance `DataProvider` for a PAGED list table (A1's convention): reads `query.page`/\n * `query.limit` (clamped, mirroring {@link governanceLimitProvider}'s `limit` handling) and returns\n * `{ rows, total, page, limit }` instead of a bare rows array. Degrades to an empty page (`total: 0`)\n * when the read-model isn't bound.\n */\nfunction governancePagedTableProvider<TRow>(\n name: string,\n defaultLimit: number,\n fetch: (queries: AgentGovernanceQueries, query: PagedQuery) => Promise<GovernancePage<TRow>>,\n format: (rows: TRow[]) => unknown[],\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n const page = resolvePage(query);\n const limit = resolveLimit(query, defaultLimit);\n if (!queries) {\n return { rows: [], total: 0, page, limit };\n }\n const resolved = await fetch(queries, { page, pageSize: limit });\n return {\n rows: format(resolved.rows),\n total: resolved.total,\n page: resolved.page,\n limit: resolved.pageSize,\n };\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/**\n * table (paged, A1) → tool-call activity, newest first, via {@link AgentGovernanceQueries.toolCallsPage}\n * rather than the capped `recentToolCalls`. See the \"Paged-table providers\" section above for why\n * the panel wiring can't set `paged: true` yet.\n */\nexport function agentToolCallsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.tools.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.toolCallsPage(query),\n toRecentToolCallRows,\n );\n}\n\n/**\n * table (paged, A1) → thread activity, newest first, via {@link AgentGovernanceQueries.threadsPage}\n * rather than the capped `recentThreads`.\n */\nexport function agentThreadsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.threads.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.threadsPage(query),\n toRecentThreadTableRows,\n );\n}\n\n/**\n * table (paged, A1) → run activity, newest first, via {@link AgentGovernanceQueries.runsPage} rather\n * than the capped `recentRuns`. Rows are shaped identically to {@link agentRecentRunsTableProvider}\n * (errorMessage capped, promptHash shortened).\n */\nexport function agentRunsPagedTableProvider(): DataProvider {\n return governancePagedTableProvider(\n 'agent.runs.paged',\n DEFAULT_RECENT_LIMIT,\n (queries, query) => queries.runsPage(query),\n toRecentRunTableRows,\n );\n}\n\n/**\n * stat → count of tool calls sitting `pending_approval` across every thread. Reads `approvalsPage`\n * for the smallest possible page and takes its `total`: an EXACT count, where the previous\n * `pendingApprovals(500).length` silently undercounted any backlog past its row cap — precisely the\n * backlog an operator most needs the stat to be right about.\n */\nexport function agentPendingApprovalsCountProvider(): DataProvider {\n return {\n name: 'agent.approvals.pending',\n async resolve(_query, ctx) {\n const queries = resolveGovernanceQueries(ctx);\n if (queries === null) {\n return { value: 0 };\n }\n const page = await queries.approvalsPage({ page: 1, pageSize: 1 });\n return { value: page.total };\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 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":";;;;AAAA,SAASA,gCAAgC;;;ACGzC,SAASC,IAAIC,KAAaC,OAAeC,MAAa;AACpD,SAAOA,SAASC,SAAY;IAAEH;IAAKC;IAAOG,MAAM;MAAEF;IAAK;EAAE,IAAI;IAAEF;IAAKC;EAAM;AAC5E;AAFSF;AAYT,IAAMM,qBAAqB;AAkBpB,SAASC,eACdC,OAAkD,CAAC,GAAC;AAEpD,QAAMC,UAAUD,KAAKC,WAAWH;AAChC,SAAO;IACLI,IAAI;IACJR,OAAO;IACPS,QAAQ,CAAA;IACRC,UAAU;MACR;;QAEEC,OAAO;QACPC,MAAM;QACNH,QAAQ;UACN;YAAEI,MAAM;YAAQF,OAAO;YAAQG,MAAM;cAAEC,UAAU;YAAa;UAAE;UAChE;YAAEF,MAAM;YAAQF,OAAO;YAAUG,MAAM;cAAEC,UAAU;YAAe;UAAE;UACpE;YACEF,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAyB;YAC3CC,QAAQ;UACV;;MAEJ;MACA;QACEL,OAAO;QACPC,MAAM;QACNH,QAAQ;UACN;YACEI,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAwB;YAC1CC,QAAQ;UACV;UACA;YACEH,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAA0B;YAC5CC,QAAQ;UACV;UACA;YACEH,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAsB;YACxCE,OAAO;UACT;UACA;YACEJ,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAoB;YACtCG,QAAQ;cAAC;cAAW;;YACpBD,OAAO;UACT;UACA;YACEJ,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAA2B;YAC7CI,SAAS;cACP;gBAAEpB,KAAK;gBAAWC,OAAO;cAAQ;cACjC;gBAAED,KAAK;gBAAYC,OAAO;cAAW;cACrC;gBAAED,KAAK;gBAAeC,OAAO;cAAe;cAC5C;gBAAED,KAAK;gBAAgBC,OAAO;cAAgB;cAC9C;gBAAED,KAAK;gBAAWC,OAAO;cAAa;;UAE1C;UACA;YACEa,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAA2B;YAC7CE,OAAO;UACT;UACA;YACEJ,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAsB;YACxCI,SAAS;cACP;gBAAEpB,KAAK;gBAAYC,OAAO;cAAQ;cAClC;gBAAED,KAAK;gBAAYC,OAAO;cAAW;cACrC;gBAAED,KAAK;gBAAeC,OAAO;cAAS;cACtC;gBAAED,KAAK;gBAAWC,OAAO;cAAa;;UAE1C;UACA;YACEa,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAyB;YAC3CI,SAAS;cACP;gBAAEpB,KAAK;gBAASC,OAAO;cAAS;cAChC;gBAAED,KAAK;gBAAYC,OAAO;cAAQ;cAClC;gBAAED,KAAK;gBAAYC,OAAO;cAAW;cACrC;gBAAED,KAAK;gBAAeC,OAAO;cAAS;cACtC;gBAAED,KAAK;gBAAWC,OAAO;cAAa;;UAE1C;;MAEJ;MACA;QACEW,OAAO;QACPC,MAAM;QACNH,QAAQ;UACN;YAAEI,MAAM;YAAQF,OAAO;YAAQG,MAAM;cAAEC,UAAU;YAAmB;UAAE;UACtE;YACEF,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAyB;YAC3CC,QAAQ;UACV;UACA;YAAEH,MAAM;YAAQF,OAAO;YAAUG,MAAM;cAAEC,UAAU;YAAoB;UAAE;UACzE;YAAEF,MAAM;YAAQF,OAAO;YAAWG,MAAM;cAAEC,UAAU;YAAqB;UAAE;UAC3E;YACEF,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;cAAuBK,OAAO;gBAAEC,QAAQ;cAAM;YAAE;YAClEL,QAAQ;UACV;UACA;YACEH,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;cAAuBK,OAAO;gBAAEC,QAAQ;cAAM;YAAE;YAClEL,QAAQ;UACV;;;UAGA;YACEH,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAmB;YACrCG,QAAQ;cAAC;cAAQ;;YACjBD,OAAO;UACT;UACA;YACEJ,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAoB;YACtCE,OAAO;UACT;UACA;YACEJ,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAqB;YACvCI,SAAS;cACP;gBAAEpB,KAAK;gBAAaC,OAAO;cAAQ;cACnC;gBAAED,KAAK;gBAAQC,OAAO;cAAO;cAC7B;gBAAED,KAAK;gBAAUC,OAAO;cAAS;cACjC;gBAAED,KAAK;gBAAWC,OAAO;cAAU;;UAEvC;;MAEJ;MACA;;;;QAIEW,OAAO;QACPC,MAAM;QACNH,QAAQ;UACN;YACEI,MAAM;YACNF,OAAO;YACPW,OAAO;YACPR,MAAM;cAAEC,UAAU;YAAmB;;;;YAIrCI,SAAS;cACP;gBAAEpB,KAAK;gBAAaC,OAAO;cAAU;cACrCF,IAAI,SAAS,OAAOS,OAAAA;cACpB;gBAAER,KAAK;gBAAaC,OAAO;cAAQ;cACnC;gBAAED,KAAK;gBAAUC,OAAO;cAAS;cACjC;gBAAED,KAAK;gBAAcC,OAAO;cAAgB;cAC5C;gBAAED,KAAK;gBAAgBC,OAAO;cAAQ;cACtC;gBAAED,KAAK;gBAAcC,OAAO;cAAS;;UAEzC;UACA;YACEa,MAAM;YACNF,OAAO;YACPW,OAAO;YACPR,MAAM;cAAEC,UAAU;YAAoB;YACtCI,SAAS;cACP;gBAAEpB,KAAK;gBAAaC,OAAO;cAAO;cAClC;gBAAED,KAAK;gBAAYC,OAAO;cAAO;cACjC;gBAAED,KAAK;gBAAYC,OAAO;cAAO;cACjC;gBAAED,KAAK;gBAAUC,OAAO;cAAS;cACjCF,IAAI,SAAS,OAAOS,OAAAA;cACpBT,IAAI,YAAY,UAAUQ,KAAKiB,UAAU;;UAE7C;UACA;YACEV,MAAM;YACNF,OAAO;YACPW,OAAO;YACPR,MAAM;cAAEC,UAAU;YAAsB;YACxCI,SAAS;cACPrB,IAAI,YAAY,UAAUQ,KAAKiB,UAAU;cACzC;gBAAExB,KAAK;gBAASC,OAAO;cAAQ;cAC/B;gBAAED,KAAK;gBAAYC,OAAO;cAAQ;cAClC;gBAAED,KAAK;gBAAgBC,OAAO;cAAW;cACzC;gBAAED,KAAK;gBAAeC,OAAO;cAAS;cACtC;gBAAED,KAAK;gBAAkBC,OAAO;cAAgB;;UAEpD;;MAEJ;MACA;QACEW,OAAO;QACPC,MAAM;QACNH,QAAQ;UACN;YACEI,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAA0B;UAC9C;UACA;YACEF,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAyB;YAC3CI,SAAS;cACP;gBAAEpB,KAAK;gBAAeC,OAAO;cAAY;cACzC;gBAAED,KAAK;gBAAYC,OAAO;cAAO;cACjC;gBAAED,KAAK;gBAAeC,OAAO;cAAS;cACtCF,IAAI,YAAY,aAAaQ,KAAKiB,UAAU;cAC5CzB,IAAI,SAAS,OAAOS,OAAAA;cACpB;gBAAER,KAAK;gBAAYC,OAAO;cAAQ;cAClC;gBAAED,KAAK;gBAAaC,OAAO;cAAQ;;UAEvC;;MAEJ;MACA;QACEW,OAAO;QACPC,MAAM;QACNH,QAAQ;UACN;YACEI,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAmB;YACrCE,OAAO;UACT;UACA;YACEJ,MAAM;YACNF,OAAO;YACPG,MAAM;cAAEC,UAAU;YAAoB;YACtCI,SAAS;cACP;gBAAEpB,KAAK;gBAAYC,OAAO;cAAO;cACjC;gBAAED,KAAK;gBAAYC,OAAO;cAAO;cACjC;gBAAED,KAAK;gBAASC,OAAO;cAAQ;cAC/B;gBAAED,KAAK;gBAAUC,OAAO;cAAS;cACjC;gBAAED,KAAK;gBAAYC,OAAO;cAAW;cACrC;gBAAED,KAAK;gBAAkBC,OAAO;cAAW;cAC3C;gBAAED,KAAK;gBAAkBC,OAAO;cAAW;;UAE/C;;MAEJ;;EAEJ;AACF;AAjQgBK;;;AChChB,SAASmB,yBAAyB;AAmBlC,eAAeC,aAAaC,KAAqB;AAC/C,QAAMC,UAAUD,IAAIE,UAAUC,IAAIC,mBAAmB;IAAEC,QAAQ;EAAM,CAAA;AAGrE,QAAMC,OAAO,MAAML,QAAQE,IAAI;IAAEI,MAAM;IAASC,OAAO;EAAM,CAAA;AAC7D,SAAOF,KAAKG;AACd;AANeV;AAQf,SAASW,QAAQC,SAAyBC,OAAa;AACrD,SAAOD,QAAQE,OAAO,CAACC,UAAUA,MAAMC,SAASH,UAAUA,KAAAA;AAC5D;AAFSF;AAKF,SAASM,oBAAAA;AACd,SAAO;IACLC,MAAM;IACN,MAAMC,QAAQC,QAAQnB,KAAG;AACvB,YAAMoB,WAAWV,QAAQ,MAAMX,aAAaC,GAAAA,GAAM,cAAA;AAClD,aAAO;QAAEqB,OAAOD,SAASE;MAAO;IAClC;EACF;AACF;AARgBN;AAWT,SAASO,sBAAAA;AACd,SAAO;IACLN,MAAM;IACN,MAAMC,QAAQC,QAAQnB,KAAG;AACvB,YAAMoB,WAAWV,QAAQ,MAAMX,aAAaC,GAAAA,GAAM,cAAA;AAClD,YAAMqB,QAAQD,SAASI,OACrB,CAACC,KAAKX,UACJW,OAAOX,MAAMC,SAASW,eAAe,MAAMZ,MAAMC,SAASY,gBAAgB,IAC5E,CAAA;AAEF,aAAO;QAAEN;MAAM;IACjB;EACF;AACF;AAbgBE;AA+BT,SAASK,qBAAAA;AACd,SAAO;IACLX,MAAM;IACN,MAAMC,QAAQC,QAAQnB,KAAG;AACvB,YAAM6B,QAAQnB,QAAQ,MAAMX,aAAaC,GAAAA,GAAM,WAAA,EAC5C8B,MAAM,GAAC,EACPC,QAAO,EACPC,IAAI,CAAClB,WAAW;QACfmB,UAAUnB,MAAMC,SAASkB,YAAY;QACrCC,UAAUpB,MAAMC,SAASmB,YAAY;QACrCC,QAAQrB,MAAMC,SAASoB,UAAU;QACjCC,OAAOtB,MAAMC,SAASqB,SAAS;MACjC,EAAA;AACF,aAAO;QAAEC,MAAMR;MAAM;IACvB;EACF;AACF;AAhBgBD;AAmBT,SAASU,0BAAAA;AACd,SAAO;IACLrB,MAAM;IACN,MAAMC,QAAQC,QAAQnB,KAAG;AACvB,YAAM6B,QAAQnB,QAAQ,MAAMX,aAAaC,GAAAA,GAAM,WAAA;AAC/C,YAAMuC,SAAS,oBAAIC,IAAAA;AACnB,iBAAWC,QAAQZ,OAAO;AACxB,cAAMM,SAASM,KAAK1B,SAASoB,UAAU;AACvCI,eAAOG,IAAIP,SAASI,OAAOpC,IAAIgC,MAAAA,KAAW,KAAK,CAAA;MACjD;AACA,aAAO;QAAEQ,UAAU;aAAIJ,OAAO5B,QAAO;UAAIqB,IAAI,CAAC,CAACY,OAAOvB,KAAAA,OAAY;UAAEuB;UAAOvB;QAAM,EAAA;MAAI;IACvF;EACF;AACF;AAbgBiB;;;AC5EhB,SAASO,gCAAgC;AAiBzC,IAAMC,4BAA4B;AAElC,IAAMC,kBAAkB;AAmCxB,IAAMC,oBAAoB;AAS1B,SAASC,SAASC,OAAc;AAC9B,SAAO,OAAOA,UAAU,YAAYA,UAAU;AAChD;AAFSD;AAKT,SAASE,oBAAoBD,OAAc;AACzC,SACED,SAASC,KAAAA,KACT,OAAOA,MAAME,iBAAiB,cAC9B,OAAOF,MAAMG,iBAAiB,cAC9B,OAAOH,MAAMI,kBAAkB,cAC/B,OAAOJ,MAAMK,eAAe,cAC5B,OAAOL,MAAMM,oBAAoB,cACjC,OAAON,MAAMO,kBAAkB,cAC/B,OAAOP,MAAMQ,eAAe,cAC5B,OAAOR,MAAMS,gBAAgB,cAC7B,OAAOT,MAAMU,cAAc,cAC3B,OAAOV,MAAMW,aAAa,cAC1B,OAAOX,MAAMY,eAAe,cAC5B,OAAOZ,MAAMa,qBAAqB,cAClC,OAAOb,MAAMc,kBAAkB,cAC/B,OAAOd,MAAMe,cAAc,cAC3B,OAAOf,MAAMgB,kBAAkB,cAC/B,OAAOhB,MAAMiB,gBAAgB,cAC7B,OAAOjB,MAAMkB,aAAa,cAC1B,OAAOlB,MAAMmB,cAAc,cAC3B,OAAOnB,MAAMoB,iBAAiB;AAElC;AAvBSnB;AA8BT,SAASoB,yBAAyBC,KAAqB;AACrD,MAAIC;AACJ,MAAI;AACFA,eAAWD,IAAIE,UAAUC,IAAIC,0BAA0B;MAAEC,QAAQ;IAAM,CAAA;EACzE,QAAQ;AACN,WAAO;EACT;AACA,SAAO1B,oBAAoBsB,QAAAA,IAAYA,WAAW;AACpD;AARSF;AAUT,SAASO,SAAS5B,OAAc;AAC9B,SAAO,OAAOA,UAAU,YAAYH,gBAAgBgC,KAAK7B,KAAAA;AAC3D;AAFS4B;AAIT,SAASE,cAAAA;AACP,UAAO,oBAAIC,KAAAA,GAAOC,YAAW,EAAGC,MAAM,GAAG,EAAA;AAC3C;AAFSH;AAKF,SAASI,YAAYC,KAAaC,WAAiB;AACxD,QAAMC,UAAU,oBAAIN,KAAK,GAAGI,GAAAA,gBAAmB;AAC/CE,UAAQC,WAAWD,QAAQE,WAAU,IAAKH,SAAAA;AAC1C,SAAOC,QAAQL,YAAW,EAAGC,MAAM,GAAG,EAAA;AACxC;AAJgBC;AAUT,SAASM,aAAaC,OAA0C;AACrE,QAAMC,QAAQD,SAASb,SAASa,MAAMC,KAAK,IAAID,MAAMC,QAAQZ,YAAAA;AAC7D,QAAMa,UACJF,SAASb,SAASa,MAAME,OAAO,IAC3BF,MAAME,UACNT,YAAYQ,OAAO,EAAE9C,4BAA4B,EAAA;AACvD,SAAO;IAAE+C;IAASD;EAAM;AAC1B;AAPgBF;AAShB,SAASI,WAAW5C,OAAa;AAC/B,SAAO6C,KAAKC,MAAM9C,QAAQ,GAAA,IAAO;AACnC;AAFS4C;AAKF,SAASG,aAAaC,MAAqB;AAChD,SAAOJ,WAAWI,KAAKC,OAAO,CAACC,KAAKC,QAAQD,MAAMC,IAAIC,SAAS,CAAA,CAAA;AACjE;AAFgBL;AAKT,SAASM,YAAYL,MAAqB;AAC/C,SAAOA,KAAKC,OAAO,CAACC,KAAKC,QAAQD,MAAMC,IAAIG,cAAcH,IAAII,cAAc,CAAA;AAC7E;AAFgBF;AAKT,SAASG,qBAAqBR,MAAqB;AACxD,SAAOA,KACJS,OAAO,CAACN,QAAQA,IAAIC,UAAU,CAAA,EAC9BM,IAAI,CAACP,SAAS;IAAEQ,OAAOR,IAAIS;IAAS5D,OAAO4C,WAAWO,IAAIC,OAAO;EAAE,EAAA;AACxE;AAJgBI;AAOT,SAASK,iBAAiBb,MAAqB;AACpD,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxBS,SAAST,IAAIS;IACbE,UAAUX,IAAIW;IACdR,aAAaH,IAAIG;IACjBC,cAAcJ,IAAII;IAClBH,SAASR,WAAWO,IAAIC,OAAO;EACjC,EAAA;AACF;AARgBS;AAWT,SAASE,iBAAiBf,MAAqB;AACpD,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxBa,UAAUb,IAAIa;IACdF,UAAUX,IAAIW;IACdT,aAAaF,IAAIE;IACjBD,SAASR,WAAWO,IAAIC,OAAO;EACjC,EAAA;AACF;AAPgBW;AAUT,SAASE,kBAAkBjB,MAAsB;AACtD,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxBe,OAAOf,IAAIe,SAASf,IAAIgB;IACxBH,UAAUb,IAAIa;IACdF,UAAUX,IAAIW;IACdT,aAAaF,IAAIE;IACjBD,SAASR,WAAWO,IAAIC,OAAO;EACjC,EAAA;AACF;AARgBa;AAWT,SAASG,qBAAqBpB,MAAqB;AACxD,SAAOA,KACJS,OAAO,CAACN,QAAQA,IAAIC,UAAU,CAAA,EAC9BM,IAAI,CAACP,SAAS;IAAEQ,OAAOR,IAAIa;IAAUhE,OAAO4C,WAAWO,IAAIC,OAAO;EAAE,EAAA;AACzE;AAJgBgB;AAOT,SAASC,iBAAiBC,QAAyB;AACxD,SAAOA,OAAOZ,IAAI,CAACa,WAAW;IAC5BZ,OAAOY,MAAMpC;IACbiB,SAASR,WAAW2B,MAAMnB,OAAO;IACjCC,aAAakB,MAAMlB;EACrB,EAAA;AACF;AANgBgB;AAYhB,IAAMG,WAAW;AAGV,SAASC,oBACdzB,MAA4B;AAE5B,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxBuB,WAAWvB,IAAIuB;IACfC,MAAMxB,IAAIwB;IACVC,QAAQzB,IAAIyB;IACZC,SAAS1B,IAAI0B;EACf,EAAA;AACF;AATgBJ;AAYT,SAASK,mBAAmB9B,MAA4B;AAC7D,SAAOA,KAAKU,IAAI,CAACP,SAAS;IAAEQ,OAAOR,IAAI4B;IAAW/E,OAAOmD,IAAI6B;EAAM,EAAA;AACrE;AAFgBF;AAYT,SAASG,eAAeX,QAAuB;AACpD,SAAOA,OAAOZ,IAAI,CAACa,WAAW;IAAEZ,OAAOY,MAAMpC;IAAKwC,MAAMJ,MAAMI;IAAMC,QAAQL,MAAMK;EAAO,EAAA;AAC3F;AAFgBK;AAKhB,IAAMC,oBAAoB;AAWnB,SAASC,gBAAgBC,SAAsB;AACpD,MAAIA,YAAY,KAAM,QAAO;AAC7B,SAAOA,QAAQC,SAASH,oBAAoB,GAAGE,QAAQnD,MAAM,GAAGiD,iBAAAA,CAAAA,WAAwBE;AAC1F;AAHgBD;AAMhB,IAAMG,0BAA0B;AAGzB,SAASC,gBAAgBC,YAAyB;AACvD,SAAOA,eAAe,OAAO,OAAOA,WAAWvD,MAAM,GAAGqD,uBAAAA;AAC1D;AAFgBC;AAoBT,SAASE,qBAAqBzC,MAAoB;AACvD,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxBuC,WAAWvC,IAAIuC;IACfC,OAAOxC,IAAIwC;IACXxB,UAAUhB,IAAIgB;IACdH,UAAUb,IAAIa;IACdU,WAAWvB,IAAIuB,aAAaF;IAC5BoB,QAAQzC,IAAIyC;IACZC,YAAY1C,IAAI0C,cAAcrB;IAC9BK,SAAS1B,IAAI0B;IACbE,WAAW5B,IAAI4B,aAAaP;IAC5BsB,cAAcX,gBAAgBhC,IAAI2C,YAAY,KAAKtB;IACnDgB,YAAYD,gBAAgBpC,IAAIqC,UAAU,KAAKhB;EACjD,EAAA;AACF;AAdgBiB;AAiBT,SAASM,qBAAqB/C,MAA2B;AAC9D,SAAOA;AACT;AAFgB+C;AAKT,SAASC,wBAAwBhD,MAAyB;AAC/D,SAAOA;AACT;AAFgBgD;AAsBT,SAASC,2BAA2BjD,MAA0B;AACnE,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxB+C,YAAY/C,IAAI+C;IAChBC,UAAUhD,IAAIgD;IACdhC,UAAUhB,IAAIgB;IACdiC,aAAajD,IAAIiD;IACjBpC,UAAUb,IAAIa;IACdU,WAAWvB,IAAIuB,aAAaF;IAC5B6B,aAAalD,IAAIkD;IACjBV,OAAOxC,IAAIwC;EACb,EAAA;AACF;AAXgBM;AAyBT,SAASK,oBAAoBtD,MAAmB;AACrD,SAAOA,KAAKU,IAAI,CAACP,SAAS;IACxBgD,UAAUhD,IAAIgD;IACdI,UAAUpD,IAAIoD;IACdC,OAAOrD,IAAIqD;IACX5B,QAAQzB,IAAIyB;IACZ6B,UAAUtD,IAAIsD;IACdC,gBAAgBvD,IAAIuD,kBAAkBlC;IACtCmC,gBAAgBxD,IAAIwD,kBAAkBnC;EACxC,EAAA;AACF;AAVgB8B;AAahB,IAAMM,oBAAgC;EACpCjC,MAAM;EACNkC,WAAW;EACXjC,QAAQ;EACRkC,aAAa;EACbjC,SAAS;EACTkC,eAAe;EACfC,eAAe;AACjB;AASA,SAASC,uBACPC,MACAC,OACAC,QAAiC;AAEjC,SAAO;IACLF;IACA,MAAMG,QAAQ5E,OAAOnB,KAAG;AACtB,YAAMgG,UAAUjG,yBAAyBC,GAAAA;AACzC,YAAM0B,OAAOsE,UAAU,MAAMH,MAAMG,SAAS9E,aAAaC,KAAAA,CAAAA,IAAU,CAAA;AACnE,aAAO2E,OAAOpE,IAAAA;IAChB;EACF;AACF;AAbSiE;AAgBF,SAASM,0BAAAA;AACd,SAAON,uBACL,yBACA,CAACK,SAASE,UAAUF,QAAQpH,aAAasH,KAAAA,GACzC,CAACxE,UAAU;IAAEhD,OAAO+C,aAAaC,IAAAA;EAAM,EAAA;AAE3C;AANgBuE;AAST,SAASE,2BAAAA;AACd,SAAOR,uBACL,2BACA,CAACK,SAASE,UAAUF,QAAQpH,aAAasH,KAAAA,GACzC,CAACxE,UAAU;IAAEhD,OAAOqD,YAAYL,IAAAA;EAAM,EAAA;AAE1C;AANgByE;AAST,SAASC,4BAAAA;AACd,SAAOT,uBACL,uBACA,CAACK,SAASE,UAAUF,QAAQpH,aAAasH,KAAAA,GACzC,CAACxE,UAAU;IAAE2E,UAAUnE,qBAAqBR,IAAAA;EAAM,EAAA;AAEtD;AANgB0E;AAST,SAASE,+BAAAA;AACd,SAAOX,uBACL,4BACA,CAACK,SAASE,UAAUF,QAAQpH,aAAasH,KAAAA,GACzC,CAACxE,UAAU;IAAEA,MAAMa,iBAAiBb,IAAAA;EAAM,EAAA;AAE9C;AANgB4E;AAST,SAASC,0BAAAA;AACd,SAAOZ,uBACL,qBACA,CAACK,SAASE,UAAUF,QAAQjH,WAAWmH,KAAAA,GACvC,CAAClD,YAAY;IAAEtB,MAAMqB,iBAAiBC,MAAAA;EAAQ,EAAA;AAElD;AANgBuD;AAST,SAASC,+BAAAA;AACd,SAAOb,uBACL,uBACA,CAACK,SAASE,UAAUF,QAAQnH,aAAaqH,KAAAA,GACzC,CAACxE,UAAU;IAAEA,MAAMe,iBAAiBf,IAAAA;EAAM,EAAA;AAE9C;AANgB8E;AAST,SAASC,4BAAAA;AACd,SAAOd,uBACL,4BACA,CAACK,SAASE,UAAUF,QAAQnH,aAAaqH,KAAAA,GACzC,CAACxE,UAAU;IAAE2E,UAAUvD,qBAAqBpB,IAAAA;EAAM,EAAA;AAEtD;AANgB+E;AAST,SAASC,+BAAAA;AACd,SAAOf,uBACL,0BACA,CAACK,SAASE,UAAUF,QAAQlH,cAAcoH,OAAO1H,iBAAAA,GACjD,CAACkD,UAAU;IAAEA,MAAMiB,kBAAkBjB,IAAAA;EAAM,EAAA;AAE/C;AANgBgF;AAgBhB,SAASC,6BACPf,MACAE,QAAwC;AAExC,SAAO;IACLF;IACA,MAAMG,QAAQ5E,OAAOnB,KAAG;AACtB,YAAMgG,UAAUjG,yBAAyBC,GAAAA;AACzC,YAAM4G,UAAUZ,UAAU,MAAMA,QAAQ9G,WAAWgC,aAAaC,KAAAA,CAAAA,IAAUmE;AAC1E,aAAOQ,OAAOc,OAAAA;IAChB;EACF;AACF;AAZSD;AAeF,SAASE,yBAAAA;AACd,SAAOF,6BAA6B,oBAAoB,CAACC,aAAa;IAAElI,OAAOkI,QAAQvD;EAAK,EAAA;AAC9F;AAFgBwD;AAKT,SAASC,+BAAAA;AACd,SAAOH,6BAA6B,0BAA0B,CAACC,aAAa;IAC1ElI,OAAOkI,QAAQpB;EACjB,EAAA;AACF;AAJgBsB;AAOT,SAASC,0BAAAA;AACd,SAAOJ,6BAA6B,qBAAqB,CAACC,aAAa;IACrElI,OAAOkI,QAAQtD;EACjB,EAAA;AACF;AAJgByD;AAOT,SAASC,2BAAAA;AACd,SAAOL,6BAA6B,sBAAsB,CAACC,aAAa;IACtElI,OAAOkI,QAAQrD;EACjB,EAAA;AACF;AAJgByD;AAaT,SAASC,4BAAAA;AACd,SAAO;IACLrB,MAAM;IACN,MAAMG,QAAQ5E,OAAOnB,KAAG;AACtB,YAAMgG,UAAUjG,yBAAyBC,GAAAA;AACzC,YAAM4G,UAAUZ,UAAU,MAAMA,QAAQ9G,WAAWgC,aAAaC,KAAAA,CAAAA,IAAUmE;AAC1E,YAAM5G,QAAQyC,OAAO+F,WAAW,QAAQN,QAAQlB,gBAAgBkB,QAAQnB;AACxE,aAAO;QAAE/G,OAAOA,SAAS;MAAE;IAC7B;EACF;AACF;AAVgBuI;AAaT,SAASE,gCAAAA;AACd,SAAOxB,uBACL,sBACA,CAACK,SAASE,UAAUF,QAAQ7G,YAAY+G,KAAAA,GACxC,CAACxE,UAAU;IAAEA,MAAMyB,oBAAoBzB,IAAAA;EAAM,EAAA;AAEjD;AANgByF;AAST,SAASC,yBAAAA;AACd,SAAOzB,uBACL,qBACA,CAACK,SAASE,UAAUF,QAAQ5G,UAAU8G,KAAAA,GACtC,CAACxE,UAAU;IAAE2E,UAAU7C,mBAAmB9B,IAAAA;EAAM,EAAA;AAEpD;AANgB0F;AAST,SAASC,yBAAAA;AACd,SAAO1B,uBACL,oBACA,CAACK,SAASE,UAAUF,QAAQ3G,SAAS6G,KAAAA,GACrC,CAAClD,YAAY;IAAEtB,MAAMiC,eAAeX,MAAAA;EAAQ,EAAA;AAEhD;AANgBqE;AAWhB,IAAMC,uBAAuB;AAE7B,IAAMC,mBAAmB;AAGzB,SAASC,aAAarG,OAA4CsG,UAAgB;AAChF,QAAMC,MAAMvG,OAAOwG;AACnB,QAAMjJ,QAAQ,OAAOgJ,QAAQ,YAAYE,OAAOC,SAASH,GAAAA,IAAOA,MAAMD;AACtE,SAAOlG,KAAKuG,IAAIP,kBAAkBhG,KAAKwG,IAAI,GAAGxG,KAAKyG,MAAMtJ,KAAAA,CAAAA,CAAAA;AAC3D;AAJS8I;AAWT,SAASS,wBACPrC,MACAsC,cACArC,OACAC,QAAiC;AAEjC,SAAO;IACLF;IACA,MAAMG,QAAQ5E,OAAOnB,KAAG;AACtB,YAAMgG,UAAUjG,yBAAyBC,GAAAA;AACzC,YAAM0B,OAAOsE,UAAU,MAAMH,MAAMG,SAASwB,aAAarG,OAAO+G,YAAAA,CAAAA,IAAiB,CAAA;AACjF,aAAOpC,OAAOpE,IAAAA;IAChB;EACF;AACF;AAdSuG;AA8BT,SAASE,YAAYhH,OAA0C;AAC7D,QAAMuG,MAAMvG,OAAOiH;AACnB,QAAM1J,QAAQ,OAAOgJ,QAAQ,YAAYE,OAAOC,SAASH,GAAAA,IAAOA,MAAM;AACtE,SAAOnG,KAAKwG,IAAI,GAAGxG,KAAKyG,MAAMtJ,KAAAA,CAAAA;AAChC;AAJSyJ;AAkBT,SAASE,6BACPzC,MACAsC,cACArC,OACAC,QAAmC;AAEnC,SAAO;IACLF;IACA,MAAMG,QAAQ5E,OAAOnB,KAAG;AACtB,YAAMgG,UAAUjG,yBAAyBC,GAAAA;AACzC,YAAMoI,OAAOD,YAAYhH,KAAAA;AACzB,YAAMwG,QAAQH,aAAarG,OAAO+G,YAAAA;AAClC,UAAI,CAAClC,SAAS;AACZ,eAAO;UAAEtE,MAAM,CAAA;UAAI4G,OAAO;UAAGF;UAAMT;QAAM;MAC3C;AACA,YAAM1H,WAAW,MAAM4F,MAAMG,SAAS;QAAEoC;QAAMG,UAAUZ;MAAM,CAAA;AAC9D,aAAO;QACLjG,MAAMoE,OAAO7F,SAASyB,IAAI;QAC1B4G,OAAOrI,SAASqI;QAChBF,MAAMnI,SAASmI;QACfT,OAAO1H,SAASsI;MAClB;IACF;EACF;AACF;AAxBSF;AA8BF,SAASG,+BAAAA;AACd,SAAOP,wBACL,qBACAX,sBACA,CAACtB,SAAS2B,UAAU3B,QAAQ1G,WAAWqI,KAAAA,GACvC,CAACjG,UAAU;IAAEA,MAAMyC,qBAAqBzC,IAAAA;EAAM,EAAA;AAElD;AAPgB8G;AAcT,SAASC,oCAAAA;AACd,SAAOR,wBACL,sBACAX,sBACA,CAACtB,SAAS2B,UAAU3B,QAAQhH,gBAAgB2I,KAAAA,GAC5C,CAACjG,UAAU;IAAEA,MAAM+C,qBAAqB/C,IAAAA;EAAM,EAAA;AAElD;AAPgB+G;AAUT,SAASC,kCAAAA;AACd,SAAOT,wBACL,wBACAX,sBACA,CAACtB,SAAS2B,UAAU3B,QAAQ/G,cAAc0I,KAAAA,GAC1C,CAACjG,UAAU;IAAEA,MAAMgD,wBAAwBhD,IAAAA;EAAM,EAAA;AAErD;AAPgBgH;AAcT,SAASC,mCAAAA;AACd,SAAON,6BACL,qBACAf,sBACA,CAACtB,SAAS7E,UAAU6E,QAAQtG,cAAcyB,KAAAA,GAC1CsD,oBAAAA;AAEJ;AAPgBkE;AAaT,SAASC,iCAAAA;AACd,SAAOP,6BACL,uBACAf,sBACA,CAACtB,SAAS7E,UAAU6E,QAAQrG,YAAYwB,KAAAA,GACxCuD,uBAAAA;AAEJ;AAPgBkE;AAcT,SAASC,8BAAAA;AACd,SAAOR,6BACL,oBACAf,sBACA,CAACtB,SAAS7E,UAAU6E,QAAQpG,SAASuB,KAAAA,GACrCgD,oBAAAA;AAEJ;AAPgB0E;AAeT,SAASC,qCAAAA;AACd,SAAO;IACLlD,MAAM;IACN,MAAMG,QAAQgD,QAAQ/I,KAAG;AACvB,YAAMgG,UAAUjG,yBAAyBC,GAAAA;AACzC,UAAIgG,YAAY,MAAM;AACpB,eAAO;UAAEtH,OAAO;QAAE;MACpB;AACA,YAAM0J,OAAO,MAAMpC,QAAQxG,cAAc;QAAE4I,MAAM;QAAGG,UAAU;MAAE,CAAA;AAChE,aAAO;QAAE7J,OAAO0J,KAAKE;MAAM;IAC7B;EACF;AACF;AAZgBQ;AAeT,SAASE,qCAAAA;AACd,SAAOf,wBACL,0BACAX,sBACA,CAACtB,SAAS2B,UAAU3B,QAAQzG,iBAAiBoI,KAAAA,GAC7C,CAACjG,UAAU;IAAEA,MAAMiD,2BAA2BjD,IAAAA;EAAM,EAAA;AAExD;AAPgBsH;AAUT,SAASC,8BAAAA;AACd,SAAOtD,uBACL,qBACA,CAACK,SAASE,UAAUF,QAAQvG,UAAUyG,KAAAA,GACtC,CAACxE,UAAU;IAAEA,MAAMsD,oBAAoBtD,IAAAA;EAAM,EAAA;AAEjD;AANgBuH;;;AC7wBhB,SAASC,WAAWC,mBAAmB;AACvC,SAASC,+BAA+B;AACxC,SAASC,aAAaC,wBAAwB;AAuBvC,IAAMC,wBAAN,MAAMA;EAzBb,OAyBaA;;;EACFC,OAAO;EACCC,YAA+B,CAAA;EAEhDC,SAASC,KAA2B;AAGlC,SAAKF,UAAUG,KAAKC,iBAAiB,SAASC,uBAAAA,CAAAA;AAC9C,eAAWC,SAASD,yBAAyB;AAC3C,YAAME,UAAUC,YAAY,SAASF,KAAAA;AACrC,YAAMG,YAAY,wBAACC,YAAAA;AACjB,cAAMC,WAAWD;AACjBR,YAAIU,OAAO;UACTb,MAAM;UACNc,SAAS;YAAEP,OAAOK,SAASL;YAAO,GAAGK,SAASG;UAAQ;UACtDC,MAAM;YAACJ,SAASL;;QAClB,CAAA;MACF,GAPkB;AAQlBU,gBAAUT,SAASE,SAAAA;AACnB,WAAKT,UAAUG,KAAK,MAAMc,YAAYV,SAASE,SAAAA,CAAAA;IACjD;EACF;;EAGAS,UAAgB;AACd,WAAO,KAAKlB,UAAUmB,OAAQ,MAAKnB,UAAUoB,IAAG,IAAA;EAClD;AACF;;;AJMO,SAASC,wBAAwBC,OAAkD,CAAC,GAAC;AAC1F,SAAOC,yBAAyB;IAC9BC,MAAM;IACNC,UAAU,6BAAM;MAAC,IAAIC,sBAAAA;OAAX;IACVC,YAAY,6BAAM;MAAC;QAAEC,IAAI;QAASC,OAAO;QAASC,KAAK;MAAgB;OAA3D;IACZC,YAAY,6BAAM;MAACC,eAAeV,IAAAA;OAAtB;IACZW,eAAe,6BAAM;MACnBC,kBAAAA;MACAC,oBAAAA;MACAC,wBAAAA;MACAC,wBAAAA;MACAC,yBAAAA;MACAC,0BAAAA;MACAC,6BAAAA;MACAC,wBAAAA;MACAC,6BAAAA;MACAC,0BAAAA;MACAC,6BAAAA;MACAC,uBAAAA;MACAC,6BAAAA;MACAC,wBAAAA;MACAC,yBAAAA;MACAC,0BAAAA;MACAC,8BAAAA;MACAC,uBAAAA;MACAC,uBAAAA;MACAC,6BAAAA;MACAC,kCAAAA;MACAC,gCAAAA;MACAC,4BAAAA;MACAC,iCAAAA;MACAC,+BAAAA;MACAC,mCAAAA;MACAC,mCAAAA;MACAC,4BAAAA;OA5Ba;EA8BjB,CAAA;AACF;AArCgBxC;","names":["defineTelescopeExtension","col","key","label","href","undefined","link","DEFAULT_TRACE_HREF","agentDashboard","opts","runHref","id","panels","sections","title","cols","kind","data","provider","format","style","series","columns","query","metric","paged","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","approvalsPage","toolStats","toolCallsPage","threadsPage","runsPage","runDetail","threadDetail","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","p50ExecutionMs","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","resolvePage","page","governancePagedTableProvider","total","pageSize","agentRecentRunsTableProvider","agentRecentToolCallsTableProvider","agentRecentThreadsTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","agentRunsPagedTableProvider","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","agentRunsPagedTableProvider","agentToolCallsPagedTableProvider","agentThreadsPagedTableProvider","agentPendingApprovalsCountProvider","agentPendingApprovalsTableProvider","agentToolStatsTableProvider"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-agent-telescope",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/DavideCarvalho/nestjs-agent.git",
@@ -30,7 +30,7 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@dudousxd/nestjs-diagnostics": "0.7.0",
33
- "@dudousxd/nestjs-agent-core": "0.10.0"
33
+ "@dudousxd/nestjs-agent-core": "0.11.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "@dudousxd/nestjs-telescope": ">=1.18.0"