@h-rig/cli 0.0.6-alpha.82 → 0.0.6-alpha.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/build-rig-binaries.js +40 -8
- package/dist/bin/rig.js +2798 -1440
- package/dist/src/app/board.js +62 -13
- package/dist/src/app-opentui/adapters/command.d.ts +2 -0
- package/dist/src/app-opentui/adapters/command.js +329 -0
- package/dist/src/app-opentui/adapters/common.js +2 -2
- package/dist/src/app-opentui/adapters/doctor.js +63 -14
- package/dist/src/app-opentui/adapters/fleet.js +84 -20
- package/dist/src/app-opentui/adapters/inbox.js +83 -19
- package/dist/src/app-opentui/adapters/init.js +87 -23
- package/dist/src/app-opentui/adapters/pi-attach.js +96 -34
- package/dist/src/app-opentui/adapters/run-detail.js +83 -19
- package/dist/src/app-opentui/adapters/server.js +100 -23
- package/dist/src/app-opentui/adapters/tasks.d.ts +11 -0
- package/dist/src/app-opentui/adapters/tasks.js +742 -94
- package/dist/src/app-opentui/bootstrap.d.ts +1 -6
- package/dist/src/app-opentui/bootstrap.js +13769 -12368
- package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
- package/dist/src/app-opentui/command-pty-host.js +248 -0
- package/dist/src/app-opentui/events.js +1 -1
- package/dist/src/app-opentui/focus-manager.d.ts +14 -0
- package/dist/src/app-opentui/focus-manager.js +24 -0
- package/dist/src/app-opentui/index.js +3802 -2882
- package/dist/src/app-opentui/intent.js +154 -48
- package/dist/src/app-opentui/keymap.d.ts +20 -0
- package/dist/src/app-opentui/keymap.js +707 -0
- package/dist/src/app-opentui/launch-routing.d.ts +16 -0
- package/dist/src/app-opentui/launch-routing.js +55 -0
- package/dist/src/app-opentui/layout.js +2 -2
- package/dist/src/app-opentui/pi-host-child.js +66 -16
- package/dist/src/app-opentui/pi-pty-host.d.ts +9 -0
- package/dist/src/app-opentui/pi-pty-host.js +9 -11
- package/dist/src/app-opentui/registry.js +3231 -2403
- package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
- package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
- package/dist/src/app-opentui/render/graphics.d.ts +1 -1
- package/dist/src/app-opentui/render/graphics.js +131 -16
- package/dist/src/app-opentui/render/image-visual-layer-worker.js +408 -957
- package/dist/src/app-opentui/render/image-visual-layer.d.ts +18 -10
- package/dist/src/app-opentui/render/image-visual-layer.js +386 -356
- package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
- package/dist/src/app-opentui/render/panel-layout.js +48 -0
- package/dist/src/app-opentui/render/panels.d.ts +2 -0
- package/dist/src/app-opentui/render/panels.js +62 -29
- package/dist/src/app-opentui/render/preloader.d.ts +10 -0
- package/dist/src/app-opentui/render/preloader.js +163 -0
- package/dist/src/app-opentui/render/scene.d.ts +3 -0
- package/dist/src/app-opentui/render/scene.js +12 -0
- package/dist/src/app-opentui/render/text.js +5 -1
- package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
- package/dist/src/app-opentui/render/type-bar.js +51 -16
- package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
- package/dist/src/app-opentui/runtime-resources.js +62 -0
- package/dist/src/app-opentui/runtime.js +2322 -1513
- package/dist/src/app-opentui/scenes/command.d.ts +3 -0
- package/dist/src/app-opentui/scenes/command.js +103 -0
- package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
- package/dist/src/app-opentui/scenes/doctor.js +53 -14
- package/dist/src/app-opentui/scenes/error.js +44 -14
- package/dist/src/app-opentui/scenes/fleet.js +40 -21
- package/dist/src/app-opentui/scenes/handoff.js +142 -27
- package/dist/src/app-opentui/scenes/help.js +63 -48
- package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
- package/dist/src/app-opentui/scenes/inbox.js +64 -17
- package/dist/src/app-opentui/scenes/init.d.ts +2 -1
- package/dist/src/app-opentui/scenes/init.js +62 -21
- package/dist/src/app-opentui/scenes/main.d.ts +2 -1
- package/dist/src/app-opentui/scenes/main.js +80 -24
- package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
- package/dist/src/app-opentui/scenes/run-detail.js +39 -25
- package/dist/src/app-opentui/scenes/server.d.ts +2 -1
- package/dist/src/app-opentui/scenes/server.js +71 -20
- package/dist/src/app-opentui/scenes/tasks.js +44 -22
- package/dist/src/app-opentui/state.js +70 -30
- package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
- package/dist/src/app-opentui/terminal-capabilities.js +15 -0
- package/dist/src/app-opentui/types.d.ts +10 -2
- package/dist/src/commands/_doctor-checks.js +62 -13
- package/dist/src/commands/_operator-view.js +63 -13
- package/dist/src/commands/_pi-frontend.js +63 -13
- package/dist/src/commands/_preflight.js +64 -14
- package/dist/src/commands/_server-client.js +82 -18
- package/dist/src/commands/_snapshot-upload.js +62 -13
- package/dist/src/commands/connect.js +7 -1
- package/dist/src/commands/doctor.js +62 -13
- package/dist/src/commands/github.js +144 -23
- package/dist/src/commands/inbox.js +62 -13
- package/dist/src/commands/init.js +82 -18
- package/dist/src/commands/inspect.js +62 -13
- package/dist/src/commands/run.js +66 -13
- package/dist/src/commands/server.js +69 -14
- package/dist/src/commands/setup.js +62 -13
- package/dist/src/commands/stats.js +62 -13
- package/dist/src/commands/task-run-driver.js +62 -13
- package/dist/src/commands/task.js +65 -14
- package/dist/src/commands.js +227 -92
- package/dist/src/index.js +234 -99
- package/package.json +8 -9
- package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
- package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
|
@@ -384,17 +384,21 @@ function cleanToken(value) {
|
|
|
384
384
|
const trimmed = value?.trim();
|
|
385
385
|
return trimmed ? trimmed : null;
|
|
386
386
|
}
|
|
387
|
-
function
|
|
387
|
+
function readRemoteAuthState(projectRoot) {
|
|
388
388
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
389
389
|
if (!existsSync2(path))
|
|
390
390
|
return null;
|
|
391
391
|
try {
|
|
392
392
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
393
|
-
return
|
|
393
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
394
394
|
} catch {
|
|
395
395
|
return null;
|
|
396
396
|
}
|
|
397
397
|
}
|
|
398
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
399
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
400
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
401
|
+
}
|
|
398
402
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
399
403
|
const scopedKey = resolve2(projectRoot);
|
|
400
404
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -405,15 +409,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
405
409
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
406
410
|
}
|
|
407
411
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
408
|
-
const
|
|
409
|
-
|
|
412
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
413
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
414
|
+
}
|
|
415
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
416
|
+
const repo = readRepoConnection(projectRoot);
|
|
417
|
+
const slug = repo?.project?.trim();
|
|
418
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
410
419
|
return null;
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
420
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
421
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
422
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
423
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
415
424
|
return null;
|
|
416
|
-
|
|
425
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
426
|
+
if (!checkoutBaseDir)
|
|
427
|
+
return null;
|
|
428
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
429
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
430
|
+
return inferred;
|
|
417
431
|
}
|
|
418
432
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
419
433
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -424,7 +438,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
424
438
|
if (selected?.connection.kind === "remote") {
|
|
425
439
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
426
440
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
427
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
441
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
428
442
|
return {
|
|
429
443
|
baseUrl: selected.connection.baseUrl,
|
|
430
444
|
authToken,
|
|
@@ -453,7 +467,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
453
467
|
if (!slug)
|
|
454
468
|
return null;
|
|
455
469
|
try {
|
|
456
|
-
const
|
|
470
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
471
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
472
|
+
url.searchParams.set("rt", authToken);
|
|
473
|
+
const response = await fetch(url, {
|
|
457
474
|
headers: mergeHeaders(undefined, authToken)
|
|
458
475
|
});
|
|
459
476
|
if (!response.ok)
|
|
@@ -470,10 +487,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
470
487
|
return null;
|
|
471
488
|
}
|
|
472
489
|
}
|
|
490
|
+
function mergeCookie(existing, name, value) {
|
|
491
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
492
|
+
if (!existing?.trim())
|
|
493
|
+
return encoded;
|
|
494
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
495
|
+
return [...parts, encoded].join("; ");
|
|
496
|
+
}
|
|
497
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
498
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
499
|
+
}
|
|
473
500
|
function mergeHeaders(headers, authToken) {
|
|
474
501
|
const merged = new Headers(headers);
|
|
475
502
|
if (authToken) {
|
|
476
|
-
|
|
503
|
+
const bearer = `Bearer ${authToken}`;
|
|
504
|
+
merged.set("authorization", bearer);
|
|
505
|
+
merged.set("x-auth", bearer);
|
|
506
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
477
507
|
}
|
|
478
508
|
return merged;
|
|
479
509
|
}
|
|
@@ -534,15 +564,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
534
564
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
535
565
|
};
|
|
536
566
|
}
|
|
567
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
568
|
+
try {
|
|
569
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
570
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
571
|
+
} catch {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
576
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
577
|
+
}
|
|
537
578
|
async function requestServerJson(context, pathname, init = {}) {
|
|
538
579
|
const server = await ensureServerForCli(context.projectRoot);
|
|
580
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
581
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
582
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
583
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
584
|
+
}
|
|
539
585
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
540
586
|
if (server.serverProjectRoot)
|
|
541
587
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
588
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
589
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
590
|
+
}
|
|
542
591
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
543
592
|
let response;
|
|
544
593
|
try {
|
|
545
|
-
response = await fetch(
|
|
594
|
+
response = await fetch(requestUrl, {
|
|
546
595
|
...init,
|
|
547
596
|
headers
|
|
548
597
|
});
|
|
@@ -502,17 +502,21 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
|
502
502
|
const scopedKey = resolve2(projectRoot ?? process.cwd());
|
|
503
503
|
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
504
504
|
}
|
|
505
|
-
function
|
|
505
|
+
function readRemoteAuthState(projectRoot) {
|
|
506
506
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
507
507
|
if (!existsSync2(path))
|
|
508
508
|
return null;
|
|
509
509
|
try {
|
|
510
510
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
511
|
-
return
|
|
511
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
512
512
|
} catch {
|
|
513
513
|
return null;
|
|
514
514
|
}
|
|
515
515
|
}
|
|
516
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
517
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
518
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
519
|
+
}
|
|
516
520
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
517
521
|
const scopedKey = resolve2(projectRoot);
|
|
518
522
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -523,15 +527,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
523
527
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
524
528
|
}
|
|
525
529
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
526
|
-
const
|
|
527
|
-
|
|
530
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
531
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
532
|
+
}
|
|
533
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
534
|
+
const repo = readRepoConnection(projectRoot);
|
|
535
|
+
const slug = repo?.project?.trim();
|
|
536
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
528
537
|
return null;
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
538
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
539
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
540
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
541
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
533
542
|
return null;
|
|
534
|
-
|
|
543
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
544
|
+
if (!checkoutBaseDir)
|
|
545
|
+
return null;
|
|
546
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
547
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
548
|
+
return inferred;
|
|
535
549
|
}
|
|
536
550
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
537
551
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -542,7 +556,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
542
556
|
if (selected?.connection.kind === "remote") {
|
|
543
557
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
544
558
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
545
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
559
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
546
560
|
return {
|
|
547
561
|
baseUrl: selected.connection.baseUrl,
|
|
548
562
|
authToken,
|
|
@@ -571,7 +585,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
571
585
|
if (!slug)
|
|
572
586
|
return null;
|
|
573
587
|
try {
|
|
574
|
-
const
|
|
588
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
589
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
590
|
+
url.searchParams.set("rt", authToken);
|
|
591
|
+
const response = await fetch(url, {
|
|
575
592
|
headers: mergeHeaders(undefined, authToken)
|
|
576
593
|
});
|
|
577
594
|
if (!response.ok)
|
|
@@ -588,10 +605,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
588
605
|
return null;
|
|
589
606
|
}
|
|
590
607
|
}
|
|
608
|
+
function mergeCookie(existing, name, value) {
|
|
609
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
610
|
+
if (!existing?.trim())
|
|
611
|
+
return encoded;
|
|
612
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
613
|
+
return [...parts, encoded].join("; ");
|
|
614
|
+
}
|
|
615
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
616
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
617
|
+
}
|
|
591
618
|
function mergeHeaders(headers, authToken) {
|
|
592
619
|
const merged = new Headers(headers);
|
|
593
620
|
if (authToken) {
|
|
594
|
-
|
|
621
|
+
const bearer = `Bearer ${authToken}`;
|
|
622
|
+
merged.set("authorization", bearer);
|
|
623
|
+
merged.set("x-auth", bearer);
|
|
624
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
595
625
|
}
|
|
596
626
|
return merged;
|
|
597
627
|
}
|
|
@@ -652,15 +682,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
652
682
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
653
683
|
};
|
|
654
684
|
}
|
|
685
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
686
|
+
try {
|
|
687
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
688
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
689
|
+
} catch {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
694
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
695
|
+
}
|
|
655
696
|
async function requestServerJson(context, pathname, init = {}) {
|
|
656
697
|
const server = await ensureServerForCli(context.projectRoot);
|
|
698
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
699
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
700
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
701
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
702
|
+
}
|
|
657
703
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
658
704
|
if (server.serverProjectRoot)
|
|
659
705
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
706
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
707
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
708
|
+
}
|
|
660
709
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
661
710
|
let response;
|
|
662
711
|
try {
|
|
663
|
-
response = await fetch(
|
|
712
|
+
response = await fetch(requestUrl, {
|
|
664
713
|
...init,
|
|
665
714
|
headers
|
|
666
715
|
});
|
|
@@ -689,11 +738,26 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
|
|
|
689
738
|
return payload;
|
|
690
739
|
}
|
|
691
740
|
async function postGitHubTokenViaServer(context, token, options = {}) {
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
741
|
+
const server = await ensureServerForCli(context.projectRoot);
|
|
742
|
+
const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
|
|
743
|
+
reportServerPhase("POST /api/github/auth/token\u2026");
|
|
744
|
+
let response;
|
|
745
|
+
try {
|
|
746
|
+
response = await fetch(requestUrl, {
|
|
747
|
+
method: "POST",
|
|
748
|
+
headers: { "content-type": "application/json" },
|
|
749
|
+
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
|
|
750
|
+
});
|
|
751
|
+
} catch (error) {
|
|
752
|
+
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
753
|
+
throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
|
|
754
|
+
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
755
|
+
}
|
|
756
|
+
const payload = await response.json().catch(() => null);
|
|
757
|
+
if (!response.ok) {
|
|
758
|
+
const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
|
|
759
|
+
throw new CliError(`Rig server auth bootstrap failed (${response.status}): ${detail}`, 1, { hint: "Re-run `rig github auth import-gh`, or check the selected server with `rig server status`." });
|
|
760
|
+
}
|
|
697
761
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
698
762
|
}
|
|
699
763
|
async function prepareRemoteCheckoutViaServer(context, input) {
|
|
@@ -180,17 +180,21 @@ function cleanToken(value) {
|
|
|
180
180
|
const trimmed = value?.trim();
|
|
181
181
|
return trimmed ? trimmed : null;
|
|
182
182
|
}
|
|
183
|
-
function
|
|
183
|
+
function readRemoteAuthState(projectRoot) {
|
|
184
184
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
185
185
|
if (!existsSync2(path))
|
|
186
186
|
return null;
|
|
187
187
|
try {
|
|
188
188
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
189
|
-
return
|
|
189
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
190
190
|
} catch {
|
|
191
191
|
return null;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
195
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
196
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
197
|
+
}
|
|
194
198
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
195
199
|
const scopedKey = resolve2(projectRoot);
|
|
196
200
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -201,15 +205,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
201
205
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
202
206
|
}
|
|
203
207
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
204
|
-
const
|
|
205
|
-
|
|
208
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
209
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
210
|
+
}
|
|
211
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
212
|
+
const repo = readRepoConnection(projectRoot);
|
|
213
|
+
const slug = repo?.project?.trim();
|
|
214
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
206
215
|
return null;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
217
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
218
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
219
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
211
220
|
return null;
|
|
212
|
-
|
|
221
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
222
|
+
if (!checkoutBaseDir)
|
|
223
|
+
return null;
|
|
224
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
225
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
226
|
+
return inferred;
|
|
213
227
|
}
|
|
214
228
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
215
229
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -220,7 +234,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
220
234
|
if (selected?.connection.kind === "remote") {
|
|
221
235
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
222
236
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
223
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
237
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
224
238
|
return {
|
|
225
239
|
baseUrl: selected.connection.baseUrl,
|
|
226
240
|
authToken,
|
|
@@ -249,7 +263,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
249
263
|
if (!slug)
|
|
250
264
|
return null;
|
|
251
265
|
try {
|
|
252
|
-
const
|
|
266
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
267
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
268
|
+
url.searchParams.set("rt", authToken);
|
|
269
|
+
const response = await fetch(url, {
|
|
253
270
|
headers: mergeHeaders(undefined, authToken)
|
|
254
271
|
});
|
|
255
272
|
if (!response.ok)
|
|
@@ -266,10 +283,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
266
283
|
return null;
|
|
267
284
|
}
|
|
268
285
|
}
|
|
286
|
+
function mergeCookie(existing, name, value) {
|
|
287
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
288
|
+
if (!existing?.trim())
|
|
289
|
+
return encoded;
|
|
290
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
291
|
+
return [...parts, encoded].join("; ");
|
|
292
|
+
}
|
|
293
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
294
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
295
|
+
}
|
|
269
296
|
function mergeHeaders(headers, authToken) {
|
|
270
297
|
const merged = new Headers(headers);
|
|
271
298
|
if (authToken) {
|
|
272
|
-
|
|
299
|
+
const bearer = `Bearer ${authToken}`;
|
|
300
|
+
merged.set("authorization", bearer);
|
|
301
|
+
merged.set("x-auth", bearer);
|
|
302
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
273
303
|
}
|
|
274
304
|
return merged;
|
|
275
305
|
}
|
|
@@ -330,15 +360,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
330
360
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
331
361
|
};
|
|
332
362
|
}
|
|
363
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
364
|
+
try {
|
|
365
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
366
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
367
|
+
} catch {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
372
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
373
|
+
}
|
|
333
374
|
async function requestServerJson(context, pathname, init = {}) {
|
|
334
375
|
const server = await ensureServerForCli(context.projectRoot);
|
|
376
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
377
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
378
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
379
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
380
|
+
}
|
|
335
381
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
336
382
|
if (server.serverProjectRoot)
|
|
337
383
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
384
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
385
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
386
|
+
}
|
|
338
387
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
339
388
|
let response;
|
|
340
389
|
try {
|
|
341
|
-
response = await fetch(
|
|
390
|
+
response = await fetch(requestUrl, {
|
|
342
391
|
...init,
|
|
343
392
|
headers
|
|
344
393
|
});
|
package/dist/src/commands/run.js
CHANGED
|
@@ -205,17 +205,21 @@ function cleanToken(value) {
|
|
|
205
205
|
const trimmed = value?.trim();
|
|
206
206
|
return trimmed ? trimmed : null;
|
|
207
207
|
}
|
|
208
|
-
function
|
|
208
|
+
function readRemoteAuthState(projectRoot) {
|
|
209
209
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
210
210
|
if (!existsSync2(path))
|
|
211
211
|
return null;
|
|
212
212
|
try {
|
|
213
213
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
214
|
-
return
|
|
214
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
215
215
|
} catch {
|
|
216
216
|
return null;
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
220
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
221
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
222
|
+
}
|
|
219
223
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
220
224
|
const scopedKey = resolve2(projectRoot);
|
|
221
225
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -226,15 +230,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
226
230
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
227
231
|
}
|
|
228
232
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
229
|
-
const
|
|
230
|
-
|
|
233
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
234
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
235
|
+
}
|
|
236
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
237
|
+
const repo = readRepoConnection(projectRoot);
|
|
238
|
+
const slug = repo?.project?.trim();
|
|
239
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
231
240
|
return null;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
241
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
242
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
243
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
244
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
236
245
|
return null;
|
|
237
|
-
|
|
246
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
247
|
+
if (!checkoutBaseDir)
|
|
248
|
+
return null;
|
|
249
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
250
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
251
|
+
return inferred;
|
|
238
252
|
}
|
|
239
253
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
240
254
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -245,7 +259,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
245
259
|
if (selected?.connection.kind === "remote") {
|
|
246
260
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
247
261
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
248
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
262
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
249
263
|
return {
|
|
250
264
|
baseUrl: selected.connection.baseUrl,
|
|
251
265
|
authToken,
|
|
@@ -274,7 +288,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
274
288
|
if (!slug)
|
|
275
289
|
return null;
|
|
276
290
|
try {
|
|
277
|
-
const
|
|
291
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
292
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
293
|
+
url.searchParams.set("rt", authToken);
|
|
294
|
+
const response = await fetch(url, {
|
|
278
295
|
headers: mergeHeaders(undefined, authToken)
|
|
279
296
|
});
|
|
280
297
|
if (!response.ok)
|
|
@@ -291,10 +308,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
291
308
|
return null;
|
|
292
309
|
}
|
|
293
310
|
}
|
|
311
|
+
function mergeCookie(existing, name, value) {
|
|
312
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
313
|
+
if (!existing?.trim())
|
|
314
|
+
return encoded;
|
|
315
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
316
|
+
return [...parts, encoded].join("; ");
|
|
317
|
+
}
|
|
318
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
319
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
320
|
+
}
|
|
294
321
|
function mergeHeaders(headers, authToken) {
|
|
295
322
|
const merged = new Headers(headers);
|
|
296
323
|
if (authToken) {
|
|
297
|
-
|
|
324
|
+
const bearer = `Bearer ${authToken}`;
|
|
325
|
+
merged.set("authorization", bearer);
|
|
326
|
+
merged.set("x-auth", bearer);
|
|
327
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
298
328
|
}
|
|
299
329
|
return merged;
|
|
300
330
|
}
|
|
@@ -355,15 +385,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
355
385
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
356
386
|
};
|
|
357
387
|
}
|
|
388
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
389
|
+
try {
|
|
390
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
391
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
392
|
+
} catch {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
397
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
398
|
+
}
|
|
358
399
|
async function requestServerJson(context, pathname, init = {}) {
|
|
359
400
|
const server = await ensureServerForCli(context.projectRoot);
|
|
401
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
402
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
403
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
404
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
405
|
+
}
|
|
360
406
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
361
407
|
if (server.serverProjectRoot)
|
|
362
408
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
409
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
410
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
411
|
+
}
|
|
363
412
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
364
413
|
let response;
|
|
365
414
|
try {
|
|
366
|
-
response = await fetch(
|
|
415
|
+
response = await fetch(requestUrl, {
|
|
367
416
|
...init,
|
|
368
417
|
headers
|
|
369
418
|
});
|
|
@@ -1181,6 +1230,7 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
1181
1230
|
let detached = false;
|
|
1182
1231
|
try {
|
|
1183
1232
|
await runPiMain([
|
|
1233
|
+
"--offline",
|
|
1184
1234
|
"--no-extensions",
|
|
1185
1235
|
"--no-skills",
|
|
1186
1236
|
"--no-prompt-templates",
|
|
@@ -1991,6 +2041,9 @@ async function executeRun(context, args) {
|
|
|
1991
2041
|
console.log(`Stop requested: ${runId}`);
|
|
1992
2042
|
return { ok: true, group: "run", command, details: stopped };
|
|
1993
2043
|
}
|
|
2044
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
2045
|
+
throw new CliError("Remote run stop requires an explicit run id.", 2, { hint: "Run `rig run list`, then `rig run stop <run-id>`." });
|
|
2046
|
+
}
|
|
1994
2047
|
const result = await runStop(context.projectRoot);
|
|
1995
2048
|
if (result.remaining.length > 0) {
|
|
1996
2049
|
throw new CliError(`Failed to stop run(s): ${result.remaining.join(", ")}`, 1, { hint: "Check `rig run status`, then retry `rig run stop <run-id>` for the remaining runs." });
|