@dudousxd/nestjs-agent-telescope 0.8.0 → 0.8.2
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 +10 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +10 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/agent-telescope.extension.ts","../src/agent-dashboard.spec-data.ts","../src/agent-data-providers.ts","../src/agent-governance-providers.ts","../src/agent-telescope.watcher.ts","../src/rag-data-providers.ts","../src/rag-telescope.watcher.ts"],"sourcesContent":["export {\n agentTelescopeExtension,\n type AgentTelescopeExtensionOptions,\n} from './agent-telescope.extension.js';\nexport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\nexport { RAG_ENTRY_TYPE, RagTelescopeWatcher } from './rag-telescope.watcher.js';\nexport { agentDashboard } from './agent-dashboard.spec-data.js';\nexport {\n meanChunks,\n percentile,\n ragChunksProvider,\n ragCollectionsTableProvider,\n ragLatencyProvider,\n ragRetrievalsProvider,\n ragRetrieverBreakdownProvider,\n ragScoresProvider,\n ragSlowestTableProvider,\n ragStoreBreakdownProvider,\n ragTrendProvider,\n ragZeroHitRateProvider,\n readRetrievals,\n toCollectionRows,\n toLatencyDistribution,\n toRagRetrieval,\n toRetrievalTrendRows,\n toRetrieverSegments,\n toScoreDistribution,\n toSlowestRows,\n toStoreSegments,\n zeroHitRate,\n type RagRetrieval,\n} from './rag-data-providers.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 type { DashboardSection, DataProvider } from '@dudousxd/nestjs-telescope';\nimport { 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';\nimport {\n ragChunksProvider,\n ragCollectionsTableProvider,\n ragLatencyProvider,\n ragRetrievalsProvider,\n ragRetrieverBreakdownProvider,\n ragScoresProvider,\n ragSlowestTableProvider,\n ragStoreBreakdownProvider,\n ragTrendProvider,\n ragZeroHitRateProvider,\n} from './rag-data-providers.js';\nimport { RagTelescopeWatcher } from './rag-telescope.watcher.js';\n\n/** The provider-name prefix this extension owns. A host contribution may not claim a name under it. */\nconst RESERVED_PROVIDER_PREFIX = 'agent.';\n\nexport interface AgentTelescopeExtensionOptions {\n /** Deep-link template for a `{threadId}` cell, e.g. `'/admin/threads/{threadId}'`. */\n threadHref?: string;\n /** Deep-link template for a `{runId}` cell. Defaults to the in-app trace waterfall. */\n runHref?: string;\n /**\n * HOST-contributed data providers, registered alongside the built-in ones.\n *\n * This exists because a panel on this dashboard **cannot** bind to a provider contributed by a\n * different extension, and the reason is structural rather than a policy we could relax: the UI\n * derives the request path from the dashboard id (`agent.overview` → `GET /ext/agent/data/:name`),\n * and the controller 404s when `providerOwner(name) !== ext` so the URL namespace cannot be\n * spoofed. A host that registers its own `TelescopeModule` extension therefore gets its own tab,\n * never a panel on this one. Passing the providers through here makes THIS extension their owner,\n * which is what makes a host section on this page resolve at all.\n *\n * Name them under your own prefix (`myapp.rag.collections`); anything starting with `agent.` is\n * refused at boot, because a collision there would surface as Telescope's generic \"contributed by\n * both agent and agent\" error, which names the same extension twice and says nothing useful.\n */\n providers?: DataProvider[];\n /**\n * HOST-contributed dashboard sections, appended after the built-in ones. Bind their panels to the\n * providers passed above (or to any built-in `agent.*` provider).\n *\n * Size each section's panel count to an exact multiple of its `cols`, for the same reason every\n * built-in section is: the renderer lays a section out as a fixed `grid-cols-N` grid with no\n * `colSpan`, so an orphan panel leaves a visible hole beside it. That is a layout convention, not\n * something validated here — a gap is cosmetic, and failing a host's boot over cosmetics would be\n * a worse trade than the gap.\n */\n sections?: DashboardSection[];\n}\n\n/**\n * The first-class Telescope extension for nestjs-agent: an \"Agent\" tab fed by three sources —\n * the `aviary:agent:*` diagnostics channel (live runs, tool calls) via the watcher, the\n * authoritative `AGENT_GOVERNANCE_QUERIES` read-model (historical spend/usage, run reliability,\n * tool activity, the approvals inbox) via the governance providers, and the `aviary:rag:retrieval`\n * channel (retrieval latency, chunk counts, score distribution, store/collection) via the RAG\n * watcher and providers. The extension `name`, entry-type ids, dashboard id, and every built-in\n * provider name share the `agent` prefix so the registry's global-uniqueness namespaces never\n * 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. The RAG panels need no binding at all —\n * they read Telescope's own storage — but they stay empty until something emits retrieval telemetry\n * (`createRetrievalTool` does by default; `instrumentRetriever` for every other call path).\n */\nexport function agentTelescopeExtension(opts: AgentTelescopeExtensionOptions = {}) {\n const hostProviders = opts.providers ?? [];\n const reserved = hostProviders.filter((provider) =>\n provider.name.startsWith(RESERVED_PROVIDER_PREFIX),\n );\n if (reserved.length > 0) {\n throw new Error(\n `agentTelescopeExtension: host-contributed data providers may not use the reserved \"${RESERVED_PROVIDER_PREFIX}\" prefix — ` +\n `rename ${reserved.map((provider) => `\"${provider.name}\"`).join(', ')} to your own namespace.`,\n );\n }\n return defineTelescopeExtension({\n name: 'agent',\n watchers: () => [new AgentTelescopeWatcher(), new RagTelescopeWatcher()],\n entryTypes: () => [\n { id: 'agent', label: 'Agent', dot: 'bg-violet-400' },\n { id: 'agent-rag', label: 'RAG', dot: 'bg-emerald-400' },\n ],\n dashboards: () => [\n agentDashboard({\n ...(opts.threadHref !== undefined ? { threadHref: opts.threadHref } : {}),\n ...(opts.runHref !== undefined ? { runHref: opts.runHref } : {}),\n ...(opts.sections !== undefined ? { sections: opts.sections } : {}),\n }),\n ],\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 ragRetrievalsProvider(),\n ragZeroHitRateProvider(),\n ragChunksProvider(),\n ragLatencyProvider(),\n ragScoresProvider(),\n ragTrendProvider(),\n ragStoreBreakdownProvider(),\n ragRetrieverBreakdownProvider(),\n ragCollectionsTableProvider(),\n ragSlowestTableProvider(),\n ...hostProviders,\n ],\n });\n}\n","import type { Column, DashboardSection, 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: eight sections (Overview lean; Spend; Reliability; Activity; Approvals; Tools;\n * Retrieval; Retrieval sources), each sized so its panel count is an exact multiple of its `cols` —\n * no half-empty row. `nestjs-telescope`'s `ExtensionDashboardPage` renders a section as a\n * `grid-cols-N` grid with one panel per cell and no `colSpan`, so a lone table in an otherwise-empty\n * row would leave a visible gap next to it.\n *\n * `sections` appends HOST-contributed sections after the built-in ones — see\n * {@link import('./agent-telescope.extension.js').agentTelescopeExtension}'s `sections`/`providers`\n * options, which is the supported way an application puts its own panels (its knowledge-base\n * collections, its ingestion activity) on this page. They are appended rather than interleaved so a\n * host's layout can never push a built-in section out of the row it was sized for.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string; sections?: DashboardSection[] } = {},\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 // RAG. Fed by the `aviary:rag:retrieval` telemetry `@dudousxd/nestjs-agent-rag` emits, NOT\n // derived from tool-call rows: a tool call that retrieved nothing and one that retrieved\n // five perfect passages are the same row with the same `ok` status, so every number here\n // would have been unanswerable from that side.\n title: 'Retrieval',\n cols: 3,\n panels: [\n { kind: 'stat', title: 'Retrievals', data: { provider: 'agent.rag.retrievals' } },\n {\n kind: 'stat',\n title: 'Zero-hit rate',\n data: { provider: 'agent.rag.zeroHitRate' },\n format: 'percent',\n // Up is bad and there is no \"good\" floor to calibrate against — a corpus that honestly\n // cannot answer a question SHOULD come back empty — so no thresholds: colouring this\n // would assert a target nobody measured.\n },\n {\n kind: 'stat',\n title: 'Passages per retrieval',\n data: { provider: 'agent.rag.chunks' },\n format: 'number',\n },\n {\n // A real histogram, unlike the run-duration pair above: retrieval events carry the raw\n // per-call duration, so there ARE samples to bucket and markers to place.\n kind: 'distribution',\n title: 'Retrieval latency',\n data: { provider: 'agent.rag.latency' },\n markers: ['p50', 'p95', 'p99'],\n format: 'duration',\n },\n {\n // Bound to ONE retriever kind on purpose — a cosine similarity, a BM25 score and an RRF\n // rank score share no scale, so a histogram over all of them has bins that mean a\n // different thing per bar. See `toScoreDistribution`.\n kind: 'distribution',\n title: 'Top score (dense)',\n data: { provider: 'agent.rag.scores', query: { retriever: 'embedding' } },\n markers: ['p50', 'p95'],\n format: 'number',\n },\n {\n kind: 'timeseries',\n title: 'Retrievals & zero-hits',\n data: { provider: 'agent.rag.trend' },\n series: ['retrievals', 'zeroHits'],\n style: 'stacked',\n },\n ],\n },\n {\n title: 'Retrieval sources',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Retrievals by store',\n data: { provider: 'agent.rag.byStore' },\n style: 'donut',\n },\n {\n kind: 'breakdown',\n title: 'Retrievals by retriever',\n data: { provider: 'agent.rag.byRetriever' },\n style: 'donut',\n },\n {\n kind: 'table',\n title: 'By collection',\n data: { provider: 'agent.rag.byCollection' },\n columns: [\n { key: 'collection', label: 'Collection' },\n { key: 'store', label: 'Store' },\n { key: 'retrievals', label: 'Retrievals' },\n { key: 'zeroHits', label: 'Zero-hits' },\n { key: 'p95Ms', label: 'p95 (ms)' },\n { key: 'meanTopScore', label: 'Mean top score' },\n ],\n },\n {\n kind: 'table',\n title: 'Slowest retrievals',\n data: { provider: 'agent.rag.slowest' },\n // Seven columns, matching the recent-runs table's width: this is the widest a table can\n // get here before it overflows its card.\n columns: [\n { key: 'at', label: 'When' },\n { key: 'retriever', label: 'Retriever' },\n { key: 'store', label: 'Store' },\n { key: 'collection', label: 'Collection' },\n { key: 'chunks', label: 'Passages' },\n { key: 'topScore', label: 'Top score' },\n { key: 'durationMs', label: 'Duration (ms)' },\n ],\n },\n ],\n },\n ...(opts.sections ?? []),\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","import type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\nimport { TELESCOPE_STORAGE } from '@dudousxd/nestjs-telescope';\nimport { RAG_ENTRY_TYPE } from './rag-telescope.watcher.js';\n\n/**\n * RAG data providers for the \"Agent\" Telescope tab: how long retrieval takes, how much it returns,\n * how good the scores are, and which store answered. They read the `agent-rag` entries\n * {@link import('./rag-telescope.watcher.js').RagTelescopeWatcher} records from the\n * `aviary:rag:retrieval` diagnostics channel.\n *\n * ## Why the ephemeral channel here, when `agent-data-providers.ts` says to prefer the durable one\n *\n * That file's deprecation note is right about what it covers: anything that is a governance FACT —\n * a tool call, its approval, what a run cost — belongs in `AGENT_GOVERNANCE_QUERIES`, because it is\n * read as history, must survive a restart, and already has a durable write on the path.\n *\n * Retrieval telemetry is not that, and routing it there would have cost more than it bought. There\n * is no durable write to piggyback on: `AGENT_GOVERNANCE_QUERIES` is implemented over the agent\n * store's own tables, retrieval happens inside `@dudousxd/nestjs-agent-rag` (which holds no store\n * handle and has no business acquiring one), and giving it one would mean a new table plus a\n * migration in `store-mikro-orm` AND `store-drizzle` AND `testing`, and a row written per retrieval —\n * write amplification on the hot path of the one operation an agent performs most often. What that\n * buys is that a latency p95 and a zero-hit rate survive a pod restart. Those are rolling\n * operational signals, read as \"what is retrieval doing lately\", over a window Telescope's own\n * retention already bounds.\n *\n * The honest consequence, so nobody is surprised by it: **these panels count only what this process\n * has seen since it started, and only as far back as Telescope's retention.** They are a live view,\n * not a ledger. A host that needs retrieval history to outlive a deploy has two supported routes,\n * neither of which requires a change here: subscribe to `aviary:rag:retrieval` itself and persist\n * what it wants, and/or contribute its own providers and panels through\n * `agentTelescopeExtension({ providers, sections })`.\n */\n\n/**\n * How many retrieval entries a panel scans. Matches the agent providers' window. Entries come back\n * NEWEST FIRST (the storage SPI's `get` sorts descending), which is what lets the \"recent\" tables\n * take a prefix rather than a suffix.\n */\nconst RETRIEVAL_WINDOW = 5_000;\n\n/** Rows in the by-collection and slowest-retrieval tables. */\nconst TABLE_LIMIT = 10;\n\n/** Hours of trend shown — one day, which is longer than a default retention window anyway. */\nconst TREND_HOURS = 24;\n\n/** Placeholder for a dimension the event did not carry (an in-process retriever has no store). */\nconst NO_VALUE = '—';\n\n/** One retrieval, normalized out of an entry's untyped `content`. */\nexport interface RagRetrieval {\n at: Date;\n retriever: string;\n store: string | null;\n collection: string | null;\n chunks: number;\n zeroHit: boolean;\n topScore: number | null;\n durationMs: number | null;\n failed: boolean;\n}\n\ninterface BreakdownSegment {\n label: string;\n value: number;\n}\n\ninterface DistributionBucket {\n label: string;\n count: number;\n}\n\n/** One row of the per-collection table. */\ninterface CollectionRow {\n collection: string;\n store: string;\n retrievals: number;\n zeroHits: number;\n p95Ms: number | string;\n meanTopScore: number | string;\n}\n\n/** One row of the slowest-retrievals table. */\ninterface SlowestRow {\n at: string;\n retriever: string;\n store: string;\n collection: string;\n chunks: number;\n topScore: number | string;\n durationMs: number | string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction readString(source: Record<string, unknown>, key: string): string | null {\n const value = source[key];\n return typeof value === 'string' ? value : null;\n}\n\nfunction readNumber(source: Record<string, unknown>, key: string): number | null {\n const value = source[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\n/**\n * The Telescope storage surface these providers use, narrowed structurally so the DI-resolved\n * binding needs no cast — the same posture `agent-governance-providers.ts` takes with\n * `AGENT_GOVERNANCE_QUERIES`.\n */\ninterface RetrievalEntryStorage {\n get(query: { type?: string; limit?: number }): Promise<{ data: unknown[] }>;\n}\n\nfunction isEntryStorage(value: unknown): value is RetrievalEntryStorage {\n return isRecord(value) && typeof value.get === 'function';\n}\n\n/**\n * Normalize one storage entry into a {@link RagRetrieval}, or `null` when it is not a retrieval this\n * shaping understands. Field-by-field `typeof` checks rather than a cast: entries are persisted JSON\n * written by a possibly older producer, so \"the field is there and is a number\" is a runtime\n * question, and a missing `durationMs` must land as `null` (excluded from percentiles) rather than as\n * a `NaN` that silently poisons every aggregate it touches.\n */\nexport function toRagRetrieval(entry: unknown): RagRetrieval | null {\n if (!isRecord(entry) || !isRecord(entry.content)) {\n return null;\n }\n const content = entry.content;\n const retriever = readString(content, 'retriever');\n if (retriever === null) {\n return null;\n }\n const chunks = readNumber(content, 'chunks') ?? 0;\n const createdAt = entry.createdAt;\n return {\n at: createdAt instanceof Date ? createdAt : new Date(0),\n retriever,\n store: readString(content, 'store'),\n collection: readString(content, 'collection'),\n chunks,\n zeroHit: content.zeroHit === true || chunks === 0,\n topScore: readNumber(content, 'topScore'),\n durationMs: readNumber(content, 'durationMs'),\n failed: content.failed === true,\n };\n}\n\n/**\n * Every retrieval in the window, newest first. Takes the resolved binding as `unknown` and narrows it\n * here, so a host whose Telescope storage is missing or unrecognised gets empty panels rather than a\n * 502 on every RAG card — the same degrade-don't-throw posture the governance providers take.\n */\nexport async function readRetrievals(storage: unknown): Promise<RagRetrieval[]> {\n if (!isEntryStorage(storage)) {\n return [];\n }\n const page = await storage.get({ type: RAG_ENTRY_TYPE, limit: RETRIEVAL_WINDOW });\n const retrievals: RagRetrieval[] = [];\n for (const entry of page.data) {\n const retrieval = toRagRetrieval(entry);\n if (retrieval !== null) {\n retrievals.push(retrieval);\n }\n }\n return retrievals;\n}\n\n/** Resolve Telescope's own storage from the host container; `undefined` when the token is unbound. */\nfunction retrievalStorage(ctx: ExtensionContext): unknown {\n try {\n return ctx.moduleRef.get(TELESCOPE_STORAGE, { strict: false });\n } catch {\n return undefined;\n }\n}\n\n/** Nearest-rank percentile over an unsorted sample. `null` for an empty sample. */\nexport function percentile(samples: number[], fraction: number): number | null {\n if (samples.length === 0) {\n return null;\n }\n const sorted = [...samples].sort((a, b) => a - b);\n const rank = Math.ceil(fraction * sorted.length);\n return sorted[Math.min(Math.max(rank, 1), sorted.length) - 1] ?? null;\n}\n\nfunction round(value: number, places: number): number {\n const factor = 10 ** places;\n return Math.round(value * factor) / factor;\n}\n\n/** Fraction (0–1) of retrievals that came back with nothing. `0` over an empty window. */\nexport function zeroHitRate(retrievals: RagRetrieval[]): number {\n if (retrievals.length === 0) {\n return 0;\n }\n const zeroHits = retrievals.filter((retrieval) => retrieval.zeroHit).length;\n return round(zeroHits / retrievals.length, 4);\n}\n\n/** Mean passages returned per retrieval — `topK` minus this is how often the corpus ran out. */\nexport function meanChunks(retrievals: RagRetrieval[]): number {\n if (retrievals.length === 0) {\n return 0;\n }\n const total = retrievals.reduce((sum, retrieval) => sum + retrieval.chunks, 0);\n return round(total / retrievals.length, 2);\n}\n\n/**\n * Fixed latency ladder, in milliseconds. Fixed rather than derived from the data because a\n * histogram whose buckets move between refreshes cannot be compared to the one you looked at a\n * minute ago — the shape changes when the data changes AND when the range does, and there is no way\n * to tell which happened.\n */\nconst LATENCY_EDGES = [10, 25, 50, 100, 250, 500, 1_000, 2_500, 5_000];\n\nfunction latencyLabel(index: number): string {\n const upper = LATENCY_EDGES[index];\n if (upper === undefined) {\n return `≥${LATENCY_EDGES[LATENCY_EDGES.length - 1] ?? 0}ms`;\n }\n return `${index === 0 ? 0 : (LATENCY_EDGES[index - 1] ?? 0)}–${upper}ms`;\n}\n\n/** Latency histogram over the ladder above, plus p50/p95/p99 of the raw samples. */\nexport function toLatencyDistribution(retrievals: RagRetrieval[]): {\n buckets: DistributionBucket[];\n p50?: number;\n p95?: number;\n p99?: number;\n} {\n const samples: number[] = [];\n const counts = new Array<number>(LATENCY_EDGES.length + 1).fill(0);\n for (const { durationMs } of retrievals) {\n if (durationMs === null) {\n continue;\n }\n samples.push(durationMs);\n const found = LATENCY_EDGES.findIndex((edge) => durationMs < edge);\n const index = found === -1 ? LATENCY_EDGES.length : found;\n counts[index] = (counts[index] ?? 0) + 1;\n }\n const buckets = counts.map((count, index) => ({ label: latencyLabel(index), count }));\n const p50 = percentile(samples, 0.5);\n const p95 = percentile(samples, 0.95);\n const p99 = percentile(samples, 0.99);\n return {\n buckets,\n ...(p50 !== null ? { p50 } : {}),\n ...(p95 !== null ? { p95 } : {}),\n ...(p99 !== null ? { p99 } : {}),\n };\n}\n\n/** Ten equal bins over `[0, 1]`, the range a cosine similarity lives in. */\nconst SCORE_BINS = 10;\n\n/**\n * Top-score histogram — **for ONE retriever kind at a time**, which is the whole reason this takes a\n * `retriever` argument instead of bucketing everything it was handed.\n *\n * A `Passage.score` has no shared meaning across strategies: `EmbeddingRetriever` returns a\n * calibrated cosine similarity in `[0, 1]`, a BM25 leg returns an unbounded relevance score in the\n * tens, and `HybridRetriever`'s RRF returns a rank-derived number that lives in a band about one\n * part in fifty wide and says nothing about quality at all (see the score section on\n * `HybridRetriever`). Pouring those into one histogram produces a chart where the bins mean a\n * different thing per bar — and the reading it invites, \"our scores collapsed\", would be a change in\n * traffic MIX rather than in retrieval quality.\n *\n * So the panel binds `query.retriever: 'embedding'`: the dense leg is the only population whose\n * score is comparable across queries, which is also why `minScore` lives on that retriever alone.\n * Scores outside `[0, 1]` are clamped into the end bins rather than dropped, so a store that reports\n * a distance-derived score still shows up as an obviously-pinned bar instead of an empty chart.\n */\nexport function toScoreDistribution(\n retrievals: RagRetrieval[],\n retriever: string,\n): { buckets: DistributionBucket[]; p50?: number; p95?: number } {\n const samples: number[] = [];\n const counts = new Array<number>(SCORE_BINS).fill(0);\n for (const retrieval of retrievals) {\n if (retrieval.retriever !== retriever || retrieval.topScore === null) {\n continue;\n }\n samples.push(retrieval.topScore);\n const clamped = Math.min(Math.max(retrieval.topScore, 0), 1);\n const index = Math.min(Math.floor(clamped * SCORE_BINS), SCORE_BINS - 1);\n counts[index] = (counts[index] ?? 0) + 1;\n }\n const buckets = counts.map((count, index) => ({\n label: `${round(index / SCORE_BINS, 1)}–${round((index + 1) / SCORE_BINS, 1)}`,\n count,\n }));\n const p50 = percentile(samples, 0.5);\n const p95 = percentile(samples, 0.95);\n return {\n buckets,\n ...(p50 !== null ? { p50: round(p50, 4) } : {}),\n ...(p95 !== null ? { p95: round(p95, 4) } : {}),\n };\n}\n\n/** Start of the UTC hour a timestamp falls in. */\nfunction hourStart(at: Date): number {\n return Math.floor(at.getTime() / 3_600_000) * 3_600_000;\n}\n\n/**\n * Retrievals and zero-hits per UTC hour, oldest bucket first, over the last {@link TREND_HOURS}.\n * Empty hours are emitted as zeroes so a quiet stretch reads as a gap in the line rather than\n * disappearing and making the outage look like it never happened.\n */\nexport function toRetrievalTrendRows(\n retrievals: RagRetrieval[],\n now = new Date(),\n): Array<{ label: string; retrievals: number; zeroHits: number }> {\n const latest = hourStart(now);\n const earliest = latest - (TREND_HOURS - 1) * 3_600_000;\n const buckets = new Map<number, { retrievals: number; zeroHits: number }>();\n for (let hour = earliest; hour <= latest; hour += 3_600_000) {\n buckets.set(hour, { retrievals: 0, zeroHits: 0 });\n }\n for (const retrieval of retrievals) {\n const bucket = buckets.get(hourStart(retrieval.at));\n if (bucket === undefined) {\n continue;\n }\n bucket.retrievals += 1;\n if (retrieval.zeroHit) {\n bucket.zeroHits += 1;\n }\n }\n return [...buckets.entries()].map(([hour, counts]) => ({\n label: `${new Date(hour).toISOString().slice(11, 13)}:00`,\n retrievals: counts.retrievals,\n zeroHits: counts.zeroHits,\n }));\n}\n\n/** Count retrievals by one dimension, biggest first, with a placeholder for the absent case. */\nfunction segmentsBy(\n retrievals: RagRetrieval[],\n pick: (retrieval: RagRetrieval) => string | null,\n): BreakdownSegment[] {\n const counts = new Map<string, number>();\n for (const retrieval of retrievals) {\n const label = pick(retrieval) ?? NO_VALUE;\n counts.set(label, (counts.get(label) ?? 0) + 1);\n }\n return [...counts.entries()]\n .map(([label, value]) => ({ label, value }))\n .sort((a, b) => b.value - a.value);\n}\n\n/** Retrievals by vector store (`memory`/`pg`/`redis`, or `—` for an in-process retriever). */\nexport function toStoreSegments(retrievals: RagRetrieval[]): BreakdownSegment[] {\n return segmentsBy(retrievals, (retrieval) => retrieval.store);\n}\n\n/** Retrievals by strategy — the composed kind, since that is what answered. */\nexport function toRetrieverSegments(retrievals: RagRetrieval[]): BreakdownSegment[] {\n return segmentsBy(retrievals, (retrieval) => retrieval.retriever);\n}\n\n/** Per-collection rollup, busiest first. `p95Ms`/`meanTopScore` fall back to `—` when unmeasured. */\nexport function toCollectionRows(retrievals: RagRetrieval[], limit = TABLE_LIMIT): CollectionRow[] {\n const groups = new Map<string, RagRetrieval[]>();\n for (const retrieval of retrievals) {\n const key = retrieval.collection ?? NO_VALUE;\n const group = groups.get(key);\n if (group === undefined) {\n groups.set(key, [retrieval]);\n } else {\n group.push(retrieval);\n }\n }\n return [...groups.entries()]\n .map(([collection, group]) => {\n const durations: number[] = [];\n const scores: number[] = [];\n for (const retrieval of group) {\n if (retrieval.durationMs !== null) {\n durations.push(retrieval.durationMs);\n }\n if (retrieval.topScore !== null) {\n scores.push(retrieval.topScore);\n }\n }\n const p95 = percentile(durations, 0.95);\n const meanScore =\n scores.length === 0 ? null : scores.reduce((sum, score) => sum + score, 0) / scores.length;\n return {\n collection,\n store: group[0]?.store ?? NO_VALUE,\n retrievals: group.length,\n zeroHits: group.filter((retrieval) => retrieval.zeroHit).length,\n p95Ms: p95 === null ? NO_VALUE : Math.round(p95),\n meanTopScore: meanScore === null ? NO_VALUE : round(meanScore, 3),\n };\n })\n .sort((a, b) => b.retrievals - a.retrievals)\n .slice(0, limit);\n}\n\n/**\n * The slowest retrievals in the window, worst first — the table an operator opens after the p95\n * moves. Sorted by duration rather than by recency on purpose: \"recent retrievals\" would be a list\n * of whatever just happened, which the trend already shows in aggregate, whereas the tail is the\n * only place a single pathological query is visible at all.\n */\nexport function toSlowestRows(retrievals: RagRetrieval[], limit = TABLE_LIMIT): SlowestRow[] {\n return retrievals\n .filter((retrieval) => retrieval.durationMs !== null)\n .sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0))\n .slice(0, limit)\n .map((retrieval) => ({\n at: retrieval.at.toISOString(),\n retriever: retrieval.retriever,\n store: retrieval.store ?? NO_VALUE,\n collection: retrieval.collection ?? NO_VALUE,\n chunks: retrieval.chunks,\n topScore: retrieval.topScore === null ? NO_VALUE : round(retrieval.topScore, 3),\n durationMs: retrieval.durationMs === null ? NO_VALUE : Math.round(retrieval.durationMs),\n }));\n}\n\n/** Build a provider from one shaping step over the retrieval window. */\nfunction retrievalProvider(\n name: string,\n format: (retrievals: RagRetrieval[], query: Record<string, unknown> | undefined) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n return format(await readRetrievals(retrievalStorage(ctx)), query);\n },\n };\n}\n\n/** stat → retrievals in the window. */\nexport function ragRetrievalsProvider(): DataProvider {\n return retrievalProvider('agent.rag.retrievals', (retrievals) => ({ value: retrievals.length }));\n}\n\n/** stat (percent) → share of retrievals that returned nothing. */\nexport function ragZeroHitRateProvider(): DataProvider {\n return retrievalProvider('agent.rag.zeroHitRate', (retrievals) => ({\n value: zeroHitRate(retrievals),\n }));\n}\n\n/** stat → mean passages returned per retrieval. */\nexport function ragChunksProvider(): DataProvider {\n return retrievalProvider('agent.rag.chunks', (retrievals) => ({ value: meanChunks(retrievals) }));\n}\n\n/** distribution → retrieval latency, with p50/p95/p99 markers. */\nexport function ragLatencyProvider(): DataProvider {\n return retrievalProvider('agent.rag.latency', toLatencyDistribution);\n}\n\n/** distribution → top score for ONE retriever kind (`query.retriever`, default `embedding`). */\nexport function ragScoresProvider(): DataProvider {\n return retrievalProvider('agent.rag.scores', (retrievals, query) => {\n const requested = query?.retriever;\n return toScoreDistribution(retrievals, typeof requested === 'string' ? requested : 'embedding');\n });\n}\n\n/** timeseries → retrievals and zero-hits per hour. */\nexport function ragTrendProvider(): DataProvider {\n return retrievalProvider('agent.rag.trend', (retrievals) => ({\n rows: toRetrievalTrendRows(retrievals),\n }));\n}\n\n/** breakdown → retrievals by vector store. */\nexport function ragStoreBreakdownProvider(): DataProvider {\n return retrievalProvider('agent.rag.byStore', (retrievals) => ({\n segments: toStoreSegments(retrievals),\n }));\n}\n\n/** breakdown → retrievals by retriever strategy. */\nexport function ragRetrieverBreakdownProvider(): DataProvider {\n return retrievalProvider('agent.rag.byRetriever', (retrievals) => ({\n segments: toRetrieverSegments(retrievals),\n }));\n}\n\n/** table → per-collection rollup, busiest first. */\nexport function ragCollectionsTableProvider(): DataProvider {\n return retrievalProvider('agent.rag.byCollection', (retrievals) => ({\n rows: toCollectionRows(retrievals),\n }));\n}\n\n/** table → the slowest retrievals in the window. */\nexport function ragSlowestTableProvider(): DataProvider {\n return retrievalProvider('agent.rag.slowest', (retrievals) => ({\n rows: toSlowestRows(retrievals),\n }));\n}\n","import { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport { channelName, claimDiagnostics } from '@dudousxd/nestjs-diagnostics';\nimport type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';\n\n/**\n * The diagnostics coordinates `@dudousxd/nestjs-agent-rag` publishes retrieval telemetry on. Kept as\n * literals rather than imported from that package, exactly as {@link AgentTelescopeWatcher} depends\n * on the diagnostics channel and not on the agent runtime: this extension must stay installable by a\n * host that has Telescope and the agent but no retrieval stack at all, and adding a dependency on the\n * rag package to read two strings would drag pg/redis-shaped code into every such install. The\n * channel name is the published wire contract (`RAG_RETRIEVAL_CHANNEL` on the producer side).\n */\nconst RAG_LIB = 'rag';\nconst RETRIEVAL_EVENT = 'retrieval';\n\n/** The Telescope entry `type` retrieval events are recorded as — see the class doc. */\nexport const RAG_ENTRY_TYPE = 'agent-rag';\n\n/** The envelope `@dudousxd/nestjs-diagnostics` publishes: metadata plus the emitter's payload. */\ninterface DiagnosticEnvelope {\n event: string;\n durationMs?: number;\n payload: Record<string, unknown>;\n}\n\nfunction isEnvelope(message: unknown): message is DiagnosticEnvelope {\n return (\n typeof message === 'object' &&\n message !== null &&\n typeof Reflect.get(message, 'payload') === 'object' &&\n Reflect.get(message, 'payload') !== null\n );\n}\n\n/**\n * Records `aviary:rag:retrieval` events as Telescope entries of type `agent-rag` — the source every\n * RAG panel on the Agent dashboard reads.\n *\n * **Its own entry type, not `agent`.** Retrieval is per-tool-call where a run is per-conversation, so\n * a busy hour produces an order of magnitude more retrieval events than agent events. Sharing the\n * `agent` type would put them in one storage window: the providers page 5k entries of a type, and\n * retrieval traffic would push `run.finished` out of that window, quietly zeroing the Runs and Tokens\n * stats that have nothing to do with RAG. Separate types make the two independent, and give the\n * Entries screen a \"RAG\" filter that lists retrievals and only retrievals.\n *\n * **The duration is lifted off the ENVELOPE into the entry content.** The emitter puts it there\n * (`emit`'s `opts.durationMs`) because that is the field Telescope's OTel exporter turns into a\n * latency histogram; the panels need it as an ordinary field they can bucket, and an entry's content\n * is all a `DataProvider` gets. Recording it in both places would mean two sources of truth for the\n * same number, so it is lifted rather than duplicated at the emitter.\n *\n * Claims `rag:retrieval` (refcounted, released in `dispose()`) so\n * `@dudousxd/nestjs-diagnostics-telescope`'s generic bridge skips it instead of recording every\n * retrieval a second time as a generic `diagnostic` entry.\n *\n * Registered by `agentTelescopeExtension()`; also usable on its own in a host's `watchers` list.\n */\nexport class RagTelescopeWatcher implements Watcher {\n readonly type = RAG_ENTRY_TYPE;\n private readonly disposers: Array<() => void> = [];\n\n register(ctx: WatcherContext): void {\n this.disposers.push(claimDiagnostics(RAG_LIB, [RETRIEVAL_EVENT]));\n const channel = channelName(RAG_LIB, RETRIEVAL_EVENT);\n const onMessage = (message: unknown) => {\n if (!isEnvelope(message)) {\n return;\n }\n ctx.record({\n type: RAG_ENTRY_TYPE,\n content: {\n event: RETRIEVAL_EVENT,\n ...message.payload,\n ...(message.durationMs !== undefined ? { durationMs: message.durationMs } : {}),\n },\n // Tagged by store and retriever kind so the Entries screen can filter to \"every retrieval\n // pgvector served\" without a provider — the same tag-per-dimension the agent watcher uses.\n tags: tagsOf(message.payload),\n });\n };\n subscribe(channel, onMessage);\n this.disposers.push(() => unsubscribe(channel, onMessage));\n }\n\n /** Detach the subscription and release the diagnostics claim (e.g. on module destroy). */\n dispose(): void {\n while (this.disposers.length) this.disposers.pop()?.();\n }\n}\n\n/** `retriever:<kind>` / `store:<kind>` / `zero-hit` / `failed`, for whichever the payload carries. */\nfunction tagsOf(payload: Record<string, unknown>): string[] {\n const tags = [RETRIEVAL_EVENT];\n if (typeof payload.retriever === 'string') {\n tags.push(`retriever:${payload.retriever}`);\n }\n if (typeof payload.store === 'string') {\n tags.push(`store:${payload.store}`);\n }\n if (payload.zeroHit === true) {\n tags.push('zero-hit');\n }\n if (payload.failed === true) {\n tags.push('failed');\n }\n return tags;\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","markers","retriever","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","import_nestjs_telescope","import_node_diagnostics_channel","import_nestjs_diagnostics","RAG_LIB","RETRIEVAL_EVENT","RAG_ENTRY_TYPE","isEnvelope","message","Reflect","get","RagTelescopeWatcher","type","disposers","register","ctx","push","claimDiagnostics","channel","channelName","onMessage","record","content","event","payload","durationMs","undefined","tags","tagsOf","subscribe","unsubscribe","dispose","length","pop","retriever","store","zeroHit","failed","RETRIEVAL_WINDOW","TABLE_LIMIT","TREND_HOURS","NO_VALUE","isRecord","value","readString","source","key","readNumber","Number","isFinite","isEntryStorage","get","toRagRetrieval","entry","content","retriever","chunks","createdAt","at","Date","store","collection","zeroHit","topScore","durationMs","failed","readRetrievals","storage","page","type","RAG_ENTRY_TYPE","limit","retrievals","data","retrieval","push","retrievalStorage","ctx","moduleRef","TELESCOPE_STORAGE","strict","undefined","percentile","samples","fraction","length","sorted","sort","a","b","rank","Math","ceil","min","max","round","places","factor","zeroHitRate","zeroHits","filter","meanChunks","total","reduce","sum","LATENCY_EDGES","latencyLabel","index","upper","toLatencyDistribution","counts","Array","fill","found","findIndex","edge","buckets","map","count","label","p50","p95","p99","SCORE_BINS","toScoreDistribution","clamped","floor","hourStart","getTime","toRetrievalTrendRows","now","latest","earliest","Map","hour","set","bucket","entries","toISOString","slice","segmentsBy","pick","toStoreSegments","toRetrieverSegments","toCollectionRows","groups","group","durations","scores","meanScore","score","p95Ms","meanTopScore","toSlowestRows","retrievalProvider","name","format","resolve","query","ragRetrievalsProvider","ragZeroHitRateProvider","ragChunksProvider","ragLatencyProvider","ragScoresProvider","requested","ragTrendProvider","rows","ragStoreBreakdownProvider","segments","ragRetrieverBreakdownProvider","ragCollectionsTableProvider","ragSlowestTableProvider","RESERVED_PROVIDER_PREFIX","agentTelescopeExtension","opts","hostProviders","providers","reserved","filter","provider","name","startsWith","length","Error","map","join","defineTelescopeExtension","watchers","AgentTelescopeWatcher","RagTelescopeWatcher","entryTypes","id","label","dot","dashboards","agentDashboard","threadHref","undefined","runHref","sections","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","ragRetrievalsProvider","ragZeroHitRateProvider","ragChunksProvider","ragLatencyProvider","ragScoresProvider","ragTrendProvider","ragStoreBreakdownProvider","ragRetrieverBreakdownProvider","ragCollectionsTableProvider","ragSlowestTableProvider"]}
|
|
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","../src/rag-data-providers.ts","../src/rag-telescope.watcher.ts"],"sourcesContent":["export {\n agentTelescopeExtension,\n type AgentTelescopeExtensionOptions,\n} from './agent-telescope.extension.js';\nexport { AgentTelescopeWatcher } from './agent-telescope.watcher.js';\nexport { RAG_ENTRY_TYPE, RagTelescopeWatcher } from './rag-telescope.watcher.js';\nexport { agentDashboard } from './agent-dashboard.spec-data.js';\nexport {\n meanChunks,\n percentile,\n ragChunksProvider,\n ragCollectionsTableProvider,\n ragLatencyProvider,\n ragRetrievalsProvider,\n ragRetrieverBreakdownProvider,\n ragScoresProvider,\n ragSlowestTableProvider,\n ragStoreBreakdownProvider,\n ragTrendProvider,\n ragZeroHitRateProvider,\n readRetrievals,\n toCollectionRows,\n toLatencyDistribution,\n toRagRetrieval,\n toRetrievalTrendRows,\n toRetrieverSegments,\n toScoreDistribution,\n toSlowestRows,\n toStoreSegments,\n zeroHitRate,\n type RagRetrieval,\n} from './rag-data-providers.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 type { DashboardSection, DataProvider } from '@dudousxd/nestjs-telescope';\nimport { 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';\nimport {\n ragChunksProvider,\n ragCollectionsTableProvider,\n ragLatencyProvider,\n ragRetrievalsProvider,\n ragRetrieverBreakdownProvider,\n ragScoresProvider,\n ragSlowestTableProvider,\n ragStoreBreakdownProvider,\n ragTrendProvider,\n ragZeroHitRateProvider,\n} from './rag-data-providers.js';\nimport { RagTelescopeWatcher } from './rag-telescope.watcher.js';\n\n/** The provider-name prefix this extension owns. A host contribution may not claim a name under it. */\nconst RESERVED_PROVIDER_PREFIX = 'agent.';\n\nexport interface AgentTelescopeExtensionOptions {\n /** Deep-link template for a `{threadId}` cell, e.g. `'/admin/threads/{threadId}'`. */\n threadHref?: string;\n /** Deep-link template for a `{runId}` cell. Defaults to the in-app trace waterfall. */\n runHref?: string;\n /**\n * HOST-contributed data providers, registered alongside the built-in ones.\n *\n * This exists because a panel on this dashboard **cannot** bind to a provider contributed by a\n * different extension, and the reason is structural rather than a policy we could relax: the UI\n * derives the request path from the dashboard id (`agent.overview` → `GET /ext/agent/data/:name`),\n * and the controller 404s when `providerOwner(name) !== ext` so the URL namespace cannot be\n * spoofed. A host that registers its own `TelescopeModule` extension therefore gets its own tab,\n * never a panel on this one. Passing the providers through here makes THIS extension their owner,\n * which is what makes a host section on this page resolve at all.\n *\n * Name them under your own prefix (`myapp.rag.collections`); anything starting with `agent.` is\n * refused at boot, because a collision there would surface as Telescope's generic \"contributed by\n * both agent and agent\" error, which names the same extension twice and says nothing useful.\n */\n providers?: DataProvider[];\n /**\n * HOST-contributed dashboard sections, appended after the built-in ones. Bind their panels to the\n * providers passed above (or to any built-in `agent.*` provider).\n *\n * Size each section's panel count to an exact multiple of its `cols`, for the same reason every\n * built-in section is: the renderer lays a section out as a fixed `grid-cols-N` grid with no\n * `colSpan`, so an orphan panel leaves a visible hole beside it. That is a layout convention, not\n * something validated here — a gap is cosmetic, and failing a host's boot over cosmetics would be\n * a worse trade than the gap.\n */\n sections?: DashboardSection[];\n}\n\n/**\n * The first-class Telescope extension for nestjs-agent: an \"Agent\" tab fed by three sources —\n * the `aviary:agent:*` diagnostics channel (live runs, tool calls) via the watcher, the\n * authoritative `AGENT_GOVERNANCE_QUERIES` read-model (historical spend/usage, run reliability,\n * tool activity, the approvals inbox) via the governance providers, and the `aviary:rag:retrieval`\n * channel (retrieval latency, chunk counts, score distribution, store/collection) via the RAG\n * watcher and providers. The extension `name`, entry-type ids, dashboard id, and every built-in\n * provider name share the `agent` prefix so the registry's global-uniqueness namespaces never\n * 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. The RAG panels need no binding at all —\n * they read Telescope's own storage — but they stay empty until something emits retrieval telemetry\n * (`createRetrievalTool` does by default; `instrumentRetriever` for every other call path).\n */\nexport function agentTelescopeExtension(opts: AgentTelescopeExtensionOptions = {}) {\n const hostProviders = opts.providers ?? [];\n const reserved = hostProviders.filter((provider) =>\n provider.name.startsWith(RESERVED_PROVIDER_PREFIX),\n );\n if (reserved.length > 0) {\n throw new Error(\n `agentTelescopeExtension: host-contributed data providers may not use the reserved \"${RESERVED_PROVIDER_PREFIX}\" prefix — ` +\n `rename ${reserved.map((provider) => `\"${provider.name}\"`).join(', ')} to your own namespace.`,\n );\n }\n return defineTelescopeExtension({\n name: 'agent',\n watchers: () => [new AgentTelescopeWatcher(), new RagTelescopeWatcher()],\n entryTypes: () => [\n { id: 'agent', label: 'Agent', dot: 'bg-violet-400' },\n { id: 'agent-rag', label: 'RAG', dot: 'bg-emerald-400' },\n ],\n dashboards: () => [\n agentDashboard({\n ...(opts.threadHref !== undefined ? { threadHref: opts.threadHref } : {}),\n ...(opts.runHref !== undefined ? { runHref: opts.runHref } : {}),\n ...(opts.sections !== undefined ? { sections: opts.sections } : {}),\n }),\n ],\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 ragRetrievalsProvider(),\n ragZeroHitRateProvider(),\n ragChunksProvider(),\n ragLatencyProvider(),\n ragScoresProvider(),\n ragTrendProvider(),\n ragStoreBreakdownProvider(),\n ragRetrieverBreakdownProvider(),\n ragCollectionsTableProvider(),\n ragSlowestTableProvider(),\n ...hostProviders,\n ],\n });\n}\n","import type { Column, DashboardSection, DashboardSpec } from '@dudousxd/nestjs-telescope';\n\n/** A plain column, or one carrying a `Column.link` to `href` when `href` is given. */\nfunction col(key: string, label: string, href?: string): Column {\n return href !== undefined ? { key, label, link: { href } } : { key, label };\n}\n\n/**\n * The \"Agent\" overview dashboard. Panels bind to the `agent.*` data providers.\n *\n * `threadHref` and `runHref` are URL templates for deep-linking a `{threadId}` / `{runId}` cell out\n * to the HOST's own viewer (e.g. the standalone `@dudousxd/nestjs-agent-dashboard` SPA). Both are\n * omitted by default, and a cell whose template is unset renders as plain text.\n *\n * `runHref` used to default to `'#/traces/{runId}'`, and that default could only 404. Telescope's\n * trace waterfall is keyed by **`traceId`** — `LinkSpec`'s doc says so, and `TracesService`\n * resolves it with `storage.get({ traceId })` — while an agent's `runId` is a different identifier\n * that {@link import('./agent-telescope.watcher.js').AgentTelescopeWatcher} never ties to one: it\n * records `type: 'agent'` entries and stamps no trace at all. So every `Run` cell on the shipped\n * dashboard pointed at a trace that does not exist, and clicking one answered\n * `404 · No entries for trace <runId>`. Substituting the wrong key into a route that had been read\n * correctly is the whole bug — hence no default here. A host that has a run viewer passes its own\n * template; one that does not gets plain text, which is honest.\n *\n * Layout: eight sections (Overview lean; Spend; Reliability; Activity; Approvals; Tools;\n * Retrieval; Retrieval sources), each sized so its panel count is an exact multiple of its `cols` —\n * no half-empty row. `nestjs-telescope`'s `ExtensionDashboardPage` renders a section as a\n * `grid-cols-N` grid with one panel per cell and no `colSpan`, so a lone table in an otherwise-empty\n * row would leave a visible gap next to it.\n *\n * `sections` appends HOST-contributed sections after the built-in ones — see\n * {@link import('./agent-telescope.extension.js').agentTelescopeExtension}'s `sections`/`providers`\n * options, which is the supported way an application puts its own panels (its knowledge-base\n * collections, its ingestion activity) on this page. They are appended rather than interleaved so a\n * host's layout can never push a built-in section out of the row it was sized for.\n */\nexport function agentDashboard(\n opts: { threadHref?: string; runHref?: string; sections?: DashboardSection[] } = {},\n): DashboardSpec {\n const runHref = opts.runHref;\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 // RAG. Fed by the `aviary:rag:retrieval` telemetry `@dudousxd/nestjs-agent-rag` emits, NOT\n // derived from tool-call rows: a tool call that retrieved nothing and one that retrieved\n // five perfect passages are the same row with the same `ok` status, so every number here\n // would have been unanswerable from that side.\n title: 'Retrieval',\n cols: 3,\n panels: [\n { kind: 'stat', title: 'Retrievals', data: { provider: 'agent.rag.retrievals' } },\n {\n kind: 'stat',\n title: 'Zero-hit rate',\n data: { provider: 'agent.rag.zeroHitRate' },\n format: 'percent',\n // Up is bad and there is no \"good\" floor to calibrate against — a corpus that honestly\n // cannot answer a question SHOULD come back empty — so no thresholds: colouring this\n // would assert a target nobody measured.\n },\n {\n kind: 'stat',\n title: 'Passages per retrieval',\n data: { provider: 'agent.rag.chunks' },\n format: 'number',\n },\n {\n // A real histogram, unlike the run-duration pair above: retrieval events carry the raw\n // per-call duration, so there ARE samples to bucket and markers to place.\n kind: 'distribution',\n title: 'Retrieval latency',\n data: { provider: 'agent.rag.latency' },\n markers: ['p50', 'p95', 'p99'],\n format: 'duration',\n },\n {\n // Bound to ONE retriever kind on purpose — a cosine similarity, a BM25 score and an RRF\n // rank score share no scale, so a histogram over all of them has bins that mean a\n // different thing per bar. See `toScoreDistribution`.\n kind: 'distribution',\n title: 'Top score (dense)',\n data: { provider: 'agent.rag.scores', query: { retriever: 'embedding' } },\n markers: ['p50', 'p95'],\n format: 'number',\n },\n {\n kind: 'timeseries',\n title: 'Retrievals & zero-hits',\n data: { provider: 'agent.rag.trend' },\n series: ['retrievals', 'zeroHits'],\n style: 'stacked',\n },\n ],\n },\n {\n title: 'Retrieval sources',\n cols: 2,\n panels: [\n {\n kind: 'breakdown',\n title: 'Retrievals by store',\n data: { provider: 'agent.rag.byStore' },\n style: 'donut',\n },\n {\n kind: 'breakdown',\n title: 'Retrievals by retriever',\n data: { provider: 'agent.rag.byRetriever' },\n style: 'donut',\n },\n {\n kind: 'table',\n title: 'By collection',\n data: { provider: 'agent.rag.byCollection' },\n columns: [\n { key: 'collection', label: 'Collection' },\n { key: 'store', label: 'Store' },\n { key: 'retrievals', label: 'Retrievals' },\n { key: 'zeroHits', label: 'Zero-hits' },\n { key: 'p95Ms', label: 'p95 (ms)' },\n { key: 'meanTopScore', label: 'Mean top score' },\n ],\n },\n {\n kind: 'table',\n title: 'Slowest retrievals',\n data: { provider: 'agent.rag.slowest' },\n // Seven columns, matching the recent-runs table's width: this is the widest a table can\n // get here before it overflows its card.\n columns: [\n { key: 'at', label: 'When' },\n { key: 'retriever', label: 'Retriever' },\n { key: 'store', label: 'Store' },\n { key: 'collection', label: 'Collection' },\n { key: 'chunks', label: 'Passages' },\n { key: 'topScore', label: 'Top score' },\n { key: 'durationMs', label: 'Duration (ms)' },\n ],\n },\n ],\n },\n ...(opts.sections ?? []),\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/**\n * Read a positive number out of a raw query value, whichever way it arrived.\n *\n * A panel's `data.query` reaches a provider as **strings**: the dashboard serializes it into the\n * URL and the host controller hands `@Query()` straight through, so `?page=2` arrives as `'2'`.\n * A `typeof raw === 'number'` guard therefore rejects every value a real request can carry and\n * silently falls back — which is not a type error anywhere, and reads at runtime as \"paging does\n * nothing\". Unit tests calling `resolve({ page: 2 })` pass either way, so the guard has to accept\n * both forms for the tests to mean anything about the deployed behaviour.\n */\nfunction readPositiveNumber(raw: unknown): number | undefined {\n if (typeof raw === 'number') return Number.isFinite(raw) && raw > 0 ? raw : undefined;\n if (typeof raw !== 'string' || raw.trim() === '') return undefined;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;\n}\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 value = readPositiveNumber(query?.limit) ?? 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/**\n * Clamp a panel-supplied `page` to `[1, Infinity)`, defaulting to 1 when absent/invalid.\n *\n * See {@link readPositiveNumber} for why this cannot demand a `number`: it did, `?page=2` arrived\n * as `'2'`, and every page resolved to 1. The visible symptom was worse than \"Next shows page 1\"\n * — the pager renders the page the RESPONSE reports, so Next appeared to do nothing, and because\n * the control then keeps computing `page + 1` from that pinned 1, the second click requests a page\n * the UI is already on, React skips the re-render, and the pager stops responding entirely.\n */\nfunction resolvePage(query: Record<string, unknown> | undefined): number {\n const value = readPositiveNumber(query?.page) ?? 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","import type { DataProvider, ExtensionContext } from '@dudousxd/nestjs-telescope';\nimport { TELESCOPE_STORAGE } from '@dudousxd/nestjs-telescope';\nimport { RAG_ENTRY_TYPE } from './rag-telescope.watcher.js';\n\n/**\n * RAG data providers for the \"Agent\" Telescope tab: how long retrieval takes, how much it returns,\n * how good the scores are, and which store answered. They read the `agent-rag` entries\n * {@link import('./rag-telescope.watcher.js').RagTelescopeWatcher} records from the\n * `aviary:rag:retrieval` diagnostics channel.\n *\n * ## Why the ephemeral channel here, when `agent-data-providers.ts` says to prefer the durable one\n *\n * That file's deprecation note is right about what it covers: anything that is a governance FACT —\n * a tool call, its approval, what a run cost — belongs in `AGENT_GOVERNANCE_QUERIES`, because it is\n * read as history, must survive a restart, and already has a durable write on the path.\n *\n * Retrieval telemetry is not that, and routing it there would have cost more than it bought. There\n * is no durable write to piggyback on: `AGENT_GOVERNANCE_QUERIES` is implemented over the agent\n * store's own tables, retrieval happens inside `@dudousxd/nestjs-agent-rag` (which holds no store\n * handle and has no business acquiring one), and giving it one would mean a new table plus a\n * migration in `store-mikro-orm` AND `store-drizzle` AND `testing`, and a row written per retrieval —\n * write amplification on the hot path of the one operation an agent performs most often. What that\n * buys is that a latency p95 and a zero-hit rate survive a pod restart. Those are rolling\n * operational signals, read as \"what is retrieval doing lately\", over a window Telescope's own\n * retention already bounds.\n *\n * The honest consequence, so nobody is surprised by it: **these panels count only what this process\n * has seen since it started, and only as far back as Telescope's retention.** They are a live view,\n * not a ledger. A host that needs retrieval history to outlive a deploy has two supported routes,\n * neither of which requires a change here: subscribe to `aviary:rag:retrieval` itself and persist\n * what it wants, and/or contribute its own providers and panels through\n * `agentTelescopeExtension({ providers, sections })`.\n */\n\n/**\n * How many retrieval entries a panel scans. Matches the agent providers' window. Entries come back\n * NEWEST FIRST (the storage SPI's `get` sorts descending), which is what lets the \"recent\" tables\n * take a prefix rather than a suffix.\n */\nconst RETRIEVAL_WINDOW = 5_000;\n\n/** Rows in the by-collection and slowest-retrieval tables. */\nconst TABLE_LIMIT = 10;\n\n/** Hours of trend shown — one day, which is longer than a default retention window anyway. */\nconst TREND_HOURS = 24;\n\n/** Placeholder for a dimension the event did not carry (an in-process retriever has no store). */\nconst NO_VALUE = '—';\n\n/** One retrieval, normalized out of an entry's untyped `content`. */\nexport interface RagRetrieval {\n at: Date;\n retriever: string;\n store: string | null;\n collection: string | null;\n chunks: number;\n zeroHit: boolean;\n topScore: number | null;\n durationMs: number | null;\n failed: boolean;\n}\n\ninterface BreakdownSegment {\n label: string;\n value: number;\n}\n\ninterface DistributionBucket {\n label: string;\n count: number;\n}\n\n/** One row of the per-collection table. */\ninterface CollectionRow {\n collection: string;\n store: string;\n retrievals: number;\n zeroHits: number;\n p95Ms: number | string;\n meanTopScore: number | string;\n}\n\n/** One row of the slowest-retrievals table. */\ninterface SlowestRow {\n at: string;\n retriever: string;\n store: string;\n collection: string;\n chunks: number;\n topScore: number | string;\n durationMs: number | string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction readString(source: Record<string, unknown>, key: string): string | null {\n const value = source[key];\n return typeof value === 'string' ? value : null;\n}\n\nfunction readNumber(source: Record<string, unknown>, key: string): number | null {\n const value = source[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\n/**\n * The Telescope storage surface these providers use, narrowed structurally so the DI-resolved\n * binding needs no cast — the same posture `agent-governance-providers.ts` takes with\n * `AGENT_GOVERNANCE_QUERIES`.\n */\ninterface RetrievalEntryStorage {\n get(query: { type?: string; limit?: number }): Promise<{ data: unknown[] }>;\n}\n\nfunction isEntryStorage(value: unknown): value is RetrievalEntryStorage {\n return isRecord(value) && typeof value.get === 'function';\n}\n\n/**\n * Normalize one storage entry into a {@link RagRetrieval}, or `null` when it is not a retrieval this\n * shaping understands. Field-by-field `typeof` checks rather than a cast: entries are persisted JSON\n * written by a possibly older producer, so \"the field is there and is a number\" is a runtime\n * question, and a missing `durationMs` must land as `null` (excluded from percentiles) rather than as\n * a `NaN` that silently poisons every aggregate it touches.\n */\nexport function toRagRetrieval(entry: unknown): RagRetrieval | null {\n if (!isRecord(entry) || !isRecord(entry.content)) {\n return null;\n }\n const content = entry.content;\n const retriever = readString(content, 'retriever');\n if (retriever === null) {\n return null;\n }\n const chunks = readNumber(content, 'chunks') ?? 0;\n const createdAt = entry.createdAt;\n return {\n at: createdAt instanceof Date ? createdAt : new Date(0),\n retriever,\n store: readString(content, 'store'),\n collection: readString(content, 'collection'),\n chunks,\n zeroHit: content.zeroHit === true || chunks === 0,\n topScore: readNumber(content, 'topScore'),\n durationMs: readNumber(content, 'durationMs'),\n failed: content.failed === true,\n };\n}\n\n/**\n * Every retrieval in the window, newest first. Takes the resolved binding as `unknown` and narrows it\n * here, so a host whose Telescope storage is missing or unrecognised gets empty panels rather than a\n * 502 on every RAG card — the same degrade-don't-throw posture the governance providers take.\n */\nexport async function readRetrievals(storage: unknown): Promise<RagRetrieval[]> {\n if (!isEntryStorage(storage)) {\n return [];\n }\n const page = await storage.get({ type: RAG_ENTRY_TYPE, limit: RETRIEVAL_WINDOW });\n const retrievals: RagRetrieval[] = [];\n for (const entry of page.data) {\n const retrieval = toRagRetrieval(entry);\n if (retrieval !== null) {\n retrievals.push(retrieval);\n }\n }\n return retrievals;\n}\n\n/** Resolve Telescope's own storage from the host container; `undefined` when the token is unbound. */\nfunction retrievalStorage(ctx: ExtensionContext): unknown {\n try {\n return ctx.moduleRef.get(TELESCOPE_STORAGE, { strict: false });\n } catch {\n return undefined;\n }\n}\n\n/** Nearest-rank percentile over an unsorted sample. `null` for an empty sample. */\nexport function percentile(samples: number[], fraction: number): number | null {\n if (samples.length === 0) {\n return null;\n }\n const sorted = [...samples].sort((a, b) => a - b);\n const rank = Math.ceil(fraction * sorted.length);\n return sorted[Math.min(Math.max(rank, 1), sorted.length) - 1] ?? null;\n}\n\nfunction round(value: number, places: number): number {\n const factor = 10 ** places;\n return Math.round(value * factor) / factor;\n}\n\n/** Fraction (0–1) of retrievals that came back with nothing. `0` over an empty window. */\nexport function zeroHitRate(retrievals: RagRetrieval[]): number {\n if (retrievals.length === 0) {\n return 0;\n }\n const zeroHits = retrievals.filter((retrieval) => retrieval.zeroHit).length;\n return round(zeroHits / retrievals.length, 4);\n}\n\n/** Mean passages returned per retrieval — `topK` minus this is how often the corpus ran out. */\nexport function meanChunks(retrievals: RagRetrieval[]): number {\n if (retrievals.length === 0) {\n return 0;\n }\n const total = retrievals.reduce((sum, retrieval) => sum + retrieval.chunks, 0);\n return round(total / retrievals.length, 2);\n}\n\n/**\n * Fixed latency ladder, in milliseconds. Fixed rather than derived from the data because a\n * histogram whose buckets move between refreshes cannot be compared to the one you looked at a\n * minute ago — the shape changes when the data changes AND when the range does, and there is no way\n * to tell which happened.\n */\nconst LATENCY_EDGES = [10, 25, 50, 100, 250, 500, 1_000, 2_500, 5_000];\n\nfunction latencyLabel(index: number): string {\n const upper = LATENCY_EDGES[index];\n if (upper === undefined) {\n return `≥${LATENCY_EDGES[LATENCY_EDGES.length - 1] ?? 0}ms`;\n }\n return `${index === 0 ? 0 : (LATENCY_EDGES[index - 1] ?? 0)}–${upper}ms`;\n}\n\n/** Latency histogram over the ladder above, plus p50/p95/p99 of the raw samples. */\nexport function toLatencyDistribution(retrievals: RagRetrieval[]): {\n buckets: DistributionBucket[];\n p50?: number;\n p95?: number;\n p99?: number;\n} {\n const samples: number[] = [];\n const counts = new Array<number>(LATENCY_EDGES.length + 1).fill(0);\n for (const { durationMs } of retrievals) {\n if (durationMs === null) {\n continue;\n }\n samples.push(durationMs);\n const found = LATENCY_EDGES.findIndex((edge) => durationMs < edge);\n const index = found === -1 ? LATENCY_EDGES.length : found;\n counts[index] = (counts[index] ?? 0) + 1;\n }\n const buckets = counts.map((count, index) => ({ label: latencyLabel(index), count }));\n const p50 = percentile(samples, 0.5);\n const p95 = percentile(samples, 0.95);\n const p99 = percentile(samples, 0.99);\n return {\n buckets,\n ...(p50 !== null ? { p50 } : {}),\n ...(p95 !== null ? { p95 } : {}),\n ...(p99 !== null ? { p99 } : {}),\n };\n}\n\n/** Ten equal bins over `[0, 1]`, the range a cosine similarity lives in. */\nconst SCORE_BINS = 10;\n\n/**\n * Top-score histogram — **for ONE retriever kind at a time**, which is the whole reason this takes a\n * `retriever` argument instead of bucketing everything it was handed.\n *\n * A `Passage.score` has no shared meaning across strategies: `EmbeddingRetriever` returns a\n * calibrated cosine similarity in `[0, 1]`, a BM25 leg returns an unbounded relevance score in the\n * tens, and `HybridRetriever`'s RRF returns a rank-derived number that lives in a band about one\n * part in fifty wide and says nothing about quality at all (see the score section on\n * `HybridRetriever`). Pouring those into one histogram produces a chart where the bins mean a\n * different thing per bar — and the reading it invites, \"our scores collapsed\", would be a change in\n * traffic MIX rather than in retrieval quality.\n *\n * So the panel binds `query.retriever: 'embedding'`: the dense leg is the only population whose\n * score is comparable across queries, which is also why `minScore` lives on that retriever alone.\n * Scores outside `[0, 1]` are clamped into the end bins rather than dropped, so a store that reports\n * a distance-derived score still shows up as an obviously-pinned bar instead of an empty chart.\n */\nexport function toScoreDistribution(\n retrievals: RagRetrieval[],\n retriever: string,\n): { buckets: DistributionBucket[]; p50?: number; p95?: number } {\n const samples: number[] = [];\n const counts = new Array<number>(SCORE_BINS).fill(0);\n for (const retrieval of retrievals) {\n if (retrieval.retriever !== retriever || retrieval.topScore === null) {\n continue;\n }\n samples.push(retrieval.topScore);\n const clamped = Math.min(Math.max(retrieval.topScore, 0), 1);\n const index = Math.min(Math.floor(clamped * SCORE_BINS), SCORE_BINS - 1);\n counts[index] = (counts[index] ?? 0) + 1;\n }\n const buckets = counts.map((count, index) => ({\n label: `${round(index / SCORE_BINS, 1)}–${round((index + 1) / SCORE_BINS, 1)}`,\n count,\n }));\n const p50 = percentile(samples, 0.5);\n const p95 = percentile(samples, 0.95);\n return {\n buckets,\n ...(p50 !== null ? { p50: round(p50, 4) } : {}),\n ...(p95 !== null ? { p95: round(p95, 4) } : {}),\n };\n}\n\n/** Start of the UTC hour a timestamp falls in. */\nfunction hourStart(at: Date): number {\n return Math.floor(at.getTime() / 3_600_000) * 3_600_000;\n}\n\n/**\n * Retrievals and zero-hits per UTC hour, oldest bucket first, over the last {@link TREND_HOURS}.\n * Empty hours are emitted as zeroes so a quiet stretch reads as a gap in the line rather than\n * disappearing and making the outage look like it never happened.\n */\nexport function toRetrievalTrendRows(\n retrievals: RagRetrieval[],\n now = new Date(),\n): Array<{ label: string; retrievals: number; zeroHits: number }> {\n const latest = hourStart(now);\n const earliest = latest - (TREND_HOURS - 1) * 3_600_000;\n const buckets = new Map<number, { retrievals: number; zeroHits: number }>();\n for (let hour = earliest; hour <= latest; hour += 3_600_000) {\n buckets.set(hour, { retrievals: 0, zeroHits: 0 });\n }\n for (const retrieval of retrievals) {\n const bucket = buckets.get(hourStart(retrieval.at));\n if (bucket === undefined) {\n continue;\n }\n bucket.retrievals += 1;\n if (retrieval.zeroHit) {\n bucket.zeroHits += 1;\n }\n }\n return [...buckets.entries()].map(([hour, counts]) => ({\n label: `${new Date(hour).toISOString().slice(11, 13)}:00`,\n retrievals: counts.retrievals,\n zeroHits: counts.zeroHits,\n }));\n}\n\n/** Count retrievals by one dimension, biggest first, with a placeholder for the absent case. */\nfunction segmentsBy(\n retrievals: RagRetrieval[],\n pick: (retrieval: RagRetrieval) => string | null,\n): BreakdownSegment[] {\n const counts = new Map<string, number>();\n for (const retrieval of retrievals) {\n const label = pick(retrieval) ?? NO_VALUE;\n counts.set(label, (counts.get(label) ?? 0) + 1);\n }\n return [...counts.entries()]\n .map(([label, value]) => ({ label, value }))\n .sort((a, b) => b.value - a.value);\n}\n\n/** Retrievals by vector store (`memory`/`pg`/`redis`, or `—` for an in-process retriever). */\nexport function toStoreSegments(retrievals: RagRetrieval[]): BreakdownSegment[] {\n return segmentsBy(retrievals, (retrieval) => retrieval.store);\n}\n\n/** Retrievals by strategy — the composed kind, since that is what answered. */\nexport function toRetrieverSegments(retrievals: RagRetrieval[]): BreakdownSegment[] {\n return segmentsBy(retrievals, (retrieval) => retrieval.retriever);\n}\n\n/** Per-collection rollup, busiest first. `p95Ms`/`meanTopScore` fall back to `—` when unmeasured. */\nexport function toCollectionRows(retrievals: RagRetrieval[], limit = TABLE_LIMIT): CollectionRow[] {\n const groups = new Map<string, RagRetrieval[]>();\n for (const retrieval of retrievals) {\n const key = retrieval.collection ?? NO_VALUE;\n const group = groups.get(key);\n if (group === undefined) {\n groups.set(key, [retrieval]);\n } else {\n group.push(retrieval);\n }\n }\n return [...groups.entries()]\n .map(([collection, group]) => {\n const durations: number[] = [];\n const scores: number[] = [];\n for (const retrieval of group) {\n if (retrieval.durationMs !== null) {\n durations.push(retrieval.durationMs);\n }\n if (retrieval.topScore !== null) {\n scores.push(retrieval.topScore);\n }\n }\n const p95 = percentile(durations, 0.95);\n const meanScore =\n scores.length === 0 ? null : scores.reduce((sum, score) => sum + score, 0) / scores.length;\n return {\n collection,\n store: group[0]?.store ?? NO_VALUE,\n retrievals: group.length,\n zeroHits: group.filter((retrieval) => retrieval.zeroHit).length,\n p95Ms: p95 === null ? NO_VALUE : Math.round(p95),\n meanTopScore: meanScore === null ? NO_VALUE : round(meanScore, 3),\n };\n })\n .sort((a, b) => b.retrievals - a.retrievals)\n .slice(0, limit);\n}\n\n/**\n * The slowest retrievals in the window, worst first — the table an operator opens after the p95\n * moves. Sorted by duration rather than by recency on purpose: \"recent retrievals\" would be a list\n * of whatever just happened, which the trend already shows in aggregate, whereas the tail is the\n * only place a single pathological query is visible at all.\n */\nexport function toSlowestRows(retrievals: RagRetrieval[], limit = TABLE_LIMIT): SlowestRow[] {\n return retrievals\n .filter((retrieval) => retrieval.durationMs !== null)\n .sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0))\n .slice(0, limit)\n .map((retrieval) => ({\n at: retrieval.at.toISOString(),\n retriever: retrieval.retriever,\n store: retrieval.store ?? NO_VALUE,\n collection: retrieval.collection ?? NO_VALUE,\n chunks: retrieval.chunks,\n topScore: retrieval.topScore === null ? NO_VALUE : round(retrieval.topScore, 3),\n durationMs: retrieval.durationMs === null ? NO_VALUE : Math.round(retrieval.durationMs),\n }));\n}\n\n/** Build a provider from one shaping step over the retrieval window. */\nfunction retrievalProvider(\n name: string,\n format: (retrievals: RagRetrieval[], query: Record<string, unknown> | undefined) => unknown,\n): DataProvider {\n return {\n name,\n async resolve(query, ctx) {\n return format(await readRetrievals(retrievalStorage(ctx)), query);\n },\n };\n}\n\n/** stat → retrievals in the window. */\nexport function ragRetrievalsProvider(): DataProvider {\n return retrievalProvider('agent.rag.retrievals', (retrievals) => ({ value: retrievals.length }));\n}\n\n/** stat (percent) → share of retrievals that returned nothing. */\nexport function ragZeroHitRateProvider(): DataProvider {\n return retrievalProvider('agent.rag.zeroHitRate', (retrievals) => ({\n value: zeroHitRate(retrievals),\n }));\n}\n\n/** stat → mean passages returned per retrieval. */\nexport function ragChunksProvider(): DataProvider {\n return retrievalProvider('agent.rag.chunks', (retrievals) => ({ value: meanChunks(retrievals) }));\n}\n\n/** distribution → retrieval latency, with p50/p95/p99 markers. */\nexport function ragLatencyProvider(): DataProvider {\n return retrievalProvider('agent.rag.latency', toLatencyDistribution);\n}\n\n/** distribution → top score for ONE retriever kind (`query.retriever`, default `embedding`). */\nexport function ragScoresProvider(): DataProvider {\n return retrievalProvider('agent.rag.scores', (retrievals, query) => {\n const requested = query?.retriever;\n return toScoreDistribution(retrievals, typeof requested === 'string' ? requested : 'embedding');\n });\n}\n\n/** timeseries → retrievals and zero-hits per hour. */\nexport function ragTrendProvider(): DataProvider {\n return retrievalProvider('agent.rag.trend', (retrievals) => ({\n rows: toRetrievalTrendRows(retrievals),\n }));\n}\n\n/** breakdown → retrievals by vector store. */\nexport function ragStoreBreakdownProvider(): DataProvider {\n return retrievalProvider('agent.rag.byStore', (retrievals) => ({\n segments: toStoreSegments(retrievals),\n }));\n}\n\n/** breakdown → retrievals by retriever strategy. */\nexport function ragRetrieverBreakdownProvider(): DataProvider {\n return retrievalProvider('agent.rag.byRetriever', (retrievals) => ({\n segments: toRetrieverSegments(retrievals),\n }));\n}\n\n/** table → per-collection rollup, busiest first. */\nexport function ragCollectionsTableProvider(): DataProvider {\n return retrievalProvider('agent.rag.byCollection', (retrievals) => ({\n rows: toCollectionRows(retrievals),\n }));\n}\n\n/** table → the slowest retrievals in the window. */\nexport function ragSlowestTableProvider(): DataProvider {\n return retrievalProvider('agent.rag.slowest', (retrievals) => ({\n rows: toSlowestRows(retrievals),\n }));\n}\n","import { subscribe, unsubscribe } from 'node:diagnostics_channel';\nimport { channelName, claimDiagnostics } from '@dudousxd/nestjs-diagnostics';\nimport type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';\n\n/**\n * The diagnostics coordinates `@dudousxd/nestjs-agent-rag` publishes retrieval telemetry on. Kept as\n * literals rather than imported from that package, exactly as {@link AgentTelescopeWatcher} depends\n * on the diagnostics channel and not on the agent runtime: this extension must stay installable by a\n * host that has Telescope and the agent but no retrieval stack at all, and adding a dependency on the\n * rag package to read two strings would drag pg/redis-shaped code into every such install. The\n * channel name is the published wire contract (`RAG_RETRIEVAL_CHANNEL` on the producer side).\n */\nconst RAG_LIB = 'rag';\nconst RETRIEVAL_EVENT = 'retrieval';\n\n/** The Telescope entry `type` retrieval events are recorded as — see the class doc. */\nexport const RAG_ENTRY_TYPE = 'agent-rag';\n\n/** The envelope `@dudousxd/nestjs-diagnostics` publishes: metadata plus the emitter's payload. */\ninterface DiagnosticEnvelope {\n event: string;\n durationMs?: number;\n payload: Record<string, unknown>;\n}\n\nfunction isEnvelope(message: unknown): message is DiagnosticEnvelope {\n return (\n typeof message === 'object' &&\n message !== null &&\n typeof Reflect.get(message, 'payload') === 'object' &&\n Reflect.get(message, 'payload') !== null\n );\n}\n\n/**\n * Records `aviary:rag:retrieval` events as Telescope entries of type `agent-rag` — the source every\n * RAG panel on the Agent dashboard reads.\n *\n * **Its own entry type, not `agent`.** Retrieval is per-tool-call where a run is per-conversation, so\n * a busy hour produces an order of magnitude more retrieval events than agent events. Sharing the\n * `agent` type would put them in one storage window: the providers page 5k entries of a type, and\n * retrieval traffic would push `run.finished` out of that window, quietly zeroing the Runs and Tokens\n * stats that have nothing to do with RAG. Separate types make the two independent, and give the\n * Entries screen a \"RAG\" filter that lists retrievals and only retrievals.\n *\n * **The duration is lifted off the ENVELOPE into the entry content.** The emitter puts it there\n * (`emit`'s `opts.durationMs`) because that is the field Telescope's OTel exporter turns into a\n * latency histogram; the panels need it as an ordinary field they can bucket, and an entry's content\n * is all a `DataProvider` gets. Recording it in both places would mean two sources of truth for the\n * same number, so it is lifted rather than duplicated at the emitter.\n *\n * Claims `rag:retrieval` (refcounted, released in `dispose()`) so\n * `@dudousxd/nestjs-diagnostics-telescope`'s generic bridge skips it instead of recording every\n * retrieval a second time as a generic `diagnostic` entry.\n *\n * Registered by `agentTelescopeExtension()`; also usable on its own in a host's `watchers` list.\n */\nexport class RagTelescopeWatcher implements Watcher {\n readonly type = RAG_ENTRY_TYPE;\n private readonly disposers: Array<() => void> = [];\n\n register(ctx: WatcherContext): void {\n this.disposers.push(claimDiagnostics(RAG_LIB, [RETRIEVAL_EVENT]));\n const channel = channelName(RAG_LIB, RETRIEVAL_EVENT);\n const onMessage = (message: unknown) => {\n if (!isEnvelope(message)) {\n return;\n }\n ctx.record({\n type: RAG_ENTRY_TYPE,\n content: {\n event: RETRIEVAL_EVENT,\n ...message.payload,\n ...(message.durationMs !== undefined ? { durationMs: message.durationMs } : {}),\n },\n // Tagged by store and retriever kind so the Entries screen can filter to \"every retrieval\n // pgvector served\" without a provider — the same tag-per-dimension the agent watcher uses.\n tags: tagsOf(message.payload),\n });\n };\n subscribe(channel, onMessage);\n this.disposers.push(() => unsubscribe(channel, onMessage));\n }\n\n /** Detach the subscription and release the diagnostics claim (e.g. on module destroy). */\n dispose(): void {\n while (this.disposers.length) this.disposers.pop()?.();\n }\n}\n\n/** `retriever:<kind>` / `store:<kind>` / `zero-hit` / `failed`, for whichever the payload carries. */\nfunction tagsOf(payload: Record<string, unknown>): string[] {\n const tags = [RETRIEVAL_EVENT];\n if (typeof payload.retriever === 'string') {\n tags.push(`retriever:${payload.retriever}`);\n }\n if (typeof payload.store === 'string') {\n tags.push(`store:${payload.store}`);\n }\n if (payload.zeroHit === true) {\n tags.push('zero-hit');\n }\n if (payload.failed === true) {\n tags.push('failed');\n }\n return tags;\n}\n"],"mappings":"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","names":["import_nestjs_telescope","col","key","label","href","undefined","link","agentDashboard","opts","runHref","id","panels","sections","title","cols","kind","data","provider","format","style","series","columns","query","metric","paged","threadHref","markers","retriever","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","readPositiveNumber","raw","Number","isFinite","undefined","trim","parsed","resolveLimit","fallback","limit","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","import_nestjs_telescope","import_node_diagnostics_channel","import_nestjs_diagnostics","RAG_LIB","RETRIEVAL_EVENT","RAG_ENTRY_TYPE","isEnvelope","message","Reflect","get","RagTelescopeWatcher","type","disposers","register","ctx","push","claimDiagnostics","channel","channelName","onMessage","record","content","event","payload","durationMs","undefined","tags","tagsOf","subscribe","unsubscribe","dispose","length","pop","retriever","store","zeroHit","failed","RETRIEVAL_WINDOW","TABLE_LIMIT","TREND_HOURS","NO_VALUE","isRecord","value","readString","source","key","readNumber","Number","isFinite","isEntryStorage","get","toRagRetrieval","entry","content","retriever","chunks","createdAt","at","Date","store","collection","zeroHit","topScore","durationMs","failed","readRetrievals","storage","page","type","RAG_ENTRY_TYPE","limit","retrievals","data","retrieval","push","retrievalStorage","ctx","moduleRef","TELESCOPE_STORAGE","strict","undefined","percentile","samples","fraction","length","sorted","sort","a","b","rank","Math","ceil","min","max","round","places","factor","zeroHitRate","zeroHits","filter","meanChunks","total","reduce","sum","LATENCY_EDGES","latencyLabel","index","upper","toLatencyDistribution","counts","Array","fill","found","findIndex","edge","buckets","map","count","label","p50","p95","p99","SCORE_BINS","toScoreDistribution","clamped","floor","hourStart","getTime","toRetrievalTrendRows","now","latest","earliest","Map","hour","set","bucket","entries","toISOString","slice","segmentsBy","pick","toStoreSegments","toRetrieverSegments","toCollectionRows","groups","group","durations","scores","meanScore","score","p95Ms","meanTopScore","toSlowestRows","retrievalProvider","name","format","resolve","query","ragRetrievalsProvider","ragZeroHitRateProvider","ragChunksProvider","ragLatencyProvider","ragScoresProvider","requested","ragTrendProvider","rows","ragStoreBreakdownProvider","segments","ragRetrieverBreakdownProvider","ragCollectionsTableProvider","ragSlowestTableProvider","RESERVED_PROVIDER_PREFIX","agentTelescopeExtension","opts","hostProviders","providers","reserved","filter","provider","name","startsWith","length","Error","map","join","defineTelescopeExtension","watchers","AgentTelescopeWatcher","RagTelescopeWatcher","entryTypes","id","label","dot","dashboards","agentDashboard","threadHref","undefined","runHref","sections","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","ragRetrievalsProvider","ragZeroHitRateProvider","ragChunksProvider","ragLatencyProvider","ragScoresProvider","ragTrendProvider","ragStoreBreakdownProvider","ragRetrieverBreakdownProvider","ragCollectionsTableProvider","ragSlowestTableProvider"]}
|