@ricsam/r5d-worker 0.0.6 → 0.0.7

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.
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var git_identity_exports = {};
20
+ __export(git_identity_exports, {
21
+ configureVisibleGitIdentity: () => configureVisibleGitIdentity
22
+ });
23
+ module.exports = __toCommonJS(git_identity_exports);
24
+ function configureVisibleGitIdentity(branchPath, identity, runGit) {
25
+ if (!identity) {
26
+ return;
27
+ }
28
+ const name = identity.name.trim();
29
+ const email = identity.email.trim();
30
+ if (!name || !email) {
31
+ throw new Error("Git identity must include name and email");
32
+ }
33
+ runGit(["config", "user.name", name], { cwd: branchPath });
34
+ runGit(["config", "user.email", email], { cwd: branchPath });
35
+ }
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ configureVisibleGitIdentity
39
+ });
package/dist/cjs/main.cjs CHANGED
@@ -97,7 +97,7 @@ function getWorkerVersion() {
97
97
  return packageVersion;
98
98
  }
99
99
  const sourceVersion = readVersionFile(import_node_path.default.join(current, "VERSION.txt"));
100
- if (sourceVersion && import_node_path.default.basename(current) === "binctl-packages") {
100
+ if (sourceVersion && import_node_path.default.basename(current) === "packages") {
101
101
  return sourceVersion;
102
102
  }
103
103
  const parent = import_node_path.default.dirname(current);
@@ -223,8 +223,8 @@ async function readResponseText(response) {
223
223
  return "";
224
224
  }
225
225
  }
