@h-rig/runtime 0.0.6-alpha.1 → 0.0.6-alpha.11
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.js +133 -14
- package/dist/bin/rig-agent.js +83 -26
- package/dist/src/control-plane/agent-wrapper.js +133 -14
- package/dist/src/control-plane/harness-main.js +83 -26
- package/dist/src/control-plane/hooks/completion-verification.js +85 -28
- package/dist/src/control-plane/hooks/inject-context.js +2 -2
- package/dist/src/control-plane/hooks/submodule-branch.js +26 -3
- package/dist/src/control-plane/hooks/task-runtime-start.js +26 -3
- package/dist/src/control-plane/native/git-ops.js +81 -24
- package/dist/src/control-plane/native/harness-cli.js +83 -26
- package/dist/src/control-plane/native/pr-automation.js +87 -16
- package/dist/src/control-plane/native/run-ops.js +23 -6
- package/dist/src/control-plane/native/task-ops.js +2 -2
- package/dist/src/control-plane/native/validator.js +2 -2
- package/dist/src/control-plane/native/verifier.js +2 -2
- package/dist/src/control-plane/runtime/index.js +38 -9
- package/dist/src/control-plane/runtime/isolation/home.js +31 -6
- package/dist/src/control-plane/runtime/isolation/index.js +38 -9
- package/dist/src/control-plane/runtime/isolation/runner.js +31 -6
- package/dist/src/control-plane/runtime/isolation/shared.js +9 -6
- package/dist/src/control-plane/runtime/isolation.js +38 -9
- package/dist/src/control-plane/runtime/queue.js +38 -9
- package/dist/src/control-plane/tasks/source-aware-task-config-source.js +14 -2
- package/dist/src/control-plane/tasks/source-lifecycle.js +2 -2
- package/dist/src/index.js +15 -13
- package/dist/src/local-server.js +20 -14
- package/native/darwin-arm64/{bin/rig-git → rig-git} +0 -0
- package/native/darwin-arm64/rig-git.build-manifest.json +4 -0
- package/native/darwin-arm64/{bin/rig-shell → rig-shell} +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +4 -0
- package/native/darwin-arm64/{bin/rig-tools → rig-tools} +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +4 -0
- package/native/darwin-arm64/{lib/runtime-native.dylib → runtime-native.dylib} +0 -0
- package/package.json +6 -6
- package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
- package/native/darwin-arm64/manifest.json +0 -1
- package/native/linux-x64/bin/rig-git +0 -0
- package/native/linux-x64/bin/rig-shell +0 -0
- package/native/linux-x64/bin/rig-tools +0 -0
- package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
- package/native/linux-x64/lib/runtime-native.so +0 -0
- package/native/linux-x64/manifest.json +0 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { appendFileSync as appendFileSync2, existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
6
6
|
import { resolve as resolve24 } from "path";
|
|
7
7
|
import {
|
|
8
|
-
escapeRegExp,
|
|
8
|
+
escapeRegExp as escapeRegExp2,
|
|
9
9
|
resolveBunCli,
|
|
10
10
|
resolveBunCliInvocation,
|
|
11
11
|
resolveProjectRoot,
|
|
@@ -2645,8 +2645,8 @@ function ensureStatusLabel(bin, repo, spawnFn, label) {
|
|
|
2645
2645
|
}
|
|
2646
2646
|
}
|
|
2647
2647
|
function selectedGitHubEnv() {
|
|
2648
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
2649
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
2648
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
2649
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
2650
2650
|
}
|
|
2651
2651
|
function ghSpawnOptions() {
|
|
2652
2652
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -5993,12 +5993,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
|
5993
5993
|
"task-result.json",
|
|
5994
5994
|
"validation-summary.json"
|
|
5995
5995
|
]);
|
|
5996
|
-
function resolveHostRigBinDir(root) {
|
|
5997
|
-
return resolve23(root, ".rig", "bin");
|
|
5998
|
-
}
|
|
5999
5996
|
function isRuntimeGatewayGitPath(candidate) {
|
|
6000
5997
|
return /\/\.rig\/bin\/git$/.test(candidate.replace(/\\/g, "/"));
|
|
6001
5998
|
}
|
|
5999
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
6000
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
6001
|
+
}
|
|
6002
6002
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
6003
6003
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6004
6004
|
if (runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
|
|
@@ -6033,6 +6033,9 @@ function resolveGitBinary(projectRoot) {
|
|
|
6033
6033
|
}
|
|
6034
6034
|
return "git";
|
|
6035
6035
|
}
|
|
6036
|
+
function escapeRegExp(value) {
|
|
6037
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6038
|
+
}
|
|
6036
6039
|
function safeCurrentTaskId(projectRoot) {
|
|
6037
6040
|
try {
|
|
6038
6041
|
const taskId = currentTaskId(projectRoot);
|
|
@@ -6101,17 +6104,15 @@ function gitOpenPr(options) {
|
|
|
6101
6104
|
const target = options.target || (taskId ? "monorepo" : "project");
|
|
6102
6105
|
let repoRoot = options.projectRoot;
|
|
6103
6106
|
let repoLabel = "project-rig";
|
|
6104
|
-
|
|
6107
|
+
const envBase = target === "monorepo" ? process.env.RIG_PR_BASE_MONOREPO?.trim() || "" : process.env.RIG_PR_BASE_PROJECT?.trim() || "";
|
|
6105
6108
|
if (target === "monorepo") {
|
|
6106
6109
|
repoRoot = resolveOptionalMonorepoRoot(options.projectRoot) || resolveMonorepoRoot2(options.projectRoot);
|
|
6107
6110
|
repoLabel = "monorepo";
|
|
6108
|
-
defaultBase = process.env.RIG_PR_BASE_MONOREPO || "main";
|
|
6109
6111
|
if (taskId) {
|
|
6110
6112
|
gitSyncBranch(options.projectRoot, taskId, "monorepo");
|
|
6111
6113
|
}
|
|
6112
6114
|
} else if (taskId) {
|
|
6113
6115
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
6114
|
-
defaultBase = inferProjectBase(options.projectRoot, defaultBase);
|
|
6115
6116
|
}
|
|
6116
6117
|
if (!existsSync20(resolve23(repoRoot, ".git"))) {
|
|
6117
6118
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
@@ -6120,9 +6121,9 @@ function gitOpenPr(options) {
|
|
|
6120
6121
|
if (!branch || branch === "HEAD") {
|
|
6121
6122
|
throw new Error(`Cannot open PR from detached HEAD in ${repoLabel}. Checkout a branch first.`);
|
|
6122
6123
|
}
|
|
6123
|
-
const base = options.base || defaultBase;
|
|
6124
6124
|
const repoNameWithOwner = resolveRepoNameWithOwner(options.projectRoot, repoRoot);
|
|
6125
6125
|
const networkRemote = resolveNetworkRemoteName(options.projectRoot, repoRoot, repoNameWithOwner);
|
|
6126
|
+
const base = options.base || envBase || inferRepositoryDefaultBase(options.projectRoot, repoRoot, repoNameWithOwner, networkRemote, target === "project" ? inferProjectBase(options.projectRoot, "main") : "main");
|
|
6126
6127
|
refreshRemoteBaseRef(options.projectRoot, repoRoot, base);
|
|
6127
6128
|
let reviewer = (options.reviewer || "").trim();
|
|
6128
6129
|
let reviewerSource = reviewer ? "flag" : undefined;
|
|
@@ -6158,6 +6159,7 @@ function gitOpenPr(options) {
|
|
|
6158
6159
|
"",
|
|
6159
6160
|
"## Task",
|
|
6160
6161
|
`- beads: ${taskId || "n/a"}`,
|
|
6162
|
+
...defaultPrRunLines(taskId, repoNameWithOwner),
|
|
6161
6163
|
"",
|
|
6162
6164
|
"## Review",
|
|
6163
6165
|
"- Completion verification will run validation, verifier review, and PR policy checks.",
|
|
@@ -6249,6 +6251,29 @@ function gitOpenPr(options) {
|
|
|
6249
6251
|
}
|
|
6250
6252
|
return result;
|
|
6251
6253
|
}
|
|
6254
|
+
function defaultPrRunLines(taskId, repoNameWithOwner) {
|
|
6255
|
+
const lines = [];
|
|
6256
|
+
const runId = process.env.RIG_SERVER_RUN_ID?.trim();
|
|
6257
|
+
if (runId) {
|
|
6258
|
+
lines.push(`- Run: ${runId}`);
|
|
6259
|
+
}
|
|
6260
|
+
const closeout = defaultPrCloseoutLine(taskId, repoNameWithOwner);
|
|
6261
|
+
if (closeout) {
|
|
6262
|
+
lines.push(`- ${closeout}`);
|
|
6263
|
+
}
|
|
6264
|
+
return lines;
|
|
6265
|
+
}
|
|
6266
|
+
function defaultPrCloseoutLine(taskId, repoNameWithOwner) {
|
|
6267
|
+
const sourceIssueId = loadRuntimeContextFromEnv()?.sourceTask?.sourceIssueId;
|
|
6268
|
+
if (sourceIssueId) {
|
|
6269
|
+
const match = sourceIssueId.match(/^([^#]+)#(\d+)$/);
|
|
6270
|
+
if (match) {
|
|
6271
|
+
const [, sourceRepo, issueNumber] = match;
|
|
6272
|
+
return sourceRepo.toLowerCase() === repoNameWithOwner.toLowerCase() ? `Closes #${issueNumber}` : `Closes ${sourceRepo}#${issueNumber}`;
|
|
6273
|
+
}
|
|
6274
|
+
}
|
|
6275
|
+
return /^\d+$/.test(taskId) ? `Closes #${taskId}` : "";
|
|
6276
|
+
}
|
|
6252
6277
|
function resolveTaskBranchRef(projectRoot, taskId) {
|
|
6253
6278
|
return `rig/${resolveTaskBranchId(projectRoot, taskId)}`;
|
|
6254
6279
|
}
|
|
@@ -6495,32 +6520,19 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
6495
6520
|
if (explicit) {
|
|
6496
6521
|
candidates.add(explicit);
|
|
6497
6522
|
}
|
|
6523
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
6524
|
+
candidates.add(candidate);
|
|
6525
|
+
}
|
|
6498
6526
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
6499
6527
|
for (const entry of explicitPathEntries) {
|
|
6500
6528
|
candidates.add(resolve23(entry, "gh"));
|
|
6501
6529
|
}
|
|
6502
|
-
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
6503
|
-
if (hostProjectRoot) {
|
|
6504
|
-
candidates.add(resolve23(resolveHostRigBinDir(hostProjectRoot), "gh"));
|
|
6505
|
-
}
|
|
6506
|
-
candidates.add(resolve23(resolveHostRigBinDir(projectRoot), "gh"));
|
|
6507
|
-
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6508
|
-
if (runtimeContext?.binDir) {
|
|
6509
|
-
candidates.add(resolve23(runtimeContext.binDir, "gh"));
|
|
6510
|
-
}
|
|
6511
|
-
const runtimeHome = process.env.RIG_RUNTIME_HOME?.trim();
|
|
6512
|
-
if (runtimeHome) {
|
|
6513
|
-
candidates.add(resolve23(runtimeHome, "bin", "gh"));
|
|
6514
|
-
}
|
|
6515
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
6516
|
-
candidates.add(candidate);
|
|
6517
|
-
}
|
|
6518
6530
|
const bunResolved = Bun.which("gh");
|
|
6519
6531
|
if (bunResolved) {
|
|
6520
6532
|
candidates.add(bunResolved);
|
|
6521
6533
|
}
|
|
6522
6534
|
for (const candidate of candidates) {
|
|
6523
|
-
if (candidate && existsSync20(candidate)) {
|
|
6535
|
+
if (candidate && existsSync20(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
6524
6536
|
return candidate;
|
|
6525
6537
|
}
|
|
6526
6538
|
}
|
|
@@ -6669,6 +6681,32 @@ function withGhRepo(command, repoNameWithOwner) {
|
|
|
6669
6681
|
}
|
|
6670
6682
|
return [command[0], command[1], command[2], ...ghRepoArgs(repoNameWithOwner), ...command.slice(3)];
|
|
6671
6683
|
}
|
|
6684
|
+
function inferRepositoryDefaultBase(projectRoot, repoRoot, repoNameWithOwner, remoteName, fallback) {
|
|
6685
|
+
const remote = remoteName || "origin";
|
|
6686
|
+
const symbolic = runCapture2(gitCmd(projectRoot, repoRoot, "symbolic-ref", "--short", `refs/remotes/${remote}/HEAD`), projectRoot);
|
|
6687
|
+
if (symbolic.exitCode === 0) {
|
|
6688
|
+
const ref = symbolic.stdout.trim().replace(new RegExp(`^${escapeRegExp(remote)}/`), "");
|
|
6689
|
+
if (ref && ref !== "HEAD") {
|
|
6690
|
+
return ref;
|
|
6691
|
+
}
|
|
6692
|
+
}
|
|
6693
|
+
const lsRemote = runCapture2(gitCmd(projectRoot, repoRoot, "ls-remote", "--symref", remote, "HEAD"), projectRoot);
|
|
6694
|
+
if (lsRemote.exitCode === 0) {
|
|
6695
|
+
const match = lsRemote.stdout.match(/^ref:\s+refs\/heads\/([^\t\r\n]+)\s+HEAD/m);
|
|
6696
|
+
if (match?.[1]) {
|
|
6697
|
+
return match[1];
|
|
6698
|
+
}
|
|
6699
|
+
}
|
|
6700
|
+
const gh = resolveGithubCliBinary(projectRoot);
|
|
6701
|
+
if (gh && repoNameWithOwner) {
|
|
6702
|
+
const api = runCapture2(withGhRepo([gh, "repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"], repoNameWithOwner), repoRoot);
|
|
6703
|
+
const branch = api.exitCode === 0 ? api.stdout.trim() : "";
|
|
6704
|
+
if (branch) {
|
|
6705
|
+
return branch;
|
|
6706
|
+
}
|
|
6707
|
+
}
|
|
6708
|
+
return fallback;
|
|
6709
|
+
}
|
|
6672
6710
|
function inferProjectBase(projectRoot, fallback) {
|
|
6673
6711
|
const containing = runCapture2(gitCmd(projectRoot, projectRoot, "branch", "-r", "--contains", "HEAD"), projectRoot);
|
|
6674
6712
|
if (containing.exitCode !== 0) {
|
|
@@ -7013,6 +7051,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7013
7051
|
}
|
|
7014
7052
|
env[key] = value;
|
|
7015
7053
|
}
|
|
7054
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
7055
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
7056
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
7057
|
+
}
|
|
7016
7058
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
7017
7059
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
7018
7060
|
}
|
|
@@ -7036,6 +7078,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7036
7078
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
7037
7079
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
7038
7080
|
}
|
|
7081
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
7082
|
+
if (gitHubToken) {
|
|
7083
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
7084
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
7085
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
7086
|
+
applyGitHubCredentialHelperEnv(env);
|
|
7087
|
+
}
|
|
7039
7088
|
if (runtimeKnownHosts && existsSync20(runtimeKnownHosts)) {
|
|
7040
7089
|
const sshParts = [
|
|
7041
7090
|
"ssh",
|
|
@@ -7052,6 +7101,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7052
7101
|
}
|
|
7053
7102
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
7054
7103
|
}
|
|
7104
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
7105
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
7106
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
7107
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
7108
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
7109
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
7110
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
7111
|
+
}
|
|
7055
7112
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
7056
7113
|
if (!runtimeRoot) {
|
|
7057
7114
|
return {};
|
|
@@ -7493,7 +7550,7 @@ async function recordVerifierFailure(projectRoot, taskId, paths) {
|
|
|
7493
7550
|
let attempts = 1;
|
|
7494
7551
|
if (existsSync21(failedApproachesPath)) {
|
|
7495
7552
|
const content = readFileSync12(failedApproachesPath, "utf-8");
|
|
7496
|
-
attempts = (content.match(new RegExp(`^## ${
|
|
7553
|
+
attempts = (content.match(new RegExp(`^## ${escapeRegExp2(taskId)}\\b`, "gm")) || []).length + 1;
|
|
7497
7554
|
} else {
|
|
7498
7555
|
mkdirSync11(resolve24(failedApproachesPath, ".."), { recursive: true });
|
|
7499
7556
|
writeFileSync11(failedApproachesPath, `# Failed Approaches
|
|
@@ -2484,8 +2484,8 @@ function githubStatusFor(issue) {
|
|
|
2484
2484
|
return "open";
|
|
2485
2485
|
}
|
|
2486
2486
|
function selectedGitHubEnv() {
|
|
2487
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
2488
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
2487
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
2488
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
2489
2489
|
}
|
|
2490
2490
|
function ghSpawnOptions() {
|
|
2491
2491
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -1706,8 +1706,8 @@ function githubStatusFor(issue) {
|
|
|
1706
1706
|
return "open";
|
|
1707
1707
|
}
|
|
1708
1708
|
function selectedGitHubEnv() {
|
|
1709
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
1710
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
1709
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
1710
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
1711
1711
|
}
|
|
1712
1712
|
function ghSpawnOptions() {
|
|
1713
1713
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -4509,6 +4509,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4509
4509
|
}
|
|
4510
4510
|
env[key] = value;
|
|
4511
4511
|
}
|
|
4512
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
4513
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
4514
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
4515
|
+
}
|
|
4512
4516
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
4513
4517
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
4514
4518
|
}
|
|
@@ -4532,6 +4536,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4532
4536
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
4533
4537
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
4534
4538
|
}
|
|
4539
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
4540
|
+
if (gitHubToken) {
|
|
4541
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
4542
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
4543
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
4544
|
+
applyGitHubCredentialHelperEnv(env);
|
|
4545
|
+
}
|
|
4535
4546
|
if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
|
|
4536
4547
|
const sshParts = [
|
|
4537
4548
|
"ssh",
|
|
@@ -4548,6 +4559,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4548
4559
|
}
|
|
4549
4560
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
4550
4561
|
}
|
|
4562
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
4563
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
4564
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
4565
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
4566
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
4567
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
4568
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
4569
|
+
}
|
|
4551
4570
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
4552
4571
|
if (!runtimeRoot) {
|
|
4553
4572
|
return {};
|
|
@@ -7603,7 +7622,11 @@ async function ensureAgentRuntime(options) {
|
|
|
7603
7622
|
mkdirSync21(runtime.binDir, { recursive: true });
|
|
7604
7623
|
mkdirSync21(workspaceLayout.distDir, { recursive: true });
|
|
7605
7624
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
7606
|
-
|
|
7625
|
+
if (options.preserveTaskArtifacts) {
|
|
7626
|
+
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
7627
|
+
} else {
|
|
7628
|
+
await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
|
|
7629
|
+
}
|
|
7607
7630
|
const ctx = {
|
|
7608
7631
|
runtimeId: options.id,
|
|
7609
7632
|
taskId: options.taskId,
|
|
@@ -1706,8 +1706,8 @@ function githubStatusFor(issue) {
|
|
|
1706
1706
|
return "open";
|
|
1707
1707
|
}
|
|
1708
1708
|
function selectedGitHubEnv() {
|
|
1709
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
1710
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
1709
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
1710
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
1711
1711
|
}
|
|
1712
1712
|
function ghSpawnOptions() {
|
|
1713
1713
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -4509,6 +4509,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4509
4509
|
}
|
|
4510
4510
|
env[key] = value;
|
|
4511
4511
|
}
|
|
4512
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
4513
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
4514
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
4515
|
+
}
|
|
4512
4516
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
4513
4517
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
4514
4518
|
}
|
|
@@ -4532,6 +4536,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4532
4536
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
4533
4537
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
4534
4538
|
}
|
|
4539
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
4540
|
+
if (gitHubToken) {
|
|
4541
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
4542
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
4543
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
4544
|
+
applyGitHubCredentialHelperEnv(env);
|
|
4545
|
+
}
|
|
4535
4546
|
if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
|
|
4536
4547
|
const sshParts = [
|
|
4537
4548
|
"ssh",
|
|
@@ -4548,6 +4559,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4548
4559
|
}
|
|
4549
4560
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
4550
4561
|
}
|
|
4562
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
4563
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
4564
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
4565
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
4566
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
4567
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
4568
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
4569
|
+
}
|
|
4551
4570
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
4552
4571
|
if (!runtimeRoot) {
|
|
4553
4572
|
return {};
|
|
@@ -7603,7 +7622,11 @@ async function ensureAgentRuntime(options) {
|
|
|
7603
7622
|
mkdirSync21(runtime.binDir, { recursive: true });
|
|
7604
7623
|
mkdirSync21(workspaceLayout.distDir, { recursive: true });
|
|
7605
7624
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
7606
|
-
|
|
7625
|
+
if (options.preserveTaskArtifacts) {
|
|
7626
|
+
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
7627
|
+
} else {
|
|
7628
|
+
await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
|
|
7629
|
+
}
|
|
7607
7630
|
const ctx = {
|
|
7608
7631
|
runtimeId: options.id,
|
|
7609
7632
|
taskId: options.taskId,
|
|
@@ -1575,12 +1575,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
|
1575
1575
|
"task-result.json",
|
|
1576
1576
|
"validation-summary.json"
|
|
1577
1577
|
]);
|
|
1578
|
-
function resolveHostRigBinDir(root) {
|
|
1579
|
-
return resolve11(root, ".rig", "bin");
|
|
1580
|
-
}
|
|
1581
1578
|
function isRuntimeGatewayGitPath(candidate) {
|
|
1582
1579
|
return /\/\.rig\/bin\/git$/.test(candidate.replace(/\\/g, "/"));
|
|
1583
1580
|
}
|
|
1581
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
1582
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
1583
|
+
}
|
|
1584
1584
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
1585
1585
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
1586
1586
|
if (runtimeWorkspace && existsSync9(resolve11(runtimeWorkspace, ".git"))) {
|
|
@@ -1615,6 +1615,9 @@ function resolveGitBinary(projectRoot) {
|
|
|
1615
1615
|
}
|
|
1616
1616
|
return "git";
|
|
1617
1617
|
}
|
|
1618
|
+
function escapeRegExp(value) {
|
|
1619
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1620
|
+
}
|
|
1618
1621
|
function safeCurrentTaskId(projectRoot) {
|
|
1619
1622
|
try {
|
|
1620
1623
|
const taskId = currentTaskId(projectRoot);
|
|
@@ -1773,17 +1776,15 @@ function gitOpenPr(options) {
|
|
|
1773
1776
|
const target = options.target || (taskId ? "monorepo" : "project");
|
|
1774
1777
|
let repoRoot = options.projectRoot;
|
|
1775
1778
|
let repoLabel = "project-rig";
|
|
1776
|
-
|
|
1779
|
+
const envBase = target === "monorepo" ? process.env.RIG_PR_BASE_MONOREPO?.trim() || "" : process.env.RIG_PR_BASE_PROJECT?.trim() || "";
|
|
1777
1780
|
if (target === "monorepo") {
|
|
1778
1781
|
repoRoot = resolveOptionalMonorepoRoot(options.projectRoot) || resolveMonorepoRoot2(options.projectRoot);
|
|
1779
1782
|
repoLabel = "monorepo";
|
|
1780
|
-
defaultBase = process.env.RIG_PR_BASE_MONOREPO || "main";
|
|
1781
1783
|
if (taskId) {
|
|
1782
1784
|
gitSyncBranch(options.projectRoot, taskId, "monorepo");
|
|
1783
1785
|
}
|
|
1784
1786
|
} else if (taskId) {
|
|
1785
1787
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
1786
|
-
defaultBase = inferProjectBase(options.projectRoot, defaultBase);
|
|
1787
1788
|
}
|
|
1788
1789
|
if (!existsSync9(resolve11(repoRoot, ".git"))) {
|
|
1789
1790
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
@@ -1792,9 +1793,9 @@ function gitOpenPr(options) {
|
|
|
1792
1793
|
if (!branch || branch === "HEAD") {
|
|
1793
1794
|
throw new Error(`Cannot open PR from detached HEAD in ${repoLabel}. Checkout a branch first.`);
|
|
1794
1795
|
}
|
|
1795
|
-
const base = options.base || defaultBase;
|
|
1796
1796
|
const repoNameWithOwner = resolveRepoNameWithOwner(options.projectRoot, repoRoot);
|
|
1797
1797
|
const networkRemote = resolveNetworkRemoteName(options.projectRoot, repoRoot, repoNameWithOwner);
|
|
1798
|
+
const base = options.base || envBase || inferRepositoryDefaultBase(options.projectRoot, repoRoot, repoNameWithOwner, networkRemote, target === "project" ? inferProjectBase(options.projectRoot, "main") : "main");
|
|
1798
1799
|
refreshRemoteBaseRef(options.projectRoot, repoRoot, base);
|
|
1799
1800
|
let reviewer = (options.reviewer || "").trim();
|
|
1800
1801
|
let reviewerSource = reviewer ? "flag" : undefined;
|
|
@@ -1830,6 +1831,7 @@ function gitOpenPr(options) {
|
|
|
1830
1831
|
"",
|
|
1831
1832
|
"## Task",
|
|
1832
1833
|
`- beads: ${taskId || "n/a"}`,
|
|
1834
|
+
...defaultPrRunLines(taskId, repoNameWithOwner),
|
|
1833
1835
|
"",
|
|
1834
1836
|
"## Review",
|
|
1835
1837
|
"- Completion verification will run validation, verifier review, and PR policy checks.",
|
|
@@ -1921,6 +1923,29 @@ function gitOpenPr(options) {
|
|
|
1921
1923
|
}
|
|
1922
1924
|
return result;
|
|
1923
1925
|
}
|
|
1926
|
+
function defaultPrRunLines(taskId, repoNameWithOwner) {
|
|
1927
|
+
const lines = [];
|
|
1928
|
+
const runId = process.env.RIG_SERVER_RUN_ID?.trim();
|
|
1929
|
+
if (runId) {
|
|
1930
|
+
lines.push(`- Run: ${runId}`);
|
|
1931
|
+
}
|
|
1932
|
+
const closeout = defaultPrCloseoutLine(taskId, repoNameWithOwner);
|
|
1933
|
+
if (closeout) {
|
|
1934
|
+
lines.push(`- ${closeout}`);
|
|
1935
|
+
}
|
|
1936
|
+
return lines;
|
|
1937
|
+
}
|
|
1938
|
+
function defaultPrCloseoutLine(taskId, repoNameWithOwner) {
|
|
1939
|
+
const sourceIssueId = loadRuntimeContextFromEnv()?.sourceTask?.sourceIssueId;
|
|
1940
|
+
if (sourceIssueId) {
|
|
1941
|
+
const match = sourceIssueId.match(/^([^#]+)#(\d+)$/);
|
|
1942
|
+
if (match) {
|
|
1943
|
+
const [, sourceRepo, issueNumber] = match;
|
|
1944
|
+
return sourceRepo.toLowerCase() === repoNameWithOwner.toLowerCase() ? `Closes #${issueNumber}` : `Closes ${sourceRepo}#${issueNumber}`;
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
return /^\d+$/.test(taskId) ? `Closes #${taskId}` : "";
|
|
1948
|
+
}
|
|
1924
1949
|
function resolveTaskBranchRef(projectRoot, taskId) {
|
|
1925
1950
|
return `rig/${resolveTaskBranchId(projectRoot, taskId)}`;
|
|
1926
1951
|
}
|
|
@@ -2171,32 +2196,19 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
2171
2196
|
if (explicit) {
|
|
2172
2197
|
candidates.add(explicit);
|
|
2173
2198
|
}
|
|
2199
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
2200
|
+
candidates.add(candidate);
|
|
2201
|
+
}
|
|
2174
2202
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
2175
2203
|
for (const entry of explicitPathEntries) {
|
|
2176
2204
|
candidates.add(resolve11(entry, "gh"));
|
|
2177
2205
|
}
|
|
2178
|
-
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
2179
|
-
if (hostProjectRoot) {
|
|
2180
|
-
candidates.add(resolve11(resolveHostRigBinDir(hostProjectRoot), "gh"));
|
|
2181
|
-
}
|
|
2182
|
-
candidates.add(resolve11(resolveHostRigBinDir(projectRoot), "gh"));
|
|
2183
|
-
const runtimeContext = loadRuntimeContextFromEnv();
|
|
2184
|
-
if (runtimeContext?.binDir) {
|
|
2185
|
-
candidates.add(resolve11(runtimeContext.binDir, "gh"));
|
|
2186
|
-
}
|
|
2187
|
-
const runtimeHome = process.env.RIG_RUNTIME_HOME?.trim();
|
|
2188
|
-
if (runtimeHome) {
|
|
2189
|
-
candidates.add(resolve11(runtimeHome, "bin", "gh"));
|
|
2190
|
-
}
|
|
2191
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
2192
|
-
candidates.add(candidate);
|
|
2193
|
-
}
|
|
2194
2206
|
const bunResolved = Bun.which("gh");
|
|
2195
2207
|
if (bunResolved) {
|
|
2196
2208
|
candidates.add(bunResolved);
|
|
2197
2209
|
}
|
|
2198
2210
|
for (const candidate of candidates) {
|
|
2199
|
-
if (candidate && existsSync9(candidate)) {
|
|
2211
|
+
if (candidate && existsSync9(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
2200
2212
|
return candidate;
|
|
2201
2213
|
}
|
|
2202
2214
|
}
|
|
@@ -2345,6 +2357,32 @@ function withGhRepo(command, repoNameWithOwner) {
|
|
|
2345
2357
|
}
|
|
2346
2358
|
return [command[0], command[1], command[2], ...ghRepoArgs(repoNameWithOwner), ...command.slice(3)];
|
|
2347
2359
|
}
|
|
2360
|
+
function inferRepositoryDefaultBase(projectRoot, repoRoot, repoNameWithOwner, remoteName, fallback) {
|
|
2361
|
+
const remote = remoteName || "origin";
|
|
2362
|
+
const symbolic = runCapture2(gitCmd(projectRoot, repoRoot, "symbolic-ref", "--short", `refs/remotes/${remote}/HEAD`), projectRoot);
|
|
2363
|
+
if (symbolic.exitCode === 0) {
|
|
2364
|
+
const ref = symbolic.stdout.trim().replace(new RegExp(`^${escapeRegExp(remote)}/`), "");
|
|
2365
|
+
if (ref && ref !== "HEAD") {
|
|
2366
|
+
return ref;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
const lsRemote = runCapture2(gitCmd(projectRoot, repoRoot, "ls-remote", "--symref", remote, "HEAD"), projectRoot);
|
|
2370
|
+
if (lsRemote.exitCode === 0) {
|
|
2371
|
+
const match = lsRemote.stdout.match(/^ref:\s+refs\/heads\/([^\t\r\n]+)\s+HEAD/m);
|
|
2372
|
+
if (match?.[1]) {
|
|
2373
|
+
return match[1];
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
const gh = resolveGithubCliBinary(projectRoot);
|
|
2377
|
+
if (gh && repoNameWithOwner) {
|
|
2378
|
+
const api = runCapture2(withGhRepo([gh, "repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"], repoNameWithOwner), repoRoot);
|
|
2379
|
+
const branch = api.exitCode === 0 ? api.stdout.trim() : "";
|
|
2380
|
+
if (branch) {
|
|
2381
|
+
return branch;
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
return fallback;
|
|
2385
|
+
}
|
|
2348
2386
|
function inferProjectBase(projectRoot, fallback) {
|
|
2349
2387
|
const containing = runCapture2(gitCmd(projectRoot, projectRoot, "branch", "-r", "--contains", "HEAD"), projectRoot);
|
|
2350
2388
|
if (containing.exitCode !== 0) {
|
|
@@ -2726,6 +2764,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
2726
2764
|
}
|
|
2727
2765
|
env[key] = value;
|
|
2728
2766
|
}
|
|
2767
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
2768
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
2769
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
2770
|
+
}
|
|
2729
2771
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
2730
2772
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
2731
2773
|
}
|
|
@@ -2749,6 +2791,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
2749
2791
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
2750
2792
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
2751
2793
|
}
|
|
2794
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
2795
|
+
if (gitHubToken) {
|
|
2796
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
2797
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
2798
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
2799
|
+
applyGitHubCredentialHelperEnv(env);
|
|
2800
|
+
}
|
|
2752
2801
|
if (runtimeKnownHosts && existsSync9(runtimeKnownHosts)) {
|
|
2753
2802
|
const sshParts = [
|
|
2754
2803
|
"ssh",
|
|
@@ -2765,6 +2814,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
2765
2814
|
}
|
|
2766
2815
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
2767
2816
|
}
|
|
2817
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
2818
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
2819
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
2820
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
2821
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
2822
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
2823
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
2824
|
+
}
|
|
2768
2825
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
2769
2826
|
if (!runtimeRoot) {
|
|
2770
2827
|
return {};
|