@ricsam/r5d-worker 0.0.48 → 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 +1 -1
- package/dist/cjs/main.cjs +187 -170
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/workspace-sync.cjs +38 -0
- package/dist/mjs/main.mjs +183 -170
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/workspace-sync.mjs +37 -0
- package/dist/types/main.d.ts +45 -6
- 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,
|
|
@@ -333,8 +337,15 @@ function projectPlanDir(planRoot, projectId, branchName) {
|
|
|
333
337
|
validateBranchName(branchName);
|
|
334
338
|
return import_node_path.default.join(planRoot, projectId, branchName);
|
|
335
339
|
}
|
|
336
|
-
function
|
|
337
|
-
|
|
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);
|
|
338
349
|
const env = {
|
|
339
350
|
[R5D_PLANS_DIR_ENV]: plansDir
|
|
340
351
|
};
|
|
@@ -352,14 +363,14 @@ function isArtifactEnvPath(filePath) {
|
|
|
352
363
|
return false;
|
|
353
364
|
}
|
|
354
365
|
}
|
|
355
|
-
function artifactApiBasePath(
|
|
356
|
-
return `/preview-api
|
|
366
|
+
function artifactApiBasePath(sessionId) {
|
|
367
|
+
return `/preview-api/artifacts/${encodeURIComponent(sessionId)}`;
|
|
357
368
|
}
|
|
358
|
-
function artifactManifestUrl(baseUrl,
|
|
359
|
-
return new URL(artifactApiBasePath(
|
|
369
|
+
function artifactManifestUrl(baseUrl, sessionId) {
|
|
370
|
+
return new URL(artifactApiBasePath(sessionId), baseUrl);
|
|
360
371
|
}
|
|
361
|
-
function artifactDownloadUrl(baseUrl,
|
|
362
|
-
return new URL(`${artifactApiBasePath(
|
|
372
|
+
function artifactDownloadUrl(baseUrl, sessionId, filename) {
|
|
373
|
+
return new URL(`${artifactApiBasePath(sessionId)}/${encodeURIComponent(filename)}`, baseUrl);
|
|
363
374
|
}
|
|
364
375
|
function sha256Path(filePath) {
|
|
365
376
|
return (0, import_node_crypto.createHash)("sha256").update(import_node_fs.default.readFileSync(filePath)).digest("hex");
|
|
@@ -451,7 +462,7 @@ async function syncRemoteFileSet(input) {
|
|
|
451
462
|
}
|
|
452
463
|
async function fetchSessionArtifactManifest(input) {
|
|
453
464
|
return fetchRemoteFileManifest({
|
|
454
|
-
url: artifactManifestUrl(input.baseUrl, input.
|
|
465
|
+
url: artifactManifestUrl(input.baseUrl, input.sessionId),
|
|
455
466
|
token: input.token,
|
|
456
467
|
collectionKey: "artifacts",
|
|
457
468
|
label: "artifact"
|
|
@@ -469,7 +480,7 @@ async function syncSessionArtifacts(input) {
|
|
|
469
480
|
files: artifacts,
|
|
470
481
|
label: "Artifact path",
|
|
471
482
|
download: (artifact) => downloadRemoteSyncedFile({
|
|
472
|
-
url: artifactDownloadUrl(input.baseUrl, input.
|
|
483
|
+
url: artifactDownloadUrl(input.baseUrl, input.sessionId, artifact.filename),
|
|
473
484
|
token: input.token,
|
|
474
485
|
targetDir,
|
|
475
486
|
file: artifact,
|
|
@@ -502,14 +513,12 @@ async function prepareBuiltInToolPaths(input) {
|
|
|
502
513
|
artifactsDir: await syncSessionArtifacts({
|
|
503
514
|
baseUrl: input.baseUrl,
|
|
504
515
|
token: input.token,
|
|
505
|
-
projectId: input.projectId,
|
|
506
|
-
branchName: input.branchName,
|
|
507
516
|
sessionId: input.sessionId,
|
|
508
517
|
artifactRoot: input.artifactRoot
|
|
509
518
|
})
|
|
510
519
|
};
|
|
511
520
|
}
|
|
512
|
-
const plansDir =
|
|
521
|
+
const plansDir = targetPlanDir(input.planRoot, input.target);
|
|
513
522
|
import_node_fs.default.mkdirSync(plansDir, { recursive: true });
|
|
514
523
|
if (parsed.ref === R5D_PLANS_DIR_REF) {
|
|
515
524
|
return { plansDir };
|
|
@@ -531,8 +540,6 @@ async function prepareArtifactEnvForShell(input) {
|
|
|
531
540
|
await syncSessionArtifacts({
|
|
532
541
|
baseUrl: input.baseUrl,
|
|
533
542
|
token: input.token,
|
|
534
|
-
projectId: input.projectId,
|
|
535
|
-
branchName: input.branchName,
|
|
536
543
|
sessionId: input.sessionId,
|
|
537
544
|
artifactRoot: input.artifactRoot
|
|
538
545
|
});
|
|
@@ -549,9 +556,9 @@ async function prepareArtifactEnvForShell(input) {
|
|
|
549
556
|
};
|
|
550
557
|
}
|
|
551
558
|
function preparePlanEnvForShell(input) {
|
|
552
|
-
const plansDir =
|
|
559
|
+
const plansDir = targetPlanDir(input.planRoot, input.target);
|
|
553
560
|
import_node_fs.default.mkdirSync(plansDir, { recursive: true });
|
|
554
|
-
return planEnv(input.planRoot, input.
|
|
561
|
+
return planEnv(input.planRoot, input.target, input.activePlanId);
|
|
555
562
|
}
|
|
556
563
|
async function verifyR5dctlAuth(baseUrl, token) {
|
|
557
564
|
const statusUrl = new URL("/api/r5dctl/auth/status", baseUrl);
|
|
@@ -1166,6 +1173,32 @@ function ensureBranchWorkspace(input) {
|
|
|
1166
1173
|
})
|
|
1167
1174
|
};
|
|
1168
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
|
+
}
|
|
1169
1202
|
function workspaceSyncCheckoutTargets(input) {
|
|
1170
1203
|
const selected = /* @__PURE__ */ new Map();
|
|
1171
1204
|
const add = (target) => {
|
|
@@ -1194,7 +1227,7 @@ function resolveCommandCwd(branchPath, cwd) {
|
|
|
1194
1227
|
const resolved = import_node_path.default.resolve(branchPath, cwd);
|
|
1195
1228
|
const relative = import_node_path.default.relative(branchPath, resolved);
|
|
1196
1229
|
if (relative === ".." || relative.startsWith(`..${import_node_path.default.sep}`) || import_node_path.default.isAbsolute(relative)) {
|
|
1197
|
-
throw new Error(`Relative cwd escapes the
|
|
1230
|
+
throw new Error(`Relative cwd escapes the execution root: ${cwd}`);
|
|
1198
1231
|
}
|
|
1199
1232
|
return resolved;
|
|
1200
1233
|
}
|
|
@@ -1229,8 +1262,8 @@ async function streamCommandOutput(stream, onData) {
|
|
|
1229
1262
|
reader.releaseLock();
|
|
1230
1263
|
}
|
|
1231
1264
|
}
|
|
1232
|
-
function
|
|
1233
|
-
return
|
|
1265
|
+
async function prepareBuiltInToolPathsForTarget(input) {
|
|
1266
|
+
return prepareBuiltInToolPaths(input);
|
|
1234
1267
|
}
|
|
1235
1268
|
function formatLineNumberedContent(content, offset, limit) {
|
|
1236
1269
|
const allLines = content.split("\n");
|
|
@@ -1356,11 +1389,11 @@ async function withFileMutationQueue(key, operation) {
|
|
|
1356
1389
|
}
|
|
1357
1390
|
}
|
|
1358
1391
|
}
|
|
1359
|
-
function mutationQueueKey(
|
|
1392
|
+
function mutationQueueKey(target, resolved) {
|
|
1360
1393
|
if (resolved.scope !== "project") {
|
|
1361
1394
|
return `${resolved.scope}:${import_node_path.default.normalize(resolved.absolutePath)}`;
|
|
1362
1395
|
}
|
|
1363
|
-
return
|
|
1396
|
+
return `${describeWorkerSessionTarget(target)}:${import_node_path.default.posix.normalize(resolved.repoRelativePath)}`;
|
|
1364
1397
|
}
|
|
1365
1398
|
function readWorkerTextFile(branchPath, filePath, offset, limit, builtInPaths) {
|
|
1366
1399
|
const resolved = resolveWorkerFilePath(branchPath, filePath, builtInPaths);
|
|
@@ -1435,57 +1468,51 @@ function editWorkerTextFile(branchPath, filePath, edits, builtInPaths) {
|
|
|
1435
1468
|
};
|
|
1436
1469
|
}
|
|
1437
1470
|
async function executeReadFileOperation(input) {
|
|
1438
|
-
const builtInPaths = await
|
|
1471
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1472
|
+
target: input.resolvedTarget.target,
|
|
1439
1473
|
filePath: input.message.filePath,
|
|
1440
1474
|
baseUrl: input.baseUrl,
|
|
1441
1475
|
token: input.token,
|
|
1442
|
-
projectId: input.projectId,
|
|
1443
|
-
branchName: input.message.branchName,
|
|
1444
1476
|
sessionId: input.message.sessionId,
|
|
1445
1477
|
activePlanId: input.message.activePlanId,
|
|
1446
1478
|
artifactRoot: input.artifactRoot,
|
|
1447
1479
|
planRoot: input.planRoot,
|
|
1448
1480
|
access: "read"
|
|
1449
1481
|
});
|
|
1450
|
-
|
|
1451
|
-
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);
|
|
1452
1483
|
}
|
|
1453
1484
|
async function executeWriteFileOperation(input) {
|
|
1454
|
-
const builtInPaths = await
|
|
1485
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1486
|
+
target: input.resolvedTarget.target,
|
|
1455
1487
|
filePath: input.message.filePath,
|
|
1456
1488
|
baseUrl: input.baseUrl,
|
|
1457
1489
|
token: input.token,
|
|
1458
|
-
projectId: input.projectId,
|
|
1459
|
-
branchName: input.message.branchName,
|
|
1460
1490
|
sessionId: input.message.sessionId,
|
|
1461
1491
|
activePlanId: input.message.activePlanId,
|
|
1462
1492
|
artifactRoot: input.artifactRoot,
|
|
1463
1493
|
planRoot: input.planRoot,
|
|
1464
1494
|
access: "write"
|
|
1465
1495
|
});
|
|
1466
|
-
const
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
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);
|
|
1470
1499
|
});
|
|
1471
1500
|
}
|
|
1472
1501
|
async function executeEditFileOperation(input) {
|
|
1473
|
-
const builtInPaths = await
|
|
1502
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1503
|
+
target: input.resolvedTarget.target,
|
|
1474
1504
|
filePath: input.message.filePath,
|
|
1475
1505
|
baseUrl: input.baseUrl,
|
|
1476
1506
|
token: input.token,
|
|
1477
|
-
projectId: input.projectId,
|
|
1478
|
-
branchName: input.message.branchName,
|
|
1479
1507
|
sessionId: input.message.sessionId,
|
|
1480
1508
|
activePlanId: input.message.activePlanId,
|
|
1481
1509
|
artifactRoot: input.artifactRoot,
|
|
1482
1510
|
planRoot: input.planRoot,
|
|
1483
1511
|
access: "write"
|
|
1484
1512
|
});
|
|
1485
|
-
const
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
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);
|
|
1489
1516
|
});
|
|
1490
1517
|
}
|
|
1491
1518
|
const IGNORED_ENTRY_NAMES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".next", ".cache", "coverage", "target"]);
|
|
@@ -1598,21 +1625,19 @@ function grepWorkerFiles(branchPath, input, builtInPaths) {
|
|
|
1598
1625
|
}
|
|
1599
1626
|
async function executeGrepOperation(input) {
|
|
1600
1627
|
const toolPath = input.message.path ?? ".";
|
|
1601
|
-
const builtInPaths = await
|
|
1628
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1629
|
+
target: input.resolvedTarget.target,
|
|
1602
1630
|
filePath: toolPath,
|
|
1603
1631
|
baseUrl: input.baseUrl,
|
|
1604
1632
|
token: input.token,
|
|
1605
|
-
projectId: input.projectId,
|
|
1606
|
-
branchName: input.message.branchName,
|
|
1607
1633
|
sessionId: input.message.sessionId,
|
|
1608
1634
|
activePlanId: input.message.activePlanId,
|
|
1609
1635
|
artifactRoot: input.artifactRoot,
|
|
1610
1636
|
planRoot: input.planRoot,
|
|
1611
1637
|
access: "read"
|
|
1612
1638
|
});
|
|
1613
|
-
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
1614
1639
|
return grepWorkerFiles(
|
|
1615
|
-
|
|
1640
|
+
input.resolvedTarget.rootPath,
|
|
1616
1641
|
{
|
|
1617
1642
|
pattern: input.message.pattern,
|
|
1618
1643
|
path: input.message.path,
|
|
@@ -1659,21 +1684,19 @@ function findWorkerFiles(branchPath, input, builtInPaths) {
|
|
|
1659
1684
|
}
|
|
1660
1685
|
async function executeFindOperation(input) {
|
|
1661
1686
|
const toolPath = input.message.path ?? ".";
|
|
1662
|
-
const builtInPaths = await
|
|
1687
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1688
|
+
target: input.resolvedTarget.target,
|
|
1663
1689
|
filePath: toolPath,
|
|
1664
1690
|
baseUrl: input.baseUrl,
|
|
1665
1691
|
token: input.token,
|
|
1666
|
-
projectId: input.projectId,
|
|
1667
|
-
branchName: input.message.branchName,
|
|
1668
1692
|
sessionId: input.message.sessionId,
|
|
1669
1693
|
activePlanId: input.message.activePlanId,
|
|
1670
1694
|
artifactRoot: input.artifactRoot,
|
|
1671
1695
|
planRoot: input.planRoot,
|
|
1672
1696
|
access: "read"
|
|
1673
1697
|
});
|
|
1674
|
-
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
1675
1698
|
return findWorkerFiles(
|
|
1676
|
-
|
|
1699
|
+
input.resolvedTarget.rootPath,
|
|
1677
1700
|
{
|
|
1678
1701
|
pattern: input.message.pattern,
|
|
1679
1702
|
path: input.message.path,
|
|
@@ -1703,20 +1726,18 @@ function listWorkerDirectory(branchPath, inputPath = ".", inputLimit, builtInPat
|
|
|
1703
1726
|
}
|
|
1704
1727
|
async function executeLsOperation(input) {
|
|
1705
1728
|
const toolPath = input.message.path ?? ".";
|
|
1706
|
-
const builtInPaths = await
|
|
1729
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1730
|
+
target: input.resolvedTarget.target,
|
|
1707
1731
|
filePath: toolPath,
|
|
1708
1732
|
baseUrl: input.baseUrl,
|
|
1709
1733
|
token: input.token,
|
|
1710
|
-
projectId: input.projectId,
|
|
1711
|
-
branchName: input.message.branchName,
|
|
1712
1734
|
sessionId: input.message.sessionId,
|
|
1713
1735
|
activePlanId: input.message.activePlanId,
|
|
1714
1736
|
artifactRoot: input.artifactRoot,
|
|
1715
1737
|
planRoot: input.planRoot,
|
|
1716
1738
|
access: "read"
|
|
1717
1739
|
});
|
|
1718
|
-
|
|
1719
|
-
return listWorkerDirectory(workspace.branchPath, input.message.path, input.message.limit, builtInPaths);
|
|
1740
|
+
return listWorkerDirectory(input.resolvedTarget.rootPath, input.message.path, input.message.limit, builtInPaths);
|
|
1720
1741
|
}
|
|
1721
1742
|
function readWorkerImageFile(branchPath, filePath, builtInPaths) {
|
|
1722
1743
|
const resolved = resolveWorkerFilePath(branchPath, filePath, builtInPaths);
|
|
@@ -1741,20 +1762,18 @@ function readWorkerImageFile(branchPath, filePath, builtInPaths) {
|
|
|
1741
1762
|
};
|
|
1742
1763
|
}
|
|
1743
1764
|
async function executeViewFileBytesOperation(input) {
|
|
1744
|
-
const builtInPaths = await
|
|
1765
|
+
const builtInPaths = await prepareBuiltInToolPathsForTarget({
|
|
1766
|
+
target: input.resolvedTarget.target,
|
|
1745
1767
|
filePath: input.message.filePath,
|
|
1746
1768
|
baseUrl: input.baseUrl,
|
|
1747
1769
|
token: input.token,
|
|
1748
|
-
projectId: input.projectId,
|
|
1749
|
-
branchName: input.message.branchName,
|
|
1750
1770
|
sessionId: input.message.sessionId,
|
|
1751
1771
|
activePlanId: input.message.activePlanId,
|
|
1752
1772
|
artifactRoot: input.artifactRoot,
|
|
1753
1773
|
planRoot: input.planRoot,
|
|
1754
1774
|
access: "read"
|
|
1755
1775
|
});
|
|
1756
|
-
|
|
1757
|
-
return readWorkerImageFile(workspace.branchPath, input.message.filePath, builtInPaths);
|
|
1776
|
+
return readWorkerImageFile(input.resolvedTarget.rootPath, input.message.filePath, builtInPaths);
|
|
1758
1777
|
}
|
|
1759
1778
|
async function executeOperation(input) {
|
|
1760
1779
|
switch (input.message.type) {
|
|
@@ -1774,38 +1793,56 @@ async function executeOperation(input) {
|
|
|
1774
1793
|
return executeViewFileBytesOperation({ ...input, message: input.message });
|
|
1775
1794
|
}
|
|
1776
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
|
+
}
|
|
1777
1832
|
async function executeCommand(input) {
|
|
1778
1833
|
const startedAt = Date.now();
|
|
1779
1834
|
let timeout;
|
|
1780
1835
|
try {
|
|
1781
|
-
const
|
|
1782
|
-
|
|
1783
|
-
baseUrl: input.baseUrl,
|
|
1784
|
-
token: input.token,
|
|
1785
|
-
projectRoot: input.projectRoot,
|
|
1786
|
-
syncRoot: input.syncRoot,
|
|
1787
|
-
branchName: input.message.branchName,
|
|
1788
|
-
manifest: input.manifest
|
|
1789
|
-
});
|
|
1790
|
-
const artifactProcessEnv = await prepareArtifactEnvForShell({
|
|
1836
|
+
const targetProcessEnv = await prepareShellEnvForTarget({
|
|
1837
|
+
target: input.resolvedTarget.target,
|
|
1791
1838
|
baseUrl: input.baseUrl,
|
|
1792
1839
|
token: input.token,
|
|
1793
|
-
projectId: input.projectId,
|
|
1794
|
-
branchName: input.message.branchName,
|
|
1795
1840
|
sessionId: input.message.sessionId,
|
|
1796
|
-
artifactRoot: input.artifactRoot
|
|
1797
|
-
});
|
|
1798
|
-
const planProcessEnv = preparePlanEnvForShell({
|
|
1799
|
-
projectId: input.projectId,
|
|
1800
|
-
branchName: input.message.branchName,
|
|
1841
|
+
artifactRoot: input.artifactRoot,
|
|
1801
1842
|
planRoot: input.planRoot,
|
|
1802
1843
|
activePlanId: input.message.env?.R5D_ACTIVE_PLAN_ID
|
|
1803
1844
|
});
|
|
1804
|
-
const
|
|
1805
|
-
if (input.message.env?.R5D_USE_WORKSPACE_GIT === "1" && !import_node_fs.default.existsSync(import_node_path.default.join(commandRoot, ".git"))) {
|
|
1806
|
-
throw new Error("The canonical workspace checkout is not initialized on this worker");
|
|
1807
|
-
}
|
|
1808
|
-
const cwd = resolveCommandCwd(commandRoot, input.message.cwd);
|
|
1845
|
+
const cwd = resolveCommandCwd(input.resolvedTarget.rootPath, input.message.cwd);
|
|
1809
1846
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1810
1847
|
cwd,
|
|
1811
1848
|
stdout: "pipe",
|
|
@@ -1815,15 +1852,13 @@ async function executeCommand(input) {
|
|
|
1815
1852
|
...process.env,
|
|
1816
1853
|
...githubProcessEnv(),
|
|
1817
1854
|
...input.message.env ?? {},
|
|
1818
|
-
...
|
|
1819
|
-
...planProcessEnv
|
|
1855
|
+
...targetProcessEnv
|
|
1820
1856
|
}
|
|
1821
1857
|
});
|
|
1822
1858
|
activeProcesses.set(input.message.runId, {
|
|
1823
1859
|
process: subprocess,
|
|
1824
|
-
|
|
1860
|
+
target: input.resolvedTarget.target,
|
|
1825
1861
|
sessionId: input.message.sessionId ?? "",
|
|
1826
|
-
branchName: input.message.branchName,
|
|
1827
1862
|
mode: "foreground",
|
|
1828
1863
|
pid: subprocess.pid,
|
|
1829
1864
|
processGroupId: process.platform === "win32" ? void 0 : subprocess.pid,
|
|
@@ -1887,34 +1922,16 @@ async function executeStreamingCommand(input) {
|
|
|
1887
1922
|
});
|
|
1888
1923
|
return;
|
|
1889
1924
|
}
|
|
1890
|
-
const
|
|
1891
|
-
|
|
1892
|
-
baseUrl: input.baseUrl,
|
|
1893
|
-
token: input.token,
|
|
1894
|
-
projectRoot: input.projectRoot,
|
|
1895
|
-
syncRoot: input.syncRoot,
|
|
1896
|
-
branchName: input.message.branchName,
|
|
1897
|
-
manifest: input.manifest
|
|
1898
|
-
});
|
|
1899
|
-
const artifactProcessEnv = await prepareArtifactEnvForShell({
|
|
1925
|
+
const targetProcessEnv = await prepareShellEnvForTarget({
|
|
1926
|
+
target: input.resolvedTarget.target,
|
|
1900
1927
|
baseUrl: input.baseUrl,
|
|
1901
1928
|
token: input.token,
|
|
1902
|
-
projectId: input.projectId,
|
|
1903
|
-
branchName: input.message.branchName,
|
|
1904
1929
|
sessionId: input.message.sessionId,
|
|
1905
|
-
artifactRoot: input.artifactRoot
|
|
1906
|
-
});
|
|
1907
|
-
const planProcessEnv = preparePlanEnvForShell({
|
|
1908
|
-
projectId: input.projectId,
|
|
1909
|
-
branchName: input.message.branchName,
|
|
1930
|
+
artifactRoot: input.artifactRoot,
|
|
1910
1931
|
planRoot: input.planRoot,
|
|
1911
1932
|
activePlanId: input.message.env?.R5D_ACTIVE_PLAN_ID
|
|
1912
1933
|
});
|
|
1913
|
-
const
|
|
1914
|
-
if (input.message.env?.R5D_USE_WORKSPACE_GIT === "1" && !import_node_fs.default.existsSync(import_node_path.default.join(commandRoot, ".git"))) {
|
|
1915
|
-
throw new Error("The canonical workspace checkout is not initialized on this worker");
|
|
1916
|
-
}
|
|
1917
|
-
const cwd = resolveCommandCwd(commandRoot, input.message.cwd);
|
|
1934
|
+
const cwd = resolveCommandCwd(input.resolvedTarget.rootPath, input.message.cwd);
|
|
1918
1935
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1919
1936
|
cwd,
|
|
1920
1937
|
stdout: "pipe",
|
|
@@ -1924,15 +1941,13 @@ async function executeStreamingCommand(input) {
|
|
|
1924
1941
|
...process.env,
|
|
1925
1942
|
...githubProcessEnv(),
|
|
1926
1943
|
...input.message.env ?? {},
|
|
1927
|
-
...
|
|
1928
|
-
...planProcessEnv
|
|
1944
|
+
...targetProcessEnv
|
|
1929
1945
|
}
|
|
1930
1946
|
});
|
|
1931
1947
|
activeProcesses.set(input.message.runId, {
|
|
1932
1948
|
process: subprocess,
|
|
1933
|
-
|
|
1949
|
+
target: input.resolvedTarget.target,
|
|
1934
1950
|
sessionId: input.message.sessionId,
|
|
1935
|
-
branchName: input.message.branchName,
|
|
1936
1951
|
mode: input.message.mode,
|
|
1937
1952
|
pid: subprocess.pid,
|
|
1938
1953
|
processGroupId: process.platform === "win32" ? void 0 : subprocess.pid,
|
|
@@ -2029,9 +2044,8 @@ function sendWorkerMessage(ws, message) {
|
|
|
2029
2044
|
function buildActiveProcessReports() {
|
|
2030
2045
|
return Array.from(activeProcesses.entries()).filter(([, active]) => active.sessionId.length > 0).map(([runId, active]) => ({
|
|
2031
2046
|
runId,
|
|
2032
|
-
|
|
2047
|
+
target: active.target,
|
|
2033
2048
|
sessionId: active.sessionId,
|
|
2034
|
-
branchName: active.branchName,
|
|
2035
2049
|
platform: process.platform,
|
|
2036
2050
|
arch: process.arch,
|
|
2037
2051
|
mode: active.mode,
|
|
@@ -2239,21 +2253,12 @@ function resolveHostShell(command, platform = process.platform) {
|
|
|
2239
2253
|
}
|
|
2240
2254
|
async function openPty(input) {
|
|
2241
2255
|
try {
|
|
2242
|
-
const
|
|
2243
|
-
|
|
2244
|
-
baseUrl: input.baseUrl,
|
|
2245
|
-
token: input.token,
|
|
2246
|
-
projectRoot: input.projectRoot,
|
|
2247
|
-
syncRoot: input.syncRoot,
|
|
2248
|
-
branchName: input.message.branchName,
|
|
2249
|
-
manifest: input.manifest
|
|
2250
|
-
});
|
|
2251
|
-
const planProcessEnv = preparePlanEnvForShell({
|
|
2252
|
-
projectId: input.projectId,
|
|
2253
|
-
branchName: input.message.branchName,
|
|
2256
|
+
const planProcessEnv = !(input.resolvedTarget.target.type === "workspace" && input.resolvedTarget.target.rootProfile === "canonical_sync") ? preparePlanEnvForShell({
|
|
2257
|
+
target: input.resolvedTarget.target,
|
|
2254
2258
|
planRoot: input.planRoot,
|
|
2255
2259
|
activePlanId: input.message.env?.R5D_ACTIVE_PLAN_ID
|
|
2256
|
-
});
|
|
2260
|
+
}) : {};
|
|
2261
|
+
const targetProcessEnv = targetIdentityEnv(input.resolvedTarget.target);
|
|
2257
2262
|
const shell = resolveHostShell(input.message.command);
|
|
2258
2263
|
const ptyProcess = createNodePtyBridge({
|
|
2259
2264
|
file: shell.file,
|
|
@@ -2262,14 +2267,13 @@ async function openPty(input) {
|
|
|
2262
2267
|
name: "xterm-256color",
|
|
2263
2268
|
cols: Math.max(1, Math.min(Math.floor(input.message.cols || 80), 500)),
|
|
2264
2269
|
rows: Math.max(1, Math.min(Math.floor(input.message.rows || 24), 500)),
|
|
2265
|
-
cwd:
|
|
2270
|
+
cwd: input.resolvedTarget.rootPath,
|
|
2266
2271
|
env: {
|
|
2267
2272
|
...process.env,
|
|
2268
2273
|
...githubProcessEnv(),
|
|
2269
2274
|
...input.message.env ?? {},
|
|
2270
2275
|
...planProcessEnv,
|
|
2271
|
-
|
|
2272
|
-
R5D_BRANCH_NAME: input.message.branchName
|
|
2276
|
+
...targetProcessEnv
|
|
2273
2277
|
}
|
|
2274
2278
|
},
|
|
2275
2279
|
onOpened: () => {
|
|
@@ -2307,8 +2311,7 @@ async function openPty(input) {
|
|
|
2307
2311
|
});
|
|
2308
2312
|
activePtys.set(input.message.ptyId, {
|
|
2309
2313
|
...ptyProcess,
|
|
2310
|
-
|
|
2311
|
-
branchName: input.message.branchName
|
|
2314
|
+
target: input.resolvedTarget.target
|
|
2312
2315
|
});
|
|
2313
2316
|
} catch (error) {
|
|
2314
2317
|
sendWorkerMessage(input.ws, {
|
|
@@ -2427,6 +2430,15 @@ async function startWorker(options) {
|
|
|
2427
2430
|
const allManifestCheckouts = () => [...manifestByProjectId.values()].flatMap(
|
|
2428
2431
|
(manifest) => manifest.branches.map((branchName) => ({ projectId: manifest.projectId, branchName }))
|
|
2429
2432
|
);
|
|
2433
|
+
const resolveMessageTarget = (target) => resolveWorkerSessionTarget({
|
|
2434
|
+
target,
|
|
2435
|
+
baseUrl,
|
|
2436
|
+
token,
|
|
2437
|
+
projectsRoot,
|
|
2438
|
+
syncRoot,
|
|
2439
|
+
workspaceShadowRoot,
|
|
2440
|
+
manifestByProjectId
|
|
2441
|
+
});
|
|
2430
2442
|
const ensureVisibleWorkspaceCheckouts = (targets, options2 = {}) => {
|
|
2431
2443
|
const created = [];
|
|
2432
2444
|
for (const target of targets) {
|
|
@@ -2682,7 +2694,11 @@ async function startWorker(options) {
|
|
|
2682
2694
|
}
|
|
2683
2695
|
if (message.type === "workspace_head_updated") {
|
|
2684
2696
|
if (!activeWorkspaceIncidentId) {
|
|
2685
|
-
await runRequestedWorkspaceSync(
|
|
2697
|
+
await runRequestedWorkspaceSync(
|
|
2698
|
+
crypto.randomUUID(),
|
|
2699
|
+
{ type: "inbound_head", detail: message.commitHash },
|
|
2700
|
+
{ skipVisibleMirror: true }
|
|
2701
|
+
);
|
|
2686
2702
|
}
|
|
2687
2703
|
return;
|
|
2688
2704
|
}
|
|
@@ -2692,8 +2708,6 @@ async function startWorker(options) {
|
|
|
2692
2708
|
await syncSessionArtifacts({
|
|
2693
2709
|
baseUrl,
|
|
2694
2710
|
token,
|
|
2695
|
-
projectId: message.projectId,
|
|
2696
|
-
branchName: message.branchName,
|
|
2697
2711
|
sessionId: message.sessionId,
|
|
2698
2712
|
artifactRoot
|
|
2699
2713
|
});
|
|
@@ -2813,11 +2827,19 @@ async function startWorker(options) {
|
|
|
2813
2827
|
});
|
|
2814
2828
|
return;
|
|
2815
2829
|
}
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2830
|
+
try {
|
|
2831
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2832
|
+
process.stdout.write(`[r5d-worker] pty ${message.ptyId}: ${describeWorkerSessionTarget(message.target)}
|
|
2819
2833
|
`);
|
|
2820
|
-
|
|
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
|
+
}
|
|
2821
2843
|
return;
|
|
2822
2844
|
}
|
|
2823
2845
|
if (message.type === "pty_input") {
|
|
@@ -2843,22 +2865,22 @@ async function startWorker(options) {
|
|
|
2843
2865
|
});
|
|
2844
2866
|
return;
|
|
2845
2867
|
}
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2868
|
+
let result;
|
|
2869
|
+
try {
|
|
2870
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2871
|
+
process.stdout.write(`[r5d-worker] exec ${message.runId}: ${message.argv.join(" ")}
|
|
2849
2872
|
`);
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
});
|
|
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
|
+
}
|
|
2862
2884
|
ws.send(JSON.stringify(result));
|
|
2863
2885
|
return;
|
|
2864
2886
|
}
|
|
@@ -2878,22 +2900,17 @@ async function startWorker(options) {
|
|
|
2878
2900
|
runId: message.runId
|
|
2879
2901
|
});
|
|
2880
2902
|
try {
|
|
2881
|
-
const
|
|
2882
|
-
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
2903
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2883
2904
|
process.stdout.write(`[r5d-worker] exec_start ${message.runId}: ${message.argv.join(" ")}
|
|
2884
2905
|
`);
|
|
2885
2906
|
void executeStreamingCommand({
|
|
2886
2907
|
ws,
|
|
2887
2908
|
message,
|
|
2888
|
-
|
|
2909
|
+
resolvedTarget,
|
|
2889
2910
|
baseUrl,
|
|
2890
2911
|
token,
|
|
2891
|
-
projectRoot,
|
|
2892
|
-
syncRoot,
|
|
2893
2912
|
artifactRoot,
|
|
2894
|
-
planRoot
|
|
2895
|
-
workspaceShadowRoot,
|
|
2896
|
-
manifest
|
|
2913
|
+
planRoot
|
|
2897
2914
|
}).catch((error) => {
|
|
2898
2915
|
sendWorkerMessage(ws, {
|
|
2899
2916
|
type: "exec_start_error",
|
|
@@ -2914,18 +2931,14 @@ async function startWorker(options) {
|
|
|
2914
2931
|
}
|
|
2915
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") {
|
|
2916
2933
|
try {
|
|
2917
|
-
const
|
|
2918
|
-
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
2934
|
+
const resolvedTarget = resolveMessageTarget(message.target);
|
|
2919
2935
|
const result = await executeOperation({
|
|
2920
2936
|
message,
|
|
2921
|
-
|
|
2937
|
+
resolvedTarget,
|
|
2922
2938
|
baseUrl,
|
|
2923
2939
|
token,
|
|
2924
|
-
projectRoot,
|
|
2925
|
-
syncRoot,
|
|
2926
2940
|
artifactRoot,
|
|
2927
|
-
planRoot
|
|
2928
|
-
manifest
|
|
2941
|
+
planRoot
|
|
2929
2942
|
});
|
|
2930
2943
|
ws.send(
|
|
2931
2944
|
JSON.stringify({
|
|
@@ -3053,6 +3066,7 @@ if (isCliEntrypoint()) {
|
|
|
3053
3066
|
}
|
|
3054
3067
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3055
3068
|
0 && (module.exports = {
|
|
3069
|
+
describeWorkerSessionTarget,
|
|
3056
3070
|
editWorkerTextFile,
|
|
3057
3071
|
ensureVisibleGitCheckout,
|
|
3058
3072
|
findWorkerFiles,
|
|
@@ -3061,11 +3075,14 @@ if (isCliEntrypoint()) {
|
|
|
3061
3075
|
isArtifactEnvPath,
|
|
3062
3076
|
listWorkerDirectory,
|
|
3063
3077
|
prepareArtifactEnvForShell,
|
|
3078
|
+
prepareBuiltInToolPathsForTarget,
|
|
3064
3079
|
preparePlanEnvForShell,
|
|
3080
|
+
prepareShellEnvForTarget,
|
|
3065
3081
|
readWorkerImageFile,
|
|
3066
3082
|
readWorkerTextFile,
|
|
3067
3083
|
resolveHostShell,
|
|
3068
3084
|
resolveWorkerFilePath,
|
|
3085
|
+
resolveWorkerSessionTarget,
|
|
3069
3086
|
syncSessionArtifacts,
|
|
3070
3087
|
visibleCheckoutGitTestHarness,
|
|
3071
3088
|
visibleCheckoutRemoteFor,
|