opencara 0.105.4 → 0.106.0

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/dist/bin.js CHANGED
@@ -1232,7 +1232,7 @@ function resolveLocalAcpAdapter(command, args) {
1232
1232
  }
1233
1233
 
1234
1234
  // src/commands/run.ts
1235
- var PKG_VERSION = "0.105.4";
1235
+ var PKG_VERSION = "0.106.0";
1236
1236
  var LOG_FLUSH_MS = 800;
1237
1237
  var MAX_CHUNK_SIZE = 4 * 1024;
1238
1238
  async function run(opts = {}) {
@@ -1505,13 +1505,15 @@ import {
1505
1505
  existsSync as existsSync4,
1506
1506
  realpathSync,
1507
1507
  writeFileSync as writeFileSync2,
1508
- renameSync
1508
+ renameSync,
1509
+ symlinkSync
1509
1510
  } from "node:fs";
1510
1511
  import { homedir as homedir2 } from "node:os";
1511
1512
  import { join as join2, sep } from "node:path";
1512
1513
  var OPENCARA_ROOT = join2(homedir2(), ".opencara");
1513
1514
  var WORK_ROOT = join2(OPENCARA_ROOT, "work");
1514
1515
  var SESSION_ROOT = join2(OPENCARA_ROOT, "sessions");
1516
+ var CACHE_ROOT = join2(OPENCARA_ROOT, "cache");
1515
1517
  async function internal(argv) {
1516
1518
  const sub = argv[0];
1517
1519
  const rest = argv.slice(1);
@@ -1554,17 +1556,51 @@ function worktreeCreate(args) {
1554
1556
  if (!key) fail(`invalid --key '${rawKey}'`);
1555
1557
  const sessionDir = join2(SESSION_ROOT, key);
1556
1558
  const checkoutDir = join2(WORK_ROOT, key, "checkout");
1559
+ const useCache = hasFlag(args, "--cache-repo");
1560
+ const useLfs = hasFlag(args, "--lfs");
1561
+ if (useLfs && !useCache) {
1562
+ fail("--lfs requires --cache-repo");
1563
+ }
1564
+ const cacheDir = useCache ? join2(CACHE_ROOT, safeKey(repo)) : null;
1565
+ const gitEnv = useCache && !useLfs ? { ...process.env, GIT_LFS_SKIP_SMUDGE: "1" } : void 0;
1557
1566
  const HELPER_SNIPPET = '!f() { echo username=x-access-token; echo "password=$GH_TOKEN"; }; f';
1558
1567
  const cleanUrl = `https://github.com/${repo}.git`;
1559
1568
  mkdirSync2(sessionDir, { recursive: true });
1569
+ if (cacheDir) {
1570
+ if (existsSync4(join2(cacheDir, ".git"))) {
1571
+ git(cacheDir, ["fetch", "--all", "--prune"], gitEnv);
1572
+ } else {
1573
+ mkdirSync2(cacheDir, { recursive: true });
1574
+ try {
1575
+ git(
1576
+ cacheDir,
1577
+ ["-c", `credential.helper=${HELPER_SNIPPET}`, "clone", cleanUrl, "."],
1578
+ gitEnv
1579
+ );
1580
+ git(cacheDir, ["config", "credential.helper", HELPER_SNIPPET]);
1581
+ } catch (err) {
1582
+ try {
1583
+ if (!existsSync4(join2(cacheDir, ".git", "HEAD"))) {
1584
+ rmSync(cacheDir, { recursive: true, force: true });
1585
+ }
1586
+ } catch {
1587
+ }
1588
+ throw err;
1589
+ }
1590
+ }
1591
+ if (useLfs) {
1592
+ git(cacheDir, ["lfs", "fetch", "--all"], gitEnv);
1593
+ mkdirSync2(join2(cacheDir, ".git", "lfs", "objects"), { recursive: true });
1594
+ }
1595
+ }
1560
1596
  if (existsSync4(join2(checkoutDir, ".git"))) {
1561
- git(checkoutDir, ["fetch", "origin"]);
1597
+ git(checkoutDir, ["fetch", "origin"], gitEnv);
1562
1598
  if (refExists(checkoutDir, `refs/remotes/origin/${branch}`)) {
1563
- git(checkoutDir, ["checkout", "-B", branch, `origin/${branch}`]);
1599
+ git(checkoutDir, ["checkout", "-B", branch, `origin/${branch}`], gitEnv);
1564
1600
  } else if (refExists(checkoutDir, `refs/heads/${branch}`)) {
1565
- git(checkoutDir, ["checkout", branch]);
1601
+ git(checkoutDir, ["checkout", branch], gitEnv);
1566
1602
  } else if (fromBranch) {
1567
- git(checkoutDir, ["checkout", "-B", branch, `origin/${fromBranch}`]);
1603
+ git(checkoutDir, ["checkout", "-B", branch, `origin/${fromBranch}`], gitEnv);
1568
1604
  } else {
1569
1605
  fail(
1570
1606
  `worktree create: '${branch}' missing locally and on origin/, no --from-branch to fall back to`
@@ -1573,18 +1609,29 @@ function worktreeCreate(args) {
1573
1609
  } else {
1574
1610
  mkdirSync2(checkoutDir, { recursive: true });
1575
1611
  const cloneArgs = ["-c", `credential.helper=${HELPER_SNIPPET}`, "clone"];
1612
+ if (cacheDir) {
1613
+ cloneArgs.push("--no-checkout", "--reference", cacheDir);
1614
+ }
1576
1615
  if (fromBranch) {
1577
1616
  cloneArgs.push("--branch", fromBranch);
1578
1617
  }
1579
1618
  cloneArgs.push(cleanUrl, ".");
1580
1619
  try {
1581
- git(checkoutDir, cloneArgs);
1620
+ git(checkoutDir, cloneArgs, gitEnv);
1621
+ if (cacheDir && useLfs) {
1622
+ const checkoutLfsDir = join2(checkoutDir, ".git", "lfs");
1623
+ mkdirSync2(checkoutLfsDir, { recursive: true });
1624
+ symlinkSync(
1625
+ join2(cacheDir, ".git", "lfs", "objects"),
1626
+ join2(checkoutLfsDir, "objects")
1627
+ );
1628
+ }
1582
1629
  if (fromBranch && branch === fromBranch) {
1583
- git(checkoutDir, ["checkout", branch]);
1630
+ git(checkoutDir, ["checkout", branch], gitEnv);
1584
1631
  } else {
1585
- git(checkoutDir, ["checkout", "-b", branch]);
1632
+ git(checkoutDir, ["checkout", "-b", branch], gitEnv);
1586
1633
  }
1587
- git(checkoutDir, ["config", "credential.helper", HELPER_SNIPPET]);
1634
+ git(checkoutDir, ["config", "credential.helper", HELPER_SNIPPET], gitEnv);
1588
1635
  } catch (err) {
1589
1636
  try {
1590
1637
  rmSync(checkoutDir, { recursive: true, force: true });
@@ -1668,8 +1715,12 @@ function worktreeRemove(args) {
1668
1715
  rmSync(resolved, { recursive: true, force: true });
1669
1716
  }
1670
1717
  }
1671
- function git(cwd, args) {
1672
- execFileSync("git", args, { cwd, stdio: ["ignore", "ignore", "inherit"] });
1718
+ function git(cwd, args, env) {
1719
+ execFileSync("git", args, {
1720
+ cwd,
1721
+ stdio: ["ignore", "ignore", "inherit"],
1722
+ env: env ?? process.env
1723
+ });
1673
1724
  }
1674
1725
  function refExists(cwd, ref) {
1675
1726
  try {
@@ -1687,6 +1738,9 @@ function pickFlag(argv, name) {
1687
1738
  if (i === -1) return void 0;
1688
1739
  return argv[i + 1];
1689
1740
  }
1741
+ function hasFlag(argv, name) {
1742
+ return argv.indexOf(name) !== -1;
1743
+ }
1690
1744
  function fail(msg) {
1691
1745
  console.error(msg);
1692
1746
  process.exit(1);
@@ -64,6 +64,7 @@ function notify(method, params) {
64
64
  var sessions = /* @__PURE__ */ new Map();
65
65
  async function runClaudeTurn(sessionId, state, promptText) {
66
66
  return new Promise((resolve, reject) => {
67
+ const idFlag = state.resume ? "--resume" : "--session-id";
67
68
  const args = [
68
69
  "-p",
69
70
  "--output-format",
@@ -73,7 +74,7 @@ async function runClaudeTurn(sessionId, state, promptText) {
73
74
  // sense only when stdin can be partial too.
74
75
  "--include-partial-messages",
75
76
  "--verbose",
76
- "--session-id",
77
+ idFlag,
77
78
  sessionId,
78
79
  // Headless: no human in the loop to approve tool use. Matches the
79
80
  // legacy `claudeAdapter` posture in agents/kinds.ts.
@@ -205,14 +206,14 @@ function handleInitialize(_params) {
205
206
  }
206
207
  function handleNewSession(params) {
207
208
  const sessionId = randomUUID();
208
- sessions.set(sessionId, { cwd: params.cwd ?? process.cwd() });
209
+ sessions.set(sessionId, { cwd: params.cwd ?? process.cwd(), resume: false });
209
210
  return { sessionId };
210
211
  }
211
212
  function handleLoadSession(params) {
212
213
  if (typeof params.sessionId !== "string" || params.sessionId.length === 0) {
213
214
  throw new Error("session/load: sessionId required");
214
215
  }
215
- sessions.set(params.sessionId, { cwd: params.cwd ?? process.cwd() });
216
+ sessions.set(params.sessionId, { cwd: params.cwd ?? process.cwd(), resume: true });
216
217
  return {};
217
218
  }
218
219
  async function handlePrompt(params) {
@@ -225,6 +226,7 @@ async function handlePrompt(params) {
225
226
  throw new Error("session/prompt: no text content blocks");
226
227
  }
227
228
  const result = await runClaudeTurn(params.sessionId, state, promptText);
229
+ state.resume = true;
228
230
  return { stopReason: result.stopReason };
229
231
  }
230
232
  var isMainModule = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("claude-acp.ts") === true || process.argv[1]?.endsWith("claude-acp.js") === true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.105.4",
3
+ "version": "0.106.0",
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": {