codeam-cli 2.39.0 → 2.39.2

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 (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.js +178 -356
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.39.1] — 2026-06-12
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Disable in-session auto-provision — it starved/killed sessions ⚠️ BREAKING CHANGE
12
+
13
+ ## [2.39.0] — 2026-06-12
14
+
15
+ ### Added
16
+
17
+ - **cli:** Auto-provision project dependencies in codespaces + preview_failed
18
+
19
+ ### Fixed
20
+
21
+ - **cli:** Emit preview_error (not a new type) with stderr tail on dev-server failure
22
+
7
23
  ## [2.38.0] — 2026-06-12
8
24
 
9
25
  ### Added
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
498
498
  // package.json
499
499
  var package_default = {
500
500
  name: "codeam-cli",
501
- version: "2.39.0",
501
+ version: "2.39.2",
502
502
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
503
503
  type: "commonjs",
504
504
  main: "dist/index.js",
@@ -1186,8 +1186,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1186
1186
  return decodedFile;
1187
1187
  };
1188
1188
  }
1189
- function normalizeWindowsPath(path53) {
1190
- return path53.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1189
+ function normalizeWindowsPath(path52) {
1190
+ return path52.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1191
1191
  }
1192
1192
 
1193
1193
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3667,9 +3667,9 @@ async function addSourceContext(frames) {
3667
3667
  LRU_FILE_CONTENTS_CACHE.reduce();
3668
3668
  return frames;
3669
3669
  }
3670
- function getContextLinesFromFile(path53, ranges, output) {
3670
+ function getContextLinesFromFile(path52, ranges, output) {
3671
3671
  return new Promise((resolve7) => {
3672
- const stream = (0, import_node_fs.createReadStream)(path53);
3672
+ const stream = (0, import_node_fs.createReadStream)(path52);
3673
3673
  const lineReaded = (0, import_node_readline.createInterface)({
3674
3674
  input: stream
3675
3675
  });
@@ -3684,7 +3684,7 @@ function getContextLinesFromFile(path53, ranges, output) {
3684
3684
  let rangeStart = range[0];
3685
3685
  let rangeEnd = range[1];
3686
3686
  function onStreamError() {
3687
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path53, 1);
3687
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path52, 1);
3688
3688
  lineReaded.close();
3689
3689
  lineReaded.removeAllListeners();
3690
3690
  destroyStreamAndResolve();
@@ -3745,8 +3745,8 @@ function clearLineContext(frame) {
3745
3745
  delete frame.context_line;
3746
3746
  delete frame.post_context;
3747
3747
  }
3748
- function shouldSkipContextLinesForFile(path53) {
3749
- return path53.startsWith("node:") || path53.endsWith(".min.js") || path53.endsWith(".min.cjs") || path53.endsWith(".min.mjs") || path53.startsWith("data:");
3748
+ function shouldSkipContextLinesForFile(path52) {
3749
+ return path52.startsWith("node:") || path52.endsWith(".min.js") || path52.endsWith(".min.cjs") || path52.endsWith(".min.mjs") || path52.startsWith("data:");
3750
3750
  }
3751
3751
  function shouldSkipContextLinesForFrame(frame) {
3752
3752
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5900,7 +5900,7 @@ function readAnonId() {
5900
5900
  }
5901
5901
  function superProperties() {
5902
5902
  return {
5903
- cliVersion: true ? "2.39.0" : "0.0.0-dev",
5903
+ cliVersion: true ? "2.39.2" : "0.0.0-dev",
5904
5904
  nodeVersion: process.version,
5905
5905
  platform: process.platform,
5906
5906
  arch: process.arch,
@@ -9978,13 +9978,13 @@ function detectStartupBanner(lines) {
9978
9978
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9979
9979
  if (metaIdx - artStart < 2) return null;
9980
9980
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9981
- const path53 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9981
+ const path52 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9982
9982
  return {
9983
9983
  title: "",
9984
9984
  subtitle: lines[metaIdx].trim(),
9985
- path: path53,
9985
+ path: path52,
9986
9986
  startIdx: artStart,
9987
- endIdx: metaIdx + (path53 ? 1 : 0)
9987
+ endIdx: metaIdx + (path52 ? 1 : 0)
9988
9988
  };
9989
9989
  }
9990
9990
 
@@ -11342,11 +11342,11 @@ function parseReview(stdout) {
11342
11342
  for (const line of lines) {
11343
11343
  const m = line.match(HUNK_LINE_RE);
11344
11344
  if (!m) continue;
11345
- const [, path53, lineNo, sevToken, message] = m;
11346
- if (!path53 || !lineNo || !message) continue;
11345
+ const [, path52, lineNo, sevToken, message] = m;
11346
+ if (!path52 || !lineNo || !message) continue;
11347
11347
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11348
11348
  hunks.push({
11349
- path: path53.trim(),
11349
+ path: path52.trim(),
11350
11350
  line: Number(lineNo),
11351
11351
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11352
11352
  message: cleanedMessage
@@ -15911,9 +15911,9 @@ function extractSelectPrompt(text) {
15911
15911
  }
15912
15912
 
15913
15913
  // src/commands/start/handlers.ts
15914
- var fs35 = __toESM(require("fs"));
15914
+ var fs34 = __toESM(require("fs"));
15915
15915
  var os27 = __toESM(require("os"));
15916
- var path42 = __toESM(require("path"));
15916
+ var path41 = __toESM(require("path"));
15917
15917
  var import_crypto3 = require("crypto");
15918
15918
  var import_child_process18 = require("child_process");
15919
15919
 
@@ -17364,10 +17364,6 @@ async function waitForPortListening(port, opts) {
17364
17364
  }
17365
17365
  }
17366
17366
 
17367
- // src/services/preview/provision-deps.ts
17368
- var import_fs2 = require("fs");
17369
- var import_path6 = __toESM(require("path"));
17370
-
17371
17367
  // src/services/preview/run-setup.ts
17372
17368
  var import_child_process12 = require("child_process");
17373
17369
  function runSetupCommand(cmd, args2, cwd, env, opts) {
@@ -17412,215 +17408,19 @@ function runSetupCommand(cmd, args2, cwd, env, opts) {
17412
17408
  });
17413
17409
  }
17414
17410
 
17415
- // src/services/preview/provision-deps.ts
17416
- var COMPOSE_FILES = [
17417
- "docker-compose.yml",
17418
- "docker-compose.yaml",
17419
- "compose.yaml",
17420
- "compose.yml"
17421
- ];
17422
- var ENV_SAMPLES = [".env.example", ".env.sample", ".env.local.example", ".env.template"];
17423
- var POSTGRES = {
17424
- name: "postgres",
17425
- image: "postgres:16",
17426
- port: 5432,
17427
- environment: { POSTGRES_USER: "postgres", POSTGRES_PASSWORD: "postgres", POSTGRES_DB: "app" },
17428
- healthTest: ["CMD-SHELL", "pg_isready -U postgres"],
17429
- envLines: [
17430
- "DATABASE_URL=postgresql://postgres:postgres@localhost:5432/app",
17431
- "DB_HOST=localhost",
17432
- "DB_PORT=5432",
17433
- "DB_USERNAME=postgres",
17434
- "DB_PASSWORD=postgres",
17435
- "DB_NAME=app"
17436
- ]
17437
- };
17438
- var MYSQL = {
17439
- name: "mysql",
17440
- image: "mysql:8",
17441
- port: 3306,
17442
- environment: { MYSQL_ROOT_PASSWORD: "mysql", MYSQL_DATABASE: "app" },
17443
- healthTest: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-pmysql"],
17444
- envLines: ["DATABASE_URL=mysql://root:mysql@localhost:3306/app"]
17445
- };
17446
- var MONGO = {
17447
- name: "mongo",
17448
- image: "mongo:7",
17449
- port: 27017,
17450
- environment: {},
17451
- healthTest: ["CMD", "mongosh", "--eval", 'db.adminCommand("ping")'],
17452
- envLines: ["MONGODB_URI=mongodb://localhost:27017/app", "MONGO_URL=mongodb://localhost:27017/app"]
17453
- };
17454
- var REDIS = {
17455
- name: "redis",
17456
- image: "redis:7",
17457
- port: 6379,
17458
- environment: {},
17459
- healthTest: ["CMD", "redis-cli", "ping"],
17460
- envLines: ["REDIS_URL=redis://localhost:6379", "REDIS_HOST=localhost", "REDIS_PORT=6379"]
17461
- };
17462
- function detectServicesFromDeps(pkg) {
17463
- const deps = /* @__PURE__ */ new Set([
17464
- ...Object.keys(pkg.dependencies ?? {}),
17465
- ...Object.keys(pkg.devDependencies ?? {})
17466
- ]);
17467
- const has = (...names) => names.some((n) => deps.has(n));
17468
- const out2 = [];
17469
- if (has("pg", "typeorm", "@nestjs/typeorm", "sequelize", "postgres", "postgres.js", "pg-promise"))
17470
- out2.push(POSTGRES);
17471
- if (has("mysql", "mysql2")) out2.push(MYSQL);
17472
- if (has("mongoose", "mongodb")) out2.push(MONGO);
17473
- if (has("ioredis", "redis", "cache-manager-ioredis-yet", "cache-manager-redis-store"))
17474
- out2.push(REDIS);
17475
- return out2;
17476
- }
17477
- function renderComposeYaml(services) {
17478
- const blocks = services.map((s) => {
17479
- const env = Object.entries(s.environment);
17480
- const envYaml = env.length ? " environment:\n" + env.map(([k2, v]) => ` ${k2}: "${v}"`).join("\n") + "\n" : "";
17481
- const health = JSON.stringify(s.healthTest);
17482
- return ` ${s.name}:
17483
- image: ${s.image}
17484
- restart: unless-stopped
17485
- ports:
17486
- - "${s.port}:${s.port}"
17487
- ` + envYaml + ` healthcheck:
17488
- test: ${health}
17489
- interval: 5s
17490
- timeout: 3s
17491
- retries: 12
17492
- `;
17493
- });
17494
- return `# Generated by codeam \u2014 auto-provisioned project dependencies.
17495
- # Do not edit; regenerated on each provision. See .codeam/provision/.
17496
- services:
17497
- ${blocks.join("")}`;
17498
- }
17499
- function pickMigrationScript(scripts) {
17500
- const preferred = [
17501
- "migration:run",
17502
- "db:migrate",
17503
- "migrate:deploy",
17504
- "migrate:latest",
17505
- "migrate:up",
17506
- "prisma:migrate",
17507
- "migrate"
17508
- ];
17509
- for (const k2 of preferred) if (scripts[k2]) return k2;
17510
- for (const k2 of Object.keys(scripts)) {
17511
- if (/migrat/i.test(k2) && /(run|deploy|latest|up)/i.test(k2) && !/(generate|create|revert|rollback|undo|down|reset|drop)/i.test(k2)) {
17512
- return k2;
17513
- }
17514
- }
17515
- return null;
17516
- }
17517
- async function exists(p2) {
17518
- try {
17519
- await import_fs2.promises.access(p2);
17520
- return true;
17521
- } catch {
17522
- return false;
17523
- }
17524
- }
17525
- async function firstExisting(cwd, names) {
17526
- for (const n of names) if (await exists(import_path6.default.join(cwd, n))) return n;
17527
- return null;
17528
- }
17529
- async function ensureEnvFile(cwd, generated) {
17530
- if (await exists(import_path6.default.join(cwd, ".env"))) {
17531
- log.info("provision", ".env already present \u2014 leaving it untouched");
17532
- return;
17533
- }
17534
- const sample = await firstExisting(cwd, ENV_SAMPLES);
17535
- if (sample) {
17536
- const body = await import_fs2.promises.readFile(import_path6.default.join(cwd, sample), "utf8");
17537
- await import_fs2.promises.writeFile(import_path6.default.join(cwd, ".env"), body);
17538
- log.info("provision", `wrote .env from ${sample}`);
17539
- return;
17540
- }
17541
- if (generated.length > 0) {
17542
- const body = "# Generated by codeam \u2014 points at the auto-provisioned local services.\n" + generated.flatMap((s) => s.envLines).join("\n") + "\n";
17543
- await import_fs2.promises.writeFile(import_path6.default.join(cwd, ".env"), body);
17544
- log.info("provision", `generated .env for ${generated.map((s) => s.name).join("+")}`);
17545
- }
17546
- }
17547
- async function readPackageJson(cwd) {
17548
- try {
17549
- return JSON.parse(await import_fs2.promises.readFile(import_path6.default.join(cwd, "package.json"), "utf8"));
17550
- } catch {
17551
- return null;
17552
- }
17553
- }
17554
- async function runMigrationsIfPresent(cwd, scripts) {
17555
- const script = pickMigrationScript(scripts);
17556
- if (!script) return;
17557
- log.info("provision", `running migrations: npm run ${script}`);
17558
- const res = await runSetupCommand("npm", ["run", script], cwd, void 0, { timeoutMs: 12e4 });
17559
- if (res.status !== "ok") log.warn("provision", `migration script "${script}" \u2192 ${res.status} (non-fatal)`);
17560
- }
17561
- async function provisionProjectDependencies(cwd) {
17562
- try {
17563
- const docker = await runSetupCommand("docker", ["info"], cwd, void 0, { timeoutMs: 15e3 });
17564
- if (docker.status !== "ok") {
17565
- log.info("provision", "docker not usable \u2014 skipping dependency provisioning");
17566
- return;
17567
- }
17568
- const pkg = await readPackageJson(cwd);
17569
- let started = false;
17570
- let generated = [];
17571
- const composeFile = await firstExisting(cwd, COMPOSE_FILES);
17572
- if (composeFile) {
17573
- log.info("provision", `compose found (${composeFile}) \u2014 docker compose up -d --wait`);
17574
- const up = await runSetupCommand("docker", ["compose", "up", "-d", "--wait"], cwd, void 0, {
17575
- timeoutMs: 18e4
17576
- });
17577
- started = up.status === "ok";
17578
- if (!started) log.warn("provision", `compose up \u2192 ${up.status} (non-fatal)`);
17579
- } else if (pkg) {
17580
- generated = detectServicesFromDeps(pkg);
17581
- if (generated.length > 0) {
17582
- const dir = import_path6.default.join(cwd, ".codeam", "provision");
17583
- await import_fs2.promises.mkdir(dir, { recursive: true });
17584
- const file = import_path6.default.join(dir, "compose.generated.yaml");
17585
- await import_fs2.promises.writeFile(file, renderComposeYaml(generated));
17586
- log.info(
17587
- "provision",
17588
- `no compose in repo \u2014 generated ${generated.map((s) => s.name).join("+")}`
17589
- );
17590
- const up = await runSetupCommand(
17591
- "docker",
17592
- ["compose", "-f", file, "up", "-d", "--wait"],
17593
- cwd,
17594
- void 0,
17595
- { timeoutMs: 18e4 }
17596
- );
17597
- started = up.status === "ok";
17598
- if (!started) log.warn("provision", `generated compose up \u2192 ${up.status} (non-fatal)`);
17599
- } else {
17600
- log.info("provision", "no compose + no known service deps \u2014 nothing to provision");
17601
- }
17602
- }
17603
- await ensureEnvFile(cwd, generated);
17604
- if (started && pkg?.scripts) await runMigrationsIfPresent(cwd, pkg.scripts);
17605
- log.info("provision", "project dependency provisioning complete");
17606
- } catch (err) {
17607
- log.warn("provision", "provisionProjectDependencies failed (non-fatal)", err);
17608
- }
17609
- }
17610
-
17611
17411
  // src/services/preview/setup-deps.ts
17612
- var import_fs3 = __toESM(require("fs"));
17613
- var import_path7 = __toESM(require("path"));
17412
+ var import_fs2 = __toESM(require("fs"));
17413
+ var import_path6 = __toESM(require("path"));
17614
17414
  function detectMissingNodeDeps(cwd) {
17615
- if (!import_fs3.default.existsSync(import_path7.default.join(cwd, "package.json"))) return null;
17616
- if (import_fs3.default.existsSync(import_path7.default.join(cwd, "node_modules"))) return null;
17617
- if (import_fs3.default.existsSync(import_path7.default.join(cwd, "pnpm-lock.yaml"))) {
17415
+ if (!import_fs2.default.existsSync(import_path6.default.join(cwd, "package.json"))) return null;
17416
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "node_modules"))) return null;
17417
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "pnpm-lock.yaml"))) {
17618
17418
  return { cmd: "pnpm", args: ["install"] };
17619
17419
  }
17620
- if (import_fs3.default.existsSync(import_path7.default.join(cwd, "yarn.lock"))) {
17420
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "yarn.lock"))) {
17621
17421
  return { cmd: "yarn", args: ["install"] };
17622
17422
  }
17623
- if (import_fs3.default.existsSync(import_path7.default.join(cwd, "bun.lockb")) || import_fs3.default.existsSync(import_path7.default.join(cwd, "bun.lock"))) {
17423
+ if (import_fs2.default.existsSync(import_path6.default.join(cwd, "bun.lockb")) || import_fs2.default.existsSync(import_path6.default.join(cwd, "bun.lock"))) {
17624
17424
  return { cmd: "bun", args: ["install"] };
17625
17425
  }
17626
17426
  return { cmd: "npm", args: ["install"] };
@@ -17675,8 +17475,8 @@ function activePreviewSessionIds() {
17675
17475
 
17676
17476
  // src/beads/bd-adapter.ts
17677
17477
  var import_child_process13 = require("child_process");
17678
- var fs31 = __toESM(require("fs"));
17679
- var path37 = __toESM(require("path"));
17478
+ var fs30 = __toESM(require("fs"));
17479
+ var path36 = __toESM(require("path"));
17680
17480
  var BD_PACKAGE = "@beads/bd";
17681
17481
  function resolveBundledBdBinary() {
17682
17482
  return _resolveSeam.resolveBundled();
@@ -17688,11 +17488,11 @@ function _defaultResolveBundled() {
17688
17488
  } catch {
17689
17489
  return null;
17690
17490
  }
17691
- const binDir = path37.join(path37.dirname(pkgJsonPath), "bin");
17491
+ const binDir = path36.join(path36.dirname(pkgJsonPath), "bin");
17692
17492
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
17693
- const binaryPath = path37.join(binDir, binaryName);
17493
+ const binaryPath = path36.join(binDir, binaryName);
17694
17494
  try {
17695
- fs31.accessSync(binaryPath, fs31.constants.F_OK);
17495
+ fs30.accessSync(binaryPath, fs30.constants.F_OK);
17696
17496
  return binaryPath;
17697
17497
  } catch {
17698
17498
  return null;
@@ -17702,13 +17502,13 @@ function resolveBdOnPath() {
17702
17502
  return _resolveSeam.resolveOnPath();
17703
17503
  }
17704
17504
  function _defaultResolveOnPath() {
17705
- const dirs = (process.env.PATH ?? "").split(path37.delimiter).filter(Boolean);
17505
+ const dirs = (process.env.PATH ?? "").split(path36.delimiter).filter(Boolean);
17706
17506
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
17707
17507
  for (const dir of dirs) {
17708
17508
  for (const candidate of candidates) {
17709
- const full = path37.join(dir, candidate);
17509
+ const full = path36.join(dir, candidate);
17710
17510
  try {
17711
- fs31.accessSync(full, fs31.constants.F_OK);
17511
+ fs30.accessSync(full, fs30.constants.F_OK);
17712
17512
  return full;
17713
17513
  } catch {
17714
17514
  }
@@ -17874,9 +17674,9 @@ function coerceIssue(row, projectKey) {
17874
17674
 
17875
17675
  // src/beads/provisioner.ts
17876
17676
  var import_child_process17 = require("child_process");
17877
- var fs34 = __toESM(require("fs"));
17677
+ var fs33 = __toESM(require("fs"));
17878
17678
  var os26 = __toESM(require("os"));
17879
- var path40 = __toESM(require("path"));
17679
+ var path39 = __toESM(require("path"));
17880
17680
 
17881
17681
  // src/beads/install-bd.ts
17882
17682
  var import_child_process14 = require("child_process");
@@ -17941,9 +17741,9 @@ async function installBd(platform2 = process.platform) {
17941
17741
 
17942
17742
  // src/beads/install-dolt.ts
17943
17743
  var import_child_process15 = require("child_process");
17944
- var fs32 = __toESM(require("fs"));
17744
+ var fs31 = __toESM(require("fs"));
17945
17745
  var os25 = __toESM(require("os"));
17946
- var path38 = __toESM(require("path"));
17746
+ var path37 = __toESM(require("path"));
17947
17747
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
17948
17748
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
17949
17749
  function resolveDoltInstallStrategy(platform2) {
@@ -18039,7 +17839,7 @@ var _doltPathSeam = {
18039
17839
  },
18040
17840
  exists: (p2) => {
18041
17841
  try {
18042
- fs32.accessSync(p2, fs32.constants.F_OK);
17842
+ fs31.accessSync(p2, fs31.constants.F_OK);
18043
17843
  return true;
18044
17844
  } catch {
18045
17845
  return false;
@@ -18050,7 +17850,7 @@ function doltBinaryNames(platform2) {
18050
17850
  return platform2 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
18051
17851
  }
18052
17852
  function knownDoltDirs(platform2) {
18053
- const P3 = platform2 === "win32" ? path38.win32 : path38.posix;
17853
+ const P3 = platform2 === "win32" ? path37.win32 : path37.posix;
18054
17854
  const home = _doltPathSeam.homedir();
18055
17855
  if (platform2 === "win32") {
18056
17856
  return [
@@ -18066,7 +17866,7 @@ function knownDoltDirs(platform2) {
18066
17866
  ].filter(Boolean);
18067
17867
  }
18068
17868
  function ensureDoltResolvable(platform2 = process.platform) {
18069
- const P3 = platform2 === "win32" ? path38.win32 : path38.posix;
17869
+ const P3 = platform2 === "win32" ? path37.win32 : path37.posix;
18070
17870
  const delim = platform2 === "win32" ? ";" : ":";
18071
17871
  const names = doltBinaryNames(platform2);
18072
17872
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -18177,8 +17977,8 @@ async function ensureSharedServer(adapter) {
18177
17977
  // src/beads/project-key.ts
18178
17978
  var import_child_process16 = require("child_process");
18179
17979
  var crypto2 = __toESM(require("crypto"));
18180
- var fs33 = __toESM(require("fs"));
18181
- var path39 = __toESM(require("path"));
17980
+ var fs32 = __toESM(require("fs"));
17981
+ var path38 = __toESM(require("path"));
18182
17982
  function normalizeOrigin(raw) {
18183
17983
  const trimmed = raw.trim();
18184
17984
  if (!trimmed) return null;
@@ -18204,17 +18004,17 @@ function normalizeOrigin(raw) {
18204
18004
  return `${host}/${pathPart}`;
18205
18005
  }
18206
18006
  function findRepoRoot(cwd) {
18207
- let dir = path39.resolve(cwd);
18007
+ let dir = path38.resolve(cwd);
18208
18008
  const seen = /* @__PURE__ */ new Set();
18209
18009
  for (let i = 0; i < 256; i++) {
18210
18010
  if (seen.has(dir)) return null;
18211
18011
  seen.add(dir);
18212
18012
  try {
18213
- const stat3 = fs33.statSync(path39.join(dir, ".git"), { throwIfNoEntry: false });
18013
+ const stat3 = fs32.statSync(path38.join(dir, ".git"), { throwIfNoEntry: false });
18214
18014
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
18215
18015
  } catch {
18216
18016
  }
18217
- const parent = path39.dirname(dir);
18017
+ const parent = path38.dirname(dir);
18218
18018
  if (parent === dir) return null;
18219
18019
  dir = parent;
18220
18020
  }
@@ -18225,7 +18025,7 @@ var _execSeam2 = {
18225
18025
  const out2 = (0, import_child_process16.execFileSync)(file, args2, opts);
18226
18026
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
18227
18027
  },
18228
- realpath: (p2) => fs33.realpathSync(p2)
18028
+ realpath: (p2) => fs32.realpathSync(p2)
18229
18029
  };
18230
18030
  function readOrigin(cwd) {
18231
18031
  try {
@@ -18254,7 +18054,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
18254
18054
  } catch {
18255
18055
  }
18256
18056
  const hash = crypto2.createHash("sha256").update(real).digest("hex");
18257
- return { projectKey: `path:${hash}`, projectLabel: path39.basename(real) || "project" };
18057
+ return { projectKey: `path:${hash}`, projectLabel: path38.basename(real) || "project" };
18258
18058
  }
18259
18059
 
18260
18060
  // src/beads/project-prefix.ts
@@ -18299,14 +18099,14 @@ var _linkSeam = {
18299
18099
  homedir: () => os26.homedir(),
18300
18100
  isWritableDir: (dir) => {
18301
18101
  try {
18302
- fs34.accessSync(dir, fs34.constants.W_OK);
18102
+ fs33.accessSync(dir, fs33.constants.W_OK);
18303
18103
  return true;
18304
18104
  } catch {
18305
18105
  return false;
18306
18106
  }
18307
18107
  },
18308
18108
  ensureDir: (dir) => {
18309
- fs34.mkdirSync(dir, { recursive: true });
18109
+ fs33.mkdirSync(dir, { recursive: true });
18310
18110
  },
18311
18111
  /**
18312
18112
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -18327,12 +18127,12 @@ var _linkSeam = {
18327
18127
  * which `linkBdOntoPath` creates if missing.
18328
18128
  */
18329
18129
  cliBinDir: () => {
18330
- const pathDirs = (process.env.PATH ?? "").split(path40.delimiter).filter(Boolean);
18130
+ const pathDirs = (process.env.PATH ?? "").split(path39.delimiter).filter(Boolean);
18331
18131
  const home = _linkSeam.homedir();
18332
- const localBin = home ? path40.join(home, ".local", "bin") : null;
18132
+ const localBin = home ? path39.join(home, ".local", "bin") : null;
18333
18133
  const candidates = [];
18334
18134
  try {
18335
- candidates.push(path40.dirname(process.execPath));
18135
+ candidates.push(path39.dirname(process.execPath));
18336
18136
  } catch {
18337
18137
  }
18338
18138
  if (localBin) candidates.push(localBin);
@@ -18340,9 +18140,9 @@ var _linkSeam = {
18340
18140
  const entry = process.argv[1];
18341
18141
  if (entry) {
18342
18142
  try {
18343
- candidates.push(path40.dirname(fs34.realpathSync(entry)));
18143
+ candidates.push(path39.dirname(fs33.realpathSync(entry)));
18344
18144
  } catch {
18345
- candidates.push(path40.dirname(entry));
18145
+ candidates.push(path39.dirname(entry));
18346
18146
  }
18347
18147
  }
18348
18148
  const onPathWritable = candidates.find(
@@ -18354,20 +18154,20 @@ var _linkSeam = {
18354
18154
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
18355
18155
  readlink: (linkPath) => {
18356
18156
  try {
18357
- return fs34.readlinkSync(linkPath);
18157
+ return fs33.readlinkSync(linkPath);
18358
18158
  } catch {
18359
18159
  return null;
18360
18160
  }
18361
18161
  },
18362
- unlink: (linkPath) => fs34.unlinkSync(linkPath),
18363
- symlink: (target, linkPath) => fs34.symlinkSync(target, linkPath)
18162
+ unlink: (linkPath) => fs33.unlinkSync(linkPath),
18163
+ symlink: (target, linkPath) => fs33.symlinkSync(target, linkPath)
18364
18164
  };
18365
18165
  function linkBdOntoPath(binaryPath) {
18366
18166
  if (_linkSeam.platform() === "win32") return;
18367
18167
  const binDir = _linkSeam.cliBinDir();
18368
18168
  if (!binDir) return;
18369
18169
  _linkSeam.ensureDir(binDir);
18370
- const linkPath = path40.join(binDir, "bd");
18170
+ const linkPath = path39.join(binDir, "bd");
18371
18171
  if (linkPath === binaryPath) return;
18372
18172
  const current = _linkSeam.readlink(linkPath);
18373
18173
  if (current === binaryPath) return;
@@ -18508,7 +18308,7 @@ function dedupeRecipes(agents) {
18508
18308
 
18509
18309
  // src/beads/watcher.ts
18510
18310
  var crypto4 = __toESM(require("crypto"));
18511
- var path41 = __toESM(require("path"));
18311
+ var path40 = __toESM(require("path"));
18512
18312
 
18513
18313
  // src/services/file-watcher/transport.ts
18514
18314
  var http5 = __toESM(require("http"));
@@ -18583,7 +18383,7 @@ var BeadsWatcher = class {
18583
18383
  constructor(opts) {
18584
18384
  this.opts = opts;
18585
18385
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
18586
- this.feedPath = opts.feedPath ?? path41.join(opts.cwd ?? process.cwd(), ".beads", "issues.jsonl");
18386
+ this.feedPath = opts.feedPath ?? path40.join(opts.cwd ?? process.cwd(), ".beads", "issues.jsonl");
18587
18387
  this.apiBase = opts.apiBaseUrl ?? API_BASE4;
18588
18388
  }
18589
18389
  opts;
@@ -18906,7 +18706,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
18906
18706
  function cleanupAttachmentTempFiles() {
18907
18707
  for (const p2 of pendingAttachmentFiles) {
18908
18708
  try {
18909
- fs35.unlinkSync(p2);
18709
+ fs34.unlinkSync(p2);
18910
18710
  } catch {
18911
18711
  }
18912
18712
  }
@@ -18915,8 +18715,8 @@ function cleanupAttachmentTempFiles() {
18915
18715
  function saveFilesTemp(files) {
18916
18716
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
18917
18717
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
18918
- const tmpPath = path42.join(os27.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18919
- fs35.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18718
+ const tmpPath = path41.join(os27.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18719
+ fs34.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18920
18720
  pendingAttachmentFiles.add(tmpPath);
18921
18721
  return tmpPath;
18922
18722
  });
@@ -18936,7 +18736,7 @@ var startTask = (ctx, _cmd, parsed) => {
18936
18736
  setTimeout(() => {
18937
18737
  for (const p2 of paths) {
18938
18738
  try {
18939
- fs35.unlinkSync(p2);
18739
+ fs34.unlinkSync(p2);
18940
18740
  } catch {
18941
18741
  }
18942
18742
  pendingAttachmentFiles.delete(p2);
@@ -19472,6 +19272,28 @@ var requestPreviewDetectH = (ctx) => {
19472
19272
  });
19473
19273
  })();
19474
19274
  };
19275
+ var previewPrewarmStarted = false;
19276
+ function prewarmPreviewDetection(runtime) {
19277
+ if (previewPrewarmStarted) return;
19278
+ previewPrewarmStarted = true;
19279
+ if (typeof runtime.generateOneShot !== "function") return;
19280
+ void (async () => {
19281
+ try {
19282
+ const cwd = process.cwd();
19283
+ if (await readPreviewConfig(cwd)) return;
19284
+ const raw = await runtime.generateOneShot(PREVIEW_DETECT_PROMPT).catch(() => null);
19285
+ const detection = safeParseDetection(raw);
19286
+ if (!detection || detection.framework === "unsupported") return;
19287
+ await writePreviewConfig(cwd, detection);
19288
+ log.info(
19289
+ "preview",
19290
+ `prewarm: cached detection (${detection.framework} on :${detection.port})`
19291
+ );
19292
+ } catch (err) {
19293
+ log.info("preview", `prewarm: skipped (${String(err)})`);
19294
+ }
19295
+ })();
19296
+ }
19475
19297
  function compileReadyPattern(pattern) {
19476
19298
  return new RegExp(pattern, "i");
19477
19299
  }
@@ -19519,8 +19341,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
19519
19341
  if (args2.length === 0) return detection;
19520
19342
  const binName = args2[0];
19521
19343
  if (binName.startsWith("-")) return detection;
19522
- const binPath = path42.join(cwd, "node_modules", ".bin", binName);
19523
- if (!fs35.existsSync(binPath)) return detection;
19344
+ const binPath = path41.join(cwd, "node_modules", ".bin", binName);
19345
+ if (!fs34.existsSync(binPath)) return detection;
19524
19346
  return {
19525
19347
  ...detection,
19526
19348
  command: binPath,
@@ -19957,9 +19779,9 @@ async function dispatchCommand(ctx, cmd) {
19957
19779
 
19958
19780
  // src/services/file-watcher.service.ts
19959
19781
  var import_child_process19 = require("child_process");
19960
- var fs36 = __toESM(require("fs"));
19782
+ var fs35 = __toESM(require("fs"));
19961
19783
  var os28 = __toESM(require("os"));
19962
- var path43 = __toESM(require("path"));
19784
+ var path42 = __toESM(require("path"));
19963
19785
  var import_ignore = __toESM(require("ignore"));
19964
19786
 
19965
19787
  // src/services/file-watcher/diff-parser.ts
@@ -20102,18 +19924,18 @@ var _findGitRootSeam = {
20102
19924
  resolve: _defaultFindGitRoot
20103
19925
  };
20104
19926
  function _defaultFindGitRoot(startDir) {
20105
- let dir = path43.resolve(startDir);
19927
+ let dir = path42.resolve(startDir);
20106
19928
  const seen = /* @__PURE__ */ new Set();
20107
19929
  for (let i = 0; i < 256; i++) {
20108
19930
  if (seen.has(dir)) return null;
20109
19931
  seen.add(dir);
20110
19932
  try {
20111
- const gitPath = path43.join(dir, ".git");
20112
- const stat3 = fs36.statSync(gitPath, { throwIfNoEntry: false });
19933
+ const gitPath = path42.join(dir, ".git");
19934
+ const stat3 = fs35.statSync(gitPath, { throwIfNoEntry: false });
20113
19935
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
20114
19936
  } catch {
20115
19937
  }
20116
- const parent = path43.dirname(dir);
19938
+ const parent = path42.dirname(dir);
20117
19939
  if (parent === dir) return null;
20118
19940
  dir = parent;
20119
19941
  }
@@ -20358,7 +20180,7 @@ var FileWatcherService = class {
20358
20180
  }
20359
20181
  async emitForFile(absPath, changeType) {
20360
20182
  if (this.stopped) return;
20361
- const fileDir = path43.dirname(absPath);
20183
+ const fileDir = path42.dirname(absPath);
20362
20184
  let gitRoot = this.gitRootByDir.get(fileDir);
20363
20185
  if (gitRoot === void 0) {
20364
20186
  gitRoot = findGitRoot2(fileDir);
@@ -20371,19 +20193,19 @@ var FileWatcherService = class {
20371
20193
  );
20372
20194
  return;
20373
20195
  }
20374
- const relPathInRepo = path43.relative(gitRoot, absPath);
20196
+ const relPathInRepo = path42.relative(gitRoot, absPath);
20375
20197
  if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
20376
20198
  const matcher = this.getGitIgnoreMatcher(gitRoot);
20377
20199
  if (matcher && matcher.ignores(relPathInRepo)) {
20378
20200
  log.trace(
20379
20201
  "fileWatcher",
20380
- `${relPathInRepo} ignored by ${path43.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
20202
+ `${relPathInRepo} ignored by ${path42.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
20381
20203
  );
20382
20204
  return;
20383
20205
  }
20384
20206
  this.opts.onRepoDirty?.(gitRoot);
20385
- const repoPath = path43.relative(this.opts.workingDir, gitRoot);
20386
- const repoName = path43.basename(gitRoot);
20207
+ const repoPath = path42.relative(this.opts.workingDir, gitRoot);
20208
+ const repoName = path42.basename(gitRoot);
20387
20209
  let diffText = "";
20388
20210
  let fileStatus = "modified";
20389
20211
  if (changeType === "unlink") {
@@ -20558,7 +20380,7 @@ var FileWatcherService = class {
20558
20380
  collectGitignoreFiles(repoRoot, dir, matcher) {
20559
20381
  let entries;
20560
20382
  try {
20561
- entries = fs36.readdirSync(dir, { withFileTypes: true });
20383
+ entries = fs35.readdirSync(dir, { withFileTypes: true });
20562
20384
  } catch {
20563
20385
  return;
20564
20386
  }
@@ -20567,16 +20389,16 @@ var FileWatcherService = class {
20567
20389
  );
20568
20390
  if (gitignoreEntry) {
20569
20391
  try {
20570
- const body = fs36.readFileSync(path43.join(dir, ".gitignore"), "utf8");
20571
- const rel = path43.relative(repoRoot, dir).replace(/\\/g, "/");
20392
+ const body = fs35.readFileSync(path42.join(dir, ".gitignore"), "utf8");
20393
+ const rel = path42.relative(repoRoot, dir).replace(/\\/g, "/");
20572
20394
  const prefixed = body.split(/\r?\n/).map((line) => {
20573
20395
  const trimmed = line.trim();
20574
20396
  if (!trimmed || trimmed.startsWith("#")) return line;
20575
20397
  if (!rel) return line;
20576
20398
  if (trimmed.startsWith("!")) {
20577
- return "!" + path43.posix.join(rel, trimmed.slice(1));
20399
+ return "!" + path42.posix.join(rel, trimmed.slice(1));
20578
20400
  }
20579
- return path43.posix.join(rel, trimmed);
20401
+ return path42.posix.join(rel, trimmed);
20580
20402
  }).join("\n");
20581
20403
  matcher.add(prefixed);
20582
20404
  } catch {
@@ -20585,7 +20407,7 @@ var FileWatcherService = class {
20585
20407
  for (const entry of entries) {
20586
20408
  if (!entry.isDirectory()) continue;
20587
20409
  if (entry.name === ".git") continue;
20588
- const childAbs = path43.join(dir, entry.name);
20410
+ const childAbs = path42.join(dir, entry.name);
20589
20411
  if (isIgnoredFilePath(childAbs)) continue;
20590
20412
  this.collectGitignoreFiles(repoRoot, childAbs, matcher);
20591
20413
  }
@@ -20755,7 +20577,7 @@ var import_crypto4 = require("crypto");
20755
20577
 
20756
20578
  // src/services/turn-files/git-changeset.ts
20757
20579
  var import_child_process20 = require("child_process");
20758
- var path44 = __toESM(require("path"));
20580
+ var path43 = __toESM(require("path"));
20759
20581
  async function collectRepoChangeset(opts) {
20760
20582
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
20761
20583
  if (status2 === null) return null;
@@ -20866,7 +20688,7 @@ function defaultRunGit(cwd, args2) {
20866
20688
  });
20867
20689
  }
20868
20690
  async function discoverRepos(workingDir, maxDepth = 4) {
20869
- const fs42 = await import("fs/promises");
20691
+ const fs41 = await import("fs/promises");
20870
20692
  const out2 = [];
20871
20693
  await walk(workingDir, 0);
20872
20694
  return out2;
@@ -20874,7 +20696,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20874
20696
  if (depth > maxDepth) return;
20875
20697
  let entries = [];
20876
20698
  try {
20877
- const dirents = await fs42.readdir(dir, { withFileTypes: true });
20699
+ const dirents = await fs41.readdir(dir, { withFileTypes: true });
20878
20700
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
20879
20701
  } catch {
20880
20702
  return;
@@ -20885,8 +20707,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20885
20707
  if (hasGit) {
20886
20708
  out2.push({
20887
20709
  repoRoot: dir,
20888
- repoPath: path44.relative(workingDir, dir),
20889
- repoName: path44.basename(dir)
20710
+ repoPath: path43.relative(workingDir, dir),
20711
+ repoName: path43.basename(dir)
20890
20712
  });
20891
20713
  return;
20892
20714
  }
@@ -20894,14 +20716,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20894
20716
  if (!entry.isDirectory) continue;
20895
20717
  if (entry.name === "node_modules") continue;
20896
20718
  if (entry.name === "dist" || entry.name === "build") continue;
20897
- await walk(path44.join(dir, entry.name), depth + 1);
20719
+ await walk(path43.join(dir, entry.name), depth + 1);
20898
20720
  }
20899
20721
  }
20900
20722
  }
20901
20723
 
20902
20724
  // src/services/turn-files/files-outbox.ts
20903
- var fs37 = __toESM(require("fs/promises"));
20904
- var path45 = __toESM(require("path"));
20725
+ var fs36 = __toESM(require("fs/promises"));
20726
+ var path44 = __toESM(require("path"));
20905
20727
  var import_os7 = require("os");
20906
20728
  var HOME_OUTBOX_DIR = ".codeam/outbox";
20907
20729
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -20934,16 +20756,16 @@ var FilesOutbox = class {
20934
20756
  backoffIndex = 0;
20935
20757
  stopped = false;
20936
20758
  constructor(opts) {
20937
- const base = opts.baseDir ?? path45.join(homeDir(), HOME_OUTBOX_DIR);
20938
- this.filePath = path45.join(base, `${opts.sessionId}.jsonl`);
20759
+ const base = opts.baseDir ?? path44.join(homeDir(), HOME_OUTBOX_DIR);
20760
+ this.filePath = path44.join(base, `${opts.sessionId}.jsonl`);
20939
20761
  this.post = opts.post;
20940
20762
  this.autoSchedule = opts.autoSchedule !== false;
20941
20763
  }
20942
20764
  /** Persist the entry to disk and trigger a flush. Returns once the
20943
20765
  * line is durable on disk (not once the POST succeeds). */
20944
20766
  async enqueue(entry) {
20945
- await fs37.mkdir(path45.dirname(this.filePath), { recursive: true });
20946
- await fs37.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
20767
+ await fs36.mkdir(path44.dirname(this.filePath), { recursive: true });
20768
+ await fs36.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
20947
20769
  this.backoffIndex = 0;
20948
20770
  if (this.autoSchedule) this.scheduleFlush(0);
20949
20771
  }
@@ -21032,7 +20854,7 @@ var FilesOutbox = class {
21032
20854
  async readAll() {
21033
20855
  let raw = "";
21034
20856
  try {
21035
- raw = await fs37.readFile(this.filePath, "utf8");
20857
+ raw = await fs36.readFile(this.filePath, "utf8");
21036
20858
  } catch {
21037
20859
  return [];
21038
20860
  }
@@ -21056,12 +20878,12 @@ var FilesOutbox = class {
21056
20878
  async rewrite(entries) {
21057
20879
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
21058
20880
  if (entries.length === 0) {
21059
- await fs37.unlink(this.filePath).catch(() => void 0);
20881
+ await fs36.unlink(this.filePath).catch(() => void 0);
21060
20882
  return;
21061
20883
  }
21062
20884
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
21063
- await fs37.writeFile(tmpPath, payload, "utf8");
21064
- await fs37.rename(tmpPath, this.filePath);
20885
+ await fs36.writeFile(tmpPath, payload, "utf8");
20886
+ await fs36.rename(tmpPath, this.filePath);
21065
20887
  }
21066
20888
  };
21067
20889
  function applyJitter(ms) {
@@ -21741,8 +21563,10 @@ async function runAcpSession(opts) {
21741
21563
  { id: opts.agent, name: opts.agent, displayName: opts.agent }
21742
21564
  );
21743
21565
  relay.start();
21566
+ const prewarmTimer = setTimeout(() => prewarmPreviewDetection(runtime), 2e4);
21744
21567
  const shutdown = async (signal) => {
21745
21568
  showInfo(`Shutting down ACP session (${signal})\u2026`);
21569
+ clearTimeout(prewarmTimer);
21746
21570
  relay.stop();
21747
21571
  void fileWatcher.stop();
21748
21572
  turnFiles.stop();
@@ -22158,10 +21982,10 @@ var ChromeStepTracker = class {
22158
21982
  const visible = lines.map((l) => parseLine2(l)).filter((s) => s !== null);
22159
21983
  if (visible.length === 0) return;
22160
21984
  for (const step of visible) {
22161
- const exists2 = this.history.some(
21985
+ const exists = this.history.some(
22162
21986
  (s) => s.tool === step.tool && s.label === step.label
22163
21987
  );
22164
- if (!exists2) this.history.push(step);
21988
+ if (!exists) this.history.push(step);
22165
21989
  }
22166
21990
  }
22167
21991
  /**
@@ -22906,8 +22730,8 @@ var OutputService = class _OutputService {
22906
22730
  };
22907
22731
 
22908
22732
  // src/services/history.service.ts
22909
- var fs38 = __toESM(require("fs"));
22910
- var path46 = __toESM(require("path"));
22733
+ var fs37 = __toESM(require("fs"));
22734
+ var path45 = __toESM(require("path"));
22911
22735
  var os29 = __toESM(require("os"));
22912
22736
  var https7 = __toESM(require("https"));
22913
22737
  var http7 = __toESM(require("http"));
@@ -22935,7 +22759,7 @@ function parseJsonl(filePath) {
22935
22759
  const messages = [];
22936
22760
  let raw;
22937
22761
  try {
22938
- raw = fs38.readFileSync(filePath, "utf8");
22762
+ raw = fs37.readFileSync(filePath, "utf8");
22939
22763
  } catch (err) {
22940
22764
  if (err.code !== "ENOENT") {
22941
22765
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -23070,7 +22894,7 @@ var HistoryService = class _HistoryService {
23070
22894
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
23071
22895
  }
23072
22896
  get projectDir() {
23073
- return this.runtime.resolveHistoryDir(this.cwd) ?? path46.join(os29.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22897
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path45.join(os29.homedir(), ".claude", "projects", encodeCwd(this.cwd));
23074
22898
  }
23075
22899
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
23076
22900
  setCurrentConversationId(id) {
@@ -23082,7 +22906,7 @@ var HistoryService = class _HistoryService {
23082
22906
  /** Return the current message count in the active conversation. */
23083
22907
  getCurrentMessageCount() {
23084
22908
  if (!this.currentConversationId) return 0;
23085
- const filePath = path46.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22909
+ const filePath = path45.join(this.projectDir, `${this.currentConversationId}.jsonl`);
23086
22910
  return parseJsonl(filePath).length;
23087
22911
  }
23088
22912
  /**
@@ -23093,7 +22917,7 @@ var HistoryService = class _HistoryService {
23093
22917
  const deadline = Date.now() + timeoutMs;
23094
22918
  while (Date.now() < deadline) {
23095
22919
  if (!this.currentConversationId) return null;
23096
- const filePath = path46.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22920
+ const filePath = path45.join(this.projectDir, `${this.currentConversationId}.jsonl`);
23097
22921
  const messages = parseJsonl(filePath);
23098
22922
  if (messages.length > previousCount) {
23099
22923
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -23119,16 +22943,16 @@ var HistoryService = class _HistoryService {
23119
22943
  const dir = this.projectDir;
23120
22944
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
23121
22945
  try {
23122
- const files = fs38.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22946
+ const files = fs37.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
23123
22947
  try {
23124
- const stat3 = fs38.statSync(path46.join(dir, e.name));
22948
+ const stat3 = fs37.statSync(path45.join(dir, e.name));
23125
22949
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
23126
22950
  } catch {
23127
22951
  return { name: e.name, mtime: 0, birthtime: 0 };
23128
22952
  }
23129
22953
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
23130
22954
  if (files.length > 0) {
23131
- this.currentConversationId = path46.basename(files[0].name, ".jsonl");
22955
+ this.currentConversationId = path45.basename(files[0].name, ".jsonl");
23132
22956
  }
23133
22957
  } catch {
23134
22958
  }
@@ -23162,13 +22986,13 @@ var HistoryService = class _HistoryService {
23162
22986
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
23163
22987
  let entries;
23164
22988
  try {
23165
- entries = fs38.readdirSync(dir, { withFileTypes: true });
22989
+ entries = fs37.readdirSync(dir, { withFileTypes: true });
23166
22990
  } catch {
23167
22991
  return null;
23168
22992
  }
23169
22993
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
23170
22994
  try {
23171
- const stat3 = fs38.statSync(path46.join(dir, e.name));
22995
+ const stat3 = fs37.statSync(path45.join(dir, e.name));
23172
22996
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
23173
22997
  } catch {
23174
22998
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -23177,12 +23001,12 @@ var HistoryService = class _HistoryService {
23177
23001
  if (files.length === 0) return null;
23178
23002
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
23179
23003
  if (!files.some((f) => f.name === targetFile)) return null;
23180
- return this.extractUsageFromFile(path46.join(dir, targetFile));
23004
+ return this.extractUsageFromFile(path45.join(dir, targetFile));
23181
23005
  }
23182
23006
  extractUsageFromFile(filePath) {
23183
23007
  let raw;
23184
23008
  try {
23185
- raw = fs38.readFileSync(filePath, "utf8");
23009
+ raw = fs37.readFileSync(filePath, "utf8");
23186
23010
  } catch {
23187
23011
  return null;
23188
23012
  }
@@ -23227,9 +23051,9 @@ var HistoryService = class _HistoryService {
23227
23051
  let totalCost = 0;
23228
23052
  let files;
23229
23053
  try {
23230
- files = fs38.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
23054
+ files = fs37.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
23231
23055
  try {
23232
- return fs38.statSync(path46.join(projectDir, f)).mtimeMs >= monthStartMs;
23056
+ return fs37.statSync(path45.join(projectDir, f)).mtimeMs >= monthStartMs;
23233
23057
  } catch {
23234
23058
  return false;
23235
23059
  }
@@ -23240,7 +23064,7 @@ var HistoryService = class _HistoryService {
23240
23064
  for (const file of files) {
23241
23065
  let raw;
23242
23066
  try {
23243
- raw = fs38.readFileSync(path46.join(projectDir, file), "utf8");
23067
+ raw = fs37.readFileSync(path45.join(projectDir, file), "utf8");
23244
23068
  } catch {
23245
23069
  continue;
23246
23070
  }
@@ -23304,7 +23128,7 @@ var HistoryService = class _HistoryService {
23304
23128
  * showing an empty conversation.
23305
23129
  */
23306
23130
  async loadConversation(sessionId) {
23307
- const filePath = path46.join(this.projectDir, `${sessionId}.jsonl`);
23131
+ const filePath = path45.join(this.projectDir, `${sessionId}.jsonl`);
23308
23132
  const messages = parseJsonl(filePath);
23309
23133
  if (messages.length === 0) return;
23310
23134
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -23358,7 +23182,7 @@ var HistoryService = class _HistoryService {
23358
23182
  if (!this.currentConversationId) return 0;
23359
23183
  }
23360
23184
  const sessionId = this.currentConversationId;
23361
- const filePath = path46.join(this.projectDir, `${sessionId}.jsonl`);
23185
+ const filePath = path45.join(this.projectDir, `${sessionId}.jsonl`);
23362
23186
  const messages = parseJsonl(filePath);
23363
23187
  if (messages.length === 0) return 0;
23364
23188
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -24279,7 +24103,7 @@ async function autoLinkAfterPair(opts) {
24279
24103
  }
24280
24104
 
24281
24105
  // src/commands/pair-auto.ts
24282
- var fs39 = __toESM(require("fs"));
24106
+ var fs38 = __toESM(require("fs"));
24283
24107
  var os30 = __toESM(require("os"));
24284
24108
  var import_crypto7 = require("crypto");
24285
24109
 
@@ -24475,12 +24299,12 @@ function readTokenFromArgs(args2) {
24475
24299
  }
24476
24300
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
24477
24301
  if (fileFlag) {
24478
- const path53 = fileFlag.slice("--token-file=".length);
24302
+ const path52 = fileFlag.slice("--token-file=".length);
24479
24303
  try {
24480
- const content = fs39.readFileSync(path53, "utf8").trim();
24481
- if (content.length === 0) fail(`--token-file ${path53} is empty`);
24304
+ const content = fs38.readFileSync(path52, "utf8").trim();
24305
+ if (content.length === 0) fail(`--token-file ${path52} is empty`);
24482
24306
  try {
24483
- fs39.unlinkSync(path53);
24307
+ fs38.unlinkSync(path52);
24484
24308
  } catch {
24485
24309
  }
24486
24310
  return content;
@@ -24598,8 +24422,6 @@ async function pairAuto(args2) {
24598
24422
  codespaceName: process.env.CODESPACE_NAME ?? void 0
24599
24423
  });
24600
24424
  console.log(` Paired with ${claimed.user.name} (${claimed.user.plan})`);
24601
- void provisionProjectDependencies(process.cwd()).catch(() => {
24602
- });
24603
24425
  if (process.env.CODEAM_SKIP_AGENT_LAUNCH === "true") {
24604
24426
  capture("pair_auto_skipped_launch", {
24605
24427
  sessionId: claimed.sessionId,
@@ -24748,7 +24570,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
24748
24570
  var import_child_process22 = require("child_process");
24749
24571
  var import_util4 = require("util");
24750
24572
  var import_picocolors8 = __toESM(require("picocolors"));
24751
- var path47 = __toESM(require("path"));
24573
+ var path46 = __toESM(require("path"));
24752
24574
  var execFileP5 = (0, import_util4.promisify)(import_child_process22.execFile);
24753
24575
  var MAX_BUFFER = 8 * 1024 * 1024;
24754
24576
  function resetStdinForChild() {
@@ -25237,7 +25059,7 @@ var GitHubCodespacesProvider = class {
25237
25059
  });
25238
25060
  }
25239
25061
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25240
- const remoteDir = path47.posix.dirname(remotePath);
25062
+ const remoteDir = path46.posix.dirname(remotePath);
25241
25063
  const parts = [
25242
25064
  `mkdir -p ${shellQuote(remoteDir)}`,
25243
25065
  `cat > ${shellQuote(remotePath)}`
@@ -25307,7 +25129,7 @@ function shellQuote(s) {
25307
25129
  // src/services/providers/gitpod.ts
25308
25130
  var import_child_process23 = require("child_process");
25309
25131
  var import_util5 = require("util");
25310
- var path48 = __toESM(require("path"));
25132
+ var path47 = __toESM(require("path"));
25311
25133
  var import_picocolors9 = __toESM(require("picocolors"));
25312
25134
  var execFileP6 = (0, import_util5.promisify)(import_child_process23.execFile);
25313
25135
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -25547,7 +25369,7 @@ var GitpodProvider = class {
25547
25369
  });
25548
25370
  }
25549
25371
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25550
- const remoteDir = path48.posix.dirname(remotePath);
25372
+ const remoteDir = path47.posix.dirname(remotePath);
25551
25373
  const parts = [
25552
25374
  `mkdir -p ${shellQuote2(remoteDir)}`,
25553
25375
  `cat > ${shellQuote2(remotePath)}`
@@ -25583,7 +25405,7 @@ function shellQuote2(s) {
25583
25405
  // src/services/providers/gitlab-workspaces.ts
25584
25406
  var import_child_process24 = require("child_process");
25585
25407
  var import_util6 = require("util");
25586
- var path49 = __toESM(require("path"));
25408
+ var path48 = __toESM(require("path"));
25587
25409
  var execFileP7 = (0, import_util6.promisify)(import_child_process24.execFile);
25588
25410
  var MAX_BUFFER3 = 8 * 1024 * 1024;
25589
25411
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -25843,7 +25665,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
25843
25665
  }
25844
25666
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25845
25667
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
25846
- const remoteDir = path49.posix.dirname(remotePath);
25668
+ const remoteDir = path48.posix.dirname(remotePath);
25847
25669
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
25848
25670
  if (options.mode != null) {
25849
25671
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -25911,7 +25733,7 @@ function shellQuote3(s) {
25911
25733
  // src/services/providers/railway.ts
25912
25734
  var import_child_process25 = require("child_process");
25913
25735
  var import_util7 = require("util");
25914
- var path50 = __toESM(require("path"));
25736
+ var path49 = __toESM(require("path"));
25915
25737
  var execFileP8 = (0, import_util7.promisify)(import_child_process25.execFile);
25916
25738
  var MAX_BUFFER4 = 8 * 1024 * 1024;
25917
25739
  function resetStdinForChild4() {
@@ -26147,7 +25969,7 @@ var RailwayProvider = class {
26147
25969
  if (!projectId || !serviceId) {
26148
25970
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
26149
25971
  }
26150
- const remoteDir = path50.posix.dirname(remotePath);
25972
+ const remoteDir = path49.posix.dirname(remotePath);
26151
25973
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
26152
25974
  if (options.mode != null) {
26153
25975
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -26690,8 +26512,8 @@ async function stopWorkspaceFromLocal(target) {
26690
26512
  var import_node_dns = require("dns");
26691
26513
  var import_node_util4 = require("util");
26692
26514
  var import_node_crypto8 = require("crypto");
26693
- var fs40 = __toESM(require("fs"));
26694
- var path51 = __toESM(require("path"));
26515
+ var fs39 = __toESM(require("fs"));
26516
+ var path50 = __toESM(require("path"));
26695
26517
  var import_picocolors12 = __toESM(require("picocolors"));
26696
26518
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
26697
26519
  async function checkDns(apiBase) {
@@ -26747,13 +26569,13 @@ async function checkHealth(apiBase) {
26747
26569
  }
26748
26570
  }
26749
26571
  function checkConfigDir() {
26750
- const dir = path51.join(require("os").homedir(), ".codeam");
26572
+ const dir = path50.join(require("os").homedir(), ".codeam");
26751
26573
  try {
26752
- fs40.mkdirSync(dir, { recursive: true, mode: 448 });
26753
- const probe = path51.join(dir, ".doctor-probe");
26754
- fs40.writeFileSync(probe, "ok", { mode: 384 });
26755
- const read = fs40.readFileSync(probe, "utf8");
26756
- fs40.unlinkSync(probe);
26574
+ fs39.mkdirSync(dir, { recursive: true, mode: 448 });
26575
+ const probe = path50.join(dir, ".doctor-probe");
26576
+ fs39.writeFileSync(probe, "ok", { mode: 384 });
26577
+ const read = fs39.readFileSync(probe, "utf8");
26578
+ fs39.unlinkSync(probe);
26757
26579
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
26758
26580
  return {
26759
26581
  id: "config-dir",
@@ -26817,7 +26639,7 @@ function checkNodePty() {
26817
26639
  detail: "not required on this platform"
26818
26640
  };
26819
26641
  }
26820
- const vendoredPath = path51.join(__dirname, "vendor", "node-pty");
26642
+ const vendoredPath = path50.join(__dirname, "vendor", "node-pty");
26821
26643
  for (const target of [vendoredPath, "node-pty"]) {
26822
26644
  try {
26823
26645
  require(target);
@@ -26859,7 +26681,7 @@ function checkChokidar() {
26859
26681
  }
26860
26682
  async function doctor(args2 = []) {
26861
26683
  const json = args2.includes("--json");
26862
- const cliVersion = true ? "2.39.0" : "0.0.0-dev";
26684
+ const cliVersion = true ? "2.39.2" : "0.0.0-dev";
26863
26685
  const apiBase = resolveApiBaseUrl();
26864
26686
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
26865
26687
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -27058,7 +26880,7 @@ async function completion(args2) {
27058
26880
  // src/commands/version.ts
27059
26881
  var import_picocolors13 = __toESM(require("picocolors"));
27060
26882
  function version2() {
27061
- const v = true ? "2.39.0" : "unknown";
26883
+ const v = true ? "2.39.2" : "unknown";
27062
26884
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
27063
26885
  }
27064
26886
 
@@ -27186,9 +27008,9 @@ function tryShowSubcommandHelp(cmd, args2) {
27186
27008
  var _subcommandHelpKeys = Object.keys(HELPS);
27187
27009
 
27188
27010
  // src/lib/updateNotifier.ts
27189
- var fs41 = __toESM(require("fs"));
27011
+ var fs40 = __toESM(require("fs"));
27190
27012
  var os31 = __toESM(require("os"));
27191
- var path52 = __toESM(require("path"));
27013
+ var path51 = __toESM(require("path"));
27192
27014
  var https8 = __toESM(require("https"));
27193
27015
  var import_node_child_process12 = require("child_process");
27194
27016
  var import_picocolors16 = __toESM(require("picocolors"));
@@ -27197,12 +27019,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
27197
27019
  var TTL_MS = 24 * 60 * 60 * 1e3;
27198
27020
  var REQUEST_TIMEOUT_MS = 1500;
27199
27021
  function cachePath() {
27200
- const dir = path52.join(os31.homedir(), ".codeam");
27201
- return path52.join(dir, "update-check.json");
27022
+ const dir = path51.join(os31.homedir(), ".codeam");
27023
+ return path51.join(dir, "update-check.json");
27202
27024
  }
27203
27025
  function readCache() {
27204
27026
  try {
27205
- const raw = fs41.readFileSync(cachePath(), "utf8");
27027
+ const raw = fs40.readFileSync(cachePath(), "utf8");
27206
27028
  const parsed = JSON.parse(raw);
27207
27029
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
27208
27030
  return parsed;
@@ -27213,10 +27035,10 @@ function readCache() {
27213
27035
  function writeCache(cache) {
27214
27036
  try {
27215
27037
  const file = cachePath();
27216
- fs41.mkdirSync(path52.dirname(file), { recursive: true });
27038
+ fs40.mkdirSync(path51.dirname(file), { recursive: true });
27217
27039
  const tmp = `${file}.${process.pid}.tmp`;
27218
- fs41.writeFileSync(tmp, JSON.stringify(cache));
27219
- fs41.renameSync(tmp, file);
27040
+ fs40.writeFileSync(tmp, JSON.stringify(cache));
27041
+ fs40.renameSync(tmp, file);
27220
27042
  } catch {
27221
27043
  }
27222
27044
  }
@@ -27290,8 +27112,8 @@ function isLinkedInstall() {
27290
27112
  timeout: 2e3
27291
27113
  }).trim();
27292
27114
  if (!root) return false;
27293
- const pkgPath = path52.join(root, PKG_NAME);
27294
- return fs41.lstatSync(pkgPath).isSymbolicLink();
27115
+ const pkgPath = path51.join(root, PKG_NAME);
27116
+ return fs40.lstatSync(pkgPath).isSymbolicLink();
27295
27117
  } catch {
27296
27118
  return false;
27297
27119
  }
@@ -27327,7 +27149,7 @@ function maybeAutoUpdate(currentVersion, latest) {
27327
27149
  return;
27328
27150
  }
27329
27151
  try {
27330
- fs41.unlinkSync(cachePath());
27152
+ fs40.unlinkSync(cachePath());
27331
27153
  } catch {
27332
27154
  }
27333
27155
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
@@ -27344,7 +27166,7 @@ function checkForUpdates() {
27344
27166
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
27345
27167
  if (process.env.CI) return;
27346
27168
  if (!process.stdout.isTTY) return;
27347
- const current = true ? "2.39.0" : null;
27169
+ const current = true ? "2.39.2" : null;
27348
27170
  if (!current) return;
27349
27171
  const cache = readCache();
27350
27172
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.0",
3
+ "version": "2.39.2",
4
4
  "description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",