@h-rig/core 0.0.6-alpha.17 → 0.0.6-alpha.170
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.
- package/dist/src/agent-role-registry.d.ts +4 -0
- package/dist/src/agent-role-registry.js +27 -0
- package/dist/src/authority-paths.d.ts +15 -0
- package/dist/src/authority-paths.js +80 -0
- package/dist/src/baked-secrets.d.ts +6 -0
- package/dist/src/baked-secrets.js +121 -0
- package/dist/src/build-time-config.d.ts +12 -0
- package/dist/src/build-time-config.js +25 -0
- package/dist/src/build-time-config.macro.d.ts +1 -0
- package/dist/src/capability-loaders.d.ts +51 -0
- package/dist/src/capability-loaders.js +758 -0
- package/dist/src/capability.d.ts +79 -0
- package/dist/src/capability.js +63 -0
- package/dist/src/checkout-root.d.ts +1 -0
- package/dist/src/checkout-root.js +30 -0
- package/dist/src/config-env.d.ts +4 -0
- package/dist/src/config-env.js +23 -0
- package/dist/src/config.d.ts +3 -0
- package/dist/src/config.js +44 -0
- package/dist/src/declarative-config.d.ts +14 -0
- package/dist/src/declarative-config.js +82 -0
- package/dist/src/default-kernel.d.ts +1 -0
- package/dist/src/default-kernel.js +12 -0
- package/dist/src/define-config.d.ts +20 -0
- package/dist/src/define-config.js +28 -15
- package/dist/src/define-plugin.d.ts +13 -0
- package/dist/src/define-plugin.js +4 -43
- package/dist/src/embedded-plugins.d.ts +59 -0
- package/dist/src/embedded-plugins.js +22 -0
- package/dist/src/exec.d.ts +13 -0
- package/dist/src/exec.js +101 -0
- package/dist/src/harness-paths.d.ts +18 -0
- package/dist/src/harness-paths.js +141 -0
- package/dist/src/hook-materializer.d.ts +72 -0
- package/dist/src/hook-materializer.js +281 -0
- package/dist/src/hook-protocol.d.ts +2 -0
- package/dist/src/hook-protocol.js +462 -0
- package/dist/src/hook-runner.d.ts +48 -0
- package/dist/src/hook-runner.js +756 -0
- package/dist/src/hook-runtime.d.ts +52 -0
- package/dist/src/hook-runtime.js +462 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +210 -2499
- package/dist/src/json-files.d.ts +9 -0
- package/dist/src/json-files.js +125 -0
- package/dist/src/kernel-boot.d.ts +2 -0
- package/dist/src/kernel-boot.js +10 -0
- package/dist/src/kernel-entrypoint.d.ts +22 -0
- package/dist/src/kernel-entrypoint.js +548 -0
- package/dist/src/kernel-plugin-abi.d.ts +1 -0
- package/dist/src/kernel-plugin-abi.js +1 -0
- package/dist/src/kernel-resolver.d.ts +2 -0
- package/dist/src/kernel-resolver.js +6 -0
- package/dist/src/layout.d.ts +10 -0
- package/dist/src/layout.js +144 -0
- package/dist/src/load-config.d.ts +2 -0
- package/dist/src/load-config.js +423 -30
- package/dist/src/placement.d.ts +50 -0
- package/dist/src/placement.js +996 -0
- package/dist/src/plugin-host-context.d.ts +66 -0
- package/dist/src/plugin-host-context.js +1292 -0
- package/dist/src/plugin-host-registries.d.ts +31 -0
- package/dist/src/plugin-host-registries.js +79 -0
- package/dist/src/plugin-host.d.ts +77 -0
- package/dist/src/plugin-host.js +127 -63
- package/dist/src/plugin-runtime.d.ts +173 -0
- package/dist/src/profile-ops.d.ts +9 -0
- package/dist/src/profile-ops.js +252 -0
- package/dist/src/project-plugins.d.ts +63 -0
- package/dist/src/project-plugins.js +793 -0
- package/dist/src/remote-config.d.ts +183 -0
- package/dist/src/remote-config.js +574 -0
- package/dist/src/root-resolver.d.ts +5 -0
- package/dist/src/root-resolver.js +69 -0
- package/dist/src/run-provisioning.d.ts +58 -0
- package/dist/src/run-provisioning.js +128 -0
- package/dist/src/runtime-context.d.ts +20 -0
- package/dist/src/runtime-context.js +257 -0
- package/dist/src/runtime-events.d.ts +44 -0
- package/dist/src/runtime-events.js +212 -0
- package/dist/src/runtime-overlay.d.ts +11 -0
- package/dist/src/runtime-overlay.js +71 -0
- package/dist/src/runtime-paths.d.ts +21 -0
- package/dist/src/runtime-paths.js +181 -0
- package/dist/src/runtime-provisioning-env.d.ts +5 -0
- package/dist/src/runtime-provisioning-env.js +217 -0
- package/dist/src/runtime-runner-context.d.ts +12 -0
- package/dist/src/runtime-runner-context.js +1 -0
- package/dist/src/safe-identifiers.d.ts +44 -0
- package/dist/src/safe-identifiers.js +96 -0
- package/dist/src/scope-rules.d.ts +4 -0
- package/dist/src/scope-rules.js +21 -0
- package/dist/src/server-paths.d.ts +26 -0
- package/dist/src/server-paths.js +308 -0
- package/dist/src/setup-version.d.ts +3 -0
- package/dist/src/setup-version.js +14 -0
- package/dist/src/task-record-reader.d.ts +3 -0
- package/dist/src/task-record-reader.js +9 -0
- package/dist/src/validator-registry.d.ts +27 -0
- package/dist/src/validator-registry.js +64 -0
- package/package.json +166 -10
- package/dist/src/engineReadModelReducer.js +0 -1780
- package/dist/src/rig-init-builder.js +0 -57
- package/dist/src/rigSelectors.js +0 -293
- package/dist/src/taskGraph.js +0 -64
- package/dist/src/taskGraphCodes.js +0 -26
- package/dist/src/taskGraphLayout.js +0 -374
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/core/src/runtime-events.ts
|
|
3
|
+
import { appendFile, mkdir } from "fs/promises";
|
|
4
|
+
import { randomUUID } from "crypto";
|
|
5
|
+
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
6
|
+
|
|
7
|
+
// packages/core/src/layout.ts
|
|
8
|
+
import { resolve as resolve2 } from "path";
|
|
9
|
+
import {
|
|
10
|
+
RIG_ARTIFACTS_DIRNAME,
|
|
11
|
+
RIG_DEFINITION_DIRNAME,
|
|
12
|
+
RIG_STATE_DIRNAME
|
|
13
|
+
} from "@rig/contracts";
|
|
14
|
+
|
|
15
|
+
// packages/core/src/checkout-root.ts
|
|
16
|
+
import { dirname, resolve } from "path";
|
|
17
|
+
import { existsSync } from "fs";
|
|
18
|
+
function findNearestGitCheckoutRoot(startDir) {
|
|
19
|
+
let current = resolve(startDir);
|
|
20
|
+
for (;; ) {
|
|
21
|
+
if (existsSync(resolve(current, ".git")))
|
|
22
|
+
return current;
|
|
23
|
+
const parent = dirname(current);
|
|
24
|
+
if (parent === current)
|
|
25
|
+
return null;
|
|
26
|
+
current = parent;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function resolveCheckoutRoot(projectRoot) {
|
|
30
|
+
const normalizedProjectRoot = resolve(projectRoot);
|
|
31
|
+
const explicit = process.env.MONOREPO_ROOT?.trim();
|
|
32
|
+
if (explicit) {
|
|
33
|
+
const explicitRoot = resolve(explicit);
|
|
34
|
+
const gitRoot = findNearestGitCheckoutRoot(explicitRoot);
|
|
35
|
+
if (gitRoot)
|
|
36
|
+
return gitRoot;
|
|
37
|
+
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there or above it.`);
|
|
38
|
+
}
|
|
39
|
+
return findNearestGitCheckoutRoot(normalizedProjectRoot) ?? normalizedProjectRoot;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// packages/core/src/layout.ts
|
|
43
|
+
var resolveMonorepoRoot = resolveCheckoutRoot;
|
|
44
|
+
function resolveRuntimeWorkspaceLayout(workspaceDir) {
|
|
45
|
+
const root = resolve2(workspaceDir);
|
|
46
|
+
const rigRoot = resolve2(root, ".rig");
|
|
47
|
+
const logsDir = resolve2(rigRoot, "logs");
|
|
48
|
+
const stateDir = resolve2(rigRoot, "state");
|
|
49
|
+
const runtimeDir = resolve2(rigRoot, "runtime");
|
|
50
|
+
const binDir = resolve2(rigRoot, "bin");
|
|
51
|
+
return {
|
|
52
|
+
workspaceDir: root,
|
|
53
|
+
rigRoot,
|
|
54
|
+
stateDir,
|
|
55
|
+
logsDir,
|
|
56
|
+
artifactsRoot: resolve2(root, RIG_ARTIFACTS_DIRNAME),
|
|
57
|
+
runtimeDir,
|
|
58
|
+
homeDir: resolve2(rigRoot, "home"),
|
|
59
|
+
tmpDir: resolve2(rigRoot, "tmp"),
|
|
60
|
+
cacheDir: resolve2(rigRoot, "cache"),
|
|
61
|
+
sessionDir: resolve2(rigRoot, "session"),
|
|
62
|
+
binDir,
|
|
63
|
+
distDir: resolve2(rigRoot, "dist"),
|
|
64
|
+
pluginBinDir: resolve2(binDir, "plugins"),
|
|
65
|
+
contextPath: resolve2(rigRoot, "runtime-context.json"),
|
|
66
|
+
controlPlaneEventsFile: resolve2(logsDir, "control-plane.events.jsonl")
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function resolveActiveRuntimeWorkspaceRoot(_monorepoRoot) {
|
|
70
|
+
const explicit = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
71
|
+
if (!explicit) {
|
|
72
|
+
throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
|
|
73
|
+
}
|
|
74
|
+
return resolve2(explicit);
|
|
75
|
+
}
|
|
76
|
+
function resolveRigLayout(projectRoot) {
|
|
77
|
+
const monorepoRoot = resolveMonorepoRoot(projectRoot);
|
|
78
|
+
const definitionRoot = resolve2(projectRoot, RIG_DEFINITION_DIRNAME);
|
|
79
|
+
const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
|
|
80
|
+
const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
|
|
81
|
+
const policyDir = resolve2(definitionRoot, "policy");
|
|
82
|
+
return {
|
|
83
|
+
projectRoot,
|
|
84
|
+
monorepoRoot,
|
|
85
|
+
definitionRoot,
|
|
86
|
+
runtimeWorkspaceRoot,
|
|
87
|
+
stateRoot: runtimeLayout.rigRoot,
|
|
88
|
+
artifactsRoot: runtimeLayout.artifactsRoot,
|
|
89
|
+
configPath: resolve2(definitionRoot, "config.sh"),
|
|
90
|
+
taskConfigPath: resolve2(runtimeWorkspaceRoot, ".rig", "task-config.json"),
|
|
91
|
+
policyDir,
|
|
92
|
+
policyFile: resolve2(policyDir, "policy.json"),
|
|
93
|
+
pluginsDir: resolve2(definitionRoot, "plugins"),
|
|
94
|
+
hooksDir: resolve2(definitionRoot, "hooks"),
|
|
95
|
+
toolsDir: resolve2(definitionRoot, "tools"),
|
|
96
|
+
templatesDir: resolve2(definitionRoot, "templates"),
|
|
97
|
+
validationDir: resolve2(definitionRoot, "validation"),
|
|
98
|
+
stateDir: runtimeLayout.stateDir,
|
|
99
|
+
logsDir: runtimeLayout.logsDir,
|
|
100
|
+
notificationsDir: resolve2(definitionRoot, "notifications"),
|
|
101
|
+
runtimeDir: runtimeLayout.runtimeDir,
|
|
102
|
+
distDir: runtimeLayout.distDir,
|
|
103
|
+
binDir: runtimeLayout.binDir,
|
|
104
|
+
pluginBinDir: runtimeLayout.pluginBinDir,
|
|
105
|
+
keybindingsPath: resolve2(definitionRoot, "keybindings.json"),
|
|
106
|
+
controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// packages/core/src/runtime-events.ts
|
|
111
|
+
async function appendEvent(eventsFile, event) {
|
|
112
|
+
await mkdir(dirname2(eventsFile), { recursive: true });
|
|
113
|
+
await appendFile(eventsFile, `${JSON.stringify(event)}
|
|
114
|
+
`, "utf-8");
|
|
115
|
+
}
|
|
116
|
+
function createEvent(runId, type, payload) {
|
|
117
|
+
return {
|
|
118
|
+
id: randomUUID(),
|
|
119
|
+
runId,
|
|
120
|
+
timestamp: new Date().toISOString(),
|
|
121
|
+
type,
|
|
122
|
+
payload
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
class RuntimeEventBus {
|
|
127
|
+
runId;
|
|
128
|
+
eventsFile;
|
|
129
|
+
memoryEvents = [];
|
|
130
|
+
constructor(options) {
|
|
131
|
+
this.runId = options.runId || randomUUID();
|
|
132
|
+
this.eventsFile = options.eventsFile ?? resolveRigLayout(options.projectRoot).controlPlaneEventsFile;
|
|
133
|
+
}
|
|
134
|
+
getRunId() {
|
|
135
|
+
return this.runId;
|
|
136
|
+
}
|
|
137
|
+
getEventsFile() {
|
|
138
|
+
return this.eventsFile;
|
|
139
|
+
}
|
|
140
|
+
getMemoryEvents() {
|
|
141
|
+
return [...this.memoryEvents];
|
|
142
|
+
}
|
|
143
|
+
async attachRuntimeBus(runtimeBus) {
|
|
144
|
+
if (runtimeBus.getEventsFile() === this.eventsFile) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
for (const event of this.memoryEvents) {
|
|
148
|
+
await runtimeBus.ingest(event);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async attachRuntimeWorkspace(projectRoot) {
|
|
152
|
+
const runtimeBus = new RuntimeEventBus({ projectRoot, runId: this.runId });
|
|
153
|
+
await this.attachRuntimeBus(runtimeBus);
|
|
154
|
+
return runtimeBus;
|
|
155
|
+
}
|
|
156
|
+
async ingest(event) {
|
|
157
|
+
this.memoryEvents.push(event);
|
|
158
|
+
await appendEvent(this.eventsFile, event);
|
|
159
|
+
}
|
|
160
|
+
async emit(type, payload) {
|
|
161
|
+
const event = createEvent(this.runId, type, payload);
|
|
162
|
+
await this.ingest(event);
|
|
163
|
+
return event;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
class GeneralCliEventBus {
|
|
168
|
+
runId;
|
|
169
|
+
eventsFile;
|
|
170
|
+
memoryEvents = [];
|
|
171
|
+
runtimeBuses = new Map;
|
|
172
|
+
constructor(options) {
|
|
173
|
+
this.runId = options.runId || randomUUID();
|
|
174
|
+
this.eventsFile = options.eventsFile ?? resolve3(options.projectRoot, ".rig", "logs", "control-plane.events.jsonl");
|
|
175
|
+
}
|
|
176
|
+
getRunId() {
|
|
177
|
+
return this.runId;
|
|
178
|
+
}
|
|
179
|
+
getEventsFile() {
|
|
180
|
+
return this.eventsFile;
|
|
181
|
+
}
|
|
182
|
+
getMemoryEvents() {
|
|
183
|
+
return [...this.memoryEvents];
|
|
184
|
+
}
|
|
185
|
+
async attachRuntimeBus(runtimeBus) {
|
|
186
|
+
const key = runtimeBus.getEventsFile();
|
|
187
|
+
if (this.runtimeBuses.has(key)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
this.runtimeBuses.set(key, runtimeBus);
|
|
191
|
+
for (const event of this.memoryEvents) {
|
|
192
|
+
await runtimeBus.ingest(event);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async attachRuntimeWorkspace(projectRoot) {
|
|
196
|
+
const runtimeBus = new RuntimeEventBus({ projectRoot, runId: this.runId });
|
|
197
|
+
await this.attachRuntimeBus(runtimeBus);
|
|
198
|
+
return runtimeBus;
|
|
199
|
+
}
|
|
200
|
+
async emit(type, payload) {
|
|
201
|
+
const event = createEvent(this.runId, type, payload);
|
|
202
|
+
this.memoryEvents.push(event);
|
|
203
|
+
await appendEvent(this.eventsFile, event);
|
|
204
|
+
await Promise.all(Array.from(this.runtimeBuses.values()).map((bus) => bus.ingest(event)));
|
|
205
|
+
return event;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export {
|
|
209
|
+
RuntimeEventBus,
|
|
210
|
+
GeneralCliEventBus,
|
|
211
|
+
GeneralCliEventBus as EventBus
|
|
212
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type RuntimeOverlay = {
|
|
2
|
+
rootDir: string;
|
|
3
|
+
homeDir: string;
|
|
4
|
+
tmpDir: string;
|
|
5
|
+
cacheDir: string;
|
|
6
|
+
logsDir: string;
|
|
7
|
+
stateDir: string;
|
|
8
|
+
sessionDir: string;
|
|
9
|
+
contextPath: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function ensureRuntimeOverlay(projectRoot: string, runtimeId: string, workspaceDir?: string): RuntimeOverlay;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/core/src/runtime-overlay.ts
|
|
3
|
+
import { mkdirSync } from "fs";
|
|
4
|
+
|
|
5
|
+
// packages/core/src/layout.ts
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
import {
|
|
8
|
+
RIG_ARTIFACTS_DIRNAME,
|
|
9
|
+
RIG_DEFINITION_DIRNAME,
|
|
10
|
+
RIG_STATE_DIRNAME
|
|
11
|
+
} from "@rig/contracts";
|
|
12
|
+
function resolveRuntimeWorkspaceLayout(workspaceDir) {
|
|
13
|
+
const root = resolve(workspaceDir);
|
|
14
|
+
const rigRoot = resolve(root, ".rig");
|
|
15
|
+
const logsDir = resolve(rigRoot, "logs");
|
|
16
|
+
const stateDir = resolve(rigRoot, "state");
|
|
17
|
+
const runtimeDir = resolve(rigRoot, "runtime");
|
|
18
|
+
const binDir = resolve(rigRoot, "bin");
|
|
19
|
+
return {
|
|
20
|
+
workspaceDir: root,
|
|
21
|
+
rigRoot,
|
|
22
|
+
stateDir,
|
|
23
|
+
logsDir,
|
|
24
|
+
artifactsRoot: resolve(root, RIG_ARTIFACTS_DIRNAME),
|
|
25
|
+
runtimeDir,
|
|
26
|
+
homeDir: resolve(rigRoot, "home"),
|
|
27
|
+
tmpDir: resolve(rigRoot, "tmp"),
|
|
28
|
+
cacheDir: resolve(rigRoot, "cache"),
|
|
29
|
+
sessionDir: resolve(rigRoot, "session"),
|
|
30
|
+
binDir,
|
|
31
|
+
distDir: resolve(rigRoot, "dist"),
|
|
32
|
+
pluginBinDir: resolve(binDir, "plugins"),
|
|
33
|
+
contextPath: resolve(rigRoot, "runtime-context.json"),
|
|
34
|
+
controlPlaneEventsFile: resolve(logsDir, "control-plane.events.jsonl")
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// packages/core/src/runtime-overlay.ts
|
|
39
|
+
function ensureRuntimeOverlay(projectRoot, runtimeId, workspaceDir) {
|
|
40
|
+
const layout = resolveRuntimeWorkspaceLayout(workspaceDir ?? projectRoot);
|
|
41
|
+
const rootDir = layout.rigRoot;
|
|
42
|
+
const homeDir = layout.homeDir;
|
|
43
|
+
const tmpDir = layout.tmpDir;
|
|
44
|
+
const cacheDir = layout.cacheDir;
|
|
45
|
+
const logsDir = layout.logsDir;
|
|
46
|
+
const stateDir = layout.stateDir;
|
|
47
|
+
const sessionDir = layout.sessionDir;
|
|
48
|
+
const runtimeDir = layout.runtimeDir;
|
|
49
|
+
const contextPath = layout.contextPath;
|
|
50
|
+
mkdirSync(rootDir, { recursive: true });
|
|
51
|
+
mkdirSync(homeDir, { recursive: true });
|
|
52
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
53
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
54
|
+
mkdirSync(logsDir, { recursive: true });
|
|
55
|
+
mkdirSync(stateDir, { recursive: true });
|
|
56
|
+
mkdirSync(sessionDir, { recursive: true });
|
|
57
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
58
|
+
return {
|
|
59
|
+
rootDir,
|
|
60
|
+
homeDir,
|
|
61
|
+
tmpDir,
|
|
62
|
+
cacheDir,
|
|
63
|
+
logsDir,
|
|
64
|
+
stateDir,
|
|
65
|
+
sessionDir,
|
|
66
|
+
contextPath
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
ensureRuntimeOverlay
|
|
71
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the real Bun binary path.
|
|
3
|
+
*
|
|
4
|
+
* Runtime PATH often starts with `.rig/bin`, where `bun` is our injected
|
|
5
|
+
* gateway symlink. That path is not a real Bun install and cannot be used to
|
|
6
|
+
* derive `${bunDir}/bin`, so skip it and fall back to a host Bun binary.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveBunBinaryPath(): string;
|
|
9
|
+
/** Resolve the real Claude CLI binary path. */
|
|
10
|
+
export declare function resolveClaudeBinaryPath(): string;
|
|
11
|
+
/** Resolve the bun install root directory (parent-of-parent of the bun binary). */
|
|
12
|
+
export declare function resolveBunInstallDir(bunBinaryPath?: string): string;
|
|
13
|
+
/** Resolve the claude CLI install directory (parent of the real claude binary). */
|
|
14
|
+
export declare function resolveClaudeInstallDir(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the Node.js install root directory.
|
|
17
|
+
* Prefers `RIG_NODE_BIN` env var, then NVM, then PATH lookup.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveNodeInstallDir(): string | null;
|
|
20
|
+
/** Resolve additional dependency roots sandbox backends need to bind-mount. */
|
|
21
|
+
export declare function resolveRuntimeDependencyRoots(runtimeDirs: string[]): string[];
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/core/src/runtime-paths.ts
|
|
3
|
+
import { existsSync, readdirSync, realpathSync } from "fs";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
function uniq(values) {
|
|
6
|
+
return [...new Set(values)];
|
|
7
|
+
}
|
|
8
|
+
function resolveBunBinaryPath() {
|
|
9
|
+
const explicit = normalizeExecutablePath(process.env.RIG_BUN_PATH?.trim());
|
|
10
|
+
if (explicit) {
|
|
11
|
+
return explicit;
|
|
12
|
+
}
|
|
13
|
+
const pathBun = normalizeExecutablePath(Bun.which("bun")?.trim());
|
|
14
|
+
if (pathBun && !looksLikeRuntimeGateway(pathBun)) {
|
|
15
|
+
return pathBun;
|
|
16
|
+
}
|
|
17
|
+
const home = process.env.HOME?.trim();
|
|
18
|
+
const fallbackCandidates = [
|
|
19
|
+
home ? resolve(home, ".bun/bin/bun") : "",
|
|
20
|
+
"/opt/homebrew/bin/bun",
|
|
21
|
+
"/usr/local/bin/bun",
|
|
22
|
+
"/usr/bin/bun"
|
|
23
|
+
];
|
|
24
|
+
for (const candidate of fallbackCandidates) {
|
|
25
|
+
const normalized = normalizeExecutablePath(candidate);
|
|
26
|
+
if (normalized) {
|
|
27
|
+
return normalized;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const execPath = normalizeExecutablePath(process.execPath?.trim());
|
|
31
|
+
if (execPath && !looksLikeRuntimeGateway(execPath)) {
|
|
32
|
+
return execPath;
|
|
33
|
+
}
|
|
34
|
+
throw new Error("bun not found in PATH");
|
|
35
|
+
}
|
|
36
|
+
function resolveClaudeBinaryPath() {
|
|
37
|
+
const explicit = normalizeExecutablePath(process.env.RIG_CLAUDE_PATH?.trim());
|
|
38
|
+
if (explicit) {
|
|
39
|
+
return explicit;
|
|
40
|
+
}
|
|
41
|
+
const pathClaude = normalizeExecutablePath(Bun.which("claude")?.trim());
|
|
42
|
+
if (pathClaude && !looksLikeRuntimeGateway(pathClaude)) {
|
|
43
|
+
return pathClaude;
|
|
44
|
+
}
|
|
45
|
+
const home = process.env.HOME?.trim();
|
|
46
|
+
const fallbackCandidates = [
|
|
47
|
+
home ? resolve(home, ".local/bin/claude") : "",
|
|
48
|
+
home ? resolve(home, ".local/share/claude/local/claude") : "",
|
|
49
|
+
"/opt/homebrew/bin/claude",
|
|
50
|
+
"/usr/local/bin/claude",
|
|
51
|
+
"/usr/bin/claude"
|
|
52
|
+
];
|
|
53
|
+
for (const candidate of fallbackCandidates) {
|
|
54
|
+
const normalized = normalizeExecutablePath(candidate);
|
|
55
|
+
if (normalized) {
|
|
56
|
+
return normalized;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
throw new Error("claude not found in PATH");
|
|
60
|
+
}
|
|
61
|
+
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
62
|
+
return resolve(bunBinaryPath, "../..");
|
|
63
|
+
}
|
|
64
|
+
function resolveClaudeInstallDir() {
|
|
65
|
+
const realPath = resolveClaudeBinaryPath();
|
|
66
|
+
return resolve(realPath, "..");
|
|
67
|
+
}
|
|
68
|
+
function resolveNodeInstallDir() {
|
|
69
|
+
const preferredNode = resolvePreferredNodeBinary();
|
|
70
|
+
if (!preferredNode)
|
|
71
|
+
return null;
|
|
72
|
+
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
73
|
+
if (explicitNode && resolve(explicitNode) === resolve(preferredNode)) {
|
|
74
|
+
return preferredNode.endsWith("/bin/node") ? resolve(preferredNode, "../..") : resolve(preferredNode, "..");
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const realPath = realpathSync(preferredNode);
|
|
78
|
+
if (realPath.endsWith("/bin/node")) {
|
|
79
|
+
return resolve(realPath, "../..");
|
|
80
|
+
}
|
|
81
|
+
return resolve(realPath, "..");
|
|
82
|
+
} catch {
|
|
83
|
+
return resolve(preferredNode, "..");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function resolveRuntimeDependencyRoots(runtimeDirs) {
|
|
87
|
+
const roots = [];
|
|
88
|
+
if (process.platform === "darwin") {
|
|
89
|
+
for (const macPath of ["/opt/homebrew", "/opt/homebrew/opt"]) {
|
|
90
|
+
if (existsSync(macPath)) {
|
|
91
|
+
roots.push(macPath);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const dir of runtimeDirs) {
|
|
96
|
+
if (dir.startsWith("/opt/homebrew/Cellar/")) {
|
|
97
|
+
roots.push("/opt/homebrew/opt");
|
|
98
|
+
} else if (dir.startsWith("/usr/local/Cellar/")) {
|
|
99
|
+
roots.push("/usr/local/opt");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return uniq(roots);
|
|
103
|
+
}
|
|
104
|
+
function resolvePreferredNodeBinary() {
|
|
105
|
+
const candidates = [];
|
|
106
|
+
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
107
|
+
if (envNode) {
|
|
108
|
+
const explicit = resolve(envNode);
|
|
109
|
+
if (existsSync(explicit)) {
|
|
110
|
+
return explicit;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const nvmBin = process.env.NVM_BIN?.trim();
|
|
114
|
+
if (nvmBin) {
|
|
115
|
+
candidates.push(resolve(nvmBin, "node"));
|
|
116
|
+
}
|
|
117
|
+
const home = process.env.HOME?.trim();
|
|
118
|
+
if (home) {
|
|
119
|
+
const nvmVersionsDir = resolve(home, ".nvm/versions/node");
|
|
120
|
+
if (existsSync(nvmVersionsDir)) {
|
|
121
|
+
try {
|
|
122
|
+
const versionDirs = readdirSync(nvmVersionsDir).map((entry) => entry.trim()).filter((entry) => /^v\d+\.\d+\.\d+$/.test(entry)).sort((a, b) => Bun.semver.order(b.replace(/^v/, ""), a.replace(/^v/, "")));
|
|
123
|
+
for (const versionDir of versionDirs) {
|
|
124
|
+
candidates.push(resolve(nvmVersionsDir, versionDir, "bin/node"));
|
|
125
|
+
}
|
|
126
|
+
} catch {}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const whichNode = Bun.which("node");
|
|
130
|
+
if (whichNode) {
|
|
131
|
+
candidates.push(whichNode);
|
|
132
|
+
}
|
|
133
|
+
const deduped = uniq(candidates.map((candidate) => resolve(candidate)));
|
|
134
|
+
const existing = deduped.filter((candidate) => existsSync(candidate));
|
|
135
|
+
if (existing.length === 0) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const stable = existing.find((candidate) => {
|
|
139
|
+
const major = inferNodeMajor(candidate);
|
|
140
|
+
return typeof major === "number" && major >= 18 && major <= 24;
|
|
141
|
+
});
|
|
142
|
+
if (stable) {
|
|
143
|
+
return stable;
|
|
144
|
+
}
|
|
145
|
+
return existing[0] ?? null;
|
|
146
|
+
}
|
|
147
|
+
function inferNodeMajor(nodeBinaryPath) {
|
|
148
|
+
const normalized = resolve(nodeBinaryPath).replace(/\\/g, "/");
|
|
149
|
+
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
150
|
+
if (!match) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
const major = Number.parseInt(match[1], 10);
|
|
154
|
+
return Number.isFinite(major) ? major : null;
|
|
155
|
+
}
|
|
156
|
+
function normalizeExecutablePath(candidate) {
|
|
157
|
+
if (!candidate) {
|
|
158
|
+
return "";
|
|
159
|
+
}
|
|
160
|
+
const normalized = resolve(candidate);
|
|
161
|
+
if (!existsSync(normalized)) {
|
|
162
|
+
return "";
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
return realpathSync(normalized);
|
|
166
|
+
} catch {
|
|
167
|
+
return normalized;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function looksLikeRuntimeGateway(candidate) {
|
|
171
|
+
const normalized = resolve(candidate).replace(/\\/g, "/");
|
|
172
|
+
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
resolveRuntimeDependencyRoots,
|
|
176
|
+
resolveNodeInstallDir,
|
|
177
|
+
resolveClaudeInstallDir,
|
|
178
|
+
resolveClaudeBinaryPath,
|
|
179
|
+
resolveBunInstallDir,
|
|
180
|
+
resolveBunBinaryPath
|
|
181
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a clean host environment for runtime provisioning steps (bun build/install).
|
|
3
|
+
* This strips sandbox wrapper markers so provisioning does not recurse into controlled-bash.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runtimeProvisioningEnv(baseEnv?: Record<string, string | undefined>): Record<string, string>;
|