@h-rig/cli 0.0.6-alpha.89 → 0.0.6-alpha.90
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/build-rig-binaries.js +8 -40
- package/dist/bin/rig.js +12519 -26675
- package/dist/src/app/board.js +74 -693
- package/dist/src/app/drone-ui.js +1 -1
- package/dist/src/app/theme.js +0 -1
- package/dist/src/commands/_async-ui.js +1 -1
- package/dist/src/commands/_authority-runs.d.ts +1 -1
- package/dist/src/commands/_authority-runs.js +12 -2
- package/dist/src/commands/_cli-format.d.ts +1 -10
- package/dist/src/commands/_cli-format.js +2 -5
- package/dist/src/commands/_connection-state.d.ts +1 -11
- package/dist/src/commands/_connection-state.js +5 -50
- package/dist/src/commands/_doctor-checks.js +40 -501
- package/dist/src/commands/_help-catalog.js +17 -99
- package/dist/src/commands/_json-output.js +0 -4
- package/dist/src/commands/_operator-view.js +54 -575
- package/dist/src/commands/_pi-frontend.d.ts +0 -27
- package/dist/src/commands/_pi-frontend.js +52 -576
- package/dist/src/commands/_preflight.js +66 -553
- package/dist/src/commands/_server-client.d.ts +0 -33
- package/dist/src/commands/_server-client.js +46 -541
- package/dist/src/commands/_snapshot-upload.js +42 -503
- package/dist/src/commands/_spinner.js +1 -1
- package/dist/src/commands/agent.js +12 -2
- package/dist/src/commands/browser.js +1 -1
- package/dist/src/commands/connect.js +15 -626
- package/dist/src/commands/doctor.js +41 -502
- package/dist/src/commands/github.js +51 -584
- package/dist/src/commands/inbox.js +41 -502
- package/dist/src/commands/init.js +74 -561
- package/dist/src/commands/inspect.js +41 -502
- package/dist/src/commands/run.js +54 -578
- package/dist/src/commands/server.js +163 -692
- package/dist/src/commands/setup.js +46 -507
- package/dist/src/commands/stats.js +58 -601
- package/dist/src/commands/task-run-driver.js +58 -509
- package/dist/src/commands/task.js +110 -729
- package/dist/src/commands.js +237 -1112
- package/dist/src/index.js +244 -1123
- package/dist/src/launcher.js +0 -4
- package/package.json +9 -13
- package/dist/src/app-opentui/adapters/command.d.ts +0 -2
- package/dist/src/app-opentui/adapters/command.js +0 -329
- package/dist/src/app-opentui/adapters/common.d.ts +0 -56
- package/dist/src/app-opentui/adapters/common.js +0 -153
- package/dist/src/app-opentui/adapters/doctor.d.ts +0 -9
- package/dist/src/app-opentui/adapters/doctor.js +0 -1217
- package/dist/src/app-opentui/adapters/family.d.ts +0 -62
- package/dist/src/app-opentui/adapters/family.js +0 -14855
- package/dist/src/app-opentui/adapters/fleet.d.ts +0 -14
- package/dist/src/app-opentui/adapters/fleet.js +0 -1335
- package/dist/src/app-opentui/adapters/inbox.d.ts +0 -43
- package/dist/src/app-opentui/adapters/inbox.js +0 -1944
- package/dist/src/app-opentui/adapters/init.d.ts +0 -11
- package/dist/src/app-opentui/adapters/init.js +0 -2818
- package/dist/src/app-opentui/adapters/inspect.d.ts +0 -52
- package/dist/src/app-opentui/adapters/inspect.js +0 -1455
- package/dist/src/app-opentui/adapters/pi-attach.d.ts +0 -32
- package/dist/src/app-opentui/adapters/pi-attach.js +0 -2101
- package/dist/src/app-opentui/adapters/pi.d.ts +0 -23
- package/dist/src/app-opentui/adapters/pi.js +0 -363
- package/dist/src/app-opentui/adapters/plugin.d.ts +0 -84
- package/dist/src/app-opentui/adapters/plugin.js +0 -544
- package/dist/src/app-opentui/adapters/repo.d.ts +0 -37
- package/dist/src/app-opentui/adapters/repo.js +0 -186
- package/dist/src/app-opentui/adapters/run-detail.d.ts +0 -27
- package/dist/src/app-opentui/adapters/run-detail.js +0 -1441
- package/dist/src/app-opentui/adapters/server.d.ts +0 -48
- package/dist/src/app-opentui/adapters/server.js +0 -1561
- package/dist/src/app-opentui/adapters/tasks.d.ts +0 -64
- package/dist/src/app-opentui/adapters/tasks.js +0 -4524
- package/dist/src/app-opentui/adapters/workspace.d.ts +0 -49
- package/dist/src/app-opentui/adapters/workspace.js +0 -333
- package/dist/src/app-opentui/autocomplete.d.ts +0 -20
- package/dist/src/app-opentui/autocomplete.js +0 -578
- package/dist/src/app-opentui/bootstrap.d.ts +0 -11
- package/dist/src/app-opentui/bootstrap.js +0 -27833
- package/dist/src/app-opentui/command-palette.d.ts +0 -3
- package/dist/src/app-opentui/command-palette.js +0 -1038
- package/dist/src/app-opentui/command-pty-host.d.ts +0 -62
- package/dist/src/app-opentui/command-pty-host.js +0 -248
- package/dist/src/app-opentui/drone.d.ts +0 -12
- package/dist/src/app-opentui/drone.js +0 -230
- package/dist/src/app-opentui/events.d.ts +0 -7
- package/dist/src/app-opentui/events.js +0 -28
- package/dist/src/app-opentui/fleet-stats.d.ts +0 -32
- package/dist/src/app-opentui/fleet-stats.js +0 -114
- package/dist/src/app-opentui/focus-manager.d.ts +0 -14
- package/dist/src/app-opentui/focus-manager.js +0 -24
- package/dist/src/app-opentui/index.d.ts +0 -8
- package/dist/src/app-opentui/index.js +0 -5260
- package/dist/src/app-opentui/intent.d.ts +0 -3
- package/dist/src/app-opentui/intent.js +0 -365
- package/dist/src/app-opentui/keymap.d.ts +0 -21
- package/dist/src/app-opentui/keymap.js +0 -1377
- package/dist/src/app-opentui/launch-routing.d.ts +0 -16
- package/dist/src/app-opentui/launch-routing.js +0 -55
- package/dist/src/app-opentui/layout.d.ts +0 -22
- package/dist/src/app-opentui/layout.js +0 -51
- package/dist/src/app-opentui/list-search.d.ts +0 -36
- package/dist/src/app-opentui/list-search.js +0 -130
- package/dist/src/app-opentui/pi-host-child.d.ts +0 -2
- package/dist/src/app-opentui/pi-host-child.js +0 -1299
- package/dist/src/app-opentui/pi-pty-host.d.ts +0 -28
- package/dist/src/app-opentui/pi-pty-host.js +0 -10
- package/dist/src/app-opentui/react/App.d.ts +0 -9
- package/dist/src/app-opentui/react/App.js +0 -3866
- package/dist/src/app-opentui/react/Backdrop.d.ts +0 -5
- package/dist/src/app-opentui/react/Backdrop.js +0 -823
- package/dist/src/app-opentui/react/ChromeHost.d.ts +0 -5
- package/dist/src/app-opentui/react/ChromeHost.js +0 -1539
- package/dist/src/app-opentui/react/SceneFrameView.d.ts +0 -7
- package/dist/src/app-opentui/react/SceneFrameView.js +0 -579
- package/dist/src/app-opentui/react/context.d.ts +0 -17
- package/dist/src/app-opentui/react/context.js +0 -37
- package/dist/src/app-opentui/react/launch.d.ts +0 -2
- package/dist/src/app-opentui/react/launch.js +0 -4897
- package/dist/src/app-opentui/react/nav.d.ts +0 -18
- package/dist/src/app-opentui/react/nav.js +0 -54
- package/dist/src/app-opentui/react/scroll.d.ts +0 -12
- package/dist/src/app-opentui/react/scroll.js +0 -21
- package/dist/src/app-opentui/react/syntax.d.ts +0 -2
- package/dist/src/app-opentui/react/syntax.js +0 -65
- package/dist/src/app-opentui/registry.d.ts +0 -4
- package/dist/src/app-opentui/registry.js +0 -22876
- package/dist/src/app-opentui/remote-link.d.ts +0 -10
- package/dist/src/app-opentui/remote-link.js +0 -47
- package/dist/src/app-opentui/render/ascii-fleet.d.ts +0 -15
- package/dist/src/app-opentui/render/ascii-fleet.js +0 -82
- package/dist/src/app-opentui/render/constants.d.ts +0 -30
- package/dist/src/app-opentui/render/constants.js +0 -64
- package/dist/src/app-opentui/render/graphics.d.ts +0 -40
- package/dist/src/app-opentui/render/graphics.js +0 -713
- package/dist/src/app-opentui/render/hover.d.ts +0 -11
- package/dist/src/app-opentui/render/hover.js +0 -34
- package/dist/src/app-opentui/render/native-host.d.ts +0 -37
- package/dist/src/app-opentui/render/native-host.js +0 -180
- package/dist/src/app-opentui/render/panel-layout.d.ts +0 -38
- package/dist/src/app-opentui/render/panel-layout.js +0 -48
- package/dist/src/app-opentui/render/panels.d.ts +0 -12
- package/dist/src/app-opentui/render/panels.js +0 -288
- package/dist/src/app-opentui/render/preloader.d.ts +0 -10
- package/dist/src/app-opentui/render/preloader.js +0 -166
- package/dist/src/app-opentui/render/scene.d.ts +0 -68
- package/dist/src/app-opentui/render/scene.js +0 -300
- package/dist/src/app-opentui/render/terminal-handoff.d.ts +0 -16
- package/dist/src/app-opentui/render/terminal-handoff.js +0 -14
- package/dist/src/app-opentui/render/text.d.ts +0 -29
- package/dist/src/app-opentui/render/text.js +0 -177
- package/dist/src/app-opentui/render/type-bar.d.ts +0 -15
- package/dist/src/app-opentui/render/type-bar.js +0 -212
- package/dist/src/app-opentui/runtime-resources.d.ts +0 -16
- package/dist/src/app-opentui/runtime-resources.js +0 -62
- package/dist/src/app-opentui/runtime.d.ts +0 -45
- package/dist/src/app-opentui/runtime.js +0 -5232
- package/dist/src/app-opentui/scenes/command.d.ts +0 -3
- package/dist/src/app-opentui/scenes/command.js +0 -118
- package/dist/src/app-opentui/scenes/doctor.d.ts +0 -3
- package/dist/src/app-opentui/scenes/doctor.js +0 -296
- package/dist/src/app-opentui/scenes/error.d.ts +0 -2
- package/dist/src/app-opentui/scenes/error.js +0 -277
- package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/agent.js +0 -349
- package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/browser.js +0 -196
- package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/dist.js +0 -244
- package/dist/src/app-opentui/scenes/family-domains/git.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/git.js +0 -196
- package/dist/src/app-opentui/scenes/family-domains/github.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/github.js +0 -275
- package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/harness.js +0 -153
- package/dist/src/app-opentui/scenes/family-domains/index.d.ts +0 -4
- package/dist/src/app-opentui/scenes/family-domains/index.js +0 -1680
- package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +0 -76
- package/dist/src/app-opentui/scenes/family-domains/kit.js +0 -306
- package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/profile.js +0 -213
- package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/queue.js +0 -147
- package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/remote.js +0 -519
- package/dist/src/app-opentui/scenes/family-domains/review.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/review.js +0 -281
- package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/setup.js +0 -268
- package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/stats.js +0 -371
- package/dist/src/app-opentui/scenes/family.d.ts +0 -3
- package/dist/src/app-opentui/scenes/family.js +0 -2199
- package/dist/src/app-opentui/scenes/fleet.d.ts +0 -3
- package/dist/src/app-opentui/scenes/fleet.js +0 -766
- package/dist/src/app-opentui/scenes/handoff.d.ts +0 -2
- package/dist/src/app-opentui/scenes/handoff.js +0 -455
- package/dist/src/app-opentui/scenes/help.d.ts +0 -3
- package/dist/src/app-opentui/scenes/help.js +0 -725
- package/dist/src/app-opentui/scenes/inbox.d.ts +0 -3
- package/dist/src/app-opentui/scenes/inbox.js +0 -427
- package/dist/src/app-opentui/scenes/init.d.ts +0 -3
- package/dist/src/app-opentui/scenes/init.js +0 -181
- package/dist/src/app-opentui/scenes/inspect.d.ts +0 -3
- package/dist/src/app-opentui/scenes/inspect.js +0 -794
- package/dist/src/app-opentui/scenes/main.d.ts +0 -3
- package/dist/src/app-opentui/scenes/main.js +0 -332
- package/dist/src/app-opentui/scenes/pi.d.ts +0 -3
- package/dist/src/app-opentui/scenes/pi.js +0 -509
- package/dist/src/app-opentui/scenes/plugin.d.ts +0 -3
- package/dist/src/app-opentui/scenes/plugin.js +0 -487
- package/dist/src/app-opentui/scenes/repo.d.ts +0 -3
- package/dist/src/app-opentui/scenes/repo.js +0 -425
- package/dist/src/app-opentui/scenes/run-detail.d.ts +0 -3
- package/dist/src/app-opentui/scenes/run-detail.js +0 -467
- package/dist/src/app-opentui/scenes/server.d.ts +0 -3
- package/dist/src/app-opentui/scenes/server.js +0 -378
- package/dist/src/app-opentui/scenes/tasks.d.ts +0 -3
- package/dist/src/app-opentui/scenes/tasks.js +0 -768
- package/dist/src/app-opentui/scenes/workspace.d.ts +0 -3
- package/dist/src/app-opentui/scenes/workspace.js +0 -427
- package/dist/src/app-opentui/selectable.d.ts +0 -19
- package/dist/src/app-opentui/selectable.js +0 -80
- package/dist/src/app-opentui/state.d.ts +0 -4
- package/dist/src/app-opentui/state.js +0 -399
- package/dist/src/app-opentui/surface-catalog.d.ts +0 -20
- package/dist/src/app-opentui/surface-catalog.js +0 -542
- package/dist/src/app-opentui/theme.d.ts +0 -59
- package/dist/src/app-opentui/theme.js +0 -142
- package/dist/src/app-opentui/types.d.ts +0 -313
- package/dist/src/app-opentui/types.js +0 -1
- package/dist/src/commands/_server-events.d.ts +0 -26
- package/dist/src/commands/_server-events.js +0 -715
package/dist/src/commands.js
CHANGED
|
@@ -107,7 +107,6 @@ function statusColor(status) {
|
|
|
107
107
|
case "validating":
|
|
108
108
|
case "reviewing":
|
|
109
109
|
case "closing-out":
|
|
110
|
-
case "stopping":
|
|
111
110
|
return cyan;
|
|
112
111
|
case "needs-attention":
|
|
113
112
|
case "needs_attention":
|
|
@@ -244,7 +243,7 @@ function createTtySpinner(input) {
|
|
|
244
243
|
output.write("\r\x1B[2K");
|
|
245
244
|
};
|
|
246
245
|
render();
|
|
247
|
-
const timer = isTty ? setInterval(render, input.intervalMs ??
|
|
246
|
+
const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
|
|
248
247
|
return {
|
|
249
248
|
setLabel(next) {
|
|
250
249
|
label = next;
|
|
@@ -864,28 +863,12 @@ function readRepoConnection(projectRoot) {
|
|
|
864
863
|
selected,
|
|
865
864
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
866
865
|
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
867
|
-
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
868
|
-
serverProjectRootAlias: typeof record.serverProjectRootAlias === "string" && record.serverProjectRootAlias.trim() ? record.serverProjectRootAlias.trim() : undefined,
|
|
869
|
-
serverProjectRootBaseUrl: typeof record.serverProjectRootBaseUrl === "string" && record.serverProjectRootBaseUrl.trim() ? record.serverProjectRootBaseUrl.trim().replace(/\/+$/, "") : undefined
|
|
866
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
870
867
|
};
|
|
871
868
|
}
|
|
872
869
|
function writeRepoConnection(projectRoot, state) {
|
|
873
870
|
writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
|
|
874
871
|
}
|
|
875
|
-
function rootAllowedForSelection(repo, connection) {
|
|
876
|
-
const root = repo.serverProjectRoot?.trim();
|
|
877
|
-
if (!root)
|
|
878
|
-
return;
|
|
879
|
-
if (connection.kind === "remote") {
|
|
880
|
-
if (repo.serverProjectRootAlias !== repo.selected)
|
|
881
|
-
return;
|
|
882
|
-
if (repo.serverProjectRootBaseUrl !== connection.baseUrl)
|
|
883
|
-
return;
|
|
884
|
-
} else if (repo.serverProjectRootAlias && repo.serverProjectRootAlias !== repo.selected) {
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
return root;
|
|
888
|
-
}
|
|
889
872
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
890
873
|
const repo = readRepoConnection(projectRoot);
|
|
891
874
|
if (!repo)
|
|
@@ -897,41 +880,13 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
897
880
|
if (!connection) {
|
|
898
881
|
throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
899
882
|
}
|
|
900
|
-
return { alias: repo.selected, connection, serverProjectRoot:
|
|
883
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
901
884
|
}
|
|
902
|
-
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot
|
|
885
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
903
886
|
const repo = readRepoConnection(projectRoot);
|
|
904
887
|
if (!repo)
|
|
905
888
|
return;
|
|
906
|
-
|
|
907
|
-
if (!inferred.alias || !inferred.baseUrl) {
|
|
908
|
-
try {
|
|
909
|
-
const selected = resolveSelectedConnection(projectRoot);
|
|
910
|
-
if (selected?.connection.kind === "remote") {
|
|
911
|
-
inferred = {
|
|
912
|
-
alias: inferred.alias ?? selected.alias,
|
|
913
|
-
baseUrl: inferred.baseUrl ?? selected.connection.baseUrl
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
} catch {}
|
|
917
|
-
}
|
|
918
|
-
writeRepoConnection(projectRoot, {
|
|
919
|
-
...repo,
|
|
920
|
-
...metadata.project ? { project: metadata.project } : {},
|
|
921
|
-
serverProjectRoot,
|
|
922
|
-
...inferred.alias ? { serverProjectRootAlias: inferred.alias } : {},
|
|
923
|
-
...inferred.baseUrl ? { serverProjectRootBaseUrl: inferred.baseUrl.replace(/\/+$/, "") } : {}
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
function clearRepoServerProjectRoot(projectRoot) {
|
|
927
|
-
const repo = readRepoConnection(projectRoot);
|
|
928
|
-
if (!repo)
|
|
929
|
-
return;
|
|
930
|
-
writeRepoConnection(projectRoot, {
|
|
931
|
-
selected: repo.selected,
|
|
932
|
-
...repo.project ? { project: repo.project } : {},
|
|
933
|
-
...repo.linkedAt ? { linkedAt: repo.linkedAt } : {}
|
|
934
|
-
});
|
|
889
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
935
890
|
}
|
|
936
891
|
function isRemoteConnectionSelected(projectRoot) {
|
|
937
892
|
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
@@ -941,8 +896,8 @@ var init__connection_state = __esm(() => {
|
|
|
941
896
|
});
|
|
942
897
|
|
|
943
898
|
// packages/cli/src/commands/_server-client.ts
|
|
944
|
-
import { existsSync as existsSync6,
|
|
945
|
-
import {
|
|
899
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
900
|
+
import { resolve as resolve10 } from "path";
|
|
946
901
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
947
902
|
function setServerPhaseListener(listener) {
|
|
948
903
|
const previous = serverPhaseListener;
|
|
@@ -960,21 +915,17 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
|
960
915
|
const scopedKey = resolve10(projectRoot ?? process.cwd());
|
|
961
916
|
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
962
917
|
}
|
|
963
|
-
function
|
|
918
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
964
919
|
const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
|
|
965
920
|
if (!existsSync6(path))
|
|
966
921
|
return null;
|
|
967
922
|
try {
|
|
968
923
|
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
969
|
-
return
|
|
924
|
+
return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
|
|
970
925
|
} catch {
|
|
971
926
|
return null;
|
|
972
927
|
}
|
|
973
928
|
}
|
|
974
|
-
function readPrivateRemoteSessionToken(projectRoot) {
|
|
975
|
-
const parsed = readRemoteAuthState(projectRoot);
|
|
976
|
-
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
977
|
-
}
|
|
978
929
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
979
930
|
const scopedKey = resolve10(projectRoot);
|
|
980
931
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -985,421 +936,18 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
985
936
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
986
937
|
}
|
|
987
938
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
988
|
-
const
|
|
989
|
-
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
990
|
-
}
|
|
991
|
-
function inferRemoteServerProjectRootCandidateFromAuthState(projectRoot, repoSlug) {
|
|
992
|
-
if (!/^[^/]+\/[^/]+$/.test(repoSlug))
|
|
993
|
-
return null;
|
|
994
|
-
const repo = readRepoConnection(projectRoot);
|
|
995
|
-
const auth = readRemoteAuthState(projectRoot);
|
|
996
|
-
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
997
|
-
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
998
|
-
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
999
|
-
return null;
|
|
1000
|
-
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
1001
|
-
if (!checkoutBaseDir)
|
|
1002
|
-
return null;
|
|
1003
|
-
return `${checkoutBaseDir.replace(/\/+$/, "")}/${repoSlug}`;
|
|
1004
|
-
}
|
|
1005
|
-
function readLocalConnectionFallbackToken(projectRoot) {
|
|
1006
|
-
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
1007
|
-
}
|
|
1008
|
-
function normalizeRepoSlug(value) {
|
|
1009
|
-
const slug = value?.trim();
|
|
1010
|
-
return slug && /^[^/\s]+\/[^/\s]+$/.test(slug) ? slug : null;
|
|
1011
|
-
}
|
|
1012
|
-
function readProjectLinkSlug(projectRoot) {
|
|
1013
|
-
const path = resolve10(projectRoot, ".rig", "state", "project-link.json");
|
|
939
|
+
const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
|
|
1014
940
|
if (!existsSync6(path))
|
|
1015
941
|
return null;
|
|
1016
942
|
try {
|
|
1017
943
|
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
1018
|
-
|
|
1019
|
-
return null;
|
|
1020
|
-
return normalizeRepoSlug(typeof parsed.repoSlug === "string" ? String(parsed.repoSlug) : null);
|
|
944
|
+
return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
|
|
1021
945
|
} catch {
|
|
1022
946
|
return null;
|
|
1023
947
|
}
|
|
1024
948
|
}
|
|
1025
|
-
function
|
|
1026
|
-
|
|
1027
|
-
mkdirSync6(dirname3(path), { recursive: true });
|
|
1028
|
-
writeFileSync5(path, `${JSON.stringify({ repoSlug, connection: alias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
1029
|
-
`, "utf8");
|
|
1030
|
-
}
|
|
1031
|
-
function remoteLinkRepairCommand(repoSlug) {
|
|
1032
|
-
return repoSlug ? `rig server repair-link --repo ${repoSlug}` : "rig server repair-link --repo owner/repo";
|
|
1033
|
-
}
|
|
1034
|
-
function formatRemoteProjectLinkHint(resolution) {
|
|
1035
|
-
const repair = remoteLinkRepairCommand(resolution.repoSlug);
|
|
1036
|
-
if (resolution.status === "auth_required") {
|
|
1037
|
-
return `Authenticate the selected remote${resolution.alias ? ` (${resolution.alias})` : ""}, then run \`${repair}\`. Use \`rig github auth import-gh\` or \`rig init --repair --server remote --github-auth device${resolution.repoSlug ? ` --repo ${resolution.repoSlug}` : ""}\`.`;
|
|
1038
|
-
}
|
|
1039
|
-
if (resolution.status === "missing_project") {
|
|
1040
|
-
return `Record the repo slug, then run \`${repair}\` (or \`rig init --repo owner/repo --server remote --github-auth device\`).`;
|
|
1041
|
-
}
|
|
1042
|
-
if (resolution.status === "not_remote")
|
|
1043
|
-
return "Select a remote server with `rig server use <alias>` before repairing a remote project link.";
|
|
1044
|
-
return `Run \`${repair}\` to backfill or prepare a server-host checkout for the selected remote${resolution.alias ? ` (${resolution.alias})` : ""}.`;
|
|
1045
|
-
}
|
|
1046
|
-
function remoteProjectLinkFailure(input) {
|
|
1047
|
-
const partial = {
|
|
1048
|
-
status: input.status,
|
|
1049
|
-
alias: input.alias,
|
|
1050
|
-
baseUrl: input.baseUrl,
|
|
1051
|
-
repoSlug: input.repoSlug
|
|
1052
|
-
};
|
|
1053
|
-
return {
|
|
1054
|
-
ok: false,
|
|
1055
|
-
...input,
|
|
1056
|
-
hint: formatRemoteProjectLinkHint(partial),
|
|
1057
|
-
next: remoteLinkRepairCommand(input.repoSlug)
|
|
1058
|
-
};
|
|
1059
|
-
}
|
|
1060
|
-
function remoteProjectLinkSuccess(input) {
|
|
1061
|
-
return {
|
|
1062
|
-
ok: true,
|
|
1063
|
-
status: input.status,
|
|
1064
|
-
alias: input.alias,
|
|
1065
|
-
baseUrl: input.baseUrl,
|
|
1066
|
-
repoSlug: input.repoSlug,
|
|
1067
|
-
serverProjectRoot: input.serverProjectRoot,
|
|
1068
|
-
source: input.source,
|
|
1069
|
-
prepared: input.prepared ?? input.status === "prepared",
|
|
1070
|
-
validated: input.validated ?? false,
|
|
1071
|
-
message: input.message ?? `Remote project link ready for ${input.repoSlug}.`,
|
|
1072
|
-
hint: "Remote-scoped task/run/status requests will send x-rig-project-root for this server-host checkout.",
|
|
1073
|
-
next: "rig task list"
|
|
1074
|
-
};
|
|
1075
|
-
}
|
|
1076
|
-
function localCheckoutPathCandidate(projectRoot, candidate) {
|
|
1077
|
-
try {
|
|
1078
|
-
const local = resolve10(projectRoot);
|
|
1079
|
-
const resolved = resolve10(candidate);
|
|
1080
|
-
return resolved === local || resolved.startsWith(`${local}/`);
|
|
1081
|
-
} catch {
|
|
1082
|
-
return false;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
async function requestRemoteProjectLinkJson(baseUrl, pathname, authToken, init = {}) {
|
|
1086
|
-
const requestUrl = new URL(`${baseUrl}${pathname}`);
|
|
1087
|
-
if (authToken && queryAuthFallbackEnabled())
|
|
1088
|
-
requestUrl.searchParams.set("rt", authToken);
|
|
1089
|
-
const response = await fetch(requestUrl, {
|
|
1090
|
-
...init,
|
|
1091
|
-
headers: mergeHeaders(init.headers, authToken)
|
|
1092
|
-
});
|
|
1093
|
-
const text = await response.text();
|
|
1094
|
-
const payload = text.trim().length > 0 ? (() => {
|
|
1095
|
-
try {
|
|
1096
|
-
return JSON.parse(text);
|
|
1097
|
-
} catch {
|
|
1098
|
-
return null;
|
|
1099
|
-
}
|
|
1100
|
-
})() : null;
|
|
1101
|
-
return { ok: response.ok, status: response.status, payload, text };
|
|
1102
|
-
}
|
|
1103
|
-
function payloadError(payload, fallback) {
|
|
1104
|
-
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
1105
|
-
const record = payload;
|
|
1106
|
-
const value = record.error ?? record.message ?? record.reason;
|
|
1107
|
-
if (typeof value === "string" && value.trim())
|
|
1108
|
-
return value.trim();
|
|
1109
|
-
}
|
|
1110
|
-
return fallback;
|
|
1111
|
-
}
|
|
1112
|
-
function checkoutPathsFromProjectPayload(payload) {
|
|
1113
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
1114
|
-
return [];
|
|
1115
|
-
const project = payload.project;
|
|
1116
|
-
if (!project || typeof project !== "object" || Array.isArray(project))
|
|
1117
|
-
return [];
|
|
1118
|
-
const checkouts = project.checkouts;
|
|
1119
|
-
if (!Array.isArray(checkouts))
|
|
1120
|
-
return [];
|
|
1121
|
-
return [...checkouts].reverse().flatMap((entry) => {
|
|
1122
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
1123
|
-
return [];
|
|
1124
|
-
const path = entry.path;
|
|
1125
|
-
return typeof path === "string" && path.trim() ? [path.trim()] : [];
|
|
1126
|
-
});
|
|
1127
|
-
}
|
|
1128
|
-
function checkoutPathFromPreparePayload(payload) {
|
|
1129
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
1130
|
-
return null;
|
|
1131
|
-
const checkout = payload.checkout;
|
|
1132
|
-
if (!checkout || typeof checkout !== "object" || Array.isArray(checkout))
|
|
1133
|
-
return null;
|
|
1134
|
-
const path = checkout.path;
|
|
1135
|
-
return typeof path === "string" && path.trim() ? path.trim() : null;
|
|
1136
|
-
}
|
|
1137
|
-
async function validateAndPersistRemoteRoot(input) {
|
|
1138
|
-
const candidate = input.candidate.trim();
|
|
1139
|
-
if (!candidate || !isAbsolute(candidate)) {
|
|
1140
|
-
return remoteProjectLinkFailure({
|
|
1141
|
-
status: "invalid_root",
|
|
1142
|
-
alias: input.alias,
|
|
1143
|
-
baseUrl: input.baseUrl,
|
|
1144
|
-
repoSlug: input.repoSlug,
|
|
1145
|
-
message: `Remote project root candidate is not an absolute server-host path: ${candidate || "(empty)"}.`
|
|
1146
|
-
});
|
|
1147
|
-
}
|
|
1148
|
-
if (localCheckoutPathCandidate(input.projectRoot, candidate)) {
|
|
1149
|
-
return remoteProjectLinkFailure({
|
|
1150
|
-
status: "invalid_root",
|
|
1151
|
-
alias: input.alias,
|
|
1152
|
-
baseUrl: input.baseUrl,
|
|
1153
|
-
repoSlug: input.repoSlug,
|
|
1154
|
-
message: `Refusing to use local checkout path ${candidate} as a remote server project root.`
|
|
1155
|
-
});
|
|
1156
|
-
}
|
|
1157
|
-
let response;
|
|
1158
|
-
try {
|
|
1159
|
-
response = await requestRemoteProjectLinkJson(input.baseUrl, "/api/server/project-root", input.authToken, {
|
|
1160
|
-
method: "POST",
|
|
1161
|
-
headers: { "content-type": "application/json" },
|
|
1162
|
-
body: JSON.stringify({ projectRoot: candidate })
|
|
1163
|
-
});
|
|
1164
|
-
} catch (error) {
|
|
1165
|
-
return remoteProjectLinkFailure({
|
|
1166
|
-
status: "error",
|
|
1167
|
-
alias: input.alias,
|
|
1168
|
-
baseUrl: input.baseUrl,
|
|
1169
|
-
repoSlug: input.repoSlug,
|
|
1170
|
-
message: `Could not validate remote project root ${candidate}: ${error instanceof Error ? error.message : String(error)}`
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
if (response.status === 401 || response.status === 403) {
|
|
1174
|
-
return remoteProjectLinkFailure({
|
|
1175
|
-
status: "auth_required",
|
|
1176
|
-
alias: input.alias,
|
|
1177
|
-
baseUrl: input.baseUrl,
|
|
1178
|
-
repoSlug: input.repoSlug,
|
|
1179
|
-
statusCode: response.status,
|
|
1180
|
-
message: `Remote server ${input.alias} requires authentication before validating project root ${candidate}.`
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1183
|
-
if (!response.ok) {
|
|
1184
|
-
return remoteProjectLinkFailure({
|
|
1185
|
-
status: "invalid_root",
|
|
1186
|
-
alias: input.alias,
|
|
1187
|
-
baseUrl: input.baseUrl,
|
|
1188
|
-
repoSlug: input.repoSlug,
|
|
1189
|
-
statusCode: response.status,
|
|
1190
|
-
message: `Remote server rejected project root ${candidate} (${response.status}): ${payloadError(response.payload, response.text || "project-root validation failed")}`
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
const record = response.payload && typeof response.payload === "object" && !Array.isArray(response.payload) ? response.payload : {};
|
|
1194
|
-
if (record.ok !== true) {
|
|
1195
|
-
return remoteProjectLinkFailure({
|
|
1196
|
-
status: "invalid_root",
|
|
1197
|
-
alias: input.alias,
|
|
1198
|
-
baseUrl: input.baseUrl,
|
|
1199
|
-
repoSlug: input.repoSlug,
|
|
1200
|
-
message: `Remote server did not accept project root ${candidate}: ${payloadError(response.payload, "project-root validation failed")}`
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1203
|
-
const accepted = typeof record.projectRoot === "string" && record.projectRoot.trim() ? record.projectRoot.trim() : typeof record.requestedProjectRoot === "string" && record.requestedProjectRoot.trim() ? record.requestedProjectRoot.trim() : candidate;
|
|
1204
|
-
writeRepoServerProjectRoot(input.projectRoot, accepted, { alias: input.alias, baseUrl: input.baseUrl, project: input.repoSlug });
|
|
1205
|
-
writeProjectLinkConnection(input.projectRoot, input.repoSlug, input.alias);
|
|
1206
|
-
const status = input.status ?? (input.prepared ? "prepared" : "backfilled");
|
|
1207
|
-
return remoteProjectLinkSuccess({
|
|
1208
|
-
status,
|
|
1209
|
-
alias: input.alias,
|
|
1210
|
-
baseUrl: input.baseUrl,
|
|
1211
|
-
repoSlug: input.repoSlug,
|
|
1212
|
-
serverProjectRoot: accepted,
|
|
1213
|
-
source: input.source,
|
|
1214
|
-
prepared: input.prepared,
|
|
1215
|
-
validated: true,
|
|
1216
|
-
message: status === "ready" ? `Remote project link already points to ${accepted} and was validated on ${input.alias}.` : input.prepared ? `Prepared and linked remote checkout ${accepted} for ${input.repoSlug}.` : `Backfilled remote checkout ${accepted} for ${input.repoSlug}.`
|
|
1217
|
-
});
|
|
1218
|
-
}
|
|
1219
|
-
async function ensureRemoteProjectRootLink(projectRoot, options = {}) {
|
|
1220
|
-
let selected;
|
|
1221
|
-
try {
|
|
1222
|
-
selected = resolveSelectedConnection(projectRoot);
|
|
1223
|
-
} catch (error) {
|
|
1224
|
-
return remoteProjectLinkFailure({ status: "error", message: error instanceof Error ? error.message : String(error) });
|
|
1225
|
-
}
|
|
1226
|
-
if (!selected || selected.connection.kind !== "remote") {
|
|
1227
|
-
return remoteProjectLinkFailure({ status: "not_remote", message: "No remote Rig server is selected for this repo." });
|
|
1228
|
-
}
|
|
1229
|
-
const repo = readRepoConnection(projectRoot);
|
|
1230
|
-
const explicitRepoRequested = options.repoSlug !== undefined;
|
|
1231
|
-
const explicitRepoSlug = explicitRepoRequested ? normalizeRepoSlug(options.repoSlug) : null;
|
|
1232
|
-
const repoProjectSlug = normalizeRepoSlug(repo?.project);
|
|
1233
|
-
const repoSlug = explicitRepoSlug ?? repoProjectSlug ?? readProjectLinkSlug(projectRoot);
|
|
1234
|
-
const alias = selected.alias;
|
|
1235
|
-
const baseUrl = selected.connection.baseUrl;
|
|
1236
|
-
const authToken = options.authToken === undefined ? readGitHubBearerTokenForRemote(projectRoot) : options.authToken;
|
|
1237
|
-
const mode = options.mode ?? "backfill-only";
|
|
1238
|
-
if (explicitRepoRequested && !explicitRepoSlug) {
|
|
1239
|
-
return remoteProjectLinkFailure({
|
|
1240
|
-
status: "missing_project",
|
|
1241
|
-
alias,
|
|
1242
|
-
baseUrl,
|
|
1243
|
-
message: `Invalid --repo value ${JSON.stringify(options.repoSlug)}. Expected owner/repo.`
|
|
1244
|
-
});
|
|
1245
|
-
}
|
|
1246
|
-
if (!repoSlug) {
|
|
1247
|
-
return remoteProjectLinkFailure({
|
|
1248
|
-
status: "missing_project",
|
|
1249
|
-
alias,
|
|
1250
|
-
baseUrl,
|
|
1251
|
-
message: `Remote server ${alias} is selected, but this checkout has no GitHub repo slug recorded.`
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
const skippedCandidates = [];
|
|
1255
|
-
const storedRoot = selected.serverProjectRoot?.trim() || null;
|
|
1256
|
-
const storedRootMatchesResolvedRepo = repoProjectSlug === repoSlug;
|
|
1257
|
-
if (storedRoot && storedRootMatchesResolvedRepo) {
|
|
1258
|
-
if (localCheckoutPathCandidate(projectRoot, storedRoot)) {
|
|
1259
|
-
clearRepoServerProjectRoot(projectRoot);
|
|
1260
|
-
skippedCandidates.push(storedRoot);
|
|
1261
|
-
} else {
|
|
1262
|
-
const storedResult = await validateAndPersistRemoteRoot({
|
|
1263
|
-
projectRoot,
|
|
1264
|
-
alias,
|
|
1265
|
-
baseUrl,
|
|
1266
|
-
authToken,
|
|
1267
|
-
repoSlug,
|
|
1268
|
-
candidate: storedRoot,
|
|
1269
|
-
source: "stored",
|
|
1270
|
-
status: "ready"
|
|
1271
|
-
});
|
|
1272
|
-
if (storedResult.ok || storedResult.status === "auth_required" || storedResult.status === "error")
|
|
1273
|
-
return storedResult;
|
|
1274
|
-
clearRepoServerProjectRoot(projectRoot);
|
|
1275
|
-
skippedCandidates.push(storedRoot);
|
|
1276
|
-
}
|
|
1277
|
-
} else if (storedRoot) {
|
|
1278
|
-
skippedCandidates.push(storedRoot);
|
|
1279
|
-
}
|
|
1280
|
-
const authCandidate = inferRemoteServerProjectRootCandidateFromAuthState(projectRoot, repoSlug);
|
|
1281
|
-
if (authCandidate) {
|
|
1282
|
-
const authResult = await validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate: authCandidate, source: "auth-state" });
|
|
1283
|
-
if (authResult.ok || authResult.status === "auth_required")
|
|
1284
|
-
return authResult;
|
|
1285
|
-
}
|
|
1286
|
-
let registryResponse;
|
|
1287
|
-
try {
|
|
1288
|
-
registryResponse = await requestRemoteProjectLinkJson(baseUrl, `/api/projects/${encodeURIComponent(repoSlug)}`, authToken);
|
|
1289
|
-
} catch (error) {
|
|
1290
|
-
return remoteProjectLinkFailure({
|
|
1291
|
-
status: "error",
|
|
1292
|
-
alias,
|
|
1293
|
-
baseUrl,
|
|
1294
|
-
repoSlug,
|
|
1295
|
-
message: `Could not read remote project registry for ${repoSlug} on ${alias}: ${error instanceof Error ? error.message : String(error)}`
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
if (registryResponse.status === 401 || registryResponse.status === 403) {
|
|
1299
|
-
return remoteProjectLinkFailure({
|
|
1300
|
-
status: "auth_required",
|
|
1301
|
-
alias,
|
|
1302
|
-
baseUrl,
|
|
1303
|
-
repoSlug,
|
|
1304
|
-
statusCode: registryResponse.status,
|
|
1305
|
-
message: `Remote server ${alias} requires authentication before reading the ${repoSlug} project registry.`
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
if (registryResponse.ok) {
|
|
1309
|
-
const candidates = checkoutPathsFromProjectPayload(registryResponse.payload);
|
|
1310
|
-
for (const candidate of candidates) {
|
|
1311
|
-
const result = await validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate, source: "registry" });
|
|
1312
|
-
if (result.ok || result.status === "auth_required")
|
|
1313
|
-
return result;
|
|
1314
|
-
skippedCandidates.push(candidate);
|
|
1315
|
-
}
|
|
1316
|
-
if (mode === "backfill-only") {
|
|
1317
|
-
return remoteProjectLinkFailure({
|
|
1318
|
-
status: candidates.length > 0 ? "invalid_root" : "no_server_checkout",
|
|
1319
|
-
alias,
|
|
1320
|
-
baseUrl,
|
|
1321
|
-
repoSlug,
|
|
1322
|
-
message: candidates.length > 0 ? `Remote registry has checkout candidates for ${repoSlug}, but none validated for ${alias}.` : `Remote registry has ${repoSlug}, but no server checkout path is linked yet.`,
|
|
1323
|
-
skippedCandidates
|
|
1324
|
-
});
|
|
1325
|
-
}
|
|
1326
|
-
} else if (registryResponse.status === 404) {
|
|
1327
|
-
if (mode === "backfill-only") {
|
|
1328
|
-
return remoteProjectLinkFailure({
|
|
1329
|
-
status: "project_not_registered",
|
|
1330
|
-
alias,
|
|
1331
|
-
baseUrl,
|
|
1332
|
-
repoSlug,
|
|
1333
|
-
statusCode: registryResponse.status,
|
|
1334
|
-
message: `Remote server ${alias} has no registered project record for ${repoSlug}.`
|
|
1335
|
-
});
|
|
1336
|
-
}
|
|
1337
|
-
} else {
|
|
1338
|
-
return remoteProjectLinkFailure({
|
|
1339
|
-
status: "error",
|
|
1340
|
-
alias,
|
|
1341
|
-
baseUrl,
|
|
1342
|
-
repoSlug,
|
|
1343
|
-
statusCode: registryResponse.status,
|
|
1344
|
-
message: `Could not backfill ${repoSlug} from remote registry (${registryResponse.status}): ${payloadError(registryResponse.payload, registryResponse.text || "registry lookup failed")}`,
|
|
1345
|
-
skippedCandidates
|
|
1346
|
-
});
|
|
1347
|
-
}
|
|
1348
|
-
let prepareResponse;
|
|
1349
|
-
try {
|
|
1350
|
-
prepareResponse = await requestRemoteProjectLinkJson(baseUrl, `/api/projects/${encodeURIComponent(repoSlug)}/prepare-checkout`, authToken, {
|
|
1351
|
-
method: "POST",
|
|
1352
|
-
headers: { "content-type": "application/json" },
|
|
1353
|
-
body: JSON.stringify({ checkout: { kind: "managed-clone" }, repoUrl: `https://github.com/${repoSlug}.git` })
|
|
1354
|
-
});
|
|
1355
|
-
} catch (error) {
|
|
1356
|
-
return remoteProjectLinkFailure({
|
|
1357
|
-
status: "error",
|
|
1358
|
-
alias,
|
|
1359
|
-
baseUrl,
|
|
1360
|
-
repoSlug,
|
|
1361
|
-
message: `Could not prepare remote checkout for ${repoSlug} on ${alias}: ${error instanceof Error ? error.message : String(error)}`
|
|
1362
|
-
});
|
|
1363
|
-
}
|
|
1364
|
-
if (prepareResponse.status === 401 || prepareResponse.status === 403) {
|
|
1365
|
-
return remoteProjectLinkFailure({
|
|
1366
|
-
status: "auth_required",
|
|
1367
|
-
alias,
|
|
1368
|
-
baseUrl,
|
|
1369
|
-
repoSlug,
|
|
1370
|
-
statusCode: prepareResponse.status,
|
|
1371
|
-
message: `Remote server ${alias} requires authentication before preparing ${repoSlug}.`
|
|
1372
|
-
});
|
|
1373
|
-
}
|
|
1374
|
-
if (!prepareResponse.ok) {
|
|
1375
|
-
return remoteProjectLinkFailure({
|
|
1376
|
-
status: "error",
|
|
1377
|
-
alias,
|
|
1378
|
-
baseUrl,
|
|
1379
|
-
repoSlug,
|
|
1380
|
-
statusCode: prepareResponse.status,
|
|
1381
|
-
message: `Remote checkout prepare failed for ${repoSlug} (${prepareResponse.status}): ${payloadError(prepareResponse.payload, prepareResponse.text || "prepare-checkout failed")}`,
|
|
1382
|
-
skippedCandidates
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
const preparedPath = checkoutPathFromPreparePayload(prepareResponse.payload);
|
|
1386
|
-
if (!preparedPath) {
|
|
1387
|
-
return remoteProjectLinkFailure({
|
|
1388
|
-
status: "invalid_root",
|
|
1389
|
-
alias,
|
|
1390
|
-
baseUrl,
|
|
1391
|
-
repoSlug,
|
|
1392
|
-
message: `Remote checkout prepare for ${repoSlug} did not return a checkout.path.`,
|
|
1393
|
-
skippedCandidates
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
return validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate: preparedPath, source: "prepare", prepared: true });
|
|
1397
|
-
}
|
|
1398
|
-
async function repairRemoteProjectRootLink(context, options = {}) {
|
|
1399
|
-
const resolution = await ensureRemoteProjectRootLink(context.projectRoot, { mode: options.mode ?? "prepare-if-missing", repoSlug: options.repoSlug });
|
|
1400
|
-
if (!resolution.ok)
|
|
1401
|
-
throw new CliError(resolution.message, 1, { hint: resolution.hint });
|
|
1402
|
-
return resolution;
|
|
949
|
+
function readLocalConnectionFallbackToken(projectRoot) {
|
|
950
|
+
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
1403
951
|
}
|
|
1404
952
|
async function ensureServerForCli(projectRoot) {
|
|
1405
953
|
try {
|
|
@@ -1407,12 +955,12 @@ async function ensureServerForCli(projectRoot) {
|
|
|
1407
955
|
if (selected?.connection.kind === "remote") {
|
|
1408
956
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
1409
957
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
1410
|
-
const
|
|
958
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
1411
959
|
return {
|
|
1412
960
|
baseUrl: selected.connection.baseUrl,
|
|
1413
961
|
authToken,
|
|
1414
962
|
connectionKind: "remote",
|
|
1415
|
-
serverProjectRoot
|
|
963
|
+
serverProjectRoot
|
|
1416
964
|
};
|
|
1417
965
|
}
|
|
1418
966
|
reportServerPhase("Starting local Rig server\u2026");
|
|
@@ -1430,6 +978,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
1430
978
|
throw error;
|
|
1431
979
|
}
|
|
1432
980
|
}
|
|
981
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
982
|
+
const repo = readRepoConnection(projectRoot);
|
|
983
|
+
const slug = repo?.project?.trim();
|
|
984
|
+
if (!slug)
|
|
985
|
+
return null;
|
|
986
|
+
try {
|
|
987
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
988
|
+
headers: mergeHeaders(undefined, authToken)
|
|
989
|
+
});
|
|
990
|
+
if (!response.ok)
|
|
991
|
+
return null;
|
|
992
|
+
const payload = await response.json();
|
|
993
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
994
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
995
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
996
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
997
|
+
if (path)
|
|
998
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
999
|
+
return path;
|
|
1000
|
+
} catch {
|
|
1001
|
+
return null;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1433
1004
|
function appendTaskFilterParams(url, filters) {
|
|
1434
1005
|
if (filters.assignee)
|
|
1435
1006
|
url.searchParams.set("assignee", filters.assignee);
|
|
@@ -1440,23 +1011,10 @@ function appendTaskFilterParams(url, filters) {
|
|
|
1440
1011
|
if (filters.limit !== undefined)
|
|
1441
1012
|
url.searchParams.set("limit", String(filters.limit));
|
|
1442
1013
|
}
|
|
1443
|
-
function mergeCookie(existing, name, value) {
|
|
1444
|
-
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
1445
|
-
if (!existing?.trim())
|
|
1446
|
-
return encoded;
|
|
1447
|
-
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
1448
|
-
return [...parts, encoded].join("; ");
|
|
1449
|
-
}
|
|
1450
|
-
function queryAuthFallbackEnabled(env = process.env) {
|
|
1451
|
-
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
1452
|
-
}
|
|
1453
1014
|
function mergeHeaders(headers, authToken) {
|
|
1454
1015
|
const merged = new Headers(headers);
|
|
1455
1016
|
if (authToken) {
|
|
1456
|
-
|
|
1457
|
-
merged.set("authorization", bearer);
|
|
1458
|
-
merged.set("x-auth", bearer);
|
|
1459
|
-
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
1017
|
+
merged.set("authorization", `Bearer ${authToken}`);
|
|
1460
1018
|
}
|
|
1461
1019
|
return merged;
|
|
1462
1020
|
}
|
|
@@ -1516,41 +1074,15 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
1516
1074
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
1517
1075
|
};
|
|
1518
1076
|
}
|
|
1519
|
-
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
1520
|
-
try {
|
|
1521
|
-
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
1522
|
-
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
1523
|
-
} catch {
|
|
1524
|
-
return false;
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
1528
|
-
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
1529
|
-
}
|
|
1530
1077
|
async function requestServerJson(context, pathname, init = {}) {
|
|
1531
1078
|
const server = await ensureServerForCli(context.projectRoot);
|
|
1532
|
-
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
1533
|
-
let scopedServerProjectRoot = server.serverProjectRoot;
|
|
1534
|
-
if (server.connectionKind === "remote" && !scopedServerProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
1535
|
-
const link = await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only", authToken: server.authToken });
|
|
1536
|
-
if (link.ok && link.serverProjectRoot) {
|
|
1537
|
-
scopedServerProjectRoot = link.serverProjectRoot;
|
|
1538
|
-
} else {
|
|
1539
|
-
const repo = readRepoConnection(context.projectRoot);
|
|
1540
|
-
const target = link.alias && link.baseUrl ? `${link.alias} (${link.baseUrl})` : server.baseUrl;
|
|
1541
|
-
throw new CliError(`Remote server ${target} is selected for ${link.repoSlug ?? repo?.project ?? "this repo"}, but this checkout has no server-host project root link. ${link.message}`, 1, { hint: link.hint });
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
1079
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
1545
|
-
if (
|
|
1546
|
-
headers.set("x-rig-project-root",
|
|
1547
|
-
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
1548
|
-
requestUrl.searchParams.set("rt", server.authToken);
|
|
1549
|
-
}
|
|
1080
|
+
if (server.serverProjectRoot)
|
|
1081
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
1550
1082
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
1551
1083
|
let response;
|
|
1552
1084
|
try {
|
|
1553
|
-
response = await fetch(
|
|
1085
|
+
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
1554
1086
|
...init,
|
|
1555
1087
|
headers
|
|
1556
1088
|
});
|
|
@@ -1612,26 +1144,11 @@ async function getGitHubAuthStatusViaServer(context) {
|
|
|
1612
1144
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
1613
1145
|
}
|
|
1614
1146
|
async function postGitHubTokenViaServer(context, token, options = {}) {
|
|
1615
|
-
const
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
response = await fetch(requestUrl, {
|
|
1621
|
-
method: "POST",
|
|
1622
|
-
headers: { "content-type": "application/json" },
|
|
1623
|
-
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
|
|
1624
|
-
});
|
|
1625
|
-
} catch (error) {
|
|
1626
|
-
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
1627
|
-
throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
|
|
1628
|
-
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
1629
|
-
}
|
|
1630
|
-
const payload = await response.json().catch(() => null);
|
|
1631
|
-
if (!response.ok) {
|
|
1632
|
-
const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
|
|
1633
|
-
throw new CliError(`Rig server auth bootstrap failed (${response.status}): ${detail}`, 1, { hint: "Re-run `rig github auth import-gh`, or check the selected server with `rig server status`." });
|
|
1634
|
-
}
|
|
1147
|
+
const payload = await requestServerJson(context, "/api/github/auth/token", {
|
|
1148
|
+
method: "POST",
|
|
1149
|
+
headers: { "content-type": "application/json" },
|
|
1150
|
+
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
|
|
1151
|
+
});
|
|
1635
1152
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
1636
1153
|
}
|
|
1637
1154
|
async function prepareRemoteCheckoutViaServer(context, input) {
|
|
@@ -1909,14 +1426,6 @@ function permissionAllowsPr(payload) {
|
|
|
1909
1426
|
function isNotFoundError(error) {
|
|
1910
1427
|
return /\b(404|not found)\b/i.test(message(error));
|
|
1911
1428
|
}
|
|
1912
|
-
function isLoopbackBaseUrl(baseUrl) {
|
|
1913
|
-
try {
|
|
1914
|
-
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
1915
|
-
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
1916
|
-
} catch {
|
|
1917
|
-
return false;
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
1429
|
function projectCheckoutReady(payload) {
|
|
1921
1430
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
1922
1431
|
return null;
|
|
@@ -1970,38 +1479,25 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
1970
1479
|
}
|
|
1971
1480
|
}
|
|
1972
1481
|
const repo = readRepoConnection(context.projectRoot);
|
|
1973
|
-
|
|
1974
|
-
let remoteRootBlocked = false;
|
|
1975
|
-
checks.push(repo ? preflightCheck("project-link", "project linked to selected server", repo.project ? "pass" : remoteWithoutProjectLink ? "fail" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : " (missing project link)"}`, remoteWithoutProjectLink ? "Run `rig server repair-link --repo owner/repo` or `rig init --repo owner/repo --server remote` to restore the remote project link." : "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to selected server", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
|
|
1976
|
-
if (selectedServer?.connectionKind === "remote" && repo?.project && !selectedServer.serverProjectRoot) {
|
|
1977
|
-
const link = await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only", authToken: selectedServer.authToken });
|
|
1978
|
-
const loopbackDevRemote = !selectedServer.authToken && isLoopbackBaseUrl(selectedServer.baseUrl);
|
|
1979
|
-
checks.push(preflightCheck("remote-project-root-link", "remote server checkout/root linked", link.ok ? "pass" : loopbackDevRemote ? "warn" : "fail", link.ok ? `${link.repoSlug} -> ${link.serverProjectRoot}` : link.message, link.ok ? undefined : loopbackDevRemote ? "Loopback development remotes may continue without x-rig-project-root; production remotes must run `rig server repair-link`." : link.hint));
|
|
1980
|
-
remoteRootBlocked = !link.ok && !loopbackDevRemote;
|
|
1981
|
-
}
|
|
1482
|
+
checks.push(repo ? preflightCheck("project-link", "project linked to Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to Rig server", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
|
|
1982
1483
|
try {
|
|
1983
1484
|
const auth = await request("/api/github/auth/status");
|
|
1984
1485
|
checks.push(isAuthenticated(auth) ? preflightCheck("github-auth", "GitHub auth valid", "pass") : preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
|
|
1985
1486
|
} catch (error) {
|
|
1986
1487
|
checks.push(preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix GitHub auth on the selected Rig server."));
|
|
1987
1488
|
}
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", message(error), "Ensure the selected token can push branches and open PRs."));
|
|
2001
|
-
}
|
|
2002
|
-
} else {
|
|
2003
|
-
checks.push(preflightCheck("task-projection", "task projection ready", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
|
|
2004
|
-
checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
|
|
1489
|
+
try {
|
|
1490
|
+
const projection = await request("/api/workspace/task-projection");
|
|
1491
|
+
checks.push(preflightCheck("task-projection", "task projection ready", "pass", JSON.stringify(projection).slice(0, 120)));
|
|
1492
|
+
} catch (error) {
|
|
1493
|
+
checks.push(preflightCheck("task-projection", "task projection ready", "warn", message(error), "Refresh task projection with `rig task list` before launching."));
|
|
1494
|
+
}
|
|
1495
|
+
try {
|
|
1496
|
+
const permissions = await request("/api/github/repo/permissions");
|
|
1497
|
+
const allowed = permissionAllowsPr(permissions);
|
|
1498
|
+
checks.push(allowed === false ? preflightCheck("github-repo-permissions", "GitHub PR permissions", "fail", JSON.stringify(permissions).slice(0, 120), "Grant the selected GitHub token permission to push branches and open PRs.") : preflightCheck("github-repo-permissions", "GitHub PR permissions", allowed === true ? "pass" : "warn", JSON.stringify(permissions).slice(0, 120), "Confirm the selected token can push branches and open PRs."));
|
|
1499
|
+
} catch (error) {
|
|
1500
|
+
checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", message(error), "Ensure the selected token can push branches and open PRs."));
|
|
2005
1501
|
}
|
|
2006
1502
|
if (repo?.project) {
|
|
2007
1503
|
try {
|
|
@@ -2013,24 +1509,19 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
2013
1509
|
}
|
|
2014
1510
|
}
|
|
2015
1511
|
if (taskId) {
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
checks.push(preflightCheck("duplicate-active-run", "one active run per task", "warn", message(error), "Could not list active runs; the server will still reject conflicting runs if configured."));
|
|
2030
|
-
}
|
|
2031
|
-
} else {
|
|
2032
|
-
checks.push(preflightCheck("issue", "task/issue accessible", "fail", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
|
|
2033
|
-
checks.push(preflightCheck("duplicate-active-run", "one active run per task", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
|
|
1512
|
+
try {
|
|
1513
|
+
const tasks = await request(`/api/workspace/tasks?limit=200&refresh=1`);
|
|
1514
|
+
const found = Array.isArray(tasks) && tasks.some((task) => taskMatchesId(task, taskId));
|
|
1515
|
+
checks.push(found ? preflightCheck("issue", "task/issue accessible", "pass", taskId) : preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", taskId, "Confirm the issue exists and matches the configured task filters."));
|
|
1516
|
+
} catch (error) {
|
|
1517
|
+
checks.push(preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix the task source before launching a run."));
|
|
1518
|
+
}
|
|
1519
|
+
try {
|
|
1520
|
+
const runs = await request("/api/runs?limit=200");
|
|
1521
|
+
const duplicate = activeDuplicateRun(runs, taskId);
|
|
1522
|
+
checks.push(duplicate ? preflightCheck("duplicate-active-run", "one active run per task", "fail", String(duplicate.runId ?? taskId), "Attach to or stop the existing run before starting another one for this task.") : preflightCheck("duplicate-active-run", "one active run per task", "pass", taskId));
|
|
1523
|
+
} catch (error) {
|
|
1524
|
+
checks.push(preflightCheck("duplicate-active-run", "one active run per task", "warn", message(error), "Could not list active runs; the server will still reject conflicting runs if configured."));
|
|
2034
1525
|
}
|
|
2035
1526
|
}
|
|
2036
1527
|
if ((options.runtimeAdapter ?? "pi") === "pi") {
|
|
@@ -2099,8 +1590,18 @@ import {
|
|
|
2099
1590
|
readJsonlFile as readJsonlFile2,
|
|
2100
1591
|
writeAuthorityRunRecord
|
|
2101
1592
|
} from "@rig/runtime/control-plane/authority-files";
|
|
2102
|
-
function normalizeRuntimeAdapter(
|
|
2103
|
-
|
|
1593
|
+
function normalizeRuntimeAdapter(value) {
|
|
1594
|
+
const normalized = value?.trim().toLowerCase();
|
|
1595
|
+
if (!normalized) {
|
|
1596
|
+
return "pi";
|
|
1597
|
+
}
|
|
1598
|
+
if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
|
|
1599
|
+
return "codex";
|
|
1600
|
+
}
|
|
1601
|
+
if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
|
|
1602
|
+
return "pi";
|
|
1603
|
+
}
|
|
1604
|
+
return "claude-code";
|
|
2104
1605
|
}
|
|
2105
1606
|
function readLatestBeadRecord(projectRoot, taskId) {
|
|
2106
1607
|
const issuesPath = resolve11(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
|
|
@@ -2514,19 +2015,16 @@ function formatConnectionList(connections) {
|
|
|
2514
2015
|
return [formatSection("Rig servers", `${rows.length} available`), `${pc3.bold(pad("ALIAS", aliasWidth))} ${pc3.bold("KIND")} ${pc3.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
|
|
2515
2016
|
`);
|
|
2516
2017
|
}
|
|
2517
|
-
function formatConnectionStatus(selected, connections
|
|
2018
|
+
function formatConnectionStatus(selected, connections) {
|
|
2518
2019
|
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
2519
2020
|
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
2520
|
-
const rootLabel = remoteProjectLink ? remoteProjectLink.ok ? `ready \xB7 ${remoteProjectLink.serverProjectRoot ?? repo?.serverProjectRoot ?? "linked"}` : `${remoteProjectLink.status ?? "needs repair"} \xB7 ${remoteProjectLink.hint ?? remoteProjectLink.message ?? "run rig server repair-link"}` : repo?.serverProjectRoot ? repo.serverProjectRoot : "not required";
|
|
2521
2021
|
return [
|
|
2522
2022
|
formatSection("Rig server", "selected for this repo"),
|
|
2523
2023
|
`${themeFaint("\u2502")} ${themeDim("selected ")} ${pc3.bold(selected)}`,
|
|
2524
2024
|
`${themeFaint("\u2502")} ${themeDim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
2525
2025
|
`${themeFaint("\u2502")} ${themeDim("target ")} ${target ?? "not configured"}`,
|
|
2526
|
-
...repo?.project ? [`${themeFaint("\u2502")} ${themeDim("project ")} ${repo.project}`] : [],
|
|
2527
|
-
...connection?.kind === "remote" ? [`${themeFaint("\u2502")} ${themeDim("root ")} ${rootLabel}`] : [],
|
|
2528
2026
|
"",
|
|
2529
|
-
...formatNextSteps(
|
|
2027
|
+
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
2530
2028
|
].join(`
|
|
2531
2029
|
`);
|
|
2532
2030
|
}
|
|
@@ -3025,7 +2523,7 @@ var init__operator_surface = __esm(() => {
|
|
|
3025
2523
|
});
|
|
3026
2524
|
|
|
3027
2525
|
// packages/cli/src/commands/_pi-frontend.ts
|
|
3028
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
2526
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync8, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
3029
2527
|
import { homedir as homedir6, tmpdir } from "os";
|
|
3030
2528
|
import { join as join3 } from "path";
|
|
3031
2529
|
import { main as runPiMain } from "@earendil-works/pi-coding-agent";
|
|
@@ -3057,27 +2555,10 @@ function buildOperatorPiEnv(input) {
|
|
|
3057
2555
|
...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
|
|
3058
2556
|
};
|
|
3059
2557
|
}
|
|
3060
|
-
function shouldRequireOperatorTranscript(status) {
|
|
3061
|
-
return typeof status === "string" && TERMINAL_RUN_STATUSES.has(status.trim().toLowerCase());
|
|
3062
|
-
}
|
|
3063
|
-
function missingOperatorTranscriptMessage(runId, status) {
|
|
3064
|
-
const shortRun = runId.trim().slice(0, 8) || "unknown";
|
|
3065
|
-
const statusText = typeof status === "string" && status.trim() ? status.trim() : "terminal";
|
|
3066
|
-
return `Run ${shortRun} is ${statusText}, but no worker Pi session transcript is recorded for this run. It likely failed before Pi started or predates full-session capture. Use \`rig run show ${runId}\` and \`rig run logs ${runId}\` for the lifecycle details.`;
|
|
3067
|
-
}
|
|
3068
|
-
function statusFromRunDetails(run) {
|
|
3069
|
-
if (!run || typeof run !== "object" || Array.isArray(run))
|
|
3070
|
-
return;
|
|
3071
|
-
const record = run;
|
|
3072
|
-
if (typeof record.status === "string")
|
|
3073
|
-
return record.status;
|
|
3074
|
-
const nested = record.run;
|
|
3075
|
-
return nested && typeof nested === "object" && !Array.isArray(nested) ? nested.status : undefined;
|
|
3076
|
-
}
|
|
3077
2558
|
async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
3078
2559
|
const server = await ensureServerForCli(context.projectRoot);
|
|
3079
2560
|
const localCwd = join3(homedir6(), ".rig", "drones", runId.slice(0, 8));
|
|
3080
|
-
|
|
2561
|
+
mkdirSync8(localCwd, { recursive: true });
|
|
3081
2562
|
trustDroneCwd(localCwd);
|
|
3082
2563
|
installRigPiTheme();
|
|
3083
2564
|
let sessionFileArg = [];
|
|
@@ -3099,28 +2580,21 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
|
3099
2580
|
return line;
|
|
3100
2581
|
}).join(`
|
|
3101
2582
|
`);
|
|
3102
|
-
|
|
2583
|
+
writeFileSync6(localSessionPath, content);
|
|
3103
2584
|
sessionFileArg = ["--session", localSessionPath];
|
|
3104
2585
|
}
|
|
3105
2586
|
} catch {}
|
|
3106
|
-
if (sessionFileArg.length === 0) {
|
|
3107
|
-
const run = await getRunDetailsViaServer(context, runId).catch(() => null);
|
|
3108
|
-
const status = statusFromRunDetails(run);
|
|
3109
|
-
if (shouldRequireOperatorTranscript(status)) {
|
|
3110
|
-
throw new OperatorTranscriptUnavailableError(missingOperatorTranscriptMessage(runId, status));
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
2587
|
return { server, sessionFileArg };
|
|
3114
2588
|
}
|
|
3115
2589
|
function trustDroneCwd(localCwd) {
|
|
3116
2590
|
try {
|
|
3117
2591
|
const agentDir = join3(homedir6(), ".pi", "agent");
|
|
3118
|
-
|
|
2592
|
+
mkdirSync8(agentDir, { recursive: true });
|
|
3119
2593
|
const trustPath = join3(agentDir, "trust.json");
|
|
3120
2594
|
const store = existsSync14(trustPath) ? JSON.parse(readFileSync10(trustPath, "utf8")) : {};
|
|
3121
2595
|
if (store[localCwd] !== true) {
|
|
3122
2596
|
store[localCwd] = true;
|
|
3123
|
-
|
|
2597
|
+
writeFileSync6(trustPath, `${JSON.stringify(store, null, "\t")}
|
|
3124
2598
|
`);
|
|
3125
2599
|
}
|
|
3126
2600
|
} catch {}
|
|
@@ -3128,38 +2602,15 @@ function trustDroneCwd(localCwd) {
|
|
|
3128
2602
|
function installRigPiTheme() {
|
|
3129
2603
|
try {
|
|
3130
2604
|
const themesDir = join3(homedir6(), ".pi", "agent", "themes");
|
|
3131
|
-
|
|
2605
|
+
mkdirSync8(themesDir, { recursive: true });
|
|
3132
2606
|
const themePath = join3(themesDir, "rig.json");
|
|
3133
2607
|
const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
|
|
3134
2608
|
`;
|
|
3135
2609
|
if (!existsSync14(themePath) || readFileSync10(themePath, "utf8") !== next) {
|
|
3136
|
-
|
|
2610
|
+
writeFileSync6(themePath, next);
|
|
3137
2611
|
}
|
|
3138
2612
|
} catch {}
|
|
3139
2613
|
}
|
|
3140
|
-
async function runWithProcessExitGuard(body) {
|
|
3141
|
-
const realExit = process.exit;
|
|
3142
|
-
let exitCode = 0;
|
|
3143
|
-
let signalQuit = () => {};
|
|
3144
|
-
const quit = new Promise((resolve22) => {
|
|
3145
|
-
signalQuit = resolve22;
|
|
3146
|
-
});
|
|
3147
|
-
const guardedExit = (code) => {
|
|
3148
|
-
exitCode = typeof code === "number" ? code : 0;
|
|
3149
|
-
signalQuit();
|
|
3150
|
-
return;
|
|
3151
|
-
};
|
|
3152
|
-
process.exit = guardedExit;
|
|
3153
|
-
try {
|
|
3154
|
-
await Promise.race([Promise.resolve().then(body), quit]);
|
|
3155
|
-
} finally {
|
|
3156
|
-
process.exit = realExit;
|
|
3157
|
-
}
|
|
3158
|
-
return exitCode;
|
|
3159
|
-
}
|
|
3160
|
-
function runPiMainReturningOnQuit(args, options) {
|
|
3161
|
-
return runWithProcessExitGuard(() => runPiMain(args, options));
|
|
3162
|
-
}
|
|
3163
2614
|
async function attachRunBundledPiFrontend(context, input) {
|
|
3164
2615
|
const tempSessionDir = mkdtempSync(join3(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
3165
2616
|
const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
|
|
@@ -3175,20 +2626,15 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
3175
2626
|
};
|
|
3176
2627
|
let detached = false;
|
|
3177
2628
|
try {
|
|
3178
|
-
|
|
3179
|
-
"--offline",
|
|
2629
|
+
await runPiMain([
|
|
3180
2630
|
"--no-extensions",
|
|
3181
2631
|
"--no-skills",
|
|
3182
2632
|
"--no-prompt-templates",
|
|
3183
2633
|
"--no-context-files",
|
|
3184
2634
|
...sessionFileArg
|
|
3185
|
-
]
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
await runPiMainReturningOnQuit(piArgs, piOptions);
|
|
3189
|
-
} else {
|
|
3190
|
-
await runPiMain(piArgs, piOptions);
|
|
3191
|
-
}
|
|
2635
|
+
], {
|
|
2636
|
+
extensionFactories: [piRigExtensionFactory]
|
|
2637
|
+
});
|
|
3192
2638
|
detached = true;
|
|
3193
2639
|
} finally {
|
|
3194
2640
|
restoreEnv();
|
|
@@ -3208,17 +2654,10 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
3208
2654
|
rendered: "stock Pi operator console with the pi-rig extension"
|
|
3209
2655
|
};
|
|
3210
2656
|
}
|
|
3211
|
-
var
|
|
2657
|
+
var RIG_PI_THEME;
|
|
3212
2658
|
var init__pi_frontend = __esm(() => {
|
|
3213
2659
|
init__server_client();
|
|
3214
2660
|
init__async_ui();
|
|
3215
|
-
TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
|
|
3216
|
-
OperatorTranscriptUnavailableError = class OperatorTranscriptUnavailableError extends Error {
|
|
3217
|
-
constructor(message2) {
|
|
3218
|
-
super(message2);
|
|
3219
|
-
this.name = "OperatorTranscriptUnavailableError";
|
|
3220
|
-
}
|
|
3221
|
-
};
|
|
3222
2661
|
RIG_PI_THEME = {
|
|
3223
2662
|
$schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3224
2663
|
name: "rig",
|
|
@@ -3373,7 +2812,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
3373
2812
|
}
|
|
3374
2813
|
const pollMs = Math.max(250, Math.trunc(input.pollMs ?? 2000));
|
|
3375
2814
|
let timelineCursor = snapshot.timelineCursor;
|
|
3376
|
-
while (!detached && !
|
|
2815
|
+
while (!detached && !TERMINAL_RUN_STATUSES.has(runStatusFromPayload(snapshot.run))) {
|
|
3377
2816
|
await Bun.sleep(pollMs);
|
|
3378
2817
|
snapshot = await readOperatorSnapshot(context, input.runId, { timelineCursor });
|
|
3379
2818
|
timelineCursor = snapshot.timelineCursor;
|
|
@@ -3385,13 +2824,13 @@ async function attachRunOperatorView(context, input) {
|
|
|
3385
2824
|
}
|
|
3386
2825
|
return { ...snapshot, steered, detached };
|
|
3387
2826
|
}
|
|
3388
|
-
var
|
|
2827
|
+
var TERMINAL_RUN_STATUSES;
|
|
3389
2828
|
var init__operator_view = __esm(() => {
|
|
3390
2829
|
init__server_client();
|
|
3391
2830
|
init__operator_surface();
|
|
3392
2831
|
init__pi_frontend();
|
|
3393
2832
|
init__async_ui();
|
|
3394
|
-
|
|
2833
|
+
TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
|
|
3395
2834
|
});
|
|
3396
2835
|
|
|
3397
2836
|
// packages/cli/src/commands/_help-catalog.ts
|
|
@@ -3561,13 +3000,12 @@ var init__help_catalog = __esm(() => {
|
|
|
3561
3000
|
{
|
|
3562
3001
|
name: "server",
|
|
3563
3002
|
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
3564
|
-
usage: ["rig server <status|list|add|use|
|
|
3003
|
+
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
3565
3004
|
commands: [
|
|
3566
|
-
{ command: "status", description: "Show the selected server
|
|
3005
|
+
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
3567
3006
|
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
3568
3007
|
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
3569
3008
|
{ command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
|
|
3570
|
-
{ command: "repair-link [--prepare|--backfill-only] [--repo owner/repo]", description: "Backfill or prepare the selected remote's server-host checkout link.", primary: true },
|
|
3571
3009
|
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
3572
3010
|
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
3573
3011
|
],
|
|
@@ -3575,7 +3013,6 @@ var init__help_catalog = __esm(() => {
|
|
|
3575
3013
|
"rig server status",
|
|
3576
3014
|
"rig server add prod https://where.rig-does.work",
|
|
3577
3015
|
"rig server use prod",
|
|
3578
|
-
"rig server repair-link --repo owner/repo",
|
|
3579
3016
|
"rig server use local",
|
|
3580
3017
|
"rig server start --port 3773"
|
|
3581
3018
|
],
|
|
@@ -3750,62 +3187,30 @@ var init__help_catalog = __esm(() => {
|
|
|
3750
3187
|
}
|
|
3751
3188
|
];
|
|
3752
3189
|
ADVANCED_GROUPS = [
|
|
3753
|
-
{
|
|
3754
|
-
|
|
3755
|
-
summary: "Bootstrap/check local setup.",
|
|
3756
|
-
usage: ["rig setup <bootstrap|check|preflight>"],
|
|
3757
|
-
commands: [
|
|
3758
|
-
{ command: "bootstrap", description: "Bootstrap local setup dependencies.", primary: true },
|
|
3759
|
-
{ command: "check", description: "Check local setup state (toolchain, deps, config).", primary: true },
|
|
3760
|
-
{ command: "preflight", description: "Run preflight checks before a run.", primary: true }
|
|
3761
|
-
]
|
|
3762
|
-
},
|
|
3763
|
-
{
|
|
3764
|
-
name: "profile",
|
|
3765
|
-
summary: "Runtime profile/model defaults.",
|
|
3766
|
-
usage: ["rig profile <show|set>"],
|
|
3767
|
-
commands: [
|
|
3768
|
-
{ command: "show", description: "Show the active execution profile.", primary: true },
|
|
3769
|
-
{ command: "set [--model <model>] [--runtime <runtime>] [--plugin <plugin>]", description: "Set model/runtime/plugin profile defaults.", primary: true }
|
|
3770
|
-
]
|
|
3771
|
-
},
|
|
3190
|
+
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
3191
|
+
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
3772
3192
|
{
|
|
3773
3193
|
name: "review",
|
|
3774
3194
|
summary: "Inspect or change completion review gate policy.",
|
|
3775
3195
|
usage: ["rig review <show|set>"],
|
|
3776
3196
|
commands: [
|
|
3777
3197
|
{ command: "show", description: "Show current review gate settings." },
|
|
3778
|
-
{ command: "set <off|advisory|required> [--provider
|
|
3198
|
+
{ command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider." }
|
|
3779
3199
|
],
|
|
3780
3200
|
examples: ["rig review show", "rig review set required --provider greptile"],
|
|
3781
3201
|
next: ["Use `rig inbox approvals` for blocked run handoffs."]
|
|
3782
3202
|
},
|
|
3783
3203
|
{
|
|
3784
3204
|
name: "browser",
|
|
3785
|
-
summary: "Browser
|
|
3786
|
-
usage: ["rig browser <help|explain|demo|hp-next
|
|
3205
|
+
summary: "Browser/app diagnostics for browser-required tasks.",
|
|
3206
|
+
usage: ["rig browser <help|explain|demo|app|hp-next> [options]"],
|
|
3787
3207
|
commands: [
|
|
3788
|
-
{ command: "help", description: "Rich browser command help (canonical: `rig browser help`)."
|
|
3789
|
-
{ command: "explain", description: "Explain the browser-required task contract
|
|
3790
|
-
{ command: "demo
|
|
3791
|
-
{ command: "
|
|
3792
|
-
{ command: "hp-next
|
|
3793
|
-
|
|
3794
|
-
{ command: "hp-next e2e", description: "Run hp-next browser e2e smoke checks through Rig Browser.", primary: true },
|
|
3795
|
-
{ command: "hp-next reset", description: "Reset the hp-next browser profile when stale browser state is suspected.", primary: true },
|
|
3796
|
-
{ command: "cdp-probe", description: "Run an isolated CDP attach/evaluate/layout probe." },
|
|
3797
|
-
{ command: "profile-persistence", description: "Verify a named browser profile persists browser state." },
|
|
3798
|
-
{ command: "profile-lock-check", description: "Verify concurrent launches reject the same profile." },
|
|
3799
|
-
{ command: "smoke-test", description: "Run the browser package smoke test." }
|
|
3800
|
-
],
|
|
3801
|
-
examples: [
|
|
3802
|
-
"rig browser help",
|
|
3803
|
-
"rig browser hp-next check",
|
|
3804
|
-
"rig browser hp-next e2e",
|
|
3805
|
-
"rig browser cdp-probe",
|
|
3806
|
-
"rig browser profile-lock-check"
|
|
3807
|
-
],
|
|
3808
|
-
next: ["Inside a task run, use rig-browser-launch, rig-browser-check, and rig-browser-attach-info from the worker PATH."]
|
|
3208
|
+
{ command: "help", description: "Rich browser command help (canonical: `rig browser help`)." },
|
|
3209
|
+
{ command: "explain", description: "Explain the browser-required task contract." },
|
|
3210
|
+
{ command: "demo", description: "Run browser demo flows against a local page." },
|
|
3211
|
+
{ command: "app", description: "Launch the Rig Browser workstation app." },
|
|
3212
|
+
{ command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
|
|
3213
|
+
]
|
|
3809
3214
|
},
|
|
3810
3215
|
{
|
|
3811
3216
|
name: "pi",
|
|
@@ -3820,60 +3225,12 @@ var init__help_catalog = __esm(() => {
|
|
|
3820
3225
|
examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
|
|
3821
3226
|
next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
|
|
3822
3227
|
},
|
|
3823
|
-
{
|
|
3824
|
-
|
|
3825
|
-
summary: "Run task queues locally.",
|
|
3826
|
-
usage: ["rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]"],
|
|
3827
|
-
commands: [
|
|
3828
|
-
{ command: "run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]", description: "Process queue work: drain matching tasks with N workers, optional per-task action and isolation.", primary: true }
|
|
3829
|
-
]
|
|
3830
|
-
},
|
|
3831
|
-
{
|
|
3832
|
-
name: "agent",
|
|
3833
|
-
summary: "Runtime agent workspace helpers.",
|
|
3834
|
-
usage: ["rig agent <list|prepare|run|cleanup>"],
|
|
3835
|
-
commands: [
|
|
3836
|
-
{ command: "list", description: "List prepared agent runtimes.", primary: true },
|
|
3837
|
-
{ command: "prepare [--id <id>] [--mode <mode>] [--task <task>]", description: "Prepare an isolated agent runtime workspace.", primary: true },
|
|
3838
|
-
{ command: "run [--id <id>] [--mode <mode>] [--task <task>] [--skip-project-sync]", description: "Prepare (if needed) and run an agent in its workspace.", primary: true },
|
|
3839
|
-
{ command: "cleanup [--all] [--id <id>]", description: "Remove prepared agent workspaces.", primary: true }
|
|
3840
|
-
]
|
|
3841
|
-
},
|
|
3228
|
+
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
3229
|
+
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
3842
3230
|
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
3843
|
-
{
|
|
3844
|
-
name: "dist",
|
|
3845
|
-
summary: "Build/install packaged Rig CLI.",
|
|
3846
|
-
usage: ["rig dist <build|install|doctor|rebuild-agent>"],
|
|
3847
|
-
commands: [
|
|
3848
|
-
{ command: "build [--output-dir <dir>]", description: "Build the distributable Rig CLI.", primary: true },
|
|
3849
|
-
{ command: "install [--scope <scope>] [--path <path>]", description: "Install the built CLI to a scope/path.", primary: true },
|
|
3850
|
-
{ command: "doctor", description: "Diagnose the dist toolchain and install state.", primary: true },
|
|
3851
|
-
{ command: "rebuild-agent", description: "Rebuild the agent runtime image, pruning stale images.", primary: true }
|
|
3852
|
-
]
|
|
3853
|
-
},
|
|
3231
|
+
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
3854
3232
|
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
3855
|
-
{
|
|
3856
|
-
name: "remote",
|
|
3857
|
-
summary: "Compatibility remote orchestration controls.",
|
|
3858
|
-
usage: ["rig remote <status|tasks|watch|pause|resume|continue|stop|refresh|add-iterations|remove-iterations|endpoint ...>"],
|
|
3859
|
-
commands: [
|
|
3860
|
-
{ command: "status [--remote <alias>]", description: "Show the remote orchestration state.", primary: true },
|
|
3861
|
-
{ command: "tasks [--remote <alias>]", description: "List the remote's tracked tasks.", primary: true },
|
|
3862
|
-
{ command: "watch [--remote <alias>] [--seconds <n>] [--event <type>]", description: "Stream remote orchestration events.", primary: true },
|
|
3863
|
-
{ command: "pause [--remote <alias>]", description: "Pause the running remote orchestration.", primary: true },
|
|
3864
|
-
{ command: "resume [--remote <alias>] [--max-workers <n>] [--max-iterations <n>] [--direct-merge]", description: "Resume the remote with optional tuning.", primary: true },
|
|
3865
|
-
{ command: "continue [--remote <alias>]", description: "Continue a paused remote orchestration.", primary: true },
|
|
3866
|
-
{ command: "stop [--remote <alias>]", description: "Stop the remote orchestration.", primary: true },
|
|
3867
|
-
{ command: "refresh [--remote <alias>]", description: "Refresh remote state.", primary: true },
|
|
3868
|
-
{ command: "add-iterations [--count <n>] [--remote <alias>]", description: "Grant the remote more iterations.", primary: true },
|
|
3869
|
-
{ command: "remove-iterations [--count <n>] [--remote <alias>]", description: "Reduce the remote's iteration budget.", primary: true },
|
|
3870
|
-
{ command: "endpoint list", description: "List configured remote endpoints.", primary: true },
|
|
3871
|
-
{ command: "endpoint add --alias <alias> --host <host> --port <n> [--token <token>]", description: "Register a remote endpoint.", primary: true },
|
|
3872
|
-
{ command: "endpoint remove --alias <alias>", description: "Remove a remote endpoint.", primary: true },
|
|
3873
|
-
{ command: "endpoint test [--alias <alias>]", description: "Test connectivity to a remote endpoint.", primary: true },
|
|
3874
|
-
{ command: "endpoint doctor", description: "Diagnose remote endpoint configuration.", primary: true }
|
|
3875
|
-
]
|
|
3876
|
-
},
|
|
3233
|
+
{ name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
3877
3234
|
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
3878
3235
|
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
3879
3236
|
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
@@ -3940,7 +3297,7 @@ var init__task_picker = __esm(() => {
|
|
|
3940
3297
|
// packages/cli/src/commands/task.ts
|
|
3941
3298
|
import { readFileSync as readFileSync11 } from "fs";
|
|
3942
3299
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
3943
|
-
import { resolve as
|
|
3300
|
+
import { resolve as resolve21 } from "path";
|
|
3944
3301
|
import {
|
|
3945
3302
|
taskArtifactDir,
|
|
3946
3303
|
taskArtifacts,
|
|
@@ -4218,7 +3575,7 @@ async function executeTask(context, args, options) {
|
|
|
4218
3575
|
const fileFlag = takeOption(rest.slice(1), "--file");
|
|
4219
3576
|
let content;
|
|
4220
3577
|
if (fileFlag.value) {
|
|
4221
|
-
content = readFileSync11(
|
|
3578
|
+
content = readFileSync11(resolve21(context.projectRoot, fileFlag.value), "utf-8");
|
|
4222
3579
|
} else {
|
|
4223
3580
|
content = await readStdin();
|
|
4224
3581
|
}
|
|
@@ -4456,47 +3813,6 @@ var init_task = __esm(() => {
|
|
|
4456
3813
|
init__connection_state();
|
|
4457
3814
|
});
|
|
4458
3815
|
|
|
4459
|
-
// packages/cli/src/commands/_server-events.ts
|
|
4460
|
-
import { WsTransport } from "@rig/client";
|
|
4461
|
-
import { RIG_WS_CHANNELS } from "@rig/contracts";
|
|
4462
|
-
function buildRigWebSocketUrl(baseUrl, authToken) {
|
|
4463
|
-
const url = new URL(baseUrl);
|
|
4464
|
-
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
4465
|
-
if (authToken)
|
|
4466
|
-
url.searchParams.set("token", authToken);
|
|
4467
|
-
return url.toString();
|
|
4468
|
-
}
|
|
4469
|
-
async function connectRigServerEvents(projectRoot, handlers) {
|
|
4470
|
-
const { baseUrl, authToken } = await ensureServerForCli(projectRoot);
|
|
4471
|
-
const transport = new WsTransport(buildRigWebSocketUrl(baseUrl, authToken));
|
|
4472
|
-
const unsubscribers = [];
|
|
4473
|
-
if (handlers.onSnapshotInvalidated)
|
|
4474
|
-
unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.snapshotInvalidated, handlers.onSnapshotInvalidated));
|
|
4475
|
-
if (handlers.onRunLogAppended)
|
|
4476
|
-
unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.runLogAppended, handlers.onRunLogAppended));
|
|
4477
|
-
if (handlers.onEngineEvent)
|
|
4478
|
-
unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.event, handlers.onEngineEvent));
|
|
4479
|
-
let status = "connecting";
|
|
4480
|
-
unsubscribers.push(transport.subscribeState((state) => {
|
|
4481
|
-
status = state.status;
|
|
4482
|
-
handlers.onStatus?.(state.status);
|
|
4483
|
-
}));
|
|
4484
|
-
return {
|
|
4485
|
-
connected: () => status === "connected",
|
|
4486
|
-
close: () => {
|
|
4487
|
-
for (const unsubscribe of unsubscribers) {
|
|
4488
|
-
try {
|
|
4489
|
-
unsubscribe();
|
|
4490
|
-
} catch {}
|
|
4491
|
-
}
|
|
4492
|
-
transport.dispose();
|
|
4493
|
-
}
|
|
4494
|
-
};
|
|
4495
|
-
}
|
|
4496
|
-
var init__server_events = __esm(() => {
|
|
4497
|
-
init__server_client();
|
|
4498
|
-
});
|
|
4499
|
-
|
|
4500
3816
|
// packages/cli/src/app/board.ts
|
|
4501
3817
|
var exports_board = {};
|
|
4502
3818
|
__export(exports_board, {
|
|
@@ -4528,7 +3844,6 @@ function statusRank(status) {
|
|
|
4528
3844
|
case "pending":
|
|
4529
3845
|
case "preparing":
|
|
4530
3846
|
case "adopted":
|
|
4531
|
-
case "stopping":
|
|
4532
3847
|
return 2;
|
|
4533
3848
|
case "completed":
|
|
4534
3849
|
case "merged":
|
|
@@ -4568,10 +3883,6 @@ class RunsList {
|
|
|
4568
3883
|
selectedRun() {
|
|
4569
3884
|
return this.visibleRuns()[this.selected] ?? null;
|
|
4570
3885
|
}
|
|
4571
|
-
patchRun(runId, patch) {
|
|
4572
|
-
this.runs = this.runs.map((run) => run.runId === runId ? { ...run, ...patch } : run);
|
|
4573
|
-
this.clampSelection();
|
|
4574
|
-
}
|
|
4575
3886
|
cycleSort() {
|
|
4576
3887
|
this.sortMode = this.sortMode === "active" ? "recent" : this.sortMode === "recent" ? "status" : "active";
|
|
4577
3888
|
this.clampSelection();
|
|
@@ -4794,14 +4105,6 @@ class InboxView {
|
|
|
4794
4105
|
selectedItem() {
|
|
4795
4106
|
return this.items[this.selected] ?? null;
|
|
4796
4107
|
}
|
|
4797
|
-
patchItem(requestId, summary) {
|
|
4798
|
-
this.items = this.items.map((item) => item.requestId === requestId ? { ...item, summary } : item);
|
|
4799
|
-
}
|
|
4800
|
-
removeItem(requestId) {
|
|
4801
|
-
const previousIndex = this.selected;
|
|
4802
|
-
this.items = this.items.filter((item) => item.requestId !== requestId);
|
|
4803
|
-
this.selected = Math.max(0, Math.min(previousIndex, Math.max(0, this.items.length - 1)));
|
|
4804
|
-
}
|
|
4805
4108
|
invalidate() {}
|
|
4806
4109
|
render(width) {
|
|
4807
4110
|
return this.renderLines(width).map((line) => truncateToWidth(line, Math.max(10, width - 1)));
|
|
@@ -5023,14 +4326,9 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5023
4326
|
tui.stop();
|
|
5024
4327
|
};
|
|
5025
4328
|
let refreshInFlight = false;
|
|
5026
|
-
const refresh = async (
|
|
4329
|
+
const refresh = async () => {
|
|
5027
4330
|
if (refreshInFlight)
|
|
5028
4331
|
return;
|
|
5029
|
-
if (!options2.quiet) {
|
|
5030
|
-
notice = "refreshing fleet\u2026";
|
|
5031
|
-
renderFooter();
|
|
5032
|
-
tui.requestRender();
|
|
5033
|
-
}
|
|
5034
4332
|
if (!hasRigProject(context.projectRoot)) {
|
|
5035
4333
|
list.loading = false;
|
|
5036
4334
|
list.noProject = true;
|
|
@@ -5113,7 +4411,6 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5113
4411
|
};
|
|
5114
4412
|
const resolveApproval = async (item, decision) => {
|
|
5115
4413
|
notice = `${decision === "approve" ? "approving" : "rejecting"} ${item.requestId.slice(0, 12)}\u2026`;
|
|
5116
|
-
inboxView.patchItem(item.requestId, `${decision === "approve" ? "approving" : "rejecting"}\u2026 ${item.summary}`);
|
|
5117
4414
|
renderFooter();
|
|
5118
4415
|
tui.requestRender();
|
|
5119
4416
|
try {
|
|
@@ -5122,10 +4419,8 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5122
4419
|
headers: { "content-type": "application/json" },
|
|
5123
4420
|
body: JSON.stringify({ runId: item.runId, requestId: item.requestId, decision, note: null })
|
|
5124
4421
|
});
|
|
5125
|
-
inboxView.removeItem(item.requestId);
|
|
5126
4422
|
notice = `${decision === "approve" ? "approved" : "rejected"} \u2014 drone resumes`;
|
|
5127
4423
|
} catch (error) {
|
|
5128
|
-
inboxView.patchItem(item.requestId, item.summary);
|
|
5129
4424
|
notice = `resolve failed: ${oneLine(error instanceof Error ? error.message : String(error))}`;
|
|
5130
4425
|
}
|
|
5131
4426
|
renderFooter();
|
|
@@ -5134,7 +4429,6 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5134
4429
|
};
|
|
5135
4430
|
const answerInput = async (item, text2) => {
|
|
5136
4431
|
notice = `answering ${item.requestId.slice(0, 12)}\u2026`;
|
|
5137
|
-
inboxView.patchItem(item.requestId, `answering\u2026 ${item.summary}`);
|
|
5138
4432
|
renderFooter();
|
|
5139
4433
|
tui.requestRender();
|
|
5140
4434
|
try {
|
|
@@ -5147,10 +4441,8 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5147
4441
|
answers: { [item.questionId ?? "response"]: text2 }
|
|
5148
4442
|
})
|
|
5149
4443
|
});
|
|
5150
|
-
inboxView.removeItem(item.requestId);
|
|
5151
4444
|
notice = "answer sent \u2014 drone resumes";
|
|
5152
4445
|
} catch (error) {
|
|
5153
|
-
inboxView.patchItem(item.requestId, item.summary);
|
|
5154
4446
|
notice = `answer failed: ${oneLine(error instanceof Error ? error.message : String(error))}`;
|
|
5155
4447
|
}
|
|
5156
4448
|
renderFooter();
|
|
@@ -5299,7 +4591,6 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5299
4591
|
const run = list.selectedRun();
|
|
5300
4592
|
if (run) {
|
|
5301
4593
|
notice = `stop requested for ${run.runId.slice(0, 8)}\u2026`;
|
|
5302
|
-
list.patchRun(run.runId, { status: "stopping" });
|
|
5303
4594
|
renderFooter();
|
|
5304
4595
|
tui.requestRender();
|
|
5305
4596
|
stopRunViaServer(context, run.runId).then(() => refresh()).catch(() => refresh());
|
|
@@ -5307,9 +4598,6 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5307
4598
|
return { consume: true };
|
|
5308
4599
|
}
|
|
5309
4600
|
if (data === "r") {
|
|
5310
|
-
notice = "refreshing fleet\u2026";
|
|
5311
|
-
renderFooter();
|
|
5312
|
-
tui.requestRender();
|
|
5313
4601
|
refresh();
|
|
5314
4602
|
return { consume: true };
|
|
5315
4603
|
}
|
|
@@ -5335,39 +4623,21 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
5335
4623
|
tui.requestRender();
|
|
5336
4624
|
}
|
|
5337
4625
|
}, BOARD_TICK_MS);
|
|
5338
|
-
const live = { subscription: null };
|
|
5339
|
-
const refreshActiveView = () => {
|
|
5340
|
-
refresh({ quiet: true });
|
|
5341
|
-
if (view === "tasks")
|
|
5342
|
-
refreshTasks();
|
|
5343
|
-
if (view === "inbox")
|
|
5344
|
-
refreshInbox();
|
|
5345
|
-
};
|
|
5346
|
-
connectRigServerEvents(context.projectRoot, {
|
|
5347
|
-
onSnapshotInvalidated: () => refreshActiveView()
|
|
5348
|
-
}).then((subscription) => {
|
|
5349
|
-
live.subscription = subscription;
|
|
5350
|
-
}).catch(() => {
|
|
5351
|
-
live.subscription = null;
|
|
5352
|
-
});
|
|
5353
4626
|
const refreshTimer = setInterval(() => {
|
|
5354
|
-
if (live.subscription?.connected())
|
|
5355
|
-
return;
|
|
5356
4627
|
refresh();
|
|
5357
4628
|
}, BOARD_REFRESH_MS);
|
|
5358
4629
|
tui.start();
|
|
5359
|
-
refresh(
|
|
5360
|
-
await new Promise((
|
|
4630
|
+
refresh();
|
|
4631
|
+
await new Promise((resolve24) => {
|
|
5361
4632
|
const poll = setInterval(() => {
|
|
5362
4633
|
if (stopped) {
|
|
5363
4634
|
clearInterval(poll);
|
|
5364
|
-
|
|
4635
|
+
resolve24();
|
|
5365
4636
|
}
|
|
5366
4637
|
}, 50);
|
|
5367
4638
|
});
|
|
5368
4639
|
clearInterval(animation);
|
|
5369
4640
|
clearInterval(refreshTimer);
|
|
5370
|
-
live.subscription?.close();
|
|
5371
4641
|
return outcome;
|
|
5372
4642
|
}
|
|
5373
4643
|
async function runOperatorBoardLoop(context, attach, options = {}) {
|
|
@@ -5380,13 +4650,12 @@ async function runOperatorBoardLoop(context, attach, options = {}) {
|
|
|
5380
4650
|
await attach(outcome.runId);
|
|
5381
4651
|
}
|
|
5382
4652
|
}
|
|
5383
|
-
var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS =
|
|
4653
|
+
var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS = 250, BOARD_TASK_PAGE = 20;
|
|
5384
4654
|
var init_board = __esm(() => {
|
|
5385
4655
|
init_theme();
|
|
5386
4656
|
init__help_catalog();
|
|
5387
4657
|
init__server_client();
|
|
5388
4658
|
init__authority_runs();
|
|
5389
|
-
init__server_events();
|
|
5390
4659
|
init_inbox();
|
|
5391
4660
|
init_task();
|
|
5392
4661
|
});
|
|
@@ -5397,7 +4666,7 @@ import {
|
|
|
5397
4666
|
existsSync as existsSync18,
|
|
5398
4667
|
readFileSync as readFileSync13
|
|
5399
4668
|
} from "fs";
|
|
5400
|
-
import { resolve as
|
|
4669
|
+
import { resolve as resolve24 } from "path";
|
|
5401
4670
|
import { readBuildConfig } from "@rig/runtime/build-time-config";
|
|
5402
4671
|
|
|
5403
4672
|
// packages/cli/src/commands/browser.ts
|
|
@@ -7904,7 +7173,7 @@ import {
|
|
|
7904
7173
|
chmodSync,
|
|
7905
7174
|
copyFileSync as copyFileSync2,
|
|
7906
7175
|
existsSync as existsSync8,
|
|
7907
|
-
mkdirSync as
|
|
7176
|
+
mkdirSync as mkdirSync6,
|
|
7908
7177
|
readdirSync,
|
|
7909
7178
|
readlinkSync,
|
|
7910
7179
|
rmSync as rmSync3,
|
|
@@ -8021,7 +7290,7 @@ async function executeDist(context, args) {
|
|
|
8021
7290
|
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
8022
7291
|
const scope = parseInstallScope(scopeResult.value);
|
|
8023
7292
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
8024
|
-
|
|
7293
|
+
mkdirSync6(installDir, { recursive: true });
|
|
8025
7294
|
let source = await findLatestDistBinary(context.projectRoot);
|
|
8026
7295
|
let buildDir = null;
|
|
8027
7296
|
if (!source) {
|
|
@@ -8076,7 +7345,7 @@ async function executeDist(context, args) {
|
|
|
8076
7345
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
8077
7346
|
const currentId = computeRuntimeImageId(fp);
|
|
8078
7347
|
const imagesDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
8079
|
-
|
|
7348
|
+
mkdirSync6(imagesDir, { recursive: true });
|
|
8080
7349
|
let pruned = 0;
|
|
8081
7350
|
for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
|
|
8082
7351
|
if (entry.isDirectory() && entry.name !== currentId) {
|
|
@@ -8088,9 +7357,9 @@ async function executeDist(context, args) {
|
|
|
8088
7357
|
console.log(`Pruned ${pruned} stale image(s).`);
|
|
8089
7358
|
}
|
|
8090
7359
|
const imageDir = resolve13(imagesDir, currentId);
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
7360
|
+
mkdirSync6(resolve13(imageDir, "bin/hooks"), { recursive: true });
|
|
7361
|
+
mkdirSync6(resolve13(imageDir, "bin/plugins"), { recursive: true });
|
|
7362
|
+
mkdirSync6(resolve13(imageDir, "bin/validators"), { recursive: true });
|
|
8094
7363
|
const hookNames = [
|
|
8095
7364
|
"scope-guard",
|
|
8096
7365
|
"import-guard",
|
|
@@ -8115,8 +7384,8 @@ async function executeDist(context, args) {
|
|
|
8115
7384
|
const binPluginsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
|
|
8116
7385
|
const validatorsRoot = resolve13(hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
8117
7386
|
const binValidatorsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
|
|
8118
|
-
|
|
8119
|
-
|
|
7387
|
+
mkdirSync6(binPluginsDir, { recursive: true });
|
|
7388
|
+
mkdirSync6(binValidatorsDir, { recursive: true });
|
|
8120
7389
|
if (existsSync8(pluginsDir)) {
|
|
8121
7390
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
8122
7391
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
@@ -8223,7 +7492,7 @@ init_inbox();
|
|
|
8223
7492
|
init_runner();
|
|
8224
7493
|
init__connection_state();
|
|
8225
7494
|
init__server_client();
|
|
8226
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as
|
|
7495
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
8227
7496
|
import { spawnSync } from "child_process";
|
|
8228
7497
|
import { basename as basename2, resolve as resolve17 } from "path";
|
|
8229
7498
|
import { buildRigInitConfigSource } from "@rig/core";
|
|
@@ -8409,7 +7678,7 @@ async function buildPiSetupChecks(input = {}) {
|
|
|
8409
7678
|
// packages/cli/src/commands/_snapshot-upload.ts
|
|
8410
7679
|
init__server_client();
|
|
8411
7680
|
import { mkdir, readdir, readFile, writeFile } from "fs/promises";
|
|
8412
|
-
import { dirname as
|
|
7681
|
+
import { dirname as dirname3, resolve as resolve15, relative, sep } from "path";
|
|
8413
7682
|
var SNAPSHOT_ARCHIVE_VERSION = 1;
|
|
8414
7683
|
var SNAPSHOT_ARCHIVE_CONTENT_TYPE = "application/vnd.rig.snapshot+json";
|
|
8415
7684
|
var DEFAULT_EXCLUDED_DIRECTORIES = new Set([
|
|
@@ -8758,14 +8027,14 @@ function parseRepoSlug(value) {
|
|
|
8758
8027
|
}
|
|
8759
8028
|
function ensureRigPrivateDirs(projectRoot) {
|
|
8760
8029
|
const rigDir = resolve17(projectRoot, ".rig");
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8030
|
+
mkdirSync7(resolve17(rigDir, "state"), { recursive: true });
|
|
8031
|
+
mkdirSync7(resolve17(rigDir, "logs"), { recursive: true });
|
|
8032
|
+
mkdirSync7(resolve17(rigDir, "runs"), { recursive: true });
|
|
8033
|
+
mkdirSync7(resolve17(rigDir, "tmp"), { recursive: true });
|
|
8034
|
+
mkdirSync7(resolve17(projectRoot, "artifacts"), { recursive: true });
|
|
8766
8035
|
const taskConfigPath = resolve17(rigDir, "task-config.json");
|
|
8767
8036
|
if (!existsSync11(taskConfigPath))
|
|
8768
|
-
|
|
8037
|
+
writeFileSync5(taskConfigPath, `{}
|
|
8769
8038
|
`, "utf-8");
|
|
8770
8039
|
}
|
|
8771
8040
|
function ensureGitignoreEntries(projectRoot) {
|
|
@@ -8793,7 +8062,7 @@ function ensureRigConfigPackageDependencies(projectRoot) {
|
|
|
8793
8062
|
...existsSync11(path) ? existing : { name: "rig-project", private: true },
|
|
8794
8063
|
devDependencies
|
|
8795
8064
|
};
|
|
8796
|
-
|
|
8065
|
+
writeFileSync5(path, `${JSON.stringify(next, null, 2)}
|
|
8797
8066
|
`, "utf8");
|
|
8798
8067
|
}
|
|
8799
8068
|
function applyGitHubProjectConfig(source, options) {
|
|
@@ -8819,9 +8088,9 @@ function checkoutForInit(projectRoot, serverKind, strategy) {
|
|
|
8819
8088
|
const selected = strategy ?? { kind: "managed-clone" };
|
|
8820
8089
|
switch (selected.kind) {
|
|
8821
8090
|
case "managed-clone":
|
|
8822
|
-
return { kind: "managed-clone" };
|
|
8091
|
+
return { kind: "managed-clone", path: projectRoot };
|
|
8823
8092
|
case "current-ref":
|
|
8824
|
-
return { kind: "current-ref", ...selected.ref ? { ref: selected.ref } : {} };
|
|
8093
|
+
return { kind: "current-ref", path: projectRoot, ...selected.ref ? { ref: selected.ref } : {} };
|
|
8825
8094
|
case "uploaded-snapshot":
|
|
8826
8095
|
return { kind: "uploaded-snapshot", path: projectRoot, source: "local-working-tree" };
|
|
8827
8096
|
case "existing-path":
|
|
@@ -9091,7 +8360,7 @@ function remoteGitHubAuthMetadata(payload) {
|
|
|
9091
8360
|
};
|
|
9092
8361
|
}
|
|
9093
8362
|
function writeRemoteGitHubAuthState(projectRoot, input) {
|
|
9094
|
-
|
|
8363
|
+
writeFileSync5(resolve17(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
|
|
9095
8364
|
authenticated: true,
|
|
9096
8365
|
source: input.source,
|
|
9097
8366
|
storedOnServer: true,
|
|
@@ -9139,7 +8408,7 @@ function runLocalFilesInit(context, options) {
|
|
|
9139
8408
|
console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
|
|
9140
8409
|
} else {
|
|
9141
8410
|
const projectName = basename2(projectRoot) || "rig-project";
|
|
9142
|
-
|
|
8411
|
+
writeFileSync5(configTsPath, buildRigInitConfigSource({
|
|
9143
8412
|
projectName,
|
|
9144
8413
|
taskSource: { kind: "files", path: "tasks" },
|
|
9145
8414
|
useStandardPlugin: true
|
|
@@ -9148,8 +8417,8 @@ function runLocalFilesInit(context, options) {
|
|
|
9148
8417
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
9149
8418
|
const tasksDir = resolve17(projectRoot, "tasks");
|
|
9150
8419
|
if (!existsSync11(tasksDir)) {
|
|
9151
|
-
|
|
9152
|
-
|
|
8420
|
+
mkdirSync7(tasksDir, { recursive: true });
|
|
8421
|
+
writeFileSync5(resolve17(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
|
|
9153
8422
|
`, "utf-8");
|
|
9154
8423
|
}
|
|
9155
8424
|
if (context.outputMode !== "json") {
|
|
@@ -9212,7 +8481,7 @@ function runDemoInit(context, options) {
|
|
|
9212
8481
|
console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it for the demo.");
|
|
9213
8482
|
}
|
|
9214
8483
|
} else {
|
|
9215
|
-
|
|
8484
|
+
writeFileSync5(configTsPath, buildRigInitConfigSource({
|
|
9216
8485
|
projectName: basename2(projectRoot) || "rig-demo",
|
|
9217
8486
|
taskSource: { kind: "files", path: DEMO_TASKS_RELATIVE_DIR },
|
|
9218
8487
|
useStandardPlugin: true
|
|
@@ -9221,14 +8490,14 @@ function runDemoInit(context, options) {
|
|
|
9221
8490
|
}
|
|
9222
8491
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
9223
8492
|
const demoTasksDir = resolve17(projectRoot, DEMO_TASKS_RELATIVE_DIR);
|
|
9224
|
-
|
|
8493
|
+
mkdirSync7(demoTasksDir, { recursive: true });
|
|
9225
8494
|
const taskIds = [];
|
|
9226
8495
|
for (const task of DEMO_TASKS) {
|
|
9227
8496
|
const id = String(task.id);
|
|
9228
8497
|
taskIds.push(id);
|
|
9229
8498
|
const taskPath = resolve17(demoTasksDir, `${id}.json`);
|
|
9230
8499
|
if (!existsSync11(taskPath)) {
|
|
9231
|
-
|
|
8500
|
+
writeFileSync5(taskPath, `${JSON.stringify(task, null, 2)}
|
|
9232
8501
|
`, "utf-8");
|
|
9233
8502
|
}
|
|
9234
8503
|
}
|
|
@@ -9256,32 +8525,21 @@ function runDemoInit(context, options) {
|
|
|
9256
8525
|
}
|
|
9257
8526
|
async function runControlPlaneInit(context, options) {
|
|
9258
8527
|
const projectRoot = context.projectRoot;
|
|
9259
|
-
const
|
|
9260
|
-
const selectedConnection = (() => {
|
|
9261
|
-
try {
|
|
9262
|
-
return resolveSelectedConnection(projectRoot);
|
|
9263
|
-
} catch {
|
|
9264
|
-
return null;
|
|
9265
|
-
}
|
|
9266
|
-
})();
|
|
9267
|
-
const selectedRemote = selectedConnection?.connection.kind === "remote" ? { alias: selectedConnection.alias, connection: selectedConnection.connection } : null;
|
|
9268
|
-
const detectedSlug = options.repoSlug ?? existingRepoConnection?.project ?? detectOriginRepoSlug(projectRoot);
|
|
9269
|
-
const serverKind = options.server ?? (selectedRemote ? "remote" : "local");
|
|
8528
|
+
const detectedSlug = options.repoSlug ?? detectOriginRepoSlug(projectRoot);
|
|
9270
8529
|
if (!detectedSlug) {
|
|
9271
8530
|
const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
|
|
9272
|
-
if (
|
|
8531
|
+
if ((options.server ?? "local") === "local" && authMethod2 === "skip") {
|
|
9273
8532
|
return runLocalFilesInit(context, options);
|
|
9274
8533
|
}
|
|
9275
8534
|
throw new CliError("Could not detect GitHub repo slug from origin. Pass --repo owner/repo \u2014 or run `rig init --yes --server local --github-auth skip` for a local files-source project without GitHub.", 1);
|
|
9276
8535
|
}
|
|
9277
8536
|
const repo = parseRepoSlug(detectedSlug);
|
|
9278
|
-
const
|
|
9279
|
-
const
|
|
9280
|
-
const remoteUrl = serverKind === "remote" ? (options.remoteUrl ?? selectedRemoteUrl)?.replace(/\/+$/, "") : undefined;
|
|
8537
|
+
const serverKind = options.server ?? "local";
|
|
8538
|
+
const connectionAlias = options.connectionAlias ?? (serverKind === "local" ? "local" : "remote");
|
|
9281
8539
|
if (serverKind === "remote") {
|
|
9282
|
-
if (!remoteUrl)
|
|
9283
|
-
throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server
|
|
9284
|
-
upsertGlobalConnection(connectionAlias, { kind: "remote", baseUrl: remoteUrl });
|
|
8540
|
+
if (!options.remoteUrl)
|
|
8541
|
+
throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server`." });
|
|
8542
|
+
upsertGlobalConnection(connectionAlias, { kind: "remote", baseUrl: options.remoteUrl });
|
|
9285
8543
|
}
|
|
9286
8544
|
writeRepoConnection(projectRoot, {
|
|
9287
8545
|
selected: connectionAlias,
|
|
@@ -9304,11 +8562,11 @@ async function runControlPlaneInit(context, options) {
|
|
|
9304
8562
|
taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
|
|
9305
8563
|
useStandardPlugin: true
|
|
9306
8564
|
}), options);
|
|
9307
|
-
|
|
8565
|
+
writeFileSync5(configTsPath, source, "utf-8");
|
|
9308
8566
|
}
|
|
9309
8567
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
9310
8568
|
}
|
|
9311
|
-
|
|
8569
|
+
writeFileSync5(resolve17(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
9312
8570
|
`, "utf8");
|
|
9313
8571
|
const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
|
|
9314
8572
|
let uploadedSnapshot = null;
|
|
@@ -9323,7 +8581,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
9323
8581
|
let githubAuth = null;
|
|
9324
8582
|
let deviceAuth = null;
|
|
9325
8583
|
const authMethod = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
|
|
9326
|
-
const remoteGhTokenWarning = serverKind === "remote" && authMethod === "gh" ? `This sends a GitHub token from this machine to ${remoteUrl ?? "the remote Rig server"}.` : null;
|
|
8584
|
+
const remoteGhTokenWarning = serverKind === "remote" && authMethod === "gh" ? `This sends a GitHub token from this machine to ${options.remoteUrl ?? "the remote Rig server"}.` : null;
|
|
9327
8585
|
if (remoteGhTokenWarning && !options.yes) {
|
|
9328
8586
|
throw new CliError(`${remoteGhTokenWarning} Re-run with --yes to confirm this explicit token transfer.`, 1);
|
|
9329
8587
|
}
|
|
@@ -9636,64 +8894,14 @@ Usage: rig init`, 1);
|
|
|
9636
8894
|
// packages/cli/src/commands/github.ts
|
|
9637
8895
|
init_runner();
|
|
9638
8896
|
init__server_client();
|
|
9639
|
-
init__connection_state();
|
|
9640
8897
|
init__async_ui();
|
|
9641
8898
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
9642
|
-
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
9643
|
-
import { dirname as dirname5, resolve as resolve18 } from "path";
|
|
9644
8899
|
function printPayload(context, payload, fallback) {
|
|
9645
8900
|
if (context.outputMode === "json")
|
|
9646
8901
|
console.log(JSON.stringify(payload, null, 2));
|
|
9647
8902
|
else
|
|
9648
8903
|
console.log(fallback);
|
|
9649
8904
|
}
|
|
9650
|
-
function apiSessionTokenFrom2(payload) {
|
|
9651
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
9652
|
-
return null;
|
|
9653
|
-
const token = payload.apiSessionToken;
|
|
9654
|
-
return typeof token === "string" && token.trim() ? token.trim() : null;
|
|
9655
|
-
}
|
|
9656
|
-
function payloadString(payload, key) {
|
|
9657
|
-
const value = payload[key];
|
|
9658
|
-
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
9659
|
-
}
|
|
9660
|
-
function payloadRecord(payload, key) {
|
|
9661
|
-
const value = payload[key];
|
|
9662
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
9663
|
-
}
|
|
9664
|
-
function remoteNamespaceMetadata(result) {
|
|
9665
|
-
const namespace = payloadRecord(result, "userNamespace");
|
|
9666
|
-
return {
|
|
9667
|
-
...payloadString(result, "login") ? { login: payloadString(result, "login") } : {},
|
|
9668
|
-
...payloadString(result, "userId") ? { userId: payloadString(result, "userId") } : {},
|
|
9669
|
-
...namespace && payloadString(namespace, "key") ? { userNamespaceKey: payloadString(namespace, "key") } : {},
|
|
9670
|
-
...namespace && payloadString(namespace, "root") ? { userNamespaceRoot: payloadString(namespace, "root") } : {},
|
|
9671
|
-
...namespace && payloadString(namespace, "checkoutBaseDir") ? { checkoutBaseDir: payloadString(namespace, "checkoutBaseDir") } : {},
|
|
9672
|
-
...namespace && payloadString(namespace, "snapshotBaseDir") ? { snapshotBaseDir: payloadString(namespace, "snapshotBaseDir") } : {}
|
|
9673
|
-
};
|
|
9674
|
-
}
|
|
9675
|
-
function persistRemoteAuthSession(context, source, result, fallbackToken) {
|
|
9676
|
-
const apiSessionToken = apiSessionTokenFrom2(result);
|
|
9677
|
-
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? fallbackToken, context.projectRoot);
|
|
9678
|
-
if (!apiSessionToken)
|
|
9679
|
-
return;
|
|
9680
|
-
const repo = readRepoConnection(context.projectRoot);
|
|
9681
|
-
const path = resolve18(context.projectRoot, ".rig", "state", "github-auth.json");
|
|
9682
|
-
mkdirSync9(dirname5(path), { recursive: true });
|
|
9683
|
-
writeFileSync7(path, `${JSON.stringify({
|
|
9684
|
-
authenticated: true,
|
|
9685
|
-
source,
|
|
9686
|
-
storedOnServer: true,
|
|
9687
|
-
...repo?.project ? { selectedRepo: repo.project } : {},
|
|
9688
|
-
...remoteNamespaceMetadata(result),
|
|
9689
|
-
apiSessionToken,
|
|
9690
|
-
updatedAt: new Date().toISOString()
|
|
9691
|
-
}, null, 2)}
|
|
9692
|
-
`, "utf8");
|
|
9693
|
-
}
|
|
9694
|
-
function isSignedIn(status) {
|
|
9695
|
-
return status.signedIn === true || status.authenticated === true;
|
|
9696
|
-
}
|
|
9697
8905
|
function readGhToken() {
|
|
9698
8906
|
const result = spawnSync2("gh", ["auth", "token"], { encoding: "utf8" });
|
|
9699
8907
|
if (result.status !== 0) {
|
|
@@ -9715,7 +8923,7 @@ async function executeGithub(context, args) {
|
|
|
9715
8923
|
if (rest.length > 0)
|
|
9716
8924
|
throw new CliError("Usage: rig github auth status", 1);
|
|
9717
8925
|
const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
|
|
9718
|
-
printPayload(context, status, `GitHub auth: ${
|
|
8926
|
+
printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
|
|
9719
8927
|
return { ok: true, group: "github", command: "auth status", details: status };
|
|
9720
8928
|
}
|
|
9721
8929
|
case "token": {
|
|
@@ -9725,20 +8933,16 @@ async function executeGithub(context, args) {
|
|
|
9725
8933
|
const token = parsed.value?.trim();
|
|
9726
8934
|
if (!token)
|
|
9727
8935
|
throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
|
|
9728
|
-
const
|
|
9729
|
-
|
|
9730
|
-
persistRemoteAuthSession(context, "token", result, token);
|
|
9731
|
-
printPayload(context, result, "GitHub token stored on the selected server.");
|
|
8936
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
|
|
8937
|
+
printPayload(context, result, "GitHub token stored on the selected Rig server.");
|
|
9732
8938
|
return { ok: true, group: "github", command: "auth token", details: result };
|
|
9733
8939
|
}
|
|
9734
8940
|
case "import-gh": {
|
|
9735
8941
|
if (rest.length > 0)
|
|
9736
8942
|
throw new CliError("Usage: rig github auth import-gh", 1);
|
|
9737
8943
|
const importedToken = readGhToken();
|
|
9738
|
-
const
|
|
9739
|
-
|
|
9740
|
-
persistRemoteAuthSession(context, "gh", result, importedToken);
|
|
9741
|
-
printPayload(context, result, "GitHub token imported from gh and stored on the selected server.");
|
|
8944
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
|
|
8945
|
+
printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
|
|
9742
8946
|
return { ok: true, group: "github", command: "auth import-gh", details: result };
|
|
9743
8947
|
}
|
|
9744
8948
|
default:
|
|
@@ -9768,7 +8972,7 @@ init_runner();
|
|
|
9768
8972
|
init__authority_runs();
|
|
9769
8973
|
init__paths();
|
|
9770
8974
|
import { readFileSync as readFileSync8 } from "fs";
|
|
9771
|
-
import { resolve as
|
|
8975
|
+
import { resolve as resolve18 } from "path";
|
|
9772
8976
|
import {
|
|
9773
8977
|
appendRunJournalEvent,
|
|
9774
8978
|
appendRunLogEntry,
|
|
@@ -9805,7 +9009,7 @@ function touchAuthorityRun(projectRoot, runId) {
|
|
|
9805
9009
|
if (!current) {
|
|
9806
9010
|
return;
|
|
9807
9011
|
}
|
|
9808
|
-
writeJsonFile3(
|
|
9012
|
+
writeJsonFile3(resolve18(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
|
|
9809
9013
|
...current,
|
|
9810
9014
|
updatedAt: new Date().toISOString()
|
|
9811
9015
|
});
|
|
@@ -10043,7 +9247,7 @@ init_runner();
|
|
|
10043
9247
|
init__server_client();
|
|
10044
9248
|
init__async_ui();
|
|
10045
9249
|
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
10046
|
-
import { resolve as
|
|
9250
|
+
import { resolve as resolve19 } from "path";
|
|
10047
9251
|
import {
|
|
10048
9252
|
listAuthorityRuns,
|
|
10049
9253
|
readAuthorityRun as readAuthorityRun3,
|
|
@@ -10087,7 +9291,7 @@ async function executeInspect(context, args) {
|
|
|
10087
9291
|
}
|
|
10088
9292
|
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
|
|
10089
9293
|
}
|
|
10090
|
-
const logsPath =
|
|
9294
|
+
const logsPath = resolve19(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
10091
9295
|
if (!existsSync12(logsPath)) {
|
|
10092
9296
|
throw new CliError(`No logs found for run ${latestRun.runId}.`, 1, { hint: `Try \`rig run show ${latestRun.runId}\` or \`rig run replay ${latestRun.runId}\`.` });
|
|
10093
9297
|
}
|
|
@@ -10175,7 +9379,7 @@ async function executeInspect(context, args) {
|
|
|
10175
9379
|
return { ok: true, group: "inspect", command };
|
|
10176
9380
|
case "audit": {
|
|
10177
9381
|
requireNoExtraArgs(rest, "rig inspect audit");
|
|
10178
|
-
const auditPath =
|
|
9382
|
+
const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
|
|
10179
9383
|
if (!existsSync12(auditPath)) {
|
|
10180
9384
|
console.log("No audit log found.");
|
|
10181
9385
|
} else {
|
|
@@ -10834,7 +10038,7 @@ import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/co
|
|
|
10834
10038
|
|
|
10835
10039
|
// packages/cli/src/commands/_run-replay.ts
|
|
10836
10040
|
import { existsSync as existsSync13, readdirSync as readdirSync2 } from "fs";
|
|
10837
|
-
import { join as join2, resolve as
|
|
10041
|
+
import { join as join2, resolve as resolve20 } from "path";
|
|
10838
10042
|
import {
|
|
10839
10043
|
readAuthorityRun as readAuthorityRun4,
|
|
10840
10044
|
readJsonlFile as readJsonlFile3,
|
|
@@ -10927,7 +10131,7 @@ function resolveRunSessionFile(record) {
|
|
|
10927
10131
|
const sessionId = text(piSession.sessionId);
|
|
10928
10132
|
if (!cwd || !sessionId)
|
|
10929
10133
|
return null;
|
|
10930
|
-
const sessionDir =
|
|
10134
|
+
const sessionDir = resolve20(cwd, ".rig", "session");
|
|
10931
10135
|
try {
|
|
10932
10136
|
const match = readdirSync2(sessionDir).find((name) => name.endsWith(`_${sessionId}.jsonl`));
|
|
10933
10137
|
return match ? join2(sessionDir, match) : null;
|
|
@@ -11425,9 +10629,6 @@ async function executeRun(context, args) {
|
|
|
11425
10629
|
console.log(`Stop requested: ${runId}`);
|
|
11426
10630
|
return { ok: true, group: "run", command, details: stopped };
|
|
11427
10631
|
}
|
|
11428
|
-
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
11429
|
-
throw new CliError("Remote run stop requires an explicit run id.", 2, { hint: "Run `rig run list`, then `rig run stop <run-id>`." });
|
|
11430
|
-
}
|
|
11431
10632
|
const result = await runStop(context.projectRoot);
|
|
11432
10633
|
if (result.remaining.length > 0) {
|
|
11433
10634
|
throw new CliError(`Failed to stop run(s): ${result.remaining.join(", ")}`, 1, { hint: "Check `rig run status`, then retry `rig run stop <run-id>` for the remaining runs." });
|
|
@@ -11460,7 +10661,6 @@ init_drone_ui();
|
|
|
11460
10661
|
init_runner();
|
|
11461
10662
|
init__connection_state();
|
|
11462
10663
|
init__cli_format();
|
|
11463
|
-
init__server_client();
|
|
11464
10664
|
function usageName(options) {
|
|
11465
10665
|
return `rig ${options.group}`;
|
|
11466
10666
|
}
|
|
@@ -11480,46 +10680,13 @@ function parseConnection(alias, value, options) {
|
|
|
11480
10680
|
}
|
|
11481
10681
|
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
11482
10682
|
}
|
|
11483
|
-
function printJsonOrText(context,
|
|
11484
|
-
if (context.outputMode
|
|
10683
|
+
function printJsonOrText(context, payload, text2) {
|
|
10684
|
+
if (context.outputMode === "json") {
|
|
10685
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
10686
|
+
} else {
|
|
11485
10687
|
console.log(text2);
|
|
11486
10688
|
}
|
|
11487
10689
|
}
|
|
11488
|
-
function formatRemoteProjectLinkText(result) {
|
|
11489
|
-
return formatSuccessCard(result.ok ? "Remote project link ready" : "Remote project link needs repair", [
|
|
11490
|
-
["selected", result.alias ?? "remote"],
|
|
11491
|
-
["target", result.baseUrl ?? "unknown"],
|
|
11492
|
-
["repo", result.repoSlug ?? "owner/repo"],
|
|
11493
|
-
["status", result.status],
|
|
11494
|
-
...result.serverProjectRoot ? [["server root", result.serverProjectRoot]] : [],
|
|
11495
|
-
["next", result.ok ? result.next ?? "rig task list" : result.hint]
|
|
11496
|
-
]);
|
|
11497
|
-
}
|
|
11498
|
-
function parseRepairLinkArgs(rest, usage) {
|
|
11499
|
-
let repoSlug;
|
|
11500
|
-
let mode = "prepare-if-missing";
|
|
11501
|
-
const pending = [...rest];
|
|
11502
|
-
while (pending.length > 0) {
|
|
11503
|
-
const token = pending.shift();
|
|
11504
|
-
if (token === "--repo") {
|
|
11505
|
-
const value = pending.shift()?.trim();
|
|
11506
|
-
if (!value)
|
|
11507
|
-
throw new CliError(`Missing --repo value. Usage: ${usage}`, 1);
|
|
11508
|
-
const normalized = normalizeRepoSlug(value);
|
|
11509
|
-
if (!normalized)
|
|
11510
|
-
throw new CliError(`Invalid --repo value: ${value}`, 1, { hint: "Use the canonical owner/repo slug, e.g. `--repo humanity-org/humanwork`." });
|
|
11511
|
-
repoSlug = normalized;
|
|
11512
|
-
} else if (token === "--backfill-only") {
|
|
11513
|
-
mode = "backfill-only";
|
|
11514
|
-
} else if (token === "--prepare") {
|
|
11515
|
-
mode = "prepare-if-missing";
|
|
11516
|
-
} else {
|
|
11517
|
-
throw new CliError(`Unexpected argument: ${String(token)}
|
|
11518
|
-
Usage: ${usage}`, 1);
|
|
11519
|
-
}
|
|
11520
|
-
}
|
|
11521
|
-
return { repoSlug, mode };
|
|
11522
|
-
}
|
|
11523
10690
|
async function promptForConnectionAlias(context) {
|
|
11524
10691
|
const state = readGlobalConnections();
|
|
11525
10692
|
const repo = readRepoConnection(context.projectRoot);
|
|
@@ -11573,67 +10740,31 @@ async function executeConnectionCommand(context, args, options) {
|
|
|
11573
10740
|
}
|
|
11574
10741
|
if (!alias)
|
|
11575
10742
|
throw new CliError(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
|
|
11576
|
-
let selectedConnection = { kind: "local", mode: "auto" };
|
|
11577
10743
|
if (alias !== "local") {
|
|
11578
10744
|
const state = readGlobalConnections();
|
|
11579
|
-
|
|
11580
|
-
if (!connection)
|
|
10745
|
+
if (!state.connections[alias])
|
|
11581
10746
|
throw new CliError(`Unknown Rig server: ${alias}`, 1, { hint: "Run `rig server list` to see saved aliases, or save one with `rig server add <alias> <url>`." });
|
|
11582
|
-
|
|
11583
|
-
}
|
|
11584
|
-
const previousRepo = readRepoConnection(context.projectRoot);
|
|
11585
|
-
const preserveRemoteRoot = Boolean(previousRepo?.serverProjectRoot && previousRepo.selected === alias && selectedConnection.kind === "remote" && previousRepo.serverProjectRootAlias === alias && previousRepo.serverProjectRootBaseUrl === selectedConnection.baseUrl);
|
|
11586
|
-
const repoState = {
|
|
11587
|
-
selected: alias,
|
|
11588
|
-
...previousRepo?.project ? { project: previousRepo.project } : {},
|
|
11589
|
-
linkedAt: new Date().toISOString(),
|
|
11590
|
-
...preserveRemoteRoot ? {
|
|
11591
|
-
serverProjectRoot: previousRepo.serverProjectRoot,
|
|
11592
|
-
serverProjectRootAlias: previousRepo.serverProjectRootAlias,
|
|
11593
|
-
serverProjectRootBaseUrl: previousRepo.serverProjectRootBaseUrl
|
|
11594
|
-
} : {}
|
|
11595
|
-
};
|
|
10747
|
+
}
|
|
10748
|
+
const repoState = { selected: alias, linkedAt: new Date().toISOString() };
|
|
11596
10749
|
writeRepoConnection(context.projectRoot, repoState);
|
|
11597
|
-
|
|
11598
|
-
ok: false,
|
|
11599
|
-
status: "error",
|
|
11600
|
-
message: error instanceof Error ? error.message : String(error),
|
|
11601
|
-
hint: "Run `rig server repair-link` after authenticating the selected remote."
|
|
11602
|
-
})) : null;
|
|
11603
|
-
const latestRepo = readRepoConnection(context.projectRoot);
|
|
11604
|
-
const details = { selected: latestRepo?.selected ?? alias, repo: latestRepo, remoteProjectLink };
|
|
11605
|
-
printJsonOrText(context, details, formatSuccessCard("Rig server selected", [
|
|
10750
|
+
printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
|
|
11606
10751
|
["selected", alias],
|
|
11607
10752
|
["scope", "this repo"],
|
|
11608
|
-
|
|
11609
|
-
["next", remoteProjectLink && !remoteProjectLink.ok ? "rig server repair-link" : "rig task list"]
|
|
10753
|
+
["next", "rig task list"]
|
|
11610
10754
|
]));
|
|
11611
|
-
return { ok: true, group: options.group, command: "use", details };
|
|
11612
|
-
}
|
|
11613
|
-
case "repair-link": {
|
|
11614
|
-
const parsed = parseRepairLinkArgs(rest, `${usageName(options)} repair-link [--prepare|--backfill-only] [--repo owner/repo]`);
|
|
11615
|
-
const result = await repairRemoteProjectRootLink(context, parsed);
|
|
11616
|
-
printJsonOrText(context, result, formatRemoteProjectLinkText(result));
|
|
11617
|
-
return { ok: true, group: options.group, command: "repair-link", details: result };
|
|
10755
|
+
return { ok: true, group: options.group, command: "use", details: repoState };
|
|
11618
10756
|
}
|
|
11619
10757
|
case "status": {
|
|
11620
10758
|
requireNoExtraArgs(rest, `${usageName(options)} status`);
|
|
11621
10759
|
const repo = readRepoConnection(context.projectRoot);
|
|
11622
10760
|
const global = readGlobalConnections();
|
|
11623
|
-
const
|
|
11624
|
-
|
|
11625
|
-
status: "error",
|
|
11626
|
-
message: error instanceof Error ? error.message : String(error),
|
|
11627
|
-
hint: "Run `rig server repair-link` after authenticating the selected remote."
|
|
11628
|
-
})) : null;
|
|
11629
|
-
const latestRepo = readRepoConnection(context.projectRoot) ?? repo;
|
|
11630
|
-
const details = { selected: latestRepo?.selected ?? "local", repo: latestRepo, connections: global.connections, remoteProjectLink };
|
|
11631
|
-
printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections, latestRepo ?? null, remoteProjectLink));
|
|
10761
|
+
const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
|
|
10762
|
+
printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections));
|
|
11632
10763
|
return { ok: true, group: options.group, command: "status", details };
|
|
11633
10764
|
}
|
|
11634
10765
|
default:
|
|
11635
10766
|
throw new CliError(`Unknown ${options.group} command: ${String(command)}
|
|
11636
|
-
Usage: ${usageName(options)} <list|add|use|status
|
|
10767
|
+
Usage: ${usageName(options)} <list|add|use|status>`, 1);
|
|
11637
10768
|
}
|
|
11638
10769
|
}
|
|
11639
10770
|
|
|
@@ -11641,7 +10772,7 @@ Usage: ${usageName(options)} <list|add|use|status|repair-link>`, 1);
|
|
|
11641
10772
|
init__server_client();
|
|
11642
10773
|
async function executeServer(context, args, options) {
|
|
11643
10774
|
const [command = "status", ...rest] = args;
|
|
11644
|
-
if (["status", "list", "add", "use"
|
|
10775
|
+
if (["status", "list", "add", "use"].includes(command)) {
|
|
11645
10776
|
return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
|
|
11646
10777
|
}
|
|
11647
10778
|
switch (command) {
|
|
@@ -11849,8 +10980,8 @@ init_task();
|
|
|
11849
10980
|
|
|
11850
10981
|
// packages/cli/src/commands/task-run-driver.ts
|
|
11851
10982
|
init_runner();
|
|
11852
|
-
import { copyFileSync as copyFileSync3, existsSync as existsSync15, mkdirSync as
|
|
11853
|
-
import { resolve as
|
|
10983
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
10984
|
+
import { resolve as resolve22 } from "path";
|
|
11854
10985
|
import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
|
|
11855
10986
|
import { createInterface as createLineInterface } from "readline";
|
|
11856
10987
|
import { loadConfig as loadConfig2 } from "@rig/core/load-config";
|
|
@@ -11949,12 +11080,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
|
|
|
11949
11080
|
return 0;
|
|
11950
11081
|
let copied = 0;
|
|
11951
11082
|
for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
|
|
11952
|
-
const sourcePath =
|
|
11953
|
-
const targetPath =
|
|
11083
|
+
const sourcePath = resolve22(sourceRoot, relativePath);
|
|
11084
|
+
const targetPath = resolve22(targetRoot, relativePath);
|
|
11954
11085
|
try {
|
|
11955
11086
|
if (!statSync2(sourcePath).isFile())
|
|
11956
11087
|
continue;
|
|
11957
|
-
|
|
11088
|
+
mkdirSync9(resolve22(targetPath, ".."), { recursive: true });
|
|
11958
11089
|
copyFileSync3(sourcePath, targetPath);
|
|
11959
11090
|
copied += 1;
|
|
11960
11091
|
} catch {}
|
|
@@ -11993,7 +11124,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
|
|
|
11993
11124
|
return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
|
|
11994
11125
|
return {
|
|
11995
11126
|
RIG_BASELINE_MODE: "dirty-snapshot",
|
|
11996
|
-
RIG_DIRTY_BASELINE_READY_FILE:
|
|
11127
|
+
RIG_DIRTY_BASELINE_READY_FILE: resolve22(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
|
|
11997
11128
|
};
|
|
11998
11129
|
}
|
|
11999
11130
|
function positiveInt(value, fallback) {
|
|
@@ -12098,9 +11229,9 @@ function createCommandRunner(binary) {
|
|
|
12098
11229
|
const stderrChunks = [];
|
|
12099
11230
|
child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
12100
11231
|
child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
12101
|
-
return await new Promise((
|
|
12102
|
-
child.once("error", (error) =>
|
|
12103
|
-
child.once("close", (code) =>
|
|
11232
|
+
return await new Promise((resolve23) => {
|
|
11233
|
+
child.once("error", (error) => resolve23({ exitCode: 1, stderr: error.message }));
|
|
11234
|
+
child.once("close", (code) => resolve23({
|
|
12104
11235
|
exitCode: code ?? 1,
|
|
12105
11236
|
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
12106
11237
|
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
@@ -12174,7 +11305,7 @@ async function runTaskRunPostValidationLifecycle(input) {
|
|
|
12174
11305
|
config,
|
|
12175
11306
|
sourceTask: input.sourceTask,
|
|
12176
11307
|
uploadedSnapshot: input.uploadedSnapshot,
|
|
12177
|
-
artifactRoot:
|
|
11308
|
+
artifactRoot: resolve22(input.projectRoot, "artifacts", taskId3),
|
|
12178
11309
|
command: ghCommand,
|
|
12179
11310
|
gitCommand,
|
|
12180
11311
|
steerPi,
|
|
@@ -12304,7 +11435,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
|
|
|
12304
11435
|
return null;
|
|
12305
11436
|
}
|
|
12306
11437
|
for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
|
|
12307
|
-
const summary = readJsonFile3(
|
|
11438
|
+
const summary = readJsonFile3(resolve22(artifactDir, "validation-summary.json"), null);
|
|
12308
11439
|
if (!summary || summary.status !== "fail") {
|
|
12309
11440
|
continue;
|
|
12310
11441
|
}
|
|
@@ -12385,9 +11516,9 @@ function readTaskRunAcceptedArtifactState(input) {
|
|
|
12385
11516
|
if (!input.taskId || !input.workspaceDir) {
|
|
12386
11517
|
return { accepted: false, reason: null };
|
|
12387
11518
|
}
|
|
12388
|
-
const artifactDir =
|
|
12389
|
-
const reviewStatusPath =
|
|
12390
|
-
const taskResultPath =
|
|
11519
|
+
const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
|
|
11520
|
+
const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
|
|
11521
|
+
const taskResultPath = resolve22(artifactDir, "task-result.json");
|
|
12391
11522
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
12392
11523
|
if (reviewStatus !== "APPROVED") {
|
|
12393
11524
|
return { accepted: false, reason: null };
|
|
@@ -12424,12 +11555,12 @@ function resolveTaskRunRetryContext(input) {
|
|
|
12424
11555
|
if (!input.taskId || !input.workspaceDir) {
|
|
12425
11556
|
return { shouldRetry: false, failureDetail: null, nextPrompt: null };
|
|
12426
11557
|
}
|
|
12427
|
-
const artifactDir =
|
|
12428
|
-
const reviewStatePath =
|
|
12429
|
-
const reviewFeedbackPath =
|
|
12430
|
-
const reviewStatusPath =
|
|
12431
|
-
const failedApproachesPath =
|
|
12432
|
-
const validationSummaryPath =
|
|
11558
|
+
const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
|
|
11559
|
+
const reviewStatePath = resolve22(artifactDir, "review-state.json");
|
|
11560
|
+
const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
|
|
11561
|
+
const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
|
|
11562
|
+
const failedApproachesPath = resolve22(input.workspaceDir, ".rig", "state", "failed_approaches.md");
|
|
11563
|
+
const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
|
|
12433
11564
|
const reviewState = readJsonFile3(reviewStatePath, null);
|
|
12434
11565
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
12435
11566
|
const reviewRejected = isTaskRunReviewRejected(reviewState);
|
|
@@ -12839,15 +11970,15 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
12839
11970
|
const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
|
|
12840
11971
|
const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
|
|
12841
11972
|
const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
|
|
12842
|
-
const planningArtifactPath =
|
|
11973
|
+
const planningArtifactPath = resolve22("artifacts", runtimeTaskId, "implementation-plan.md");
|
|
12843
11974
|
const persistedPlanning = {
|
|
12844
11975
|
...planningClassification,
|
|
12845
11976
|
classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
|
|
12846
11977
|
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
12847
11978
|
classifiedAt: new Date().toISOString()
|
|
12848
11979
|
};
|
|
12849
|
-
|
|
12850
|
-
|
|
11980
|
+
mkdirSync9(resolve22(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
|
|
11981
|
+
writeFileSync7(resolve22(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
|
|
12851
11982
|
`, "utf8");
|
|
12852
11983
|
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
12853
11984
|
prompt = `${prompt}
|
|
@@ -12897,7 +12028,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
12897
12028
|
let verificationStarted = false;
|
|
12898
12029
|
let reviewStarted = false;
|
|
12899
12030
|
let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
|
|
12900
|
-
let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ?
|
|
12031
|
+
let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve22(existingRunRecord.sessionPath, "..") : null;
|
|
12901
12032
|
let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
|
|
12902
12033
|
let latestProviderCommand = null;
|
|
12903
12034
|
let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
|
|
@@ -12983,10 +12114,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
12983
12114
|
setRunStatusOrFail(context.projectRoot, input.runId, "running");
|
|
12984
12115
|
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
12985
12116
|
worktreePath: latestRuntimeWorkspace,
|
|
12986
|
-
artifactRoot: latestRuntimeWorkspace && input.taskId ?
|
|
12117
|
+
artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve22(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
|
|
12987
12118
|
logRoot: latestLogsDir,
|
|
12988
|
-
sessionPath: latestSessionDir ?
|
|
12989
|
-
sessionLogPath: latestLogsDir ?
|
|
12119
|
+
sessionPath: latestSessionDir ? resolve22(latestSessionDir, "session.json") : null,
|
|
12120
|
+
sessionLogPath: latestLogsDir ? resolve22(latestLogsDir, "agent-stdout.log") : null,
|
|
12990
12121
|
branch: runtimeId
|
|
12991
12122
|
});
|
|
12992
12123
|
if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
|
|
@@ -12994,8 +12125,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
12994
12125
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
12995
12126
|
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
12996
12127
|
if (readyFile) {
|
|
12997
|
-
|
|
12998
|
-
|
|
12128
|
+
mkdirSync9(resolve22(readyFile, ".."), { recursive: true });
|
|
12129
|
+
writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
12999
12130
|
`, "utf8");
|
|
13000
12131
|
}
|
|
13001
12132
|
appendRunLog(context.projectRoot, input.runId, {
|
|
@@ -13391,7 +12522,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
13391
12522
|
let acceptedArtifactObservedAt = null;
|
|
13392
12523
|
let acceptedArtifactPollTimer = null;
|
|
13393
12524
|
let acceptedArtifactKillTimer = null;
|
|
13394
|
-
const attemptExit = await new Promise((
|
|
12525
|
+
const attemptExit = await new Promise((resolve23) => {
|
|
13395
12526
|
let settled = false;
|
|
13396
12527
|
const settle = (result) => {
|
|
13397
12528
|
if (settled)
|
|
@@ -13399,7 +12530,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
13399
12530
|
settled = true;
|
|
13400
12531
|
if (acceptedArtifactPollTimer)
|
|
13401
12532
|
clearInterval(acceptedArtifactPollTimer);
|
|
13402
|
-
|
|
12533
|
+
resolve23(result);
|
|
13403
12534
|
};
|
|
13404
12535
|
const pollAcceptedArtifacts = () => {
|
|
13405
12536
|
const artifactState = readTaskRunAcceptedArtifactState({
|
|
@@ -13602,7 +12733,7 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
13602
12733
|
}
|
|
13603
12734
|
if (planningClassification.planningRequired) {
|
|
13604
12735
|
const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
|
|
13605
|
-
const expectedPlanPath =
|
|
12736
|
+
const expectedPlanPath = resolve22(planWorkspace, planningArtifactPath);
|
|
13606
12737
|
if (!existsSync15(expectedPlanPath)) {
|
|
13607
12738
|
const failedAt = new Date().toISOString();
|
|
13608
12739
|
const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
|
|
@@ -13772,9 +12903,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
13772
12903
|
});
|
|
13773
12904
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
|
|
13774
12905
|
});
|
|
13775
|
-
const exitCode = await new Promise((
|
|
13776
|
-
child.once("error", () =>
|
|
13777
|
-
child.once("close", (code) =>
|
|
12906
|
+
const exitCode = await new Promise((resolve23) => {
|
|
12907
|
+
child.once("error", () => resolve23(1));
|
|
12908
|
+
child.once("close", (code) => resolve23(code ?? 1));
|
|
13778
12909
|
});
|
|
13779
12910
|
for (const pendingLog of flushPendingClaudeToolUseLogs({
|
|
13780
12911
|
runId: input.runId,
|
|
@@ -13915,8 +13046,8 @@ async function executeTest(context, args) {
|
|
|
13915
13046
|
init_runner();
|
|
13916
13047
|
init__parsers();
|
|
13917
13048
|
init__paths();
|
|
13918
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
13919
|
-
import { resolve as
|
|
13049
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, readdirSync as readdirSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
13050
|
+
import { resolve as resolve23 } from "path";
|
|
13920
13051
|
import { createPluginHost } from "@rig/core";
|
|
13921
13052
|
import {
|
|
13922
13053
|
isSupportedBunVersion as isSupportedBunVersion2,
|
|
@@ -13971,12 +13102,12 @@ function runSetupInit(projectRoot) {
|
|
|
13971
13102
|
const stateDir = resolveControlPlaneHostStateDir(projectRoot);
|
|
13972
13103
|
const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
|
|
13973
13104
|
const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
const failuresPath =
|
|
13105
|
+
mkdirSync10(stateDir, { recursive: true });
|
|
13106
|
+
mkdirSync10(logsDir, { recursive: true });
|
|
13107
|
+
mkdirSync10(artifactsDir, { recursive: true });
|
|
13108
|
+
const failuresPath = resolve23(stateDir, "failed_approaches.md");
|
|
13978
13109
|
if (!existsSync16(failuresPath)) {
|
|
13979
|
-
|
|
13110
|
+
writeFileSync8(failuresPath, `# Failed Approaches
|
|
13980
13111
|
|
|
13981
13112
|
`, "utf-8");
|
|
13982
13113
|
}
|
|
@@ -13993,17 +13124,17 @@ async function runSetupCheck(projectRoot, outputMode = "text") {
|
|
|
13993
13124
|
}
|
|
13994
13125
|
async function runSetupPreflight(projectRoot, outputMode = "text") {
|
|
13995
13126
|
await runSetupCheck(projectRoot, outputMode);
|
|
13996
|
-
const validationRoot =
|
|
13127
|
+
const validationRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
13997
13128
|
if (existsSync16(validationRoot)) {
|
|
13998
13129
|
const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
13999
13130
|
for (const validator of validators) {
|
|
14000
|
-
const script =
|
|
13131
|
+
const script = resolve23(validationRoot, validator.name, "validate.sh");
|
|
14001
13132
|
if (existsSync16(script)) {
|
|
14002
13133
|
console.log(`OK: validator script ${script}`);
|
|
14003
13134
|
}
|
|
14004
13135
|
}
|
|
14005
13136
|
}
|
|
14006
|
-
const hooksRoot =
|
|
13137
|
+
const hooksRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
|
|
14007
13138
|
if (existsSync16(hooksRoot)) {
|
|
14008
13139
|
const hooks = readdirSync3(hooksRoot).filter((name) => name.endsWith(".sh"));
|
|
14009
13140
|
for (const hook of hooks) {
|
|
@@ -14150,7 +13281,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
|
|
|
14150
13281
|
]);
|
|
14151
13282
|
var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
14152
13283
|
function hasInitializedRigProject(projectRoot) {
|
|
14153
|
-
return RIG_CONFIG_FILENAMES.some((name) => existsSync18(
|
|
13284
|
+
return RIG_CONFIG_FILENAMES.some((name) => existsSync18(resolve24(projectRoot, name))) || existsSync18(resolve24(projectRoot, ".rig"));
|
|
14154
13285
|
}
|
|
14155
13286
|
function requireInitializedRigProject(context, group) {
|
|
14156
13287
|
if (hasInitializedRigProject(context.projectRoot)) {
|
|
@@ -14204,7 +13335,7 @@ function resolveTopLevelLaunchState(context) {
|
|
|
14204
13335
|
let selectedServer = null;
|
|
14205
13336
|
if (projectInitialized) {
|
|
14206
13337
|
try {
|
|
14207
|
-
const statePath =
|
|
13338
|
+
const statePath = resolve24(context.projectRoot, ".rig", "state", "connection.json");
|
|
14208
13339
|
if (existsSync18(statePath)) {
|
|
14209
13340
|
const parsed = JSON.parse(readFileSync13(statePath, "utf-8"));
|
|
14210
13341
|
selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
|
|
@@ -14213,14 +13344,8 @@ function resolveTopLevelLaunchState(context) {
|
|
|
14213
13344
|
}
|
|
14214
13345
|
return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
|
|
14215
13346
|
}
|
|
14216
|
-
function envTruthy(value) {
|
|
14217
|
-
if (!value)
|
|
14218
|
-
return false;
|
|
14219
|
-
const normalized = value.trim().toLowerCase();
|
|
14220
|
-
return normalized !== "0" && normalized !== "false" && normalized !== "no";
|
|
14221
|
-
}
|
|
14222
13347
|
function shouldOpenApp(context) {
|
|
14223
|
-
return context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1"
|
|
13348
|
+
return context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
14224
13349
|
}
|
|
14225
13350
|
async function openApp(context, options = {}) {
|
|
14226
13351
|
const { runOperatorBoardLoop: runOperatorBoardLoop2 } = await Promise.resolve().then(() => (init_board(), exports_board));
|