@h-rig/cli-surface-plugin 0.0.6-alpha.146

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 (94) hide show
  1. package/README.md +1 -0
  2. package/dist/src/app/drone-ui.d.ts +34 -0
  3. package/dist/src/app/drone-ui.js +278 -0
  4. package/dist/src/commands/_async-ui.d.ts +10 -0
  5. package/dist/src/commands/_async-ui.js +121 -0
  6. package/dist/src/commands/_cli-format.d.ts +56 -0
  7. package/dist/src/commands/_cli-format.js +332 -0
  8. package/dist/src/commands/_connection-state.d.ts +54 -0
  9. package/dist/src/commands/_connection-state.js +187 -0
  10. package/dist/src/commands/_doctor-checks.d.ts +9 -0
  11. package/dist/src/commands/_doctor-checks.js +24 -0
  12. package/dist/src/commands/_help-catalog.d.ts +29 -0
  13. package/dist/src/commands/_help-catalog.js +157 -0
  14. package/dist/src/commands/_inprocess-services.d.ts +33 -0
  15. package/dist/src/commands/_inprocess-services.js +102 -0
  16. package/dist/src/commands/_json-output.d.ts +11 -0
  17. package/dist/src/commands/_json-output.js +54 -0
  18. package/dist/src/commands/_parsers.d.ts +15 -0
  19. package/dist/src/commands/_parsers.js +114 -0
  20. package/dist/src/commands/_paths.d.ts +11 -0
  21. package/dist/src/commands/_paths.js +50 -0
  22. package/dist/src/commands/_pi-frontend.d.ts +35 -0
  23. package/dist/src/commands/_pi-frontend.js +64 -0
  24. package/dist/src/commands/_pi-install.d.ts +42 -0
  25. package/dist/src/commands/_pi-install.js +167 -0
  26. package/dist/src/commands/_policy.d.ts +8 -0
  27. package/dist/src/commands/_policy.js +138 -0
  28. package/dist/src/commands/_probes.d.ts +1 -0
  29. package/dist/src/commands/_probes.js +13 -0
  30. package/dist/src/commands/_run-driver-helpers.d.ts +26 -0
  31. package/dist/src/commands/_run-driver-helpers.js +132 -0
  32. package/dist/src/commands/_run-subcommands.d.ts +3 -0
  33. package/dist/src/commands/_run-subcommands.js +31 -0
  34. package/dist/src/commands/_spinner.d.ts +25 -0
  35. package/dist/src/commands/_spinner.js +65 -0
  36. package/dist/src/commands/agent.d.ts +3 -0
  37. package/dist/src/commands/agent.js +322 -0
  38. package/dist/src/commands/config.d.ts +3 -0
  39. package/dist/src/commands/config.js +193 -0
  40. package/dist/src/commands/dist.d.ts +28 -0
  41. package/dist/src/commands/dist.js +435 -0
  42. package/dist/src/commands/doctor.d.ts +3 -0
  43. package/dist/src/commands/doctor.js +171 -0
  44. package/dist/src/commands/github.d.ts +3 -0
  45. package/dist/src/commands/github.js +342 -0
  46. package/dist/src/commands/inbox.d.ts +19 -0
  47. package/dist/src/commands/inbox.js +241 -0
  48. package/dist/src/commands/init.d.ts +64 -0
  49. package/dist/src/commands/init.js +1449 -0
  50. package/dist/src/commands/inspect.d.ts +20 -0
  51. package/dist/src/commands/inspect.js +337 -0
  52. package/dist/src/commands/pi.d.ts +3 -0
  53. package/dist/src/commands/pi.js +177 -0
  54. package/dist/src/commands/plugin.d.ts +20 -0
  55. package/dist/src/commands/plugin.js +238 -0
  56. package/dist/src/commands/profile-and-review.d.ts +4 -0
  57. package/dist/src/commands/profile-and-review.js +223 -0
  58. package/dist/src/commands/queue.d.ts +3 -0
  59. package/dist/src/commands/queue.js +197 -0
  60. package/dist/src/commands/remote.d.ts +3 -0
  61. package/dist/src/commands/remote.js +516 -0
  62. package/dist/src/commands/repo-git-harness.d.ts +5 -0
  63. package/dist/src/commands/repo-git-harness.js +282 -0
  64. package/dist/src/commands/run.d.ts +22 -0
  65. package/dist/src/commands/run.js +645 -0
  66. package/dist/src/commands/server.d.ts +3 -0
  67. package/dist/src/commands/server.js +155 -0
  68. package/dist/src/commands/setup.d.ts +16 -0
  69. package/dist/src/commands/setup.js +356 -0
  70. package/dist/src/commands/stats.d.ts +11 -0
  71. package/dist/src/commands/stats.js +219 -0
  72. package/dist/src/commands/task-run-driver.d.ts +93 -0
  73. package/dist/src/commands/task-run-driver.js +136 -0
  74. package/dist/src/commands/task.d.ts +46 -0
  75. package/dist/src/commands/task.js +555 -0
  76. package/dist/src/commands/test.d.ts +3 -0
  77. package/dist/src/commands/test.js +46 -0
  78. package/dist/src/commands/triage.d.ts +11 -0
  79. package/dist/src/commands/triage.js +224 -0
  80. package/dist/src/commands/workspace.d.ts +3 -0
  81. package/dist/src/commands/workspace.js +130 -0
  82. package/dist/src/kernel-dispatch.d.ts +15 -0
  83. package/dist/src/kernel-dispatch.js +16 -0
  84. package/dist/src/plugin.d.ts +3 -0
  85. package/dist/src/plugin.js +5440 -0
  86. package/dist/src/rig-config-package-deps.d.ts +10 -0
  87. package/dist/src/rig-config-package-deps.js +272 -0
  88. package/dist/src/runner.d.ts +47 -0
  89. package/dist/src/runner.js +267 -0
  90. package/dist/src/version.d.ts +8 -0
  91. package/dist/src/version.js +47 -0
  92. package/dist/src/withMutedConsole.d.ts +2 -0
  93. package/dist/src/withMutedConsole.js +42 -0
  94. package/package.json +34 -0
