@ricsam/r5d-worker 0.0.47 → 0.0.49
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/README.md +3 -1
- package/dist/cjs/main.cjs +201 -171
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/port-forward-client.cjs +148 -0
- package/dist/cjs/workspace-sync.cjs +38 -0
- package/dist/mjs/main.mjs +197 -171
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/port-forward-client.mjs +114 -0
- package/dist/mjs/workspace-sync.mjs +37 -0
- package/dist/types/main.d.ts +45 -6
- package/dist/types/port-forward-client.d.ts +8 -0
- package/dist/types/workspace-sync.d.ts +1 -0
- package/package.json +1 -1
package/dist/cjs/main.cjs
CHANGED
|
@@ -29,6 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
30
|
var main_exports = {};
|
|
31
31
|
__export(main_exports, {
|
|
32
|
+
describeWorkerSessionTarget: () => describeWorkerSessionTarget,
|
|
32
33
|
editWorkerTextFile: () => editWorkerTextFile,
|
|
33
34
|
ensureVisibleGitCheckout: () => ensureVisibleGitCheckout,
|
|
34
35
|
findWorkerFiles: () => findWorkerFiles,
|
|
@@ -37,11 +38,14 @@ __export(main_exports, {
|
|
|
37
38
|
isArtifactEnvPath: () => isArtifactEnvPath,
|
|
38
39
|
listWorkerDirectory: () => listWorkerDirectory,
|
|
39
40
|
prepareArtifactEnvForShell: () => prepareArtifactEnvForShell,
|
|
41
|
+
prepareBuiltInToolPathsForTarget: () => prepareBuiltInToolPathsForTarget,
|
|
40
42
|
preparePlanEnvForShell: () => preparePlanEnvForShell,
|
|
43
|
+
prepareShellEnvForTarget: () => prepareShellEnvForTarget,
|
|
41
44
|
readWorkerImageFile: () => readWorkerImageFile,
|
|
42
45
|
readWorkerTextFile: () => readWorkerTextFile,
|
|
43
46
|
resolveHostShell: () => resolveHostShell,
|
|
44
47
|
resolveWorkerFilePath: () => resolveWorkerFilePath,
|
|
48
|
+
resolveWorkerSessionTarget: () => resolveWorkerSessionTarget,
|
|
45
49
|
syncSessionArtifacts: () => syncSessionArtifacts,
|
|
46
50
|
visibleCheckoutGitTestHarness: () => visibleCheckoutGitTestHarness,
|
|
47
51
|
visibleCheckoutRemoteFor: () => visibleCheckoutRemoteFor,
|
|
@@ -58,6 +62,7 @@ var import_cli_update = require("./cli-update.cjs");
|
|
|
58
62
|
var import_git_identity = require("./git-identity.cjs");
|
|
59
63
|
var import_heartbeat = require("./heartbeat.cjs");
|
|
60
64
|
var import_process_tree = require("./process-tree.cjs");
|
|
65
|
+
var import_port_forward_client = require("./port-forward-client.cjs");
|
|
61
66
|
var import_supervisor = require("./supervisor.cjs");
|
|
62
67
|
var import_managed_paths = require("./managed-paths.cjs");
|
|
63
68
|
var import_workspace_sync = require("./workspace-sync.cjs");
|
|
@@ -332,8 +337,15 @@ function projectPlanDir(planRoot, projectId, branchName) {
|
|
|
332
337
|
validateBranchName(branchName);
|
|
333
338
|
return import_node_path.default.join(planRoot, projectId, branchName);
|
|
334
339
|
}
|
|
335
|
-
function
|
|
336
|
-
|
|
340
|
+
function targetPlanDir(planRoot, target) {
|
|
341
|
+
if (target.type === "project") return projectPlanDir(planRoot, target.projectId, target.branchName);
|
|
342
|
+
if (target.rootProfile === "canonical_sync") {
|
|
343
|
+
throw new Error("Ordinary plans are unavailable in canonical synchronization sessions");
|
|
344
|
+
}
|
|
345
|
+
return import_node_path.default.join(planRoot, "workspace");
|
|
346
|
+
}
|
|
347
|
+
function planEnv(planRoot, target, activePlanId) {
|
|
348
|
+
const plansDir = targetPlanDir(planRoot, target);
|
|
337
349
|
const env = {
|
|
338
350
|
[R5D_PLANS_DIR_ENV]: plansDir
|
|
339
351
|
};
|
|
@@ -351,14 +363,14 @@ function isArtifactEnvPath(filePath) {
|
|
|
351
363
|
return false;
|
|
352
364
|
}
|
|
353
365
|
}
|
|
354
|
-
function artifactApiBasePath(
|
|
355
|
-
return `/preview-api
|
|
366
|
+
function artifactApiBasePath(sessionId) {
|
|
367
|
+
return `/preview-api/artifacts/${encodeURIComponent(sessionId)}`;
|
|
356
368
|
}
|
|
357
|
-
function artifactManifestUrl(baseUrl,
|
|
358
|
-
return new URL(artifactApiBasePath(
|
|
369
|
+
function artifactManifestUrl(baseUrl, sessionId) {
|
|
370
|
+
return new URL(artifactApiBasePath(sessionId), baseUrl);
|
|
359
371
|
}
|
|
360
|
-
function artifactDownloadUrl(baseUrl,
|
|
361
|
-
return new URL(`${artifactApiBasePath(
|
|
372
|
+
function artifactDownloadUrl(baseUrl, sessionId, filename) {
|
|
373
|
+
return new URL(`${artifactApiBasePath(sessionId)}/${encodeURIComponent(filename)}`, baseUrl);
|
|
362
374
|
}
|
|
363
375
|
function sha256Path(filePath) {
|
|
364
376
|
return (0, import_node_crypto.createHash)("sha256").update(import_node_fs.default.readFileSync(filePath)).digest("hex");
|
|
@@ -450,7 +462,7 @@ async function syncRemoteFileSet(input) {
|
|
|
450
462
|
}
|
|
451
463
|
async function fetchSessionArtifactManifest(input) {
|
|
452
464
|
return fetchRemoteFileManifest({
|
|
453
|
-
url: artifactManifestUrl(input.baseUrl, input.
|
|
465
|
+
url: artifactManifestUrl(input.baseUrl, input.sessionId),
|
|
454
466
|
token: input.token,
|
|
455
467
|
collectionKey: "artifacts",
|
|
456
468
|
label: "artifact"
|
|
@@ -468,7 +480,7 @@ async function syncSessionArtifacts(input) {
|
|
|
468
480
|
files: artifacts,
|
|
469
481
|
label: "Artifact path",
|
|
470
482
|
download: (artifact) => downloadRemoteSyncedFile({
|
|
471
|
-
url: artifactDownloadUrl(input.baseUrl, input.
|
|
483
|
+
url: artifactDownloadUrl(input.baseUrl, input.sessionId, artifact.filename),
|
|
472
484
|
token: input.token,
|
|
473
485
|
targetDir,
|
|
474
486
|
file: artifact,
|
|
@@ -501,14 +513,12 @@ async function prepareBuiltInToolPaths(input) {
|
|
|
501
513
|
artifactsDir: await syncSessionArtifacts({
|
|
502
514
|
baseUrl: input.baseUrl,
|
|
503
515
|
token: input.token,
|
|
504
|
-
projectId: input.projectId,
|
|
505
|
-
branchName: input.branchName,
|
|
506
516
|
sessionId: input.sessionId,
|
|
507
517
|
artifactRoot: input.artifactRoot
|
|
508
518
|
})
|
|
509
519
|
};
|
|
510
520
|
}
|
|
511
|
-
const plansDir =
|
|
521
|
+
const plansDir = targetPlanDir(input.planRoot, input.target);
|
|
512
522
|
import_node_fs.default.mkdirSync(plansDir, { recursive: true });
|
|
513
523
|
if (parsed.ref === R5D_PLANS_DIR_REF) {
|
|
514
524
|
return { plansDir };
|
|
@@ -530,8 +540,6 @@ async function prepareArtifactEnvForShell(input) {
|
|
|
530
540
|
await syncSessionArtifacts({
|
|
531
541
|
baseUrl: input.baseUrl,
|
|
532
542
|
token: input.token,
|
|
533
|
-
projectId: input.projectId,
|
|
534
|
-
branchName: input.branchName,
|
|
535
543
|
sessionId: input.sessionId,
|
|
536
544
|
artifactRoot: input.artifactRoot
|
|
537
545
|
});
|
|
@@ -548,9 +556,9 @@ async function prepareArtifactEnvForShell(input) {
|
|
|
548
556
|
};
|
|
549
557
|
}
|
|
550
558
|
function preparePlanEnvForShell(input) {
|
|
551
|
-
const plansDir =
|
|
559
|
+
const plansDir = targetPlanDir(input.planRoot, input.target);
|
|
552
560
|
import_node_fs.default.mkdirSync(plansDir, { recursive: true });
|
|
553
|
-
return planEnv(input.planRoot, input.
|
|
561
|
+
return planEnv(input.planRoot, input.target, input.activePlanId);
|
|
554
562
|
}
|
|
555
563
|
async function verifyR5dctlAuth(baseUrl, token) {
|
|
556
564
|
const statusUrl = new URL("/api/r5dctl/auth/status", baseUrl);
|
|
@@ -1165,6 +1173,32 @@ function ensureBranchWorkspace(input) {
|
|
|
1165
1173
|
})
|
|
1166
1174
|
};
|
|
1167
1175
|
}
|
|
1176
|
+
function describeWorkerSessionTarget(target) {
|
|
1177
|
+
return target.type === "project" ? `${target.projectId}/${target.branchName}` : `${target.ownerUserId}/${target.rootProfile}`;
|
|
1178
|
+
}
|
|
1179
|
+
function resolveWorkerSessionTarget(input) {
|
|
1180
|
+
if (input.target.type === "workspace") {
|
|
1181
|
+
if (input.target.rootProfile === "visible_projects") {
|
|
1182
|
+
return { target: input.target, rootPath: input.projectsRoot };
|
|
1183
|
+
}
|
|
1184
|
+
if (!import_node_fs.default.existsSync(import_node_path.default.join(input.workspaceShadowRoot, ".git"))) {
|
|
1185
|
+
throw new Error("The canonical workspace checkout is not initialized on this worker");
|
|
1186
|
+
}
|
|
1187
|
+
return { target: input.target, rootPath: input.workspaceShadowRoot };
|
|
1188
|
+
}
|
|
1189
|
+
const manifest = input.manifestByProjectId.get(input.target.projectId);
|
|
1190
|
+
const projectRoot = projectRootFor(input.projectsRoot, input.target.projectId, input.manifestByProjectId);
|
|
1191
|
+
const workspace = ensureBranchWorkspace({
|
|
1192
|
+
projectId: input.target.projectId,
|
|
1193
|
+
baseUrl: input.baseUrl,
|
|
1194
|
+
token: input.token,
|
|
1195
|
+
projectRoot,
|
|
1196
|
+
syncRoot: input.syncRoot,
|
|
1197
|
+
branchName: input.target.branchName,
|
|
1198
|
+
manifest
|
|
1199
|
+
});
|
|
1200
|
+
return { target: input.target, rootPath: workspace.branchPath, manifest };
|
|
1201
|
+
}
|
|
1168
1202
|
function workspaceSyncCheckoutTargets(input) {
|
|
1169
1203
|
const selected = /* @__PURE__ */ new Map();
|
|
1170
1204
|
const add = (target) => {
|
|
@@ -1193,7 +1227,7 @@ function resolveCommandCwd(branchPath, cwd) {
|
|
|
1193
1227
|
const resolved = import_node_path.default.resolve(branchPath, cwd);
|
|
1194
1228
|
const relative = import_node_path.default.relative(branchPath, resolved);
|
|
1195
1229
|
if (relative === ".." || relative.startsWith(`..${import_node_path.default.sep}`) || import_node_path.default.isAbsolute(relative)) {
|
|
1196
|
-
throw new Error(`Relative cwd escapes the
|
|
1230
|
+
throw new Error(`Relative cwd escapes the execution root: ${cwd}`);
|
|
1197
1231
|
}
|
|
1198
1232
|
return resolved;
|
|
1199
1233
|
}
|
|
@@ -1228,8 +1262,8 @@ async function streamCommandOutput(stream, onData) {
|
|
|
1228
1262
|
reader.releaseLock();
|
|
1229
1263
|
}
|
|
1230
1264
|
}
|
|
1231
|
-
function
|
|
1232
|
-
return
|
|
1265
|
+
async function prepareBuiltInToolPathsForTarget(input) {
|
|
1266
|
+
return prepareBuiltInToolPaths(input);
|
|
1233
1267
|
}
|
|
1234
1268
|
function formatLineNumberedContent(content, offset, limit) {
|
|
1235
1269
|
const allLines = content.split("\n");
|
|
@@ -1355,11 +1389,11 @@ async function withFileMutationQueue(key, operation) {
|
|
|
1355
1389
|
}
|
|
1356
1390
|
}
|
|
1357
1391
|
}
|
|
1358
|
-
function mutationQueueKey(
|
|
1392
|
+
function mutationQueueKey(target, resolved) {
|
|
1359
1393
|
if (resolved.scope !== "project") {
|
|
1360
1394
|
return `${resolved.scope}:${import_node_path.default.normalize(resolved.absolutePath)}`;
|
|
1361
1395
|
}
|
|
1362
|
-
return
|
|
1396
|
+
return `${describeWorkerSessionTarget(target)}:${import_node_path.default.posix.normalize(resolved.repoRelativePath)}`;
|
|
1363
1397
|
}
|
|
1364
1398
|
function readWorkerTextFile(branchPath, filePath, offset, limit, builtInPaths) {
|
|
1365
1399
|
const resolved = resolveWorkerFilePath(branchPath, filePath, builtInPaths);
|
|
@@ -1434,57 +1468,51 @@ function editWorkerTextFile(branchPath, filePath, edits, builtInPaths) {
|
|
|
1434
1468
|
};
|
|
1435
1469
|
}
|
|
1436
1470
|
async function executeReadFileOperation(input) {
|
|
1437
|
-
const builtInPaths = await
|
|
1471
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1472
|
+
target: input.resolvedTarget.target,
|
|
1438
1473
|
filePath: input.message.filePath,
|
|
1439
1474
|
baseUrl: input.baseUrl,
|
|
1440
1475
|
token: input.token,
|
|
1441
|
-
projectId: input.projectId,
|
|
1442
|
-
branchName: input.message.branchName,
|
|
1443
1476
|
sessionId: input.message.sessionId,
|
|
1444
1477
|
activePlanId: input.message.activePlanId,
|
|
1445
1478
|
artifactRoot: input.artifactRoot,
|
|
1446
1479
|
planRoot: input.planRoot,
|
|
1447
1480
|
access: "read"
|
|
1448
1481
|
});
|
|
1449
|
-
|
|
1450
|
-
return readWorkerTextFile(workspace.branchPath, input.message.filePath, input.message.offset, input.message.limit, builtInPaths);
|
|
1482
|
+
return readWorkerTextFile(input.resolvedTarget.rootPath, input.message.filePath, input.message.offset, input.message.limit, builtInPaths);
|
|
1451
1483
|
}
|
|
1452
1484
|
async function executeWriteFileOperation(input) {
|
|
1453
|
-
const builtInPaths = await
|
|
1485
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1486
|
+
target: input.resolvedTarget.target,
|
|
1454
1487
|
filePath: input.message.filePath,
|
|
1455
1488
|
baseUrl: input.baseUrl,
|
|
1456
1489
|
token: input.token,
|
|
1457
|
-
projectId: input.projectId,
|
|
1458
|
-
branchName: input.message.branchName,
|
|
1459
1490
|
sessionId: input.message.sessionId,
|
|
1460
1491
|
activePlanId: input.message.activePlanId,
|
|
1461
1492
|
artifactRoot: input.artifactRoot,
|
|
1462
1493
|
planRoot: input.planRoot,
|
|
1463
1494
|
access: "write"
|
|
1464
1495
|
});
|
|
1465
|
-
const
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
return writeWorkerTextFile(workspace.branchPath, input.message.filePath, input.message.content, builtInPaths);
|
|
1496
|
+
const resolved = resolveWorkerFilePath(input.resolvedTarget.rootPath, input.message.filePath, builtInPaths);
|
|
1497
|
+
return withFileMutationQueue(mutationQueueKey(input.resolvedTarget.target, resolved), async () => {
|
|
1498
|
+
return writeWorkerTextFile(input.resolvedTarget.rootPath, input.message.filePath, input.message.content, builtInPaths);
|
|
1469
1499
|
});
|
|
1470
1500
|
}
|
|
1471
1501
|
async function executeEditFileOperation(input) {
|
|
1472
|
-
const builtInPaths = await
|
|
1502
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1503
|
+
target: input.resolvedTarget.target,
|
|
1473
1504
|
filePath: input.message.filePath,
|
|
1474
1505
|
baseUrl: input.baseUrl,
|
|
1475
1506
|
token: input.token,
|
|
1476
|
-
projectId: input.projectId,
|
|
1477
|
-
branchName: input.message.branchName,
|
|
1478
1507
|
sessionId: input.message.sessionId,
|
|
1479
1508
|
activePlanId: input.message.activePlanId,
|
|
1480
1509
|
artifactRoot: input.artifactRoot,
|
|
1481
1510
|
planRoot: input.planRoot,
|
|
1482
1511
|
access: "write"
|
|
1483
1512
|
});
|
|
1484
|
-
const
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
return editWorkerTextFile(workspace.branchPath, input.message.filePath, input.message.edits, builtInPaths);
|
|
1513
|
+
const resolved = resolveWorkerFilePath(input.resolvedTarget.rootPath, input.message.filePath, builtInPaths);
|
|
1514
|
+
return withFileMutationQueue(mutationQueueKey(input.resolvedTarget.target, resolved), async () => {
|
|
1515
|
+
return editWorkerTextFile(input.resolvedTarget.rootPath, input.message.filePath, input.message.edits, builtInPaths);
|
|
1488
1516
|
});
|
|
1489
1517
|
}
|
|
1490
1518
|
const IGNORED_ENTRY_NAMES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".next", ".cache", "coverage", "target"]);
|
|
@@ -1597,21 +1625,19 @@ function grepWorkerFiles(branchPath, input, builtInPaths) {
|
|
|
1597
1625
|
}
|
|
1598
1626
|
async function executeGrepOperation(input) {
|
|
1599
1627
|
const toolPath = input.message.path ?? ".";
|
|
1600
|
-
const builtInPaths = await
|
|
1628
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1629
|
+
target: input.resolvedTarget.target,
|
|
1601
1630
|
filePath: toolPath,
|
|
1602
1631
|
baseUrl: input.baseUrl,
|
|
1603
1632
|
token: input.token,
|
|
1604
|
-
projectId: input.projectId,
|
|
1605
|
-
branchName: input.message.branchName,
|
|
1606
1633
|
sessionId: input.message.sessionId,
|
|
1607
1634
|
activePlanId: input.message.activePlanId,
|
|
1608
1635
|
artifactRoot: input.artifactRoot,
|
|
1609
1636
|
planRoot: input.planRoot,
|
|
1610
1637
|
access: "read"
|
|
1611
1638
|
});
|
|
1612
|
-
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
1613
1639
|
return grepWorkerFiles(
|
|
1614
|
-
|
|
1640
|
+
input.resolvedTarget.rootPath,
|
|
1615
1641
|
{
|
|
1616
1642
|
pattern: input.message.pattern,
|
|
1617
1643
|
path: input.message.path,
|
|
@@ -1658,21 +1684,19 @@ function findWorkerFiles(branchPath, input, builtInPaths) {
|
|
|
1658
1684
|
}
|
|
1659
1685
|
async function executeFindOperation(input) {
|
|
1660
1686
|
const toolPath = input.message.path ?? ".";
|
|
1661
|
-
const builtInPaths = await
|
|
1687
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1688
|
+
target: input.resolvedTarget.target,
|
|
1662
1689
|
filePath: toolPath,
|
|
1663
1690
|
baseUrl: input.baseUrl,
|
|
1664
1691
|
token: input.token,
|
|
1665
|
-
projectId: input.projectId,
|
|
1666
|
-
branchName: input.message.branchName,
|
|
1667
1692
|
sessionId: input.message.sessionId,
|
|
1668
1693
|
activePlanId: input.message.activePlanId,
|
|
1669
1694
|
artifactRoot: input.artifactRoot,
|
|
1670
1695
|
planRoot: input.planRoot,
|
|
1671
1696
|
access: "read"
|
|
1672
1697
|
});
|
|
1673
|
-
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
1674
1698
|
return findWorkerFiles(
|
|
1675
|
-
|
|
1699
|
+
input.resolvedTarget.rootPath,
|
|
1676
1700
|
{
|
|
1677
1701
|
pattern: input.message.pattern,
|
|
1678
1702
|
path: input.message.path,
|
|
@@ -1702,20 +1726,18 @@ function listWorkerDirectory(branchPath, inputPath = ".", inputLimit, builtInPat
|
|
|
1702
1726
|
}
|
|
1703
1727
|
async function executeLsOperation(input) {
|
|
1704
1728
|
const toolPath = input.message.path ?? ".";
|
|
1705
|
-
const builtInPaths = await
|
|
1729
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1730
|
+
target: input.resolvedTarget.target,
|
|
1706
1731
|
filePath: toolPath,
|
|
1707
1732
|
baseUrl: input.baseUrl,
|
|
1708
1733
|
token: input.token,
|
|
1709
|
-
projectId: input.projectId,
|
|
1710
|
-
branchName: input.message.branchName,
|
|
1711
1734
|
sessionId: input.message.sessionId,
|
|
1712
1735
|
activePlanId: input.message.activePlanId,
|
|
1713
1736
|
artifactRoot: input.artifactRoot,
|
|
1714
1737
|
planRoot: input.planRoot,
|
|
1715
1738
|
access: "read"
|
|
1716
1739
|
});
|
|
1717
|
-
|
|
1718
|
-
return listWorkerDirectory(workspace.branchPath, input.message.path, input.message.limit, builtInPaths);
|
|
1740
|
+
return listWorkerDirectory(input.resolvedTarget.rootPath, input.message.path, input.message.limit, builtInPaths);
|
|
1719
1741
|
}
|
|
1720
1742
|
function readWorkerImageFile(branchPath, filePath, builtInPaths) {
|
|
1721
1743
|
const resolved = resolveWorkerFilePath(branchPath, filePath, builtInPaths);
|
|
@@ -1740,20 +1762,18 @@ function readWorkerImageFile(branchPath, filePath, builtInPaths) {
|
|
|
1740
1762
|
};
|
|
1741
1763
|
}
|
|
1742
1764
|
async function executeViewFileBytesOperation(input) {
|
|
1743
|
-
const builtInPaths = await
|
|
1765
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1766
|
+
target: input.resolvedTarget.target,
|
|
1744
1767
|
filePath: input.message.filePath,
|
|
1745
1768
|
baseUrl: input.baseUrl,
|
|
1746
1769
|
token: input.token,
|
|
1747
|
-
projectId: input.projectId,
|
|
1748
|
-
branchName: input.message.branchName,
|
|
1749
1770
|
sessionId: input.message.sessionId,
|
|
1750
1771
|
activePlanId: input.message.activePlanId,
|
|
1751
1772
|
artifactRoot: input.artifactRoot,
|
|
1752
1773
|
planRoot: input.planRoot,
|
|
1753
1774
|
access: "read"
|
|
1754
1775
|
});
|
|
1755
|
-
|
|
1756
|
-
return readWorkerImageFile(workspace.branchPath, input.message.filePath, builtInPaths);
|
|
1776
|
+
return readWorkerImageFile(input.resolvedTarget.rootPath, input.message.filePath, builtInPaths);
|
|
1757
1777
|
}
|
|
1758
1778
|
async function executeOperation(input) {
|
|
1759
1779
|
switch (input.message.type) {
|
|
@@ -1773,38 +1793,56 @@ async function executeOperation(input) {
|
|
|
1773
1793
|
return executeViewFileBytesOperation({ ...input, message: input.message });
|
|
1774
1794
|
}
|
|
1775
1795
|
}
|
|
1796
|
+
function targetIdentityEnv(target) {
|
|
1797
|
+
return target.type === "project" ? {
|
|
1798
|
+
R5D_PROJECT_ID: target.projectId,
|
|
1799
|
+
R5D_BRANCH_NAME: target.branchName,
|
|
1800
|
+
R5D_WORKSPACE_OWNER_ID: "",
|
|
1801
|
+
R5D_WORKSPACE_ROOT_PROFILE: ""
|
|
1802
|
+
} : {
|
|
1803
|
+
R5D_WORKSPACE_OWNER_ID: target.ownerUserId,
|
|
1804
|
+
R5D_WORKSPACE_ROOT_PROFILE: target.rootProfile,
|
|
1805
|
+
R5D_PROJECT_ID: "",
|
|
1806
|
+
R5D_BRANCH_NAME: ""
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
async function prepareShellEnvForTarget(input) {
|
|
1810
|
+
const artifactProcessEnv = await prepareArtifactEnvForShell({
|
|
1811
|
+
baseUrl: input.baseUrl,
|
|
1812
|
+
token: input.token,
|
|
1813
|
+
sessionId: input.sessionId,
|
|
1814
|
+
artifactRoot: input.artifactRoot
|
|
1815
|
+
});
|
|
1816
|
+
if (input.target.type === "workspace" && input.target.rootProfile === "canonical_sync") {
|
|
1817
|
+
return {
|
|
1818
|
+
...artifactProcessEnv,
|
|
1819
|
+
...targetIdentityEnv(input.target)
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1822
|
+
return {
|
|
1823
|
+
...artifactProcessEnv,
|
|
1824
|
+
...preparePlanEnvForShell({
|
|
1825
|
+
target: input.target,
|
|
1826
|
+
planRoot: input.planRoot,
|
|
1827
|
+
activePlanId: input.activePlanId
|
|
1828
|
+
}),
|
|
1829
|
+
...targetIdentityEnv(input.target)
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1776
1832
|
async function executeCommand(input) {
|
|
1777
1833
|
const startedAt = Date.now();
|
|
1778
1834
|
let timeout;
|
|
1779
1835
|
try {
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
baseUrl: input.baseUrl,
|
|
1783
|
-
token: input.token,
|
|
1784
|
-
projectRoot: input.projectRoot,
|
|
1785
|
-
syncRoot: input.syncRoot,
|
|
1786
|
-
branchName: input.message.branchName,
|
|
1787
|
-
manifest: input.manifest
|
|
1788
|
-
});
|
|
1789
|
-
const artifactProcessEnv = await prepareArtifactEnvForShell({
|
|
1836
|
+
const targetProcessEnv = await prepareShellEnvForTarget({
|
|
1837
|
+
target: input.resolvedTarget.target,
|
|
1790
1838
|
baseUrl: input.baseUrl,
|
|
1791
1839
|
token: input.token,
|
|
1792
|
-
projectId: input.projectId,
|
|
1793
|
-
branchName: input.message.branchName,
|
|
1794
1840
|
sessionId: input.message.sessionId,
|
|
1795
|
-
artifactRoot: input.artifactRoot
|
|
1796
|
-
});
|
|
1797
|
-
const planProcessEnv = preparePlanEnvForShell({
|
|
1798
|
-
projectId: input.projectId,
|
|
1799
|
-
branchName: input.message.branchName,
|
|
1841
|
+
artifactRoot: input.artifactRoot,
|
|
1800
1842
|
planRoot: input.planRoot,
|
|
1801
1843
|
activePlanId: input.message.env?.R5D_ACTIVE_PLAN_ID
|
|
1802
1844
|
});
|
|
1803
|
-
const
|
|
1804
|
-
if (input.message.env?.R5D_USE_WORKSPACE_GIT === "1" && !import_node_fs.default.existsSync(import_node_path.default.join(commandRoot, ".git"))) {
|
|
1805
|
-
throw new Error("The canonical workspace checkout is not initialized on this worker");
|
|
1806
|
-
}
|
|
1807
|
-
const cwd = resolveCommandCwd(commandRoot, input.message.cwd);
|
|
1845
|
+
const cwd = resolveCommandCwd(input.resolvedTarget.rootPath, input.message.cwd);
|
|
1808
1846
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1809
1847
|
cwd,
|
|
1810
1848
|
stdout: "pipe",
|
|
@@ -1814,15 +1852,13 @@ async function executeCommand(input) {
|
|
|
1814
1852
|
...process.env,
|
|
1815
1853
|
...githubProcessEnv(),
|
|
1816
1854
|
...input.message.env ?? {},
|
|
1817
|
-
...
|
|
1818
|
-
...planProcessEnv
|
|
1855
|
+
...targetProcessEnv
|
|
1819
1856
|
}
|
|
1820
1857
|
});
|
|
1821
1858
|
activeProcesses.set(input.message.runId, {
|
|
1822
1859
|
process: subprocess,
|
|
1823
|
-
|
|
1860
|
+
target: input.resolvedTarget.target,
|
|
1824
1861
|
sessionId: input.message.sessionId ?? "",
|
|
1825
|
-
branchName: input.message.branchName,
|
|
1826
1862
|
mode: "foreground",
|
|
1827
1863
|
pid: subprocess.pid,
|
|
1828
1864
|
processGroupId: process.platform === "win32" ? void 0 : subprocess.pid,
|
|
@@ -1886,34 +1922,16 @@ async function executeStreamingCommand(input) {
|
|
|
1886
1922
|
});
|
|
1887
1923
|
return;
|
|
1888
1924
|
}
|
|
1889
|
-
const
|
|
1890
|
-
|
|
1891
|
-
baseUrl: input.baseUrl,
|
|
1892
|
-
token: input.token,
|
|
1893
|
-
projectRoot: input.projectRoot,
|
|
1894
|
-
syncRoot: input.syncRoot,
|
|
1895
|
-
branchName: input.message.branchName,
|
|
1896
|
-
manifest: input.manifest
|
|
1897
|
-
});
|
|
1898
|
-
const artifactProcessEnv = await prepareArtifactEnvForShell({
|
|
1925
|
+
const targetProcessEnv = await prepareShellEnvForTarget({
|
|
1926
|
+
target: input.resolvedTarget.target,
|
|
1899
1927
|
baseUrl: input.baseUrl,
|
|
1900
1928
|
token: input.token,
|
|
1901
|
-
projectId: input.projectId,
|
|
1902
|
-
branchName: input.message.branchName,
|
|
1903
1929
|
sessionId: input.message.sessionId,
|
|
1904
|
-
artifactRoot: input.artifactRoot
|
|
1905
|
-
});
|
|
1906
|
-
const planProcessEnv = preparePlanEnvForShell({
|
|
1907
|
-
projectId: input.projectId,
|
|
1908
|
-
branchName: input.message.branchName,
|
|
1930
|
+
artifactRoot: input.artifactRoot,
|
|
1909
1931
|
planRoot: input.planRoot,
|
|
1910
1932
|
activePlanId: input.message.env?.R5D_ACTIVE_PLAN_ID
|
|
1911
1933
|
});
|
|
1912
|
-
const
|
|
1913
|
-
if (input.message.env?.R5D_USE_WORKSPACE_GIT === "1" && !import_node_fs.default.existsSync(import_node_path.default.join(commandRoot, ".git"))) {
|
|
1914
|
-
throw new Error("The canonical workspace checkout is not initialized on this worker");
|
|
1915
|
-
}
|
|
1916
|
-
const cwd = resolveCommandCwd(commandRoot, input.message.cwd);
|
|
1934
|
+
const cwd = resolveCommandCwd(input.resolvedTarget.rootPath, input.message.cwd);
|
|
1917
1935
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1918
1936
|
cwd,
|
|
1919
1937
|
stdout: "pipe",
|
|
@@ -1923,15 +1941,13 @@ async function executeStreamingCommand(input) {
|
|
|
1923
1941
|
...process.env,
|
|
1924
1942
|
...githubProcessEnv(),
|
|
1925
1943
|
...input.message.env ?? {},
|
|
1926
|
-
...
|
|
1927
|
-
...planProcessEnv
|
|
1944
|
+
...targetProcessEnv
|
|
1928
1945
|
}
|
|
1929
1946
|
});
|
|
1930
1947
|
activeProcesses.set(input.message.runId, {
|
|
1931
1948
|
process: subprocess,
|
|
1932
|
-
|
|
1949
|
+
target: input.resolvedTarget.target,
|
|
1933
1950
|
sessionId: input.message.sessionId,
|
|
1934
|
-
branchName: input.message.branchName,
|
|
1935
1951
|
mode: input.message.mode,
|
|
1936
1952
|
pid: subprocess.pid,
|
|
1937
1953
|
processGroupId: process.platform === "win32" ? void 0 : subprocess.pid,
|
|
@@ -2028,9 +2044,8 @@ function sendWorkerMessage(ws, message) {
|
|
|
2028
2044
|
function buildActiveProcessReports() {
|
|
2029
2045
|
return Array.from(activeProcesses.entries()).filter(([, active]) => active.sessionId.length > 0).map(([runId, active]) => ({
|
|
2030
2046
|
runId,
|
|
2031
|
-
|
|
2047
|
+
target: active.target,
|
|
2032
2048
|
sessionId: active.sessionId,
|
|
2033
|
-
branchName: active.branchName,
|
|
2034
2049
|
platform: process.platform,
|
|
2035
2050
|
arch: process.arch,
|
|
2036
2051
|
mode: active.mode,
|
|
@@ -2238,21 +2253,12 @@ function resolveHostShell(command, platform = process.platform) {
|
|
|
2238
2253
|
}
|
|
2239
2254
|
async function openPty(input) {
|
|
2240
2255
|
try {
|
|
2241
|
-
const
|
|
2242
|
-
|
|
2243
|
-
baseUrl: input.baseUrl,
|
|
2244
|
-
token: input.token,
|
|
2245
|
-
projectRoot: input.projectRoot,
|
|
2246
|
-
syncRoot: input.syncRoot,
|
|
2247
|
-
branchName: input.message.branchName,
|
|
2248
|
-
manifest: input.manifest
|
|
2249
|
-
});
|
|
2250
|
-
const planProcessEnv = preparePlanEnvForShell({
|
|
2251
|
-
projectId: input.projectId,
|
|
2252
|
-
branchName: input.message.branchName,
|
|
2256
|
+
const planProcessEnv = !(input.resolvedTarget.target.type === "workspace" && input.resolvedTarget.target.rootProfile === "canonical_sync") ? preparePlanEnvForShell({
|
|
2257
|
+
target: input.resolvedTarget.target,
|
|
2253
2258
|
planRoot: input.planRoot,
|
|
2254
2259
|
activePlanId: input.message.env?.R5D_ACTIVE_PLAN_ID
|
|
2255
|
-
});
|
|
2260
|
+
}) : {};
|
|
2261
|
+
const targetProcessEnv = targetIdentityEnv(input.resolvedTarget.target);
|
|
2256
2262
|
const shell = resolveHostShell(input.message.command);
|
|
2257
2263
|
const ptyProcess = createNodePtyBridge({
|
|
2258
2264
|
file: shell.file,
|
|
@@ -2261,14 +2267,13 @@ async function openPty(input) {
|
|
|
2261
2267
|
name: "xterm-256color",
|
|
2262
2268
|
cols: Math.max(1, Math.min(Math.floor(input.message.cols || 80), 500)),
|
|
2263
2269
|
rows: Math.max(1, Math.min(Math.floor(input.message.rows || 24), 500)),
|
|
2264
|
-
cwd:
|
|
2270
|
+
cwd: input.resolvedTarget.rootPath,
|
|
2265
2271
|
env: {
|
|
2266
2272
|
...process.env,
|
|
2267
2273
|
...githubProcessEnv(),
|
|
2268
2274
|
...input.message.env ?? {},
|
|
2269
2275
|
...planProcessEnv,
|
|
2270
|
-
|
|
2271
|
-
R5D_BRANCH_NAME: input.message.branchName
|
|
2276
|
+
...targetProcessEnv
|
|
2272
2277
|
}
|
|
2273
2278
|
},
|
|
2274
2279
|
onOpened: () => {
|
|
@@ -2306,8 +2311,7 @@ async function openPty(input) {
|
|
|
2306
2311
|
});
|
|
2307
2312
|
activePtys.set(input.message.ptyId, {
|
|
2308
2313
|
...ptyProcess,
|
|
2309
|
-
|
|
2310
|
-
branchName: input.message.branchName
|
|
2314
|
+
target: input.resolvedTarget.target
|
|
2311
2315
|
});
|
|
2312
2316
|
} catch (error) {
|
|
2313
2317
|
sendWorkerMessage(input.ws, {
|
|
@@ -2426,6 +2430,15 @@ async function startWorker(options) {
|
|
|
2426
2430
|
const allManifestCheckouts = () => [...manifestByProjectId.values()].flatMap(
|
|
2427
2431
|
(manifest) => manifest.branches.map((branchName) => ({ projectId: manifest.projectId, branchName }))
|
|
2428
2432
|
);
|
|
2433
|
+
const resolveMessageTarget = (target) => resolveWorkerSessionTarget({
|
|
2434
|
+
target,
|
|
2435
|
+
baseUrl,
|
|
2436
|
+
token,
|
|
2437
|
+
projectsRoot,
|
|
2438
|
+
syncRoot,
|
|
2439
|
+
workspaceShadowRoot,
|
|
2440
|
+
manifestByProjectId
|
|
2441
|
+
});
|
|
2429
2442
|
const ensureVisibleWorkspaceCheckouts = (targets, options2 = {}) => {
|
|
2430
2443
|
const created = [];
|
|
2431
2444
|
for (const target of targets) {
|
|
@@ -2568,7 +2581,8 @@ async function startWorker(options) {
|
|
|
2568
2581
|
r5dctlVersion: (0, import_cli_update.readInstalledCliVersion)("r5dctl"),
|
|
2569
2582
|
capabilities: {
|
|
2570
2583
|
updateClis: true,
|
|
2571
|
-
canonicalResolverCheckout: true
|
|
2584
|
+
canonicalResolverCheckout: true,
|
|
2585
|
+
browserPortForwarding: true
|
|
2572
2586
|
},
|
|
2573
2587
|
projectRoot: projectsRoot,
|
|
2574
2588
|
artifactRoot,
|
|
@@ -2680,7 +2694,11 @@ async function startWorker(options) {
|
|
|
2680
2694
|
}
|
|
2681
2695
|
if (message.type === "workspace_head_updated") {
|
|
2682
2696
|
if (!activeWorkspaceIncidentId) {
|
|
2683
|
-
await runRequestedWorkspaceSync(
|
|
2697
|
+
await runRequestedWorkspaceSync(
|
|
2698
|
+
crypto.randomUUID(),
|
|
2699
|
+
{ type: "inbound_head", detail: message.commitHash },
|
|
2700
|
+
{ skipVisibleMirror: true }
|
|
2701
|
+
);
|
|
2684
2702
|
}
|
|
2685
2703
|
return;
|
|
2686
2704
|
}
|
|
@@ -2690,8 +2708,6 @@ async function startWorker(options) {
|
|
|
2690
2708
|
await syncSessionArtifacts({
|
|
2691
2709
|
baseUrl,
|
|
2692
2710
|
token,
|
|
2693
|
-
projectId: message.projectId,
|
|
2694
|
-
branchName: message.branchName,
|
|
2695
2711
|
sessionId: message.sessionId,
|
|
2696
2712
|
artifactRoot
|
|
2697
2713
|
});
|
|
@@ -2721,6 +2737,17 @@ async function startWorker(options) {
|
|
|
2721
2737
|
pendingProcessTerminals.delete(message.runId);
|
|
2722
2738
|
return;
|
|
2723
2739
|
}
|
|
2740
|
+
if (message.type === "port_forward_connect") {
|
|
2741
|
+
(0, import_port_forward_client.openWorkerPortForwardRelay)({
|
|
2742
|
+
baseUrl,
|
|
2743
|
+
token,
|
|
2744
|
+
label,
|
|
2745
|
+
forwardId: message.forwardId,
|
|
2746
|
+
relayConnectionId: message.relayConnectionId,
|
|
2747
|
+
workerPort: message.workerPort
|
|
2748
|
+
});
|
|
2749
|
+
return;
|
|
2750
|
+
}
|
|
2724
2751
|
if (message.type === "update_clis") {
|
|
2725
2752
|
if (cliUpdateInProgress) {
|
|
2726
2753
|
sendWorkerMessage(ws, {
|
|
@@ -2800,11 +2827,19 @@ async function startWorker(options) {
|
|
|
2800
2827
|
});
|
|
2801
2828
|
return;
|
|
2802
2829
|
}
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2830
|
+
try {
|
|
2831
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2832
|
+
process.stdout.write(`[r5d-worker] pty ${message.ptyId}: ${describeWorkerSessionTarget(message.target)}
|
|
2806
2833
|
`);
|
|
2807
|
-
|
|
2834
|
+
await openPty({ ws, message, resolvedTarget, planRoot });
|
|
2835
|
+
} catch (error) {
|
|
2836
|
+
sendWorkerMessage(ws, {
|
|
2837
|
+
type: "pty_error",
|
|
2838
|
+
requestId: message.requestId,
|
|
2839
|
+
ptyId: message.ptyId,
|
|
2840
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2841
|
+
});
|
|
2842
|
+
}
|
|
2808
2843
|
return;
|
|
2809
2844
|
}
|
|
2810
2845
|
if (message.type === "pty_input") {
|
|
@@ -2830,22 +2865,22 @@ async function startWorker(options) {
|
|
|
2830
2865
|
});
|
|
2831
2866
|
return;
|
|
2832
2867
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2868
|
+
let result;
|
|
2869
|
+
try {
|
|
2870
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2871
|
+
process.stdout.write(`[r5d-worker] exec ${message.runId}: ${message.argv.join(" ")}
|
|
2836
2872
|
`);
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
});
|
|
2873
|
+
result = await executeCommand({ message, resolvedTarget, baseUrl, token, artifactRoot, planRoot });
|
|
2874
|
+
} catch (error) {
|
|
2875
|
+
result = {
|
|
2876
|
+
type: "exec_result",
|
|
2877
|
+
requestId: message.requestId,
|
|
2878
|
+
stdout: "",
|
|
2879
|
+
stderr: "",
|
|
2880
|
+
exitCode: 1,
|
|
2881
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2882
|
+
};
|
|
2883
|
+
}
|
|
2849
2884
|
ws.send(JSON.stringify(result));
|
|
2850
2885
|
return;
|
|
2851
2886
|
}
|
|
@@ -2865,22 +2900,17 @@ async function startWorker(options) {
|
|
|
2865
2900
|
runId: message.runId
|
|
2866
2901
|
});
|
|
2867
2902
|
try {
|
|
2868
|
-
const
|
|
2869
|
-
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
2903
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2870
2904
|
process.stdout.write(`[r5d-worker] exec_start ${message.runId}: ${message.argv.join(" ")}
|
|
2871
2905
|
`);
|
|
2872
2906
|
void executeStreamingCommand({
|
|
2873
2907
|
ws,
|
|
2874
2908
|
message,
|
|
2875
|
-
|
|
2909
|
+
resolvedTarget,
|
|
2876
2910
|
baseUrl,
|
|
2877
2911
|
token,
|
|
2878
|
-
projectRoot,
|
|
2879
|
-
syncRoot,
|
|
2880
2912
|
artifactRoot,
|
|
2881
|
-
planRoot
|
|
2882
|
-
workspaceShadowRoot,
|
|
2883
|
-
manifest
|
|
2913
|
+
planRoot
|
|
2884
2914
|
}).catch((error) => {
|
|
2885
2915
|
sendWorkerMessage(ws, {
|
|
2886
2916
|
type: "exec_start_error",
|
|
@@ -2901,18 +2931,14 @@ async function startWorker(options) {
|
|
|
2901
2931
|
}
|
|
2902
2932
|
if (message.type === "read" || message.type === "write" || message.type === "edit" || message.type === "grep" || message.type === "find" || message.type === "ls" || message.type === "view_file_bytes") {
|
|
2903
2933
|
try {
|
|
2904
|
-
const
|
|
2905
|
-
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
2934
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2906
2935
|
const result = await executeOperation({
|
|
2907
2936
|
message,
|
|
2908
|
-
|
|
2937
|
+
resolvedTarget,
|
|
2909
2938
|
baseUrl,
|
|
2910
2939
|
token,
|
|
2911
|
-
projectRoot,
|
|
2912
|
-
syncRoot,
|
|
2913
2940
|
artifactRoot,
|
|
2914
|
-
planRoot
|
|
2915
|
-
manifest
|
|
2941
|
+
planRoot
|
|
2916
2942
|
});
|
|
2917
2943
|
ws.send(
|
|
2918
2944
|
JSON.stringify({
|
|
@@ -3040,6 +3066,7 @@ if (isCliEntrypoint()) {
|
|
|
3040
3066
|
}
|
|
3041
3067
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3042
3068
|
0 && (module.exports = {
|
|
3069
|
+
describeWorkerSessionTarget,
|
|
3043
3070
|
editWorkerTextFile,
|
|
3044
3071
|
ensureVisibleGitCheckout,
|
|
3045
3072
|
findWorkerFiles,
|
|
@@ -3048,11 +3075,14 @@ if (isCliEntrypoint()) {
|
|
|
3048
3075
|
isArtifactEnvPath,
|
|
3049
3076
|
listWorkerDirectory,
|
|
3050
3077
|
prepareArtifactEnvForShell,
|
|
3078
|
+
prepareBuiltInToolPathsForTarget,
|
|
3051
3079
|
preparePlanEnvForShell,
|
|
3080
|
+
prepareShellEnvForTarget,
|
|
3052
3081
|
readWorkerImageFile,
|
|
3053
3082
|
readWorkerTextFile,
|
|
3054
3083
|
resolveHostShell,
|
|
3055
3084
|
resolveWorkerFilePath,
|
|
3085
|
+
resolveWorkerSessionTarget,
|
|
3056
3086
|
syncSessionArtifacts,
|
|
3057
3087
|
visibleCheckoutGitTestHarness,
|
|
3058
3088
|
visibleCheckoutRemoteFor,
|