@ricsam/r5d-worker 0.0.7 → 0.0.9
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 +244 -16
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/main.mjs +234 -18
- package/dist/mjs/package.json +1 -1
- package/dist/types/main.d.ts +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ The worker uses the existing `r5dctl` config file and accepts `R5D_WORKER_TOKEN`
|
|
|
13
13
|
~/.r5d/projects/<namespace-repo>/<branch-name>
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
Visible branch checkouts
|
|
16
|
+
Visible branch checkouts are the user/agent workbench. The worker may clone the connected GitHub `origin` during first setup, but ongoing pull/push/fetch/reset behavior is manual Git work. r5d internal sync git metadata lives separately under `~/.r5d/sync`.
|
|
17
17
|
|
|
18
18
|
Worker labels are mandatory and unique per user. Choose labels that describe host capabilities, such as `macos`, `linux`, `ios`, or `ec2-build`.
|
|
19
19
|
|
package/dist/cjs/main.cjs
CHANGED
|
@@ -6,6 +6,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
9
13
|
var __copyProps = (to, from, except, desc) => {
|
|
10
14
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
15
|
for (let key of __getOwnPropNames(from))
|
|
@@ -22,6 +26,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
26
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
27
|
mod
|
|
24
28
|
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var main_exports = {};
|
|
31
|
+
__export(main_exports, {
|
|
32
|
+
ensureVisibleGitCheckout: () => ensureVisibleGitCheckout
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(main_exports);
|
|
25
35
|
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
26
36
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
27
37
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
@@ -29,6 +39,7 @@ var import_node_crypto = require("node:crypto");
|
|
|
29
39
|
var import_node_os2 = require("node:os");
|
|
30
40
|
var import_node_child_process = require("node:child_process");
|
|
31
41
|
var import_git_identity = require("./git-identity.cjs");
|
|
42
|
+
const import_meta = {};
|
|
32
43
|
const DEFAULT_BASE_URL = "https://r5d.dev";
|
|
33
44
|
const WORKER_PACKAGE_NAME = "@ricsam/r5d-worker";
|
|
34
45
|
const LABEL_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,62}$/;
|
|
@@ -39,6 +50,7 @@ const MAX_SYNC_DIFF_BYTES = 5 * 1024 * 1024;
|
|
|
39
50
|
const R5D_REMOTE_NAME = "r5d";
|
|
40
51
|
const LEGACY_BUILD_IT_NOW_REMOTE_NAME = "build-it-now";
|
|
41
52
|
const activeProcesses = /* @__PURE__ */ new Map();
|
|
53
|
+
const cancelledProcessRuns = /* @__PURE__ */ new Set();
|
|
42
54
|
const activePtys = /* @__PURE__ */ new Map();
|
|
43
55
|
const branchLocks = /* @__PURE__ */ new Map();
|
|
44
56
|
let containerRegistryCredential = null;
|
|
@@ -595,19 +607,23 @@ function ensureVisibleGitCheckout(input) {
|
|
|
595
607
|
validateBranchName(input.branchName);
|
|
596
608
|
import_node_fs.default.mkdirSync(input.projectRoot, { recursive: true });
|
|
597
609
|
const branchPath = import_node_path.default.join(input.projectRoot, input.branchName);
|
|
598
|
-
|
|
610
|
+
const createdCheckout = !hasNormalVisibleGitDir(branchPath);
|
|
611
|
+
if (createdCheckout) {
|
|
599
612
|
import_node_fs.default.rmSync(branchPath, { recursive: true, force: true });
|
|
600
613
|
import_node_fs.default.mkdirSync(import_node_path.default.dirname(branchPath), { recursive: true });
|
|
601
614
|
if (!tryGit(["clone", "--origin", "origin", input.githubRemoteUrl, branchPath], { auth: input.githubAuth })) {
|
|
602
615
|
import_node_fs.default.mkdirSync(branchPath, { recursive: true });
|
|
603
616
|
runGit(["init"], { cwd: branchPath });
|
|
604
617
|
}
|
|
618
|
+
ensureOriginRemote(branchPath, input.githubRemoteUrl);
|
|
619
|
+
configureVisibleGitHubAuth(branchPath, input.githubRemoteUrl, input.githubAuthHeader);
|
|
620
|
+
(0, import_git_identity.configureVisibleGitIdentity)(branchPath, visibleGitIdentity, runGit);
|
|
621
|
+
tryGit(["fetch", "origin", "--prune"], { cwd: branchPath, auth: input.githubAuth });
|
|
622
|
+
checkoutVisibleBranch({ branchPath, branchName: input.branchName, defaultBranch: input.defaultBranch });
|
|
623
|
+
return branchPath;
|
|
605
624
|
}
|
|
606
|
-
ensureOriginRemote(branchPath, input.githubRemoteUrl);
|
|
607
625
|
configureVisibleGitHubAuth(branchPath, input.githubRemoteUrl, input.githubAuthHeader);
|
|
608
626
|
(0, import_git_identity.configureVisibleGitIdentity)(branchPath, visibleGitIdentity, runGit);
|
|
609
|
-
tryGit(["fetch", "origin", "--prune"], { cwd: branchPath, auth: input.githubAuth });
|
|
610
|
-
checkoutVisibleBranch({ branchPath, branchName: input.branchName, defaultBranch: input.defaultBranch });
|
|
611
627
|
return branchPath;
|
|
612
628
|
}
|
|
613
629
|
function configureInternalRepo(context, remoteUrl) {
|
|
@@ -713,6 +729,15 @@ async function streamCommandOutput(stream, onData) {
|
|
|
713
729
|
function ensureOperationBranch(input) {
|
|
714
730
|
return ensureBranchWorkspace(input);
|
|
715
731
|
}
|
|
732
|
+
function internalGitProcessEnv(workspace, env) {
|
|
733
|
+
if (env?.R5D_USE_INTERNAL_GIT !== "1") {
|
|
734
|
+
return {};
|
|
735
|
+
}
|
|
736
|
+
return {
|
|
737
|
+
GIT_DIR: workspace.internalGit.gitDir,
|
|
738
|
+
GIT_WORK_TREE: workspace.branchPath
|
|
739
|
+
};
|
|
740
|
+
}
|
|
716
741
|
function formatLineNumberedContent(content, offset, limit) {
|
|
717
742
|
const allLines = content.split("\n");
|
|
718
743
|
const totalLines = allLines.length;
|
|
@@ -856,6 +881,171 @@ async function executeEditFileOperation(input) {
|
|
|
856
881
|
file: resolved.virtualPath
|
|
857
882
|
};
|
|
858
883
|
}
|
|
884
|
+
function decodePatchPath(rawPath) {
|
|
885
|
+
const trimmed = rawPath.trim();
|
|
886
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
887
|
+
try {
|
|
888
|
+
return JSON.parse(trimmed);
|
|
889
|
+
} catch {
|
|
890
|
+
return trimmed.slice(1, -1);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
return trimmed;
|
|
894
|
+
}
|
|
895
|
+
function normalizePatchPath(rawPath) {
|
|
896
|
+
const withoutMetadata = rawPath.split(" ")[0] ?? rawPath;
|
|
897
|
+
let patchPath = decodePatchPath(withoutMetadata);
|
|
898
|
+
if (patchPath === "/dev/null") {
|
|
899
|
+
return null;
|
|
900
|
+
}
|
|
901
|
+
if (patchPath.startsWith("a/") || patchPath.startsWith("b/")) {
|
|
902
|
+
patchPath = patchPath.slice(2);
|
|
903
|
+
}
|
|
904
|
+
if (!patchPath || import_node_path.default.isAbsolute(patchPath)) {
|
|
905
|
+
throw new Error(`Invalid patch path: ${rawPath}`);
|
|
906
|
+
}
|
|
907
|
+
const normalized = import_node_path.default.posix.normalize(patchPath);
|
|
908
|
+
if (normalized === "." || normalized.startsWith("../") || normalized === "..") {
|
|
909
|
+
throw new Error(`Invalid patch path: ${rawPath}`);
|
|
910
|
+
}
|
|
911
|
+
return normalized;
|
|
912
|
+
}
|
|
913
|
+
function readDiffPathToken(value, startIndex) {
|
|
914
|
+
let index = startIndex;
|
|
915
|
+
while (index < value.length && /\s/.test(value[index] ?? "")) {
|
|
916
|
+
index += 1;
|
|
917
|
+
}
|
|
918
|
+
if (index >= value.length) {
|
|
919
|
+
throw new Error("Missing path in patch header");
|
|
920
|
+
}
|
|
921
|
+
if (value[index] !== '"') {
|
|
922
|
+
const tokenStart2 = index;
|
|
923
|
+
while (index < value.length && !/\s/.test(value[index] ?? "")) {
|
|
924
|
+
index += 1;
|
|
925
|
+
}
|
|
926
|
+
return { token: value.slice(tokenStart2, index), nextIndex: index };
|
|
927
|
+
}
|
|
928
|
+
const tokenStart = index;
|
|
929
|
+
index += 1;
|
|
930
|
+
let escaped = false;
|
|
931
|
+
while (index < value.length) {
|
|
932
|
+
const character = value[index];
|
|
933
|
+
if (escaped) {
|
|
934
|
+
escaped = false;
|
|
935
|
+
} else if (character === "\\") {
|
|
936
|
+
escaped = true;
|
|
937
|
+
} else if (character === '"') {
|
|
938
|
+
index += 1;
|
|
939
|
+
return { token: value.slice(tokenStart, index), nextIndex: index };
|
|
940
|
+
}
|
|
941
|
+
index += 1;
|
|
942
|
+
}
|
|
943
|
+
throw new Error("Unterminated quoted path in patch header");
|
|
944
|
+
}
|
|
945
|
+
function parseDiffGitPaths(line) {
|
|
946
|
+
if (!line.startsWith("diff --git ")) {
|
|
947
|
+
throw new Error(`Invalid patch header: ${line}`);
|
|
948
|
+
}
|
|
949
|
+
const rest = line.slice("diff --git ".length);
|
|
950
|
+
const first = readDiffPathToken(rest, 0);
|
|
951
|
+
const second = readDiffPathToken(rest, first.nextIndex);
|
|
952
|
+
if (rest.slice(second.nextIndex).trim()) {
|
|
953
|
+
throw new Error(`Invalid patch header: ${line}`);
|
|
954
|
+
}
|
|
955
|
+
return {
|
|
956
|
+
oldPath: normalizePatchPath(first.token),
|
|
957
|
+
newPath: normalizePatchPath(second.token)
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
function summarizePatch(patch) {
|
|
961
|
+
if (!patch.trim()) {
|
|
962
|
+
throw new Error("Patch cannot be empty");
|
|
963
|
+
}
|
|
964
|
+
const files = [];
|
|
965
|
+
let current;
|
|
966
|
+
for (const line of patch.split(/\r?\n/)) {
|
|
967
|
+
if (line.startsWith("diff --git ")) {
|
|
968
|
+
const { oldPath, newPath } = parseDiffGitPaths(line);
|
|
969
|
+
if (!oldPath && !newPath) {
|
|
970
|
+
throw new Error(`Invalid patch header: ${line}`);
|
|
971
|
+
}
|
|
972
|
+
current = {
|
|
973
|
+
path: newPath ?? oldPath,
|
|
974
|
+
...oldPath && newPath && oldPath !== newPath ? { oldPath } : {},
|
|
975
|
+
operation: oldPath && newPath && oldPath !== newPath ? "move" : "update",
|
|
976
|
+
additions: 0,
|
|
977
|
+
deletions: 0,
|
|
978
|
+
hunks: 0
|
|
979
|
+
};
|
|
980
|
+
files.push(current);
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
if (!current) {
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
986
|
+
if (line.startsWith("new file mode ")) {
|
|
987
|
+
current.operation = "add";
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
if (line.startsWith("deleted file mode ")) {
|
|
991
|
+
current.operation = "delete";
|
|
992
|
+
if (current.oldPath) {
|
|
993
|
+
current.path = current.oldPath;
|
|
994
|
+
delete current.oldPath;
|
|
995
|
+
}
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
if (line.startsWith("rename from ")) {
|
|
999
|
+
current.operation = "move";
|
|
1000
|
+
current.oldPath = normalizePatchPath(line.slice("rename from ".length)) ?? void 0;
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
if (line.startsWith("rename to ")) {
|
|
1004
|
+
current.operation = "move";
|
|
1005
|
+
current.path = normalizePatchPath(line.slice("rename to ".length)) ?? current.path;
|
|
1006
|
+
continue;
|
|
1007
|
+
}
|
|
1008
|
+
if (line.startsWith("@@")) {
|
|
1009
|
+
current.hunks += 1;
|
|
1010
|
+
continue;
|
|
1011
|
+
}
|
|
1012
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
1013
|
+
current.additions += 1;
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
if (line.startsWith("-") && !line.startsWith("---")) {
|
|
1017
|
+
current.deletions += 1;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (files.length === 0) {
|
|
1021
|
+
throw new Error("Patch must contain at least one diff --git file header");
|
|
1022
|
+
}
|
|
1023
|
+
return files;
|
|
1024
|
+
}
|
|
1025
|
+
async function executeApplyPatchOperation(input) {
|
|
1026
|
+
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
1027
|
+
const files = summarizePatch(input.message.patch);
|
|
1028
|
+
const patchPath = import_node_path.default.join(import_node_os.default.tmpdir(), `r5d-apply-patch-${(0, import_node_crypto.randomUUID)()}.patch`);
|
|
1029
|
+
try {
|
|
1030
|
+
import_node_fs.default.writeFileSync(patchPath, input.message.patch, "utf8");
|
|
1031
|
+
runInternalGit(workspace.internalGit, ["apply", "--check", "--whitespace=nowarn", patchPath]);
|
|
1032
|
+
runInternalGit(workspace.internalGit, ["apply", "--whitespace=nowarn", patchPath]);
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
throw new Error(`Patch did not apply: ${error instanceof Error ? error.message : String(error)}`);
|
|
1035
|
+
} finally {
|
|
1036
|
+
import_node_fs.default.rmSync(patchPath, { force: true });
|
|
1037
|
+
}
|
|
1038
|
+
return {
|
|
1039
|
+
type: "apply_patch",
|
|
1040
|
+
files,
|
|
1041
|
+
summary: {
|
|
1042
|
+
filesChanged: files.length,
|
|
1043
|
+
additions: files.reduce((sum, file) => sum + file.additions, 0),
|
|
1044
|
+
deletions: files.reduce((sum, file) => sum + file.deletions, 0),
|
|
1045
|
+
hunks: files.reduce((sum, file) => sum + file.hunks, 0)
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
859
1049
|
async function executeViewFileBytesOperation(input) {
|
|
860
1050
|
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
861
1051
|
const resolved = resolveProjectFilePath(workspace.branchPath, input.message.filePath);
|
|
@@ -977,6 +1167,8 @@ async function executeOperation(input) {
|
|
|
977
1167
|
return executeCreateFileOperation({ ...input, message: input.message });
|
|
978
1168
|
case "edit_file":
|
|
979
1169
|
return executeEditFileOperation({ ...input, message: input.message });
|
|
1170
|
+
case "apply_patch":
|
|
1171
|
+
return executeApplyPatchOperation({ ...input, message: input.message });
|
|
980
1172
|
case "view_file_bytes":
|
|
981
1173
|
return executeViewFileBytesOperation({ ...input, message: input.message });
|
|
982
1174
|
case "sync":
|
|
@@ -1022,7 +1214,7 @@ async function executeCommand(input) {
|
|
|
1022
1214
|
const startedAt = Date.now();
|
|
1023
1215
|
let timeout;
|
|
1024
1216
|
try {
|
|
1025
|
-
const
|
|
1217
|
+
const workspace = ensureBranchWorkspace({
|
|
1026
1218
|
projectId: input.projectId,
|
|
1027
1219
|
baseUrl: input.baseUrl,
|
|
1028
1220
|
token: input.token,
|
|
@@ -1031,7 +1223,7 @@ async function executeCommand(input) {
|
|
|
1031
1223
|
branchName: input.message.branchName,
|
|
1032
1224
|
manifest: input.manifest
|
|
1033
1225
|
});
|
|
1034
|
-
const cwd = resolveCommandCwd(
|
|
1226
|
+
const cwd = resolveCommandCwd(workspace.branchPath, input.message.cwd);
|
|
1035
1227
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1036
1228
|
cwd,
|
|
1037
1229
|
stdout: "pipe",
|
|
@@ -1039,7 +1231,8 @@ async function executeCommand(input) {
|
|
|
1039
1231
|
env: {
|
|
1040
1232
|
...process.env,
|
|
1041
1233
|
...containerRegistryEnv(),
|
|
1042
|
-
...input.message.env ?? {}
|
|
1234
|
+
...input.message.env ?? {},
|
|
1235
|
+
...internalGitProcessEnv(workspace, input.message.env)
|
|
1043
1236
|
}
|
|
1044
1237
|
});
|
|
1045
1238
|
activeProcesses.set(input.message.runId, { process: subprocess, command: input.message.argv });
|
|
@@ -1084,7 +1277,16 @@ async function executeStreamingCommand(input) {
|
|
|
1084
1277
|
let started = false;
|
|
1085
1278
|
let timedOut = false;
|
|
1086
1279
|
try {
|
|
1087
|
-
|
|
1280
|
+
if (cancelledProcessRuns.delete(input.message.runId)) {
|
|
1281
|
+
sendWorkerMessage(input.ws, {
|
|
1282
|
+
type: "exec_start_error",
|
|
1283
|
+
requestId: input.message.requestId,
|
|
1284
|
+
runId: input.message.runId,
|
|
1285
|
+
error: "Command cancelled before it started"
|
|
1286
|
+
});
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
const workspace = ensureBranchWorkspace({
|
|
1088
1290
|
projectId: input.projectId,
|
|
1089
1291
|
baseUrl: input.baseUrl,
|
|
1090
1292
|
token: input.token,
|
|
@@ -1093,7 +1295,7 @@ async function executeStreamingCommand(input) {
|
|
|
1093
1295
|
branchName: input.message.branchName,
|
|
1094
1296
|
manifest: input.manifest
|
|
1095
1297
|
});
|
|
1096
|
-
const cwd = resolveCommandCwd(
|
|
1298
|
+
const cwd = resolveCommandCwd(workspace.branchPath, input.message.cwd);
|
|
1097
1299
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1098
1300
|
cwd,
|
|
1099
1301
|
stdout: "pipe",
|
|
@@ -1101,7 +1303,8 @@ async function executeStreamingCommand(input) {
|
|
|
1101
1303
|
env: {
|
|
1102
1304
|
...process.env,
|
|
1103
1305
|
...containerRegistryEnv(),
|
|
1104
|
-
...input.message.env ?? {}
|
|
1306
|
+
...input.message.env ?? {},
|
|
1307
|
+
...internalGitProcessEnv(workspace, input.message.env)
|
|
1105
1308
|
}
|
|
1106
1309
|
});
|
|
1107
1310
|
activeProcesses.set(input.message.runId, { process: subprocess, command: input.message.argv });
|
|
@@ -1165,6 +1368,7 @@ async function executeStreamingCommand(input) {
|
|
|
1165
1368
|
clearTimeout(timeout);
|
|
1166
1369
|
}
|
|
1167
1370
|
activeProcesses.delete(input.message.runId);
|
|
1371
|
+
cancelledProcessRuns.delete(input.message.runId);
|
|
1168
1372
|
}
|
|
1169
1373
|
}
|
|
1170
1374
|
function sendWorkerMessage(ws, message) {
|
|
@@ -1557,14 +1761,16 @@ async function startWorker(options) {
|
|
|
1557
1761
|
const active = activeProcesses.get(message.runId);
|
|
1558
1762
|
if (active) {
|
|
1559
1763
|
active.process.kill("SIGTERM");
|
|
1764
|
+
} else {
|
|
1765
|
+
cancelledProcessRuns.add(message.runId);
|
|
1560
1766
|
}
|
|
1561
1767
|
ws.send(
|
|
1562
1768
|
JSON.stringify({
|
|
1563
1769
|
type: "cancel_result",
|
|
1564
1770
|
requestId: message.requestId,
|
|
1565
1771
|
runId: message.runId,
|
|
1566
|
-
cancelled:
|
|
1567
|
-
message: active ? `Sent SIGTERM to ${active.command.join(" ")}` : "
|
|
1772
|
+
cancelled: true,
|
|
1773
|
+
message: active ? `Sent SIGTERM to ${active.command.join(" ")}` : "Cancellation queued before command start"
|
|
1568
1774
|
})
|
|
1569
1775
|
);
|
|
1570
1776
|
return;
|
|
@@ -1603,6 +1809,11 @@ async function startWorker(options) {
|
|
|
1603
1809
|
return;
|
|
1604
1810
|
}
|
|
1605
1811
|
if (message.type === "exec_start") {
|
|
1812
|
+
sendWorkerMessage(ws, {
|
|
1813
|
+
type: "exec_accepted",
|
|
1814
|
+
requestId: message.requestId,
|
|
1815
|
+
runId: message.runId
|
|
1816
|
+
});
|
|
1606
1817
|
try {
|
|
1607
1818
|
const manifest = manifestByProjectId.get(message.projectId);
|
|
1608
1819
|
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
@@ -1630,7 +1841,7 @@ async function startWorker(options) {
|
|
|
1630
1841
|
}
|
|
1631
1842
|
return;
|
|
1632
1843
|
}
|
|
1633
|
-
if (message.type === "read_file" || message.type === "create_file" || message.type === "edit_file" || message.type === "view_file_bytes" || message.type === "sync" || message.type === "confirm_large_diff" || message.type === "pull_branch") {
|
|
1844
|
+
if (message.type === "read_file" || message.type === "create_file" || message.type === "edit_file" || message.type === "apply_patch" || message.type === "view_file_bytes" || message.type === "sync" || message.type === "confirm_large_diff" || message.type === "pull_branch") {
|
|
1634
1845
|
try {
|
|
1635
1846
|
const manifest = manifestByProjectId.get(message.projectId);
|
|
1636
1847
|
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
@@ -1655,6 +1866,17 @@ async function startWorker(options) {
|
|
|
1655
1866
|
})
|
|
1656
1867
|
);
|
|
1657
1868
|
}
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
const unhandledMessage = message;
|
|
1872
|
+
if (typeof unhandledMessage.requestId === "string") {
|
|
1873
|
+
ws.send(
|
|
1874
|
+
JSON.stringify({
|
|
1875
|
+
type: "operation_result",
|
|
1876
|
+
requestId: unhandledMessage.requestId,
|
|
1877
|
+
error: `Unsupported worker message type: ${String(unhandledMessage.type)}`
|
|
1878
|
+
})
|
|
1879
|
+
);
|
|
1658
1880
|
}
|
|
1659
1881
|
})().catch((error) => {
|
|
1660
1882
|
process.stderr.write(`[r5d-worker] message handling failed: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -1688,8 +1910,14 @@ async function main() {
|
|
|
1688
1910
|
}
|
|
1689
1911
|
await startWorker(parsed.options);
|
|
1690
1912
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1913
|
+
if (import_meta.main) {
|
|
1914
|
+
main().catch((error) => {
|
|
1915
|
+
process.stderr.write(`[r5d-worker] ${error instanceof Error ? error.message : String(error)}
|
|
1693
1916
|
`);
|
|
1694
|
-
|
|
1917
|
+
process.exit(1);
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1921
|
+
0 && (module.exports = {
|
|
1922
|
+
ensureVisibleGitCheckout
|
|
1695
1923
|
});
|
package/dist/cjs/package.json
CHANGED
package/dist/mjs/main.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { createHash } from "node:crypto";
|
|
5
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import { hostname } from "node:os";
|
|
7
7
|
import { spawn as spawnChildProcess } from "node:child_process";
|
|
8
8
|
import { configureVisibleGitIdentity } from "./git-identity.mjs";
|
|
@@ -16,6 +16,7 @@ const MAX_SYNC_DIFF_BYTES = 5 * 1024 * 1024;
|
|
|
16
16
|
const R5D_REMOTE_NAME = "r5d";
|
|
17
17
|
const LEGACY_BUILD_IT_NOW_REMOTE_NAME = "build-it-now";
|
|
18
18
|
const activeProcesses = /* @__PURE__ */ new Map();
|
|
19
|
+
const cancelledProcessRuns = /* @__PURE__ */ new Set();
|
|
19
20
|
const activePtys = /* @__PURE__ */ new Map();
|
|
20
21
|
const branchLocks = /* @__PURE__ */ new Map();
|
|
21
22
|
let containerRegistryCredential = null;
|
|
@@ -572,19 +573,23 @@ function ensureVisibleGitCheckout(input) {
|
|
|
572
573
|
validateBranchName(input.branchName);
|
|
573
574
|
fs.mkdirSync(input.projectRoot, { recursive: true });
|
|
574
575
|
const branchPath = path.join(input.projectRoot, input.branchName);
|
|
575
|
-
|
|
576
|
+
const createdCheckout = !hasNormalVisibleGitDir(branchPath);
|
|
577
|
+
if (createdCheckout) {
|
|
576
578
|
fs.rmSync(branchPath, { recursive: true, force: true });
|
|
577
579
|
fs.mkdirSync(path.dirname(branchPath), { recursive: true });
|
|
578
580
|
if (!tryGit(["clone", "--origin", "origin", input.githubRemoteUrl, branchPath], { auth: input.githubAuth })) {
|
|
579
581
|
fs.mkdirSync(branchPath, { recursive: true });
|
|
580
582
|
runGit(["init"], { cwd: branchPath });
|
|
581
583
|
}
|
|
584
|
+
ensureOriginRemote(branchPath, input.githubRemoteUrl);
|
|
585
|
+
configureVisibleGitHubAuth(branchPath, input.githubRemoteUrl, input.githubAuthHeader);
|
|
586
|
+
configureVisibleGitIdentity(branchPath, visibleGitIdentity, runGit);
|
|
587
|
+
tryGit(["fetch", "origin", "--prune"], { cwd: branchPath, auth: input.githubAuth });
|
|
588
|
+
checkoutVisibleBranch({ branchPath, branchName: input.branchName, defaultBranch: input.defaultBranch });
|
|
589
|
+
return branchPath;
|
|
582
590
|
}
|
|
583
|
-
ensureOriginRemote(branchPath, input.githubRemoteUrl);
|
|
584
591
|
configureVisibleGitHubAuth(branchPath, input.githubRemoteUrl, input.githubAuthHeader);
|
|
585
592
|
configureVisibleGitIdentity(branchPath, visibleGitIdentity, runGit);
|
|
586
|
-
tryGit(["fetch", "origin", "--prune"], { cwd: branchPath, auth: input.githubAuth });
|
|
587
|
-
checkoutVisibleBranch({ branchPath, branchName: input.branchName, defaultBranch: input.defaultBranch });
|
|
588
593
|
return branchPath;
|
|
589
594
|
}
|
|
590
595
|
function configureInternalRepo(context, remoteUrl) {
|
|
@@ -690,6 +695,15 @@ async function streamCommandOutput(stream, onData) {
|
|
|
690
695
|
function ensureOperationBranch(input) {
|
|
691
696
|
return ensureBranchWorkspace(input);
|
|
692
697
|
}
|
|
698
|
+
function internalGitProcessEnv(workspace, env) {
|
|
699
|
+
if (env?.R5D_USE_INTERNAL_GIT !== "1") {
|
|
700
|
+
return {};
|
|
701
|
+
}
|
|
702
|
+
return {
|
|
703
|
+
GIT_DIR: workspace.internalGit.gitDir,
|
|
704
|
+
GIT_WORK_TREE: workspace.branchPath
|
|
705
|
+
};
|
|
706
|
+
}
|
|
693
707
|
function formatLineNumberedContent(content, offset, limit) {
|
|
694
708
|
const allLines = content.split("\n");
|
|
695
709
|
const totalLines = allLines.length;
|
|
@@ -833,6 +847,171 @@ async function executeEditFileOperation(input) {
|
|
|
833
847
|
file: resolved.virtualPath
|
|
834
848
|
};
|
|
835
849
|
}
|
|
850
|
+
function decodePatchPath(rawPath) {
|
|
851
|
+
const trimmed = rawPath.trim();
|
|
852
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
853
|
+
try {
|
|
854
|
+
return JSON.parse(trimmed);
|
|
855
|
+
} catch {
|
|
856
|
+
return trimmed.slice(1, -1);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return trimmed;
|
|
860
|
+
}
|
|
861
|
+
function normalizePatchPath(rawPath) {
|
|
862
|
+
const withoutMetadata = rawPath.split(" ")[0] ?? rawPath;
|
|
863
|
+
let patchPath = decodePatchPath(withoutMetadata);
|
|
864
|
+
if (patchPath === "/dev/null") {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
if (patchPath.startsWith("a/") || patchPath.startsWith("b/")) {
|
|
868
|
+
patchPath = patchPath.slice(2);
|
|
869
|
+
}
|
|
870
|
+
if (!patchPath || path.isAbsolute(patchPath)) {
|
|
871
|
+
throw new Error(`Invalid patch path: ${rawPath}`);
|
|
872
|
+
}
|
|
873
|
+
const normalized = path.posix.normalize(patchPath);
|
|
874
|
+
if (normalized === "." || normalized.startsWith("../") || normalized === "..") {
|
|
875
|
+
throw new Error(`Invalid patch path: ${rawPath}`);
|
|
876
|
+
}
|
|
877
|
+
return normalized;
|
|
878
|
+
}
|
|
879
|
+
function readDiffPathToken(value, startIndex) {
|
|
880
|
+
let index = startIndex;
|
|
881
|
+
while (index < value.length && /\s/.test(value[index] ?? "")) {
|
|
882
|
+
index += 1;
|
|
883
|
+
}
|
|
884
|
+
if (index >= value.length) {
|
|
885
|
+
throw new Error("Missing path in patch header");
|
|
886
|
+
}
|
|
887
|
+
if (value[index] !== '"') {
|
|
888
|
+
const tokenStart2 = index;
|
|
889
|
+
while (index < value.length && !/\s/.test(value[index] ?? "")) {
|
|
890
|
+
index += 1;
|
|
891
|
+
}
|
|
892
|
+
return { token: value.slice(tokenStart2, index), nextIndex: index };
|
|
893
|
+
}
|
|
894
|
+
const tokenStart = index;
|
|
895
|
+
index += 1;
|
|
896
|
+
let escaped = false;
|
|
897
|
+
while (index < value.length) {
|
|
898
|
+
const character = value[index];
|
|
899
|
+
if (escaped) {
|
|
900
|
+
escaped = false;
|
|
901
|
+
} else if (character === "\\") {
|
|
902
|
+
escaped = true;
|
|
903
|
+
} else if (character === '"') {
|
|
904
|
+
index += 1;
|
|
905
|
+
return { token: value.slice(tokenStart, index), nextIndex: index };
|
|
906
|
+
}
|
|
907
|
+
index += 1;
|
|
908
|
+
}
|
|
909
|
+
throw new Error("Unterminated quoted path in patch header");
|
|
910
|
+
}
|
|
911
|
+
function parseDiffGitPaths(line) {
|
|
912
|
+
if (!line.startsWith("diff --git ")) {
|
|
913
|
+
throw new Error(`Invalid patch header: ${line}`);
|
|
914
|
+
}
|
|
915
|
+
const rest = line.slice("diff --git ".length);
|
|
916
|
+
const first = readDiffPathToken(rest, 0);
|
|
917
|
+
const second = readDiffPathToken(rest, first.nextIndex);
|
|
918
|
+
if (rest.slice(second.nextIndex).trim()) {
|
|
919
|
+
throw new Error(`Invalid patch header: ${line}`);
|
|
920
|
+
}
|
|
921
|
+
return {
|
|
922
|
+
oldPath: normalizePatchPath(first.token),
|
|
923
|
+
newPath: normalizePatchPath(second.token)
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
function summarizePatch(patch) {
|
|
927
|
+
if (!patch.trim()) {
|
|
928
|
+
throw new Error("Patch cannot be empty");
|
|
929
|
+
}
|
|
930
|
+
const files = [];
|
|
931
|
+
let current;
|
|
932
|
+
for (const line of patch.split(/\r?\n/)) {
|
|
933
|
+
if (line.startsWith("diff --git ")) {
|
|
934
|
+
const { oldPath, newPath } = parseDiffGitPaths(line);
|
|
935
|
+
if (!oldPath && !newPath) {
|
|
936
|
+
throw new Error(`Invalid patch header: ${line}`);
|
|
937
|
+
}
|
|
938
|
+
current = {
|
|
939
|
+
path: newPath ?? oldPath,
|
|
940
|
+
...oldPath && newPath && oldPath !== newPath ? { oldPath } : {},
|
|
941
|
+
operation: oldPath && newPath && oldPath !== newPath ? "move" : "update",
|
|
942
|
+
additions: 0,
|
|
943
|
+
deletions: 0,
|
|
944
|
+
hunks: 0
|
|
945
|
+
};
|
|
946
|
+
files.push(current);
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
if (!current) {
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
if (line.startsWith("new file mode ")) {
|
|
953
|
+
current.operation = "add";
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
if (line.startsWith("deleted file mode ")) {
|
|
957
|
+
current.operation = "delete";
|
|
958
|
+
if (current.oldPath) {
|
|
959
|
+
current.path = current.oldPath;
|
|
960
|
+
delete current.oldPath;
|
|
961
|
+
}
|
|
962
|
+
continue;
|
|
963
|
+
}
|
|
964
|
+
if (line.startsWith("rename from ")) {
|
|
965
|
+
current.operation = "move";
|
|
966
|
+
current.oldPath = normalizePatchPath(line.slice("rename from ".length)) ?? void 0;
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if (line.startsWith("rename to ")) {
|
|
970
|
+
current.operation = "move";
|
|
971
|
+
current.path = normalizePatchPath(line.slice("rename to ".length)) ?? current.path;
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
if (line.startsWith("@@")) {
|
|
975
|
+
current.hunks += 1;
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
979
|
+
current.additions += 1;
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
if (line.startsWith("-") && !line.startsWith("---")) {
|
|
983
|
+
current.deletions += 1;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
if (files.length === 0) {
|
|
987
|
+
throw new Error("Patch must contain at least one diff --git file header");
|
|
988
|
+
}
|
|
989
|
+
return files;
|
|
990
|
+
}
|
|
991
|
+
async function executeApplyPatchOperation(input) {
|
|
992
|
+
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
993
|
+
const files = summarizePatch(input.message.patch);
|
|
994
|
+
const patchPath = path.join(os.tmpdir(), `r5d-apply-patch-${randomUUID()}.patch`);
|
|
995
|
+
try {
|
|
996
|
+
fs.writeFileSync(patchPath, input.message.patch, "utf8");
|
|
997
|
+
runInternalGit(workspace.internalGit, ["apply", "--check", "--whitespace=nowarn", patchPath]);
|
|
998
|
+
runInternalGit(workspace.internalGit, ["apply", "--whitespace=nowarn", patchPath]);
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
throw new Error(`Patch did not apply: ${error instanceof Error ? error.message : String(error)}`);
|
|
1001
|
+
} finally {
|
|
1002
|
+
fs.rmSync(patchPath, { force: true });
|
|
1003
|
+
}
|
|
1004
|
+
return {
|
|
1005
|
+
type: "apply_patch",
|
|
1006
|
+
files,
|
|
1007
|
+
summary: {
|
|
1008
|
+
filesChanged: files.length,
|
|
1009
|
+
additions: files.reduce((sum, file) => sum + file.additions, 0),
|
|
1010
|
+
deletions: files.reduce((sum, file) => sum + file.deletions, 0),
|
|
1011
|
+
hunks: files.reduce((sum, file) => sum + file.hunks, 0)
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
836
1015
|
async function executeViewFileBytesOperation(input) {
|
|
837
1016
|
const workspace = ensureOperationBranch({ ...input, branchName: input.message.branchName });
|
|
838
1017
|
const resolved = resolveProjectFilePath(workspace.branchPath, input.message.filePath);
|
|
@@ -954,6 +1133,8 @@ async function executeOperation(input) {
|
|
|
954
1133
|
return executeCreateFileOperation({ ...input, message: input.message });
|
|
955
1134
|
case "edit_file":
|
|
956
1135
|
return executeEditFileOperation({ ...input, message: input.message });
|
|
1136
|
+
case "apply_patch":
|
|
1137
|
+
return executeApplyPatchOperation({ ...input, message: input.message });
|
|
957
1138
|
case "view_file_bytes":
|
|
958
1139
|
return executeViewFileBytesOperation({ ...input, message: input.message });
|
|
959
1140
|
case "sync":
|
|
@@ -999,7 +1180,7 @@ async function executeCommand(input) {
|
|
|
999
1180
|
const startedAt = Date.now();
|
|
1000
1181
|
let timeout;
|
|
1001
1182
|
try {
|
|
1002
|
-
const
|
|
1183
|
+
const workspace = ensureBranchWorkspace({
|
|
1003
1184
|
projectId: input.projectId,
|
|
1004
1185
|
baseUrl: input.baseUrl,
|
|
1005
1186
|
token: input.token,
|
|
@@ -1008,7 +1189,7 @@ async function executeCommand(input) {
|
|
|
1008
1189
|
branchName: input.message.branchName,
|
|
1009
1190
|
manifest: input.manifest
|
|
1010
1191
|
});
|
|
1011
|
-
const cwd = resolveCommandCwd(
|
|
1192
|
+
const cwd = resolveCommandCwd(workspace.branchPath, input.message.cwd);
|
|
1012
1193
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1013
1194
|
cwd,
|
|
1014
1195
|
stdout: "pipe",
|
|
@@ -1016,7 +1197,8 @@ async function executeCommand(input) {
|
|
|
1016
1197
|
env: {
|
|
1017
1198
|
...process.env,
|
|
1018
1199
|
...containerRegistryEnv(),
|
|
1019
|
-
...input.message.env ?? {}
|
|
1200
|
+
...input.message.env ?? {},
|
|
1201
|
+
...internalGitProcessEnv(workspace, input.message.env)
|
|
1020
1202
|
}
|
|
1021
1203
|
});
|
|
1022
1204
|
activeProcesses.set(input.message.runId, { process: subprocess, command: input.message.argv });
|
|
@@ -1061,7 +1243,16 @@ async function executeStreamingCommand(input) {
|
|
|
1061
1243
|
let started = false;
|
|
1062
1244
|
let timedOut = false;
|
|
1063
1245
|
try {
|
|
1064
|
-
|
|
1246
|
+
if (cancelledProcessRuns.delete(input.message.runId)) {
|
|
1247
|
+
sendWorkerMessage(input.ws, {
|
|
1248
|
+
type: "exec_start_error",
|
|
1249
|
+
requestId: input.message.requestId,
|
|
1250
|
+
runId: input.message.runId,
|
|
1251
|
+
error: "Command cancelled before it started"
|
|
1252
|
+
});
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
const workspace = ensureBranchWorkspace({
|
|
1065
1256
|
projectId: input.projectId,
|
|
1066
1257
|
baseUrl: input.baseUrl,
|
|
1067
1258
|
token: input.token,
|
|
@@ -1070,7 +1261,7 @@ async function executeStreamingCommand(input) {
|
|
|
1070
1261
|
branchName: input.message.branchName,
|
|
1071
1262
|
manifest: input.manifest
|
|
1072
1263
|
});
|
|
1073
|
-
const cwd = resolveCommandCwd(
|
|
1264
|
+
const cwd = resolveCommandCwd(workspace.branchPath, input.message.cwd);
|
|
1074
1265
|
const subprocess = Bun.spawn(input.message.argv, {
|
|
1075
1266
|
cwd,
|
|
1076
1267
|
stdout: "pipe",
|
|
@@ -1078,7 +1269,8 @@ async function executeStreamingCommand(input) {
|
|
|
1078
1269
|
env: {
|
|
1079
1270
|
...process.env,
|
|
1080
1271
|
...containerRegistryEnv(),
|
|
1081
|
-
...input.message.env ?? {}
|
|
1272
|
+
...input.message.env ?? {},
|
|
1273
|
+
...internalGitProcessEnv(workspace, input.message.env)
|
|
1082
1274
|
}
|
|
1083
1275
|
});
|
|
1084
1276
|
activeProcesses.set(input.message.runId, { process: subprocess, command: input.message.argv });
|
|
@@ -1142,6 +1334,7 @@ async function executeStreamingCommand(input) {
|
|
|
1142
1334
|
clearTimeout(timeout);
|
|
1143
1335
|
}
|
|
1144
1336
|
activeProcesses.delete(input.message.runId);
|
|
1337
|
+
cancelledProcessRuns.delete(input.message.runId);
|
|
1145
1338
|
}
|
|
1146
1339
|
}
|
|
1147
1340
|
function sendWorkerMessage(ws, message) {
|
|
@@ -1534,14 +1727,16 @@ async function startWorker(options) {
|
|
|
1534
1727
|
const active = activeProcesses.get(message.runId);
|
|
1535
1728
|
if (active) {
|
|
1536
1729
|
active.process.kill("SIGTERM");
|
|
1730
|
+
} else {
|
|
1731
|
+
cancelledProcessRuns.add(message.runId);
|
|
1537
1732
|
}
|
|
1538
1733
|
ws.send(
|
|
1539
1734
|
JSON.stringify({
|
|
1540
1735
|
type: "cancel_result",
|
|
1541
1736
|
requestId: message.requestId,
|
|
1542
1737
|
runId: message.runId,
|
|
1543
|
-
cancelled:
|
|
1544
|
-
message: active ? `Sent SIGTERM to ${active.command.join(" ")}` : "
|
|
1738
|
+
cancelled: true,
|
|
1739
|
+
message: active ? `Sent SIGTERM to ${active.command.join(" ")}` : "Cancellation queued before command start"
|
|
1545
1740
|
})
|
|
1546
1741
|
);
|
|
1547
1742
|
return;
|
|
@@ -1580,6 +1775,11 @@ async function startWorker(options) {
|
|
|
1580
1775
|
return;
|
|
1581
1776
|
}
|
|
1582
1777
|
if (message.type === "exec_start") {
|
|
1778
|
+
sendWorkerMessage(ws, {
|
|
1779
|
+
type: "exec_accepted",
|
|
1780
|
+
requestId: message.requestId,
|
|
1781
|
+
runId: message.runId
|
|
1782
|
+
});
|
|
1583
1783
|
try {
|
|
1584
1784
|
const manifest = manifestByProjectId.get(message.projectId);
|
|
1585
1785
|
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
@@ -1607,7 +1807,7 @@ async function startWorker(options) {
|
|
|
1607
1807
|
}
|
|
1608
1808
|
return;
|
|
1609
1809
|
}
|
|
1610
|
-
if (message.type === "read_file" || message.type === "create_file" || message.type === "edit_file" || message.type === "view_file_bytes" || message.type === "sync" || message.type === "confirm_large_diff" || message.type === "pull_branch") {
|
|
1810
|
+
if (message.type === "read_file" || message.type === "create_file" || message.type === "edit_file" || message.type === "apply_patch" || message.type === "view_file_bytes" || message.type === "sync" || message.type === "confirm_large_diff" || message.type === "pull_branch") {
|
|
1611
1811
|
try {
|
|
1612
1812
|
const manifest = manifestByProjectId.get(message.projectId);
|
|
1613
1813
|
const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
|
|
@@ -1632,6 +1832,17 @@ async function startWorker(options) {
|
|
|
1632
1832
|
})
|
|
1633
1833
|
);
|
|
1634
1834
|
}
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
const unhandledMessage = message;
|
|
1838
|
+
if (typeof unhandledMessage.requestId === "string") {
|
|
1839
|
+
ws.send(
|
|
1840
|
+
JSON.stringify({
|
|
1841
|
+
type: "operation_result",
|
|
1842
|
+
requestId: unhandledMessage.requestId,
|
|
1843
|
+
error: `Unsupported worker message type: ${String(unhandledMessage.type)}`
|
|
1844
|
+
})
|
|
1845
|
+
);
|
|
1635
1846
|
}
|
|
1636
1847
|
})().catch((error) => {
|
|
1637
1848
|
process.stderr.write(`[r5d-worker] message handling failed: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -1665,8 +1876,13 @@ async function main() {
|
|
|
1665
1876
|
}
|
|
1666
1877
|
await startWorker(parsed.options);
|
|
1667
1878
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1879
|
+
if (import.meta.main) {
|
|
1880
|
+
main().catch((error) => {
|
|
1881
|
+
process.stderr.write(`[r5d-worker] ${error instanceof Error ? error.message : String(error)}
|
|
1670
1882
|
`);
|
|
1671
|
-
|
|
1672
|
-
});
|
|
1883
|
+
process.exit(1);
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
export {
|
|
1887
|
+
ensureVisibleGitCheckout
|
|
1888
|
+
};
|
package/dist/mjs/package.json
CHANGED
package/dist/types/main.d.ts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
type GitAuth = {
|
|
3
|
+
extraHeaderUrl: string;
|
|
4
|
+
header: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function ensureVisibleGitCheckout(input: {
|
|
7
|
+
projectRoot: string;
|
|
8
|
+
branchName: string;
|
|
9
|
+
githubRemoteUrl: string;
|
|
10
|
+
githubAuth?: GitAuth;
|
|
11
|
+
githubAuthHeader?: string | null;
|
|
12
|
+
defaultBranch: string;
|
|
13
|
+
}): string;
|
|
2
14
|
export {};
|