@@ -0,0 +1,10 @@
1
+ export declare function hasRigConfig(projectRoot: string): boolean;
2
+ export declare function resolveRigConfigPackageVersion(): string;
3
+ export declare function rigConfigDevDependencies(): Record<string, string>;
4
+ export type RigConfigDependencyPreflightResult = {
5
+ readonly rewroteManifest: boolean;
6
+ readonly ranInstall: boolean;
7
+ readonly command: string | null;
8
+ readonly version: string;
9
+ };
10
+ export declare function ensureRigConfigDependenciesInstalled(projectRoot: string): RigConfigDependencyPreflightResult;
@@ -0,0 +1,272 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/rig-config-package-deps.ts
3
+ import { spawnSync } from "child_process";
4
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
5
+ import { basename, join, resolve as resolve2 } from "path";
6
+
7
+ // packages/cli-surface-plugin/src/version.ts
8
+ import { existsSync, readFileSync } from "fs";
9
+ import { dirname, resolve } from "path";
10
+ import { fileURLToPath } from "url";
11
+ import { readBuildConfig } from "@rig/runtime/build-time-config";
12
+ var SOURCE_CLI_VERSION = "0.0.0-alpha.1";
13
+ var DEV_CLI_VERSION = "0.0.0-dev";
14
+ function resolveInstalledCliVersion() {
15
+ const buildConfig = readBuildConfig();
16
+ const envVersion = process.env.RIG_CLI_VERSION?.trim();
17
+ const buildVersion = buildConfig.RIG_CLI_VERSION?.trim();
18
+ let version = envVersion || buildVersion || "";
19
+ if (!version) {
20
+ try {
21
+ const execPath = process.execPath || "";
22
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
23
+ const candidates = [
24
+ execPath ? resolve(dirname(execPath), "..", "manifest.json") : "",
25
+ resolve(moduleDir, "..", "package.json"),
26
+ resolve(moduleDir, "..", "..", "package.json"),
27
+ resolve(process.cwd(), "packages/cli/package.json")
28
+ ].filter(Boolean);
29
+ for (const candidate of candidates) {
30
+ if (!existsSync(candidate))
31
+ continue;
32
+ const parsed = JSON.parse(readFileSync(candidate, "utf-8"));
33
+ const candidateVersion = parsed.version?.trim();
34
+ if (candidateVersion) {
35
+ version = candidateVersion;
36
+ break;
37
+ }
38
+ }
39
+ } catch {}
40
+ }
41
+ return version || DEV_CLI_VERSION;
42
+ }
43
+ function isPublishedCliVersion(version) {
44
+ const normalized = version.trim();
45
+ return normalized.length > 0 && normalized !== SOURCE_CLI_VERSION && normalized !== DEV_CLI_VERSION;
46
+ }
47
+
48
+ // packages/cli-surface-plugin/src/rig-config-package-deps.ts
49
+ var REQUIRED_RIG_CONFIG_PACKAGE_NAMES = ["core", "standard-plugin"];
50
+ var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
51
+ var DEPENDENCY_SECTION_NAMES = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
52
+ var INSTALL_CHECK_SECTION_NAMES = ["dependencies", "devDependencies", "optionalDependencies"];
53
+ function hasRigConfig(projectRoot) {
54
+ const root = resolve2(projectRoot);
55
+ return RIG_CONFIG_FILENAMES.some((name) => existsSync2(join(root, name)));
56
+ }
57
+ function resolveRigConfigPackageVersion() {
58
+ const explicit = process.env.RIG_CONFIG_PACKAGE_VERSION?.trim();
59
+ if (explicit)
60
+ return explicit;
61
+ const installed = resolveInstalledCliVersion();
62
+ return isPublishedCliVersion(installed) ? installed : "latest";
63
+ }
64
+ function rigConfigDevDependencies() {
65
+ const version = resolveRigConfigPackageVersion();
66
+ return Object.fromEntries(REQUIRED_RIG_CONFIG_PACKAGE_NAMES.map((name) => [`@rig/${name}`, rigPackageSpec(name, version)]));
67
+ }
68
+ function readPackageManifest(path) {
69
+ if (!existsSync2(path))
70
+ return null;
71
+ return JSON.parse(readFileSync2(path, "utf8"));
72
+ }
73
+ function mutableDeps(manifest, key) {
74
+ const source = manifest[key];
75
+ return source && typeof source === "object" && !Array.isArray(source) ? { ...source } : {};
76
+ }
77
+ function rigPackageName(name) {
78
+ const match = name.match(/^@rig\/([^/]+)$/);
79
+ return match?.[1] ?? null;
80
+ }
81
+ function rigPackageNameFromSpecifier(specifier) {
82
+ const match = specifier.match(/^@rig\/([^/]+)/);
83
+ return match?.[1] ?? null;
84
+ }
85
+ function rigPackageSpec(packageName, version = resolveRigConfigPackageVersion()) {
86
+ return `npm:@h-rig/${packageName}@${version}`;
87
+ }
88
+ function mutableDependencySections(manifest) {
89
+ return Object.fromEntries(DEPENDENCY_SECTION_NAMES.map((section) => [section, mutableDeps(manifest, section)]));
90
+ }
91
+ function discoveredConfigRigSpecs(sections, packageNames) {
92
+ const version = resolveRigConfigPackageVersion();
93
+ const expected = {};
94
+ for (const section of DEPENDENCY_SECTION_NAMES) {
95
+ for (const name of Object.keys(sections[section])) {
96
+ const packageName = rigPackageName(name);
97
+ if (packageName && packageNames.has(packageName))
98
+ expected[name] = rigPackageSpec(packageName, version);
99
+ }
100
+ }
101
+ return expected;
102
+ }
103
+ function installedConfigDependencySpecs(sections, packageNames) {
104
+ const expected = {};
105
+ for (const section of INSTALL_CHECK_SECTION_NAMES) {
106
+ for (const [name, spec] of Object.entries(sections[section])) {
107
+ const packageName = rigPackageName(name);
108
+ if (packageName && packageNames.has(packageName) && typeof spec === "string")
109
+ expected[name] = spec;
110
+ }
111
+ }
112
+ return expected;
113
+ }
114
+ function hasFirstPartyRigDependency(manifest) {
115
+ const sections = mutableDependencySections(manifest);
116
+ return DEPENDENCY_SECTION_NAMES.some((section) => Object.keys(sections[section]).some((name) => rigPackageName(name) !== null));
117
+ }
118
+ function rigConfigImportPackageNames(projectRoot) {
119
+ const names = new Set;
120
+ for (const filename of RIG_CONFIG_FILENAMES) {
121
+ const path = join(projectRoot, filename);
122
+ if (!existsSync2(path))
123
+ continue;
124
+ const source = readFileSync2(path, "utf8");
125
+ const importPattern = /(?:from\s*|import\s*\(\s*|import\s*)["'](@rig\/[^"']+)["']/g;
126
+ for (const match of source.matchAll(importPattern)) {
127
+ const packageName = rigPackageNameFromSpecifier(match[1] ?? "");
128
+ if (packageName)
129
+ names.add(packageName);
130
+ }
131
+ }
132
+ return [...names];
133
+ }
134
+ function withRigConfigDeps(projectRoot, manifest, options) {
135
+ const configPackageNames = new Set(options.requiredConfigPackageNames);
136
+ const sections = mutableDependencySections(manifest);
137
+ let changed = false;
138
+ for (const [name, spec] of Object.entries(discoveredConfigRigSpecs(sections, configPackageNames))) {
139
+ for (const section of DEPENDENCY_SECTION_NAMES) {
140
+ if (!Object.prototype.hasOwnProperty.call(sections[section], name))
141
+ continue;
142
+ if (sections[section][name] !== spec) {
143
+ sections[section][name] = spec;
144
+ changed = true;
145
+ }
146
+ }
147
+ }
148
+ for (const packageName of options.requiredConfigPackageNames) {
149
+ const name = `@rig/${packageName}`;
150
+ const existsInInstallableSection = INSTALL_CHECK_SECTION_NAMES.some((section) => Object.prototype.hasOwnProperty.call(sections[section], name));
151
+ if (existsInInstallableSection)
152
+ continue;
153
+ sections.devDependencies[name] = rigPackageSpec(packageName);
154
+ changed = true;
155
+ }
156
+ const next = {
157
+ ...Object.keys(manifest).length > 0 ? manifest : { name: basename(projectRoot) || "rig-project", private: true }
158
+ };
159
+ for (const section of DEPENDENCY_SECTION_NAMES) {
160
+ if (Object.keys(sections[section]).length > 0)
161
+ next[section] = sections[section];
162
+ }
163
+ return { next, changed, expectedInstalled: installedConfigDependencySpecs(sections, configPackageNames) };
164
+ }
165
+ function expectedPublishedVersion(spec) {
166
+ const match = spec.match(/^npm:@h-rig\/[^@]+@(.+)$/);
167
+ if (!match)
168
+ return null;
169
+ return match[1] === "latest" ? null : match[1] ?? null;
170
+ }
171
+ function installedRigPackageHealthy(projectRoot, packageName, expectedSpec) {
172
+ const rigName = rigPackageName(packageName);
173
+ if (!rigName)
174
+ return true;
175
+ const manifest = readPackageManifest(join(projectRoot, "node_modules", "@rig", rigName, "package.json"));
176
+ if (!manifest)
177
+ return false;
178
+ const installedVersion = typeof manifest.version === "string" ? manifest.version.trim() : "";
179
+ const expectedVersion = expectedPublishedVersion(expectedSpec);
180
+ if (expectedVersion && installedVersion !== expectedVersion)
181
+ return false;
182
+ if (!installedVersion)
183
+ return false;
184
+ if (rigName === "core" || rigName === "standard-plugin") {
185
+ const exportsField = manifest.exports;
186
+ if (!exportsField || typeof exportsField !== "object" || Array.isArray(exportsField))
187
+ return false;
188
+ const exportsRecord = exportsField;
189
+ if (rigName === "core" && !("./config" in exportsRecord))
190
+ return false;
191
+ if (rigName === "standard-plugin" && !("./bundle" in exportsRecord))
192
+ return false;
193
+ }
194
+ return true;
195
+ }
196
+ function resolvePackageManagerBinary(manager) {
197
+ if (manager !== "bun")
198
+ return manager;
199
+ const candidates = [
200
+ Bun.which("bun") ?? "",
201
+ process.env.RIG_BUN_PATH?.trim() ?? "",
202
+ process.env.HOME ? join(process.env.HOME, ".bun", "bin", "bun") : "",
203
+ "/opt/homebrew/bin/bun",
204
+ "/usr/local/bin/bun",
205
+ "/usr/bin/bun"
206
+ ];
207
+ for (const candidate of candidates) {
208
+ if (candidate && existsSync2(candidate))
209
+ return candidate;
210
+ }
211
+ return "bun";
212
+ }
213
+ function installCommandFor(manifest) {
214
+ const packageManager = typeof manifest.packageManager === "string" ? manifest.packageManager.trim() : "";
215
+ const manager = packageManager.split("@")[0] || "bun";
216
+ switch (manager) {
217
+ case "npm":
218
+ return ["npm", "install", "--ignore-scripts"];
219
+ case "pnpm":
220
+ return ["pnpm", "install", "--ignore-scripts"];
221
+ case "yarn":
222
+ return ["yarn", "install", "--ignore-scripts"];
223
+ default:
224
+ return [resolvePackageManagerBinary("bun"), "install", "--ignore-scripts"];
225
+ }
226
+ }
227
+ function ensureRigConfigDependenciesInstalled(projectRoot) {
228
+ const root = resolve2(projectRoot);
229
+ const version = resolveRigConfigPackageVersion();
230
+ const manifestPath = join(root, "package.json");
231
+ const current = readPackageManifest(manifestPath);
232
+ const hasConfig = hasRigConfig(root);
233
+ if (!hasConfig && (!current || !hasFirstPartyRigDependency(current))) {
234
+ return { rewroteManifest: false, ranInstall: false, command: null, version };
235
+ }
236
+ const requiredConfigPackageNames = hasConfig ? [...new Set([...REQUIRED_RIG_CONFIG_PACKAGE_NAMES, ...rigConfigImportPackageNames(root)])] : [];
237
+ const { next, changed, expectedInstalled } = withRigConfigDeps(root, current ?? {}, { requiredConfigPackageNames });
238
+ const installNeeded = changed || Object.entries(expectedInstalled).some(([name, spec]) => !installedRigPackageHealthy(root, name, spec));
239
+ if (changed) {
240
+ writeFileSync(manifestPath, `${JSON.stringify(next, null, 2)}
241
+ `, "utf8");
242
+ }
243
+ if (!installNeeded) {
244
+ return { rewroteManifest: changed, ranInstall: false, command: null, version };
245
+ }
246
+ const command = installCommandFor(next);
247
+ const executable = command[0];
248
+ if (!executable)
249
+ throw new Error("Rig dependency preflight could not determine a package manager command.");
250
+ const result = spawnSync(executable, command.slice(1), {
251
+ cwd: root,
252
+ encoding: "utf8",
253
+ env: process.env
254
+ });
255
+ if (result.status !== 0) {
256
+ const detail = [
257
+ result.error ? String(result.error) : "",
258
+ `${result.stdout ?? ""}${result.stderr ?? ""}`.trim()
259
+ ].filter(Boolean).join(`
260
+ `);
261
+ throw new Error(`Rig dependency preflight failed in ${root}: ${command.join(" ")}${detail ? `
262
+ ${detail}` : ""}
263
+ Rig does not delete node_modules or lockfiles automatically; fix the repo/package-manager state explicitly if install recovery is needed.`.trim());
264
+ }
265
+ return { rewroteManifest: changed, ranInstall: true, command: command.join(" "), version };
266
+ }
267
+ export {
268
+ rigConfigDevDependencies,
269
+ resolveRigConfigPackageVersion,
270
+ hasRigConfig,
271
+ ensureRigConfigDependenciesInstalled
272
+ };
@@ -0,0 +1,47 @@
1
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
2
+ import type { PolicyMode } from "@rig/runtime/control-plane/runtime/guard-types";
3
+ import type { RunnerContext } from "@rig/runtime/control-plane/runtime/runner-context";
4
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
5
+ import type { CommandExecutionResult, OutputMode } from "@rig/runtime/control-plane/runtime/types";
6
+ export type { RunnerContext } from "@rig/runtime/control-plane/runtime/runner-context";
7
+ /**
8
+ * CLI-side error with an optional remediation hint. The hint is rendered on
9
+ * its own line as `Next: <hint>` (and carried in the --json error payload),
10
+ * so every failure names the next command to run. Extends the runtime
11
+ * CliError so `instanceof` checks against either class keep working.
12
+ */
13
+ export declare class CliError extends RuntimeCliError {
14
+ readonly hint?: string;
15
+ constructor(message: string, exitCode?: number, options?: {
16
+ readonly hint?: string;
17
+ });
18
+ }
19
+ export declare function withProjectRoot(projectRoot: string): void;
20
+ export declare function formatCommand(parts: string[]): string;
21
+ type AgentShellBuild = typeof buildBinary;
22
+ type AgentShellMaterializationOptions = {
23
+ readonly env?: Record<string, string | undefined>;
24
+ readonly cwd?: string;
25
+ readonly moduleDir?: string;
26
+ readonly build?: AgentShellBuild;
27
+ };
28
+ export declare function resolveAgentMaterializationSourceRoot(projectRoot: string, options?: AgentShellMaterializationOptions): string;
29
+ export declare function ensureAgentShellBinary(projectRoot: string, options?: AgentShellMaterializationOptions): Promise<string>;
30
+ export declare function initializeRuntime(options: {
31
+ projectRoot: string;
32
+ dryRun: boolean;
33
+ outputMode: OutputMode;
34
+ runId?: string;
35
+ policyMode?: PolicyMode;
36
+ }): Promise<RunnerContext>;
37
+ export declare function runCommand(context: RunnerContext, parts: string[]): Promise<CommandExecutionResult>;
38
+ export declare function takeFlag(args: string[], flag: string): {
39
+ value: boolean;
40
+ rest: string[];
41
+ };
42
+ export declare function takeOption(args: string[], option: string): {
43
+ value: string | undefined;
44
+ rest: string[];
45
+ };
46
+ export declare function requireNoExtraArgs(args: string[], usage: string): void;
47
+ export declare function requireTask(taskId: string | undefined, usage: string): string;
@@ -0,0 +1,267 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/runner.ts
3
+ var {$ } = globalThis.Bun;
4
+ import { existsSync, mkdirSync } from "fs";
5
+ import { resolve } from "path";
6
+ import { EventBus } from "@rig/runtime/control-plane/runtime/events";
7
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
8
+ import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
9
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
10
+
11
+ class CliError extends RuntimeCliError {
12
+ hint;
13
+ constructor(message, exitCode = 1, options = {}) {
14
+ super(message, exitCode);
15
+ if (options.hint?.trim()) {
16
+ this.hint = options.hint.trim();
17
+ }
18
+ }
19
+ }
20
+ function withProjectRoot(projectRoot) {
21
+ $.cwd(projectRoot);
22
+ }
23
+ function formatCommand(parts) {
24
+ return parts.map((part) => /[^a-zA-Z0-9_./:-]/.test(part) ? JSON.stringify(part) : part).join(" ");
25
+ }
26
+ var AGENT_DISPATCH_SOURCE = "packages/runtime/bin/rig-agent-dispatch.ts";
27
+ function hasAgentDispatchSource(root) {
28
+ return existsSync(resolve(root, AGENT_DISPATCH_SOURCE));
29
+ }
30
+ function resolveAgentMaterializationSourceRoot(projectRoot, options = {}) {
31
+ const env = options.env ?? process.env;
32
+ const candidates = [
33
+ env.RIG_HOST_PROJECT_ROOT?.trim(),
34
+ env.PROJECT_RIG_ROOT?.trim(),
35
+ options.cwd ?? process.cwd(),
36
+ resolve(options.moduleDir ?? import.meta.dir, "../../.."),
37
+ projectRoot
38
+ ].filter((value) => Boolean(value));
39
+ for (const candidate of candidates) {
40
+ const root = resolve(candidate);
41
+ if (hasAgentDispatchSource(root)) {
42
+ return root;
43
+ }
44
+ }
45
+ return resolve(projectRoot);
46
+ }
47
+ async function ensureAgentShellBinary(projectRoot, options = {}) {
48
+ const agentBinary = resolve(projectRoot, ".rig", "bin", "rig-agent");
49
+ if (existsSync(agentBinary)) {
50
+ return agentBinary;
51
+ }
52
+ const sourceRoot = resolveAgentMaterializationSourceRoot(projectRoot, options);
53
+ if (!hasAgentDispatchSource(sourceRoot)) {
54
+ throw new CliError(`Missing compiled agent dispatch binary at ${agentBinary}, and no Rig source checkout with ${AGENT_DISPATCH_SOURCE} was found to materialize it automatically.`, 2);
55
+ }
56
+ mkdirSync(resolve(agentBinary, ".."), { recursive: true });
57
+ try {
58
+ await (options.build ?? buildBinary)(AGENT_DISPATCH_SOURCE, agentBinary, sourceRoot, {
59
+ AGENT_PROJECT_ROOT: projectRoot
60
+ });
61
+ } catch (error) {
62
+ throw new CliError(`Missing compiled agent dispatch binary at ${agentBinary}, and automatic materialization from ${sourceRoot} failed: ${error instanceof Error ? error.message : String(error)}`, 2);
63
+ }
64
+ if (!existsSync(agentBinary)) {
65
+ throw new CliError(`Automatic agent dispatch materialization from ${sourceRoot} did not create ${agentBinary}.`, 2);
66
+ }
67
+ return agentBinary;
68
+ }
69
+ async function initializeRuntime(options) {
70
+ const eventBus = new EventBus({ projectRoot: options.projectRoot, runId: options.runId });
71
+ const context = {
72
+ projectRoot: options.projectRoot,
73
+ dryRun: options.dryRun,
74
+ outputMode: options.outputMode,
75
+ runId: eventBus.getRunId(),
76
+ policyMode: options.policyMode,
77
+ eventBus,
78
+ emitEvent: async (type, payload) => {
79
+ await eventBus.emit(type, payload);
80
+ }
81
+ };
82
+ context.runCommand = async (parts) => runCommand(context, parts);
83
+ await context.emitEvent("runtime.init", {
84
+ runId: context.runId,
85
+ outputMode: context.outputMode,
86
+ dryRun: context.dryRun,
87
+ policyMode: context.policyMode ?? loadPolicy(options.projectRoot).mode,
88
+ policyFile: resolve(options.projectRoot, "rig/policy/policy.json")
89
+ });
90
+ return context;
91
+ }
92
+ async function runCommand(context, parts) {
93
+ if (parts.length === 0) {
94
+ throw new CliError("Cannot execute an empty command.");
95
+ }
96
+ const envMode = process.env.RIG_BASH_MODE;
97
+ const effectiveMode = context.policyMode || (envMode === "off" || envMode === "observe" || envMode === "enforce" ? envMode : loadPolicy(context.projectRoot).mode);
98
+ const controlledPath = `${resolve(context.projectRoot, ".rig", "bin")}:${context.projectRoot}/rig/tools:${process.env.PATH ?? ""}`;
99
+ const usesInfrastructureBinary = parts[0] === "rig-server";
100
+ const controlledBash = usesInfrastructureBinary ? null : await ensureAgentShellBinary(context.projectRoot);
101
+ const commandEnv = [
102
+ "env",
103
+ `PATH=${controlledPath}`,
104
+ `PROJECT_RIG_ROOT=${context.projectRoot}`,
105
+ ...controlledBash ? [`BASH=${controlledBash}`] : [],
106
+ `RIG_BASH_MODE=${effectiveMode}`,
107
+ `RIG_POLICY_FILE=${resolve(context.projectRoot, "rig/policy/policy.json")}`,
108
+ ...context.eventBus.getEventsFile() ? [`RIG_EVENTS_FILE=${context.eventBus.getEventsFile()}`] : []
109
+ ];
110
+ const commandWithEnv = [...commandEnv, ...parts];
111
+ const formatted = formatCommand(commandWithEnv);
112
+ await context.emitEvent("command.received", {
113
+ command: commandWithEnv,
114
+ formattedCommand: formatted
115
+ });
116
+ const guardDecision = evaluate({
117
+ projectRoot: context.projectRoot,
118
+ evaluation: { type: "command", command: formatted }
119
+ });
120
+ const guardAction = resolveAction(effectiveMode, guardDecision.matchedRules);
121
+ await context.emitEvent("policy.decision", {
122
+ target: "command",
123
+ command: formatted,
124
+ mode: effectiveMode,
125
+ allowed: guardAction !== "block",
126
+ matchedRuleIds: guardDecision.matchedRules.map((r) => r.id),
127
+ reasons: guardDecision.matchedRules.map((r) => r.reason)
128
+ });
129
+ if (guardAction === "block") {
130
+ await context.emitEvent("command.failed", {
131
+ command: commandWithEnv,
132
+ formattedCommand: formatted,
133
+ reason: "Policy denied command",
134
+ matchedRuleIds: guardDecision.matchedRules.map((r) => r.id),
135
+ mode: effectiveMode
136
+ });
137
+ throw new CliError(`Policy blocked command: ${formatted}`, 126, { hint: "Review rig/policy/policy.json, or re-run with `--policy-mode observe` to log instead of block." });
138
+ }
139
+ const startedAt = new Date;
140
+ await context.emitEvent("command.started", {
141
+ command: commandWithEnv,
142
+ formattedCommand: formatted,
143
+ startedAt: startedAt.toISOString(),
144
+ dryRun: context.dryRun
145
+ });
146
+ if (context.dryRun) {
147
+ const dryResult = {
148
+ command: commandWithEnv,
149
+ formattedCommand: formatted,
150
+ exitCode: 0,
151
+ durationMs: 0,
152
+ startedAt: startedAt.toISOString(),
153
+ finishedAt: startedAt.toISOString()
154
+ };
155
+ if (context.outputMode === "text") {
156
+ console.log(`$ ${formatted}`);
157
+ }
158
+ await context.emitEvent("command.finished", {
159
+ ...dryResult,
160
+ dryRun: true
161
+ });
162
+ return dryResult;
163
+ }
164
+ let exitCode = 0;
165
+ let stdout = "";
166
+ let stderr = "";
167
+ if (context.outputMode === "json") {
168
+ const child = Bun.spawn(commandWithEnv, {
169
+ cwd: context.projectRoot,
170
+ stdin: "inherit",
171
+ stdout: "pipe",
172
+ stderr: "pipe"
173
+ });
174
+ exitCode = await child.exited;
175
+ stdout = await new Response(child.stdout).text();
176
+ stderr = await new Response(child.stderr).text();
177
+ } else {
178
+ const child = Bun.spawn(commandWithEnv, {
179
+ cwd: context.projectRoot,
180
+ stdin: "inherit",
181
+ stdout: "inherit",
182
+ stderr: "inherit"
183
+ });
184
+ exitCode = await child.exited;
185
+ }
186
+ const finishedAt = new Date;
187
+ const result = {
188
+ command: commandWithEnv,
189
+ formattedCommand: formatted,
190
+ exitCode,
191
+ durationMs: finishedAt.getTime() - startedAt.getTime(),
192
+ startedAt: startedAt.toISOString(),
193
+ finishedAt: finishedAt.toISOString(),
194
+ stdout: context.outputMode === "json" ? stdout : undefined,
195
+ stderr: context.outputMode === "json" ? stderr : undefined
196
+ };
197
+ if (exitCode !== 0) {
198
+ await context.emitEvent("command.failed", {
199
+ ...result
200
+ });
201
+ const errorSuffix = context.outputMode === "json" && stderr ? `
202
+ ${stderr.trim()}` : "";
203
+ throw new CliError(`Command failed (${exitCode}): ${formatted}${errorSuffix}`, exitCode);
204
+ }
205
+ await context.emitEvent("command.finished", {
206
+ ...result
207
+ });
208
+ return result;
209
+ }
210
+ function takeFlag(args, flag) {
211
+ const rest = [];
212
+ let value = false;
213
+ for (const arg of args) {
214
+ if (arg === flag) {
215
+ value = true;
216
+ continue;
217
+ }
218
+ rest.push(arg);
219
+ }
220
+ return { value, rest };
221
+ }
222
+ function takeOption(args, option) {
223
+ const rest = [];
224
+ let value;
225
+ for (let index = 0;index < args.length; index += 1) {
226
+ const current = args[index];
227
+ if (current === option) {
228
+ const next = args[index + 1];
229
+ if (!next || next.startsWith("-")) {
230
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
231
+ }
232
+ value = next;
233
+ index += 1;
234
+ continue;
235
+ }
236
+ if (current !== undefined) {
237
+ rest.push(current);
238
+ }
239
+ }
240
+ return { value, rest };
241
+ }
242
+ function requireNoExtraArgs(args, usage) {
243
+ if (args.length > 0) {
244
+ throw new CliError(`Unexpected arguments: ${args.join(" ")}
245
+ Usage: ${usage}`);
246
+ }
247
+ }
248
+ function requireTask(taskId, usage) {
249
+ if (!taskId) {
250
+ throw new CliError(`Missing --task option.
251
+ Usage: ${usage}`);
252
+ }
253
+ return taskId;
254
+ }
255
+ export {
256
+ withProjectRoot,
257
+ takeOption,
258
+ takeFlag,
259
+ runCommand,
260
+ resolveAgentMaterializationSourceRoot,
261
+ requireTask,
262
+ requireNoExtraArgs,
263
+ initializeRuntime,
264
+ formatCommand,
265
+ ensureAgentShellBinary,
266
+ CliError
267
+ };
@@ -0,0 +1,8 @@
1
+ export declare const SOURCE_CLI_VERSION = "0.0.0-alpha.1";
2
+ export declare const DEV_CLI_VERSION = "0.0.0-dev";
3
+ /**
4
+ * Resolve the CLI version no matter how the command was launched:
5
+ * compiled binary, dist artifact, npm JS bin, or source checkout.
6
+ */
7
+ export declare function resolveInstalledCliVersion(): string;
8
+ export declare function isPublishedCliVersion(version: string): boolean;
@@ -0,0 +1,47 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/version.ts
3
+ import { existsSync, readFileSync } from "fs";
4
+ import { dirname, resolve } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { readBuildConfig } from "@rig/runtime/build-time-config";
7
+ var SOURCE_CLI_VERSION = "0.0.0-alpha.1";
8
+ var DEV_CLI_VERSION = "0.0.0-dev";
9
+ function resolveInstalledCliVersion() {
10
+ const buildConfig = readBuildConfig();
11
+ const envVersion = process.env.RIG_CLI_VERSION?.trim();
12
+ const buildVersion = buildConfig.RIG_CLI_VERSION?.trim();
13
+ let version = envVersion || buildVersion || "";
14
+ if (!version) {
15
+ try {
16
+ const execPath = process.execPath || "";
17
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
18
+ const candidates = [
19
+ execPath ? resolve(dirname(execPath), "..", "manifest.json") : "",
20
+ resolve(moduleDir, "..", "package.json"),
21
+ resolve(moduleDir, "..", "..", "package.json"),
22
+ resolve(process.cwd(), "packages/cli/package.json")
23
+ ].filter(Boolean);
24
+ for (const candidate of candidates) {
25
+ if (!existsSync(candidate))
26
+ continue;
27
+ const parsed = JSON.parse(readFileSync(candidate, "utf-8"));
28
+ const candidateVersion = parsed.version?.trim();
29
+ if (candidateVersion) {
30
+ version = candidateVersion;
31
+ break;
32
+ }
33
+ }
34
+ } catch {}
35
+ }
36
+ return version || DEV_CLI_VERSION;
37
+ }
38
+ function isPublishedCliVersion(version) {
39
+ const normalized = version.trim();
40
+ return normalized.length > 0 && normalized !== SOURCE_CLI_VERSION && normalized !== DEV_CLI_VERSION;
41
+ }
42
+ export {
43
+ resolveInstalledCliVersion,
44
+ isPublishedCliVersion,
45
+ SOURCE_CLI_VERSION,
46
+ DEV_CLI_VERSION
47
+ };
@@ -0,0 +1,2 @@
1
+ export declare function withMutedConsole<T>(mute: boolean, fn: () => Promise<T>): Promise<T>;
2
+ export declare function withMutedConsole<T>(mute: boolean, fn: () => T): T;