@pi-unipi/unipi 2.10.2 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +23 -23
  3. package/packages/ask-user/package.json +2 -2
  4. package/packages/autocomplete/package.json +1 -1
  5. package/packages/background-tasks/package.json +2 -2
  6. package/packages/btw/package.json +2 -2
  7. package/packages/compactor/package.json +3 -3
  8. package/packages/core/package.json +1 -1
  9. package/packages/footer/package.json +2 -2
  10. package/packages/image/package.json +2 -2
  11. package/packages/info-screen/package.json +2 -2
  12. package/packages/input-shortcuts/package.json +2 -2
  13. package/packages/kanboard/package.json +2 -2
  14. package/packages/mcp/package.json +2 -2
  15. package/packages/memory/package.json +3 -3
  16. package/packages/milestone/package.json +2 -2
  17. package/packages/notify/package.json +2 -2
  18. package/packages/ralph/package.json +3 -3
  19. package/packages/subagents/package.json +2 -2
  20. package/packages/trajectory/README.md +23 -7
  21. package/packages/trajectory/index.ts +23 -3
  22. package/packages/trajectory/package.json +1 -1
  23. package/packages/trajectory/src/capture.ts +150 -30
  24. package/packages/trajectory/src/prefix-integrity.ts +213 -0
  25. package/packages/trajectory/src/project.ts +57 -5
  26. package/packages/trajectory/src/server.ts +10 -3
  27. package/packages/trajectory/src/telemetry.ts +79 -18
  28. package/packages/trajectory/src/tracer.ts +401 -0
  29. package/packages/trajectory/src/ui.ts +14 -12
  30. package/packages/unipi/bundled.js +1554 -769
  31. package/packages/unipi/index.ts +25 -22
  32. package/packages/updater/package.json +2 -2
  33. package/packages/utility/package.json +2 -2
  34. package/packages/web-api/package.json +2 -2
  35. package/packages/workflow/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.11.0] — 2026-08-26
10
+
11
+ ### Added
12
+
13
+ - `trajectory`: full UniPi-owned package attribution for lifecycle hooks, command handlers, tool execution, mutating `ExtensionAPI` calls, context/session actions, and custom EventBus delivery, including duration, result fingerprints, errors, and bounded mutation evidence.
14
+ - `trajectory`: per-request prefix-integrity verdicts (`first_request`, `identical_retry`, `prefix_extended`, `boundary`, `violation`) over final serialized provider payloads. Violations identify the first changed message index/path and separately report system prompt, tool schema/order, provider route, thinking level, and envelope drift.
15
+ - `trajectory`: explicit cache epochs for compaction, tree navigation, model changes, and thinking-level changes; append-only enforcement resumes immediately after each boundary.
16
+ - `trajectory`: **UniPi** and **Violations** filters plus Trace, Integrity, and Attribution inspector tabs.
17
+
18
+ ### Changed
19
+
20
+ - Umbrella `@pi-unipi/unipi` now loads every owned module through a package-scoped tracing API and keeps trajectory as the final unwrapped sink. Unrelated third-party extensions are intentionally excluded from attribution.
21
+ - Trajectory is now context-focused: the ledger includes provider-visible messages, system prompts, serialized requests, prefix verdicts, and only UniPi operations that mutate context or establish a cache epoch. Inert lifecycle hooks, registrations, notifications, response headers, and stream deltas are excluded.
22
+ - Trajectory live updates now cache the telemetry tail and projected snapshot, read only the last 5 MB of existing sidecars, use conditional 1.5-second polling, and avoid rerendering unchanged pages.
23
+
9
24
  ## [2.10.2] — 2026-08-25
10
25
 
11
26
  Follow-up to 2.10.1: the 2.10.1 tarballs shipped with `@pi-unipi/*` cross-dependency pins still pointing at `2.10.0`, so installing `@pi-unipi/unipi@2.10.1` resolved the old `@pi-unipi/trajectory@2.10.0` (without the auto-completion fix) instead of `2.10.1`. This release re-synchronizes every cross-pin to `2.10.2` and republishes the full synchronized set.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/unipi",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "All-in-one extension suite for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -82,28 +82,28 @@
