@h-rig/cli 0.0.6-alpha.93 → 0.0.6-alpha.95

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 (108) hide show
  1. package/README.md +6 -27
  2. package/bin/rig.js +16 -0
  3. package/package.json +14 -40
  4. package/dist/bin/build-rig-binaries.d.ts +0 -2
  5. package/dist/bin/build-rig-binaries.js +0 -119
  6. package/dist/bin/rig.d.ts +0 -72
  7. package/dist/bin/rig.js +0 -17845
  8. package/dist/config/rig-default-config.yml +0 -5
  9. package/dist/src/app/drone-ui.d.ts +0 -34
  10. package/dist/src/app/drone-ui.js +0 -278
  11. package/dist/src/commands/_async-ui.d.ts +0 -10
  12. package/dist/src/commands/_async-ui.js +0 -121
  13. package/dist/src/commands/_cli-format.d.ts +0 -56
  14. package/dist/src/commands/_cli-format.js +0 -319
  15. package/dist/src/commands/_connection-state.d.ts +0 -54
  16. package/dist/src/commands/_connection-state.js +0 -187
  17. package/dist/src/commands/_doctor-checks.d.ts +0 -46
  18. package/dist/src/commands/_doctor-checks.js +0 -352
  19. package/dist/src/commands/_help-catalog.d.ts +0 -51
  20. package/dist/src/commands/_help-catalog.js +0 -502
  21. package/dist/src/commands/_inprocess-services.d.ts +0 -33
  22. package/dist/src/commands/_inprocess-services.js +0 -102
  23. package/dist/src/commands/_json-output.d.ts +0 -11
  24. package/dist/src/commands/_json-output.js +0 -60
  25. package/dist/src/commands/_lazy-reconcile.d.ts +0 -34
  26. package/dist/src/commands/_lazy-reconcile.js +0 -102
  27. package/dist/src/commands/_parsers.d.ts +0 -15
  28. package/dist/src/commands/_parsers.js +0 -114
  29. package/dist/src/commands/_paths.d.ts +0 -11
  30. package/dist/src/commands/_paths.js +0 -50
  31. package/dist/src/commands/_pi-frontend.d.ts +0 -35
  32. package/dist/src/commands/_pi-frontend.js +0 -64
  33. package/dist/src/commands/_pi-install.d.ts +0 -42
  34. package/dist/src/commands/_pi-install.js +0 -167
  35. package/dist/src/commands/_policy.d.ts +0 -8
  36. package/dist/src/commands/_policy.js +0 -127
  37. package/dist/src/commands/_probes.d.ts +0 -1
  38. package/dist/src/commands/_probes.js +0 -13
  39. package/dist/src/commands/_run-bridge.d.ts +0 -114
  40. package/dist/src/commands/_run-bridge.js +0 -387
  41. package/dist/src/commands/_run-diagnostics.d.ts +0 -9
  42. package/dist/src/commands/_run-diagnostics.js +0 -51
  43. package/dist/src/commands/_run-driver-helpers.d.ts +0 -26
  44. package/dist/src/commands/_run-driver-helpers.js +0 -138
  45. package/dist/src/commands/_run-projection.d.ts +0 -50
  46. package/dist/src/commands/_run-projection.js +0 -349
  47. package/dist/src/commands/_run-subcommands.d.ts +0 -3
  48. package/dist/src/commands/_run-subcommands.js +0 -31
  49. package/dist/src/commands/_spinner.d.ts +0 -25
  50. package/dist/src/commands/_spinner.js +0 -65
  51. package/dist/src/commands/agent.d.ts +0 -3
  52. package/dist/src/commands/agent.js +0 -8837
  53. package/dist/src/commands/dist.d.ts +0 -28
  54. package/dist/src/commands/dist.js +0 -417
  55. package/dist/src/commands/doctor.d.ts +0 -3
  56. package/dist/src/commands/doctor.js +0 -480
  57. package/dist/src/commands/github.d.ts +0 -3
  58. package/dist/src/commands/github.js +0 -342
  59. package/dist/src/commands/inbox.d.ts +0 -28
  60. package/dist/src/commands/inbox.js +0 -579
  61. package/dist/src/commands/init.d.ts +0 -64
  62. package/dist/src/commands/init.js +0 -1541
  63. package/dist/src/commands/inspect.d.ts +0 -20
  64. package/dist/src/commands/inspect.js +0 -764
  65. package/dist/src/commands/pi.d.ts +0 -3
  66. package/dist/src/commands/pi.js +0 -177
  67. package/dist/src/commands/plugin.d.ts +0 -16
  68. package/dist/src/commands/plugin.js +0 -714
  69. package/dist/src/commands/profile-and-review.d.ts +0 -4
  70. package/dist/src/commands/profile-and-review.js +0 -223
  71. package/dist/src/commands/queue.d.ts +0 -3
  72. package/dist/src/commands/queue.js +0 -197
  73. package/dist/src/commands/remote.d.ts +0 -3
  74. package/dist/src/commands/remote.js +0 -1337
  75. package/dist/src/commands/repo-git-harness.d.ts +0 -5
  76. package/dist/src/commands/repo-git-harness.js +0 -271
  77. package/dist/src/commands/run.d.ts +0 -21
  78. package/dist/src/commands/run.js +0 -17837
  79. package/dist/src/commands/server.d.ts +0 -3
  80. package/dist/src/commands/server.js +0 -249
  81. package/dist/src/commands/setup.d.ts +0 -16
  82. package/dist/src/commands/setup.js +0 -644
  83. package/dist/src/commands/stats.d.ts +0 -15
  84. package/dist/src/commands/stats.js +0 -979
  85. package/dist/src/commands/task-run-driver.d.ts +0 -94
  86. package/dist/src/commands/task-run-driver.js +0 -203
  87. package/dist/src/commands/task.d.ts +0 -35
  88. package/dist/src/commands/task.js +0 -818
  89. package/dist/src/commands/test.d.ts +0 -3
  90. package/dist/src/commands/test.js +0 -46
  91. package/dist/src/commands/triage.d.ts +0 -11
  92. package/dist/src/commands/triage.js +0 -227
  93. package/dist/src/commands/workspace.d.ts +0 -3
  94. package/dist/src/commands/workspace.js +0 -130
  95. package/dist/src/commands.d.ts +0 -13
  96. package/dist/src/commands.js +0 -17969
  97. package/dist/src/index.d.ts +0 -4
  98. package/dist/src/index.js +0 -17981
  99. package/dist/src/launcher.d.ts +0 -61
  100. package/dist/src/launcher.js +0 -199
  101. package/dist/src/operator-cli.d.ts +0 -2
  102. package/dist/src/operator-cli.js +0 -17837
  103. package/dist/src/operator-entry.d.ts +0 -1
  104. package/dist/src/operator-entry.js +0 -3
  105. package/dist/src/runner.d.ts +0 -47
  106. package/dist/src/runner.js +0 -267
  107. package/dist/src/withMutedConsole.d.ts +0 -2
  108. package/dist/src/withMutedConsole.js +0 -42
