@h-rig/cli 0.0.6-alpha.45 → 0.0.6-alpha.47
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 +51 -22
- package/dist/src/commands/_connection-state.js +11 -3
- package/dist/src/commands/_doctor-checks.js +52 -7
- package/dist/src/commands/_operator-view.js +54 -7
- package/dist/src/commands/_pi-frontend.js +54 -7
- package/dist/src/commands/_pi-remote-session.js +54 -7
- package/dist/src/commands/_pi-worker-bridge-extension.js +54 -7
- package/dist/src/commands/_preflight.js +52 -7
- package/dist/src/commands/_server-client.js +59 -22
- package/dist/src/commands/_snapshot-upload.js +52 -7
- package/dist/src/commands/connect.js +2 -1
- package/dist/src/commands/doctor.js +52 -7
- package/dist/src/commands/github.js +52 -7
- package/dist/src/commands/inbox.js +52 -7
- package/dist/src/commands/init.js +49 -22
- package/dist/src/commands/inspect.js +52 -7
- package/dist/src/commands/run.js +54 -7
- package/dist/src/commands/server.js +44 -7
- package/dist/src/commands/setup.js +52 -7
- package/dist/src/commands/task-run-driver.js +52 -7
- package/dist/src/commands/task.js +54 -7
- package/dist/src/commands.js +51 -22
- package/dist/src/index.js +51 -22
- package/package.json +6 -6
|
@@ -146,7 +146,8 @@ function readRepoConnection(projectRoot) {
|
|
|
146
146
|
return {
|
|
147
147
|
selected,
|
|
148
148
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
149
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
149
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
150
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
150
151
|
};
|
|
151
152
|
}
|
|
152
153
|
function writeRepoConnection(projectRoot, state) {
|
|
@@ -157,13 +158,19 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
157
158
|
if (!repo)
|
|
158
159
|
return null;
|
|
159
160
|
if (repo.selected === "local")
|
|
160
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
161
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
161
162
|
const global = readGlobalConnections(options);
|
|
162
163
|
const connection = global.connections[repo.selected];
|
|
163
164
|
if (!connection) {
|
|
164
165
|
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
165
166
|
}
|
|
166
|
-
return { alias: repo.selected, connection };
|
|
167
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
168
|
+
}
|
|
169
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
170
|
+
const repo = readRepoConnection(projectRoot);
|
|
171
|
+
if (!repo)
|
|
172
|
+
return;
|
|
173
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
167
174
|
}
|
|
168
175
|
|
|
169
176
|
// packages/cli/src/commands/_cli-format.ts
|
|
@@ -374,17 +381,21 @@ async function ensureServerForCli(projectRoot) {
|
|
|
374
381
|
try {
|
|
375
382
|
const selected = resolveSelectedConnection(projectRoot);
|
|
376
383
|
if (selected?.connection.kind === "remote") {
|
|
384
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
385
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
377
386
|
return {
|
|
378
387
|
baseUrl: selected.connection.baseUrl,
|
|
379
|
-
authToken
|
|
380
|
-
connectionKind: "remote"
|
|
388
|
+
authToken,
|
|
389
|
+
connectionKind: "remote",
|
|
390
|
+
serverProjectRoot
|
|
381
391
|
};
|
|
382
392
|
}
|
|
383
393
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
384
394
|
return {
|
|
385
395
|
baseUrl: connection.baseUrl,
|
|
386
396
|
authToken: connection.authToken,
|
|
387
|
-
connectionKind: "local"
|
|
397
|
+
connectionKind: "local",
|
|
398
|
+
serverProjectRoot: resolve2(projectRoot)
|
|
388
399
|
};
|
|
389
400
|
} catch (error) {
|
|
390
401
|
if (error instanceof Error) {
|
|
@@ -393,6 +404,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
393
404
|
throw error;
|
|
394
405
|
}
|
|
395
406
|
}
|
|
407
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
408
|
+
const repo = readRepoConnection(projectRoot);
|
|
409
|
+
const slug = repo?.project?.trim();
|
|
410
|
+
if (!slug)
|
|
411
|
+
return null;
|
|
412
|
+
try {
|
|
413
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
414
|
+
headers: mergeHeaders(undefined, authToken)
|
|
415
|
+
});
|
|
416
|
+
if (!response.ok)
|
|
417
|
+
return null;
|
|
418
|
+
const payload = await response.json();
|
|
419
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
420
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
421
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
422
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
423
|
+
if (path)
|
|
424
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
425
|
+
return path;
|
|
426
|
+
} catch {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
396
430
|
function mergeHeaders(headers, authToken) {
|
|
397
431
|
const merged = new Headers(headers);
|
|
398
432
|
if (authToken) {
|
|
@@ -417,9 +451,12 @@ function diagnosticMessage(payload) {
|
|
|
417
451
|
}
|
|
418
452
|
async function requestServerJson(context, pathname, init = {}) {
|
|
419
453
|
const server = await ensureServerForCli(context.projectRoot);
|
|
454
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
455
|
+
if (server.serverProjectRoot)
|
|
456
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
420
457
|
const response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
421
458
|
...init,
|
|
422
|
-
headers
|
|
459
|
+
headers
|
|
423
460
|
});
|
|
424
461
|
const text = await response.text();
|
|
425
462
|
const payload = text.trim().length > 0 ? (() => {
|
|
@@ -199,6 +199,11 @@ function readJsonFile(path) {
|
|
|
199
199
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
+
function writeJsonFile(path, value) {
|
|
203
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
204
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
205
|
+
`, "utf8");
|
|
206
|
+
}
|
|
202
207
|
function normalizeConnection(value) {
|
|
203
208
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
204
209
|
return null;
|
|
@@ -239,21 +244,31 @@ function readRepoConnection(projectRoot) {
|
|
|
239
244
|
return {
|
|
240
245
|
selected,
|
|
241
246
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
242
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
247
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
248
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
243
249
|
};
|
|
244
250
|
}
|
|
251
|
+
function writeRepoConnection(projectRoot, state) {
|
|
252
|
+
writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
|
|
253
|
+
}
|
|
245
254
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
246
255
|
const repo = readRepoConnection(projectRoot);
|
|
247
256
|
if (!repo)
|
|
248
257
|
return null;
|
|
249
258
|
if (repo.selected === "local")
|
|
250
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
259
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
251
260
|
const global = readGlobalConnections(options);
|
|
252
261
|
const connection = global.connections[repo.selected];
|
|
253
262
|
if (!connection) {
|
|
254
263
|
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
255
264
|
}
|
|
256
|
-
return { alias: repo.selected, connection };
|
|
265
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
266
|
+
}
|
|
267
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
268
|
+
const repo = readRepoConnection(projectRoot);
|
|
269
|
+
if (!repo)
|
|
270
|
+
return;
|
|
271
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
257
272
|
}
|
|
258
273
|
|
|
259
274
|
// packages/cli/src/commands/_server-client.ts
|
|
@@ -289,17 +304,21 @@ async function ensureServerForCli(projectRoot) {
|
|
|
289
304
|
try {
|
|
290
305
|
const selected = resolveSelectedConnection(projectRoot);
|
|
291
306
|
if (selected?.connection.kind === "remote") {
|
|
307
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
308
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
292
309
|
return {
|
|
293
310
|
baseUrl: selected.connection.baseUrl,
|
|
294
|
-
authToken
|
|
295
|
-
connectionKind: "remote"
|
|
311
|
+
authToken,
|
|
312
|
+
connectionKind: "remote",
|
|
313
|
+
serverProjectRoot
|
|
296
314
|
};
|
|
297
315
|
}
|
|
298
316
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
299
317
|
return {
|
|
300
318
|
baseUrl: connection.baseUrl,
|
|
301
319
|
authToken: connection.authToken,
|
|
302
|
-
connectionKind: "local"
|
|
320
|
+
connectionKind: "local",
|
|
321
|
+
serverProjectRoot: resolve4(projectRoot)
|
|
303
322
|
};
|
|
304
323
|
} catch (error) {
|
|
305
324
|
if (error instanceof Error) {
|
|
@@ -308,6 +327,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
308
327
|
throw error;
|
|
309
328
|
}
|
|
310
329
|
}
|
|
330
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
331
|
+
const repo = readRepoConnection(projectRoot);
|
|
332
|
+
const slug = repo?.project?.trim();
|
|
333
|
+
if (!slug)
|
|
334
|
+
return null;
|
|
335
|
+
try {
|
|
336
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
337
|
+
headers: mergeHeaders(undefined, authToken)
|
|
338
|
+
});
|
|
339
|
+
if (!response.ok)
|
|
340
|
+
return null;
|
|
341
|
+
const payload = await response.json();
|
|
342
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
343
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
344
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
345
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
346
|
+
if (path)
|
|
347
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
348
|
+
return path;
|
|
349
|
+
} catch {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
311
353
|
function mergeHeaders(headers, authToken) {
|
|
312
354
|
const merged = new Headers(headers);
|
|
313
355
|
if (authToken) {
|
|
@@ -332,9 +374,12 @@ function diagnosticMessage(payload) {
|
|
|
332
374
|
}
|
|
333
375
|
async function requestServerJson(context, pathname, init = {}) {
|
|
334
376
|
const server = await ensureServerForCli(context.projectRoot);
|
|
377
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
378
|
+
if (server.serverProjectRoot)
|
|
379
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
335
380
|
const response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
336
381
|
...init,
|
|
337
|
-
headers
|
|
382
|
+
headers
|
|
338
383
|
});
|
|
339
384
|
const text = await response.text();
|
|
340
385
|
const payload = text.trim().length > 0 ? (() => {
|
|
@@ -418,6 +418,11 @@ function readJsonFile(path) {
|
|
|
418
418
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
|
+
function writeJsonFile3(path, value) {
|
|
422
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
423
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
424
|
+
`, "utf8");
|
|
425
|
+
}
|
|
421
426
|
function normalizeConnection(value) {
|
|
422
427
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
423
428
|
return null;
|
|
@@ -458,21 +463,31 @@ function readRepoConnection(projectRoot) {
|
|
|
458
463
|
return {
|
|
459
464
|
selected,
|
|
460
465
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
461
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
466
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
467
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
462
468
|
};
|
|
463
469
|
}
|
|
470
|
+
function writeRepoConnection(projectRoot, state) {
|
|
471
|
+
writeJsonFile3(resolveRepoConnectionPath(projectRoot), state);
|
|
472
|
+
}
|
|
464
473
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
465
474
|
const repo = readRepoConnection(projectRoot);
|
|
466
475
|
if (!repo)
|
|
467
476
|
return null;
|
|
468
477
|
if (repo.selected === "local")
|
|
469
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
478
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
470
479
|
const global = readGlobalConnections(options);
|
|
471
480
|
const connection = global.connections[repo.selected];
|
|
472
481
|
if (!connection) {
|
|
473
482
|
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
474
483
|
}
|
|
475
|
-
return { alias: repo.selected, connection };
|
|
484
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
485
|
+
}
|
|
486
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
487
|
+
const repo = readRepoConnection(projectRoot);
|
|
488
|
+
if (!repo)
|
|
489
|
+
return;
|
|
490
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
476
491
|
}
|
|
477
492
|
|
|
478
493
|
// packages/cli/src/commands/_server-client.ts
|
|
@@ -505,17 +520,21 @@ async function ensureServerForCli(projectRoot) {
|
|
|
505
520
|
try {
|
|
506
521
|
const selected = resolveSelectedConnection(projectRoot);
|
|
507
522
|
if (selected?.connection.kind === "remote") {
|
|
523
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
524
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
508
525
|
return {
|
|
509
526
|
baseUrl: selected.connection.baseUrl,
|
|
510
|
-
authToken
|
|
511
|
-
connectionKind: "remote"
|
|
527
|
+
authToken,
|
|
528
|
+
connectionKind: "remote",
|
|
529
|
+
serverProjectRoot
|
|
512
530
|
};
|
|
513
531
|
}
|
|
514
532
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
515
533
|
return {
|
|
516
534
|
baseUrl: connection.baseUrl,
|
|
517
535
|
authToken: connection.authToken,
|
|
518
|
-
connectionKind: "local"
|
|
536
|
+
connectionKind: "local",
|
|
537
|
+
serverProjectRoot: resolve5(projectRoot)
|
|
519
538
|
};
|
|
520
539
|
} catch (error) {
|
|
521
540
|
if (error instanceof Error) {
|
|
@@ -524,6 +543,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
524
543
|
throw error;
|
|
525
544
|
}
|
|
526
545
|
}
|
|
546
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
547
|
+
const repo = readRepoConnection(projectRoot);
|
|
548
|
+
const slug = repo?.project?.trim();
|
|
549
|
+
if (!slug)
|
|
550
|
+
return null;
|
|
551
|
+
try {
|
|
552
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
553
|
+
headers: mergeHeaders(undefined, authToken)
|
|
554
|
+
});
|
|
555
|
+
if (!response.ok)
|
|
556
|
+
return null;
|
|
557
|
+
const payload = await response.json();
|
|
558
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
559
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
560
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
561
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
562
|
+
if (path)
|
|
563
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
564
|
+
return path;
|
|
565
|
+
} catch {
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
527
569
|
function mergeHeaders(headers, authToken) {
|
|
528
570
|
const merged = new Headers(headers);
|
|
529
571
|
if (authToken) {
|
|
@@ -548,9 +590,12 @@ function diagnosticMessage(payload) {
|
|
|
548
590
|
}
|
|
549
591
|
async function requestServerJson(context, pathname, init = {}) {
|
|
550
592
|
const server = await ensureServerForCli(context.projectRoot);
|
|
593
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
594
|
+
if (server.serverProjectRoot)
|
|
595
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
551
596
|
const response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
552
597
|
...init,
|
|
553
|
-
headers
|
|
598
|
+
headers
|
|
554
599
|
});
|
|
555
600
|
const text = await response.text();
|
|
556
601
|
const payload = text.trim().length > 0 ? (() => {
|
|
@@ -128,6 +128,11 @@ function readJsonFile(path) {
|
|
|
128
128
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
+
function writeJsonFile2(path, value) {
|
|
132
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
133
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
134
|
+
`, "utf8");
|
|
135
|
+
}
|
|
131
136
|
function normalizeConnection(value) {
|
|
132
137
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
133
138
|
return null;
|
|
@@ -168,21 +173,31 @@ function readRepoConnection(projectRoot) {
|
|
|
168
173
|
return {
|
|
169
174
|
selected,
|
|
170
175
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
171
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
176
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
177
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
172
178
|
};
|
|
173
179
|
}
|
|
180
|
+
function writeRepoConnection(projectRoot, state) {
|
|
181
|
+
writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
|
|
182
|
+
}
|
|
174
183
|
function resolveSelectedConnection(projectRoot, options = {}) {
|
|
175
184
|
const repo = readRepoConnection(projectRoot);
|
|
176
185
|
if (!repo)
|
|
177
186
|
return null;
|
|
178
187
|
if (repo.selected === "local")
|
|
179
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
188
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
180
189
|
const global = readGlobalConnections(options);
|
|
181
190
|
const connection = global.connections[repo.selected];
|
|
182
191
|
if (!connection) {
|
|
183
192
|
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
184
193
|
}
|
|
185
|
-
return { alias: repo.selected, connection };
|
|
194
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
195
|
+
}
|
|
196
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
197
|
+
const repo = readRepoConnection(projectRoot);
|
|
198
|
+
if (!repo)
|
|
199
|
+
return;
|
|
200
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
186
201
|
}
|
|
187
202
|
|
|
188
203
|
// packages/cli/src/commands/_server-client.ts
|
|
@@ -218,17 +233,21 @@ async function ensureServerForCli(projectRoot) {
|
|
|
218
233
|
try {
|
|
219
234
|
const selected = resolveSelectedConnection(projectRoot);
|
|
220
235
|
if (selected?.connection.kind === "remote") {
|
|
236
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
237
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
221
238
|
return {
|
|
222
239
|
baseUrl: selected.connection.baseUrl,
|
|
223
|
-
authToken
|
|
224
|
-
connectionKind: "remote"
|
|
240
|
+
authToken,
|
|
241
|
+
connectionKind: "remote",
|
|
242
|
+
serverProjectRoot
|
|
225
243
|
};
|
|
226
244
|
}
|
|
227
245
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
228
246
|
return {
|
|
229
247
|
baseUrl: connection.baseUrl,
|
|
230
248
|
authToken: connection.authToken,
|
|
231
|
-
connectionKind: "local"
|
|
249
|
+
connectionKind: "local",
|
|
250
|
+
serverProjectRoot: resolve2(projectRoot)
|
|
232
251
|
};
|
|
233
252
|
} catch (error) {
|
|
234
253
|
if (error instanceof Error) {
|
|
@@ -237,6 +256,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
237
256
|
throw error;
|
|
238
257
|
}
|
|
239
258
|
}
|
|
259
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
260
|
+
const repo = readRepoConnection(projectRoot);
|
|
261
|
+
const slug = repo?.project?.trim();
|
|
262
|
+
if (!slug)
|
|
263
|
+
return null;
|
|
264
|
+
try {
|
|
265
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
266
|
+
headers: mergeHeaders(undefined, authToken)
|
|
267
|
+
});
|
|
268
|
+
if (!response.ok)
|
|
269
|
+
return null;
|
|
270
|
+
const payload = await response.json();
|
|
271
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
272
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
273
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
274
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
275
|
+
if (path)
|
|
276
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
277
|
+
return path;
|
|
278
|
+
} catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
240
282
|
function appendTaskFilterParams(url, filters) {
|
|
241
283
|
if (filters.assignee)
|
|
242
284
|
url.searchParams.set("assignee", filters.assignee);
|
|
@@ -271,9 +313,12 @@ function diagnosticMessage(payload) {
|
|
|
271
313
|
}
|
|
272
314
|
async function requestServerJson(context, pathname, init = {}) {
|
|
273
315
|
const server = await ensureServerForCli(context.projectRoot);
|
|
316
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
317
|
+
if (server.serverProjectRoot)
|
|
318
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
274
319
|
const response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
275
320
|
...init,
|
|
276
|
-
headers
|
|
321
|
+
headers
|
|
277
322
|
});
|
|
278
323
|
const text = await response.text();
|
|
279
324
|
const payload = text.trim().length > 0 ? (() => {
|
|
@@ -419,6 +464,8 @@ async function buildRunPiEventsWebSocketUrl(context, runId) {
|
|
|
419
464
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
420
465
|
if (server.authToken)
|
|
421
466
|
url.searchParams.set("token", server.authToken);
|
|
467
|
+
if (server.serverProjectRoot)
|
|
468
|
+
url.searchParams.set("rigProjectRoot", server.serverProjectRoot);
|
|
422
469
|
return url.toString();
|
|
423
470
|
}
|
|
424
471
|
async function submitTaskRunViaServer(context, input) {
|
package/dist/src/commands.js
CHANGED
|
@@ -2694,7 +2694,8 @@ function readRepoConnection(projectRoot) {
|
|
|
2694
2694
|
return {
|
|
2695
2695
|
selected,
|
|
2696
2696
|
project: typeof record.project === "string" ? record.project : undefined,
|
|
2697
|
-
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
|
|
2697
|
+
linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
|
|
2698
|
+
serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
|
|
2698
2699
|
};
|
|
2699
2700
|
}
|
|
2700
2701
|
function writeRepoConnection(projectRoot, state) {
|
|
@@ -2705,13 +2706,19 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
2705
2706
|
if (!repo)
|
|
2706
2707
|
return null;
|
|
2707
2708
|
if (repo.selected === "local")
|
|
2708
|
-
return { alias: "local", connection: { kind: "local", mode: "auto" } };
|
|
2709
|
+
return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
|
|
2709
2710
|
const global = readGlobalConnections(options);
|
|
2710
2711
|
const connection = global.connections[repo.selected];
|
|
2711
2712
|
if (!connection) {
|
|
2712
2713
|
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
2713
2714
|
}
|
|
2714
|
-
return { alias: repo.selected, connection };
|
|
2715
|
+
return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
|
|
2716
|
+
}
|
|
2717
|
+
function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
|
|
2718
|
+
const repo = readRepoConnection(projectRoot);
|
|
2719
|
+
if (!repo)
|
|
2720
|
+
return;
|
|
2721
|
+
writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
|
|
2715
2722
|
}
|
|
2716
2723
|
|
|
2717
2724
|
// packages/cli/src/commands/_server-client.ts
|
|
@@ -2752,17 +2759,21 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2752
2759
|
try {
|
|
2753
2760
|
const selected = resolveSelectedConnection(projectRoot);
|
|
2754
2761
|
if (selected?.connection.kind === "remote") {
|
|
2762
|
+
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
2763
|
+
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
2755
2764
|
return {
|
|
2756
2765
|
baseUrl: selected.connection.baseUrl,
|
|
2757
|
-
authToken
|
|
2758
|
-
connectionKind: "remote"
|
|
2766
|
+
authToken,
|
|
2767
|
+
connectionKind: "remote",
|
|
2768
|
+
serverProjectRoot
|
|
2759
2769
|
};
|
|
2760
2770
|
}
|
|
2761
2771
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
2762
2772
|
return {
|
|
2763
2773
|
baseUrl: connection.baseUrl,
|
|
2764
2774
|
authToken: connection.authToken,
|
|
2765
|
-
connectionKind: "local"
|
|
2775
|
+
connectionKind: "local",
|
|
2776
|
+
serverProjectRoot: resolve10(projectRoot)
|
|
2766
2777
|
};
|
|
2767
2778
|
} catch (error) {
|
|
2768
2779
|
if (error instanceof Error) {
|
|
@@ -2771,6 +2782,29 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2771
2782
|
throw error;
|
|
2772
2783
|
}
|
|
2773
2784
|
}
|
|
2785
|
+
async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
|
|
2786
|
+
const repo = readRepoConnection(projectRoot);
|
|
2787
|
+
const slug = repo?.project?.trim();
|
|
2788
|
+
if (!slug)
|
|
2789
|
+
return null;
|
|
2790
|
+
try {
|
|
2791
|
+
const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
|
|
2792
|
+
headers: mergeHeaders(undefined, authToken)
|
|
2793
|
+
});
|
|
2794
|
+
if (!response.ok)
|
|
2795
|
+
return null;
|
|
2796
|
+
const payload = await response.json();
|
|
2797
|
+
const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
|
|
2798
|
+
const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
|
|
2799
|
+
const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
|
|
2800
|
+
const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
|
|
2801
|
+
if (path)
|
|
2802
|
+
writeRepoServerProjectRoot(projectRoot, path);
|
|
2803
|
+
return path;
|
|
2804
|
+
} catch {
|
|
2805
|
+
return null;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2774
2808
|
function appendTaskFilterParams(url, filters) {
|
|
2775
2809
|
if (filters.assignee)
|
|
2776
2810
|
url.searchParams.set("assignee", filters.assignee);
|
|
@@ -2805,9 +2839,12 @@ function diagnosticMessage(payload) {
|
|
|
2805
2839
|
}
|
|
2806
2840
|
async function requestServerJson(context, pathname, init = {}) {
|
|
2807
2841
|
const server = await ensureServerForCli(context.projectRoot);
|
|
2842
|
+
const headers = mergeHeaders(init.headers, server.authToken);
|
|
2843
|
+
if (server.serverProjectRoot)
|
|
2844
|
+
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
2808
2845
|
const response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
2809
2846
|
...init,
|
|
2810
|
-
headers
|
|
2847
|
+
headers
|
|
2811
2848
|
});
|
|
2812
2849
|
const text2 = await response.text();
|
|
2813
2850
|
const payload = text2.trim().length > 0 ? (() => {
|
|
@@ -2914,22 +2951,12 @@ async function switchServerProjectRootViaServer(context, projectRoot, options =
|
|
|
2914
2951
|
if (!switched) {
|
|
2915
2952
|
throw new CliError2(`Rig server did not accept project-root switch to ${projectRoot} before timeout (${lastError instanceof Error ? lastError.message : String(lastError ?? "no response")}).`, 1);
|
|
2916
2953
|
}
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
const record = status;
|
|
2922
|
-
if (record.projectRoot === projectRoot) {
|
|
2923
|
-
return { ok: true, switched, status: record };
|
|
2924
|
-
}
|
|
2925
|
-
lastError = `server projectRoot=${String(record.projectRoot ?? "unknown")}`;
|
|
2926
|
-
}
|
|
2927
|
-
} catch (error) {
|
|
2928
|
-
lastError = error;
|
|
2929
|
-
}
|
|
2930
|
-
await sleep(pollMs);
|
|
2954
|
+
const record = switched && typeof switched === "object" && !Array.isArray(switched) ? switched : {};
|
|
2955
|
+
if (record.ok === true) {
|
|
2956
|
+
writeRepoServerProjectRoot(context.projectRoot, projectRoot);
|
|
2957
|
+
return { ok: true, switched: record };
|
|
2931
2958
|
}
|
|
2932
|
-
throw new CliError2(`Rig server
|
|
2959
|
+
throw new CliError2(`Rig server rejected project-root scope ${projectRoot}: ${String(record.message ?? record.error ?? "unknown error")}`, 1);
|
|
2933
2960
|
}
|
|
2934
2961
|
async function listRunsViaServer(context, options = {}) {
|
|
2935
2962
|
const url = new URL("http://rig.local/api/runs");
|
|
@@ -3061,6 +3088,8 @@ async function buildRunPiEventsWebSocketUrl(context, runId) {
|
|
|
3061
3088
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
3062
3089
|
if (server.authToken)
|
|
3063
3090
|
url.searchParams.set("token", server.authToken);
|
|
3091
|
+
if (server.serverProjectRoot)
|
|
3092
|
+
url.searchParams.set("rigProjectRoot", server.serverProjectRoot);
|
|
3064
3093
|
return url.toString();
|
|
3065
3094
|
}
|
|
3066
3095
|
async function submitTaskRunViaServer(context, input) {
|