@h-rig/provider-plugin 0.0.6-alpha.157 → 0.0.6-alpha.159
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/bin/rig-agent-dispatch.d.ts +2 -0
- package/dist/bin/rig-agent-dispatch.js +863 -0
- package/dist/src/agent-harness/agent-mode.d.ts +1 -0
- package/dist/src/agent-harness/agent-mode.js +48 -0
- package/dist/src/agent-harness/agent-wrapper.d.ts +53 -0
- package/dist/src/agent-harness/agent-wrapper.js +916 -0
- package/dist/src/agent-harness/controlled-bash.d.ts +3 -0
- package/dist/src/agent-harness/controlled-bash.js +45 -0
- package/dist/src/agent-harness/git-ops.d.ts +2 -0
- package/dist/src/agent-harness/git-ops.js +27 -0
- package/dist/src/agent-harness/repo-ops.d.ts +8 -0
- package/dist/src/agent-harness/repo-ops.js +471 -0
- package/dist/src/agent-harness/rig-agent-entrypoint.d.ts +1 -0
- package/dist/src/agent-harness/rig-agent-entrypoint.js +1277 -0
- package/dist/src/agent-harness/rig-agent.d.ts +2 -0
- package/dist/src/agent-harness/rig-agent.js +1244 -0
- package/dist/src/agent-harness/runtime-snapshot-config.d.ts +2 -0
- package/dist/src/agent-harness/runtime-snapshot-config.js +25 -0
- package/dist/src/agent-harness/task-data.d.ts +2 -0
- package/dist/src/agent-harness/task-data.js +12 -0
- package/dist/src/agent-harness/task-ops.d.ts +10 -0
- package/dist/src/agent-harness/task-ops.js +53 -0
- package/dist/src/index.js +3366 -16
- package/dist/src/pi-settings-materializer.d.ts +10 -0
- package/dist/src/pi-settings-materializer.js +52 -0
- package/dist/src/plugin.d.ts +9 -2
- package/dist/src/plugin.js +3360 -8
- package/dist/src/service.d.ts +1 -1
- package/dist/src/session-asset-materializer-service.d.ts +13 -0
- package/dist/src/session-asset-materializer-service.js +124 -0
- package/dist/src/skill-materializer.d.ts +25 -0
- package/dist/src/skill-materializer.js +46 -0
- package/dist/src/tooling/binary-build-worker.d.ts +1 -0
- package/dist/src/tooling/binary-build-worker.js +323 -0
- package/dist/src/tooling/browser-tool-entrypoint.d.ts +2 -0
- package/dist/src/tooling/browser-tool-entrypoint.js +125 -0
- package/dist/src/tooling/browser-tools.d.ts +3 -0
- package/dist/src/tooling/browser-tools.js +27 -0
- package/dist/src/tooling/claude-router-binary.d.ts +3 -0
- package/dist/src/tooling/claude-router-binary.js +381 -0
- package/dist/src/tooling/claude-router.d.ts +22 -0
- package/dist/src/tooling/claude-router.js +524 -0
- package/dist/src/tooling/embedded-native-assets.d.ts +7 -0
- package/dist/src/tooling/embedded-native-assets.js +6 -0
- package/dist/src/tooling/file-tools.d.ts +5 -0
- package/dist/src/tooling/file-tools.js +224 -0
- package/dist/src/tooling/gateway.d.ts +4 -0
- package/dist/src/tooling/gateway.js +430 -0
- package/dist/src/tooling/native-extract.d.ts +2 -0
- package/dist/src/tooling/native-extract.js +44 -0
- package/dist/src/tooling/runtime-binary-build.d.ts +88 -0
- package/dist/src/tooling/runtime-binary-build.js +480 -0
- package/dist/src/tooling/shell-tools.d.ts +5 -0
- package/dist/src/tooling/shell-tools.js +217 -0
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +4 -0
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +4 -0
- package/native/darwin-x64/rig-shell +0 -0
- package/native/darwin-x64/rig-tools +0 -0
- package/native/linux-arm64/rig-shell +0 -0
- package/native/linux-arm64/rig-tools +0 -0
- package/native/linux-x64/rig-shell +0 -0
- package/native/linux-x64/rig-tools +0 -0
- package/native/win32-x64/rig-shell.exe +0 -0
- package/native/win32-x64/rig-tools.exe +0 -0
- package/package.json +54 -5
- package/dist/src/claude-stream-records.d.ts +0 -24
- package/dist/src/claude-stream-records.js +0 -158
- package/dist/src/codex-app-server.d.ts +0 -16
- package/dist/src/codex-app-server.js +0 -548
- package/dist/src/codex-exec-records.d.ts +0 -27
- package/dist/src/codex-exec-records.js +0 -203
|
@@ -0,0 +1,1277 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
|
|
18
|
+
// packages/provider-plugin/src/agent-harness/controlled-bash.ts
|
|
19
|
+
import { existsSync } from "fs";
|
|
20
|
+
import { resolve } from "path";
|
|
21
|
+
import { resolveRigLayout } from "@rig/core/layout";
|
|
22
|
+
function controlledBashCandidates(projectRoot) {
|
|
23
|
+
const layout = resolveRigLayout(projectRoot);
|
|
24
|
+
const candidates = [
|
|
25
|
+
process.env.RIG_CONTROLLED_BASH_BIN?.trim() || "",
|
|
26
|
+
resolve(layout.binDir, "controlled-bash"),
|
|
27
|
+
Bun.which("controlled-bash") || ""
|
|
28
|
+
];
|
|
29
|
+
return candidates.filter((candidate) => Boolean(candidate));
|
|
30
|
+
}
|
|
31
|
+
function resolveControlledBash(projectRoot) {
|
|
32
|
+
for (const candidate of controlledBashCandidates(projectRoot)) {
|
|
33
|
+
if (existsSync(candidate))
|
|
34
|
+
return candidate;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
async function runControlledBash(args, options) {
|
|
39
|
+
const projectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || process.env.PROJECT_RIG_ROOT?.trim() || process.env.RIG_TASK_WORKSPACE?.trim() || process.cwd() || options.projectRootFallbackDir;
|
|
40
|
+
const controlled = resolveControlledBash(projectRoot);
|
|
41
|
+
if (!controlled) {
|
|
42
|
+
console.error("[rig-agent] controlled-bash entrypoint unavailable; refusing to run an unguarded shell.");
|
|
43
|
+
return 126;
|
|
44
|
+
}
|
|
45
|
+
const command = [controlled, ...args];
|
|
46
|
+
const child = Bun.spawn(command, {
|
|
47
|
+
stdin: "inherit",
|
|
48
|
+
stdout: "inherit",
|
|
49
|
+
stderr: "inherit",
|
|
50
|
+
cwd: process.cwd(),
|
|
51
|
+
env: {
|
|
52
|
+
...process.env,
|
|
53
|
+
PROJECT_RIG_ROOT: projectRoot,
|
|
54
|
+
RIG_BASH_ACTIVE: "1"
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return await child.exited;
|
|
58
|
+
}
|
|
59
|
+
var init_controlled_bash = () => {};
|
|
60
|
+
|
|
61
|
+
// packages/provider-plugin/src/agent-harness/agent-mode.ts
|
|
62
|
+
function looksLikeShellInvocation(args, mode = process.env.RIG_AGENT_MODE) {
|
|
63
|
+
if (mode === "shell") {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (mode === "agent") {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (args.length === 0) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const first = args[0];
|
|
73
|
+
if (!first) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const bashLikeFlags = new Set([
|
|
77
|
+
"-c",
|
|
78
|
+
"-lc",
|
|
79
|
+
"-l",
|
|
80
|
+
"-i",
|
|
81
|
+
"-s",
|
|
82
|
+
"--login",
|
|
83
|
+
"--noprofile",
|
|
84
|
+
"--norc",
|
|
85
|
+
"--posix",
|
|
86
|
+
"--rcfile",
|
|
87
|
+
"--init-file",
|
|
88
|
+
"--restricted",
|
|
89
|
+
"--debug",
|
|
90
|
+
"--debugger",
|
|
91
|
+
"--verbose",
|
|
92
|
+
"--wordexp",
|
|
93
|
+
"--dump-strings",
|
|
94
|
+
"--dump-po-strings",
|
|
95
|
+
"--help"
|
|
96
|
+
]);
|
|
97
|
+
if (bashLikeFlags.has(first)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
if (!first.startsWith("-")) {
|
|
101
|
+
return first.endsWith(".sh");
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// packages/provider-plugin/src/agent-harness/git-ops.ts
|
|
107
|
+
import { LIFECYCLE_GIT_AGENT } from "@rig/contracts";
|
|
108
|
+
import { defineCapability } from "@rig/core/capability";
|
|
109
|
+
import { buildPluginHostContext } from "@rig/core/plugin-host-context";
|
|
110
|
+
import { loadCapabilityForRoot } from "@rig/core/capability-loaders";
|
|
111
|
+
async function ensureHostContext(projectRoot) {
|
|
112
|
+
let cached = hostContextByRoot.get(projectRoot);
|
|
113
|
+
if (!cached) {
|
|
114
|
+
cached = buildPluginHostContext(projectRoot);
|
|
115
|
+
hostContextByRoot.set(projectRoot, cached);
|
|
116
|
+
}
|
|
117
|
+
await cached;
|
|
118
|
+
}
|
|
119
|
+
async function loadLifecycleGit(projectRoot) {
|
|
120
|
+
await ensureHostContext(projectRoot);
|
|
121
|
+
const git = await loadCapabilityForRoot(projectRoot, LifecycleGitAgentCap);
|
|
122
|
+
if (!git) {
|
|
123
|
+
throw new Error("lifecycle git capability unavailable: load @rig/bundle-default-lifecycle (default bundle) before running rig-agent git commands.");
|
|
124
|
+
}
|
|
125
|
+
return git;
|
|
126
|
+
}
|
|
127
|
+
var LifecycleGitAgentCap, hostContextByRoot;
|
|
128
|
+
var init_git_ops = __esm(() => {
|
|
129
|
+
LifecycleGitAgentCap = defineCapability(LIFECYCLE_GIT_AGENT);
|
|
130
|
+
hostContextByRoot = new Map;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// packages/provider-plugin/src/agent-harness/repo-ops.ts
|
|
134
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
135
|
+
import { basename, dirname, resolve as resolve2 } from "path";
|
|
136
|
+
import { loadRuntimeContext } from "@rig/core/runtime-context";
|
|
137
|
+
import {
|
|
138
|
+
MANAGED_REPO_SERVICE_CAPABILITY,
|
|
139
|
+
TASK_DATA_SERVICE_CAPABILITY
|
|
140
|
+
} from "@rig/contracts";
|
|
141
|
+
import { defineCapability as defineCapability2 } from "@rig/core/capability";
|
|
142
|
+
import { getInstalledCapability, requireInstalledCapability } from "@rig/core/capability-loaders";
|
|
143
|
+
import { resolveHarnessPaths } from "@rig/core/harness-paths";
|
|
144
|
+
function runCapture(command, cwd, env) {
|
|
145
|
+
const result = Bun.spawnSync(command, {
|
|
146
|
+
cwd,
|
|
147
|
+
env: env ? { ...process.env, ...env } : process.env,
|
|
148
|
+
stdout: "pipe",
|
|
149
|
+
stderr: "pipe",
|
|
150
|
+
stdin: "ignore"
|
|
151
|
+
});
|
|
152
|
+
return {
|
|
153
|
+
exitCode: result.exitCode,
|
|
154
|
+
stdout: result.stdout.toString(),
|
|
155
|
+
stderr: result.stderr.toString()
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function readJsonFile(path, fallback) {
|
|
159
|
+
if (!existsSync2(path))
|
|
160
|
+
return fallback;
|
|
161
|
+
try {
|
|
162
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
163
|
+
} catch {
|
|
164
|
+
return fallback;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function nowIso() {
|
|
168
|
+
return new Date().toISOString();
|
|
169
|
+
}
|
|
170
|
+
function managedRepoEntries() {
|
|
171
|
+
return getManagedRepoService()?.listManagedRepoEntries() ?? [];
|
|
172
|
+
}
|
|
173
|
+
function requireManagedRepoService() {
|
|
174
|
+
const service = getManagedRepoService();
|
|
175
|
+
if (!service) {
|
|
176
|
+
throw new Error("managed-repo service not installed: configure @rig/repos-plugin in rig.config to use managed-repo operations.");
|
|
177
|
+
}
|
|
178
|
+
return service;
|
|
179
|
+
}
|
|
180
|
+
function primaryManagedRepoId() {
|
|
181
|
+
const entries = managedRepoEntries();
|
|
182
|
+
return entries.length > 0 ? entries[0].id : null;
|
|
183
|
+
}
|
|
184
|
+
function primaryManagedRepoAlias() {
|
|
185
|
+
const entries = managedRepoEntries();
|
|
186
|
+
return entries.length > 0 ? entries[0].alias : null;
|
|
187
|
+
}
|
|
188
|
+
function repoEnsure(projectRoot, taskId) {
|
|
189
|
+
const monorepo = ensureMonorepoReady(projectRoot);
|
|
190
|
+
const resolvedTask = taskId || taskData().currentTaskId(projectRoot);
|
|
191
|
+
if (!resolvedTask) {
|
|
192
|
+
if (monorepo) {
|
|
193
|
+
const alias = primaryManagedRepoAlias();
|
|
194
|
+
if (alias) {
|
|
195
|
+
persistBaselinePins(projectRoot, { [alias]: monorepo.headCommit });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
console.log("No active task. Refreshed baseline repo pins.");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const pins = resolvedPins(projectRoot, resolvedTask);
|
|
202
|
+
applyPins(projectRoot, pins);
|
|
203
|
+
verifyPins(projectRoot, pins);
|
|
204
|
+
}
|
|
205
|
+
function repoPins(projectRoot, taskId) {
|
|
206
|
+
const resolvedTask = taskId || taskData().currentTaskId(projectRoot);
|
|
207
|
+
if (!resolvedTask) {
|
|
208
|
+
return {};
|
|
209
|
+
}
|
|
210
|
+
return resolvedPins(projectRoot, resolvedTask);
|
|
211
|
+
}
|
|
212
|
+
function repoVerify(projectRoot, taskId) {
|
|
213
|
+
const resolvedTask = taskId || taskData().currentTaskId(projectRoot);
|
|
214
|
+
if (!resolvedTask) {
|
|
215
|
+
console.log("No active task. Nothing to verify.");
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
const pins = resolvedPins(projectRoot, resolvedTask);
|
|
219
|
+
return verifyPins(projectRoot, pins);
|
|
220
|
+
}
|
|
221
|
+
function repoDiscover(projectRoot, taskId) {
|
|
222
|
+
const resolvedTask = taskId || taskData().currentTaskId(projectRoot);
|
|
223
|
+
if (!resolvedTask) {
|
|
224
|
+
return {};
|
|
225
|
+
}
|
|
226
|
+
const explicit = explicitPins(projectRoot, resolvedTask);
|
|
227
|
+
if (Object.keys(explicit).length > 0) {
|
|
228
|
+
return explicit;
|
|
229
|
+
}
|
|
230
|
+
return discoverPins(projectRoot, resolvedTask);
|
|
231
|
+
}
|
|
232
|
+
function repoBaseline(projectRoot, refresh = false) {
|
|
233
|
+
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
234
|
+
if (!refresh && existsSync2(paths.baseRepoPinsPath)) {
|
|
235
|
+
const baseline = readJsonFile(paths.baseRepoPinsPath, { recorded_at: nowIso(), repos: {} });
|
|
236
|
+
return baseline.repos || {};
|
|
237
|
+
}
|
|
238
|
+
const id = primaryManagedRepoId();
|
|
239
|
+
if (!id) {
|
|
240
|
+
return persistBaselinePins(projectRoot, {});
|
|
241
|
+
}
|
|
242
|
+
const synced = requireManagedRepoService().syncManagedRepo(projectRoot, id);
|
|
243
|
+
const alias = primaryManagedRepoAlias() ?? id;
|
|
244
|
+
return persistBaselinePins(projectRoot, { [alias]: synced.headCommit });
|
|
245
|
+
}
|
|
246
|
+
function ensureMonorepoReady(projectRoot) {
|
|
247
|
+
const id = primaryManagedRepoId();
|
|
248
|
+
if (!id) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const synced = requireManagedRepoService().syncManagedRepo(projectRoot, id);
|
|
252
|
+
const sha = synced.headCommit.slice(0, 7);
|
|
253
|
+
console.log(`Monorepo ready: ${synced.layout.alias}@${sha}`);
|
|
254
|
+
return synced;
|
|
255
|
+
}
|
|
256
|
+
function persistBaselinePins(projectRoot, repos) {
|
|
257
|
+
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
258
|
+
mkdirSync(resolve2(paths.baseRepoPinsPath, ".."), { recursive: true });
|
|
259
|
+
writeFileSync(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
|
|
260
|
+
`, "utf-8");
|
|
261
|
+
return repos;
|
|
262
|
+
}
|
|
263
|
+
function resolvedPins(projectRoot, taskId) {
|
|
264
|
+
const explicit = explicitPins(projectRoot, taskId);
|
|
265
|
+
if (Object.keys(explicit).length > 0) {
|
|
266
|
+
return explicit;
|
|
267
|
+
}
|
|
268
|
+
return discoverPins(projectRoot, taskId);
|
|
269
|
+
}
|
|
270
|
+
function explicitPins(projectRoot, taskId) {
|
|
271
|
+
const repoPins2 = readRepoDiscoveryTaskConfig(projectRoot)[taskId]?.repo_pins || {};
|
|
272
|
+
const normalized = {};
|
|
273
|
+
const validAliases = new Set(managedRepoEntries().map((e) => e.alias));
|
|
274
|
+
for (const [key, value] of Object.entries(repoPins2)) {
|
|
275
|
+
if (!value) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (validAliases.size > 0 && !validAliases.has(key)) {
|
|
279
|
+
throw new Error(`Unsupported repo pin key for ${taskId}: ${key}. Known aliases: ${[...validAliases].join(", ") || "(none registered)"}`);
|
|
280
|
+
}
|
|
281
|
+
const existing = normalized[key];
|
|
282
|
+
if (existing && existing !== value) {
|
|
283
|
+
throw new Error(`Conflicting explicit repo pins for ${key}: ${existing} vs ${value}`);
|
|
284
|
+
}
|
|
285
|
+
normalized[key] = value;
|
|
286
|
+
}
|
|
287
|
+
return normalized;
|
|
288
|
+
}
|
|
289
|
+
function taskDependencies(projectRoot, taskId) {
|
|
290
|
+
return taskData().taskDependencyIds(projectRoot, taskId);
|
|
291
|
+
}
|
|
292
|
+
function discoverPins(projectRoot, taskId) {
|
|
293
|
+
const deps = taskDependencies(projectRoot, taskId);
|
|
294
|
+
if (deps.length === 0) {
|
|
295
|
+
return repoBaseline(projectRoot, true);
|
|
296
|
+
}
|
|
297
|
+
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
298
|
+
const state = readJsonFile(paths.taskRepoCommitsPath, {});
|
|
299
|
+
const pinKeys = managedRepoEntries().map((e) => e.alias);
|
|
300
|
+
if (pinKeys.length === 0) {
|
|
301
|
+
return {};
|
|
302
|
+
}
|
|
303
|
+
const discovered = {};
|
|
304
|
+
for (const key of pinKeys) {
|
|
305
|
+
const commits = new Set;
|
|
306
|
+
for (const dep of deps) {
|
|
307
|
+
const fromState = state[dep]?.repos?.[key];
|
|
308
|
+
if (fromState) {
|
|
309
|
+
commits.add(fromState);
|
|
310
|
+
}
|
|
311
|
+
const fromArtifact = readPinFromArtifact(projectRoot, dep, key);
|
|
312
|
+
if (fromArtifact) {
|
|
313
|
+
commits.add(fromArtifact);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (commits.size > 1) {
|
|
317
|
+
const values = [...commits].join(`
|
|
318
|
+
- `);
|
|
319
|
+
throw new Error(`Conflicting discovered pins for ${key} from dependency graph of ${taskId}:
|
|
320
|
+
- ${values}`);
|
|
321
|
+
}
|
|
322
|
+
if (commits.size === 1) {
|
|
323
|
+
discovered[key] = [...commits][0];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return discovered;
|
|
327
|
+
}
|
|
328
|
+
function readRepoDiscoveryTaskConfig(projectRoot) {
|
|
329
|
+
try {
|
|
330
|
+
return taskData().readSourceTaskConfig(projectRoot);
|
|
331
|
+
} catch {
|
|
332
|
+
return taskData().readTaskConfig(projectRoot);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function resolveRepoDiscoveryPaths(projectRoot) {
|
|
336
|
+
const monorepoRoot = requireManagedRepoService().resolveMonorepoRepoLayout(projectRoot).checkoutRoot;
|
|
337
|
+
const explicitHostProjectRoot = (process.env.RIG_HOST_PROJECT_ROOT || "").trim();
|
|
338
|
+
const normalizedProjectRoot = resolve2(projectRoot);
|
|
339
|
+
const hostProjectRoot = explicitHostProjectRoot && shouldUseHostProjectStateRoot(normalizedProjectRoot) ? explicitHostProjectRoot : normalizedProjectRoot;
|
|
340
|
+
const stateDir = resolve2(hostProjectRoot, ".rig", "state");
|
|
341
|
+
return {
|
|
342
|
+
monorepoRoot,
|
|
343
|
+
taskRepoCommitsPath: resolve2(stateDir, "task-repo-commits.json"),
|
|
344
|
+
baseRepoPinsPath: resolve2(stateDir, "base-repo-pins.json")
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function shouldUseHostProjectStateRoot(projectRoot) {
|
|
348
|
+
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
349
|
+
if (runtimeWorkspace && resolve2(runtimeWorkspace) === projectRoot) {
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
return basename(dirname(projectRoot)) === ".worktrees";
|
|
353
|
+
}
|
|
354
|
+
function readPinFromArtifact(projectRoot, depTask, repoKey) {
|
|
355
|
+
const snapshot = resolve2(taskData().artifactDirForId(projectRoot, depTask), "git-state.txt");
|
|
356
|
+
if (!existsSync2(snapshot)) {
|
|
357
|
+
return "";
|
|
358
|
+
}
|
|
359
|
+
const content = readFileSync(snapshot, "utf-8");
|
|
360
|
+
const chunk = content.split(/\r?\n/);
|
|
361
|
+
let inSection = false;
|
|
362
|
+
for (const line of chunk) {
|
|
363
|
+
if (line.startsWith("## ")) {
|
|
364
|
+
inSection = line.startsWith(`## ${repoKey}`);
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (!inSection) {
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
if (line.startsWith("head:")) {
|
|
371
|
+
return line.replace(/^head:\s*/, "").trim();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return "";
|
|
375
|
+
}
|
|
376
|
+
function repoPath(projectRoot, key) {
|
|
377
|
+
const managed = getManagedRepoService()?.resolveManagedRepoLayoutByAlias(projectRoot, key) ?? null;
|
|
378
|
+
if (managed) {
|
|
379
|
+
return managed.checkoutRoot;
|
|
380
|
+
}
|
|
381
|
+
return key.startsWith("/") ? key : resolve2(projectRoot, key);
|
|
382
|
+
}
|
|
383
|
+
function applyPins(projectRoot, pins) {
|
|
384
|
+
for (const [key, commit] of Object.entries(pins)) {
|
|
385
|
+
const path = repoPath(projectRoot, key);
|
|
386
|
+
if (!existsSync2(resolve2(path, ".git"))) {
|
|
387
|
+
throw new Error(`Repo for pin not available: ${key} (${path})`);
|
|
388
|
+
}
|
|
389
|
+
let hasCommit = runGitCapture(["git", "-C", path, "cat-file", "-e", `${commit}^{commit}`], projectRoot).exitCode === 0;
|
|
390
|
+
if (!hasCommit) {
|
|
391
|
+
runGitCapture(["git", "-C", path, "fetch", "--all", "--tags", "--prune"], projectRoot);
|
|
392
|
+
hasCommit = runGitCapture(["git", "-C", path, "cat-file", "-e", `${commit}^{commit}`], projectRoot).exitCode === 0;
|
|
393
|
+
}
|
|
394
|
+
if (!hasCommit) {
|
|
395
|
+
throw new Error(`Commit not found for ${key}: ${commit}`);
|
|
396
|
+
}
|
|
397
|
+
const current = runGitCapture(["git", "-C", path, "rev-parse", "HEAD"], projectRoot).stdout.trim();
|
|
398
|
+
if (current === commit) {
|
|
399
|
+
console.log(`Repo pin: ${key} already at ${commit}`);
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
const branch = runGitCapture(["git", "-C", path, "rev-parse", "--abbrev-ref", "HEAD"], projectRoot).stdout.trim();
|
|
403
|
+
const checkout = branch.startsWith("rig/") ? runGitCapture(["git", "-C", path, "reset", "--hard", commit], projectRoot) : runGitCapture(["git", "-C", path, "checkout", "--detach", commit], projectRoot);
|
|
404
|
+
if (checkout.exitCode !== 0) {
|
|
405
|
+
throw new Error(`Failed to apply repo pin ${key} -> ${commit}:
|
|
406
|
+
${checkout.stderr || checkout.stdout}`);
|
|
407
|
+
}
|
|
408
|
+
console.log(`Repo pin: ${key} -> ${commit}`);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function verifyPins(projectRoot, pins) {
|
|
412
|
+
let ok = true;
|
|
413
|
+
for (const [key, expected] of Object.entries(pins)) {
|
|
414
|
+
const path = repoPath(projectRoot, key);
|
|
415
|
+
if (!existsSync2(resolve2(path, ".git"))) {
|
|
416
|
+
console.error(`ERROR: repo missing during pin verification: ${key}`);
|
|
417
|
+
ok = false;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
const current = runGitCapture(["git", "-C", path, "rev-parse", "HEAD"], projectRoot).stdout.trim();
|
|
421
|
+
if (current === expected) {
|
|
422
|
+
console.log(`Repo verify: ${key} at ${current}`);
|
|
423
|
+
} else {
|
|
424
|
+
console.error(`ERROR: repo pin mismatch for ${key}: expected ${expected}, got ${current}`);
|
|
425
|
+
ok = false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return ok;
|
|
429
|
+
}
|
|
430
|
+
function runGitCapture(command, projectRoot) {
|
|
431
|
+
return runCapture(command, projectRoot, resolveRuntimeGitEnv());
|
|
432
|
+
}
|
|
433
|
+
function resolveRuntimeGitEnv() {
|
|
434
|
+
if (process.env.GIT_SSH_COMMAND?.trim()) {
|
|
435
|
+
return {
|
|
436
|
+
HOME: process.env.HOME ?? "",
|
|
437
|
+
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ? resolve2(process.env.RIG_RUNTIME_CONTEXT_FILE, "..") : inferRuntimeRootFromWorkspace(process.cwd()));
|
|
441
|
+
const runtimeHome = runtimeRoot ? resolve2(runtimeRoot, "home") : process.env.HOME?.trim() || "";
|
|
442
|
+
if (!runtimeHome) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const knownHostsPath = resolve2(runtimeHome, ".ssh", "known_hosts");
|
|
446
|
+
if (!existsSync2(knownHostsPath)) {
|
|
447
|
+
return { HOME: runtimeHome };
|
|
448
|
+
}
|
|
449
|
+
const agentSshKey = resolve2(runtimeHome, ".ssh", "rig-agent-key");
|
|
450
|
+
const sshParts = [
|
|
451
|
+
"ssh",
|
|
452
|
+
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
453
|
+
"-o StrictHostKeyChecking=yes",
|
|
454
|
+
"-F /dev/null"
|
|
455
|
+
];
|
|
456
|
+
if (existsSync2(agentSshKey)) {
|
|
457
|
+
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
HOME: runtimeHome,
|
|
461
|
+
GIT_SSH_COMMAND: sshParts.join(" ")
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function inferRuntimeRootFromWorkspace(cwd) {
|
|
465
|
+
const contextPath = findRuntimeContextFile(cwd);
|
|
466
|
+
if (!contextPath || !existsSync2(contextPath)) {
|
|
467
|
+
return "";
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
loadRuntimeContext(contextPath);
|
|
471
|
+
return resolve2(contextPath, "..");
|
|
472
|
+
} catch {
|
|
473
|
+
return "";
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function findRuntimeContextFile(startPath) {
|
|
477
|
+
let current = resolve2(startPath);
|
|
478
|
+
while (true) {
|
|
479
|
+
const candidate = resolve2(current, "runtime-context.json");
|
|
480
|
+
if (existsSync2(candidate)) {
|
|
481
|
+
return candidate;
|
|
482
|
+
}
|
|
483
|
+
const parent = resolve2(current, "..");
|
|
484
|
+
if (parent === current) {
|
|
485
|
+
return "";
|
|
486
|
+
}
|
|
487
|
+
current = parent;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
var ManagedRepoCap, getManagedRepoService = () => getInstalledCapability(ManagedRepoCap), TaskDataCap, taskData = () => requireInstalledCapability(TaskDataCap, "task-data capability unavailable: load @rig/task-sources-plugin (default bundle) before resolving task repos.");
|
|
491
|
+
var init_repo_ops = __esm(() => {
|
|
492
|
+
ManagedRepoCap = defineCapability2(MANAGED_REPO_SERVICE_CAPABILITY);
|
|
493
|
+
TaskDataCap = defineCapability2(TASK_DATA_SERVICE_CAPABILITY);
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
// packages/provider-plugin/src/agent-harness/task-data.ts
|
|
497
|
+
import { TASK_DATA_SERVICE_CAPABILITY as TASK_DATA_SERVICE_CAPABILITY2 } from "@rig/contracts";
|
|
498
|
+
import { defineCapability as defineCapability3 } from "@rig/core/capability";
|
|
499
|
+
import { requireInstalledCapability as requireInstalledCapability2 } from "@rig/core/capability-loaders";
|
|
500
|
+
function taskData2() {
|
|
501
|
+
return requireInstalledCapability2(TaskDataCap2, "task-data capability unavailable: load @rig/task-sources-plugin (default bundle) before running the provider agent harness.");
|
|
502
|
+
}
|
|
503
|
+
var TaskDataCap2;
|
|
504
|
+
var init_task_data = __esm(() => {
|
|
505
|
+
TaskDataCap2 = defineCapability3(TASK_DATA_SERVICE_CAPABILITY2);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// packages/provider-plugin/src/agent-harness/task-ops.ts
|
|
509
|
+
function taskArtifactDir(projectRoot, taskId) {
|
|
510
|
+
return taskData2().taskArtifactDir(projectRoot, taskId);
|
|
511
|
+
}
|
|
512
|
+
function taskArtifacts(projectRoot, taskId) {
|
|
513
|
+
taskData2().taskArtifacts(projectRoot, taskId);
|
|
514
|
+
}
|
|
515
|
+
function taskArtifactWrite(projectRoot, filename, content, taskId) {
|
|
516
|
+
taskData2().taskArtifactWrite(projectRoot, filename, content, taskId);
|
|
517
|
+
}
|
|
518
|
+
function taskDeps(projectRoot, taskId) {
|
|
519
|
+
return taskData2().taskDeps(projectRoot, taskId);
|
|
520
|
+
}
|
|
521
|
+
function taskInfo(projectRoot, taskId) {
|
|
522
|
+
return taskData2().taskInfo(projectRoot, taskId);
|
|
523
|
+
}
|
|
524
|
+
function taskLookup(projectRoot, id) {
|
|
525
|
+
return taskData2().taskLookup(projectRoot, id);
|
|
526
|
+
}
|
|
527
|
+
function taskRecord(projectRoot, type, text, taskId) {
|
|
528
|
+
taskData2().taskRecord(projectRoot, type, text, taskId);
|
|
529
|
+
}
|
|
530
|
+
function taskScope(projectRoot, expandFiles, taskId) {
|
|
531
|
+
return taskData2().taskScope(projectRoot, expandFiles, taskId);
|
|
532
|
+
}
|
|
533
|
+
function taskStatus(projectRoot) {
|
|
534
|
+
taskData2().taskStatus(projectRoot);
|
|
535
|
+
}
|
|
536
|
+
function taskValidate(projectRoot, taskId, validatorRegistry) {
|
|
537
|
+
return taskData2().taskValidate(projectRoot, taskId, validatorRegistry);
|
|
538
|
+
}
|
|
539
|
+
var init_task_ops = __esm(() => {
|
|
540
|
+
init_task_data();
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// packages/provider-plugin/src/agent-harness/rig-agent.ts
|
|
544
|
+
var exports_rig_agent = {};
|
|
545
|
+
__export(exports_rig_agent, {
|
|
546
|
+
looksLikeShellInvocation: () => looksLikeShellInvocation
|
|
547
|
+
});
|
|
548
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
549
|
+
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
550
|
+
import { readBuildConfig } from "@rig/core/build-time-config";
|
|
551
|
+
import { COMPLETION_VERIFICATION_CAPABILITY, MEMORY } from "@rig/contracts";
|
|
552
|
+
import { defineCapability as defineCapability4 } from "@rig/core/capability";
|
|
553
|
+
import { buildProjectPluginHost, loadCapabilityForRoot as loadCapabilityForRoot2 } from "@rig/core/capability-loaders";
|
|
554
|
+
import { resolveCheckoutRoot as resolveMonorepoRoot } from "@rig/core/checkout-root";
|
|
555
|
+
import { browserEnvFromContext, loadRuntimeContext as loadRuntimeContext2, loadRuntimeContextFromEnv } from "@rig/core/runtime-context";
|
|
556
|
+
import { loadDotEnvSecrets, resolveRuntimeSecrets } from "@rig/core/baked-secrets";
|
|
557
|
+
import { RuntimeEventBus } from "@rig/core/runtime-events";
|
|
558
|
+
import {
|
|
559
|
+
setProfile,
|
|
560
|
+
setReviewProfile,
|
|
561
|
+
showProfile,
|
|
562
|
+
showReviewProfile
|
|
563
|
+
} from "@rig/core/profile-ops";
|
|
564
|
+
function getContext() {
|
|
565
|
+
if (cachedContext !== undefined)
|
|
566
|
+
return cachedContext;
|
|
567
|
+
cachedContext = loadRuntimeContextFromEnv() ?? inferRuntimeContext();
|
|
568
|
+
return cachedContext;
|
|
569
|
+
}
|
|
570
|
+
function getEventBus() {
|
|
571
|
+
if (cachedEventBus !== undefined) {
|
|
572
|
+
return cachedEventBus ?? undefined;
|
|
573
|
+
}
|
|
574
|
+
const ctx = getContext();
|
|
575
|
+
if (!ctx) {
|
|
576
|
+
cachedEventBus = null;
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const runId = ctx.runtimeId || BAKED_RUNTIME_ID || "";
|
|
580
|
+
cachedEventBus = new RuntimeEventBus({
|
|
581
|
+
projectRoot: ctx.workspaceDir,
|
|
582
|
+
...runId ? { runId } : {}
|
|
583
|
+
});
|
|
584
|
+
return cachedEventBus;
|
|
585
|
+
}
|
|
586
|
+
function inferRuntimeContext() {
|
|
587
|
+
for (const candidate of runtimeContextCandidates()) {
|
|
588
|
+
if (!candidate || !existsSync3(candidate)) {
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
try {
|
|
592
|
+
process.env.RIG_RUNTIME_CONTEXT_FILE = candidate;
|
|
593
|
+
return loadRuntimeContext2(candidate);
|
|
594
|
+
} catch {}
|
|
595
|
+
}
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
598
|
+
function runtimeContextCandidates() {
|
|
599
|
+
const cwd = process.cwd();
|
|
600
|
+
const candidates = [
|
|
601
|
+
resolve3(cwd, "..", "runtime-context.json"),
|
|
602
|
+
resolve3(cwd, ".rig", "runtime-context.json")
|
|
603
|
+
];
|
|
604
|
+
const argv1 = process.argv[1]?.trim();
|
|
605
|
+
if (argv1) {
|
|
606
|
+
candidates.push(resolve3(argv1, "..", "..", "runtime-context.json"));
|
|
607
|
+
}
|
|
608
|
+
if (BAKED_BINARY_PATH) {
|
|
609
|
+
candidates.push(resolve3(BAKED_BINARY_PATH, "..", "..", "runtime-context.json"));
|
|
610
|
+
}
|
|
611
|
+
return Array.from(new Set(candidates));
|
|
612
|
+
}
|
|
613
|
+
function sha256Hex(input) {
|
|
614
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
615
|
+
hasher.update(input);
|
|
616
|
+
return hasher.digest("hex");
|
|
617
|
+
}
|
|
618
|
+
function ensureRuntimeKnownHosts(runtimeHome) {
|
|
619
|
+
const sshDir = resolve3(runtimeHome, ".ssh");
|
|
620
|
+
const knownHostsPath = resolve3(sshDir, "known_hosts");
|
|
621
|
+
if (!existsSync3(sshDir)) {
|
|
622
|
+
mkdirSync2(sshDir, { recursive: true });
|
|
623
|
+
}
|
|
624
|
+
const existing = existsSync3(knownHostsPath) ? readFileSync2(knownHostsPath, "utf-8") : "";
|
|
625
|
+
const existingLines = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
626
|
+
const missing = GITHUB_KNOWN_HOSTS.filter((line) => !existingLines.has(line));
|
|
627
|
+
if (missing.length === 0) {
|
|
628
|
+
return knownHostsPath;
|
|
629
|
+
}
|
|
630
|
+
try {
|
|
631
|
+
for (const line of missing) {
|
|
632
|
+
existingLines.add(line);
|
|
633
|
+
}
|
|
634
|
+
writeFileSync2(knownHostsPath, `${Array.from(existingLines).join(`
|
|
635
|
+
`)}
|
|
636
|
+
`, { mode: 420 });
|
|
637
|
+
} catch (err) {
|
|
638
|
+
const hint = existsSync3(knownHostsPath) ? "" : " \u2014 known_hosts is missing; git SSH operations may fail";
|
|
639
|
+
console.warn(`[rig-agent] Could not update ${knownHostsPath}: ${err instanceof Error ? err.message : String(err)}${hint}`);
|
|
640
|
+
}
|
|
641
|
+
return knownHostsPath;
|
|
642
|
+
}
|
|
643
|
+
function hydrateRuntimeProcessEnv(ctx) {
|
|
644
|
+
if (!ctx) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const contextFile = process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() || inferRuntimeContextFileFromWorkspace(ctx.workspaceDir);
|
|
648
|
+
if (!contextFile) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
process.env.RIG_RUNTIME_CONTEXT_FILE = contextFile;
|
|
652
|
+
const runtimeRoot = dirname2(resolve3(contextFile));
|
|
653
|
+
const runtimeHome = resolve3(runtimeRoot, "home");
|
|
654
|
+
const runtimeTmp = resolve3(runtimeRoot, "tmp");
|
|
655
|
+
const runtimeCache = resolve3(runtimeRoot, "cache");
|
|
656
|
+
const runtimeBin = resolve3(runtimeRoot, "bin");
|
|
657
|
+
const runtimeWorkspaceBin = resolve3(ctx.workspaceDir, ".rig", "bin");
|
|
658
|
+
const runtimeTools = resolve3(ctx.workspaceDir, "rig", "tools");
|
|
659
|
+
if (ctx.hostProjectRoot) {
|
|
660
|
+
process.env.PROJECT_RIG_ROOT = ctx.hostProjectRoot;
|
|
661
|
+
}
|
|
662
|
+
process.env.RIG_TASK_ID = ctx.taskId;
|
|
663
|
+
process.env.RIG_TASK_WORKSPACE = ctx.workspaceDir;
|
|
664
|
+
process.env.RIG_STATE_DIR = ctx.stateDir;
|
|
665
|
+
process.env.RIG_LOGS_DIR = ctx.logsDir;
|
|
666
|
+
process.env.RIG_SESSION_FILE = ctx.sessionFile;
|
|
667
|
+
process.env.RIG_RUNTIME_HOME = runtimeRoot;
|
|
668
|
+
if (!process.env.RIG_HOST_PROJECT_ROOT && ctx.hostProjectRoot) {
|
|
669
|
+
process.env.RIG_HOST_PROJECT_ROOT = ctx.hostProjectRoot;
|
|
670
|
+
}
|
|
671
|
+
for (const [key, value] of Object.entries(browserEnvFromContext(ctx.browser))) {
|
|
672
|
+
process.env[key] = value;
|
|
673
|
+
}
|
|
674
|
+
if (existsSync3(runtimeHome)) {
|
|
675
|
+
process.env.HOME = runtimeHome;
|
|
676
|
+
}
|
|
677
|
+
if (existsSync3(runtimeTmp)) {
|
|
678
|
+
process.env.TMPDIR = runtimeTmp;
|
|
679
|
+
}
|
|
680
|
+
if (existsSync3(runtimeCache)) {
|
|
681
|
+
process.env.XDG_CACHE_HOME = runtimeCache;
|
|
682
|
+
}
|
|
683
|
+
const workspaceSecrets = loadDotEnvSecrets(ctx.workspaceDir, process.env);
|
|
684
|
+
const hostWorkspaceSecrets = ctx.hostProjectRoot && ctx.hostProjectRoot !== ctx.workspaceDir ? loadDotEnvSecrets(ctx.hostProjectRoot, process.env) : {};
|
|
685
|
+
const resolvedSecrets = resolveRuntimeSecrets(process.env, {
|
|
686
|
+
...hostWorkspaceSecrets,
|
|
687
|
+
...workspaceSecrets
|
|
688
|
+
});
|
|
689
|
+
for (const [key, value] of Object.entries(resolvedSecrets)) {
|
|
690
|
+
if (value && !process.env[key]) {
|
|
691
|
+
process.env[key] = value;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
if (!process.env.GITHUB_TOKEN && process.env.GH_TOKEN) {
|
|
695
|
+
process.env.GITHUB_TOKEN = process.env.GH_TOKEN;
|
|
696
|
+
}
|
|
697
|
+
if (!process.env.GH_TOKEN && process.env.GITHUB_TOKEN) {
|
|
698
|
+
process.env.GH_TOKEN = process.env.GITHUB_TOKEN;
|
|
699
|
+
}
|
|
700
|
+
if (!process.env.GREPTILE_GITHUB_TOKEN && process.env.GITHUB_TOKEN) {
|
|
701
|
+
process.env.GREPTILE_GITHUB_TOKEN = process.env.GITHUB_TOKEN;
|
|
702
|
+
}
|
|
703
|
+
const currentPath = process.env.PATH || "";
|
|
704
|
+
const pathEntries = currentPath.split(":").filter(Boolean);
|
|
705
|
+
for (const entry of [runtimeBin, runtimeWorkspaceBin, runtimeTools, "/usr/bin", "/bin", "/usr/sbin", "/sbin"]) {
|
|
706
|
+
if (existsSync3(entry) && !pathEntries.includes(entry)) {
|
|
707
|
+
pathEntries.unshift(entry);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
process.env.PATH = pathEntries.join(":");
|
|
711
|
+
if (!process.env.RIG_GIT_BIN) {
|
|
712
|
+
const runtimeGit = resolve3(runtimeBin, "git");
|
|
713
|
+
process.env.RIG_GIT_BIN = existsSync3(runtimeGit) ? runtimeGit : Bun.which("git") || "/usr/bin/git";
|
|
714
|
+
}
|
|
715
|
+
const knownHosts = ensureRuntimeKnownHosts(runtimeHome);
|
|
716
|
+
const agentKey = resolve3(runtimeHome, ".ssh", "rig-agent-key");
|
|
717
|
+
const sshParts = [
|
|
718
|
+
"ssh",
|
|
719
|
+
`-o UserKnownHostsFile="${knownHosts}"`,
|
|
720
|
+
"-o StrictHostKeyChecking=yes",
|
|
721
|
+
"-F /dev/null"
|
|
722
|
+
];
|
|
723
|
+
if (existsSync3(agentKey)) {
|
|
724
|
+
sshParts.splice(1, 0, `-i "${agentKey}"`, "-o IdentitiesOnly=yes");
|
|
725
|
+
}
|
|
726
|
+
process.env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
727
|
+
}
|
|
728
|
+
function inferRuntimeContextFileFromWorkspace(workspaceDir) {
|
|
729
|
+
const candidate = resolve3(workspaceDir, "..", "runtime-context.json");
|
|
730
|
+
return existsSync3(candidate) ? candidate : "";
|
|
731
|
+
}
|
|
732
|
+
async function main() {
|
|
733
|
+
const args = process.argv.slice(2);
|
|
734
|
+
hydrateRuntimeProcessEnv(getContext());
|
|
735
|
+
if (isVersionProbe(args)) {
|
|
736
|
+
await printVersion();
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (args[0] === "internal") {
|
|
740
|
+
await runInternal(args.slice(1));
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
const ctx = getContext();
|
|
744
|
+
if (!BAKED_PROJECT_ROOT && !ctx) {
|
|
745
|
+
console.error("[rig-agent] Runtime binary is missing baked task context and no runtime context file found.");
|
|
746
|
+
console.error("[rig-agent] Set RIG_RUNTIME_CONTEXT_FILE or use the compiled host dispatch binary.");
|
|
747
|
+
process.exit(1);
|
|
748
|
+
}
|
|
749
|
+
await verifyRuntimeManifest();
|
|
750
|
+
const commandResult = await runAgentCommand(args);
|
|
751
|
+
if (commandResult !== undefined) {
|
|
752
|
+
process.exit(commandResult);
|
|
753
|
+
}
|
|
754
|
+
if (looksLikeShellInvocation(args)) {
|
|
755
|
+
const code = await runControlledBash(args, { projectRootFallbackDir: import.meta.dir });
|
|
756
|
+
process.exit(code);
|
|
757
|
+
}
|
|
758
|
+
console.error(`[rig-agent] Unknown command: ${args[0] || "(none)"}. Run 'rig-agent help' for usage.`);
|
|
759
|
+
process.exit(1);
|
|
760
|
+
}
|
|
761
|
+
function isVersionProbe(args) {
|
|
762
|
+
if (args.length !== 1) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
return args[0] === "--version" || args[0] === "-v" || args[0] === "version";
|
|
766
|
+
}
|
|
767
|
+
async function printVersion() {
|
|
768
|
+
const probe = await Bun.$`claude --version`.cwd(process.cwd()).env(process.env).quiet().nothrow();
|
|
769
|
+
if (probe.exitCode === 0) {
|
|
770
|
+
const output = probe.stdout.toString().trim();
|
|
771
|
+
if (output) {
|
|
772
|
+
console.log(output);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
console.log("rig-agent 1.0.0");
|
|
777
|
+
}
|
|
778
|
+
async function runAgentCommand(args) {
|
|
779
|
+
const [command, ...rest] = args;
|
|
780
|
+
if (!command || !TASK_COMMANDS.has(command)) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
const ctx = getContext();
|
|
784
|
+
const projectRoot = ctx?.workspaceDir || BAKED_PROJECT_ROOT || "";
|
|
785
|
+
const taskId = ctx?.taskId || BAKED_TASK_ID || "";
|
|
786
|
+
if (!projectRoot) {
|
|
787
|
+
console.error("[rig-agent] No project root baked in.");
|
|
788
|
+
return 1;
|
|
789
|
+
}
|
|
790
|
+
if (!taskId) {
|
|
791
|
+
console.error("[rig-agent] No task ID baked in.");
|
|
792
|
+
return 1;
|
|
793
|
+
}
|
|
794
|
+
try {
|
|
795
|
+
switch (command) {
|
|
796
|
+
case "info":
|
|
797
|
+
await taskInfo(projectRoot, taskId);
|
|
798
|
+
return 0;
|
|
799
|
+
case "scope":
|
|
800
|
+
await taskScope(projectRoot, rest.includes("--files"), taskId);
|
|
801
|
+
return 0;
|
|
802
|
+
case "deps":
|
|
803
|
+
await taskDeps(projectRoot, taskId);
|
|
804
|
+
return 0;
|
|
805
|
+
case "status":
|
|
806
|
+
taskStatus(projectRoot);
|
|
807
|
+
return 0;
|
|
808
|
+
case "artifacts":
|
|
809
|
+
taskArtifacts(projectRoot, taskId);
|
|
810
|
+
return 0;
|
|
811
|
+
case "artifact-dir":
|
|
812
|
+
console.log(taskArtifactDir(projectRoot, taskId));
|
|
813
|
+
return 0;
|
|
814
|
+
case "project-root":
|
|
815
|
+
console.log(projectRoot);
|
|
816
|
+
return 0;
|
|
817
|
+
case "monorepo-root":
|
|
818
|
+
console.log(resolveMonorepoRoot(projectRoot));
|
|
819
|
+
return 0;
|
|
820
|
+
case "artifact-write": {
|
|
821
|
+
const filename = rest[0];
|
|
822
|
+
if (!filename) {
|
|
823
|
+
console.error(`Usage: rig-agent artifact-write <filename> [--file <path>]
|
|
824
|
+
` + ` Reads content from stdin (or --file), writes to the active task artifact dir.
|
|
825
|
+
` + " Example: echo '...' | rig-agent artifact-write collection-audit.md");
|
|
826
|
+
return 1;
|
|
827
|
+
}
|
|
828
|
+
let content;
|
|
829
|
+
const fileIdx = rest.indexOf("--file");
|
|
830
|
+
const inputFile = fileIdx !== -1 ? rest[fileIdx + 1] : undefined;
|
|
831
|
+
if (inputFile) {
|
|
832
|
+
content = readFileSync2(resolve3(projectRoot, inputFile), "utf-8");
|
|
833
|
+
} else {
|
|
834
|
+
const chunks = [];
|
|
835
|
+
for await (const chunk of process.stdin) {
|
|
836
|
+
chunks.push(Buffer.from(chunk));
|
|
837
|
+
}
|
|
838
|
+
content = Buffer.concat(chunks).toString("utf-8");
|
|
839
|
+
}
|
|
840
|
+
taskArtifactWrite(projectRoot, filename, content, taskId);
|
|
841
|
+
return 0;
|
|
842
|
+
}
|
|
843
|
+
case "validate": {
|
|
844
|
+
const passed = await taskValidate(projectRoot, taskId);
|
|
845
|
+
return passed ? 0 : 1;
|
|
846
|
+
}
|
|
847
|
+
case "completion-verification":
|
|
848
|
+
case "completition-verification":
|
|
849
|
+
return await runCompletionVerification(projectRoot);
|
|
850
|
+
case "lookup": {
|
|
851
|
+
if (rest.length !== 1) {
|
|
852
|
+
console.error("Usage: rig-agent lookup <beads-id>");
|
|
853
|
+
return 1;
|
|
854
|
+
}
|
|
855
|
+
const lookupId = rest[0];
|
|
856
|
+
if (!lookupId) {
|
|
857
|
+
console.error("Usage: rig-agent lookup <beads-id>");
|
|
858
|
+
return 1;
|
|
859
|
+
}
|
|
860
|
+
console.log(taskLookup(projectRoot, lookupId));
|
|
861
|
+
return 0;
|
|
862
|
+
}
|
|
863
|
+
case "record": {
|
|
864
|
+
if (rest.length < 2) {
|
|
865
|
+
console.error("Usage: rig-agent record <decision|failure> <text>");
|
|
866
|
+
return 1;
|
|
867
|
+
}
|
|
868
|
+
const type = rest[0];
|
|
869
|
+
if (type !== "decision" && type !== "failure") {
|
|
870
|
+
console.error("Usage: rig-agent record <decision|failure> <text>");
|
|
871
|
+
return 1;
|
|
872
|
+
}
|
|
873
|
+
taskRecord(projectRoot, type, rest.slice(1).join(" "), taskId);
|
|
874
|
+
return 0;
|
|
875
|
+
}
|
|
876
|
+
case "memory": {
|
|
877
|
+
const memoryService = await loadCapabilityForRoot2(projectRoot, defineCapability4(MEMORY));
|
|
878
|
+
if (!memoryService) {
|
|
879
|
+
console.error("[rig-agent] Shared memory requires the @rig/memory-plugin plugin in rig.config.");
|
|
880
|
+
return 1;
|
|
881
|
+
}
|
|
882
|
+
const eventBus = getEventBus();
|
|
883
|
+
console.log(await memoryService.executeMemoryCommand({
|
|
884
|
+
projectRoot,
|
|
885
|
+
taskId,
|
|
886
|
+
runtimeContext: ctx,
|
|
887
|
+
args: rest,
|
|
888
|
+
...eventBus ? { eventBus } : {}
|
|
889
|
+
}));
|
|
890
|
+
return 0;
|
|
891
|
+
}
|
|
892
|
+
case "git":
|
|
893
|
+
await runGitCommand(projectRoot, taskId, rest);
|
|
894
|
+
return 0;
|
|
895
|
+
case "repo":
|
|
896
|
+
case "repo-sync":
|
|
897
|
+
runRepoSyncCommand(projectRoot, taskId, rest);
|
|
898
|
+
return 0;
|
|
899
|
+
case "profile":
|
|
900
|
+
runProfileCommand(projectRoot, rest);
|
|
901
|
+
return 0;
|
|
902
|
+
case "review":
|
|
903
|
+
runReviewCommand(projectRoot, rest);
|
|
904
|
+
return 0;
|
|
905
|
+
case "help":
|
|
906
|
+
printAgentHelp();
|
|
907
|
+
return 0;
|
|
908
|
+
default:
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
} catch (error) {
|
|
912
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
913
|
+
return 1;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
async function runGitCommand(projectRoot, bakedTaskId, args) {
|
|
917
|
+
const [sub = "status", ...rest] = args;
|
|
918
|
+
const task = takeOption(rest, "--task");
|
|
919
|
+
const tid = task.value || bakedTaskId;
|
|
920
|
+
const flags = task.rest;
|
|
921
|
+
const git = await loadLifecycleGit(projectRoot);
|
|
922
|
+
switch (sub) {
|
|
923
|
+
case "status":
|
|
924
|
+
git.gitStatus(projectRoot, tid);
|
|
925
|
+
return;
|
|
926
|
+
case "changed": {
|
|
927
|
+
const scoped = flags.includes("--scoped");
|
|
928
|
+
const files = git.gitChanged(projectRoot, tid, scoped);
|
|
929
|
+
console.log(files.length > 0 ? files.join(`
|
|
930
|
+
`) : "(none)");
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
case "preflight": {
|
|
934
|
+
const strict = flags.includes("--strict");
|
|
935
|
+
const ok = git.gitPreflight(projectRoot, tid, strict);
|
|
936
|
+
if (!ok)
|
|
937
|
+
throw new Error("Git preflight failed.");
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
case "sync-branch":
|
|
941
|
+
case "ensure-branch":
|
|
942
|
+
git.gitSyncBranch(projectRoot, tid);
|
|
943
|
+
return;
|
|
944
|
+
case "commit": {
|
|
945
|
+
const target = takeOption(flags, "--target");
|
|
946
|
+
const message = takeOption(target.rest, "--message");
|
|
947
|
+
const allowEmpty = message.rest.includes("--allow-empty");
|
|
948
|
+
const scoped = git.shouldScopeGitCommit(message.rest, Boolean(tid));
|
|
949
|
+
git.gitCommit({
|
|
950
|
+
projectRoot,
|
|
951
|
+
taskId: tid,
|
|
952
|
+
target: target.value || "monorepo",
|
|
953
|
+
allowEmpty,
|
|
954
|
+
scoped,
|
|
955
|
+
...message.value ? { message: message.value } : {}
|
|
956
|
+
});
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
case "snapshot": {
|
|
960
|
+
const output = takeOption(flags, "--output");
|
|
961
|
+
const file = git.gitSnapshot(projectRoot, tid, output.value);
|
|
962
|
+
console.log(`Snapshot written: ${file}`);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
case "open-pr": {
|
|
966
|
+
const target = takeOption(flags, "--target");
|
|
967
|
+
const reviewer = takeOption(target.rest, "--reviewer");
|
|
968
|
+
const base = takeOption(reviewer.rest, "--base");
|
|
969
|
+
const title = takeOption(base.rest, "--title");
|
|
970
|
+
const body = takeOption(title.rest, "--body");
|
|
971
|
+
const draft = body.rest.includes("--draft");
|
|
972
|
+
const result = git.gitOpenPr({
|
|
973
|
+
projectRoot,
|
|
974
|
+
taskId: tid,
|
|
975
|
+
...target.value ? { target: target.value } : {},
|
|
976
|
+
...reviewer.value ? { reviewer: reviewer.value } : {},
|
|
977
|
+
...base.value ? { base: base.value } : {},
|
|
978
|
+
...title.value ? { title: title.value } : {},
|
|
979
|
+
...body.value ? { body: body.value } : {},
|
|
980
|
+
draft
|
|
981
|
+
});
|
|
982
|
+
console.log(`PR ready (${result.repoLabel}): ${result.url}`);
|
|
983
|
+
console.log(`Reviewer assigned: ${result.reviewer} (${result.reviewerSource})`);
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
default:
|
|
987
|
+
throw new Error(`Unknown git subcommand: ${sub}. Try: status, changed, preflight, sync-branch, commit, snapshot, open-pr`);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function runRepoSyncCommand(projectRoot, bakedTaskId, args) {
|
|
991
|
+
const [sub = "ensure", ...rest] = args;
|
|
992
|
+
const task = takeOption(rest, "--task");
|
|
993
|
+
const tid = task.value || bakedTaskId;
|
|
994
|
+
switch (sub) {
|
|
995
|
+
case "sync":
|
|
996
|
+
case "ensure":
|
|
997
|
+
repoEnsure(projectRoot, tid);
|
|
998
|
+
return;
|
|
999
|
+
case "pins": {
|
|
1000
|
+
const pins = repoPins(projectRoot, tid);
|
|
1001
|
+
printPins(pins);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
case "verify": {
|
|
1005
|
+
const ok = repoVerify(projectRoot, tid);
|
|
1006
|
+
if (!ok)
|
|
1007
|
+
throw new Error("Repo pin verification failed.");
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
case "discover": {
|
|
1011
|
+
const pins = repoDiscover(projectRoot, tid);
|
|
1012
|
+
printPins(pins);
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
case "baseline": {
|
|
1016
|
+
const refresh = task.rest.includes("--refresh");
|
|
1017
|
+
const pins = repoBaseline(projectRoot, refresh);
|
|
1018
|
+
printPins(pins);
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
default:
|
|
1022
|
+
throw new Error(`Unknown repo subcommand: ${sub}. Try: sync, ensure, pins, verify, discover, baseline`);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
function runProfileCommand(projectRoot, args) {
|
|
1026
|
+
const [sub = "show", ...rest] = args;
|
|
1027
|
+
if (sub === "show") {
|
|
1028
|
+
showProfile(projectRoot, rest.includes("--compact"));
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
if (sub === "set") {
|
|
1032
|
+
const first = rest[0];
|
|
1033
|
+
if (first === "claude-code" || first === "codex-cli" || first === "codex-app-server") {
|
|
1034
|
+
setProfile(projectRoot, { preset: first });
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
const model = takeOption(rest, "--model");
|
|
1038
|
+
const runtime = takeOption(model.rest, "--runtime");
|
|
1039
|
+
const plugin = takeOption(runtime.rest, "--plugin");
|
|
1040
|
+
setProfile(projectRoot, {
|
|
1041
|
+
...model.value ? { model: model.value } : {},
|
|
1042
|
+
...runtime.value ? { runtime: runtime.value } : {},
|
|
1043
|
+
...plugin.value ? { plugin: plugin.value } : {}
|
|
1044
|
+
});
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
throw new Error(`Unknown profile subcommand: ${sub}. Try: show, set`);
|
|
1048
|
+
}
|
|
1049
|
+
function runReviewCommand(projectRoot, args) {
|
|
1050
|
+
const [sub = "show", ...rest] = args;
|
|
1051
|
+
if (sub === "show") {
|
|
1052
|
+
showReviewProfile(projectRoot);
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
if (sub === "set") {
|
|
1056
|
+
const mode = rest[0];
|
|
1057
|
+
if (!mode) {
|
|
1058
|
+
throw new Error("Usage: rig-agent review set <off|advisory|required> [--provider github|greptile]");
|
|
1059
|
+
}
|
|
1060
|
+
const provider = takeOption(rest.slice(1), "--provider");
|
|
1061
|
+
setReviewProfile(projectRoot, mode, provider.value);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
throw new Error(`Unknown review subcommand: ${sub}. Try: show, set`);
|
|
1065
|
+
}
|
|
1066
|
+
function takeOption(args, option) {
|
|
1067
|
+
const rest = [];
|
|
1068
|
+
let value;
|
|
1069
|
+
for (let i = 0;i < args.length; i += 1) {
|
|
1070
|
+
const current = args[i];
|
|
1071
|
+
if (current === option) {
|
|
1072
|
+
const next = args[i + 1];
|
|
1073
|
+
if (!next || next.startsWith("-")) {
|
|
1074
|
+
throw new Error(`Missing value for ${option}`);
|
|
1075
|
+
}
|
|
1076
|
+
value = next;
|
|
1077
|
+
i += 1;
|
|
1078
|
+
continue;
|
|
1079
|
+
}
|
|
1080
|
+
if (current !== undefined) {
|
|
1081
|
+
rest.push(current);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return { value, rest };
|
|
1085
|
+
}
|
|
1086
|
+
function printPins(pins) {
|
|
1087
|
+
if (Object.keys(pins).length === 0) {
|
|
1088
|
+
console.log("(none)");
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
for (const [key, value] of Object.entries(pins)) {
|
|
1092
|
+
console.log(`${key} ${value}`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
function printAgentHelp() {
|
|
1096
|
+
console.log(`rig-agent \u2014 CLI for Project Rig agents
|
|
1097
|
+
|
|
1098
|
+
ORIENTATION:
|
|
1099
|
+
rig-agent info Your task, role, scope, deps \u2014 start here
|
|
1100
|
+
rig-agent scope [--files] Scope globs; --files expands to file list
|
|
1101
|
+
rig-agent deps Read dependency artifacts (decisions, next-actions)
|
|
1102
|
+
rig-agent lookup <id> Validate a beads task ID
|
|
1103
|
+
rig-agent status Epic/task progress overview
|
|
1104
|
+
|
|
1105
|
+
EXECUTION:
|
|
1106
|
+
rig-agent validate Run validation commands for your task
|
|
1107
|
+
rig-agent record decision "..." Record an architectural decision
|
|
1108
|
+
rig-agent record failure "..." Record a failed approach (cross-session only \u2014 not re-read in this session)
|
|
1109
|
+
rig-agent memory observe ... Promote a shared memory immediately
|
|
1110
|
+
rig-agent memory recall [query] Recall relevant shared memories
|
|
1111
|
+
rig-agent git status Task-aware git status
|
|
1112
|
+
rig-agent git changed Changed files (--scoped for scope-filtered)
|
|
1113
|
+
rig-agent git commit Task-aware commit (--target monorepo|project|both)
|
|
1114
|
+
rig-agent git snapshot Capture worktree state
|
|
1115
|
+
rig-agent git sync-branch Ensure task branch exists
|
|
1116
|
+
rig-agent git open-pr Create PR for task changes
|
|
1117
|
+
rig-agent repo sync Ensure monorepo checkout + task repo pins
|
|
1118
|
+
rig-agent profile show Show runtime profile
|
|
1119
|
+
rig-agent review show Show AI review gate settings
|
|
1120
|
+
|
|
1121
|
+
COMPLETION:
|
|
1122
|
+
rig-agent artifacts Scaffold completion artifacts (templates)
|
|
1123
|
+
rig-agent artifact-dir Print absolute artifact directory path
|
|
1124
|
+
rig-agent project-root Print absolute task worktree root
|
|
1125
|
+
rig-agent monorepo-root Print absolute monorepo root in the task worktree
|
|
1126
|
+
rig-agent artifact-write <filename> Write artifact from stdin
|
|
1127
|
+
rig-agent completion-verification Run final validation/review gate
|
|
1128
|
+
rig-agent completition-verification Alias for the same final gate
|
|
1129
|
+
|
|
1130
|
+
WORKFLOW:
|
|
1131
|
+
1. rig-agent info Understand your assignment
|
|
1132
|
+
2. rig-agent deps Read what prior tasks decided
|
|
1133
|
+
3. rig-agent repo sync Align monorepo checkout + repo pins
|
|
1134
|
+
4. (do your work)
|
|
1135
|
+
5. rig-agent record decision "chose X because Y"
|
|
1136
|
+
6. rig-agent validate Check your work
|
|
1137
|
+
7. rig-agent artifacts Scaffold completion artifacts
|
|
1138
|
+
8. rig-agent artifact-write collection-audit.md (write custom artifacts)
|
|
1139
|
+
9. rig-agent completion-verification
|
|
1140
|
+
`);
|
|
1141
|
+
}
|
|
1142
|
+
async function runCompletionVerification(projectRoot) {
|
|
1143
|
+
const host = await buildProjectPluginHost(projectRoot);
|
|
1144
|
+
const run = host ? await defineCapability4(COMPLETION_VERIFICATION_CAPABILITY).resolve(host) : null;
|
|
1145
|
+
if (!run) {
|
|
1146
|
+
console.error("[rig-agent] Completion verification requires the @rig/bundle-default-lifecycle plugin in rig.config.");
|
|
1147
|
+
return 1;
|
|
1148
|
+
}
|
|
1149
|
+
const { ok } = await run({ projectRoot });
|
|
1150
|
+
return ok ? 0 : 1;
|
|
1151
|
+
}
|
|
1152
|
+
async function runInternal(args) {
|
|
1153
|
+
const [command = "", ...rest] = args;
|
|
1154
|
+
if (command === "shell") {
|
|
1155
|
+
const code = await runControlledBash(rest, { projectRootFallbackDir: import.meta.dir });
|
|
1156
|
+
process.exit(code);
|
|
1157
|
+
}
|
|
1158
|
+
if (command === "manifest-verify") {
|
|
1159
|
+
await verifyRuntimeManifest();
|
|
1160
|
+
console.log("manifest: ok");
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
throw new Error("Unknown internal command. Use `rig-agent internal shell <bash-args...>` or `rig-agent internal manifest-verify`.");
|
|
1164
|
+
}
|
|
1165
|
+
async function verifyRuntimeManifest() {
|
|
1166
|
+
if (getContext()) {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const manifestPath = BAKED_MANIFEST_PATH;
|
|
1170
|
+
if (!manifestPath) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
if (!existsSync3(manifestPath)) {
|
|
1174
|
+
throw new Error(`[rig-agent] Runtime manifest missing: ${manifestPath}`);
|
|
1175
|
+
}
|
|
1176
|
+
let manifest;
|
|
1177
|
+
try {
|
|
1178
|
+
manifest = await Bun.file(manifestPath).json();
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
throw new Error(`[rig-agent] Failed to parse runtime manifest at ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1181
|
+
}
|
|
1182
|
+
assertMatch("taskId", BAKED_TASK_ID, manifest.taskId);
|
|
1183
|
+
assertMatch("runtimeId", BAKED_RUNTIME_ID, manifest.runtimeId);
|
|
1184
|
+
assertMatch("scopeHash", BAKED_SCOPE_HASH, manifest.scopeHash);
|
|
1185
|
+
const manifestBinaryPath = manifest.binary?.path || BAKED_BINARY_PATH || process.execPath;
|
|
1186
|
+
const expectedHash = manifest.binary?.sha256 || "";
|
|
1187
|
+
if (!manifestBinaryPath || !expectedHash) {
|
|
1188
|
+
throw new Error(`[rig-agent] Runtime manifest is missing binary hash data (${manifestPath}).`);
|
|
1189
|
+
}
|
|
1190
|
+
if (!existsSync3(manifestBinaryPath)) {
|
|
1191
|
+
throw new Error(`[rig-agent] Runtime binary not found at ${manifestBinaryPath}.`);
|
|
1192
|
+
}
|
|
1193
|
+
const actualHash = sha256Hex(readFileSync2(resolve3(manifestBinaryPath)));
|
|
1194
|
+
if (actualHash !== expectedHash) {
|
|
1195
|
+
throw new Error(`[rig-agent] Runtime manifest mismatch for binary hash.
|
|
1196
|
+
` + `expected=${expectedHash}
|
|
1197
|
+
` + `actual=${actualHash}
|
|
1198
|
+
` + `path=${manifestBinaryPath}`);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
function assertMatch(name, expected, actual) {
|
|
1202
|
+
if (!expected && !actual) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
if (expected !== (actual || "")) {
|
|
1206
|
+
throw new Error(`[rig-agent] Runtime manifest mismatch for ${name}: expected='${expected}' actual='${actual || ""}'.`);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
var BUILD_CONFIG, BAKED_BINARY_PATH, BAKED_MANIFEST_PATH, BAKED_PROJECT_ROOT, BAKED_RUNTIME_ID, BAKED_TASK_ID, BAKED_SCOPE_HASH, BAKED_INFO_OUTPUT, BAKED_DEPS_OUTPUT, BAKED_STATUS_OUTPUT, BAKED_GIT_BRANCH, BAKED_BASE_COMMIT, cachedContext, cachedEventBus, GITHUB_KNOWN_HOSTS, TASK_COMMANDS;
|
|
1210
|
+
var init_rig_agent = __esm(() => {
|
|
1211
|
+
init_controlled_bash();
|
|
1212
|
+
init_git_ops();
|
|
1213
|
+
init_repo_ops();
|
|
1214
|
+
init_task_ops();
|
|
1215
|
+
BUILD_CONFIG = readBuildConfig();
|
|
1216
|
+
BAKED_BINARY_PATH = BUILD_CONFIG.AGENT_BINARY_PATH ?? "";
|
|
1217
|
+
BAKED_MANIFEST_PATH = BUILD_CONFIG.AGENT_MANIFEST_PATH ?? "";
|
|
1218
|
+
BAKED_PROJECT_ROOT = BUILD_CONFIG.AGENT_PROJECT_ROOT ?? "";
|
|
1219
|
+
BAKED_RUNTIME_ID = BUILD_CONFIG.AGENT_RUNTIME_ID ?? "";
|
|
1220
|
+
BAKED_TASK_ID = BUILD_CONFIG.AGENT_TASK_ID ?? "";
|
|
1221
|
+
BAKED_SCOPE_HASH = BUILD_CONFIG.AGENT_SCOPE_HASH ?? "";
|
|
1222
|
+
BAKED_INFO_OUTPUT = BUILD_CONFIG.AGENT_INFO_OUTPUT ?? "";
|
|
1223
|
+
BAKED_DEPS_OUTPUT = BUILD_CONFIG.AGENT_DEPS_OUTPUT ?? "";
|
|
1224
|
+
BAKED_STATUS_OUTPUT = BUILD_CONFIG.AGENT_STATUS_OUTPUT ?? "";
|
|
1225
|
+
BAKED_GIT_BRANCH = BUILD_CONFIG.AGENT_GIT_BRANCH ?? "";
|
|
1226
|
+
BAKED_BASE_COMMIT = BUILD_CONFIG.AGENT_BASE_COMMIT ?? "";
|
|
1227
|
+
if (BAKED_BINARY_PATH) {
|
|
1228
|
+
const binaryDir = dirname2(BAKED_BINARY_PATH);
|
|
1229
|
+
const currentPath = process.env.PATH || "";
|
|
1230
|
+
const pathEntries = currentPath.split(":").filter(Boolean);
|
|
1231
|
+
if (!pathEntries.includes(binaryDir)) {
|
|
1232
|
+
process.env.PATH = currentPath ? `${binaryDir}:${currentPath}` : binaryDir;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
GITHUB_KNOWN_HOSTS = [
|
|
1236
|
+
"github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl",
|
|
1237
|
+
"github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=",
|
|
1238
|
+
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
|
|
1239
|
+
];
|
|
1240
|
+
TASK_COMMANDS = new Set([
|
|
1241
|
+
"info",
|
|
1242
|
+
"scope",
|
|
1243
|
+
"deps",
|
|
1244
|
+
"status",
|
|
1245
|
+
"artifacts",
|
|
1246
|
+
"artifact-dir",
|
|
1247
|
+
"artifact-write",
|
|
1248
|
+
"project-root",
|
|
1249
|
+
"monorepo-root",
|
|
1250
|
+
"validate",
|
|
1251
|
+
"lookup",
|
|
1252
|
+
"record",
|
|
1253
|
+
"help",
|
|
1254
|
+
"completion-verification",
|
|
1255
|
+
"completition-verification",
|
|
1256
|
+
"git",
|
|
1257
|
+
"repo",
|
|
1258
|
+
"repo-sync",
|
|
1259
|
+
"profile",
|
|
1260
|
+
"review",
|
|
1261
|
+
"memory"
|
|
1262
|
+
]);
|
|
1263
|
+
main().catch((error) => {
|
|
1264
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1265
|
+
process.exit(1);
|
|
1266
|
+
});
|
|
1267
|
+
});
|
|
1268
|
+
|
|
1269
|
+
// packages/provider-plugin/src/agent-harness/rig-agent-entrypoint.ts
|
|
1270
|
+
import { adopt } from "@rig/core/kernel-entrypoint";
|
|
1271
|
+
async function runRigAgentEntrypoint() {
|
|
1272
|
+
await adopt(undefined, { entrypoint: "rig-agent" });
|
|
1273
|
+
await Promise.resolve().then(() => (init_rig_agent(), exports_rig_agent));
|
|
1274
|
+
}
|
|
1275
|
+
export {
|
|
1276
|
+
runRigAgentEntrypoint
|
|
1277
|
+
};
|