@blackbelt-technology/pi-agent-dashboard 0.3.0 → 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.
Files changed (197) hide show
  1. package/AGENTS.md +67 -116
  2. package/README.md +93 -7
  3. package/docs/architecture.md +408 -9
  4. package/package.json +6 -4
  5. package/packages/extension/package.json +11 -3
  6. package/packages/extension/src/__tests__/enrich-model-metadata.test.ts +201 -0
  7. package/packages/extension/src/__tests__/git-info.test.ts +67 -55
  8. package/packages/extension/src/__tests__/openspec-poller.test.ts +101 -96
  9. package/packages/extension/src/__tests__/process-scanner-kill.test.ts +61 -0
  10. package/packages/extension/src/__tests__/provider-register-reload.test.ts +394 -0
  11. package/packages/extension/src/__tests__/server-auto-start.test.ts +95 -4
  12. package/packages/extension/src/__tests__/server-launcher.test.ts +16 -0
  13. package/packages/extension/src/bridge.ts +69 -2
  14. package/packages/extension/src/dev-build.ts +1 -1
  15. package/packages/extension/src/git-info.ts +9 -19
  16. package/packages/extension/src/pi-env.d.ts +1 -0
  17. package/packages/extension/src/process-scanner.ts +72 -38
  18. package/packages/extension/src/provider-register.ts +304 -16
  19. package/packages/extension/src/server-auto-start.ts +27 -1
  20. package/packages/extension/src/server-launcher.ts +71 -27
  21. package/packages/server/package.json +16 -2
  22. package/packages/server/src/__tests__/bootstrap-queue.test.ts +120 -0
  23. package/packages/server/src/__tests__/bootstrap-routes.test.ts +125 -0
  24. package/packages/server/src/__tests__/bootstrap-state.test.ts +119 -0
  25. package/packages/server/src/__tests__/browse-endpoint.test.ts +17 -0
  26. package/packages/server/src/__tests__/cli-parse.test.ts +11 -0
  27. package/packages/server/src/__tests__/concurrent-launch.test.ts +110 -0
  28. package/packages/server/src/__tests__/config-api.test.ts +68 -0
  29. package/packages/server/src/__tests__/crash-recovery.test.ts +88 -0
  30. package/packages/server/src/__tests__/directory-service.test.ts +234 -8
  31. package/packages/server/src/__tests__/editor-registry.test.ts +28 -15
  32. package/packages/server/src/__tests__/extension-register-appimage.test.ts +5 -1
  33. package/packages/server/src/__tests__/extension-register.test.ts +3 -1
  34. package/packages/server/src/__tests__/find-port-holders.test.ts +94 -0
  35. package/packages/server/src/__tests__/force-kill-handler.test.ts +57 -8
  36. package/packages/server/src/__tests__/home-lock-escape-hatch.test.ts +60 -0
  37. package/packages/server/src/__tests__/home-lock-release.test.ts +85 -0
  38. package/packages/server/src/__tests__/home-lock.test.ts +308 -0
  39. package/packages/server/src/__tests__/is-pi-process.test.ts +36 -0
  40. package/packages/server/src/__tests__/node-guard.test.ts +85 -0
  41. package/packages/server/src/__tests__/package-manager-wrapper-resolve.test.ts +5 -1
  42. package/packages/server/src/__tests__/package-manager-wrapper.test.ts +45 -10
  43. package/packages/server/src/__tests__/pi-version-skew.test.ts +165 -0
  44. package/packages/server/src/__tests__/preferences-store.test.ts +73 -4
  45. package/packages/server/src/__tests__/process-manager.test.ts +45 -18
  46. package/packages/server/src/__tests__/provider-probe.test.ts +287 -0
  47. package/packages/server/src/__tests__/provider-test-route.test.ts +149 -0
  48. package/packages/server/src/__tests__/restart-helper.test.ts +83 -0
  49. package/packages/server/src/__tests__/session-action-handler-headless-reload.test.ts +467 -0
  50. package/packages/server/src/__tests__/session-action-handler-reload-predicate.test.ts +73 -0
  51. package/packages/server/src/__tests__/session-action-handler-spawn-error.test.ts +74 -0
  52. package/packages/server/src/__tests__/terminal-manager.test.ts +41 -1
  53. package/packages/server/src/__tests__/tool-routes.test.ts +277 -0
  54. package/packages/server/src/__tests__/trusted-networks-config.test.ts +19 -0
  55. package/packages/server/src/__tests__/trusted-networks-no-oauth-roundtrip.test.ts +126 -0
  56. package/packages/server/src/__tests__/tunnel-cleanup.test.ts +90 -0
  57. package/packages/server/src/__tests__/tunnel.test.ts +13 -7
  58. package/packages/server/src/__tests__/wsl-tmux-probe-cache.test.ts +44 -0
  59. package/packages/server/src/bootstrap-queue.ts +130 -0
  60. package/packages/server/src/bootstrap-state.ts +131 -0
  61. package/packages/server/src/browse.ts +8 -3
  62. package/packages/server/src/browser-handlers/directory-handler.ts +23 -8
  63. package/packages/server/src/browser-handlers/session-action-handler.ts +213 -79
  64. package/packages/server/src/browser-handlers/session-action-helpers.ts +36 -0
  65. package/packages/server/src/cli.ts +256 -32
  66. package/packages/server/src/config-api.ts +16 -0
  67. package/packages/server/src/directory-service.ts +270 -39
  68. package/packages/server/src/editor-detection.ts +12 -9
  69. package/packages/server/src/editor-manager.ts +19 -4
  70. package/packages/server/src/editor-pid-registry.ts +9 -8
  71. package/packages/server/src/editor-registry.ts +22 -25
  72. package/packages/server/src/git-operations.ts +1 -1
  73. package/packages/server/src/headless-pid-registry.ts +7 -20
  74. package/packages/server/src/home-lock-release.ts +72 -0
  75. package/packages/server/src/home-lock.ts +389 -0
  76. package/packages/server/src/node-guard.ts +52 -0
  77. package/packages/server/src/package-manager-wrapper.ts +207 -47
  78. package/packages/server/src/pi-core-checker.ts +1 -1
  79. package/packages/server/src/pi-core-updater.ts +7 -1
  80. package/packages/server/src/pi-resource-scanner.ts +5 -8
  81. package/packages/server/src/pi-version-skew.ts +196 -0
  82. package/packages/server/src/preferences-store.ts +17 -3
  83. package/packages/server/src/process-manager.ts +403 -222
  84. package/packages/server/src/provider-probe.ts +234 -0
  85. package/packages/server/src/restart-helper.ts +130 -0
  86. package/packages/server/src/routes/bootstrap-routes.ts +88 -0
  87. package/packages/server/src/routes/openspec-routes.ts +25 -1
  88. package/packages/server/src/routes/pi-core-routes.ts +24 -1
  89. package/packages/server/src/routes/provider-auth-routes.ts +8 -8
  90. package/packages/server/src/routes/provider-routes.ts +43 -0
  91. package/packages/server/src/routes/recommended-routes.ts +10 -12
  92. package/packages/server/src/routes/system-routes.ts +20 -33
  93. package/packages/server/src/routes/tool-routes.ts +153 -0
  94. package/packages/server/src/server-pid.ts +5 -9
  95. package/packages/server/src/server.ts +211 -10
  96. package/packages/server/src/session-api.ts +77 -8
  97. package/packages/server/src/session-bootstrap.ts +17 -3
  98. package/packages/server/src/session-diff.ts +21 -21
  99. package/packages/server/src/terminal-manager.ts +61 -20
  100. package/packages/server/src/tunnel.ts +42 -28
  101. package/packages/shared/package.json +10 -3
  102. package/packages/shared/src/__tests__/{tool-resolver.test.ts → binary-lookup.test.ts} +32 -12
  103. package/packages/shared/src/__tests__/bootstrap/README.md +133 -0
  104. package/packages/shared/src/__tests__/bootstrap/__snapshots__/cube.test.ts.snap +370 -0
  105. package/packages/shared/src/__tests__/bootstrap/assertions.ts +136 -0
  106. package/packages/shared/src/__tests__/bootstrap/cube.test.ts +47 -0
  107. package/packages/shared/src/__tests__/bootstrap/cube.ts +66 -0
  108. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/a-electron.test.ts.snap +83 -0
  109. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/b-npm-global.test.ts.snap +89 -0
  110. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/c-dev-monorepo.test.ts.snap +33 -0
  111. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/d-overrides.test.ts.snap +20 -0
  112. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/e-stale-partial.test.ts.snap +61 -0
  113. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/f-cwd-variants.test.ts.snap +33 -0
  114. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/g-windows-specifics.test.ts.snap +46 -0
  115. package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/j-path-gui-minimal.test.ts.snap +12 -0
  116. package/packages/shared/src/__tests__/bootstrap/families/a-electron.test.ts +156 -0
  117. package/packages/shared/src/__tests__/bootstrap/families/b-npm-global.test.ts +157 -0
  118. package/packages/shared/src/__tests__/bootstrap/families/c-dev-monorepo.test.ts +102 -0
  119. package/packages/shared/src/__tests__/bootstrap/families/d-overrides.test.ts +76 -0
  120. package/packages/shared/src/__tests__/bootstrap/families/e-stale-partial.test.ts +94 -0
  121. package/packages/shared/src/__tests__/bootstrap/families/f-cwd-variants.test.ts +87 -0
  122. package/packages/shared/src/__tests__/bootstrap/families/g-windows-specifics.test.ts +143 -0
  123. package/packages/shared/src/__tests__/bootstrap/families/h-home-drift.test.ts +64 -0
  124. package/packages/shared/src/__tests__/bootstrap/families/i-malformed-settings.test.ts +77 -0
  125. package/packages/shared/src/__tests__/bootstrap/families/index.ts +19 -0
  126. package/packages/shared/src/__tests__/bootstrap/families/j-path-gui-minimal.test.ts +61 -0
  127. package/packages/shared/src/__tests__/bootstrap/families/k-dashboard-absent.test.ts +50 -0
  128. package/packages/shared/src/__tests__/bootstrap/families/l-instance-coordination.test.ts +272 -0
  129. package/packages/shared/src/__tests__/bootstrap/fixtures/dev-monorepo.ts +58 -0
  130. package/packages/shared/src/__tests__/bootstrap/fixtures/electron-layout.ts +84 -0
  131. package/packages/shared/src/__tests__/bootstrap/fixtures/index.ts +9 -0
  132. package/packages/shared/src/__tests__/bootstrap/fixtures/managed-install.ts +85 -0
  133. package/packages/shared/src/__tests__/bootstrap/fixtures/npm-global-layout.ts +122 -0
  134. package/packages/shared/src/__tests__/bootstrap/fixtures/pi-versions.ts +36 -0
  135. package/packages/shared/src/__tests__/bootstrap/fixtures/settings-json.ts +39 -0
  136. package/packages/shared/src/__tests__/bootstrap/harness.smoke.test.ts +220 -0
  137. package/packages/shared/src/__tests__/bootstrap/harness.ts +413 -0
  138. package/packages/shared/src/__tests__/bootstrap/scenarios-skipped.ts +125 -0
  139. package/packages/shared/src/__tests__/bootstrap/scenarios.ts +132 -0
  140. package/packages/shared/src/__tests__/bridge-register.test.ts +29 -6
  141. package/packages/shared/src/__tests__/config-openspec.test.ts +106 -0
  142. package/packages/shared/src/__tests__/config.test.ts +56 -0
  143. package/packages/shared/src/__tests__/detached-spawn.test.ts +243 -0
  144. package/packages/shared/src/__tests__/managed-paths.test.ts +60 -0
  145. package/packages/shared/src/__tests__/no-direct-child-process.test.ts +112 -0
  146. package/packages/shared/src/__tests__/no-direct-platform-branch.test.ts +174 -0
  147. package/packages/shared/src/__tests__/no-direct-process-kill.test.ts +105 -0
  148. package/packages/shared/src/__tests__/platform-commands.test.ts +108 -0
  149. package/packages/shared/src/__tests__/platform-exec.test.ts +103 -0
  150. package/packages/shared/src/__tests__/platform-git.test.ts +194 -0
  151. package/packages/shared/src/__tests__/platform-npm.test.ts +137 -0
  152. package/packages/shared/src/__tests__/platform-openspec.test.ts +92 -0
  153. package/packages/shared/src/__tests__/platform-paths.test.ts +284 -0
  154. package/packages/shared/src/__tests__/platform-process-scan.test.ts +55 -0
  155. package/packages/shared/src/__tests__/platform-process.test.ts +160 -0
  156. package/packages/shared/src/__tests__/platform-runner.test.ts +173 -0
  157. package/packages/shared/src/__tests__/platform-shell.test.ts +74 -0
  158. package/packages/shared/src/__tests__/process-identify.test.ts +113 -0
  159. package/packages/shared/src/__tests__/recommended-extensions.test.ts +40 -7
  160. package/packages/shared/src/__tests__/resolve-jiti.test.ts +43 -7
  161. package/packages/shared/src/__tests__/semaphore.test.ts +119 -0
  162. package/packages/shared/src/__tests__/spawn-mechanism.test.ts +131 -0
  163. package/packages/shared/src/__tests__/tool-registry-definitions.test.ts +239 -0
  164. package/packages/shared/src/__tests__/tool-registry-overrides.test.ts +137 -0
  165. package/packages/shared/src/__tests__/tool-registry-registry.test.ts +343 -0
  166. package/packages/shared/src/bootstrap-install.ts +212 -0
  167. package/packages/shared/src/bridge-register.ts +87 -20
  168. package/packages/shared/src/browser-protocol.ts +71 -1
  169. package/packages/shared/src/config.ts +87 -15
  170. package/packages/shared/src/managed-paths.ts +31 -4
  171. package/packages/shared/src/openspec-poller.ts +63 -46
  172. package/packages/shared/src/{tool-resolver.ts → platform/binary-lookup.ts} +125 -25
  173. package/packages/shared/src/platform/commands.ts +100 -0
  174. package/packages/shared/src/platform/detached-spawn.ts +305 -0
  175. package/packages/shared/src/platform/exec.ts +220 -0
  176. package/packages/shared/src/platform/git.ts +155 -0
  177. package/packages/shared/src/platform/index.ts +15 -0
  178. package/packages/shared/src/platform/npm.ts +162 -0
  179. package/packages/shared/src/platform/openspec.ts +91 -0
  180. package/packages/shared/src/platform/paths.ts +276 -0
  181. package/packages/shared/src/platform/process-identify.ts +126 -0
  182. package/packages/shared/src/platform/process-scan.ts +94 -0
  183. package/packages/shared/src/platform/process.ts +168 -0
  184. package/packages/shared/src/platform/runner.ts +369 -0
  185. package/packages/shared/src/platform/shell.ts +44 -0
  186. package/packages/shared/src/platform/spawn-mechanism.ts +124 -0
  187. package/packages/shared/src/platform/subprocess-adapter.ts +124 -0
  188. package/packages/shared/src/recommended-extensions.ts +18 -2
  189. package/packages/shared/src/resolve-jiti.ts +62 -3
  190. package/packages/shared/src/rest-api.ts +26 -0
  191. package/packages/shared/src/semaphore.ts +83 -0
  192. package/packages/shared/src/tool-registry/definitions.ts +342 -0
  193. package/packages/shared/src/tool-registry/index.ts +56 -0
  194. package/packages/shared/src/tool-registry/overrides.ts +118 -0
  195. package/packages/shared/src/tool-registry/registry.ts +262 -0
  196. package/packages/shared/src/tool-registry/strategies.ts +198 -0
  197. package/packages/shared/src/tool-registry/types.ts +180 -0
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Public type contract for the tool registry.
3
+ *
4
+ * The registry resolves every external binary, module, or directory the
5
+ * dashboard depends on through an ordered list of strategies. Each
6
+ * resolution records a diagnostic trail (what was tried + why it
7
+ * succeeded/failed) alongside the winning path.
8
+ *
9
+ * See change: consolidate-tool-resolution.
10
+ */
11
+
12
+ /** What kind of artifact a tool definition resolves. */
13
+ export type ToolKind = "binary" | "module" | "directory" | "executor";
14
+
15
+ /**
16
+ * How a resolved path was obtained. Strategy name → source mapping is
17
+ * declared by each tool definition's `classify()` (see registry).
18
+ */
19
+ export type Source =
20
+ | "override"
21
+ | "managed"
22
+ | "system"
23
+ | "npm-global"
24
+ | "bare-import";
25
+
26
+ /** Result returned by a single strategy attempt. */
27
+ export type StrategyResult =
28
+ | { ok: true; path: string }
29
+ | { ok: false; reason: string };
30
+
31
+ /** One attempt recorded on a Resolution's `tried[]` list. */
32
+ export interface TriedEntry {
33
+ /** Strategy name, e.g. "override", "managed", "npm-global". */
34
+ strategy: string;
35
+ /** "ok" on success, the strategy's failure reason on miss. */
36
+ result: "ok" | string;
37
+ }
38
+
39
+ /** Output of `ToolRegistry.resolve(name)`. */
40
+ export interface Resolution {
41
+ /** Tool name as registered. */
42
+ name: string;
43
+ /** True if any strategy produced a valid path. */
44
+ ok: boolean;
45
+ /** Absolute path (binary / module entry / directory). Null on failure. */
46
+ path: string | null;
47
+ /** Source classification of the winning strategy. Null on failure. */
48
+ source: Source | null;
49
+ /** Ordered diagnostic trail — one entry per attempted strategy. */
50
+ tried: TriedEntry[];
51
+ /** Epoch ms when resolution completed. */
52
+ resolvedAt: number;
53
+ }
54
+
55
+ /**
56
+ * Output of `ToolRegistry.resolveExecutor(name)` — extends Resolution
57
+ * with `argv`, the ready-to-spawn command array.
58
+ *
59
+ * Callers spawn via `spawn(argv[0], [...argv.slice(1), ...userArgs])`.
60
+ * For simple binaries `argv = [path]`; for scripts that need an
61
+ * interpreter (e.g. pi's `node dist/cli.js` on Windows) `argv =
62
+ * [interpreter, scriptPath]`.
63
+ *
64
+ * See change: consolidate-windows-spawn-and-platform-handlers.
65
+ */
66
+ export interface ExecutorResolution extends Resolution {
67
+ argv: string[];
68
+ }
69
+
70
+ /** Context passed to every strategy function. */
71
+ export interface StrategyCtx {
72
+ /** Per-registry override map, { [toolName]: absolutePath }. */
73
+ overrides: Readonly<Record<string, string>>;
74
+ /** Platform discriminator (injectable for tests). */
75
+ platform: NodeJS.Platform;
76
+ /**
77
+ * Environment overrides used by HOME-sensitive strategies (managed/*,
78
+ * npm-global under APPDATA on win32, etc.). Production registries
79
+ * populate from `os.homedir()` + `process.cwd()`; tests inject fakes
80
+ * so the harness can reason about alternate HOME directories without
81
+ * mutating globals.
82
+ */
83
+ env?: {
84
+ homedir?: string;
85
+ cwd?: string;
86
+ };
87
+ }
88
+
89
+ /** A single resolution strategy. Pure function of its ctx + the tool's data. */
90
+ export interface Strategy {
91
+ /** Name recorded in `tried[]`. */
92
+ name: string;
93
+ /** Attempt resolution. Never throws — signal failure via { ok: false }. */
94
+ run(ctx: StrategyCtx): StrategyResult;
95
+ }
96
+
97
+ /**
98
+ * Transform a successfully-resolved path into an argv ready to pass
99
+ * to `spawn(argv[0], argv.slice(1))`.
100
+ *
101
+ * Default behaviour (when a definition omits `toArgv`): `argv = [path]`.
102
+ * Scripts that need an interpreter (e.g. pi's `cli.js` on Windows)
103
+ * return `[interpreterPath, scriptPath]`.
104
+ *
105
+ * The function may call `registry.resolve(...)` to look up peer tools
106
+ * (e.g. `node`). It MUST NOT throw — return the path-only fallback
107
+ * `[path]` if a peer tool is missing.
108
+ */
109
+ export type ToArgvFn = (resolvedPath: string, ctx: { platform: NodeJS.Platform; registry: ToolRegistryLike }) => string[];
110
+
111
+ /** Minimal interface used by `toArgv` functions to look up peer tools. */
112
+ export interface ToolRegistryLike {
113
+ resolve(name: string): Resolution;
114
+ }
115
+
116
+ /** Declarative tool registration. */
117
+ export interface ToolDefinition {
118
+ /** Registry key — unique within the registry. */
119
+ name: string;
120
+ /** Kind drives how `resolveModule()` / path validation behaves. */
121
+ kind: ToolKind;
122
+ /**
123
+ * Ordered strategies used when no platform-specific override exists
124
+ * for the current OS. First successful strategy wins.
125
+ */
126
+ strategies: Strategy[];
127
+ /**
128
+ * Optional per-platform strategy override. Present key wins over
129
+ * `strategies`. Absent key falls back to `strategies`.
130
+ *
131
+ * Use this when the chain itself is OS-dependent — e.g. pi on
132
+ * Windows looks for a JS entry (dist/cli.js via module strategies),
133
+ * while on Unix it looks for a `pi` binary on PATH.
134
+ */
135
+ platformStrategies?: Partial<Record<NodeJS.Platform, Strategy[]>>;
136
+ /**
137
+ * Optional transform from resolved path → ready-to-spawn argv.
138
+ * Used by `resolveExecutor(name)`. Omitted → argv defaults to `[path]`.
139
+ */
140
+ toArgv?: ToArgvFn;
141
+ /**
142
+ * Map a winning strategy name → Source. Unknown strategy names fall
143
+ * back to the default ("system"). Definitions usually set this so
144
+ * that e.g. "managed" → "managed", "bare-import" → "bare-import".
145
+ */
146
+ classify?(strategyName: string): Source;
147
+ /**
148
+ * Optional post-resolution validation (e.g. "dist/index.js exists").
149
+ * If provided and returns a reason, the strategy is demoted to a
150
+ * failure carrying that reason, and the next strategy is tried.
151
+ */
152
+ validate?(resolvedPath: string): { ok: true } | { ok: false; reason: string };
153
+ }
154
+
155
+ // ── Errors ──────────────────────────────────────────────────────────────────
156
+
157
+ /** Thrown by `resolve()` / `resolveModule()` for unregistered names. */
158
+ export class UnknownToolError extends Error {
159
+ public readonly tool: string;
160
+ constructor(tool: string) {
161
+ super(`Unknown tool: ${tool}`);
162
+ this.name = "UnknownToolError";
163
+ this.tool = tool;
164
+ }
165
+ }
166
+
167
+ /** Thrown by `resolveModule()` when every strategy fails. */
168
+ export class ModuleResolutionError extends Error {
169
+ public readonly resolution: Resolution;
170
+ constructor(resolution: Resolution) {
171
+ const trail = resolution.tried
172
+ .map((t) => ` - ${t.strategy}: ${t.result}`)
173
+ .join("\n");
174
+ super(
175
+ `Could not resolve module "${resolution.name}". Tried:\n${trail}`,
176
+ );
177
+ this.name = "ModuleResolutionError";
178
+ this.resolution = resolution;
179
+ }
180
+ }