@polderlabs/bizar 5.5.0 → 5.5.2

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 (71) hide show
  1. package/bizar-dash/dist/assets/{EnvVarsSection-L413CQEI.js → EnvVarsSection-DoIzqrlb.js} +3 -3
  2. package/bizar-dash/dist/assets/{EnvVarsSection-L413CQEI.js.map → EnvVarsSection-DoIzqrlb.js.map} +1 -1
  3. package/bizar-dash/dist/assets/{MobileChat-0kGQb1S6.js → MobileChat-CoUCUsbr.js} +1 -1
  4. package/bizar-dash/dist/assets/{MobileChat-0kGQb1S6.js.map → MobileChat-CoUCUsbr.js.map} +1 -1
  5. package/bizar-dash/dist/assets/MobileSettings-BeO04g52.js +1 -0
  6. package/bizar-dash/dist/assets/MobileSettings-BeO04g52.js.map +1 -0
  7. package/bizar-dash/dist/assets/{Toast-C6f1zFJ2.js → Toast-D9nv5N6m.js} +1 -1
  8. package/bizar-dash/dist/assets/{Toast-C6f1zFJ2.js.map → Toast-D9nv5N6m.js.map} +1 -1
  9. package/bizar-dash/dist/assets/{icons-BsWXWkEF.js → icons-Btipv2pp.js} +100 -90
  10. package/bizar-dash/dist/assets/icons-Btipv2pp.js.map +1 -0
  11. package/bizar-dash/dist/assets/main-DHXPuddY.js +18 -0
  12. package/bizar-dash/dist/assets/main-DHXPuddY.js.map +1 -0
  13. package/bizar-dash/dist/assets/{main-BklYy02e.css → main-UG4jKK-F.css} +1 -1
  14. package/bizar-dash/dist/assets/mobile-H5KH9cTL.js +1 -0
  15. package/bizar-dash/dist/assets/{mobile-CsaN4CxH.js.map → mobile-H5KH9cTL.js.map} +1 -1
  16. package/bizar-dash/dist/assets/{mobile-layout-iFBdjEE4.js → mobile-layout-BqHxVb6_.js} +2 -2
  17. package/bizar-dash/dist/assets/{mobile-layout-iFBdjEE4.js.map → mobile-layout-BqHxVb6_.js.map} +1 -1
  18. package/bizar-dash/dist/assets/{useSlashCommands-DGJcC9iQ.js → useSlashCommands-C24-O1e7.js} +2 -2
  19. package/bizar-dash/dist/assets/{useSlashCommands-DGJcC9iQ.js.map → useSlashCommands-C24-O1e7.js.map} +1 -1
  20. package/bizar-dash/dist/index.html +7 -7
  21. package/bizar-dash/dist/mobile.html +3 -3
  22. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  23. package/bizar-dash/src/server/bg-spawner.mjs +522 -305
  24. package/bizar-dash/src/server/headroom.mjs +3 -1
  25. package/bizar-dash/src/server/memory-lightrag.mjs +26 -2
  26. package/bizar-dash/src/server/memory-store.mjs +74 -28
  27. package/bizar-dash/src/server/opencode-sdk.mjs +63 -3
  28. package/bizar-dash/src/server/plugins/registry.mjs +1 -1
  29. package/bizar-dash/src/server/routes/activity.mjs +85 -0
  30. package/bizar-dash/src/server/routes/background.mjs +31 -13
  31. package/bizar-dash/src/server/routes/memory.mjs +91 -38
  32. package/bizar-dash/src/server/routes/opencode-session-detail.mjs +1 -1
  33. package/bizar-dash/src/server/server.mjs +4 -1
  34. package/bizar-dash/src/web/components/Sidebar.tsx +0 -1
  35. package/bizar-dash/src/web/styles/main.css +52 -13
  36. package/bizar-dash/src/web/styles/memory.css +17 -0
  37. package/bizar-dash/src/web/styles/settings.css +6 -56
  38. package/bizar-dash/src/web/views/Marketplace.tsx +192 -31
  39. package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +157 -7
  40. package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +11 -0
  41. package/bizar-dash/src/web/views/settings/MemorySection.tsx +65 -11
  42. package/bizar-dash/tests/background-sdk-session.test.mjs +94 -0
  43. package/bizar-dash/tests/background-session-events.test.mjs +74 -0
  44. package/bizar-dash/tests/background-steer-sdk.test.mjs +71 -0
  45. package/bizar-dash/tests/background-steer.test.mjs +25 -7
  46. package/bizar-dash/tests/memory-namespace.test.mjs +2 -2
  47. package/bizar-dash/tests/memory-status-root.test.mjs +144 -0
  48. package/bizar-dash/tests/memory-store.test.mjs +5 -4
  49. package/bizar-dash/tests/memory-vault-config-endpoint.test.mjs +173 -0
  50. package/bizar-dash/tests/settings-mode-wiring.test.tsx +1 -1
  51. package/bizar-dash/tests/settings-nav.test.tsx +0 -1
  52. package/bizar-dash/tests/views/Marketplace.test.tsx +200 -0
  53. package/bizar-dash/tests/views/Memory.test.tsx +274 -0
  54. package/bizar-dash/tests/views/sidebar.test.tsx +116 -0
  55. package/bizar-dash/tests/views/topbar.test.tsx +87 -0
  56. package/cli/commands/marketplace.mjs +1 -1
  57. package/cli/memory.mjs +1 -1
  58. package/package.json +1 -1
  59. package/plugins/bizar/src/background-state.ts +11 -0
  60. package/plugins/bizar/src/background.ts +212 -34
  61. package/plugins/bizar/src/opencode-runner.ts +80 -353
  62. package/plugins/bizar/src/tools/bg-send-message.ts +160 -61
  63. package/plugins/bizar/src/tools/bg-spawn.ts +235 -156
  64. package/plugins/bizar/tests/tools/bg-send-message.test.ts +84 -11
  65. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +223 -0
  66. package/bizar-dash/dist/assets/MobileSettings-Cq1oFIdO.js +0 -1
  67. package/bizar-dash/dist/assets/MobileSettings-Cq1oFIdO.js.map +0 -1
  68. package/bizar-dash/dist/assets/icons-BsWXWkEF.js.map +0 -1
  69. package/bizar-dash/dist/assets/main-CBTgYSeG.js +0 -18
  70. package/bizar-dash/dist/assets/main-CBTgYSeG.js.map +0 -1
  71. package/bizar-dash/dist/assets/mobile-CsaN4CxH.js +0 -1