@@ -1,387 +0,0 @@
1
- // @bun
2
- var __require = import.meta.require;
3
-
4
- // packages/cli/src/commands/_run-bridge.ts
5
- import { randomUUID } from "crypto";
6
- import { spawn as nodeSpawn } from "child_process";
7
- import { existsSync, readdirSync, readFileSync } from "fs";
8
- import { dirname, resolve } from "path";
9
- import { fileURLToPath } from "url";
10
- import { CUSTOM_TYPE_FOR, sessionIdFromSessionFile } from "@rig/contracts";
11
- import { createPluginHost } from "@rig/core";
12
- import { loadConfig } from "@rig/core/load-config";
13
- import { resolveOwnerNamespaceKey, resolveRegistryBaseUrl, resolveRegistrySecret, resolveSelectedRemote } from "@rig/runtime/control-plane/remote";
14
- import { listAgentRuntimes } from "@rig/runtime/control-plane/runtime/isolation";
15
- import { createRegistryClient } from "@rig/relay-registry";
16
- import {
17
- listActiveCollabSessions as ompListActiveCollabSessions
18
- } from "@oh-my-pi/pi-coding-agent/collab/api";
19
- var DEFAULT_ATTACH_TIMEOUT_MS = 15000;
20
- var DEFAULT_ATTACH_POLL_INTERVAL_MS = 250;
21
- function stringField(value) {
22
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
23
- }
24
- function githubUserId(value) {
25
- if (typeof value === "number" && Number.isInteger(value))
26
- return String(value);
27
- return stringField(value);
28
- }
29
- function readJsonRecord(path) {
30
- if (!existsSync(path))
31
- return null;
32
- try {
33
- const parsed = JSON.parse(readFileSync(path, "utf8"));
34
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
35
- } catch {
36
- return null;
37
- }
38
- }
39
- function publicIdentityEnv(projectRoot) {
40
- const auth = readJsonRecord(resolve(projectRoot, ".rig", "state", "github-auth.json"));
41
- const connection = readJsonRecord(resolve(projectRoot, ".rig", "state", "connection.json"));
42
- const values = {};
43
- const selectedRepo = stringField(auth?.selectedRepo) ?? stringField(connection?.project);
44
- const userId = githubUserId(auth?.userId);
45
- const login = stringField(auth?.login);
46
- const namespaceKey = stringField(auth?.userNamespaceKey) ?? resolveOwnerNamespaceKey(projectRoot);
47
- if (selectedRepo)
48
- values.RIG_SELECTED_REPO = selectedRepo;
49
- if (userId)
50
- values.RIG_GITHUB_USER_ID = userId;
51
- if (login)
52
- values.RIG_GITHUB_LOGIN = login;
53
- if (namespaceKey)
54
- values.RIG_GITHUB_NAMESPACE_KEY = namespaceKey;
55
- return values;
56
- }
57
- function taskText(value) {
58
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
59
- }
60
- function taskUrl(record) {
61
- const metadata = record;
62
- return taskText(metadata.url) ?? taskText(metadata.html_url) ?? taskText(metadata.webUrl);
63
- }
64
- function taskBody(record) {
65
- const metadata = record;
66
- return taskText(metadata.body) ?? taskText(metadata.description);
67
- }
68
- function taskTitle(record) {
69
- const metadata = record;
70
- return taskText(metadata.title) ?? taskText(metadata.name) ?? record.id;
71
- }
72
- function toExtensionTask(record, sourceKind) {
73
- return {
74
- id: record.id,
75
- title: taskTitle(record),
76
- status: typeof record.status === "string" ? record.status : null,
77
- source: sourceKind,
78
- url: taskUrl(record),
79
- body: taskBody(record)
80
- };
81
- }
82
- async function loadConfiguredTaskSource(projectRoot) {
83
- const normalizedRoot = resolve(projectRoot);
84
- const config = await loadConfig(normalizedRoot);
85
- const pluginHost = createPluginHost(config.plugins);
86
- const taskSourceFactory = pluginHost.resolveTaskSourceFactoryByKind(config.taskSource.kind);
87
- if (!taskSourceFactory) {
88
- const kinds = pluginHost.listExecutableTaskSources().map((entry) => entry.kind).join(", ") || "none";
89
- throw new Error(`No task source factory registered for kind "${config.taskSource.kind}". Registered kinds: ${kinds}.`);
90
- }
91
- return {
92
- kind: config.taskSource.kind,
93
- source: taskSourceFactory.factory(config.taskSource, { projectRoot: normalizedRoot })
94
- };
95
- }
96
- async function listTasksFromSource(projectRoot, deps = {}) {
97
- const { kind, source } = await (deps.loadTaskSource ?? loadConfiguredTaskSource)(projectRoot);
98
- return (await source.list()).map((task) => toExtensionTask(task, kind));
99
- }
100
- async function getTaskFromSource(projectRoot, taskId, deps = {}) {
101
- const tasks = await listTasksFromSource(projectRoot, deps);
102
- return tasks.find((task) => task.id === taskId) ?? null;
103
- }
104
- async function readSelectedTarget(projectRoot, env = process.env) {
105
- const config = await loadConfig(resolve(projectRoot));
106
- const selected = resolveSelectedRemote(projectRoot, env);
107
- return {
108
- alias: selected?.alias ?? "local",
109
- kind: selected ? "remote" : "local",
110
- projectRoot,
111
- status: "ready",
112
- taskSource: config.taskSource.kind
113
- };
114
- }
115
- function runningFromCompiledBinary() {
116
- return import.meta.url.includes("$bunfs");
117
- }
118
- function resolveRigRunBin() {
119
- if (runningFromCompiledBinary())
120
- return resolve(dirname(process.execPath), "rig-run");
121
- return resolve(dirname(fileURLToPath(import.meta.url)), "../../../rig-host/bin/rig-run.ts");
122
- }
123
- async function defaultRunRunProcess(input) {
124
- const { runRunProcess } = await import("@rig/rig-host");
125
- return await runRunProcess(input);
126
- }
127
- function shellQuote(value) {
128
- return `'${value.replace(/'/g, "'\\''")}'`;
129
- }
130
- function readProjectSlug(projectRoot) {
131
- const connection = readJsonRecord(resolve(projectRoot, ".rig", "state", "connection.json"));
132
- return stringField(connection?.project) ?? null;
133
- }
134
- function resolveProjectOriginUrl(projectRoot) {
135
- const slug = readProjectSlug(projectRoot);
136
- return slug && /^[^/]+\/[^/]+$/.test(slug) ? `https://github.com/${slug}.git` : null;
137
- }
138
- async function spawnRunProcess(input, deps = {}) {
139
- const runId = (deps.uuid ?? randomUUID)();
140
- const env = deps.env ?? process.env;
141
- const identityEnv = publicIdentityEnv(input.projectRoot);
142
- const selected = resolveSelectedRemote(input.projectRoot, env);
143
- const sshTarget = selected?.sshTarget ?? env.RIG_REMOTE_ALIAS?.trim();
144
- if (sshTarget) {
145
- const namespaceKey = identityEnv.RIG_GITHUB_NAMESPACE_KEY ?? resolveOwnerNamespaceKey(input.projectRoot, env) ?? "";
146
- const sh = shellQuote;
147
- const originUrl = resolveProjectOriginUrl(input.projectRoot);
148
- const repoName = (readProjectSlug(input.projectRoot)?.split("/").pop() ?? "project").replace(/[^A-Za-z0-9._-]/g, "-");
149
- const checkoutExpr = selected?.checkout ? sh(selected.checkout) : `"$HOME/.rig/checkouts/${repoName}"`;
150
- const identityAssignments = Object.entries(identityEnv).map(([k, v]) => `${k}=${sh(v)}`);
151
- if (namespaceKey && !identityEnv.RIG_GITHUB_NAMESPACE_KEY)
152
- identityAssignments.push(`RIG_GITHUB_NAMESPACE_KEY=${sh(namespaceKey)}`);
153
- const runInvocation = [
154
- `RIG_RUN_ID=${sh(runId)}`,
155
- `RIG_TASK_ID=${sh(input.taskId)}`,
156
- ...identityAssignments,
157
- selected?.registryBaseUrl ? `RIG_REGISTRY_URL=${sh(selected.registryBaseUrl)}` : "",
158
- `rig run start --task ${sh(input.taskId)}`
159
- ].filter(Boolean).join(" ");
160
- const provisionAndRun = [
161
- "set -e",
162
- `CHECKOUT=${checkoutExpr}`,
163
- originUrl ? `[ -d "$CHECKOUT/.git" ] || git clone ${sh(originUrl)} "$CHECKOUT"` : `[ -d "$CHECKOUT/.git" ] || { echo "rig: remote checkout $CHECKOUT missing and no origin to clone" >&2; exit 1; }`,
164
- `cd "$CHECKOUT"`,
165
- "git fetch origin --prune --quiet || true",
166
- runInvocation
167
- ].join("; ");
168
- const child = (deps.spawn ?? nodeSpawn)("ssh", [sshTarget, `bash -lc ${sh(provisionAndRun)}`], {
169
- cwd: input.projectRoot,
170
- env: { ...env, ...identityEnv },
171
- detached: true,
172
- stdio: "ignore"
173
- });
174
- child.unref();
175
- return { runId };
176
- }
177
- await (deps.runRunProcess ?? defaultRunRunProcess)({
178
- projectRoot: input.projectRoot,
179
- taskId: input.taskId,
180
- runId,
181
- title: input.title,
182
- rigRunBin: (deps.resolveRigRunBin ?? resolveRigRunBin)()
183
- });
184
- return { runId };
185
- }
186
- function buildRemoteControlCommand(runId, control, ctx) {
187
- const verb = control.kind === "stop" ? `rig run stop ${shellQuote(runId)}${control.reason.trim() ? ` --reason ${shellQuote(control.reason)}` : ""}` : `rig run steer ${shellQuote(runId)} --message ${shellQuote(control.message)}`;
188
- return [
189
- ctx.checkout ? `cd ${shellQuote(ctx.checkout)} &&` : "",
190
- ctx.namespaceKey ? `RIG_GITHUB_NAMESPACE_KEY=${shellQuote(ctx.namespaceKey)}` : "",
191
- ctx.registryBaseUrl ? `RIG_REGISTRY_URL=${shellQuote(ctx.registryBaseUrl)}` : "",
192
- verb
193
- ].filter(Boolean).join(" ");
194
- }
195
- async function deliverRemoteRunControl(projectRoot, runId, control, deps = {}) {
196
- const env = deps.env ?? process.env;
197
- const selected = resolveSelectedRemote(projectRoot, env);
198
- const sshTarget = selected?.sshTarget ?? env.RIG_REMOTE_ALIAS?.trim();
199
- if (!sshTarget) {
200
- throw new Error(`Run ${runId} is remote but no SSH target is configured (set one with \`rig server use <alias>\`).`);
201
- }
202
- const identityEnv = publicIdentityEnv(projectRoot);
203
- const namespaceKey = identityEnv.RIG_GITHUB_NAMESPACE_KEY ?? resolveOwnerNamespaceKey(projectRoot, env) ?? "";
204
- const remoteCommand = buildRemoteControlCommand(runId, control, {
205
- checkout: selected?.checkout ?? null,
206
- registryBaseUrl: selected?.registryBaseUrl ?? null,
207
- namespaceKey
208
- });
209
- await new Promise((resolveDone, rejectDone) => {
210
- const child = (deps.spawn ?? nodeSpawn)("ssh", [sshTarget, `bash -lc ${shellQuote(remoteCommand)}`], {
211
- cwd: projectRoot,
212
- env: { ...env, ...identityEnv },
213
- stdio: ["ignore", "ignore", "pipe"]
214
- });
215
- let stderr = "";
216
- child.stderr?.on("data", (chunk) => {
217
- stderr += String(chunk);
218
- });
219
- child.on("error", rejectDone);
220
- child.on("close", (code) => {
221
- if (code === 0) {
222
- resolveDone();
223
- return;
224
- }
225
- const detail = stderr.trim();
226
- rejectDone(new Error(`remote \`rig run ${control.kind}\` exited ${code ?? "null"}${detail ? `: ${detail}` : ""}`));
227
- });
228
- });
229
- }
230
- function registrySecret(env = process.env) {
231
- return resolveRegistrySecret(process.cwd(), env) ?? null;
232
- }
233
- function registryBaseUrl(env = process.env) {
234
- return resolveRegistryBaseUrl(process.cwd(), env);
235
- }
236
- function collabFromRegistryEntry(entry) {
237
- return {
238
- sessionId: entry.roomId,
239
- sessionPath: "",
240
- cwd: "",
241
- title: entry.title,
242
- joinLink: entry.joinLink,
243
- webLink: entry.webLink,
244
- relayUrl: entry.relayUrl,
245
- owner: entry.owner,
246
- selectedRepo: entry.repo,
247
- startedAt: entry.startedAt,
248
- updatedAt: entry.heartbeatAt,
249
- ...entry.pid === undefined ? {} : { pid: entry.pid },
250
- stale: entry.stale
251
- };
252
- }
253
- function isRecord(value) {
254
- return typeof value === "object" && value !== null;
255
- }
256
- function readLocalRunCollab(runtime) {
257
- if (!runtime.sessionDir || !existsSync(runtime.sessionDir))
258
- return null;
259
- let files;
260
- try {
261
- files = readdirSync(runtime.sessionDir).filter((f) => f.endsWith(".jsonl")).sort().reverse();
262
- } catch {
263
- return null;
264
- }
265
- for (const file of files) {
266
- let lines;
267
- try {
268
- lines = readFileSync(resolve(runtime.sessionDir, file), "utf8").split(`
269
- `);
270
- } catch {
271
- continue;
272
- }
273
- let host = null;
274
- for (const line of lines) {
275
- if (!line.includes("collab-host-started"))
276
- continue;
277
- let entry;
278
- try {
279
- entry = JSON.parse(line);
280
- } catch {
281
- continue;
282
- }
283
- if (!isRecord(entry) || entry.customType !== CUSTOM_TYPE_FOR["timeline-entry"] || !isRecord(entry.data))
284
- continue;
285
- const payload = isRecord(entry.data.payload) ? entry.data.payload : entry.data;
286
- if (payload.type !== "collab-host-started")
287
- continue;
288
- host = {
289
- roomId: typeof payload.roomId === "string" ? payload.roomId : undefined,
290
- joinLink: typeof payload.joinLink === "string" ? payload.joinLink : undefined,
291
- webLink: typeof payload.webLink === "string" ? payload.webLink : undefined,
292
- relayUrl: typeof payload.relayUrl === "string" ? payload.relayUrl : undefined,
293
- at: typeof entry.data.at === "string" ? entry.data.at : undefined
294
- };
295
- }
296
- if (!host?.joinLink)
297
- continue;
298
- const at = host.at ?? "";
299
- const sessionId = host.roomId ?? sessionIdFromSessionFile(resolve(runtime.sessionDir, file)) ?? runtime.id;
300
- return {
301
- sessionId,
302
- sessionPath: resolve(runtime.sessionDir, file),
303
- cwd: runtime.workspaceDir,
304
- joinLink: host.joinLink,
305
- webLink: host.webLink ?? "",
306
- relayUrl: host.relayUrl ?? "",
307
- title: runtime.taskId ? `[${runtime.taskId}] Rig run ${sessionId}` : `Rig run ${sessionId}`,
308
- startedAt: at,
309
- updatedAt: at,
310
- stale: false
311
- };
312
- }
313
- return null;
314
- }
315
- async function listLocalRunCollabSessions(projectRoot) {
316
- let runtimes;
317
- try {
318
- runtimes = await listAgentRuntimes(projectRoot);
319
- } catch {
320
- return [];
321
- }
322
- const out = [];
323
- for (const runtime of runtimes) {
324
- const collab = readLocalRunCollab(runtime);
325
- if (collab)
326
- out.push(collab);
327
- }
328
- return out;
329
- }
330
- async function listActiveRunCollab(filter) {
331
- return defaultListActiveCollabSessions(filter);
332
- }
333
- async function defaultListActiveCollabSessions(filter) {
334
- const projectRoot = process.cwd();
335
- const local = await listLocalRunCollabSessions(projectRoot);
336
- const namespaceKey = filter.namespaceKey ?? resolveOwnerNamespaceKey(projectRoot);
337
- const secret = registrySecret();
338
- const remote = namespaceKey && secret ? (await createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey, secret }).listRoomsByOwner(filter)).map(collabFromRegistryEntry) : await ompListActiveCollabSessions(filter);
339
- const seen = new Set(local.map((c) => c.sessionId));
340
- return [...local, ...remote.filter((c) => !seen.has(c.sessionId))];
341
- }
342
- function sleep(ms) {
343
- const { promise, resolve: resolveSleep } = Promise.withResolvers();
344
- setTimeout(resolveSleep, ms);
345
- return promise;
346
- }
347
- function matchesRun(collab, runId, taskId) {
348
- if (collab.sessionId === runId)
349
- return true;
350
- if (runId && collab.title?.includes(runId))
351
- return true;
352
- return Boolean(taskId && collab.title?.includes(taskId));
353
- }
354
- async function attachViaRelay(input, deps = {}) {
355
- const timeoutMs = input.timeoutMs ?? DEFAULT_ATTACH_TIMEOUT_MS;
356
- const pollIntervalMs = input.pollIntervalMs ?? DEFAULT_ATTACH_POLL_INTERVAL_MS;
357
- const listActive = deps.listActiveCollabSessions ?? defaultListActiveCollabSessions;
358
- const now = deps.now ?? Date.now;
359
- const pause = deps.sleep ?? sleep;
360
- const deadline = now() + timeoutMs;
361
- do {
362
- const live = await listActive(input.identityFilter);
363
- const match = live.find((collab) => matchesRun(collab, input.runId, input.taskId) && !collab.stale);
364
- if (match) {
365
- return {
366
- sessionPath: match.sessionPath || null,
367
- joinLink: match.joinLink || null,
368
- collabSessionId: match.sessionId
369
- };
370
- }
371
- if (now() >= deadline)
372
- break;
373
- await pause(pollIntervalMs);
374
- } while (now() <= deadline);
375
- return null;
376
- }
377
- export {
378
- spawnRunProcess,
379
- resolveRigRunBin,
380
- readSelectedTarget,
381
- listTasksFromSource,
382
- listActiveRunCollab,
383
- getTaskFromSource,
384
- deliverRemoteRunControl,
385
- buildRemoteControlCommand,
386
- attachViaRelay
387
- };
@@ -1,9 +0,0 @@
1
- import type { RunJournalProjection } from "@rig/contracts";
2
- /**
3
- * Extract the most useful human-facing failure diagnostic from the folded run journal.
4
- *
5
- * The live projection deliberately does not retain log/timeline lines, so this mirrors the
6
- * deleted server-side categorization using only fields that survive folding: record fields,
7
- * status reasons, closeout details, and reducer anomalies.
8
- */
9
- export declare function summarizeUsefulRunError(projection: RunJournalProjection): string | null;
@@ -1,51 +0,0 @@
1
- // @bun
2
- // packages/cli/src/commands/_run-diagnostics.ts
3
- function normalizeString(value) {
4
- if (typeof value !== "string")
5
- return null;
6
- const normalized = value.replace(/\s+/g, " ").trim();
7
- return normalized.length > 0 ? normalized : null;
8
- }
9
- function isGenericRunFailure(value) {
10
- const text = normalizeString(value);
11
- return Boolean(text && /^Task run failed \([^)]*\)$/i.test(text));
12
- }
13
- function appendCandidate(candidates, value) {
14
- const text = normalizeString(value);
15
- if (text && !candidates.includes(text))
16
- candidates.push(text);
17
- }
18
- function categorizeUsefulRunError(lines) {
19
- const taskSourceFailure = lines.find((line) => /failed to update task source/i.test(line));
20
- if (taskSourceFailure)
21
- return `Task source update failed: ${taskSourceFailure}`;
22
- const moduleFailure = lines.find((line) => /cannot find module/i.test(line));
23
- if (moduleFailure)
24
- return `Runtime module resolution failed: ${moduleFailure}`;
25
- const providerFailure = lines.find((line) => /no api key found|unauthorized|authentication failed|invalid api key/i.test(line));
26
- if (providerFailure)
27
- return `Provider authentication failed: ${providerFailure}`;
28
- return null;
29
- }
30
- function summarizeUsefulRunError(projection) {
31
- if (projection.status !== "failed")
32
- return null;
33
- const candidates = [];
34
- for (const anomaly of projection.anomalies) {
35
- appendCandidate(candidates, `Journal anomaly (${anomaly.kind}): ${anomaly.detail}`);
36
- }
37
- for (const phase of projection.closeoutPhases) {
38
- if (phase.outcome === "failed")
39
- appendCandidate(candidates, phase.detail);
40
- }
41
- for (const entry of projection.statusHistory) {
42
- appendCandidate(candidates, entry.reason);
43
- }
44
- appendCandidate(candidates, projection.record.statusDetail);
45
- appendCandidate(candidates, projection.record.errorText);
46
- const nonGeneric = candidates.filter((candidate) => !isGenericRunFailure(candidate));
47
- return categorizeUsefulRunError(nonGeneric) ?? nonGeneric.at(-1) ?? normalizeString(projection.record.errorText);
48
- }
49
- export {
50
- summarizeUsefulRunError
51
- };
@@ -1,26 +0,0 @@
1
- export type SourceTaskContract = {
2
- id: string;
3
- title?: string | null;
4
- description?: string | null;
5
- body?: string | null;
6
- acceptanceCriteria?: string | null;
7
- acceptance_criteria?: string | null;
8
- sourceIssueId?: string | null;
9
- status?: string | null;
10
- issueType?: string | null;
11
- role?: string | null;
12
- validation?: string[];
13
- validators?: string[];
14
- labels?: string[];
15
- scope?: string[];
16
- };
17
- export declare function buildRunPrompt(input: {
18
- projectRoot: string;
19
- taskId?: string | undefined;
20
- fallbackTitle?: string | undefined;
21
- fallbackDescription?: string | undefined;
22
- fallbackAcceptanceCriteria?: string | undefined;
23
- sourceTask?: SourceTaskContract | null;
24
- initialPrompt?: string;
25
- runtimeAdapter: "claude-code" | "codex" | "pi";
26
- }): string;
@@ -1,138 +0,0 @@
1
- // @bun
2
- // packages/cli/src/commands/_run-driver-helpers.ts
3
- import { existsSync, readFileSync } from "fs";
4
- import { resolve as resolve2 } from "path";
5
-
6
- // packages/cli/src/commands/_paths.ts
7
- import { resolve } from "path";
8
- import { resolveMonorepoRoot } from "@rig/runtime/layout";
9
- function resolveControlPlaneMonorepoRoot(projectRoot) {
10
- return resolveMonorepoRoot(projectRoot);
11
- }
12
- function resolveControlPlaneTaskConfigPath(projectRoot) {
13
- return resolve(resolveControlPlaneMonorepoRoot(projectRoot), ".rig", "task-config.json");
14
- }
15
-
16
- // packages/cli/src/commands/_run-driver-helpers.ts
17
- function readLatestBeadRecord(projectRoot, taskId) {
18
- const issuesPath = resolve2(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
19
- if (!existsSync(issuesPath)) {
20
- return null;
21
- }
22
- let latest = null;
23
- for (const line of readFileSync(issuesPath, "utf8").split(/\r?\n/)) {
24
- const trimmed = line.trim();
25
- if (!trimmed)
26
- continue;
27
- try {
28
- const parsed = JSON.parse(trimmed);
29
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
30
- continue;
31
- const record = parsed;
32
- if (record.id === taskId)
33
- latest = record;
34
- } catch {}
35
- }
36
- return latest;
37
- }
38
- function firstPromptString(...values) {
39
- for (const value of values) {
40
- if (typeof value === "string" && value.trim())
41
- return value.trim();
42
- }
43
- return null;
44
- }
45
- function uniqueStrings(values) {
46
- return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
47
- }
48
- function renderSourceTaskContract(task, validation) {
49
- if (!task)
50
- return validation.length > 0 ? [`Validation: ${validation.join(", ")}`] : [];
51
- const lines = [`id: ${task.id}`];
52
- if (task.sourceIssueId)
53
- lines.push(`source issue: ${task.sourceIssueId}`);
54
- if (task.status)
55
- lines.push(`status: ${task.status}`);
56
- if (task.issueType)
57
- lines.push(`issue type: ${task.issueType}`);
58
- if (task.role)
59
- lines.push(`role: ${task.role}`);
60
- if (validation.length > 0)
61
- lines.push(`validation: ${validation.join(", ")}`);
62
- return lines;
63
- }
64
- function renderSourceScopeValidation(task, validation) {
65
- if (task || validation.length === 0)
66
- return "";
67
- return `Validation:
68
- - ${validation.join(`
69
- - `)}`;
70
- }
71
- function readTaskScopeText(projectRoot, taskId) {
72
- try {
73
- const parsed = JSON.parse(readFileSync(resolveControlPlaneTaskConfigPath(projectRoot), "utf8"));
74
- const entry = parsed[taskId] ?? {};
75
- const scope = Array.isArray(entry.scope) ? entry.scope.filter((item) => typeof item === "string") : [];
76
- const validation = Array.isArray(entry.validation) ? entry.validation.filter((item) => typeof item === "string") : [];
77
- const lines = [];
78
- if (scope.length > 0)
79
- lines.push(`Scope:
80
- - ${scope.join(`
81
- - `)}`);
82
- if (validation.length > 0)
83
- lines.push(`Validation:
84
- - ${validation.join(`
85
- - `)}`);
86
- return lines.join(`
87
-
88
- `);
89
- } catch {
90
- return "";
91
- }
92
- }
93
- function providerInstructionLines(runtimeAdapter) {
94
- if (runtimeAdapter === "pi") {
95
- return ["Keep file writes inside the scoped task workspace and use the bridged Pi tooling for shell and follow-up prompts."];
96
- }
97
- if (runtimeAdapter === "codex") {
98
- return ["Keep file writes inside the scoped task workspace and prefer compact terminal output."];
99
- }
100
- return ["Keep file writes inside the scoped task workspace and stay within the provided tool surface."];
101
- }
102
- function buildRunPrompt(input) {
103
- const initialPrompt = input.initialPrompt?.trim() || null;
104
- if (!input.taskId) {
105
- return initialPrompt ?? input.fallbackTitle?.trim() ?? "Continue the requested run and complete the work.";
106
- }
107
- const bead = readLatestBeadRecord(input.projectRoot, input.taskId);
108
- const sourceTask = input.sourceTask ?? null;
109
- const sourceDescription = firstPromptString(sourceTask?.description, sourceTask?.body);
110
- const sourceAcceptance = firstPromptString(sourceTask?.acceptanceCriteria, sourceTask?.acceptance_criteria);
111
- const sourceValidation = uniqueStrings([...sourceTask?.validation ?? [], ...sourceTask?.validators ?? []]);
112
- const title = (bead && typeof bead.title === "string" ? bead.title : null) ?? firstPromptString(sourceTask?.title) ?? input.fallbackTitle ?? input.taskId;
113
- const description = (bead && typeof bead.description === "string" ? bead.description : null) ?? sourceDescription ?? input.fallbackDescription ?? "";
114
- const acceptance = (bead && typeof bead.acceptance_criteria === "string" ? bead.acceptance_criteria : null) ?? sourceAcceptance ?? input.fallbackAcceptanceCriteria ?? "";
115
- const scopeText = readTaskScopeText(input.projectRoot, input.taskId);
116
- const sourceContractLines = renderSourceTaskContract(sourceTask, sourceValidation);
117
- const providerLines = providerInstructionLines(input.runtimeAdapter);
118
- return [
119
- `You are working on task ${input.taskId}: ${title}.`,
120
- description ? `Description:
121
- ${description}` : null,
122
- acceptance ? `Acceptance criteria:
123
- ${acceptance}` : null,
124
- sourceContractLines.length > 0 ? `Source task contract:
125
- ${sourceContractLines.join(`
126
- `)}` : null,
127
- scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
128
- initialPrompt ? `Additional operator guidance:
129
- ${initialPrompt}` : null,
130
- providerLines.length > 0 ? `Provider-specific runtime tooling:
131
- ${providerLines.join(" ")}` : null
132
- ].filter((value) => Boolean(value)).join(`
133
-
134
- `);
135
- }
136
- export {
137
- buildRunPrompt
138
- };
@@ -1,50 +0,0 @@
1
- import { type RunJournalProjection, type RunSessionCustomEntry } from "@rig/contracts";
2
- import type { CollabRegistryFilter } from "@oh-my-pi/pi-coding-agent/collab/api";
3
- /** A run as seen by the operator CLI: live-presence facts joined with the folded journal. */
4
- export interface RunProjectionRecord {
5
- readonly runId: string;
6
- readonly taskId: string | null;
7
- readonly title: string;
8
- /** RunStatus from the folded journal, or a liveness-derived fallback. */
9
- readonly status: string;
10
- readonly source: "local" | "remote";
11
- /** True when the run is currently discoverable (registry heartbeat or local host). */
12
- readonly live: boolean;
13
- readonly stale: boolean;
14
- readonly startedAt: string | null;
15
- readonly updatedAt: string | null;
16
- readonly completedAt: string | null;
17
- readonly joinLink: string | null;
18
- readonly webLink: string | null;
19
- readonly relayUrl: string | null;
20
- readonly sessionPath: string | null;
21
- readonly prUrl: string | null;
22
- readonly worktreePath: string | null;
23
- readonly pendingApprovals: number;
24
- readonly pendingInputs: number;
25
- readonly steeringCount: number;
26
- readonly stallCount: number;
27
- readonly errorSummary?: string | null;
28
- /** The full folded journal (empty projection when no journal was readable). */
29
- readonly projection: RunJournalProjection;
30
- }
31
- /** What an attach/steer caller needs to reach a live run over collab. */
32
- export interface RunJoinTarget {
33
- readonly runId: string;
34
- readonly taskId: string | null;
35
- readonly joinLink: string;
36
- readonly cwd: string | null;
37
- readonly stale: boolean;
38
- }
39
- /** Parse an OMP session JSONL into the custom-entry shape `foldRunSessionEntries` expects. */
40
- export declare function readSessionRunEntries(sessionPath: string | null): RunSessionCustomEntry[];
41
- /**
42
- * List every discoverable run: live collab (relay-registry + local hosts) merged
43
- * with finished/local runs recovered from on-disk agent-runtime session journals.
44
- * Live entries win on runId collisions (they carry join links + current presence).
45
- */
46
- export declare function listRunProjections(projectRoot: string, filter?: CollabRegistryFilter): Promise<RunProjectionRecord[]>;
47
- /** Resolve a single run by id (or unambiguous prefix). */
48
- export declare function getRunProjection(projectRoot: string, runId: string, filter?: CollabRegistryFilter): Promise<RunProjectionRecord | null>;
49
- /** Resolve the live join target for attach/steer; null when the run is not currently joinable. */
50
- export declare function resolveRunJoinTarget(projectRoot: string, runId: string, filter?: CollabRegistryFilter): Promise<RunJoinTarget | null>;