@agimon-ai/doompi-log 0.0.1-alpha.2 → 0.0.1-alpha.20
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/README.md +42 -19
- package/dist/adapters/node/metricsSource.cjs +2 -0
- package/dist/adapters/node/metricsSource.cjs.map +1 -0
- package/dist/adapters/node/metricsSource.d.cts +14 -0
- package/dist/adapters/node/metricsSource.d.cts.map +1 -0
- package/dist/adapters/node/metricsSource.d.mts +14 -0
- package/dist/adapters/node/metricsSource.d.mts.map +1 -0
- package/dist/adapters/node/metricsSource.mjs +2 -0
- package/dist/adapters/node/metricsSource.mjs.map +1 -0
- package/dist/adapters/pi/extension.cjs +2 -0
- package/dist/adapters/pi/extension.cjs.map +1 -0
- package/dist/adapters/pi/extension.d.cts +34 -0
- package/dist/adapters/pi/extension.d.cts.map +1 -0
- package/dist/adapters/pi/extension.d.mts +34 -0
- package/dist/adapters/pi/extension.d.mts.map +1 -0
- package/dist/adapters/pi/extension.mjs +2 -0
- package/dist/adapters/pi/extension.mjs.map +1 -0
- package/dist/extension.cjs +1 -2
- package/dist/extension.d.cts +2 -33
- package/dist/extension.d.mts +2 -33
- package/dist/extension.mjs +1 -2
- package/dist/extensions/pi.cjs +1 -2
- package/dist/extensions/pi.d.cts +2 -4
- package/dist/extensions/pi.d.mts +2 -5
- package/dist/extensions/pi.mjs +1 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +1 -1
- package/dist/metrics.cjs +1 -2
- package/dist/metrics.d.cts +3 -94
- package/dist/metrics.d.mts +3 -94
- package/dist/metrics.mjs +1 -2
- package/dist/metricsSource.cjs +1 -2
- package/dist/metricsSource.d.cts +3 -25
- package/dist/metricsSource.d.mts +3 -25
- package/dist/metricsSource.mjs +1 -2
- package/dist/services/findings.cjs +2 -0
- package/dist/services/findings.cjs.map +1 -0
- package/dist/services/findings.d.cts +23 -0
- package/dist/services/findings.d.cts.map +1 -0
- package/dist/services/findings.d.mts +23 -0
- package/dist/services/findings.d.mts.map +1 -0
- package/dist/services/findings.mjs +2 -0
- package/dist/services/findings.mjs.map +1 -0
- package/dist/services/metrics.cjs +2 -0
- package/dist/services/metrics.cjs.map +1 -0
- package/dist/services/metrics.d.cts +155 -0
- package/dist/services/metrics.d.cts.map +1 -0
- package/dist/services/metrics.d.mts +155 -0
- package/dist/services/metrics.d.mts.map +1 -0
- package/dist/services/metrics.mjs +2 -0
- package/dist/services/metrics.mjs.map +1 -0
- package/dist/tui/logMetricsOverlay.cjs +2 -0
- package/dist/tui/logMetricsOverlay.cjs.map +1 -0
- package/dist/tui/logMetricsOverlay.d.cts +80 -0
- package/dist/tui/logMetricsOverlay.d.cts.map +1 -0
- package/dist/tui/logMetricsOverlay.d.mts +80 -0
- package/dist/tui/logMetricsOverlay.d.mts.map +1 -0
- package/dist/tui/logMetricsOverlay.mjs +2 -0
- package/dist/tui/logMetricsOverlay.mjs.map +1 -0
- package/dist/tui/metricsOverlay.cjs +1 -2
- package/dist/tui/metricsOverlay.d.cts +2 -71
- package/dist/tui/metricsOverlay.d.mts +2 -71
- package/dist/tui/metricsOverlay.mjs +1 -2
- package/dist/types/metricsSource.d.cts +16 -0
- package/dist/types/metricsSource.d.cts.map +1 -0
- package/dist/types/metricsSource.d.mts +16 -0
- package/dist/types/metricsSource.d.mts.map +1 -0
- package/package.json +16 -9
- package/dist/extension.cjs.map +0 -1
- package/dist/extension.d.cts.map +0 -1
- package/dist/extension.d.mts.map +0 -1
- package/dist/extension.mjs.map +0 -1
- package/dist/extensions/pi.cjs.map +0 -1
- package/dist/extensions/pi.d.cts.map +0 -1
- package/dist/extensions/pi.d.mts.map +0 -1
- package/dist/extensions/pi.mjs.map +0 -1
- package/dist/metrics.cjs.map +0 -1
- package/dist/metrics.d.cts.map +0 -1
- package/dist/metrics.d.mts.map +0 -1
- package/dist/metrics.mjs.map +0 -1
- package/dist/metricsSource.cjs.map +0 -1
- package/dist/metricsSource.d.cts.map +0 -1
- package/dist/metricsSource.d.mts.map +0 -1
- package/dist/metricsSource.mjs.map +0 -1
- package/dist/tui/metricsOverlay.cjs.map +0 -1
- package/dist/tui/metricsOverlay.d.cts.map +0 -1
- package/dist/tui/metricsOverlay.d.mts.map +0 -1
- package/dist/tui/metricsOverlay.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# @agimon-ai/doompi-log
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**If the agent emits telemetry, you should be able to see it.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package turns Doompi's LogSink records into session-local metrics and a terminal
|
|
6
|
+
overlay. Counters and spans stay useful to the person running the session instead of
|
|
7
|
+
disappearing into a database nobody opens.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
installed on its own.
|
|
9
|
+
This is part of [Doompi](https://www.npmjs.com/package/@agimon-ai/doompi). Most users get
|
|
10
|
+
it with the distribution.
|
|
10
11
|
|
|
11
12
|
## Install
|
|
12
13
|
|
|
@@ -16,25 +17,47 @@ npm install @agimon-ai/doompi-log
|
|
|
16
17
|
|
|
17
18
|
## How it loads
|
|
18
19
|
|
|
19
|
-
Doompi loads
|
|
20
|
-
`.doom/modes.yaml
|
|
21
|
-
|
|
22
|
-
Extension entry: `@agimon-ai/doompi-log/extensions/pi`
|
|
20
|
+
Doompi loads the log viewer as core. It is not a layer and does not appear in
|
|
21
|
+
`.doom/modes.yaml`. The bare package name follows its Pi manifest and loads the Pi adapter.
|
|
23
22
|
|
|
24
23
|
## Leader
|
|
25
24
|
|
|
26
|
-
`SPC h l` opens
|
|
25
|
+
`SPC h l` opens the Log Metrics overlay for the current session.
|
|
26
|
+
|
|
27
|
+
## What the overlay shows
|
|
28
|
+
|
|
29
|
+
The panel answers two questions — what is this session costing, and what should change
|
|
30
|
+
next — so every row is something you can act on.
|
|
31
|
+
|
|
32
|
+
| Panel | What it tells you |
|
|
33
|
+
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| Headline | Tokens, cache hit rate, cost per turn, tool failure rate, and issues. Cache and tool-failure values are coloured against a threshold; the rest are workload-dependent and stay neutral. |
|
|
35
|
+
| `WHAT TO FIX` | Ranked findings derived from the session, each paired with the change that moves it: a failing tool, redone turns, a cold cache, a tool dragging outsized turns. Critical first. |
|
|
36
|
+
| `TOOL COST` | Tools ranked by cost per call rather than by how often they run, with call count, failure rate, and p95 latency alongside. |
|
|
37
|
+
| `TOP CONSUMERS` | Biggest token consumers from the sink database for the selected dimension and period. Rows with issues render in the error colour. |
|
|
38
|
+
| `TOKEN BURN` | Token spend per time bucket, newest last. |
|
|
39
|
+
| `RECENT ERRORS` | The session's most recent failures, newest first. |
|
|
40
|
+
| `SINK STATUS` | Backend and endpoint. Press `?` for full wiring, collection scope, and the caveats behind each panel. |
|
|
41
|
+
|
|
42
|
+
Findings are computed in-process from records the extension already emits, so the panel
|
|
43
|
+
keeps working with no sink connected — only `TOP CONSUMERS` and `TOKEN BURN` need one.
|
|
44
|
+
|
|
45
|
+
Thresholds are deliberately conservative: a finding that fires on a healthy session
|
|
46
|
+
teaches you to ignore the panel.
|
|
47
|
+
|
|
48
|
+
### A note on `TOOL COST`
|
|
49
|
+
|
|
50
|
+
The column reports the p90 _turn_ total for turns a tool took part in, which is the only
|
|
51
|
+
attribution Pi emits. A turn running several tools attributes its total to each of them,
|
|
52
|
+
so the number ranks tools by the weight of the turns they appear in — it is not a per-tool
|
|
53
|
+
share of spend. The same caveat is available in the overlay under `?`.
|
|
54
|
+
|
|
55
|
+
Keys: `r` refresh · `g` cycle dimension · `p` cycle period · `?` detail · `esc` close.
|
|
27
56
|
|
|
28
|
-
##
|
|
57
|
+
## Public API
|
|
29
58
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
| `@agimon-ai/doompi-log` |
|
|
33
|
-
| `@agimon-ai/doompi-log/extension` |
|
|
34
|
-
| `@agimon-ai/doompi-log/extensions/pi` |
|
|
35
|
-
| `@agimon-ai/doompi-log/metrics` |
|
|
36
|
-
| `@agimon-ai/doompi-log/metricsSource` |
|
|
37
|
-
| `@agimon-ai/doompi-log/tui/metricsOverlay` |
|
|
59
|
+
The package exports the extension, metrics source, overlay, and Pi adapter through declared
|
|
60
|
+
subpaths. See `package.json` for the complete list.
|
|
38
61
|
|
|
39
62
|
## License
|
|
40
63
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:child_process"),n=require("node:module"),r=require("node:path");r=e.__toESM(r,1);let i=require("@agimon-ai/log-sink-mcp");const a=`total-tokens`;function o(){let e=(0,n.createRequire)(require("url").pathToFileURL(__filename).href).resolve(`@agimon-ai/log-sink-mcp/package.json`);return r.default.join(r.default.dirname(e),`dist`,`cli.mjs`)}function s(e){return new URLSearchParams({groupBy:e.groupBy,period:e.period,sort:a,limit:String(e.limit),toolLimit:`1`}).toString()}async function c(e,t,n){let r=await n(`${e}/api/metrics?${s(t)}`,{signal:AbortSignal.timeout(5e3)});if(!r.ok)throw Error(`sink responded ${r.status}`);let i=await r.json();if(i.error||!Array.isArray(i.timeline))throw Error(i.error??`sink is an older version`);return i}function l(e){return new Promise((n,r)=>{(0,t.execFile)(process.execPath,[o(),`logs`,`metrics`,`--group-by`,e.groupBy,`--period`,e.period,`--sort`,a,`--limit`,String(e.limit),`--tool-limit`,`1`],{timeout:3e4,maxBuffer:33554432},(e,t,i)=>{if(e){r(Error(i.trim()||e.message));return}try{n(JSON.parse(t))}catch{r(Error(`metrics CLI returned unparsable output`))}})})}function u(e={}){let t=e.fetchImpl??globalThis.fetch,n=e.cliRunner??l,r,a,o=async()=>{if(a!==void 0)return a??void 0;try{a=(await(0,i.resolveLogSinkPort)({env:e.env,cwd:e.cwd,healthCheck:!0}))?.endpoint??null}catch{a=null}return a??void 0};return{lastTransport:()=>r,async query(e){let i=await o();if(i&&t)try{let n=await c(i,e,t);return r=`http`,n}catch{a=null}let s=await n(e);return r=`cli`,s}}}exports.createMetricsSource=u;
|
|
2
|
+
//# sourceMappingURL=metricsSource.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metricsSource.cjs","names":["createRequire","path","resolveLogSinkPort"],"sources":["../../../src/adapters/node/metricsSource.ts"],"sourcesContent":["/**\n * Historical metrics access for the `SPC h l` overlay.\n *\n * Two transports, in order: the running sink's HTTP API, then the installed\n * CLI as a subprocess. The sink daemon is long-lived and often lags the\n * installed package, so a daemon that rejects newer query parameters is treated\n * as unavailable rather than fatal. The reader exported by log-sink-mcp is\n * deliberately not used in-process: better-sqlite3 is synchronous and a\n * one-day window blocks for seconds, which would freeze the TUI.\n */\nimport { execFile } from 'node:child_process';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport type { LogMetricsReport } from '@agimon-ai/log-sink-mcp';\nimport { resolveLogSinkPort } from '@agimon-ai/log-sink-mcp';\nimport type { MetricsQueryParams, MetricsSource, MetricsTransport } from '../../types/metricsSource.ts';\n\nconst PACKAGE_NAME = '@agimon-ai/log-sink-mcp';\nconst HTTP_TIMEOUT_MS = 5000;\nconst CLI_TIMEOUT_MS = 30000;\n/** A day of dev telemetry is already ~140k records; keep the payload bounded. */\nconst MAX_CLI_BUFFER = 32 * 1024 * 1024;\nconst TOOL_LIMIT = '1';\n/** The panel ranks consumers, so ask for the biggest rather than the most recent. */\nconst TOKEN_SORT = 'total-tokens';\n\nexport interface MetricsSourceOptions {\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n /** Overrides transport discovery in tests. */\n fetchImpl?: typeof fetch;\n cliRunner?: (params: MetricsQueryParams) => Promise<LogMetricsReport>;\n}\n\nfunction cliEntryPoint(): string {\n const require = createRequire(import.meta.url);\n // The published bin is CJS; the ESM build sits beside it and starts faster.\n const packageJson = require.resolve(`${PACKAGE_NAME}/package.json`);\n return path.join(path.dirname(packageJson), 'dist', 'cli.mjs');\n}\n\nfunction searchParams(params: MetricsQueryParams): string {\n return new URLSearchParams({\n groupBy: params.groupBy,\n period: params.period,\n sort: TOKEN_SORT,\n limit: String(params.limit),\n toolLimit: TOOL_LIMIT,\n }).toString();\n}\n\nasync function queryHttp(\n endpoint: string,\n params: MetricsQueryParams,\n fetchImpl: typeof fetch,\n): Promise<LogMetricsReport> {\n const response = await fetchImpl(`${endpoint}/api/metrics?${searchParams(params)}`, {\n signal: AbortSignal.timeout(HTTP_TIMEOUT_MS),\n });\n if (!response.ok) throw new Error(`sink responded ${response.status}`);\n\n const body = (await response.json()) as LogMetricsReport & { error?: string };\n // An older daemon rejects unknown group-by values and omits the timeline.\n if (body.error || !Array.isArray(body.timeline)) throw new Error(body.error ?? 'sink is an older version');\n return body;\n}\n\nfunction runCli(params: MetricsQueryParams): Promise<LogMetricsReport> {\n return new Promise((resolve, reject) => {\n execFile(\n process.execPath,\n [\n cliEntryPoint(),\n 'logs',\n 'metrics',\n '--group-by',\n params.groupBy,\n '--period',\n params.period,\n '--sort',\n TOKEN_SORT,\n '--limit',\n String(params.limit),\n '--tool-limit',\n TOOL_LIMIT,\n ],\n { timeout: CLI_TIMEOUT_MS, maxBuffer: MAX_CLI_BUFFER },\n (error, stdout, stderr) => {\n if (error) {\n reject(new Error(stderr.trim() || error.message));\n return;\n }\n try {\n resolve(JSON.parse(stdout) as LogMetricsReport);\n } catch {\n reject(new Error('metrics CLI returned unparsable output'));\n }\n },\n );\n });\n}\n\nexport function createMetricsSource(options: MetricsSourceOptions = {}): MetricsSource {\n const fetchImpl = options.fetchImpl ?? globalThis.fetch;\n const cliRunner = options.cliRunner ?? runCli;\n let transport: MetricsTransport | undefined;\n let endpoint: string | undefined | null;\n\n const resolveEndpoint = async (): Promise<string | undefined> => {\n if (endpoint !== undefined) return endpoint ?? undefined;\n try {\n const resolved = await resolveLogSinkPort({ env: options.env, cwd: options.cwd, healthCheck: true });\n endpoint = resolved?.endpoint ?? null;\n } catch {\n endpoint = null;\n }\n return endpoint ?? undefined;\n };\n\n return {\n lastTransport: () => transport,\n async query(params) {\n const httpEndpoint = await resolveEndpoint();\n if (httpEndpoint && fetchImpl) {\n try {\n const report = await queryHttp(httpEndpoint, params, fetchImpl);\n transport = 'http';\n return report;\n } catch {\n // A stale or unhealthy daemon must not hide data the CLI can still read.\n endpoint = null;\n }\n }\n\n const report = await cliRunner(params);\n transport = 'cli';\n return report;\n },\n };\n}\n"],"mappings":"sMAiBA,MAOM,EAAa,eAUnB,SAAS,GAAwB,CAG/B,IAAM,GAAA,EAFUA,EAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAEU,CAAC,CAAC,QAAQ,sCAA8B,EAClE,OAAOC,EAAAA,QAAK,KAAKA,EAAAA,QAAK,QAAQ,CAAW,EAAG,OAAQ,SAAS,CAC/D,CAEA,SAAS,EAAa,EAAoC,CACxD,OAAO,IAAI,gBAAgB,CACzB,QAAS,EAAO,QAChB,OAAQ,EAAO,OACf,KAAM,EACN,MAAO,OAAO,EAAO,KAAK,EAC1B,UAAW,GACb,CAAC,CAAC,CAAC,SAAS,CACd,CAEA,eAAe,EACb,EACA,EACA,EAC2B,CAC3B,IAAM,EAAW,MAAM,EAAU,GAAG,EAAS,eAAe,EAAa,CAAM,IAAK,CAClF,OAAQ,YAAY,QAAQ,GAAe,CAC7C,CAAC,EACD,GAAI,CAAC,EAAS,GAAI,MAAU,MAAM,kBAAkB,EAAS,QAAQ,EAErE,IAAM,EAAQ,MAAM,EAAS,KAAK,EAElC,GAAI,EAAK,OAAS,CAAC,MAAM,QAAQ,EAAK,QAAQ,EAAG,MAAU,MAAM,EAAK,OAAS,0BAA0B,EACzG,OAAO,CACT,CAEA,SAAS,EAAO,EAAuD,CACrE,OAAO,IAAI,SAAS,EAAS,IAAW,EACtC,EAAA,EAAA,SAAA,CACE,QAAQ,SACR,CACE,EAAc,EACd,OACA,UACA,aACA,EAAO,QACP,WACA,EAAO,OACP,SACA,EACA,UACA,OAAO,EAAO,KAAK,EACnB,eACA,GACF,EACA,CAAE,QAAS,IAAgB,UAAW,QAAe,GACpD,EAAO,EAAQ,IAAW,CACzB,GAAI,EAAO,CACT,EAAW,MAAM,EAAO,KAAK,GAAK,EAAM,OAAO,CAAC,EAChD,MACF,CACA,GAAI,CACF,EAAQ,KAAK,MAAM,CAAM,CAAqB,CAChD,MAAQ,CACN,EAAW,MAAM,wCAAwC,CAAC,CAC5D,CACF,CACF,CACF,CAAC,CACH,CAEA,SAAgB,EAAoB,EAAgC,CAAC,EAAkB,CACrF,IAAM,EAAY,EAAQ,WAAa,WAAW,MAC5C,EAAY,EAAQ,WAAa,EACnC,EACA,EAEE,EAAkB,SAAyC,CAC/D,GAAI,IAAa,IAAA,GAAW,OAAO,GAAY,IAAA,GAC/C,GAAI,CAEF,GAAW,MAAA,EADYC,EAAAA,mBAAAA,CAAmB,CAAE,IAAK,EAAQ,IAAK,IAAK,EAAQ,IAAK,YAAa,EAAK,CAAC,EAAA,EAC9E,UAAY,IACnC,MAAQ,CACN,EAAW,IACb,CACA,OAAO,GAAY,IAAA,EACrB,EAEA,MAAO,CACL,kBAAqB,EACrB,MAAM,MAAM,EAAQ,CAClB,IAAM,EAAe,MAAM,EAAgB,EAC3C,GAAI,GAAgB,EAClB,GAAI,CACF,IAAM,EAAS,MAAM,EAAU,EAAc,EAAQ,CAAS,EAE9D,MADA,GAAY,OACL,CACT,MAAQ,CAEN,EAAW,IACb,CAGF,IAAM,EAAS,MAAM,EAAU,CAAM,EAErC,MADA,GAAY,MACL,CACT,CACF,CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MetricsQueryParams, MetricsSource } from "../../types/metricsSource.cjs";
|
|
2
|
+
import { LogMetricsReport } from "@agimon-ai/log-sink-mcp";
|
|
3
|
+
//#region src/adapters/node/metricsSource.d.ts
|
|
4
|
+
interface MetricsSourceOptions {
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
/** Overrides transport discovery in tests. */
|
|
8
|
+
fetchImpl?: typeof fetch;
|
|
9
|
+
cliRunner?: (params: MetricsQueryParams) => Promise<LogMetricsReport>;
|
|
10
|
+
}
|
|
11
|
+
declare function createMetricsSource(options?: MetricsSourceOptions): MetricsSource;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { MetricsSourceOptions, createMetricsSource };
|
|
14
|
+
//# sourceMappingURL=metricsSource.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metricsSource.d.cts","names":[],"sources":["../../../src/adapters/node/metricsSource.ts"],"mappings":";;;UA0BiB;EACf,MAAM,OAAO;EACb;;EAEA,mBAAmB;EACnB,aAAa,QAAQ,uBAAuB,QAAQ;;iBAuEtC,oBAAoB,UAAS,uBAA4B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MetricsQueryParams, MetricsSource } from "../../types/metricsSource.mjs";
|
|
2
|
+
import { LogMetricsReport } from "@agimon-ai/log-sink-mcp";
|
|
3
|
+
//#region src/adapters/node/metricsSource.d.ts
|
|
4
|
+
interface MetricsSourceOptions {
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
/** Overrides transport discovery in tests. */
|
|
8
|
+
fetchImpl?: typeof fetch;
|
|
9
|
+
cliRunner?: (params: MetricsQueryParams) => Promise<LogMetricsReport>;
|
|
10
|
+
}
|
|
11
|
+
declare function createMetricsSource(options?: MetricsSourceOptions): MetricsSource;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { MetricsSourceOptions, createMetricsSource };
|
|
14
|
+
//# sourceMappingURL=metricsSource.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metricsSource.d.mts","names":[],"sources":["../../../src/adapters/node/metricsSource.ts"],"mappings":";;;UA0BiB;EACf,MAAM,OAAO;EACb;;EAEA,mBAAmB;EACnB,aAAa,QAAQ,uBAAuB,QAAQ;;iBAuEtC,oBAAoB,UAAS,uBAA4B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createRequire as e}from"node:module";import{execFile as t}from"node:child_process";import n from"node:path";import{resolveLogSinkPort as r}from"@agimon-ai/log-sink-mcp";const i=`total-tokens`;function a(){let t=e(import.meta.url).resolve(`@agimon-ai/log-sink-mcp/package.json`);return n.join(n.dirname(t),`dist`,`cli.mjs`)}function o(e){return new URLSearchParams({groupBy:e.groupBy,period:e.period,sort:i,limit:String(e.limit),toolLimit:`1`}).toString()}async function s(e,t,n){let r=await n(`${e}/api/metrics?${o(t)}`,{signal:AbortSignal.timeout(5e3)});if(!r.ok)throw Error(`sink responded ${r.status}`);let i=await r.json();if(i.error||!Array.isArray(i.timeline))throw Error(i.error??`sink is an older version`);return i}function c(e){return new Promise((n,r)=>{t(process.execPath,[a(),`logs`,`metrics`,`--group-by`,e.groupBy,`--period`,e.period,`--sort`,i,`--limit`,String(e.limit),`--tool-limit`,`1`],{timeout:3e4,maxBuffer:33554432},(e,t,i)=>{if(e){r(Error(i.trim()||e.message));return}try{n(JSON.parse(t))}catch{r(Error(`metrics CLI returned unparsable output`))}})})}function l(e={}){let t=e.fetchImpl??globalThis.fetch,n=e.cliRunner??c,i,a,o=async()=>{if(a!==void 0)return a??void 0;try{a=(await r({env:e.env,cwd:e.cwd,healthCheck:!0}))?.endpoint??null}catch{a=null}return a??void 0};return{lastTransport:()=>i,async query(e){let r=await o();if(r&&t)try{let n=await s(r,e,t);return i=`http`,n}catch{a=null}let c=await n(e);return i=`cli`,c}}}export{l as createMetricsSource};
|
|
2
|
+
//# sourceMappingURL=metricsSource.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metricsSource.mjs","names":[],"sources":["../../../src/adapters/node/metricsSource.ts"],"sourcesContent":["/**\n * Historical metrics access for the `SPC h l` overlay.\n *\n * Two transports, in order: the running sink's HTTP API, then the installed\n * CLI as a subprocess. The sink daemon is long-lived and often lags the\n * installed package, so a daemon that rejects newer query parameters is treated\n * as unavailable rather than fatal. The reader exported by log-sink-mcp is\n * deliberately not used in-process: better-sqlite3 is synchronous and a\n * one-day window blocks for seconds, which would freeze the TUI.\n */\nimport { execFile } from 'node:child_process';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\nimport type { LogMetricsReport } from '@agimon-ai/log-sink-mcp';\nimport { resolveLogSinkPort } from '@agimon-ai/log-sink-mcp';\nimport type { MetricsQueryParams, MetricsSource, MetricsTransport } from '../../types/metricsSource.ts';\n\nconst PACKAGE_NAME = '@agimon-ai/log-sink-mcp';\nconst HTTP_TIMEOUT_MS = 5000;\nconst CLI_TIMEOUT_MS = 30000;\n/** A day of dev telemetry is already ~140k records; keep the payload bounded. */\nconst MAX_CLI_BUFFER = 32 * 1024 * 1024;\nconst TOOL_LIMIT = '1';\n/** The panel ranks consumers, so ask for the biggest rather than the most recent. */\nconst TOKEN_SORT = 'total-tokens';\n\nexport interface MetricsSourceOptions {\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n /** Overrides transport discovery in tests. */\n fetchImpl?: typeof fetch;\n cliRunner?: (params: MetricsQueryParams) => Promise<LogMetricsReport>;\n}\n\nfunction cliEntryPoint(): string {\n const require = createRequire(import.meta.url);\n // The published bin is CJS; the ESM build sits beside it and starts faster.\n const packageJson = require.resolve(`${PACKAGE_NAME}/package.json`);\n return path.join(path.dirname(packageJson), 'dist', 'cli.mjs');\n}\n\nfunction searchParams(params: MetricsQueryParams): string {\n return new URLSearchParams({\n groupBy: params.groupBy,\n period: params.period,\n sort: TOKEN_SORT,\n limit: String(params.limit),\n toolLimit: TOOL_LIMIT,\n }).toString();\n}\n\nasync function queryHttp(\n endpoint: string,\n params: MetricsQueryParams,\n fetchImpl: typeof fetch,\n): Promise<LogMetricsReport> {\n const response = await fetchImpl(`${endpoint}/api/metrics?${searchParams(params)}`, {\n signal: AbortSignal.timeout(HTTP_TIMEOUT_MS),\n });\n if (!response.ok) throw new Error(`sink responded ${response.status}`);\n\n const body = (await response.json()) as LogMetricsReport & { error?: string };\n // An older daemon rejects unknown group-by values and omits the timeline.\n if (body.error || !Array.isArray(body.timeline)) throw new Error(body.error ?? 'sink is an older version');\n return body;\n}\n\nfunction runCli(params: MetricsQueryParams): Promise<LogMetricsReport> {\n return new Promise((resolve, reject) => {\n execFile(\n process.execPath,\n [\n cliEntryPoint(),\n 'logs',\n 'metrics',\n '--group-by',\n params.groupBy,\n '--period',\n params.period,\n '--sort',\n TOKEN_SORT,\n '--limit',\n String(params.limit),\n '--tool-limit',\n TOOL_LIMIT,\n ],\n { timeout: CLI_TIMEOUT_MS, maxBuffer: MAX_CLI_BUFFER },\n (error, stdout, stderr) => {\n if (error) {\n reject(new Error(stderr.trim() || error.message));\n return;\n }\n try {\n resolve(JSON.parse(stdout) as LogMetricsReport);\n } catch {\n reject(new Error('metrics CLI returned unparsable output'));\n }\n },\n );\n });\n}\n\nexport function createMetricsSource(options: MetricsSourceOptions = {}): MetricsSource {\n const fetchImpl = options.fetchImpl ?? globalThis.fetch;\n const cliRunner = options.cliRunner ?? runCli;\n let transport: MetricsTransport | undefined;\n let endpoint: string | undefined | null;\n\n const resolveEndpoint = async (): Promise<string | undefined> => {\n if (endpoint !== undefined) return endpoint ?? undefined;\n try {\n const resolved = await resolveLogSinkPort({ env: options.env, cwd: options.cwd, healthCheck: true });\n endpoint = resolved?.endpoint ?? null;\n } catch {\n endpoint = null;\n }\n return endpoint ?? undefined;\n };\n\n return {\n lastTransport: () => transport,\n async query(params) {\n const httpEndpoint = await resolveEndpoint();\n if (httpEndpoint && fetchImpl) {\n try {\n const report = await queryHttp(httpEndpoint, params, fetchImpl);\n transport = 'http';\n return report;\n } catch {\n // A stale or unhealthy daemon must not hide data the CLI can still read.\n endpoint = null;\n }\n }\n\n const report = await cliRunner(params);\n transport = 'cli';\n return report;\n },\n };\n}\n"],"mappings":"gLAiBA,MAOM,EAAa,eAUnB,SAAS,GAAwB,CAG/B,IAAM,EAFU,EAAc,YAAY,GAEhB,CAAC,CAAC,QAAQ,sCAA8B,EAClE,OAAO,EAAK,KAAK,EAAK,QAAQ,CAAW,EAAG,OAAQ,SAAS,CAC/D,CAEA,SAAS,EAAa,EAAoC,CACxD,OAAO,IAAI,gBAAgB,CACzB,QAAS,EAAO,QAChB,OAAQ,EAAO,OACf,KAAM,EACN,MAAO,OAAO,EAAO,KAAK,EAC1B,UAAW,GACb,CAAC,CAAC,CAAC,SAAS,CACd,CAEA,eAAe,EACb,EACA,EACA,EAC2B,CAC3B,IAAM,EAAW,MAAM,EAAU,GAAG,EAAS,eAAe,EAAa,CAAM,IAAK,CAClF,OAAQ,YAAY,QAAQ,GAAe,CAC7C,CAAC,EACD,GAAI,CAAC,EAAS,GAAI,MAAU,MAAM,kBAAkB,EAAS,QAAQ,EAErE,IAAM,EAAQ,MAAM,EAAS,KAAK,EAElC,GAAI,EAAK,OAAS,CAAC,MAAM,QAAQ,EAAK,QAAQ,EAAG,MAAU,MAAM,EAAK,OAAS,0BAA0B,EACzG,OAAO,CACT,CAEA,SAAS,EAAO,EAAuD,CACrE,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,EACE,QAAQ,SACR,CACE,EAAc,EACd,OACA,UACA,aACA,EAAO,QACP,WACA,EAAO,OACP,SACA,EACA,UACA,OAAO,EAAO,KAAK,EACnB,eACA,GACF,EACA,CAAE,QAAS,IAAgB,UAAW,QAAe,GACpD,EAAO,EAAQ,IAAW,CACzB,GAAI,EAAO,CACT,EAAW,MAAM,EAAO,KAAK,GAAK,EAAM,OAAO,CAAC,EAChD,MACF,CACA,GAAI,CACF,EAAQ,KAAK,MAAM,CAAM,CAAqB,CAChD,MAAQ,CACN,EAAW,MAAM,wCAAwC,CAAC,CAC5D,CACF,CACF,CACF,CAAC,CACH,CAEA,SAAgB,EAAoB,EAAgC,CAAC,EAAkB,CACrF,IAAM,EAAY,EAAQ,WAAa,WAAW,MAC5C,EAAY,EAAQ,WAAa,EACnC,EACA,EAEE,EAAkB,SAAyC,CAC/D,GAAI,IAAa,IAAA,GAAW,OAAO,GAAY,IAAA,GAC/C,GAAI,CAEF,GAAW,MADY,EAAmB,CAAE,IAAK,EAAQ,IAAK,IAAK,EAAQ,IAAK,YAAa,EAAK,CAAC,EAAA,EAC9E,UAAY,IACnC,MAAQ,CACN,EAAW,IACb,CACA,OAAO,GAAY,IAAA,EACrB,EAEA,MAAO,CACL,kBAAqB,EACrB,MAAM,MAAM,EAAQ,CAClB,IAAM,EAAe,MAAM,EAAgB,EAC3C,GAAI,GAAgB,EAClB,GAAI,CACF,IAAM,EAAS,MAAM,EAAU,EAAc,EAAQ,CAAS,EAE9D,MADA,GAAY,OACL,CACT,MAAQ,CAEN,EAAW,IACb,CAGF,IAAM,EAAS,MAAM,EAAU,CAAM,EAErC,MADA,GAAY,MACL,CACT,CACF,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../services/metrics.cjs"),t=require("../../tui/logMetricsOverlay.cjs"),n=require("../node/metricsSource.cjs");let r=require("@agimon-ai/doompi-extension-contracts/leader"),i=require("@agimon-ai/doompi-telemetry");const a=`log-metrics`,o=new Set([`error`,`aborted`]);function s(e){return e===`1`||e?.toLowerCase()===`true`||e?.toLowerCase()===`yes`}function c(e){let t={"pi.mode":e.mode,"pi.session.id":e.sessionManager.getSessionId()};return e.thinkingLevel&&(t[`pi.thinking_level`]=e.thinkingLevel),e.model&&(t[`gen_ai.provider.name`]=e.model.provider,t[`gen_ai.request.model`]=e.model.id),t}function l(e){if(e.role!==`assistant`)return;let t={"gen_ai.response.model":e.responseModel??e.model,"gen_ai.response.finish_reasons":e.stopReason,"gen_ai.usage.input_tokens":e.usage.input,"gen_ai.usage.output_tokens":e.usage.output,"gen_ai.usage.cache_read_tokens":e.usage.cacheRead,"gen_ai.usage.cache_write_tokens":e.usage.cacheWrite,"gen_ai.usage.total_tokens":e.usage.totalTokens,"gen_ai.usage.cost":e.usage.cost.total};return e.usage.reasoning!==void 0&&(t[`gen_ai.usage.reasoning_tokens`]=e.usage.reasoning),t}function u(e){if(e.role!==`assistant`)return{"error.type":`AgentError`,outcome:`error`};let t=e.stopReason===`aborted`;return{"error.type":`ProviderError`,"error.code":e.stopReason,outcome:t?`aborted`:`error`}}function d(e){return{service:e.serviceName,backend:e.backend,endpoint:e.endpoint??`none`,endpointSource:e.endpointSource,traces:e.traces,redaction:!0,fileFallback:e.fileFallback}}function f(e={}){return function(t){let n=e.env??process.env,r=e.metrics,a=new Map,f,p,m=async(e,t,n)=>{p&&(e===`debug`?await p.recordDebug(t,n):e===`warn`?await p.recordWarning(t,void 0,n):e===`error`?await p.recordError(t,void 0,n):await p.recordEvent(t,n))},h=t=>(p??=(0,i.createDoomTelemetry)({serviceName:e.serviceName??`pi`,packageName:`@agimon-ai/doompi-log`,cwd:t.cwd,env:n,allowFileFallback:e.allowFileFallback,telemetryFactory:e.telemetryFactory,warn:e.onDiagnostic,enableLogs:!0,enableTraces:n.AGENT_OTEL_TRACES===void 0||s(n.AGENT_OTEL_TRACES),onRecord:e=>r?.record(e.event,e.attributes),onStatus:t=>e.onSinkStatus?.(d(t))}),e.onSinkStatus?.(d(p.status())),p);t.on(`session_start`,async(e,t)=>{h(t),await m(`info`,`pi.session.started`,{...c(t),"pi.session.reason":e.reason,"pi.session.previous":e.previousSessionFile!==void 0})}),t.on(`before_agent_start`,async(e,t)=>{h(t),await m(`info`,`pi.user_prompt`,{...c(t),"pi.user_message.length":e.prompt.length,"pi.user_message.image_count":e.images?.length??0})}),t.on(`agent_start`,async(e,t)=>{f=Date.now(),h(t),await m(`info`,`pi.agent.started`,c(t))}),t.on(`turn_start`,async(e,t)=>{h(t),await m(`debug`,`pi.turn.started`,{...c(t),"pi.turn.index":e.turnIndex})}),t.on(`turn_end`,async(e,t)=>{h(t);let n=l(e.message);if(await m(`info`,`pi.turn.finished`,{...c(t),"pi.turn.index":e.turnIndex,"pi.tool_result.count":e.toolResults.length,...n}),e.message.role===`assistant`&&o.has(e.message.stopReason)&&await m(e.message.stopReason===`aborted`?`warn`:`error`,`pi.turn.failed`,{...c(t),"pi.turn.index":e.turnIndex,...u(e.message),...n}),n)for(let r of e.toolResults)await m(`debug`,`pi.tool_token_sample`,{...c(t),...n,"tool.name":r.toolName,token_attribution:`toolCallTurn`})}),t.on(`tool_execution_start`,async(e,t)=>{a.set(e.toolCallId,Date.now()),h(t),await m(`debug`,`pi.tool_call`,{...c(t),"tool.name":e.toolName,"tool.call.id":e.toolCallId})}),t.on(`tool_execution_end`,async(e,t)=>{let n=a.get(e.toolCallId);a.delete(e.toolCallId),h(t),await m(`info`,`pi.tool_result`,{...c(t),success:!e.isError,"tool.name":e.toolName,"tool.call.id":e.toolCallId,"tool.result.error":e.isError,...n===void 0?{}:{"tool.duration_ms":Date.now()-n}})}),t.on(`after_provider_response`,async(e,t)=>{h(t);let n={...c(t),"http.response.status_code":e.status};e.status>=400?await m(`error`,`pi.api_error`,n):await m(`debug`,`pi.api_response`,n)}),t.on(`model_select`,async(e,t)=>{h(t),await m(`info`,`pi.model.selected`,{...c(t),"pi.model.source":e.source,"gen_ai.provider.name":e.model.provider,"gen_ai.request.model":e.model.id})}),t.on(`agent_end`,async(e,t)=>{h(t),await m(`info`,`pi.agent.finished`,{...c(t),"pi.message.count":e.messages.length,...f===void 0?{}:{"pi.agent.duration_ms":Date.now()-f}}),f=void 0,await p?.flush()}),t.on(`agent_settled`,async(e,t)=>{h(t),await m(`debug`,`pi.agent.settled`,c(t))}),t.on(`session_shutdown`,async(e,t)=>{h(t),await m(`info`,`pi.session.finished`,{...c(t),"pi.session.reason":e.reason}),await p?.shutdown()})}}function p(e,t={}){return(0,r.registerDoomLeaderContribution)(e,{source:t.source??`@agimon-ai/doompi-log`,bindings:[{id:`log.metrics`,path:[{key:`h`,label:`help`,order:70},{key:`l`,label:`logs`,detail:`telemetry`}],command:{name:a}}]})}async function m(e,n,r){await e.ui.custom((e,i,a,o)=>new t.LogMetricsOverlayComponent(e,i,n,o,r),{overlay:!0,overlayOptions:{anchor:`top-left`,width:`100%`,maxHeight:`100%`,margin:0}})}function h(t={}){return function(r){let i=t.env??process.env,o=new e.LogMetricsAggregator,c=t.metricsSource??n.createMetricsSource({env:i}),l,u;f({...t,metrics:o,onDiagnostic:e=>{u=e,t.onDiagnostic?t.onDiagnostic(e):i.AGENT_OTEL_DIAGNOSTICS===`stderr`&&process.emitWarning(e)},onSinkStatus:e=>{l=e,t.onSinkStatus?.(e)}})(r),p(r,{source:t.leaderSource}),r.registerCommand(a,{description:`Show session-local log metrics`,handler:async(e,t)=>{await m(t,()=>({disabled:s(i.AGENT_TELEMETRY_DISABLED)||s(i.OTEL_SDK_DISABLED),snapshot:o.snapshot(),sink:l,transport:c.lastTransport(),lastDiagnostic:u}),c.query)}})}}const g=h();exports.createDoomLogExtension=h,exports.createPiTelemetryExtension=f,exports.doomLogExtension=g,exports.openLogMetricsOverlay=m,exports.registerLogMetricsLeaderBinding=p;
|
|
2
|
+
//# sourceMappingURL=extension.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.cjs","names":["createDoomTelemetry","registerDoomLeaderContribution","LogMetricsOverlayComponent","LogMetricsAggregator","createMetricsSource"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["/**\n * Pi telemetry wiring for the Doom harness.\n *\n * This extension deliberately emits metadata-only records. Prompt, message,\n * tool payload, file path, diagnostic text, exception, and stack data never\n * cross the shared telemetry boundary.\n */\n\nimport { registerDoomLeaderContribution } from '@agimon-ai/doompi-extension-contracts/leader';\nimport { createDoomTelemetry, type DoomTelemetry, type DoomTelemetryOptions } from '@agimon-ai/doompi-telemetry';\nimport type { ExtensionAPI, ExtensionContext, TurnEndEvent } from '@earendil-works/pi-coding-agent';\nimport { LogMetricsAggregator, type LogMetricsRecorder } from '../../services/metrics.ts';\nimport { LogMetricsOverlayComponent, type LogMetricsView, type SinkStatus } from '../../tui/logMetricsOverlay.ts';\nimport type { MetricsQuery, MetricsSource } from '../../types/metricsSource.ts';\nimport { createMetricsSource } from '../node/metricsSource.ts';\n\nconst SERVICE_NAME = 'pi';\nconst PACKAGE_NAME = '@agimon-ai/doompi-log';\n/** Opt back into stderr diagnostics when debugging outside a live TUI. */\nconst DIAGNOSTICS_STDERR = 'stderr';\nconst LEADER_SOURCE = '@agimon-ai/doompi-log';\nconst LOG_METRICS_COMMAND = 'log-metrics';\nconst LOG_METRICS_DESCRIPTION = 'Show session-local log metrics';\nconst HELP_GROUP_ORDER = 70;\nconst NO_ENDPOINT = 'none';\nconst API_ERROR_STATUS = 400;\nconst FAILURE_STOP_REASONS = new Set(['error', 'aborted']);\n\ntype TelemetryFactory = NonNullable<DoomTelemetryOptions['telemetryFactory']>;\ntype TelemetryAttributes = Record<string, string | number | boolean>;\ntype RecordLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface PiTelemetryExtensionOptions {\n allowFileFallback?: boolean;\n /** Overrides the telemetry service identity. */\n serviceName?: string;\n /** Overrides the leader contribution owner. */\n leaderSource?: string;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: TelemetryFactory;\n /** Receives every sanitized record, whether or not a sink is live. */\n metrics?: LogMetricsRecorder;\n /** Called once the sink backend is resolved, so the overlay can report it. */\n onSinkStatus?: (status: SinkStatus | undefined) => void;\n /** Overrides the sink-history transport; injected in tests. */\n metricsSource?: MetricsSource;\n /** Receives telemetry lifecycle failures without writing into the TUI. */\n onDiagnostic?: (message: string) => void;\n}\n\nfunction isEnabled(value: string | undefined): boolean {\n return value === '1' || value?.toLowerCase() === 'true' || value?.toLowerCase() === 'yes';\n}\n\nfunction contextAttributes(ctx: ExtensionContext): TelemetryAttributes {\n const attributes: TelemetryAttributes = {\n 'pi.mode': ctx.mode,\n 'pi.session.id': ctx.sessionManager.getSessionId(),\n };\n if (ctx.thinkingLevel) attributes['pi.thinking_level'] = ctx.thinkingLevel;\n if (ctx.model) {\n attributes['gen_ai.provider.name'] = ctx.model.provider;\n attributes['gen_ai.request.model'] = ctx.model.id;\n }\n return attributes;\n}\n\nfunction usageAttributes(message: TurnEndEvent['message']): TelemetryAttributes | undefined {\n if (message.role !== 'assistant') return undefined;\n const attributes: TelemetryAttributes = {\n 'gen_ai.response.model': message.responseModel ?? message.model,\n 'gen_ai.response.finish_reasons': message.stopReason,\n 'gen_ai.usage.input_tokens': message.usage.input,\n 'gen_ai.usage.output_tokens': message.usage.output,\n 'gen_ai.usage.cache_read_tokens': message.usage.cacheRead,\n 'gen_ai.usage.cache_write_tokens': message.usage.cacheWrite,\n 'gen_ai.usage.total_tokens': message.usage.totalTokens,\n 'gen_ai.usage.cost': message.usage.cost.total,\n };\n if (message.usage.reasoning !== undefined) attributes['gen_ai.usage.reasoning_tokens'] = message.usage.reasoning;\n return attributes;\n}\n\nfunction failureAttributes(message: TurnEndEvent['message']): TelemetryAttributes {\n if (message.role !== 'assistant') return { 'error.type': 'AgentError', outcome: 'error' };\n const aborted = message.stopReason === 'aborted';\n return {\n 'error.type': 'ProviderError',\n 'error.code': message.stopReason,\n outcome: aborted ? 'aborted' : 'error',\n };\n}\n\nfunction statusFromTelemetry(status: ReturnType<DoomTelemetry['status']>): SinkStatus {\n return {\n service: status.serviceName,\n backend: status.backend,\n endpoint: status.endpoint ?? NO_ENDPOINT,\n endpointSource: status.endpointSource,\n traces: status.traces,\n redaction: true,\n fileFallback: status.fileFallback,\n };\n}\n\nexport function createPiTelemetryExtension(options: PiTelemetryExtensionOptions = {}) {\n return function registerPiTelemetry(pi: ExtensionAPI): void {\n const env = options.env ?? process.env;\n const metrics = options.metrics;\n const toolStartedAt = new Map<string, number>();\n let agentStartedAt: number | undefined;\n let telemetry: DoomTelemetry | undefined;\n\n const emit = async (level: RecordLevel, name: string, attributes: TelemetryAttributes): Promise<void> => {\n if (!telemetry) return;\n if (level === 'debug') await telemetry.recordDebug(name, attributes);\n else if (level === 'warn') await telemetry.recordWarning(name, undefined, attributes);\n else if (level === 'error') await telemetry.recordError(name, undefined, attributes);\n else await telemetry.recordEvent(name, attributes);\n };\n\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: options.serviceName ?? SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: ctx.cwd,\n env,\n allowFileFallback: options.allowFileFallback,\n telemetryFactory: options.telemetryFactory,\n warn: options.onDiagnostic,\n enableLogs: true,\n enableTraces: env.AGENT_OTEL_TRACES === undefined || isEnabled(env.AGENT_OTEL_TRACES),\n onRecord: (record) => metrics?.record(record.event, record.attributes),\n onStatus: (status) => options.onSinkStatus?.(statusFromTelemetry(status)),\n });\n options.onSinkStatus?.(statusFromTelemetry(telemetry.status()));\n return telemetry;\n };\n\n pi.on('session_start', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.session.started', {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n 'pi.session.previous': event.previousSessionFile !== undefined,\n });\n });\n\n pi.on('before_agent_start', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.user_prompt', {\n ...contextAttributes(ctx),\n 'pi.user_message.length': event.prompt.length,\n 'pi.user_message.image_count': event.images?.length ?? 0,\n });\n });\n\n pi.on('agent_start', async (_event, ctx) => {\n agentStartedAt = Date.now();\n getTelemetry(ctx);\n await emit('info', 'pi.agent.started', contextAttributes(ctx));\n });\n\n pi.on('turn_start', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('debug', 'pi.turn.started', {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n });\n });\n\n pi.on('turn_end', async (event, ctx) => {\n getTelemetry(ctx);\n const usage = usageAttributes(event.message);\n await emit('info', 'pi.turn.finished', {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n 'pi.tool_result.count': event.toolResults.length,\n ...usage,\n });\n if (event.message.role === 'assistant' && FAILURE_STOP_REASONS.has(event.message.stopReason)) {\n await emit(event.message.stopReason === 'aborted' ? 'warn' : 'error', 'pi.turn.failed', {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n ...failureAttributes(event.message),\n ...usage,\n });\n }\n if (!usage) return;\n for (const result of event.toolResults) {\n await emit('debug', 'pi.tool_token_sample', {\n ...contextAttributes(ctx),\n ...usage,\n 'tool.name': result.toolName,\n token_attribution: 'toolCallTurn',\n });\n }\n });\n\n pi.on('tool_execution_start', async (event, ctx) => {\n toolStartedAt.set(event.toolCallId, Date.now());\n getTelemetry(ctx);\n await emit('debug', 'pi.tool_call', {\n ...contextAttributes(ctx),\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n });\n });\n\n pi.on('tool_execution_end', async (event, ctx) => {\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n getTelemetry(ctx);\n await emit('info', 'pi.tool_result', {\n ...contextAttributes(ctx),\n success: !event.isError,\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n 'tool.result.error': event.isError,\n ...(startedAt === undefined ? {} : { 'tool.duration_ms': Date.now() - startedAt }),\n });\n });\n\n pi.on('after_provider_response', async (event, ctx) => {\n getTelemetry(ctx);\n const attributes = {\n ...contextAttributes(ctx),\n 'http.response.status_code': event.status,\n };\n if (event.status >= API_ERROR_STATUS) await emit('error', 'pi.api_error', attributes);\n else await emit('debug', 'pi.api_response', attributes);\n });\n\n pi.on('model_select', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.model.selected', {\n ...contextAttributes(ctx),\n 'pi.model.source': event.source,\n 'gen_ai.provider.name': event.model.provider,\n 'gen_ai.request.model': event.model.id,\n });\n });\n\n pi.on('agent_end', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.agent.finished', {\n ...contextAttributes(ctx),\n 'pi.message.count': event.messages.length,\n ...(agentStartedAt === undefined ? {} : { 'pi.agent.duration_ms': Date.now() - agentStartedAt }),\n });\n agentStartedAt = undefined;\n await telemetry?.flush();\n });\n\n pi.on('agent_settled', async (_event, ctx) => {\n getTelemetry(ctx);\n await emit('debug', 'pi.agent.settled', contextAttributes(ctx));\n });\n\n pi.on('session_shutdown', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.session.finished', {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n });\n await telemetry?.shutdown();\n });\n };\n}\n\nexport function registerLogMetricsLeaderBinding(\n pi: Pick<ExtensionAPI, 'events' | 'on'>,\n options: { source?: string } = {},\n): () => void {\n return registerDoomLeaderContribution(pi, {\n source: options.source ?? LEADER_SOURCE,\n bindings: [\n {\n id: 'log.metrics',\n path: [\n { key: 'h', label: 'help', order: HELP_GROUP_ORDER },\n { key: 'l', label: 'logs', detail: 'telemetry' },\n ],\n command: { name: LOG_METRICS_COMMAND },\n },\n ],\n });\n}\n\nexport async function openLogMetricsOverlay(\n ctx: ExtensionContext,\n getView: () => LogMetricsView,\n query?: MetricsQuery,\n): Promise<void> {\n await ctx.ui.custom<undefined>(\n (tui, theme, _keybindings, done) => new LogMetricsOverlayComponent(tui, theme, getView, done, query),\n {\n overlay: true,\n overlayOptions: {\n anchor: 'top-left',\n width: '100%',\n maxHeight: '100%',\n margin: 0,\n },\n },\n );\n}\n\nexport function createDoomLogExtension(options: PiTelemetryExtensionOptions = {}) {\n return function registerDoomLog(pi: ExtensionAPI): void {\n const env = options.env ?? process.env;\n const metrics = new LogMetricsAggregator();\n const metricsSource = options.metricsSource ?? createMetricsSource({ env });\n let sink: SinkStatus | undefined;\n let lastDiagnostic: string | undefined;\n\n createPiTelemetryExtension({\n ...options,\n metrics,\n // Always supply a sink so doom-telemetry never falls back to\n // process.emitWarning, which writes raw stderr over the TUI frame.\n // Diagnostics surface in the Log Metrics overlay instead.\n onDiagnostic: (message) => {\n lastDiagnostic = message;\n if (options.onDiagnostic) options.onDiagnostic(message);\n else if (env.AGENT_OTEL_DIAGNOSTICS === DIAGNOSTICS_STDERR) process.emitWarning(message);\n },\n onSinkStatus: (status) => {\n sink = status;\n options.onSinkStatus?.(status);\n },\n })(pi);\n\n registerLogMetricsLeaderBinding(pi, { source: options.leaderSource });\n pi.registerCommand(LOG_METRICS_COMMAND, {\n description: LOG_METRICS_DESCRIPTION,\n handler: async (_args, ctx) => {\n await openLogMetricsOverlay(\n ctx,\n () => ({\n disabled: isEnabled(env.AGENT_TELEMETRY_DISABLED) || isEnabled(env.OTEL_SDK_DISABLED),\n snapshot: metrics.snapshot(),\n sink,\n transport: metricsSource.lastTransport(),\n lastDiagnostic,\n }),\n metricsSource.query,\n );\n },\n });\n };\n}\n\nexport const doomLogExtension = createDoomLogExtension();\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { LogMetricsRecorder } from "../../services/metrics.cjs";
|
|
2
|
+
import { MetricsQuery, MetricsSource } from "../../types/metricsSource.cjs";
|
|
3
|
+
import { LogMetricsView, SinkStatus } from "../../tui/logMetricsOverlay.cjs";
|
|
4
|
+
import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
|
|
5
|
+
import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
//#region src/adapters/pi/extension.d.ts
|
|
7
|
+
type TelemetryFactory = NonNullable<DoomTelemetryOptions['telemetryFactory']>;
|
|
8
|
+
interface PiTelemetryExtensionOptions {
|
|
9
|
+
allowFileFallback?: boolean;
|
|
10
|
+
/** Overrides the telemetry service identity. */
|
|
11
|
+
serviceName?: string;
|
|
12
|
+
/** Overrides the leader contribution owner. */
|
|
13
|
+
leaderSource?: string;
|
|
14
|
+
env?: NodeJS.ProcessEnv;
|
|
15
|
+
telemetryFactory?: TelemetryFactory;
|
|
16
|
+
/** Receives every sanitized record, whether or not a sink is live. */
|
|
17
|
+
metrics?: LogMetricsRecorder;
|
|
18
|
+
/** Called once the sink backend is resolved, so the overlay can report it. */
|
|
19
|
+
onSinkStatus?: (status: SinkStatus | undefined) => void;
|
|
20
|
+
/** Overrides the sink-history transport; injected in tests. */
|
|
21
|
+
metricsSource?: MetricsSource;
|
|
22
|
+
/** Receives telemetry lifecycle failures without writing into the TUI. */
|
|
23
|
+
onDiagnostic?: (message: string) => void;
|
|
24
|
+
}
|
|
25
|
+
declare function createPiTelemetryExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
26
|
+
declare function registerLogMetricsLeaderBinding(pi: Pick<ExtensionAPI, 'events' | 'on'>, options?: {
|
|
27
|
+
source?: string;
|
|
28
|
+
}): () => void;
|
|
29
|
+
declare function openLogMetricsOverlay(ctx: ExtensionContext, getView: () => LogMetricsView, query?: MetricsQuery): Promise<void>;
|
|
30
|
+
declare function createDoomLogExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
31
|
+
declare const doomLogExtension: (pi: ExtensionAPI) => void;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, doomLogExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
|
34
|
+
//# sourceMappingURL=extension.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;KA4BK,mBAAmB,YAAY;UAInB;EACf;;EAEA;;EAEA;EACA,MAAM,OAAO;EACb,mBAAmB;;EAEnB,UAAU;;EAEV,gBAAgB,QAAQ;;EAExB,gBAAgB;;EAEhB,gBAAgB;;iBA0DF,2BAA2B,UAAS,+BACd,IAAI;iBAoK1B,gCACd,IAAI,KAAK,gCACT;EAAW;;iBAiBS,sBACpB,KAAK,kBACL,eAAe,gBACf,QAAQ,eACP;iBAea,uBAAuB,UAAS,+BACd,IAAI;cA4CzB,mBAAgB,IA5CS"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { LogMetricsRecorder } from "../../services/metrics.mjs";
|
|
2
|
+
import { MetricsQuery, MetricsSource } from "../../types/metricsSource.mjs";
|
|
3
|
+
import { LogMetricsView, SinkStatus } from "../../tui/logMetricsOverlay.mjs";
|
|
4
|
+
import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
|
|
5
|
+
import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
//#region src/adapters/pi/extension.d.ts
|
|
7
|
+
type TelemetryFactory = NonNullable<DoomTelemetryOptions['telemetryFactory']>;
|
|
8
|
+
interface PiTelemetryExtensionOptions {
|
|
9
|
+
allowFileFallback?: boolean;
|
|
10
|
+
/** Overrides the telemetry service identity. */
|
|
11
|
+
serviceName?: string;
|
|
12
|
+
/** Overrides the leader contribution owner. */
|
|
13
|
+
leaderSource?: string;
|
|
14
|
+
env?: NodeJS.ProcessEnv;
|
|
15
|
+
telemetryFactory?: TelemetryFactory;
|
|
16
|
+
/** Receives every sanitized record, whether or not a sink is live. */
|
|
17
|
+
metrics?: LogMetricsRecorder;
|
|
18
|
+
/** Called once the sink backend is resolved, so the overlay can report it. */
|
|
19
|
+
onSinkStatus?: (status: SinkStatus | undefined) => void;
|
|
20
|
+
/** Overrides the sink-history transport; injected in tests. */
|
|
21
|
+
metricsSource?: MetricsSource;
|
|
22
|
+
/** Receives telemetry lifecycle failures without writing into the TUI. */
|
|
23
|
+
onDiagnostic?: (message: string) => void;
|
|
24
|
+
}
|
|
25
|
+
declare function createPiTelemetryExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
26
|
+
declare function registerLogMetricsLeaderBinding(pi: Pick<ExtensionAPI, 'events' | 'on'>, options?: {
|
|
27
|
+
source?: string;
|
|
28
|
+
}): () => void;
|
|
29
|
+
declare function openLogMetricsOverlay(ctx: ExtensionContext, getView: () => LogMetricsView, query?: MetricsQuery): Promise<void>;
|
|
30
|
+
declare function createDoomLogExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
31
|
+
declare const doomLogExtension: (pi: ExtensionAPI) => void;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, doomLogExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
|
34
|
+
//# sourceMappingURL=extension.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;KA4BK,mBAAmB,YAAY;UAInB;EACf;;EAEA;;EAEA;EACA,MAAM,OAAO;EACb,mBAAmB;;EAEnB,UAAU;;EAEV,gBAAgB,QAAQ;;EAExB,gBAAgB;;EAEhB,gBAAgB;;iBA0DF,2BAA2B,UAAS,+BACd,IAAI;iBAoK1B,gCACd,IAAI,KAAK,gCACT;EAAW;;iBAiBS,sBACpB,KAAK,kBACL,eAAe,gBACf,QAAQ,eACP;iBAea,uBAAuB,UAAS,+BACd,IAAI;cA4CzB,mBAAgB,IA5CS"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{LogMetricsAggregator as e}from"../../services/metrics.mjs";import{LogMetricsOverlayComponent as t}from"../../tui/logMetricsOverlay.mjs";import{createMetricsSource as n}from"../node/metricsSource.mjs";import{registerDoomLeaderContribution as r}from"@agimon-ai/doompi-extension-contracts/leader";import{createDoomTelemetry as i}from"@agimon-ai/doompi-telemetry";const a=`log-metrics`,o=new Set([`error`,`aborted`]);function s(e){return e===`1`||e?.toLowerCase()===`true`||e?.toLowerCase()===`yes`}function c(e){let t={"pi.mode":e.mode,"pi.session.id":e.sessionManager.getSessionId()};return e.thinkingLevel&&(t[`pi.thinking_level`]=e.thinkingLevel),e.model&&(t[`gen_ai.provider.name`]=e.model.provider,t[`gen_ai.request.model`]=e.model.id),t}function l(e){if(e.role!==`assistant`)return;let t={"gen_ai.response.model":e.responseModel??e.model,"gen_ai.response.finish_reasons":e.stopReason,"gen_ai.usage.input_tokens":e.usage.input,"gen_ai.usage.output_tokens":e.usage.output,"gen_ai.usage.cache_read_tokens":e.usage.cacheRead,"gen_ai.usage.cache_write_tokens":e.usage.cacheWrite,"gen_ai.usage.total_tokens":e.usage.totalTokens,"gen_ai.usage.cost":e.usage.cost.total};return e.usage.reasoning!==void 0&&(t[`gen_ai.usage.reasoning_tokens`]=e.usage.reasoning),t}function u(e){if(e.role!==`assistant`)return{"error.type":`AgentError`,outcome:`error`};let t=e.stopReason===`aborted`;return{"error.type":`ProviderError`,"error.code":e.stopReason,outcome:t?`aborted`:`error`}}function d(e){return{service:e.serviceName,backend:e.backend,endpoint:e.endpoint??`none`,endpointSource:e.endpointSource,traces:e.traces,redaction:!0,fileFallback:e.fileFallback}}function f(e={}){return function(t){let n=e.env??process.env,r=e.metrics,a=new Map,f,p,m=async(e,t,n)=>{p&&(e===`debug`?await p.recordDebug(t,n):e===`warn`?await p.recordWarning(t,void 0,n):e===`error`?await p.recordError(t,void 0,n):await p.recordEvent(t,n))},h=t=>(p??=i({serviceName:e.serviceName??`pi`,packageName:`@agimon-ai/doompi-log`,cwd:t.cwd,env:n,allowFileFallback:e.allowFileFallback,telemetryFactory:e.telemetryFactory,warn:e.onDiagnostic,enableLogs:!0,enableTraces:n.AGENT_OTEL_TRACES===void 0||s(n.AGENT_OTEL_TRACES),onRecord:e=>r?.record(e.event,e.attributes),onStatus:t=>e.onSinkStatus?.(d(t))}),e.onSinkStatus?.(d(p.status())),p);t.on(`session_start`,async(e,t)=>{h(t),await m(`info`,`pi.session.started`,{...c(t),"pi.session.reason":e.reason,"pi.session.previous":e.previousSessionFile!==void 0})}),t.on(`before_agent_start`,async(e,t)=>{h(t),await m(`info`,`pi.user_prompt`,{...c(t),"pi.user_message.length":e.prompt.length,"pi.user_message.image_count":e.images?.length??0})}),t.on(`agent_start`,async(e,t)=>{f=Date.now(),h(t),await m(`info`,`pi.agent.started`,c(t))}),t.on(`turn_start`,async(e,t)=>{h(t),await m(`debug`,`pi.turn.started`,{...c(t),"pi.turn.index":e.turnIndex})}),t.on(`turn_end`,async(e,t)=>{h(t);let n=l(e.message);if(await m(`info`,`pi.turn.finished`,{...c(t),"pi.turn.index":e.turnIndex,"pi.tool_result.count":e.toolResults.length,...n}),e.message.role===`assistant`&&o.has(e.message.stopReason)&&await m(e.message.stopReason===`aborted`?`warn`:`error`,`pi.turn.failed`,{...c(t),"pi.turn.index":e.turnIndex,...u(e.message),...n}),n)for(let r of e.toolResults)await m(`debug`,`pi.tool_token_sample`,{...c(t),...n,"tool.name":r.toolName,token_attribution:`toolCallTurn`})}),t.on(`tool_execution_start`,async(e,t)=>{a.set(e.toolCallId,Date.now()),h(t),await m(`debug`,`pi.tool_call`,{...c(t),"tool.name":e.toolName,"tool.call.id":e.toolCallId})}),t.on(`tool_execution_end`,async(e,t)=>{let n=a.get(e.toolCallId);a.delete(e.toolCallId),h(t),await m(`info`,`pi.tool_result`,{...c(t),success:!e.isError,"tool.name":e.toolName,"tool.call.id":e.toolCallId,"tool.result.error":e.isError,...n===void 0?{}:{"tool.duration_ms":Date.now()-n}})}),t.on(`after_provider_response`,async(e,t)=>{h(t);let n={...c(t),"http.response.status_code":e.status};e.status>=400?await m(`error`,`pi.api_error`,n):await m(`debug`,`pi.api_response`,n)}),t.on(`model_select`,async(e,t)=>{h(t),await m(`info`,`pi.model.selected`,{...c(t),"pi.model.source":e.source,"gen_ai.provider.name":e.model.provider,"gen_ai.request.model":e.model.id})}),t.on(`agent_end`,async(e,t)=>{h(t),await m(`info`,`pi.agent.finished`,{...c(t),"pi.message.count":e.messages.length,...f===void 0?{}:{"pi.agent.duration_ms":Date.now()-f}}),f=void 0,await p?.flush()}),t.on(`agent_settled`,async(e,t)=>{h(t),await m(`debug`,`pi.agent.settled`,c(t))}),t.on(`session_shutdown`,async(e,t)=>{h(t),await m(`info`,`pi.session.finished`,{...c(t),"pi.session.reason":e.reason}),await p?.shutdown()})}}function p(e,t={}){return r(e,{source:t.source??`@agimon-ai/doompi-log`,bindings:[{id:`log.metrics`,path:[{key:`h`,label:`help`,order:70},{key:`l`,label:`logs`,detail:`telemetry`}],command:{name:a}}]})}async function m(e,n,r){await e.ui.custom((e,i,a,o)=>new t(e,i,n,o,r),{overlay:!0,overlayOptions:{anchor:`top-left`,width:`100%`,maxHeight:`100%`,margin:0}})}function h(t={}){return function(r){let i=t.env??process.env,o=new e,c=t.metricsSource??n({env:i}),l,u;f({...t,metrics:o,onDiagnostic:e=>{u=e,t.onDiagnostic?t.onDiagnostic(e):i.AGENT_OTEL_DIAGNOSTICS===`stderr`&&process.emitWarning(e)},onSinkStatus:e=>{l=e,t.onSinkStatus?.(e)}})(r),p(r,{source:t.leaderSource}),r.registerCommand(a,{description:`Show session-local log metrics`,handler:async(e,t)=>{await m(t,()=>({disabled:s(i.AGENT_TELEMETRY_DISABLED)||s(i.OTEL_SDK_DISABLED),snapshot:o.snapshot(),sink:l,transport:c.lastTransport(),lastDiagnostic:u}),c.query)}})}}const g=h();export{h as createDoomLogExtension,f as createPiTelemetryExtension,g as doomLogExtension,m as openLogMetricsOverlay,p as registerLogMetricsLeaderBinding};
|
|
2
|
+
//# sourceMappingURL=extension.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["/**\n * Pi telemetry wiring for the Doom harness.\n *\n * This extension deliberately emits metadata-only records. Prompt, message,\n * tool payload, file path, diagnostic text, exception, and stack data never\n * cross the shared telemetry boundary.\n */\n\nimport { registerDoomLeaderContribution } from '@agimon-ai/doompi-extension-contracts/leader';\nimport { createDoomTelemetry, type DoomTelemetry, type DoomTelemetryOptions } from '@agimon-ai/doompi-telemetry';\nimport type { ExtensionAPI, ExtensionContext, TurnEndEvent } from '@earendil-works/pi-coding-agent';\nimport { LogMetricsAggregator, type LogMetricsRecorder } from '../../services/metrics.ts';\nimport { LogMetricsOverlayComponent, type LogMetricsView, type SinkStatus } from '../../tui/logMetricsOverlay.ts';\nimport type { MetricsQuery, MetricsSource } from '../../types/metricsSource.ts';\nimport { createMetricsSource } from '../node/metricsSource.ts';\n\nconst SERVICE_NAME = 'pi';\nconst PACKAGE_NAME = '@agimon-ai/doompi-log';\n/** Opt back into stderr diagnostics when debugging outside a live TUI. */\nconst DIAGNOSTICS_STDERR = 'stderr';\nconst LEADER_SOURCE = '@agimon-ai/doompi-log';\nconst LOG_METRICS_COMMAND = 'log-metrics';\nconst LOG_METRICS_DESCRIPTION = 'Show session-local log metrics';\nconst HELP_GROUP_ORDER = 70;\nconst NO_ENDPOINT = 'none';\nconst API_ERROR_STATUS = 400;\nconst FAILURE_STOP_REASONS = new Set(['error', 'aborted']);\n\ntype TelemetryFactory = NonNullable<DoomTelemetryOptions['telemetryFactory']>;\ntype TelemetryAttributes = Record<string, string | number | boolean>;\ntype RecordLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface PiTelemetryExtensionOptions {\n allowFileFallback?: boolean;\n /** Overrides the telemetry service identity. */\n serviceName?: string;\n /** Overrides the leader contribution owner. */\n leaderSource?: string;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: TelemetryFactory;\n /** Receives every sanitized record, whether or not a sink is live. */\n metrics?: LogMetricsRecorder;\n /** Called once the sink backend is resolved, so the overlay can report it. */\n onSinkStatus?: (status: SinkStatus | undefined) => void;\n /** Overrides the sink-history transport; injected in tests. */\n metricsSource?: MetricsSource;\n /** Receives telemetry lifecycle failures without writing into the TUI. */\n onDiagnostic?: (message: string) => void;\n}\n\nfunction isEnabled(value: string | undefined): boolean {\n return value === '1' || value?.toLowerCase() === 'true' || value?.toLowerCase() === 'yes';\n}\n\nfunction contextAttributes(ctx: ExtensionContext): TelemetryAttributes {\n const attributes: TelemetryAttributes = {\n 'pi.mode': ctx.mode,\n 'pi.session.id': ctx.sessionManager.getSessionId(),\n };\n if (ctx.thinkingLevel) attributes['pi.thinking_level'] = ctx.thinkingLevel;\n if (ctx.model) {\n attributes['gen_ai.provider.name'] = ctx.model.provider;\n attributes['gen_ai.request.model'] = ctx.model.id;\n }\n return attributes;\n}\n\nfunction usageAttributes(message: TurnEndEvent['message']): TelemetryAttributes | undefined {\n if (message.role !== 'assistant') return undefined;\n const attributes: TelemetryAttributes = {\n 'gen_ai.response.model': message.responseModel ?? message.model,\n 'gen_ai.response.finish_reasons': message.stopReason,\n 'gen_ai.usage.input_tokens': message.usage.input,\n 'gen_ai.usage.output_tokens': message.usage.output,\n 'gen_ai.usage.cache_read_tokens': message.usage.cacheRead,\n 'gen_ai.usage.cache_write_tokens': message.usage.cacheWrite,\n 'gen_ai.usage.total_tokens': message.usage.totalTokens,\n 'gen_ai.usage.cost': message.usage.cost.total,\n };\n if (message.usage.reasoning !== undefined) attributes['gen_ai.usage.reasoning_tokens'] = message.usage.reasoning;\n return attributes;\n}\n\nfunction failureAttributes(message: TurnEndEvent['message']): TelemetryAttributes {\n if (message.role !== 'assistant') return { 'error.type': 'AgentError', outcome: 'error' };\n const aborted = message.stopReason === 'aborted';\n return {\n 'error.type': 'ProviderError',\n 'error.code': message.stopReason,\n outcome: aborted ? 'aborted' : 'error',\n };\n}\n\nfunction statusFromTelemetry(status: ReturnType<DoomTelemetry['status']>): SinkStatus {\n return {\n service: status.serviceName,\n backend: status.backend,\n endpoint: status.endpoint ?? NO_ENDPOINT,\n endpointSource: status.endpointSource,\n traces: status.traces,\n redaction: true,\n fileFallback: status.fileFallback,\n };\n}\n\nexport function createPiTelemetryExtension(options: PiTelemetryExtensionOptions = {}) {\n return function registerPiTelemetry(pi: ExtensionAPI): void {\n const env = options.env ?? process.env;\n const metrics = options.metrics;\n const toolStartedAt = new Map<string, number>();\n let agentStartedAt: number | undefined;\n let telemetry: DoomTelemetry | undefined;\n\n const emit = async (level: RecordLevel, name: string, attributes: TelemetryAttributes): Promise<void> => {\n if (!telemetry) return;\n if (level === 'debug') await telemetry.recordDebug(name, attributes);\n else if (level === 'warn') await telemetry.recordWarning(name, undefined, attributes);\n else if (level === 'error') await telemetry.recordError(name, undefined, attributes);\n else await telemetry.recordEvent(name, attributes);\n };\n\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: options.serviceName ?? SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: ctx.cwd,\n env,\n allowFileFallback: options.allowFileFallback,\n telemetryFactory: options.telemetryFactory,\n warn: options.onDiagnostic,\n enableLogs: true,\n enableTraces: env.AGENT_OTEL_TRACES === undefined || isEnabled(env.AGENT_OTEL_TRACES),\n onRecord: (record) => metrics?.record(record.event, record.attributes),\n onStatus: (status) => options.onSinkStatus?.(statusFromTelemetry(status)),\n });\n options.onSinkStatus?.(statusFromTelemetry(telemetry.status()));\n return telemetry;\n };\n\n pi.on('session_start', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.session.started', {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n 'pi.session.previous': event.previousSessionFile !== undefined,\n });\n });\n\n pi.on('before_agent_start', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.user_prompt', {\n ...contextAttributes(ctx),\n 'pi.user_message.length': event.prompt.length,\n 'pi.user_message.image_count': event.images?.length ?? 0,\n });\n });\n\n pi.on('agent_start', async (_event, ctx) => {\n agentStartedAt = Date.now();\n getTelemetry(ctx);\n await emit('info', 'pi.agent.started', contextAttributes(ctx));\n });\n\n pi.on('turn_start', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('debug', 'pi.turn.started', {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n });\n });\n\n pi.on('turn_end', async (event, ctx) => {\n getTelemetry(ctx);\n const usage = usageAttributes(event.message);\n await emit('info', 'pi.turn.finished', {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n 'pi.tool_result.count': event.toolResults.length,\n ...usage,\n });\n if (event.message.role === 'assistant' && FAILURE_STOP_REASONS.has(event.message.stopReason)) {\n await emit(event.message.stopReason === 'aborted' ? 'warn' : 'error', 'pi.turn.failed', {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n ...failureAttributes(event.message),\n ...usage,\n });\n }\n if (!usage) return;\n for (const result of event.toolResults) {\n await emit('debug', 'pi.tool_token_sample', {\n ...contextAttributes(ctx),\n ...usage,\n 'tool.name': result.toolName,\n token_attribution: 'toolCallTurn',\n });\n }\n });\n\n pi.on('tool_execution_start', async (event, ctx) => {\n toolStartedAt.set(event.toolCallId, Date.now());\n getTelemetry(ctx);\n await emit('debug', 'pi.tool_call', {\n ...contextAttributes(ctx),\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n });\n });\n\n pi.on('tool_execution_end', async (event, ctx) => {\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n getTelemetry(ctx);\n await emit('info', 'pi.tool_result', {\n ...contextAttributes(ctx),\n success: !event.isError,\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n 'tool.result.error': event.isError,\n ...(startedAt === undefined ? {} : { 'tool.duration_ms': Date.now() - startedAt }),\n });\n });\n\n pi.on('after_provider_response', async (event, ctx) => {\n getTelemetry(ctx);\n const attributes = {\n ...contextAttributes(ctx),\n 'http.response.status_code': event.status,\n };\n if (event.status >= API_ERROR_STATUS) await emit('error', 'pi.api_error', attributes);\n else await emit('debug', 'pi.api_response', attributes);\n });\n\n pi.on('model_select', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.model.selected', {\n ...contextAttributes(ctx),\n 'pi.model.source': event.source,\n 'gen_ai.provider.name': event.model.provider,\n 'gen_ai.request.model': event.model.id,\n });\n });\n\n pi.on('agent_end', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.agent.finished', {\n ...contextAttributes(ctx),\n 'pi.message.count': event.messages.length,\n ...(agentStartedAt === undefined ? {} : { 'pi.agent.duration_ms': Date.now() - agentStartedAt }),\n });\n agentStartedAt = undefined;\n await telemetry?.flush();\n });\n\n pi.on('agent_settled', async (_event, ctx) => {\n getTelemetry(ctx);\n await emit('debug', 'pi.agent.settled', contextAttributes(ctx));\n });\n\n pi.on('session_shutdown', async (event, ctx) => {\n getTelemetry(ctx);\n await emit('info', 'pi.session.finished', {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n });\n await telemetry?.shutdown();\n });\n };\n}\n\nexport function registerLogMetricsLeaderBinding(\n pi: Pick<ExtensionAPI, 'events' | 'on'>,\n options: { source?: string } = {},\n): () => void {\n return registerDoomLeaderContribution(pi, {\n source: options.source ?? LEADER_SOURCE,\n bindings: [\n {\n id: 'log.metrics',\n path: [\n { key: 'h', label: 'help', order: HELP_GROUP_ORDER },\n { key: 'l', label: 'logs', detail: 'telemetry' },\n ],\n command: { name: LOG_METRICS_COMMAND },\n },\n ],\n });\n}\n\nexport async function openLogMetricsOverlay(\n ctx: ExtensionContext,\n getView: () => LogMetricsView,\n query?: MetricsQuery,\n): Promise<void> {\n await ctx.ui.custom<undefined>(\n (tui, theme, _keybindings, done) => new LogMetricsOverlayComponent(tui, theme, getView, done, query),\n {\n overlay: true,\n overlayOptions: {\n anchor: 'top-left',\n width: '100%',\n maxHeight: '100%',\n margin: 0,\n },\n },\n );\n}\n\nexport function createDoomLogExtension(options: PiTelemetryExtensionOptions = {}) {\n return function registerDoomLog(pi: ExtensionAPI): void {\n const env = options.env ?? process.env;\n const metrics = new LogMetricsAggregator();\n const metricsSource = options.metricsSource ?? createMetricsSource({ env });\n let sink: SinkStatus | undefined;\n let lastDiagnostic: string | undefined;\n\n createPiTelemetryExtension({\n ...options,\n metrics,\n // Always supply a sink so doom-telemetry never falls back to\n // process.emitWarning, which writes raw stderr over the TUI frame.\n // Diagnostics surface in the Log Metrics overlay instead.\n onDiagnostic: (message) => {\n lastDiagnostic = message;\n if (options.onDiagnostic) options.onDiagnostic(message);\n else if (env.AGENT_OTEL_DIAGNOSTICS === DIAGNOSTICS_STDERR) process.emitWarning(message);\n },\n onSinkStatus: (status) => {\n sink = status;\n options.onSinkStatus?.(status);\n },\n })(pi);\n\n registerLogMetricsLeaderBinding(pi, { source: options.leaderSource });\n pi.registerCommand(LOG_METRICS_COMMAND, {\n description: LOG_METRICS_DESCRIPTION,\n handler: async (_args, ctx) => {\n await openLogMetricsOverlay(\n ctx,\n () => ({\n disabled: isEnabled(env.AGENT_TELEMETRY_DISABLED) || isEnabled(env.OTEL_SDK_DISABLED),\n snapshot: metrics.snapshot(),\n sink,\n transport: metricsSource.lastTransport(),\n lastDiagnostic,\n }),\n metricsSource.query,\n );\n },\n });\n };\n}\n\nexport const doomLogExtension = createDoomLogExtension();\n"],"mappings":"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"}
|
package/dist/extension.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
2
|
-
//# sourceMappingURL=extension.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/pi/extension.cjs");exports.createDoomLogExtension=e.createDoomLogExtension,exports.createPiTelemetryExtension=e.createPiTelemetryExtension,exports.openLogMetricsOverlay=e.openLogMetricsOverlay,exports.registerLogMetricsLeaderBinding=e.registerLogMetricsLeaderBinding;
|
package/dist/extension.d.cts
CHANGED
|
@@ -1,33 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { LogMetricsView, SinkStatus } from "./tui/metricsOverlay.cjs";
|
|
4
|
-
import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
|
-
import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
|
|
6
|
-
//#region src/extension.d.ts
|
|
7
|
-
type TelemetryFactory = NonNullable<DoomTelemetryOptions['telemetryFactory']>;
|
|
8
|
-
interface PiTelemetryExtensionOptions {
|
|
9
|
-
allowFileFallback?: boolean;
|
|
10
|
-
/** Overrides the telemetry service identity. */
|
|
11
|
-
serviceName?: string;
|
|
12
|
-
/** Overrides the leader contribution owner. */
|
|
13
|
-
leaderSource?: string;
|
|
14
|
-
env?: NodeJS.ProcessEnv;
|
|
15
|
-
telemetryFactory?: TelemetryFactory;
|
|
16
|
-
/** Receives every sanitized record, whether or not a sink is live. */
|
|
17
|
-
metrics?: LogMetricsRecorder;
|
|
18
|
-
/** Called once the sink backend is resolved, so the overlay can report it. */
|
|
19
|
-
onSinkStatus?: (status: SinkStatus | undefined) => void;
|
|
20
|
-
/** Overrides the sink-history transport; injected in tests. */
|
|
21
|
-
metricsSource?: MetricsSource;
|
|
22
|
-
/** Receives telemetry lifecycle failures without writing into the TUI. */
|
|
23
|
-
onDiagnostic?: (message: string) => void;
|
|
24
|
-
}
|
|
25
|
-
declare function createPiTelemetryExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
26
|
-
declare function registerLogMetricsLeaderBinding(pi: Pick<ExtensionAPI, 'events' | 'on'>, options?: {
|
|
27
|
-
source?: string;
|
|
28
|
-
}): () => void;
|
|
29
|
-
declare function openLogMetricsOverlay(ctx: ExtensionContext, getView: () => LogMetricsView, query?: MetricsQuery): Promise<void>;
|
|
30
|
-
declare function createDoomLogExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
31
|
-
//#endregion
|
|
32
|
-
export { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
|
33
|
-
//# sourceMappingURL=extension.d.cts.map
|
|
1
|
+
import { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding } from "./adapters/pi/extension.cjs";
|
|
2
|
+
export { type PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
package/dist/extension.d.mts
CHANGED
|
@@ -1,33 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { LogMetricsView, SinkStatus } from "./tui/metricsOverlay.mjs";
|
|
4
|
-
import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
|
|
5
|
-
import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
6
|
-
//#region src/extension.d.ts
|
|
7
|
-
type TelemetryFactory = NonNullable<DoomTelemetryOptions['telemetryFactory']>;
|
|
8
|
-
interface PiTelemetryExtensionOptions {
|
|
9
|
-
allowFileFallback?: boolean;
|
|
10
|
-
/** Overrides the telemetry service identity. */
|
|
11
|
-
serviceName?: string;
|
|
12
|
-
/** Overrides the leader contribution owner. */
|
|
13
|
-
leaderSource?: string;
|
|
14
|
-
env?: NodeJS.ProcessEnv;
|
|
15
|
-
telemetryFactory?: TelemetryFactory;
|
|
16
|
-
/** Receives every sanitized record, whether or not a sink is live. */
|
|
17
|
-
metrics?: LogMetricsRecorder;
|
|
18
|
-
/** Called once the sink backend is resolved, so the overlay can report it. */
|
|
19
|
-
onSinkStatus?: (status: SinkStatus | undefined) => void;
|
|
20
|
-
/** Overrides the sink-history transport; injected in tests. */
|
|
21
|
-
metricsSource?: MetricsSource;
|
|
22
|
-
/** Receives telemetry lifecycle failures without writing into the TUI. */
|
|
23
|
-
onDiagnostic?: (message: string) => void;
|
|
24
|
-
}
|
|
25
|
-
declare function createPiTelemetryExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
26
|
-
declare function registerLogMetricsLeaderBinding(pi: Pick<ExtensionAPI, 'events' | 'on'>, options?: {
|
|
27
|
-
source?: string;
|
|
28
|
-
}): () => void;
|
|
29
|
-
declare function openLogMetricsOverlay(ctx: ExtensionContext, getView: () => LogMetricsView, query?: MetricsQuery): Promise<void>;
|
|
30
|
-
declare function createDoomLogExtension(options?: PiTelemetryExtensionOptions): (pi: ExtensionAPI) => void;
|
|
31
|
-
//#endregion
|
|
32
|
-
export { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
|
33
|
-
//# sourceMappingURL=extension.d.mts.map
|
|
1
|
+
import { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding } from "./adapters/pi/extension.mjs";
|
|
2
|
+
export { type PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
package/dist/extension.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import{
|
|
2
|
-
//# sourceMappingURL=extension.mjs.map
|
|
1
|
+
import{createDoomLogExtension as e,createPiTelemetryExtension as t,openLogMetricsOverlay as n,registerLogMetricsLeaderBinding as r}from"./adapters/pi/extension.mjs";export{e as createDoomLogExtension,t as createPiTelemetryExtension,n as openLogMetricsOverlay,r as registerLogMetricsLeaderBinding};
|
package/dist/extensions/pi.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//# sourceMappingURL=pi.cjs.map
|
|
1
|
+
const e=require("../adapters/pi/extension.cjs");module.exports=e.doomLogExtension;
|
package/dist/extensions/pi.d.cts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export = _default;
|
|
4
|
-
//# sourceMappingURL=pi.d.cts.map
|
|
1
|
+
import { doomLogExtension } from "../adapters/pi/extension.cjs";
|
|
2
|
+
export = doomLogExtension;
|
package/dist/extensions/pi.d.mts
CHANGED
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//#endregion
|
|
4
|
-
export { _default as default };
|
|
5
|
-
//# sourceMappingURL=pi.d.mts.map
|
|
1
|
+
import { doomLogExtension } from "../adapters/pi/extension.mjs";
|
|
2
|
+
export { doomLogExtension as default };
|
package/dist/extensions/pi.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import{
|
|
2
|
-
//# sourceMappingURL=pi.mjs.map
|
|
1
|
+
import{doomLogExtension as e}from"../adapters/pi/extension.mjs";export{e as default};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./metrics.cjs"),t=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./services/metrics.cjs"),t=require("./services/findings.cjs"),n=require("./tui/logMetricsOverlay.cjs"),r=require("./adapters/pi/extension.cjs");exports.API_ERROR_RECORD=e.API_ERROR_RECORD,exports.LogMetricsAggregator=e.LogMetricsAggregator,exports.LogMetricsOverlayComponent=n.LogMetricsOverlayComponent,exports.MAX_RETAINED_STATE_PER_TOOL=e.MAX_RETAINED_STATE_PER_TOOL,exports.MAX_RETAINED_TOKEN_BUCKETS=e.MAX_RETAINED_TOKEN_BUCKETS,exports.TOOL_RESULT_RECORD=e.TOOL_RESULT_RECORD,exports.TOOL_TOKEN_SAMPLE_RECORD=e.TOOL_TOKEN_SAMPLE_RECORD,exports.TURN_FAILED_RECORD=e.TURN_FAILED_RECORD,exports.TURN_FINISHED_RECORD=e.TURN_FINISHED_RECORD,exports.createDoomLogExtension=r.createDoomLogExtension,exports.createPiTelemetryExtension=r.createPiTelemetryExtension,exports.deriveFindings=t.deriveFindings,exports.openLogMetricsOverlay=r.openLogMetricsOverlay,exports.registerLogMetricsLeaderBinding=r.registerLogMetricsLeaderBinding;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { API_ERROR_RECORD, LogMetricsAggregator, LogMetricsAggregatorOptions, LogMetricsError, LogMetricsEventCount, LogMetricsOperationDuration, LogMetricsRecorder, LogMetricsSnapshot, LogMetricsTokenTotals, LogMetricsToolLatency, MAX_RETAINED_STATE_PER_TOOL, TOOL_RESULT_RECORD, TURN_FINISHED_RECORD } from "./metrics.cjs";
|
|
2
|
-
import { LogMetricsOverlayComponent, LogMetricsView, SinkStatus } from "./tui/
|
|
3
|
-
import { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding } from "./extension.cjs";
|
|
4
|
-
|
|
1
|
+
import { API_ERROR_RECORD, LogMetricsAggregator, LogMetricsAggregatorOptions, LogMetricsError, LogMetricsEventCount, LogMetricsOperationDuration, LogMetricsRecorder, LogMetricsSnapshot, LogMetricsTokenTotals, LogMetricsToolCost, LogMetricsToolLatency, MAX_RETAINED_STATE_PER_TOOL, MAX_RETAINED_TOKEN_BUCKETS, TOOL_RESULT_RECORD, TOOL_TOKEN_SAMPLE_RECORD, TURN_FAILED_RECORD, TURN_FINISHED_RECORD } from "./services/metrics.cjs";
|
|
2
|
+
import { LogMetricsOverlayComponent, LogMetricsView, SinkStatus } from "./tui/logMetricsOverlay.cjs";
|
|
3
|
+
import { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding } from "./adapters/pi/extension.cjs";
|
|
4
|
+
import { LogMetricsFinding, LogMetricsFindingSeverity, deriveFindings } from "./services/findings.cjs";
|
|
5
|
+
export { API_ERROR_RECORD, LogMetricsAggregator, type LogMetricsAggregatorOptions, type LogMetricsError, type LogMetricsEventCount, type LogMetricsFinding, type LogMetricsFindingSeverity, type LogMetricsOperationDuration, LogMetricsOverlayComponent, type LogMetricsRecorder, type LogMetricsSnapshot, type LogMetricsTokenTotals, type LogMetricsToolCost, type LogMetricsToolLatency, type LogMetricsView, MAX_RETAINED_STATE_PER_TOOL, MAX_RETAINED_TOKEN_BUCKETS, type PiTelemetryExtensionOptions, type SinkStatus, TOOL_RESULT_RECORD, TOOL_TOKEN_SAMPLE_RECORD, TURN_FAILED_RECORD, TURN_FINISHED_RECORD, createDoomLogExtension, createPiTelemetryExtension, deriveFindings, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { API_ERROR_RECORD, LogMetricsAggregator, LogMetricsAggregatorOptions, LogMetricsError, LogMetricsEventCount, LogMetricsOperationDuration, LogMetricsRecorder, LogMetricsSnapshot, LogMetricsTokenTotals, LogMetricsToolLatency, MAX_RETAINED_STATE_PER_TOOL, TOOL_RESULT_RECORD, TURN_FINISHED_RECORD } from "./metrics.mjs";
|
|
2
|
-
import { LogMetricsOverlayComponent, LogMetricsView, SinkStatus } from "./tui/
|
|
3
|
-
import { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding } from "./extension.mjs";
|
|
4
|
-
|
|
1
|
+
import { API_ERROR_RECORD, LogMetricsAggregator, LogMetricsAggregatorOptions, LogMetricsError, LogMetricsEventCount, LogMetricsOperationDuration, LogMetricsRecorder, LogMetricsSnapshot, LogMetricsTokenTotals, LogMetricsToolCost, LogMetricsToolLatency, MAX_RETAINED_STATE_PER_TOOL, MAX_RETAINED_TOKEN_BUCKETS, TOOL_RESULT_RECORD, TOOL_TOKEN_SAMPLE_RECORD, TURN_FAILED_RECORD, TURN_FINISHED_RECORD } from "./services/metrics.mjs";
|
|
2
|
+
import { LogMetricsOverlayComponent, LogMetricsView, SinkStatus } from "./tui/logMetricsOverlay.mjs";
|
|
3
|
+
import { PiTelemetryExtensionOptions, createDoomLogExtension, createPiTelemetryExtension, openLogMetricsOverlay, registerLogMetricsLeaderBinding } from "./adapters/pi/extension.mjs";
|
|
4
|
+
import { LogMetricsFinding, LogMetricsFindingSeverity, deriveFindings } from "./services/findings.mjs";
|
|
5
|
+
export { API_ERROR_RECORD, LogMetricsAggregator, type LogMetricsAggregatorOptions, type LogMetricsError, type LogMetricsEventCount, type LogMetricsFinding, type LogMetricsFindingSeverity, type LogMetricsOperationDuration, LogMetricsOverlayComponent, type LogMetricsRecorder, type LogMetricsSnapshot, type LogMetricsTokenTotals, type LogMetricsToolCost, type LogMetricsToolLatency, type LogMetricsView, MAX_RETAINED_STATE_PER_TOOL, MAX_RETAINED_TOKEN_BUCKETS, type PiTelemetryExtensionOptions, type SinkStatus, TOOL_RESULT_RECORD, TOOL_TOKEN_SAMPLE_RECORD, TURN_FAILED_RECORD, TURN_FINISHED_RECORD, createDoomLogExtension, createPiTelemetryExtension, deriveFindings, openLogMetricsOverlay, registerLogMetricsLeaderBinding };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{API_ERROR_RECORD as e,LogMetricsAggregator as t,MAX_RETAINED_STATE_PER_TOOL as n,
|
|
1
|
+
import{API_ERROR_RECORD as e,LogMetricsAggregator as t,MAX_RETAINED_STATE_PER_TOOL as n,MAX_RETAINED_TOKEN_BUCKETS as r,TOOL_RESULT_RECORD as i,TOOL_TOKEN_SAMPLE_RECORD as a,TURN_FAILED_RECORD as o,TURN_FINISHED_RECORD as s}from"./services/metrics.mjs";import{deriveFindings as c}from"./services/findings.mjs";import{LogMetricsOverlayComponent as l}from"./tui/logMetricsOverlay.mjs";import{createDoomLogExtension as u,createPiTelemetryExtension as d,openLogMetricsOverlay as f,registerLogMetricsLeaderBinding as p}from"./adapters/pi/extension.mjs";export{e as API_ERROR_RECORD,t as LogMetricsAggregator,l as LogMetricsOverlayComponent,n as MAX_RETAINED_STATE_PER_TOOL,r as MAX_RETAINED_TOKEN_BUCKETS,i as TOOL_RESULT_RECORD,a as TOOL_TOKEN_SAMPLE_RECORD,o as TURN_FAILED_RECORD,s as TURN_FINISHED_RECORD,u as createDoomLogExtension,d as createPiTelemetryExtension,c as deriveFindings,f as openLogMetricsOverlay,p as registerLogMetricsLeaderBinding};
|
package/dist/metrics.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=
|
|
2
|
-
//# sourceMappingURL=metrics.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./services/metrics.cjs"),t=require("./services/findings.cjs");exports.API_ERROR_RECORD=e.API_ERROR_RECORD,exports.LogMetricsAggregator=e.LogMetricsAggregator,exports.MAX_RETAINED_STATE_PER_TOOL=e.MAX_RETAINED_STATE_PER_TOOL,exports.MAX_RETAINED_TOKEN_BUCKETS=e.MAX_RETAINED_TOKEN_BUCKETS,exports.TOOL_RESULT_RECORD=e.TOOL_RESULT_RECORD,exports.TOOL_TOKEN_SAMPLE_RECORD=e.TOOL_TOKEN_SAMPLE_RECORD,exports.TURN_FAILED_RECORD=e.TURN_FAILED_RECORD,exports.TURN_FINISHED_RECORD=e.TURN_FINISHED_RECORD,exports.deriveFindings=t.deriveFindings;
|