@blackbelt-technology/pi-agent-dashboard 0.2.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 (212) hide show
  1. package/AGENTS.md +342 -0
  2. package/README.md +619 -0
  3. package/docs/architecture.md +646 -0
  4. package/package.json +92 -0
  5. package/packages/extension/package.json +33 -0
  6. package/packages/extension/src/__tests__/ask-user-tool.test.ts +85 -0
  7. package/packages/extension/src/__tests__/command-handler.test.ts +712 -0
  8. package/packages/extension/src/__tests__/connection.test.ts +344 -0
  9. package/packages/extension/src/__tests__/credentials-updated.test.ts +26 -0
  10. package/packages/extension/src/__tests__/dev-build.test.ts +79 -0
  11. package/packages/extension/src/__tests__/event-forwarder.test.ts +89 -0
  12. package/packages/extension/src/__tests__/git-info.test.ts +112 -0
  13. package/packages/extension/src/__tests__/git-link-builder.test.ts +102 -0
  14. package/packages/extension/src/__tests__/openspec-activity-detector.test.ts +232 -0
  15. package/packages/extension/src/__tests__/openspec-poller.test.ts +119 -0
  16. package/packages/extension/src/__tests__/process-metrics.test.ts +47 -0
  17. package/packages/extension/src/__tests__/process-scanner.test.ts +202 -0
  18. package/packages/extension/src/__tests__/prompt-expander.test.ts +54 -0
  19. package/packages/extension/src/__tests__/server-auto-start.test.ts +167 -0
  20. package/packages/extension/src/__tests__/server-launcher.test.ts +44 -0
  21. package/packages/extension/src/__tests__/server-probe.test.ts +25 -0
  22. package/packages/extension/src/__tests__/session-switch.test.ts +139 -0
  23. package/packages/extension/src/__tests__/session-sync.test.ts +55 -0
  24. package/packages/extension/src/__tests__/source-detector.test.ts +73 -0
  25. package/packages/extension/src/__tests__/stats-extractor.test.ts +92 -0
  26. package/packages/extension/src/__tests__/ui-proxy.test.ts +583 -0
  27. package/packages/extension/src/__tests__/watchdog.test.ts +161 -0
  28. package/packages/extension/src/ask-user-tool.ts +63 -0
  29. package/packages/extension/src/bridge-context.ts +64 -0
  30. package/packages/extension/src/bridge.ts +926 -0
  31. package/packages/extension/src/command-handler.ts +538 -0
  32. package/packages/extension/src/connection.ts +204 -0
  33. package/packages/extension/src/dev-build.ts +39 -0
  34. package/packages/extension/src/event-forwarder.ts +40 -0
  35. package/packages/extension/src/flow-event-wiring.ts +102 -0
  36. package/packages/extension/src/git-info.ts +65 -0
  37. package/packages/extension/src/git-link-builder.ts +112 -0
  38. package/packages/extension/src/model-tracker.ts +56 -0
  39. package/packages/extension/src/pi-env.d.ts +23 -0
  40. package/packages/extension/src/process-metrics.ts +70 -0
  41. package/packages/extension/src/process-scanner.ts +396 -0
  42. package/packages/extension/src/prompt-expander.ts +87 -0
  43. package/packages/extension/src/provider-register.ts +276 -0
  44. package/packages/extension/src/server-auto-start.ts +87 -0
  45. package/packages/extension/src/server-launcher.ts +82 -0
  46. package/packages/extension/src/server-probe.ts +33 -0
  47. package/packages/extension/src/session-sync.ts +154 -0
  48. package/packages/extension/src/source-detector.ts +26 -0
  49. package/packages/extension/src/ui-proxy.ts +269 -0
  50. package/packages/extension/tsconfig.json +11 -0
  51. package/packages/server/package.json +37 -0
  52. package/packages/server/src/__tests__/auth-plugin.test.ts +117 -0
  53. package/packages/server/src/__tests__/auth.test.ts +224 -0
  54. package/packages/server/src/__tests__/auto-attach.test.ts +246 -0
  55. package/packages/server/src/__tests__/auto-resume.test.ts +135 -0
  56. package/packages/server/src/__tests__/auto-shutdown.test.ts +136 -0
  57. package/packages/server/src/__tests__/browse-endpoint.test.ts +104 -0
  58. package/packages/server/src/__tests__/bulk-archive-handler.test.ts +15 -0
  59. package/packages/server/src/__tests__/cli-parse.test.ts +73 -0
  60. package/packages/server/src/__tests__/client-discovery.test.ts +39 -0
  61. package/packages/server/src/__tests__/config-api.test.ts +104 -0
  62. package/packages/server/src/__tests__/cors.test.ts +48 -0
  63. package/packages/server/src/__tests__/directory-service.test.ts +240 -0
  64. package/packages/server/src/__tests__/editor-detection.test.ts +60 -0
  65. package/packages/server/src/__tests__/editor-endpoints.test.ts +26 -0
  66. package/packages/server/src/__tests__/editor-manager.test.ts +73 -0
  67. package/packages/server/src/__tests__/editor-registry.test.ts +151 -0
  68. package/packages/server/src/__tests__/event-status-extraction-flow.test.ts +55 -0
  69. package/packages/server/src/__tests__/event-status-extraction.test.ts +58 -0
  70. package/packages/server/src/__tests__/extension-register.test.ts +61 -0
  71. package/packages/server/src/__tests__/file-endpoint.test.ts +49 -0
  72. package/packages/server/src/__tests__/force-kill-handler.test.ts +109 -0
  73. package/packages/server/src/__tests__/git-operations.test.ts +251 -0
  74. package/packages/server/src/__tests__/headless-pid-registry.test.ts +233 -0
  75. package/packages/server/src/__tests__/headless-shutdown-fallback.test.ts +109 -0
  76. package/packages/server/src/__tests__/health-endpoint.test.ts +35 -0
  77. package/packages/server/src/__tests__/heartbeat-ack.test.ts +63 -0
  78. package/packages/server/src/__tests__/json-store.test.ts +70 -0
  79. package/packages/server/src/__tests__/localhost-guard.test.ts +149 -0
  80. package/packages/server/src/__tests__/memory-event-store.test.ts +260 -0
  81. package/packages/server/src/__tests__/memory-session-manager.test.ts +80 -0
  82. package/packages/server/src/__tests__/meta-persistence.test.ts +107 -0
  83. package/packages/server/src/__tests__/migrate-persistence.test.ts +180 -0
  84. package/packages/server/src/__tests__/npm-search-proxy.test.ts +153 -0
  85. package/packages/server/src/__tests__/oauth-callback-server.test.ts +165 -0
  86. package/packages/server/src/__tests__/openspec-archive.test.ts +87 -0
  87. package/packages/server/src/__tests__/package-manager-wrapper.test.ts +163 -0
  88. package/packages/server/src/__tests__/package-routes.test.ts +172 -0
  89. package/packages/server/src/__tests__/pending-fork-registry.test.ts +69 -0
  90. package/packages/server/src/__tests__/pending-load-manager.test.ts +144 -0
  91. package/packages/server/src/__tests__/pending-resume-registry.test.ts +130 -0
  92. package/packages/server/src/__tests__/pi-resource-scanner.test.ts +235 -0
  93. package/packages/server/src/__tests__/preferences-store.test.ts +108 -0
  94. package/packages/server/src/__tests__/process-manager.test.ts +184 -0
  95. package/packages/server/src/__tests__/provider-auth-handlers.test.ts +93 -0
  96. package/packages/server/src/__tests__/provider-auth-routes.test.ts +143 -0
  97. package/packages/server/src/__tests__/provider-auth-storage.test.ts +114 -0
  98. package/packages/server/src/__tests__/resolve-path.test.ts +38 -0
  99. package/packages/server/src/__tests__/ring-buffer.test.ts +45 -0
  100. package/packages/server/src/__tests__/server-pid.test.ts +89 -0
  101. package/packages/server/src/__tests__/session-api.test.ts +244 -0
  102. package/packages/server/src/__tests__/session-diff.test.ts +138 -0
  103. package/packages/server/src/__tests__/session-file-dedup.test.ts +102 -0
  104. package/packages/server/src/__tests__/session-file-reader.test.ts +85 -0
  105. package/packages/server/src/__tests__/session-lifecycle-logging.test.ts +138 -0
  106. package/packages/server/src/__tests__/session-order-manager.test.ts +135 -0
  107. package/packages/server/src/__tests__/session-ordering-integration.test.ts +102 -0
  108. package/packages/server/src/__tests__/session-scanner.test.ts +199 -0
  109. package/packages/server/src/__tests__/shutdown-endpoint.test.ts +42 -0
  110. package/packages/server/src/__tests__/skip-wipe.test.ts +123 -0
  111. package/packages/server/src/__tests__/sleep-aware-heartbeat.test.ts +126 -0
  112. package/packages/server/src/__tests__/smoke-integration.test.ts +175 -0
  113. package/packages/server/src/__tests__/spa-fallback.test.ts +68 -0
  114. package/packages/server/src/__tests__/subscription-handler.test.ts +155 -0
  115. package/packages/server/src/__tests__/terminal-gateway.test.ts +61 -0
  116. package/packages/server/src/__tests__/terminal-manager.test.ts +257 -0
  117. package/packages/server/src/__tests__/trusted-networks-config.test.ts +84 -0
  118. package/packages/server/src/__tests__/tunnel.test.ts +206 -0
  119. package/packages/server/src/__tests__/ws-ping-pong.test.ts +112 -0
  120. package/packages/server/src/auth-plugin.ts +302 -0
  121. package/packages/server/src/auth.ts +323 -0
  122. package/packages/server/src/browse.ts +55 -0
  123. package/packages/server/src/browser-gateway.ts +495 -0
  124. package/packages/server/src/browser-handlers/directory-handler.ts +137 -0
  125. package/packages/server/src/browser-handlers/handler-context.ts +45 -0
  126. package/packages/server/src/browser-handlers/session-action-handler.ts +271 -0
  127. package/packages/server/src/browser-handlers/session-meta-handler.ts +95 -0
  128. package/packages/server/src/browser-handlers/subscription-handler.ts +154 -0
  129. package/packages/server/src/browser-handlers/terminal-handler.ts +37 -0
  130. package/packages/server/src/cli.ts +347 -0
  131. package/packages/server/src/config-api.ts +130 -0
  132. package/packages/server/src/directory-service.ts +162 -0
  133. package/packages/server/src/editor-detection.ts +60 -0
  134. package/packages/server/src/editor-manager.ts +352 -0
  135. package/packages/server/src/editor-proxy.ts +134 -0
  136. package/packages/server/src/editor-registry.ts +108 -0
  137. package/packages/server/src/event-status-extraction.ts +131 -0
  138. package/packages/server/src/event-wiring.ts +589 -0
  139. package/packages/server/src/extension-register.ts +92 -0
  140. package/packages/server/src/git-operations.ts +200 -0
  141. package/packages/server/src/headless-pid-registry.ts +207 -0
  142. package/packages/server/src/idle-timer.ts +61 -0
  143. package/packages/server/src/json-store.ts +32 -0
  144. package/packages/server/src/localhost-guard.ts +117 -0
  145. package/packages/server/src/memory-event-store.ts +193 -0
  146. package/packages/server/src/memory-session-manager.ts +123 -0
  147. package/packages/server/src/meta-persistence.ts +64 -0
  148. package/packages/server/src/migrate-persistence.ts +195 -0
  149. package/packages/server/src/npm-search-proxy.ts +143 -0
  150. package/packages/server/src/oauth-callback-server.ts +177 -0
  151. package/packages/server/src/openspec-archive.ts +60 -0
  152. package/packages/server/src/package-manager-wrapper.ts +200 -0
  153. package/packages/server/src/pending-fork-registry.ts +53 -0
  154. package/packages/server/src/pending-load-manager.ts +110 -0
  155. package/packages/server/src/pending-resume-registry.ts +69 -0
  156. package/packages/server/src/pi-gateway.ts +419 -0
  157. package/packages/server/src/pi-resource-scanner.ts +369 -0
  158. package/packages/server/src/preferences-store.ts +116 -0
  159. package/packages/server/src/process-manager.ts +311 -0
  160. package/packages/server/src/provider-auth-handlers.ts +438 -0
  161. package/packages/server/src/provider-auth-storage.ts +200 -0
  162. package/packages/server/src/resolve-path.ts +12 -0
  163. package/packages/server/src/routes/editor-routes.ts +86 -0
  164. package/packages/server/src/routes/file-routes.ts +116 -0
  165. package/packages/server/src/routes/git-routes.ts +89 -0
  166. package/packages/server/src/routes/openspec-routes.ts +99 -0
  167. package/packages/server/src/routes/package-routes.ts +172 -0
  168. package/packages/server/src/routes/provider-auth-routes.ts +244 -0
  169. package/packages/server/src/routes/provider-routes.ts +101 -0
  170. package/packages/server/src/routes/route-deps.ts +23 -0
  171. package/packages/server/src/routes/session-routes.ts +91 -0
  172. package/packages/server/src/routes/system-routes.ts +271 -0
  173. package/packages/server/src/server-pid.ts +84 -0
  174. package/packages/server/src/server.ts +554 -0
  175. package/packages/server/src/session-api.ts +330 -0
  176. package/packages/server/src/session-bootstrap.ts +80 -0
  177. package/packages/server/src/session-diff.ts +178 -0
  178. package/packages/server/src/session-discovery.ts +134 -0
  179. package/packages/server/src/session-file-reader.ts +135 -0
  180. package/packages/server/src/session-order-manager.ts +73 -0
  181. package/packages/server/src/session-scanner.ts +233 -0
  182. package/packages/server/src/session-stats-reader.ts +99 -0
  183. package/packages/server/src/terminal-gateway.ts +51 -0
  184. package/packages/server/src/terminal-manager.ts +241 -0
  185. package/packages/server/src/tunnel.ts +329 -0
  186. package/packages/server/tsconfig.json +11 -0
  187. package/packages/shared/package.json +15 -0
  188. package/packages/shared/src/__tests__/config.test.ts +358 -0
  189. package/packages/shared/src/__tests__/deriveChangeState.test.ts +95 -0
  190. package/packages/shared/src/__tests__/mdns-discovery.test.ts +80 -0
  191. package/packages/shared/src/__tests__/protocol.test.ts +243 -0
  192. package/packages/shared/src/__tests__/resolve-jiti.test.ts +17 -0
  193. package/packages/shared/src/__tests__/server-identity.test.ts +73 -0
  194. package/packages/shared/src/__tests__/session-meta.test.ts +125 -0
  195. package/packages/shared/src/archive-types.ts +11 -0
  196. package/packages/shared/src/browser-protocol.ts +534 -0
  197. package/packages/shared/src/config.ts +245 -0
  198. package/packages/shared/src/diff-types.ts +41 -0
  199. package/packages/shared/src/editor-types.ts +18 -0
  200. package/packages/shared/src/mdns-discovery.ts +248 -0
  201. package/packages/shared/src/openspec-activity-detector.ts +109 -0
  202. package/packages/shared/src/openspec-poller.ts +96 -0
  203. package/packages/shared/src/protocol.ts +369 -0
  204. package/packages/shared/src/resolve-jiti.ts +43 -0
  205. package/packages/shared/src/rest-api.ts +255 -0
  206. package/packages/shared/src/server-identity.ts +51 -0
  207. package/packages/shared/src/session-meta.ts +86 -0
  208. package/packages/shared/src/state-replay.ts +174 -0
  209. package/packages/shared/src/stats-extractor.ts +54 -0
  210. package/packages/shared/src/terminal-types.ts +18 -0
  211. package/packages/shared/src/types.ts +351 -0
  212. package/packages/shared/tsconfig.json +8 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Polls the openspec CLI to gather change data for the session's project.
