@h-rig/cli 0.0.6-alpha.24 → 0.0.6-alpha.240

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 (51) hide show
  1. package/README.md +6 -28
  2. package/package.json +13 -28
  3. package/dist/bin/build-rig-binaries.js +0 -107
  4. package/dist/bin/rig.js +0 -11112
  5. package/dist/src/commands/_authority-runs.js +0 -111
  6. package/dist/src/commands/_cli-format.js +0 -106
  7. package/dist/src/commands/_connection-state.js +0 -123
  8. package/dist/src/commands/_doctor-checks.js +0 -507
  9. package/dist/src/commands/_operator-surface.js +0 -204
  10. package/dist/src/commands/_operator-view.js +0 -1147
  11. package/dist/src/commands/_parsers.js +0 -107
  12. package/dist/src/commands/_paths.js +0 -50
  13. package/dist/src/commands/_pi-frontend.js +0 -843
  14. package/dist/src/commands/_pi-install.js +0 -185
  15. package/dist/src/commands/_pi-worker-bridge-extension.js +0 -761
  16. package/dist/src/commands/_policy.js +0 -79
  17. package/dist/src/commands/_preflight.js +0 -403
  18. package/dist/src/commands/_probes.js +0 -13
  19. package/dist/src/commands/_run-driver-helpers.js +0 -289
  20. package/dist/src/commands/_server-client.js +0 -514
  21. package/dist/src/commands/_snapshot-upload.js +0 -318
  22. package/dist/src/commands/_task-picker.js +0 -76
  23. package/dist/src/commands/agent.js +0 -499
  24. package/dist/src/commands/browser.js +0 -890
  25. package/dist/src/commands/connect.js +0 -180
  26. package/dist/src/commands/dist.js +0 -402
  27. package/dist/src/commands/doctor.js +0 -517
  28. package/dist/src/commands/github.js +0 -281
  29. package/dist/src/commands/inbox.js +0 -160
  30. package/dist/src/commands/init.js +0 -1563
  31. package/dist/src/commands/inspect.js +0 -174
  32. package/dist/src/commands/inspector.js +0 -256
  33. package/dist/src/commands/plugin.js +0 -167
  34. package/dist/src/commands/profile-and-review.js +0 -178
  35. package/dist/src/commands/queue.js +0 -198
  36. package/dist/src/commands/remote.js +0 -507
  37. package/dist/src/commands/repo-git-harness.js +0 -221
  38. package/dist/src/commands/run.js +0 -1674
  39. package/dist/src/commands/server.js +0 -373
  40. package/dist/src/commands/setup.js +0 -687
  41. package/dist/src/commands/task-report-bug.js +0 -1083
  42. package/dist/src/commands/task-run-driver.js +0 -2600
  43. package/dist/src/commands/task.js +0 -2178
  44. package/dist/src/commands/test.js +0 -39
  45. package/dist/src/commands/workspace.js +0 -123
  46. package/dist/src/commands.js +0 -10791
  47. package/dist/src/index.js +0 -11130
  48. package/dist/src/launcher.js +0 -133
  49. package/dist/src/report-bug.js +0 -260
  50. package/dist/src/runner.js +0 -273
  51. package/dist/src/withMutedConsole.js +0 -42
