@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 CHANGED
@@ -1,23 +1,17 @@
1
- # 📈 pi-analytics — Local Analytics for Pi
1
+ # 📈 pi-analytics — Understand Pi Activity Without Sending Data Away
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@narumitw/pi-analytics)](https://www.npmjs.com/package/@narumitw/pi-analytics) [![Pi extension](https://img.shields.io/badge/Pi-extension-blue)](https://pi.dev) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
4
4
 
5
- > [!WARNING]
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
- - Starts collecting settled Pi response cycles after installation with no configuration or startup I/O.
13
- - Breaks skill activations down by explicit user invocation, model loading, provider, and model.
14
- - Counts tool calls, failures, average duration, and model attribution.
15
- - Reports logical LLM calls per response with average, median, P95, maximum, and distribution buckets.
16
- - Separates HTTP 429/5xx responses, conservative connection-error categories, recovered errors, and terminal provider failures.
17
- - Offers Today, rolling 7-day, rolling 30-day, and all-time views through one `/analytics` TUI/RPC dashboard.
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
- Try a local checkout from the repository root:
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 storage implementation uses Node's built-in filesystem APIs and has no native database dependency.
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
- `just try analytics` runs that build automatically.
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 time range or browse Skills, Tools, Provider reliability, Response cycles, and Data & privacy. Only fully settled cycles are included; active work is omitted.
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`. Automatic retries, overflow-compaction recovery, tool follow-ups, and queued continuations before settlement stay in that cycle.
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. A provider may make several HTTP attempts inside it, so `429 → 429 → 200` is one LLM call, three observed HTTP responses, two provider errors, and a recovered 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 is associated with an active or subsequently started response cycle. This includes skill commands queued while Pi is streaming. It is **Model initiated** when the built-in `read` tool successfully loads the exact canonical `SKILL.md` path Pi discovered. A skill is counted at most once per response cycle, and explicit user use takes precedence.
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 a post-chain acceptance event for input observers. Non-standard loading such as `bash` plus `cat SKILL.md`, unsuccessful reads, and provider behavior invisible to Pi are not counted.
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`. The extension stores the tool name, model attribution, timing, completion state, and final error flag. It cannot reliably distinguish another extension blocking a call from every other tool error, so both appear as errors.
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. The dashboard therefore labels these values as **observed provider errors**. It reports HTTP 429 and 5xx counts; conservative DNS, timeout, connection, TLS, network, and provider categories; recovered errors; and terminal failures. Error messages are classified in memory and discarded.
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
- ## 💬 Command
101
+ ## 💬 Commands
96
102
 
97
103
  ```text
98
104
  /analytics
99
105
  ```
100
106
 
101
- The command accepts no arguments. TUI mode uses the full dashboard; RPC mode adapts the same standard screens to dialogs. Print and JSON modes reject the interactive command observably instead of writing ad hoc protocol output.
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. Skills and Tools are searchable browse views with details and model breakdowns. Escape goes Back from nested screens and closes the root. Ctrl+C closes the menu. Data deletion uses Pi TUI Kit's standalone confirmation: Back keeps the dashboard open, Ctrl+C closes it in TUI mode, and cancellation never clears data.
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
- ## 🔐 Local data and privacy
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. On Unix, directories are restricted to mode `0700` and files to `0600`. Linked storage roots, markers, and writer files are rejected.
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. Provider-supplied tool-call IDs are replaced with local ordinals before publication.
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 settled response is one versioned, newline-terminated frame. Frames larger than 1 MiB are dropped. Local writes receive a 500 ms cancellation deadline; Node filesystem cancellation is best-effort, so an operating-system request that has already begun may still finish. The extension reports the first failed or timed-out write and a later recovery without exposing filesystem errors.
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. A crash-truncated final frame is ignored; completed malformed frames and unsupported format versions fail closed without replacing existing files.
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 atomically publish a fresh active generation. Other Pi processes observe that generation before their next write. Records racing with Clear may land immediately before or after the generation switch.
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 the previous generation. If another process still has an obsolete file in use, Clear remains logically complete and reports that physical cleanup is incomplete; stop other Pi processes and clear again. Clearing files is not a secure-erasure guarantee for underlying storage media.
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 deliberately does not open, import, migrate, delete, or rewrite those files, so startup cannot re-enter the old native database path. New analytics start empty.
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. If it does not matter, stop every old Pi process before deleting both files manually. Never copy or remove only the main DB while an old process may still own its WAL.
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. A failed or interrupted local write may be omitted.
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. See [`LICENSE`](./LICENSE).
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.7",
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.8",
45
- "@earendil-works/pi-coding-agent": "0.84.2",
46
- "@types/node": "26.2.0",
47
- "esbuild": "0.28.1",
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);