82
82
  "typebox": "^1.1.38"
83
83
  },
84
84
  "dependencies": {
85
- "@pi-unipi/ask-user": "2.10.2",
86
- "@pi-unipi/background-tasks": "2.10.2",
87
- "@pi-unipi/btw": "2.10.2",
88
- "@pi-unipi/command-enchantment": "2.10.2",
89
- "@pi-unipi/compactor": "2.10.2",
90
- "@pi-unipi/core": "2.10.2",
91
- "@pi-unipi/footer": "2.10.2",
92
- "@pi-unipi/image": "2.10.2",
93
- "@pi-unipi/info-screen": "2.10.2",
94
- "@pi-unipi/input-shortcuts": "2.10.2",
95
- "@pi-unipi/kanboard": "2.10.2",
96
- "@pi-unipi/mcp": "2.10.2",
97
- "@pi-unipi/memory": "2.10.2",
98
- "@pi-unipi/milestone": "2.10.2",
99
- "@pi-unipi/notify": "2.10.2",
100
- "@pi-unipi/ralph": "2.10.2",
101
- "@pi-unipi/subagents": "2.10.2",
102
- "@pi-unipi/trajectory": "2.10.2",
103
- "@pi-unipi/updater": "2.10.2",
104
- "@pi-unipi/utility": "2.10.2",
105
- "@pi-unipi/web-api": "2.10.2",
106
- "@pi-unipi/workflow": "2.10.2"
85
+ "@pi-unipi/ask-user": "2.11.0",
86
+ "@pi-unipi/background-tasks": "2.11.0",
87
+ "@pi-unipi/btw": "2.11.0",
88
+ "@pi-unipi/command-enchantment": "2.11.0",
89
+ "@pi-unipi/compactor": "2.11.0",
90
+ "@pi-unipi/core": "2.11.0",
91
+ "@pi-unipi/footer": "2.11.0",
92
+ "@pi-unipi/image": "2.11.0",
93
+ "@pi-unipi/info-screen": "2.11.0",
94
+ "@pi-unipi/input-shortcuts": "2.11.0",
95
+ "@pi-unipi/kanboard": "2.11.0",
96
+ "@pi-unipi/mcp": "2.11.0",
97
+ "@pi-unipi/memory": "2.11.0",
98
+ "@pi-unipi/milestone": "2.11.0",
99
+ "@pi-unipi/notify": "2.11.0",
100
+ "@pi-unipi/ralph": "2.11.0",
101
+ "@pi-unipi/subagents": "2.11.0",
102
+ "@pi-unipi/trajectory": "2.11.0",
103
+ "@pi-unipi/updater": "2.11.0",
104
+ "@pi-unipi/utility": "2.11.0",
105
+ "@pi-unipi/web-api": "2.11.0",
106
+ "@pi-unipi/workflow": "2.11.0"
107
107
  },
108
108
  "devDependencies": {
109
109
  "@earendil-works/pi-agent-core": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/ask-user",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Structured user input tool for Pi coding agent — single-select, multi-select, freeform",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -40,7 +40,7 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "@pi-unipi/core": "2.10.2"
43
+ "@pi-unipi/core": "2.11.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/command-enchantment",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Enhanced TUI autocomplete for /unipi:* commands — colored, sorted, and grouped by package",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/background-tasks",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Background tasks for UniPi — durable shell jobs, delegated agents, attested Pi runs, and fixed-purpose Fusion workflows",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@earendil-works/pi-ai": "^0.84.0",
13
- "@pi-unipi/core": "2.10.2",
13
+ "@pi-unipi/core": "2.11.0",
14
14
  "turndown": "^7.2.4"
15
15
  },
16
16
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/btw",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "A pi extension for parallel side conversations with /unipi:btw — part of the Unipi suite",
5
5
  "type": "module",
6
6
  "main": "extensions/btw.ts",
@@ -37,7 +37,7 @@
37
37
  "@earendil-works/pi-tui": "^0.84.0"
38
38
  },
39
39
  "dependencies": {
40
- "@pi-unipi/core": "2.10.2"
40
+ "@pi-unipi/core": "2.11.0"
41
41
  },
