@h-rig/cli 0.0.6-alpha.88 → 0.0.6-alpha.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rig.js +1159 -292
- package/dist/src/app/board.js +462 -48
- package/dist/src/app-opentui/adapters/doctor.js +458 -46
- package/dist/src/app-opentui/adapters/family.js +670 -147
- package/dist/src/app-opentui/adapters/fleet.js +477 -46
- package/dist/src/app-opentui/adapters/inbox.js +477 -46
- package/dist/src/app-opentui/adapters/init.js +497 -74
- package/dist/src/app-opentui/adapters/inspect.js +477 -46
- package/dist/src/app-opentui/adapters/pi-attach.js +484 -53
- package/dist/src/app-opentui/adapters/run-detail.js +477 -46
- package/dist/src/app-opentui/adapters/server.d.ts +26 -0
- package/dist/src/app-opentui/adapters/server.js +676 -59
- package/dist/src/app-opentui/adapters/tasks.js +539 -81
- package/dist/src/app-opentui/autocomplete.js +4 -2
- package/dist/src/app-opentui/bootstrap.js +1155 -288
- package/dist/src/app-opentui/command-palette.js +37 -10
- package/dist/src/app-opentui/index.js +566 -89
- package/dist/src/app-opentui/intent.js +33 -8
- package/dist/src/app-opentui/keymap.js +43 -29
- package/dist/src/app-opentui/pi-host-child.js +465 -53
- package/dist/src/app-opentui/react/App.js +104 -44
- package/dist/src/app-opentui/react/ChromeHost.js +16 -4
- package/dist/src/app-opentui/react/launch.js +555 -88
- package/dist/src/app-opentui/react/nav.js +1 -1
- package/dist/src/app-opentui/registry.js +1062 -237
- package/dist/src/app-opentui/remote-link.d.ts +10 -0
- package/dist/src/app-opentui/remote-link.js +47 -0
- package/dist/src/app-opentui/runtime.js +566 -89
- package/dist/src/app-opentui/scenes/doctor.js +1 -1
- package/dist/src/app-opentui/scenes/error.js +50 -4
- package/dist/src/app-opentui/scenes/family.js +60 -6
- package/dist/src/app-opentui/scenes/fleet.js +65 -13
- package/dist/src/app-opentui/scenes/help.js +4 -2
- package/dist/src/app-opentui/scenes/init.js +12 -12
- package/dist/src/app-opentui/scenes/main.js +7 -7
- package/dist/src/app-opentui/scenes/server.js +83 -11
- package/dist/src/app-opentui/scenes/tasks.js +79 -16
- package/dist/src/app-opentui/state.js +25 -5
- package/dist/src/app-opentui/surface-catalog.js +4 -2
- package/dist/src/app-opentui/types.d.ts +1 -1
- package/dist/src/commands/_cli-format.d.ts +10 -1
- package/dist/src/commands/_cli-format.js +5 -2
- package/dist/src/commands/_connection-state.d.ts +11 -1
- package/dist/src/commands/_connection-state.js +50 -5
- package/dist/src/commands/_doctor-checks.js +458 -46
- package/dist/src/commands/_help-catalog.js +4 -2
- package/dist/src/commands/_json-output.js +4 -0
- package/dist/src/commands/_operator-view.js +465 -53
- package/dist/src/commands/_pi-frontend.js +465 -53
- package/dist/src/commands/_preflight.js +509 -72
- package/dist/src/commands/_server-client.d.ts +33 -0
- package/dist/src/commands/_server-client.js +477 -46
- package/dist/src/commands/_server-events.js +446 -41
- package/dist/src/commands/_snapshot-upload.js +460 -48
- package/dist/src/commands/connect.js +620 -15
- package/dist/src/commands/doctor.js +458 -46
- package/dist/src/commands/github.js +462 -50
- package/dist/src/commands/inbox.js +458 -46
- package/dist/src/commands/init.js +497 -74
- package/dist/src/commands/inspect.js +458 -46
- package/dist/src/commands/run.js +465 -53
- package/dist/src/commands/server.js +647 -163
- package/dist/src/commands/setup.js +463 -51
- package/dist/src/commands/stats.js +462 -48
- package/dist/src/commands/task-run-driver.js +464 -52
- package/dist/src/commands/task.js +520 -81
- package/dist/src/commands.js +670 -147
- package/dist/src/index.js +674 -147
- package/dist/src/launcher.js +4 -0
- package/package.json +8 -8
package/dist/bin/rig.js
CHANGED
|
@@ -338,7 +338,8 @@ __export(exports__connection_state, {
|
|
|
338
338
|
resolveGlobalConnectionsPath: () => resolveGlobalConnectionsPath,
|
|
339
339
|
readRepoConnection: () => readRepoConnection,
|
|
340
340
|
readGlobalConnections: () => readGlobalConnections,
|
|
341
|
-
isRemoteConnectionSelected: () => isRemoteConnectionSelected
|
|
341
|
+
isRemoteConnectionSelected: () => isRemoteConnectionSelected,
|
|
342
|
+
clearRepoServerProjectRoot: () => clearRepoServerProjectRoot
|
|
342
343
|
});
|
|
343
344
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
|
|
344
345
|
import { homedir } from "os";
|
|
@@ -422,12 +423,28 @@ function readRepoConnection(projectRoot) {
|
|
|
422
423
|
selected,
|
|
423
424
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
424
425
|
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
425
|
-
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
426
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined,
|
|
427
|
+
serverProjectRootAlias: typeof record.serverProjectRootAlias === "string" && record.serverProjectRootAlias.trim() ? record.serverProjectRootAlias.trim() : undefined,
|
|
428
|
+
serverProjectRootBaseUrl: typeof record.serverProjectRootBaseUrl === "string" && record.serverProjectRootBaseUrl.trim() ? record.serverProjectRootBaseUrl.trim().replace(/\/+$/, "") : undefined
|
|
426
429
|
};
|
|
427
430
|
}
|
|
428
431
|
function writeRepoConnection(projectRoot, state) {
|
|
429
432
|
writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
|
|
430
433
|
}
|
|
434
|
+
function rootAllowedForSelection(repo, connection) {
|
|
435
|
+
const root = repo.serverProjectRoot?.trim();
|
|
436
|
+
if (!root)
|
|
437
|
+
return;
|
|
438
|
+
if (connection.kind === "remote") {
|
|
439
|
+
if (repo.serverProjectRootAlias !== repo.selected)
|
|
440
|
+
return;
|
|
441
|
+
if (repo.serverProjectRootBaseUrl !== connection.baseUrl)
|
|
442
|
+
return;
|
|
443
|
+
} else if (repo.serverProjectRootAlias && repo.serverProjectRootAlias !== repo.selected) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
return root;
|
|
447
|
+
}
|
|
431
448
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
432
449
|
const repo = readRepoConnection(projectRoot);
|
|
433
450
|
if (!repo)
|
|
@@ -439,13 +456,41 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
439
456
|
if (!connection) {
|
|
440
457
|
throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
441
458
|
}
|
|
442
|
-
return { alias: repo.selected, connection, serverProjectRoot: repo
|
|
459
|
+
return { alias: repo.selected, connection, serverProjectRoot: rootAllowedForSelection(repo, connection) };
|
|
443
460
|
}
|
|
444
|
-
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
461
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot, metadata = {}) {
|
|
445
462
|
const repo = readRepoConnection(projectRoot);
|
|
446
463
|
if (!repo)
|
|
447
464
|
return;
|
|
448
|
-
|
|
465
|
+
let inferred = metadata;
|
|
466
|
+
if (!inferred.alias || !inferred.baseUrl) {
|
|
467
|
+
try {
|
|
468
|
+
const selected = resolveSelectedConnection(projectRoot);
|
|
469
|
+
if (selected?.connection.kind === "remote") {
|
|
470
|
+
inferred = {
|
|
471
|
+
alias: inferred.alias ?? selected.alias,
|
|
472
|
+
baseUrl: inferred.baseUrl ?? selected.connection.baseUrl
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
} catch {}
|
|
476
|
+
}
|
|
477
|
+
writeRepoConnection(projectRoot, {
|
|
478
|
+
...repo,
|
|
479
|
+
...metadata.project ? { project: metadata.project } : {},
|
|
480
|
+
serverProjectRoot,
|
|
481
|
+
...inferred.alias ? { serverProjectRootAlias: inferred.alias } : {},
|
|
482
|
+
...inferred.baseUrl ? { serverProjectRootBaseUrl: inferred.baseUrl.replace(/\/+$/, "") } : {}
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
function clearRepoServerProjectRoot(projectRoot) {
|
|
486
|
+
const repo = readRepoConnection(projectRoot);
|
|
487
|
+
if (!repo)
|
|
488
|
+
return;
|
|
489
|
+
writeRepoConnection(projectRoot, {
|
|
490
|
+
selected: repo.selected,
|
|
491
|
+
...repo.project ? { project: repo.project } : {},
|
|
492
|
+
...repo.linkedAt ? { linkedAt: repo.linkedAt } : {}
|
|
493
|
+
});
|
|
449
494
|
}
|
|
450
495
|
function isRemoteConnectionSelected(projectRoot) {
|
|
451
496
|
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
@@ -472,12 +517,16 @@ __export(exports__server_client, {
|
|
|
472
517
|
respondRunPiExtensionUiViaServer: () => respondRunPiExtensionUiViaServer,
|
|
473
518
|
resolveServerConnectionLabel: () => resolveServerConnectionLabel,
|
|
474
519
|
requestServerJson: () => requestServerJson,
|
|
520
|
+
repairRemoteProjectRootLink: () => repairRemoteProjectRootLink,
|
|
475
521
|
registerProjectViaServer: () => registerProjectViaServer,
|
|
476
522
|
prepareRemoteCheckoutViaServer: () => prepareRemoteCheckoutViaServer,
|
|
477
523
|
postGitHubTokenViaServer: () => postGitHubTokenViaServer,
|
|
524
|
+
normalizeRepoSlug: () => normalizeRepoSlug,
|
|
478
525
|
listWorkspaceTasksViaServer: () => listWorkspaceTasksViaServer,
|
|
479
526
|
listRunsViaServer: () => listRunsViaServer,
|
|
480
527
|
listGitHubProjectsViaServer: () => listGitHubProjectsViaServer,
|
|
528
|
+
isRemoteProjectRootLinkError: () => isRemoteProjectRootLinkError,
|
|
529
|
+
inspectRemoteProjectLink: () => inspectRemoteProjectLink,
|
|
481
530
|
getWorkspaceTaskViaServer: () => getWorkspaceTaskViaServer,
|
|
482
531
|
getRunTimelineViaServer: () => getRunTimelineViaServer,
|
|
483
532
|
getRunPiStatusViaServer: () => getRunPiStatusViaServer,
|
|
@@ -489,13 +538,15 @@ __export(exports__server_client, {
|
|
|
489
538
|
getRunDetailsViaServer: () => getRunDetailsViaServer,
|
|
490
539
|
getGitHubProjectStatusFieldViaServer: () => getGitHubProjectStatusFieldViaServer,
|
|
491
540
|
getGitHubAuthStatusViaServer: () => getGitHubAuthStatusViaServer,
|
|
541
|
+
formatRemoteProjectLinkHint: () => formatRemoteProjectLinkHint,
|
|
492
542
|
ensureTaskLabelsViaServer: () => ensureTaskLabelsViaServer,
|
|
493
543
|
ensureServerForCli: () => ensureServerForCli,
|
|
544
|
+
ensureRemoteProjectRootLink: () => ensureRemoteProjectRootLink,
|
|
494
545
|
buildRunPiEventsWebSocketUrl: () => buildRunPiEventsWebSocketUrl,
|
|
495
546
|
abortRunPiViaServer: () => abortRunPiViaServer
|
|
496
547
|
});
|
|
497
|
-
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
498
|
-
import { resolve as resolve3 } from "path";
|
|
548
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
549
|
+
import { dirname as dirname2, isAbsolute, resolve as resolve3 } from "path";
|
|
499
550
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
500
551
|
function setServerPhaseListener(listener) {
|
|
501
552
|
const previous = serverPhaseListener;
|
|
@@ -541,11 +592,10 @@ function readStoredGitHubAuthToken(projectRoot) {
|
|
|
541
592
|
const parsed = readRemoteAuthState(projectRoot);
|
|
542
593
|
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
543
594
|
}
|
|
544
|
-
function
|
|
545
|
-
|
|
546
|
-
const slug = repo?.project?.trim();
|
|
547
|
-
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
595
|
+
function inferRemoteServerProjectRootCandidateFromAuthState(projectRoot, repoSlug) {
|
|
596
|
+
if (!/^[^/]+\/[^/]+$/.test(repoSlug))
|
|
548
597
|
return null;
|
|
598
|
+
const repo = readRepoConnection(projectRoot);
|
|
549
599
|
const auth = readRemoteAuthState(projectRoot);
|
|
550
600
|
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
551
601
|
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
@@ -554,25 +604,426 @@ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
|
554
604
|
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
555
605
|
if (!checkoutBaseDir)
|
|
556
606
|
return null;
|
|
557
|
-
|
|
558
|
-
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
559
|
-
return inferred;
|
|
607
|
+
return `${checkoutBaseDir.replace(/\/+$/, "")}/${repoSlug}`;
|
|
560
608
|
}
|
|
561
609
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
562
610
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
563
611
|
}
|
|
612
|
+
function normalizeRepoSlug(value) {
|
|
613
|
+
const slug = value?.trim();
|
|
614
|
+
return slug && /^[^/\s]+\/[^/\s]+$/.test(slug) ? slug : null;
|
|
615
|
+
}
|
|
616
|
+
function readProjectLinkSlug(projectRoot) {
|
|
617
|
+
const path = resolve3(projectRoot, ".rig", "state", "project-link.json");
|
|
618
|
+
if (!existsSync3(path))
|
|
619
|
+
return null;
|
|
620
|
+
try {
|
|
621
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
622
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
623
|
+
return null;
|
|
624
|
+
return normalizeRepoSlug(typeof parsed.repoSlug === "string" ? String(parsed.repoSlug) : null);
|
|
625
|
+
} catch {
|
|
626
|
+
return null;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
function writeProjectLinkConnection(projectRoot, repoSlug, alias) {
|
|
630
|
+
const path = resolve3(projectRoot, ".rig", "state", "project-link.json");
|
|
631
|
+
mkdirSync3(dirname2(path), { recursive: true });
|
|
632
|
+
writeFileSync2(path, `${JSON.stringify({ repoSlug, connection: alias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
633
|
+
`, "utf8");
|
|
634
|
+
}
|
|
635
|
+
function remoteLinkRepairCommand(repoSlug) {
|
|
636
|
+
return repoSlug ? `rig server repair-link --repo ${repoSlug}` : "rig server repair-link --repo owner/repo";
|
|
637
|
+
}
|
|
638
|
+
function isRemoteProjectRootLinkError(error) {
|
|
639
|
+
const text = error instanceof Error ? error.message : String(error ?? "");
|
|
640
|
+
return /no server-host project root link|remote project(?:-root)? link|x-rig-project-root|serverProjectRoot/i.test(text);
|
|
641
|
+
}
|
|
642
|
+
function formatRemoteProjectLinkHint(resolution) {
|
|
643
|
+
const repair = remoteLinkRepairCommand(resolution.repoSlug);
|
|
644
|
+
if (resolution.status === "auth_required") {
|
|
645
|
+
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}` : ""}\`.`;
|
|
646
|
+
}
|
|
647
|
+
if (resolution.status === "missing_project") {
|
|
648
|
+
return `Record the repo slug, then run \`${repair}\` (or \`rig init --repo owner/repo --server remote --github-auth device\`).`;
|
|
649
|
+
}
|
|
650
|
+
if (resolution.status === "not_remote")
|
|
651
|
+
return "Select a remote server with `rig server use <alias>` before repairing a remote project link.";
|
|
652
|
+
return `Run \`${repair}\` to backfill or prepare a server-host checkout for the selected remote${resolution.alias ? ` (${resolution.alias})` : ""}.`;
|
|
653
|
+
}
|
|
654
|
+
function remoteProjectLinkFailure(input) {
|
|
655
|
+
const partial = {
|
|
656
|
+
status: input.status,
|
|
657
|
+
alias: input.alias,
|
|
658
|
+
baseUrl: input.baseUrl,
|
|
659
|
+
repoSlug: input.repoSlug
|
|
660
|
+
};
|
|
661
|
+
return {
|
|
662
|
+
ok: false,
|
|
663
|
+
...input,
|
|
664
|
+
hint: formatRemoteProjectLinkHint(partial),
|
|
665
|
+
next: remoteLinkRepairCommand(input.repoSlug)
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function remoteProjectLinkSuccess(input) {
|
|
669
|
+
return {
|
|
670
|
+
ok: true,
|
|
671
|
+
status: input.status,
|
|
672
|
+
alias: input.alias,
|
|
673
|
+
baseUrl: input.baseUrl,
|
|
674
|
+
repoSlug: input.repoSlug,
|
|
675
|
+
serverProjectRoot: input.serverProjectRoot,
|
|
676
|
+
source: input.source,
|
|
677
|
+
prepared: input.prepared ?? input.status === "prepared",
|
|
678
|
+
validated: input.validated ?? false,
|
|
679
|
+
message: input.message ?? `Remote project link ready for ${input.repoSlug}.`,
|
|
680
|
+
hint: "Remote-scoped task/run/status requests will send x-rig-project-root for this server-host checkout.",
|
|
681
|
+
next: "rig task list"
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function localCheckoutPathCandidate(projectRoot, candidate) {
|
|
685
|
+
try {
|
|
686
|
+
const local = resolve3(projectRoot);
|
|
687
|
+
const resolved = resolve3(candidate);
|
|
688
|
+
return resolved === local || resolved.startsWith(`${local}/`);
|
|
689
|
+
} catch {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
async function requestRemoteProjectLinkJson(baseUrl, pathname, authToken, init = {}) {
|
|
694
|
+
const requestUrl = new URL(`${baseUrl}${pathname}`);
|
|
695
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
696
|
+
requestUrl.searchParams.set("rt", authToken);
|
|
697
|
+
const response = await fetch(requestUrl, {
|
|
698
|
+
...init,
|
|
699
|
+
headers: mergeHeaders(init.headers, authToken)
|
|
700
|
+
});
|
|
701
|
+
const text = await response.text();
|
|
702
|
+
const payload = text.trim().length > 0 ? (() => {
|
|
703
|
+
try {
|
|
704
|
+
return JSON.parse(text);
|
|
705
|
+
} catch {
|
|
706
|
+
return null;
|
|
707
|
+
}
|
|
708
|
+
})() : null;
|
|
709
|
+
return { ok: response.ok, status: response.status, payload, text };
|
|
710
|
+
}
|
|
711
|
+
function payloadError(payload, fallback) {
|
|
712
|
+
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
713
|
+
const record = payload;
|
|
714
|
+
const value = record.error ?? record.message ?? record.reason;
|
|
715
|
+
if (typeof value === "string" && value.trim())
|
|
716
|
+
return value.trim();
|
|
717
|
+
}
|
|
718
|
+
return fallback;
|
|
719
|
+
}
|
|
720
|
+
function checkoutPathsFromProjectPayload(payload) {
|
|
721
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
722
|
+
return [];
|
|
723
|
+
const project = payload.project;
|
|
724
|
+
if (!project || typeof project !== "object" || Array.isArray(project))
|
|
725
|
+
return [];
|
|
726
|
+
const checkouts = project.checkouts;
|
|
727
|
+
if (!Array.isArray(checkouts))
|
|
728
|
+
return [];
|
|
729
|
+
return [...checkouts].reverse().flatMap((entry) => {
|
|
730
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
731
|
+
return [];
|
|
732
|
+
const path = entry.path;
|
|
733
|
+
return typeof path === "string" && path.trim() ? [path.trim()] : [];
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
function checkoutPathFromPreparePayload(payload) {
|
|
737
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
738
|
+
return null;
|
|
739
|
+
const checkout = payload.checkout;
|
|
740
|
+
if (!checkout || typeof checkout !== "object" || Array.isArray(checkout))
|
|
741
|
+
return null;
|
|
742
|
+
const path = checkout.path;
|
|
743
|
+
return typeof path === "string" && path.trim() ? path.trim() : null;
|
|
744
|
+
}
|
|
745
|
+
async function validateAndPersistRemoteRoot(input) {
|
|
746
|
+
const candidate = input.candidate.trim();
|
|
747
|
+
if (!candidate || !isAbsolute(candidate)) {
|
|
748
|
+
return remoteProjectLinkFailure({
|
|
749
|
+
status: "invalid_root",
|
|
750
|
+
alias: input.alias,
|
|
751
|
+
baseUrl: input.baseUrl,
|
|
752
|
+
repoSlug: input.repoSlug,
|
|
753
|
+
message: `Remote project root candidate is not an absolute server-host path: ${candidate || "(empty)"}.`
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
if (localCheckoutPathCandidate(input.projectRoot, candidate)) {
|
|
757
|
+
return remoteProjectLinkFailure({
|
|
758
|
+
status: "invalid_root",
|
|
759
|
+
alias: input.alias,
|
|
760
|
+
baseUrl: input.baseUrl,
|
|
761
|
+
repoSlug: input.repoSlug,
|
|
762
|
+
message: `Refusing to use local checkout path ${candidate} as a remote server project root.`
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
let response;
|
|
766
|
+
try {
|
|
767
|
+
response = await requestRemoteProjectLinkJson(input.baseUrl, "/api/server/project-root", input.authToken, {
|
|
768
|
+
method: "POST",
|
|
769
|
+
headers: { "content-type": "application/json" },
|
|
770
|
+
body: JSON.stringify({ projectRoot: candidate })
|
|
771
|
+
});
|
|
772
|
+
} catch (error) {
|
|
773
|
+
return remoteProjectLinkFailure({
|
|
774
|
+
status: "error",
|
|
775
|
+
alias: input.alias,
|
|
776
|
+
baseUrl: input.baseUrl,
|
|
777
|
+
repoSlug: input.repoSlug,
|
|
778
|
+
message: `Could not validate remote project root ${candidate}: ${error instanceof Error ? error.message : String(error)}`
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
if (response.status === 401 || response.status === 403) {
|
|
782
|
+
return remoteProjectLinkFailure({
|
|
783
|
+
status: "auth_required",
|
|
784
|
+
alias: input.alias,
|
|
785
|
+
baseUrl: input.baseUrl,
|
|
786
|
+
repoSlug: input.repoSlug,
|
|
787
|
+
statusCode: response.status,
|
|
788
|
+
message: `Remote server ${input.alias} requires authentication before validating project root ${candidate}.`
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
if (!response.ok) {
|
|
792
|
+
return remoteProjectLinkFailure({
|
|
793
|
+
status: "invalid_root",
|
|
794
|
+
alias: input.alias,
|
|
795
|
+
baseUrl: input.baseUrl,
|
|
796
|
+
repoSlug: input.repoSlug,
|
|
797
|
+
statusCode: response.status,
|
|
798
|
+
message: `Remote server rejected project root ${candidate} (${response.status}): ${payloadError(response.payload, response.text || "project-root validation failed")}`
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
const record = response.payload && typeof response.payload === "object" && !Array.isArray(response.payload) ? response.payload : {};
|
|
802
|
+
if (record.ok !== true) {
|
|
803
|
+
return remoteProjectLinkFailure({
|
|
804
|
+
status: "invalid_root",
|
|
805
|
+
alias: input.alias,
|
|
806
|
+
baseUrl: input.baseUrl,
|
|
807
|
+
repoSlug: input.repoSlug,
|
|
808
|
+
message: `Remote server did not accept project root ${candidate}: ${payloadError(response.payload, "project-root validation failed")}`
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
const accepted = typeof record.projectRoot === "string" && record.projectRoot.trim() ? record.projectRoot.trim() : typeof record.requestedProjectRoot === "string" && record.requestedProjectRoot.trim() ? record.requestedProjectRoot.trim() : candidate;
|
|
812
|
+
writeRepoServerProjectRoot(input.projectRoot, accepted, { alias: input.alias, baseUrl: input.baseUrl, project: input.repoSlug });
|
|
813
|
+
writeProjectLinkConnection(input.projectRoot, input.repoSlug, input.alias);
|
|
814
|
+
const status = input.status ?? (input.prepared ? "prepared" : "backfilled");
|
|
815
|
+
return remoteProjectLinkSuccess({
|
|
816
|
+
status,
|
|
817
|
+
alias: input.alias,
|
|
818
|
+
baseUrl: input.baseUrl,
|
|
819
|
+
repoSlug: input.repoSlug,
|
|
820
|
+
serverProjectRoot: accepted,
|
|
821
|
+
source: input.source,
|
|
822
|
+
prepared: input.prepared,
|
|
823
|
+
validated: true,
|
|
824
|
+
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}.`
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
async function ensureRemoteProjectRootLink(projectRoot, options = {}) {
|
|
828
|
+
let selected;
|
|
829
|
+
try {
|
|
830
|
+
selected = resolveSelectedConnection(projectRoot);
|
|
831
|
+
} catch (error) {
|
|
832
|
+
return remoteProjectLinkFailure({ status: "error", message: error instanceof Error ? error.message : String(error) });
|
|
833
|
+
}
|
|
834
|
+
if (!selected || selected.connection.kind !== "remote") {
|
|
835
|
+
return remoteProjectLinkFailure({ status: "not_remote", message: "No remote Rig server is selected for this repo." });
|
|
836
|
+
}
|
|
837
|
+
const repo = readRepoConnection(projectRoot);
|
|
838
|
+
const explicitRepoRequested = options.repoSlug !== undefined;
|
|
839
|
+
const explicitRepoSlug = explicitRepoRequested ? normalizeRepoSlug(options.repoSlug) : null;
|
|
840
|
+
const repoProjectSlug = normalizeRepoSlug(repo?.project);
|
|
841
|
+
const repoSlug = explicitRepoSlug ?? repoProjectSlug ?? readProjectLinkSlug(projectRoot);
|
|
842
|
+
const alias = selected.alias;
|
|
843
|
+
const baseUrl = selected.connection.baseUrl;
|
|
844
|
+
const authToken = options.authToken === undefined ? readGitHubBearerTokenForRemote(projectRoot) : options.authToken;
|
|
845
|
+
const mode = options.mode ?? "backfill-only";
|
|
846
|
+
if (explicitRepoRequested && !explicitRepoSlug) {
|
|
847
|
+
return remoteProjectLinkFailure({
|
|
848
|
+
status: "missing_project",
|
|
849
|
+
alias,
|
|
850
|
+
baseUrl,
|
|
851
|
+
message: `Invalid --repo value ${JSON.stringify(options.repoSlug)}. Expected owner/repo.`
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
if (!repoSlug) {
|
|
855
|
+
return remoteProjectLinkFailure({
|
|
856
|
+
status: "missing_project",
|
|
857
|
+
alias,
|
|
858
|
+
baseUrl,
|
|
859
|
+
message: `Remote server ${alias} is selected, but this checkout has no GitHub repo slug recorded.`
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
const skippedCandidates = [];
|
|
863
|
+
const storedRoot = selected.serverProjectRoot?.trim() || null;
|
|
864
|
+
const storedRootMatchesResolvedRepo = repoProjectSlug === repoSlug;
|
|
865
|
+
if (storedRoot && storedRootMatchesResolvedRepo) {
|
|
866
|
+
if (localCheckoutPathCandidate(projectRoot, storedRoot)) {
|
|
867
|
+
clearRepoServerProjectRoot(projectRoot);
|
|
868
|
+
skippedCandidates.push(storedRoot);
|
|
869
|
+
} else {
|
|
870
|
+
const storedResult = await validateAndPersistRemoteRoot({
|
|
871
|
+
projectRoot,
|
|
872
|
+
alias,
|
|
873
|
+
baseUrl,
|
|
874
|
+
authToken,
|
|
875
|
+
repoSlug,
|
|
876
|
+
candidate: storedRoot,
|
|
877
|
+
source: "stored",
|
|
878
|
+
status: "ready"
|
|
879
|
+
});
|
|
880
|
+
if (storedResult.ok || storedResult.status === "auth_required" || storedResult.status === "error")
|
|
881
|
+
return storedResult;
|
|
882
|
+
clearRepoServerProjectRoot(projectRoot);
|
|
883
|
+
skippedCandidates.push(storedRoot);
|
|
884
|
+
}
|
|
885
|
+
} else if (storedRoot) {
|
|
886
|
+
skippedCandidates.push(storedRoot);
|
|
887
|
+
}
|
|
888
|
+
const authCandidate = inferRemoteServerProjectRootCandidateFromAuthState(projectRoot, repoSlug);
|
|
889
|
+
if (authCandidate) {
|
|
890
|
+
const authResult = await validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate: authCandidate, source: "auth-state" });
|
|
891
|
+
if (authResult.ok || authResult.status === "auth_required")
|
|
892
|
+
return authResult;
|
|
893
|
+
}
|
|
894
|
+
let registryResponse;
|
|
895
|
+
try {
|
|
896
|
+
registryResponse = await requestRemoteProjectLinkJson(baseUrl, `/api/projects/${encodeURIComponent(repoSlug)}`, authToken);
|
|
897
|
+
} catch (error) {
|
|
898
|
+
return remoteProjectLinkFailure({
|
|
899
|
+
status: "error",
|
|
900
|
+
alias,
|
|
901
|
+
baseUrl,
|
|
902
|
+
repoSlug,
|
|
903
|
+
message: `Could not read remote project registry for ${repoSlug} on ${alias}: ${error instanceof Error ? error.message : String(error)}`
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
if (registryResponse.status === 401 || registryResponse.status === 403) {
|
|
907
|
+
return remoteProjectLinkFailure({
|
|
908
|
+
status: "auth_required",
|
|
909
|
+
alias,
|
|
910
|
+
baseUrl,
|
|
911
|
+
repoSlug,
|
|
912
|
+
statusCode: registryResponse.status,
|
|
913
|
+
message: `Remote server ${alias} requires authentication before reading the ${repoSlug} project registry.`
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
if (registryResponse.ok) {
|
|
917
|
+
const candidates = checkoutPathsFromProjectPayload(registryResponse.payload);
|
|
918
|
+
for (const candidate of candidates) {
|
|
919
|
+
const result = await validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate, source: "registry" });
|
|
920
|
+
if (result.ok || result.status === "auth_required")
|
|
921
|
+
return result;
|
|
922
|
+
skippedCandidates.push(candidate);
|
|
923
|
+
}
|
|
924
|
+
if (mode === "backfill-only") {
|
|
925
|
+
return remoteProjectLinkFailure({
|
|
926
|
+
status: candidates.length > 0 ? "invalid_root" : "no_server_checkout",
|
|
927
|
+
alias,
|
|
928
|
+
baseUrl,
|
|
929
|
+
repoSlug,
|
|
930
|
+
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.`,
|
|
931
|
+
skippedCandidates
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
} else if (registryResponse.status === 404) {
|
|
935
|
+
if (mode === "backfill-only") {
|
|
936
|
+
return remoteProjectLinkFailure({
|
|
937
|
+
status: "project_not_registered",
|
|
938
|
+
alias,
|
|
939
|
+
baseUrl,
|
|
940
|
+
repoSlug,
|
|
941
|
+
statusCode: registryResponse.status,
|
|
942
|
+
message: `Remote server ${alias} has no registered project record for ${repoSlug}.`
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
} else {
|
|
946
|
+
return remoteProjectLinkFailure({
|
|
947
|
+
status: "error",
|
|
948
|
+
alias,
|
|
949
|
+
baseUrl,
|
|
950
|
+
repoSlug,
|
|
951
|
+
statusCode: registryResponse.status,
|
|
952
|
+
message: `Could not backfill ${repoSlug} from remote registry (${registryResponse.status}): ${payloadError(registryResponse.payload, registryResponse.text || "registry lookup failed")}`,
|
|
953
|
+
skippedCandidates
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
let prepareResponse;
|
|
957
|
+
try {
|
|
958
|
+
prepareResponse = await requestRemoteProjectLinkJson(baseUrl, `/api/projects/${encodeURIComponent(repoSlug)}/prepare-checkout`, authToken, {
|
|
959
|
+
method: "POST",
|
|
960
|
+
headers: { "content-type": "application/json" },
|
|
961
|
+
body: JSON.stringify({ checkout: { kind: "managed-clone" }, repoUrl: `https://github.com/${repoSlug}.git` })
|
|
962
|
+
});
|
|
963
|
+
} catch (error) {
|
|
964
|
+
return remoteProjectLinkFailure({
|
|
965
|
+
status: "error",
|
|
966
|
+
alias,
|
|
967
|
+
baseUrl,
|
|
968
|
+
repoSlug,
|
|
969
|
+
message: `Could not prepare remote checkout for ${repoSlug} on ${alias}: ${error instanceof Error ? error.message : String(error)}`
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
if (prepareResponse.status === 401 || prepareResponse.status === 403) {
|
|
973
|
+
return remoteProjectLinkFailure({
|
|
974
|
+
status: "auth_required",
|
|
975
|
+
alias,
|
|
976
|
+
baseUrl,
|
|
977
|
+
repoSlug,
|
|
978
|
+
statusCode: prepareResponse.status,
|
|
979
|
+
message: `Remote server ${alias} requires authentication before preparing ${repoSlug}.`
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
if (!prepareResponse.ok) {
|
|
983
|
+
return remoteProjectLinkFailure({
|
|
984
|
+
status: "error",
|
|
985
|
+
alias,
|
|
986
|
+
baseUrl,
|
|
987
|
+
repoSlug,
|
|
988
|
+
statusCode: prepareResponse.status,
|
|
989
|
+
message: `Remote checkout prepare failed for ${repoSlug} (${prepareResponse.status}): ${payloadError(prepareResponse.payload, prepareResponse.text || "prepare-checkout failed")}`,
|
|
990
|
+
skippedCandidates
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
const preparedPath = checkoutPathFromPreparePayload(prepareResponse.payload);
|
|
994
|
+
if (!preparedPath) {
|
|
995
|
+
return remoteProjectLinkFailure({
|
|
996
|
+
status: "invalid_root",
|
|
997
|
+
alias,
|
|
998
|
+
baseUrl,
|
|
999
|
+
repoSlug,
|
|
1000
|
+
message: `Remote checkout prepare for ${repoSlug} did not return a checkout.path.`,
|
|
1001
|
+
skippedCandidates
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
return validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate: preparedPath, source: "prepare", prepared: true });
|
|
1005
|
+
}
|
|
1006
|
+
async function inspectRemoteProjectLink(projectRoot) {
|
|
1007
|
+
return ensureRemoteProjectRootLink(projectRoot, { mode: "backfill-only" });
|
|
1008
|
+
}
|
|
1009
|
+
async function repairRemoteProjectRootLink(context, options = {}) {
|
|
1010
|
+
const resolution = await ensureRemoteProjectRootLink(context.projectRoot, { mode: options.mode ?? "prepare-if-missing", repoSlug: options.repoSlug });
|
|
1011
|
+
if (!resolution.ok)
|
|
1012
|
+
throw new CliError(resolution.message, 1, { hint: resolution.hint });
|
|
1013
|
+
return resolution;
|
|
1014
|
+
}
|
|
564
1015
|
async function ensureServerForCli(projectRoot) {
|
|
565
1016
|
try {
|
|
566
1017
|
const selected = resolveSelectedConnection(projectRoot);
|
|
567
1018
|
if (selected?.connection.kind === "remote") {
|
|
568
1019
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
569
1020
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
570
|
-
const
|
|
1021
|
+
const link = await ensureRemoteProjectRootLink(projectRoot, { mode: "backfill-only", authToken });
|
|
571
1022
|
return {
|
|
572
1023
|
baseUrl: selected.connection.baseUrl,
|
|
573
1024
|
authToken,
|
|
574
1025
|
connectionKind: "remote",
|
|
575
|
-
serverProjectRoot
|
|
1026
|
+
serverProjectRoot: link.ok ? link.serverProjectRoot ?? null : null
|
|
576
1027
|
};
|
|
577
1028
|
}
|
|
578
1029
|
reportServerPhase("Starting local Rig server\u2026");
|
|
@@ -590,32 +1041,6 @@ async function ensureServerForCli(projectRoot) {
|
|
|
590
1041
|
throw error;
|
|
591
1042
|
}
|
|
592
1043
|
}
|
|
593
|
-
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
594
|
-
const repo = readRepoConnection(projectRoot);
|
|
595
|
-
const slug = repo?.project?.trim();
|
|
596
|
-
if (!slug)
|
|
597
|
-
return null;
|
|
598
|
-
try {
|
|
599
|
-
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
600
|
-
if (authToken && queryAuthFallbackEnabled())
|
|
601
|
-
url.searchParams.set("rt", authToken);
|
|
602
|
-
const response = await fetch(url, {
|
|
603
|
-
headers: mergeHeaders(undefined, authToken)
|
|
604
|
-
});
|
|
605
|
-
if (!response.ok)
|
|
606
|
-
return null;
|
|
607
|
-
const payload = await response.json();
|
|
608
|
-
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
609
|
-
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
610
|
-
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
611
|
-
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
612
|
-
if (path)
|
|
613
|
-
writeRepoServerProjectRoot(projectRoot, path);
|
|
614
|
-
return path;
|
|
615
|
-
} catch {
|
|
616
|
-
return null;
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
1044
|
function appendTaskFilterParams(url, filters) {
|
|
620
1045
|
if (filters.assignee)
|
|
621
1046
|
url.searchParams.set("assignee", filters.assignee);
|
|
@@ -716,13 +1141,20 @@ function canUseRemoteWithoutProjectRoot(pathname) {
|
|
|
716
1141
|
async function requestServerJson(context, pathname, init = {}) {
|
|
717
1142
|
const server = await ensureServerForCli(context.projectRoot);
|
|
718
1143
|
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
1144
|
+
let scopedServerProjectRoot = server.serverProjectRoot;
|
|
1145
|
+
if (server.connectionKind === "remote" && !scopedServerProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
1146
|
+
const link = await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only", authToken: server.authToken });
|
|
1147
|
+
if (link.ok && link.serverProjectRoot) {
|
|
1148
|
+
scopedServerProjectRoot = link.serverProjectRoot;
|
|
1149
|
+
} else {
|
|
1150
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
1151
|
+
const target = link.alias && link.baseUrl ? `${link.alias} (${link.baseUrl})` : server.baseUrl;
|
|
1152
|
+
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 });
|
|
1153
|
+
}
|
|
722
1154
|
}
|
|
723
1155
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
724
|
-
if (
|
|
725
|
-
headers.set("x-rig-project-root",
|
|
1156
|
+
if (scopedServerProjectRoot)
|
|
1157
|
+
headers.set("x-rig-project-root", scopedServerProjectRoot);
|
|
726
1158
|
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
727
1159
|
requestUrl.searchParams.set("rt", server.authToken);
|
|
728
1160
|
}
|
|
@@ -1354,7 +1786,7 @@ __export(exports__pi_frontend, {
|
|
|
1354
1786
|
buildOperatorPiEnv: () => buildOperatorPiEnv,
|
|
1355
1787
|
attachRunBundledPiFrontend: () => attachRunBundledPiFrontend
|
|
1356
1788
|
});
|
|
1357
|
-
import { existsSync as existsSync4, mkdirSync as
|
|
1789
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
1358
1790
|
import { homedir as homedir2, tmpdir } from "os";
|
|
1359
1791
|
import { join } from "path";
|
|
1360
1792
|
import { main as runPiMain } from "@earendil-works/pi-coding-agent";
|
|
@@ -1406,7 +1838,7 @@ function statusFromRunDetails(run) {
|
|
|
1406
1838
|
async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
1407
1839
|
const server = await ensureServerForCli(context.projectRoot);
|
|
1408
1840
|
const localCwd = join(homedir2(), ".rig", "drones", runId.slice(0, 8));
|
|
1409
|
-
|
|
1841
|
+
mkdirSync4(localCwd, { recursive: true });
|
|
1410
1842
|
trustDroneCwd(localCwd);
|
|
1411
1843
|
installRigPiTheme();
|
|
1412
1844
|
let sessionFileArg = [];
|
|
@@ -1428,7 +1860,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
|
1428
1860
|
return line;
|
|
1429
1861
|
}).join(`
|
|
1430
1862
|
`);
|
|
1431
|
-
|
|
1863
|
+
writeFileSync3(localSessionPath, content);
|
|
1432
1864
|
sessionFileArg = ["--session", localSessionPath];
|
|
1433
1865
|
}
|
|
1434
1866
|
} catch {}
|
|
@@ -1444,12 +1876,12 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
|
1444
1876
|
function trustDroneCwd(localCwd) {
|
|
1445
1877
|
try {
|
|
1446
1878
|
const agentDir = join(homedir2(), ".pi", "agent");
|
|
1447
|
-
|
|
1879
|
+
mkdirSync4(agentDir, { recursive: true });
|
|
1448
1880
|
const trustPath = join(agentDir, "trust.json");
|
|
1449
1881
|
const store = existsSync4(trustPath) ? JSON.parse(readFileSync3(trustPath, "utf8")) : {};
|
|
1450
1882
|
if (store[localCwd] !== true) {
|
|
1451
1883
|
store[localCwd] = true;
|
|
1452
|
-
|
|
1884
|
+
writeFileSync3(trustPath, `${JSON.stringify(store, null, "\t")}
|
|
1453
1885
|
`);
|
|
1454
1886
|
}
|
|
1455
1887
|
} catch {}
|
|
@@ -1457,12 +1889,12 @@ function trustDroneCwd(localCwd) {
|
|
|
1457
1889
|
function installRigPiTheme() {
|
|
1458
1890
|
try {
|
|
1459
1891
|
const themesDir = join(homedir2(), ".pi", "agent", "themes");
|
|
1460
|
-
|
|
1892
|
+
mkdirSync4(themesDir, { recursive: true });
|
|
1461
1893
|
const themePath = join(themesDir, "rig.json");
|
|
1462
1894
|
const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
|
|
1463
1895
|
`;
|
|
1464
1896
|
if (!existsSync4(themePath) || readFileSync3(themePath, "utf8") !== next) {
|
|
1465
|
-
|
|
1897
|
+
writeFileSync3(themePath, next);
|
|
1466
1898
|
}
|
|
1467
1899
|
} catch {}
|
|
1468
1900
|
}
|
|
@@ -2777,12 +3209,13 @@ var init__help_catalog = __esm(() => {
|
|
|
2777
3209
|
{
|
|
2778
3210
|
name: "server",
|
|
2779
3211
|
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
2780
|
-
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
3212
|
+
usage: ["rig server <status|list|add|use|repair-link|start> [options]"],
|
|
2781
3213
|
commands: [
|
|
2782
|
-
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
3214
|
+
{ command: "status", description: "Show the selected server and remote project-root link for this repo.", primary: true },
|
|
2783
3215
|
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
2784
3216
|
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
2785
3217
|
{ command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
|
|
3218
|
+
{ command: "repair-link [--prepare|--backfill-only] [--repo owner/repo]", description: "Backfill or prepare the selected remote's server-host checkout link.", primary: true },
|
|
2786
3219
|
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
2787
3220
|
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
2788
3221
|
],
|
|
@@ -2790,6 +3223,7 @@ var init__help_catalog = __esm(() => {
|
|
|
2790
3223
|
"rig server status",
|
|
2791
3224
|
"rig server add prod https://where.rig-does.work",
|
|
2792
3225
|
"rig server use prod",
|
|
3226
|
+
"rig server repair-link --repo owner/repo",
|
|
2793
3227
|
"rig server use local",
|
|
2794
3228
|
"rig server start --port 3773"
|
|
2795
3229
|
],
|
|
@@ -3304,7 +3738,7 @@ function resolveControlPlaneDefinitionRoot(projectRoot) {
|
|
|
3304
3738
|
var init__paths = () => {};
|
|
3305
3739
|
|
|
3306
3740
|
// packages/cli/src/report-bug.ts
|
|
3307
|
-
import { copyFileSync, existsSync as existsSync7, mkdirSync as
|
|
3741
|
+
import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync5, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3308
3742
|
import { basename as basename2, extname, join as join2, resolve as resolve8 } from "path";
|
|
3309
3743
|
function slugifyBugTitle(value) {
|
|
3310
3744
|
const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80).replace(/-+$/g, "");
|
|
@@ -3343,8 +3777,8 @@ function createBugReportFiles(input) {
|
|
|
3343
3777
|
}
|
|
3344
3778
|
rmSync3(reportDir, { recursive: true, force: true });
|
|
3345
3779
|
}
|
|
3346
|
-
|
|
3347
|
-
|
|
3780
|
+
mkdirSync5(assetDir, { recursive: true });
|
|
3781
|
+
mkdirSync5(screenshotDir, { recursive: true });
|
|
3348
3782
|
const copiedScreenshots = copyEvidenceFiles(input.projectRoot, screenshotDir, input.screenshots ?? [], "screenshot");
|
|
3349
3783
|
const copiedAssets = copyEvidenceFiles(input.projectRoot, assetDir, input.assets ?? [], "asset");
|
|
3350
3784
|
const manifestAssets = [
|
|
@@ -3374,15 +3808,15 @@ function createBugReportFiles(input) {
|
|
|
3374
3808
|
platform: process.platform,
|
|
3375
3809
|
arch: process.arch
|
|
3376
3810
|
};
|
|
3377
|
-
|
|
3378
|
-
|
|
3811
|
+
writeFileSync4(join2(assetDir, "README.md"), buildAssetReadme(input.title), "utf8");
|
|
3812
|
+
writeFileSync4(join2(screenshotDir, "README.md"), buildScreenshotReadme(input.title), "utf8");
|
|
3379
3813
|
if (browserPath && browser) {
|
|
3380
|
-
|
|
3814
|
+
writeFileSync4(browserPath, `${JSON.stringify(browser, null, 2)}
|
|
3381
3815
|
`, "utf8");
|
|
3382
3816
|
}
|
|
3383
|
-
|
|
3817
|
+
writeFileSync4(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
3384
3818
|
`, "utf8");
|
|
3385
|
-
|
|
3819
|
+
writeFileSync4(taskPath, buildBugReportMarkdown(input, browser, copiedScreenshots, copiedAssets), "utf8");
|
|
3386
3820
|
return {
|
|
3387
3821
|
slug,
|
|
3388
3822
|
reportDir,
|
|
@@ -3559,7 +3993,7 @@ function formatAssetMarkdown(name, path) {
|
|
|
3559
3993
|
var init_report_bug = () => {};
|
|
3560
3994
|
|
|
3561
3995
|
// packages/cli/src/commands/task-report-bug.ts
|
|
3562
|
-
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as
|
|
3996
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3563
3997
|
import { resolve as resolve9 } from "path";
|
|
3564
3998
|
import pc3 from "picocolors";
|
|
3565
3999
|
import {
|
|
@@ -3921,7 +4355,7 @@ function appendTaskConfigEntryPreservingText(taskConfigPath, issueId, entry) {
|
|
|
3921
4355
|
`).map((line) => ` ${line}`).join(`
|
|
3922
4356
|
`);
|
|
3923
4357
|
if (!trimmed || trimmed === "{}") {
|
|
3924
|
-
|
|
4358
|
+
writeFileSync5(taskConfigPath, `{
|
|
3925
4359
|
${serializedEntry}
|
|
3926
4360
|
}
|
|
3927
4361
|
`, "utf8");
|
|
@@ -3937,7 +4371,7 @@ ${serializedEntry}
|
|
|
3937
4371
|
throw new CliError(`Invalid trailing content in task config: ${taskConfigPath}`, 1, { hint: "Remove the trailing content so the file is a single JSON object, then retry." });
|
|
3938
4372
|
}
|
|
3939
4373
|
const comma = before.trim() === "{" ? "" : ",";
|
|
3940
|
-
|
|
4374
|
+
writeFileSync5(taskConfigPath, `${before}${comma}
|
|
3941
4375
|
${serializedEntry}
|
|
3942
4376
|
}
|
|
3943
4377
|
`, "utf8");
|
|
@@ -4322,7 +4756,7 @@ var init_task_report_bug = __esm(() => {
|
|
|
4322
4756
|
});
|
|
4323
4757
|
|
|
4324
4758
|
// packages/cli/src/commands/browser.ts
|
|
4325
|
-
import { mkdirSync as
|
|
4759
|
+
import { mkdirSync as mkdirSync6, rmSync as rmSync4 } from "fs";
|
|
4326
4760
|
import { resolve as resolve10 } from "path";
|
|
4327
4761
|
import { spawn } from "child_process";
|
|
4328
4762
|
import { emitKeypressEvents } from "readline";
|
|
@@ -4900,7 +5334,7 @@ function readBrowserDemoCommandLine(command) {
|
|
|
4900
5334
|
}
|
|
4901
5335
|
async function launchBrowserDemo(runtime) {
|
|
4902
5336
|
rmSync4(resolve10(runtime.browserDir, runtime.stateDir), { recursive: true, force: true });
|
|
4903
|
-
|
|
5337
|
+
mkdirSync6(resolve10(runtime.browserDir, runtime.stateDir), { recursive: true });
|
|
4904
5338
|
const launcherPath = resolve10(runtime.browserDir, "scripts/electron-launcher.mjs");
|
|
4905
5339
|
const launcher = await import(pathToFileURL(launcherPath).href);
|
|
4906
5340
|
const electronPath = await launcher.resolveElectronPath();
|
|
@@ -5249,7 +5683,7 @@ var init_profile_and_review = __esm(() => {
|
|
|
5249
5683
|
});
|
|
5250
5684
|
|
|
5251
5685
|
// packages/cli/src/commands/_policy.ts
|
|
5252
|
-
import { appendFileSync, mkdirSync as
|
|
5686
|
+
import { appendFileSync, mkdirSync as mkdirSync7 } from "fs";
|
|
5253
5687
|
import { resolve as resolve11 } from "path";
|
|
5254
5688
|
import { evaluate as evaluate2, loadPolicy as loadPolicy2, resolveAction as resolveAction2 } from "@rig/runtime/control-plane/runtime/guard";
|
|
5255
5689
|
import { resolveHarnessPaths } from "@rig/runtime/control-plane/native/utils";
|
|
@@ -5266,7 +5700,7 @@ function appendControlledBashAudit(context, mode, command, args, matchedRuleIds,
|
|
|
5266
5700
|
}
|
|
5267
5701
|
const logsDir = resolveHarnessPaths(context.projectRoot).logsDir;
|
|
5268
5702
|
const logFile = resolve11(logsDir, "controlled-bash.jsonl");
|
|
5269
|
-
|
|
5703
|
+
mkdirSync7(logsDir, { recursive: true });
|
|
5270
5704
|
const payload = {
|
|
5271
5705
|
timestamp: new Date().toISOString(),
|
|
5272
5706
|
mode,
|
|
@@ -5560,9 +5994,9 @@ var exports_pi = {};
|
|
|
5560
5994
|
__export(exports_pi, {
|
|
5561
5995
|
executePi: () => executePi
|
|
5562
5996
|
});
|
|
5563
|
-
import { existsSync as existsSync10, mkdirSync as
|
|
5997
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
5564
5998
|
import { homedir as homedir5 } from "os";
|
|
5565
|
-
import { dirname as
|
|
5999
|
+
import { dirname as dirname3, resolve as resolve13 } from "path";
|
|
5566
6000
|
function settingsPath(root) {
|
|
5567
6001
|
return resolve13(root, ".pi", "settings.json");
|
|
5568
6002
|
}
|
|
@@ -5587,8 +6021,8 @@ function packageKey(entry) {
|
|
|
5587
6021
|
return JSON.stringify(entry);
|
|
5588
6022
|
}
|
|
5589
6023
|
function writeSettings(path, settings) {
|
|
5590
|
-
|
|
5591
|
-
|
|
6024
|
+
mkdirSync8(dirname3(path), { recursive: true });
|
|
6025
|
+
writeFileSync6(path, `${JSON.stringify(settings, null, 2)}
|
|
5592
6026
|
`, "utf-8");
|
|
5593
6027
|
}
|
|
5594
6028
|
async function searchNpmForPiExtensions(term) {
|
|
@@ -5771,6 +6205,14 @@ function permissionAllowsPr2(payload) {
|
|
|
5771
6205
|
function isNotFoundError(error) {
|
|
5772
6206
|
return /\b(404|not found)\b/i.test(message(error));
|
|
5773
6207
|
}
|
|
6208
|
+
function isLoopbackBaseUrl(baseUrl) {
|
|
6209
|
+
try {
|
|
6210
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
6211
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
6212
|
+
} catch {
|
|
6213
|
+
return false;
|
|
6214
|
+
}
|
|
6215
|
+
}
|
|
5774
6216
|
function projectCheckoutReady(payload) {
|
|
5775
6217
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
5776
6218
|
return null;
|
|
@@ -5825,25 +6267,37 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
5825
6267
|
}
|
|
5826
6268
|
const repo = readRepoConnection(context.projectRoot);
|
|
5827
6269
|
const remoteWithoutProjectLink = selectedServer?.connectionKind === "remote" && !repo?.project;
|
|
5828
|
-
|
|
6270
|
+
let remoteRootBlocked = false;
|
|
6271
|
+
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>`."));
|
|
6272
|
+
if (selectedServer?.connectionKind === "remote" && repo?.project && !selectedServer.serverProjectRoot) {
|
|
6273
|
+
const link = await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only", authToken: selectedServer.authToken });
|
|
6274
|
+
const loopbackDevRemote = !selectedServer.authToken && isLoopbackBaseUrl(selectedServer.baseUrl);
|
|
6275
|
+
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));
|
|
6276
|
+
remoteRootBlocked = !link.ok && !loopbackDevRemote;
|
|
6277
|
+
}
|
|
5829
6278
|
try {
|
|
5830
6279
|
const auth = await request("/api/github/auth/status");
|
|
5831
6280
|
checks.push(isAuthenticated2(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>`."));
|
|
5832
6281
|
} catch (error) {
|
|
5833
6282
|
checks.push(preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix GitHub auth on the selected Rig server."));
|
|
5834
6283
|
}
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
6284
|
+
if (!remoteRootBlocked) {
|
|
6285
|
+
try {
|
|
6286
|
+
const projection = await request("/api/workspace/task-projection");
|
|
6287
|
+
checks.push(preflightCheck("task-projection", "task projection ready", "pass", JSON.stringify(projection).slice(0, 120)));
|
|
6288
|
+
} catch (error) {
|
|
6289
|
+
checks.push(preflightCheck("task-projection", "task projection ready", "warn", message(error), "Refresh task projection with `rig task list` before launching."));
|
|
6290
|
+
}
|
|
6291
|
+
try {
|
|
6292
|
+
const permissions = await request("/api/github/repo/permissions");
|
|
6293
|
+
const allowed = permissionAllowsPr2(permissions);
|
|
6294
|
+
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."));
|
|
6295
|
+
} catch (error) {
|
|
6296
|
+
checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", message(error), "Ensure the selected token can push branches and open PRs."));
|
|
6297
|
+
}
|
|
6298
|
+
} else {
|
|
6299
|
+
checks.push(preflightCheck("task-projection", "task projection ready", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
|
|
6300
|
+
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."));
|
|
5847
6301
|
}
|
|
5848
6302
|
if (repo?.project) {
|
|
5849
6303
|
try {
|
|
@@ -5855,19 +6309,24 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
5855
6309
|
}
|
|
5856
6310
|
}
|
|
5857
6311
|
if (taskId) {
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
6312
|
+
if (!remoteRootBlocked) {
|
|
6313
|
+
try {
|
|
6314
|
+
const tasks = await request(`/api/workspace/tasks?limit=200&refresh=1`);
|
|
6315
|
+
const found = Array.isArray(tasks) && tasks.some((task) => taskMatchesId(task, taskId));
|
|
6316
|
+
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."));
|
|
6317
|
+
} catch (error) {
|
|
6318
|
+
checks.push(preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix the task source before launching a run."));
|
|
6319
|
+
}
|
|
6320
|
+
try {
|
|
6321
|
+
const runs = await request("/api/runs?limit=200");
|
|
6322
|
+
const duplicate = activeDuplicateRun(runs, taskId);
|
|
6323
|
+
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));
|
|
6324
|
+
} catch (error) {
|
|
6325
|
+
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."));
|
|
6326
|
+
}
|
|
6327
|
+
} else {
|
|
6328
|
+
checks.push(preflightCheck("issue", "task/issue accessible", "fail", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
|
|
6329
|
+
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."));
|
|
5871
6330
|
}
|
|
5872
6331
|
}
|
|
5873
6332
|
if ((options.runtimeAdapter ?? "pi") === "pi") {
|
|
@@ -6348,7 +6807,7 @@ import {
|
|
|
6348
6807
|
chmodSync,
|
|
6349
6808
|
copyFileSync as copyFileSync2,
|
|
6350
6809
|
existsSync as existsSync12,
|
|
6351
|
-
mkdirSync as
|
|
6810
|
+
mkdirSync as mkdirSync9,
|
|
6352
6811
|
readdirSync,
|
|
6353
6812
|
readlinkSync,
|
|
6354
6813
|
rmSync as rmSync5,
|
|
@@ -6453,7 +6912,7 @@ async function executeDist(context, args) {
|
|
|
6453
6912
|
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
6454
6913
|
const scope = parseInstallScope(scopeResult.value);
|
|
6455
6914
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
6456
|
-
|
|
6915
|
+
mkdirSync9(installDir, { recursive: true });
|
|
6457
6916
|
let source = await findLatestDistBinary(context.projectRoot);
|
|
6458
6917
|
let buildDir = null;
|
|
6459
6918
|
if (!source) {
|
|
@@ -6508,7 +6967,7 @@ async function executeDist(context, args) {
|
|
|
6508
6967
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
6509
6968
|
const currentId = computeRuntimeImageId(fp);
|
|
6510
6969
|
const imagesDir = resolve16(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
6511
|
-
|
|
6970
|
+
mkdirSync9(imagesDir, { recursive: true });
|
|
6512
6971
|
let pruned = 0;
|
|
6513
6972
|
for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
|
|
6514
6973
|
if (entry.isDirectory() && entry.name !== currentId) {
|
|
@@ -6520,9 +6979,9 @@ async function executeDist(context, args) {
|
|
|
6520
6979
|
console.log(`Pruned ${pruned} stale image(s).`);
|
|
6521
6980
|
}
|
|
6522
6981
|
const imageDir = resolve16(imagesDir, currentId);
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6982
|
+
mkdirSync9(resolve16(imageDir, "bin/hooks"), { recursive: true });
|
|
6983
|
+
mkdirSync9(resolve16(imageDir, "bin/plugins"), { recursive: true });
|
|
6984
|
+
mkdirSync9(resolve16(imageDir, "bin/validators"), { recursive: true });
|
|
6526
6985
|
const hookNames = [
|
|
6527
6986
|
"scope-guard",
|
|
6528
6987
|
"import-guard",
|
|
@@ -6547,8 +7006,8 @@ async function executeDist(context, args) {
|
|
|
6547
7006
|
const binPluginsDir = resolve16(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
|
|
6548
7007
|
const validatorsRoot = resolve16(hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
6549
7008
|
const binValidatorsDir = resolve16(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
|
|
6550
|
-
|
|
6551
|
-
|
|
7009
|
+
mkdirSync9(binPluginsDir, { recursive: true });
|
|
7010
|
+
mkdirSync9(binValidatorsDir, { recursive: true });
|
|
6552
7011
|
if (existsSync12(pluginsDir)) {
|
|
6553
7012
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
6554
7013
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
@@ -6987,16 +7446,19 @@ function formatConnectionList(connections) {
|
|
|
6987
7446
|
return [formatSection("Rig servers", `${rows.length} available`), `${pc5.bold(pad("ALIAS", aliasWidth))} ${pc5.bold("KIND")} ${pc5.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
|
|
6988
7447
|
`);
|
|
6989
7448
|
}
|
|
6990
|
-
function formatConnectionStatus(selected, connections) {
|
|
7449
|
+
function formatConnectionStatus(selected, connections, repo, remoteProjectLink) {
|
|
6991
7450
|
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
6992
7451
|
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
7452
|
+
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";
|
|
6993
7453
|
return [
|
|
6994
7454
|
formatSection("Rig server", "selected for this repo"),
|
|
6995
7455
|
`${themeFaint("\u2502")} ${themeDim("selected ")} ${pc5.bold(selected)}`,
|
|
6996
7456
|
`${themeFaint("\u2502")} ${themeDim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
6997
7457
|
`${themeFaint("\u2502")} ${themeDim("target ")} ${target ?? "not configured"}`,
|
|
7458
|
+
...repo?.project ? [`${themeFaint("\u2502")} ${themeDim("project ")} ${repo.project}`] : [],
|
|
7459
|
+
...connection?.kind === "remote" ? [`${themeFaint("\u2502")} ${themeDim("root ")} ${rootLabel}`] : [],
|
|
6998
7460
|
"",
|
|
6999
|
-
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
7461
|
+
...formatNextSteps(remoteProjectLink && !remoteProjectLink.ok ? ["Repair remote link: `rig server repair-link`", "Authenticate first if needed: `rig github auth import-gh`"] : ["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
7000
7462
|
].join(`
|
|
7001
7463
|
`);
|
|
7002
7464
|
}
|
|
@@ -7225,7 +7687,7 @@ var init_inbox = __esm(() => {
|
|
|
7225
7687
|
|
|
7226
7688
|
// packages/cli/src/commands/_snapshot-upload.ts
|
|
7227
7689
|
import { mkdir, readdir, readFile, writeFile } from "fs/promises";
|
|
7228
|
-
import { dirname as
|
|
7690
|
+
import { dirname as dirname4, resolve as resolve17, relative, sep } from "path";
|
|
7229
7691
|
function toPosixPath(path) {
|
|
7230
7692
|
return path.split(sep).join("/");
|
|
7231
7693
|
}
|
|
@@ -7326,7 +7788,7 @@ __export(exports_init, {
|
|
|
7326
7788
|
DEMO_TASKS_RELATIVE_DIR: () => DEMO_TASKS_RELATIVE_DIR,
|
|
7327
7789
|
DEMO_TASKS: () => DEMO_TASKS
|
|
7328
7790
|
});
|
|
7329
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync13, mkdirSync as
|
|
7791
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
7330
7792
|
import { spawnSync } from "child_process";
|
|
7331
7793
|
import { basename as basename3, resolve as resolve18 } from "path";
|
|
7332
7794
|
import { buildRigInitConfigSource } from "@rig/core";
|
|
@@ -7350,14 +7812,14 @@ function parseRepoSlug(value) {
|
|
|
7350
7812
|
}
|
|
7351
7813
|
function ensureRigPrivateDirs(projectRoot) {
|
|
7352
7814
|
const rigDir = resolve18(projectRoot, ".rig");
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7815
|
+
mkdirSync10(resolve18(rigDir, "state"), { recursive: true });
|
|
7816
|
+
mkdirSync10(resolve18(rigDir, "logs"), { recursive: true });
|
|
7817
|
+
mkdirSync10(resolve18(rigDir, "runs"), { recursive: true });
|
|
7818
|
+
mkdirSync10(resolve18(rigDir, "tmp"), { recursive: true });
|
|
7819
|
+
mkdirSync10(resolve18(projectRoot, "artifacts"), { recursive: true });
|
|
7358
7820
|
const taskConfigPath = resolve18(rigDir, "task-config.json");
|
|
7359
7821
|
if (!existsSync13(taskConfigPath))
|
|
7360
|
-
|
|
7822
|
+
writeFileSync7(taskConfigPath, `{}
|
|
7361
7823
|
`, "utf-8");
|
|
7362
7824
|
}
|
|
7363
7825
|
function ensureGitignoreEntries(projectRoot) {
|
|
@@ -7385,7 +7847,7 @@ function ensureRigConfigPackageDependencies(projectRoot) {
|
|
|
7385
7847
|
...existsSync13(path) ? existing : { name: "rig-project", private: true },
|
|
7386
7848
|
devDependencies
|
|
7387
7849
|
};
|
|
7388
|
-
|
|
7850
|
+
writeFileSync7(path, `${JSON.stringify(next, null, 2)}
|
|
7389
7851
|
`, "utf8");
|
|
7390
7852
|
}
|
|
7391
7853
|
function applyGitHubProjectConfig(source, options) {
|
|
@@ -7411,9 +7873,9 @@ function checkoutForInit(projectRoot, serverKind, strategy) {
|
|
|
7411
7873
|
const selected = strategy ?? { kind: "managed-clone" };
|
|
7412
7874
|
switch (selected.kind) {
|
|
7413
7875
|
case "managed-clone":
|
|
7414
|
-
return { kind: "managed-clone"
|
|
7876
|
+
return { kind: "managed-clone" };
|
|
7415
7877
|
case "current-ref":
|
|
7416
|
-
return { kind: "current-ref",
|
|
7878
|
+
return { kind: "current-ref", ...selected.ref ? { ref: selected.ref } : {} };
|
|
7417
7879
|
case "uploaded-snapshot":
|
|
7418
7880
|
return { kind: "uploaded-snapshot", path: projectRoot, source: "local-working-tree" };
|
|
7419
7881
|
case "existing-path":
|
|
@@ -7666,7 +8128,7 @@ function remoteGitHubAuthMetadata(payload) {
|
|
|
7666
8128
|
};
|
|
7667
8129
|
}
|
|
7668
8130
|
function writeRemoteGitHubAuthState(projectRoot, input) {
|
|
7669
|
-
|
|
8131
|
+
writeFileSync7(resolve18(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
|
|
7670
8132
|
authenticated: true,
|
|
7671
8133
|
source: input.source,
|
|
7672
8134
|
storedOnServer: true,
|
|
@@ -7714,7 +8176,7 @@ function runLocalFilesInit(context, options) {
|
|
|
7714
8176
|
console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
|
|
7715
8177
|
} else {
|
|
7716
8178
|
const projectName = basename3(projectRoot) || "rig-project";
|
|
7717
|
-
|
|
8179
|
+
writeFileSync7(configTsPath, buildRigInitConfigSource({
|
|
7718
8180
|
projectName,
|
|
7719
8181
|
taskSource: { kind: "files", path: "tasks" },
|
|
7720
8182
|
useStandardPlugin: true
|
|
@@ -7723,8 +8185,8 @@ function runLocalFilesInit(context, options) {
|
|
|
7723
8185
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
7724
8186
|
const tasksDir = resolve18(projectRoot, "tasks");
|
|
7725
8187
|
if (!existsSync13(tasksDir)) {
|
|
7726
|
-
|
|
7727
|
-
|
|
8188
|
+
mkdirSync10(tasksDir, { recursive: true });
|
|
8189
|
+
writeFileSync7(resolve18(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)}
|
|
7728
8190
|
`, "utf-8");
|
|
7729
8191
|
}
|
|
7730
8192
|
if (context.outputMode !== "json") {
|
|
@@ -7748,7 +8210,7 @@ function runDemoInit(context, options) {
|
|
|
7748
8210
|
console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it for the demo.");
|
|
7749
8211
|
}
|
|
7750
8212
|
} else {
|
|
7751
|
-
|
|
8213
|
+
writeFileSync7(configTsPath, buildRigInitConfigSource({
|
|
7752
8214
|
projectName: basename3(projectRoot) || "rig-demo",
|
|
7753
8215
|
taskSource: { kind: "files", path: DEMO_TASKS_RELATIVE_DIR },
|
|
7754
8216
|
useStandardPlugin: true
|
|
@@ -7757,14 +8219,14 @@ function runDemoInit(context, options) {
|
|
|
7757
8219
|
}
|
|
7758
8220
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
7759
8221
|
const demoTasksDir = resolve18(projectRoot, DEMO_TASKS_RELATIVE_DIR);
|
|
7760
|
-
|
|
8222
|
+
mkdirSync10(demoTasksDir, { recursive: true });
|
|
7761
8223
|
const taskIds = [];
|
|
7762
8224
|
for (const task of DEMO_TASKS) {
|
|
7763
8225
|
const id = String(task.id);
|
|
7764
8226
|
taskIds.push(id);
|
|
7765
8227
|
const taskPath = resolve18(demoTasksDir, `${id}.json`);
|
|
7766
8228
|
if (!existsSync13(taskPath)) {
|
|
7767
|
-
|
|
8229
|
+
writeFileSync7(taskPath, `${JSON.stringify(task, null, 2)}
|
|
7768
8230
|
`, "utf-8");
|
|
7769
8231
|
}
|
|
7770
8232
|
}
|
|
@@ -7792,21 +8254,32 @@ function runDemoInit(context, options) {
|
|
|
7792
8254
|
}
|
|
7793
8255
|
async function runControlPlaneInit(context, options) {
|
|
7794
8256
|
const projectRoot = context.projectRoot;
|
|
7795
|
-
const
|
|
8257
|
+
const existingRepoConnection = readRepoConnection(projectRoot);
|
|
8258
|
+
const selectedConnection = (() => {
|
|
8259
|
+
try {
|
|
8260
|
+
return resolveSelectedConnection(projectRoot);
|
|
8261
|
+
} catch {
|
|
8262
|
+
return null;
|
|
8263
|
+
}
|
|
8264
|
+
})();
|
|
8265
|
+
const selectedRemote = selectedConnection?.connection.kind === "remote" ? { alias: selectedConnection.alias, connection: selectedConnection.connection } : null;
|
|
8266
|
+
const detectedSlug = options.repoSlug ?? existingRepoConnection?.project ?? detectOriginRepoSlug(projectRoot);
|
|
8267
|
+
const serverKind = options.server ?? (selectedRemote ? "remote" : "local");
|
|
7796
8268
|
if (!detectedSlug) {
|
|
7797
8269
|
const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
|
|
7798
|
-
if (
|
|
8270
|
+
if (serverKind === "local" && authMethod2 === "skip") {
|
|
7799
8271
|
return runLocalFilesInit(context, options);
|
|
7800
8272
|
}
|
|
7801
8273
|
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);
|
|
7802
8274
|
}
|
|
7803
8275
|
const repo = parseRepoSlug(detectedSlug);
|
|
7804
|
-
const
|
|
7805
|
-
const
|
|
8276
|
+
const connectionAlias = options.connectionAlias ?? (serverKind === "local" ? "local" : selectedRemote?.alias ?? "remote");
|
|
8277
|
+
const selectedRemoteUrl = selectedRemote && (!options.connectionAlias || options.connectionAlias === selectedRemote.alias) ? selectedRemote.connection.baseUrl : undefined;
|
|
8278
|
+
const remoteUrl = serverKind === "remote" ? (options.remoteUrl ?? selectedRemoteUrl)?.replace(/\/+$/, "") : undefined;
|
|
7806
8279
|
if (serverKind === "remote") {
|
|
7807
|
-
if (!
|
|
7808
|
-
throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server
|
|
7809
|
-
upsertGlobalConnection(connectionAlias, { kind: "remote", baseUrl:
|
|
8280
|
+
if (!remoteUrl)
|
|
8281
|
+
throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server`, or first select a saved remote with `rig server use <alias>`." });
|
|
8282
|
+
upsertGlobalConnection(connectionAlias, { kind: "remote", baseUrl: remoteUrl });
|
|
7810
8283
|
}
|
|
7811
8284
|
writeRepoConnection(projectRoot, {
|
|
7812
8285
|
selected: connectionAlias,
|
|
@@ -7829,11 +8302,11 @@ async function runControlPlaneInit(context, options) {
|
|
|
7829
8302
|
taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
|
|
7830
8303
|
useStandardPlugin: true
|
|
7831
8304
|
}), options);
|
|
7832
|
-
|
|
8305
|
+
writeFileSync7(configTsPath, source, "utf-8");
|
|
7833
8306
|
}
|
|
7834
8307
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
7835
8308
|
}
|
|
7836
|
-
|
|
8309
|
+
writeFileSync7(resolve18(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
7837
8310
|
`, "utf8");
|
|
7838
8311
|
const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
|
|
7839
8312
|
let uploadedSnapshot = null;
|
|
@@ -7848,7 +8321,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
7848
8321
|
let githubAuth = null;
|
|
7849
8322
|
let deviceAuth = null;
|
|
7850
8323
|
const authMethod = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
|
|
7851
|
-
const remoteGhTokenWarning = serverKind === "remote" && authMethod === "gh" ? `This sends a GitHub token from this machine to ${
|
|
8324
|
+
const remoteGhTokenWarning = serverKind === "remote" && authMethod === "gh" ? `This sends a GitHub token from this machine to ${remoteUrl ?? "the remote Rig server"}.` : null;
|
|
7852
8325
|
if (remoteGhTokenWarning && !options.yes) {
|
|
7853
8326
|
throw new CliError(`${remoteGhTokenWarning} Re-run with --yes to confirm this explicit token transfer.`, 1);
|
|
7854
8327
|
}
|
|
@@ -8228,8 +8701,8 @@ var init_init = __esm(() => {
|
|
|
8228
8701
|
|
|
8229
8702
|
// packages/cli/src/commands/github.ts
|
|
8230
8703
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
8231
|
-
import { mkdirSync as
|
|
8232
|
-
import { dirname as
|
|
8704
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync8 } from "fs";
|
|
8705
|
+
import { dirname as dirname5, resolve as resolve19 } from "path";
|
|
8233
8706
|
function printPayload(context, payload, fallback) {
|
|
8234
8707
|
if (context.outputMode === "json")
|
|
8235
8708
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -8268,8 +8741,8 @@ function persistRemoteAuthSession(context, source, result, fallbackToken) {
|
|
|
8268
8741
|
return;
|
|
8269
8742
|
const repo = readRepoConnection(context.projectRoot);
|
|
8270
8743
|
const path = resolve19(context.projectRoot, ".rig", "state", "github-auth.json");
|
|
8271
|
-
|
|
8272
|
-
|
|
8744
|
+
mkdirSync11(dirname5(path), { recursive: true });
|
|
8745
|
+
writeFileSync8(path, `${JSON.stringify({
|
|
8273
8746
|
authenticated: true,
|
|
8274
8747
|
source,
|
|
8275
8748
|
storedOnServer: true,
|
|
@@ -10393,13 +10866,46 @@ function parseConnection(alias, value, options) {
|
|
|
10393
10866
|
}
|
|
10394
10867
|
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
10395
10868
|
}
|
|
10396
|
-
function printJsonOrText(context,
|
|
10397
|
-
if (context.outputMode
|
|
10398
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
10399
|
-
} else {
|
|
10869
|
+
function printJsonOrText(context, _payload, text2) {
|
|
10870
|
+
if (context.outputMode !== "json") {
|
|
10400
10871
|
console.log(text2);
|
|
10401
10872
|
}
|
|
10402
10873
|
}
|
|
10874
|
+
function formatRemoteProjectLinkText(result) {
|
|
10875
|
+
return formatSuccessCard(result.ok ? "Remote project link ready" : "Remote project link needs repair", [
|
|
10876
|
+
["selected", result.alias ?? "remote"],
|
|
10877
|
+
["target", result.baseUrl ?? "unknown"],
|
|
10878
|
+
["repo", result.repoSlug ?? "owner/repo"],
|
|
10879
|
+
["status", result.status],
|
|
10880
|
+
...result.serverProjectRoot ? [["server root", result.serverProjectRoot]] : [],
|
|
10881
|
+
["next", result.ok ? result.next ?? "rig task list" : result.hint]
|
|
10882
|
+
]);
|
|
10883
|
+
}
|
|
10884
|
+
function parseRepairLinkArgs(rest, usage) {
|
|
10885
|
+
let repoSlug;
|
|
10886
|
+
let mode = "prepare-if-missing";
|
|
10887
|
+
const pending = [...rest];
|
|
10888
|
+
while (pending.length > 0) {
|
|
10889
|
+
const token = pending.shift();
|
|
10890
|
+
if (token === "--repo") {
|
|
10891
|
+
const value = pending.shift()?.trim();
|
|
10892
|
+
if (!value)
|
|
10893
|
+
throw new CliError(`Missing --repo value. Usage: ${usage}`, 1);
|
|
10894
|
+
const normalized = normalizeRepoSlug(value);
|
|
10895
|
+
if (!normalized)
|
|
10896
|
+
throw new CliError(`Invalid --repo value: ${value}`, 1, { hint: "Use the canonical owner/repo slug, e.g. `--repo humanity-org/humanwork`." });
|
|
10897
|
+
repoSlug = normalized;
|
|
10898
|
+
} else if (token === "--backfill-only") {
|
|
10899
|
+
mode = "backfill-only";
|
|
10900
|
+
} else if (token === "--prepare") {
|
|
10901
|
+
mode = "prepare-if-missing";
|
|
10902
|
+
} else {
|
|
10903
|
+
throw new CliError(`Unexpected argument: ${String(token)}
|
|
10904
|
+
Usage: ${usage}`, 1);
|
|
10905
|
+
}
|
|
10906
|
+
}
|
|
10907
|
+
return { repoSlug, mode };
|
|
10908
|
+
}
|
|
10403
10909
|
async function promptForConnectionAlias(context) {
|
|
10404
10910
|
const state = readGlobalConnections();
|
|
10405
10911
|
const repo = readRepoConnection(context.projectRoot);
|
|
@@ -10453,37 +10959,67 @@ async function executeConnectionCommand(context, args, options) {
|
|
|
10453
10959
|
}
|
|
10454
10960
|
if (!alias)
|
|
10455
10961
|
throw new CliError(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
|
|
10962
|
+
let selectedConnection = { kind: "local", mode: "auto" };
|
|
10456
10963
|
if (alias !== "local") {
|
|
10457
10964
|
const state = readGlobalConnections();
|
|
10458
|
-
|
|
10965
|
+
const connection = state.connections[alias];
|
|
10966
|
+
if (!connection)
|
|
10459
10967
|
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>`." });
|
|
10968
|
+
selectedConnection = connection;
|
|
10460
10969
|
}
|
|
10461
10970
|
const previousRepo = readRepoConnection(context.projectRoot);
|
|
10971
|
+
const preserveRemoteRoot = Boolean(previousRepo?.serverProjectRoot && previousRepo.selected === alias && selectedConnection.kind === "remote" && previousRepo.serverProjectRootAlias === alias && previousRepo.serverProjectRootBaseUrl === selectedConnection.baseUrl);
|
|
10462
10972
|
const repoState = {
|
|
10463
10973
|
selected: alias,
|
|
10464
10974
|
...previousRepo?.project ? { project: previousRepo.project } : {},
|
|
10465
10975
|
linkedAt: new Date().toISOString(),
|
|
10466
|
-
...
|
|
10976
|
+
...preserveRemoteRoot ? {
|
|
10977
|
+
serverProjectRoot: previousRepo.serverProjectRoot,
|
|
10978
|
+
serverProjectRootAlias: previousRepo.serverProjectRootAlias,
|
|
10979
|
+
serverProjectRootBaseUrl: previousRepo.serverProjectRootBaseUrl
|
|
10980
|
+
} : {}
|
|
10467
10981
|
};
|
|
10468
10982
|
writeRepoConnection(context.projectRoot, repoState);
|
|
10469
|
-
|
|
10983
|
+
const remoteProjectLink = alias !== "local" ? await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only" }).catch((error) => ({
|
|
10984
|
+
ok: false,
|
|
10985
|
+
status: "error",
|
|
10986
|
+
message: error instanceof Error ? error.message : String(error),
|
|
10987
|
+
hint: "Run `rig server repair-link` after authenticating the selected remote."
|
|
10988
|
+
})) : null;
|
|
10989
|
+
const latestRepo = readRepoConnection(context.projectRoot);
|
|
10990
|
+
const details = { selected: latestRepo?.selected ?? alias, repo: latestRepo, remoteProjectLink };
|
|
10991
|
+
printJsonOrText(context, details, formatSuccessCard("Rig server selected", [
|
|
10470
10992
|
["selected", alias],
|
|
10471
10993
|
["scope", "this repo"],
|
|
10472
|
-
["
|
|
10994
|
+
...remoteProjectLink ? [["remote link", remoteProjectLink.ok ? `ready (${remoteProjectLink.serverProjectRoot ?? "linked"})` : `${remoteProjectLink.status}: ${remoteProjectLink.hint}`]] : [],
|
|
10995
|
+
["next", remoteProjectLink && !remoteProjectLink.ok ? "rig server repair-link" : "rig task list"]
|
|
10473
10996
|
]));
|
|
10474
|
-
return { ok: true, group: options.group, command: "use", details
|
|
10997
|
+
return { ok: true, group: options.group, command: "use", details };
|
|
10998
|
+
}
|
|
10999
|
+
case "repair-link": {
|
|
11000
|
+
const parsed = parseRepairLinkArgs(rest, `${usageName(options)} repair-link [--prepare|--backfill-only] [--repo owner/repo]`);
|
|
11001
|
+
const result = await repairRemoteProjectRootLink(context, parsed);
|
|
11002
|
+
printJsonOrText(context, result, formatRemoteProjectLinkText(result));
|
|
11003
|
+
return { ok: true, group: options.group, command: "repair-link", details: result };
|
|
10475
11004
|
}
|
|
10476
11005
|
case "status": {
|
|
10477
11006
|
requireNoExtraArgs(rest, `${usageName(options)} status`);
|
|
10478
11007
|
const repo = readRepoConnection(context.projectRoot);
|
|
10479
11008
|
const global = readGlobalConnections();
|
|
10480
|
-
const
|
|
10481
|
-
|
|
11009
|
+
const remoteProjectLink = repo?.selected && repo.selected !== "local" ? await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only" }).catch((error) => ({
|
|
11010
|
+
ok: false,
|
|
11011
|
+
status: "error",
|
|
11012
|
+
message: error instanceof Error ? error.message : String(error),
|
|
11013
|
+
hint: "Run `rig server repair-link` after authenticating the selected remote."
|
|
11014
|
+
})) : null;
|
|
11015
|
+
const latestRepo = readRepoConnection(context.projectRoot) ?? repo;
|
|
11016
|
+
const details = { selected: latestRepo?.selected ?? "local", repo: latestRepo, connections: global.connections, remoteProjectLink };
|
|
11017
|
+
printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections, latestRepo ?? null, remoteProjectLink));
|
|
10482
11018
|
return { ok: true, group: options.group, command: "status", details };
|
|
10483
11019
|
}
|
|
10484
11020
|
default:
|
|
10485
11021
|
throw new CliError(`Unknown ${options.group} command: ${String(command)}
|
|
10486
|
-
Usage: ${usageName(options)} <list|add|use|status>`, 1);
|
|
11022
|
+
Usage: ${usageName(options)} <list|add|use|status|repair-link>`, 1);
|
|
10487
11023
|
}
|
|
10488
11024
|
}
|
|
10489
11025
|
var init_connect = __esm(() => {
|
|
@@ -10491,13 +11027,14 @@ var init_connect = __esm(() => {
|
|
|
10491
11027
|
init_runner();
|
|
10492
11028
|
init__connection_state();
|
|
10493
11029
|
init__cli_format();
|
|
11030
|
+
init__server_client();
|
|
10494
11031
|
});
|
|
10495
11032
|
|
|
10496
11033
|
// packages/cli/src/commands/server.ts
|
|
10497
11034
|
import { resolveRigServerCommand } from "@rig/runtime/local-server";
|
|
10498
11035
|
async function executeServer(context, args, options) {
|
|
10499
11036
|
const [command = "status", ...rest] = args;
|
|
10500
|
-
if (["status", "list", "add", "use"].includes(command)) {
|
|
11037
|
+
if (["status", "list", "add", "use", "repair-link"].includes(command)) {
|
|
10501
11038
|
return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
|
|
10502
11039
|
}
|
|
10503
11040
|
switch (command) {
|
|
@@ -11284,7 +11821,7 @@ var init_task = __esm(() => {
|
|
|
11284
11821
|
});
|
|
11285
11822
|
|
|
11286
11823
|
// packages/cli/src/commands/task-run-driver.ts
|
|
11287
|
-
import { copyFileSync as copyFileSync3, existsSync as existsSync16, mkdirSync as
|
|
11824
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync16, mkdirSync as mkdirSync12, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync9 } from "fs";
|
|
11288
11825
|
import { resolve as resolve24 } from "path";
|
|
11289
11826
|
import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
|
|
11290
11827
|
import { createInterface as createLineInterface } from "readline";
|
|
@@ -11387,7 +11924,7 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
|
|
|
11387
11924
|
try {
|
|
11388
11925
|
if (!statSync2(sourcePath).isFile())
|
|
11389
11926
|
continue;
|
|
11390
|
-
|
|
11927
|
+
mkdirSync12(resolve24(targetPath, ".."), { recursive: true });
|
|
11391
11928
|
copyFileSync3(sourcePath, targetPath);
|
|
11392
11929
|
copied += 1;
|
|
11393
11930
|
} catch {}
|
|
@@ -12258,8 +12795,8 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
12258
12795
|
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
12259
12796
|
classifiedAt: new Date().toISOString()
|
|
12260
12797
|
};
|
|
12261
|
-
|
|
12262
|
-
|
|
12798
|
+
mkdirSync12(resolve24(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
|
|
12799
|
+
writeFileSync9(resolve24(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
|
|
12263
12800
|
`, "utf8");
|
|
12264
12801
|
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
12265
12802
|
prompt = `${prompt}
|
|
@@ -12406,8 +12943,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
12406
12943
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
12407
12944
|
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
12408
12945
|
if (readyFile) {
|
|
12409
|
-
|
|
12410
|
-
|
|
12946
|
+
mkdirSync12(resolve24(readyFile, ".."), { recursive: true });
|
|
12947
|
+
writeFileSync9(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
12411
12948
|
`, "utf8");
|
|
12412
12949
|
}
|
|
12413
12950
|
appendRunLog(context.projectRoot, input.runId, {
|
|
@@ -13353,7 +13890,7 @@ var init_test = __esm(() => {
|
|
|
13353
13890
|
});
|
|
13354
13891
|
|
|
13355
13892
|
// packages/cli/src/commands/setup.ts
|
|
13356
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
13893
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, readdirSync as readdirSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
13357
13894
|
import { resolve as resolve25 } from "path";
|
|
13358
13895
|
import { createPluginHost } from "@rig/core";
|
|
13359
13896
|
import {
|
|
@@ -13408,12 +13945,12 @@ function runSetupInit(projectRoot) {
|
|
|
13408
13945
|
const stateDir = resolveControlPlaneHostStateDir(projectRoot);
|
|
13409
13946
|
const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
|
|
13410
13947
|
const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13948
|
+
mkdirSync13(stateDir, { recursive: true });
|
|
13949
|
+
mkdirSync13(logsDir, { recursive: true });
|
|
13950
|
+
mkdirSync13(artifactsDir, { recursive: true });
|
|
13414
13951
|
const failuresPath = resolve25(stateDir, "failed_approaches.md");
|
|
13415
13952
|
if (!existsSync17(failuresPath)) {
|
|
13416
|
-
|
|
13953
|
+
writeFileSync10(failuresPath, `# Failed Approaches
|
|
13417
13954
|
|
|
13418
13955
|
`, "utf-8");
|
|
13419
13956
|
}
|
|
@@ -16291,6 +16828,7 @@ var LOG_PAGE = 100, TIMELINE_PAGE = 200;
|
|
|
16291
16828
|
var init_run_detail = () => {};
|
|
16292
16829
|
|
|
16293
16830
|
// packages/cli/src/app-opentui/adapters/server.ts
|
|
16831
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
16294
16832
|
function withTimeout(promise, ms, label) {
|
|
16295
16833
|
return new Promise((resolve29, reject) => {
|
|
16296
16834
|
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
@@ -16327,11 +16865,128 @@ function startLocalRequested(ctx) {
|
|
|
16327
16865
|
const action = intent.action;
|
|
16328
16866
|
return action?.payload?.startLocal === true;
|
|
16329
16867
|
}
|
|
16868
|
+
async function serverAliases(projectRoot) {
|
|
16869
|
+
const { readGlobalConnections: readGlobalConnections2, readRepoConnection: readRepoConnection2 } = await Promise.resolve().then(() => (init__connection_state(), exports__connection_state));
|
|
16870
|
+
const selected = readRepoConnection2(projectRoot)?.selected ?? "local";
|
|
16871
|
+
const global = readGlobalConnections2();
|
|
16872
|
+
const aliases = [{ alias: "local", kind: "local", selected: selected === "local" }];
|
|
16873
|
+
for (const [alias, connection] of Object.entries(global.connections)) {
|
|
16874
|
+
aliases.push({
|
|
16875
|
+
alias,
|
|
16876
|
+
kind: connection.kind,
|
|
16877
|
+
...connection.kind === "remote" ? { baseUrl: connection.baseUrl } : {},
|
|
16878
|
+
selected: alias === selected
|
|
16879
|
+
});
|
|
16880
|
+
}
|
|
16881
|
+
return aliases;
|
|
16882
|
+
}
|
|
16883
|
+
function firstString2(parts, offset = 0) {
|
|
16884
|
+
return parts.slice(offset).find((part) => part.trim() && !part.startsWith("-"))?.trim();
|
|
16885
|
+
}
|
|
16886
|
+
function normalizeUrl(value) {
|
|
16887
|
+
const trimmed = value?.trim().replace(/\/+$/, "");
|
|
16888
|
+
if (!trimmed)
|
|
16889
|
+
return;
|
|
16890
|
+
return /^https?:\/\//i.test(trimmed) ? trimmed : undefined;
|
|
16891
|
+
}
|
|
16892
|
+
async function useLocalServerFromApp(ctx) {
|
|
16893
|
+
const label = "Selecting local server";
|
|
16894
|
+
emitStarted(ctx, label);
|
|
16895
|
+
try {
|
|
16896
|
+
const projectRoot = projectRootOf(ctx);
|
|
16897
|
+
const { readRepoConnection: readRepoConnection2, writeRepoConnection: writeRepoConnection2 } = await Promise.resolve().then(() => (init__connection_state(), exports__connection_state));
|
|
16898
|
+
const previous = readRepoConnection2(projectRoot);
|
|
16899
|
+
writeRepoConnection2(projectRoot, {
|
|
16900
|
+
selected: "local",
|
|
16901
|
+
...previous?.project ? { project: previous.project } : {},
|
|
16902
|
+
linkedAt: new Date().toISOString()
|
|
16903
|
+
});
|
|
16904
|
+
emitCompleted(ctx, label, { selected: "local" });
|
|
16905
|
+
return refreshServerStatus(ctx);
|
|
16906
|
+
} catch (error) {
|
|
16907
|
+
emitFailed(ctx, label, error);
|
|
16908
|
+
throw error;
|
|
16909
|
+
}
|
|
16910
|
+
}
|
|
16911
|
+
async function useRemoteServerFromApp(ctx, alias) {
|
|
16912
|
+
const label = alias ? `Selecting remote ${alias}` : "Selecting remote server";
|
|
16913
|
+
emitStarted(ctx, label);
|
|
16914
|
+
try {
|
|
16915
|
+
const cleanAlias = alias?.trim();
|
|
16916
|
+
if (!cleanAlias)
|
|
16917
|
+
throw new Error("Enter a saved remote alias, or add one with: add remote \u2192 <alias> <https-url>.");
|
|
16918
|
+
const projectRoot = projectRootOf(ctx);
|
|
16919
|
+
const { readGlobalConnections: readGlobalConnections2, readRepoConnection: readRepoConnection2, writeRepoConnection: writeRepoConnection2 } = await Promise.resolve().then(() => (init__connection_state(), exports__connection_state));
|
|
16920
|
+
const connection = readGlobalConnections2().connections[cleanAlias];
|
|
16921
|
+
if (!connection)
|
|
16922
|
+
throw new Error(`Remote alias ${cleanAlias} is not saved yet. Use add remote first.`);
|
|
16923
|
+
if (connection.kind !== "remote")
|
|
16924
|
+
throw new Error(`${cleanAlias} is not a remote server alias.`);
|
|
16925
|
+
const previous = readRepoConnection2(projectRoot);
|
|
16926
|
+
writeRepoConnection2(projectRoot, {
|
|
16927
|
+
selected: cleanAlias,
|
|
16928
|
+
...previous?.project ? { project: previous.project } : {},
|
|
16929
|
+
linkedAt: new Date().toISOString()
|
|
16930
|
+
});
|
|
16931
|
+
emitCompleted(ctx, label, { selected: cleanAlias, baseUrl: connection.baseUrl });
|
|
16932
|
+
return refreshServerStatus(ctx);
|
|
16933
|
+
} catch (error) {
|
|
16934
|
+
emitFailed(ctx, label, error);
|
|
16935
|
+
throw error;
|
|
16936
|
+
}
|
|
16937
|
+
}
|
|
16938
|
+
async function addRemoteServerFromApp(ctx, args) {
|
|
16939
|
+
const label = "Adding remote server";
|
|
16940
|
+
emitStarted(ctx, label);
|
|
16941
|
+
try {
|
|
16942
|
+
const alias = firstString2(args, 2);
|
|
16943
|
+
const url = normalizeUrl(firstString2(args, alias ? args.indexOf(alias) + 1 : 3));
|
|
16944
|
+
if (!alias || !url)
|
|
16945
|
+
throw new Error("Add remote expects: <alias> <https-url>. Example: prod https://rig.example.com");
|
|
16946
|
+
const projectRoot = projectRootOf(ctx);
|
|
16947
|
+
const { readRepoConnection: readRepoConnection2, upsertGlobalConnection: upsertGlobalConnection2, writeRepoConnection: writeRepoConnection2 } = await Promise.resolve().then(() => (init__connection_state(), exports__connection_state));
|
|
16948
|
+
upsertGlobalConnection2(alias, { kind: "remote", baseUrl: url });
|
|
16949
|
+
const previous = readRepoConnection2(projectRoot);
|
|
16950
|
+
writeRepoConnection2(projectRoot, {
|
|
16951
|
+
selected: alias,
|
|
16952
|
+
...previous?.project ? { project: previous.project } : {},
|
|
16953
|
+
linkedAt: new Date().toISOString()
|
|
16954
|
+
});
|
|
16955
|
+
emitCompleted(ctx, label, { alias, baseUrl: url });
|
|
16956
|
+
return refreshServerStatus(ctx);
|
|
16957
|
+
} catch (error) {
|
|
16958
|
+
emitFailed(ctx, label, error);
|
|
16959
|
+
throw error;
|
|
16960
|
+
}
|
|
16961
|
+
}
|
|
16962
|
+
async function importGitHubAuthFromGhApp(ctx) {
|
|
16963
|
+
const label = "Importing GitHub auth";
|
|
16964
|
+
emitStarted(ctx, label);
|
|
16965
|
+
try {
|
|
16966
|
+
const projectRoot = projectRootOf(ctx);
|
|
16967
|
+
const token = spawnSync5("gh", ["auth", "token"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 }).stdout.trim();
|
|
16968
|
+
if (!token)
|
|
16969
|
+
throw new Error("Could not read GitHub token from gh. Sign in with gh auth login, then retry import auth.");
|
|
16970
|
+
const runtime = await runtimeOf(ctx);
|
|
16971
|
+
const { postGitHubTokenViaServer: postGitHubTokenViaServer2, setGitHubBearerTokenForCurrentProcess: setGitHubBearerTokenForCurrentProcess2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
16972
|
+
const { readRepoConnection: readRepoConnection2 } = await Promise.resolve().then(() => (init__connection_state(), exports__connection_state));
|
|
16973
|
+
const selectedRepo = readRepoConnection2(projectRoot)?.project;
|
|
16974
|
+
const payload = await postGitHubTokenViaServer2(runtime, token, selectedRepo ? { selectedRepo } : {});
|
|
16975
|
+
const apiSessionToken = payload && typeof payload === "object" && !Array.isArray(payload) ? payload.apiSessionToken : undefined;
|
|
16976
|
+
setGitHubBearerTokenForCurrentProcess2(typeof apiSessionToken === "string" ? apiSessionToken : token, projectRoot);
|
|
16977
|
+
emitCompleted(ctx, label, { selectedRepo: selectedRepo ?? null });
|
|
16978
|
+
return refreshServerStatus(ctx);
|
|
16979
|
+
} catch (error) {
|
|
16980
|
+
emitFailed(ctx, label, error);
|
|
16981
|
+
throw error;
|
|
16982
|
+
}
|
|
16983
|
+
}
|
|
16330
16984
|
async function startLocalServerFromApp(ctx) {
|
|
16331
16985
|
const label = "Starting local server";
|
|
16332
16986
|
emitStarted(ctx, label);
|
|
16333
16987
|
patchData(ctx, {
|
|
16334
16988
|
lastIntent: undefined,
|
|
16989
|
+
remoteProjectLink: undefined,
|
|
16335
16990
|
server: { label: "starting local server", reachable: false, error: "spawning local rig-server (detached)\u2026" }
|
|
16336
16991
|
});
|
|
16337
16992
|
try {
|
|
@@ -16356,32 +17011,61 @@ async function startLocalServerFromApp(ctx) {
|
|
|
16356
17011
|
reachable: false,
|
|
16357
17012
|
error: error instanceof Error ? error.message : String(error)
|
|
16358
17013
|
};
|
|
16359
|
-
patchData(ctx, { server: state, lastRefreshError: state.error });
|
|
17014
|
+
patchData(ctx, { server: state, remoteProjectLink: undefined, lastRefreshError: state.error });
|
|
16360
17015
|
patchFooter(ctx, { server: "unavailable" });
|
|
16361
|
-
emitCompleted(ctx, label, {
|
|
17016
|
+
emitCompleted(ctx, label, { serverLabel: state.label, reachable: false, error: state.error });
|
|
16362
17017
|
return state;
|
|
16363
17018
|
}
|
|
16364
17019
|
}
|
|
17020
|
+
async function repairRemoteProjectRootLinkFromApp(ctx) {
|
|
17021
|
+
const label = "Repairing remote project link";
|
|
17022
|
+
emitStarted(ctx, label);
|
|
17023
|
+
try {
|
|
17024
|
+
const projectRoot = projectRootOf(ctx);
|
|
17025
|
+
const { ensureRemoteProjectRootLink: ensureRemoteProjectRootLink2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
17026
|
+
emitProgress(ctx, label, "backfilling or preparing server-host checkout");
|
|
17027
|
+
const result = await ensureRemoteProjectRootLink2(projectRoot, { mode: "prepare-if-missing" });
|
|
17028
|
+
patchData(ctx, { remoteProjectLink: result, server: { label: result.alias ?? "remote", baseUrl: result.baseUrl, kind: "remote", reachable: result.status !== "not_remote", remoteProjectLink: result } });
|
|
17029
|
+
patchFooter(ctx, { server: result.alias ?? "remote", message: `remote link ${result.status}` });
|
|
17030
|
+
if (!result.ok) {
|
|
17031
|
+
const error = new Error(result.message);
|
|
17032
|
+
error.hint = result.hint;
|
|
17033
|
+
patchData(ctx, { lastRefreshError: result.message });
|
|
17034
|
+
throw error;
|
|
17035
|
+
}
|
|
17036
|
+
emitCompleted(ctx, label, { repoSlug: result.repoSlug, serverProjectRoot: result.serverProjectRoot, status: result.status });
|
|
17037
|
+
return result;
|
|
17038
|
+
} catch (error) {
|
|
17039
|
+
const message2 = error instanceof Error ? error.message : String(error);
|
|
17040
|
+
const existing = ctx.getState().data?.remoteProjectLink;
|
|
17041
|
+
const remoteProjectLink = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : { ok: false, status: "error", message: message2 };
|
|
17042
|
+
patchData(ctx, { lastRefreshError: message2, remoteProjectLink });
|
|
17043
|
+
emitCompleted(ctx, label, { ok: false, error: message2, remoteProjectLink });
|
|
17044
|
+
throw error;
|
|
17045
|
+
}
|
|
17046
|
+
}
|
|
16365
17047
|
async function refreshServerStatus(ctx) {
|
|
16366
17048
|
if (startLocalRequested(ctx)) {
|
|
16367
17049
|
return startLocalServerFromApp(ctx);
|
|
16368
17050
|
}
|
|
16369
17051
|
const label = "Checking server";
|
|
16370
17052
|
emitStarted(ctx, label);
|
|
16371
|
-
patchData(ctx, { server: { label: "checking selected server", reachable: false, error: "checking selected server\u2026" } });
|
|
17053
|
+
patchData(ctx, { server: { label: "checking selected server", reachable: false, error: "checking selected server\u2026" }, remoteProjectLink: undefined });
|
|
16372
17054
|
const started = Date.now();
|
|
16373
17055
|
try {
|
|
16374
|
-
const { ensureServerForCli: ensureServerForCli2, requestServerJson: requestServerJson2, resolveServerConnectionLabel: resolveServerConnectionLabel2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
17056
|
+
const { ensureRemoteProjectRootLink: ensureRemoteProjectRootLink2, ensureServerForCli: ensureServerForCli2, requestServerJson: requestServerJson2, resolveServerConnectionLabel: resolveServerConnectionLabel2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
16375
17057
|
const projectRoot = projectRootOf(ctx);
|
|
17058
|
+
const aliases = await serverAliases(projectRoot);
|
|
16376
17059
|
emitProgress(ctx, label, "resolving selected server");
|
|
16377
17060
|
const [connectionLabel, server] = await Promise.all([
|
|
16378
17061
|
resolveServerConnectionLabel2(projectRoot),
|
|
16379
17062
|
withTimeout(ensureServerForCli2(projectRoot), 5000, "server connection")
|
|
16380
17063
|
]);
|
|
16381
17064
|
emitProgress(ctx, label, "requesting server status", { baseUrl: server.baseUrl, kind: server.connectionKind });
|
|
16382
|
-
const [status, auth] = await Promise.all([
|
|
17065
|
+
const [status, auth, remoteProjectLink] = await Promise.all([
|
|
16383
17066
|
withRetry("server status", () => withTimeout(requestServerJson2({ projectRoot }, "/api/server/status"), SERVER_PROBE_TIMEOUT_MS, "server status")).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) })),
|
|
16384
|
-
withRetry("github auth status", () => withTimeout(requestServerJson2({ projectRoot }, "/api/github/auth/status"), SERVER_PROBE_TIMEOUT_MS, "github auth status")).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) }))
|
|
17067
|
+
withRetry("github auth status", () => withTimeout(requestServerJson2({ projectRoot }, "/api/github/auth/status"), SERVER_PROBE_TIMEOUT_MS, "github auth status")).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) })),
|
|
17068
|
+
server.connectionKind === "remote" ? withTimeout(ensureRemoteProjectRootLink2(projectRoot, { mode: "backfill-only", authToken: server.authToken }), SERVER_PROBE_TIMEOUT_MS, "remote project link").catch((error) => ({ ok: false, status: "error", message: error instanceof Error ? error.message : String(error) })) : Promise.resolve(null)
|
|
16385
17069
|
]);
|
|
16386
17070
|
const state = {
|
|
16387
17071
|
label: connectionLabel,
|
|
@@ -16390,22 +17074,25 @@ async function refreshServerStatus(ctx) {
|
|
|
16390
17074
|
reachable: true,
|
|
16391
17075
|
latencyMs: Date.now() - started,
|
|
16392
17076
|
status: status && typeof status === "object" && !Array.isArray(status) ? status : {},
|
|
16393
|
-
auth: auth && typeof auth === "object" && !Array.isArray(auth) ? auth : {}
|
|
17077
|
+
auth: auth && typeof auth === "object" && !Array.isArray(auth) ? auth : {},
|
|
17078
|
+
aliases,
|
|
17079
|
+
...remoteProjectLink && typeof remoteProjectLink === "object" && !Array.isArray(remoteProjectLink) ? { remoteProjectLink } : {}
|
|
16394
17080
|
};
|
|
16395
|
-
patchData(ctx, { server: state });
|
|
17081
|
+
patchData(ctx, { server: state, remoteProjectLink: state.remoteProjectLink });
|
|
16396
17082
|
patchFooter(ctx, { server: connectionLabel, latency: `${state.latencyMs}ms` });
|
|
16397
|
-
emitCompleted(ctx, label, {
|
|
17083
|
+
emitCompleted(ctx, label, { serverLabel: connectionLabel, latencyMs: state.latencyMs });
|
|
16398
17084
|
return state;
|
|
16399
17085
|
} catch (error) {
|
|
16400
17086
|
const state = {
|
|
16401
17087
|
label: "server unavailable",
|
|
16402
17088
|
reachable: false,
|
|
16403
17089
|
latencyMs: Date.now() - started,
|
|
17090
|
+
aliases: await serverAliases(projectRootOf(ctx)).catch(() => []),
|
|
16404
17091
|
error: error instanceof Error ? error.message : String(error)
|
|
16405
17092
|
};
|
|
16406
|
-
patchData(ctx, { server: state });
|
|
17093
|
+
patchData(ctx, { server: state, remoteProjectLink: undefined });
|
|
16407
17094
|
patchFooter(ctx, { server: "unavailable" });
|
|
16408
|
-
emitCompleted(ctx, label, {
|
|
17095
|
+
emitCompleted(ctx, label, { serverLabel: state.label, reachable: false, error: state.error });
|
|
16409
17096
|
return state;
|
|
16410
17097
|
}
|
|
16411
17098
|
}
|
|
@@ -17433,11 +18120,56 @@ var init_doctor3 = __esm(() => {
|
|
|
17433
18120
|
DOCTOR_ACTIONS = [
|
|
17434
18121
|
{ detail: "run diagnostics now", item: { id: "run", label: "run", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "run diagnostics" } },
|
|
17435
18122
|
{ detail: "open server controls", item: { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "open server controls" } },
|
|
17436
|
-
{ detail: "repair project/server/auth link", item: { id: "repair", label: "repair", intent: { scene: "
|
|
18123
|
+
{ detail: "repair project/server/auth link", item: { id: "repair", label: "repair", intent: { scene: "init", argv: ["init", "--repair", "--yes"], action: { kind: "init-start", label: "Repair project link" } }, message: "repair project link natively" } },
|
|
17437
18124
|
{ detail: "open tasks", item: { id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Open tasks" } }, message: "open tasks" } }
|
|
17438
18125
|
];
|
|
17439
18126
|
});
|
|
17440
18127
|
|
|
18128
|
+
// packages/cli/src/app-opentui/remote-link.ts
|
|
18129
|
+
function remoteProjectLinkError(message2) {
|
|
18130
|
+
return /no server-host project root link|remote project(?:-root)? link|x-rig-project-root|serverProjectRoot/i.test(message2 ?? "");
|
|
18131
|
+
}
|
|
18132
|
+
function serverRecordForRemoteLink(state) {
|
|
18133
|
+
const server = state.data.server;
|
|
18134
|
+
return server && typeof server === "object" && !Array.isArray(server) ? server : null;
|
|
18135
|
+
}
|
|
18136
|
+
function remoteProjectLinkState(state) {
|
|
18137
|
+
const serverRecord = serverRecordForRemoteLink(state);
|
|
18138
|
+
if (!serverRecord || serverRecord.kind !== "remote")
|
|
18139
|
+
return null;
|
|
18140
|
+
const link = serverRecord.remoteProjectLink;
|
|
18141
|
+
if (link && typeof link === "object" && !Array.isArray(link))
|
|
18142
|
+
return link;
|
|
18143
|
+
const direct = state.data.remoteProjectLink;
|
|
18144
|
+
if (direct && typeof direct === "object" && !Array.isArray(direct))
|
|
18145
|
+
return direct;
|
|
18146
|
+
return null;
|
|
18147
|
+
}
|
|
18148
|
+
function shouldOfferRemoteLinkRepair(state, message2) {
|
|
18149
|
+
const link = remoteProjectLinkState(state);
|
|
18150
|
+
if (link) {
|
|
18151
|
+
if (link.ok === true)
|
|
18152
|
+
return false;
|
|
18153
|
+
const status = link.status ?? "";
|
|
18154
|
+
return REPAIRABLE_REMOTE_LINK_STATUSES.has(status);
|
|
18155
|
+
}
|
|
18156
|
+
const serverRecord = serverRecordForRemoteLink(state);
|
|
18157
|
+
if (serverRecord && serverRecord.kind !== "remote")
|
|
18158
|
+
return false;
|
|
18159
|
+
return remoteProjectLinkError(message2 ?? state.error?.message);
|
|
18160
|
+
}
|
|
18161
|
+
var REPAIRABLE_REMOTE_LINK_STATUSES;
|
|
18162
|
+
var init_remote_link = __esm(() => {
|
|
18163
|
+
REPAIRABLE_REMOTE_LINK_STATUSES = new Set([
|
|
18164
|
+
"auth_required",
|
|
18165
|
+
"project_not_registered",
|
|
18166
|
+
"no_server_checkout",
|
|
18167
|
+
"invalid_root",
|
|
18168
|
+
"needs_prepare",
|
|
18169
|
+
"error"
|
|
18170
|
+
]);
|
|
18171
|
+
});
|
|
18172
|
+
|
|
17441
18173
|
// packages/cli/src/app-opentui/fleet-stats.ts
|
|
17442
18174
|
function normalizeStatus(status) {
|
|
17443
18175
|
return status.replace(/_/g, "-").toLowerCase();
|
|
@@ -19353,13 +20085,18 @@ function overviewBody(state, family, snap, layout) {
|
|
|
19353
20085
|
function familyRecoveryRows(state, family, errorMessage2) {
|
|
19354
20086
|
const selected = Math.max(0, state.selection.index);
|
|
19355
20087
|
const intro = errorMessage2 ? line(`\u2717 couldn't load ${family || "this family"} \u2014 ${errorMessage2}`, { fg: RIG_UI.red, bold: true }) : line(`No data for ${family || "this family"} yet.`, { fg: RIG_UI.ink2 });
|
|
19356
|
-
|
|
20088
|
+
const repairRemote = shouldOfferRemoteLinkRepair(state, errorMessage2);
|
|
20089
|
+
const rows = [
|
|
19357
20090
|
intro,
|
|
19358
|
-
blank()
|
|
19359
|
-
selectableDeckRow({ label: "retry", detail: `reload ${family || "the family"}`, index: 0, active: selected === 0 }, { id: "family-retry", label: "retry", intent: { scene: "family", argv: [family], action: { kind: "refresh", label: `Reload ${family}`, payload: { family } } }, message: "reload this family" }),
|
|
19360
|
-
selectableDeckRow({ label: "cockpit", detail: "back to the project cockpit", index: 1, active: selected === 1 }, { id: "family-home", label: "cockpit", intent: { scene: "main", argv: [], action: { kind: "refresh", label: "Home" } }, message: "back to the cockpit" }),
|
|
19361
|
-
selectableDeckRow({ label: "doctor", detail: "diagnose project/setup", index: 2, active: selected === 2 }, { id: "family-doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose setup" })
|
|
20091
|
+
blank()
|
|
19362
20092
|
];
|
|
20093
|
+
let index = 0;
|
|
20094
|
+
if (repairRemote) {
|
|
20095
|
+
rows.push(selectableDeckRow({ label: "repair link", detail: "backfill/prepare selected remote checkout link", index, active: selected === index }, { id: "family-repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "family", family } } }, message: "repair remote project link" }));
|
|
20096
|
+
index += 1;
|
|
20097
|
+
}
|
|
20098
|
+
rows.push(selectableDeckRow({ label: "retry", detail: `reload ${family || "the family"}`, index, active: selected === index }, { id: "family-retry", label: "retry", intent: { scene: "family", argv: [family], action: { kind: "refresh", label: `Reload ${family}`, payload: { family } } }, message: "reload this family" }), selectableDeckRow({ label: "cockpit", detail: "back to the project cockpit", index: index + 1, active: selected === index + 1 }, { id: "family-home", label: "cockpit", intent: { scene: "main", argv: [], action: { kind: "refresh", label: "Home" } }, message: "back to the cockpit" }), selectableDeckRow({ label: "doctor", detail: "diagnose project/setup", index: index + 2, active: selected === index + 2 }, { id: "family-doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose setup" }));
|
|
20099
|
+
return rows;
|
|
19363
20100
|
}
|
|
19364
20101
|
function renderFamilyScene(state, layout) {
|
|
19365
20102
|
const family = typeof state.data.familyName === "string" ? state.data.familyName : "";
|
|
@@ -19368,9 +20105,16 @@ function renderFamilyScene(state, layout) {
|
|
|
19368
20105
|
const loading = state.status === "loading" && !snap;
|
|
19369
20106
|
const errorMessage2 = state.error?.message ?? lastRefreshError(state) ?? undefined;
|
|
19370
20107
|
const probeFailed = snap ? snap.state.ran === false && Boolean(state.error) : Boolean(state.error);
|
|
20108
|
+
const selected = Math.max(0, state.selection.index);
|
|
19371
20109
|
const body = [
|
|
19372
20110
|
...loading ? loadingRows(family || "family", state.tick) : snap ? [
|
|
19373
|
-
...probeFailed && errorMessage2 ? [
|
|
20111
|
+
...probeFailed && errorMessage2 ? [
|
|
20112
|
+
...errorBanner(errorMessage2),
|
|
20113
|
+
...shouldOfferRemoteLinkRepair(state, errorMessage2) ? [
|
|
20114
|
+
selectableDeckRow({ label: "repair link", detail: "backfill/prepare selected remote checkout link", index: 0, active: selected === 0 }, { id: "family-repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "family", family } } }, message: "repair remote project link" })
|
|
20115
|
+
] : [],
|
|
20116
|
+
blank()
|
|
20117
|
+
] : [],
|
|
19374
20118
|
...current.subId ? formView(state, family, snap, current).lines : overviewBody(state, family, snap, layout)
|
|
19375
20119
|
] : familyRecoveryRows(state, family, errorMessage2)
|
|
19376
20120
|
];
|
|
@@ -19404,6 +20148,7 @@ function renderFamilyScene(state, layout) {
|
|
|
19404
20148
|
var init_family2 = __esm(() => {
|
|
19405
20149
|
init_scene();
|
|
19406
20150
|
init_selectable();
|
|
20151
|
+
init_remote_link();
|
|
19407
20152
|
init_theme2();
|
|
19408
20153
|
init_family_domains();
|
|
19409
20154
|
init_kit();
|
|
@@ -19674,27 +20419,38 @@ function runRow(width, run, active, optimistic) {
|
|
|
19674
20419
|
const item = runSelectableItem(run);
|
|
19675
20420
|
return item ? withSelectable(row, item) : row;
|
|
19676
20421
|
}
|
|
19677
|
-
function
|
|
20422
|
+
function fleetRecoveryItems(state) {
|
|
20423
|
+
if (!shouldOfferRemoteLinkRepair(state))
|
|
20424
|
+
return BASE_FLEET_RECOVERY_ITEMS;
|
|
20425
|
+
return [BASE_FLEET_RECOVERY_ITEMS[0], FLEET_REPAIR_LINK_ITEM, ...BASE_FLEET_RECOVERY_ITEMS.slice(1)];
|
|
20426
|
+
}
|
|
20427
|
+
function fleetRecoveryDecks(state) {
|
|
20428
|
+
if (!shouldOfferRemoteLinkRepair(state))
|
|
20429
|
+
return BASE_RECOVERY_DECKS;
|
|
20430
|
+
return [BASE_RECOVERY_DECKS[0], { label: "repair link", detail: "backfill/prepare remote project-root link" }, ...BASE_RECOVERY_DECKS.slice(1)];
|
|
20431
|
+
}
|
|
20432
|
+
function recoveryRows(state, selected, reason) {
|
|
20433
|
+
const items = fleetRecoveryItems(state);
|
|
19678
20434
|
return [
|
|
19679
20435
|
...reason ? [line(reason, { fg: RIG_UI.yellow }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
19680
20436
|
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
19681
|
-
...
|
|
20437
|
+
...fleetRecoveryDecks(state).map((deck, index) => selectableDeckRow({ ...deck, index, active: selected === index }, items[index]))
|
|
19682
20438
|
];
|
|
19683
20439
|
}
|
|
19684
|
-
function emptyRows(query, total, selected) {
|
|
20440
|
+
function emptyRows(state, query, total, selected) {
|
|
19685
20441
|
if (!query.trim() && total === 0)
|
|
19686
|
-
return recoveryRows(selected, "No runs yet.");
|
|
20442
|
+
return recoveryRows(state, selected, "No runs yet.");
|
|
19687
20443
|
if (query.trim() && total > 0) {
|
|
19688
20444
|
return [
|
|
19689
|
-
...recoveryRows(selected, `No matching runs for ${JSON.stringify(query)} (${total} total).`)
|
|
20445
|
+
...recoveryRows(state, selected, `No matching runs for ${JSON.stringify(query)} (${total} total).`)
|
|
19690
20446
|
];
|
|
19691
20447
|
}
|
|
19692
|
-
return recoveryRows(selected, "No runs are visible with this filter.");
|
|
20448
|
+
return recoveryRows(state, selected, "No runs are visible with this filter.");
|
|
19693
20449
|
}
|
|
19694
20450
|
function degradedRows(state, selected) {
|
|
19695
20451
|
if (!state.error)
|
|
19696
20452
|
return [];
|
|
19697
|
-
return recoveryRows(selected, state.error.message);
|
|
20453
|
+
return recoveryRows(state, selected, state.error.message);
|
|
19698
20454
|
}
|
|
19699
20455
|
function renderFleetScene(state, layout) {
|
|
19700
20456
|
const width = panelWidth4(layout);
|
|
@@ -19704,7 +20460,7 @@ function renderFleetScene(state, layout) {
|
|
|
19704
20460
|
const runs = sortRuns(filterRunsForSearch(allRuns, query), spec);
|
|
19705
20461
|
const selectedRun = typeof state.data.selectedRunId === "string" && runs.some((run) => run.runId === state.data.selectedRunId) ? state.data.selectedRunId : runs[0]?.runId;
|
|
19706
20462
|
const selectedIndex = Math.max(0, runs.findIndex((run) => run.runId === selectedRun));
|
|
19707
|
-
const recoveryIndex = Math.max(0, Math.min(
|
|
20463
|
+
const recoveryIndex = Math.max(0, Math.min(fleetRecoveryItems(state).length - 1, state.selection.index));
|
|
19708
20464
|
const optimistic = optimisticStatuses(state);
|
|
19709
20465
|
const updatedAgo = updatedAgoLabel(state);
|
|
19710
20466
|
const panelTop = 0;
|
|
@@ -19736,7 +20492,7 @@ function renderFleetScene(state, layout) {
|
|
|
19736
20492
|
...runs.map((run, index) => runRow(contentWidth, run, index === selectedIndex, optimistic.get(run.runId)))
|
|
19737
20493
|
] : state.error ? degradedRows(state, recoveryIndex) : loading ? loadingRows("runs", state.tick) : [
|
|
19738
20494
|
...query.trim() ? [line(searchSummary("runs", query, runs.length, allRuns.length), { fg: RIG_UI.ink4 }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
19739
|
-
...emptyRows(query, allRuns.length, recoveryIndex)
|
|
20495
|
+
...emptyRows(state, query, allRuns.length, recoveryIndex)
|
|
19740
20496
|
]
|
|
19741
20497
|
];
|
|
19742
20498
|
return makeSceneFrame({
|
|
@@ -19771,18 +20527,19 @@ function renderFleetScene(state, layout) {
|
|
|
19771
20527
|
live: true
|
|
19772
20528
|
});
|
|
19773
20529
|
}
|
|
19774
|
-
var
|
|
20530
|
+
var BASE_FLEET_RECOVERY_ITEMS, FLEET_REPAIR_LINK_ITEM, COL2, GUTTER3 = " ", RUN_COLUMNS, BASE_RECOVERY_DECKS;
|
|
19775
20531
|
var init_fleet2 = __esm(() => {
|
|
19776
20532
|
init_scene();
|
|
19777
20533
|
init_selectable();
|
|
19778
20534
|
init_fleet_stats();
|
|
20535
|
+
init_remote_link();
|
|
19779
20536
|
init_theme2();
|
|
19780
|
-
|
|
20537
|
+
BASE_FLEET_RECOVERY_ITEMS = [
|
|
19781
20538
|
{ id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Open tasks" } }, message: "open tasks and dispatch work" },
|
|
19782
|
-
{ id: "repair", label: "repair", intent: { scene: "command", argv: ["init", "--repair"], action: { kind: "command-run", label: "Repair project link" } }, message: "repair project/server/auth link" },
|
|
19783
20539
|
{ id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "server controls" },
|
|
19784
20540
|
{ id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose project" }
|
|
19785
20541
|
];
|
|
20542
|
+
FLEET_REPAIR_LINK_ITEM = { id: "repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "fleet" } } }, message: "backfill or prepare remote project link" };
|
|
19786
20543
|
COL2 = {
|
|
19787
20544
|
glyph: 1,
|
|
19788
20545
|
runId: 8,
|
|
@@ -19796,9 +20553,8 @@ var init_fleet2 = __esm(() => {
|
|
|
19796
20553
|
{ key: "title", label: "task/title", hint: "by task title" },
|
|
19797
20554
|
{ key: "age", label: "age", hint: "by recency" }
|
|
19798
20555
|
];
|
|
19799
|
-
|
|
20556
|
+
BASE_RECOVERY_DECKS = [
|
|
19800
20557
|
{ label: "tasks", detail: "open tasks and dispatch work" },
|
|
19801
|
-
{ label: "repair", detail: "repair project/server/auth link" },
|
|
19802
20558
|
{ label: "server", detail: "open server controls" },
|
|
19803
20559
|
{ label: "doctor", detail: "diagnose project" }
|
|
19804
20560
|
];
|
|
@@ -20378,11 +21134,11 @@ function renderInitScene(state, layout) {
|
|
|
20378
21134
|
const allDone = completed === SETUP_STEPS.length;
|
|
20379
21135
|
const nextStep = SETUP_STEPS.find((step) => !step.done(signals));
|
|
20380
21136
|
const selected = Math.max(0, state.selection.index);
|
|
20381
|
-
const primary = nextStep ? selectableDeckRow({ label: "next", detail: `${nextStep.cta} \u2014 recommended`, active: selected === 0 }, { ...nextStep.item, id: "init-primary" }) : selectableDeckRow({ label: "verify", detail: "
|
|
21137
|
+
const primary = nextStep ? selectableDeckRow({ label: "next", detail: `${nextStep.cta} \u2014 recommended`, active: selected === 0 }, { ...nextStep.item, id: "init-primary" }) : selectableDeckRow({ label: "verify", detail: "Init complete \u2014 run doctor to confirm", active: selected === 0 }, { id: "init-primary", label: "verify", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "verify setup end-to-end" });
|
|
20382
21138
|
const secondaryRows = SECONDARY_ACTIONS.map(({ label, detail, item }, index) => selectableDeckRow({ label, detail, active: selected === index + 1 }, item));
|
|
20383
21139
|
const progress = allDone ? "all set" : `${completed} of ${SETUP_STEPS.length} complete`;
|
|
20384
21140
|
const panelLines = [
|
|
20385
|
-
line(allDone ? "
|
|
21141
|
+
line(allDone ? "INIT \xB7 ready to go" : "INIT \xB7 let's get you running", { fg: allDone ? RIG_UI.limeDim : RIG_UI.ink, bold: true }),
|
|
20386
21142
|
line(`progress ${progress}`, { fg: allDone ? RIG_UI.limeDim : RIG_UI.ink2 }),
|
|
20387
21143
|
blank(),
|
|
20388
21144
|
line("CHECKLIST", { fg: RIG_UI.ink3, bold: true }),
|
|
@@ -20394,11 +21150,11 @@ function renderInitScene(state, layout) {
|
|
|
20394
21150
|
line("OTHER PATHS", { fg: RIG_UI.ink3, bold: true }),
|
|
20395
21151
|
...secondaryRows,
|
|
20396
21152
|
blank(),
|
|
20397
|
-
line("enter/click runs the highlighted action \xB7 esc goes back \xB7 tab switches sections", { fg: RIG_UI.ink4 })
|
|
21153
|
+
line("enter/click runs the highlighted native action \xB7 esc goes back \xB7 tab switches sections", { fg: RIG_UI.ink4 })
|
|
20398
21154
|
];
|
|
20399
21155
|
return makeSceneFrame({
|
|
20400
21156
|
scene: "init",
|
|
20401
|
-
title: "
|
|
21157
|
+
title: "Init",
|
|
20402
21158
|
lines: [],
|
|
20403
21159
|
panels: [{
|
|
20404
21160
|
id: "init-setup",
|
|
@@ -20411,11 +21167,11 @@ function renderInitScene(state, layout) {
|
|
|
20411
21167
|
opacity: 0.98,
|
|
20412
21168
|
border: false,
|
|
20413
21169
|
chrome: "ad-terminal",
|
|
20414
|
-
headerText: "rig
|
|
21170
|
+
headerText: "rig init \xB7 guided onboarding",
|
|
20415
21171
|
paddingX: 5,
|
|
20416
21172
|
paddingY: 2
|
|
20417
21173
|
}],
|
|
20418
|
-
footer: { message: allDone ? "
|
|
21174
|
+
footer: { message: allDone ? "init complete" : "init in progress" },
|
|
20419
21175
|
live: !allDone || state.status === "action"
|
|
20420
21176
|
});
|
|
20421
21177
|
}
|
|
@@ -20424,19 +21180,19 @@ var init_init3 = __esm(() => {
|
|
|
20424
21180
|
init_scene();
|
|
20425
21181
|
init_selectable();
|
|
20426
21182
|
init_theme2();
|
|
20427
|
-
STEP_CONFIG_RUN = { id: "step-config", label: "run
|
|
21183
|
+
STEP_CONFIG_RUN = { id: "step-config", label: "run init", intent: { scene: "init", argv: ["init", "--yes"], action: { kind: "init-start", label: "Run init" } }, message: "initialize without embedded CLI prompts" };
|
|
20428
21184
|
STEP_SERVER = { id: "step-server", label: "select server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Choose server" } }, message: "select local or remote server" };
|
|
20429
|
-
STEP_AUTH = { id: "step-auth", label: "connect GitHub", intent: { scene: "
|
|
20430
|
-
STEP_TASKS = { id: "step-tasks", label: "
|
|
21185
|
+
STEP_AUTH = { id: "step-auth", label: "connect GitHub", intent: { scene: "server", argv: ["github", "auth", "status"], action: { kind: "refresh", label: "Open GitHub auth" } }, message: "open native server/auth controls" };
|
|
21186
|
+
STEP_TASKS = { id: "step-tasks", label: "repair task source", intent: { scene: "init", argv: ["init", "--repair", "--yes"], action: { kind: "init-start", label: "Repair task source" } }, message: "repair generated task-source config without embedded CLI prompts" };
|
|
20431
21187
|
SETUP_STEPS = [
|
|
20432
|
-
{ id: "config", label: "Project config", detail: "rig.config + private state", done: (s) => s.configured, cta: "Run
|
|
21188
|
+
{ id: "config", label: "Project config", detail: "rig.config + private state", done: (s) => s.configured, cta: "Run init", item: STEP_CONFIG_RUN },
|
|
20433
21189
|
{ id: "server", label: "Server target", detail: "local or remote, reachable", done: (s) => s.serverReachable, cta: "Choose a server", item: STEP_SERVER },
|
|
20434
21190
|
{ id: "auth", label: "GitHub auth", detail: "signed in on the selected server", done: (s) => s.authSignedIn, cta: "Connect GitHub", item: STEP_AUTH },
|
|
20435
21191
|
{ id: "tasks", label: "Task source", detail: "where work comes from", done: (s) => s.taskSourceReady, cta: "Pick a task source", item: STEP_TASKS }
|
|
20436
21192
|
];
|
|
20437
21193
|
SECONDARY_ACTIONS = [
|
|
20438
|
-
{ label: "repair", detail: "reconfigure generated config and private state", item: { id: "repair", label: "repair", intent: { scene: "
|
|
20439
|
-
{ label: "demo", detail: "seed an offline demo task source to explore", item: { id: "demo", label: "demo", intent: { scene: "
|
|
21194
|
+
{ label: "repair", detail: "reconfigure generated config and private state", item: { id: "repair", label: "repair", intent: { scene: "init", argv: ["init", "--repair", "--yes"], action: { kind: "init-start", label: "Reconfigure project" } }, message: "verify or rewrite generated config natively" } },
|
|
21195
|
+
{ label: "demo", detail: "seed an offline demo task source to explore", item: { id: "demo", label: "demo", intent: { scene: "init", argv: ["init", "--demo", "--repair", "--yes"], action: { kind: "init-start", label: "Seed demo project" } }, message: "offline demo project without embedded CLI prompts" } },
|
|
20440
21196
|
{ label: "doctor", detail: "diagnose what is still missing", item: { id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "verify setup" } }
|
|
20441
21197
|
];
|
|
20442
21198
|
});
|
|
@@ -21735,6 +22491,30 @@ var init_run_detail2 = __esm(() => {
|
|
|
21735
22491
|
});
|
|
21736
22492
|
|
|
21737
22493
|
// packages/cli/src/app-opentui/scenes/server.ts
|
|
22494
|
+
function remoteAliasActions(server) {
|
|
22495
|
+
const aliases = (server?.aliases ?? []).filter((alias) => alias.kind === "remote");
|
|
22496
|
+
return aliases.map((alias) => ({
|
|
22497
|
+
detail: `${alias.selected ? "selected" : "select"} ${alias.baseUrl ?? "remote endpoint"}`,
|
|
22498
|
+
item: {
|
|
22499
|
+
id: `remote-alias:${alias.alias}`,
|
|
22500
|
+
label: alias.selected ? `\u2713 ${alias.alias}` : `use ${alias.alias}`,
|
|
22501
|
+
intent: { scene: "server", argv: ["server", "use", alias.alias], action: { kind: "server-use-remote", label: `Use ${alias.alias}`, payload: { alias: alias.alias } } },
|
|
22502
|
+
message: `select ${alias.alias}`
|
|
22503
|
+
}
|
|
22504
|
+
}));
|
|
22505
|
+
}
|
|
22506
|
+
function serverActions(state) {
|
|
22507
|
+
const server = serverState(state);
|
|
22508
|
+
const remoteRows = remoteAliasActions(server);
|
|
22509
|
+
let actions = remoteRows.length > 0 ? [...SERVER_ACTIONS.slice(0, 3), ...remoteRows, ...SERVER_ACTIONS.slice(3)] : [...SERVER_ACTIONS];
|
|
22510
|
+
if (!shouldOfferRemoteLinkRepair(state))
|
|
22511
|
+
return actions;
|
|
22512
|
+
const repair = { detail: "backfill or prepare the selected remote checkout/root link", item: { id: "repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link" } }, message: "prepare remote checkout link" } };
|
|
22513
|
+
const doctorIndex = actions.findIndex((entry) => entry.item.id === "doctor");
|
|
22514
|
+
if (doctorIndex < 0)
|
|
22515
|
+
return [...actions, repair];
|
|
22516
|
+
return [...actions.slice(0, doctorIndex), repair, ...actions.slice(doctorIndex)];
|
|
22517
|
+
}
|
|
21738
22518
|
function cleanVisible(value, fallback = "unknown") {
|
|
21739
22519
|
return value?.trim() || fallback;
|
|
21740
22520
|
}
|
|
@@ -21759,31 +22539,37 @@ function selectedIndex(state, count) {
|
|
|
21759
22539
|
function statusRows2(server) {
|
|
21760
22540
|
const auth = server?.auth;
|
|
21761
22541
|
const signedIn = auth && (auth.signedIn === true || auth.authenticated === true || auth.status === "authenticated") ? "authenticated" : "auth unknown";
|
|
22542
|
+
const link = server?.remoteProjectLink;
|
|
22543
|
+
const linkText = link ? link.ok ? `ready \xB7 ${link.serverProjectRoot ?? "linked"}` : `${link.status ?? "needs repair"} \xB7 ${link.hint ?? link.message ?? "run repair link"}` : server?.kind === "remote" ? "not checked" : "not required";
|
|
22544
|
+
const selectedLinkSummary = link?.ok ? " \xB7 root link ready" : server?.kind === "remote" && link ? ` \xB7 root link ${link.status ?? "needs repair"}` : "";
|
|
21762
22545
|
return [
|
|
21763
|
-
line(`selected ${cleanVisible(server?.label, "not checked")}`, { fg: RIG_UI.ink2 }),
|
|
22546
|
+
line(`selected ${cleanVisible(server?.label, "not checked")}${selectedLinkSummary}`, { fg: RIG_UI.ink2 }),
|
|
21764
22547
|
line(`target ${targetLabel(server)}`, { fg: RIG_UI.ink3 }),
|
|
21765
22548
|
line(`mode ${server?.kind ?? "local or remote"}`, { fg: RIG_UI.ink3 }),
|
|
21766
22549
|
line(`health ${server ? server.reachable ? "reachable" : "unreachable" : "check pending"}`, { fg: server?.reachable ? RIG_UI.limeDim : server ? RIG_UI.red : RIG_UI.yellow }),
|
|
21767
22550
|
line(`github ${signedIn}`, { fg: signedIn === "authenticated" ? RIG_UI.limeDim : RIG_UI.ink4 }),
|
|
22551
|
+
line(`root link ${linkText}`, { fg: link?.ok ? RIG_UI.limeDim : server?.kind === "remote" ? RIG_UI.yellow : RIG_UI.ink4 }),
|
|
22552
|
+
...server?.aliases && server.aliases.length > 0 ? [line(`aliases ${server.aliases.map((alias) => `${alias.selected ? "*" : ""}${alias.alias}${alias.kind === "remote" && alias.baseUrl ? `=${alias.baseUrl}` : ""}`).join(", ")}`, { fg: RIG_UI.ink4 })] : [],
|
|
21768
22553
|
...server?.error ? [line(`attention ${server.error}`, { fg: RIG_UI.yellow })] : []
|
|
21769
22554
|
];
|
|
21770
22555
|
}
|
|
21771
22556
|
function renderServerScene(state, layout) {
|
|
21772
22557
|
const server = serverState(state);
|
|
21773
|
-
const
|
|
22558
|
+
const actions = serverActions(state);
|
|
22559
|
+
const selected = selectedIndex(state, actions.length);
|
|
21774
22560
|
const loading = state.status === "loading" && !server;
|
|
21775
22561
|
const errorText = state.error?.message ?? lastRefreshError(state);
|
|
21776
22562
|
const panelLines = [
|
|
21777
22563
|
...errorText ? errorBanner(errorText, "select refresh or doctor below to retry") : [],
|
|
21778
22564
|
line("server controls", { fg: RIG_UI.ink3 }),
|
|
21779
22565
|
blank(),
|
|
21780
|
-
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
21781
|
-
...SERVER_ACTIONS.map(({ detail, item }, index) => selectableDeckRow({ label: item.label, detail, index, active: selected === index }, item)),
|
|
21782
|
-
blank(),
|
|
21783
22566
|
line("STATUS", { fg: RIG_UI.ink3, bold: true }),
|
|
21784
22567
|
...loading ? loadingRows("server status", state.tick) : statusRows2(server),
|
|
21785
22568
|
blank(),
|
|
21786
|
-
line("
|
|
22569
|
+
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
22570
|
+
...actions.map(({ detail, item }, index) => selectableDeckRow({ label: item.label, detail, index, active: selected === index }, item)),
|
|
22571
|
+
blank(),
|
|
22572
|
+
line("enter/click runs native actions \xB7 add/use remote prompts stay in OpenTUI", { fg: RIG_UI.ink4 })
|
|
21787
22573
|
];
|
|
21788
22574
|
return makeSceneFrame({
|
|
21789
22575
|
scene: "server",
|
|
@@ -21813,14 +22599,15 @@ var init_server3 = __esm(() => {
|
|
|
21813
22599
|
init_scene();
|
|
21814
22600
|
init_selectable();
|
|
21815
22601
|
init_theme2();
|
|
22602
|
+
init_remote_link();
|
|
21816
22603
|
SERVER_ACTIONS = [
|
|
21817
22604
|
{ detail: "probe selected server, project root, and GitHub auth", item: { id: "refresh", label: "refresh", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Refresh server" } }, message: "refresh selected server" } },
|
|
21818
|
-
{ detail: "select local server for this repo", item: { id: "local", label: "use local", intent: { scene: "
|
|
21819
|
-
{ detail: "
|
|
21820
|
-
{ detail: "show saved local/remote aliases", item: { id: "list", label: "list servers", intent: { scene: "
|
|
21821
|
-
{ detail: "
|
|
22605
|
+
{ detail: "select local server for this repo", item: { id: "local", label: "use local", intent: { scene: "server", argv: ["server", "use", "local"], action: { kind: "server-use-local", label: "Use local server" } }, message: "switch this repo to local" } },
|
|
22606
|
+
{ detail: "type a saved remote alias to select", item: { id: "remote", label: "use remote", prompt: { label: "Use remote alias", scene: "server", argv: ["server", "use"], intentKind: "server-use-remote", payloadBase: {}, payloadKey: "alias" }, message: "choose a saved remote alias" } },
|
|
22607
|
+
{ detail: "show saved local/remote aliases in the status panel", item: { id: "list", label: "list servers", intent: { scene: "server", argv: ["server", "list"], action: { kind: "refresh", label: "List servers" } }, message: "list saved server aliases" } },
|
|
22608
|
+
{ detail: "add and select a remote: enter <alias> <https-url>", item: { id: "add", label: "add remote", prompt: { label: "Add remote", scene: "server", argv: ["server", "add"], intentKind: "server-add-remote", payloadBase: {}, payloadKey: "remote", appendValueToArgv: true }, message: "add a remote server alias" } },
|
|
21822
22609
|
{ detail: "spawn the local rig-server detached and return here", item: { id: "start", label: "start local", intent: { scene: "server", argv: ["server", "start"], action: { kind: "refresh", payload: { startLocal: true }, label: "Start local server" } }, message: "start local server detached" } },
|
|
21823
|
-
{ detail: "import gh token into the selected server namespace", item: { id: "auth", label: "import auth", intent: { scene: "
|
|
22610
|
+
{ detail: "import gh token into the selected server namespace", item: { id: "auth", label: "import auth", intent: { scene: "server", argv: ["github", "auth", "import-gh"], action: { kind: "github-auth-import", label: "Import GitHub auth" } }, message: "import gh auth to selected server" } },
|
|
21824
22611
|
{ detail: "diagnose server/auth/project linkage", item: { id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "verify server/auth" } },
|
|
21825
22612
|
{ detail: "verify selected server can list task source", item: { id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["task", "list"], action: { kind: "refresh", label: "Open tasks" } }, message: "verify task source" } },
|
|
21826
22613
|
{ detail: "verify selected server can list recent runs", item: { id: "runs", label: "runs", intent: { scene: "fleet", argv: ["run", "status"], action: { kind: "refresh", label: "Open runs" } }, message: "open recent runs" } }
|
|
@@ -21972,27 +22759,38 @@ function taskRow(width, task, active, optimistic) {
|
|
|
21972
22759
|
const item = taskSelectableItem(task);
|
|
21973
22760
|
return item ? withSelectable(row, item) : row;
|
|
21974
22761
|
}
|
|
21975
|
-
function
|
|
22762
|
+
function taskRecoveryItems(state) {
|
|
22763
|
+
if (!shouldOfferRemoteLinkRepair(state))
|
|
22764
|
+
return BASE_TASK_RECOVERY_ITEMS;
|
|
22765
|
+
return [BASE_TASK_RECOVERY_ITEMS[0], BASE_TASK_RECOVERY_ITEMS[1], TASK_REPAIR_LINK_ITEM, ...BASE_TASK_RECOVERY_ITEMS.slice(2)];
|
|
22766
|
+
}
|
|
22767
|
+
function taskRecoveryDecks(state) {
|
|
22768
|
+
if (!shouldOfferRemoteLinkRepair(state))
|
|
22769
|
+
return BASE_RECOVERY_DECKS2;
|
|
22770
|
+
return [BASE_RECOVERY_DECKS2[0], BASE_RECOVERY_DECKS2[1], { label: "repair link", detail: "backfill/prepare remote project-root link" }, ...BASE_RECOVERY_DECKS2.slice(2)];
|
|
22771
|
+
}
|
|
22772
|
+
function recoveryRows2(state, selected, reason) {
|
|
22773
|
+
const items = taskRecoveryItems(state);
|
|
21976
22774
|
return [
|
|
21977
22775
|
...reason ? [line(reason, { fg: RIG_UI.yellow }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
21978
22776
|
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
21979
|
-
...
|
|
22777
|
+
...taskRecoveryDecks(state).map((deck, index) => selectableDeckRow({ ...deck, index, active: selected === index }, items[index]))
|
|
21980
22778
|
];
|
|
21981
22779
|
}
|
|
21982
|
-
function emptyRows2(query, total, selected) {
|
|
22780
|
+
function emptyRows2(state, query, total, selected) {
|
|
21983
22781
|
if (!query.trim() && total === 0)
|
|
21984
|
-
return recoveryRows2(selected, "No tasks loaded.");
|
|
22782
|
+
return recoveryRows2(state, selected, "No tasks loaded.");
|
|
21985
22783
|
if (query.trim() && total > 0) {
|
|
21986
22784
|
return [
|
|
21987
|
-
...recoveryRows2(selected, `No matching tasks for ${JSON.stringify(query)} (${total} total).`)
|
|
22785
|
+
...recoveryRows2(state, selected, `No matching tasks for ${JSON.stringify(query)} (${total} total).`)
|
|
21988
22786
|
];
|
|
21989
22787
|
}
|
|
21990
|
-
return recoveryRows2(selected, "No tasks are visible with this filter.");
|
|
22788
|
+
return recoveryRows2(state, selected, "No tasks are visible with this filter.");
|
|
21991
22789
|
}
|
|
21992
22790
|
function degradedRows2(state, selected) {
|
|
21993
22791
|
if (!state.error)
|
|
21994
22792
|
return [];
|
|
21995
|
-
return recoveryRows2(selected, state.error.message);
|
|
22793
|
+
return recoveryRows2(state, selected, state.error.message);
|
|
21996
22794
|
}
|
|
21997
22795
|
function rawString(raw, key) {
|
|
21998
22796
|
const value = raw?.[key];
|
|
@@ -22016,7 +22814,10 @@ function renderTaskDetail(state, taskId3, layout) {
|
|
|
22016
22814
|
const activeRunId = task?.activeRun?.runId?.trim();
|
|
22017
22815
|
const width = panelWidth13(layout);
|
|
22018
22816
|
const selected = Math.max(0, state.selection.index);
|
|
22817
|
+
const errorText = state.error?.message ?? lastRefreshError(state);
|
|
22818
|
+
const offerRepairLink = shouldOfferRemoteLinkRepair(state, errorText);
|
|
22019
22819
|
const headerLines = [
|
|
22820
|
+
...errorText ? errorBanner(errorText, offerRepairLink ? "select repair link below to prepare the remote checkout" : "retry dispatch after resolving the issue") : [],
|
|
22020
22821
|
line(`${glyph2} ${title}`, { fg: color, bold: true }),
|
|
22021
22822
|
line(`task ${taskId3} \xB7 ${status}`, { fg: RIG_UI.ink3 }),
|
|
22022
22823
|
...task && task.labels.length > 0 ? [line(`labels: ${task.labels.join(", ")}`, { fg: RIG_UI.ink4 })] : [],
|
|
@@ -22028,8 +22829,16 @@ function renderTaskDetail(state, taskId3, layout) {
|
|
|
22028
22829
|
const actionRows2 = [];
|
|
22029
22830
|
actionRows2.push(selectableDeckRow({ label: "back", detail: "return to the task list", index, active: selected === index }, { id: "task-detail-back", label: "back", data: { taskDetailId: undefined }, message: "back to task list" }));
|
|
22030
22831
|
index += 1;
|
|
22031
|
-
|
|
22032
|
-
|
|
22832
|
+
if (offerRepairLink) {
|
|
22833
|
+
actionRows2.push(selectableDeckRow({ label: "repair link", detail: "prepare/backfill the selected remote project-root link", index, active: selected === index }, { id: `task-detail-repair-link:${taskId3}`, label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "tasks", taskDetailId: taskId3 } } }, message: "prepare remote checkout link" }));
|
|
22834
|
+
index += 1;
|
|
22835
|
+
}
|
|
22836
|
+
if (offerRepairLink) {
|
|
22837
|
+
actionRows2.push(line(" dispatch blocked until the remote project link is repaired", { fg: RIG_UI.ink4 }));
|
|
22838
|
+
} else {
|
|
22839
|
+
actionRows2.push(selectableDeckRow({ label: "dispatch", detail: "submit a Pi run for this task", index, active: selected === index }, { id: `task-detail-run:${taskId3}`, label: `dispatch ${taskId3}`, intent: { scene: "tasks", argv: ["run", taskId3], action: { kind: "task-run-id", payload: { task: taskId3 }, label: `Dispatching ${taskId3}` } }, message: `dispatch task ${taskId3}` }));
|
|
22840
|
+
index += 1;
|
|
22841
|
+
}
|
|
22033
22842
|
if (activeRunId) {
|
|
22034
22843
|
actionRows2.push(selectableDeckRow({ label: "attach", detail: `attach the Pi console to run ${activeRunId.slice(0, 8)}`, index, active: selected === index }, { id: `task-detail-attach:${taskId3}`, label: `attach ${activeRunId.slice(0, 8)}`, intent: { scene: "handoff", argv: ["attach", activeRunId], action: { kind: "run-attach", payload: { runId: activeRunId }, label: `Attach Pi ${activeRunId.slice(0, 8)}` } }, message: `attach Pi to ${activeRunId.slice(0, 8)}` }));
|
|
22035
22844
|
index += 1;
|
|
@@ -22088,7 +22897,7 @@ function renderTasksScene(state, layout) {
|
|
|
22088
22897
|
const tasks = sortTasks2(filterTasksForSearch(allTasks, query), spec);
|
|
22089
22898
|
const selected = typeof state.data.selectedTaskId === "string" && tasks.some((task) => task.id === state.data.selectedTaskId) ? state.data.selectedTaskId : tasks[0]?.id;
|
|
22090
22899
|
const selectedIndex2 = Math.max(0, tasks.findIndex((task) => task.id === selected));
|
|
22091
|
-
const recoveryIndex = Math.max(0, Math.min(
|
|
22900
|
+
const recoveryIndex = Math.max(0, Math.min(taskRecoveryItems(state).length - 1, state.selection.index));
|
|
22092
22901
|
const dispatching = dispatchingFor(state);
|
|
22093
22902
|
const dispatchLine = dispatching ? ` \xB7 ${state.data.dispatchingRun?.runId ?? "new"} ${dispatching.status}` : "";
|
|
22094
22903
|
const updatedAgo = updatedAgoLabel2(state);
|
|
@@ -22108,7 +22917,7 @@ function renderTasksScene(state, layout) {
|
|
|
22108
22917
|
...tasks.map((task, index) => taskRow(contentWidth, task, index === selectedIndex2, dispatching && dispatching.taskId === task.id ? dispatching.status : undefined))
|
|
22109
22918
|
] : state.error ? degradedRows2(state, recoveryIndex) : loading ? loadingRows("tasks", state.tick) : [
|
|
22110
22919
|
...query.trim() ? [line(searchSummary("tasks", query, tasks.length, allTasks.length), { fg: RIG_UI.ink4 }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
22111
|
-
...emptyRows2(query, allTasks.length, recoveryIndex)
|
|
22920
|
+
...emptyRows2(state, query, allTasks.length, recoveryIndex)
|
|
22112
22921
|
]
|
|
22113
22922
|
];
|
|
22114
22923
|
return makeSceneFrame({
|
|
@@ -22142,18 +22951,19 @@ function renderTasksScene(state, layout) {
|
|
|
22142
22951
|
live: true
|
|
22143
22952
|
});
|
|
22144
22953
|
}
|
|
22145
|
-
var
|
|
22954
|
+
var BASE_TASK_RECOVERY_ITEMS, TASK_REPAIR_LINK_ITEM, COL3, GUTTER4 = " ", TASK_COLUMNS, BASE_RECOVERY_DECKS2;
|
|
22146
22955
|
var init_tasks2 = __esm(() => {
|
|
22147
22956
|
init_scene();
|
|
22148
22957
|
init_selectable();
|
|
22958
|
+
init_remote_link();
|
|
22149
22959
|
init_theme2();
|
|
22150
|
-
|
|
22960
|
+
BASE_TASK_RECOVERY_ITEMS = [
|
|
22151
22961
|
{ id: "refresh", label: "refresh", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Refresh tasks" } }, message: "refresh task source" },
|
|
22152
|
-
{ id: "next", label: "next", intent: { scene: "
|
|
22153
|
-
{ id: "repair", label: "repair", intent: { scene: "command", argv: ["init", "--repair"], action: { kind: "command-run", label: "Repair task source" } }, message: "repair project/task source" },
|
|
22962
|
+
{ id: "next", label: "next", intent: { scene: "tasks", argv: ["task", "run", "--next"], action: { kind: "task-run-next", label: "Dispatch next task" } }, message: "dispatch next runnable task" },
|
|
22154
22963
|
{ id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "server controls" },
|
|
22155
22964
|
{ id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose task source" }
|
|
22156
22965
|
];
|
|
22966
|
+
TASK_REPAIR_LINK_ITEM = { id: "repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "tasks" } } }, message: "backfill or prepare remote project link" };
|
|
22157
22967
|
COL3 = {
|
|
22158
22968
|
glyph: 1,
|
|
22159
22969
|
id: 11,
|
|
@@ -22168,10 +22978,9 @@ var init_tasks2 = __esm(() => {
|
|
|
22168
22978
|
{ key: "assignee", label: "assignee", hint: "by assignee" },
|
|
22169
22979
|
{ key: "title", label: "title", hint: "by title" }
|
|
22170
22980
|
];
|
|
22171
|
-
|
|
22981
|
+
BASE_RECOVERY_DECKS2 = [
|
|
22172
22982
|
{ label: "refresh", detail: "reload task source" },
|
|
22173
22983
|
{ label: "next", detail: "dispatch next runnable task" },
|
|
22174
|
-
{ label: "repair", detail: "repair project/task source link" },
|
|
22175
22984
|
{ label: "server", detail: "open server controls" },
|
|
22176
22985
|
{ label: "doctor", detail: "diagnose task source" }
|
|
22177
22986
|
];
|
|
@@ -22505,6 +23314,29 @@ function createDomainAdapter() {
|
|
|
22505
23314
|
else
|
|
22506
23315
|
await loadInitFacts(ctx);
|
|
22507
23316
|
return true;
|
|
23317
|
+
case "server-use-local":
|
|
23318
|
+
await useLocalServerFromApp(ctx);
|
|
23319
|
+
return true;
|
|
23320
|
+
case "server-use-remote":
|
|
23321
|
+
await useRemoteServerFromApp(ctx, payloadString8(intent, "alias") ?? intent.argv[2]);
|
|
23322
|
+
return true;
|
|
23323
|
+
case "server-add-remote":
|
|
23324
|
+
await addRemoteServerFromApp(ctx, intent.argv);
|
|
23325
|
+
return true;
|
|
23326
|
+
case "github-auth-import":
|
|
23327
|
+
await importGitHubAuthFromGhApp(ctx);
|
|
23328
|
+
return true;
|
|
23329
|
+
case "remote-link-repair": {
|
|
23330
|
+
await repairRemoteProjectRootLinkFromApp(ctx);
|
|
23331
|
+
const returnScene = payloadString8(intent, "returnScene");
|
|
23332
|
+
if (returnScene && returnScene !== intent.scene) {
|
|
23333
|
+
ctx.emit({ type: "scene.change", scene: returnScene, intent: { scene: returnScene, argv: intent.argv, action: { kind: "refresh", label: `Refresh ${returnScene}`, payload: intent.action.payload } } });
|
|
23334
|
+
await refreshScene(ctx, returnScene, { scene: returnScene, argv: intent.argv, action: { kind: "refresh", label: `Refresh ${returnScene}`, payload: intent.action.payload } });
|
|
23335
|
+
} else {
|
|
23336
|
+
await refreshServerStatus(ctx);
|
|
23337
|
+
}
|
|
23338
|
+
return true;
|
|
23339
|
+
}
|
|
22508
23340
|
case "doctor-run":
|
|
22509
23341
|
await runDoctorChecksForApp(ctx);
|
|
22510
23342
|
return true;
|
|
@@ -22607,7 +23439,9 @@ import {
|
|
|
22607
23439
|
RigInboxInputsOutput,
|
|
22608
23440
|
RigRunListOutput,
|
|
22609
23441
|
RigRunShowOutput,
|
|
23442
|
+
RigServerRepairLinkOutput,
|
|
22610
23443
|
RigServerStatusOutput,
|
|
23444
|
+
RigServerUseOutput,
|
|
22611
23445
|
RigStatsOutput,
|
|
22612
23446
|
RigTaskListOutput,
|
|
22613
23447
|
RigTaskShowOutput
|
|
@@ -22643,7 +23477,9 @@ var init__json_output = __esm(() => {
|
|
|
22643
23477
|
"task show": RigTaskShowOutput,
|
|
22644
23478
|
"run list": RigRunListOutput,
|
|
22645
23479
|
"run show": RigRunShowOutput,
|
|
23480
|
+
"server use": RigServerUseOutput,
|
|
22646
23481
|
"server status": RigServerStatusOutput,
|
|
23482
|
+
"server repair-link": RigServerRepairLinkOutput,
|
|
22647
23483
|
"inbox approvals": RigInboxApprovalsOutput,
|
|
22648
23484
|
"inbox inputs": RigInboxInputsOutput,
|
|
22649
23485
|
"doctor check": RigDoctorCheckOutput,
|
|
@@ -22974,16 +23810,31 @@ function taskViewIntent(argv, command = "", rest = [], raw) {
|
|
|
22974
23810
|
const { payload, label } = taskViewPayload(command, rest);
|
|
22975
23811
|
return intent("tasks", argv, "refresh", payload, label, raw);
|
|
22976
23812
|
}
|
|
22977
|
-
function routeServer(argv, command, raw, checkingLabel) {
|
|
22978
|
-
if (!command || command === "status") {
|
|
23813
|
+
function routeServer(argv, command, rest, raw, checkingLabel) {
|
|
23814
|
+
if (!command || command === "status" || command === "list") {
|
|
22979
23815
|
return intent("server", argv, "refresh", undefined, command ? checkingLabel : "Loading server", raw);
|
|
22980
23816
|
}
|
|
23817
|
+
if (command === "use") {
|
|
23818
|
+
const alias = firstNonOption(rest);
|
|
23819
|
+
if (alias === "local")
|
|
23820
|
+
return intent("server", argv, "server-use-local", undefined, "Use local server", raw);
|
|
23821
|
+
if (alias)
|
|
23822
|
+
return intent("server", argv, "server-use-remote", { alias }, `Use ${alias}`, raw);
|
|
23823
|
+
return intent("server", argv, "refresh", undefined, "Select a remote alias in Server", raw);
|
|
23824
|
+
}
|
|
23825
|
+
if (command === "add")
|
|
23826
|
+
return intent("server", argv, "server-add-remote", { argv: [...argv] }, "Add remote server", raw);
|
|
23827
|
+
if (command === "repair-link")
|
|
23828
|
+
return intent("server", argv, "remote-link-repair", undefined, "Repair remote link", raw);
|
|
22981
23829
|
return commandRunIntent(argv, raw);
|
|
22982
23830
|
}
|
|
22983
23831
|
function routeGithub(argv, command, rest, raw) {
|
|
22984
23832
|
if (command === "auth" && (rest[0]?.toLowerCase() ?? "status") === "status" && rest.length <= 1) {
|
|
22985
23833
|
return intent("server", argv, "refresh", undefined, "Checking GitHub auth", raw);
|
|
22986
23834
|
}
|
|
23835
|
+
if (command === "auth" && rest[0]?.toLowerCase() === "import-gh" && rest.length <= 1) {
|
|
23836
|
+
return intent("server", argv, "github-auth-import", undefined, "Import GitHub auth", raw);
|
|
23837
|
+
}
|
|
22987
23838
|
return commandRunIntent(argv, raw);
|
|
22988
23839
|
}
|
|
22989
23840
|
function routeDoctor(argv, command, raw) {
|
|
@@ -23032,11 +23883,16 @@ function intentFromArgv(argv) {
|
|
|
23032
23883
|
return commandRunIntent(argv);
|
|
23033
23884
|
}
|
|
23034
23885
|
if (normalizedGroup === "server")
|
|
23035
|
-
return routeServer(argv, normalizedCommand, undefined, "Checking server");
|
|
23886
|
+
return routeServer(argv, normalizedCommand, rest, undefined, "Checking server");
|
|
23036
23887
|
if (normalizedGroup === "github")
|
|
23037
23888
|
return routeGithub(argv, normalizedCommand, rest);
|
|
23038
|
-
if (normalizedGroup === "init")
|
|
23039
|
-
|
|
23889
|
+
if (normalizedGroup === "init") {
|
|
23890
|
+
if (!normalizedCommand)
|
|
23891
|
+
return intent("init", argv, "refresh", undefined, "Open init");
|
|
23892
|
+
if (rest.includes("--yes") || normalizedCommand === "--yes")
|
|
23893
|
+
return intent("init", argv, "init-start", undefined, "Run init");
|
|
23894
|
+
return intent("init", argv, "refresh", undefined, "Open init");
|
|
23895
|
+
}
|
|
23040
23896
|
if (normalizedGroup === "doctor")
|
|
23041
23897
|
return routeDoctor(argv, normalizedCommand);
|
|
23042
23898
|
if (normalizedGroup === "inbox")
|
|
@@ -23099,12 +23955,17 @@ function intentFromTypeBar(value) {
|
|
|
23099
23955
|
return commandRunIntent(parts, value);
|
|
23100
23956
|
return intent("tasks", parts, "refresh", undefined, "Select a task, then press Enter; or use run next", value);
|
|
23101
23957
|
}
|
|
23102
|
-
if (first === "init")
|
|
23103
|
-
|
|
23958
|
+
if (first === "init") {
|
|
23959
|
+
if (!second)
|
|
23960
|
+
return intent("init", parts, "refresh", undefined, "Open init", value);
|
|
23961
|
+
if (parts.includes("--yes"))
|
|
23962
|
+
return intent("init", parts, "init-start", undefined, "Run init", value);
|
|
23963
|
+
return intent("init", parts, "refresh", undefined, "Open init", value);
|
|
23964
|
+
}
|
|
23104
23965
|
if (first === "doctor")
|
|
23105
23966
|
return routeDoctor(parts, second, value);
|
|
23106
23967
|
if (first === "server")
|
|
23107
|
-
return routeServer(parts, second, value, "Loading server");
|
|
23968
|
+
return routeServer(parts, second, rest, value, "Loading server");
|
|
23108
23969
|
if (first === "github")
|
|
23109
23970
|
return routeGithub(parts, second, rest, value);
|
|
23110
23971
|
if (first === "inbox")
|
|
@@ -23547,12 +24408,6 @@ var init_autocomplete = __esm(() => {
|
|
|
23547
24408
|
NAV_VERBS = ["runs", "tasks", "inbox", "server", "doctor", "help", "init", "main"];
|
|
23548
24409
|
});
|
|
23549
24410
|
|
|
23550
|
-
// packages/cli/src/app-opentui/pi-pty-host.ts
|
|
23551
|
-
function getActivePiHost() {
|
|
23552
|
-
return null;
|
|
23553
|
-
}
|
|
23554
|
-
function stopActivePiHost(_reason) {}
|
|
23555
|
-
|
|
23556
24411
|
// packages/cli/src/app-opentui/keymap.ts
|
|
23557
24412
|
function clearTypeBar(context, message2) {
|
|
23558
24413
|
const typeBar = context.getTypeBar();
|
|
@@ -23561,22 +24416,15 @@ function clearTypeBar(context, message2) {
|
|
|
23561
24416
|
context.emitTypeBarPatch({ value: "", mode: "nav", prompt: undefined, message: message2 });
|
|
23562
24417
|
}
|
|
23563
24418
|
function handleEmbeddedTerminalKey(context, key) {
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
const
|
|
23567
|
-
const host = state.scene === "handoff" ? piHost : state.scene === "command" ? commandHost : null;
|
|
24419
|
+
if (context.getState().scene !== "command")
|
|
24420
|
+
return false;
|
|
24421
|
+
const host = getActiveCommandHost();
|
|
23568
24422
|
if (!host)
|
|
23569
24423
|
return false;
|
|
23570
24424
|
if (key.ctrl && key.name === "]") {
|
|
23571
|
-
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
context.runAppAction("Opening runs", () => context.runtime.runIntent({ scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } }));
|
|
23575
|
-
} else {
|
|
23576
|
-
stopActiveCommandHost("operator detach");
|
|
23577
|
-
clearTypeBar(context, "closed command");
|
|
23578
|
-
context.runAppAction("Project menu", () => context.runtime.runIntent({ scene: "main", argv: ["main"], action: { kind: "none", label: "Project menu" } }));
|
|
23579
|
-
}
|
|
24425
|
+
stopActiveCommandHost("operator detach");
|
|
24426
|
+
clearTypeBar(context, "closed command");
|
|
24427
|
+
context.runAppAction("Project menu", () => context.runtime.runIntent({ scene: "main", argv: ["main"], action: { kind: "none", label: "Project menu" } }));
|
|
23580
24428
|
return true;
|
|
23581
24429
|
}
|
|
23582
24430
|
const sequence = key.raw || key.sequence;
|
|
@@ -25085,10 +25933,14 @@ var init_preloader = __esm(() => {
|
|
|
25085
25933
|
});
|
|
25086
25934
|
|
|
25087
25935
|
// packages/cli/src/app-opentui/scenes/error.ts
|
|
25936
|
+
function errorActions(state) {
|
|
25937
|
+
return shouldOfferRemoteLinkRepair(state, state.error?.message) ? [...ERROR_ACTIONS, ERROR_REPAIR_LINK_ACTION] : ERROR_ACTIONS;
|
|
25938
|
+
}
|
|
25088
25939
|
function renderErrorScene(state) {
|
|
25089
25940
|
const message2 = state.error?.message ?? "Unknown app error";
|
|
25090
25941
|
const hint = state.error?.hint ?? "Use the actions below to recover.";
|
|
25091
|
-
const
|
|
25942
|
+
const actions = errorActions(state);
|
|
25943
|
+
const selected = Math.max(0, Math.min(actions.length - 1, state.selection.index));
|
|
25092
25944
|
return makeSceneFrame({
|
|
25093
25945
|
scene: "error",
|
|
25094
25946
|
title: "Error",
|
|
@@ -25106,7 +25958,7 @@ function renderErrorScene(state) {
|
|
|
25106
25958
|
...hint ? [line(hint, { fg: RIG_UI.yellow })] : [],
|
|
25107
25959
|
line("", { fg: RIG_UI.ink3 }),
|
|
25108
25960
|
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
25109
|
-
...
|
|
25961
|
+
...actions.map(({ detail, item }, index) => selectableDeckRow({ label: item.label, detail, index, active: selected === index }, item))
|
|
25110
25962
|
],
|
|
25111
25963
|
backgroundColor: RIG_UI.panel,
|
|
25112
25964
|
backgroundAlpha: 184,
|
|
@@ -25123,18 +25975,19 @@ function renderErrorScene(state) {
|
|
|
25123
25975
|
live: true
|
|
25124
25976
|
});
|
|
25125
25977
|
}
|
|
25126
|
-
var ERROR_ACTIONS;
|
|
25978
|
+
var ERROR_ACTIONS, ERROR_REPAIR_LINK_ACTION;
|
|
25127
25979
|
var init_error = __esm(() => {
|
|
25128
25980
|
init_drone();
|
|
25129
25981
|
init_theme2();
|
|
25982
|
+
init_remote_link();
|
|
25130
25983
|
init_scene();
|
|
25131
25984
|
init_selectable();
|
|
25132
25985
|
ERROR_ACTIONS = [
|
|
25133
25986
|
{ detail: "return to dashboard", item: { id: "main", label: "main", intent: { scene: "main", argv: [], action: { kind: "refresh", label: "Back to dashboard" } }, message: "back to dashboard" } },
|
|
25134
25987
|
{ detail: "run diagnostics", item: { id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "run diagnostics" } },
|
|
25135
|
-
{ detail: "open server controls", item: { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "open server controls" } }
|
|
25136
|
-
{ detail: "repair project/server/auth link", item: { id: "repair", label: "repair", intent: { scene: "command", argv: ["init", "--repair"], action: { kind: "command-run", label: "Repair project link" } }, message: "repair project link" } }
|
|
25988
|
+
{ detail: "open server controls", item: { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "open server controls" } }
|
|
25137
25989
|
];
|
|
25990
|
+
ERROR_REPAIR_LINK_ACTION = { detail: "backfill or prepare selected remote project-root link", item: { id: "repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "server" } } }, message: "repair remote project link" } };
|
|
25138
25991
|
});
|
|
25139
25992
|
|
|
25140
25993
|
// packages/cli/src/app-opentui/scenes/help.ts
|
|
@@ -25309,7 +26162,7 @@ function configuredMenuRows(selectedIndex2) {
|
|
|
25309
26162
|
}));
|
|
25310
26163
|
}
|
|
25311
26164
|
function onboardingRows(selectedIndex2) {
|
|
25312
|
-
const primary = selectableDeckRow({ label: "
|
|
26165
|
+
const primary = selectableDeckRow({ label: "init", detail: "Start guided init \u2014 recommended", active: selectedIndex2 === 0 }, ONBOARD_PRIMARY);
|
|
25313
26166
|
const secondary = ONBOARD_SECONDARY.map(([label, detail, item], index) => ({
|
|
25314
26167
|
...deckRow({ label, detail, index: index + 1, active: selectedIndex2 === index + 1, activateOnClick: true }),
|
|
25315
26168
|
selectable: item
|
|
@@ -25369,7 +26222,7 @@ function renderMainScene(state, layout) {
|
|
|
25369
26222
|
statusLine(state)
|
|
25370
26223
|
] : [
|
|
25371
26224
|
line("WELCOME", { fg: RIG_UI.ink, bold: true }),
|
|
25372
|
-
line("This project isn't
|
|
26225
|
+
line("This project isn't initialized yet. One native init flow gets you running.", { fg: RIG_UI.ink2 }),
|
|
25373
26226
|
blank(),
|
|
25374
26227
|
line("GET STARTED", { fg: RIG_UI.ink, bold: true }),
|
|
25375
26228
|
...onboardingRows(actionSelected),
|
|
@@ -25410,7 +26263,7 @@ var init_main = __esm(() => {
|
|
|
25410
26263
|
init_theme2();
|
|
25411
26264
|
init_fleet_stats();
|
|
25412
26265
|
CONFIGURED_MENU = [
|
|
25413
|
-
["init", "setup, reconfigure, repair project state", { id: "init", label: "init", intent: { scene: "
|
|
26266
|
+
["init", "guided setup, reconfigure, repair project state", { id: "init", label: "init", intent: { scene: "init", argv: ["init"], action: { kind: "refresh", label: "Open init" } }, message: "open native init flow" }],
|
|
25414
26267
|
["server", "local/remote target, auth, linkage", { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Checking server" } }, message: "check selected server" }],
|
|
25415
26268
|
["github", "auth, selected repo, stored token", { id: "github", label: "github", intent: { scene: "server", argv: ["github", "auth", "status"], action: { kind: "refresh", label: "Checking GitHub auth" } }, message: "check GitHub auth" }],
|
|
25416
26269
|
["tasks", "browse, filter, dispatch, attach active work", { id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Opening tasks" } }, message: "selected tasks" }],
|
|
@@ -25429,10 +26282,10 @@ var init_main = __esm(() => {
|
|
|
25429
26282
|
["help", "all actions, shortcuts, mouse controls", { id: "help", label: "help", intent: { scene: "help", argv: ["help"], action: { kind: "none", label: "Opening help" } }, message: "selected help" }]
|
|
25430
26283
|
];
|
|
25431
26284
|
ONBOARD_PRIMARY = {
|
|
25432
|
-
id: "onboard-
|
|
25433
|
-
label: "Start guided
|
|
25434
|
-
intent: { scene: "init", argv: ["init"], action: { kind: "refresh", label: "
|
|
25435
|
-
message: "open the
|
|
26285
|
+
id: "onboard-init",
|
|
26286
|
+
label: "Start guided init",
|
|
26287
|
+
intent: { scene: "init", argv: ["init"], action: { kind: "refresh", label: "Init" } },
|
|
26288
|
+
message: "open the native init checklist"
|
|
25436
26289
|
};
|
|
25437
26290
|
ONBOARD_SECONDARY = [
|
|
25438
26291
|
["server", "select a local or remote target", { id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Checking server" } }, message: "check selected server" }],
|
|
@@ -25445,6 +26298,12 @@ var init_main = __esm(() => {
|
|
|
25445
26298
|
TILE_TASKS = { id: "tile-tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Opening tasks" } }, message: "ready tasks \u2014 dispatch work" };
|
|
25446
26299
|
});
|
|
25447
26300
|
|
|
26301
|
+
// packages/cli/src/app-opentui/pi-pty-host.ts
|
|
26302
|
+
function getActivePiHost() {
|
|
26303
|
+
return null;
|
|
26304
|
+
}
|
|
26305
|
+
function stopActivePiHost(_reason) {}
|
|
26306
|
+
|
|
25448
26307
|
// packages/cli/src/app-opentui/runtime.ts
|
|
25449
26308
|
var exports_runtime = {};
|
|
25450
26309
|
__export(exports_runtime, {
|
|
@@ -25511,7 +26370,7 @@ function entryIntentForScene(scene) {
|
|
|
25511
26370
|
case "doctor":
|
|
25512
26371
|
return { scene, argv: ["doctor"], action: { kind: "doctor-run", label: "Doctor" } };
|
|
25513
26372
|
case "init":
|
|
25514
|
-
return { scene, argv: ["init"], action: { kind: "refresh", label: "
|
|
26373
|
+
return { scene, argv: ["init"], action: { kind: "refresh", label: "Init" } };
|
|
25515
26374
|
case "run-detail":
|
|
25516
26375
|
return { scene, argv: ["run", "status"], action: { kind: "refresh", label: "Run" } };
|
|
25517
26376
|
case "pi":
|
|
@@ -25600,7 +26459,7 @@ function sceneSectionLabel(scene) {
|
|
|
25600
26459
|
handoff: "pi console",
|
|
25601
26460
|
server: "server",
|
|
25602
26461
|
doctor: "doctor",
|
|
25603
|
-
init: "
|
|
26462
|
+
init: "init",
|
|
25604
26463
|
pi: "pi",
|
|
25605
26464
|
plugin: "plugins",
|
|
25606
26465
|
repo: "repo",
|
|
@@ -26090,7 +26949,7 @@ async function launchRigOpenTuiApp(options) {
|
|
|
26090
26949
|
}
|
|
26091
26950
|
for (const adapter of options.adapters ?? [])
|
|
26092
26951
|
await adapter.start?.(runtime);
|
|
26093
|
-
|
|
26952
|
+
connectRigServerEvents(options.projectRoot, {
|
|
26094
26953
|
onSnapshotInvalidated: () => refreshCurrentDataScene(),
|
|
26095
26954
|
onRunLogAppended: () => {
|
|
26096
26955
|
const scene = store.getState().scene;
|
|
@@ -26098,11 +26957,17 @@ async function launchRigOpenTuiApp(options) {
|
|
|
26098
26957
|
refreshCurrentDataScene();
|
|
26099
26958
|
},
|
|
26100
26959
|
onStatus: (status) => store.patch({ footer: { live: liveLinkLabel(status) } })
|
|
26101
|
-
}).
|
|
26102
|
-
|
|
26103
|
-
|
|
26104
|
-
|
|
26960
|
+
}).then((subscription) => {
|
|
26961
|
+
if (destroyed) {
|
|
26962
|
+
subscription.close();
|
|
26963
|
+
return;
|
|
26964
|
+
}
|
|
26965
|
+
liveEvents = subscription;
|
|
26105
26966
|
resources.add(() => liveEvents?.close());
|
|
26967
|
+
}).catch(() => {
|
|
26968
|
+
if (!destroyed)
|
|
26969
|
+
store.patch({ footer: { live: liveLinkLabel("disconnected") } });
|
|
26970
|
+
});
|
|
26106
26971
|
await runtime.runIntent(store.getState().intent);
|
|
26107
26972
|
} catch (error) {
|
|
26108
26973
|
const normalized = normalizeError(error);
|
|
@@ -26295,7 +27160,7 @@ var init_runtime = __esm(() => {
|
|
|
26295
27160
|
{ id: "tasks", label: "Tasks", scene: "tasks", argv: ["tasks"], enterLabel: "Tasks", member: ["tasks"] },
|
|
26296
27161
|
{ id: "inbox", label: "Inbox", scene: "inbox", argv: ["inbox"], enterLabel: "Inbox", member: ["inbox"], badge: inboxPendingCount },
|
|
26297
27162
|
{ id: "stats", label: "Stats", scene: "family", argv: ["stats"], enterLabel: "Stats", member: ["family"] },
|
|
26298
|
-
{ id: "
|
|
27163
|
+
{ id: "init", label: "Init", scene: "init", argv: ["init"], enterLabel: "Init", member: ["init", "doctor", "server", "pi", "plugin", "repo", "workspace"] },
|
|
26299
27164
|
{ id: "help", label: "Help", scene: "help", argv: ["help"], enterLabel: "Help", member: ["help"] }
|
|
26300
27165
|
];
|
|
26301
27166
|
SCENE_DATA_KEY = {
|
|
@@ -26659,7 +27524,7 @@ var init_nav = __esm(() => {
|
|
|
26659
27524
|
{ id: "tasks", label: "Tasks", scene: "tasks", argv: ["tasks"], enterLabel: "Tasks", member: ["tasks"] },
|
|
26660
27525
|
{ id: "inbox", label: "Inbox", scene: "inbox", argv: ["inbox"], enterLabel: "Inbox", member: ["inbox"], badge: inboxPendingCount2 },
|
|
26661
27526
|
{ id: "stats", label: "Stats", scene: "family", argv: ["stats"], enterLabel: "Stats", member: ["family"] },
|
|
26662
|
-
{ id: "
|
|
27527
|
+
{ id: "init", label: "Init", scene: "init", argv: ["init"], enterLabel: "Init", member: ["init", "doctor", "server", "pi", "plugin", "repo", "workspace"] },
|
|
26663
27528
|
{ id: "help", label: "Help", scene: "help", argv: ["help"], enterLabel: "Help", member: ["help"] }
|
|
26664
27529
|
];
|
|
26665
27530
|
});
|
|
@@ -26925,7 +27790,7 @@ async function launchRigReactApp(options) {
|
|
|
26925
27790
|
}
|
|
26926
27791
|
for (const adapter of options.adapters ?? [])
|
|
26927
27792
|
await adapter.start?.(runtime);
|
|
26928
|
-
|
|
27793
|
+
connectRigServerEvents(options.projectRoot, {
|
|
26929
27794
|
onSnapshotInvalidated: () => refreshCurrentDataScene(),
|
|
26930
27795
|
onRunLogAppended: () => {
|
|
26931
27796
|
const scene = store.getState().scene;
|
|
@@ -26933,9 +27798,11 @@ async function launchRigReactApp(options) {
|
|
|
26933
27798
|
refreshCurrentDataScene();
|
|
26934
27799
|
},
|
|
26935
27800
|
onStatus: (status) => store.patch({ footer: { live: liveLinkLabel(status) } })
|
|
26936
|
-
}).
|
|
26937
|
-
|
|
27801
|
+
}).then((subscription) => {
|
|
27802
|
+
liveEvents = subscription;
|
|
27803
|
+
}).catch(() => {
|
|
26938
27804
|
store.patch({ footer: { live: liveLinkLabel("disconnected") } });
|
|
27805
|
+
});
|
|
26939
27806
|
await runtime.runIntent(store.getState().intent);
|
|
26940
27807
|
} catch (error) {
|
|
26941
27808
|
const n = normalizeError(error);
|
|
@@ -27136,7 +28003,7 @@ var init_bootstrap = __esm(() => {
|
|
|
27136
28003
|
// packages/cli/bin/rig.ts
|
|
27137
28004
|
init_launch_routing();
|
|
27138
28005
|
import { existsSync as existsSync25, readFileSync as readFileSync16 } from "fs";
|
|
27139
|
-
import { dirname as
|
|
28006
|
+
import { dirname as dirname6, resolve as resolve32 } from "path";
|
|
27140
28007
|
function packageVersionFrom(startDir) {
|
|
27141
28008
|
let current = resolve32(startDir);
|
|
27142
28009
|
while (true) {
|
|
@@ -27148,7 +28015,7 @@ function packageVersionFrom(startDir) {
|
|
|
27148
28015
|
return pkg.version;
|
|
27149
28016
|
} catch {}
|
|
27150
28017
|
}
|
|
27151
|
-
const parent =
|
|
28018
|
+
const parent = dirname6(current);
|
|
27152
28019
|
if (parent === current)
|
|
27153
28020
|
return null;
|
|
27154
28021
|
current = parent;
|