226
- async function verifyBinctlAuth(baseUrl, token) {
227
- const statusUrl = new URL("/api/binctl/auth/status", baseUrl);
226
+ async function verifyR5dctlAuth(baseUrl, token) {
227
+ const statusUrl = new URL("/api/r5dctl/auth/status", baseUrl);
228
228
  let response;
229
229
  try {
230
230
  response = await fetch(statusUrl, {
@@ -253,12 +253,12 @@ async function verifyBinctlAuth(baseUrl, token) {
253
253
  );
254
254
  }
255
255
  function resolveCredentials(options, config) {
256
- const token = options.token ?? process.env.R5D_WORKER_TOKEN ?? process.env.R5D_TOKEN ?? process.env.BINCTL_TOKEN ?? config.token ?? options.apiKey ?? process.env.R5D_API_KEY ?? process.env.BINCTL_API_KEY ?? config.apiKey;
256
+ const token = options.token ?? process.env.R5D_WORKER_TOKEN ?? process.env.R5D_TOKEN ?? process.env.R5DCTL_TOKEN ?? config.token ?? options.apiKey ?? process.env.R5D_API_KEY ?? process.env.R5DCTL_API_KEY ?? config.apiKey;
257
257
  if (!token) {
258
258
  throw new Error("Authentication required. Run `r5dctl auth login` or set R5D_WORKER_TOKEN/R5D_API_KEY.");
259
259
  }
260
260
  return {
261
- baseUrl: normalizeBaseUrl(options.baseUrl ?? process.env.R5D_BASE_URL ?? process.env.BINCTL_BASE_URL ?? config.baseUrl ?? DEFAULT_BASE_URL),
261
+ baseUrl: normalizeBaseUrl(options.baseUrl ?? process.env.R5D_BASE_URL ?? process.env.R5DCTL_BASE_URL ?? config.baseUrl ?? DEFAULT_BASE_URL),
262
262
  token
263
263
  };
264
264
  }
@@ -685,6 +685,31 @@ async function collectStream(stream) {
685
685
  }
686
686
  return await new Response(stream).text();
687
687
  }
688
+ async function streamCommandOutput(stream, onData) {
689
+ if (!stream) {
690
+ return;
691
+ }
692
+ const reader = stream.getReader();
693
+ const decoder = new TextDecoder();
694
+ try {
695
+ while (true) {
696
+ const chunk = await reader.read();
697
+ if (chunk.done) {
698
+ break;
699
+ }
700
+ const text = decoder.decode(chunk.value, { stream: true });
701
+ if (text.length > 0) {
702
+ onData(text);
703
+ }
704
+ }
705
+ const trailing = decoder.decode();
706
+ if (trailing.length > 0) {
707
+ onData(trailing);
708
+ }
709
+ } finally {
710
+ reader.releaseLock();
711
+ }
712
+ }
688
713
  function ensureOperationBranch(input) {
689
714
  return ensureBranchWorkspace(input);
690
715
  }
@@ -1053,6 +1078,95 @@ async function executeCommand(input) {
1053
1078
  activeProcesses.delete(input.message.runId);
1054
1079
  }
1055
1080
  }
1081
+ async function executeStreamingCommand(input) {
1082
+ const startedAt = Date.now();
1083
+ let timeout;
1084
+ let started = false;
1085
+ let timedOut = false;
1086
+ try {
1087
+ const branchPath = ensureBranchWorkspace({
1088
+ projectId: input.projectId,
1089
+ baseUrl: input.baseUrl,
1090
+ token: input.token,
1091
+ projectRoot: input.projectRoot,
1092
+ syncRoot: input.syncRoot,
1093
+ branchName: input.message.branchName,
1094
+ manifest: input.manifest
1095
+ });
1096
+ const cwd = resolveCommandCwd(branchPath.branchPath, input.message.cwd);
1097
+ const subprocess = Bun.spawn(input.message.argv, {
1098
+ cwd,
1099
+ stdout: "pipe",
1100
+ stderr: "pipe",
1101
+ env: {
1102
+ ...process.env,
1103
+ ...containerRegistryEnv(),
1104
+ ...input.message.env ?? {}
1105
+ }
1106
+ });
1107
+ activeProcesses.set(input.message.runId, { process: subprocess, command: input.message.argv });
1108
+ started = true;
1109
+ sendWorkerMessage(input.ws, {
1110
+ type: "exec_started",
1111
+ requestId: input.message.requestId,
1112
+ runId: input.message.runId
1113
+ });
1114
+ if (input.message.timeoutMs) {
1115
+ timeout = setTimeout(() => {
1116
+ timedOut = true;
1117
+ subprocess.kill("SIGTERM");
1118
+ }, input.message.timeoutMs);
1119
+ }
1120
+ const [exitCode] = await Promise.all([
1121
+ subprocess.exited,
1122
+ streamCommandOutput(subprocess.stdout, (data) => {
1123
+ sendWorkerMessage(input.ws, {
1124
+ type: "exec_output",
1125
+ runId: input.message.runId,
1126
+ stream: "stdout",
1127
+ data
1128
+ });
1129
+ }),
1130
+ streamCommandOutput(subprocess.stderr, (data) => {
1131
+ sendWorkerMessage(input.ws, {
1132
+ type: "exec_output",
1133
+ runId: input.message.runId,
1134
+ stream: "stderr",
1135
+ data
1136
+ });
1137
+ })
1138
+ ]);
1139
+ sendWorkerMessage(input.ws, {
1140
+ type: "exec_exit",
1141
+ runId: input.message.runId,
1142
+ exitCode,
1143
+ durationMs: Date.now() - startedAt,
1144
+ ...timedOut ? { timedOut: true } : {}
1145
+ });
1146
+ } catch (error) {
1147
+ const message = error instanceof Error ? error.message : String(error);
1148
+ if (started) {
1149
+ sendWorkerMessage(input.ws, {
1150
+ type: "exec_error",
1151
+ runId: input.message.runId,
1152
+ error: message,
1153
+ durationMs: Date.now() - startedAt
1154
+ });
1155
+ } else {
1156
+ sendWorkerMessage(input.ws, {
1157
+ type: "exec_start_error",
1158
+ requestId: input.message.requestId,
1159
+ runId: input.message.runId,
1160
+ error: message
1161
+ });
1162
+ }
1163
+ } finally {
1164
+ if (timeout) {
1165
+ clearTimeout(timeout);
1166
+ }
1167
+ activeProcesses.delete(input.message.runId);
1168
+ }
1169
+ }
1056
1170
  function sendWorkerMessage(ws, message) {
1057
1171
  ws.send(JSON.stringify(message));
1058
1172
  }
@@ -1370,7 +1484,7 @@ async function startWorker(options) {
1370
1484
  process.stdout.write(`[r5d-worker] server: ${baseUrl}
1371
1485
  `);
1372
1486
  runGit(["--version"]);
1373
- await verifyBinctlAuth(baseUrl, token);
1487
+ await verifyR5dctlAuth(baseUrl, token);
1374
1488
  import_node_fs.default.mkdirSync(projectsRoot, { recursive: true });
1375
1489
  import_node_fs.default.mkdirSync(syncRoot, { recursive: true });
1376
1490
  const manifestByProjectId = /* @__PURE__ */ new Map();
@@ -1488,6 +1602,34 @@ async function startWorker(options) {
1488
1602
  ws.send(JSON.stringify(result));
1489
1603
  return;
1490
1604
  }
1605
+ if (message.type === "exec_start") {
1606
+ try {
1607
+ const manifest = manifestByProjectId.get(message.projectId);
1608
+ const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
1609
+ process.stdout.write(`[r5d-worker] exec_start ${message.runId}: ${message.argv.join(" ")}
1610
+ `);
1611
+ void withBranchLock(
1612
+ message.projectId,
1613
+ message.branchName,
1614
+ () => executeStreamingCommand({ ws, message, projectId: message.projectId, baseUrl, token, projectRoot, syncRoot, manifest })
1615
+ ).catch((error) => {
1616
+ sendWorkerMessage(ws, {
1617
+ type: "exec_start_error",
1618
+ requestId: message.requestId,
1619
+ runId: message.runId,
1620
+ error: error instanceof Error ? error.message : String(error)
1621
+ });
1622
+ });
1623
+ } catch (error) {
1624
+ sendWorkerMessage(ws, {
1625
+ type: "exec_start_error",
1626
+ requestId: message.requestId,
1627
+ runId: message.runId,
1628
+ error: error instanceof Error ? error.message : String(error)
1629
+ });
1630
+ }
1631
+ return;
1632
+ }
1491
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") {
1492
1634
  try {
1493
1635
  const manifest = manifestByProjectId.get(message.projectId);
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "type": "commonjs"
5
5
  }
@@ -0,0 +1,15 @@
1
+ function configureVisibleGitIdentity(branchPath, identity, runGit) {
2
+ if (!identity) {
3
+ return;
4
+ }
5
+ const name = identity.name.trim();
6
+ const email = identity.email.trim();
7
+ if (!name || !email) {
8
+ throw new Error("Git identity must include name and email");
9
+ }
10
+ runGit(["config", "user.name", name], { cwd: branchPath });
11
+ runGit(["config", "user.email", email], { cwd: branchPath });
12
+ }
13
+ export {
14
+ configureVisibleGitIdentity
15
+ };
package/dist/mjs/main.mjs CHANGED
@@ -74,7 +74,7 @@ function getWorkerVersion() {
74
74
  return packageVersion;
75
75
  }
76
76
  const sourceVersion = readVersionFile(path.join(current, "VERSION.txt"));
77
- if (sourceVersion && path.basename(current) === "binctl-packages") {
77
+ if (sourceVersion && path.basename(current) === "packages") {
78
78
  return sourceVersion;
79
79
  }
80
80
  const parent = path.dirname(current);
@@ -200,8 +200,8 @@ async function readResponseText(response) {
200
200
  return "";
201
201
  }
202
202
  }
203
- async function verifyBinctlAuth(baseUrl, token) {
204
- const statusUrl = new URL("/api/binctl/auth/status", baseUrl);
203
+ async function verifyR5dctlAuth(baseUrl, token) {
204
+ const statusUrl = new URL("/api/r5dctl/auth/status", baseUrl);
205
205
  let response;
206
206
  try {
207
207
  response = await fetch(statusUrl, {
@@ -230,12 +230,12 @@ async function verifyBinctlAuth(baseUrl, token) {
230
230
  );
231
231
  }
232
232
  function resolveCredentials(options, config) {
233
- const token = options.token ?? process.env.R5D_WORKER_TOKEN ?? process.env.R5D_TOKEN ?? process.env.BINCTL_TOKEN ?? config.token ?? options.apiKey ?? process.env.R5D_API_KEY ?? process.env.BINCTL_API_KEY ?? config.apiKey;
233
+ const token = options.token ?? process.env.R5D_WORKER_TOKEN ?? process.env.R5D_TOKEN ?? process.env.R5DCTL_TOKEN ?? config.token ?? options.apiKey ?? process.env.R5D_API_KEY ?? process.env.R5DCTL_API_KEY ?? config.apiKey;
234
234
  if (!token) {
235
235
  throw new Error("Authentication required. Run `r5dctl auth login` or set R5D_WORKER_TOKEN/R5D_API_KEY.");
236
236
  }
237
237
  return {
238
- baseUrl: normalizeBaseUrl(options.baseUrl ?? process.env.R5D_BASE_URL ?? process.env.BINCTL_BASE_URL ?? config.baseUrl ?? DEFAULT_BASE_URL),
238
+ baseUrl: normalizeBaseUrl(options.baseUrl ?? process.env.R5D_BASE_URL ?? process.env.R5DCTL_BASE_URL ?? config.baseUrl ?? DEFAULT_BASE_URL),
239
239
  token
240
240
  };
241
241
  }
@@ -662,6 +662,31 @@ async function collectStream(stream) {
662
662
  }
663
663
  return await new Response(stream).text();
664
664
  }
665
+ async function streamCommandOutput(stream, onData) {
666
+ if (!stream) {
667
+ return;
668
+ }
669
+ const reader = stream.getReader();
670
+ const decoder = new TextDecoder();
671
+ try {
672
+ while (true) {
673
+ const chunk = await reader.read();
674
+ if (chunk.done) {
675
+ break;
676
+ }
677
+ const text = decoder.decode(chunk.value, { stream: true });
678
+ if (text.length > 0) {
679
+ onData(text);
680
+ }
681
+ }
682
+ const trailing = decoder.decode();
683
+ if (trailing.length > 0) {
684
+ onData(trailing);
685
+ }
686
+ } finally {
687
+ reader.releaseLock();
688
+ }
689
+ }
665
690
  function ensureOperationBranch(input) {
666
691
  return ensureBranchWorkspace(input);
667
692
  }
@@ -1030,6 +1055,95 @@ async function executeCommand(input) {
1030
1055
  activeProcesses.delete(input.message.runId);
1031
1056
  }
1032
1057
  }
1058
+ async function executeStreamingCommand(input) {
1059
+ const startedAt = Date.now();
1060
+ let timeout;
1061
+ let started = false;
1062
+ let timedOut = false;
1063
+ try {
1064
+ const branchPath = ensureBranchWorkspace({
1065
+ projectId: input.projectId,
1066
+ baseUrl: input.baseUrl,
1067
+ token: input.token,
1068
+ projectRoot: input.projectRoot,
1069
+ syncRoot: input.syncRoot,
1070
+ branchName: input.message.branchName,
1071
+ manifest: input.manifest
1072
+ });
1073
+ const cwd = resolveCommandCwd(branchPath.branchPath, input.message.cwd);
1074
+ const subprocess = Bun.spawn(input.message.argv, {
1075
+ cwd,
1076
+ stdout: "pipe",
1077
+ stderr: "pipe",
1078
+ env: {
1079
+ ...process.env,
1080
+ ...containerRegistryEnv(),
1081
+ ...input.message.env ?? {}
1082
+ }
1083
+ });
1084
+ activeProcesses.set(input.message.runId, { process: subprocess, command: input.message.argv });
1085
+ started = true;
1086
+ sendWorkerMessage(input.ws, {
1087
+ type: "exec_started",
1088
+ requestId: input.message.requestId,
1089
+ runId: input.message.runId
1090
+ });
1091
+ if (input.message.timeoutMs) {
1092
+ timeout = setTimeout(() => {
1093
+ timedOut = true;
1094
+ subprocess.kill("SIGTERM");
1095
+ }, input.message.timeoutMs);
1096
+ }
1097
+ const [exitCode] = await Promise.all([
1098
+ subprocess.exited,
1099
+ streamCommandOutput(subprocess.stdout, (data) => {
1100
+ sendWorkerMessage(input.ws, {
1101
+ type: "exec_output",
1102
+ runId: input.message.runId,
1103
+ stream: "stdout",
1104
+ data
1105
+ });
1106
+ }),
1107
+ streamCommandOutput(subprocess.stderr, (data) => {
1108
+ sendWorkerMessage(input.ws, {
1109
+ type: "exec_output",
1110
+ runId: input.message.runId,
1111
+ stream: "stderr",
1112
+ data
1113
+ });
1114
+ })
1115
+ ]);
1116
+ sendWorkerMessage(input.ws, {
1117
+ type: "exec_exit",
1118
+ runId: input.message.runId,
1119
+ exitCode,
1120
+ durationMs: Date.now() - startedAt,
1121
+ ...timedOut ? { timedOut: true } : {}
1122
+ });
1123
+ } catch (error) {
1124
+ const message = error instanceof Error ? error.message : String(error);
1125
+ if (started) {
1126
+ sendWorkerMessage(input.ws, {
1127
+ type: "exec_error",
1128
+ runId: input.message.runId,
1129
+ error: message,
1130
+ durationMs: Date.now() - startedAt
1131
+ });
1132
+ } else {
1133
+ sendWorkerMessage(input.ws, {
1134
+ type: "exec_start_error",
1135
+ requestId: input.message.requestId,
1136
+ runId: input.message.runId,
1137
+ error: message
1138
+ });
1139
+ }
1140
+ } finally {
1141
+ if (timeout) {
1142
+ clearTimeout(timeout);
1143
+ }
1144
+ activeProcesses.delete(input.message.runId);
1145
+ }
1146
+ }
1033
1147
  function sendWorkerMessage(ws, message) {
1034
1148
  ws.send(JSON.stringify(message));
1035
1149
  }
@@ -1347,7 +1461,7 @@ async function startWorker(options) {
1347
1461
  process.stdout.write(`[r5d-worker] server: ${baseUrl}
1348
1462
  `);
1349
1463
  runGit(["--version"]);
1350
- await verifyBinctlAuth(baseUrl, token);
1464
+ await verifyR5dctlAuth(baseUrl, token);
1351
1465
  fs.mkdirSync(projectsRoot, { recursive: true });
1352
1466
  fs.mkdirSync(syncRoot, { recursive: true });
1353
1467
  const manifestByProjectId = /* @__PURE__ */ new Map();
@@ -1465,6 +1579,34 @@ async function startWorker(options) {
1465
1579
  ws.send(JSON.stringify(result));
1466
1580
  return;
1467
1581
  }
1582
+ if (message.type === "exec_start") {
1583
+ try {
1584
+ const manifest = manifestByProjectId.get(message.projectId);
1585
+ const projectRoot = projectRootFor(projectsRoot, message.projectId, manifestByProjectId);
1586
+ process.stdout.write(`[r5d-worker] exec_start ${message.runId}: ${message.argv.join(" ")}
1587
+ `);
1588
+ void withBranchLock(
1589
+ message.projectId,
1590
+ message.branchName,
1591
+ () => executeStreamingCommand({ ws, message, projectId: message.projectId, baseUrl, token, projectRoot, syncRoot, manifest })
1592
+ ).catch((error) => {
1593
+ sendWorkerMessage(ws, {
1594
+ type: "exec_start_error",
1595
+ requestId: message.requestId,
1596
+ runId: message.runId,
1597
+ error: error instanceof Error ? error.message : String(error)
1598
+ });
1599
+ });
1600
+ } catch (error) {
1601
+ sendWorkerMessage(ws, {
1602
+ type: "exec_start_error",
1603
+ requestId: message.requestId,
1604
+ runId: message.runId,
1605
+ error: error instanceof Error ? error.message : String(error)
1606
+ });
1607
+ }
1608
+ return;
1609
+ }
1468
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") {
1469
1611
  try {
1470
1612
  const manifest = manifestByProjectId.get(message.projectId);
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "type": "module"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/main.cjs",
6
6
  "module": "./dist/mjs/main.mjs",
@@ -15,7 +15,7 @@
15
15
  "repository": {
16
16
  "type": "git",
17
17
  "url": "git+https://github.com/ricsam/r5d-dev.git",
18
- "directory": "binctl-packages/r5d-worker"
18
+ "directory": "packages/r5d-worker"
19
19
  },
20
20
  "bin": {
21
21
  "r5d-worker": "dist/cjs/main.cjs"