@@ -1,54 +1,32 @@
1
1
  /**
2
2
  * plugins/bizar/src/opencode-runner.ts
3
3
  *
4
- * v0.8.0Process-based background agent runner.
4
+ * v5.5.1DEAD CODE stub.
5
5
  *
6
- * Replaces the v0.4–v0.7 `opencode serve` HTTP path. The HTTP API is
7
- * passive see the opencode docs:
8
- * "When you run opencode it starts a TUI and a server. Where the
9
- * TUI is the client that talks to the server."
6
+ * Background agents no longer run as `opencode run` subprocesses. They
7
+ * run as long-lived opencode serve SDK sessions, managed by the
8
+ * Bizar dashboard (`bizar-dash/src/server/bg-spawner.mjs`). The plugin
9
+ * delegates to the dashboard via HTTP (`bg-spawn.ts`,
10
+ * `bg-send-message.ts`, …) instead of spawning anything directly.
10
11
  *
11
- * `opencode run <prompt>` is the active path: it spawns the agent
12
- * loop in-process, drives it to completion, and exits. This module
13
- * gives the plugin a clean way to spawn one `opencode run` per
14
- * background agent, capture its output to the LogWriter's log file,
15
- * track the PID for status/kill, and extract the opencode session
16
- * id from the structured log stream.
12
+ * This module is kept as a stub for two reasons:
17
13
  *
18
- * ─────────────────────────────────────────────────────────────────
19
- * Why this exists (v0.7.0-alpha.1 → v0.8.0)
20
- * ─────────────────────────────────────────────────────────────────
21
- * Pre-v0.8.0, the plugin POSTed to `/api/session/{id}/prompt` on the
22
- * opencode serve child. The server admitted the prompt
23
- * (`session.next.prompt.admitted` event) but no agent loop processed
24
- * it. The result: a session record was created, a tmux pane was
25
- * spawned, and nothing happened. The user saw "spawns but does
26
- * nothing" and was right.
14
+ * 1. `buildOpencodeRunArgs` and the `SpawnAgentOptions` type are
15
+ * still imported by `plugins/bizar/tests/tools/opencode-runner.test.ts`
16
+ * and serve as a regression pin for the argv layout that USED to
17
+ * be passed to `Bun.spawn`. The test suite stays green because
18
+ * the pure helpers are unchanged.
27
19
  *
28
- * This module fixes that by spawning `opencode run` directly.
20
+ * 2. A handful of function names (`isAlive`, `killAgent`, …) are
21
+ * imported elsewhere (`background.ts`) as a future-proofing hook.
22
+ * We replace the implementations with no-op / error stubs so any
23
+ * leftover call gets a clear, deliberate response instead of
24
+ * silently succeeding.
29
25
  *
30
- * ─────────────────────────────────────────────────────────────────
31
- * Wire format
32
- * ─────────────────────────────────────────────────────────────────
33
- * `opencode run` writes structured logs to stderr, one log per line:
34
- *
35
- * timestamp=2026-06-24T01:25:13.537Z level=INFO run=<uuid> message="creating instance" directory=/tmp
36
- * timestamp=2026-06-24T01:25:16.555Z level=INFO run=<uuid> message=created id=ses_… title="…" agent=…
37
- * timestamp=2026-06-24T01:25:16.951Z level=INFO run=<uuid> message=loop session.id=ses_… step=0
38
- * timestamp=2026-06-24T01:25:21.253Z level=INFO run=<uuid> message="exiting loop" session.id=ses_…
39
- *
40
- * The `message=created id=ses_<id>` line is how we recover the
41
- * sessionId (the agent generated it; we don't pre-allocate). We
42
- * parse the line with `message=created id=(ses_[A-Za-z0-9_]+)`.
43
- *
44
- * Both stdout and stderr are piped to `logPath` so the operator's
45
- * tmux pane (and the dashboard's log viewer) can watch the agent
46
- * work in real time. We prefix each line with the stream name
47
- * ([stdout] / [stderr]) for human readability; downstream parsers
48
- * can split on the first `] `.
26
+ * If something imports `spawnAgent`, it now gets back `{ ok: false,
27
+ * error: "spawnAgent removed in v5.5.1" }`. This forces callers to the
28
+ * dashboard path; nothing in the plugin should be calling this anymore.
49
29
  */