3
+ * Uses async child processes to avoid blocking the event loop.
4
+ */
5
+ import { spawnSync, execFile } from "node:child_process";
6
+ import { promisify } from "node:util";
7
+ import type { OpenSpecData, OpenSpecChange, OpenSpecArtifact } from "./types.js";
8
+
9
+ const execFileAsync = promisify(execFile);
10
+ const EMPTY_DATA: OpenSpecData = { initialized: false, changes: [] };
11
+
12
+ /** Synchronous version — only used by bridge extension where async isn't practical */
13
+ function runOpenSpecSync(args: string[], cwd: string): unknown | null {
14
+ try {
15
+ const result = spawnSync("openspec", args, {
16
+ cwd,
17
+ encoding: "utf-8",
18
+ stdio: ["pipe", "pipe", "pipe"],
19
+ timeout: 10_000,
20
+ });
21
+ if (result.status !== 0 || !result.stdout) return null;
22
+ return JSON.parse(result.stdout);
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ /** Async version — non-blocking, used by server */
29
+ async function runOpenSpecAsync(args: string[], cwd: string): Promise<unknown | null> {
30
+ try {
31
+ const { stdout } = await execFileAsync("openspec", args, {
32
+ cwd,
33
+ encoding: "utf-8",
34
+ timeout: 10_000,
35
+ });
36
+ if (!stdout) return null;
37
+ return JSON.parse(stdout);
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ function buildOpenSpecData(
44
+ listResult: { changes?: Array<{ name: string; status: string; completedTasks: number; totalTasks: number }> } | null,
45
+ statusResults: Map<string, { artifacts?: Array<{ id: string; status: string }> } | null>,
46
+ ): OpenSpecData {
47
+ if (!listResult || !Array.isArray(listResult.changes)) {
48
+ return EMPTY_DATA;
49
+ }
50
+
51
+ const changes: OpenSpecChange[] = listResult.changes.map((c) => {
52
+ const statusResult = statusResults.get(c.name) ?? null;
53
+ const artifacts: OpenSpecArtifact[] = (statusResult?.artifacts ?? []).map((a) => ({
54
+ id: a.id,
55
+ status: (a.status === "done" ? "done" : a.status === "ready" ? "ready" : "blocked") as OpenSpecArtifact["status"],
56
+ }));
57
+
58
+ return {
59
+ name: c.name,
60
+ status: (c.status === "complete" ? "complete" : c.status === "in-progress" ? "in-progress" : "no-tasks") as OpenSpecChange["status"],
61
+ completedTasks: c.completedTasks ?? 0,
62
+ totalTasks: c.totalTasks ?? 0,
63
+ artifacts,
64
+ };
65
+ });
66
+
67
+ return { initialized: true, changes };
68
+ }
69
+
70
+ /** Synchronous poll — blocks event loop. Used by bridge extension. */
71
+ export function pollOpenSpec(cwd: string): OpenSpecData {
72
+ const listResult = runOpenSpecSync(["list", "--json"], cwd) as any;
73
+ if (!listResult || !Array.isArray(listResult.changes)) return EMPTY_DATA;
74
+
75
+ const statusResults = new Map<string, any>();
76
+ for (const c of listResult.changes) {
77
+ statusResults.set(c.name, runOpenSpecSync(["status", "--change", c.name, "--json"], cwd));
78
+ }
79
+ return buildOpenSpecData(listResult, statusResults);
80
+ }
81
+
82
+ /** Async poll — non-blocking. Used by server directory service. */
83
+ export async function pollOpenSpecAsync(cwd: string): Promise<OpenSpecData> {
84
+ const listResult = await runOpenSpecAsync(["list", "--json"], cwd) as any;
85
+ if (!listResult || !Array.isArray(listResult.changes)) return EMPTY_DATA;
86
+
87
+ // Run all status queries in parallel
88
+ const entries = await Promise.all(
89
+ listResult.changes.map(async (c: any): Promise<[string, any]> => {
90
+ const status = await runOpenSpecAsync(["status", "--change", c.name, "--json"], cwd);
91
+ return [c.name, status];
92
+ }),
93
+ );
94
+ const statusResults = new Map<string, any>(entries);
95
+ return buildOpenSpecData(listResult, statusResults);
96
+ }
@@ -0,0 +1,369 @@
1
+ /**
2
+ * Extension ↔ Server WebSocket protocol messages.
3
+ */
4
+ import type { DashboardEvent, CommandInfo, FlowInfo, SessionSource, ImageContent, FileEntry, TurnUsage, ContextUsage, ModelInfo, PiSessionInfo, OpenSpecPhase, RoleInfo } from "./types.js";
5
+
6
+ // ── Extension → Server ──────────────────────────────────────────────
7
+
8
+ export interface SessionRegisterMessage {
9
+ type: "session_register";
10
+ sessionId: string;
11
+ cwd: string;
12
+ name?: string;
13
+ source: SessionSource;
14
+ model?: string;
15
+ thinkingLevel?: string;
16
+ sessionFile?: string;
17
+ sessionDir?: string;
18
+ firstMessage?: string;
19
+ /** True when this is a fresh session start (not a reconnection) */
20
+ isNew?: boolean;
21
+ /** Number of conversation entries — used by server to skip event wipe on reconnect */
22
+ eventCount?: number;
23
+ /** OS process ID of the pi agent — used for force-kill escalation */
24
+ pid?: number;
25
+ }
26
+
27
+ export interface SessionUnregisterMessage {
28
+ type: "session_unregister";
29
+ sessionId: string;
30
+ }
31
+
32
+ export interface ProcessMetrics {
33
+ /** RSS in bytes */
34
+ rss: number;
35
+ /** Heap used in bytes */
36
+ heapUsed: number;
37
+ /** Heap total in bytes */
38
+ heapTotal: number;
39
+ /** CPU usage percent since last heartbeat (0-100+) */
40
+ cpuPercent: number;
41
+ /** Event loop max delay in ms since last heartbeat */
42
+ eventLoopMaxMs?: number;
43
+ /** System load average (1 min) */
44
+ loadAvg1m: number;
45
+ }
46
+
47
+ export interface SessionHeartbeatMessage {
48
+ type: "session_heartbeat";
49
+ sessionId: string;
50
+ /** Process metrics from the pi agent process */
51
+ metrics?: ProcessMetrics;
52
+ }
53
+
54
+ export interface EventForwardMessage {
55
+ type: "event_forward";
56
+ sessionId: string;
57
+ event: DashboardEvent;
58
+ }
59
+
60
+ export interface CommandsListMessage {
61
+ type: "commands_list";
62
+ sessionId: string;
63
+ commands: CommandInfo[];
64
+ }
65
+
66
+ export interface FlowsListMessage {
67
+ type: "flows_list";
68
+ sessionId: string;
69
+ flows: FlowInfo[];
70
+ }
71
+
72
+ export interface ExtensionUiRequestMessage {
73
+ type: "extension_ui_request";
74
+ sessionId: string;
75
+ requestId: string;
76
+ method: string;
77
+ params: Record<string, unknown>;
78
+ }
79
+
80
+ // StatsUpdateMessage removed — server extracts stats directly from forwarded turn_end events
81
+
82
+ export interface FilesListMessage {
83
+ type: "files_list";
84
+ sessionId: string;
85
+ query: string;
86
+ files: FileEntry[];
87
+ }
88
+
89
+ export interface GitInfoUpdateMessage {
90
+ type: "git_info_update";
91
+ sessionId: string;
92
+ gitBranch: string;
93
+ gitBranchUrl?: string;
94
+ gitPrNumber?: number;
95
+ gitPrUrl?: string;
96
+ }
97
+
98
+ // OpenSpecUpdateMessage removed — server polls directly via DirectoryService
99
+
100
+ export interface ModelsListMessage {
101
+ type: "models_list";
102
+ sessionId: string;
103
+ models: ModelInfo[];
104
+ }
105
+
106
+ export interface SessionNameUpdateMessage {
107
+ type: "session_name_update";
108
+ sessionId: string;
109
+ name: string;
110
+ }
111
+
112
+ export interface SessionsListExtensionMessage {
113
+ type: "sessions_list";
114
+ sessionId: string;
115
+ cwd: string;
116
+ sessions: PiSessionInfo[];
117
+ }
118
+
119
+ // SessionHistorySyncMessage removed — server reads history directly via DirectoryService
120
+ // OpenSpecActivityUpdateMessage removed — server detects OpenSpec activity from forwarded events
121
+
122
+ export interface ModelUpdateMessage {
123
+ type: "model_update";
124
+ sessionId: string;
125
+ model: string;
126
+ thinkingLevel?: string;
127
+ }
128
+
129
+ export interface ReplayCompleteMessage {
130
+ type: "replay_complete";
131
+ sessionId: string;
132
+ }
133
+
134
+ export interface FirstMessageUpdateMessage {
135
+ type: "first_message_update";
136
+ sessionId: string;
137
+ firstMessage: string;
138
+ }
139
+
140
+ export interface RolesListMessage {
141
+ type: "roles_list";
142
+ sessionId: string;
143
+ roles: Record<string, string>;
144
+ presets: Array<{ name: string; roles: Record<string, string> }>;
145
+ activePreset: string | null;
146
+ }
147
+
148
+ export interface ExtensionUiDismissMessage {
149
+ type: "extension_ui_dismiss";
150
+ sessionId: string;
151
+ requestId: string;
152
+ }
153
+
154
+ export interface SpawnNewSessionMessage {
155
+ type: "spawn_new_session";
156
+ sessionId: string;
157
+ cwd: string;
158
+ }
159
+
160
+ export interface ProcessInfo {
161
+ pid: number;
162
+ pgid: number;
163
+ command: string;
164
+ elapsedMs: number;
165
+ }
166
+
167
+ export interface ProcessListMessage {
168
+ type: "process_list";
169
+ sessionId: string;
170
+ processes: ProcessInfo[];
171
+ }
172
+
173
+ // LoadSessionEventsResultMessage and LoadSessionEventsErrorMessage removed — server loads directly
174
+
175
+ export type ExtensionToServerMessage =
176
+ | SessionRegisterMessage
177
+ | SessionUnregisterMessage
178
+ | SessionHeartbeatMessage
179
+ | EventForwardMessage
180
+ | CommandsListMessage
181
+ | FlowsListMessage
182
+ | ExtensionUiRequestMessage
183
+ | FilesListMessage
184
+ | GitInfoUpdateMessage
185
+ | SessionNameUpdateMessage
186
+ | ModelsListMessage
187
+ | ModelUpdateMessage
188
+ | SessionsListExtensionMessage
189
+ | ExtensionUiDismissMessage
190
+ | ReplayCompleteMessage
191
+ | FirstMessageUpdateMessage
192
+ | RolesListMessage
193
+ | SpawnNewSessionMessage
194
+ | ProcessListMessage;
195
+
196
+ // ── Server → Extension ──────────────────────────────────────────────
197
+
198
+ export interface SendPromptToExtensionMessage {
199
+ type: "send_prompt";
200
+ sessionId: string;
201
+ text: string;
202
+ images?: ImageContent[];
203
+ }
204
+
205
+ export interface AbortToExtensionMessage {
206
+ type: "abort";
207
+ sessionId: string;
208
+ }
209
+
210
+ export interface RequestCommandsMessage {
211
+ type: "request_commands";
212
+ sessionId: string;
213
+ }
214
+
215
+ export interface RequestStateSyncMessage {
216
+ type: "request_state_sync";
217
+ sessionId: string;
218
+ }
219
+
220
+ export interface ListFilesMessage {
221
+ type: "list_files";
222
+ sessionId: string;
223
+ query: string;
224
+ }
225
+
226
+ // OpenSpecRefreshMessage removed — server refreshes directly via DirectoryService
227
+
228
+ export interface RenameSessionExtensionMessage {
229
+ type: "rename_session";
230
+ sessionId: string;
231
+ name: string;
232
+ }
233
+
234
+ export interface RequestModelsMessage {
235
+ type: "request_models";
236
+ sessionId: string;
237
+ }
238
+
239
+ export interface SetThinkingLevelMessage {
240
+ type: "set_thinking_level";
241
+ sessionId: string;
242
+ level: string;
243
+ }
244
+
245
+ export interface ListSessionsExtensionMessage {
246
+ type: "list_sessions";
247
+ sessionId: string;
248
+ cwd: string;
249
+ }
250
+
251
+ export interface SetModelMessage {
252
+ type: "set_model";
253
+ sessionId: string;
254
+ provider: string;
255
+ modelId: string;
256
+ }
257
+
258
+ export interface ShutdownExtensionMessage {
259
+ type: "shutdown";
260
+ sessionId: string;
261
+ }
262
+
263
+ export interface FlowControlExtensionMessage {
264
+ type: "flow_control";
265
+ sessionId: string;
266
+ action: "abort" | "toggle_autonomous" | "dismiss_summary";
267
+ }
268
+
269
+ // LoadSessionEventsMessage removed — server loads directly via DirectoryService
270
+
271
+ export interface HeartbeatAckMessage {
272
+ type: "heartbeat_ack";
273
+ }
274
+
275
+ export interface RequestFlowsRefreshMessage {
276
+ type: "request_flows_refresh";
277
+ sessionId: string;
278
+ }
279
+
280
+ export interface CredentialsUpdatedMessage {
281
+ type: "credentials_updated";
282
+ }
283
+
284
+ export interface FlowManagementExtensionMessage {
285
+ type: "flow_management";
286
+ sessionId: string;
287
+ action: "run" | "new" | "edit" | "delete";
288
+ flowName?: string;
289
+ task?: string;
290
+ description?: string;
291
+ }
292
+
293
+ export interface ArchitectPromptResponseExtensionMessage {
294
+ type: "architect_prompt_response";
295
+ sessionId: string;
296
+ promptId: string;
297
+ answer?: string;
298
+ cancelled?: boolean;
299
+ }
300
+
301
+ export interface RoleSetExtensionMessage {
302
+ type: "role_set";
303
+ sessionId: string;
304
+ role: string;
305
+ modelId: string;
306
+ }
307
+
308
+ export interface RolePresetLoadExtensionMessage {
309
+ type: "role_preset_load";
310
+ sessionId: string;
311
+ presetName: string;
312
+ }
313
+
314
+ export interface RolePresetSaveExtensionMessage {
315
+ type: "role_preset_save";
316
+ sessionId: string;
317
+ presetName: string;
318
+ }
319
+
320
+ export interface RolePresetDeleteExtensionMessage {
321
+ type: "role_preset_delete";
322
+ sessionId: string;
323
+ presetName: string;
324
+ }
325
+
326
+ export interface RequestRolesMessage {
327
+ type: "request_roles";
328
+ sessionId: string;
329
+ }
330
+
331
+ export interface KillProcessMessage {
332
+ type: "kill_process";
333
+ sessionId: string;
334
+ pgid: number;
335
+ }
336
+
337
+ export interface ExtensionUiResponseMessage {
338
+ type: "extension_ui_response";
339
+ sessionId: string;
340
+ requestId: string;
341
+ result?: unknown;
342
+ cancelled?: boolean;
343
+ }
344
+
345
+ export type ServerToExtensionMessage =
346
+ | SendPromptToExtensionMessage
347
+ | AbortToExtensionMessage
348
+ | ExtensionUiResponseMessage
349
+ | RequestCommandsMessage
350
+ | RequestStateSyncMessage
351
+ | ListFilesMessage
352
+ | RenameSessionExtensionMessage
353
+ | RequestModelsMessage
354
+ | SetThinkingLevelMessage
355
+ | ListSessionsExtensionMessage
356
+ | SetModelMessage
357
+ | ShutdownExtensionMessage
358
+ | FlowControlExtensionMessage
359
+ | HeartbeatAckMessage
360
+ | RequestFlowsRefreshMessage
361
+ | CredentialsUpdatedMessage
362
+ | FlowManagementExtensionMessage
363
+ | ArchitectPromptResponseExtensionMessage
364
+ | RoleSetExtensionMessage
365
+ | RolePresetLoadExtensionMessage
366
+ | RolePresetSaveExtensionMessage
367
+ | RolePresetDeleteExtensionMessage
368
+ | RequestRolesMessage
369
+ | KillProcessMessage;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Resolve the jiti register hook from pi's process context.
3
+ *
4
+ * The bridge extension runs inside pi's Node.js process. process.argv[1]
5
+ * points to pi's CLI entry (e.g., pi-coding-agent/dist/cli.js). Since
6
+ * jiti is a dependency of pi-coding-agent, createRequire(process.argv[1])
7
+ * can resolve it directly.
8
+ */
9
+
10
+ import { createRequire } from "node:module";
11
+ import { realpathSync } from "node:fs";
12
+ import path from "node:path";
13
+
14
+ const JITI_PACKAGES = [
15
+ "@mariozechner/jiti",
16
+ "@oh-my-pi/jiti",
17
+ ];
18
+
19
+ /**
20
+ * Returns the absolute path to jiti's register hook (lib/jiti-register.mjs).
21
+ * Uses process.argv[1] (pi's entry point) to anchor module resolution.
22
+ */
23
+ export function resolveJitiImport(): string {
24
+ const anchor = process.argv[1];
25
+ if (anchor) {
26
+ try {
27
+ // Resolve symlinks — process.argv[1] may be a symlink (e.g., bin/pi → dist/cli.js)
28
+ const resolved = realpathSync(anchor);
29
+ const req = createRequire(resolved);
30
+ for (const jiti of JITI_PACKAGES) {
31
+ try {
32
+ const pkgJson = req.resolve(`${jiti}/package.json`);
33
+ return path.join(path.dirname(pkgJson), "lib", "jiti-register.mjs");
34
+ } catch { /* next */ }
35
+ }
36
+ } catch { /* fall through */ }
37
+ }
38
+
39
+ throw new Error(
40
+ "Cannot find pi's TypeScript loader (jiti). " +
41
+ "Is @mariozechner/pi-coding-agent or @oh-my-pi/pi-coding-agent installed?"
42
+ );
43
+ }