opencara 0.105.1 → 0.105.3

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.
Files changed (2) hide show
  1. package/dist/bin.js +86 -2
  2. package/package.json +2 -2
package/dist/bin.js CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  uptime
14
14
  } from "node:os";
15
15
  import { statfsSync } from "node:fs";
16
+ import { spawn as spawn3 } from "node:child_process";
16
17
 
17
18
  // src/config/store.ts
18
19
  import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from "node:fs";
@@ -1205,7 +1206,7 @@ function resolveLocalAcpAdapter(command, args) {
1205
1206
  }
1206
1207
 
1207
1208
  // src/commands/run.ts
1208
- var PKG_VERSION = "0.105.1";
1209
+ var PKG_VERSION = "0.105.3";
1209
1210
  var LOG_FLUSH_MS = 800;
1210
1211
  var MAX_CHUNK_SIZE = 4 * 1024;
1211
1212
  async function run(opts = {}) {
@@ -1281,6 +1282,11 @@ async function executeJob(job, client) {
1281
1282
  if (flushTimer) return;
1282
1283
  flushTimer = setTimeout(flush, LOG_FLUSH_MS);
1283
1284
  };
1285
+ if (isInternalCommand(job.spec)) {
1286
+ flush();
1287
+ await runInternalCommand(job, client);
1288
+ return;
1289
+ }
1284
1290
  if (!job.spec.acp) {
1285
1291
  flush();
1286
1292
  const message = `legacy stdin-JSON dispatch removed in v0.30 \u2014 orchestrator must send spec.acp. Got command: ${job.spec.command}.`;
@@ -1322,6 +1328,63 @@ async function executeJob(job, client) {
1322
1328
  acpControllers.delete(runId);
1323
1329
  }
1324
1330
  }
1331
+ function isInternalCommand(spec) {
1332
+ return spec.command === "opencara" && Array.isArray(spec.args) && spec.args[0] === "internal";
1333
+ }
1334
+ async function runInternalCommand(job, client, opts = {}) {
1335
+ const runId = job.run.id;
1336
+ const args = job.spec.args ?? [];
1337
+ const binPath = opts.binPath ?? process.argv[1];
1338
+ const nodePath = opts.nodePath ?? process.execPath;
1339
+ if (!binPath) {
1340
+ client.send({
1341
+ type: "done",
1342
+ runId,
1343
+ status: "failed",
1344
+ errorMessage: "internal: process.argv[1] missing \u2014 cannot re-invoke bin"
1345
+ });
1346
+ return;
1347
+ }
1348
+ let seq = 0;
1349
+ const emit = (stream, chunk) => {
1350
+ let remaining = chunk;
1351
+ while (remaining.length > 0) {
1352
+ const take = remaining.slice(0, MAX_CHUNK_SIZE);
1353
+ client.send({ type: "log", runId, seq: seq++, stream, chunk: take });
1354
+ remaining = remaining.slice(MAX_CHUNK_SIZE);
1355
+ }
1356
+ };
1357
+ const child = spawn3(nodePath, [binPath, ...args], {
1358
+ cwd: job.spec.cwd,
1359
+ env: job.spec.env ? { ...process.env, ...job.spec.env } : process.env,
1360
+ stdio: ["ignore", "pipe", "pipe"]
1361
+ });
1362
+ child.stdout.setEncoding("utf8");
1363
+ child.stdout.on("data", (c) => emit("stdout", c));
1364
+ child.stderr.setEncoding("utf8");
1365
+ child.stderr.on("data", (c) => emit("stderr", c));
1366
+ const { exitCode, errorMessage } = await new Promise((resolve) => {
1367
+ let done = false;
1368
+ child.on("error", (err) => {
1369
+ if (done) return;
1370
+ done = true;
1371
+ resolve({ exitCode: 1, errorMessage: `internal spawn error: ${err.message}` });
1372
+ });
1373
+ child.on("close", (code, signal) => {
1374
+ if (done) return;
1375
+ done = true;
1376
+ resolve({ exitCode: code ?? (signal ? 1 : 0) });
1377
+ });
1378
+ });
1379
+ client.send({
1380
+ type: "done",
1381
+ runId,
1382
+ status: exitCode === 0 ? "succeeded" : "failed",
1383
+ exitCode,
1384
+ ...errorMessage ? { errorMessage } : {}
1385
+ });
1386
+ console.log(`[opencara] job ${runId.slice(-8)} (internal) \u2192 exit=${exitCode}`);
1387
+ }
1325
1388
  function collectSystemInfo() {
1326
1389
  try {
1327
1390
  const cpuList = cpus();
@@ -1470,7 +1533,17 @@ function worktreeCreate(args) {
1470
1533
  mkdirSync2(sessionDir, { recursive: true });
1471
1534
  if (existsSync4(join2(checkoutDir, ".git"))) {
1472
1535
  git(checkoutDir, ["fetch", "origin"]);
1473
- git(checkoutDir, ["checkout", "-B", branch, `origin/${branch}`]);
1536
+ if (refExists(checkoutDir, `refs/remotes/origin/${branch}`)) {
1537
+ git(checkoutDir, ["checkout", "-B", branch, `origin/${branch}`]);
1538
+ } else if (refExists(checkoutDir, `refs/heads/${branch}`)) {
1539
+ git(checkoutDir, ["checkout", branch]);
1540
+ } else if (fromBranch) {
1541
+ git(checkoutDir, ["checkout", "-B", branch, `origin/${fromBranch}`]);
1542
+ } else {
1543
+ fail(
1544
+ `worktree create: '${branch}' missing locally and on origin/, no --from-branch to fall back to`
1545
+ );
1546
+ }
1474
1547
  } else {
1475
1548
  mkdirSync2(checkoutDir, { recursive: true });
1476
1549
  const cloneArgs = ["-c", `credential.helper=${HELPER_SNIPPET}`, "clone"];
@@ -1572,6 +1645,17 @@ function worktreeRemove(args) {
1572
1645
  function git(cwd, args) {
1573
1646
  execFileSync("git", args, { cwd, stdio: ["ignore", "ignore", "inherit"] });
1574
1647
  }
1648
+ function refExists(cwd, ref) {
1649
+ try {
1650
+ execFileSync("git", ["rev-parse", "--verify", "--quiet", ref], {
1651
+ cwd,
1652
+ stdio: ["ignore", "ignore", "ignore"]
1653
+ });
1654
+ return true;
1655
+ } catch {
1656
+ return false;
1657
+ }
1658
+ }
1575
1659
  function pickFlag(argv, name) {
1576
1660
  const i = argv.indexOf(name);
1577
1661
  if (i === -1) return void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.105.1",
3
+ "version": "0.105.3",
4
4
  "description": "OpenCara agent-host CLI: register a machine as an agent host and run dispatched agents.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,7 @@
38
38
  "dev": "tsx watch src/bin.ts",
39
39
  "start": "node dist/bin.js",
40
40
  "typecheck": "tsc -b",
41
- "test": "node --import tsx --test --test-reporter=spec src/acp/__tests__/*.test.ts src/mcp/__tests__/*.test.ts src/runner/__tests__/*.test.ts src/bin/__tests__/*.test.ts",
41
+ "test": "node --import tsx --test --test-reporter=spec src/acp/__tests__/*.test.ts src/mcp/__tests__/*.test.ts src/runner/__tests__/*.test.ts src/bin/__tests__/*.test.ts src/commands/__tests__/*.test.ts",
42
42
  "acp:spike": "tsx src/acp/spike.ts",
43
43
  "mcp:smoke": "tsx src/mcp/smoke.ts",
44
44
  "clean": "rm -rf dist *.tsbuildinfo"