42
42
  "pi": {
43
43
  "extensions": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/compactor",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Context engine for Pi — zero-LLM compaction, session continuity, sandbox execution, and tool display optimization",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -34,8 +34,8 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@pi-unipi/core": "2.10.2",
38
- "@pi-unipi/info-screen": "2.10.2",
37
+ "@pi-unipi/core": "2.11.0",
38
+ "@pi-unipi/info-screen": "2.11.0",
39
39
  "@earendil-works/pi-agent-core": "^0.84.0"
40
40
  },
41
41
  "peerDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/core",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Shared utilities, event types, and constants for Unipi extension suite",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/footer",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Persistent status bar for Unipi — subscribes to UNIPI_EVENTS and renders key stats from all unipi packages",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -32,7 +32,7 @@
32
32
  "access": "public"
33
33
  },
34
34
  "dependencies": {
35
- "@pi-unipi/core": "2.10.2"
35
+ "@pi-unipi/core": "2.11.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/image",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Image generation and image recognition tools for the Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@pi-unipi/core": "2.10.2"
37
+ "@pi-unipi/core": "2.11.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@earendil-works/pi-ai": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/info-screen",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -33,7 +33,7 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@pi-unipi/core": "2.10.2"
36
+ "@pi-unipi/core": "2.11.0"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/input-shortcuts",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Keyboard shortcuts for stash/restore, undo/redo, clipboard, and thinking toggle — chord-based overlay system",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -33,7 +33,7 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@pi-unipi/core": "2.10.2"
36
+ "@pi-unipi/core": "2.11.0"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/kanboard",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Visualization layer for unipi workflow — HTTP server with htmx/Alpine.js UI, modular parsers, TUI overlay, and kanban board",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -39,7 +39,7 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@pi-unipi/core": "2.10.2"
42
+ "@pi-unipi/core": "2.11.0"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/mcp",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "MCP server management extension for Pi coding agent — browse, add, configure, and use MCP servers",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -30,7 +30,7 @@
30
30
  "test": "npx tsx --test tests/**/*.test.ts"
31
31
  },
32
32
  "dependencies": {
33
- "@pi-unipi/core": "2.10.2"
33
+ "@pi-unipi/core": "2.11.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/memory",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Persistent cross-session memory with MemPalace backend (auto-installed) and SQLite fallback for Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -39,8 +39,8 @@
39
39
  "README.md"
40
40
  ],
41
41
  "dependencies": {
42
- "@pi-unipi/core": "2.10.2",
43
- "@pi-unipi/info-screen": "2.10.2",
42
+ "@pi-unipi/core": "2.11.0",
43
+ "@pi-unipi/info-screen": "2.11.0",
44
44
  "js-yaml": "^4.1.0"
45
45
  },
46
46
  "peerDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/milestone",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Lifecycle layer for project-level goals — MILESTONES.md tracking, session hooks, auto-sync",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -32,7 +32,7 @@
32
32
  "access": "public"
33
33
  },
34
34
  "dependencies": {
35
- "@pi-unipi/core": "2.10.2"
35
+ "@pi-unipi/core": "2.11.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/notify",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Cross-platform notification extension for Pi — native OS, Gotify, and Telegram notifications for agent lifecycle events",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@pi-unipi/core": "2.10.2",
37
+ "@pi-unipi/core": "2.11.0",
38
38
  "node-notifier": "^10.0.1"
39
39
  },
40
40
  "peerDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/ralph",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Long-running iterative development loops for Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -31,8 +31,8 @@
31
31
  "test": "npx tsx --test reminder.test.ts"
32
32
  },
33
33
  "dependencies": {
34
- "@pi-unipi/core": "2.10.2",
35
- "@pi-unipi/info-screen": "2.10.2"
34
+ "@pi-unipi/core": "2.11.0",
35
+ "@pi-unipi/info-screen": "2.11.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@earendil-works/pi-ai": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/subagents",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Subagents for UniPi — parallel execution, file locking, workflow integration",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -9,7 +9,7 @@
9
9
  "test": "npx tsx --test src/__tests__/*.test.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@pi-unipi/core": "2.10.2",
12
+ "@pi-unipi/core": "2.11.0",
13
13
  "@earendil-works/pi-agent-core": "^0.84.0",
14
14
  "acorn": "8.18.0"
15
15
  },
