codeam-cli 2.76.33 → 2.76.34
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/CHANGELOG.md +7 -0
- package/dist/index.js +133 -18
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ 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.76.33] — 2026-10-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **box:** Bake PHP CLI + Composer into the Box image
|
|
12
|
+
- **cli:** Composer pre-flight + PHP guidance for in-app Preview
|
|
13
|
+
|
|
7
14
|
## [2.76.32] — 2026-10-14
|
|
8
15
|
|
|
9
16
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -10636,7 +10636,7 @@ function readAnonId() {
|
|
|
10636
10636
|
}
|
|
10637
10637
|
function superProperties() {
|
|
10638
10638
|
return {
|
|
10639
|
-
cliVersion: true ? "2.76.
|
|
10639
|
+
cliVersion: true ? "2.76.34" : "0.0.0-dev",
|
|
10640
10640
|
nodeVersion: process.version,
|
|
10641
10641
|
platform: process.platform,
|
|
10642
10642
|
arch: process.arch,
|
|
@@ -10885,7 +10885,7 @@ var http = __toESM(require("http"));
|
|
|
10885
10885
|
// package.json
|
|
10886
10886
|
var package_default = {
|
|
10887
10887
|
name: "codeam-cli",
|
|
10888
|
-
version: "2.76.
|
|
10888
|
+
version: "2.76.34",
|
|
10889
10889
|
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.",
|
|
10890
10890
|
type: "commonjs",
|
|
10891
10891
|
main: "dist/index.js",
|
|
@@ -10973,7 +10973,7 @@ var package_default = {
|
|
|
10973
10973
|
zod: "^4.3.6"
|
|
10974
10974
|
},
|
|
10975
10975
|
optionalDependencies: {
|
|
10976
|
-
"@beads/bd": "1.
|
|
10976
|
+
"@beads/bd": "1.3.1"
|
|
10977
10977
|
},
|
|
10978
10978
|
devDependencies: {
|
|
10979
10979
|
"@codeam/shared": "*",
|
|
@@ -12261,7 +12261,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12261
12261
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12262
12262
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12263
12263
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12264
|
-
..."2.76.
|
|
12264
|
+
..."2.76.34" ? { ideVersion: "2.76.34" } : {}
|
|
12265
12265
|
};
|
|
12266
12266
|
try {
|
|
12267
12267
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -27509,6 +27509,43 @@ var import_child_process21 = require("child_process");
|
|
|
27509
27509
|
var fs59 = __toESM(require("fs"));
|
|
27510
27510
|
var os40 = __toESM(require("os"));
|
|
27511
27511
|
var path67 = __toESM(require("path"));
|
|
27512
|
+
|
|
27513
|
+
// src/beads/schema-migrate.ts
|
|
27514
|
+
var SCHEMA_SKEW_RE = /Error 1146|table not found|refusing to auto-apply \d+ pending schema migration/i;
|
|
27515
|
+
function isSchemaSkew(text) {
|
|
27516
|
+
return SCHEMA_SKEW_RE.test(text);
|
|
27517
|
+
}
|
|
27518
|
+
var APPLIED_RE = /applying (\d+) pending schema migration/i;
|
|
27519
|
+
var REMOTE_GATE_RE = /remote-backed database/i;
|
|
27520
|
+
async function migrateSchema(bd) {
|
|
27521
|
+
let forced = false;
|
|
27522
|
+
let res = await bd.run(["migrate", "schema"]);
|
|
27523
|
+
if (res.code !== 0 && REMOTE_GATE_RE.test(res.stderr + res.stdout)) {
|
|
27524
|
+
log.info("beads", "schema migrate refused for a remote-backed DB \u2014 migrating with --force");
|
|
27525
|
+
forced = true;
|
|
27526
|
+
res = await bd.run(["migrate", "schema", "--force"]);
|
|
27527
|
+
}
|
|
27528
|
+
const text = `${res.stderr}
|
|
27529
|
+
${res.stdout}`;
|
|
27530
|
+
if (res.code !== 0) {
|
|
27531
|
+
const detail = (res.stderr || res.stdout).trim().slice(0, 200);
|
|
27532
|
+
log.warn("beads", `bd migrate schema failed (code=${res.code}): ${detail}`);
|
|
27533
|
+
return { status: "failed", detail };
|
|
27534
|
+
}
|
|
27535
|
+
const applied = APPLIED_RE.exec(text);
|
|
27536
|
+
if (applied) {
|
|
27537
|
+
const count = Number(applied[1]);
|
|
27538
|
+
log.info(
|
|
27539
|
+
"beads",
|
|
27540
|
+
`bd migrate schema applied ${count} migration(s)${forced ? " (--force)" : ""}`
|
|
27541
|
+
);
|
|
27542
|
+
return { status: "applied", count, forced };
|
|
27543
|
+
}
|
|
27544
|
+
log.trace("beads", "bd migrate schema: already current");
|
|
27545
|
+
return { status: "current" };
|
|
27546
|
+
}
|
|
27547
|
+
|
|
27548
|
+
// src/beads/bd-adapter.ts
|
|
27512
27549
|
var BD_PACKAGE = "@beads/bd";
|
|
27513
27550
|
function resolveBundledBdBinary() {
|
|
27514
27551
|
return _resolveSeam.resolveBundled();
|
|
@@ -27586,6 +27623,8 @@ var BdAdapter = class {
|
|
|
27586
27623
|
}
|
|
27587
27624
|
opts;
|
|
27588
27625
|
resolved;
|
|
27626
|
+
/** Set when a bd call failed on schema skew; read + cleared by `takeSchemaSkew`. */
|
|
27627
|
+
schemaSkewSeen = false;
|
|
27589
27628
|
/**
|
|
27590
27629
|
* Resolve the bd binary lazily, caching the result. Order:
|
|
27591
27630
|
* bundled @beads/bd → PATH. Returns null when neither is available — the
|
|
@@ -27641,8 +27680,20 @@ var BdAdapter = class {
|
|
|
27641
27680
|
await _adapterSeam.sleep(750 * attempt);
|
|
27642
27681
|
res = await _spawnSeam.run(binary, args2, { cwd, env });
|
|
27643
27682
|
}
|
|
27683
|
+
if (res.code !== 0 && isSchemaSkew(res.stderr + res.stdout)) this.schemaSkewSeen = true;
|
|
27644
27684
|
return res;
|
|
27645
27685
|
}
|
|
27686
|
+
/**
|
|
27687
|
+
* Whether a bd call since the last check failed because the project DB is
|
|
27688
|
+
* behind this bd's schema (see `schema-migrate.ts`). `listIssues` /
|
|
27689
|
+
* `statusSummary` swallow failures into []/null, so this is how the watcher
|
|
27690
|
+
* learns the cause. Clears the flag.
|
|
27691
|
+
*/
|
|
27692
|
+
takeSchemaSkew() {
|
|
27693
|
+
const seen2 = this.schemaSkewSeen;
|
|
27694
|
+
this.schemaSkewSeen = false;
|
|
27695
|
+
return seen2;
|
|
27696
|
+
}
|
|
27646
27697
|
/**
|
|
27647
27698
|
* `bd ready --json` → typed issue array. `bd list --json` shares the shape,
|
|
27648
27699
|
* so `listIssues` reuses the same parser. Bad JSON / non-zero exit → [].
|
|
@@ -28208,7 +28259,8 @@ async function provisionBeads(opts = {}) {
|
|
|
28208
28259
|
prefix: null,
|
|
28209
28260
|
initialized: false,
|
|
28210
28261
|
exportEnabled: false,
|
|
28211
|
-
agentsWired: []
|
|
28262
|
+
agentsWired: [],
|
|
28263
|
+
schemaMigrate: null
|
|
28212
28264
|
};
|
|
28213
28265
|
if (!bd.isAvailable()) {
|
|
28214
28266
|
log.info("beads", "bd binary missing \u2014 running OS installer fallback");
|
|
@@ -28290,6 +28342,7 @@ async function provisionBeads(opts = {}) {
|
|
|
28290
28342
|
log.warn("beads", "shared dolt sql-server not up \u2014 beads disabled this run");
|
|
28291
28343
|
return result;
|
|
28292
28344
|
}
|
|
28345
|
+
result.schemaMigrate = await migrateSchemaSafely(bd);
|
|
28293
28346
|
try {
|
|
28294
28347
|
if (!await projectDbReachable(bd)) {
|
|
28295
28348
|
log.info(
|
|
@@ -28305,6 +28358,8 @@ async function provisionBeads(opts = {}) {
|
|
|
28305
28358
|
"beads",
|
|
28306
28359
|
`bd bootstrap failed (code=${boot.code}): ${boot.stderr.slice(0, 200)} \u2014 prefix DB may be absent`
|
|
28307
28360
|
);
|
|
28361
|
+
} else {
|
|
28362
|
+
result.schemaMigrate = await migrateSchemaSafely(bd);
|
|
28308
28363
|
}
|
|
28309
28364
|
}
|
|
28310
28365
|
if (!await projectDbReachable(bd)) {
|
|
@@ -28356,10 +28411,25 @@ async function provisionBeads(opts = {}) {
|
|
|
28356
28411
|
result.agentsWired = await setupAgents(bd, opts.agents ?? []);
|
|
28357
28412
|
log.info(
|
|
28358
28413
|
"beads",
|
|
28359
|
-
`provision done dolt=${result.doltAvailable} server=${result.serverUp} prefix=${result.prefix} initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
|
|
28414
|
+
`provision done dolt=${result.doltAvailable} server=${result.serverUp} prefix=${result.prefix} initialized=${result.initialized} schema=${describeSchemaMigrate(result.schemaMigrate)} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
|
|
28360
28415
|
);
|
|
28361
28416
|
return result;
|
|
28362
28417
|
}
|
|
28418
|
+
async function migrateSchemaSafely(bd) {
|
|
28419
|
+
try {
|
|
28420
|
+
return await migrateSchema(bd);
|
|
28421
|
+
} catch (err) {
|
|
28422
|
+
log.warn("beads", "bd migrate schema threw (non-fatal)", err);
|
|
28423
|
+
return { status: "failed", detail: err.message };
|
|
28424
|
+
}
|
|
28425
|
+
}
|
|
28426
|
+
function describeSchemaMigrate(outcome) {
|
|
28427
|
+
if (!outcome) return "skipped";
|
|
28428
|
+
if (outcome.status === "applied") {
|
|
28429
|
+
return `applied:${outcome.count}${outcome.forced ? ":forced" : ""}`;
|
|
28430
|
+
}
|
|
28431
|
+
return outcome.status;
|
|
28432
|
+
}
|
|
28363
28433
|
async function projectDbReachable(bd) {
|
|
28364
28434
|
const ping = await bd.run(["ping"]);
|
|
28365
28435
|
return ping.code === 0;
|
|
@@ -28455,6 +28525,8 @@ var BeadsWatcher = class {
|
|
|
28455
28525
|
debounceTimer = null;
|
|
28456
28526
|
stopped = false;
|
|
28457
28527
|
lastPushedHash = null;
|
|
28528
|
+
/** One schema-heal attempt per watcher — a failing migrate must not loop. */
|
|
28529
|
+
schemaHealTried = false;
|
|
28458
28530
|
bd;
|
|
28459
28531
|
feedPath;
|
|
28460
28532
|
apiBase;
|
|
@@ -28523,10 +28595,15 @@ var BeadsWatcher = class {
|
|
|
28523
28595
|
async syncNow() {
|
|
28524
28596
|
if (this.stopped) return;
|
|
28525
28597
|
const { projectKey, projectLabel } = deriveProjectIdentity(this.opts.cwd);
|
|
28526
|
-
|
|
28527
|
-
|
|
28528
|
-
this.
|
|
28529
|
-
|
|
28598
|
+
let [issues, summary] = await this.readSnapshot(projectKey);
|
|
28599
|
+
if (!this.schemaHealTried && this.bd.takeSchemaSkew()) {
|
|
28600
|
+
this.schemaHealTried = true;
|
|
28601
|
+
log.info("beads", "snapshot hit schema skew \u2014 running bd migrate schema once");
|
|
28602
|
+
const outcome = await migrateSchema(this.bd);
|
|
28603
|
+
if (outcome.status !== "failed") {
|
|
28604
|
+
[issues, summary] = await this.readSnapshot(projectKey);
|
|
28605
|
+
}
|
|
28606
|
+
}
|
|
28530
28607
|
const payload = {
|
|
28531
28608
|
sessionId: this.opts.sessionId,
|
|
28532
28609
|
pluginId: this.opts.pluginId,
|
|
@@ -28565,6 +28642,9 @@ var BeadsWatcher = class {
|
|
|
28565
28642
|
log.warn("beads", "ingest POST error", err);
|
|
28566
28643
|
}
|
|
28567
28644
|
}
|
|
28645
|
+
readSnapshot(projectKey) {
|
|
28646
|
+
return Promise.all([this.bd.listIssues(projectKey), this.bd.statusSummary()]);
|
|
28647
|
+
}
|
|
28568
28648
|
headers() {
|
|
28569
28649
|
return {
|
|
28570
28650
|
"Content-Type": "application/json",
|
|
@@ -51542,7 +51622,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51542
51622
|
if (process.env.NODE_ENV === "test") return;
|
|
51543
51623
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51544
51624
|
if (process.env.CI) return;
|
|
51545
|
-
const current2 = true ? "2.76.
|
|
51625
|
+
const current2 = true ? "2.76.34" : null;
|
|
51546
51626
|
if (!current2) return;
|
|
51547
51627
|
const cache = readCache();
|
|
51548
51628
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51559,7 +51639,7 @@ function checkForUpdates() {
|
|
|
51559
51639
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51560
51640
|
if (process.env.CI) return;
|
|
51561
51641
|
if (!process.stdout.isTTY) return;
|
|
51562
|
-
const current2 = true ? "2.76.
|
|
51642
|
+
const current2 = true ? "2.76.34" : null;
|
|
51563
51643
|
if (!current2) return;
|
|
51564
51644
|
const cache = readCache();
|
|
51565
51645
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51735,14 +51815,37 @@ function pidAlive3(pid) {
|
|
|
51735
51815
|
return err.code === "EPERM";
|
|
51736
51816
|
}
|
|
51737
51817
|
}
|
|
51818
|
+
var CLK_TCK = 100;
|
|
51819
|
+
function processStartMs(pid) {
|
|
51820
|
+
try {
|
|
51821
|
+
const stat3 = fs96.readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
51822
|
+
const ticks = Number(stat3.slice(stat3.lastIndexOf(")") + 2).split(" ")[19]);
|
|
51823
|
+
const btime = /^btime (\d+)$/m.exec(fs96.readFileSync("/proc/stat", "utf8"))?.[1];
|
|
51824
|
+
if (!Number.isFinite(ticks) || !btime) return null;
|
|
51825
|
+
return Number(btime) * 1e3 + ticks * 1e3 / CLK_TCK;
|
|
51826
|
+
} catch {
|
|
51827
|
+
return null;
|
|
51828
|
+
}
|
|
51829
|
+
}
|
|
51830
|
+
var PID_REUSE_SLACK_MS = 2e3;
|
|
51738
51831
|
function livePids(versionDir) {
|
|
51832
|
+
const dir = path109.join(versionDir, ".pids");
|
|
51739
51833
|
let names;
|
|
51740
51834
|
try {
|
|
51741
|
-
names = fs96.readdirSync(
|
|
51835
|
+
names = fs96.readdirSync(dir);
|
|
51742
51836
|
} catch {
|
|
51743
51837
|
return [];
|
|
51744
51838
|
}
|
|
51745
|
-
return names.map(Number).filter((pid) =>
|
|
51839
|
+
return names.map(Number).filter((pid) => {
|
|
51840
|
+
if (!Number.isInteger(pid) || pid <= 0 || !pidAlive3(pid)) return false;
|
|
51841
|
+
const started = processStartMs(pid);
|
|
51842
|
+
if (started === null) return true;
|
|
51843
|
+
try {
|
|
51844
|
+
return started <= fs96.statSync(path109.join(dir, String(pid))).mtimeMs + PID_REUSE_SLACK_MS;
|
|
51845
|
+
} catch {
|
|
51846
|
+
return true;
|
|
51847
|
+
}
|
|
51848
|
+
});
|
|
51746
51849
|
}
|
|
51747
51850
|
function registerRunningVersion(root = cliVersionsRoot(), entry = process.argv[1]) {
|
|
51748
51851
|
const dir = versionDirContaining(root, entry);
|
|
@@ -51842,7 +51945,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51842
51945
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51843
51946
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51844
51947
|
function currentCliVersion() {
|
|
51845
|
-
return true ? "2.76.
|
|
51948
|
+
return true ? "2.76.34" : null;
|
|
51846
51949
|
}
|
|
51847
51950
|
async function installedVersion(deps) {
|
|
51848
51951
|
const ls = await deps.run(
|
|
@@ -51927,6 +52030,7 @@ async function runSelfUpdateWith(deps) {
|
|
|
51927
52030
|
}
|
|
51928
52031
|
if (compareSemver(latest, current2) <= 0) {
|
|
51929
52032
|
log.info("host-agent", `self-update: running ${current2}, npm latest ${latest} \u2014 up to date`);
|
|
52033
|
+
if (versionedModeSupported(deps.platform)) collectOldVersions(root);
|
|
51930
52034
|
return { status: "current" };
|
|
51931
52035
|
}
|
|
51932
52036
|
if (!versionedModeSupported(deps.platform)) {
|
|
@@ -51943,6 +52047,17 @@ async function runSelfUpdateWith(deps) {
|
|
|
51943
52047
|
return { status: "skipped" };
|
|
51944
52048
|
}
|
|
51945
52049
|
}
|
|
52050
|
+
function collectOldVersions(root) {
|
|
52051
|
+
const release3 = acquireInstallLock(root);
|
|
52052
|
+
if (!release3) return [];
|
|
52053
|
+
try {
|
|
52054
|
+
const removed = gcVersions(root);
|
|
52055
|
+
if (removed.length) log.info("host-agent", `self-update: gc removed ${removed.join(", ")}`);
|
|
52056
|
+
return removed;
|
|
52057
|
+
} finally {
|
|
52058
|
+
release3();
|
|
52059
|
+
}
|
|
52060
|
+
}
|
|
51946
52061
|
var VERIFY_TIMEOUT_MS = 3e4;
|
|
51947
52062
|
async function installVersioned(deps, root, latest, running2) {
|
|
51948
52063
|
const node = deps.nodePath ?? process.execPath;
|
|
@@ -52053,7 +52168,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
52053
52168
|
}
|
|
52054
52169
|
function defaultDeps() {
|
|
52055
52170
|
return {
|
|
52056
|
-
ownVersion: true ? "2.76.
|
|
52171
|
+
ownVersion: true ? "2.76.34" : null,
|
|
52057
52172
|
root: cliVersionsRoot(),
|
|
52058
52173
|
args: process.argv.slice(3),
|
|
52059
52174
|
execPath: process.execPath,
|
|
@@ -54591,7 +54706,7 @@ function checkChokidar() {
|
|
|
54591
54706
|
}
|
|
54592
54707
|
async function doctor(args2 = []) {
|
|
54593
54708
|
const json = args2.includes("--json");
|
|
54594
|
-
const cliVersion = true ? "2.76.
|
|
54709
|
+
const cliVersion = true ? "2.76.34" : "0.0.0-dev";
|
|
54595
54710
|
const apiBase2 = resolveApiBaseUrl();
|
|
54596
54711
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54597
54712
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -55127,7 +55242,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
55127
55242
|
// src/commands/version.ts
|
|
55128
55243
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
55129
55244
|
function version2() {
|
|
55130
|
-
const v = true ? "2.76.
|
|
55245
|
+
const v = true ? "2.76.34" : "unknown";
|
|
55131
55246
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
55132
55247
|
}
|
|
55133
55248
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.76.
|
|
3
|
+
"version": "2.76.34",
|
|
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",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"zod": "^4.3.6"
|
|
89
89
|
},
|
|
90
90
|
"optionalDependencies": {
|
|
91
|
-
"@beads/bd": "1.
|
|
91
|
+
"@beads/bd": "1.3.1"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@codeam/shared": "*",
|