@h-rig/cli 0.0.6-alpha.87 → 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 +1380 -865
- package/dist/src/app/board.js +462 -48
- package/dist/src/app-opentui/adapters/common.d.ts +3 -0
- package/dist/src/app-opentui/adapters/common.js +4 -0
- package/dist/src/app-opentui/adapters/doctor.js +458 -46
- package/dist/src/app-opentui/adapters/family.js +701 -151
- 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.d.ts +7 -0
- package/dist/src/app-opentui/adapters/pi-attach.js +1004 -519
- 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 +621 -549
- package/dist/src/app-opentui/autocomplete.js +4 -2
- package/dist/src/app-opentui/bootstrap.js +1376 -861
- package/dist/src/app-opentui/command-palette.js +37 -10
- package/dist/src/app-opentui/index.js +632 -528
- package/dist/src/app-opentui/intent.js +33 -8
- package/dist/src/app-opentui/keymap.js +43 -414
- package/dist/src/app-opentui/pi-host-child.js +496 -57
- package/dist/src/app-opentui/pi-pty-host.d.ts +14 -64
- package/dist/src/app-opentui/pi-pty-host.js +3 -397
- package/dist/src/app-opentui/react/App.js +144 -469
- package/dist/src/app-opentui/react/ChromeHost.js +44 -415
- package/dist/src/app-opentui/react/launch.js +659 -552
- package/dist/src/app-opentui/react/nav.js +1 -1
- package/dist/src/app-opentui/registry.js +1181 -742
- 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/render/terminal-handoff.d.ts +16 -0
- package/dist/src/app-opentui/render/terminal-handoff.js +14 -0
- package/dist/src/app-opentui/runtime.js +632 -528
- 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 +496 -57
- package/dist/src/commands/_pi-frontend.d.ts +25 -0
- package/dist/src/commands/_pi-frontend.js +497 -57
- 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 +496 -57
- 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 +551 -85
- package/dist/src/commands.js +701 -151
- package/dist/src/index.js +705 -151
- 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) };
|
|
460
|
+
}
|
|
461
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot, metadata = {}) {
|
|
462
|
+
const repo = readRepoConnection(projectRoot);
|
|
463
|
+
if (!repo)
|
|
464
|
+
return;
|
|
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
|
+
});
|
|
443
484
|
}
|
|
444
|
-
function
|
|
485
|
+
function clearRepoServerProjectRoot(projectRoot) {
|
|
445
486
|
const repo = readRepoConnection(projectRoot);
|
|
446
487
|
if (!repo)
|
|
447
488
|
return;
|
|
448
|
-
writeRepoConnection(projectRoot, {
|
|
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
|
}
|
|
@@ -1346,7 +1778,15 @@ var init__async_ui = __esm(() => {
|
|
|
1346
1778
|
});
|
|
1347
1779
|
|
|
1348
1780
|
// packages/cli/src/commands/_pi-frontend.ts
|
|
1349
|
-
|
|
1781
|
+
var exports__pi_frontend = {};
|
|
1782
|
+
__export(exports__pi_frontend, {
|
|
1783
|
+
shouldRequireOperatorTranscript: () => shouldRequireOperatorTranscript,
|
|
1784
|
+
runWithProcessExitGuard: () => runWithProcessExitGuard,
|
|
1785
|
+
missingOperatorTranscriptMessage: () => missingOperatorTranscriptMessage,
|
|
1786
|
+
buildOperatorPiEnv: () => buildOperatorPiEnv,
|
|
1787
|
+
attachRunBundledPiFrontend: () => attachRunBundledPiFrontend
|
|
1788
|
+
});
|
|
1789
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
1350
1790
|
import { homedir as homedir2, tmpdir } from "os";
|
|
1351
1791
|
import { join } from "path";
|
|
1352
1792
|
import { main as runPiMain } from "@earendil-works/pi-coding-agent";
|
|
@@ -1398,7 +1838,7 @@ function statusFromRunDetails(run) {
|
|
|
1398
1838
|
async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
1399
1839
|
const server = await ensureServerForCli(context.projectRoot);
|
|
1400
1840
|
const localCwd = join(homedir2(), ".rig", "drones", runId.slice(0, 8));
|
|
1401
|
-
|
|
1841
|
+
mkdirSync4(localCwd, { recursive: true });
|
|
1402
1842
|
trustDroneCwd(localCwd);
|
|
1403
1843
|
installRigPiTheme();
|
|
1404
1844
|
let sessionFileArg = [];
|
|
@@ -1420,7 +1860,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
|
1420
1860
|
return line;
|
|
1421
1861
|
}).join(`
|
|
1422
1862
|
`);
|
|
1423
|
-
|
|
1863
|
+
writeFileSync3(localSessionPath, content);
|
|
1424
1864
|
sessionFileArg = ["--session", localSessionPath];
|
|
1425
1865
|
}
|
|
1426
1866
|
} catch {}
|
|
@@ -1436,12 +1876,12 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
|
1436
1876
|
function trustDroneCwd(localCwd) {
|
|
1437
1877
|
try {
|
|
1438
1878
|
const agentDir = join(homedir2(), ".pi", "agent");
|
|
1439
|
-
|
|
1879
|
+
mkdirSync4(agentDir, { recursive: true });
|
|
1440
1880
|
const trustPath = join(agentDir, "trust.json");
|
|
1441
1881
|
const store = existsSync4(trustPath) ? JSON.parse(readFileSync3(trustPath, "utf8")) : {};
|
|
1442
1882
|
if (store[localCwd] !== true) {
|
|
1443
1883
|
store[localCwd] = true;
|
|
1444
|
-
|
|
1884
|
+
writeFileSync3(trustPath, `${JSON.stringify(store, null, "\t")}
|
|
1445
1885
|
`);
|
|
1446
1886
|
}
|
|
1447
1887
|
} catch {}
|
|
@@ -1449,15 +1889,38 @@ function trustDroneCwd(localCwd) {
|
|
|
1449
1889
|
function installRigPiTheme() {
|
|
1450
1890
|
try {
|
|
1451
1891
|
const themesDir = join(homedir2(), ".pi", "agent", "themes");
|
|
1452
|
-
|
|
1892
|
+
mkdirSync4(themesDir, { recursive: true });
|
|
1453
1893
|
const themePath = join(themesDir, "rig.json");
|
|
1454
1894
|
const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
|
|
1455
1895
|
`;
|
|
1456
1896
|
if (!existsSync4(themePath) || readFileSync3(themePath, "utf8") !== next) {
|
|
1457
|
-
|
|
1897
|
+
writeFileSync3(themePath, next);
|
|
1458
1898
|
}
|
|
1459
1899
|
} catch {}
|
|
1460
1900
|
}
|
|
1901
|
+
async function runWithProcessExitGuard(body) {
|
|
1902
|
+
const realExit = process.exit;
|
|
1903
|
+
let exitCode = 0;
|
|
1904
|
+
let signalQuit = () => {};
|
|
1905
|
+
const quit = new Promise((resolve4) => {
|
|
1906
|
+
signalQuit = resolve4;
|
|
1907
|
+
});
|
|
1908
|
+
const guardedExit = (code) => {
|
|
1909
|
+
exitCode = typeof code === "number" ? code : 0;
|
|
1910
|
+
signalQuit();
|
|
1911
|
+
return;
|
|
1912
|
+
};
|
|
1913
|
+
process.exit = guardedExit;
|
|
1914
|
+
try {
|
|
1915
|
+
await Promise.race([Promise.resolve().then(body), quit]);
|
|
1916
|
+
} finally {
|
|
1917
|
+
process.exit = realExit;
|
|
1918
|
+
}
|
|
1919
|
+
return exitCode;
|
|
1920
|
+
}
|
|
1921
|
+
function runPiMainReturningOnQuit(args, options) {
|
|
1922
|
+
return runWithProcessExitGuard(() => runPiMain(args, options));
|
|
1923
|
+
}
|
|
1461
1924
|
async function attachRunBundledPiFrontend(context, input) {
|
|
1462
1925
|
const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
1463
1926
|
const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
|
|
@@ -1473,16 +1936,20 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
1473
1936
|
};
|
|
1474
1937
|
let detached = false;
|
|
1475
1938
|
try {
|
|
1476
|
-
|
|
1939
|
+
const piArgs = [
|
|
1477
1940
|
"--offline",
|
|
1478
1941
|
"--no-extensions",
|
|
1479
1942
|
"--no-skills",
|
|
1480
1943
|
"--no-prompt-templates",
|
|
1481
1944
|
"--no-context-files",
|
|
1482
1945
|
...sessionFileArg
|
|
1483
|
-
]
|
|
1484
|
-
|
|
1485
|
-
|
|
1946
|
+
];
|
|
1947
|
+
const piOptions = { extensionFactories: [piRigExtensionFactory] };
|
|
1948
|
+
if (input.returnOnQuit) {
|
|
1949
|
+
await runPiMainReturningOnQuit(piArgs, piOptions);
|
|
1950
|
+
} else {
|
|
1951
|
+
await runPiMain(piArgs, piOptions);
|
|
1952
|
+
}
|
|
1486
1953
|
detached = true;
|
|
1487
1954
|
} finally {
|
|
1488
1955
|
restoreEnv();
|
|
@@ -1695,6 +2162,21 @@ async function captureConsole(fn) {
|
|
|
1695
2162
|
console.error = original.error;
|
|
1696
2163
|
}
|
|
1697
2164
|
}
|
|
2165
|
+
async function releaseRendererForExternalTui(ctx) {
|
|
2166
|
+
const renderer = ctx.renderer;
|
|
2167
|
+
if (!renderer)
|
|
2168
|
+
return;
|
|
2169
|
+
if (renderer.suspend) {
|
|
2170
|
+
await renderer.suspend();
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
if (renderer.destroy) {
|
|
2174
|
+
await renderer.destroy();
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
async function resumeRendererAfterExternalTui(ctx) {
|
|
2178
|
+
await ctx.renderer?.resume?.();
|
|
2179
|
+
}
|
|
1698
2180
|
function arrayFromPayload(value) {
|
|
1699
2181
|
if (Array.isArray(value)) {
|
|
1700
2182
|
return value.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry)));
|
|
@@ -2727,12 +3209,13 @@ var init__help_catalog = __esm(() => {
|
|
|
2727
3209
|
{
|
|
2728
3210
|
name: "server",
|
|
2729
3211
|
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
2730
|
-
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
3212
|
+
usage: ["rig server <status|list|add|use|repair-link|start> [options]"],
|
|
2731
3213
|
commands: [
|
|
2732
|
-
{ 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 },
|
|
2733
3215
|
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
2734
3216
|
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
2735
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 },
|
|
2736
3219
|
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
2737
3220
|
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
2738
3221
|
],
|
|
@@ -2740,6 +3223,7 @@ var init__help_catalog = __esm(() => {
|
|
|
2740
3223
|
"rig server status",
|
|
2741
3224
|
"rig server add prod https://where.rig-does.work",
|
|
2742
3225
|
"rig server use prod",
|
|
3226
|
+
"rig server repair-link --repo owner/repo",
|
|
2743
3227
|
"rig server use local",
|
|
2744
3228
|
"rig server start --port 3773"
|
|
2745
3229
|
],
|
|
@@ -3254,7 +3738,7 @@ function resolveControlPlaneDefinitionRoot(projectRoot) {
|
|
|
3254
3738
|
var init__paths = () => {};
|
|
3255
3739
|
|
|
3256
3740
|
// packages/cli/src/report-bug.ts
|
|
3257
|
-
import { copyFileSync, existsSync as existsSync7, mkdirSync as
|
|
3741
|
+
import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync5, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3258
3742
|
import { basename as basename2, extname, join as join2, resolve as resolve8 } from "path";
|
|
3259
3743
|
function slugifyBugTitle(value) {
|
|
3260
3744
|
const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80).replace(/-+$/g, "");
|
|
@@ -3293,8 +3777,8 @@ function createBugReportFiles(input) {
|
|
|
3293
3777
|
}
|
|
3294
3778
|
rmSync3(reportDir, { recursive: true, force: true });
|
|
3295
3779
|
}
|
|
3296
|
-
|
|
3297
|
-
|
|
3780
|
+
mkdirSync5(assetDir, { recursive: true });
|
|
3781
|
+
mkdirSync5(screenshotDir, { recursive: true });
|
|
3298
3782
|
const copiedScreenshots = copyEvidenceFiles(input.projectRoot, screenshotDir, input.screenshots ?? [], "screenshot");
|
|
3299
3783
|
const copiedAssets = copyEvidenceFiles(input.projectRoot, assetDir, input.assets ?? [], "asset");
|
|
3300
3784
|
const manifestAssets = [
|
|
@@ -3324,15 +3808,15 @@ function createBugReportFiles(input) {
|
|
|
3324
3808
|
platform: process.platform,
|
|
3325
3809
|
arch: process.arch
|
|
3326
3810
|
};
|
|
3327
|
-
|
|
3328
|
-
|
|
3811
|
+
writeFileSync4(join2(assetDir, "README.md"), buildAssetReadme(input.title), "utf8");
|
|
3812
|
+
writeFileSync4(join2(screenshotDir, "README.md"), buildScreenshotReadme(input.title), "utf8");
|
|
3329
3813
|
if (browserPath && browser) {
|
|
3330
|
-
|
|
3814
|
+
writeFileSync4(browserPath, `${JSON.stringify(browser, null, 2)}
|
|
3331
3815
|
`, "utf8");
|
|
3332
3816
|
}
|
|
3333
|
-
|
|
3817
|
+
writeFileSync4(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
3334
3818
|
`, "utf8");
|
|
3335
|
-
|
|
3819
|
+
writeFileSync4(taskPath, buildBugReportMarkdown(input, browser, copiedScreenshots, copiedAssets), "utf8");
|
|
3336
3820
|
return {
|
|
3337
3821
|
slug,
|
|
3338
3822
|
reportDir,
|
|
@@ -3509,7 +3993,7 @@ function formatAssetMarkdown(name, path) {
|
|
|
3509
3993
|
var init_report_bug = () => {};
|
|
3510
3994
|
|
|
3511
3995
|
// packages/cli/src/commands/task-report-bug.ts
|
|
3512
|
-
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as
|
|
3996
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
3513
3997
|
import { resolve as resolve9 } from "path";
|
|
3514
3998
|
import pc3 from "picocolors";
|
|
3515
3999
|
import {
|
|
@@ -3871,7 +4355,7 @@ function appendTaskConfigEntryPreservingText(taskConfigPath, issueId, entry) {
|
|
|
3871
4355
|
`).map((line) => ` ${line}`).join(`
|
|
3872
4356
|
`);
|
|
3873
4357
|
if (!trimmed || trimmed === "{}") {
|
|
3874
|
-
|
|
4358
|
+
writeFileSync5(taskConfigPath, `{
|
|
3875
4359
|
${serializedEntry}
|
|
3876
4360
|
}
|
|
3877
4361
|
`, "utf8");
|
|
@@ -3887,7 +4371,7 @@ ${serializedEntry}
|
|
|
3887
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." });
|
|
3888
4372
|
}
|
|
3889
4373
|
const comma = before.trim() === "{" ? "" : ",";
|
|
3890
|
-
|
|
4374
|
+
writeFileSync5(taskConfigPath, `${before}${comma}
|
|
3891
4375
|
${serializedEntry}
|
|
3892
4376
|
}
|
|
3893
4377
|
`, "utf8");
|
|
@@ -4272,7 +4756,7 @@ var init_task_report_bug = __esm(() => {
|
|
|
4272
4756
|
});
|
|
4273
4757
|
|
|
4274
4758
|
// packages/cli/src/commands/browser.ts
|
|
4275
|
-
import { mkdirSync as
|
|
4759
|
+
import { mkdirSync as mkdirSync6, rmSync as rmSync4 } from "fs";
|
|
4276
4760
|
import { resolve as resolve10 } from "path";
|
|
4277
4761
|
import { spawn } from "child_process";
|
|
4278
4762
|
import { emitKeypressEvents } from "readline";
|
|
@@ -4850,7 +5334,7 @@ function readBrowserDemoCommandLine(command) {
|
|
|
4850
5334
|
}
|
|
4851
5335
|
async function launchBrowserDemo(runtime) {
|
|
4852
5336
|
rmSync4(resolve10(runtime.browserDir, runtime.stateDir), { recursive: true, force: true });
|
|
4853
|
-
|
|
5337
|
+
mkdirSync6(resolve10(runtime.browserDir, runtime.stateDir), { recursive: true });
|
|
4854
5338
|
const launcherPath = resolve10(runtime.browserDir, "scripts/electron-launcher.mjs");
|
|
4855
5339
|
const launcher = await import(pathToFileURL(launcherPath).href);
|
|
4856
5340
|
const electronPath = await launcher.resolveElectronPath();
|
|
@@ -5199,7 +5683,7 @@ var init_profile_and_review = __esm(() => {
|
|
|
5199
5683
|
});
|
|
5200
5684
|
|
|
5201
5685
|
// packages/cli/src/commands/_policy.ts
|
|
5202
|
-
import { appendFileSync, mkdirSync as
|
|
5686
|
+
import { appendFileSync, mkdirSync as mkdirSync7 } from "fs";
|
|
5203
5687
|
import { resolve as resolve11 } from "path";
|
|
5204
5688
|
import { evaluate as evaluate2, loadPolicy as loadPolicy2, resolveAction as resolveAction2 } from "@rig/runtime/control-plane/runtime/guard";
|
|
5205
5689
|
import { resolveHarnessPaths } from "@rig/runtime/control-plane/native/utils";
|
|
@@ -5216,7 +5700,7 @@ function appendControlledBashAudit(context, mode, command, args, matchedRuleIds,
|
|
|
5216
5700
|
}
|
|
5217
5701
|
const logsDir = resolveHarnessPaths(context.projectRoot).logsDir;
|
|
5218
5702
|
const logFile = resolve11(logsDir, "controlled-bash.jsonl");
|
|
5219
|
-
|
|
5703
|
+
mkdirSync7(logsDir, { recursive: true });
|
|
5220
5704
|
const payload = {
|
|
5221
5705
|
timestamp: new Date().toISOString(),
|
|
5222
5706
|
mode,
|
|
@@ -5510,9 +5994,9 @@ var exports_pi = {};
|
|
|
5510
5994
|
__export(exports_pi, {
|
|
5511
5995
|
executePi: () => executePi
|
|
5512
5996
|
});
|
|
5513
|
-
import { existsSync as existsSync10, mkdirSync as
|
|
5997
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
5514
5998
|
import { homedir as homedir5 } from "os";
|
|
5515
|
-
import { dirname as
|
|
5999
|
+
import { dirname as dirname3, resolve as resolve13 } from "path";
|
|
5516
6000
|
function settingsPath(root) {
|
|
5517
6001
|
return resolve13(root, ".pi", "settings.json");
|
|
5518
6002
|
}
|
|
@@ -5537,8 +6021,8 @@ function packageKey(entry) {
|
|
|
5537
6021
|
return JSON.stringify(entry);
|
|
5538
6022
|
}
|
|
5539
6023
|
function writeSettings(path, settings) {
|
|
5540
|
-
|
|
5541
|
-
|
|
6024
|
+
mkdirSync8(dirname3(path), { recursive: true });
|
|
6025
|
+
writeFileSync6(path, `${JSON.stringify(settings, null, 2)}
|
|
5542
6026
|
`, "utf-8");
|
|
5543
6027
|
}
|
|
5544
6028
|
async function searchNpmForPiExtensions(term) {
|
|
@@ -5721,6 +6205,14 @@ function permissionAllowsPr2(payload) {
|
|
|
5721
6205
|
function isNotFoundError(error) {
|
|
5722
6206
|
return /\b(404|not found)\b/i.test(message(error));
|
|
5723
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
|
+
}
|
|
5724
6216
|
function projectCheckoutReady(payload) {
|
|
5725
6217
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
5726
6218
|
return null;
|
|
@@ -5775,25 +6267,37 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
5775
6267
|
}
|
|
5776
6268
|
const repo = readRepoConnection(context.projectRoot);
|
|
5777
6269
|
const remoteWithoutProjectLink = selectedServer?.connectionKind === "remote" && !repo?.project;
|
|
5778
|
-
|
|
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
|
+
}
|
|
5779
6278
|
try {
|
|
5780
6279
|
const auth = await request("/api/github/auth/status");
|
|
5781
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>`."));
|
|
5782
6281
|
} catch (error) {
|
|
5783
6282
|
checks.push(preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix GitHub auth on the selected Rig server."));
|
|
5784
6283
|
}
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
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."));
|
|
5797
6301
|
}
|
|
5798
6302
|
if (repo?.project) {
|
|
5799
6303
|
try {
|
|
@@ -5805,19 +6309,24 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
5805
6309
|
}
|
|
5806
6310
|
}
|
|
5807
6311
|
if (taskId) {
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
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."));
|
|
5821
6330
|
}
|
|
5822
6331
|
}
|
|
5823
6332
|
if ((options.runtimeAdapter ?? "pi") === "pi") {
|
|
@@ -6298,7 +6807,7 @@ import {
|
|
|
6298
6807
|
chmodSync,
|
|
6299
6808
|
copyFileSync as copyFileSync2,
|
|
6300
6809
|
existsSync as existsSync12,
|
|
6301
|
-
mkdirSync as
|
|
6810
|
+
mkdirSync as mkdirSync9,
|
|
6302
6811
|
readdirSync,
|
|
6303
6812
|
readlinkSync,
|
|
6304
6813
|
rmSync as rmSync5,
|
|
@@ -6403,7 +6912,7 @@ async function executeDist(context, args) {
|
|
|
6403
6912
|
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
6404
6913
|
const scope = parseInstallScope(scopeResult.value);
|
|
6405
6914
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
6406
|
-
|
|
6915
|
+
mkdirSync9(installDir, { recursive: true });
|
|
6407
6916
|
let source = await findLatestDistBinary(context.projectRoot);
|
|
6408
6917
|
let buildDir = null;
|
|
6409
6918
|
if (!source) {
|
|
@@ -6458,7 +6967,7 @@ async function executeDist(context, args) {
|
|
|
6458
6967
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
6459
6968
|
const currentId = computeRuntimeImageId(fp);
|
|
6460
6969
|
const imagesDir = resolve16(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
6461
|
-
|
|
6970
|
+
mkdirSync9(imagesDir, { recursive: true });
|
|
6462
6971
|
let pruned = 0;
|
|
6463
6972
|
for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
|
|
6464
6973
|
if (entry.isDirectory() && entry.name !== currentId) {
|
|
@@ -6470,9 +6979,9 @@ async function executeDist(context, args) {
|
|
|
6470
6979
|
console.log(`Pruned ${pruned} stale image(s).`);
|
|
6471
6980
|
}
|
|
6472
6981
|
const imageDir = resolve16(imagesDir, currentId);
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6982
|
+
mkdirSync9(resolve16(imageDir, "bin/hooks"), { recursive: true });
|
|
6983
|
+
mkdirSync9(resolve16(imageDir, "bin/plugins"), { recursive: true });
|
|
6984
|
+
mkdirSync9(resolve16(imageDir, "bin/validators"), { recursive: true });
|
|
6476
6985
|
const hookNames = [
|
|
6477
6986
|
"scope-guard",
|
|
6478
6987
|
"import-guard",
|
|
@@ -6497,8 +7006,8 @@ async function executeDist(context, args) {
|
|
|
6497
7006
|
const binPluginsDir = resolve16(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
|
|
6498
7007
|
const validatorsRoot = resolve16(hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
6499
7008
|
const binValidatorsDir = resolve16(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
|
|
6500
|
-
|
|
6501
|
-
|
|
7009
|
+
mkdirSync9(binPluginsDir, { recursive: true });
|
|
7010
|
+
mkdirSync9(binValidatorsDir, { recursive: true });
|
|
6502
7011
|
if (existsSync12(pluginsDir)) {
|
|
6503
7012
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
6504
7013
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
@@ -6937,16 +7446,19 @@ function formatConnectionList(connections) {
|
|
|
6937
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(`
|
|
6938
7447
|
`);
|
|
6939
7448
|
}
|
|
6940
|
-
function formatConnectionStatus(selected, connections) {
|
|
7449
|
+
function formatConnectionStatus(selected, connections, repo, remoteProjectLink) {
|
|
6941
7450
|
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
6942
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";
|
|
6943
7453
|
return [
|
|
6944
7454
|
formatSection("Rig server", "selected for this repo"),
|
|
6945
7455
|
`${themeFaint("\u2502")} ${themeDim("selected ")} ${pc5.bold(selected)}`,
|
|
6946
7456
|
`${themeFaint("\u2502")} ${themeDim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
6947
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}`] : [],
|
|
6948
7460
|
"",
|
|
6949
|
-
...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`"])
|
|
6950
7462
|
].join(`
|
|
6951
7463
|
`);
|
|
6952
7464
|
}
|
|
@@ -7175,7 +7687,7 @@ var init_inbox = __esm(() => {
|
|
|
7175
7687
|
|
|
7176
7688
|
// packages/cli/src/commands/_snapshot-upload.ts
|
|
7177
7689
|
import { mkdir, readdir, readFile, writeFile } from "fs/promises";
|
|
7178
|
-
import { dirname as
|
|
7690
|
+
import { dirname as dirname4, resolve as resolve17, relative, sep } from "path";
|
|
7179
7691
|
function toPosixPath(path) {
|
|
7180
7692
|
return path.split(sep).join("/");
|
|
7181
7693
|
}
|
|
@@ -7276,7 +7788,7 @@ __export(exports_init, {
|
|
|
7276
7788
|
DEMO_TASKS_RELATIVE_DIR: () => DEMO_TASKS_RELATIVE_DIR,
|
|
7277
7789
|
DEMO_TASKS: () => DEMO_TASKS
|
|
7278
7790
|
});
|
|
7279
|
-
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";
|
|
7280
7792
|
import { spawnSync } from "child_process";
|
|
7281
7793
|
import { basename as basename3, resolve as resolve18 } from "path";
|
|
7282
7794
|
import { buildRigInitConfigSource } from "@rig/core";
|
|
@@ -7300,14 +7812,14 @@ function parseRepoSlug(value) {
|
|
|
7300
7812
|
}
|
|
7301
7813
|
function ensureRigPrivateDirs(projectRoot) {
|
|
7302
7814
|
const rigDir = resolve18(projectRoot, ".rig");
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
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 });
|
|
7308
7820
|
const taskConfigPath = resolve18(rigDir, "task-config.json");
|
|
7309
7821
|
if (!existsSync13(taskConfigPath))
|
|
7310
|
-
|
|
7822
|
+
writeFileSync7(taskConfigPath, `{}
|
|
7311
7823
|
`, "utf-8");
|
|
7312
7824
|
}
|
|
7313
7825
|
function ensureGitignoreEntries(projectRoot) {
|
|
@@ -7335,7 +7847,7 @@ function ensureRigConfigPackageDependencies(projectRoot) {
|
|
|
7335
7847
|
...existsSync13(path) ? existing : { name: "rig-project", private: true },
|
|
7336
7848
|
devDependencies
|
|
7337
7849
|
};
|
|
7338
|
-
|
|
7850
|
+
writeFileSync7(path, `${JSON.stringify(next, null, 2)}
|
|
7339
7851
|
`, "utf8");
|
|
7340
7852
|
}
|
|
7341
7853
|
function applyGitHubProjectConfig(source, options) {
|
|
@@ -7361,9 +7873,9 @@ function checkoutForInit(projectRoot, serverKind, strategy) {
|
|
|
7361
7873
|
const selected = strategy ?? { kind: "managed-clone" };
|
|
7362
7874
|
switch (selected.kind) {
|
|
7363
7875
|
case "managed-clone":
|
|
7364
|
-
return { kind: "managed-clone"
|
|
7876
|
+
return { kind: "managed-clone" };
|
|
7365
7877
|
case "current-ref":
|
|
7366
|
-
return { kind: "current-ref",
|
|
7878
|
+
return { kind: "current-ref", ...selected.ref ? { ref: selected.ref } : {} };
|
|
7367
7879
|
case "uploaded-snapshot":
|
|
7368
7880
|
return { kind: "uploaded-snapshot", path: projectRoot, source: "local-working-tree" };
|
|
7369
7881
|
case "existing-path":
|
|
@@ -7616,7 +8128,7 @@ function remoteGitHubAuthMetadata(payload) {
|
|
|
7616
8128
|
};
|
|
7617
8129
|
}
|
|
7618
8130
|
function writeRemoteGitHubAuthState(projectRoot, input) {
|
|
7619
|
-
|
|
8131
|
+
writeFileSync7(resolve18(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
|
|
7620
8132
|
authenticated: true,
|
|
7621
8133
|
source: input.source,
|
|
7622
8134
|
storedOnServer: true,
|
|
@@ -7664,7 +8176,7 @@ function runLocalFilesInit(context, options) {
|
|
|
7664
8176
|
console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
|
|
7665
8177
|
} else {
|
|
7666
8178
|
const projectName = basename3(projectRoot) || "rig-project";
|
|
7667
|
-
|
|
8179
|
+
writeFileSync7(configTsPath, buildRigInitConfigSource({
|
|
7668
8180
|
projectName,
|
|
7669
8181
|
taskSource: { kind: "files", path: "tasks" },
|
|
7670
8182
|
useStandardPlugin: true
|
|
@@ -7673,8 +8185,8 @@ function runLocalFilesInit(context, options) {
|
|
|
7673
8185
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
7674
8186
|
const tasksDir = resolve18(projectRoot, "tasks");
|
|
7675
8187
|
if (!existsSync13(tasksDir)) {
|
|
7676
|
-
|
|
7677
|
-
|
|
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)}
|
|
7678
8190
|
`, "utf-8");
|
|
7679
8191
|
}
|
|
7680
8192
|
if (context.outputMode !== "json") {
|
|
@@ -7698,7 +8210,7 @@ function runDemoInit(context, options) {
|
|
|
7698
8210
|
console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it for the demo.");
|
|
7699
8211
|
}
|
|
7700
8212
|
} else {
|
|
7701
|
-
|
|
8213
|
+
writeFileSync7(configTsPath, buildRigInitConfigSource({
|
|
7702
8214
|
projectName: basename3(projectRoot) || "rig-demo",
|
|
7703
8215
|
taskSource: { kind: "files", path: DEMO_TASKS_RELATIVE_DIR },
|
|
7704
8216
|
useStandardPlugin: true
|
|
@@ -7707,14 +8219,14 @@ function runDemoInit(context, options) {
|
|
|
7707
8219
|
}
|
|
7708
8220
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
7709
8221
|
const demoTasksDir = resolve18(projectRoot, DEMO_TASKS_RELATIVE_DIR);
|
|
7710
|
-
|
|
8222
|
+
mkdirSync10(demoTasksDir, { recursive: true });
|
|
7711
8223
|
const taskIds = [];
|
|
7712
8224
|
for (const task of DEMO_TASKS) {
|
|
7713
8225
|
const id = String(task.id);
|
|
7714
8226
|
taskIds.push(id);
|
|
7715
8227
|
const taskPath = resolve18(demoTasksDir, `${id}.json`);
|
|
7716
8228
|
if (!existsSync13(taskPath)) {
|
|
7717
|
-
|
|
8229
|
+
writeFileSync7(taskPath, `${JSON.stringify(task, null, 2)}
|
|
7718
8230
|
`, "utf-8");
|
|
7719
8231
|
}
|
|
7720
8232
|
}
|
|
@@ -7742,21 +8254,32 @@ function runDemoInit(context, options) {
|
|
|
7742
8254
|
}
|
|
7743
8255
|
async function runControlPlaneInit(context, options) {
|
|
7744
8256
|
const projectRoot = context.projectRoot;
|
|
7745
|
-
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");
|
|
7746
8268
|
if (!detectedSlug) {
|
|
7747
8269
|
const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
|
|
7748
|
-
if (
|
|
8270
|
+
if (serverKind === "local" && authMethod2 === "skip") {
|
|
7749
8271
|
return runLocalFilesInit(context, options);
|
|
7750
8272
|
}
|
|
7751
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);
|
|
7752
8274
|
}
|
|
7753
8275
|
const repo = parseRepoSlug(detectedSlug);
|
|
7754
|
-
const
|
|
7755
|
-
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;
|
|
7756
8279
|
if (serverKind === "remote") {
|
|
7757
|
-
if (!
|
|
7758
|
-
throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server
|
|
7759
|
-
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 });
|
|
7760
8283
|
}
|
|
7761
8284
|
writeRepoConnection(projectRoot, {
|
|
7762
8285
|
selected: connectionAlias,
|
|
@@ -7779,11 +8302,11 @@ async function runControlPlaneInit(context, options) {
|
|
|
7779
8302
|
taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
|
|
7780
8303
|
useStandardPlugin: true
|
|
7781
8304
|
}), options);
|
|
7782
|
-
|
|
8305
|
+
writeFileSync7(configTsPath, source, "utf-8");
|
|
7783
8306
|
}
|
|
7784
8307
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
7785
8308
|
}
|
|
7786
|
-
|
|
8309
|
+
writeFileSync7(resolve18(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
7787
8310
|
`, "utf8");
|
|
7788
8311
|
const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
|
|
7789
8312
|
let uploadedSnapshot = null;
|
|
@@ -7798,7 +8321,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
7798
8321
|
let githubAuth = null;
|
|
7799
8322
|
let deviceAuth = null;
|
|
7800
8323
|
const authMethod = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
|
|
7801
|
-
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;
|
|
7802
8325
|
if (remoteGhTokenWarning && !options.yes) {
|
|
7803
8326
|
throw new CliError(`${remoteGhTokenWarning} Re-run with --yes to confirm this explicit token transfer.`, 1);
|
|
7804
8327
|
}
|
|
@@ -8178,8 +8701,8 @@ var init_init = __esm(() => {
|
|
|
8178
8701
|
|
|
8179
8702
|
// packages/cli/src/commands/github.ts
|
|
8180
8703
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
8181
|
-
import { mkdirSync as
|
|
8182
|
-
import { dirname as
|
|
8704
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync8 } from "fs";
|
|
8705
|
+
import { dirname as dirname5, resolve as resolve19 } from "path";
|
|
8183
8706
|
function printPayload(context, payload, fallback) {
|
|
8184
8707
|
if (context.outputMode === "json")
|
|
8185
8708
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -8218,8 +8741,8 @@ function persistRemoteAuthSession(context, source, result, fallbackToken) {
|
|
|
8218
8741
|
return;
|
|
8219
8742
|
const repo = readRepoConnection(context.projectRoot);
|
|
8220
8743
|
const path = resolve19(context.projectRoot, ".rig", "state", "github-auth.json");
|
|
8221
|
-
|
|
8222
|
-
|
|
8744
|
+
mkdirSync11(dirname5(path), { recursive: true });
|
|
8745
|
+
writeFileSync8(path, `${JSON.stringify({
|
|
8223
8746
|
authenticated: true,
|
|
8224
8747
|
source,
|
|
8225
8748
|
storedOnServer: true,
|
|
@@ -10343,13 +10866,46 @@ function parseConnection(alias, value, options) {
|
|
|
10343
10866
|
}
|
|
10344
10867
|
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
10345
10868
|
}
|
|
10346
|
-
function printJsonOrText(context,
|
|
10347
|
-
if (context.outputMode
|
|
10348
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
10349
|
-
} else {
|
|
10869
|
+
function printJsonOrText(context, _payload, text2) {
|
|
10870
|
+
if (context.outputMode !== "json") {
|
|
10350
10871
|
console.log(text2);
|
|
10351
10872
|
}
|
|
10352
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
|
+
}
|
|
10353
10909
|
async function promptForConnectionAlias(context) {
|
|
10354
10910
|
const state = readGlobalConnections();
|
|
10355
10911
|
const repo = readRepoConnection(context.projectRoot);
|
|
@@ -10403,37 +10959,67 @@ async function executeConnectionCommand(context, args, options) {
|
|
|
10403
10959
|
}
|
|
10404
10960
|
if (!alias)
|
|
10405
10961
|
throw new CliError(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
|
|
10962
|
+
let selectedConnection = { kind: "local", mode: "auto" };
|
|
10406
10963
|
if (alias !== "local") {
|
|
10407
10964
|
const state = readGlobalConnections();
|
|
10408
|
-
|
|
10965
|
+
const connection = state.connections[alias];
|
|
10966
|
+
if (!connection)
|
|
10409
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;
|
|
10410
10969
|
}
|
|
10411
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);
|
|
10412
10972
|
const repoState = {
|
|
10413
10973
|
selected: alias,
|
|
10414
10974
|
...previousRepo?.project ? { project: previousRepo.project } : {},
|
|
10415
10975
|
linkedAt: new Date().toISOString(),
|
|
10416
|
-
...
|
|
10976
|
+
...preserveRemoteRoot ? {
|
|
10977
|
+
serverProjectRoot: previousRepo.serverProjectRoot,
|
|
10978
|
+
serverProjectRootAlias: previousRepo.serverProjectRootAlias,
|
|
10979
|
+
serverProjectRootBaseUrl: previousRepo.serverProjectRootBaseUrl
|
|
10980
|
+
} : {}
|
|
10417
10981
|
};
|
|
10418
10982
|
writeRepoConnection(context.projectRoot, repoState);
|
|
10419
|
-
|
|
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", [
|
|
10420
10992
|
["selected", alias],
|
|
10421
10993
|
["scope", "this repo"],
|
|
10422
|
-
["
|
|
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"]
|
|
10423
10996
|
]));
|
|
10424
|
-
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 };
|
|
10425
11004
|
}
|
|
10426
11005
|
case "status": {
|
|
10427
11006
|
requireNoExtraArgs(rest, `${usageName(options)} status`);
|
|
10428
11007
|
const repo = readRepoConnection(context.projectRoot);
|
|
10429
11008
|
const global = readGlobalConnections();
|
|
10430
|
-
const
|
|
10431
|
-
|
|
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));
|
|
10432
11018
|
return { ok: true, group: options.group, command: "status", details };
|
|
10433
11019
|
}
|
|
10434
11020
|
default:
|
|
10435
11021
|
throw new CliError(`Unknown ${options.group} command: ${String(command)}
|
|
10436
|
-
Usage: ${usageName(options)} <list|add|use|status>`, 1);
|
|
11022
|
+
Usage: ${usageName(options)} <list|add|use|status|repair-link>`, 1);
|
|
10437
11023
|
}
|
|
10438
11024
|
}
|
|
10439
11025
|
var init_connect = __esm(() => {
|
|
@@ -10441,13 +11027,14 @@ var init_connect = __esm(() => {
|
|
|
10441
11027
|
init_runner();
|
|
10442
11028
|
init__connection_state();
|
|
10443
11029
|
init__cli_format();
|
|
11030
|
+
init__server_client();
|
|
10444
11031
|
});
|
|
10445
11032
|
|
|
10446
11033
|
// packages/cli/src/commands/server.ts
|
|
10447
11034
|
import { resolveRigServerCommand } from "@rig/runtime/local-server";
|
|
10448
11035
|
async function executeServer(context, args, options) {
|
|
10449
11036
|
const [command = "status", ...rest] = args;
|
|
10450
|
-
if (["status", "list", "add", "use"].includes(command)) {
|
|
11037
|
+
if (["status", "list", "add", "use", "repair-link"].includes(command)) {
|
|
10451
11038
|
return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
|
|
10452
11039
|
}
|
|
10453
11040
|
switch (command) {
|
|
@@ -11234,7 +11821,7 @@ var init_task = __esm(() => {
|
|
|
11234
11821
|
});
|
|
11235
11822
|
|
|
11236
11823
|
// packages/cli/src/commands/task-run-driver.ts
|
|
11237
|
-
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";
|
|
11238
11825
|
import { resolve as resolve24 } from "path";
|
|
11239
11826
|
import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
|
|
11240
11827
|
import { createInterface as createLineInterface } from "readline";
|
|
@@ -11337,7 +11924,7 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
|
|
|
11337
11924
|
try {
|
|
11338
11925
|
if (!statSync2(sourcePath).isFile())
|
|
11339
11926
|
continue;
|
|
11340
|
-
|
|
11927
|
+
mkdirSync12(resolve24(targetPath, ".."), { recursive: true });
|
|
11341
11928
|
copyFileSync3(sourcePath, targetPath);
|
|
11342
11929
|
copied += 1;
|
|
11343
11930
|
} catch {}
|
|
@@ -12208,8 +12795,8 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
12208
12795
|
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
12209
12796
|
classifiedAt: new Date().toISOString()
|
|
12210
12797
|
};
|
|
12211
|
-
|
|
12212
|
-
|
|
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)}
|
|
12213
12800
|
`, "utf8");
|
|
12214
12801
|
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
12215
12802
|
prompt = `${prompt}
|
|
@@ -12356,8 +12943,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
12356
12943
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
12357
12944
|
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
12358
12945
|
if (readyFile) {
|
|
12359
|
-
|
|
12360
|
-
|
|
12946
|
+
mkdirSync12(resolve24(readyFile, ".."), { recursive: true });
|
|
12947
|
+
writeFileSync9(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
12361
12948
|
`, "utf8");
|
|
12362
12949
|
}
|
|
12363
12950
|
appendRunLog(context.projectRoot, input.runId, {
|
|
@@ -13303,7 +13890,7 @@ var init_test = __esm(() => {
|
|
|
13303
13890
|
});
|
|
13304
13891
|
|
|
13305
13892
|
// packages/cli/src/commands/setup.ts
|
|
13306
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
13893
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, readdirSync as readdirSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
13307
13894
|
import { resolve as resolve25 } from "path";
|
|
13308
13895
|
import { createPluginHost } from "@rig/core";
|
|
13309
13896
|
import {
|
|
@@ -13358,12 +13945,12 @@ function runSetupInit(projectRoot) {
|
|
|
13358
13945
|
const stateDir = resolveControlPlaneHostStateDir(projectRoot);
|
|
13359
13946
|
const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
|
|
13360
13947
|
const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13948
|
+
mkdirSync13(stateDir, { recursive: true });
|
|
13949
|
+
mkdirSync13(logsDir, { recursive: true });
|
|
13950
|
+
mkdirSync13(artifactsDir, { recursive: true });
|
|
13364
13951
|
const failuresPath = resolve25(stateDir, "failed_approaches.md");
|
|
13365
13952
|
if (!existsSync17(failuresPath)) {
|
|
13366
|
-
|
|
13953
|
+
writeFileSync10(failuresPath, `# Failed Approaches
|
|
13367
13954
|
|
|
13368
13955
|
`, "utf-8");
|
|
13369
13956
|
}
|
|
@@ -15341,414 +15928,23 @@ async function runInitYes(ctx, args = ["--yes"]) {
|
|
|
15341
15928
|
}
|
|
15342
15929
|
var init_init2 = () => {};
|
|
15343
15930
|
|
|
15344
|
-
// packages/cli/src/app-opentui/
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
|
|
15348
|
-
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
}
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
}
|
|
15355
|
-
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
}
|
|
15362
|
-
return;
|
|
15363
|
-
}
|
|
15364
|
-
function textAttributesFromCell(cell) {
|
|
15365
|
-
let attributes = TextAttributes.NONE;
|
|
15366
|
-
if (cell.isBold())
|
|
15367
|
-
attributes |= TextAttributes.BOLD;
|
|
15368
|
-
if (cell.isDim())
|
|
15369
|
-
attributes |= TextAttributes.DIM;
|
|
15370
|
-
if (cell.isItalic())
|
|
15371
|
-
attributes |= TextAttributes.ITALIC;
|
|
15372
|
-
if (cell.isUnderline())
|
|
15373
|
-
attributes |= TextAttributes.UNDERLINE;
|
|
15374
|
-
if (cell.isBlink())
|
|
15375
|
-
attributes |= TextAttributes.BLINK;
|
|
15376
|
-
if (cell.isInverse())
|
|
15377
|
-
attributes |= TextAttributes.INVERSE;
|
|
15378
|
-
if (cell.isInvisible())
|
|
15379
|
-
attributes |= TextAttributes.HIDDEN;
|
|
15380
|
-
if (cell.isStrikethrough())
|
|
15381
|
-
attributes |= TextAttributes.STRIKETHROUGH;
|
|
15382
|
-
return attributes;
|
|
15383
|
-
}
|
|
15384
|
-
function sameRgba(a, b) {
|
|
15385
|
-
if (!a && !b)
|
|
15386
|
-
return true;
|
|
15387
|
-
return Boolean(a && b && a.equals(b));
|
|
15388
|
-
}
|
|
15389
|
-
function sameStyle(a, b) {
|
|
15390
|
-
return sameRgba(a.fg, b.fg) && sameRgba(a.bg, b.bg) && (a.attributes ?? 0) === (b.attributes ?? 0);
|
|
15391
|
-
}
|
|
15392
|
-
function styleFromCell(cell) {
|
|
15393
|
-
return {
|
|
15394
|
-
fg: rgbaFromXtermColor(cell.getFgColorMode(), cell.getFgColor()),
|
|
15395
|
-
bg: rgbaFromXtermColor(cell.getBgColorMode(), cell.getBgColor()),
|
|
15396
|
-
attributes: textAttributesFromCell(cell)
|
|
15397
|
-
};
|
|
15398
|
-
}
|
|
15399
|
-
function lineToStyledText(line, cols) {
|
|
15400
|
-
if (!line)
|
|
15401
|
-
return new StyledText([{ __isChunk: true, text: "" }]);
|
|
15402
|
-
const chunks = [];
|
|
15403
|
-
let run = "";
|
|
15404
|
-
let runStyle = null;
|
|
15405
|
-
const flush = () => {
|
|
15406
|
-
if (!run)
|
|
15407
|
-
return;
|
|
15408
|
-
chunks.push({
|
|
15409
|
-
__isChunk: true,
|
|
15410
|
-
text: run,
|
|
15411
|
-
...runStyle?.fg ? { fg: runStyle.fg } : {},
|
|
15412
|
-
...runStyle?.bg ? { bg: runStyle.bg } : {},
|
|
15413
|
-
...(runStyle?.attributes ?? 0) !== 0 ? { attributes: runStyle.attributes } : {}
|
|
15414
|
-
});
|
|
15415
|
-
run = "";
|
|
15416
|
-
};
|
|
15417
|
-
for (let index = 0;index < cols; index += 1) {
|
|
15418
|
-
const cell = line.getCell(index);
|
|
15419
|
-
if (!cell) {
|
|
15420
|
-
if (runStyle !== null)
|
|
15421
|
-
flush();
|
|
15422
|
-
runStyle = null;
|
|
15423
|
-
run += " ";
|
|
15424
|
-
continue;
|
|
15425
|
-
}
|
|
15426
|
-
if (cell.getWidth() === 0)
|
|
15427
|
-
continue;
|
|
15428
|
-
const style = styleFromCell(cell);
|
|
15429
|
-
if (!runStyle || !sameStyle(runStyle, style)) {
|
|
15430
|
-
flush();
|
|
15431
|
-
runStyle = style;
|
|
15432
|
-
}
|
|
15433
|
-
run += cell.getChars() || " ";
|
|
15434
|
-
}
|
|
15435
|
-
flush();
|
|
15436
|
-
return new StyledText(chunks.length > 0 ? chunks : [{ __isChunk: true, text: "" }]);
|
|
15437
|
-
}
|
|
15438
|
-
function childCommandPrefix2() {
|
|
15439
|
-
const execName = basename4(process.execPath).toLowerCase();
|
|
15440
|
-
const currentEntry = process.argv[1];
|
|
15441
|
-
if (execName === "bun" || execName === "bun.exe") {
|
|
15442
|
-
return currentEntry ? [process.execPath, currentEntry, "__opentui-pi-host"] : [process.execPath, fallbackChildScriptPath];
|
|
15443
|
-
}
|
|
15444
|
-
return [process.execPath, "__opentui-pi-host"];
|
|
15445
|
-
}
|
|
15446
|
-
function withEnv2(base) {
|
|
15447
|
-
const env = {};
|
|
15448
|
-
for (const [key, value] of Object.entries(base ?? process.env)) {
|
|
15449
|
-
if (key === "RIG_PLAIN" || key === "RIG_CLI_PLAIN_HELP" || key === "NO_COLOR")
|
|
15450
|
-
continue;
|
|
15451
|
-
if (typeof value === "string")
|
|
15452
|
-
env[key] = value;
|
|
15453
|
-
}
|
|
15454
|
-
return {
|
|
15455
|
-
...env,
|
|
15456
|
-
TERM: "xterm-256color",
|
|
15457
|
-
COLORTERM: "truecolor",
|
|
15458
|
-
FORCE_COLOR: env.FORCE_COLOR ?? "1",
|
|
15459
|
-
RIG_OPENTUI_PI_HOST: "1"
|
|
15460
|
-
};
|
|
15461
|
-
}
|
|
15462
|
-
function getActivePiHost() {
|
|
15463
|
-
return activeHost2 && !activeHost2.disposed ? activeHost2 : null;
|
|
15464
|
-
}
|
|
15465
|
-
async function startPiPtyHost(options) {
|
|
15466
|
-
activeHost2?.dispose("replace");
|
|
15467
|
-
const host = new PiPtyHost(options);
|
|
15468
|
-
activeHost2 = host;
|
|
15469
|
-
await host.start();
|
|
15470
|
-
return host;
|
|
15471
|
-
}
|
|
15472
|
-
function stopActivePiHost(reason = "detach") {
|
|
15473
|
-
activeHost2?.dispose(reason);
|
|
15474
|
-
activeHost2 = null;
|
|
15475
|
-
}
|
|
15476
|
-
|
|
15477
|
-
class PiPtyHost {
|
|
15478
|
-
runId;
|
|
15479
|
-
projectRoot;
|
|
15480
|
-
onSnapshot;
|
|
15481
|
-
onExit;
|
|
15482
|
-
onError;
|
|
15483
|
-
terminal;
|
|
15484
|
-
disposables = [];
|
|
15485
|
-
decoder = new TextDecoder("utf-8");
|
|
15486
|
-
proc = null;
|
|
15487
|
-
pty = null;
|
|
15488
|
-
status = "starting";
|
|
15489
|
-
cols;
|
|
15490
|
-
rows;
|
|
15491
|
-
message = "starting bundled Pi";
|
|
15492
|
-
lastResizeError = null;
|
|
15493
|
-
exitCode;
|
|
15494
|
-
signal;
|
|
15495
|
-
notifyTimer = null;
|
|
15496
|
-
lastStreamKey = "";
|
|
15497
|
-
_disposed = false;
|
|
15498
|
-
constructor(options) {
|
|
15499
|
-
this.runId = options.runId;
|
|
15500
|
-
this.projectRoot = options.projectRoot;
|
|
15501
|
-
this.cols = clampCols2(options.cols);
|
|
15502
|
-
this.rows = clampRows2(options.rows);
|
|
15503
|
-
this.onSnapshot = options.onSnapshot;
|
|
15504
|
-
this.onExit = options.onExit;
|
|
15505
|
-
this.onError = options.onError;
|
|
15506
|
-
this.terminal = new XtermTerminal2({
|
|
15507
|
-
allowProposedApi: true,
|
|
15508
|
-
cols: this.cols,
|
|
15509
|
-
rows: this.rows,
|
|
15510
|
-
scrollback: 1000
|
|
15511
|
-
});
|
|
15512
|
-
this.registerTerminalResponders();
|
|
15513
|
-
this.disposables.push(this.terminal.onWriteParsed(() => {
|
|
15514
|
-
if (this._disposed)
|
|
15515
|
-
return;
|
|
15516
|
-
const snapshot = this.createSnapshot();
|
|
15517
|
-
const key = snapshot.lines.join(`
|
|
15518
|
-
`);
|
|
15519
|
-
if (key === this.lastStreamKey)
|
|
15520
|
-
return;
|
|
15521
|
-
this.lastStreamKey = key;
|
|
15522
|
-
this.onSnapshot?.(snapshot);
|
|
15523
|
-
}));
|
|
15524
|
-
}
|
|
15525
|
-
get disposed() {
|
|
15526
|
-
return this._disposed;
|
|
15527
|
-
}
|
|
15528
|
-
get snapshot() {
|
|
15529
|
-
return this.createSnapshot();
|
|
15530
|
-
}
|
|
15531
|
-
async start() {
|
|
15532
|
-
if (this._disposed)
|
|
15533
|
-
throw new Error("Pi PTY host is disposed.");
|
|
15534
|
-
if (typeof Bun.Terminal !== "function") {
|
|
15535
|
-
throw new Error("Bun native PTY is unavailable in this runtime. Pi host requires Bun.Terminal.");
|
|
15536
|
-
}
|
|
15537
|
-
const spawnOptions = {
|
|
15538
|
-
cwd: this.projectRoot,
|
|
15539
|
-
env: withEnv2(process.env),
|
|
15540
|
-
terminal: {
|
|
15541
|
-
cols: this.cols,
|
|
15542
|
-
rows: this.rows,
|
|
15543
|
-
name: "xterm-256color",
|
|
15544
|
-
data: (_terminal, data) => this.handlePtyData(data)
|
|
15545
|
-
}
|
|
15546
|
-
};
|
|
15547
|
-
const proc = Bun.spawn([
|
|
15548
|
-
...childCommandPrefix2(),
|
|
15549
|
-
"--run-id",
|
|
15550
|
-
this.runId,
|
|
15551
|
-
"--project-root",
|
|
15552
|
-
this.projectRoot
|
|
15553
|
-
], spawnOptions);
|
|
15554
|
-
if (!proc.terminal)
|
|
15555
|
-
throw new Error("Bun did not attach a terminal to the bundled Pi child process.");
|
|
15556
|
-
this.proc = proc;
|
|
15557
|
-
this.pty = proc.terminal;
|
|
15558
|
-
this.status = "running";
|
|
15559
|
-
this.message = "bundled Pi running inside this app";
|
|
15560
|
-
this.emitSnapshotSoon(0);
|
|
15561
|
-
proc.exited.then((exitCode) => {
|
|
15562
|
-
if (this._disposed)
|
|
15563
|
-
return;
|
|
15564
|
-
this.status = exitCode === 0 ? "exited" : "failed";
|
|
15565
|
-
this.exitCode = exitCode;
|
|
15566
|
-
this.signal = null;
|
|
15567
|
-
this.message = exitCode === 0 ? "bundled Pi exited" : `bundled Pi exited with code ${exitCode}`;
|
|
15568
|
-
const snapshot = this.createSnapshot();
|
|
15569
|
-
this.onSnapshot?.(snapshot);
|
|
15570
|
-
this.onExit?.(snapshot);
|
|
15571
|
-
if (activeHost2 === this)
|
|
15572
|
-
activeHost2 = null;
|
|
15573
|
-
this.dispose("exit", { kill: false, notify: false });
|
|
15574
|
-
}).catch((error) => {
|
|
15575
|
-
if (this._disposed)
|
|
15576
|
-
return;
|
|
15577
|
-
this.status = "failed";
|
|
15578
|
-
this.message = error instanceof Error ? error.message : String(error);
|
|
15579
|
-
const snapshot = this.createSnapshot();
|
|
15580
|
-
this.onSnapshot?.(snapshot);
|
|
15581
|
-
this.onError?.(error, snapshot);
|
|
15582
|
-
if (activeHost2 === this)
|
|
15583
|
-
activeHost2 = null;
|
|
15584
|
-
this.dispose("error", { kill: false, notify: false });
|
|
15585
|
-
});
|
|
15586
|
-
}
|
|
15587
|
-
write(data) {
|
|
15588
|
-
if (this._disposed || !this.pty)
|
|
15589
|
-
return;
|
|
15590
|
-
try {
|
|
15591
|
-
this.pty.write(data);
|
|
15592
|
-
} catch (error) {
|
|
15593
|
-
this.status = "failed";
|
|
15594
|
-
this.message = error instanceof Error ? error.message : String(error);
|
|
15595
|
-
const snapshot = this.createSnapshot();
|
|
15596
|
-
this.onSnapshot?.(snapshot);
|
|
15597
|
-
this.onError?.(error, snapshot);
|
|
15598
|
-
}
|
|
15599
|
-
}
|
|
15600
|
-
resize(cols, rows) {
|
|
15601
|
-
const nextCols = clampCols2(cols);
|
|
15602
|
-
const nextRows = clampRows2(rows);
|
|
15603
|
-
if (nextCols === this.cols && nextRows === this.rows)
|
|
15604
|
-
return;
|
|
15605
|
-
this.cols = nextCols;
|
|
15606
|
-
this.rows = nextRows;
|
|
15607
|
-
this.terminal.resize(nextCols, nextRows);
|
|
15608
|
-
try {
|
|
15609
|
-
this.pty?.resize(nextCols, nextRows);
|
|
15610
|
-
this.lastResizeError = null;
|
|
15611
|
-
} catch (error) {
|
|
15612
|
-
this.lastResizeError = error instanceof Error ? error.message : String(error);
|
|
15613
|
-
}
|
|
15614
|
-
this.emitSnapshotSoon(0);
|
|
15615
|
-
}
|
|
15616
|
-
detach() {
|
|
15617
|
-
this.dispose("detach");
|
|
15618
|
-
return this.createSnapshot("detached from bundled Pi");
|
|
15619
|
-
}
|
|
15620
|
-
dispose(reason = "dispose", options = {}) {
|
|
15621
|
-
if (this._disposed)
|
|
15622
|
-
return;
|
|
15623
|
-
this._disposed = true;
|
|
15624
|
-
if (this.notifyTimer)
|
|
15625
|
-
clearTimeout(this.notifyTimer);
|
|
15626
|
-
this.notifyTimer = null;
|
|
15627
|
-
for (const disposable of this.disposables.splice(0)) {
|
|
15628
|
-
try {
|
|
15629
|
-
disposable.dispose();
|
|
15630
|
-
} catch {}
|
|
15631
|
-
}
|
|
15632
|
-
if (options.kill !== false) {
|
|
15633
|
-
try {
|
|
15634
|
-
this.proc?.kill("SIGTERM");
|
|
15635
|
-
} catch {}
|
|
15636
|
-
}
|
|
15637
|
-
try {
|
|
15638
|
-
this.pty?.close();
|
|
15639
|
-
} catch {}
|
|
15640
|
-
try {
|
|
15641
|
-
this.terminal.dispose();
|
|
15642
|
-
} catch {}
|
|
15643
|
-
if (activeHost2 === this)
|
|
15644
|
-
activeHost2 = null;
|
|
15645
|
-
if (options.notify) {
|
|
15646
|
-
this.message = reason;
|
|
15647
|
-
this.onSnapshot?.(this.createSnapshot(reason));
|
|
15648
|
-
}
|
|
15649
|
-
}
|
|
15650
|
-
handlePtyData(data) {
|
|
15651
|
-
if (this._disposed)
|
|
15652
|
-
return;
|
|
15653
|
-
const text2 = this.decoder.decode(data, { stream: true });
|
|
15654
|
-
this.respondToRawTerminalQueries(text2);
|
|
15655
|
-
this.terminal.write(data);
|
|
15656
|
-
}
|
|
15657
|
-
emitSnapshotSoon(delayMs = SNAPSHOT_DELAY_MS2) {
|
|
15658
|
-
if (this._disposed || this.notifyTimer)
|
|
15659
|
-
return;
|
|
15660
|
-
this.notifyTimer = setTimeout(() => {
|
|
15661
|
-
this.notifyTimer = null;
|
|
15662
|
-
if (this._disposed)
|
|
15663
|
-
return;
|
|
15664
|
-
this.onSnapshot?.(this.createSnapshot());
|
|
15665
|
-
}, delayMs);
|
|
15666
|
-
}
|
|
15667
|
-
createSnapshot(message2 = this.message) {
|
|
15668
|
-
const buffer = this.terminal.buffer.active;
|
|
15669
|
-
const end = buffer.length;
|
|
15670
|
-
const start = Math.max(0, end - MAX_SNAPSHOT_LINES2);
|
|
15671
|
-
const styledStart = Math.max(start, end - this.rows - STYLED_SNAPSHOT_MARGIN);
|
|
15672
|
-
const lines = [];
|
|
15673
|
-
const styledLines = [];
|
|
15674
|
-
for (let row = start;row < end; row += 1) {
|
|
15675
|
-
const line = buffer.getLine(row);
|
|
15676
|
-
lines.push((line?.translateToString(false) ?? "").slice(0, this.cols));
|
|
15677
|
-
if (row >= styledStart)
|
|
15678
|
-
styledLines[lines.length - 1] = lineToStyledText(line, this.cols);
|
|
15679
|
-
}
|
|
15680
|
-
while (lines.length < this.rows) {
|
|
15681
|
-
lines.push("");
|
|
15682
|
-
styledLines[lines.length - 1] = new StyledText([{ __isChunk: true, text: "" }]);
|
|
15683
|
-
}
|
|
15684
|
-
const resolvedMessage = this.lastResizeError ? `resize degraded: ${this.lastResizeError}` : message2;
|
|
15685
|
-
return {
|
|
15686
|
-
runId: this.runId,
|
|
15687
|
-
status: this.status,
|
|
15688
|
-
cols: this.cols,
|
|
15689
|
-
rows: this.rows,
|
|
15690
|
-
lines,
|
|
15691
|
-
styledLines,
|
|
15692
|
-
message: resolvedMessage,
|
|
15693
|
-
...this.lastResizeError ? { resizeError: this.lastResizeError } : {},
|
|
15694
|
-
...this.exitCode !== undefined ? { exitCode: this.exitCode } : {},
|
|
15695
|
-
...this.signal !== undefined ? { signal: this.signal } : {}
|
|
15696
|
-
};
|
|
15697
|
-
}
|
|
15698
|
-
registerTerminalResponders() {
|
|
15699
|
-
this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "c" }, (params) => {
|
|
15700
|
-
if (params.length === 0 || params[0] === 0)
|
|
15701
|
-
this.write("\x1B[?62;22c");
|
|
15702
|
-
return false;
|
|
15703
|
-
}));
|
|
15704
|
-
this.disposables.push(this.terminal.parser.registerCsiHandler({ prefix: ">", final: "c" }, (params) => {
|
|
15705
|
-
if (params.length === 0 || params[0] === 0)
|
|
15706
|
-
this.write("\x1B[>0;0;0c");
|
|
15707
|
-
return false;
|
|
15708
|
-
}));
|
|
15709
|
-
this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "n" }, (params) => {
|
|
15710
|
-
if (params[0] === 5) {
|
|
15711
|
-
this.write("\x1B[0n");
|
|
15712
|
-
} else if (params[0] === 6) {
|
|
15713
|
-
const row = this.terminal.buffer.active.cursorY + 1;
|
|
15714
|
-
const col = this.terminal.buffer.active.cursorX + 1;
|
|
15715
|
-
this.write(`\x1B[${row};${col}R`);
|
|
15716
|
-
}
|
|
15717
|
-
return false;
|
|
15718
|
-
}));
|
|
15719
|
-
}
|
|
15720
|
-
respondToRawTerminalQueries(text2) {
|
|
15721
|
-
if (!text2)
|
|
15722
|
-
return;
|
|
15723
|
-
const decrqm = /\x1b\[\?(\d+)\$p/g;
|
|
15724
|
-
let match;
|
|
15725
|
-
while ((match = decrqm.exec(text2)) !== null) {
|
|
15726
|
-
this.write(`\x1B[?${match[1]};2$y`);
|
|
15727
|
-
}
|
|
15728
|
-
}
|
|
15729
|
-
}
|
|
15730
|
-
var MIN_COLS2 = 40, MIN_ROWS2 = 12, MAX_ROWS2 = 300, MAX_SNAPSHOT_LINES2 = 360, STYLED_SNAPSHOT_MARGIN = 6, SNAPSHOT_DELAY_MS2 = 120, fallbackChildScriptPath, activeHost2 = null, XTERM_COLOR_MODE_INDEXED_16 = 16777216, XTERM_COLOR_MODE_INDEXED_256 = 33554432, XTERM_COLOR_MODE_RGB = 50331648;
|
|
15731
|
-
var init_pi_pty_host = __esm(() => {
|
|
15732
|
-
fallbackChildScriptPath = fileURLToPath2(new URL("./pi-host-child.ts", import.meta.url));
|
|
15733
|
-
});
|
|
15734
|
-
|
|
15735
|
-
// packages/cli/src/app-opentui/adapters/inspect.ts
|
|
15736
|
-
var exports_inspect = {};
|
|
15737
|
-
__export(exports_inspect, {
|
|
15738
|
-
loadInspectRuns: () => loadInspectRuns,
|
|
15739
|
-
loadInspect: () => loadInspect,
|
|
15740
|
-
INSPECT_VIEWS: () => INSPECT_VIEWS
|
|
15741
|
-
});
|
|
15742
|
-
import { execFile } from "child_process";
|
|
15743
|
-
import { existsSync as existsSync21, readFileSync as readFileSync14, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
15744
|
-
import { resolve as resolve28 } from "path";
|
|
15745
|
-
import { promisify } from "util";
|
|
15746
|
-
import { resolveTaskArtifactDirs as resolveTaskArtifactDirs3 } from "@rig/runtime/control-plane/authority-files";
|
|
15747
|
-
import { readTaskArtifactPreview as readTaskArtifactPreview2 } from "@rig/runtime/control-plane/native/workspace-ops";
|
|
15748
|
-
import { resolveHarnessPaths as resolveHarnessPaths3, resolveMonorepoRoot as resolveMonorepoRoot3, runCapture as runCapture4 } from "@rig/runtime/control-plane/native/utils";
|
|
15749
|
-
function isFailureEntry(entry) {
|
|
15750
|
-
const status = `${entry.status ?? entry.level ?? entry.type ?? ""}`.toLowerCase();
|
|
15751
|
-
return status.includes("fail") || status.includes("error");
|
|
15931
|
+
// packages/cli/src/app-opentui/adapters/inspect.ts
|
|
15932
|
+
var exports_inspect = {};
|
|
15933
|
+
__export(exports_inspect, {
|
|
15934
|
+
loadInspectRuns: () => loadInspectRuns,
|
|
15935
|
+
loadInspect: () => loadInspect,
|
|
15936
|
+
INSPECT_VIEWS: () => INSPECT_VIEWS
|
|
15937
|
+
});
|
|
15938
|
+
import { execFile } from "child_process";
|
|
15939
|
+
import { existsSync as existsSync21, readFileSync as readFileSync14, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
15940
|
+
import { resolve as resolve28 } from "path";
|
|
15941
|
+
import { promisify } from "util";
|
|
15942
|
+
import { resolveTaskArtifactDirs as resolveTaskArtifactDirs3 } from "@rig/runtime/control-plane/authority-files";
|
|
15943
|
+
import { readTaskArtifactPreview as readTaskArtifactPreview2 } from "@rig/runtime/control-plane/native/workspace-ops";
|
|
15944
|
+
import { resolveHarnessPaths as resolveHarnessPaths3, resolveMonorepoRoot as resolveMonorepoRoot3, runCapture as runCapture4 } from "@rig/runtime/control-plane/native/utils";
|
|
15945
|
+
function isFailureEntry(entry) {
|
|
15946
|
+
const status = `${entry.status ?? entry.level ?? entry.type ?? ""}`.toLowerCase();
|
|
15947
|
+
return status.includes("fail") || status.includes("error");
|
|
15752
15948
|
}
|
|
15753
15949
|
async function gitDiff(projectRoot) {
|
|
15754
15950
|
try {
|
|
@@ -15954,14 +16150,6 @@ function recordStep(ctx, runId, label, emitLabel) {
|
|
|
15954
16150
|
});
|
|
15955
16151
|
emitProgress(ctx, emitLabel, label);
|
|
15956
16152
|
}
|
|
15957
|
-
function settleSteps(ctx, runId) {
|
|
15958
|
-
const now = Date.now();
|
|
15959
|
-
const previous = currentAttachState(ctx, runId);
|
|
15960
|
-
if (!previous?.steps)
|
|
15961
|
-
return;
|
|
15962
|
-
const steps = previous.steps.map((step) => step.status === "running" ? { ...step, status: "done", endedAtMs: step.endedAtMs ?? now } : step);
|
|
15963
|
-
patchData(ctx, { piAttach: { ...previous, steps } });
|
|
15964
|
-
}
|
|
15965
16153
|
async function preparePiAttachHandoff(ctx, runId) {
|
|
15966
16154
|
const cleanRunId = runId.trim();
|
|
15967
16155
|
const label = `Preparing Pi ${cleanRunId.slice(0, 8)}`;
|
|
@@ -16009,85 +16197,41 @@ async function attachRunWithBundledPi(ctx, runId) {
|
|
|
16009
16197
|
throw error;
|
|
16010
16198
|
}
|
|
16011
16199
|
emitStarted(ctx, label, { piAttach: { runId: cleanRunId, status: "entering-pi" } });
|
|
16012
|
-
patchData(ctx, { piAttach: { runId: cleanRunId, status: "entering-pi", message: "
|
|
16200
|
+
patchData(ctx, { piAttach: { runId: cleanRunId, status: "entering-pi", message: "handing the terminal to worker Pi\u2026" } });
|
|
16201
|
+
const projectRoot = projectRootOf(ctx);
|
|
16202
|
+
const outputMode = ctx.rig?.outputMode ?? "text";
|
|
16203
|
+
await releaseRendererForExternalTui(ctx);
|
|
16204
|
+
let outcome = null;
|
|
16205
|
+
let attachError = null;
|
|
16013
16206
|
try {
|
|
16014
|
-
|
|
16015
|
-
await
|
|
16016
|
-
patchData(ctx, { lastRefreshError: normalizeAppError(error).message });
|
|
16017
|
-
return null;
|
|
16018
|
-
});
|
|
16019
|
-
recordStep(ctx, cleanRunId, "spawning Bun PTY host for bundled Pi", label);
|
|
16020
|
-
const projectRoot = projectRootOf(ctx);
|
|
16021
|
-
const cols = typeof process.stdout.columns === "number" ? process.stdout.columns : 100;
|
|
16022
|
-
const rows = Math.max(1, (typeof process.stdout.rows === "number" ? process.stdout.rows : 35) - 1);
|
|
16023
|
-
const patchTerminal = (snapshot) => {
|
|
16024
|
-
const previousSteps = currentAttachState(ctx, cleanRunId)?.steps;
|
|
16025
|
-
const failed = snapshot.status === "failed";
|
|
16026
|
-
const reason = failed ? snapshot.message ?? `bundled Pi exited with code ${snapshot.exitCode ?? "unknown"}` : undefined;
|
|
16027
|
-
patchData(ctx, {
|
|
16028
|
-
piTerminal: snapshot,
|
|
16029
|
-
piAttach: {
|
|
16030
|
-
runId: cleanRunId,
|
|
16031
|
-
status: failed ? "failed" : snapshot.status === "exited" ? "returned" : "entering-pi",
|
|
16032
|
-
message: snapshot.message ?? "bundled Pi running",
|
|
16033
|
-
result: { runId: cleanRunId, status: snapshot.status, exitCode: snapshot.exitCode },
|
|
16034
|
-
...previousSteps ? { steps: previousSteps } : {},
|
|
16035
|
-
...reason ? { failureReason: reason } : {}
|
|
16036
|
-
}
|
|
16037
|
-
});
|
|
16038
|
-
};
|
|
16039
|
-
recordStep(ctx, cleanRunId, "starting bundled Pi", label);
|
|
16040
|
-
await startPiPtyHost({
|
|
16041
|
-
runId: cleanRunId,
|
|
16042
|
-
projectRoot,
|
|
16043
|
-
cols,
|
|
16044
|
-
rows,
|
|
16045
|
-
onSnapshot: (snapshot) => {
|
|
16046
|
-
if (snapshot.status === "running" && snapshot.lines.some((entry) => entry.trim().length > 0)) {
|
|
16047
|
-
settleSteps(ctx, cleanRunId);
|
|
16048
|
-
}
|
|
16049
|
-
patchTerminal(snapshot);
|
|
16050
|
-
},
|
|
16051
|
-
onExit: (snapshot) => {
|
|
16052
|
-
patchTerminal(snapshot);
|
|
16053
|
-
if (snapshot.status === "failed") {
|
|
16054
|
-
Promise.resolve().then(() => (init_inspect2(), exports_inspect)).then(({ loadInspect: loadInspect2 }) => loadInspect2(ctx, cleanRunId)).catch(() => null);
|
|
16055
|
-
emitFailed(ctx, label, new Error(snapshot.message ?? `bundled Pi exited with code ${snapshot.exitCode ?? "unknown"}`), { runId: cleanRunId, result: { status: snapshot.status, exitCode: snapshot.exitCode } });
|
|
16056
|
-
return;
|
|
16057
|
-
}
|
|
16058
|
-
emitCompleted(ctx, label, { runId: cleanRunId, result: { status: snapshot.status, exitCode: snapshot.exitCode } });
|
|
16059
|
-
ctx.emit({ type: "scene.change", scene: "fleet", intent: { scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } } });
|
|
16060
|
-
refreshFleet(ctx).catch((error) => emitFailed(ctx, "Refresh runs", error));
|
|
16061
|
-
},
|
|
16062
|
-
onError: (error, snapshot) => {
|
|
16063
|
-
patchTerminal(snapshot);
|
|
16064
|
-
emitFailed(ctx, label, error, { runId: cleanRunId });
|
|
16065
|
-
}
|
|
16066
|
-
});
|
|
16067
|
-
const record = {
|
|
16068
|
-
runId: cleanRunId,
|
|
16069
|
-
status: "running",
|
|
16070
|
-
rendered: "bundled Pi embedded via Bun.Terminal + @xterm/headless"
|
|
16071
|
-
};
|
|
16072
|
-
emitProgress(ctx, label, "bundled Pi is running", { piAttach: { runId: cleanRunId, status: "entering-pi", message: "bundled Pi running", result: record } });
|
|
16073
|
-
return record;
|
|
16207
|
+
const { attachRunBundledPiFrontend: attachRunBundledPiFrontend2 } = await Promise.resolve().then(() => (init__pi_frontend(), exports__pi_frontend));
|
|
16208
|
+
outcome = await attachRunBundledPiFrontend2({ projectRoot, outputMode }, { runId: cleanRunId, returnOnQuit: true });
|
|
16074
16209
|
} catch (error) {
|
|
16075
|
-
|
|
16210
|
+
attachError = error;
|
|
16211
|
+
} finally {
|
|
16212
|
+
await resumeRendererAfterExternalTui(ctx);
|
|
16213
|
+
}
|
|
16214
|
+
if (attachError) {
|
|
16215
|
+
const reason = normalizeAppError(attachError).message;
|
|
16076
16216
|
patchData(ctx, {
|
|
16077
|
-
|
|
16078
|
-
|
|
16079
|
-
status: "failed",
|
|
16080
|
-
message: reason,
|
|
16081
|
-
failureReason: reason,
|
|
16082
|
-
...currentAttachState(ctx, cleanRunId)?.steps ? { steps: currentAttachState(ctx, cleanRunId).steps } : {}
|
|
16083
|
-
}
|
|
16217
|
+
piTerminal: undefined,
|
|
16218
|
+
piAttach: { runId: cleanRunId, status: "failed", message: reason, failureReason: reason }
|
|
16084
16219
|
});
|
|
16085
|
-
|
|
16086
|
-
|
|
16220
|
+
Promise.resolve().then(() => (init_inspect2(), exports_inspect)).then(({ loadInspect: loadInspect2 }) => loadInspect2(ctx, cleanRunId)).catch(() => null);
|
|
16221
|
+
emitFailed(ctx, label, attachError, { runId: cleanRunId });
|
|
16222
|
+
throw attachError;
|
|
16087
16223
|
}
|
|
16224
|
+
const detached = outcome?.detached === true;
|
|
16225
|
+
patchData(ctx, {
|
|
16226
|
+
piTerminal: undefined,
|
|
16227
|
+
piAttach: { runId: cleanRunId, status: "returned", message: detached ? "detached from worker Pi" : "returned from worker Pi" }
|
|
16228
|
+
});
|
|
16229
|
+
emitCompleted(ctx, label, { runId: cleanRunId, result: { runId: cleanRunId, detached } });
|
|
16230
|
+
ctx.emit({ type: "scene.change", scene: "fleet", intent: { scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } } });
|
|
16231
|
+
refreshFleet(ctx).catch((error) => emitFailed(ctx, "Refresh runs", error));
|
|
16232
|
+
return { runId: cleanRunId, status: "returned", detached };
|
|
16088
16233
|
}
|
|
16089
16234
|
var init_pi_attach = __esm(() => {
|
|
16090
|
-
init_pi_pty_host();
|
|
16091
16235
|
init_fleet();
|
|
16092
16236
|
});
|
|
16093
16237
|
|
|
@@ -16684,6 +16828,7 @@ var LOG_PAGE = 100, TIMELINE_PAGE = 200;
|
|
|
16684
16828
|
var init_run_detail = () => {};
|
|
16685
16829
|
|
|
16686
16830
|
// packages/cli/src/app-opentui/adapters/server.ts
|
|
16831
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
16687
16832
|
function withTimeout(promise, ms, label) {
|
|
16688
16833
|
return new Promise((resolve29, reject) => {
|
|
16689
16834
|
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
@@ -16720,11 +16865,128 @@ function startLocalRequested(ctx) {
|
|
|
16720
16865
|
const action = intent.action;
|
|
16721
16866
|
return action?.payload?.startLocal === true;
|
|
16722
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
|
+
}
|
|
16723
16984
|
async function startLocalServerFromApp(ctx) {
|
|
16724
16985
|
const label = "Starting local server";
|
|
16725
16986
|
emitStarted(ctx, label);
|
|
16726
16987
|
patchData(ctx, {
|
|
16727
16988
|
lastIntent: undefined,
|
|
16989
|
+
remoteProjectLink: undefined,
|
|
16728
16990
|
server: { label: "starting local server", reachable: false, error: "spawning local rig-server (detached)\u2026" }
|
|
16729
16991
|
});
|
|
16730
16992
|
try {
|
|
@@ -16749,32 +17011,61 @@ async function startLocalServerFromApp(ctx) {
|
|
|
16749
17011
|
reachable: false,
|
|
16750
17012
|
error: error instanceof Error ? error.message : String(error)
|
|
16751
17013
|
};
|
|
16752
|
-
patchData(ctx, { server: state, lastRefreshError: state.error });
|
|
17014
|
+
patchData(ctx, { server: state, remoteProjectLink: undefined, lastRefreshError: state.error });
|
|
16753
17015
|
patchFooter(ctx, { server: "unavailable" });
|
|
16754
|
-
emitCompleted(ctx, label, {
|
|
17016
|
+
emitCompleted(ctx, label, { serverLabel: state.label, reachable: false, error: state.error });
|
|
16755
17017
|
return state;
|
|
16756
17018
|
}
|
|
16757
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
|
+
}
|
|
16758
17047
|
async function refreshServerStatus(ctx) {
|
|
16759
17048
|
if (startLocalRequested(ctx)) {
|
|
16760
17049
|
return startLocalServerFromApp(ctx);
|
|
16761
17050
|
}
|
|
16762
17051
|
const label = "Checking server";
|
|
16763
17052
|
emitStarted(ctx, label);
|
|
16764
|
-
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 });
|
|
16765
17054
|
const started = Date.now();
|
|
16766
17055
|
try {
|
|
16767
|
-
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));
|
|
16768
17057
|
const projectRoot = projectRootOf(ctx);
|
|
17058
|
+
const aliases = await serverAliases(projectRoot);
|
|
16769
17059
|
emitProgress(ctx, label, "resolving selected server");
|
|
16770
17060
|
const [connectionLabel, server] = await Promise.all([
|
|
16771
17061
|
resolveServerConnectionLabel2(projectRoot),
|
|
16772
17062
|
withTimeout(ensureServerForCli2(projectRoot), 5000, "server connection")
|
|
16773
17063
|
]);
|
|
16774
17064
|
emitProgress(ctx, label, "requesting server status", { baseUrl: server.baseUrl, kind: server.connectionKind });
|
|
16775
|
-
const [status, auth] = await Promise.all([
|
|
17065
|
+
const [status, auth, remoteProjectLink] = await Promise.all([
|
|
16776
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) })),
|
|
16777
|
-
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)
|
|
16778
17069
|
]);
|
|
16779
17070
|
const state = {
|
|
16780
17071
|
label: connectionLabel,
|
|
@@ -16783,22 +17074,25 @@ async function refreshServerStatus(ctx) {
|
|
|
16783
17074
|
reachable: true,
|
|
16784
17075
|
latencyMs: Date.now() - started,
|
|
16785
17076
|
status: status && typeof status === "object" && !Array.isArray(status) ? status : {},
|
|
16786
|
-
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 } : {}
|
|
16787
17080
|
};
|
|
16788
|
-
patchData(ctx, { server: state });
|
|
17081
|
+
patchData(ctx, { server: state, remoteProjectLink: state.remoteProjectLink });
|
|
16789
17082
|
patchFooter(ctx, { server: connectionLabel, latency: `${state.latencyMs}ms` });
|
|
16790
|
-
emitCompleted(ctx, label, {
|
|
17083
|
+
emitCompleted(ctx, label, { serverLabel: connectionLabel, latencyMs: state.latencyMs });
|
|
16791
17084
|
return state;
|
|
16792
17085
|
} catch (error) {
|
|
16793
17086
|
const state = {
|
|
16794
17087
|
label: "server unavailable",
|
|
16795
17088
|
reachable: false,
|
|
16796
17089
|
latencyMs: Date.now() - started,
|
|
17090
|
+
aliases: await serverAliases(projectRootOf(ctx)).catch(() => []),
|
|
16797
17091
|
error: error instanceof Error ? error.message : String(error)
|
|
16798
17092
|
};
|
|
16799
|
-
patchData(ctx, { server: state });
|
|
17093
|
+
patchData(ctx, { server: state, remoteProjectLink: undefined });
|
|
16800
17094
|
patchFooter(ctx, { server: "unavailable" });
|
|
16801
|
-
emitCompleted(ctx, label, {
|
|
17095
|
+
emitCompleted(ctx, label, { serverLabel: state.label, reachable: false, error: state.error });
|
|
16802
17096
|
return state;
|
|
16803
17097
|
}
|
|
16804
17098
|
}
|
|
@@ -17378,7 +17672,7 @@ import {
|
|
|
17378
17672
|
dim as otuiDim,
|
|
17379
17673
|
fg as otuiFg,
|
|
17380
17674
|
t,
|
|
17381
|
-
TextAttributes
|
|
17675
|
+
TextAttributes
|
|
17382
17676
|
} from "@opentui/core";
|
|
17383
17677
|
function statusColor3(status) {
|
|
17384
17678
|
switch (status) {
|
|
@@ -17483,7 +17777,7 @@ var init_theme2 = __esm(() => {
|
|
|
17483
17777
|
});
|
|
17484
17778
|
|
|
17485
17779
|
// packages/cli/src/app-opentui/drone.ts
|
|
17486
|
-
import { RGBA
|
|
17780
|
+
import { RGBA, StyledText, TextAttributes as TextAttributes2 } from "@opentui/core";
|
|
17487
17781
|
function bladeForTick(tick, phase = 0) {
|
|
17488
17782
|
return BLADE_FRAMES2[(Math.floor(tick / 3) + phase) % BLADE_FRAMES2.length];
|
|
17489
17783
|
}
|
|
@@ -17492,12 +17786,12 @@ function eyeForTick(tick, phase = 0) {
|
|
|
17492
17786
|
return pulse > 0.55 ? EYE_FRAMES2[1] : pulse > 0.1 ? EYE_FRAMES2[0] : pulse > -0.45 ? EYE_FRAMES2[2] : EYE_FRAMES2[3];
|
|
17493
17787
|
}
|
|
17494
17788
|
function chunk(text2, fg2, bold2 = false, dim = false) {
|
|
17495
|
-
let attributes =
|
|
17789
|
+
let attributes = TextAttributes2.NONE;
|
|
17496
17790
|
if (bold2)
|
|
17497
|
-
attributes |=
|
|
17791
|
+
attributes |= TextAttributes2.BOLD;
|
|
17498
17792
|
if (dim)
|
|
17499
|
-
attributes |=
|
|
17500
|
-
return { __isChunk: true, text: text2, fg: fg2, ...attributes !==
|
|
17793
|
+
attributes |= TextAttributes2.DIM;
|
|
17794
|
+
return { __isChunk: true, text: text2, fg: fg2, ...attributes !== TextAttributes2.NONE ? { attributes } : {} };
|
|
17501
17795
|
}
|
|
17502
17796
|
function styledLine(text2, colorFor) {
|
|
17503
17797
|
const chunks = [];
|
|
@@ -17518,7 +17812,7 @@ function styledLine(text2, colorFor) {
|
|
|
17518
17812
|
run += char;
|
|
17519
17813
|
}
|
|
17520
17814
|
flush();
|
|
17521
|
-
return new
|
|
17815
|
+
return new StyledText(chunks.length > 0 ? chunks : [chunk("", COLOR.ink)]);
|
|
17522
17816
|
}
|
|
17523
17817
|
function droneColor(char) {
|
|
17524
17818
|
if (char === "?" || char === "o" || char === "@" || char === "\u2022")
|
|
@@ -17610,13 +17904,13 @@ var init_drone = __esm(() => {
|
|
|
17610
17904
|
BLADE_FRAMES2 = ["---", "\\\\\\", "|||", "///"];
|
|
17611
17905
|
EYE_FRAMES2 = ["o", "@", "\u2022", "."];
|
|
17612
17906
|
COLOR = {
|
|
17613
|
-
body:
|
|
17614
|
-
mini:
|
|
17615
|
-
rotor:
|
|
17616
|
-
path:
|
|
17617
|
-
eye:
|
|
17618
|
-
dim:
|
|
17619
|
-
ink:
|
|
17907
|
+
body: RGBA.fromHex(RIG_UI.lime),
|
|
17908
|
+
mini: RGBA.fromHex(RIG_UI.limeDim),
|
|
17909
|
+
rotor: RGBA.fromHex(RIG_UI.cyan),
|
|
17910
|
+
path: RGBA.fromHex(RIG_UI.cyan),
|
|
17911
|
+
eye: RGBA.fromHex(RIG_UI.ink),
|
|
17912
|
+
dim: RGBA.fromHex(RIG_UI.ink4),
|
|
17913
|
+
ink: RGBA.fromHex(RIG_UI.ink2)
|
|
17620
17914
|
};
|
|
17621
17915
|
});
|
|
17622
17916
|
|
|
@@ -17826,11 +18120,56 @@ var init_doctor3 = __esm(() => {
|
|
|
17826
18120
|
DOCTOR_ACTIONS = [
|
|
17827
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" } },
|
|
17828
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" } },
|
|
17829
|
-
{ 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" } },
|
|
17830
18124
|
{ detail: "open tasks", item: { id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Open tasks" } }, message: "open tasks" } }
|
|
17831
18125
|
];
|
|
17832
18126
|
});
|
|
17833
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
|
+
|
|
17834
18173
|
// packages/cli/src/app-opentui/fleet-stats.ts
|
|
17835
18174
|
function normalizeStatus(status) {
|
|
17836
18175
|
return status.replace(/_/g, "-").toLowerCase();
|
|
@@ -19746,13 +20085,18 @@ function overviewBody(state, family, snap, layout) {
|
|
|
19746
20085
|
function familyRecoveryRows(state, family, errorMessage2) {
|
|
19747
20086
|
const selected = Math.max(0, state.selection.index);
|
|
19748
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 });
|
|
19749
|
-
|
|
20088
|
+
const repairRemote = shouldOfferRemoteLinkRepair(state, errorMessage2);
|
|
20089
|
+
const rows = [
|
|
19750
20090
|
intro,
|
|
19751
|
-
blank()
|
|
19752
|
-
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" }),
|
|
19753
|
-
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" }),
|
|
19754
|
-
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()
|
|
19755
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;
|
|
19756
20100
|
}
|
|
19757
20101
|
function renderFamilyScene(state, layout) {
|
|
19758
20102
|
const family = typeof state.data.familyName === "string" ? state.data.familyName : "";
|
|
@@ -19761,9 +20105,16 @@ function renderFamilyScene(state, layout) {
|
|
|
19761
20105
|
const loading = state.status === "loading" && !snap;
|
|
19762
20106
|
const errorMessage2 = state.error?.message ?? lastRefreshError(state) ?? undefined;
|
|
19763
20107
|
const probeFailed = snap ? snap.state.ran === false && Boolean(state.error) : Boolean(state.error);
|
|
20108
|
+
const selected = Math.max(0, state.selection.index);
|
|
19764
20109
|
const body = [
|
|
19765
20110
|
...loading ? loadingRows(family || "family", state.tick) : snap ? [
|
|
19766
|
-
...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
|
+
] : [],
|
|
19767
20118
|
...current.subId ? formView(state, family, snap, current).lines : overviewBody(state, family, snap, layout)
|
|
19768
20119
|
] : familyRecoveryRows(state, family, errorMessage2)
|
|
19769
20120
|
];
|
|
@@ -19797,6 +20148,7 @@ function renderFamilyScene(state, layout) {
|
|
|
19797
20148
|
var init_family2 = __esm(() => {
|
|
19798
20149
|
init_scene();
|
|
19799
20150
|
init_selectable();
|
|
20151
|
+
init_remote_link();
|
|
19800
20152
|
init_theme2();
|
|
19801
20153
|
init_family_domains();
|
|
19802
20154
|
init_kit();
|
|
@@ -20067,27 +20419,38 @@ function runRow(width, run, active, optimistic) {
|
|
|
20067
20419
|
const item = runSelectableItem(run);
|
|
20068
20420
|
return item ? withSelectable(row, item) : row;
|
|
20069
20421
|
}
|
|
20070
|
-
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);
|
|
20071
20434
|
return [
|
|
20072
20435
|
...reason ? [line(reason, { fg: RIG_UI.yellow }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
20073
20436
|
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
20074
|
-
...
|
|
20437
|
+
...fleetRecoveryDecks(state).map((deck, index) => selectableDeckRow({ ...deck, index, active: selected === index }, items[index]))
|
|
20075
20438
|
];
|
|
20076
20439
|
}
|
|
20077
|
-
function emptyRows(query, total, selected) {
|
|
20440
|
+
function emptyRows(state, query, total, selected) {
|
|
20078
20441
|
if (!query.trim() && total === 0)
|
|
20079
|
-
return recoveryRows(selected, "No runs yet.");
|
|
20442
|
+
return recoveryRows(state, selected, "No runs yet.");
|
|
20080
20443
|
if (query.trim() && total > 0) {
|
|
20081
20444
|
return [
|
|
20082
|
-
...recoveryRows(selected, `No matching runs for ${JSON.stringify(query)} (${total} total).`)
|
|
20445
|
+
...recoveryRows(state, selected, `No matching runs for ${JSON.stringify(query)} (${total} total).`)
|
|
20083
20446
|
];
|
|
20084
20447
|
}
|
|
20085
|
-
return recoveryRows(selected, "No runs are visible with this filter.");
|
|
20448
|
+
return recoveryRows(state, selected, "No runs are visible with this filter.");
|
|
20086
20449
|
}
|
|
20087
20450
|
function degradedRows(state, selected) {
|
|
20088
20451
|
if (!state.error)
|
|
20089
20452
|
return [];
|
|
20090
|
-
return recoveryRows(selected, state.error.message);
|
|
20453
|
+
return recoveryRows(state, selected, state.error.message);
|
|
20091
20454
|
}
|
|
20092
20455
|
function renderFleetScene(state, layout) {
|
|
20093
20456
|
const width = panelWidth4(layout);
|
|
@@ -20097,7 +20460,7 @@ function renderFleetScene(state, layout) {
|
|
|
20097
20460
|
const runs = sortRuns(filterRunsForSearch(allRuns, query), spec);
|
|
20098
20461
|
const selectedRun = typeof state.data.selectedRunId === "string" && runs.some((run) => run.runId === state.data.selectedRunId) ? state.data.selectedRunId : runs[0]?.runId;
|
|
20099
20462
|
const selectedIndex = Math.max(0, runs.findIndex((run) => run.runId === selectedRun));
|
|
20100
|
-
const recoveryIndex = Math.max(0, Math.min(
|
|
20463
|
+
const recoveryIndex = Math.max(0, Math.min(fleetRecoveryItems(state).length - 1, state.selection.index));
|
|
20101
20464
|
const optimistic = optimisticStatuses(state);
|
|
20102
20465
|
const updatedAgo = updatedAgoLabel(state);
|
|
20103
20466
|
const panelTop = 0;
|
|
@@ -20129,7 +20492,7 @@ function renderFleetScene(state, layout) {
|
|
|
20129
20492
|
...runs.map((run, index) => runRow(contentWidth, run, index === selectedIndex, optimistic.get(run.runId)))
|
|
20130
20493
|
] : state.error ? degradedRows(state, recoveryIndex) : loading ? loadingRows("runs", state.tick) : [
|
|
20131
20494
|
...query.trim() ? [line(searchSummary("runs", query, runs.length, allRuns.length), { fg: RIG_UI.ink4 }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
20132
|
-
...emptyRows(query, allRuns.length, recoveryIndex)
|
|
20495
|
+
...emptyRows(state, query, allRuns.length, recoveryIndex)
|
|
20133
20496
|
]
|
|
20134
20497
|
];
|
|
20135
20498
|
return makeSceneFrame({
|
|
@@ -20164,18 +20527,19 @@ function renderFleetScene(state, layout) {
|
|
|
20164
20527
|
live: true
|
|
20165
20528
|
});
|
|
20166
20529
|
}
|
|
20167
|
-
var
|
|
20530
|
+
var BASE_FLEET_RECOVERY_ITEMS, FLEET_REPAIR_LINK_ITEM, COL2, GUTTER3 = " ", RUN_COLUMNS, BASE_RECOVERY_DECKS;
|
|
20168
20531
|
var init_fleet2 = __esm(() => {
|
|
20169
20532
|
init_scene();
|
|
20170
20533
|
init_selectable();
|
|
20171
20534
|
init_fleet_stats();
|
|
20535
|
+
init_remote_link();
|
|
20172
20536
|
init_theme2();
|
|
20173
|
-
|
|
20537
|
+
BASE_FLEET_RECOVERY_ITEMS = [
|
|
20174
20538
|
{ id: "tasks", label: "tasks", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Open tasks" } }, message: "open tasks and dispatch work" },
|
|
20175
|
-
{ id: "repair", label: "repair", intent: { scene: "command", argv: ["init", "--repair"], action: { kind: "command-run", label: "Repair project link" } }, message: "repair project/server/auth link" },
|
|
20176
20539
|
{ id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "server controls" },
|
|
20177
20540
|
{ id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose project" }
|
|
20178
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" };
|
|
20179
20543
|
COL2 = {
|
|
20180
20544
|
glyph: 1,
|
|
20181
20545
|
runId: 8,
|
|
@@ -20189,9 +20553,8 @@ var init_fleet2 = __esm(() => {
|
|
|
20189
20553
|
{ key: "title", label: "task/title", hint: "by task title" },
|
|
20190
20554
|
{ key: "age", label: "age", hint: "by recency" }
|
|
20191
20555
|
];
|
|
20192
|
-
|
|
20556
|
+
BASE_RECOVERY_DECKS = [
|
|
20193
20557
|
{ label: "tasks", detail: "open tasks and dispatch work" },
|
|
20194
|
-
{ label: "repair", detail: "repair project/server/auth link" },
|
|
20195
20558
|
{ label: "server", detail: "open server controls" },
|
|
20196
20559
|
{ label: "doctor", detail: "diagnose project" }
|
|
20197
20560
|
];
|
|
@@ -20771,11 +21134,11 @@ function renderInitScene(state, layout) {
|
|
|
20771
21134
|
const allDone = completed === SETUP_STEPS.length;
|
|
20772
21135
|
const nextStep = SETUP_STEPS.find((step) => !step.done(signals));
|
|
20773
21136
|
const selected = Math.max(0, state.selection.index);
|
|
20774
|
-
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" });
|
|
20775
21138
|
const secondaryRows = SECONDARY_ACTIONS.map(({ label, detail, item }, index) => selectableDeckRow({ label, detail, active: selected === index + 1 }, item));
|
|
20776
21139
|
const progress = allDone ? "all set" : `${completed} of ${SETUP_STEPS.length} complete`;
|
|
20777
21140
|
const panelLines = [
|
|
20778
|
-
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 }),
|
|
20779
21142
|
line(`progress ${progress}`, { fg: allDone ? RIG_UI.limeDim : RIG_UI.ink2 }),
|
|
20780
21143
|
blank(),
|
|
20781
21144
|
line("CHECKLIST", { fg: RIG_UI.ink3, bold: true }),
|
|
@@ -20787,11 +21150,11 @@ function renderInitScene(state, layout) {
|
|
|
20787
21150
|
line("OTHER PATHS", { fg: RIG_UI.ink3, bold: true }),
|
|
20788
21151
|
...secondaryRows,
|
|
20789
21152
|
blank(),
|
|
20790
|
-
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 })
|
|
20791
21154
|
];
|
|
20792
21155
|
return makeSceneFrame({
|
|
20793
21156
|
scene: "init",
|
|
20794
|
-
title: "
|
|
21157
|
+
title: "Init",
|
|
20795
21158
|
lines: [],
|
|
20796
21159
|
panels: [{
|
|
20797
21160
|
id: "init-setup",
|
|
@@ -20804,11 +21167,11 @@ function renderInitScene(state, layout) {
|
|
|
20804
21167
|
opacity: 0.98,
|
|
20805
21168
|
border: false,
|
|
20806
21169
|
chrome: "ad-terminal",
|
|
20807
|
-
headerText: "rig
|
|
21170
|
+
headerText: "rig init \xB7 guided onboarding",
|
|
20808
21171
|
paddingX: 5,
|
|
20809
21172
|
paddingY: 2
|
|
20810
21173
|
}],
|
|
20811
|
-
footer: { message: allDone ? "
|
|
21174
|
+
footer: { message: allDone ? "init complete" : "init in progress" },
|
|
20812
21175
|
live: !allDone || state.status === "action"
|
|
20813
21176
|
});
|
|
20814
21177
|
}
|
|
@@ -20817,19 +21180,19 @@ var init_init3 = __esm(() => {
|
|
|
20817
21180
|
init_scene();
|
|
20818
21181
|
init_selectable();
|
|
20819
21182
|
init_theme2();
|
|
20820
|
-
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" };
|
|
20821
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" };
|
|
20822
|
-
STEP_AUTH = { id: "step-auth", label: "connect GitHub", intent: { scene: "
|
|
20823
|
-
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" };
|
|
20824
21187
|
SETUP_STEPS = [
|
|
20825
|
-
{ 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 },
|
|
20826
21189
|
{ id: "server", label: "Server target", detail: "local or remote, reachable", done: (s) => s.serverReachable, cta: "Choose a server", item: STEP_SERVER },
|
|
20827
21190
|
{ id: "auth", label: "GitHub auth", detail: "signed in on the selected server", done: (s) => s.authSignedIn, cta: "Connect GitHub", item: STEP_AUTH },
|
|
20828
21191
|
{ id: "tasks", label: "Task source", detail: "where work comes from", done: (s) => s.taskSourceReady, cta: "Pick a task source", item: STEP_TASKS }
|
|
20829
21192
|
];
|
|
20830
21193
|
SECONDARY_ACTIONS = [
|
|
20831
|
-
{ label: "repair", detail: "reconfigure generated config and private state", item: { id: "repair", label: "repair", intent: { scene: "
|
|
20832
|
-
{ 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" } },
|
|
20833
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" } }
|
|
20834
21197
|
];
|
|
20835
21198
|
});
|
|
@@ -22128,6 +22491,30 @@ var init_run_detail2 = __esm(() => {
|
|
|
22128
22491
|
});
|
|
22129
22492
|
|
|
22130
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
|
+
}
|
|
22131
22518
|
function cleanVisible(value, fallback = "unknown") {
|
|
22132
22519
|
return value?.trim() || fallback;
|
|
22133
22520
|
}
|
|
@@ -22152,31 +22539,37 @@ function selectedIndex(state, count) {
|
|
|
22152
22539
|
function statusRows2(server) {
|
|
22153
22540
|
const auth = server?.auth;
|
|
22154
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"}` : "";
|
|
22155
22545
|
return [
|
|
22156
|
-
line(`selected ${cleanVisible(server?.label, "not checked")}`, { fg: RIG_UI.ink2 }),
|
|
22546
|
+
line(`selected ${cleanVisible(server?.label, "not checked")}${selectedLinkSummary}`, { fg: RIG_UI.ink2 }),
|
|
22157
22547
|
line(`target ${targetLabel(server)}`, { fg: RIG_UI.ink3 }),
|
|
22158
22548
|
line(`mode ${server?.kind ?? "local or remote"}`, { fg: RIG_UI.ink3 }),
|
|
22159
22549
|
line(`health ${server ? server.reachable ? "reachable" : "unreachable" : "check pending"}`, { fg: server?.reachable ? RIG_UI.limeDim : server ? RIG_UI.red : RIG_UI.yellow }),
|
|
22160
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 })] : [],
|
|
22161
22553
|
...server?.error ? [line(`attention ${server.error}`, { fg: RIG_UI.yellow })] : []
|
|
22162
22554
|
];
|
|
22163
22555
|
}
|
|
22164
22556
|
function renderServerScene(state, layout) {
|
|
22165
22557
|
const server = serverState(state);
|
|
22166
|
-
const
|
|
22558
|
+
const actions = serverActions(state);
|
|
22559
|
+
const selected = selectedIndex(state, actions.length);
|
|
22167
22560
|
const loading = state.status === "loading" && !server;
|
|
22168
22561
|
const errorText = state.error?.message ?? lastRefreshError(state);
|
|
22169
22562
|
const panelLines = [
|
|
22170
22563
|
...errorText ? errorBanner(errorText, "select refresh or doctor below to retry") : [],
|
|
22171
22564
|
line("server controls", { fg: RIG_UI.ink3 }),
|
|
22172
22565
|
blank(),
|
|
22173
|
-
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
22174
|
-
...SERVER_ACTIONS.map(({ detail, item }, index) => selectableDeckRow({ label: item.label, detail, index, active: selected === index }, item)),
|
|
22175
|
-
blank(),
|
|
22176
22566
|
line("STATUS", { fg: RIG_UI.ink3, bold: true }),
|
|
22177
22567
|
...loading ? loadingRows("server status", state.tick) : statusRows2(server),
|
|
22178
22568
|
blank(),
|
|
22179
|
-
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 })
|
|
22180
22573
|
];
|
|
22181
22574
|
return makeSceneFrame({
|
|
22182
22575
|
scene: "server",
|
|
@@ -22206,14 +22599,15 @@ var init_server3 = __esm(() => {
|
|
|
22206
22599
|
init_scene();
|
|
22207
22600
|
init_selectable();
|
|
22208
22601
|
init_theme2();
|
|
22602
|
+
init_remote_link();
|
|
22209
22603
|
SERVER_ACTIONS = [
|
|
22210
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" } },
|
|
22211
|
-
{ detail: "select local server for this repo", item: { id: "local", label: "use local", intent: { scene: "
|
|
22212
|
-
{ detail: "
|
|
22213
|
-
{ detail: "show saved local/remote aliases", item: { id: "list", label: "list servers", intent: { scene: "
|
|
22214
|
-
{ 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" } },
|
|
22215
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" } },
|
|
22216
|
-
{ 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" } },
|
|
22217
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" } },
|
|
22218
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" } },
|
|
22219
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" } }
|
|
@@ -22365,27 +22759,38 @@ function taskRow(width, task, active, optimistic) {
|
|
|
22365
22759
|
const item = taskSelectableItem(task);
|
|
22366
22760
|
return item ? withSelectable(row, item) : row;
|
|
22367
22761
|
}
|
|
22368
|
-
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);
|
|
22369
22774
|
return [
|
|
22370
22775
|
...reason ? [line(reason, { fg: RIG_UI.yellow }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
22371
22776
|
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
22372
|
-
...
|
|
22777
|
+
...taskRecoveryDecks(state).map((deck, index) => selectableDeckRow({ ...deck, index, active: selected === index }, items[index]))
|
|
22373
22778
|
];
|
|
22374
22779
|
}
|
|
22375
|
-
function emptyRows2(query, total, selected) {
|
|
22780
|
+
function emptyRows2(state, query, total, selected) {
|
|
22376
22781
|
if (!query.trim() && total === 0)
|
|
22377
|
-
return recoveryRows2(selected, "No tasks loaded.");
|
|
22782
|
+
return recoveryRows2(state, selected, "No tasks loaded.");
|
|
22378
22783
|
if (query.trim() && total > 0) {
|
|
22379
22784
|
return [
|
|
22380
|
-
...recoveryRows2(selected, `No matching tasks for ${JSON.stringify(query)} (${total} total).`)
|
|
22785
|
+
...recoveryRows2(state, selected, `No matching tasks for ${JSON.stringify(query)} (${total} total).`)
|
|
22381
22786
|
];
|
|
22382
22787
|
}
|
|
22383
|
-
return recoveryRows2(selected, "No tasks are visible with this filter.");
|
|
22788
|
+
return recoveryRows2(state, selected, "No tasks are visible with this filter.");
|
|
22384
22789
|
}
|
|
22385
22790
|
function degradedRows2(state, selected) {
|
|
22386
22791
|
if (!state.error)
|
|
22387
22792
|
return [];
|
|
22388
|
-
return recoveryRows2(selected, state.error.message);
|
|
22793
|
+
return recoveryRows2(state, selected, state.error.message);
|
|
22389
22794
|
}
|
|
22390
22795
|
function rawString(raw, key) {
|
|
22391
22796
|
const value = raw?.[key];
|
|
@@ -22409,7 +22814,10 @@ function renderTaskDetail(state, taskId3, layout) {
|
|
|
22409
22814
|
const activeRunId = task?.activeRun?.runId?.trim();
|
|
22410
22815
|
const width = panelWidth13(layout);
|
|
22411
22816
|
const selected = Math.max(0, state.selection.index);
|
|
22817
|
+
const errorText = state.error?.message ?? lastRefreshError(state);
|
|
22818
|
+
const offerRepairLink = shouldOfferRemoteLinkRepair(state, errorText);
|
|
22412
22819
|
const headerLines = [
|
|
22820
|
+
...errorText ? errorBanner(errorText, offerRepairLink ? "select repair link below to prepare the remote checkout" : "retry dispatch after resolving the issue") : [],
|
|
22413
22821
|
line(`${glyph2} ${title}`, { fg: color, bold: true }),
|
|
22414
22822
|
line(`task ${taskId3} \xB7 ${status}`, { fg: RIG_UI.ink3 }),
|
|
22415
22823
|
...task && task.labels.length > 0 ? [line(`labels: ${task.labels.join(", ")}`, { fg: RIG_UI.ink4 })] : [],
|
|
@@ -22421,8 +22829,16 @@ function renderTaskDetail(state, taskId3, layout) {
|
|
|
22421
22829
|
const actionRows2 = [];
|
|
22422
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" }));
|
|
22423
22831
|
index += 1;
|
|
22424
|
-
|
|
22425
|
-
|
|
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
|
+
}
|
|
22426
22842
|
if (activeRunId) {
|
|
22427
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)}` }));
|
|
22428
22844
|
index += 1;
|
|
@@ -22481,7 +22897,7 @@ function renderTasksScene(state, layout) {
|
|
|
22481
22897
|
const tasks = sortTasks2(filterTasksForSearch(allTasks, query), spec);
|
|
22482
22898
|
const selected = typeof state.data.selectedTaskId === "string" && tasks.some((task) => task.id === state.data.selectedTaskId) ? state.data.selectedTaskId : tasks[0]?.id;
|
|
22483
22899
|
const selectedIndex2 = Math.max(0, tasks.findIndex((task) => task.id === selected));
|
|
22484
|
-
const recoveryIndex = Math.max(0, Math.min(
|
|
22900
|
+
const recoveryIndex = Math.max(0, Math.min(taskRecoveryItems(state).length - 1, state.selection.index));
|
|
22485
22901
|
const dispatching = dispatchingFor(state);
|
|
22486
22902
|
const dispatchLine = dispatching ? ` \xB7 ${state.data.dispatchingRun?.runId ?? "new"} ${dispatching.status}` : "";
|
|
22487
22903
|
const updatedAgo = updatedAgoLabel2(state);
|
|
@@ -22501,7 +22917,7 @@ function renderTasksScene(state, layout) {
|
|
|
22501
22917
|
...tasks.map((task, index) => taskRow(contentWidth, task, index === selectedIndex2, dispatching && dispatching.taskId === task.id ? dispatching.status : undefined))
|
|
22502
22918
|
] : state.error ? degradedRows2(state, recoveryIndex) : loading ? loadingRows("tasks", state.tick) : [
|
|
22503
22919
|
...query.trim() ? [line(searchSummary("tasks", query, tasks.length, allTasks.length), { fg: RIG_UI.ink4 }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
22504
|
-
...emptyRows2(query, allTasks.length, recoveryIndex)
|
|
22920
|
+
...emptyRows2(state, query, allTasks.length, recoveryIndex)
|
|
22505
22921
|
]
|
|
22506
22922
|
];
|
|
22507
22923
|
return makeSceneFrame({
|
|
@@ -22535,18 +22951,19 @@ function renderTasksScene(state, layout) {
|
|
|
22535
22951
|
live: true
|
|
22536
22952
|
});
|
|
22537
22953
|
}
|
|
22538
|
-
var
|
|
22954
|
+
var BASE_TASK_RECOVERY_ITEMS, TASK_REPAIR_LINK_ITEM, COL3, GUTTER4 = " ", TASK_COLUMNS, BASE_RECOVERY_DECKS2;
|
|
22539
22955
|
var init_tasks2 = __esm(() => {
|
|
22540
22956
|
init_scene();
|
|
22541
22957
|
init_selectable();
|
|
22958
|
+
init_remote_link();
|
|
22542
22959
|
init_theme2();
|
|
22543
|
-
|
|
22960
|
+
BASE_TASK_RECOVERY_ITEMS = [
|
|
22544
22961
|
{ id: "refresh", label: "refresh", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Refresh tasks" } }, message: "refresh task source" },
|
|
22545
|
-
{ id: "next", label: "next", intent: { scene: "
|
|
22546
|
-
{ 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" },
|
|
22547
22963
|
{ id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "server controls" },
|
|
22548
22964
|
{ id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose task source" }
|
|
22549
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" };
|
|
22550
22967
|
COL3 = {
|
|
22551
22968
|
glyph: 1,
|
|
22552
22969
|
id: 11,
|
|
@@ -22561,10 +22978,9 @@ var init_tasks2 = __esm(() => {
|
|
|
22561
22978
|
{ key: "assignee", label: "assignee", hint: "by assignee" },
|
|
22562
22979
|
{ key: "title", label: "title", hint: "by title" }
|
|
22563
22980
|
];
|
|
22564
|
-
|
|
22981
|
+
BASE_RECOVERY_DECKS2 = [
|
|
22565
22982
|
{ label: "refresh", detail: "reload task source" },
|
|
22566
22983
|
{ label: "next", detail: "dispatch next runnable task" },
|
|
22567
|
-
{ label: "repair", detail: "repair project/task source link" },
|
|
22568
22984
|
{ label: "server", detail: "open server controls" },
|
|
22569
22985
|
{ label: "doctor", detail: "diagnose task source" }
|
|
22570
22986
|
];
|
|
@@ -22898,6 +23314,29 @@ function createDomainAdapter() {
|
|
|
22898
23314
|
else
|
|
22899
23315
|
await loadInitFacts(ctx);
|
|
22900
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
|
+
}
|
|
22901
23340
|
case "doctor-run":
|
|
22902
23341
|
await runDoctorChecksForApp(ctx);
|
|
22903
23342
|
return true;
|
|
@@ -23000,7 +23439,9 @@ import {
|
|
|
23000
23439
|
RigInboxInputsOutput,
|
|
23001
23440
|
RigRunListOutput,
|
|
23002
23441
|
RigRunShowOutput,
|
|
23442
|
+
RigServerRepairLinkOutput,
|
|
23003
23443
|
RigServerStatusOutput,
|
|
23444
|
+
RigServerUseOutput,
|
|
23004
23445
|
RigStatsOutput,
|
|
23005
23446
|
RigTaskListOutput,
|
|
23006
23447
|
RigTaskShowOutput
|
|
@@ -23036,7 +23477,9 @@ var init__json_output = __esm(() => {
|
|
|
23036
23477
|
"task show": RigTaskShowOutput,
|
|
23037
23478
|
"run list": RigRunListOutput,
|
|
23038
23479
|
"run show": RigRunShowOutput,
|
|
23480
|
+
"server use": RigServerUseOutput,
|
|
23039
23481
|
"server status": RigServerStatusOutput,
|
|
23482
|
+
"server repair-link": RigServerRepairLinkOutput,
|
|
23040
23483
|
"inbox approvals": RigInboxApprovalsOutput,
|
|
23041
23484
|
"inbox inputs": RigInboxInputsOutput,
|
|
23042
23485
|
"doctor check": RigDoctorCheckOutput,
|
|
@@ -23046,7 +23489,7 @@ var init__json_output = __esm(() => {
|
|
|
23046
23489
|
|
|
23047
23490
|
// packages/cli/src/launcher.ts
|
|
23048
23491
|
import { existsSync as existsSync22 } from "fs";
|
|
23049
|
-
import { basename as
|
|
23492
|
+
import { basename as basename4, resolve as resolve29 } from "path";
|
|
23050
23493
|
import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
|
|
23051
23494
|
import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
|
|
23052
23495
|
function parsePolicyMode(value) {
|
|
@@ -23071,7 +23514,7 @@ function resolveProjectRoot({
|
|
|
23071
23514
|
return resolve29(cwd, envProjectRoot);
|
|
23072
23515
|
}
|
|
23073
23516
|
const fallbackImportDir = importDir ?? cwd;
|
|
23074
|
-
const execName =
|
|
23517
|
+
const execName = basename4(execPath).toLowerCase();
|
|
23075
23518
|
const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve29(execPath, "..", "..")] : [];
|
|
23076
23519
|
const candidates = [cwd, ...execCandidates, resolve29(fallbackImportDir, "..")];
|
|
23077
23520
|
for (const candidate of candidates) {
|
|
@@ -23367,16 +23810,31 @@ function taskViewIntent(argv, command = "", rest = [], raw) {
|
|
|
23367
23810
|
const { payload, label } = taskViewPayload(command, rest);
|
|
23368
23811
|
return intent("tasks", argv, "refresh", payload, label, raw);
|
|
23369
23812
|
}
|
|
23370
|
-
function routeServer(argv, command, raw, checkingLabel) {
|
|
23371
|
-
if (!command || command === "status") {
|
|
23813
|
+
function routeServer(argv, command, rest, raw, checkingLabel) {
|
|
23814
|
+
if (!command || command === "status" || command === "list") {
|
|
23372
23815
|
return intent("server", argv, "refresh", undefined, command ? checkingLabel : "Loading server", raw);
|
|
23373
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);
|
|
23374
23829
|
return commandRunIntent(argv, raw);
|
|
23375
23830
|
}
|
|
23376
23831
|
function routeGithub(argv, command, rest, raw) {
|
|
23377
23832
|
if (command === "auth" && (rest[0]?.toLowerCase() ?? "status") === "status" && rest.length <= 1) {
|
|
23378
23833
|
return intent("server", argv, "refresh", undefined, "Checking GitHub auth", raw);
|
|
23379
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
|
+
}
|
|
23380
23838
|
return commandRunIntent(argv, raw);
|
|
23381
23839
|
}
|
|
23382
23840
|
function routeDoctor(argv, command, raw) {
|
|
@@ -23425,11 +23883,16 @@ function intentFromArgv(argv) {
|
|
|
23425
23883
|
return commandRunIntent(argv);
|
|
23426
23884
|
}
|
|
23427
23885
|
if (normalizedGroup === "server")
|
|
23428
|
-
return routeServer(argv, normalizedCommand, undefined, "Checking server");
|
|
23886
|
+
return routeServer(argv, normalizedCommand, rest, undefined, "Checking server");
|
|
23429
23887
|
if (normalizedGroup === "github")
|
|
23430
23888
|
return routeGithub(argv, normalizedCommand, rest);
|
|
23431
|
-
if (normalizedGroup === "init")
|
|
23432
|
-
|
|
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
|
+
}
|
|
23433
23896
|
if (normalizedGroup === "doctor")
|
|
23434
23897
|
return routeDoctor(argv, normalizedCommand);
|
|
23435
23898
|
if (normalizedGroup === "inbox")
|
|
@@ -23492,12 +23955,17 @@ function intentFromTypeBar(value) {
|
|
|
23492
23955
|
return commandRunIntent(parts, value);
|
|
23493
23956
|
return intent("tasks", parts, "refresh", undefined, "Select a task, then press Enter; or use run next", value);
|
|
23494
23957
|
}
|
|
23495
|
-
if (first === "init")
|
|
23496
|
-
|
|
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
|
+
}
|
|
23497
23965
|
if (first === "doctor")
|
|
23498
23966
|
return routeDoctor(parts, second, value);
|
|
23499
23967
|
if (first === "server")
|
|
23500
|
-
return routeServer(parts, second, value, "Loading server");
|
|
23968
|
+
return routeServer(parts, second, rest, value, "Loading server");
|
|
23501
23969
|
if (first === "github")
|
|
23502
23970
|
return routeGithub(parts, second, rest, value);
|
|
23503
23971
|
if (first === "inbox")
|
|
@@ -23948,22 +24416,15 @@ function clearTypeBar(context, message2) {
|
|
|
23948
24416
|
context.emitTypeBarPatch({ value: "", mode: "nav", prompt: undefined, message: message2 });
|
|
23949
24417
|
}
|
|
23950
24418
|
function handleEmbeddedTerminalKey(context, key) {
|
|
23951
|
-
|
|
23952
|
-
|
|
23953
|
-
const
|
|
23954
|
-
const host = state.scene === "handoff" ? piHost : state.scene === "command" ? commandHost : null;
|
|
24419
|
+
if (context.getState().scene !== "command")
|
|
24420
|
+
return false;
|
|
24421
|
+
const host = getActiveCommandHost();
|
|
23955
24422
|
if (!host)
|
|
23956
24423
|
return false;
|
|
23957
24424
|
if (key.ctrl && key.name === "]") {
|
|
23958
|
-
|
|
23959
|
-
|
|
23960
|
-
|
|
23961
|
-
context.runAppAction("Opening runs", () => context.runtime.runIntent({ scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } }));
|
|
23962
|
-
} else {
|
|
23963
|
-
stopActiveCommandHost("operator detach");
|
|
23964
|
-
clearTypeBar(context, "closed command");
|
|
23965
|
-
context.runAppAction("Project menu", () => context.runtime.runIntent({ scene: "main", argv: ["main"], action: { kind: "none", label: "Project menu" } }));
|
|
23966
|
-
}
|
|
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" } }));
|
|
23967
24428
|
return true;
|
|
23968
24429
|
}
|
|
23969
24430
|
const sequence = key.raw || key.sequence;
|
|
@@ -24172,7 +24633,6 @@ var init_keymap = __esm(() => {
|
|
|
24172
24633
|
init_autocomplete();
|
|
24173
24634
|
init_command_pty_host();
|
|
24174
24635
|
init_intent();
|
|
24175
|
-
init_pi_pty_host();
|
|
24176
24636
|
});
|
|
24177
24637
|
|
|
24178
24638
|
// packages/cli/src/app-opentui/runtime-resources.ts
|
|
@@ -24329,7 +24789,7 @@ var init_constants = __esm(() => {
|
|
|
24329
24789
|
});
|
|
24330
24790
|
|
|
24331
24791
|
// packages/cli/src/app-opentui/render/graphics.ts
|
|
24332
|
-
import { FrameBufferRenderable, RGBA as
|
|
24792
|
+
import { FrameBufferRenderable, RGBA as RGBA2 } from "@opentui/core";
|
|
24333
24793
|
function sceneKind(scene) {
|
|
24334
24794
|
if (scene === "tasks")
|
|
24335
24795
|
return "loop";
|
|
@@ -24424,7 +24884,7 @@ function paletteColor(ac, c2, mg, ink5) {
|
|
|
24424
24884
|
const b = (AC_RGB[2] * ac + C2_RGB[2] * c2 + MG_RGB[2] * mg + INK_RGB[2] * ink5) / total;
|
|
24425
24885
|
const intensity = Math.min(1, total / 4);
|
|
24426
24886
|
const lift = 0.34 + intensity * 0.66;
|
|
24427
|
-
return
|
|
24887
|
+
return RGBA2.fromInts(Math.round(r * lift), Math.round(g * lift), Math.round(b * lift), 255);
|
|
24428
24888
|
}
|
|
24429
24889
|
function clearCanvas(canvas) {
|
|
24430
24890
|
canvas.ac.fill(0);
|
|
@@ -24779,8 +25239,8 @@ function staticFleetTick(scene) {
|
|
|
24779
25239
|
}
|
|
24780
25240
|
function withAlpha(hex, alpha) {
|
|
24781
25241
|
const a = Math.max(0, Math.min(255, Math.round(alpha * 255)));
|
|
24782
|
-
const [r, g, b] =
|
|
24783
|
-
return
|
|
25242
|
+
const [r, g, b] = RGBA2.fromHex(hex).toInts();
|
|
25243
|
+
return RGBA2.fromInts(r, g, b, a);
|
|
24784
25244
|
}
|
|
24785
25245
|
function asciiFleetColor(char, row, alpha) {
|
|
24786
25246
|
if (char === "@" || char === "$" || char === "o")
|
|
@@ -24788,7 +25248,7 @@ function asciiFleetColor(char, row, alpha) {
|
|
|
24788
25248
|
if (char === "%" || char === "!" || char === "/" || char === "\\" || char === "|")
|
|
24789
25249
|
return withAlpha(RIG_UI.cyan, alpha);
|
|
24790
25250
|
if (char === "." || char === "'" || char === "_" || row < 3 || row > FLEET_GRID_HEIGHT - 4) {
|
|
24791
|
-
return
|
|
25251
|
+
return RGBA2.fromInts(108, 110, 121, Math.min(170, Math.max(0, Math.min(255, Math.round(alpha * 255)))));
|
|
24792
25252
|
}
|
|
24793
25253
|
return withAlpha(RIG_UI.limeDim, alpha);
|
|
24794
25254
|
}
|
|
@@ -24842,13 +25302,13 @@ var init_graphics = __esm(() => {
|
|
|
24842
25302
|
init_theme2();
|
|
24843
25303
|
init_ascii_fleet();
|
|
24844
25304
|
init_constants();
|
|
24845
|
-
TRANSPARENT =
|
|
24846
|
-
BACKDROP =
|
|
24847
|
-
PANEL_BG =
|
|
24848
|
-
PANEL_HEADER_BG =
|
|
24849
|
-
PANEL_LINE =
|
|
24850
|
-
PANEL_LINE_DIM =
|
|
24851
|
-
PANEL_TEXT_DIM =
|
|
25305
|
+
TRANSPARENT = RGBA2.fromValues(0, 0, 0, 0);
|
|
25306
|
+
BACKDROP = RGBA2.fromHex(RIG_UI.bg);
|
|
25307
|
+
PANEL_BG = RGBA2.fromInts(16, 17, 21, 184);
|
|
25308
|
+
PANEL_HEADER_BG = RGBA2.fromInts(16, 17, 21, 188);
|
|
25309
|
+
PANEL_LINE = RGBA2.fromInts(255, 255, 255, 20);
|
|
25310
|
+
PANEL_LINE_DIM = RGBA2.fromInts(255, 255, 255, 8);
|
|
25311
|
+
PANEL_TEXT_DIM = RGBA2.fromInts(108, 110, 121, 255);
|
|
24852
25312
|
AC_RGB = [204, 255, 77];
|
|
24853
25313
|
C2_RGB = [86, 216, 255];
|
|
24854
25314
|
MG_RGB = [255, 121, 176];
|
|
@@ -24891,7 +25351,7 @@ var init_hover = __esm(() => {
|
|
|
24891
25351
|
});
|
|
24892
25352
|
|
|
24893
25353
|
// packages/cli/src/app-opentui/render/text.ts
|
|
24894
|
-
import { RGBA as
|
|
25354
|
+
import { RGBA as RGBA3, TextAttributes as TextAttributes3, TextRenderable } from "@opentui/core";
|
|
24895
25355
|
function lineIsClickable(line2) {
|
|
24896
25356
|
return line2?.selectable !== undefined || line2?.selectableIndex !== undefined;
|
|
24897
25357
|
}
|
|
@@ -24900,7 +25360,7 @@ function lineSelectableId(line2) {
|
|
|
24900
25360
|
}
|
|
24901
25361
|
function lineBackground(line2) {
|
|
24902
25362
|
if (line2?.bg)
|
|
24903
|
-
return
|
|
25363
|
+
return RGBA3.fromHex(line2.bg);
|
|
24904
25364
|
const id = lineSelectableId(line2);
|
|
24905
25365
|
if (id !== undefined && isHovered(id))
|
|
24906
25366
|
return HOVER_BG;
|
|
@@ -24969,7 +25429,7 @@ function applyTextLine(renderable, line2, top, left, width) {
|
|
|
24969
25429
|
renderable.content = line2?.styledText ?? line2?.text ?? "";
|
|
24970
25430
|
renderable.fg = line2?.fg ?? RIG_UI.ink2;
|
|
24971
25431
|
renderable.bg = lineBackground(line2);
|
|
24972
|
-
renderable.attributes = line2?.bold ?
|
|
25432
|
+
renderable.attributes = line2?.bold ? TextAttributes3.BOLD : line2?.dim ? TextAttributes3.DIM : 0;
|
|
24973
25433
|
}
|
|
24974
25434
|
function applyFlowTextLine(renderable, line2, width) {
|
|
24975
25435
|
renderable.setRigSceneLine?.(line2);
|
|
@@ -24979,7 +25439,7 @@ function applyFlowTextLine(renderable, line2, width) {
|
|
|
24979
25439
|
renderable.content = line2?.styledText ?? line2?.text ?? "";
|
|
24980
25440
|
renderable.fg = line2?.fg ?? RIG_UI.ink2;
|
|
24981
25441
|
renderable.bg = lineBackground(line2);
|
|
24982
|
-
renderable.attributes = line2?.bold ?
|
|
25442
|
+
renderable.attributes = line2?.bold ? TextAttributes3.BOLD : line2?.dim ? TextAttributes3.DIM : 0;
|
|
24983
25443
|
}
|
|
24984
25444
|
function clearTextLines(renderables, from = 0) {
|
|
24985
25445
|
for (let index = from;index < renderables.length; index += 1) {
|
|
@@ -24996,19 +25456,30 @@ var TRANSPARENT2, HOVER_BG;
|
|
|
24996
25456
|
var init_text = __esm(() => {
|
|
24997
25457
|
init_theme2();
|
|
24998
25458
|
init_hover();
|
|
24999
|
-
TRANSPARENT2 =
|
|
25000
|
-
HOVER_BG =
|
|
25459
|
+
TRANSPARENT2 = RGBA3.fromInts(0, 0, 0, 0);
|
|
25460
|
+
HOVER_BG = RGBA3.fromHex(RIG_UI.hover);
|
|
25001
25461
|
});
|
|
25002
25462
|
|
|
25463
|
+
// packages/cli/src/app-opentui/render/terminal-handoff.ts
|
|
25464
|
+
function resumeRendererClean(renderer) {
|
|
25465
|
+
try {
|
|
25466
|
+
renderer.pendingSuspendedTerminalSetup = true;
|
|
25467
|
+
} catch {}
|
|
25468
|
+
renderer.resume();
|
|
25469
|
+
try {
|
|
25470
|
+
renderer.requestRender?.();
|
|
25471
|
+
} catch {}
|
|
25472
|
+
}
|
|
25473
|
+
|
|
25003
25474
|
// packages/cli/src/app-opentui/render/panels.ts
|
|
25004
|
-
import { RGBA as
|
|
25475
|
+
import { RGBA as RGBA4, ScrollBoxRenderable } from "@opentui/core";
|
|
25005
25476
|
function hexToRgba(hex, alpha) {
|
|
25006
25477
|
const clean = hex.replace(/^#/, "");
|
|
25007
25478
|
const full = clean.length === 3 ? clean.split("").map((part) => `${part}${part}`).join("") : clean;
|
|
25008
25479
|
const value = Number.parseInt(full, 16);
|
|
25009
25480
|
if (!Number.isFinite(value))
|
|
25010
|
-
return
|
|
25011
|
-
return
|
|
25481
|
+
return RGBA4.fromInts(14, 15, 17, alpha);
|
|
25482
|
+
return RGBA4.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255, alpha);
|
|
25012
25483
|
}
|
|
25013
25484
|
function panelBackground(panel) {
|
|
25014
25485
|
return hexToRgba(panel.backgroundColor ?? RIG_UI.panel, PANEL_OPAQUE_ALPHA);
|
|
@@ -25125,12 +25596,12 @@ var TRANSPARENT3, MAX_PANEL_LINES = 420, PANEL_OPAQUE_ALPHA = 255, PANEL_BORDER;
|
|
|
25125
25596
|
var init_panels = __esm(() => {
|
|
25126
25597
|
init_theme2();
|
|
25127
25598
|
init_text();
|
|
25128
|
-
TRANSPARENT3 =
|
|
25599
|
+
TRANSPARENT3 = RGBA4.fromInts(0, 0, 0, 0);
|
|
25129
25600
|
PANEL_BORDER = hexToRgba(RIG_UI.border, 255);
|
|
25130
25601
|
});
|
|
25131
25602
|
|
|
25132
25603
|
// packages/cli/src/app-opentui/render/type-bar.ts
|
|
25133
|
-
import { BoxRenderable, InputRenderable, InputRenderableEvents, RGBA as
|
|
25604
|
+
import { BoxRenderable, InputRenderable, InputRenderableEvents, RGBA as RGBA5, StyledText as StyledText2, TextRenderable as TextRenderable2 } from "@opentui/core";
|
|
25134
25605
|
function createTypeBar(renderer) {
|
|
25135
25606
|
const background = new BoxRenderable(renderer, {
|
|
25136
25607
|
id: "typebar-card",
|
|
@@ -25277,13 +25748,13 @@ function formatFooter(footer, width) {
|
|
|
25277
25748
|
chunks.push(cell4.style(text2));
|
|
25278
25749
|
used += visibleWidth(text2);
|
|
25279
25750
|
});
|
|
25280
|
-
return new
|
|
25751
|
+
return new StyledText2(chunks);
|
|
25281
25752
|
}
|
|
25282
25753
|
var TYPEBAR_BG, TYPEBAR_BORDER, FOOTER_SEPARATOR = " \xB7 ";
|
|
25283
25754
|
var init_type_bar = __esm(() => {
|
|
25284
25755
|
init_theme2();
|
|
25285
|
-
TYPEBAR_BG =
|
|
25286
|
-
TYPEBAR_BORDER =
|
|
25756
|
+
TYPEBAR_BG = RGBA5.fromInts(20, 25, 14, 224);
|
|
25757
|
+
TYPEBAR_BORDER = RGBA5.fromInts(204, 255, 77, 92);
|
|
25287
25758
|
});
|
|
25288
25759
|
|
|
25289
25760
|
// packages/cli/src/app-opentui/render/native-host.ts
|
|
@@ -25291,7 +25762,7 @@ import {
|
|
|
25291
25762
|
BoxRenderable as BoxRenderable2,
|
|
25292
25763
|
CodeRenderable,
|
|
25293
25764
|
DiffRenderable,
|
|
25294
|
-
RGBA as
|
|
25765
|
+
RGBA as RGBA6,
|
|
25295
25766
|
ScrollBoxRenderable as ScrollBoxRenderable2,
|
|
25296
25767
|
SyntaxStyle,
|
|
25297
25768
|
TextRenderable as TextRenderable3,
|
|
@@ -25301,19 +25772,19 @@ function rigSyntaxStyle() {
|
|
|
25301
25772
|
if (syntaxStyle)
|
|
25302
25773
|
return syntaxStyle;
|
|
25303
25774
|
syntaxStyle = SyntaxStyle.fromStyles({
|
|
25304
|
-
keyword: { fg:
|
|
25305
|
-
string: { fg:
|
|
25306
|
-
number: { fg:
|
|
25307
|
-
comment: { fg:
|
|
25308
|
-
function: { fg:
|
|
25309
|
-
type: { fg:
|
|
25310
|
-
constant: { fg:
|
|
25311
|
-
default: { fg:
|
|
25775
|
+
keyword: { fg: RGBA6.fromHex(RIG_UI.magenta), bold: true },
|
|
25776
|
+
string: { fg: RGBA6.fromHex(RIG_UI.lime) },
|
|
25777
|
+
number: { fg: RGBA6.fromHex(RIG_UI.cyan) },
|
|
25778
|
+
comment: { fg: RGBA6.fromHex(RIG_UI.ink4), italic: true },
|
|
25779
|
+
function: { fg: RGBA6.fromHex(RIG_UI.cyan) },
|
|
25780
|
+
type: { fg: RGBA6.fromHex(RIG_UI.limeDim) },
|
|
25781
|
+
constant: { fg: RGBA6.fromHex(RIG_UI.yellow) },
|
|
25782
|
+
default: { fg: RGBA6.fromHex(RIG_UI.ink2) }
|
|
25312
25783
|
});
|
|
25313
25784
|
return syntaxStyle;
|
|
25314
25785
|
}
|
|
25315
25786
|
function tableContent(rows) {
|
|
25316
|
-
return rows.map((row, rowIndex) => row.map((cell4) => [{ __isChunk: true, text: cell4, fg:
|
|
25787
|
+
return rows.map((row, rowIndex) => row.map((cell4) => [{ __isChunk: true, text: cell4, fg: RGBA6.fromHex(rowIndex === 0 ? RIG_UI.ink3 : RIG_UI.ink2) }]));
|
|
25317
25788
|
}
|
|
25318
25789
|
function createNativeHost(renderer) {
|
|
25319
25790
|
try {
|
|
@@ -25462,10 +25933,14 @@ var init_preloader = __esm(() => {
|
|
|
25462
25933
|
});
|
|
25463
25934
|
|
|
25464
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
|
+
}
|
|
25465
25939
|
function renderErrorScene(state) {
|
|
25466
25940
|
const message2 = state.error?.message ?? "Unknown app error";
|
|
25467
25941
|
const hint = state.error?.hint ?? "Use the actions below to recover.";
|
|
25468
|
-
const
|
|
25942
|
+
const actions = errorActions(state);
|
|
25943
|
+
const selected = Math.max(0, Math.min(actions.length - 1, state.selection.index));
|
|
25469
25944
|
return makeSceneFrame({
|
|
25470
25945
|
scene: "error",
|
|
25471
25946
|
title: "Error",
|
|
@@ -25483,7 +25958,7 @@ function renderErrorScene(state) {
|
|
|
25483
25958
|
...hint ? [line(hint, { fg: RIG_UI.yellow })] : [],
|
|
25484
25959
|
line("", { fg: RIG_UI.ink3 }),
|
|
25485
25960
|
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
25486
|
-
...
|
|
25961
|
+
...actions.map(({ detail, item }, index) => selectableDeckRow({ label: item.label, detail, index, active: selected === index }, item))
|
|
25487
25962
|
],
|
|
25488
25963
|
backgroundColor: RIG_UI.panel,
|
|
25489
25964
|
backgroundAlpha: 184,
|
|
@@ -25500,18 +25975,19 @@ function renderErrorScene(state) {
|
|
|
25500
25975
|
live: true
|
|
25501
25976
|
});
|
|
25502
25977
|
}
|
|
25503
|
-
var ERROR_ACTIONS;
|
|
25978
|
+
var ERROR_ACTIONS, ERROR_REPAIR_LINK_ACTION;
|
|
25504
25979
|
var init_error = __esm(() => {
|
|
25505
25980
|
init_drone();
|
|
25506
25981
|
init_theme2();
|
|
25982
|
+
init_remote_link();
|
|
25507
25983
|
init_scene();
|
|
25508
25984
|
init_selectable();
|
|
25509
25985
|
ERROR_ACTIONS = [
|
|
25510
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" } },
|
|
25511
25987
|
{ detail: "run diagnostics", item: { id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "run diagnostics" } },
|
|
25512
|
-
{ 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" } }
|
|
25513
|
-
{ 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" } }
|
|
25514
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" } };
|
|
25515
25991
|
});
|
|
25516
25992
|
|
|
25517
25993
|
// packages/cli/src/app-opentui/scenes/help.ts
|
|
@@ -25686,7 +26162,7 @@ function configuredMenuRows(selectedIndex2) {
|
|
|
25686
26162
|
}));
|
|
25687
26163
|
}
|
|
25688
26164
|
function onboardingRows(selectedIndex2) {
|
|
25689
|
-
const primary = selectableDeckRow({ label: "
|
|
26165
|
+
const primary = selectableDeckRow({ label: "init", detail: "Start guided init \u2014 recommended", active: selectedIndex2 === 0 }, ONBOARD_PRIMARY);
|
|
25690
26166
|
const secondary = ONBOARD_SECONDARY.map(([label, detail, item], index) => ({
|
|
25691
26167
|
...deckRow({ label, detail, index: index + 1, active: selectedIndex2 === index + 1, activateOnClick: true }),
|
|
25692
26168
|
selectable: item
|
|
@@ -25746,7 +26222,7 @@ function renderMainScene(state, layout) {
|
|
|
25746
26222
|
statusLine(state)
|
|
25747
26223
|
] : [
|
|
25748
26224
|
line("WELCOME", { fg: RIG_UI.ink, bold: true }),
|
|
25749
|
-
line("This project isn't
|
|
26225
|
+
line("This project isn't initialized yet. One native init flow gets you running.", { fg: RIG_UI.ink2 }),
|
|
25750
26226
|
blank(),
|
|
25751
26227
|
line("GET STARTED", { fg: RIG_UI.ink, bold: true }),
|
|
25752
26228
|
...onboardingRows(actionSelected),
|
|
@@ -25787,7 +26263,7 @@ var init_main = __esm(() => {
|
|
|
25787
26263
|
init_theme2();
|
|
25788
26264
|
init_fleet_stats();
|
|
25789
26265
|
CONFIGURED_MENU = [
|
|
25790
|
-
["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" }],
|
|
25791
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" }],
|
|
25792
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" }],
|
|
25793
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" }],
|
|
@@ -25806,10 +26282,10 @@ var init_main = __esm(() => {
|
|
|
25806
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" }]
|
|
25807
26283
|
];
|
|
25808
26284
|
ONBOARD_PRIMARY = {
|
|
25809
|
-
id: "onboard-
|
|
25810
|
-
label: "Start guided
|
|
25811
|
-
intent: { scene: "init", argv: ["init"], action: { kind: "refresh", label: "
|
|
25812
|
-
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"
|
|
25813
26289
|
};
|
|
25814
26290
|
ONBOARD_SECONDARY = [
|
|
25815
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" }],
|
|
@@ -25822,6 +26298,12 @@ var init_main = __esm(() => {
|
|
|
25822
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" };
|
|
25823
26299
|
});
|
|
25824
26300
|
|
|
26301
|
+
// packages/cli/src/app-opentui/pi-pty-host.ts
|
|
26302
|
+
function getActivePiHost() {
|
|
26303
|
+
return null;
|
|
26304
|
+
}
|
|
26305
|
+
function stopActivePiHost(_reason) {}
|
|
26306
|
+
|
|
25825
26307
|
// packages/cli/src/app-opentui/runtime.ts
|
|
25826
26308
|
var exports_runtime = {};
|
|
25827
26309
|
__export(exports_runtime, {
|
|
@@ -25841,7 +26323,7 @@ __export(exports_runtime, {
|
|
|
25841
26323
|
});
|
|
25842
26324
|
import { existsSync as existsSync23 } from "fs";
|
|
25843
26325
|
import { resolve as resolve30 } from "path";
|
|
25844
|
-
import { BoxRenderable as BoxRenderable3, RGBA as
|
|
26326
|
+
import { BoxRenderable as BoxRenderable3, RGBA as RGBA7, StyledText as StyledText3, TextRenderable as TextRenderable4, createCliRenderer } from "@opentui/core";
|
|
25845
26327
|
function inboxPendingCount(state) {
|
|
25846
26328
|
const inbox = state.data.inbox;
|
|
25847
26329
|
if (!inbox || typeof inbox !== "object" || Array.isArray(inbox))
|
|
@@ -25888,7 +26370,7 @@ function entryIntentForScene(scene) {
|
|
|
25888
26370
|
case "doctor":
|
|
25889
26371
|
return { scene, argv: ["doctor"], action: { kind: "doctor-run", label: "Doctor" } };
|
|
25890
26372
|
case "init":
|
|
25891
|
-
return { scene, argv: ["init"], action: { kind: "refresh", label: "
|
|
26373
|
+
return { scene, argv: ["init"], action: { kind: "refresh", label: "Init" } };
|
|
25892
26374
|
case "run-detail":
|
|
25893
26375
|
return { scene, argv: ["run", "status"], action: { kind: "refresh", label: "Run" } };
|
|
25894
26376
|
case "pi":
|
|
@@ -25977,7 +26459,7 @@ function sceneSectionLabel(scene) {
|
|
|
25977
26459
|
handoff: "pi console",
|
|
25978
26460
|
server: "server",
|
|
25979
26461
|
doctor: "doctor",
|
|
25980
|
-
init: "
|
|
26462
|
+
init: "init",
|
|
25981
26463
|
pi: "pi",
|
|
25982
26464
|
plugin: "plugins",
|
|
25983
26465
|
repo: "repo",
|
|
@@ -26010,7 +26492,7 @@ function buildNavStrip(state) {
|
|
|
26010
26492
|
chunks.push(otuiBold(styles.yellow(String(badgeCount))));
|
|
26011
26493
|
}
|
|
26012
26494
|
});
|
|
26013
|
-
return new
|
|
26495
|
+
return new StyledText3(chunks);
|
|
26014
26496
|
}
|
|
26015
26497
|
function requestRender(renderer) {
|
|
26016
26498
|
renderer.requestRender?.();
|
|
@@ -26238,7 +26720,8 @@ async function launchRigOpenTuiApp(options) {
|
|
|
26238
26720
|
},
|
|
26239
26721
|
suspend: () => renderer?.suspend(),
|
|
26240
26722
|
resume: () => {
|
|
26241
|
-
renderer
|
|
26723
|
+
if (renderer)
|
|
26724
|
+
resumeRendererClean(renderer);
|
|
26242
26725
|
renderApp();
|
|
26243
26726
|
},
|
|
26244
26727
|
destroy: () => renderer?.destroy()
|
|
@@ -26466,7 +26949,7 @@ async function launchRigOpenTuiApp(options) {
|
|
|
26466
26949
|
}
|
|
26467
26950
|
for (const adapter of options.adapters ?? [])
|
|
26468
26951
|
await adapter.start?.(runtime);
|
|
26469
|
-
|
|
26952
|
+
connectRigServerEvents(options.projectRoot, {
|
|
26470
26953
|
onSnapshotInvalidated: () => refreshCurrentDataScene(),
|
|
26471
26954
|
onRunLogAppended: () => {
|
|
26472
26955
|
const scene = store.getState().scene;
|
|
@@ -26474,11 +26957,17 @@ async function launchRigOpenTuiApp(options) {
|
|
|
26474
26957
|
refreshCurrentDataScene();
|
|
26475
26958
|
},
|
|
26476
26959
|
onStatus: (status) => store.patch({ footer: { live: liveLinkLabel(status) } })
|
|
26477
|
-
}).
|
|
26478
|
-
|
|
26479
|
-
|
|
26480
|
-
|
|
26960
|
+
}).then((subscription) => {
|
|
26961
|
+
if (destroyed) {
|
|
26962
|
+
subscription.close();
|
|
26963
|
+
return;
|
|
26964
|
+
}
|
|
26965
|
+
liveEvents = subscription;
|
|
26481
26966
|
resources.add(() => liveEvents?.close());
|
|
26967
|
+
}).catch(() => {
|
|
26968
|
+
if (!destroyed)
|
|
26969
|
+
store.patch({ footer: { live: liveLinkLabel("disconnected") } });
|
|
26970
|
+
});
|
|
26482
26971
|
await runtime.runIntent(store.getState().intent);
|
|
26483
26972
|
} catch (error) {
|
|
26484
26973
|
const normalized = normalizeError(error);
|
|
@@ -26664,15 +27153,14 @@ var init_runtime = __esm(() => {
|
|
|
26664
27153
|
init_help();
|
|
26665
27154
|
init_main();
|
|
26666
27155
|
init_selectable();
|
|
26667
|
-
|
|
26668
|
-
PRELOADER_BACKDROP = RGBA8.fromHex(RIG_UI.bg);
|
|
27156
|
+
PRELOADER_BACKDROP = RGBA7.fromHex(RIG_UI.bg);
|
|
26669
27157
|
PRIMARY_NAV = [
|
|
26670
27158
|
{ id: "cockpit", label: "Cockpit", scene: "main", argv: ["main"], enterLabel: "Cockpit", member: ["main"] },
|
|
26671
27159
|
{ id: "runs", label: "Runs", scene: "fleet", argv: ["runs"], enterLabel: "Runs", member: ["fleet", "run-detail", "inspect", "handoff"] },
|
|
26672
27160
|
{ id: "tasks", label: "Tasks", scene: "tasks", argv: ["tasks"], enterLabel: "Tasks", member: ["tasks"] },
|
|
26673
27161
|
{ id: "inbox", label: "Inbox", scene: "inbox", argv: ["inbox"], enterLabel: "Inbox", member: ["inbox"], badge: inboxPendingCount },
|
|
26674
27162
|
{ id: "stats", label: "Stats", scene: "family", argv: ["stats"], enterLabel: "Stats", member: ["family"] },
|
|
26675
|
-
{ id: "
|
|
27163
|
+
{ id: "init", label: "Init", scene: "init", argv: ["init"], enterLabel: "Init", member: ["init", "doctor", "server", "pi", "plugin", "repo", "workspace"] },
|
|
26676
27164
|
{ id: "help", label: "Help", scene: "help", argv: ["help"], enterLabel: "Help", member: ["help"] }
|
|
26677
27165
|
];
|
|
26678
27166
|
SCENE_DATA_KEY = {
|
|
@@ -26782,10 +27270,10 @@ var init_scroll = __esm(() => {
|
|
|
26782
27270
|
// packages/cli/src/app-opentui/react/SceneFrameView.tsx
|
|
26783
27271
|
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
26784
27272
|
import { useRenderer as useRenderer2 } from "@opentui/react";
|
|
26785
|
-
import { TextAttributes as
|
|
27273
|
+
import { TextAttributes as TextAttributes4 } from "@opentui/core";
|
|
26786
27274
|
import { jsxDEV, Fragment } from "@opentui/react/jsx-dev-runtime";
|
|
26787
27275
|
function lineAttributes(line2) {
|
|
26788
|
-
return line2?.bold ?
|
|
27276
|
+
return line2?.bold ? TextAttributes4.BOLD : line2?.dim ? TextAttributes4.DIM : 0;
|
|
26789
27277
|
}
|
|
26790
27278
|
function lineContent(line2) {
|
|
26791
27279
|
return line2.styledText ?? line2.text ?? "";
|
|
@@ -27036,7 +27524,7 @@ var init_nav = __esm(() => {
|
|
|
27036
27524
|
{ id: "tasks", label: "Tasks", scene: "tasks", argv: ["tasks"], enterLabel: "Tasks", member: ["tasks"] },
|
|
27037
27525
|
{ id: "inbox", label: "Inbox", scene: "inbox", argv: ["inbox"], enterLabel: "Inbox", member: ["inbox"], badge: inboxPendingCount2 },
|
|
27038
27526
|
{ id: "stats", label: "Stats", scene: "family", argv: ["stats"], enterLabel: "Stats", member: ["family"] },
|
|
27039
|
-
{ id: "
|
|
27527
|
+
{ id: "init", label: "Init", scene: "init", argv: ["init"], enterLabel: "Init", member: ["init", "doctor", "server", "pi", "plugin", "repo", "workspace"] },
|
|
27040
27528
|
{ id: "help", label: "Help", scene: "help", argv: ["help"], enterLabel: "Help", member: ["help"] }
|
|
27041
27529
|
];
|
|
27042
27530
|
});
|
|
@@ -27168,8 +27656,48 @@ async function launchRigReactApp(options) {
|
|
|
27168
27656
|
const store = createAppStore(initialState);
|
|
27169
27657
|
const events = createAppEventBus();
|
|
27170
27658
|
let renderer = null;
|
|
27659
|
+
let root = null;
|
|
27171
27660
|
let runnerPromise = null;
|
|
27172
27661
|
let suppressHistoryPush = false;
|
|
27662
|
+
let resolveExit = () => {};
|
|
27663
|
+
const appExit = new Promise((resolve31) => {
|
|
27664
|
+
resolveExit = resolve31;
|
|
27665
|
+
});
|
|
27666
|
+
let relaunching = false;
|
|
27667
|
+
const mountRenderer = async () => {
|
|
27668
|
+
renderer = await createCliRenderer2({
|
|
27669
|
+
screenMode: "alternate-screen",
|
|
27670
|
+
exitOnCtrlC: false,
|
|
27671
|
+
targetFps: 30,
|
|
27672
|
+
maxFps: 30,
|
|
27673
|
+
useMouse: true,
|
|
27674
|
+
autoFocus: false,
|
|
27675
|
+
useKittyKeyboard: { disambiguate: true }
|
|
27676
|
+
});
|
|
27677
|
+
renderer.on("destroy", () => {
|
|
27678
|
+
if (!relaunching)
|
|
27679
|
+
resolveExit();
|
|
27680
|
+
});
|
|
27681
|
+
root = createRoot(renderer);
|
|
27682
|
+
root.render(/* @__PURE__ */ jsxDEV4(RigAppProvider, {
|
|
27683
|
+
value: { store, runtime, runAppAction },
|
|
27684
|
+
children: /* @__PURE__ */ jsxDEV4(App, {
|
|
27685
|
+
sceneRenderers: options.sceneRenderers
|
|
27686
|
+
}, undefined, false, undefined, this)
|
|
27687
|
+
}, undefined, false, undefined, this));
|
|
27688
|
+
relaunching = false;
|
|
27689
|
+
};
|
|
27690
|
+
const teardownRenderer = () => {
|
|
27691
|
+
relaunching = true;
|
|
27692
|
+
try {
|
|
27693
|
+
root?.unmount();
|
|
27694
|
+
} catch {}
|
|
27695
|
+
root = null;
|
|
27696
|
+
try {
|
|
27697
|
+
renderer?.destroy();
|
|
27698
|
+
} catch {}
|
|
27699
|
+
renderer = null;
|
|
27700
|
+
};
|
|
27173
27701
|
const runAppAction = (label, action) => {
|
|
27174
27702
|
action().catch((error) => {
|
|
27175
27703
|
const n = normalizeError(error);
|
|
@@ -27211,8 +27739,10 @@ async function launchRigReactApp(options) {
|
|
|
27211
27739
|
runnerPromise ??= options.initializeRuntime();
|
|
27212
27740
|
return runnerPromise;
|
|
27213
27741
|
},
|
|
27214
|
-
suspend: () =>
|
|
27215
|
-
resume: () =>
|
|
27742
|
+
suspend: () => teardownRenderer(),
|
|
27743
|
+
resume: async () => {
|
|
27744
|
+
await mountRenderer();
|
|
27745
|
+
},
|
|
27216
27746
|
destroy: () => renderer?.destroy()
|
|
27217
27747
|
};
|
|
27218
27748
|
events.subscribe((event) => store.patch(reduceAppEvent(store.getState(), event)));
|
|
@@ -27220,15 +27750,7 @@ async function launchRigReactApp(options) {
|
|
|
27220
27750
|
if (typeof tick.unref === "function") {
|
|
27221
27751
|
tick.unref();
|
|
27222
27752
|
}
|
|
27223
|
-
|
|
27224
|
-
screenMode: "alternate-screen",
|
|
27225
|
-
exitOnCtrlC: false,
|
|
27226
|
-
targetFps: 30,
|
|
27227
|
-
maxFps: 30,
|
|
27228
|
-
useMouse: true,
|
|
27229
|
-
autoFocus: false,
|
|
27230
|
-
useKittyKeyboard: { disambiguate: true }
|
|
27231
|
-
});
|
|
27753
|
+
await mountRenderer();
|
|
27232
27754
|
let liveEvents = null;
|
|
27233
27755
|
const canAutoRefresh = (state) => {
|
|
27234
27756
|
if (state.status === "action" || state.status === "loading")
|
|
@@ -27259,12 +27781,6 @@ async function launchRigReactApp(options) {
|
|
|
27259
27781
|
}, FALLBACK_REFRESH_MS);
|
|
27260
27782
|
if (typeof poll.unref === "function")
|
|
27261
27783
|
poll.unref();
|
|
27262
|
-
createRoot(renderer).render(/* @__PURE__ */ jsxDEV4(RigAppProvider, {
|
|
27263
|
-
value: { store, runtime, runAppAction },
|
|
27264
|
-
children: /* @__PURE__ */ jsxDEV4(App, {
|
|
27265
|
-
sceneRenderers: options.sceneRenderers
|
|
27266
|
-
}, undefined, false, undefined, this)
|
|
27267
|
-
}, undefined, false, undefined, this));
|
|
27268
27784
|
queueMicrotask(() => {
|
|
27269
27785
|
(async () => {
|
|
27270
27786
|
try {
|
|
@@ -27274,7 +27790,7 @@ async function launchRigReactApp(options) {
|
|
|
27274
27790
|
}
|
|
27275
27791
|
for (const adapter of options.adapters ?? [])
|
|
27276
27792
|
await adapter.start?.(runtime);
|
|
27277
|
-
|
|
27793
|
+
connectRigServerEvents(options.projectRoot, {
|
|
27278
27794
|
onSnapshotInvalidated: () => refreshCurrentDataScene(),
|
|
27279
27795
|
onRunLogAppended: () => {
|
|
27280
27796
|
const scene = store.getState().scene;
|
|
@@ -27282,9 +27798,11 @@ async function launchRigReactApp(options) {
|
|
|
27282
27798
|
refreshCurrentDataScene();
|
|
27283
27799
|
},
|
|
27284
27800
|
onStatus: (status) => store.patch({ footer: { live: liveLinkLabel(status) } })
|
|
27285
|
-
}).
|
|
27286
|
-
|
|
27801
|
+
}).then((subscription) => {
|
|
27802
|
+
liveEvents = subscription;
|
|
27803
|
+
}).catch(() => {
|
|
27287
27804
|
store.patch({ footer: { live: liveLinkLabel("disconnected") } });
|
|
27805
|
+
});
|
|
27288
27806
|
await runtime.runIntent(store.getState().intent);
|
|
27289
27807
|
} catch (error) {
|
|
27290
27808
|
const n = normalizeError(error);
|
|
@@ -27292,14 +27810,11 @@ async function launchRigReactApp(options) {
|
|
|
27292
27810
|
}
|
|
27293
27811
|
})();
|
|
27294
27812
|
});
|
|
27295
|
-
await
|
|
27296
|
-
|
|
27297
|
-
|
|
27298
|
-
|
|
27299
|
-
|
|
27300
|
-
resolve31();
|
|
27301
|
-
});
|
|
27302
|
-
});
|
|
27813
|
+
await appExit;
|
|
27814
|
+
clearInterval(tick);
|
|
27815
|
+
clearInterval(poll);
|
|
27816
|
+
liveEvents?.close();
|
|
27817
|
+
teardownRenderer();
|
|
27303
27818
|
}
|
|
27304
27819
|
var POLLABLE_SCENES;
|
|
27305
27820
|
var init_launch = __esm(() => {
|
|
@@ -27319,7 +27834,7 @@ __export(exports_bootstrap, {
|
|
|
27319
27834
|
buildAppLaunchOptions: () => buildAppLaunchOptions
|
|
27320
27835
|
});
|
|
27321
27836
|
import { existsSync as existsSync24, readFileSync as readFileSync15 } from "fs";
|
|
27322
|
-
import { basename as
|
|
27837
|
+
import { basename as basename5, resolve as resolve31 } from "path";
|
|
27323
27838
|
async function launchRigOpenTuiBootstrap(options) {
|
|
27324
27839
|
const launchOptions = buildAppLaunchOptions(options);
|
|
27325
27840
|
await launchOpenTuiApp(launchOptions);
|
|
@@ -27425,7 +27940,7 @@ function parsePolicyMode2(value) {
|
|
|
27425
27940
|
function resolveProjectRoot2(input) {
|
|
27426
27941
|
if (input.envProjectRoot)
|
|
27427
27942
|
return resolve31(input.cwd, input.envProjectRoot);
|
|
27428
|
-
const execName =
|
|
27943
|
+
const execName = basename5(input.execPath).toLowerCase();
|
|
27429
27944
|
const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve31(input.execPath, "..", "..")] : [];
|
|
27430
27945
|
const candidates = [input.cwd, ...execCandidates, resolve31(input.importDir, "..")];
|
|
27431
27946
|
for (const candidate of candidates) {
|
|
@@ -27488,7 +28003,7 @@ var init_bootstrap = __esm(() => {
|
|
|
27488
28003
|
// packages/cli/bin/rig.ts
|
|
27489
28004
|
init_launch_routing();
|
|
27490
28005
|
import { existsSync as existsSync25, readFileSync as readFileSync16 } from "fs";
|
|
27491
|
-
import { dirname as
|
|
28006
|
+
import { dirname as dirname6, resolve as resolve32 } from "path";
|
|
27492
28007
|
function packageVersionFrom(startDir) {
|
|
27493
28008
|
let current = resolve32(startDir);
|
|
27494
28009
|
while (true) {
|
|
@@ -27500,7 +28015,7 @@ function packageVersionFrom(startDir) {
|
|
|
27500
28015
|
return pkg.version;
|
|
27501
28016
|
} catch {}
|
|
27502
28017
|
}
|
|
27503
|
-
const parent =
|
|
28018
|
+
const parent = dirname6(current);
|
|
27504
28019
|
if (parent === current)
|
|
27505
28020
|
return null;
|
|
27506
28021
|
current = parent;
|