@blackbelt-technology/pi-agent-dashboard 0.2.9 → 0.4.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.
- package/AGENTS.md +64 -8
- package/README.md +308 -101
- package/docs/architecture.md +515 -16
- package/package.json +14 -7
- package/packages/extension/package.json +11 -3
- package/packages/extension/src/__tests__/ask-user-tool.test.ts +300 -3
- package/packages/extension/src/__tests__/enrich-model-metadata.test.ts +201 -0
- package/packages/extension/src/__tests__/fork-entryid-timing.test.ts +100 -0
- package/packages/extension/src/__tests__/git-info.test.ts +67 -55
- package/packages/extension/src/__tests__/openspec-poller.test.ts +101 -96
- package/packages/extension/src/__tests__/process-scanner-kill.test.ts +61 -0
- package/packages/extension/src/__tests__/provider-register-reload.test.ts +394 -0
- package/packages/extension/src/__tests__/server-auto-start.test.ts +95 -4
- package/packages/extension/src/__tests__/server-launcher.test.ts +16 -0
- package/packages/extension/src/ask-user-tool.ts +289 -20
- package/packages/extension/src/bridge.ts +107 -6
- package/packages/extension/src/command-handler.ts +34 -39
- package/packages/extension/src/dev-build.ts +1 -1
- package/packages/extension/src/git-info.ts +9 -19
- package/packages/extension/src/pi-env.d.ts +1 -0
- package/packages/extension/src/process-scanner.ts +72 -38
- package/packages/extension/src/prompt-expander.ts +25 -4
- package/packages/extension/src/provider-register.ts +304 -16
- package/packages/extension/src/server-auto-start.ts +27 -1
- package/packages/extension/src/server-launcher.ts +71 -27
- package/packages/server/package.json +17 -2
- package/packages/server/src/__tests__/auto-attach.test.ts +10 -1
- package/packages/server/src/__tests__/auto-shutdown.test.ts +8 -2
- package/packages/server/src/__tests__/bootstrap-queue.test.ts +120 -0
- package/packages/server/src/__tests__/bootstrap-routes.test.ts +125 -0
- package/packages/server/src/__tests__/bootstrap-state.test.ts +119 -0
- package/packages/server/src/__tests__/browse-endpoint.test.ts +246 -10
- package/packages/server/src/__tests__/browser-gateway-handler-errors.test.ts +129 -0
- package/packages/server/src/__tests__/cli-parse.test.ts +11 -0
- package/packages/server/src/__tests__/concurrent-launch.test.ts +110 -0
- package/packages/server/src/__tests__/config-api.test.ts +68 -0
- package/packages/server/src/__tests__/cors.test.ts +34 -2
- package/packages/server/src/__tests__/crash-recovery.test.ts +88 -0
- package/packages/server/src/__tests__/directory-service.test.ts +234 -8
- package/packages/server/src/__tests__/editor-manager-pid-registry.test.ts +168 -0
- package/packages/server/src/__tests__/editor-manager.test.ts +33 -0
- package/packages/server/src/__tests__/editor-pid-registry.test.ts +191 -0
- package/packages/server/src/__tests__/editor-registry.test.ts +29 -15
- package/packages/server/src/__tests__/extension-register-appimage.test.ts +5 -1
- package/packages/server/src/__tests__/extension-register.test.ts +3 -1
- package/packages/server/src/__tests__/find-port-holders.test.ts +94 -0
- package/packages/server/src/__tests__/fix-pty-permissions.test.ts +59 -0
- package/packages/server/src/__tests__/force-kill-handler.test.ts +57 -8
- package/packages/server/src/__tests__/git-operations.test.ts +9 -7
- package/packages/server/src/__tests__/health-endpoint.test.ts +11 -13
- package/packages/server/src/__tests__/home-lock-escape-hatch.test.ts +60 -0
- package/packages/server/src/__tests__/home-lock-release.test.ts +85 -0
- package/packages/server/src/__tests__/home-lock.test.ts +308 -0
- package/packages/server/src/__tests__/is-pi-process.test.ts +36 -0
- package/packages/server/src/__tests__/node-guard.test.ts +85 -0
- package/packages/server/src/__tests__/openspec-tasks-parser.test.ts +178 -0
- package/packages/server/src/__tests__/openspec-tasks-routes.test.ts +180 -0
- package/packages/server/src/__tests__/package-manager-wrapper-resolve.test.ts +126 -0
- package/packages/server/src/__tests__/package-manager-wrapper.test.ts +45 -10
- package/packages/server/src/__tests__/pi-core-checker.test.ts +195 -0
- package/packages/server/src/__tests__/pi-core-routes.test.ts +184 -0
- package/packages/server/src/__tests__/pi-core-updater.test.ts +214 -0
- package/packages/server/src/__tests__/pi-version-skew.test.ts +165 -0
- package/packages/server/src/__tests__/preferences-store.test.ts +73 -4
- package/packages/server/src/__tests__/process-manager.test.ts +45 -18
- package/packages/server/src/__tests__/provider-auth-routes.test.ts +13 -3
- package/packages/server/src/__tests__/provider-probe.test.ts +287 -0
- package/packages/server/src/__tests__/provider-test-route.test.ts +149 -0
- package/packages/server/src/__tests__/recommended-routes.test.ts +389 -0
- package/packages/server/src/__tests__/restart-helper.test.ts +83 -0
- package/packages/server/src/__tests__/session-action-handler-headless-reload.test.ts +467 -0
- package/packages/server/src/__tests__/session-action-handler-reload-predicate.test.ts +73 -0
- package/packages/server/src/__tests__/session-action-handler-spawn-error.test.ts +74 -0
- package/packages/server/src/__tests__/session-file-dedup.test.ts +10 -10
- package/packages/server/src/__tests__/session-lifecycle-logging.test.ts +8 -2
- package/packages/server/src/__tests__/sleep-aware-heartbeat.test.ts +3 -1
- package/packages/server/src/__tests__/smoke-integration.test.ts +10 -10
- package/packages/server/src/__tests__/terminal-manager.test.ts +41 -1
- package/packages/server/src/__tests__/test-server-canary.test.ts +31 -0
- package/packages/server/src/__tests__/tool-routes.test.ts +277 -0
- package/packages/server/src/__tests__/trusted-networks-config.test.ts +19 -0
- package/packages/server/src/__tests__/trusted-networks-no-oauth-roundtrip.test.ts +126 -0
- package/packages/server/src/__tests__/tunnel-cleanup.test.ts +90 -0
- package/packages/server/src/__tests__/tunnel.test.ts +103 -6
- package/packages/server/src/__tests__/ws-ping-pong.test.ts +10 -2
- package/packages/server/src/__tests__/wsl-tmux-probe-cache.test.ts +44 -0
- package/packages/server/src/bootstrap-queue.ts +130 -0
- package/packages/server/src/bootstrap-state.ts +131 -0
- package/packages/server/src/browse.ts +108 -9
- package/packages/server/src/browser-gateway.ts +16 -3
- package/packages/server/src/browser-handlers/directory-handler.ts +23 -8
- package/packages/server/src/browser-handlers/session-action-handler.ts +213 -79
- package/packages/server/src/browser-handlers/session-action-helpers.ts +36 -0
- package/packages/server/src/cli.ts +256 -32
- package/packages/server/src/config-api.ts +16 -0
- package/packages/server/src/directory-service.ts +270 -39
- package/packages/server/src/editor-detection.ts +12 -9
- package/packages/server/src/editor-manager.ts +39 -5
- package/packages/server/src/editor-pid-registry.ts +199 -0
- package/packages/server/src/editor-registry.ts +22 -25
- package/packages/server/src/fix-pty-permissions.ts +44 -0
- package/packages/server/src/git-operations.ts +1 -1
- package/packages/server/src/headless-pid-registry.ts +16 -20
- package/packages/server/src/home-lock-release.ts +72 -0
- package/packages/server/src/home-lock.ts +389 -0
- package/packages/server/src/node-guard.ts +52 -0
- package/packages/server/src/npm-search-proxy.ts +71 -0
- package/packages/server/src/openspec-tasks.ts +158 -0
- package/packages/server/src/package-manager-wrapper.ts +225 -34
- package/packages/server/src/pi-core-checker.ts +290 -0
- package/packages/server/src/pi-core-updater.ts +172 -0
- package/packages/server/src/pi-gateway.ts +7 -0
- package/packages/server/src/pi-resource-scanner.ts +5 -8
- package/packages/server/src/pi-version-skew.ts +196 -0
- package/packages/server/src/preferences-store.ts +17 -3
- package/packages/server/src/process-manager.ts +403 -222
- package/packages/server/src/provider-probe.ts +234 -0
- package/packages/server/src/restart-helper.ts +130 -0
- package/packages/server/src/routes/bootstrap-routes.ts +88 -0
- package/packages/server/src/routes/file-routes.ts +30 -3
- package/packages/server/src/routes/openspec-routes.ts +107 -1
- package/packages/server/src/routes/pi-core-routes.ts +140 -0
- package/packages/server/src/routes/provider-auth-routes.ts +12 -10
- package/packages/server/src/routes/provider-routes.ts +55 -2
- package/packages/server/src/routes/recommended-routes.ts +225 -0
- package/packages/server/src/routes/system-routes.ts +30 -34
- package/packages/server/src/routes/tool-routes.ts +153 -0
- package/packages/server/src/server-pid.ts +5 -9
- package/packages/server/src/server.ts +363 -26
- package/packages/server/src/session-api.ts +77 -8
- package/packages/server/src/session-bootstrap.ts +17 -3
- package/packages/server/src/session-diff.ts +21 -21
- package/packages/server/src/terminal-manager.ts +65 -20
- package/packages/server/src/test-env-guard.ts +26 -0
- package/packages/server/src/test-support/test-server.ts +63 -0
- package/packages/server/src/tunnel.ts +172 -34
- package/packages/shared/package.json +10 -3
- package/packages/shared/src/__tests__/{tool-resolver.test.ts → binary-lookup.test.ts} +32 -12
- package/packages/shared/src/__tests__/bootstrap/README.md +133 -0
- package/packages/shared/src/__tests__/bootstrap/__snapshots__/cube.test.ts.snap +370 -0
- package/packages/shared/src/__tests__/bootstrap/assertions.ts +136 -0
- package/packages/shared/src/__tests__/bootstrap/cube.test.ts +47 -0
- package/packages/shared/src/__tests__/bootstrap/cube.ts +66 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/a-electron.test.ts.snap +83 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/b-npm-global.test.ts.snap +89 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/c-dev-monorepo.test.ts.snap +33 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/d-overrides.test.ts.snap +20 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/e-stale-partial.test.ts.snap +61 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/f-cwd-variants.test.ts.snap +33 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/g-windows-specifics.test.ts.snap +46 -0
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/j-path-gui-minimal.test.ts.snap +12 -0
- package/packages/shared/src/__tests__/bootstrap/families/a-electron.test.ts +156 -0
- package/packages/shared/src/__tests__/bootstrap/families/b-npm-global.test.ts +157 -0
- package/packages/shared/src/__tests__/bootstrap/families/c-dev-monorepo.test.ts +102 -0
- package/packages/shared/src/__tests__/bootstrap/families/d-overrides.test.ts +76 -0
- package/packages/shared/src/__tests__/bootstrap/families/e-stale-partial.test.ts +94 -0
- package/packages/shared/src/__tests__/bootstrap/families/f-cwd-variants.test.ts +87 -0
- package/packages/shared/src/__tests__/bootstrap/families/g-windows-specifics.test.ts +143 -0
- package/packages/shared/src/__tests__/bootstrap/families/h-home-drift.test.ts +64 -0
- package/packages/shared/src/__tests__/bootstrap/families/i-malformed-settings.test.ts +77 -0
- package/packages/shared/src/__tests__/bootstrap/families/index.ts +19 -0
- package/packages/shared/src/__tests__/bootstrap/families/j-path-gui-minimal.test.ts +61 -0
- package/packages/shared/src/__tests__/bootstrap/families/k-dashboard-absent.test.ts +50 -0
- package/packages/shared/src/__tests__/bootstrap/families/l-instance-coordination.test.ts +272 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/dev-monorepo.ts +58 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/electron-layout.ts +84 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/index.ts +9 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/managed-install.ts +85 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/npm-global-layout.ts +122 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/pi-versions.ts +36 -0
- package/packages/shared/src/__tests__/bootstrap/fixtures/settings-json.ts +39 -0
- package/packages/shared/src/__tests__/bootstrap/harness.smoke.test.ts +220 -0
- package/packages/shared/src/__tests__/bootstrap/harness.ts +413 -0
- package/packages/shared/src/__tests__/bootstrap/scenarios-skipped.ts +125 -0
- package/packages/shared/src/__tests__/bootstrap/scenarios.ts +132 -0
- package/packages/shared/src/__tests__/bridge-register.test.ts +29 -6
- package/packages/shared/src/__tests__/config-openspec.test.ts +106 -0
- package/packages/shared/src/__tests__/config.test.ts +59 -3
- package/packages/shared/src/__tests__/detached-spawn.test.ts +243 -0
- package/packages/shared/src/__tests__/managed-paths.test.ts +60 -0
- package/packages/shared/src/__tests__/no-direct-child-process.test.ts +112 -0
- package/packages/shared/src/__tests__/no-direct-platform-branch.test.ts +174 -0
- package/packages/shared/src/__tests__/no-direct-process-kill.test.ts +105 -0
- package/packages/shared/src/__tests__/openspec-poller.test.ts +44 -0
- package/packages/shared/src/__tests__/platform-commands.test.ts +108 -0
- package/packages/shared/src/__tests__/platform-exec.test.ts +103 -0
- package/packages/shared/src/__tests__/platform-git.test.ts +194 -0
- package/packages/shared/src/__tests__/platform-npm.test.ts +137 -0
- package/packages/shared/src/__tests__/platform-openspec.test.ts +92 -0
- package/packages/shared/src/__tests__/platform-paths.test.ts +284 -0
- package/packages/shared/src/__tests__/platform-process-scan.test.ts +55 -0
- package/packages/shared/src/__tests__/platform-process.test.ts +160 -0
- package/packages/shared/src/__tests__/platform-runner.test.ts +173 -0
- package/packages/shared/src/__tests__/platform-shell.test.ts +74 -0
- package/packages/shared/src/__tests__/process-identify.test.ts +113 -0
- package/packages/shared/src/__tests__/recommended-extensions.test.ts +156 -0
- package/packages/shared/src/__tests__/resolve-jiti.test.ts +43 -7
- package/packages/shared/src/__tests__/semaphore.test.ts +119 -0
- package/packages/shared/src/__tests__/source-matching.test.ts +143 -0
- package/packages/shared/src/__tests__/spawn-mechanism.test.ts +131 -0
- package/packages/shared/src/__tests__/tool-registry-definitions.test.ts +239 -0
- package/packages/shared/src/__tests__/tool-registry-overrides.test.ts +137 -0
- package/packages/shared/src/__tests__/tool-registry-registry.test.ts +343 -0
- package/packages/shared/src/bootstrap-install.ts +212 -0
- package/packages/shared/src/bridge-register.ts +87 -20
- package/packages/shared/src/browser-protocol.ts +93 -1
- package/packages/shared/src/config.ts +87 -15
- package/packages/shared/src/managed-paths.ts +31 -4
- package/packages/shared/src/openspec-poller.ts +71 -49
- package/packages/shared/src/{tool-resolver.ts → platform/binary-lookup.ts} +125 -25
- package/packages/shared/src/platform/commands.ts +100 -0
- package/packages/shared/src/platform/detached-spawn.ts +305 -0
- package/packages/shared/src/platform/exec.ts +220 -0
- package/packages/shared/src/platform/git.ts +155 -0
- package/packages/shared/src/platform/index.ts +15 -0
- package/packages/shared/src/platform/npm.ts +162 -0
- package/packages/shared/src/platform/openspec.ts +91 -0
- package/packages/shared/src/platform/paths.ts +276 -0
- package/packages/shared/src/platform/process-identify.ts +126 -0
- package/packages/shared/src/platform/process-scan.ts +94 -0
- package/packages/shared/src/platform/process.ts +168 -0
- package/packages/shared/src/platform/runner.ts +369 -0
- package/packages/shared/src/platform/shell.ts +44 -0
- package/packages/shared/src/platform/spawn-mechanism.ts +124 -0
- package/packages/shared/src/platform/subprocess-adapter.ts +124 -0
- package/packages/shared/src/recommended-extensions.ts +196 -0
- package/packages/shared/src/resolve-jiti.ts +62 -3
- package/packages/shared/src/rest-api.ts +97 -0
- package/packages/shared/src/semaphore.ts +83 -0
- package/packages/shared/src/source-matching.ts +126 -0
- package/packages/shared/src/test-support/setup-home.ts +74 -0
- package/packages/shared/src/tool-registry/definitions.ts +342 -0
- package/packages/shared/src/tool-registry/index.ts +56 -0
- package/packages/shared/src/tool-registry/overrides.ts +118 -0
- package/packages/shared/src/tool-registry/registry.ts +262 -0
- package/packages/shared/src/tool-registry/strategies.ts +198 -0
- package/packages/shared/src/tool-registry/types.ts +180 -0
- package/packages/shared/src/types.ts +7 -0
package/AGENTS.md
CHANGED
|
@@ -20,6 +20,8 @@ See [docs/architecture.md](docs/architecture.md) for full details.
|
|
|
20
20
|
npm install # Install dependencies
|
|
21
21
|
npm test # Run all tests (vitest)
|
|
22
22
|
npm run test:watch # Watch mode
|
|
23
|
+
npm run test:bootstrap # Run the bootstrap resolution harness only
|
|
24
|
+
npm run test:bootstrap:watch # Bootstrap harness in watch mode
|
|
23
25
|
npm run build # Build web client (Vite)
|
|
24
26
|
npm run dev # Start Vite dev server
|
|
25
27
|
npm run reload # Reload all connected pi sessions
|
|
@@ -58,7 +60,8 @@ make clean # Destroy all cloned VMs
|
|
|
58
60
|
| `src/shared/protocol.ts` | Extension↔Server WebSocket messages |
|
|
59
61
|
| `src/shared/browser-protocol.ts` | Server↔Browser WebSocket messages (all message types including PromptBus `prompt_request`/`prompt_dismiss`/`prompt_cancel` must be in the `ServerToBrowserMessage` union — `as any` switch cases are stripped by esbuild in production) |
|
|
60
62
|
| `src/shared/types.ts` | Data models (Session, Workspace, Event) |
|
|
61
|
-
| `src/shared/config.ts` | Shared config loader (`~/.pi/dashboard/config.json`) |
|
|
63
|
+
| `src/shared/config.ts` | Shared config loader (`~/.pi/dashboard/config.json`). Includes `openspec: OpenSpecPollConfig` block (`pollIntervalSeconds` 5–3600, `maxConcurrentSpawns` 1–16, `changeDetection` `"mtime"\|"always"`, `jitterSeconds` 0–60) with clamping via `parseOpenSpecPollConfig`. See change: optimize-openspec-poll-burst |
|
|
64
|
+
| `src/shared/semaphore.ts` | Tiny FIFO semaphore (`createSemaphore(max)` → `{run, setMax, size}`). Used by `directory-service.ts` to cap concurrent `openspec` CLI spawns. Supports live resize via `setMax(n)` for runtime reconfig. |
|
|
62
65
|
| `src/extension/bridge.ts` | Main extension entry point (composes sync/tracker/flow modules, tracks `isAgentStreaming` in persistent BridgeState) |
|
|
63
66
|
| `src/extension/bridge-context.ts` | Shared mutable state type + helpers for bridge modules |
|
|
64
67
|
| `src/extension/session-sync.ts` | Session register, replay, and switch/fork handling |
|
|
@@ -68,7 +71,7 @@ make clean # Destroy all cloned VMs
|
|
|
68
71
|
| `src/extension/server-probe.ts` | TCP probe to detect running server |
|
|
69
72
|
| `src/shared/server-identity.ts` | Identity-verified health check (`isDashboardRunning`) replacing bare TCP probes |
|
|
70
73
|
| `src/shared/mdns-discovery.ts` | mDNS advertise/discover/browse for `_pi-dashboard._tcp` services |
|
|
71
|
-
| `src/extension/server-launcher.ts` | Auto-start server as detached process |
|
|
74
|
+
| `src/extension/server-launcher.ts` | Auto-start server as detached process; captures **both stdout AND stderr** to `~/.pi/dashboard/server.log` (append mode) by passing `stdoutFd: logFd` alongside `logFd` — parity with `pi-dashboard start`'s `stdio: ["ignore", logFd, logFd]`. Exports pure `buildSpawnDetachedOptions` and `buildReadyTimeoutMessage`; the latter appends a `nodejs/node#58515` upgrade hint when `isKnownBadNode(process.version)` is true. |
|
|
72
75
|
| `src/extension/command-handler.ts` | Command routing: `!`/`!!` bash, `/compact`, slash commands |
|
|
73
76
|
| `src/extension/prompt-expander.ts` | Slash command → prompt template expansion (supports colon-to-hyphen aliasing: `/opsx:cmd` → `opsx-cmd.md`) |
|
|
74
77
|
| `src/extension/dev-build.ts` | Dev build-on-reload helper (client build + server shutdown) |
|
|
@@ -105,7 +108,8 @@ make clean # Destroy all cloned VMs
|
|
|
105
108
|
| `src/server/browser-gateway.ts` | Browser WebSocket gateway (dispatches to handler modules) |
|
|
106
109
|
| `src/server/browser-handlers/handler-context.ts` | Shared context type for browser message handlers |
|
|
107
110
|
| `src/server/browser-handlers/subscription-handler.ts` | Subscribe/unsubscribe with async batched replay, backpressure, lazy loading |
|
|
108
|
-
| `src/server/browser-handlers/session-action-handler.ts` | Send prompt, abort, resume, spawn, shutdown, force kill, flow control |
|
|
111
|
+
| `src/server/browser-handlers/session-action-handler.ts` | Send prompt, abort, resume, spawn, shutdown, force kill, flow control. `handleForceKill` delegates the SIGTERM→wait→SIGKILL escalation to `killProcess` from `platform/process.ts` so Windows gets `taskkill /F /T /PID` (genuine tree kill). No direct `process.kill()` anywhere (enforced by `no-direct-process-kill.test.ts`). `handleSendPrompt` also intercepts `/reload` on headless sessions (gated by `headlessPidRegistry.getPid`) and delegates to `handleHeadlessReload`, which SIGTERMs the pi process and respawns with `--session <file> --mode continue` — pi 0.68.0 has no extension-accessible reload path in RPC mode, so kill-and-respawn is the only way to reload settings/extensions/skills for headless sessions. See changes: route-kill-paths-through-platform, headless-reload-via-respawn. |
|
|
112
|
+
| `src/server/browser-handlers/session-action-helpers.ts` | Pure helpers for session-action-handler. `shouldInterceptReload(msg, headlessPidRegistry)` gates the headless-reload interception: exact `/reload` text, no images, PID tracked in registry. Extracted for testability. |
|
|
109
113
|
| `src/client/components/ImageLightbox.tsx` | Full-size image lightbox with zoom/pan (useZoomPan), Esc/backdrop close |
|
|
110
114
|
| `src/client/components/CollapsedToolGroup.tsx` | Collapsed group of repeated tool calls with expand toggle |
|
|
111
115
|
| `src/client/lib/group-tool-calls.ts` | Groups consecutive identical tool calls for chat display |
|
|
@@ -125,7 +129,23 @@ make clean # Destroy all cloned VMs
|
|
|
125
129
|
| `src/client/lib/browse-api.ts` | Client-side browse API helper for PathPicker |
|
|
126
130
|
| `src/server/browse.ts` | Directory listing logic for browse API endpoint |
|
|
127
131
|
| `src/server/pi-resource-scanner.ts` | Discovers pi extensions, skills, prompts from local, global, and package sources |
|
|
128
|
-
| `src/server/package-manager-wrapper.ts` | Thin adapter around pi's `DefaultPackageManager` with operation serialization, progress forwarding, and session reload |
|
|
132
|
+
| `src/server/package-manager-wrapper.ts` | Thin adapter around pi's `DefaultPackageManager` with operation serialization, progress forwarding, and session reload; delegates module resolution to `ToolRegistry.resolveModule("pi-coding-agent")` |
|
|
133
|
+
| `src/shared/tool-registry/registry.ts` | `ToolRegistry` service — single-source resolver for every external binary/module (pi, pi-coding-agent, openspec, npm, node, tsx, git, zrok, pi-dashboard). Ordered strategy chain per tool, per-resolution diagnostic trail, in-memory cache, override-aware |
|
|
134
|
+
| `src/shared/tool-registry/definitions.ts` | Registers the standard tool set. Each definition declares an ordered strategy chain (override → bare-import → managed → npm-global → where) and a classifier (strategy → source) |
|
|
135
|
+
| `src/shared/tool-registry/strategies.ts` | Reusable resolution strategies: `overrideStrategy`, `managedBinStrategy`, `managedModuleStrategy`, `npmGlobalStrategy`, `whereStrategy`, `bareImportStrategy` (uses `createRequire` for sync probe). All take injectable `StrategyDeps` for tests |
|
|
136
|
+
| `src/shared/tool-registry/overrides.ts` | Read/write `~/.pi/dashboard/tool-overrides.json` (machine-local, separate from `config.json`). Lazy-loaded, atomic write via tmp+rename, malformed-file tolerant |
|
|
137
|
+
| `src/shared/tool-registry/types.ts` | `ToolDefinition`, `Strategy`, `StrategyResult`, `Resolution`, `Source`, `UnknownToolError`, `ModuleResolutionError` |
|
|
138
|
+
| `src/shared/tool-registry/index.ts` | Barrel export + `getDefaultRegistry()` singleton accessor |
|
|
139
|
+
| `src/server/routes/tool-routes.ts` | REST routes: `GET /api/tools`, `GET /api/tools/:name`, `POST /api/tools/rescan`, `PUT/DELETE /api/tools/:name`, `POST /api/tools/diagnostics` (text/plain export) |
|
|
140
|
+
| `packages/shared/src/bootstrap-install.ts` | Shared bootstrap installer (`bootstrapInstall({ packages, managedDir?, progress?, npmArgv?, env?, registry? })`, `bootstrapInstallDefaults`, `ensureManagedDir`, `resolveNpmArgv`). Single entry point for pi/openspec/tsx install into `~/.pi-dashboard/` — called from the Electron wizard (via `packages/electron/src/lib/dependency-installer.ts` wrapper that adds bundled-node + offline-cacache concerns) and from the CLI first-run path (`cli.ts runDegradedModeBootstrap`). See change: unified-bootstrap-install. |
|
|
141
|
+
| `packages/server/src/bootstrap-state.ts` | In-memory bootstrap state store (`createBootstrapState()`, `BootstrapState { status, progress, error, version, compatibility, bridgeRegistrationError }`, `BootstrapStateStore` with get/set/subscribe/dispose plus side-channel `setLastInstallPackages` / `getLastInstallPackages` so `POST /api/bootstrap/retry` re-runs the exact failed set instead of a hard-coded default). Partial `set()` supports `undefined` = clear semantics; `setLastInstallPackages` does NOT trigger subscribers (it's not part of the broadcast snapshot). |
|
|
142
|
+
| `packages/server/src/routes/bootstrap-routes.ts` | REST routes: `GET /api/bootstrap/status`, `POST /api/bootstrap/upgrade-pi` (202+ticketId or 409), `POST /api/bootstrap/retry` (202 if failed, else 409). Trigger callbacks are injected so CLI wires them to `bootstrapInstall` while tests wire them to spies. |
|
|
143
|
+
| `packages/server/src/bootstrap-queue.ts` | In-memory ticket queue (`createBootstrapQueue()`, `enqueue(handler)`, `flushAll()`, `size()`, `clear(reason)`, `onTicketComplete(listener)`). `server.ts` flushes on bootstrap-state transition to "ready" and wires `onTicketComplete` → `bootstrap_ticket_complete` WS broadcast so browsers holding a 202 ticketId learn the queued op's outcome. `session-api.ts gateOrEnqueue` uses the queue to defer session spawn during installs. On `clear`, pending tickets are rejected directly (reject closure stored on the entry) so no caller hangs at shutdown. |
|
|
144
|
+
| `packages/server/src/pi-version-skew.ts` | Pi compatibility range reader (`readPiCompatibility` reads `piCompatibility` from `packages/server/package.json`; `readCurrentPiVersion` via `createRequire`), comparator (`parseVersion`, `compareVersions`, `isBelow`, `isAbove` supporting `0.x` wildcard), + `updateBootstrapCompatibility(store, pkgPath)` that writes the result into `bootstrapState.compatibility` with a 60 s cache. Below-minimum adds a 503-blocking `error` message. |
|
|
145
|
+
| `packages/client/src/hooks/useBootstrapStatus.ts` | Client hook for bootstrap state. Fetches `/api/bootstrap/status` on mount, subscribes to `bootstrap-status` `CustomEvent` dispatched by `useMessageHandler` on `bootstrap_status_update` WS broadcasts. Exposes `{ state, isLoading, error, refresh, retry, upgradePi }`. |
|
|
146
|
+
| `packages/client/src/components/BootstrapBanner.tsx` | Banner mounted in `App.tsx` above `<MobileShell>`. Hidden at status="ready" with no compatibility hints; blue "Installing pi…" when installing; red "pi install failed — [Retry]" when failed; amber upgrade hints when `compatibility.upgradeRecommended` or `upgradeDashboard` is true. |
|
|
147
|
+
| `src/client/lib/tools-api.ts` | Client-side fetch helpers for `/api/tools*` (`fetchTools`, `rescanAll`, `rescanOne`, `setOverride`, `clearOverride`, `downloadDiagnostics`) |
|
|
148
|
+
| `src/client/components/ToolsSection.tsx` | Settings → General → **Tools** section. One row per registered tool: status badge, source, truncated path, expand-to-trail, override input, per-row rescan. Top-level: Rescan all / Reset overrides / Export diagnostics |
|
|
129
149
|
| `src/server/npm-search-proxy.ts` | Cached proxy for npm registry search (`keywords:pi-package`) and README fetch |
|
|
130
150
|
| `src/server/routes/package-routes.ts` | REST routes: search, readme, installed, install, remove, update, check-updates |
|
|
131
151
|
| `src/client/components/SortablePinnedGroup.tsx` | Drag-to-reorder wrapper for pinned directory groups |
|
|
@@ -134,11 +154,20 @@ make clean # Destroy all cloned VMs
|
|
|
134
154
|
| `src/server/session-scanner.ts` | Startup session discovery by scanning `~/.pi/agent/sessions/` |
|
|
135
155
|
| `src/server/migrate-persistence.ts` | One-time migration from `sessions.json` + `state.json` to `.meta.json` |
|
|
136
156
|
| `src/server/session-order-manager.ts` | Per-cwd session ordering with persistence |
|
|
137
|
-
| `src/server/directory-service.ts` | Server-side session discovery, event loading, and OpenSpec polling |
|
|
157
|
+
| `src/server/directory-service.ts` | Server-side session discovery, event loading, and OpenSpec polling. Uses mtime-gated per-directory cache (`DirCache`), shared FIFO semaphore, and deterministic per-cwd `phaseOffsetMs(cwd, jitterSeconds)` jitter (FNV-1a 32-bit hash). `refreshOpenSpec(cwd)` bypasses the mtime gate but still acquires the semaphore. `reconfigurePolling(cfg)` applies live config changes without a restart. Pi-resources scan lives on its own 5×-interval timer so it doesn't stack with the openspec burst. See change: optimize-openspec-poll-burst |
|
|
138
158
|
| `src/server/pending-fork-registry.ts` | Tracks pending fork operations for session placement |
|
|
139
159
|
| `src/server/pending-resume-registry.ts` | Queues prompts for auto-resume of ended sessions |
|
|
140
160
|
| `src/server/json-store.ts` | Atomic JSON file read/write helpers |
|
|
141
|
-
| `src/server/process-manager.ts` | Session spawning via tmux
|
|
161
|
+
| `src/server/process-manager.ts` | Session spawning: dispatches via `platform/spawn-mechanism.ts` `selectMechanism` → `tmux` / `wt` / `wsl-tmux` / `headless`. All mechanisms forward `sessionFile`/`mode` uniformly via `sessionFlagsToArgv`. Windows headless uses `spawnDetached` primitive with `detached: true` (PGID-equivalent via libuv) and stderr-to-file-fd (crash-visible). |
|
|
162
|
+
| `src/shared/platform/detached-spawn.ts` | Three primitives: `spawnDetached` (libuv-correct detached defaults on every OS), `waitForNoCrash` (negative liveness — did it survive the window?), `waitForReady` (positive liveness — did a probe turn true?). All spawn sites with long-lived detached children delegate here. `SpawnDetachedOptions` exposes optional `stdoutFd` (defaults to `"ignore"`) and `logFd` (stderr, defaults to `"ignore"`); the bridge server-launcher sets both to the same fd for parity with the CLI. |
|
|
163
|
+
| `src/shared/platform/node-version-check.ts` | Pure predicate `isKnownBadNode(version)` + message builder `buildNodeVersionWarning(version)` for Node ranges affected by [nodejs/node#58515](https://github.com/nodejs/node/issues/58515) (22.0.0–22.17.x and 24.1.0–24.2.x). Consumed by `packages/server/src/cli.ts` (preflight warning), `packages/extension/src/server-launcher.ts` (ready-timeout hint), and `packages/electron/src/lib/doctor.ts` (Node runtime compatibility row). |
|
|
164
|
+
| `src/shared/platform/preload-fastify.ts` | Shared resolver `resolvePreloadFastifyPath(): string \| null` — returns absolute native path (never `file://`) to `packages/server/preload-fastify.cjs`. Used by all four server-spawn sites (cli daemon, bridge launcher, Electron lifecycle, restart-helper orchestrator) to inject `--require <preloadPath>` BEFORE `--import <jitiLoader>` so Fastify's CJS chain is cached before any ESM hook runs — sidesteps nodejs/node#58515 race-independently. See change: `preload-fastify-cjs`. |
|
|
165
|
+
| `packages/server/preload-fastify.cjs` | CommonJS preload file — loaded by Node's legacy synchronous CJS loader via `--require`. Populates `require.cache` with `fastify` + `@fastify/ajv-compiler` + `@fastify/ajv-compiler/standalone` so the ESM→CJS translator short-circuits on later imports. MUST stay `.cjs`; MUST NOT use ESM syntax. |
|
|
166
|
+
| `src/shared/platform/spawn-mechanism.ts` | `SpawnMechanism` enum (`tmux`/`wt`/`wsl-tmux`/`headless`) + pure `selectMechanism({ platform, userStrategy, electronMode, available })` selector. `buildWtArgs` builds argv for Windows Terminal `new-tab`. `sessionFlagsToArgv` is the uniform flag builder every mechanism MUST call. |
|
|
167
|
+
| `src/shared/platform/process-identify.ts` | `findPidByMarker` + `isProcessLikePi` + `isPiCommandLine` — consolidates the three `process.platform === "win32"` branches that previously lived inside `session-action-handler.ts`. Windows stubs are documented (command-line lookup goes via `headlessPidRegistry` instead). |
|
|
168
|
+
| `src/shared/platform/process.ts` | **Sole source of process termination + liveness primitives**: `isProcessAlive(pid)` (signal 0), `killProcess(pid, {timeoutMs})` (Windows `taskkill /F /T /PID`, POSIX `SIGTERM` → wait → `SIGKILL` tree kill), `killPidWithGroup(pid, sig)` (POSIX `kill(-pid, sig)`, Windows direct kill). Every `process.kill(...)` call outside this file is banned by `no-direct-process-kill.test.ts`. See change: route-kill-paths-through-platform. |
|
|
169
|
+
| `src/shared/__tests__/no-direct-process-kill.test.ts` | Repo-level lint: scans `packages/*/src/` (excluding platform/ and `__tests__/`) for `process.kill(` calls and fails with file:line if any are found. Mirrors `no-direct-child-process.test.ts`. |
|
|
170
|
+
| `src/shared/__tests__/bootstrap/` | In-memory bootstrap resolution harness (memfs-backed). `harness.ts` (withFakeEnv + layer), `fixtures/` (managed/npm-g/electron/dev-monorepo/settings-json layouts), `assertions.ts` (snapshotTrail + snapshotSettingsDelta with `<HOME>` / `<NPM_ROOT>` normalization), `scenarios.ts` (1080-cell cube: platform × dash × pi × settings × env), `scenarios-skipped.ts` (bulk-skip manifest with documented reasons), `cube.test.ts` (fail-closed sweep), `families/*.test.ts` (30+ registered scenario cells across A-K). Run via `npm run test:bootstrap`. See change: bootstrap-resolution-harness. |
|
|
142
171
|
| `src/server/editor-registry.ts` | Detects available native editors (running processes + CLI) |
|
|
143
172
|
| `src/server/editor-manager.ts` | Lifecycle manager for code-server child processes (spawn, stop, idle, heartbeat) |
|
|
144
173
|
| `src/server/editor-proxy.ts` | Reverse proxy for `/editor/:id/*` to code-server instances |
|
|
@@ -150,9 +179,13 @@ make clean # Destroy all cloned VMs
|
|
|
150
179
|
| `src/server/provider-auth-handlers.ts` | Pi provider OAuth handlers (Anthropic, Codex, GitHub Copilot, Gemini CLI, Antigravity) |
|
|
151
180
|
| `src/server/provider-auth-storage.ts` | Read/write ~/.pi/agent/auth.json with lockfile for pi provider credentials |
|
|
152
181
|
| `src/server/routes/provider-auth-routes.ts` | REST routes: provider OAuth authorize/exchange/callback, device-code, API key CRUD |
|
|
182
|
+
| `src/server/routes/provider-routes.ts` | REST routes: custom LLM provider CRUD (`GET/PUT /api/providers`) + **`POST /api/providers/test`** connection probe (reuses `provider-probe.ts`). See change: `hot-reload-custom-providers` |
|
|
183
|
+
| `src/server/provider-probe.ts` | Pure per-API-type probe builders (`buildProbeRequest` for `openai-completions`/`openai-responses`/`anthropic-messages`/`google-generative-ai`) + `resolveProbeApiKey` (handles literal, `$ENV_VAR`, and `***` REDACTED sentinel via injected providers reader) + I/O-bearing `probeProvider` (8 s timeout, never echoes apiKey in error text, caps body excerpts at 500 chars). Used by the `/api/providers/test` route and shared with the bridge's discovery path |
|
|
184
|
+
| `src/extension/provider-register.ts` | Reads `~/.pi/agent/providers.json`, calls `pi.registerProvider()` with auto-discovered models, exports `reloadProviders(pi)` + `onProviderChanged(cb)`. `reloadProviders` diffs the current file against a module-level `lastRegistered` snapshot and applies add/remove/change via `registerEntry` / `pi.unregisterProvider`. Called from the bridge's `credentials_updated` handler BEFORE `modelRegistry.refresh()` so new providers appear in `/model` without a session restart. Every discovered model is enriched via `enrichModelMetadata(id, api, probe)` where `probe` wraps pi's `modelRegistry.find()` (captured from `ctx.modelRegistry` at the first `session_start` event; `model_select` is a fallback capture point) — this resolves accurate `contextWindow`, `maxTokens`, `reasoning`, `cost`, and `input` for catalog-known models (e.g., `proxy/cc/claude-opus-4-7` → 1M ctx / reasoning / Opus pricing) and falls back to api-appropriate defaults otherwise (`anthropic-messages` → 200k/64k, `google-generative-ai` → 1M/65k, `openai-completions` → 128k/16k). The fallback path keeps `input: ["text", "image"]` so pasted images reach vision-capable models without pi-ai's `downgradeUnsupportedImages` stripping them client-side; text-only models either ignore the image silently or return a 400 that the user sees. See changes: enrich-custom-provider-model-metadata, enable-image-input-custom-providers |
|
|
185
|
+
| `src/client/lib/providers-api.ts` | Client-side fetch helper: `testProvider({ name?, baseUrl, apiKey, api })` → structured `{ ok, status?, modelCount?, sample?, error? }`. Used by the **Test** button on the LLM Providers card |
|
|
153
186
|
| `src/client/components/ProviderAuthSection.tsx` | Settings section: OAuth login buttons, device-code modal, API key inputs |
|
|
154
187
|
| `src/server/auth-plugin.ts` | Fastify plugin: auth routes, onRequest hook, WS upgrade validation |
|
|
155
|
-
| `src/server/config-api.ts` | Config REST API: read (redacted), write (partial merge), secret preservation |
|
|
188
|
+
| `src/server/config-api.ts` | Config REST API: read (redacted), write (partial merge), secret preservation. `writeConfigPartial` auth-merge propagates `secret`, `providers`, `allowedUsers`, `bypassHosts`, `bypassUrls` (the last two added by change `fix-trusted-networks-no-oauth` — silently dropped before, breaking Trusted Networks saves for users without OAuth). |
|
|
156
189
|
| `src/client/components/SettingsPanel.tsx` | Settings UI: all dashboard config fields, grouped form, save to server |
|
|
157
190
|
| `src/client/hooks/useAuthStatus.ts` | Client auth status hook and login redirect helper |
|
|
158
191
|
| `src/server/localhost-guard.ts` | Network access guard: `createNetworkGuard` (loopback/trusted/authenticated), `isBypassedHost` (CIDR/wildcard/exact), netmask-to-CIDR helpers |
|
|
@@ -171,9 +204,15 @@ make clean # Destroy all cloned VMs
|
|
|
171
204
|
| `public/manifest.json` | PWA web app manifest for installability |
|
|
172
205
|
| `public/sw.js` | Minimal service worker for PWA installability |
|
|
173
206
|
| `src/client/components/ZrokInstallGuide.tsx` | OS-aware zrok installation guide view (macOS/Linux/Windows) |
|
|
174
|
-
| `src/server/cli.ts` | CLI entry point with subcommands (start/stop/restart/status) |
|
|
207
|
+
| `src/server/cli.ts` | CLI entry point with subcommands (start/stop/restart/status); `findPortHolders` is cross-platform (netstat/taskkill on Windows, lsof on Unix) and `server.log` is opened append-mode with timestamped headers |
|
|
208
|
+
| `src/server/restart-helper.ts` | Cross-platform `/api/restart` orchestrator: spawns a detached `node -e` child using only Node built-ins (net, http) — no sh/lsof/curl dependency; exports pure `buildOrchestratorScript(params)` for testing |
|
|
209
|
+
| `src/shared/resolve-jiti.ts` | Resolves pi's jiti register hook as a `file://` URL (required for `node --import` on Windows); exports pure `buildJitiRegisterUrl(pkgJsonPath)` helper and `resolveJitiFromAnchor(anchorPath)` for managed-install/system-pi callers |
|
|
210
|
+
| `src/shared/platform/paths.ts` | OS-aware path primitives: `normalizePath`, `samePath` (filesystem-level equality), `parsePathInput` (picker input), `withTrailingSep`, `isFilesystemRoot`. All accept optional trailing `platform: NodeJS.Platform` for testability. Windows multi-drive invariant: A:\, B:\, C:\ never merge; bare `B:` input treated as drive root, not cwd-relative. Exported from `platform/index.ts` as `paths.*` namespace alongside `git.*`, `openspec.*`, `npm.*` |
|
|
211
|
+
| `src/client/lib/session-grouping.ts` | `inferPlatform(samples)` heuristic (backslash/drive-letter = Windows, leading `/` = POSIX) + `groupSessionsByDirectory` that uses `normalizePath`-keyed Maps so sessions group under their pinned folder across separator/case/trailing drift |
|
|
212
|
+
| `src/shared/platform/` | Unified cross-OS primitives (see `index.ts` barrel). Sub-modules: `exec.ts` (**the only module that imports `node:child_process`** — wraps `execSync`/`exec`/`execFile`/`spawn`/`spawnSync` with `windowsHide: true` by default; enforced by `no-direct-child-process.test.ts`), `runner.ts` (the Recipe engine — `run(recipe, input)` resolves binaries via `ToolResolver`, applies timeout / tolerate / error normalization, returns `Result<T>`), `git.ts` / `openspec.ts` / `npm.ts` (Recipe-based tool modules — typed functions like `git.diff(...)`, `openspec.list(...)`, `npm.rootGlobal()` that never touch `child_process` or `process.platform`), `binary-lookup.ts` (`where`/`which`, `.cmd` ext, `ToolResolver` class), `process.ts` (`findPortHolders`, `killProcess`, `isProcessAlive`, `killPidWithGroup`, `parseNetstatListeners`), `process-scan.ts` (`isProcessRunning` via pgrep/tasklist, `parseEtime`), `shell.ts` (`detectShell` for SHELL/COMSPEC, `getTerminalEnvHints`), `commands.ts` (`openBrowser`, `isVirtualMachine`). All exported helpers that depend on OS take an optional `platform: NodeJS.Platform` parameter so tests can exercise both branches without mutating `process.platform`. See changes: consolidate-platform-handlers, platform-command-executor. |
|
|
175
213
|
| `src/shared/rest-api.ts` | REST API type definitions |
|
|
176
214
|
| `scripts/reload-all.sh` | Build bridge + reload all pi sessions |
|
|
215
|
+
| `scripts/sync-versions.js` | Post-bump release helper. Reads every workspace `package.json`, enforces lockstep versions, rewrites every inter-package dep specifier (e.g. `"@blackbelt-technology/pi-dashboard-shared": "^<ver>"`) to the current bumped version. Called by `release-cut` skill AND by `.github/workflows/publish.yml` (defensively) between `npm version -ws` and `npm run build`. Required because the npm CLI does not implement the pnpm/yarn `workspace:` protocol — we use plain semver ranges and sync them at bump time. Cross-ref specifiers use plain `"^<ver>"`; `packages/electron` is `"private": true` so `npm publish -ws` skips it automatically. |
|
|
177
216
|
| `src/client/components/PiResourcesView.tsx` | Content area view for browsing pi extensions, skills, and prompts (with Installed/Packages tabs) |
|
|
178
217
|
| `src/client/components/PackageBrowser.tsx` | Reusable inline package browser: npm search, type filters, install/uninstall, manual URL input |
|
|
179
218
|
| `src/client/components/PackageCard.tsx` | Package card with type badges, downloads, install/uninstall actions |
|
|
@@ -181,6 +220,11 @@ make clean # Destroy all cloned VMs
|
|
|
181
220
|
| `src/client/components/PackageInstallConfirmDialog.tsx` | Confirmation dialog before package install (name, source, scope) |
|
|
182
221
|
| `src/client/hooks/usePackageSearch.ts` | Debounced fetch hook for `/api/packages/search` |
|
|
183
222
|
| `src/client/hooks/useInstalledPackages.ts` | Fetch hook for `/api/packages/installed` |
|
|
223
|
+
| `src/client/hooks/useRecommendedExtensions.ts` | Fetch hook for `/api/packages/recommended`; auto-refreshes on `package_operation_complete` |
|
|
224
|
+
| `src/client/components/RecommendedExtensions.tsx` | Curated-recommended-extensions card grid, rendered above search in Packages tab |
|
|
225
|
+
| `src/client/components/MissingRequiredBanner.tsx` | Top-of-page banner when any `required` recommended extension is missing from `~/.pi/agent/settings.json` `packages[]` |
|
|
226
|
+
| `src/shared/recommended-extensions.ts` | Static `RECOMMENDED_EXTENSIONS` manifest (pi-anthropic-messages, @tintinweb/pi-subagents, pi-flows, pi-web-access, pi-agent-browser); enriched server-side with live description/version and installed/active cross-reference |
|
|
227
|
+
| `src/server/routes/recommended-routes.ts` | `GET /api/packages/recommended` — enrichment + 60s cache, invalidated on successful install/remove/update |
|
|
184
228
|
| `src/client/hooks/usePackageOperations.ts` | Install/remove/update actions with WebSocket progress listening |
|
|
185
229
|
| `src/client/hooks/usePiResources.ts` | Fetch + 30s polling hook for pi resources API |
|
|
186
230
|
| `src/client/components/MarkdownPreviewView.tsx` | Generic reusable markdown preview with back button, tabs, loading/error states |
|
|
@@ -202,6 +246,9 @@ make clean # Destroy all cloned VMs
|
|
|
202
246
|
| `src/client/components/SessionHeader.tsx` | Session header with OpenSpec attach/detach, flow launcher, MobileAttachButton |
|
|
203
247
|
| `src/client/hooks/useSwipeBack.ts` | iOS-style left-edge swipe-back gesture (40px edge zone, document-level listeners) |
|
|
204
248
|
| `src/client/components/ChatView.tsx` | Chat message view with scroll-lock: pauses auto-scroll when user scrolls up, floating scroll-to-bottom button, per-session scroll position persistence |
|
|
249
|
+
| `src/client/components/CommandInput.tsx` | Chat textarea + autocomplete + controlled draft / history. Props: `sessionId`, `draft`, `onDraftChange` (lifted to App.tsx so the draft survives navigation), `history` (newest-first user prompts for this session). `ArrowUp`/`ArrowDown` walk history bash-style (only when no dropdown is open AND caret is on first/last line); `Escape` during history mode restores the in-progress draft. See change: chat-input-draft-and-history |
|
|
250
|
+
| `src/client/lib/draft-storage.ts` | Per-session chat input draft persistence helpers: `readAllDrafts()`, `writeDraft(sid, text)`, `deleteDraft(sid)`, key prefix `chat-draft:`. Wraps `localStorage` in try/catch (private-mode / quota safe). |
|
|
251
|
+
| `src/client/lib/message-history.ts` | `extractUserPromptHistory(messages)` — pure filter+dedup over `ChatMessage[]` returning newest-first user prompts with consecutive duplicates collapsed. Drives `ArrowUp`/`ArrowDown` history recall in `CommandInput`. |
|
|
205
252
|
| `src/client/lib/mobile-depth.ts` | Pure function computing MobileShell depth from route state |
|
|
206
253
|
| `src/client/hooks/useZoomPan.ts` | Reusable zoom/pan hook (wheel, drag, pinch, buttons) |
|
|
207
254
|
| `src/client/hooks/useMessageHandler.ts` | WebSocket message dispatch hook (extracted from App.tsx) |
|
|
@@ -260,6 +307,15 @@ make clean # Destroy all cloned VMs
|
|
|
260
307
|
| `packages/electron/scripts/docker-make.sh` | Docker entrypoint: platform-aware native module handling, ZIP for Windows |
|
|
261
308
|
| `packages/electron/scripts/Dockerfile.build` | Docker image for cross-platform builds (node:22-bookworm-slim + build tools) |
|
|
262
309
|
| `packages/electron/scripts/bundle-server.sh` | Bundles dashboard server source + deps into resources/server/ (--source-only for cross-builds) |
|
|
310
|
+
| `packages/electron/offline-packages.json` | Pinned versions of pi-coding-agent / openspec / tsx that get bundled as an offline npm cacache per release (see change: `electron-offline-bundled-packages`) |
|
|
311
|
+
| `packages/electron/scripts/bundle-offline-packages.sh` | Build-time script that runs `npm install --os=<os> --cpu=<cpu> --ignore-scripts` for the pinned versions, tars the resulting `_cacache/` (pax format — ustar is too narrow), writes `manifest.json` with SHA-256, and enforces a 100 MB hard budget. Opt-in via `BUNDLE_OFFLINE_PACKAGES=1`. |
|
|
312
|
+
| `packages/electron/resources/offline-packages/manifest.json` | Offline-cache manifest (`{bundledAt, targetPlatform, tarball, tarballBytes, sha256, packages}`). Consumed at runtime by `dependency-installer.ts` via `resolveOfflinePackages()`. |
|
|
313
|
+
| `packages/electron/resources/offline-packages/npm-cache.tar.gz` | gzipped npm cacache used by the first-run offline install. Extracted to `~/.pi-dashboard/.offline-cache/`, verified by SHA-256, consumed by `npm install --offline`, then deleted to reclaim ~140 MB. |
|
|
314
|
+
| `packages/electron/src/lib/offline-packages.ts` | Pure helpers: `parseOfflineManifest`, `resolveOfflinePackages`, `fileSha256`, `extractOfflineCache`, `buildOfflineInstallArgs`, `selectInstallStrategy`. 19 unit tests in `packages/electron/src/__tests__/offline-packages.test.ts`. |
|
|
315
|
+
| `packages/electron/scripts/bundle-recommended-extensions.sh` | Opt-in (via `BUNDLE_RECOMMENDED_EXTENSIONS=1`) build-time bundler that clones each id in `BUNDLED_EXTENSION_IDS` into `packages/electron/resources/bundled-extensions/<id>/`, records `.bundled-sha`, enforces SPDX allowlist (MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC) and a 15 MB total size budget. See change: bundle-first-party-extensions. |
|
|
316
|
+
| `packages/electron/src/lib/dependency-installer.ts` → `installBundledExtensions` | First-run activation of pre-bundled extensions. Copies `<resourcesPath>/bundled-extensions/<id>/` into pi's git cache (`~/.pi/agent/git/<host>/<path>/`), runs `npm install --omit=dev` if runtime deps declared, then calls `manager.addSourceToSettings(gitUrl)` + `settingsManager.flush()`. Returns activated ids so `installRecommendedExtensions` can skip them with `output: "Already installed (bundled)"`. |
|
|
317
|
+
| `packages/electron/src/lib/wizard-badge.ts` | Pure `classifyProgressBadge(output)` helper (`bundled` / `system` / null) shared between wizard HTML inline JS and unit tests. |
|
|
318
|
+
| `packages/shared/src/recommended-extensions.ts` → `BUNDLED_EXTENSION_IDS` | Single source of truth for which recommended ids ship bundled in the Electron installer. Currently `["pi-anthropic-messages", "pi-flows"]` (see design.md for pi-flows license blocker). |
|
|
263
319
|
| `packages/electron/scripts/docker-make.sh` | Docker entrypoint: bundles server, installs native deps, runs Forge make |
|
|
264
320
|
| `packages/electron/scripts/Dockerfile.build` | Docker image for cross-platform builds (node:22-bookworm-slim + build tools) |
|
|
265
321
|
| `packages/electron/scripts/test-server-launch.sh` | Docker-based test for server launch on clean Linux |
|