50
- import { createWriteStream, mkdirSync, existsSync } from "node:fs";
51
- import { dirname } from "node:path";
52
30
  import type { Subprocess } from "bun";
53
31
 
54
32
  export type AgentState =
@@ -97,38 +75,15 @@ export interface SpawnAgentResult {
97
75
 
98
76
  type ExitCallback = (status: AgentStatus) => void;
99
77
 
100
- interface AgentRecord {
101
- status: AgentStatus;
102
- proc: Subprocess;
103
- onExit: ExitCallback[];
104
- // Resolvers for the spawn promise. Consumed when the sessionId
105
- // arrives (or the process exits before that).
106
- spawnResolvers: Array<(result: SpawnAgentResult) => void>;
107
- }
108
-
109
- // Module-level registry of running agents.
110
- const agents = new Map<number, AgentRecord>();
111
-
112
- // --- Public API -----------------------------------------------------------
113
-
114
78
  /**
115
- * Pure: build the argv array for `opencode run` from SpawnAgentOptions.
116
- *
117
- * Extracted from spawnAgent so it can be unit-tested without spawning
118
- * a real process. Throws when opts.agent is empty `opencode run`
119
- * requires a known agent name; passing an empty string would silently
120
- * fall back to opencode's default agent and break session attribution
121
- * (the title prefix `bgr:<agent>:...` would also degrade to `bgr::...`).
79
+ * v5.5.1 — Pure helper, UNCHANGED. Kept around so the regression test
80
+ * that pins the argv layout still passes. (The argv used to be passed
81
+ * to `Bun.spawn`; v5.5.1 no longer spawns anything, but the wire format
82
+ * is a useful reference and may be reused if we ever revive subprocess
83
+ * mode.)
122
84
  *
123
- * Arg layout (matches `opencode run --help`):
124
- * opencode run
125
- * --dir <worktree>
126
- * --print-logs
127
- * --log-level INFO
128
- * --title <title>
129
- * --agent <agent> ← REQUIRED; was missing pre-v0.8.1
130
- * [--model <providerID>/<modelID>] ← optional override
131
- * -- <prompt>
85
+ * @param opts
86
+ * @returns argv that USED to be passed to `Bun.spawn(["opencode", "run", …])`
132
87
  */
133
88
  export function buildOpencodeRunArgs(opts: SpawnAgentOptions): string[] {
134
89
  if (!opts.agent) {
@@ -146,331 +101,103 @@ export function buildOpencodeRunArgs(opts: SpawnAgentOptions): string[] {
146
101
  if (opts.model) {
147
102
  args.push("--model", `${opts.model.providerID}/${opts.model.modelID}`);
148
103
  }
149
- // `--` separates flags from positional so a prompt starting with
150
- // `-` is treated as a message.
151
104
  args.push("--", opts.prompt);
152
105
  return args;
153
106
  }
154
107
 
155
108
  /**
156
- * Spawn a single `opencode run` process. The promise resolves once
157
- * the opencode child has reported its session id in the structured
158
- * log stream (or once the process exits before that — typically
159
- * because of an early error like a missing API key).
109
+ * v5.5.1 STUB. Background agents run on the opencode serve SDK,
110
+ * not as `opencode run` subprocesses. Returns an error directing the
111
+ * caller to the dashboard HTTP API.
160
112
  *
161
- * @param opts
162
- * @returns Promise resolving with `{ ok, sessionId?, processId? }` or `{ ok: false, error }`
113
+ * The plugin's `bg-spawn.ts` no longer calls this; it's kept for any
114
+ * late caller we missed.
163
115
  */
164
- export async function spawnAgent(opts: SpawnAgentOptions): Promise<SpawnAgentResult> {
165
- // 1. Pre-flight: log dir must exist so the stream can open.
166
- const logDir = dirname(opts.logPath);
167
- if (!existsSync(logDir)) {
168
- try {
169
- mkdirSync(logDir, { recursive: true });
170
- } catch (err: unknown) {
171
- return {
172
- ok: false,
173
- error: `cannot create log dir ${logDir}: ${err instanceof Error ? err.message : String(err)}`,
174
- };
175
- }
176
- }
177
-
178
- // 2. Build argv. Pulled into a pure function so tests can assert the
179
- // flag layout (notably the `--agent` flag and the migrated model
180
- // ID format) without spawning a real `opencode run` process.
181
- const args = buildOpencodeRunArgs(opts);
182
-
183
- // 3. Spawn the process.
184
- let proc: Subprocess;
185
- try {
186
- proc = Bun.spawn(args, {
187
- stdout: "pipe",
188
- stderr: "pipe",
189
- env: { ...process.env, ...(opts.env || {}) },
190
- });
191
- } catch (err: unknown) {
192
- return {
193
- ok: false,
194
- error: `failed to spawn opencode run: ${err instanceof Error ? err.message : String(err)}`,
195
- };
196
- }
197
-
198
- // 4. Track the agent.
199
- const rec: AgentRecord = {
200
- status: {
201
- state: "starting",
202
- processId: proc.pid,
203
- startedAt: Date.now(),
204
- },
205
- proc,
206
- onExit: [],
207
- spawnResolvers: [],
208
- };
209
- agents.set(proc.pid, rec);
210
-
211
- // 5. Pipe stdout+stderr to the log file. Both go to the same file;
212
- // lines are prefixed [stdout] / [stderr] for readability.
213
- const logStream = createWriteStream(opts.logPath, { flags: "a" });
214
- const decoder = new TextDecoder("utf-8");
215
- const sessionIdRegex = /message=created id=(ses_[A-Za-z0-9_]+)/;
216
- let sessionId: string | undefined;
217
-
218
- const resolveSpawnIfReady = (forceError?: string) => {
219
- const resolvers = rec.spawnResolvers.splice(0);
220
- if (resolvers.length === 0) return;
221
- if (forceError) {
222
- for (const r of resolvers) {
223
- r({ ok: false, processId: proc.pid, error: forceError });
224
- }
225
- return;
226
- }
227
- if (sessionId) {
228
- rec.status.state = "running";
229
- for (const r of resolvers) {
230
- r({ ok: true, sessionId, processId: proc.pid });
231
- }
232
- }
116
+ export async function spawnAgent(_opts: SpawnAgentOptions): Promise<SpawnAgentResult> {
117
+ return {
118
+ ok: false,
119
+ error:
120
+ "spawnAgent removed in v5.5.1 — bg agents now run as opencode serve sessions " +
121
+ "managed by the Bizar dashboard. POST /api/background instead. " +
122
+ "See plugins/bizar/src/tools/bg-spawn.ts.",
233
123
  };
234
-
235
- const readStream = async (
236
- reader: ReadableStreamDefaultReader<Uint8Array>,
237
- label: "stderr" | "stdout",
238
- ): Promise<void> => {
239
- let buf = "";
240
- try {
241
- while (true) {
242
- const { done, value } = await reader.read();
243
- if (done) break;
244
- const text = decoder.decode(value, { stream: true });
245
- logStream.write(`[${label}] ${text}`);
246
- if (label === "stderr" && !sessionId) {
247
- buf += text;
248
- const m = buf.match(sessionIdRegex);
249
- if (m && m[1]) {
250
- sessionId = m[1];
251
- rec.status.sessionId = sessionId;
252
- resolveSpawnIfReady();
253
- }
254
- }
255
- }
256
- } finally {
257
- try { reader.releaseLock(); } catch { /* ignore */ }
258
- }
259
- };
260
-
261
- // 6. Stream readers + exit handler — install BEFORE returning the
262
- // promise so a fast-exiting process still produces a clean
263
- // resolution.
264
- const stderrReader = (proc.stderr as ReadableStream<Uint8Array>).getReader() as unknown as ReadableStreamDefaultReader<Uint8Array<ArrayBufferLike>>;
265
- const stdoutReader = (proc.stdout as ReadableStream<Uint8Array>).getReader() as unknown as ReadableStreamDefaultReader<Uint8Array<ArrayBufferLike>>;
266
- void readStream(stderrReader, "stderr");
267
- void readStream(stdoutReader, "stdout");
268
-
269
- proc.exited
270
- .then((exitCode: number | null) => {
271
- const code = exitCode ?? -1;
272
- rec.status.exitCode = exitCode ?? undefined;
273
- rec.status.endedAt = Date.now();
274
- if (rec.status.state !== "killed") {
275
- rec.status.state = code === 0 ? "done" : "failed";
276
- if (code !== 0 && !rec.status.error) {
277
- rec.status.error = `opencode run exited with code ${code}`;
278
- }
279
- }
280
- // Resolve any unresolved spawn promises.
281
- if (!sessionId) {
282
- resolveSpawnIfReady(rec.status.error || "opencode run exited before reporting session id");
283
- }
284
- // Fire subscribers.
285
- const cbs = rec.onExit.splice(0);
286
- for (const cb of cbs) {
287
- try { cb({ ...rec.status }); } catch { /* ignore */ }
288
- }
289
- // Best-effort flush + close of the log stream.
290
- try { logStream.end(); } catch { /* ignore */ }
291
- })
292
- .catch(() => {
293
- // proc.exited only rejects if the proc was already awaited or
294
- // never spawned; safe to ignore.
295
- });
296
-
297
- // 7. Race the spawn promise against a timeout. The default is 10s
298
- // which is plenty for opencode to print the "created" line on
299
- // a warm host (<500ms in practice).
300
- const sessionIdTimeoutMs = opts.sessionIdTimeoutMs ?? 10_000;
301
- return new Promise<SpawnAgentResult>((resolve) => {
302
- rec.spawnResolvers.push(resolve);
303
- setTimeout(() => {
304
- if (!sessionId) {
305
- resolveSpawnIfReady(
306
- `opencode run did not report a session id within ${sessionIdTimeoutMs}ms`,
307
- );
308
- }
309
- }, sessionIdTimeoutMs);
310
- });
311
124
  }
312
125
 
313
126
  /**
314
- * Snapshot the current status of an agent. Returns null if the
315
- * processId is not tracked (e.g. the plugin restarted and lost its
316
- * in-memory map).
127
+ * v5.5.1 STUB. Returns null because there is no in-process subprocess
128
+ * registry to look up.
317
129
  */
318
- export function getStatus(processId: number): AgentStatus | null {
319
- const rec = agents.get(processId);
320
- if (!rec) return null;
321
- return { ...rec.status };
130
+ export function getStatus(_processId: number): AgentStatus | null {
131
+ return null;
322
132
  }
323
133
 
324
134
  /**
325
- * Subscribe to the exit event. The callback fires exactly once when
326
- * the process exits (whether naturally or via signal). Multiple
327
- * subscribers are allowed; all of them fire in registration order.
328
- *
329
- * @returns unsubscribe function
135
+ * v5.5.1 STUB. The real exit subscription lives on the dashboard side.
136
+ * Returns a no-op unsubscribe.
330
137
  */
331
- export function onExit(processId: number, cb: ExitCallback): () => void {
332
- const rec = agents.get(processId);
333
- if (!rec) return () => undefined;
334
- rec.onExit.push(cb);
335
- // If the agent has already exited, fire the callback immediately
336
- // (next microtask) so the caller doesn't have to special-case
337
- // pre-exited agents.
338
- if (rec.status.endedAt !== undefined) {
339
- queueMicrotask(() => {
340
- try { cb({ ...rec.status }); } catch { /* ignore */ }
341
- });
342
- }
343
- return () => {
344
- const i = rec.onExit.indexOf(cb);
345
- if (i >= 0) rec.onExit.splice(i, 1);
346
- };
138
+ export function onExit(_processId: number, _cb: ExitCallback): () => void {
139
+ return () => undefined;
347
140
  }
348
141
 
349
142
  /**
350
- * Kill the agent. Sends the requested signal (default SIGTERM),
351
- * waits up to 5s, then SIGKILL. Idempotent.
143
+ * v5.5.1 STUB. Kill is now a dashboard-side operation
144
+ * (`sdk.sessions.abort`). The plugin's `bg-kill.ts` posts to the
145
+ * dashboard HTTP API; this function is here only as a fallback that
146
+ * always reports "no such process tracked" so the dashboard's view of
147
+ * the world is the source of truth.
352
148
  */
353
149
  export function killAgent(
354
- processId: number,
355
- signal: "SIGTERM" | "SIGKILL" = "SIGTERM",
150
+ _processId: number,
151
+ _signal: "SIGTERM" | "SIGKILL" = "SIGTERM",
356
152
  ): { ok: boolean; error?: string } {
357
- const rec = agents.get(processId);
358
- if (!rec) {
359
- return { ok: true, error: "no such process tracked" };
360
- }
361
- if (rec.status.endedAt !== undefined) {
362
- return { ok: true, error: "process already exited" };
363
- }
364
- rec.status.state = "killed";
365
- try {
366
- rec.proc.kill(signal);
367
- } catch (err: unknown) {
368
- return {
369
- ok: false,
370
- error: `kill(${signal}) failed: ${err instanceof Error ? err.message : String(err)}`,
371
- };
372
- }
373
- // Schedule a forced kill after 5s in case SIGTERM is ignored.
374
- setTimeout(() => {
375
- if (rec.status.endedAt === undefined) {
376
- try { rec.proc.kill("SIGKILL"); } catch { /* ignore */ }
377
- }
378
- }, 5_000);
379
- return { ok: true };
153
+ return { ok: true, error: "no_such_process_tracked_v5_5_1_use_dashboard_delete" };
380
154
  }
381
155
 
382
156
  /**
383
- * v5.x — Pause a tracked agent by sending SIGSTOP. POSIX only —
384
- * Windows has no signal model and returns `ok: false`. Idempotent
385
- * against an exited process (returns `ok: true` with a note).
386
- *
387
- * The agent's `state` flips to `"paused"` so {@link getStatus}
388
- * reflects the new lifecycle accurately.
157
+ * v5.5.1STUB. Pause is an output-pause at the dashboard side now.
158
+ * The plugin's `bg-pause.ts` posts to the dashboard; this stub returns
159
+ * `unsupported` so a leftover caller gets a clear signal.
389
160
  */
390
- export function pauseAgent(
391
- processId: number,
392
- ): { ok: boolean; error?: string } {
393
- if (process.platform === "win32") {
394
- return { ok: false, error: "pause unsupported on win32" };
395
- }
396
- const rec = agents.get(processId);
397
- if (!rec) return { ok: false, error: "no such process" };
398
- if (rec.status.endedAt !== undefined) return { ok: true, error: "already_exited" };
399
- if (rec.status.state === "paused") return { ok: true };
400
- try {
401
- rec.proc.kill("SIGSTOP");
402
- rec.status.state = "paused";
403
- return { ok: true };
404
- } catch (err: unknown) {
405
- return {
406
- ok: false,
407
- error: `SIGSTOP failed: ${err instanceof Error ? err.message : String(err)}`,
408
- };
409
- }
161
+ export function pauseAgent(_processId: number): { ok: boolean; error?: string } {
162
+ return { ok: false, error: "pause_via_dashboard_v5_5_1" };
410
163
  }
411
164
 
412
165
  /**
413
- * v5.xResume a paused agent by sending SIGCONT. POSIX only. No-op
414
- * against an exited process.
166
+ * v5.5.1STUB. Same as `pauseAgent` dashboard-side only.
415
167
  */
416
- export function resumeAgent(
417
- processId: number,
418
- ): { ok: boolean; error?: string } {
419
- if (process.platform === "win32") {
420
- return { ok: false, error: "resume unsupported on win32" };
421
- }
422
- const rec = agents.get(processId);
423
- if (!rec) return { ok: false, error: "no such process" };
424
- if (rec.status.endedAt !== undefined) return { ok: true, error: "already_exited" };
425
- if (rec.status.state !== "paused") return { ok: true };
426
- try {
427
- rec.proc.kill("SIGCONT");
428
- rec.status.state = "running";
429
- return { ok: true };
430
- } catch (err: unknown) {
431
- return {
432
- ok: false,
433
- error: `SIGCONT failed: ${err instanceof Error ? err.message : String(err)}`,
434
- };
435
- }
168
+ export function resumeAgent(_processId: number): { ok: boolean; error?: string } {
169
+ return { ok: false, error: "resume_via_dashboard_v5_5_1" };
436
170
  }
437
171
 
438
172
  /**
439
- * v5.xLiveness check for a previously spawned PID. Uses
440
- * `process.kill(pid, 0)` which sends no signal it just probes the
441
- * process table. Returns `false` for unknown / exited PIDs and on
442
- * permission errors.
443
- *
444
- * NOTE: this is a separate registry from the in-memory `agents` map.
445
- * After a plugin restart, the in-memory map is empty but the
446
- * underlying PID may still be alive. The function probes the OS, so
447
- * it answers the underlying question even when the agent record has
448
- * been forgotten.
173
+ * v5.5.1STUB. Returns false because there is no in-process PID
174
+ * registry. Liveness is owned by the dashboard; the plugin's state
175
+ * reconciliation code already uses this as a probe and falls back to
176
+ * "fail closed" when the answer is false.
449
177
  */
450
178
  export function isAlive(processId: number): boolean {
451
179
  if (!Number.isFinite(processId) || processId <= 0) return false;
452
- try {
453
- // Signal 0 = probe only. Returns true if the process exists and
454
- // we have permission to signal it.
455
- process.kill(processId, 0);
456
- return true;
457
- } catch {
458
- return false;
459
- }
180
+ return false;
460
181
  }
461
182
 
462
183
  /**
463
- * List every tracked agent. Used by the plugin's startup to reconcile
464
- * state and by tests.
184
+ * v5.5.1 STUB. Returns an empty list — the runner registry is gone.
465
185
  */
466
186
  export function list(): AgentStatus[] {
467
- return Array.from(agents.values()).map((r) => ({ ...r.status }));
187
+ return [];
468
188
  }
469
189
 
470
190
  /**
471
- * For tests: clear the in-memory registry. Does NOT kill running
472
- * processes callers must `killAgent()` first if they want that.
191
+ * v5.5.1 STUB. Clears nothing (the registry is empty). Kept for the
192
+ * test suite that imports it.
473
193
  */
474
194
  export function _resetForTests(): void {
475
- agents.clear();
195
+ // no-op — the in-memory registry was removed.
476
196
  }
197
+
198
+ /**
199
+ * v5.5.1 — STUB. Returns an empty record because no agent is tracked
200
+ * here. Provided so the module typechecks in callers that still reach
201
+ * for a status record shape.
202
+ */
203
+ export type { Subprocess };