@@ -1,180 +0,0 @@
1
- // @bun
2
- // packages/cli/src/runner.ts
3
- import { EventBus } from "@rig/runtime/control-plane/runtime/events";
4
- import { CliError } from "@rig/runtime/control-plane/errors";
5
- import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
6
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
7
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
8
- import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
9
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
10
- function requireNoExtraArgs(args, usage) {
11
- if (args.length > 0) {
12
- throw new CliError(`Unexpected arguments: ${args.join(" ")}
13
- Usage: ${usage}`);
14
- }
15
- }
16
-
17
- // packages/cli/src/commands/_connection-state.ts
18
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
19
- import { homedir } from "os";
20
- import { dirname, resolve } from "path";
21
- function resolveGlobalConnectionsPath(env = process.env) {
22
- const explicit = env.RIG_CONNECTIONS_FILE?.trim();
23
- if (explicit)
24
- return resolve(explicit);
25
- const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
26
- if (stateDir)
27
- return resolve(stateDir, "connections.json");
28
- return resolve(homedir(), ".rig", "connections.json");
29
- }
30
- function resolveRepoConnectionPath(projectRoot) {
31
- return resolve(projectRoot, ".rig", "state", "connection.json");
32
- }
33
- function readJsonFile(path) {
34
- if (!existsSync(path))
35
- return null;
36
- try {
37
- return JSON.parse(readFileSync(path, "utf8"));
38
- } catch (error) {
39
- throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
40
- }
41
- }
42
- function writeJsonFile(path, value) {
43
- mkdirSync(dirname(path), { recursive: true });
44
- writeFileSync(path, `${JSON.stringify(value, null, 2)}
45
- `, "utf8");
46
- }
47
- function normalizeConnection(value) {
48
- if (!value || typeof value !== "object" || Array.isArray(value))
49
- return null;
50
- const record = value;
51
- if (record.kind === "local")
52
- return { kind: "local", mode: "auto" };
53
- if (record.kind === "remote" && typeof record.baseUrl === "string" && record.baseUrl.trim()) {
54
- const baseUrl = record.baseUrl.trim().replace(/\/+$/, "");
55
- return { kind: "remote", baseUrl };
56
- }
57
- return null;
58
- }
59
- function readGlobalConnections(options = {}) {
60
- const path = resolveGlobalConnectionsPath(options.env ?? process.env);
61
- const payload = readJsonFile(path);
62
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
63
- return { connections: {} };
64
- }
65
- const rawConnections = payload.connections;
66
- const connections = {};
67
- if (rawConnections && typeof rawConnections === "object" && !Array.isArray(rawConnections)) {
68
- for (const [alias, raw] of Object.entries(rawConnections)) {
69
- const connection = normalizeConnection(raw);
70
- if (connection)
71
- connections[alias] = connection;
72
- }
73
- }
74
- return { connections };
75
- }
76
- function writeGlobalConnections(state, options = {}) {
77
- writeJsonFile(resolveGlobalConnectionsPath(options.env ?? process.env), state);
78
- }
79
- function upsertGlobalConnection(alias, connection, options = {}) {
80
- const cleanAlias = alias.trim();
81
- if (!cleanAlias)
82
- throw new CliError2("Connection alias is required.", 1);
83
- const state = readGlobalConnections(options);
84
- state.connections[cleanAlias] = connection;
85
- writeGlobalConnections(state, options);
86
- return state;
87
- }
88
- function readRepoConnection(projectRoot) {
89
- const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
90
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
91
- return null;
92
- const record = payload;
93
- const selected = typeof record.selected === "string" ? record.selected.trim() : "";
94
- if (!selected)
95
- return null;
96
- return {
97
- selected,
98
- project: typeof record.project === "string" ? record.project : undefined,
99
- linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
100
- };
101
- }
102
- function writeRepoConnection(projectRoot, state) {
103
- writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
104
- }
105
-
106
- // packages/cli/src/commands/connect.ts
107
- function parseConnection(alias, value) {
108
- if (alias === "local" && !value)
109
- return { kind: "local", mode: "auto" };
110
- if (!value)
111
- throw new CliError2("Missing remote server URL. Usage: rig connect add <alias> <url>", 1);
112
- let parsed;
113
- try {
114
- parsed = new URL(value);
115
- } catch {
116
- throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
117
- }
118
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
119
- throw new CliError2("Rig remote server URL must be http(s).", 1);
120
- }
121
- return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
122
- }
123
- function printJsonOrText(context, payload, text) {
124
- if (context.outputMode === "json") {
125
- console.log(JSON.stringify(payload, null, 2));
126
- } else {
127
- console.log(text);
128
- }
129
- }
130
- async function executeConnect(context, args) {
131
- const [command, ...rest] = args;
132
- switch (command ?? "status") {
133
- case "list": {
134
- requireNoExtraArgs(rest, "rig connect list");
135
- const state = readGlobalConnections();
136
- printJsonOrText(context, state, Object.entries(state.connections).map(([alias, connection]) => `${alias} ${connection.kind === "remote" ? connection.baseUrl : "local"}`).join(`
137
- `) || "No Rig connections configured.");
138
- return { ok: true, group: "connect", command: "list", details: state };
139
- }
140
- case "add": {
141
- const [alias, url, ...extra] = rest;
142
- if (!alias)
143
- throw new CliError2("Missing alias. Usage: rig connect add <alias> <url>", 1);
144
- requireNoExtraArgs(extra, "rig connect add <alias> <url>");
145
- const connection = parseConnection(alias, url);
146
- const state = upsertGlobalConnection(alias, connection);
147
- printJsonOrText(context, { alias, connection }, `Added Rig connection ${alias}.`);
148
- return { ok: true, group: "connect", command: "add", details: { alias, connection, count: Object.keys(state.connections).length } };
149
- }
150
- case "use": {
151
- const [alias, ...extra] = rest;
152
- if (!alias)
153
- throw new CliError2("Missing alias. Usage: rig connect use <alias|local>", 1);
154
- requireNoExtraArgs(extra, "rig connect use <alias|local>");
155
- if (alias !== "local") {
156
- const state = readGlobalConnections();
157
- if (!state.connections[alias])
158
- throw new CliError2(`Unknown Rig connection: ${alias}`, 1);
159
- }
160
- const repoState = { selected: alias, linkedAt: new Date().toISOString() };
161
- writeRepoConnection(context.projectRoot, repoState);
162
- printJsonOrText(context, repoState, `Selected Rig connection ${alias} for this repo.`);
163
- return { ok: true, group: "connect", command: "use", details: repoState };
164
- }
165
- case "status": {
166
- requireNoExtraArgs(rest, "rig connect status");
167
- const repo = readRepoConnection(context.projectRoot);
168
- const global = readGlobalConnections();
169
- const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
170
- printJsonOrText(context, details, `Selected Rig connection: ${details.selected}`);
171
- return { ok: true, group: "connect", command: "status", details };
172
- }
173
- default:
174
- throw new CliError2(`Unknown connect command: ${String(command)}
175
- Usage: rig connect <list|add|use|status>`, 1);
176
- }
177
- }
178
- export {
179
- executeConnect
180
- };
@@ -1,402 +0,0 @@
1
- // @bun
2
- // packages/cli/src/commands/dist.ts
3
- import {
4
- chmodSync,
5
- copyFileSync,
6
- existsSync,
7
- mkdirSync,
8
- readdirSync,
9
- readlinkSync,
10
- rmSync,
11
- statSync,
12
- symlinkSync,
13
- unlinkSync
14
- } from "fs";
15
- import { homedir as homedir2 } from "os";
16
- import { resolve as resolve3 } from "path";
17
-
18
- // packages/cli/src/runner.ts
19
- import { EventBus } from "@rig/runtime/control-plane/runtime/events";
20
- import { CliError } from "@rig/runtime/control-plane/errors";
21
- import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
22
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
23
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
24
- import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
25
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
26
- function takeOption(args, option) {
27
- const rest = [];
28
- let value;
29
- for (let index = 0;index < args.length; index += 1) {
30
- const current = args[index];
31
- if (current === option) {
32
- const next = args[index + 1];
33
- if (!next || next.startsWith("-")) {
34
- throw new CliError(`Missing value for ${option}`);
35
- }
36
- value = next;
37
- index += 1;
38
- continue;
39
- }
40
- if (current !== undefined) {
41
- rest.push(current);
42
- }
43
- }
44
- return { value, rest };
45
- }
46
- function requireNoExtraArgs(args, usage) {
47
- if (args.length > 0) {
48
- throw new CliError(`Unexpected arguments: ${args.join(" ")}
49
- Usage: ${usage}`);
50
- }
51
- }
52
-
53
- // packages/cli/src/commands/dist.ts
54
- import { buildBinary as buildBinary2 } from "@rig/runtime/control-plane/runtime/isolation";
55
- import {
56
- computeRuntimeImageFingerprint,
57
- computeRuntimeImageId
58
- } from "@rig/runtime/control-plane/runtime/image/index";
59
-
60
- // packages/cli/src/commands/_parsers.ts
61
- import { homedir } from "os";
62
- import { resolve } from "path";
63
- function parseInstallScope(value) {
64
- if (!value || value === "user") {
65
- return "user";
66
- }
67
- if (value === "system") {
68
- return "system";
69
- }
70
- throw new CliError2(`Invalid --scope value: ${value}. Use user|system.`);
71
- }
72
- function resolveInstallDir(scope, explicitPath) {
73
- if (explicitPath) {
74
- return resolve(explicitPath);
75
- }
76
- if (scope === "system") {
77
- return "/usr/local/bin";
78
- }
79
- return resolve(homedir(), ".local/bin");
80
- }
81
-
82
- // packages/cli/src/commands/_paths.ts
83
- import { resolve as resolve2 } from "path";
84
- import { resolveMonorepoRoot } from "@rig/runtime/control-plane/native/utils";
85
- function resolveControlPlaneMonorepoRoot(projectRoot) {
86
- return resolveMonorepoRoot(projectRoot);
87
- }
88
- function resolveControlPlaneHostStateRoot(projectRoot) {
89
- return resolve2(projectRoot, ".rig");
90
- }
91
- function resolveControlPlaneHostBinDir(projectRoot) {
92
- return resolve2(resolveControlPlaneHostStateRoot(projectRoot), "bin");
93
- }
94
- function resolveControlPlaneHostDistDir(projectRoot) {
95
- return resolve2(resolveControlPlaneHostStateRoot(projectRoot), "dist");
96
- }
97
- function resolveControlPlaneMonorepoStateRoot(projectRoot) {
98
- return resolve2(resolveControlPlaneMonorepoRoot(projectRoot), ".rig");
99
- }
100
- function resolveControlPlaneMonorepoRuntimeDir(projectRoot) {
101
- return resolve2(resolveControlPlaneMonorepoStateRoot(projectRoot), "runtime");
102
- }
103
-
104
- // packages/cli/src/commands/_probes.ts
105
- async function runQuietBinaryProbe(binaryPath, args, cwd) {
106
- try {
107
- const run = await Bun.$`${binaryPath} ${args}`.cwd(cwd).quiet().nothrow();
108
- return run.exitCode === 0;
109
- } catch {
110
- return false;
111
- }
112
- }
113
-
114
- // packages/cli/src/commands/dist.ts
115
- function collectRigValidatorBuildTargets(input) {
116
- const validatorsRoot = resolve3(input.hostProjectRoot, "packages/runtime/src/control-plane/validators");
117
- if (!existsSync(validatorsRoot))
118
- return [];
119
- const targets = [];
120
- const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
121
- for (const category of categories) {
122
- const categoryDir = resolve3(validatorsRoot, category.name);
123
- for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
124
- if (!entry.isFile() || !entry.name.endsWith(".ts"))
125
- continue;
126
- const check = entry.name.replace(/\.ts$/, "");
127
- if (!check || check === "index" || check === "shared")
128
- continue;
129
- targets.push({
130
- source: `packages/runtime/src/control-plane/validators/${category.name}/${entry.name}`,
131
- dest: resolve3(input.imageDir, `bin/validators/${category.name}-${check}`),
132
- cwd: input.hostProjectRoot
133
- });
134
- }
135
- }
136
- return targets;
137
- }
138
- async function findLatestDistBinary(projectRoot) {
139
- const distRoot = resolveControlPlaneHostDistDir(projectRoot);
140
- if (!existsSync(distRoot)) {
141
- return null;
142
- }
143
- const entries = readdirSync(distRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("rig-")).map((entry) => ({
144
- name: entry.name,
145
- mtimeMs: statSync(resolve3(distRoot, entry.name)).mtimeMs
146
- })).sort((a, b) => b.mtimeMs - a.mtimeMs || b.name.localeCompare(a.name));
147
- for (const { name } of entries) {
148
- const candidate = resolve3(distRoot, name, "bin", "rig");
149
- if (existsSync(candidate) && await isRunnableRigBinary(candidate, projectRoot)) {
150
- return candidate;
151
- }
152
- }
153
- return null;
154
- }
155
- async function isRunnableRigBinary(binaryPath, projectRoot) {
156
- return runQuietBinaryProbe(binaryPath, ["help"], projectRoot);
157
- }
158
- async function runDistDoctor(projectRoot) {
159
- const bunPath = Bun.which("bun");
160
- const rigPath = Bun.which("rig");
161
- const userBinDir = resolve3(homedir2(), ".local/bin");
162
- const userBinInPath = (process.env.PATH || "").split(":").filter(Boolean).includes(userBinDir);
163
- let rigRunnable = false;
164
- if (rigPath) {
165
- rigRunnable = await runQuietBinaryProbe(rigPath, ["help"], projectRoot);
166
- }
167
- return {
168
- bun: {
169
- available: Boolean(bunPath),
170
- path: bunPath || null,
171
- version: Bun.version
172
- },
173
- rig: {
174
- onPath: Boolean(rigPath),
175
- path: rigPath || null,
176
- runnable: rigRunnable
177
- },
178
- userBinDir,
179
- userBinInPath,
180
- latestDistBinary: await findLatestDistBinary(projectRoot)
181
- };
182
- }
183
- async function executeDist(context, args) {
184
- const [command = "build", ...rest] = args;
185
- switch (command) {
186
- case "build": {
187
- const { value: outputDir, rest: pending } = takeOption(rest, "--output-dir");
188
- requireNoExtraArgs(pending, "bun run rig dist build [--output-dir <dir>]");
189
- const commandParts = ["bun", "run", "packages/cli/bin/build-rig-binaries.ts"];
190
- if (outputDir) {
191
- commandParts.push("--output-dir", outputDir);
192
- }
193
- await context.runCommand(commandParts);
194
- return { ok: true, group: "dist", command, details: { outputDir: outputDir || null } };
195
- }
196
- case "install": {
197
- let pending = rest;
198
- const scopeResult = takeOption(pending, "--scope");
199
- pending = scopeResult.rest;
200
- const pathResult = takeOption(pending, "--path");
201
- pending = pathResult.rest;
202
- requireNoExtraArgs(pending, "bun run rig dist install [--scope user|system] [--path <dir>]");
203
- const scope = parseInstallScope(scopeResult.value);
204
- const installDir = resolveInstallDir(scope, pathResult.value);
205
- mkdirSync(installDir, { recursive: true });
206
- let source = await findLatestDistBinary(context.projectRoot);
207
- let buildDir = null;
208
- if (!source) {
209
- buildDir = resolve3(resolveControlPlaneHostDistDir(context.projectRoot), `rig-install-${Date.now()}`);
210
- await context.runCommand(["bun", "run", "packages/cli/bin/build-rig-binaries.ts", "--output-dir", buildDir]);
211
- source = resolve3(buildDir, "bin", "rig");
212
- }
213
- if (!existsSync(source)) {
214
- throw new CliError2(`Unable to locate rig binary at ${source}.`, 2);
215
- }
216
- const installedPath = resolve3(installDir, "rig");
217
- if (existsSync(installedPath)) {
218
- unlinkSync(installedPath);
219
- }
220
- copyFileSync(source, installedPath);
221
- chmodSync(installedPath, 493);
222
- const pathEntries = (process.env.PATH || "").split(":").filter(Boolean);
223
- const inPath = pathEntries.includes(installDir);
224
- if (context.outputMode === "text") {
225
- console.log(`Installed: ${installedPath}`);
226
- if (!inPath) {
227
- console.log(`PATH note: add ${installDir} to PATH to run 'rig' directly.`);
228
- }
229
- }
230
- return {
231
- ok: true,
232
- group: "dist",
233
- command,
234
- details: {
235
- scope,
236
- installDir,
237
- installedPath,
238
- sourcePath: source,
239
- builtNow: Boolean(buildDir),
240
- inPath
241
- }
242
- };
243
- }
244
- case "doctor": {
245
- requireNoExtraArgs(rest, "bun run rig dist doctor");
246
- const details = await runDistDoctor(context.projectRoot);
247
- if (context.outputMode === "text") {
248
- console.log(`bun: ${details.bun.available ? `ok (${details.bun.version})` : "missing"}`);
249
- console.log(`rig on PATH: ${details.rig.onPath ? details.rig.path : "missing"}`);
250
- console.log(`user bin dir: ${details.userBinDir} (${details.userBinInPath ? "in PATH" : "not in PATH"})`);
251
- console.log(`latest dist binary: ${details.latestDistBinary || "none"}`);
252
- }
253
- return { ok: true, group: "dist", command, details };
254
- }
255
- case "rebuild-agent": {
256
- requireNoExtraArgs(rest, "bun run rig dist rebuild-agent");
257
- const fp = await computeRuntimeImageFingerprint(context.projectRoot);
258
- const currentId = computeRuntimeImageId(fp);
259
- const imagesDir = resolve3(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
260
- mkdirSync(imagesDir, { recursive: true });
261
- let pruned = 0;
262
- for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
263
- if (entry.isDirectory() && entry.name !== currentId) {
264
- rmSync(resolve3(imagesDir, entry.name), { recursive: true, force: true });
265
- pruned++;
266
- }
267
- }
268
- if (pruned > 0 && context.outputMode === "text") {
269
- console.log(`Pruned ${pruned} stale image(s).`);
270
- }
271
- const imageDir = resolve3(imagesDir, currentId);
272
- mkdirSync(resolve3(imageDir, "bin/hooks"), { recursive: true });
273
- mkdirSync(resolve3(imageDir, "bin/plugins"), { recursive: true });
274
- mkdirSync(resolve3(imageDir, "bin/validators"), { recursive: true });
275
- const hookNames = [
276
- "scope-guard",
277
- "import-guard",
278
- "safety-guard",
279
- "test-integrity-guard",
280
- "audit-trail",
281
- "post-edit-lint",
282
- "completion-verification",
283
- "inject-context",
284
- "task-runtime-start"
285
- ];
286
- const targets = [];
287
- const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || context.projectRoot;
288
- targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest: resolve3(imageDir, "bin/rig-agent"), cwd: hostProjectRoot });
289
- targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest: resolve3(resolveControlPlaneHostBinDir(context.projectRoot), "rig-agent"), cwd: hostProjectRoot });
290
- for (const hookName of hookNames) {
291
- const src = `packages/runtime/src/control-plane/hooks/${hookName}.ts`;
292
- targets.push({ source: src, dest: resolve3(imageDir, `bin/hooks/${hookName}`), cwd: hostProjectRoot });
293
- targets.push({ source: src, dest: resolve3(resolveControlPlaneHostBinDir(context.projectRoot), `hooks/${hookName}`), cwd: hostProjectRoot });
294
- }
295
- const pluginsDir = resolve3(context.projectRoot, "rig/plugins");
296
- const binPluginsDir = resolve3(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
297
- const validatorsRoot = resolve3(hostProjectRoot, "packages/runtime/src/control-plane/validators");
298
- const binValidatorsDir = resolve3(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
299
- mkdirSync(binPluginsDir, { recursive: true });
300
- mkdirSync(binValidatorsDir, { recursive: true });
301
- if (existsSync(pluginsDir)) {
302
- for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
303
- const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
304
- if (!m)
305
- continue;
306
- targets.push({ source: `rig/plugins/${entry.name}`, dest: resolve3(imageDir, `bin/plugins/${m[1]}`), cwd: context.projectRoot });
307
- }
308
- }
309
- targets.push(...collectRigValidatorBuildTargets({ contextProjectRoot: context.projectRoot, hostProjectRoot, imageDir }));
310
- for (const { source, dest, cwd } of targets) {
311
- if (context.outputMode === "text") {
312
- console.log(`Building: ${dest}`);
313
- }
314
- const isValidator = dest.includes("/bin/validators/");
315
- await buildBinary2(source, dest, cwd, isValidator ? { AGENT_BUN_PATH: Bun.which("bun") || "bun" } : { AGENT_PROJECT_ROOT: context.projectRoot });
316
- }
317
- if (existsSync(pluginsDir)) {
318
- for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
319
- const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
320
- if (!m)
321
- continue;
322
- const pluginName = m[1];
323
- const imageBin = resolve3(imageDir, `bin/plugins/${pluginName}`);
324
- if (!pluginName)
325
- continue;
326
- const symlinkPath = resolve3(binPluginsDir, pluginName);
327
- if (existsSync(imageBin)) {
328
- try {
329
- unlinkSync(symlinkPath);
330
- } catch {}
331
- symlinkSync(imageBin, symlinkPath);
332
- }
333
- }
334
- }
335
- if (existsSync(validatorsRoot)) {
336
- const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
337
- for (const category of categories) {
338
- const categoryDir = resolve3(validatorsRoot, category.name);
339
- for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
340
- if (!entry.isFile() || !entry.name.endsWith(".ts"))
341
- continue;
342
- const check = entry.name.replace(/\.ts$/, "");
343
- if (!check || check === "index" || check === "shared")
344
- continue;
345
- const validatorName = `${category.name}-${check}`;
346
- const imageBin = resolve3(imageDir, `bin/validators/${validatorName}`);
347
- const symlinkPath = resolve3(binValidatorsDir, validatorName);
348
- if (existsSync(imageBin)) {
349
- try {
350
- unlinkSync(symlinkPath);
351
- } catch {}
352
- symlinkSync(imageBin, symlinkPath);
353
- }
354
- }
355
- }
356
- }
357
- const agentsDir = resolve3(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "agents");
358
- if (existsSync(agentsDir)) {
359
- let relinkCount = 0;
360
- for (const agentEntry of readdirSync(agentsDir, { withFileTypes: true })) {
361
- if (!agentEntry.isDirectory())
362
- continue;
363
- const agentBinDir = resolve3(agentsDir, agentEntry.name, "worktree", ".rig", "bin");
364
- if (!existsSync(agentBinDir))
365
- continue;
366
- const walkDir = (dir) => {
367
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
368
- const fullPath = resolve3(dir, entry.name);
369
- if (entry.isDirectory()) {
370
- walkDir(fullPath);
371
- } else if (entry.isSymbolicLink()) {
372
- const target = readlinkSync(fullPath);
373
- if (target.includes("/.rig/runtime/images/") && !target.includes(`/${currentId}/`)) {
374
- const newTarget = target.replace(/\/\.rig\/runtime\/images\/[^/]+\//, `/.rig/runtime/images/${currentId}/`);
375
- try {
376
- unlinkSync(fullPath);
377
- symlinkSync(newTarget, fullPath);
378
- relinkCount++;
379
- } catch {}
380
- }
381
- }
382
- }
383
- };
384
- walkDir(agentBinDir);
385
- }
386
- if (relinkCount > 0 && context.outputMode === "text") {
387
- console.log(`Re-linked ${relinkCount} worktree symlink(s) to image ${currentId}.`);
388
- }
389
- }
390
- if (context.outputMode === "text") {
391
- console.log(`Rebuilt ${targets.length} binaries into image ${currentId}.`);
392
- }
393
- return { ok: true, group: "dist", command, details: { imageId: currentId, count: targets.length } };
394
- }
395
- default:
396
- throw new CliError2(`Unknown dist command: ${command}`);
397
- }
398
- }
399
- export {
400
- executeDist,
401
- collectRigValidatorBuildTargets
402
- };