@@ -15,15 +15,23 @@ Typing `/unipi:trajectory` followed by a space auto-completes the available
15
15
  actions (`stop`, `off`, `toggle`), so the options are discoverable without
16
16
  reading the docs. Running it with no argument opens or reuses the server.
17
17
 
18
- The command starts or reuses an in-process server on `127.0.0.1:8176-8186` and opens it in the default browser. The page follows the active session every 500 ms. The server is owned by the current Pi process and is stopped on any Pi session shutdown/reload/resume/new/fork event.
18
+ The command starts or reuses an in-process server on `127.0.0.1:8176-8186` and opens it in the default browser. The page follows the active session every 1.5 seconds, skips unchanged snapshots, and reuses an in-memory telemetry tail instead of rereading the JSONL file. The server is owned by the current Pi process and is stopped on any Pi session shutdown/reload/resume/new/fork event.
19
19
 
20
20
  ## What it shows
21
21
 
22
+ - The exact provider-context path: user/assistant/tool messages, effective system prompt, serialized provider request, and prefix-integrity verdict
23
+ - UniPi package operations only when they mutate context or cross an explicit context epoch boundary; UI-only hooks, registrations, notifications, command bookkeeping, and unrelated EventBus traffic are intentionally excluded from the ledger
24
+ - A per-request prefix-integrity verdict: first request, identical retry, append-only extension, explicit lifecycle boundary, or violation
25
+ - Exact prefix-break evidence: first changed message index/path plus independent system-prompt, tool-schema/order, route, thinking-level, and provider-envelope drift
26
+ - Contributing UniPi package operations between the previous request and a violation
27
+ - One-click **UniPi** and **Violations** filters, plus Trace, Integrity, and Attribution detail tabs
28
+ - The fully assembled effective system prompt for each agent run
22
29
  - Turn-aware User, Assistant, Tool, Compaction, and Branch ledger
23
- - Assistant reasoning and final output
24
- - Tool payloads, results, errors, and measured call duration
30
+ - Effective context messages before each model request and the final provider payload after serialization/extension rewrites
31
+ - Assistant reasoning and final output, including streamed assistant events
32
+ - Tool payloads, final results, errors, and measured call duration
25
33
  - Provider, model, stop reason, token usage, cache reads/writes, and cost
26
- - Provider, model, thinking level, request payload/options, tool schemas, response status/headers
34
+ - Provider, model, thinking level, serialized request payload, and tool schemas
27
35
  - Exact TTFT, decoding/total request timing, and tool execution timing
28
36
  - Input/Model/Tools overview timeline with drag-to-focus
29
37
  - Search, turn folding, call folding, and a local record inspector
@@ -34,7 +42,15 @@ The server binds only to `127.0.0.1`. It reads `SessionManager.getBranch()` and
34
42
 
35
43
  Detailed telemetry is appended to `~/.unipi/trajectory/<session-id>.jsonl` with a private directory/file mode. Authorization, API-key, token, cookie, secret, password, and credential fields and credential-shaped values are recursively redacted before persistence.
36
44
 
37
- Detailed request fields appear when captured by the trajectory telemetry sidecar.
45
+ Context-relevant prompt, request, package mutation, and prefix-integrity fields appear when captured by the trajectory telemetry sidecar. Stream deltas, response headers, inert hooks, and other activity that cannot affect model context are not persisted. Secret-shaped headers and values are redacted before persistence, and pathological events/read volume are bounded so debug capture cannot exhaust the Pi process.
46
+
47
+ ## Prefix integrity
48
+
49
+ Inside one cache epoch, the previous serialized message sequence must be an exact prefix of the next request. An identical retry is also safe. Any earlier edit, removal, reorder, or middle insertion is a violation. System instructions, tool definitions/order, provider route, thinking level, and request envelope are checked independently because changes there also invalidate provider prefix caches.
50
+
51
+ Compaction, tree navigation, model changes, and thinking-level changes create explicit epoch boundaries. The first request after a boundary is labeled as such; append-only enforcement resumes on the following request.
52
+
53
+ Package attribution is intentionally limited to UniPi modules loaded through the all-in-one `@pi-unipi/unipi` umbrella. Standalone trajectory still captures Pi's observable hooks and requests, but cannot attribute calls made by independently loaded packages.
38
54
 
