@narumitw/pi-analytics 0.49.7 → 0.49.8
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 +70 -40
- package/dist/index.ts +0 -2
- package/dist/index.ts.map +2 -2
- package/package.json +5 -8
- package/src/analytics.ts +0 -2
package/README.md
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
# 📈 pi-analytics —
|
|
1
|
+
# 📈 pi-analytics — Understand Pi Activity Without Sending Data Away
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@narumitw/pi-analytics) [](https://pi.dev) [](./LICENSE)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
> This extension is experimental. Its metrics, storage format, and dashboard may change between releases.
|
|
7
|
-
|
|
8
|
-
`@narumitw/pi-analytics` is a local-first [Pi coding agent](https://pi.dev) extension that counts model calls, skill activations, tool activity, and observed provider errors without storing conversation or tool content.
|
|
5
|
+
Measure local model, skill, tool, and provider reliability activity without storing conversation or tool content or sending analytics elsewhere.
|
|
9
6
|
|
|
10
7
|
## ✨ Features
|
|
11
8
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- Stores only content-free metadata in private, versioned JSON Lines files.
|
|
19
|
-
- Uses one writer file per Pi runtime, so concurrent Pi processes never share a routine writer lock.
|
|
20
|
-
- Never starts a server or sends analytics anywhere.
|
|
9
|
+
- Collects content-free metrics automatically after installation.
|
|
10
|
+
- Counts settled response cycles, logical LLM calls, skill activations, tool calls, and observed provider errors.
|
|
11
|
+
- Reports tool failures and duration, model attribution, and per-response call distributions.
|
|
12
|
+
- Separates recovered provider errors from terminal failures.
|
|
13
|
+
- Provides Today, rolling 7-day, rolling 30-day, and all-time views through `/analytics`.
|
|
14
|
+
- Stores private, versioned JSONL locally, isolates concurrent writers, and does not start an analytics server.
|
|
21
15
|
|
|
22
16
|
## 📦 Install
|
|
23
17
|
|
|
@@ -33,17 +27,17 @@ Try the published package without installing:
|
|
|
33
27
|
pi -e npm:@narumitw/pi-analytics
|
|
34
28
|
```
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
Build and try a local checkout from the repository root:
|
|
37
31
|
|
|
38
32
|
```bash
|
|
33
|
+
npm --workspace @narumitw/pi-analytics run build
|
|
39
34
|
pi -e ./packages/pi-analytics
|
|
40
35
|
```
|
|
41
36
|
|
|
42
|
-
The
|
|
43
|
-
|
|
44
|
-
The package declares `dist/index.ts`, so an unbuilt local checkout must run `npm --workspace @narumitw/pi-analytics run build` before Pi loads the package directory.
|
|
37
|
+
The package declares `dist/index.ts`, so an unbuilt local checkout must run the build before Pi loads the package directory.
|
|
45
38
|
|
|
46
|
-
|
|
39
|
+
The extension uses Node's built-in filesystem APIs and has no native database dependency.
|
|
40
|
+
Pi extensions run with the Pi process's user permissions, so install only trusted packages.
|
|
47
41
|
|
|
48
42
|
## 🚀 Quick start
|
|
49
43
|
|
|
@@ -68,41 +62,58 @@ Provider errors 4
|
|
|
68
62
|
Recovered errors 3
|
|
69
63
|
```
|
|
70
64
|
|
|
71
|
-
Use the menu to change the
|
|
65
|
+
Use the menu to change the range or inspect Skills, Tools, Provider reliability, Response cycles, and Data & privacy.
|
|
66
|
+
The dashboard includes finalized cycles and omits active work.
|
|
72
67
|
|
|
73
68
|
## 📐 Metric definitions
|
|
74
69
|
|
|
75
70
|
### Response cycles and LLM calls
|
|
76
71
|
|
|
77
|
-
A **response cycle** starts when Pi begins agent work and ends at `agent_settled`.
|
|
72
|
+
A **response cycle** starts when Pi begins agent work and normally ends at `agent_settled`.
|
|
73
|
+
Retries, overflow-compaction recovery, tool follow-ups, and queued continuations before settlement remain in that cycle.
|
|
78
74
|
|
|
79
|
-
An **LLM call** is one logical provider generation.
|
|
75
|
+
An **LLM call** is one logical provider generation.
|
|
76
|
+
A provider can make several HTTP attempts within it, so `429 → 429 → 200` counts as one LLM call, three observed HTTP responses, two provider errors, and one recovered generation.
|
|
80
77
|
|
|
81
78
|
### Skills
|
|
82
79
|
|
|
83
|
-
An activation is **User initiated** when an observed interactive or RPC `/skill:<name>` input
|
|
80
|
+
An activation is **User initiated** when an observed interactive or RPC `/skill:<name>` input belongs to an active or subsequently started response cycle.
|
|
81
|
+
This includes skill commands queued while Pi is streaming.
|
|
82
|
+
It is **Model initiated** when Pi's built-in `read` tool successfully loads the exact canonical `SKILL.md` path Pi discovered.
|
|
83
|
+
Each skill counts at most once per response cycle, with explicit user use taking precedence.
|
|
84
84
|
|
|
85
|
-
Pi does not expose a first-class skill-invocation event or
|
|
85
|
+
Pi does not expose a first-class skill-invocation event or post-chain acceptance event to input observers.
|
|
86
|
+
The extension does not count unsuccessful reads, provider behavior hidden from Pi, or non-standard loading such as `bash` plus `cat SKILL.md`.
|
|
86
87
|
|
|
87
88
|
### Tools
|
|
88
89
|
|
|
89
|
-
A tool call starts at Pi's `tool_execution_start` event and finishes at `tool_execution_end`.
|
|
90
|
+
A tool call starts at Pi's `tool_execution_start` event and finishes at `tool_execution_end`.
|
|
91
|
+
The extension stores the tool name, model attribution, timing, completion state, and final error flag.
|
|
92
|
+
Pi does not expose enough information to distinguish a call blocked by another extension from other tool errors, so both count as errors.
|
|
90
93
|
|
|
91
94
|
### Provider reliability
|
|
92
95
|
|
|
93
|
-
Pi exposes HTTP responses and final assistant failures, not every provider-SDK transport retry.
|
|
96
|
+
Pi exposes HTTP responses and final assistant failures, but not every provider-SDK transport retry.
|
|
97
|
+
The dashboard therefore calls these values **observed provider errors**.
|
|
98
|
+
It reports HTTP 429 and 5xx counts, conservative error categories, recovered errors, and terminal failures.
|
|
99
|
+
Raw error messages are classified in memory and discarded.
|
|
94
100
|
|
|
95
|
-
## 💬
|
|
101
|
+
## 💬 Commands
|
|
96
102
|
|
|
97
103
|
```text
|
|
98
104
|
/analytics
|
|
99
105
|
```
|
|
100
106
|
|
|
101
|
-
The command accepts no arguments.
|
|
107
|
+
The command accepts no arguments.
|
|
108
|
+
TUI mode shows the full dashboard, and RPC mode adapts the same screens to dialogs.
|
|
109
|
+
Print and JSON modes reject the command before reading analytics data.
|
|
102
110
|
|
|
103
|
-
The root menu contains Change time range, Skills, Tools, Provider reliability, Response cycles, Data & privacy, and Close.
|
|
111
|
+
The root menu contains Change time range, Skills, Tools, Provider reliability, Response cycles, Data & privacy, and Close.
|
|
112
|
+
Skills and Tools provide searchable details and model breakdowns.
|
|
113
|
+
Escape goes back from nested screens and closes the root, while Ctrl+C closes the menu.
|
|
114
|
+
Deleting data requires confirmation; Back keeps the dashboard open, Ctrl+C closes it in TUI mode, and cancellation leaves data unchanged.
|
|
104
115
|
|
|
105
|
-
##
|
|
116
|
+
## 🔒 Security and privacy
|
|
106
117
|
|
|
107
118
|
Current analytics live under:
|
|
108
119
|
|
|
@@ -114,21 +125,35 @@ Current analytics live under:
|
|
|
114
125
|
└── <opaque-writer-id>.jsonl
|
|
115
126
|
```
|
|
116
127
|
|
|
117
|
-
The opaque IDs are storage coordination identifiers generated by the extension; they are not Pi session IDs.
|
|
128
|
+
The opaque IDs are storage coordination identifiers generated by the extension; they are not Pi session IDs.
|
|
129
|
+
On Unix, directories are restricted to mode `0700` and files to `0600`.
|
|
130
|
+
Linked storage roots, markers, and writer files are rejected.
|
|
118
131
|
|
|
119
|
-
Stored fields are limited to timestamps and durations; extension-generated record IDs; provider/model IDs and thinking level; tool and skill names; user/model skill source; counts, outcomes, and completion states; HTTP status codes; and classified provider-error categories.
|
|
132
|
+
Stored fields are limited to timestamps and durations; extension-generated record IDs; provider/model IDs and thinking level; tool and skill names; user/model skill source; counts, outcomes, and completion states; HTTP status codes; and classified provider-error categories.
|
|
133
|
+
Provider-supplied tool-call IDs are replaced with local ordinals before publication.
|
|
120
134
|
|
|
121
135
|
The extension does **not** store prompts, responses, thinking content, tool arguments or results, raw error messages, HTTP headers, cwd/project/file paths, session names or IDs, or credentials.
|
|
122
136
|
|
|
123
|
-
Each
|
|
137
|
+
Each finalized response cycle is one versioned, newline-terminated frame.
|
|
138
|
+
Frames larger than 1 MiB are dropped.
|
|
139
|
+
Local writes receive a 5-second cancellation deadline.
|
|
140
|
+
Node filesystem cancellation is best-effort, so an operating-system request that has begun may still finish.
|
|
141
|
+
The extension reports the first failed or timed-out write and a later recovery without exposing filesystem errors.
|
|
124
142
|
|
|
125
|
-
`/analytics` streams and validates the active generation, checks cancellation between files and records, and periodically yields to the event loop.
|
|
143
|
+
`/analytics` streams and validates the active generation, checks cancellation between files and records, and periodically yields to the event loop.
|
|
144
|
+
It ignores a crash-truncated final frame.
|
|
145
|
+
Completed malformed frames and unsupported format versions fail closed without replacing existing files.
|
|
126
146
|
|
|
127
147
|
### Clear analytics data
|
|
128
148
|
|
|
129
|
-
Choose **Data & privacy → Clear analytics data…** to
|
|
149
|
+
Choose **Data & privacy → Clear analytics data…** to publish a fresh active generation atomically.
|
|
150
|
+
Other Pi processes observe it before their next write.
|
|
151
|
+
A record racing with Clear can land immediately before or after the switch.
|
|
130
152
|
|
|
131
|
-
The extension then removes
|
|
153
|
+
The extension then removes obsolete generations.
|
|
154
|
+
If another process still uses an obsolete file, Clear reports incomplete physical cleanup but the logical clear remains complete.
|
|
155
|
+
Stop other Pi processes and clear again to retry cleanup.
|
|
156
|
+
File deletion does not guarantee secure erasure from the storage medium.
|
|
132
157
|
|
|
133
158
|
## 🧭 Legacy SQLite data
|
|
134
159
|
|
|
@@ -139,14 +164,18 @@ Versions that used Turso/SQLite stored data in:
|
|
|
139
164
|
<pi-agent-directory>/pi-analytics.db-wal
|
|
140
165
|
```
|
|
141
166
|
|
|
142
|
-
The JSONL version
|
|
167
|
+
The JSONL version does not open, import, migrate, delete, or rewrite these files.
|
|
168
|
+
New analytics start empty.
|
|
143
169
|
|
|
144
|
-
If legacy history matters, stop every old Pi process first and preserve both files together.
|
|
170
|
+
If legacy history matters, stop every old Pi process first and preserve both files together.
|
|
171
|
+
If it does not matter, stop every old Pi process before deleting both files manually.
|
|
172
|
+
Never copy or remove only the main DB while an old process may still own its WAL.
|
|
145
173
|
|
|
146
174
|
## 🚧 Limitations
|
|
147
175
|
|
|
148
176
|
- There are no retention settings; records remain until explicitly cleared.
|
|
149
|
-
- Analytics are best-effort derived metadata.
|
|
177
|
+
- Analytics are best-effort derived metadata.
|
|
178
|
+
A failed or interrupted local write may be omitted.
|
|
150
179
|
- Large all-time histories require scanning the active JSONL generation when the dashboard opens.
|
|
151
180
|
- Prometheus, JSON/CSV export, cloud sync, browser dashboards, token/cost reporting, and project attribution are not included.
|
|
152
181
|
- Statistics cover only events visible through Pi's public extension API.
|
|
@@ -186,4 +215,5 @@ Pi extension, Pi coding agent, local analytics, agent skills, tool usage, model
|
|
|
186
215
|
|
|
187
216
|
## 📄 License
|
|
188
217
|
|
|
189
|
-
MIT.
|
|
218
|
+
MIT.
|
|
219
|
+
See [`LICENSE`](./LICENSE).
|
package/dist/index.ts
CHANGED
|
@@ -1498,7 +1498,6 @@ var AnalyticsStore = class {
|
|
|
1498
1498
|
};
|
|
1499
1499
|
|
|
1500
1500
|
// src/analytics.ts
|
|
1501
|
-
var EXPERIMENTAL_WARNING = "pi-analytics is experimental; its metrics and dashboard may change.";
|
|
1502
1501
|
var STORAGE_DIRECTORY = "pi-analytics";
|
|
1503
1502
|
function createAnalyticsExtension(dependencies = {}) {
|
|
1504
1503
|
const deps = {
|
|
@@ -1543,7 +1542,6 @@ function createAnalyticsExtension(dependencies = {}) {
|
|
|
1543
1542
|
});
|
|
1544
1543
|
pi.on("session_start", (_event, ctx) => {
|
|
1545
1544
|
++sessionGeneration;
|
|
1546
|
-
if (ctx.hasUI) ctx.ui.notify(EXPERIMENTAL_WARNING, "warning");
|
|
1547
1545
|
const previousStore = store;
|
|
1548
1546
|
sessionController.abort(new DOMException("Analytics session replaced", "AbortError"));
|
|
1549
1547
|
if (previousStore) retire(previousStore);
|
package/dist/index.ts.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/analytics.ts", "../src/collector.ts", "../src/errors.ts", "../src/menu.ts", "../src/storage/queries.ts", "../src/skills.ts", "../src/storage/files.ts", "../src/storage/format.ts", "../src/storage/store.ts"],
|
|
4
|
-
"sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\tgetAgentDir,\n} from \"@earendil-works/pi-coding-agent\";\nimport { ResponseCollector } from \"./collector.js\";\nimport { type AnalyticsMenuDataSource, showAnalyticsMenu } from \"./menu.js\";\nimport { SkillTracker } from \"./skills.js\";\nimport type { ClearAnalyticsResult } from \"./storage/files.js\";\nimport type { AnalyticsSnapshot, TimeRange } from \"./storage/queries.js\";\nimport { AnalyticsStore } from \"./storage/store.js\";\nimport type { ModelIdentity, SettledRun, TriggerSource } from \"./types.js\";\n\nconst EXPERIMENTAL_WARNING = \"pi-analytics is experimental; its metrics and dashboard may change.\";\nconst STORAGE_DIRECTORY = \"pi-analytics\";\n\nexport interface AnalyticsStorePort {\n\treadonly path: string;\n\trecordRun(run: SettledRun, signal?: AbortSignal): Promise<void>;\n\tgetSnapshot(range: TimeRange, signal?: AbortSignal): Promise<AnalyticsSnapshot>;\n\tclearAll(signal?: AbortSignal): Promise<ClearAnalyticsResult>;\n\tclose(): Promise<void>;\n}\n\ninterface AnalyticsDependencies {\n\tcreateStore(path: string): AnalyticsStorePort;\n\tcreateSkillTracker(cwd: string): SkillTracker;\n\tgetAgentDir(): string;\n\tnow(): number;\n\tcreateId(): string;\n}\n\nexport function createAnalyticsExtension(\n\tdependencies: Partial<AnalyticsDependencies> = {},\n): (pi: ExtensionAPI) => void {\n\tconst deps: AnalyticsDependencies = {\n\t\tcreateStore: dependencies.createStore ?? ((rootPath) => new AnalyticsStore(rootPath)),\n\t\tcreateSkillTracker: dependencies.createSkillTracker ?? ((cwd) => new SkillTracker(cwd)),\n\t\tgetAgentDir: dependencies.getAgentDir ?? getAgentDir,\n\t\tnow: dependencies.now ?? Date.now,\n\t\tcreateId: dependencies.createId ?? randomUUID,\n\t};\n\n\treturn function analyticsExtension(pi: ExtensionAPI): void {\n\t\tlet sessionGeneration = 0;\n\t\tlet sessionController = new AbortController();\n\t\tlet collector = new ResponseCollector();\n\t\tlet skillTracker: SkillTracker | undefined;\n\t\tlet store: AnalyticsStorePort | undefined;\n\t\tlet storageFailure: string | undefined;\n\t\tconst retiredCloseTasks = new Set<Promise<boolean>>();\n\t\tlet writeFailureActive = false;\n\t\tlet pendingTriggerSource: TriggerSource = \"unknown\";\n\t\tlet pendingAttemptWithoutRun = false;\n\n\t\tpi.registerCommand(\"analytics\", {\n\t\t\tdescription: \"Open local Pi usage analytics\",\n\t\t\thandler: async (args, ctx) => {\n\t\t\t\tif (args.trim()) {\n\t\t\t\t\tif (!ctx.hasUI || (ctx.mode !== \"tui\" && ctx.mode !== \"rpc\")) {\n\t\t\t\t\t\tthrow new Error(\"/analytics does not accept arguments.\");\n\t\t\t\t\t}\n\t\t\t\t\tctx.ui.notify(\"/analytics does not accept arguments.\", \"warning\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!ctx.hasUI || (ctx.mode !== \"tui\" && ctx.mode !== \"rpc\")) {\n\t\t\t\t\tthrow new Error(\"/analytics requires Pi TUI or RPC mode.\");\n\t\t\t\t}\n\t\t\t\tconst generation = sessionGeneration;\n\t\t\t\tconst owner = sessionController;\n\t\t\t\tconst source = menuSource(generation, owner.signal);\n\t\t\t\tawait showAnalyticsMenu(ctx, source, {\n\t\t\t\t\tsignal: owner.signal,\n\t\t\t\t\tisCurrent: () => generation === sessionGeneration && !owner.signal.aborted,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tpi.on(\"session_start\", (_event, ctx) => {\n\t\t\t++sessionGeneration;\n\t\t\tif (ctx.hasUI) ctx.ui.notify(EXPERIMENTAL_WARNING, \"warning\");\n\t\t\tconst previousStore = store;\n\t\t\tsessionController.abort(new DOMException(\"Analytics session replaced\", \"AbortError\"));\n\t\t\tif (previousStore) retire(previousStore);\n\t\t\tsessionController = new AbortController();\n\t\t\tcollector = new ResponseCollector();\n\t\t\tskillTracker = deps.createSkillTracker(ctx.cwd);\n\t\t\tstore = undefined;\n\t\t\tstorageFailure = undefined;\n\t\t\twriteFailureActive = false;\n\t\t\tpendingTriggerSource = \"unknown\";\n\t\t\tpendingAttemptWithoutRun = false;\n\t\t\tconst storageRoot = path.join(deps.getAgentDir(), STORAGE_DIRECTORY);\n\t\t\ttry {\n\t\t\t\tstore = deps.createStore(storageRoot);\n\t\t\t} catch {\n\t\t\t\tstorageFailure = unavailableMessage();\n\t\t\t\tsafeNotify(ctx, storageFailure, \"warning\");\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"input\", (event, ctx) => {\n\t\t\tconst now = deps.now();\n\t\t\tconst tracker = skillTracker;\n\t\t\ttracker?.observeInput(event.text, event.source, now);\n\t\t\tif (event.source !== \"extension\") pendingTriggerSource = event.source;\n\t\t\tif (!tracker || !collector.hasActiveRun()) return;\n\t\t\tconst explicit = tracker.consumeExplicitSkill();\n\t\t\tif (!explicit || !tracker.hasAvailableSkill(explicit.name)) return;\n\t\t\tcollector.activateSkill({\n\t\t\t\tname: explicit.name,\n\t\t\t\tinitiatedBy: \"user\",\n\t\t\t\tnow: explicit.observedAtMs,\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\t\tconst generation = sessionGeneration;\n\t\t\tconst tracker = skillTracker;\n\t\t\tconst activeCollector = collector;\n\t\t\tif (!tracker) return;\n\t\t\tconst skills = availableSkills(pi, event.systemPromptOptions.skills ?? []);\n\t\t\tawait tracker.setAvailableSkills(skills);\n\t\t\tif (\n\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\ttracker !== skillTracker ||\n\t\t\t\tactiveCollector !== collector\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst explicit = tracker.consumeExplicitSkill();\n\t\t\tconst interrupted = activeCollector.begin({\n\t\t\t\tid: deps.createId(),\n\t\t\t\tnow: deps.now(),\n\t\t\t\ttriggerSource: explicit?.source ?? pendingTriggerSource,\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t\tpendingTriggerSource = \"unknown\";\n\t\t\tif (interrupted) {\n\t\t\t\tawait persistRun(interrupted, ctx, generation, sessionController.signal);\n\t\t\t\tif (\n\t\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\t\ttracker !== skillTracker ||\n\t\t\t\t\tactiveCollector !== collector\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (explicit && skills.some(({ name }) => name === explicit.name)) {\n\t\t\t\tactiveCollector.activateSkill({\n\t\t\t\t\tname: explicit.name,\n\t\t\t\t\tinitiatedBy: \"user\",\n\t\t\t\t\tnow: explicit.observedAtMs,\n\t\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"agent_start\", () => {\n\t\t\tif (collector.hasActiveRun()) collector.beginAttempt();\n\t\t\telse pendingAttemptWithoutRun = true;\n\t\t});\n\n\t\tpi.on(\"turn_start\", (_event, ctx) => ensureRun(ctx, \"extension\"));\n\n\t\tpi.on(\"before_provider_request\", (_event, ctx) => {\n\t\t\tensureRun(ctx, \"extension\");\n\t\t\tcollector.beginGeneration({\n\t\t\t\tid: deps.createId(),\n\t\t\t\tnow: deps.now(),\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"after_provider_response\", (event) => {\n\t\t\tcollector.recordProviderResponse({ status: event.status, now: deps.now() });\n\t\t});\n\n\t\tpi.on(\"message_end\", (event) => {\n\t\t\tif (event.message.role !== \"assistant\") return;\n\t\t\tcollector.finishGeneration({\n\t\t\t\tnow: deps.now(),\n\t\t\t\tstopReason: event.message.stopReason,\n\t\t\t\terrorMessage: event.message.errorMessage,\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_execution_start\", (event, ctx) => {\n\t\t\tensureRun(ctx, \"extension\");\n\t\t\tcollector.beginTool({\n\t\t\t\tid: event.toolCallId,\n\t\t\t\tname: event.toolName,\n\t\t\t\tnow: deps.now(),\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\t\tif (event.toolName === \"read\" && !isBuiltinReadTool(pi)) return;\n\t\t\tconst generation = sessionGeneration;\n\t\t\tconst tracker = skillTracker;\n\t\t\tconst activeCollector = collector;\n\t\t\tconst runId = activeCollector.getActiveRunId();\n\t\t\tif (!tracker || !runId) return;\n\t\t\tconst name = await tracker.matchSuccessfulRead({\n\t\t\t\ttoolName: event.toolName,\n\t\t\t\tinput: event.input,\n\t\t\t\tisError: event.isError,\n\t\t\t});\n\t\t\tif (\n\t\t\t\t!name ||\n\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\ttracker !== skillTracker ||\n\t\t\t\tactiveCollector !== collector ||\n\t\t\t\tactiveCollector.getActiveRunId() !== runId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactiveCollector.activateSkill({\n\t\t\t\tname,\n\t\t\t\tinitiatedBy: \"model\",\n\t\t\t\tnow: deps.now(),\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_execution_end\", (event) => {\n\t\t\tcollector.finishTool({ id: event.toolCallId, now: deps.now(), isError: event.isError });\n\t\t});\n\n\t\tpi.on(\"agent_settled\", async (_event, ctx) => {\n\t\t\tconst generation = sessionGeneration;\n\t\t\tconst owner = sessionController;\n\t\t\tconst run = collector.settle(deps.now());\n\t\t\tpendingAttemptWithoutRun = false;\n\t\t\tpendingTriggerSource = \"unknown\";\n\t\t\tskillTracker?.clearPending();\n\t\t\tif (run) await persistRun(run, ctx, generation, owner.signal);\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tconst activeStore = store;\n\t\t\t++sessionGeneration;\n\t\t\tsessionController.abort(new DOMException(\"Analytics session shut down\", \"AbortError\"));\n\t\t\tskillTracker?.clearPending();\n\t\t\tskillTracker = undefined;\n\t\t\tstore = undefined;\n\t\t\tcollector.interrupt(deps.now());\n\t\t\tconst closing = activeStore\n\t\t\t\t? [closeResult(activeStore), ...retiredCloseTasks]\n\t\t\t\t: [...retiredCloseTasks];\n\t\t\tconst results = await Promise.all(closing);\n\t\t\tif (results.some((closed) => !closed)) {\n\t\t\t\tsafeNotify(ctx, \"Analytics storage shutdown was incomplete.\", \"warning\");\n\t\t\t}\n\t\t});\n\n\t\tfunction retire(retiredStore: AnalyticsStorePort): void {\n\t\t\tconst task = closeResult(retiredStore).finally(() => retiredCloseTasks.delete(task));\n\t\t\tretiredCloseTasks.add(task);\n\t\t}\n\n\t\tasync function closeResult(activeStore: AnalyticsStorePort): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tawait activeStore.close();\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfunction ensureRun(ctx: ExtensionContext, triggerSource: TriggerSource): void {\n\t\t\tif (collector.hasActiveRun()) return;\n\t\t\tcollector.begin({\n\t\t\t\tid: deps.createId(),\n\t\t\t\tnow: deps.now(),\n\t\t\t\ttriggerSource,\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t\tif (pendingAttemptWithoutRun) {\n\t\t\t\tpendingAttemptWithoutRun = false;\n\t\t\t\tcollector.beginAttempt();\n\t\t\t}\n\t\t}\n\n\t\tasync function persistRun(\n\t\t\trun: SettledRun,\n\t\t\tctx: ExtensionContext,\n\t\t\tgeneration: number,\n\t\t\tsignal: AbortSignal,\n\t\t): Promise<void> {\n\t\t\tconst activeStore = store;\n\t\t\tif (!activeStore || signal.aborted) return;\n\t\t\ttry {\n\t\t\t\tawait activeStore.recordRun(run, signal);\n\t\t\t\tif (generation !== sessionGeneration || activeStore !== store || signal.aborted) return;\n\t\t\t\tif (writeFailureActive) {\n\t\t\t\t\twriteFailureActive = false;\n\t\t\t\t\tsafeNotify(ctx, \"Local analytics storage recovered.\", \"info\");\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (\n\t\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\t\tactiveStore !== store ||\n\t\t\t\t\tsignal.aborted ||\n\t\t\t\t\twriteFailureActive\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\twriteFailureActive = true;\n\t\t\t\tsafeNotify(\n\t\t\t\t\tctx,\n\t\t\t\t\t\"Analytics could not save this response cycle; its metrics were dropped.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tfunction menuSource(generation: number, signal: AbortSignal): AnalyticsMenuDataSource {\n\t\t\treturn {\n\t\t\t\tpath: store?.path ?? path.join(deps.getAgentDir(), STORAGE_DIRECTORY),\n\t\t\t\tasync load(range, actionSignal) {\n\t\t\t\t\tassertCurrent(generation, signal);\n\t\t\t\t\tconst activeStore = store;\n\t\t\t\t\tif (!activeStore) {\n\t\t\t\t\t\treturn { kind: \"unavailable\", message: storageFailure ?? unavailableMessage() };\n\t\t\t\t\t}\n\t\t\t\t\tconst snapshot = await activeStore.getSnapshot(range, actionSignal);\n\t\t\t\t\tassertCurrent(generation, signal);\n\t\t\t\t\treturn { kind: \"ready\", snapshot };\n\t\t\t\t},\n\t\t\t\tasync clearAll(actionSignal) {\n\t\t\t\t\tassertCurrent(generation, signal);\n\t\t\t\t\tconst activeStore = store;\n\t\t\t\t\tif (!activeStore) return { cleanupIncomplete: false };\n\t\t\t\t\treturn activeStore.clearAll(actionSignal);\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tfunction assertCurrent(generation: number, signal: AbortSignal): void {\n\t\t\tif (generation !== sessionGeneration || signal.aborted) {\n\t\t\t\tthrow new DOMException(\"Analytics interaction replaced\", \"AbortError\");\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction modelIdentity(ctx: ExtensionContext, pi: ExtensionAPI): ModelIdentity | undefined {\n\tif (!ctx.model) return undefined;\n\treturn {\n\t\tprovider: ctx.model.provider,\n\t\tmodel: ctx.model.id,\n\t\tthinkingLevel: pi.getThinkingLevel(),\n\t};\n}\n\nexport function isBuiltinReadTool(pi: ExtensionAPI): boolean {\n\tconst read = pi.getAllTools().find(({ name }) => name === \"read\");\n\treturn read?.sourceInfo.source === \"builtin\";\n}\n\nfunction availableSkills(\n\tpi: ExtensionAPI,\n\tsystemSkills: ReadonlyArray<{ name: string; filePath: string }>,\n): Array<{ name: string; filePath: string }> {\n\tconst result = [...systemSkills];\n\tconst seen = new Set(result.map(({ name }) => name));\n\tconst getCommands = (pi as ExtensionAPI & { getCommands?: ExtensionAPI[\"getCommands\"] })\n\t\t.getCommands;\n\tfor (const command of typeof getCommands === \"function\" ? getCommands.call(pi) : []) {\n\t\tif (command.source !== \"skill\" || seen.has(command.name.replace(/^skill:/u, \"\"))) continue;\n\t\tconst name = command.name.replace(/^skill:/u, \"\");\n\t\tseen.add(name);\n\t\tresult.push({ name, filePath: command.sourceInfo.path });\n\t}\n\treturn result;\n}\n\nfunction unavailableMessage(): string {\n\treturn [\n\t\t\"Local analytics storage could not be initialized safely.\",\n\t\t\"Existing files were not replaced.\",\n\t\t\"No analytics are being collected.\",\n\t].join(\"\\n\");\n}\n\nfunction safeNotify(ctx: ExtensionContext, message: string, level: \"info\" | \"warning\"): void {\n\ttry {\n\t\tctx.ui.notify(message, level);\n\t} catch {\n\t\t// A replaced Pi context cannot receive lifecycle feedback.\n\t}\n}\n\nexport default createAnalyticsExtension();\n", "import { randomUUID } from \"node:crypto\";\nimport { classifyProviderError } from \"./errors.js\";\nimport type {\n\tGenerationOutcome,\n\tGenerationRecord,\n\tModelIdentity,\n\tProviderErrorRecord,\n\tRunOutcome,\n\tSettledRun,\n\tSkillActivationRecord,\n\tToolCallRecord,\n\tTriggerSource,\n} from \"./types.js\";\n\ninterface ActiveRun {\n\tid: string;\n\tstartedAtMs: number;\n\ttriggerSource: TriggerSource;\n\tinitialModel?: ModelIdentity;\n\tattemptCount: number;\n\tgenerations: GenerationRecord[];\n\tgenerationIds: Set<string>;\n\ttools: ToolCallRecord[];\n\ttoolIds: Set<string>;\n\tskills: SkillActivationRecord[];\n\tskillIndexes: Map<string, number>;\n\tproviderErrors: ProviderErrorRecord[];\n}\n\nexport class ResponseCollector {\n\tprivate active: ActiveRun | undefined;\n\n\thasActiveRun(): boolean {\n\t\treturn this.active !== undefined;\n\t}\n\n\tgetActiveRunId(): string | undefined {\n\t\treturn this.active?.id;\n\t}\n\n\tbegin(input: {\n\t\tid: string;\n\t\tnow: number;\n\t\ttriggerSource: TriggerSource;\n\t\tmodel?: ModelIdentity;\n\t}): SettledRun | undefined {\n\t\tconst interrupted = this.active ? this.finalize(input.now, \"interrupted\") : undefined;\n\t\tthis.active = {\n\t\t\tid: input.id,\n\t\t\tstartedAtMs: input.now,\n\t\t\ttriggerSource: input.triggerSource,\n\t\t\tinitialModel: input.model,\n\t\t\tattemptCount: 0,\n\t\t\tgenerations: [],\n\t\t\tgenerationIds: new Set(),\n\t\t\ttools: [],\n\t\t\ttoolIds: new Set(),\n\t\t\tskills: [],\n\t\t\tskillIndexes: new Map(),\n\t\t\tproviderErrors: [],\n\t\t};\n\t\treturn interrupted;\n\t}\n\n\tbeginAttempt(): void {\n\t\tif (this.active) this.active.attemptCount += 1;\n\t}\n\n\tbeginGeneration(input: { id: string; now: number; model?: ModelIdentity }): void {\n\t\tconst active = this.active;\n\t\tif (!active || active.generationIds.has(input.id)) return;\n\t\tactive.generationIds.add(input.id);\n\t\tactive.generations.push({\n\t\t\tid: input.id,\n\t\t\tordinal: active.generations.length,\n\t\t\tprovider: input.model?.provider,\n\t\t\tmodel: input.model?.model,\n\t\t\tthinkingLevel: input.model?.thinkingLevel,\n\t\t\tstartedAtMs: input.now,\n\t\t\toutcome: \"pending\",\n\t\t\tresponses: [],\n\t\t});\n\t}\n\n\trecordProviderResponse(input: { status: number; now: number }): void {\n\t\tconst generation = this.latestGeneration();\n\t\tif (generation?.outcome !== \"pending\") return;\n\t\tgeneration.responses.push({\n\t\t\tordinal: generation.responses.length,\n\t\t\toccurredAtMs: input.now,\n\t\t\tstatus: input.status,\n\t\t});\n\t}\n\n\tfinishGeneration(input: { now: number; stopReason: string; errorMessage?: string }): void {\n\t\tconst active = this.active;\n\t\tconst generation = this.latestGeneration();\n\t\tif (!active || !generation || generation.outcome !== \"pending\") return;\n\t\tgeneration.finishedAtMs = input.now;\n\t\tgeneration.durationMs = elapsed(generation.startedAtMs, input.now);\n\t\tgeneration.stopReason = input.stopReason;\n\t\tgeneration.outcome = generationOutcome(input.stopReason);\n\t\tif (generation.outcome === \"error\") {\n\t\t\tactive.providerErrors.push({\n\t\t\t\tid: randomUUID(),\n\t\t\t\tgenerationId: generation.id,\n\t\t\t\toccurredAtMs: input.now,\n\t\t\t\tprovider: generation.provider,\n\t\t\t\tmodel: generation.model,\n\t\t\t\tcategory: classifyProviderError(input.errorMessage),\n\t\t\t\trecovered: false,\n\t\t\t\tterminal: true,\n\t\t\t});\n\t\t}\n\t}\n\n\tbeginTool(input: { id: string; name: string; now: number; model?: ModelIdentity }): void {\n\t\tconst active = this.active;\n\t\tif (!active || active.toolIds.has(input.id)) return;\n\t\tactive.toolIds.add(input.id);\n\t\tactive.tools.push({\n\t\t\tid: input.id,\n\t\t\tordinal: active.tools.length,\n\t\t\tname: input.name,\n\t\t\tprovider: input.model?.provider,\n\t\t\tmodel: input.model?.model,\n\t\t\tstartedAtMs: input.now,\n\t\t\tisError: false,\n\t\t\tcompletionState: \"running\",\n\t\t});\n\t}\n\n\tfinishTool(input: { id: string; now: number; isError: boolean }): void {\n\t\tconst tool = this.active?.tools.find(({ id }) => id === input.id);\n\t\tif (tool?.completionState !== \"running\") return;\n\t\ttool.finishedAtMs = input.now;\n\t\ttool.durationMs = elapsed(tool.startedAtMs, input.now);\n\t\ttool.isError = input.isError;\n\t\ttool.completionState = \"finished\";\n\t}\n\n\tactivateSkill(input: {\n\t\tname: string;\n\t\tinitiatedBy: \"user\" | \"model\";\n\t\tnow: number;\n\t\tmodel?: ModelIdentity;\n\t}): void {\n\t\tconst active = this.active;\n\t\tif (!active) return;\n\t\tconst existingIndex = active.skillIndexes.get(input.name);\n\t\tif (existingIndex !== undefined) {\n\t\t\tconst existing = active.skills[existingIndex];\n\t\t\tif (existing && existing.initiatedBy === \"model\" && input.initiatedBy === \"user\") {\n\t\t\t\texisting.initiatedBy = \"user\";\n\t\t\t\texisting.occurredAtMs = input.now;\n\t\t\t\texisting.provider = input.model?.provider;\n\t\t\t\texisting.model = input.model?.model;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tactive.skillIndexes.set(input.name, active.skills.length);\n\t\tactive.skills.push({\n\t\t\tid: randomUUID(),\n\t\t\tname: input.name,\n\t\t\tinitiatedBy: input.initiatedBy,\n\t\t\toccurredAtMs: input.now,\n\t\t\tprovider: input.model?.provider,\n\t\t\tmodel: input.model?.model,\n\t\t});\n\t}\n\n\tsettle(now: number): SettledRun | undefined {\n\t\treturn this.finalize(now);\n\t}\n\n\tinterrupt(now: number): SettledRun | undefined {\n\t\treturn this.finalize(now, \"interrupted\");\n\t}\n\n\tprivate latestGeneration(): GenerationRecord | undefined {\n\t\treturn this.active?.generations.at(-1);\n\t}\n\n\tprivate finalize(now: number, forcedOutcome?: RunOutcome): SettledRun | undefined {\n\t\tconst active = this.active;\n\t\tif (!active) return undefined;\n\t\tthis.active = undefined;\n\n\t\tfor (const generation of active.generations) {\n\t\t\tif (generation.outcome !== \"pending\") continue;\n\t\t\tgeneration.outcome = \"interrupted\";\n\t\t\tgeneration.finishedAtMs = now;\n\t\t\tgeneration.durationMs = elapsed(generation.startedAtMs, now);\n\t\t}\n\t\tfor (const tool of active.tools) {\n\t\t\tif (tool.completionState !== \"running\") continue;\n\t\t\ttool.completionState = \"interrupted\";\n\t\t\ttool.finishedAtMs = now;\n\t\t\ttool.durationMs = elapsed(tool.startedAtMs, now);\n\t\t}\n\n\t\tconst successfulGenerationIndexes = new Set(\n\t\t\tactive.generations\n\t\t\t\t.map((generation, index) => ({ generation, index }))\n\t\t\t\t.filter(({ generation }) => isSuccessfulGeneration(generation))\n\t\t\t\t.map(({ index }) => index),\n\t\t);\n\t\tlet recoveredHttpErrors = 0;\n\t\tlet httpErrors = 0;\n\t\tfor (const [generationIndex, generation] of active.generations.entries()) {\n\t\t\tconst hasLaterSuccess = [...successfulGenerationIndexes].some(\n\t\t\t\t(index) => index > generationIndex,\n\t\t\t);\n\t\t\tfor (const [responseIndex, response] of generation.responses.entries()) {\n\t\t\t\tif (response.status < 400) continue;\n\t\t\t\thttpErrors += 1;\n\t\t\t\tconst laterSuccessInGeneration = generation.responses\n\t\t\t\t\t.slice(responseIndex + 1)\n\t\t\t\t\t.some(({ status }) => status >= 200 && status < 400);\n\t\t\t\tif (laterSuccessInGeneration || hasLaterSuccess) recoveredHttpErrors += 1;\n\t\t\t}\n\t\t}\n\t\tfor (const error of active.providerErrors) {\n\t\t\tconst generationIndex = active.generations.findIndex(({ id }) => id === error.generationId);\n\t\t\terror.recovered = [...successfulGenerationIndexes].some((index) => index > generationIndex);\n\t\t\terror.terminal = !error.recovered;\n\t\t}\n\n\t\tconst recoveredGenerationErrors = active.providerErrors.filter(\n\t\t\t({ recovered }) => recovered,\n\t\t).length;\n\t\tconst providerErrorCount = httpErrors + active.providerErrors.length;\n\t\tconst recoveredErrorCount = recoveredHttpErrors + recoveredGenerationErrors;\n\t\tconst outcome = forcedOutcome ?? deriveOutcome(active.generations, providerErrorCount);\n\n\t\treturn {\n\t\t\tid: active.id,\n\t\t\tstartedAtMs: active.startedAtMs,\n\t\t\tfinishedAtMs: now,\n\t\t\tdurationMs: elapsed(active.startedAtMs, now),\n\t\t\ttriggerSource: active.triggerSource,\n\t\t\tinitialProvider: active.initialModel?.provider,\n\t\t\tinitialModel: active.initialModel?.model,\n\t\t\toutcome,\n\t\t\tattemptCount: active.attemptCount,\n\t\t\tgenerations: active.generations,\n\t\t\ttools: active.tools,\n\t\t\tskills: active.skills,\n\t\t\tproviderErrors: active.providerErrors,\n\t\t\ttoolErrorCount: active.tools.filter(({ isError }) => isError).length,\n\t\t\tproviderErrorCount,\n\t\t\trecoveredErrorCount,\n\t\t};\n\t}\n}\n\nfunction elapsed(start: number, end: number): number {\n\treturn Math.max(0, end - start);\n}\n\nfunction generationOutcome(stopReason: string): GenerationOutcome {\n\tswitch (stopReason) {\n\t\tcase \"stop\":\n\t\t\treturn \"stop\";\n\t\tcase \"toolUse\":\n\t\t\treturn \"tool_use\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"aborted\":\n\t\t\treturn \"aborted\";\n\t\tcase \"length\":\n\t\t\treturn \"length\";\n\t\tdefault:\n\t\t\treturn \"interrupted\";\n\t}\n}\n\nfunction isSuccessfulGeneration(generation: GenerationRecord): boolean {\n\treturn generation.outcome === \"stop\" || generation.outcome === \"tool_use\";\n}\n\nfunction deriveOutcome(\n\tgenerations: readonly GenerationRecord[],\n\tproviderErrors: number,\n): RunOutcome {\n\tconst last = generations.at(-1);\n\tif (!last) return providerErrors > 0 ? \"error\" : \"success\";\n\tswitch (last.outcome) {\n\t\tcase \"stop\":\n\t\tcase \"tool_use\":\n\t\t\treturn providerErrors > 0 ? \"recovered_success\" : \"success\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"aborted\":\n\t\t\treturn \"aborted\";\n\t\tcase \"length\":\n\t\t\treturn \"length\";\n\t\tdefault:\n\t\t\treturn \"interrupted\";\n\t}\n}\n", "import type { ProviderErrorCategory } from \"./types.js\";\n\nexport function classifyProviderError(message: string | undefined): ProviderErrorCategory {\n\tconst value = message?.toLowerCase() ?? \"\";\n\tif (/\\b(enotfound|eai_again|dns|getaddrinfo)\\b/u.test(value)) return \"dns\";\n\tif (/\\b(etimedout|timeout|timed out)\\b/u.test(value)) return \"timeout\";\n\tif (/\\b(econnrefused|connection refused)\\b/u.test(value)) return \"connection_refused\";\n\tif (/\\b(econnreset|connection reset|socket hang up)\\b/u.test(value)) {\n\t\treturn \"connection_reset\";\n\t}\n\tif (/\\b(tls|ssl|certificate|cert_|handshake)\\b/u.test(value)) return \"tls\";\n\tif (/\\b(fetch failed|network|socket|connection|transport)\\b/u.test(value)) {\n\t\treturn \"network_other\";\n\t}\n\treturn \"provider_other\";\n}\n", "import { stripVTControlCharacters } from \"node:util\";\nimport type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport type { MenuDefinition } from \"@narumitw/pi-tui-kit\";\nimport type { ClearAnalyticsResult } from \"./storage/files.js\";\nimport type {\n\tAnalyticsSnapshot,\n\tSkillStats,\n\tTimeRange,\n\tTimeRangeId,\n\tToolStats,\n} from \"./storage/queries.js\";\nimport { resolveTimeRange } from \"./storage/queries.js\";\n\nexport type AnalyticsLoadResult =\n\t| { kind: \"ready\"; snapshot: AnalyticsSnapshot }\n\t| { kind: \"unavailable\"; message: string };\n\nexport interface AnalyticsMenuDataSource {\n\tpath: string;\n\tload(range: TimeRange, signal: AbortSignal): Promise<AnalyticsLoadResult>;\n\tclearAll(signal: AbortSignal): Promise<ClearAnalyticsResult>;\n}\n\nexport interface AnalyticsMenuState {\n\trangeId: TimeRangeId;\n\trange: TimeRange;\n\tpath: string;\n\tresult: AnalyticsLoadResult;\n}\n\nexport interface AnalyticsMenuOptions {\n\trunConfirmation: typeof import(\"@narumitw/pi-tui-kit\")[\"runConfirmation\"];\n\tisCurrent(): boolean;\n}\n\ntype Screen = \"main\" | \"range\" | \"skills\" | \"tools\" | \"reliability\" | \"responses\" | \"privacy\";\ntype Action = \"setRange\" | \"clearData\";\n\nconst RANGE_LABELS: Record<TimeRangeId, string> = {\n\ttoday: \"Today\",\n\t\"7d\": \"Last 7 days\",\n\t\"30d\": \"Last 30 days\",\n\tall: \"All time\",\n};\n\nexport function createAnalyticsMenu(\n\tsource: AnalyticsMenuDataSource,\n\tnow: () => number = Date.now,\n\toptions?: AnalyticsMenuOptions,\n) {\n\tlet rangeId: TimeRangeId = \"7d\";\n\tlet cachedState: AnalyticsMenuState | undefined;\n\tconst loadState = async (signal: AbortSignal): Promise<AnalyticsMenuState> => {\n\t\tif (cachedState?.rangeId === rangeId) return cachedState;\n\t\tconst range = resolveTimeRange(rangeId, now());\n\t\tconst loaded = { rangeId, range, path: source.path, result: await source.load(range, signal) };\n\t\tif (!signal.aborted && rangeId === loaded.rangeId) cachedState = loaded;\n\t\treturn loaded;\n\t};\n\tconst getState = ({ signal }: { signal: AbortSignal }): Promise<AnalyticsMenuState> =>\n\t\tloadState(signal);\n\tconst menu: MenuDefinition<AnalyticsMenuState, Screen, Action> = {\n\t\tstart: \"main\",\n\t\tscreens: {\n\t\t\tmain: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: `Analytics \u00B7 ${RANGE_LABELS[state.rangeId]}`,\n\t\t\t\tlines: overviewLines(state.result),\n\t\t\t\titems: [\n\t\t\t\t\t{ id: \"range\", label: \"Change time range\", to: \"range\" },\n\t\t\t\t\t{ id: \"skills\", label: \"Skills\", to: \"skills\" },\n\t\t\t\t\t{ id: \"tools\", label: \"Tools\", to: \"tools\" },\n\t\t\t\t\t{ id: \"reliability\", label: \"Provider reliability\", to: \"reliability\" },\n\t\t\t\t\t{ id: \"responses\", label: \"Response cycles\", to: \"responses\" },\n\t\t\t\t\t{ id: \"privacy\", label: \"Data & privacy\", to: \"privacy\" },\n\t\t\t\t\t{ id: \"close\", label: \"Close\", close: true },\n\t\t\t\t],\n\t\t\t\thint: \"close\",\n\t\t\t}),\n\t\t\trange: ({ state }) => ({\n\t\t\t\tkind: \"choice\",\n\t\t\t\ttitle: \"Analytics time range\",\n\t\t\t\titems: (Object.keys(RANGE_LABELS) as TimeRangeId[]).map((id) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tlabel: RANGE_LABELS[id],\n\t\t\t\t})),\n\t\t\t\taction: \"setRange\",\n\t\t\t\tcurrentItemId: state.rangeId,\n\t\t\t\tinitialItemId: state.rangeId,\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tskills: ({ state }) => skillsScreen(state.result),\n\t\t\ttools: ({ state }) => toolsScreen(state.result),\n\t\t\treliability: ({ state }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: `Provider reliability \u00B7 ${RANGE_LABELS[state.rangeId]}`,\n\t\t\t\tlines: reliabilityLines(state.result),\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tresponses: ({ state }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: `Response cycles \u00B7 ${RANGE_LABELS[state.rangeId]}`,\n\t\t\t\tlines: responseLines(state.result),\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tprivacy: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: \"Analytics data & privacy\",\n\t\t\t\tlines: privacyLines(state),\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"clear\",\n\t\t\t\t\t\tlabel: \"Clear analytics data\u2026\",\n\t\t\t\t\t\taction: \"clearData\",\n\t\t\t\t\t\tdisabled: state.result.kind !== \"ready\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\tsetRange: async ({ itemId, signal }) => {\n\t\t\t\tif (!isRangeId(itemId)) return { kind: \"rejected\", error: new Error(\"Unknown range\") };\n\t\t\t\trangeId = itemId;\n\t\t\t\tcachedState = undefined;\n\t\t\t\tawait loadState(signal);\n\t\t\t\treturn signal.aborted ? { kind: \"close\" } : { kind: \"to\", screen: \"main\" };\n\t\t\t},\n\t\t\tclearData: async ({ ctx, state, signal }) => {\n\t\t\t\tif (state.result.kind !== \"ready\") return { kind: \"stay\" };\n\t\t\t\tif (!options) throw new Error(\"Analytics confirmation is unavailable\");\n\t\t\t\tconst count = state.result.snapshot.overview.responseCycles;\n\t\t\t\tconst confirmation = await options.runConfirmation(ctx, {\n\t\t\t\t\ttitle: \"Delete analytics data?\",\n\t\t\t\t\tmessage: `This will clear all local analytics history from:\\n\\n${safeDisplayText(state.path)}\\n\\nThe selected range currently shows ${count} response cycles. Other running Pi processes may add new records afterward.`,\n\t\t\t\t\tconfirmLabel: \"Delete data\",\n\t\t\t\t\tcancelLabel: \"Keep data\",\n\t\t\t\t\tsignal,\n\t\t\t\t\tisCurrent: options.isCurrent,\n\t\t\t\t\t// Keep the dashboard's existing domain-level error route as the only notifier.\n\t\t\t\t\tonError: () => undefined,\n\t\t\t\t});\n\t\t\t\tif (signal.aborted || !options.isCurrent()) return { kind: \"close\" };\n\t\t\t\tif (confirmation.kind === \"closed\") {\n\t\t\t\t\treturn confirmation.reason === \"close\" ? { kind: \"close\" } : { kind: \"stay\" };\n\t\t\t\t}\n\t\t\t\tif (confirmation.kind === \"stale\") return { kind: \"close\" };\n\t\t\t\tif (confirmation.kind === \"unsupported\") {\n\t\t\t\t\tthrow new Error(`Analytics confirmation is unavailable in ${confirmation.mode} mode`);\n\t\t\t\t}\n\t\t\t\tif (confirmation.kind === \"error\") throw confirmation.error;\n\n\t\t\t\tconst result = await source.clearAll(signal);\n\t\t\t\tcachedState = undefined;\n\t\t\t\tconst isCurrent = options.isCurrent();\n\t\t\t\tif (isCurrent) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctx.ui.notify(\"Cleared local analytics data.\", \"info\");\n\t\t\t\t\t\tif (result.cleanupIncomplete) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t\"Some obsolete analytics files are still in use. Stop other Pi processes and clear again to remove them.\",\n\t\t\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// The host can dispose the current UI after the ownership check.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn signal.aborted || !isCurrent ? { kind: \"close\" } : { kind: \"to\", screen: \"main\" };\n\t\t\t},\n\t\t},\n\t};\n\treturn {\n\t\tmenu,\n\t\tgetState,\n\t\tpreload: (signal: AbortSignal) => loadState(signal),\n\t\tget rangeId() {\n\t\t\treturn rangeId;\n\t\t},\n\t};\n}\n\nexport async function showAnalyticsMenu(\n\tctx: ExtensionCommandContext,\n\tsource: AnalyticsMenuDataSource,\n\toptions: { signal: AbortSignal; isCurrent: () => boolean },\n): Promise<void> {\n\tconst { runConfirmation, runMenu, runTask } = await import(\"@narumitw/pi-tui-kit\");\n\tif (options.signal.aborted || !options.isCurrent()) return;\n\tconst controller = createAnalyticsMenu(source, Date.now, {\n\t\trunConfirmation,\n\t\tisCurrent: options.isCurrent,\n\t});\n\tconst loading = await runTask(ctx, {\n\t\tlabel: \"Loading local analytics\u2026\",\n\t\tsignal: options.signal,\n\t\tisCurrent: options.isCurrent,\n\t\ttask: ({ signal }) => controller.preload(signal),\n\t\tonError: () => undefined,\n\t});\n\tif (loading.kind !== \"completed\") {\n\t\tif (loading.kind === \"error\") {\n\t\t\tctx.ui.notify(\n\t\t\t\t\"Analytics failed: The local analytics query could not be completed. Existing data was not changed.\",\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\tawait runMenu(ctx, controller.menu, {\n\t\tgetState: controller.getState,\n\t\tsignal: options.signal,\n\t\tisCurrent: options.isCurrent,\n\t\tonError: (_ctx, error) => {\n\t\t\tctx.ui.notify(`Analytics failed: ${safeErrorMessage(error)}`, \"error\");\n\t\t},\n\t});\n}\n\nfunction overviewLines(result: AnalyticsLoadResult): string[] {\n\tif (result.kind === \"unavailable\") {\n\t\treturn [result.message, \"\", \"No analytics are being collected.\"];\n\t}\n\tconst stats = result.snapshot.overview;\n\tif (stats.responseCycles === 0) {\n\t\treturn [\n\t\t\t\"No analytics yet.\",\n\t\t\t\"Collection is active. Complete one Pi response cycle, then open /analytics again.\",\n\t\t\t\"\",\n\t\t\t\"Includes settled response cycles only.\",\n\t\t];\n\t}\n\treturn [\n\t\tmetric(\"Response cycles\", stats.responseCycles),\n\t\tmetric(\"LLM calls\", stats.llmCalls),\n\t\tmetric(\n\t\t\t\"Calls per response\",\n\t\t\t`${formatDecimal(stats.callsPerResponse)} \u00B7 P95 ${stats.p95CallsPerResponse}`,\n\t\t),\n\t\tmetric(\"Tool calls\", stats.toolCalls),\n\t\tmetric(\"Tool errors\", stats.toolErrors),\n\t\tmetric(\"Skill activations\", stats.skillActivations),\n\t\tmetric(\"Provider errors\", stats.providerErrors),\n\t\tmetric(\"Recovered errors\", stats.recoveredErrors),\n\t\t\"\",\n\t\t\"Includes settled response cycles only.\",\n\t];\n}\n\nfunction skillsScreen(result: AnalyticsLoadResult) {\n\tif (result.kind === \"unavailable\") {\n\t\treturn {\n\t\t\tkind: \"browse\" as const,\n\t\t\ttitle: \"Skills\",\n\t\t\tlines: [result.message],\n\t\t\titems: [],\n\t\t\thint: \"back\" as const,\n\t\t};\n\t}\n\treturn {\n\t\tkind: \"browse\" as const,\n\t\ttitle: \"Skills\",\n\t\tlines:\n\t\t\tresult.snapshot.skills.length === 0\n\t\t\t\t? [\"No skill activations detected in this time range.\"]\n\t\t\t\t: undefined,\n\t\titems: result.snapshot.skills.map(skillItem),\n\t\tviewportSize: \"adaptive\" as const,\n\t\thint: \"back\" as const,\n\t};\n}\n\nfunction skillItem(skill: SkillStats) {\n\treturn {\n\t\tid: skill.name,\n\t\tlabel: safeDisplayText(skill.name),\n\t\tstatusText: `${skill.count} \u00B7 ${skill.modelInitiated} model / ${skill.userInitiated} user`,\n\t\tsearchText: skill.models.map(modelLabel).join(\" \"),\n\t\tdetails: [\n\t\t\tmetric(\"Activations\", skill.count),\n\t\t\tmetric(\"Model initiated\", skill.modelInitiated),\n\t\t\tmetric(\"User initiated\", skill.userInitiated),\n\t\t\t\"\",\n\t\t\t\"By model\",\n\t\t\t...skill.models.map((model) => `${modelLabel(model)}: ${model.count}`),\n\t\t\t\"\",\n\t\t\t`Last detected: ${formatTimestamp(skill.lastOccurredAtMs)}`,\n\t\t],\n\t};\n}\n\nfunction toolsScreen(result: AnalyticsLoadResult) {\n\tif (result.kind === \"unavailable\") {\n\t\treturn {\n\t\t\tkind: \"browse\" as const,\n\t\t\ttitle: \"Tools\",\n\t\t\tlines: [result.message],\n\t\t\titems: [],\n\t\t\thint: \"back\" as const,\n\t\t};\n\t}\n\treturn {\n\t\tkind: \"browse\" as const,\n\t\ttitle: \"Tools\",\n\t\tlines:\n\t\t\tresult.snapshot.tools.length === 0\n\t\t\t\t? [\"No tool calls detected in this time range.\"]\n\t\t\t\t: undefined,\n\t\titems: result.snapshot.tools.map(toolItem),\n\t\tviewportSize: \"adaptive\" as const,\n\t\thint: \"back\" as const,\n\t};\n}\n\nfunction toolItem(tool: ToolStats) {\n\treturn {\n\t\tid: tool.name,\n\t\tlabel: safeDisplayText(tool.name),\n\t\tstatusText: `${tool.count} \u00B7 ${tool.errors} errors`,\n\t\tsearchText: tool.models.map(modelLabel).join(\" \"),\n\t\tdetails: [\n\t\t\tmetric(\"Calls\", tool.count),\n\t\t\tmetric(\"Errors\", tool.errors),\n\t\t\t`Average duration: ${formatDecimal(tool.averageDurationMs)} ms`,\n\t\t\t\"\",\n\t\t\t\"By model\",\n\t\t\t...tool.models.map((model) => `${modelLabel(model)}: ${model.count}`),\n\t\t\t\"\",\n\t\t\t`Last detected: ${formatTimestamp(tool.lastOccurredAtMs)}`,\n\t\t],\n\t};\n}\n\nfunction reliabilityLines(result: AnalyticsLoadResult): string[] {\n\tif (result.kind === \"unavailable\") return [result.message];\n\tconst value = result.snapshot.reliability;\n\treturn [\n\t\t\"Observed provider errors only; provider-internal failures may be invisible.\",\n\t\t\"\",\n\t\tmetric(\"HTTP 429\", value.http429),\n\t\tmetric(\"HTTP 5xx\", value.http5xx),\n\t\tmetric(\"DNS\", value.categories.dns),\n\t\tmetric(\"Connection timeout\", value.categories.timeout),\n\t\tmetric(\"Connection refused\", value.categories.connection_refused),\n\t\tmetric(\"Connection reset\", value.categories.connection_reset),\n\t\tmetric(\"TLS\", value.categories.tls),\n\t\tmetric(\"Other network\", value.categories.network_other),\n\t\tmetric(\"Other provider\", value.categories.provider_other),\n\t\t\"\",\n\t\tmetric(\"Recovered\", value.recovered),\n\t\tmetric(\"Terminal failures\", value.terminal),\n\t];\n}\n\nfunction responseLines(result: AnalyticsLoadResult): string[] {\n\tif (result.kind === \"unavailable\") return [result.message];\n\tconst value = result.snapshot.responses;\n\treturn [\n\t\tmetric(\"Cycles\", value.count),\n\t\tmetric(\"LLM calls\", value.llmCalls),\n\t\tmetric(\"Average\", formatDecimal(value.average)),\n\t\tmetric(\"Median\", formatDecimal(value.median)),\n\t\tmetric(\"P95\", value.p95),\n\t\tmetric(\"Maximum\", value.maximum),\n\t\t\"\",\n\t\t\"Calls per response\",\n\t\tmetric(\"1 call\", value.distribution.one),\n\t\tmetric(\"2\u20133 calls\", value.distribution.twoToThree),\n\t\tmetric(\"4\u20136 calls\", value.distribution.fourToSix),\n\t\tmetric(\"7+ calls\", value.distribution.sevenPlus),\n\t];\n}\n\nfunction privacyLines(state: AnalyticsMenuState): string[] {\n\treturn [\n\t\t\"Local analytics files:\",\n\t\tsafeDisplayText(state.path),\n\t\t\"\",\n\t\t\"Stored: timestamps, extension-generated record IDs, model/provider IDs, thinking level, tool and skill names, durations, counts, HTTP statuses, and classified errors.\",\n\t\t\"Not stored: prompts, responses, thinking, tool arguments/results, raw errors, headers, cwd/file paths, session identity, or credentials.\",\n\t\t\"\",\n\t\t\"No database server, cloud connection, or other remote telemetry is used.\",\n\t\t\"Analytics are non-critical derived metadata; a failed local write may be dropped.\",\n\t];\n}\n\nfunction metric(label: string, value: string | number): string {\n\treturn `${label.padEnd(24)} ${value}`;\n}\n\nfunction formatDecimal(value: number): string {\n\treturn Number.isInteger(value)\n\t\t? String(value)\n\t\t: value.toFixed(2).replace(/0+$/u, \"\").replace(/\\.$/u, \"\");\n}\n\nfunction formatTimestamp(value: number): string {\n\treturn new Date(value).toLocaleString();\n}\n\nfunction modelLabel(model: { provider?: string; model?: string }): string {\n\tif (!model.provider && !model.model) return \"unknown\";\n\treturn safeDisplayText(`${model.provider ?? \"unknown\"}/${model.model ?? \"unknown\"}`);\n}\n\nfunction safeDisplayText(value: unknown): string {\n\treturn Array.from(stripVTControlCharacters(String(value)), (character) => {\n\t\tconst codePoint = character.codePointAt(0) ?? 0;\n\t\treturn codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f) ? \" \" : character;\n\t}).join(\"\");\n}\n\nfunction isRangeId(value: string): value is TimeRangeId {\n\treturn value === \"today\" || value === \"7d\" || value === \"30d\" || value === \"all\";\n}\n\nfunction safeErrorMessage(_error: unknown): string {\n\treturn \"The local analytics query could not be completed. Try again; existing data was not changed.\";\n}\n", "import type { ProviderErrorCategory, SettledRun } from \"../types.js\";\n\nexport type TimeRangeId = \"today\" | \"7d\" | \"30d\" | \"all\";\nexport interface TimeRange {\n\tid?: TimeRangeId;\n\tfromMs: number;\n\ttoMs: number;\n}\n\nexport interface OverviewStats {\n\tresponseCycles: number;\n\tllmCalls: number;\n\tcallsPerResponse: number;\n\tp95CallsPerResponse: number;\n\ttoolCalls: number;\n\ttoolErrors: number;\n\tskillActivations: number;\n\tproviderErrors: number;\n\trecoveredErrors: number;\n}\n\nexport interface ModelCount {\n\tprovider?: string;\n\tmodel?: string;\n\tcount: number;\n}\n\nexport interface SkillStats {\n\tname: string;\n\tcount: number;\n\tmodelInitiated: number;\n\tuserInitiated: number;\n\tlastOccurredAtMs: number;\n\tmodels: ModelCount[];\n}\n\nexport interface ToolStats {\n\tname: string;\n\tcount: number;\n\terrors: number;\n\taverageDurationMs: number;\n\tlastOccurredAtMs: number;\n\tmodels: ModelCount[];\n}\n\nexport interface ReliabilityStats {\n\thttp429: number;\n\thttp5xx: number;\n\trecovered: number;\n\tterminal: number;\n\tcategories: Record<ProviderErrorCategory, number>;\n}\n\nexport interface ResponseStats {\n\tcount: number;\n\tllmCalls: number;\n\taverage: number;\n\tmedian: number;\n\tp95: number;\n\tmaximum: number;\n\tdistribution: { one: number; twoToThree: number; fourToSix: number; sevenPlus: number };\n}\n\nexport interface AnalyticsSnapshot {\n\toverview: OverviewStats;\n\tskills: SkillStats[];\n\ttools: ToolStats[];\n\treliability: ReliabilityStats;\n\tresponses: ResponseStats;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1_000;\nconst ERROR_CATEGORIES: readonly ProviderErrorCategory[] = [\n\t\"dns\",\n\t\"timeout\",\n\t\"connection_refused\",\n\t\"connection_reset\",\n\t\"tls\",\n\t\"network_other\",\n\t\"provider_other\",\n];\n\nexport function resolveTimeRange(id: TimeRangeId, now = Date.now()): TimeRange {\n\tlet fromMs = 0;\n\tif (id === \"today\") {\n\t\tconst date = new Date(now);\n\t\tfromMs = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();\n\t} else if (id === \"7d\") fromMs = now - 7 * DAY_MS;\n\telse if (id === \"30d\") fromMs = now - 30 * DAY_MS;\n\treturn { id, fromMs, toMs: now + 1 };\n}\n\nexport async function querySnapshot(\n\truns: AsyncIterable<SettledRun> | Iterable<SettledRun>,\n\trange: TimeRange,\n\tsignal?: AbortSignal,\n): Promise<AnalyticsSnapshot> {\n\tconst generationCounts: number[] = [];\n\tconst seenRunIds = new Set<string>();\n\tconst skills = new Map<string, SkillStats>();\n\tconst tools = new Map<string, ToolStats & { totalDurationMs: number }>();\n\tconst categories = Object.fromEntries(\n\t\tERROR_CATEGORIES.map((category) => [category, 0]),\n\t) as Record<ProviderErrorCategory, number>;\n\tlet toolErrors = 0;\n\tlet providerErrors = 0;\n\tlet recoveredErrors = 0;\n\tlet http429 = 0;\n\tlet http5xx = 0;\n\tlet terminal = 0;\n\n\tfor await (const run of runs) {\n\t\tthrowIfAborted(signal);\n\t\tif (seenRunIds.has(run.id)) continue;\n\t\tseenRunIds.add(run.id);\n\t\tif (run.startedAtMs < range.fromMs || run.startedAtMs >= range.toMs) continue;\n\t\tgenerationCounts.push(run.generations.length);\n\t\ttoolErrors += run.toolErrorCount;\n\t\tproviderErrors += run.providerErrorCount;\n\t\trecoveredErrors += run.recoveredErrorCount;\n\n\t\tfor (const skill of run.skills) {\n\t\t\tconst item = skills.get(skill.name) ?? {\n\t\t\t\tname: skill.name,\n\t\t\t\tcount: 0,\n\t\t\t\tmodelInitiated: 0,\n\t\t\t\tuserInitiated: 0,\n\t\t\t\tlastOccurredAtMs: 0,\n\t\t\t\tmodels: [],\n\t\t\t};\n\t\t\titem.count += 1;\n\t\t\tif (skill.initiatedBy === \"user\") item.userInitiated += 1;\n\t\t\telse item.modelInitiated += 1;\n\t\t\titem.lastOccurredAtMs = Math.max(item.lastOccurredAtMs, skill.occurredAtMs);\n\t\t\tmergeModelCount(item.models, {\n\t\t\t\tprovider: skill.provider,\n\t\t\t\tmodel: skill.model,\n\t\t\t\tcount: 1,\n\t\t\t});\n\t\t\tskills.set(skill.name, item);\n\t\t}\n\n\t\tfor (const tool of run.tools) {\n\t\t\tconst item = tools.get(tool.name) ?? {\n\t\t\t\tname: tool.name,\n\t\t\t\tcount: 0,\n\t\t\t\terrors: 0,\n\t\t\t\taverageDurationMs: 0,\n\t\t\t\ttotalDurationMs: 0,\n\t\t\t\tlastOccurredAtMs: 0,\n\t\t\t\tmodels: [],\n\t\t\t};\n\t\t\titem.count += 1;\n\t\t\titem.errors += tool.isError ? 1 : 0;\n\t\t\titem.totalDurationMs += tool.durationMs ?? 0;\n\t\t\titem.averageDurationMs = item.totalDurationMs / item.count;\n\t\t\titem.lastOccurredAtMs = Math.max(item.lastOccurredAtMs, tool.startedAtMs);\n\t\t\tmergeModelCount(item.models, {\n\t\t\t\tprovider: tool.provider,\n\t\t\t\tmodel: tool.model,\n\t\t\t\tcount: 1,\n\t\t\t});\n\t\t\ttools.set(tool.name, item);\n\t\t}\n\n\t\tfor (const error of run.providerErrors) {\n\t\t\tcategories[error.category] += 1;\n\t\t\tterminal += error.terminal ? 1 : 0;\n\t\t}\n\t\tfor (const generation of run.generations) {\n\t\t\tfor (const response of generation.responses) {\n\t\t\t\tif (response.status === 429) http429 += 1;\n\t\t\t\tif (response.status >= 500 && response.status < 600) http5xx += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst responses = responseStatistics(generationCounts);\n\treturn {\n\t\toverview: {\n\t\t\tresponseCycles: responses.count,\n\t\t\tllmCalls: responses.llmCalls,\n\t\t\tcallsPerResponse: responses.average,\n\t\t\tp95CallsPerResponse: responses.p95,\n\t\t\ttoolCalls: sum([...tools.values()].map(({ count }) => count)),\n\t\t\ttoolErrors,\n\t\t\tskillActivations: sum([...skills.values()].map(({ count }) => count)),\n\t\t\tproviderErrors,\n\t\t\trecoveredErrors,\n\t\t},\n\t\tskills: [...skills.values()]\n\t\t\t.map((item) => ({ ...item, models: sortModels(item.models) }))\n\t\t\t.sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)),\n\t\ttools: [...tools.values()]\n\t\t\t.map(({ totalDurationMs: _, ...item }) => ({ ...item, models: sortModels(item.models) }))\n\t\t\t.sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)),\n\t\treliability: {\n\t\t\thttp429,\n\t\t\thttp5xx,\n\t\t\trecovered: recoveredErrors,\n\t\t\tterminal,\n\t\t\tcategories,\n\t\t},\n\t\tresponses,\n\t};\n}\n\nfunction responseStatistics(generationCounts: number[]): ResponseStats {\n\tconst sorted = [...generationCounts].sort((left, right) => left - right);\n\tconst count = sorted.length;\n\tconst llmCalls = sum(sorted);\n\tconst nearestRank = (percentile: number) =>\n\t\tcount === 0 ? 0 : (sorted[Math.max(0, Math.ceil(percentile * count) - 1)] ?? 0);\n\tconst median =\n\t\tcount === 0\n\t\t\t? 0\n\t\t\t: count % 2 === 1\n\t\t\t\t? (sorted[Math.floor(count / 2)] ?? 0)\n\t\t\t\t: ((sorted[count / 2 - 1] ?? 0) + (sorted[count / 2] ?? 0)) / 2;\n\treturn {\n\t\tcount,\n\t\tllmCalls,\n\t\taverage: count > 0 ? llmCalls / count : 0,\n\t\tmedian,\n\t\tp95: nearestRank(0.95),\n\t\tmaximum: sorted.at(-1) ?? 0,\n\t\tdistribution: {\n\t\t\tone: sorted.filter((value) => value === 1).length,\n\t\t\ttwoToThree: sorted.filter((value) => value >= 2 && value <= 3).length,\n\t\t\tfourToSix: sorted.filter((value) => value >= 4 && value <= 6).length,\n\t\t\tsevenPlus: sorted.filter((value) => value >= 7).length,\n\t\t},\n\t};\n}\n\nfunction mergeModelCount(models: ModelCount[], next: ModelCount): void {\n\tconst existing = models.find(\n\t\t({ provider, model }) => provider === next.provider && model === next.model,\n\t);\n\tif (existing) existing.count += next.count;\n\telse models.push(next);\n}\n\nfunction sortModels(models: ModelCount[]): ModelCount[] {\n\treturn models.sort(\n\t\t(left, right) =>\n\t\t\tright.count - left.count ||\n\t\t\t`${left.provider ?? \"\"}/${left.model ?? \"\"}`.localeCompare(\n\t\t\t\t`${right.provider ?? \"\"}/${right.model ?? \"\"}`,\n\t\t\t),\n\t);\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n\tif (signal?.aborted)\n\t\tthrow signal.reason ?? new DOMException(\"Analytics query aborted\", \"AbortError\");\n}\n\nfunction sum(values: readonly number[]): number {\n\treturn values.reduce((total, value) => total + value, 0);\n}\n", "import { realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { InputSource } from \"@earendil-works/pi-coding-agent\";\n\nexport interface AvailableSkill {\n\tname: string;\n\tfilePath: string;\n}\n\nexport interface PendingExplicitSkill {\n\tname: string;\n\tobservedAtMs: number;\n\tsource: \"interactive\" | \"rpc\";\n}\n\nexport function explicitSkillName(text: string): string | undefined {\n\treturn text.match(/^\\/skill:([a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?)(?:\\s|$)/u)?.[1];\n}\n\nexport class SkillTracker {\n\tprivate pending: PendingExplicitSkill | undefined;\n\tprivate readonly skillByPath = new Map<string, string>();\n\tprivate readonly availableNames = new Set<string>();\n\n\tconstructor(\n\t\tprivate readonly cwd: string,\n\t\tprivate readonly canonicalize: (filePath: string) => Promise<string> = realpath,\n\t) {}\n\n\tobserveInput(text: string, source: InputSource, now: number): void {\n\t\tif (source === \"extension\") return;\n\t\tconst name = explicitSkillName(text);\n\t\tthis.pending = name ? { name, observedAtMs: now, source } : undefined;\n\t}\n\n\tconsumeExplicitSkill(): PendingExplicitSkill | undefined {\n\t\tconst pending = this.pending;\n\t\tthis.pending = undefined;\n\t\treturn pending;\n\t}\n\n\tclearPending(): void {\n\t\tthis.pending = undefined;\n\t}\n\n\thasAvailableSkill(name: string): boolean {\n\t\treturn this.availableNames.has(name);\n\t}\n\n\tasync setAvailableSkills(skills: readonly AvailableSkill[]): Promise<void> {\n\t\tthis.skillByPath.clear();\n\t\tthis.availableNames.clear();\n\t\tconst seenNames = new Set<string>();\n\t\tfor (const skill of skills) {\n\t\t\tif (seenNames.has(skill.name)) continue;\n\t\t\tseenNames.add(skill.name);\n\t\t\tthis.availableNames.add(skill.name);\n\t\t\tconst canonical = await this.canonicalize(skill.filePath).catch(() =>\n\t\t\t\tpath.resolve(this.cwd, skill.filePath),\n\t\t\t);\n\t\t\tthis.skillByPath.set(canonical, skill.name);\n\t\t}\n\t}\n\n\tasync matchSuccessfulRead(input: {\n\t\ttoolName: string;\n\t\tinput: unknown;\n\t\tisError: boolean;\n\t}): Promise<string | undefined> {\n\t\tif (input.toolName !== \"read\" || input.isError || !isRecord(input.input)) return undefined;\n\t\tconst rawPath = input.input.path;\n\t\tif (typeof rawPath !== \"string\" || rawPath.length === 0) return undefined;\n\t\tconst normalized = rawPath.startsWith(\"@\") ? rawPath.slice(1) : rawPath;\n\t\tconst absolute = path.resolve(this.cwd, normalized);\n\t\tconst canonical = await this.canonicalize(absolute).catch(() => absolute);\n\t\treturn this.skillByPath.get(canonical);\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n", "import { randomUUID } from \"node:crypto\";\nimport { createReadStream, type Dirent } from \"node:fs\";\nimport {\n\tchmod,\n\tlstat,\n\tmkdir,\n\topen,\n\treaddir,\n\treadFile,\n\trename,\n\trm,\n\trmdir,\n\tunlink,\n\twriteFile,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { SettledRun } from \"../types.js\";\nimport {\n\tAnalyticsStorageFormatError,\n\tdecodeStoredRun,\n\tencodeStoredRun,\n\tMAX_STORED_RUN_BYTES,\n} from \"./format.js\";\n\nconst GENERATION_PATTERN =\n\t/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;\nconst DEFAULT_WRITE_TIMEOUT_MS = 5_000;\nconst YIELD_EVERY_RECORDS = 100;\n\nexport interface ClearAnalyticsResult {\n\tcleanupIncomplete: boolean;\n}\n\nexport class AnalyticsGenerationChangedError extends Error {\n\tconstructor() {\n\t\tsuper(\"The active analytics generation changed during the read.\");\n\t\tthis.name = \"AnalyticsGenerationChangedError\";\n\t}\n}\n\nexport class AnalyticsRunFiles {\n\tprivate readonly createId: () => string;\n\tprivate readonly writeTimeoutMs: number;\n\tprivate readonly beforeAppend?: (generation: string, signal: AbortSignal) => Promise<void>;\n\tprivate readonly beforeCleanupEntry?: (signal?: AbortSignal) => Promise<void>;\n\tprivate readonly beforeReadFile?: (signal?: AbortSignal) => Promise<void>;\n\tprivate writerId: string;\n\tprivate mutationTail: Promise<void> = Promise.resolve();\n\tprivate readonly lifecycle = new AbortController();\n\tprivate closed = false;\n\n\tconstructor(\n\t\treadonly path: string,\n\t\toptions: {\n\t\t\tcreateId?: () => string;\n\t\t\twriteTimeoutMs?: number;\n\t\t\tbeforeAppend?: (generation: string, signal: AbortSignal) => Promise<void>;\n\t\t\tbeforeCleanupEntry?: (signal?: AbortSignal) => Promise<void>;\n\t\t\tbeforeReadFile?: (signal?: AbortSignal) => Promise<void>;\n\t\t} = {},\n\t) {\n\t\tthis.createId = options.createId ?? randomUUID;\n\t\tthis.writeTimeoutMs = options.writeTimeoutMs ?? DEFAULT_WRITE_TIMEOUT_MS;\n\t\tthis.beforeAppend = options.beforeAppend;\n\t\tthis.beforeCleanupEntry = options.beforeCleanupEntry;\n\t\tthis.beforeReadFile = options.beforeReadFile;\n\t\tthis.writerId = validCreatedId(this.createId());\n\t}\n\n\tappend(run: SettledRun, signal?: AbortSignal): Promise<void> {\n\t\tif (this.closed) return Promise.reject(new Error(\"Analytics storage is closed.\"));\n\t\tconst frame = encodeStoredRun(run);\n\t\treturn this.enqueueMutation(() =>\n\t\t\twithDeadline(signal, this.lifecycle.signal, this.writeTimeoutMs, (operationSignal) =>\n\t\t\t\tthis.appendFrame(frame, operationSignal),\n\t\t\t),\n\t\t);\n\t}\n\n\tasync *read(signal?: AbortSignal): AsyncIterable<SettledRun> {\n\t\tthrowIfAborted(signal);\n\t\tconst generation = await this.readOrCreateGeneration(signal);\n\t\tconst directory = this.generationPath(generation);\n\t\tlet entries: Dirent[];\n\t\ttry {\n\t\t\tentries = await readdir(directory, { withFileTypes: true });\n\t\t} catch (error) {\n\t\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\t\tawait this.assertGenerationUnchanged(generation, signal);\n\t\t\t\tthrow new AnalyticsGenerationChangedError();\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tlet count = 0;\n\t\tfor (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n\t\t\tthrowIfAborted(signal);\n\t\t\tif (!entry.name.endsWith(\".jsonl\")) continue;\n\t\t\tconst filePath = path.join(directory, entry.name);\n\t\t\ttry {\n\t\t\t\tawait this.beforeReadFile?.(signal);\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tawait assertPrivateRegularFile(filePath);\n\t\t\t\tfor await (const run of readFrames(filePath, signal)) {\n\t\t\t\t\tyield run;\n\t\t\t\t\tcount += 1;\n\t\t\t\t\tif (count % YIELD_EVERY_RECORDS === 0) await yieldToEventLoop(signal);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\t\t\tawait this.assertGenerationUnchanged(generation, signal);\n\t\t\t\t\tthrow new AnalyticsGenerationChangedError();\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tawait this.assertGenerationUnchanged(generation, signal);\n\t}\n\n\tclear(signal?: AbortSignal): Promise<ClearAnalyticsResult> {\n\t\tif (this.closed) return Promise.reject(new Error(\"Analytics storage is closed.\"));\n\t\tlet result: ClearAnalyticsResult = { cleanupIncomplete: false };\n\t\treturn this.enqueueMutation(() =>\n\t\t\twithLinkedSignals(signal, this.lifecycle.signal, async (operationSignal) => {\n\t\t\t\tthrowIfAborted(operationSignal);\n\t\t\t\tawait this.readOrCreateGeneration(operationSignal);\n\t\t\t\tconst next = validCreatedId(this.createId());\n\t\t\t\tawait this.publishGeneration(next);\n\t\t\t\tthis.writerId = validCreatedId(this.createId());\n\t\t\t\tconst current = await readGenerationMarker(path.join(this.path, \"current\"));\n\t\t\t\tawait ensurePrivateDirectory(this.generationPath(current));\n\t\t\t\tif (!(await this.cleanupObsoleteGenerations(operationSignal))) {\n\t\t\t\t\tresult = { cleanupIncomplete: true };\n\t\t\t\t}\n\t\t\t}),\n\t\t).then(() => result);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.lifecycle.abort(new DOMException(\"Analytics storage closed\", \"AbortError\"));\n\t\tawait this.mutationTail.catch(() => undefined);\n\t}\n\n\tprivate enqueueMutation(operation: () => Promise<void>): Promise<void> {\n\t\tconst result = this.mutationTail.then(operation);\n\t\tthis.mutationTail = result.catch(() => undefined);\n\t\treturn result;\n\t}\n\n\tprivate async appendFrame(frame: string, signal: AbortSignal): Promise<void> {\n\t\tthrowIfAborted(signal);\n\t\tlet obsoleteDirectory: string | undefined;\n\t\tfor (let attempt = 0; attempt < 3; attempt += 1) {\n\t\t\tconst generation = await this.readOrCreateGeneration(signal);\n\t\t\tconst directory = this.generationPath(generation);\n\t\t\tawait ensurePrivateDirectory(directory);\n\t\t\tconst filePath = path.join(directory, `${this.writerId}.jsonl`);\n\t\t\tawait assertOptionalPrivateRegularFile(filePath);\n\t\t\tthrowIfAborted(signal);\n\t\t\tawait this.beforeAppend?.(generation, signal);\n\t\t\tthrowIfAborted(signal);\n\t\t\ttry {\n\t\t\t\tawait writeFile(filePath, frame, {\n\t\t\t\t\tencoding: \"utf8\",\n\t\t\t\t\tflag: \"a\",\n\t\t\t\t\tmode: 0o600,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\tif (process.platform !== \"win32\") await chmod(filePath, 0o600);\n\t\t\t\tconst current = await readGenerationMarker(path.join(this.path, \"current\"), signal);\n\t\t\t\tif (current === generation) {\n\t\t\t\t\tif (obsoleteDirectory) {\n\t\t\t\t\t\tawait cleanupGeneration(obsoleteDirectory, signal).catch(() => undefined);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tobsoleteDirectory = directory;\n\t\t\t} catch (error) {\n\t\t\t\tthis.writerId = validCreatedId(this.createId());\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tif (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n\t\t\t}\n\t\t}\n\t\tthrow new AnalyticsGenerationChangedError();\n\t}\n\n\tprivate async readOrCreateGeneration(signal?: AbortSignal): Promise<string> {\n\t\tthrowIfAborted(signal);\n\t\tawait ensurePrivateDirectory(this.path);\n\t\tawait ensurePrivateDirectory(path.join(this.path, \"generations\"));\n\t\tconst markerPath = path.join(this.path, \"current\");\n\t\tfor (let attempt = 0; attempt < 3; attempt += 1) {\n\t\t\tlet generation: string;\n\t\t\ttry {\n\t\t\t\tgeneration = await readGenerationMarker(markerPath, signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n\t\t\t\tgeneration = validCreatedId(this.createId());\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\ttry {\n\t\t\t\t\tawait createPrivateFile(markerPath, `${generation}\\n`);\n\t\t\t\t} catch (createError) {\n\t\t\t\t\tif (!isNodeError(createError) || createError.code !== \"EEXIST\") throw createError;\n\t\t\t\t\tgeneration = await readGenerationMarker(markerPath, signal);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait ensurePrivateDirectory(this.generationPath(generation));\n\t\t\tconst current = await readGenerationMarker(markerPath, signal);\n\t\t\tif (current === generation) return generation;\n\t\t}\n\t\tthrow new AnalyticsGenerationChangedError();\n\t}\n\n\tprivate async publishGeneration(generation: string): Promise<void> {\n\t\tconst markerPath = path.join(this.path, \"current\");\n\t\tconst temporaryPath = path.join(this.path, `.current.${validCreatedId(this.createId())}.tmp`);\n\t\tawait createPrivateFile(temporaryPath, `${generation}\\n`);\n\t\ttry {\n\t\t\tawait rename(temporaryPath, markerPath);\n\t\t\tif (process.platform !== \"win32\") await chmod(markerPath, 0o600);\n\t\t} catch (error) {\n\t\t\tawait rm(temporaryPath, { force: true }).catch(() => undefined);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async cleanupObsoleteGenerations(signal?: AbortSignal): Promise<boolean> {\n\t\tlet complete = true;\n\t\tconst root = path.join(this.path, \"generations\");\n\t\tfor (const entry of await readdir(root, { withFileTypes: true })) {\n\t\t\tconst active = await readGenerationMarker(path.join(this.path, \"current\"));\n\t\t\tif (entry.name === active) continue;\n\t\t\tif (!entry.isDirectory() || !GENERATION_PATTERN.test(entry.name)) {\n\t\t\t\tcomplete = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait cleanupGeneration(path.join(root, entry.name), signal, this.beforeCleanupEntry);\n\t\t\t} catch {\n\t\t\t\tcomplete = false;\n\t\t\t\tif (signal?.aborted) break;\n\t\t\t}\n\t\t}\n\t\tconst active = await readGenerationMarker(path.join(this.path, \"current\"));\n\t\tconst remaining = await readdir(root, { withFileTypes: true });\n\t\treturn complete && remaining.every((entry) => entry.isDirectory() && entry.name === active);\n\t}\n\n\tprivate async assertGenerationUnchanged(generation: string, signal?: AbortSignal): Promise<void> {\n\t\tconst current = await readGenerationMarker(path.join(this.path, \"current\"), signal);\n\t\tif (current !== generation) throw new AnalyticsGenerationChangedError();\n\t}\n\n\tprivate generationPath(generation: string): string {\n\t\treturn path.join(this.path, \"generations\", generation);\n\t}\n}\n\nasync function* readFrames(filePath: string, signal?: AbortSignal): AsyncIterable<SettledRun> {\n\tlet pending = \"\";\n\tconst stream = createReadStream(filePath, { encoding: \"utf8\", signal });\n\tfor await (const chunk of stream) {\n\t\tthrowIfAborted(signal);\n\t\tpending += String(chunk);\n\t\twhile (true) {\n\t\t\tconst newline = pending.indexOf(\"\\n\");\n\t\t\tif (newline < 0) break;\n\t\t\tconst line = pending.slice(0, newline);\n\t\t\tpending = pending.slice(newline + 1);\n\t\t\tif (!line) continue;\n\t\t\tyield decodeStoredRun(line);\n\t\t}\n\t\tif (Buffer.byteLength(pending) > MAX_STORED_RUN_BYTES) {\n\t\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to read safely.\");\n\t\t}\n\t}\n\t// A writer always terminates complete frames with a newline. An unterminated tail is a\n\t// crash residue and is ignored; this writer file will not be reused after its process exits.\n}\n\nasync function readGenerationMarker(markerPath: string, signal?: AbortSignal): Promise<string> {\n\tawait assertPrivateRegularFile(markerPath);\n\tthrowIfAborted(signal);\n\tconst value = (await readFile(markerPath, { encoding: \"utf8\", signal })).trim();\n\tif (!GENERATION_PATTERN.test(value)) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics generation marker is invalid.\");\n\t}\n\treturn value;\n}\n\nasync function ensurePrivateDirectory(directoryPath: string): Promise<void> {\n\ttry {\n\t\tconst metadata = await lstat(directoryPath);\n\t\tif (!metadata.isDirectory() || metadata.isSymbolicLink()) {\n\t\t\tthrow new Error(\"Analytics storage paths must be regular directories, not links.\");\n\t\t}\n\t} catch (error) {\n\t\tif (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n\t\tawait mkdir(directoryPath, { recursive: true, mode: 0o700 });\n\t\tconst metadata = await lstat(directoryPath);\n\t\tif (!metadata.isDirectory() || metadata.isSymbolicLink()) {\n\t\t\tthrow new Error(\"Analytics storage paths must be regular directories, not links.\");\n\t\t}\n\t}\n\tif (process.platform !== \"win32\") await chmod(directoryPath, 0o700);\n}\n\nasync function assertOptionalPrivateRegularFile(filePath: string): Promise<void> {\n\ttry {\n\t\tawait assertPrivateRegularFile(filePath);\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") return;\n\t\tthrow error;\n\t}\n}\n\nasync function assertPrivateRegularFile(filePath: string): Promise<void> {\n\tconst metadata = await lstat(filePath);\n\tif (!metadata.isFile() || metadata.isSymbolicLink()) {\n\t\tthrow new Error(\"Analytics storage files must be regular files, not links.\");\n\t}\n\tif (process.platform !== \"win32\") await chmod(filePath, 0o600);\n}\n\nasync function createPrivateFile(filePath: string, content: string): Promise<void> {\n\tconst handle = await open(filePath, \"wx\", 0o600);\n\ttry {\n\t\tawait handle.writeFile(content, \"utf8\");\n\t\tawait handle.sync();\n\t} finally {\n\t\tawait handle.close();\n\t}\n}\n\nasync function cleanupGeneration(\n\tdirectoryPath: string,\n\tsignal?: AbortSignal,\n\tbeforeEntry?: (signal?: AbortSignal) => Promise<void>,\n): Promise<void> {\n\tthrowIfAborted(signal);\n\tlet entries: Dirent[];\n\ttry {\n\t\tentries = await readdir(directoryPath, { withFileTypes: true });\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") return;\n\t\tthrow error;\n\t}\n\tfor (const entry of entries) {\n\t\tthrowIfAborted(signal);\n\t\tawait beforeEntry?.(signal);\n\t\tthrowIfAborted(signal);\n\t\tif (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n\t\t\tthrow new Error(\"Analytics generation contains an unexpected storage entry.\");\n\t\t}\n\t\tawait unlink(path.join(directoryPath, entry.name));\n\t}\n\tthrowIfAborted(signal);\n\tawait rmdir(directoryPath);\n}\n\nasync function withLinkedSignals<T>(\n\tcallerSignal: AbortSignal | undefined,\n\tlifecycleSignal: AbortSignal,\n\toperation: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n\tthrowIfAborted(callerSignal);\n\tthrowIfAborted(lifecycleSignal);\n\tconst controller = new AbortController();\n\tconst abort = (signal: AbortSignal) =>\n\t\tcontroller.abort(\n\t\t\tsignal.reason ?? new DOMException(\"Analytics operation aborted\", \"AbortError\"),\n\t\t);\n\tconst callerAbort = () => callerSignal && abort(callerSignal);\n\tconst lifecycleAbort = () => abort(lifecycleSignal);\n\tcallerSignal?.addEventListener(\"abort\", callerAbort, { once: true });\n\tlifecycleSignal.addEventListener(\"abort\", lifecycleAbort, { once: true });\n\ttry {\n\t\treturn await operation(controller.signal);\n\t} finally {\n\t\tcallerSignal?.removeEventListener(\"abort\", callerAbort);\n\t\tlifecycleSignal.removeEventListener(\"abort\", lifecycleAbort);\n\t}\n}\n\nasync function withDeadline<T>(\n\tcallerSignal: AbortSignal | undefined,\n\tlifecycleSignal: AbortSignal,\n\ttimeoutMs: number,\n\toperation: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n\tthrowIfAborted(callerSignal);\n\tthrowIfAborted(lifecycleSignal);\n\tconst controller = new AbortController();\n\tconst abort = (signal: AbortSignal) =>\n\t\tcontroller.abort(\n\t\t\tsignal.reason ?? new DOMException(\"Analytics operation aborted\", \"AbortError\"),\n\t\t);\n\tconst callerAbort = () => callerSignal && abort(callerSignal);\n\tconst lifecycleAbort = () => abort(lifecycleSignal);\n\tcallerSignal?.addEventListener(\"abort\", callerAbort, { once: true });\n\tlifecycleSignal.addEventListener(\"abort\", lifecycleAbort, { once: true });\n\tconst timer = setTimeout(\n\t\t() => controller.abort(new DOMException(\"Analytics write timed out\", \"TimeoutError\")),\n\t\tMath.max(1, timeoutMs),\n\t);\n\ttry {\n\t\treturn await operation(controller.signal);\n\t} catch (error) {\n\t\tif (\n\t\t\tcontroller.signal.aborted &&\n\t\t\terror instanceof Error &&\n\t\t\terror.name === \"AbortError\" &&\n\t\t\terror.cause === controller.signal.reason\n\t\t) {\n\t\t\tthrow controller.signal.reason;\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tclearTimeout(timer);\n\t\tcallerSignal?.removeEventListener(\"abort\", callerAbort);\n\t\tlifecycleSignal.removeEventListener(\"abort\", lifecycleAbort);\n\t}\n}\n\nasync function yieldToEventLoop(signal?: AbortSignal): Promise<void> {\n\tawait new Promise<void>((resolve) => setImmediate(resolve));\n\tthrowIfAborted(signal);\n}\n\nfunction validCreatedId(value: string): string {\n\tif (!GENERATION_PATTERN.test(value)) throw new Error(\"Analytics storage received an invalid ID.\");\n\treturn value;\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n\tif (signal?.aborted) {\n\t\tthrow signal.reason ?? new DOMException(\"Analytics operation aborted\", \"AbortError\");\n\t}\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n", "import type {\n\tGenerationOutcome,\n\tGenerationRecord,\n\tProviderErrorCategory,\n\tProviderErrorRecord,\n\tProviderResponseRecord,\n\tRunOutcome,\n\tSettledRun,\n\tSkillActivationRecord,\n\tToolCallRecord,\n} from \"../types.js\";\n\nexport const MAX_STORED_RUN_BYTES = 1024 * 1024;\nconst MAX_STRING_LENGTH = 4096;\nconst MAX_NESTED_RECORDS = 20_000;\nconst TRIGGER_SOURCES = [\"interactive\", \"rpc\", \"extension\", \"unknown\"] as const;\nconst RUN_OUTCOMES = [\n\t\"success\",\n\t\"recovered_success\",\n\t\"error\",\n\t\"aborted\",\n\t\"length\",\n\t\"interrupted\",\n] as const;\nconst GENERATION_OUTCOMES = [\n\t\"pending\",\n\t\"stop\",\n\t\"tool_use\",\n\t\"error\",\n\t\"aborted\",\n\t\"length\",\n\t\"interrupted\",\n] as const;\nconst ERROR_CATEGORIES = [\n\t\"dns\",\n\t\"timeout\",\n\t\"connection_refused\",\n\t\"connection_reset\",\n\t\"tls\",\n\t\"network_other\",\n\t\"provider_other\",\n] as const;\n\nexport class AnalyticsStorageFormatError extends Error {\n\tconstructor(message: string, options: { cause?: unknown } = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = \"AnalyticsStorageFormatError\";\n\t}\n}\n\nexport function encodeStoredRun(run: SettledRun): string {\n\tconst encoded = `${JSON.stringify({\n\t\tformatVersion: 1,\n\t\trun: parseRun(run, { remaining: MAX_NESTED_RECORDS }),\n\t})}\\n`;\n\tif (Buffer.byteLength(encoded) > MAX_STORED_RUN_BYTES) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to store safely.\");\n\t}\n\treturn encoded;\n}\n\nexport function decodeStoredRun(line: string): SettledRun {\n\tif (Buffer.byteLength(line) > MAX_STORED_RUN_BYTES) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to read safely.\");\n\t}\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(line);\n\t} catch (error) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record contains invalid JSON.\", {\n\t\t\tcause: error,\n\t\t});\n\t}\n\tconst envelope = asRecord(value, \"analytics record\");\n\tif (envelope.formatVersion !== 1) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record uses an unsupported format version.\");\n\t}\n\treturn parseRun(envelope.run, { remaining: MAX_NESTED_RECORDS });\n}\n\ninterface ParseBudget {\n\tremaining: number;\n}\n\nfunction parseRun(value: unknown, budget: ParseBudget): SettledRun {\n\tconst run = asRecord(value, \"run\");\n\treturn {\n\t\tid: requiredString(run.id, \"run.id\"),\n\t\tstartedAtMs: timestampValue(run.startedAtMs, \"run.startedAtMs\"),\n\t\tfinishedAtMs: timestampValue(run.finishedAtMs, \"run.finishedAtMs\"),\n\t\tdurationMs: durationValue(run.durationMs, \"run.durationMs\"),\n\t\ttriggerSource: enumValue(run.triggerSource, TRIGGER_SOURCES, \"run.triggerSource\"),\n\t\t...optionalProperty(\n\t\t\t\"initialProvider\",\n\t\t\toptionalString(run.initialProvider, \"run.initialProvider\"),\n\t\t),\n\t\t...optionalProperty(\"initialModel\", optionalString(run.initialModel, \"run.initialModel\")),\n\t\toutcome: enumValue(run.outcome, RUN_OUTCOMES, \"run.outcome\") as RunOutcome,\n\t\tattemptCount: boundedCount(run.attemptCount, \"run.attemptCount\"),\n\t\tgenerations: boundedArray(run.generations, \"run.generations\", budget).map((item, index) =>\n\t\t\tparseGeneration(item, index, budget),\n\t\t),\n\t\ttools: boundedArray(run.tools, \"run.tools\", budget).map(parseTool),\n\t\tskills: boundedArray(run.skills, \"run.skills\", budget).map(parseSkill),\n\t\tproviderErrors: boundedArray(run.providerErrors, \"run.providerErrors\", budget).map(\n\t\t\tparseProviderError,\n\t\t),\n\t\ttoolErrorCount: boundedCount(run.toolErrorCount, \"run.toolErrorCount\"),\n\t\tproviderErrorCount: boundedCount(run.providerErrorCount, \"run.providerErrorCount\"),\n\t\trecoveredErrorCount: boundedCount(run.recoveredErrorCount, \"run.recoveredErrorCount\"),\n\t};\n}\n\nfunction parseGeneration(value: unknown, index: number, budget: ParseBudget): GenerationRecord {\n\tconst item = asRecord(value, `run.generations[${index}]`);\n\tconst prefix = `run.generations[${index}]`;\n\treturn {\n\t\tid: requiredString(item.id, `${prefix}.id`),\n\t\tordinal: boundedCount(item.ordinal, `${prefix}.ordinal`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t\t...optionalProperty(\n\t\t\t\"thinkingLevel\",\n\t\t\toptionalString(item.thinkingLevel, `${prefix}.thinkingLevel`),\n\t\t),\n\t\tstartedAtMs: timestampValue(item.startedAtMs, `${prefix}.startedAtMs`),\n\t\t...optionalProperty(\n\t\t\t\"finishedAtMs\",\n\t\t\toptionalTimestamp(item.finishedAtMs, `${prefix}.finishedAtMs`),\n\t\t),\n\t\t...optionalProperty(\"durationMs\", optionalDuration(item.durationMs, `${prefix}.durationMs`)),\n\t\t...optionalProperty(\"stopReason\", optionalString(item.stopReason, `${prefix}.stopReason`)),\n\t\toutcome: enumValue(item.outcome, GENERATION_OUTCOMES, `${prefix}.outcome`) as GenerationOutcome,\n\t\tresponses: boundedArray(item.responses, `${prefix}.responses`, budget).map(\n\t\t\tparseProviderResponse,\n\t\t),\n\t};\n}\n\nfunction parseProviderResponse(value: unknown, index: number): ProviderResponseRecord {\n\tconst item = asRecord(value, `provider response ${index}`);\n\treturn {\n\t\tordinal: boundedCount(item.ordinal, \"providerResponse.ordinal\"),\n\t\toccurredAtMs: timestampValue(item.occurredAtMs, \"providerResponse.occurredAtMs\"),\n\t\tstatus: boundedInteger(item.status, \"providerResponse.status\", 999),\n\t};\n}\n\nfunction parseTool(value: unknown, index: number): ToolCallRecord {\n\tconst item = asRecord(value, `run.tools[${index}]`);\n\tconst prefix = `run.tools[${index}]`;\n\tconst ordinal = boundedCount(item.ordinal, `${prefix}.ordinal`);\n\treturn {\n\t\tid: `tool-${ordinal}`,\n\t\tordinal,\n\t\tname: requiredString(item.name, `${prefix}.name`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t\tstartedAtMs: timestampValue(item.startedAtMs, `${prefix}.startedAtMs`),\n\t\t...optionalProperty(\n\t\t\t\"finishedAtMs\",\n\t\t\toptionalTimestamp(item.finishedAtMs, `${prefix}.finishedAtMs`),\n\t\t),\n\t\t...optionalProperty(\"durationMs\", optionalDuration(item.durationMs, `${prefix}.durationMs`)),\n\t\tisError: booleanValue(item.isError, `${prefix}.isError`),\n\t\tcompletionState: enumValue(\n\t\t\titem.completionState,\n\t\t\t[\"running\", \"finished\", \"interrupted\"] as const,\n\t\t\t`${prefix}.completionState`,\n\t\t),\n\t};\n}\n\nfunction parseSkill(value: unknown, index: number): SkillActivationRecord {\n\tconst item = asRecord(value, `run.skills[${index}]`);\n\tconst prefix = `run.skills[${index}]`;\n\treturn {\n\t\tid: requiredString(item.id, `${prefix}.id`),\n\t\tname: requiredString(item.name, `${prefix}.name`),\n\t\tinitiatedBy: enumValue(item.initiatedBy, [\"user\", \"model\"] as const, `${prefix}.initiatedBy`),\n\t\toccurredAtMs: timestampValue(item.occurredAtMs, `${prefix}.occurredAtMs`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t};\n}\n\nfunction parseProviderError(value: unknown, index: number): ProviderErrorRecord {\n\tconst item = asRecord(value, `run.providerErrors[${index}]`);\n\tconst prefix = `run.providerErrors[${index}]`;\n\treturn {\n\t\tid: requiredString(item.id, `${prefix}.id`),\n\t\t...optionalProperty(\n\t\t\t\"generationId\",\n\t\t\toptionalString(item.generationId, `${prefix}.generationId`),\n\t\t),\n\t\toccurredAtMs: timestampValue(item.occurredAtMs, `${prefix}.occurredAtMs`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t\tcategory: enumValue(\n\t\t\titem.category,\n\t\t\tERROR_CATEGORIES,\n\t\t\t`${prefix}.category`,\n\t\t) as ProviderErrorCategory,\n\t\trecovered: booleanValue(item.recovered, `${prefix}.recovered`),\n\t\tterminal: booleanValue(item.terminal, `${prefix}.terminal`),\n\t};\n}\n\nfunction asRecord(value: unknown, name: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) invalid(name);\n\treturn value as Record<string, unknown>;\n}\n\nfunction boundedArray(value: unknown, name: string, budget: ParseBudget): unknown[] {\n\tif (!Array.isArray(value)) invalid(name);\n\tbudget.remaining -= value.length;\n\tif (budget.remaining < 0) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to process safely.\");\n\t}\n\treturn value;\n}\n\nfunction requiredString(value: unknown, name: string): string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > MAX_STRING_LENGTH) {\n\t\tinvalid(name);\n\t}\n\treturn value;\n}\n\nfunction optionalString(value: unknown, name: string): string | undefined {\n\treturn value === undefined ? undefined : requiredString(value, name);\n}\n\nfunction boundedInteger(value: unknown, name: string, maximum: number): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0 || value > maximum) {\n\t\tinvalid(name);\n\t}\n\treturn value;\n}\n\nfunction timestampValue(value: unknown, name: string): number {\n\treturn boundedInteger(value, name, Number.MAX_SAFE_INTEGER);\n}\n\nfunction optionalTimestamp(value: unknown, name: string): number | undefined {\n\treturn value === undefined ? undefined : timestampValue(value, name);\n}\n\nfunction durationValue(value: unknown, name: string): number {\n\treturn boundedInteger(value, name, Math.floor(Number.MAX_SAFE_INTEGER / MAX_NESTED_RECORDS));\n}\n\nfunction optionalDuration(value: unknown, name: string): number | undefined {\n\treturn value === undefined ? undefined : durationValue(value, name);\n}\n\nfunction boundedCount(value: unknown, name: string): number {\n\treturn boundedInteger(value, name, MAX_NESTED_RECORDS);\n}\n\nfunction booleanValue(value: unknown, name: string): boolean {\n\tif (typeof value !== \"boolean\") invalid(name);\n\treturn value;\n}\n\nfunction enumValue<const T extends readonly string[]>(\n\tvalue: unknown,\n\tvalues: T,\n\tname: string,\n): T[number] {\n\tif (typeof value !== \"string\" || !values.includes(value)) invalid(name);\n\treturn value as T[number];\n}\n\nfunction optionalProperty<K extends string, T>(key: K, value: T | undefined): { [P in K]?: T } {\n\treturn value === undefined ? {} : ({ [key]: value } as { [P in K]?: T });\n}\n\nfunction invalid(name: string): never {\n\tthrow new AnalyticsStorageFormatError(`Analytics record has an invalid ${name}.`);\n}\n", "import type { SettledRun } from \"../types.js\";\nimport {\n\tAnalyticsGenerationChangedError,\n\tAnalyticsRunFiles,\n\ttype ClearAnalyticsResult,\n} from \"./files.js\";\nimport { type AnalyticsSnapshot, querySnapshot, type TimeRange } from \"./queries.js\";\n\nexport class AnalyticsStore {\n\tprivate readonly files: AnalyticsRunFiles;\n\n\tconstructor(\n\t\trootPath: string,\n\t\tdependencies: {\n\t\t\tfiles?: AnalyticsRunFiles;\n\t\t\tcreateId?: () => string;\n\t\t\twriteTimeoutMs?: number;\n\t\t} = {},\n\t) {\n\t\tthis.files =\n\t\t\tdependencies.files ??\n\t\t\tnew AnalyticsRunFiles(rootPath, {\n\t\t\t\tcreateId: dependencies.createId,\n\t\t\t\twriteTimeoutMs: dependencies.writeTimeoutMs,\n\t\t\t});\n\t}\n\n\tget path(): string {\n\t\treturn this.files.path;\n\t}\n\n\trecordRun(run: SettledRun, signal?: AbortSignal): Promise<void> {\n\t\treturn this.files.append(run, signal);\n\t}\n\n\tasync getSnapshot(range: TimeRange, signal?: AbortSignal): Promise<AnalyticsSnapshot> {\n\t\tfor (let attempt = 0; attempt < 2; attempt += 1) {\n\t\t\ttry {\n\t\t\t\treturn await querySnapshot(this.files.read(signal), range, signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof AnalyticsGenerationChangedError) || attempt > 0) throw error;\n\t\t\t}\n\t\t}\n\t\tthrow new AnalyticsGenerationChangedError();\n\t}\n\n\tclearAll(signal?: AbortSignal): Promise<ClearAnalyticsResult> {\n\t\treturn this.files.clear(signal);\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.files.close();\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\tgetAgentDir,\n} from \"@earendil-works/pi-coding-agent\";\nimport { ResponseCollector } from \"./collector.js\";\nimport { type AnalyticsMenuDataSource, showAnalyticsMenu } from \"./menu.js\";\nimport { SkillTracker } from \"./skills.js\";\nimport type { ClearAnalyticsResult } from \"./storage/files.js\";\nimport type { AnalyticsSnapshot, TimeRange } from \"./storage/queries.js\";\nimport { AnalyticsStore } from \"./storage/store.js\";\nimport type { ModelIdentity, SettledRun, TriggerSource } from \"./types.js\";\n\nconst STORAGE_DIRECTORY = \"pi-analytics\";\n\nexport interface AnalyticsStorePort {\n\treadonly path: string;\n\trecordRun(run: SettledRun, signal?: AbortSignal): Promise<void>;\n\tgetSnapshot(range: TimeRange, signal?: AbortSignal): Promise<AnalyticsSnapshot>;\n\tclearAll(signal?: AbortSignal): Promise<ClearAnalyticsResult>;\n\tclose(): Promise<void>;\n}\n\ninterface AnalyticsDependencies {\n\tcreateStore(path: string): AnalyticsStorePort;\n\tcreateSkillTracker(cwd: string): SkillTracker;\n\tgetAgentDir(): string;\n\tnow(): number;\n\tcreateId(): string;\n}\n\nexport function createAnalyticsExtension(\n\tdependencies: Partial<AnalyticsDependencies> = {},\n): (pi: ExtensionAPI) => void {\n\tconst deps: AnalyticsDependencies = {\n\t\tcreateStore: dependencies.createStore ?? ((rootPath) => new AnalyticsStore(rootPath)),\n\t\tcreateSkillTracker: dependencies.createSkillTracker ?? ((cwd) => new SkillTracker(cwd)),\n\t\tgetAgentDir: dependencies.getAgentDir ?? getAgentDir,\n\t\tnow: dependencies.now ?? Date.now,\n\t\tcreateId: dependencies.createId ?? randomUUID,\n\t};\n\n\treturn function analyticsExtension(pi: ExtensionAPI): void {\n\t\tlet sessionGeneration = 0;\n\t\tlet sessionController = new AbortController();\n\t\tlet collector = new ResponseCollector();\n\t\tlet skillTracker: SkillTracker | undefined;\n\t\tlet store: AnalyticsStorePort | undefined;\n\t\tlet storageFailure: string | undefined;\n\t\tconst retiredCloseTasks = new Set<Promise<boolean>>();\n\t\tlet writeFailureActive = false;\n\t\tlet pendingTriggerSource: TriggerSource = \"unknown\";\n\t\tlet pendingAttemptWithoutRun = false;\n\n\t\tpi.registerCommand(\"analytics\", {\n\t\t\tdescription: \"Open local Pi usage analytics\",\n\t\t\thandler: async (args, ctx) => {\n\t\t\t\tif (args.trim()) {\n\t\t\t\t\tif (!ctx.hasUI || (ctx.mode !== \"tui\" && ctx.mode !== \"rpc\")) {\n\t\t\t\t\t\tthrow new Error(\"/analytics does not accept arguments.\");\n\t\t\t\t\t}\n\t\t\t\t\tctx.ui.notify(\"/analytics does not accept arguments.\", \"warning\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!ctx.hasUI || (ctx.mode !== \"tui\" && ctx.mode !== \"rpc\")) {\n\t\t\t\t\tthrow new Error(\"/analytics requires Pi TUI or RPC mode.\");\n\t\t\t\t}\n\t\t\t\tconst generation = sessionGeneration;\n\t\t\t\tconst owner = sessionController;\n\t\t\t\tconst source = menuSource(generation, owner.signal);\n\t\t\t\tawait showAnalyticsMenu(ctx, source, {\n\t\t\t\t\tsignal: owner.signal,\n\t\t\t\t\tisCurrent: () => generation === sessionGeneration && !owner.signal.aborted,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tpi.on(\"session_start\", (_event, ctx) => {\n\t\t\t++sessionGeneration;\n\t\t\tconst previousStore = store;\n\t\t\tsessionController.abort(new DOMException(\"Analytics session replaced\", \"AbortError\"));\n\t\t\tif (previousStore) retire(previousStore);\n\t\t\tsessionController = new AbortController();\n\t\t\tcollector = new ResponseCollector();\n\t\t\tskillTracker = deps.createSkillTracker(ctx.cwd);\n\t\t\tstore = undefined;\n\t\t\tstorageFailure = undefined;\n\t\t\twriteFailureActive = false;\n\t\t\tpendingTriggerSource = \"unknown\";\n\t\t\tpendingAttemptWithoutRun = false;\n\t\t\tconst storageRoot = path.join(deps.getAgentDir(), STORAGE_DIRECTORY);\n\t\t\ttry {\n\t\t\t\tstore = deps.createStore(storageRoot);\n\t\t\t} catch {\n\t\t\t\tstorageFailure = unavailableMessage();\n\t\t\t\tsafeNotify(ctx, storageFailure, \"warning\");\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"input\", (event, ctx) => {\n\t\t\tconst now = deps.now();\n\t\t\tconst tracker = skillTracker;\n\t\t\ttracker?.observeInput(event.text, event.source, now);\n\t\t\tif (event.source !== \"extension\") pendingTriggerSource = event.source;\n\t\t\tif (!tracker || !collector.hasActiveRun()) return;\n\t\t\tconst explicit = tracker.consumeExplicitSkill();\n\t\t\tif (!explicit || !tracker.hasAvailableSkill(explicit.name)) return;\n\t\t\tcollector.activateSkill({\n\t\t\t\tname: explicit.name,\n\t\t\t\tinitiatedBy: \"user\",\n\t\t\t\tnow: explicit.observedAtMs,\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\t\tconst generation = sessionGeneration;\n\t\t\tconst tracker = skillTracker;\n\t\t\tconst activeCollector = collector;\n\t\t\tif (!tracker) return;\n\t\t\tconst skills = availableSkills(pi, event.systemPromptOptions.skills ?? []);\n\t\t\tawait tracker.setAvailableSkills(skills);\n\t\t\tif (\n\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\ttracker !== skillTracker ||\n\t\t\t\tactiveCollector !== collector\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst explicit = tracker.consumeExplicitSkill();\n\t\t\tconst interrupted = activeCollector.begin({\n\t\t\t\tid: deps.createId(),\n\t\t\t\tnow: deps.now(),\n\t\t\t\ttriggerSource: explicit?.source ?? pendingTriggerSource,\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t\tpendingTriggerSource = \"unknown\";\n\t\t\tif (interrupted) {\n\t\t\t\tawait persistRun(interrupted, ctx, generation, sessionController.signal);\n\t\t\t\tif (\n\t\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\t\ttracker !== skillTracker ||\n\t\t\t\t\tactiveCollector !== collector\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (explicit && skills.some(({ name }) => name === explicit.name)) {\n\t\t\t\tactiveCollector.activateSkill({\n\t\t\t\t\tname: explicit.name,\n\t\t\t\t\tinitiatedBy: \"user\",\n\t\t\t\t\tnow: explicit.observedAtMs,\n\t\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"agent_start\", () => {\n\t\t\tif (collector.hasActiveRun()) collector.beginAttempt();\n\t\t\telse pendingAttemptWithoutRun = true;\n\t\t});\n\n\t\tpi.on(\"turn_start\", (_event, ctx) => ensureRun(ctx, \"extension\"));\n\n\t\tpi.on(\"before_provider_request\", (_event, ctx) => {\n\t\t\tensureRun(ctx, \"extension\");\n\t\t\tcollector.beginGeneration({\n\t\t\t\tid: deps.createId(),\n\t\t\t\tnow: deps.now(),\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"after_provider_response\", (event) => {\n\t\t\tcollector.recordProviderResponse({ status: event.status, now: deps.now() });\n\t\t});\n\n\t\tpi.on(\"message_end\", (event) => {\n\t\t\tif (event.message.role !== \"assistant\") return;\n\t\t\tcollector.finishGeneration({\n\t\t\t\tnow: deps.now(),\n\t\t\t\tstopReason: event.message.stopReason,\n\t\t\t\terrorMessage: event.message.errorMessage,\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_execution_start\", (event, ctx) => {\n\t\t\tensureRun(ctx, \"extension\");\n\t\t\tcollector.beginTool({\n\t\t\t\tid: event.toolCallId,\n\t\t\t\tname: event.toolName,\n\t\t\t\tnow: deps.now(),\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\t\tif (event.toolName === \"read\" && !isBuiltinReadTool(pi)) return;\n\t\t\tconst generation = sessionGeneration;\n\t\t\tconst tracker = skillTracker;\n\t\t\tconst activeCollector = collector;\n\t\t\tconst runId = activeCollector.getActiveRunId();\n\t\t\tif (!tracker || !runId) return;\n\t\t\tconst name = await tracker.matchSuccessfulRead({\n\t\t\t\ttoolName: event.toolName,\n\t\t\t\tinput: event.input,\n\t\t\t\tisError: event.isError,\n\t\t\t});\n\t\t\tif (\n\t\t\t\t!name ||\n\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\ttracker !== skillTracker ||\n\t\t\t\tactiveCollector !== collector ||\n\t\t\t\tactiveCollector.getActiveRunId() !== runId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactiveCollector.activateSkill({\n\t\t\t\tname,\n\t\t\t\tinitiatedBy: \"model\",\n\t\t\t\tnow: deps.now(),\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_execution_end\", (event) => {\n\t\t\tcollector.finishTool({ id: event.toolCallId, now: deps.now(), isError: event.isError });\n\t\t});\n\n\t\tpi.on(\"agent_settled\", async (_event, ctx) => {\n\t\t\tconst generation = sessionGeneration;\n\t\t\tconst owner = sessionController;\n\t\t\tconst run = collector.settle(deps.now());\n\t\t\tpendingAttemptWithoutRun = false;\n\t\t\tpendingTriggerSource = \"unknown\";\n\t\t\tskillTracker?.clearPending();\n\t\t\tif (run) await persistRun(run, ctx, generation, owner.signal);\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tconst activeStore = store;\n\t\t\t++sessionGeneration;\n\t\t\tsessionController.abort(new DOMException(\"Analytics session shut down\", \"AbortError\"));\n\t\t\tskillTracker?.clearPending();\n\t\t\tskillTracker = undefined;\n\t\t\tstore = undefined;\n\t\t\tcollector.interrupt(deps.now());\n\t\t\tconst closing = activeStore\n\t\t\t\t? [closeResult(activeStore), ...retiredCloseTasks]\n\t\t\t\t: [...retiredCloseTasks];\n\t\t\tconst results = await Promise.all(closing);\n\t\t\tif (results.some((closed) => !closed)) {\n\t\t\t\tsafeNotify(ctx, \"Analytics storage shutdown was incomplete.\", \"warning\");\n\t\t\t}\n\t\t});\n\n\t\tfunction retire(retiredStore: AnalyticsStorePort): void {\n\t\t\tconst task = closeResult(retiredStore).finally(() => retiredCloseTasks.delete(task));\n\t\t\tretiredCloseTasks.add(task);\n\t\t}\n\n\t\tasync function closeResult(activeStore: AnalyticsStorePort): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tawait activeStore.close();\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfunction ensureRun(ctx: ExtensionContext, triggerSource: TriggerSource): void {\n\t\t\tif (collector.hasActiveRun()) return;\n\t\t\tcollector.begin({\n\t\t\t\tid: deps.createId(),\n\t\t\t\tnow: deps.now(),\n\t\t\t\ttriggerSource,\n\t\t\t\tmodel: modelIdentity(ctx, pi),\n\t\t\t});\n\t\t\tif (pendingAttemptWithoutRun) {\n\t\t\t\tpendingAttemptWithoutRun = false;\n\t\t\t\tcollector.beginAttempt();\n\t\t\t}\n\t\t}\n\n\t\tasync function persistRun(\n\t\t\trun: SettledRun,\n\t\t\tctx: ExtensionContext,\n\t\t\tgeneration: number,\n\t\t\tsignal: AbortSignal,\n\t\t): Promise<void> {\n\t\t\tconst activeStore = store;\n\t\t\tif (!activeStore || signal.aborted) return;\n\t\t\ttry {\n\t\t\t\tawait activeStore.recordRun(run, signal);\n\t\t\t\tif (generation !== sessionGeneration || activeStore !== store || signal.aborted) return;\n\t\t\t\tif (writeFailureActive) {\n\t\t\t\t\twriteFailureActive = false;\n\t\t\t\t\tsafeNotify(ctx, \"Local analytics storage recovered.\", \"info\");\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (\n\t\t\t\t\tgeneration !== sessionGeneration ||\n\t\t\t\t\tactiveStore !== store ||\n\t\t\t\t\tsignal.aborted ||\n\t\t\t\t\twriteFailureActive\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\twriteFailureActive = true;\n\t\t\t\tsafeNotify(\n\t\t\t\t\tctx,\n\t\t\t\t\t\"Analytics could not save this response cycle; its metrics were dropped.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tfunction menuSource(generation: number, signal: AbortSignal): AnalyticsMenuDataSource {\n\t\t\treturn {\n\t\t\t\tpath: store?.path ?? path.join(deps.getAgentDir(), STORAGE_DIRECTORY),\n\t\t\t\tasync load(range, actionSignal) {\n\t\t\t\t\tassertCurrent(generation, signal);\n\t\t\t\t\tconst activeStore = store;\n\t\t\t\t\tif (!activeStore) {\n\t\t\t\t\t\treturn { kind: \"unavailable\", message: storageFailure ?? unavailableMessage() };\n\t\t\t\t\t}\n\t\t\t\t\tconst snapshot = await activeStore.getSnapshot(range, actionSignal);\n\t\t\t\t\tassertCurrent(generation, signal);\n\t\t\t\t\treturn { kind: \"ready\", snapshot };\n\t\t\t\t},\n\t\t\t\tasync clearAll(actionSignal) {\n\t\t\t\t\tassertCurrent(generation, signal);\n\t\t\t\t\tconst activeStore = store;\n\t\t\t\t\tif (!activeStore) return { cleanupIncomplete: false };\n\t\t\t\t\treturn activeStore.clearAll(actionSignal);\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tfunction assertCurrent(generation: number, signal: AbortSignal): void {\n\t\t\tif (generation !== sessionGeneration || signal.aborted) {\n\t\t\t\tthrow new DOMException(\"Analytics interaction replaced\", \"AbortError\");\n\t\t\t}\n\t\t}\n\t};\n}\n\nfunction modelIdentity(ctx: ExtensionContext, pi: ExtensionAPI): ModelIdentity | undefined {\n\tif (!ctx.model) return undefined;\n\treturn {\n\t\tprovider: ctx.model.provider,\n\t\tmodel: ctx.model.id,\n\t\tthinkingLevel: pi.getThinkingLevel(),\n\t};\n}\n\nexport function isBuiltinReadTool(pi: ExtensionAPI): boolean {\n\tconst read = pi.getAllTools().find(({ name }) => name === \"read\");\n\treturn read?.sourceInfo.source === \"builtin\";\n}\n\nfunction availableSkills(\n\tpi: ExtensionAPI,\n\tsystemSkills: ReadonlyArray<{ name: string; filePath: string }>,\n): Array<{ name: string; filePath: string }> {\n\tconst result = [...systemSkills];\n\tconst seen = new Set(result.map(({ name }) => name));\n\tconst getCommands = (pi as ExtensionAPI & { getCommands?: ExtensionAPI[\"getCommands\"] })\n\t\t.getCommands;\n\tfor (const command of typeof getCommands === \"function\" ? getCommands.call(pi) : []) {\n\t\tif (command.source !== \"skill\" || seen.has(command.name.replace(/^skill:/u, \"\"))) continue;\n\t\tconst name = command.name.replace(/^skill:/u, \"\");\n\t\tseen.add(name);\n\t\tresult.push({ name, filePath: command.sourceInfo.path });\n\t}\n\treturn result;\n}\n\nfunction unavailableMessage(): string {\n\treturn [\n\t\t\"Local analytics storage could not be initialized safely.\",\n\t\t\"Existing files were not replaced.\",\n\t\t\"No analytics are being collected.\",\n\t].join(\"\\n\");\n}\n\nfunction safeNotify(ctx: ExtensionContext, message: string, level: \"info\" | \"warning\"): void {\n\ttry {\n\t\tctx.ui.notify(message, level);\n\t} catch {\n\t\t// A replaced Pi context cannot receive lifecycle feedback.\n\t}\n}\n\nexport default createAnalyticsExtension();\n", "import { randomUUID } from \"node:crypto\";\nimport { classifyProviderError } from \"./errors.js\";\nimport type {\n\tGenerationOutcome,\n\tGenerationRecord,\n\tModelIdentity,\n\tProviderErrorRecord,\n\tRunOutcome,\n\tSettledRun,\n\tSkillActivationRecord,\n\tToolCallRecord,\n\tTriggerSource,\n} from \"./types.js\";\n\ninterface ActiveRun {\n\tid: string;\n\tstartedAtMs: number;\n\ttriggerSource: TriggerSource;\n\tinitialModel?: ModelIdentity;\n\tattemptCount: number;\n\tgenerations: GenerationRecord[];\n\tgenerationIds: Set<string>;\n\ttools: ToolCallRecord[];\n\ttoolIds: Set<string>;\n\tskills: SkillActivationRecord[];\n\tskillIndexes: Map<string, number>;\n\tproviderErrors: ProviderErrorRecord[];\n}\n\nexport class ResponseCollector {\n\tprivate active: ActiveRun | undefined;\n\n\thasActiveRun(): boolean {\n\t\treturn this.active !== undefined;\n\t}\n\n\tgetActiveRunId(): string | undefined {\n\t\treturn this.active?.id;\n\t}\n\n\tbegin(input: {\n\t\tid: string;\n\t\tnow: number;\n\t\ttriggerSource: TriggerSource;\n\t\tmodel?: ModelIdentity;\n\t}): SettledRun | undefined {\n\t\tconst interrupted = this.active ? this.finalize(input.now, \"interrupted\") : undefined;\n\t\tthis.active = {\n\t\t\tid: input.id,\n\t\t\tstartedAtMs: input.now,\n\t\t\ttriggerSource: input.triggerSource,\n\t\t\tinitialModel: input.model,\n\t\t\tattemptCount: 0,\n\t\t\tgenerations: [],\n\t\t\tgenerationIds: new Set(),\n\t\t\ttools: [],\n\t\t\ttoolIds: new Set(),\n\t\t\tskills: [],\n\t\t\tskillIndexes: new Map(),\n\t\t\tproviderErrors: [],\n\t\t};\n\t\treturn interrupted;\n\t}\n\n\tbeginAttempt(): void {\n\t\tif (this.active) this.active.attemptCount += 1;\n\t}\n\n\tbeginGeneration(input: { id: string; now: number; model?: ModelIdentity }): void {\n\t\tconst active = this.active;\n\t\tif (!active || active.generationIds.has(input.id)) return;\n\t\tactive.generationIds.add(input.id);\n\t\tactive.generations.push({\n\t\t\tid: input.id,\n\t\t\tordinal: active.generations.length,\n\t\t\tprovider: input.model?.provider,\n\t\t\tmodel: input.model?.model,\n\t\t\tthinkingLevel: input.model?.thinkingLevel,\n\t\t\tstartedAtMs: input.now,\n\t\t\toutcome: \"pending\",\n\t\t\tresponses: [],\n\t\t});\n\t}\n\n\trecordProviderResponse(input: { status: number; now: number }): void {\n\t\tconst generation = this.latestGeneration();\n\t\tif (generation?.outcome !== \"pending\") return;\n\t\tgeneration.responses.push({\n\t\t\tordinal: generation.responses.length,\n\t\t\toccurredAtMs: input.now,\n\t\t\tstatus: input.status,\n\t\t});\n\t}\n\n\tfinishGeneration(input: { now: number; stopReason: string; errorMessage?: string }): void {\n\t\tconst active = this.active;\n\t\tconst generation = this.latestGeneration();\n\t\tif (!active || !generation || generation.outcome !== \"pending\") return;\n\t\tgeneration.finishedAtMs = input.now;\n\t\tgeneration.durationMs = elapsed(generation.startedAtMs, input.now);\n\t\tgeneration.stopReason = input.stopReason;\n\t\tgeneration.outcome = generationOutcome(input.stopReason);\n\t\tif (generation.outcome === \"error\") {\n\t\t\tactive.providerErrors.push({\n\t\t\t\tid: randomUUID(),\n\t\t\t\tgenerationId: generation.id,\n\t\t\t\toccurredAtMs: input.now,\n\t\t\t\tprovider: generation.provider,\n\t\t\t\tmodel: generation.model,\n\t\t\t\tcategory: classifyProviderError(input.errorMessage),\n\t\t\t\trecovered: false,\n\t\t\t\tterminal: true,\n\t\t\t});\n\t\t}\n\t}\n\n\tbeginTool(input: { id: string; name: string; now: number; model?: ModelIdentity }): void {\n\t\tconst active = this.active;\n\t\tif (!active || active.toolIds.has(input.id)) return;\n\t\tactive.toolIds.add(input.id);\n\t\tactive.tools.push({\n\t\t\tid: input.id,\n\t\t\tordinal: active.tools.length,\n\t\t\tname: input.name,\n\t\t\tprovider: input.model?.provider,\n\t\t\tmodel: input.model?.model,\n\t\t\tstartedAtMs: input.now,\n\t\t\tisError: false,\n\t\t\tcompletionState: \"running\",\n\t\t});\n\t}\n\n\tfinishTool(input: { id: string; now: number; isError: boolean }): void {\n\t\tconst tool = this.active?.tools.find(({ id }) => id === input.id);\n\t\tif (tool?.completionState !== \"running\") return;\n\t\ttool.finishedAtMs = input.now;\n\t\ttool.durationMs = elapsed(tool.startedAtMs, input.now);\n\t\ttool.isError = input.isError;\n\t\ttool.completionState = \"finished\";\n\t}\n\n\tactivateSkill(input: {\n\t\tname: string;\n\t\tinitiatedBy: \"user\" | \"model\";\n\t\tnow: number;\n\t\tmodel?: ModelIdentity;\n\t}): void {\n\t\tconst active = this.active;\n\t\tif (!active) return;\n\t\tconst existingIndex = active.skillIndexes.get(input.name);\n\t\tif (existingIndex !== undefined) {\n\t\t\tconst existing = active.skills[existingIndex];\n\t\t\tif (existing && existing.initiatedBy === \"model\" && input.initiatedBy === \"user\") {\n\t\t\t\texisting.initiatedBy = \"user\";\n\t\t\t\texisting.occurredAtMs = input.now;\n\t\t\t\texisting.provider = input.model?.provider;\n\t\t\t\texisting.model = input.model?.model;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tactive.skillIndexes.set(input.name, active.skills.length);\n\t\tactive.skills.push({\n\t\t\tid: randomUUID(),\n\t\t\tname: input.name,\n\t\t\tinitiatedBy: input.initiatedBy,\n\t\t\toccurredAtMs: input.now,\n\t\t\tprovider: input.model?.provider,\n\t\t\tmodel: input.model?.model,\n\t\t});\n\t}\n\n\tsettle(now: number): SettledRun | undefined {\n\t\treturn this.finalize(now);\n\t}\n\n\tinterrupt(now: number): SettledRun | undefined {\n\t\treturn this.finalize(now, \"interrupted\");\n\t}\n\n\tprivate latestGeneration(): GenerationRecord | undefined {\n\t\treturn this.active?.generations.at(-1);\n\t}\n\n\tprivate finalize(now: number, forcedOutcome?: RunOutcome): SettledRun | undefined {\n\t\tconst active = this.active;\n\t\tif (!active) return undefined;\n\t\tthis.active = undefined;\n\n\t\tfor (const generation of active.generations) {\n\t\t\tif (generation.outcome !== \"pending\") continue;\n\t\t\tgeneration.outcome = \"interrupted\";\n\t\t\tgeneration.finishedAtMs = now;\n\t\t\tgeneration.durationMs = elapsed(generation.startedAtMs, now);\n\t\t}\n\t\tfor (const tool of active.tools) {\n\t\t\tif (tool.completionState !== \"running\") continue;\n\t\t\ttool.completionState = \"interrupted\";\n\t\t\ttool.finishedAtMs = now;\n\t\t\ttool.durationMs = elapsed(tool.startedAtMs, now);\n\t\t}\n\n\t\tconst successfulGenerationIndexes = new Set(\n\t\t\tactive.generations\n\t\t\t\t.map((generation, index) => ({ generation, index }))\n\t\t\t\t.filter(({ generation }) => isSuccessfulGeneration(generation))\n\t\t\t\t.map(({ index }) => index),\n\t\t);\n\t\tlet recoveredHttpErrors = 0;\n\t\tlet httpErrors = 0;\n\t\tfor (const [generationIndex, generation] of active.generations.entries()) {\n\t\t\tconst hasLaterSuccess = [...successfulGenerationIndexes].some(\n\t\t\t\t(index) => index > generationIndex,\n\t\t\t);\n\t\t\tfor (const [responseIndex, response] of generation.responses.entries()) {\n\t\t\t\tif (response.status < 400) continue;\n\t\t\t\thttpErrors += 1;\n\t\t\t\tconst laterSuccessInGeneration = generation.responses\n\t\t\t\t\t.slice(responseIndex + 1)\n\t\t\t\t\t.some(({ status }) => status >= 200 && status < 400);\n\t\t\t\tif (laterSuccessInGeneration || hasLaterSuccess) recoveredHttpErrors += 1;\n\t\t\t}\n\t\t}\n\t\tfor (const error of active.providerErrors) {\n\t\t\tconst generationIndex = active.generations.findIndex(({ id }) => id === error.generationId);\n\t\t\terror.recovered = [...successfulGenerationIndexes].some((index) => index > generationIndex);\n\t\t\terror.terminal = !error.recovered;\n\t\t}\n\n\t\tconst recoveredGenerationErrors = active.providerErrors.filter(\n\t\t\t({ recovered }) => recovered,\n\t\t).length;\n\t\tconst providerErrorCount = httpErrors + active.providerErrors.length;\n\t\tconst recoveredErrorCount = recoveredHttpErrors + recoveredGenerationErrors;\n\t\tconst outcome = forcedOutcome ?? deriveOutcome(active.generations, providerErrorCount);\n\n\t\treturn {\n\t\t\tid: active.id,\n\t\t\tstartedAtMs: active.startedAtMs,\n\t\t\tfinishedAtMs: now,\n\t\t\tdurationMs: elapsed(active.startedAtMs, now),\n\t\t\ttriggerSource: active.triggerSource,\n\t\t\tinitialProvider: active.initialModel?.provider,\n\t\t\tinitialModel: active.initialModel?.model,\n\t\t\toutcome,\n\t\t\tattemptCount: active.attemptCount,\n\t\t\tgenerations: active.generations,\n\t\t\ttools: active.tools,\n\t\t\tskills: active.skills,\n\t\t\tproviderErrors: active.providerErrors,\n\t\t\ttoolErrorCount: active.tools.filter(({ isError }) => isError).length,\n\t\t\tproviderErrorCount,\n\t\t\trecoveredErrorCount,\n\t\t};\n\t}\n}\n\nfunction elapsed(start: number, end: number): number {\n\treturn Math.max(0, end - start);\n}\n\nfunction generationOutcome(stopReason: string): GenerationOutcome {\n\tswitch (stopReason) {\n\t\tcase \"stop\":\n\t\t\treturn \"stop\";\n\t\tcase \"toolUse\":\n\t\t\treturn \"tool_use\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"aborted\":\n\t\t\treturn \"aborted\";\n\t\tcase \"length\":\n\t\t\treturn \"length\";\n\t\tdefault:\n\t\t\treturn \"interrupted\";\n\t}\n}\n\nfunction isSuccessfulGeneration(generation: GenerationRecord): boolean {\n\treturn generation.outcome === \"stop\" || generation.outcome === \"tool_use\";\n}\n\nfunction deriveOutcome(\n\tgenerations: readonly GenerationRecord[],\n\tproviderErrors: number,\n): RunOutcome {\n\tconst last = generations.at(-1);\n\tif (!last) return providerErrors > 0 ? \"error\" : \"success\";\n\tswitch (last.outcome) {\n\t\tcase \"stop\":\n\t\tcase \"tool_use\":\n\t\t\treturn providerErrors > 0 ? \"recovered_success\" : \"success\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"aborted\":\n\t\t\treturn \"aborted\";\n\t\tcase \"length\":\n\t\t\treturn \"length\";\n\t\tdefault:\n\t\t\treturn \"interrupted\";\n\t}\n}\n", "import type { ProviderErrorCategory } from \"./types.js\";\n\nexport function classifyProviderError(message: string | undefined): ProviderErrorCategory {\n\tconst value = message?.toLowerCase() ?? \"\";\n\tif (/\\b(enotfound|eai_again|dns|getaddrinfo)\\b/u.test(value)) return \"dns\";\n\tif (/\\b(etimedout|timeout|timed out)\\b/u.test(value)) return \"timeout\";\n\tif (/\\b(econnrefused|connection refused)\\b/u.test(value)) return \"connection_refused\";\n\tif (/\\b(econnreset|connection reset|socket hang up)\\b/u.test(value)) {\n\t\treturn \"connection_reset\";\n\t}\n\tif (/\\b(tls|ssl|certificate|cert_|handshake)\\b/u.test(value)) return \"tls\";\n\tif (/\\b(fetch failed|network|socket|connection|transport)\\b/u.test(value)) {\n\t\treturn \"network_other\";\n\t}\n\treturn \"provider_other\";\n}\n", "import { stripVTControlCharacters } from \"node:util\";\nimport type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport type { MenuDefinition } from \"@narumitw/pi-tui-kit\";\nimport type { ClearAnalyticsResult } from \"./storage/files.js\";\nimport type {\n\tAnalyticsSnapshot,\n\tSkillStats,\n\tTimeRange,\n\tTimeRangeId,\n\tToolStats,\n} from \"./storage/queries.js\";\nimport { resolveTimeRange } from \"./storage/queries.js\";\n\nexport type AnalyticsLoadResult =\n\t| { kind: \"ready\"; snapshot: AnalyticsSnapshot }\n\t| { kind: \"unavailable\"; message: string };\n\nexport interface AnalyticsMenuDataSource {\n\tpath: string;\n\tload(range: TimeRange, signal: AbortSignal): Promise<AnalyticsLoadResult>;\n\tclearAll(signal: AbortSignal): Promise<ClearAnalyticsResult>;\n}\n\nexport interface AnalyticsMenuState {\n\trangeId: TimeRangeId;\n\trange: TimeRange;\n\tpath: string;\n\tresult: AnalyticsLoadResult;\n}\n\nexport interface AnalyticsMenuOptions {\n\trunConfirmation: typeof import(\"@narumitw/pi-tui-kit\")[\"runConfirmation\"];\n\tisCurrent(): boolean;\n}\n\ntype Screen = \"main\" | \"range\" | \"skills\" | \"tools\" | \"reliability\" | \"responses\" | \"privacy\";\ntype Action = \"setRange\" | \"clearData\";\n\nconst RANGE_LABELS: Record<TimeRangeId, string> = {\n\ttoday: \"Today\",\n\t\"7d\": \"Last 7 days\",\n\t\"30d\": \"Last 30 days\",\n\tall: \"All time\",\n};\n\nexport function createAnalyticsMenu(\n\tsource: AnalyticsMenuDataSource,\n\tnow: () => number = Date.now,\n\toptions?: AnalyticsMenuOptions,\n) {\n\tlet rangeId: TimeRangeId = \"7d\";\n\tlet cachedState: AnalyticsMenuState | undefined;\n\tconst loadState = async (signal: AbortSignal): Promise<AnalyticsMenuState> => {\n\t\tif (cachedState?.rangeId === rangeId) return cachedState;\n\t\tconst range = resolveTimeRange(rangeId, now());\n\t\tconst loaded = { rangeId, range, path: source.path, result: await source.load(range, signal) };\n\t\tif (!signal.aborted && rangeId === loaded.rangeId) cachedState = loaded;\n\t\treturn loaded;\n\t};\n\tconst getState = ({ signal }: { signal: AbortSignal }): Promise<AnalyticsMenuState> =>\n\t\tloadState(signal);\n\tconst menu: MenuDefinition<AnalyticsMenuState, Screen, Action> = {\n\t\tstart: \"main\",\n\t\tscreens: {\n\t\t\tmain: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: `Analytics \u00B7 ${RANGE_LABELS[state.rangeId]}`,\n\t\t\t\tlines: overviewLines(state.result),\n\t\t\t\titems: [\n\t\t\t\t\t{ id: \"range\", label: \"Change time range\", to: \"range\" },\n\t\t\t\t\t{ id: \"skills\", label: \"Skills\", to: \"skills\" },\n\t\t\t\t\t{ id: \"tools\", label: \"Tools\", to: \"tools\" },\n\t\t\t\t\t{ id: \"reliability\", label: \"Provider reliability\", to: \"reliability\" },\n\t\t\t\t\t{ id: \"responses\", label: \"Response cycles\", to: \"responses\" },\n\t\t\t\t\t{ id: \"privacy\", label: \"Data & privacy\", to: \"privacy\" },\n\t\t\t\t\t{ id: \"close\", label: \"Close\", close: true },\n\t\t\t\t],\n\t\t\t\thint: \"close\",\n\t\t\t}),\n\t\t\trange: ({ state }) => ({\n\t\t\t\tkind: \"choice\",\n\t\t\t\ttitle: \"Analytics time range\",\n\t\t\t\titems: (Object.keys(RANGE_LABELS) as TimeRangeId[]).map((id) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tlabel: RANGE_LABELS[id],\n\t\t\t\t})),\n\t\t\t\taction: \"setRange\",\n\t\t\t\tcurrentItemId: state.rangeId,\n\t\t\t\tinitialItemId: state.rangeId,\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tskills: ({ state }) => skillsScreen(state.result),\n\t\t\ttools: ({ state }) => toolsScreen(state.result),\n\t\t\treliability: ({ state }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: `Provider reliability \u00B7 ${RANGE_LABELS[state.rangeId]}`,\n\t\t\t\tlines: reliabilityLines(state.result),\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tresponses: ({ state }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: `Response cycles \u00B7 ${RANGE_LABELS[state.rangeId]}`,\n\t\t\t\tlines: responseLines(state.result),\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tprivacy: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: \"Analytics data & privacy\",\n\t\t\t\tlines: privacyLines(state),\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"clear\",\n\t\t\t\t\t\tlabel: \"Clear analytics data\u2026\",\n\t\t\t\t\t\taction: \"clearData\",\n\t\t\t\t\t\tdisabled: state.result.kind !== \"ready\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\tsetRange: async ({ itemId, signal }) => {\n\t\t\t\tif (!isRangeId(itemId)) return { kind: \"rejected\", error: new Error(\"Unknown range\") };\n\t\t\t\trangeId = itemId;\n\t\t\t\tcachedState = undefined;\n\t\t\t\tawait loadState(signal);\n\t\t\t\treturn signal.aborted ? { kind: \"close\" } : { kind: \"to\", screen: \"main\" };\n\t\t\t},\n\t\t\tclearData: async ({ ctx, state, signal }) => {\n\t\t\t\tif (state.result.kind !== \"ready\") return { kind: \"stay\" };\n\t\t\t\tif (!options) throw new Error(\"Analytics confirmation is unavailable\");\n\t\t\t\tconst count = state.result.snapshot.overview.responseCycles;\n\t\t\t\tconst confirmation = await options.runConfirmation(ctx, {\n\t\t\t\t\ttitle: \"Delete analytics data?\",\n\t\t\t\t\tmessage: `This will clear all local analytics history from:\\n\\n${safeDisplayText(state.path)}\\n\\nThe selected range currently shows ${count} response cycles. Other running Pi processes may add new records afterward.`,\n\t\t\t\t\tconfirmLabel: \"Delete data\",\n\t\t\t\t\tcancelLabel: \"Keep data\",\n\t\t\t\t\tsignal,\n\t\t\t\t\tisCurrent: options.isCurrent,\n\t\t\t\t\t// Keep the dashboard's existing domain-level error route as the only notifier.\n\t\t\t\t\tonError: () => undefined,\n\t\t\t\t});\n\t\t\t\tif (signal.aborted || !options.isCurrent()) return { kind: \"close\" };\n\t\t\t\tif (confirmation.kind === \"closed\") {\n\t\t\t\t\treturn confirmation.reason === \"close\" ? { kind: \"close\" } : { kind: \"stay\" };\n\t\t\t\t}\n\t\t\t\tif (confirmation.kind === \"stale\") return { kind: \"close\" };\n\t\t\t\tif (confirmation.kind === \"unsupported\") {\n\t\t\t\t\tthrow new Error(`Analytics confirmation is unavailable in ${confirmation.mode} mode`);\n\t\t\t\t}\n\t\t\t\tif (confirmation.kind === \"error\") throw confirmation.error;\n\n\t\t\t\tconst result = await source.clearAll(signal);\n\t\t\t\tcachedState = undefined;\n\t\t\t\tconst isCurrent = options.isCurrent();\n\t\t\t\tif (isCurrent) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tctx.ui.notify(\"Cleared local analytics data.\", \"info\");\n\t\t\t\t\t\tif (result.cleanupIncomplete) {\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t\"Some obsolete analytics files are still in use. Stop other Pi processes and clear again to remove them.\",\n\t\t\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// The host can dispose the current UI after the ownership check.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn signal.aborted || !isCurrent ? { kind: \"close\" } : { kind: \"to\", screen: \"main\" };\n\t\t\t},\n\t\t},\n\t};\n\treturn {\n\t\tmenu,\n\t\tgetState,\n\t\tpreload: (signal: AbortSignal) => loadState(signal),\n\t\tget rangeId() {\n\t\t\treturn rangeId;\n\t\t},\n\t};\n}\n\nexport async function showAnalyticsMenu(\n\tctx: ExtensionCommandContext,\n\tsource: AnalyticsMenuDataSource,\n\toptions: { signal: AbortSignal; isCurrent: () => boolean },\n): Promise<void> {\n\tconst { runConfirmation, runMenu, runTask } = await import(\"@narumitw/pi-tui-kit\");\n\tif (options.signal.aborted || !options.isCurrent()) return;\n\tconst controller = createAnalyticsMenu(source, Date.now, {\n\t\trunConfirmation,\n\t\tisCurrent: options.isCurrent,\n\t});\n\tconst loading = await runTask(ctx, {\n\t\tlabel: \"Loading local analytics\u2026\",\n\t\tsignal: options.signal,\n\t\tisCurrent: options.isCurrent,\n\t\ttask: ({ signal }) => controller.preload(signal),\n\t\tonError: () => undefined,\n\t});\n\tif (loading.kind !== \"completed\") {\n\t\tif (loading.kind === \"error\") {\n\t\t\tctx.ui.notify(\n\t\t\t\t\"Analytics failed: The local analytics query could not be completed. Existing data was not changed.\",\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\tawait runMenu(ctx, controller.menu, {\n\t\tgetState: controller.getState,\n\t\tsignal: options.signal,\n\t\tisCurrent: options.isCurrent,\n\t\tonError: (_ctx, error) => {\n\t\t\tctx.ui.notify(`Analytics failed: ${safeErrorMessage(error)}`, \"error\");\n\t\t},\n\t});\n}\n\nfunction overviewLines(result: AnalyticsLoadResult): string[] {\n\tif (result.kind === \"unavailable\") {\n\t\treturn [result.message, \"\", \"No analytics are being collected.\"];\n\t}\n\tconst stats = result.snapshot.overview;\n\tif (stats.responseCycles === 0) {\n\t\treturn [\n\t\t\t\"No analytics yet.\",\n\t\t\t\"Collection is active. Complete one Pi response cycle, then open /analytics again.\",\n\t\t\t\"\",\n\t\t\t\"Includes settled response cycles only.\",\n\t\t];\n\t}\n\treturn [\n\t\tmetric(\"Response cycles\", stats.responseCycles),\n\t\tmetric(\"LLM calls\", stats.llmCalls),\n\t\tmetric(\n\t\t\t\"Calls per response\",\n\t\t\t`${formatDecimal(stats.callsPerResponse)} \u00B7 P95 ${stats.p95CallsPerResponse}`,\n\t\t),\n\t\tmetric(\"Tool calls\", stats.toolCalls),\n\t\tmetric(\"Tool errors\", stats.toolErrors),\n\t\tmetric(\"Skill activations\", stats.skillActivations),\n\t\tmetric(\"Provider errors\", stats.providerErrors),\n\t\tmetric(\"Recovered errors\", stats.recoveredErrors),\n\t\t\"\",\n\t\t\"Includes settled response cycles only.\",\n\t];\n}\n\nfunction skillsScreen(result: AnalyticsLoadResult) {\n\tif (result.kind === \"unavailable\") {\n\t\treturn {\n\t\t\tkind: \"browse\" as const,\n\t\t\ttitle: \"Skills\",\n\t\t\tlines: [result.message],\n\t\t\titems: [],\n\t\t\thint: \"back\" as const,\n\t\t};\n\t}\n\treturn {\n\t\tkind: \"browse\" as const,\n\t\ttitle: \"Skills\",\n\t\tlines:\n\t\t\tresult.snapshot.skills.length === 0\n\t\t\t\t? [\"No skill activations detected in this time range.\"]\n\t\t\t\t: undefined,\n\t\titems: result.snapshot.skills.map(skillItem),\n\t\tviewportSize: \"adaptive\" as const,\n\t\thint: \"back\" as const,\n\t};\n}\n\nfunction skillItem(skill: SkillStats) {\n\treturn {\n\t\tid: skill.name,\n\t\tlabel: safeDisplayText(skill.name),\n\t\tstatusText: `${skill.count} \u00B7 ${skill.modelInitiated} model / ${skill.userInitiated} user`,\n\t\tsearchText: skill.models.map(modelLabel).join(\" \"),\n\t\tdetails: [\n\t\t\tmetric(\"Activations\", skill.count),\n\t\t\tmetric(\"Model initiated\", skill.modelInitiated),\n\t\t\tmetric(\"User initiated\", skill.userInitiated),\n\t\t\t\"\",\n\t\t\t\"By model\",\n\t\t\t...skill.models.map((model) => `${modelLabel(model)}: ${model.count}`),\n\t\t\t\"\",\n\t\t\t`Last detected: ${formatTimestamp(skill.lastOccurredAtMs)}`,\n\t\t],\n\t};\n}\n\nfunction toolsScreen(result: AnalyticsLoadResult) {\n\tif (result.kind === \"unavailable\") {\n\t\treturn {\n\t\t\tkind: \"browse\" as const,\n\t\t\ttitle: \"Tools\",\n\t\t\tlines: [result.message],\n\t\t\titems: [],\n\t\t\thint: \"back\" as const,\n\t\t};\n\t}\n\treturn {\n\t\tkind: \"browse\" as const,\n\t\ttitle: \"Tools\",\n\t\tlines:\n\t\t\tresult.snapshot.tools.length === 0\n\t\t\t\t? [\"No tool calls detected in this time range.\"]\n\t\t\t\t: undefined,\n\t\titems: result.snapshot.tools.map(toolItem),\n\t\tviewportSize: \"adaptive\" as const,\n\t\thint: \"back\" as const,\n\t};\n}\n\nfunction toolItem(tool: ToolStats) {\n\treturn {\n\t\tid: tool.name,\n\t\tlabel: safeDisplayText(tool.name),\n\t\tstatusText: `${tool.count} \u00B7 ${tool.errors} errors`,\n\t\tsearchText: tool.models.map(modelLabel).join(\" \"),\n\t\tdetails: [\n\t\t\tmetric(\"Calls\", tool.count),\n\t\t\tmetric(\"Errors\", tool.errors),\n\t\t\t`Average duration: ${formatDecimal(tool.averageDurationMs)} ms`,\n\t\t\t\"\",\n\t\t\t\"By model\",\n\t\t\t...tool.models.map((model) => `${modelLabel(model)}: ${model.count}`),\n\t\t\t\"\",\n\t\t\t`Last detected: ${formatTimestamp(tool.lastOccurredAtMs)}`,\n\t\t],\n\t};\n}\n\nfunction reliabilityLines(result: AnalyticsLoadResult): string[] {\n\tif (result.kind === \"unavailable\") return [result.message];\n\tconst value = result.snapshot.reliability;\n\treturn [\n\t\t\"Observed provider errors only; provider-internal failures may be invisible.\",\n\t\t\"\",\n\t\tmetric(\"HTTP 429\", value.http429),\n\t\tmetric(\"HTTP 5xx\", value.http5xx),\n\t\tmetric(\"DNS\", value.categories.dns),\n\t\tmetric(\"Connection timeout\", value.categories.timeout),\n\t\tmetric(\"Connection refused\", value.categories.connection_refused),\n\t\tmetric(\"Connection reset\", value.categories.connection_reset),\n\t\tmetric(\"TLS\", value.categories.tls),\n\t\tmetric(\"Other network\", value.categories.network_other),\n\t\tmetric(\"Other provider\", value.categories.provider_other),\n\t\t\"\",\n\t\tmetric(\"Recovered\", value.recovered),\n\t\tmetric(\"Terminal failures\", value.terminal),\n\t];\n}\n\nfunction responseLines(result: AnalyticsLoadResult): string[] {\n\tif (result.kind === \"unavailable\") return [result.message];\n\tconst value = result.snapshot.responses;\n\treturn [\n\t\tmetric(\"Cycles\", value.count),\n\t\tmetric(\"LLM calls\", value.llmCalls),\n\t\tmetric(\"Average\", formatDecimal(value.average)),\n\t\tmetric(\"Median\", formatDecimal(value.median)),\n\t\tmetric(\"P95\", value.p95),\n\t\tmetric(\"Maximum\", value.maximum),\n\t\t\"\",\n\t\t\"Calls per response\",\n\t\tmetric(\"1 call\", value.distribution.one),\n\t\tmetric(\"2\u20133 calls\", value.distribution.twoToThree),\n\t\tmetric(\"4\u20136 calls\", value.distribution.fourToSix),\n\t\tmetric(\"7+ calls\", value.distribution.sevenPlus),\n\t];\n}\n\nfunction privacyLines(state: AnalyticsMenuState): string[] {\n\treturn [\n\t\t\"Local analytics files:\",\n\t\tsafeDisplayText(state.path),\n\t\t\"\",\n\t\t\"Stored: timestamps, extension-generated record IDs, model/provider IDs, thinking level, tool and skill names, durations, counts, HTTP statuses, and classified errors.\",\n\t\t\"Not stored: prompts, responses, thinking, tool arguments/results, raw errors, headers, cwd/file paths, session identity, or credentials.\",\n\t\t\"\",\n\t\t\"No database server, cloud connection, or other remote telemetry is used.\",\n\t\t\"Analytics are non-critical derived metadata; a failed local write may be dropped.\",\n\t];\n}\n\nfunction metric(label: string, value: string | number): string {\n\treturn `${label.padEnd(24)} ${value}`;\n}\n\nfunction formatDecimal(value: number): string {\n\treturn Number.isInteger(value)\n\t\t? String(value)\n\t\t: value.toFixed(2).replace(/0+$/u, \"\").replace(/\\.$/u, \"\");\n}\n\nfunction formatTimestamp(value: number): string {\n\treturn new Date(value).toLocaleString();\n}\n\nfunction modelLabel(model: { provider?: string; model?: string }): string {\n\tif (!model.provider && !model.model) return \"unknown\";\n\treturn safeDisplayText(`${model.provider ?? \"unknown\"}/${model.model ?? \"unknown\"}`);\n}\n\nfunction safeDisplayText(value: unknown): string {\n\treturn Array.from(stripVTControlCharacters(String(value)), (character) => {\n\t\tconst codePoint = character.codePointAt(0) ?? 0;\n\t\treturn codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f) ? \" \" : character;\n\t}).join(\"\");\n}\n\nfunction isRangeId(value: string): value is TimeRangeId {\n\treturn value === \"today\" || value === \"7d\" || value === \"30d\" || value === \"all\";\n}\n\nfunction safeErrorMessage(_error: unknown): string {\n\treturn \"The local analytics query could not be completed. Try again; existing data was not changed.\";\n}\n", "import type { ProviderErrorCategory, SettledRun } from \"../types.js\";\n\nexport type TimeRangeId = \"today\" | \"7d\" | \"30d\" | \"all\";\nexport interface TimeRange {\n\tid?: TimeRangeId;\n\tfromMs: number;\n\ttoMs: number;\n}\n\nexport interface OverviewStats {\n\tresponseCycles: number;\n\tllmCalls: number;\n\tcallsPerResponse: number;\n\tp95CallsPerResponse: number;\n\ttoolCalls: number;\n\ttoolErrors: number;\n\tskillActivations: number;\n\tproviderErrors: number;\n\trecoveredErrors: number;\n}\n\nexport interface ModelCount {\n\tprovider?: string;\n\tmodel?: string;\n\tcount: number;\n}\n\nexport interface SkillStats {\n\tname: string;\n\tcount: number;\n\tmodelInitiated: number;\n\tuserInitiated: number;\n\tlastOccurredAtMs: number;\n\tmodels: ModelCount[];\n}\n\nexport interface ToolStats {\n\tname: string;\n\tcount: number;\n\terrors: number;\n\taverageDurationMs: number;\n\tlastOccurredAtMs: number;\n\tmodels: ModelCount[];\n}\n\nexport interface ReliabilityStats {\n\thttp429: number;\n\thttp5xx: number;\n\trecovered: number;\n\tterminal: number;\n\tcategories: Record<ProviderErrorCategory, number>;\n}\n\nexport interface ResponseStats {\n\tcount: number;\n\tllmCalls: number;\n\taverage: number;\n\tmedian: number;\n\tp95: number;\n\tmaximum: number;\n\tdistribution: { one: number; twoToThree: number; fourToSix: number; sevenPlus: number };\n}\n\nexport interface AnalyticsSnapshot {\n\toverview: OverviewStats;\n\tskills: SkillStats[];\n\ttools: ToolStats[];\n\treliability: ReliabilityStats;\n\tresponses: ResponseStats;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1_000;\nconst ERROR_CATEGORIES: readonly ProviderErrorCategory[] = [\n\t\"dns\",\n\t\"timeout\",\n\t\"connection_refused\",\n\t\"connection_reset\",\n\t\"tls\",\n\t\"network_other\",\n\t\"provider_other\",\n];\n\nexport function resolveTimeRange(id: TimeRangeId, now = Date.now()): TimeRange {\n\tlet fromMs = 0;\n\tif (id === \"today\") {\n\t\tconst date = new Date(now);\n\t\tfromMs = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();\n\t} else if (id === \"7d\") fromMs = now - 7 * DAY_MS;\n\telse if (id === \"30d\") fromMs = now - 30 * DAY_MS;\n\treturn { id, fromMs, toMs: now + 1 };\n}\n\nexport async function querySnapshot(\n\truns: AsyncIterable<SettledRun> | Iterable<SettledRun>,\n\trange: TimeRange,\n\tsignal?: AbortSignal,\n): Promise<AnalyticsSnapshot> {\n\tconst generationCounts: number[] = [];\n\tconst seenRunIds = new Set<string>();\n\tconst skills = new Map<string, SkillStats>();\n\tconst tools = new Map<string, ToolStats & { totalDurationMs: number }>();\n\tconst categories = Object.fromEntries(\n\t\tERROR_CATEGORIES.map((category) => [category, 0]),\n\t) as Record<ProviderErrorCategory, number>;\n\tlet toolErrors = 0;\n\tlet providerErrors = 0;\n\tlet recoveredErrors = 0;\n\tlet http429 = 0;\n\tlet http5xx = 0;\n\tlet terminal = 0;\n\n\tfor await (const run of runs) {\n\t\tthrowIfAborted(signal);\n\t\tif (seenRunIds.has(run.id)) continue;\n\t\tseenRunIds.add(run.id);\n\t\tif (run.startedAtMs < range.fromMs || run.startedAtMs >= range.toMs) continue;\n\t\tgenerationCounts.push(run.generations.length);\n\t\ttoolErrors += run.toolErrorCount;\n\t\tproviderErrors += run.providerErrorCount;\n\t\trecoveredErrors += run.recoveredErrorCount;\n\n\t\tfor (const skill of run.skills) {\n\t\t\tconst item = skills.get(skill.name) ?? {\n\t\t\t\tname: skill.name,\n\t\t\t\tcount: 0,\n\t\t\t\tmodelInitiated: 0,\n\t\t\t\tuserInitiated: 0,\n\t\t\t\tlastOccurredAtMs: 0,\n\t\t\t\tmodels: [],\n\t\t\t};\n\t\t\titem.count += 1;\n\t\t\tif (skill.initiatedBy === \"user\") item.userInitiated += 1;\n\t\t\telse item.modelInitiated += 1;\n\t\t\titem.lastOccurredAtMs = Math.max(item.lastOccurredAtMs, skill.occurredAtMs);\n\t\t\tmergeModelCount(item.models, {\n\t\t\t\tprovider: skill.provider,\n\t\t\t\tmodel: skill.model,\n\t\t\t\tcount: 1,\n\t\t\t});\n\t\t\tskills.set(skill.name, item);\n\t\t}\n\n\t\tfor (const tool of run.tools) {\n\t\t\tconst item = tools.get(tool.name) ?? {\n\t\t\t\tname: tool.name,\n\t\t\t\tcount: 0,\n\t\t\t\terrors: 0,\n\t\t\t\taverageDurationMs: 0,\n\t\t\t\ttotalDurationMs: 0,\n\t\t\t\tlastOccurredAtMs: 0,\n\t\t\t\tmodels: [],\n\t\t\t};\n\t\t\titem.count += 1;\n\t\t\titem.errors += tool.isError ? 1 : 0;\n\t\t\titem.totalDurationMs += tool.durationMs ?? 0;\n\t\t\titem.averageDurationMs = item.totalDurationMs / item.count;\n\t\t\titem.lastOccurredAtMs = Math.max(item.lastOccurredAtMs, tool.startedAtMs);\n\t\t\tmergeModelCount(item.models, {\n\t\t\t\tprovider: tool.provider,\n\t\t\t\tmodel: tool.model,\n\t\t\t\tcount: 1,\n\t\t\t});\n\t\t\ttools.set(tool.name, item);\n\t\t}\n\n\t\tfor (const error of run.providerErrors) {\n\t\t\tcategories[error.category] += 1;\n\t\t\tterminal += error.terminal ? 1 : 0;\n\t\t}\n\t\tfor (const generation of run.generations) {\n\t\t\tfor (const response of generation.responses) {\n\t\t\t\tif (response.status === 429) http429 += 1;\n\t\t\t\tif (response.status >= 500 && response.status < 600) http5xx += 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst responses = responseStatistics(generationCounts);\n\treturn {\n\t\toverview: {\n\t\t\tresponseCycles: responses.count,\n\t\t\tllmCalls: responses.llmCalls,\n\t\t\tcallsPerResponse: responses.average,\n\t\t\tp95CallsPerResponse: responses.p95,\n\t\t\ttoolCalls: sum([...tools.values()].map(({ count }) => count)),\n\t\t\ttoolErrors,\n\t\t\tskillActivations: sum([...skills.values()].map(({ count }) => count)),\n\t\t\tproviderErrors,\n\t\t\trecoveredErrors,\n\t\t},\n\t\tskills: [...skills.values()]\n\t\t\t.map((item) => ({ ...item, models: sortModels(item.models) }))\n\t\t\t.sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)),\n\t\ttools: [...tools.values()]\n\t\t\t.map(({ totalDurationMs: _, ...item }) => ({ ...item, models: sortModels(item.models) }))\n\t\t\t.sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)),\n\t\treliability: {\n\t\t\thttp429,\n\t\t\thttp5xx,\n\t\t\trecovered: recoveredErrors,\n\t\t\tterminal,\n\t\t\tcategories,\n\t\t},\n\t\tresponses,\n\t};\n}\n\nfunction responseStatistics(generationCounts: number[]): ResponseStats {\n\tconst sorted = [...generationCounts].sort((left, right) => left - right);\n\tconst count = sorted.length;\n\tconst llmCalls = sum(sorted);\n\tconst nearestRank = (percentile: number) =>\n\t\tcount === 0 ? 0 : (sorted[Math.max(0, Math.ceil(percentile * count) - 1)] ?? 0);\n\tconst median =\n\t\tcount === 0\n\t\t\t? 0\n\t\t\t: count % 2 === 1\n\t\t\t\t? (sorted[Math.floor(count / 2)] ?? 0)\n\t\t\t\t: ((sorted[count / 2 - 1] ?? 0) + (sorted[count / 2] ?? 0)) / 2;\n\treturn {\n\t\tcount,\n\t\tllmCalls,\n\t\taverage: count > 0 ? llmCalls / count : 0,\n\t\tmedian,\n\t\tp95: nearestRank(0.95),\n\t\tmaximum: sorted.at(-1) ?? 0,\n\t\tdistribution: {\n\t\t\tone: sorted.filter((value) => value === 1).length,\n\t\t\ttwoToThree: sorted.filter((value) => value >= 2 && value <= 3).length,\n\t\t\tfourToSix: sorted.filter((value) => value >= 4 && value <= 6).length,\n\t\t\tsevenPlus: sorted.filter((value) => value >= 7).length,\n\t\t},\n\t};\n}\n\nfunction mergeModelCount(models: ModelCount[], next: ModelCount): void {\n\tconst existing = models.find(\n\t\t({ provider, model }) => provider === next.provider && model === next.model,\n\t);\n\tif (existing) existing.count += next.count;\n\telse models.push(next);\n}\n\nfunction sortModels(models: ModelCount[]): ModelCount[] {\n\treturn models.sort(\n\t\t(left, right) =>\n\t\t\tright.count - left.count ||\n\t\t\t`${left.provider ?? \"\"}/${left.model ?? \"\"}`.localeCompare(\n\t\t\t\t`${right.provider ?? \"\"}/${right.model ?? \"\"}`,\n\t\t\t),\n\t);\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n\tif (signal?.aborted)\n\t\tthrow signal.reason ?? new DOMException(\"Analytics query aborted\", \"AbortError\");\n}\n\nfunction sum(values: readonly number[]): number {\n\treturn values.reduce((total, value) => total + value, 0);\n}\n", "import { realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { InputSource } from \"@earendil-works/pi-coding-agent\";\n\nexport interface AvailableSkill {\n\tname: string;\n\tfilePath: string;\n}\n\nexport interface PendingExplicitSkill {\n\tname: string;\n\tobservedAtMs: number;\n\tsource: \"interactive\" | \"rpc\";\n}\n\nexport function explicitSkillName(text: string): string | undefined {\n\treturn text.match(/^\\/skill:([a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?)(?:\\s|$)/u)?.[1];\n}\n\nexport class SkillTracker {\n\tprivate pending: PendingExplicitSkill | undefined;\n\tprivate readonly skillByPath = new Map<string, string>();\n\tprivate readonly availableNames = new Set<string>();\n\n\tconstructor(\n\t\tprivate readonly cwd: string,\n\t\tprivate readonly canonicalize: (filePath: string) => Promise<string> = realpath,\n\t) {}\n\n\tobserveInput(text: string, source: InputSource, now: number): void {\n\t\tif (source === \"extension\") return;\n\t\tconst name = explicitSkillName(text);\n\t\tthis.pending = name ? { name, observedAtMs: now, source } : undefined;\n\t}\n\n\tconsumeExplicitSkill(): PendingExplicitSkill | undefined {\n\t\tconst pending = this.pending;\n\t\tthis.pending = undefined;\n\t\treturn pending;\n\t}\n\n\tclearPending(): void {\n\t\tthis.pending = undefined;\n\t}\n\n\thasAvailableSkill(name: string): boolean {\n\t\treturn this.availableNames.has(name);\n\t}\n\n\tasync setAvailableSkills(skills: readonly AvailableSkill[]): Promise<void> {\n\t\tthis.skillByPath.clear();\n\t\tthis.availableNames.clear();\n\t\tconst seenNames = new Set<string>();\n\t\tfor (const skill of skills) {\n\t\t\tif (seenNames.has(skill.name)) continue;\n\t\t\tseenNames.add(skill.name);\n\t\t\tthis.availableNames.add(skill.name);\n\t\t\tconst canonical = await this.canonicalize(skill.filePath).catch(() =>\n\t\t\t\tpath.resolve(this.cwd, skill.filePath),\n\t\t\t);\n\t\t\tthis.skillByPath.set(canonical, skill.name);\n\t\t}\n\t}\n\n\tasync matchSuccessfulRead(input: {\n\t\ttoolName: string;\n\t\tinput: unknown;\n\t\tisError: boolean;\n\t}): Promise<string | undefined> {\n\t\tif (input.toolName !== \"read\" || input.isError || !isRecord(input.input)) return undefined;\n\t\tconst rawPath = input.input.path;\n\t\tif (typeof rawPath !== \"string\" || rawPath.length === 0) return undefined;\n\t\tconst normalized = rawPath.startsWith(\"@\") ? rawPath.slice(1) : rawPath;\n\t\tconst absolute = path.resolve(this.cwd, normalized);\n\t\tconst canonical = await this.canonicalize(absolute).catch(() => absolute);\n\t\treturn this.skillByPath.get(canonical);\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n", "import { randomUUID } from \"node:crypto\";\nimport { createReadStream, type Dirent } from \"node:fs\";\nimport {\n\tchmod,\n\tlstat,\n\tmkdir,\n\topen,\n\treaddir,\n\treadFile,\n\trename,\n\trm,\n\trmdir,\n\tunlink,\n\twriteFile,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { SettledRun } from \"../types.js\";\nimport {\n\tAnalyticsStorageFormatError,\n\tdecodeStoredRun,\n\tencodeStoredRun,\n\tMAX_STORED_RUN_BYTES,\n} from \"./format.js\";\n\nconst GENERATION_PATTERN =\n\t/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;\nconst DEFAULT_WRITE_TIMEOUT_MS = 5_000;\nconst YIELD_EVERY_RECORDS = 100;\n\nexport interface ClearAnalyticsResult {\n\tcleanupIncomplete: boolean;\n}\n\nexport class AnalyticsGenerationChangedError extends Error {\n\tconstructor() {\n\t\tsuper(\"The active analytics generation changed during the read.\");\n\t\tthis.name = \"AnalyticsGenerationChangedError\";\n\t}\n}\n\nexport class AnalyticsRunFiles {\n\tprivate readonly createId: () => string;\n\tprivate readonly writeTimeoutMs: number;\n\tprivate readonly beforeAppend?: (generation: string, signal: AbortSignal) => Promise<void>;\n\tprivate readonly beforeCleanupEntry?: (signal?: AbortSignal) => Promise<void>;\n\tprivate readonly beforeReadFile?: (signal?: AbortSignal) => Promise<void>;\n\tprivate writerId: string;\n\tprivate mutationTail: Promise<void> = Promise.resolve();\n\tprivate readonly lifecycle = new AbortController();\n\tprivate closed = false;\n\n\tconstructor(\n\t\treadonly path: string,\n\t\toptions: {\n\t\t\tcreateId?: () => string;\n\t\t\twriteTimeoutMs?: number;\n\t\t\tbeforeAppend?: (generation: string, signal: AbortSignal) => Promise<void>;\n\t\t\tbeforeCleanupEntry?: (signal?: AbortSignal) => Promise<void>;\n\t\t\tbeforeReadFile?: (signal?: AbortSignal) => Promise<void>;\n\t\t} = {},\n\t) {\n\t\tthis.createId = options.createId ?? randomUUID;\n\t\tthis.writeTimeoutMs = options.writeTimeoutMs ?? DEFAULT_WRITE_TIMEOUT_MS;\n\t\tthis.beforeAppend = options.beforeAppend;\n\t\tthis.beforeCleanupEntry = options.beforeCleanupEntry;\n\t\tthis.beforeReadFile = options.beforeReadFile;\n\t\tthis.writerId = validCreatedId(this.createId());\n\t}\n\n\tappend(run: SettledRun, signal?: AbortSignal): Promise<void> {\n\t\tif (this.closed) return Promise.reject(new Error(\"Analytics storage is closed.\"));\n\t\tconst frame = encodeStoredRun(run);\n\t\treturn this.enqueueMutation(() =>\n\t\t\twithDeadline(signal, this.lifecycle.signal, this.writeTimeoutMs, (operationSignal) =>\n\t\t\t\tthis.appendFrame(frame, operationSignal),\n\t\t\t),\n\t\t);\n\t}\n\n\tasync *read(signal?: AbortSignal): AsyncIterable<SettledRun> {\n\t\tthrowIfAborted(signal);\n\t\tconst generation = await this.readOrCreateGeneration(signal);\n\t\tconst directory = this.generationPath(generation);\n\t\tlet entries: Dirent[];\n\t\ttry {\n\t\t\tentries = await readdir(directory, { withFileTypes: true });\n\t\t} catch (error) {\n\t\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\t\tawait this.assertGenerationUnchanged(generation, signal);\n\t\t\t\tthrow new AnalyticsGenerationChangedError();\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tlet count = 0;\n\t\tfor (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n\t\t\tthrowIfAborted(signal);\n\t\t\tif (!entry.name.endsWith(\".jsonl\")) continue;\n\t\t\tconst filePath = path.join(directory, entry.name);\n\t\t\ttry {\n\t\t\t\tawait this.beforeReadFile?.(signal);\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tawait assertPrivateRegularFile(filePath);\n\t\t\t\tfor await (const run of readFrames(filePath, signal)) {\n\t\t\t\t\tyield run;\n\t\t\t\t\tcount += 1;\n\t\t\t\t\tif (count % YIELD_EVERY_RECORDS === 0) await yieldToEventLoop(signal);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\t\t\tawait this.assertGenerationUnchanged(generation, signal);\n\t\t\t\t\tthrow new AnalyticsGenerationChangedError();\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tawait this.assertGenerationUnchanged(generation, signal);\n\t}\n\n\tclear(signal?: AbortSignal): Promise<ClearAnalyticsResult> {\n\t\tif (this.closed) return Promise.reject(new Error(\"Analytics storage is closed.\"));\n\t\tlet result: ClearAnalyticsResult = { cleanupIncomplete: false };\n\t\treturn this.enqueueMutation(() =>\n\t\t\twithLinkedSignals(signal, this.lifecycle.signal, async (operationSignal) => {\n\t\t\t\tthrowIfAborted(operationSignal);\n\t\t\t\tawait this.readOrCreateGeneration(operationSignal);\n\t\t\t\tconst next = validCreatedId(this.createId());\n\t\t\t\tawait this.publishGeneration(next);\n\t\t\t\tthis.writerId = validCreatedId(this.createId());\n\t\t\t\tconst current = await readGenerationMarker(path.join(this.path, \"current\"));\n\t\t\t\tawait ensurePrivateDirectory(this.generationPath(current));\n\t\t\t\tif (!(await this.cleanupObsoleteGenerations(operationSignal))) {\n\t\t\t\t\tresult = { cleanupIncomplete: true };\n\t\t\t\t}\n\t\t\t}),\n\t\t).then(() => result);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.lifecycle.abort(new DOMException(\"Analytics storage closed\", \"AbortError\"));\n\t\tawait this.mutationTail.catch(() => undefined);\n\t}\n\n\tprivate enqueueMutation(operation: () => Promise<void>): Promise<void> {\n\t\tconst result = this.mutationTail.then(operation);\n\t\tthis.mutationTail = result.catch(() => undefined);\n\t\treturn result;\n\t}\n\n\tprivate async appendFrame(frame: string, signal: AbortSignal): Promise<void> {\n\t\tthrowIfAborted(signal);\n\t\tlet obsoleteDirectory: string | undefined;\n\t\tfor (let attempt = 0; attempt < 3; attempt += 1) {\n\t\t\tconst generation = await this.readOrCreateGeneration(signal);\n\t\t\tconst directory = this.generationPath(generation);\n\t\t\tawait ensurePrivateDirectory(directory);\n\t\t\tconst filePath = path.join(directory, `${this.writerId}.jsonl`);\n\t\t\tawait assertOptionalPrivateRegularFile(filePath);\n\t\t\tthrowIfAborted(signal);\n\t\t\tawait this.beforeAppend?.(generation, signal);\n\t\t\tthrowIfAborted(signal);\n\t\t\ttry {\n\t\t\t\tawait writeFile(filePath, frame, {\n\t\t\t\t\tencoding: \"utf8\",\n\t\t\t\t\tflag: \"a\",\n\t\t\t\t\tmode: 0o600,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\tif (process.platform !== \"win32\") await chmod(filePath, 0o600);\n\t\t\t\tconst current = await readGenerationMarker(path.join(this.path, \"current\"), signal);\n\t\t\t\tif (current === generation) {\n\t\t\t\t\tif (obsoleteDirectory) {\n\t\t\t\t\t\tawait cleanupGeneration(obsoleteDirectory, signal).catch(() => undefined);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tobsoleteDirectory = directory;\n\t\t\t} catch (error) {\n\t\t\t\tthis.writerId = validCreatedId(this.createId());\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tif (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n\t\t\t}\n\t\t}\n\t\tthrow new AnalyticsGenerationChangedError();\n\t}\n\n\tprivate async readOrCreateGeneration(signal?: AbortSignal): Promise<string> {\n\t\tthrowIfAborted(signal);\n\t\tawait ensurePrivateDirectory(this.path);\n\t\tawait ensurePrivateDirectory(path.join(this.path, \"generations\"));\n\t\tconst markerPath = path.join(this.path, \"current\");\n\t\tfor (let attempt = 0; attempt < 3; attempt += 1) {\n\t\t\tlet generation: string;\n\t\t\ttry {\n\t\t\t\tgeneration = await readGenerationMarker(markerPath, signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n\t\t\t\tgeneration = validCreatedId(this.createId());\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\ttry {\n\t\t\t\t\tawait createPrivateFile(markerPath, `${generation}\\n`);\n\t\t\t\t} catch (createError) {\n\t\t\t\t\tif (!isNodeError(createError) || createError.code !== \"EEXIST\") throw createError;\n\t\t\t\t\tgeneration = await readGenerationMarker(markerPath, signal);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait ensurePrivateDirectory(this.generationPath(generation));\n\t\t\tconst current = await readGenerationMarker(markerPath, signal);\n\t\t\tif (current === generation) return generation;\n\t\t}\n\t\tthrow new AnalyticsGenerationChangedError();\n\t}\n\n\tprivate async publishGeneration(generation: string): Promise<void> {\n\t\tconst markerPath = path.join(this.path, \"current\");\n\t\tconst temporaryPath = path.join(this.path, `.current.${validCreatedId(this.createId())}.tmp`);\n\t\tawait createPrivateFile(temporaryPath, `${generation}\\n`);\n\t\ttry {\n\t\t\tawait rename(temporaryPath, markerPath);\n\t\t\tif (process.platform !== \"win32\") await chmod(markerPath, 0o600);\n\t\t} catch (error) {\n\t\t\tawait rm(temporaryPath, { force: true }).catch(() => undefined);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async cleanupObsoleteGenerations(signal?: AbortSignal): Promise<boolean> {\n\t\tlet complete = true;\n\t\tconst root = path.join(this.path, \"generations\");\n\t\tfor (const entry of await readdir(root, { withFileTypes: true })) {\n\t\t\tconst active = await readGenerationMarker(path.join(this.path, \"current\"));\n\t\t\tif (entry.name === active) continue;\n\t\t\tif (!entry.isDirectory() || !GENERATION_PATTERN.test(entry.name)) {\n\t\t\t\tcomplete = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait cleanupGeneration(path.join(root, entry.name), signal, this.beforeCleanupEntry);\n\t\t\t} catch {\n\t\t\t\tcomplete = false;\n\t\t\t\tif (signal?.aborted) break;\n\t\t\t}\n\t\t}\n\t\tconst active = await readGenerationMarker(path.join(this.path, \"current\"));\n\t\tconst remaining = await readdir(root, { withFileTypes: true });\n\t\treturn complete && remaining.every((entry) => entry.isDirectory() && entry.name === active);\n\t}\n\n\tprivate async assertGenerationUnchanged(generation: string, signal?: AbortSignal): Promise<void> {\n\t\tconst current = await readGenerationMarker(path.join(this.path, \"current\"), signal);\n\t\tif (current !== generation) throw new AnalyticsGenerationChangedError();\n\t}\n\n\tprivate generationPath(generation: string): string {\n\t\treturn path.join(this.path, \"generations\", generation);\n\t}\n}\n\nasync function* readFrames(filePath: string, signal?: AbortSignal): AsyncIterable<SettledRun> {\n\tlet pending = \"\";\n\tconst stream = createReadStream(filePath, { encoding: \"utf8\", signal });\n\tfor await (const chunk of stream) {\n\t\tthrowIfAborted(signal);\n\t\tpending += String(chunk);\n\t\twhile (true) {\n\t\t\tconst newline = pending.indexOf(\"\\n\");\n\t\t\tif (newline < 0) break;\n\t\t\tconst line = pending.slice(0, newline);\n\t\t\tpending = pending.slice(newline + 1);\n\t\t\tif (!line) continue;\n\t\t\tyield decodeStoredRun(line);\n\t\t}\n\t\tif (Buffer.byteLength(pending) > MAX_STORED_RUN_BYTES) {\n\t\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to read safely.\");\n\t\t}\n\t}\n\t// A writer always terminates complete frames with a newline. An unterminated tail is a\n\t// crash residue and is ignored; this writer file will not be reused after its process exits.\n}\n\nasync function readGenerationMarker(markerPath: string, signal?: AbortSignal): Promise<string> {\n\tawait assertPrivateRegularFile(markerPath);\n\tthrowIfAborted(signal);\n\tconst value = (await readFile(markerPath, { encoding: \"utf8\", signal })).trim();\n\tif (!GENERATION_PATTERN.test(value)) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics generation marker is invalid.\");\n\t}\n\treturn value;\n}\n\nasync function ensurePrivateDirectory(directoryPath: string): Promise<void> {\n\ttry {\n\t\tconst metadata = await lstat(directoryPath);\n\t\tif (!metadata.isDirectory() || metadata.isSymbolicLink()) {\n\t\t\tthrow new Error(\"Analytics storage paths must be regular directories, not links.\");\n\t\t}\n\t} catch (error) {\n\t\tif (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n\t\tawait mkdir(directoryPath, { recursive: true, mode: 0o700 });\n\t\tconst metadata = await lstat(directoryPath);\n\t\tif (!metadata.isDirectory() || metadata.isSymbolicLink()) {\n\t\t\tthrow new Error(\"Analytics storage paths must be regular directories, not links.\");\n\t\t}\n\t}\n\tif (process.platform !== \"win32\") await chmod(directoryPath, 0o700);\n}\n\nasync function assertOptionalPrivateRegularFile(filePath: string): Promise<void> {\n\ttry {\n\t\tawait assertPrivateRegularFile(filePath);\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") return;\n\t\tthrow error;\n\t}\n}\n\nasync function assertPrivateRegularFile(filePath: string): Promise<void> {\n\tconst metadata = await lstat(filePath);\n\tif (!metadata.isFile() || metadata.isSymbolicLink()) {\n\t\tthrow new Error(\"Analytics storage files must be regular files, not links.\");\n\t}\n\tif (process.platform !== \"win32\") await chmod(filePath, 0o600);\n}\n\nasync function createPrivateFile(filePath: string, content: string): Promise<void> {\n\tconst handle = await open(filePath, \"wx\", 0o600);\n\ttry {\n\t\tawait handle.writeFile(content, \"utf8\");\n\t\tawait handle.sync();\n\t} finally {\n\t\tawait handle.close();\n\t}\n}\n\nasync function cleanupGeneration(\n\tdirectoryPath: string,\n\tsignal?: AbortSignal,\n\tbeforeEntry?: (signal?: AbortSignal) => Promise<void>,\n): Promise<void> {\n\tthrowIfAborted(signal);\n\tlet entries: Dirent[];\n\ttry {\n\t\tentries = await readdir(directoryPath, { withFileTypes: true });\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") return;\n\t\tthrow error;\n\t}\n\tfor (const entry of entries) {\n\t\tthrowIfAborted(signal);\n\t\tawait beforeEntry?.(signal);\n\t\tthrowIfAborted(signal);\n\t\tif (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n\t\t\tthrow new Error(\"Analytics generation contains an unexpected storage entry.\");\n\t\t}\n\t\tawait unlink(path.join(directoryPath, entry.name));\n\t}\n\tthrowIfAborted(signal);\n\tawait rmdir(directoryPath);\n}\n\nasync function withLinkedSignals<T>(\n\tcallerSignal: AbortSignal | undefined,\n\tlifecycleSignal: AbortSignal,\n\toperation: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n\tthrowIfAborted(callerSignal);\n\tthrowIfAborted(lifecycleSignal);\n\tconst controller = new AbortController();\n\tconst abort = (signal: AbortSignal) =>\n\t\tcontroller.abort(\n\t\t\tsignal.reason ?? new DOMException(\"Analytics operation aborted\", \"AbortError\"),\n\t\t);\n\tconst callerAbort = () => callerSignal && abort(callerSignal);\n\tconst lifecycleAbort = () => abort(lifecycleSignal);\n\tcallerSignal?.addEventListener(\"abort\", callerAbort, { once: true });\n\tlifecycleSignal.addEventListener(\"abort\", lifecycleAbort, { once: true });\n\ttry {\n\t\treturn await operation(controller.signal);\n\t} finally {\n\t\tcallerSignal?.removeEventListener(\"abort\", callerAbort);\n\t\tlifecycleSignal.removeEventListener(\"abort\", lifecycleAbort);\n\t}\n}\n\nasync function withDeadline<T>(\n\tcallerSignal: AbortSignal | undefined,\n\tlifecycleSignal: AbortSignal,\n\ttimeoutMs: number,\n\toperation: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n\tthrowIfAborted(callerSignal);\n\tthrowIfAborted(lifecycleSignal);\n\tconst controller = new AbortController();\n\tconst abort = (signal: AbortSignal) =>\n\t\tcontroller.abort(\n\t\t\tsignal.reason ?? new DOMException(\"Analytics operation aborted\", \"AbortError\"),\n\t\t);\n\tconst callerAbort = () => callerSignal && abort(callerSignal);\n\tconst lifecycleAbort = () => abort(lifecycleSignal);\n\tcallerSignal?.addEventListener(\"abort\", callerAbort, { once: true });\n\tlifecycleSignal.addEventListener(\"abort\", lifecycleAbort, { once: true });\n\tconst timer = setTimeout(\n\t\t() => controller.abort(new DOMException(\"Analytics write timed out\", \"TimeoutError\")),\n\t\tMath.max(1, timeoutMs),\n\t);\n\ttry {\n\t\treturn await operation(controller.signal);\n\t} catch (error) {\n\t\tif (\n\t\t\tcontroller.signal.aborted &&\n\t\t\terror instanceof Error &&\n\t\t\terror.name === \"AbortError\" &&\n\t\t\terror.cause === controller.signal.reason\n\t\t) {\n\t\t\tthrow controller.signal.reason;\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tclearTimeout(timer);\n\t\tcallerSignal?.removeEventListener(\"abort\", callerAbort);\n\t\tlifecycleSignal.removeEventListener(\"abort\", lifecycleAbort);\n\t}\n}\n\nasync function yieldToEventLoop(signal?: AbortSignal): Promise<void> {\n\tawait new Promise<void>((resolve) => setImmediate(resolve));\n\tthrowIfAborted(signal);\n}\n\nfunction validCreatedId(value: string): string {\n\tif (!GENERATION_PATTERN.test(value)) throw new Error(\"Analytics storage received an invalid ID.\");\n\treturn value;\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n\tif (signal?.aborted) {\n\t\tthrow signal.reason ?? new DOMException(\"Analytics operation aborted\", \"AbortError\");\n\t}\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n", "import type {\n\tGenerationOutcome,\n\tGenerationRecord,\n\tProviderErrorCategory,\n\tProviderErrorRecord,\n\tProviderResponseRecord,\n\tRunOutcome,\n\tSettledRun,\n\tSkillActivationRecord,\n\tToolCallRecord,\n} from \"../types.js\";\n\nexport const MAX_STORED_RUN_BYTES = 1024 * 1024;\nconst MAX_STRING_LENGTH = 4096;\nconst MAX_NESTED_RECORDS = 20_000;\nconst TRIGGER_SOURCES = [\"interactive\", \"rpc\", \"extension\", \"unknown\"] as const;\nconst RUN_OUTCOMES = [\n\t\"success\",\n\t\"recovered_success\",\n\t\"error\",\n\t\"aborted\",\n\t\"length\",\n\t\"interrupted\",\n] as const;\nconst GENERATION_OUTCOMES = [\n\t\"pending\",\n\t\"stop\",\n\t\"tool_use\",\n\t\"error\",\n\t\"aborted\",\n\t\"length\",\n\t\"interrupted\",\n] as const;\nconst ERROR_CATEGORIES = [\n\t\"dns\",\n\t\"timeout\",\n\t\"connection_refused\",\n\t\"connection_reset\",\n\t\"tls\",\n\t\"network_other\",\n\t\"provider_other\",\n] as const;\n\nexport class AnalyticsStorageFormatError extends Error {\n\tconstructor(message: string, options: { cause?: unknown } = {}) {\n\t\tsuper(message, options);\n\t\tthis.name = \"AnalyticsStorageFormatError\";\n\t}\n}\n\nexport function encodeStoredRun(run: SettledRun): string {\n\tconst encoded = `${JSON.stringify({\n\t\tformatVersion: 1,\n\t\trun: parseRun(run, { remaining: MAX_NESTED_RECORDS }),\n\t})}\\n`;\n\tif (Buffer.byteLength(encoded) > MAX_STORED_RUN_BYTES) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to store safely.\");\n\t}\n\treturn encoded;\n}\n\nexport function decodeStoredRun(line: string): SettledRun {\n\tif (Buffer.byteLength(line) > MAX_STORED_RUN_BYTES) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to read safely.\");\n\t}\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(line);\n\t} catch (error) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record contains invalid JSON.\", {\n\t\t\tcause: error,\n\t\t});\n\t}\n\tconst envelope = asRecord(value, \"analytics record\");\n\tif (envelope.formatVersion !== 1) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record uses an unsupported format version.\");\n\t}\n\treturn parseRun(envelope.run, { remaining: MAX_NESTED_RECORDS });\n}\n\ninterface ParseBudget {\n\tremaining: number;\n}\n\nfunction parseRun(value: unknown, budget: ParseBudget): SettledRun {\n\tconst run = asRecord(value, \"run\");\n\treturn {\n\t\tid: requiredString(run.id, \"run.id\"),\n\t\tstartedAtMs: timestampValue(run.startedAtMs, \"run.startedAtMs\"),\n\t\tfinishedAtMs: timestampValue(run.finishedAtMs, \"run.finishedAtMs\"),\n\t\tdurationMs: durationValue(run.durationMs, \"run.durationMs\"),\n\t\ttriggerSource: enumValue(run.triggerSource, TRIGGER_SOURCES, \"run.triggerSource\"),\n\t\t...optionalProperty(\n\t\t\t\"initialProvider\",\n\t\t\toptionalString(run.initialProvider, \"run.initialProvider\"),\n\t\t),\n\t\t...optionalProperty(\"initialModel\", optionalString(run.initialModel, \"run.initialModel\")),\n\t\toutcome: enumValue(run.outcome, RUN_OUTCOMES, \"run.outcome\") as RunOutcome,\n\t\tattemptCount: boundedCount(run.attemptCount, \"run.attemptCount\"),\n\t\tgenerations: boundedArray(run.generations, \"run.generations\", budget).map((item, index) =>\n\t\t\tparseGeneration(item, index, budget),\n\t\t),\n\t\ttools: boundedArray(run.tools, \"run.tools\", budget).map(parseTool),\n\t\tskills: boundedArray(run.skills, \"run.skills\", budget).map(parseSkill),\n\t\tproviderErrors: boundedArray(run.providerErrors, \"run.providerErrors\", budget).map(\n\t\t\tparseProviderError,\n\t\t),\n\t\ttoolErrorCount: boundedCount(run.toolErrorCount, \"run.toolErrorCount\"),\n\t\tproviderErrorCount: boundedCount(run.providerErrorCount, \"run.providerErrorCount\"),\n\t\trecoveredErrorCount: boundedCount(run.recoveredErrorCount, \"run.recoveredErrorCount\"),\n\t};\n}\n\nfunction parseGeneration(value: unknown, index: number, budget: ParseBudget): GenerationRecord {\n\tconst item = asRecord(value, `run.generations[${index}]`);\n\tconst prefix = `run.generations[${index}]`;\n\treturn {\n\t\tid: requiredString(item.id, `${prefix}.id`),\n\t\tordinal: boundedCount(item.ordinal, `${prefix}.ordinal`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t\t...optionalProperty(\n\t\t\t\"thinkingLevel\",\n\t\t\toptionalString(item.thinkingLevel, `${prefix}.thinkingLevel`),\n\t\t),\n\t\tstartedAtMs: timestampValue(item.startedAtMs, `${prefix}.startedAtMs`),\n\t\t...optionalProperty(\n\t\t\t\"finishedAtMs\",\n\t\t\toptionalTimestamp(item.finishedAtMs, `${prefix}.finishedAtMs`),\n\t\t),\n\t\t...optionalProperty(\"durationMs\", optionalDuration(item.durationMs, `${prefix}.durationMs`)),\n\t\t...optionalProperty(\"stopReason\", optionalString(item.stopReason, `${prefix}.stopReason`)),\n\t\toutcome: enumValue(item.outcome, GENERATION_OUTCOMES, `${prefix}.outcome`) as GenerationOutcome,\n\t\tresponses: boundedArray(item.responses, `${prefix}.responses`, budget).map(\n\t\t\tparseProviderResponse,\n\t\t),\n\t};\n}\n\nfunction parseProviderResponse(value: unknown, index: number): ProviderResponseRecord {\n\tconst item = asRecord(value, `provider response ${index}`);\n\treturn {\n\t\tordinal: boundedCount(item.ordinal, \"providerResponse.ordinal\"),\n\t\toccurredAtMs: timestampValue(item.occurredAtMs, \"providerResponse.occurredAtMs\"),\n\t\tstatus: boundedInteger(item.status, \"providerResponse.status\", 999),\n\t};\n}\n\nfunction parseTool(value: unknown, index: number): ToolCallRecord {\n\tconst item = asRecord(value, `run.tools[${index}]`);\n\tconst prefix = `run.tools[${index}]`;\n\tconst ordinal = boundedCount(item.ordinal, `${prefix}.ordinal`);\n\treturn {\n\t\tid: `tool-${ordinal}`,\n\t\tordinal,\n\t\tname: requiredString(item.name, `${prefix}.name`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t\tstartedAtMs: timestampValue(item.startedAtMs, `${prefix}.startedAtMs`),\n\t\t...optionalProperty(\n\t\t\t\"finishedAtMs\",\n\t\t\toptionalTimestamp(item.finishedAtMs, `${prefix}.finishedAtMs`),\n\t\t),\n\t\t...optionalProperty(\"durationMs\", optionalDuration(item.durationMs, `${prefix}.durationMs`)),\n\t\tisError: booleanValue(item.isError, `${prefix}.isError`),\n\t\tcompletionState: enumValue(\n\t\t\titem.completionState,\n\t\t\t[\"running\", \"finished\", \"interrupted\"] as const,\n\t\t\t`${prefix}.completionState`,\n\t\t),\n\t};\n}\n\nfunction parseSkill(value: unknown, index: number): SkillActivationRecord {\n\tconst item = asRecord(value, `run.skills[${index}]`);\n\tconst prefix = `run.skills[${index}]`;\n\treturn {\n\t\tid: requiredString(item.id, `${prefix}.id`),\n\t\tname: requiredString(item.name, `${prefix}.name`),\n\t\tinitiatedBy: enumValue(item.initiatedBy, [\"user\", \"model\"] as const, `${prefix}.initiatedBy`),\n\t\toccurredAtMs: timestampValue(item.occurredAtMs, `${prefix}.occurredAtMs`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t};\n}\n\nfunction parseProviderError(value: unknown, index: number): ProviderErrorRecord {\n\tconst item = asRecord(value, `run.providerErrors[${index}]`);\n\tconst prefix = `run.providerErrors[${index}]`;\n\treturn {\n\t\tid: requiredString(item.id, `${prefix}.id`),\n\t\t...optionalProperty(\n\t\t\t\"generationId\",\n\t\t\toptionalString(item.generationId, `${prefix}.generationId`),\n\t\t),\n\t\toccurredAtMs: timestampValue(item.occurredAtMs, `${prefix}.occurredAtMs`),\n\t\t...optionalProperty(\"provider\", optionalString(item.provider, `${prefix}.provider`)),\n\t\t...optionalProperty(\"model\", optionalString(item.model, `${prefix}.model`)),\n\t\tcategory: enumValue(\n\t\t\titem.category,\n\t\t\tERROR_CATEGORIES,\n\t\t\t`${prefix}.category`,\n\t\t) as ProviderErrorCategory,\n\t\trecovered: booleanValue(item.recovered, `${prefix}.recovered`),\n\t\tterminal: booleanValue(item.terminal, `${prefix}.terminal`),\n\t};\n}\n\nfunction asRecord(value: unknown, name: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) invalid(name);\n\treturn value as Record<string, unknown>;\n}\n\nfunction boundedArray(value: unknown, name: string, budget: ParseBudget): unknown[] {\n\tif (!Array.isArray(value)) invalid(name);\n\tbudget.remaining -= value.length;\n\tif (budget.remaining < 0) {\n\t\tthrow new AnalyticsStorageFormatError(\"Analytics record is too large to process safely.\");\n\t}\n\treturn value;\n}\n\nfunction requiredString(value: unknown, name: string): string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > MAX_STRING_LENGTH) {\n\t\tinvalid(name);\n\t}\n\treturn value;\n}\n\nfunction optionalString(value: unknown, name: string): string | undefined {\n\treturn value === undefined ? undefined : requiredString(value, name);\n}\n\nfunction boundedInteger(value: unknown, name: string, maximum: number): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0 || value > maximum) {\n\t\tinvalid(name);\n\t}\n\treturn value;\n}\n\nfunction timestampValue(value: unknown, name: string): number {\n\treturn boundedInteger(value, name, Number.MAX_SAFE_INTEGER);\n}\n\nfunction optionalTimestamp(value: unknown, name: string): number | undefined {\n\treturn value === undefined ? undefined : timestampValue(value, name);\n}\n\nfunction durationValue(value: unknown, name: string): number {\n\treturn boundedInteger(value, name, Math.floor(Number.MAX_SAFE_INTEGER / MAX_NESTED_RECORDS));\n}\n\nfunction optionalDuration(value: unknown, name: string): number | undefined {\n\treturn value === undefined ? undefined : durationValue(value, name);\n}\n\nfunction boundedCount(value: unknown, name: string): number {\n\treturn boundedInteger(value, name, MAX_NESTED_RECORDS);\n}\n\nfunction booleanValue(value: unknown, name: string): boolean {\n\tif (typeof value !== \"boolean\") invalid(name);\n\treturn value;\n}\n\nfunction enumValue<const T extends readonly string[]>(\n\tvalue: unknown,\n\tvalues: T,\n\tname: string,\n): T[number] {\n\tif (typeof value !== \"string\" || !values.includes(value)) invalid(name);\n\treturn value as T[number];\n}\n\nfunction optionalProperty<K extends string, T>(key: K, value: T | undefined): { [P in K]?: T } {\n\treturn value === undefined ? {} : ({ [key]: value } as { [P in K]?: T });\n}\n\nfunction invalid(name: string): never {\n\tthrow new AnalyticsStorageFormatError(`Analytics record has an invalid ${name}.`);\n}\n", "import type { SettledRun } from \"../types.js\";\nimport {\n\tAnalyticsGenerationChangedError,\n\tAnalyticsRunFiles,\n\ttype ClearAnalyticsResult,\n} from \"./files.js\";\nimport { type AnalyticsSnapshot, querySnapshot, type TimeRange } from \"./queries.js\";\n\nexport class AnalyticsStore {\n\tprivate readonly files: AnalyticsRunFiles;\n\n\tconstructor(\n\t\trootPath: string,\n\t\tdependencies: {\n\t\t\tfiles?: AnalyticsRunFiles;\n\t\t\tcreateId?: () => string;\n\t\t\twriteTimeoutMs?: number;\n\t\t} = {},\n\t) {\n\t\tthis.files =\n\t\t\tdependencies.files ??\n\t\t\tnew AnalyticsRunFiles(rootPath, {\n\t\t\t\tcreateId: dependencies.createId,\n\t\t\t\twriteTimeoutMs: dependencies.writeTimeoutMs,\n\t\t\t});\n\t}\n\n\tget path(): string {\n\t\treturn this.files.path;\n\t}\n\n\trecordRun(run: SettledRun, signal?: AbortSignal): Promise<void> {\n\t\treturn this.files.append(run, signal);\n\t}\n\n\tasync getSnapshot(range: TimeRange, signal?: AbortSignal): Promise<AnalyticsSnapshot> {\n\t\tfor (let attempt = 0; attempt < 2; attempt += 1) {\n\t\t\ttry {\n\t\t\t\treturn await querySnapshot(this.files.read(signal), range, signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof AnalyticsGenerationChangedError) || attempt > 0) throw error;\n\t\t\t}\n\t\t}\n\t\tthrow new AnalyticsGenerationChangedError();\n\t}\n\n\tclearAll(signal?: AbortSignal): Promise<ClearAnalyticsResult> {\n\t\treturn this.files.clear(signal);\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.files.close();\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["randomUUID", "path", "randomUUID", "path", "ERROR_CATEGORIES", "path", "randomUUID", "throwIfAborted", "active", "randomUUID", "path"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-analytics",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.8",
|
|
4
4
|
"description": "Local-first usage analytics for Pi models, skills, tools, and reliability.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,9 +24,6 @@
|
|
|
24
24
|
"./dist/index.ts"
|
|
25
25
|
]
|
|
26
26
|
},
|
|
27
|
-
"piExtension": {
|
|
28
|
-
"lifecycle": "experimental"
|
|
29
|
-
},
|
|
30
27
|
"scripts": {
|
|
31
28
|
"build": "node scripts/build-runtime.mjs",
|
|
32
29
|
"check": "npm run build && biome check --vcs-use-ignore-file=false src test scripts package.json tsconfig.json README.md && npm run typecheck",
|
|
@@ -41,10 +38,10 @@
|
|
|
41
38
|
"@earendil-works/pi-coding-agent": "*"
|
|
42
39
|
},
|
|
43
40
|
"devDependencies": {
|
|
44
|
-
"@biomejs/biome": "2.5.
|
|
45
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
46
|
-
"@types/node": "26.
|
|
47
|
-
"esbuild": "0.28.
|
|
41
|
+
"@biomejs/biome": "2.5.11",
|
|
42
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
43
|
+
"@types/node": "26.4.0",
|
|
44
|
+
"esbuild": "0.28.2",
|
|
48
45
|
"typescript": "7.0.2"
|
|
49
46
|
},
|
|
50
47
|
"repository": {
|
package/src/analytics.ts
CHANGED
|
@@ -13,7 +13,6 @@ import type { AnalyticsSnapshot, TimeRange } from "./storage/queries.js";
|
|
|
13
13
|
import { AnalyticsStore } from "./storage/store.js";
|
|
14
14
|
import type { ModelIdentity, SettledRun, TriggerSource } from "./types.js";
|
|
15
15
|
|
|
16
|
-
const EXPERIMENTAL_WARNING = "pi-analytics is experimental; its metrics and dashboard may change.";
|
|
17
16
|
const STORAGE_DIRECTORY = "pi-analytics";
|
|
18
17
|
|
|
19
18
|
export interface AnalyticsStorePort {
|
|
@@ -80,7 +79,6 @@ export function createAnalyticsExtension(
|
|
|
80
79
|
|
|
81
80
|
pi.on("session_start", (_event, ctx) => {
|
|
82
81
|
++sessionGeneration;
|
|
83
|
-
if (ctx.hasUI) ctx.ui.notify(EXPERIMENTAL_WARNING, "warning");
|
|
84
82
|
const previousStore = store;
|
|
85
83
|
sessionController.abort(new DOMException("Analytics session replaced", "AbortError"));
|
|
86
84
|
if (previousStore) retire(previousStore);
|