39
55
  ## Lifecycle
40
56
 
@@ -42,6 +58,6 @@ Each Pi process owns its own trajectory server. A second Pi process running `/un
42
58
 
43
59
  ## Limitations
44
60
 
45
- - Live transport uses 500 ms polling rather than a push stream.
46
- - Very large branches are rendered in one table; browser virtualization can be added if measured sessions require it.
61
+ - Live transport uses conditional 1.5-second polling rather than a push stream.
62
+ - Very large active branches are rendered in one table; unchanged snapshots are not rebuilt or rerendered.
47
63
  - Tool duration uses exact executor telemetry when captured and session timestamps otherwise.
@@ -2,19 +2,33 @@ import type { ExtensionAPI, ExtensionContext, SessionEntry } from "@earendil-wor
2
2
  import { registerTelemetryCapture } from "./src/capture.js";
3
3
  import { projectTrajectory } from "./src/project.js";
4
4
  import { openBrowser, TrajectoryServer } from "./src/server.js";
5
+ import { createUnipiTracer, type UnipiTraceRecorder } from "./src/tracer.js";
6
+
7
+ export { createUnipiTracer, type UnipiTraceRecorder, type UnipiTracer } from "./src/tracer.js";
5
8
 
6
9
  let server: TrajectoryServer | null = null;
7
10
  let currentContext: ExtensionContext | null = null;
11
+ let cachedLeafId: string | null | undefined;
12
+ let cachedTelemetryRevision = -1;
13
+ let cachedSnapshot: ReturnType<typeof projectTrajectory> | null = null;
8
14
 
9
15
  function stopServer(): boolean {
10
16
  if (!server?.url) return false;
11
17
  server.stop();
12
18
  server = null;
19
+ cachedLeafId = undefined;
20
+ cachedTelemetryRevision = -1;
21
+ cachedSnapshot = null;
13
22
  return true;
14
23
  }
15
24
 
16
- export default function trajectory(pi: ExtensionAPI): void {
17
- const readTelemetry = registerTelemetryCapture(pi);
25
+ export interface TrajectoryOptions {
26
+ traceRecorder?: UnipiTraceRecorder;
27
+ }
28
+
29
+ export default function trajectory(pi: ExtensionAPI, options: TrajectoryOptions = {}): void {
30
+ const recorder = options.traceRecorder ?? createUnipiTracer(pi).recorder;
31
+ const readTelemetry = registerTelemetryCapture(pi, undefined, recorder);
18
32
 
19
33
  pi.registerCommand("unipi:trajectory", {
20
34
  description: "Open or manage UniPi's live trajectory for the current session",
@@ -54,11 +68,17 @@ export default function trajectory(pi: ExtensionAPI): void {
54
68
  server = new TrajectoryServer({
55
69
  snapshot: () => {
56
70
  const active = currentContext ?? ctx;
57
- return projectTrajectory(active.sessionManager.getBranch() as SessionEntry[], {
71
+ const leafId = active.sessionManager.getLeafId();
72
+ const telemetryRevision = recorder.revision();
73
+ if (cachedSnapshot && cachedLeafId === leafId && cachedTelemetryRevision === telemetryRevision) return cachedSnapshot;
74
+ cachedLeafId = leafId;
75
+ cachedTelemetryRevision = telemetryRevision;
76
+ cachedSnapshot = projectTrajectory(active.sessionManager.getBranch() as SessionEntry[], {
58
77
  sessionId: active.sessionManager.getSessionId(),
59
78
  name: active.sessionManager.getSessionName(),
60
79
  cwd: active.cwd,
61
80
  }, readTelemetry());
81
+ return cachedSnapshot;
62
82
  },
63
83
  });
64
84
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/trajectory",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "Live UniPi trajectory inspector for Pi sessions",
5
5
  "type": "module",
6
6
  "main": "index.ts",