codeam-cli 2.39.51 → 2.39.52
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 +6 -0
- package/dist/index.js +119 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ 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.51] — 2026-06-20
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Reuse running preview on re-open instead of re-spawn (EADDRINUSE)
|
|
12
|
+
|
|
7
13
|
## [2.39.50] — 2026-06-19
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -5388,7 +5388,7 @@ function readAnonId() {
|
|
|
5388
5388
|
}
|
|
5389
5389
|
function superProperties() {
|
|
5390
5390
|
return {
|
|
5391
|
-
cliVersion: true ? "2.39.
|
|
5391
|
+
cliVersion: true ? "2.39.52" : "0.0.0-dev",
|
|
5392
5392
|
nodeVersion: process.version,
|
|
5393
5393
|
platform: process.platform,
|
|
5394
5394
|
arch: process.arch,
|
|
@@ -5547,7 +5547,7 @@ var os4 = __toESM(require("os"));
|
|
|
5547
5547
|
// package.json
|
|
5548
5548
|
var package_default = {
|
|
5549
5549
|
name: "codeam-cli",
|
|
5550
|
-
version: "2.39.
|
|
5550
|
+
version: "2.39.52",
|
|
5551
5551
|
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.",
|
|
5552
5552
|
type: "commonjs",
|
|
5553
5553
|
main: "dist/index.js",
|
|
@@ -17245,6 +17245,15 @@ function isDeployPayload(p2) {
|
|
|
17245
17245
|
if (p2.cloneToken !== void 0 && typeof p2.cloneToken !== "string") {
|
|
17246
17246
|
return false;
|
|
17247
17247
|
}
|
|
17248
|
+
if (p2.headroomEnabled !== void 0 && typeof p2.headroomEnabled !== "boolean") {
|
|
17249
|
+
return false;
|
|
17250
|
+
}
|
|
17251
|
+
if (p2.headroomAgent !== void 0 && typeof p2.headroomAgent !== "string") {
|
|
17252
|
+
return false;
|
|
17253
|
+
}
|
|
17254
|
+
if (p2.headroomSavingsIngestUrl !== void 0 && typeof p2.headroomSavingsIngestUrl !== "string") {
|
|
17255
|
+
return false;
|
|
17256
|
+
}
|
|
17248
17257
|
const hasHouse = isHouseProxy(p2.houseProxy);
|
|
17249
17258
|
const hasSealed = typeof p2.sealedAgentAuth === "string";
|
|
17250
17259
|
return hasHouse || hasSealed;
|
|
@@ -17260,6 +17269,95 @@ var CONTROL_AGENT_META = {
|
|
|
17260
17269
|
supportedAuthKinds: ["oauth_token"],
|
|
17261
17270
|
preferredAuthKind: "oauth_token"
|
|
17262
17271
|
};
|
|
17272
|
+
async function setupHeadroomForSelfHosted(agent) {
|
|
17273
|
+
const INSTALL_TIMEOUT_MS2 = 12e4;
|
|
17274
|
+
const PIP_PACKAGES = [
|
|
17275
|
+
"headroom-ai",
|
|
17276
|
+
"fastapi",
|
|
17277
|
+
"uvicorn",
|
|
17278
|
+
"httpx[http2]",
|
|
17279
|
+
"websockets",
|
|
17280
|
+
"zstandard"
|
|
17281
|
+
];
|
|
17282
|
+
const installOk = await new Promise((resolve7) => {
|
|
17283
|
+
const tryPip = (cmd) => new Promise((res) => {
|
|
17284
|
+
const child = (0, import_node_child_process12.spawn)(cmd, ["install", "--quiet", ...PIP_PACKAGES], {
|
|
17285
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
17286
|
+
});
|
|
17287
|
+
let settled = false;
|
|
17288
|
+
const done = (ok) => {
|
|
17289
|
+
if (settled) return;
|
|
17290
|
+
settled = true;
|
|
17291
|
+
res(ok);
|
|
17292
|
+
};
|
|
17293
|
+
const onData = (b) => {
|
|
17294
|
+
const line = b.toString().replace(/\n+$/g, "");
|
|
17295
|
+
if (line) log.info("host-agent", `headroom-install: ${line}`);
|
|
17296
|
+
};
|
|
17297
|
+
child.stdout?.on("data", onData);
|
|
17298
|
+
child.stderr?.on("data", onData);
|
|
17299
|
+
const timer = setTimeout(() => {
|
|
17300
|
+
log.warn("host-agent", `headroom pip install timed out (${INSTALL_TIMEOUT_MS2 / 1e3}s) \u2014 skipping Headroom`);
|
|
17301
|
+
try {
|
|
17302
|
+
child.kill("SIGTERM");
|
|
17303
|
+
} catch {
|
|
17304
|
+
}
|
|
17305
|
+
done(false);
|
|
17306
|
+
}, INSTALL_TIMEOUT_MS2);
|
|
17307
|
+
child.once("exit", (code) => {
|
|
17308
|
+
clearTimeout(timer);
|
|
17309
|
+
if (code === 0) {
|
|
17310
|
+
log.info("host-agent", "headroom pip install succeeded");
|
|
17311
|
+
} else {
|
|
17312
|
+
log.warn("host-agent", `headroom pip install exited code=${String(code)} \u2014 skipping Headroom`);
|
|
17313
|
+
}
|
|
17314
|
+
done(code === 0);
|
|
17315
|
+
});
|
|
17316
|
+
child.once("error", (e) => {
|
|
17317
|
+
clearTimeout(timer);
|
|
17318
|
+
done(false);
|
|
17319
|
+
log.trace("host-agent", `headroom pip spawn error (${cmd}): ${e.message}`);
|
|
17320
|
+
});
|
|
17321
|
+
});
|
|
17322
|
+
tryPip("pip").then((ok) => ok ? resolve7(true) : tryPip("pip3").then(resolve7)).catch(() => resolve7(false));
|
|
17323
|
+
});
|
|
17324
|
+
if (!installOk) {
|
|
17325
|
+
return false;
|
|
17326
|
+
}
|
|
17327
|
+
const initOk = await new Promise((resolve7) => {
|
|
17328
|
+
(0, import_node_child_process12.execFile)("which", ["headroom"], (whichErr) => {
|
|
17329
|
+
if (whichErr) {
|
|
17330
|
+
log.warn("host-agent", "headroom not found on PATH after install \u2014 skipping init");
|
|
17331
|
+
resolve7(false);
|
|
17332
|
+
return;
|
|
17333
|
+
}
|
|
17334
|
+
(0, import_node_child_process12.execFile)("headroom", ["init", "--global", agent], (initErr, stdout, stderr) => {
|
|
17335
|
+
if (initErr) {
|
|
17336
|
+
const detail = (stderr || initErr.message).replace(/\n+$/g, "");
|
|
17337
|
+
log.warn("host-agent", `headroom init failed (best-effort): ${detail}`);
|
|
17338
|
+
resolve7(false);
|
|
17339
|
+
} else {
|
|
17340
|
+
if (stdout.trim()) log.info("host-agent", `headroom init: ${stdout.trim()}`);
|
|
17341
|
+
log.info("host-agent", "headroom init --global succeeded");
|
|
17342
|
+
resolve7(true);
|
|
17343
|
+
}
|
|
17344
|
+
});
|
|
17345
|
+
});
|
|
17346
|
+
});
|
|
17347
|
+
if (!initOk) {
|
|
17348
|
+
return false;
|
|
17349
|
+
}
|
|
17350
|
+
try {
|
|
17351
|
+
const proxy = (0, import_node_child_process12.spawn)("headroom", ["proxy", "--port", "8787"], {
|
|
17352
|
+
stdio: "ignore",
|
|
17353
|
+
detached: true
|
|
17354
|
+
});
|
|
17355
|
+
proxy.unref();
|
|
17356
|
+
} catch (e) {
|
|
17357
|
+
log.warn("host-agent", `headroom proxy warm-start failed (best-effort): ${e instanceof Error ? e.message : String(e)}`);
|
|
17358
|
+
}
|
|
17359
|
+
return true;
|
|
17360
|
+
}
|
|
17263
17361
|
var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process12.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
|
|
17264
17362
|
cwd,
|
|
17265
17363
|
env: { ...process.env, ...env },
|
|
@@ -17283,6 +17381,7 @@ var HostAgentSupervisor = class {
|
|
|
17283
17381
|
this.deps = deps;
|
|
17284
17382
|
this.spawnChild = deps.spawnChild ?? defaultSpawner;
|
|
17285
17383
|
this.resolveAgentAuth = deps.resolveAgentAuth ?? unsealAgentAuth;
|
|
17384
|
+
this.setupHeadroom = deps.setupHeadroom ?? setupHeadroomForSelfHosted;
|
|
17286
17385
|
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
17287
17386
|
this.onIdentityRejected = deps.onIdentityRejected ?? defaultOnIdentityRejected;
|
|
17288
17387
|
this.disableService = deps.disableService ?? defaultDisableService;
|
|
@@ -17292,6 +17391,7 @@ var HostAgentSupervisor = class {
|
|
|
17292
17391
|
children = /* @__PURE__ */ new Map();
|
|
17293
17392
|
spawnChild;
|
|
17294
17393
|
resolveAgentAuth;
|
|
17394
|
+
setupHeadroom;
|
|
17295
17395
|
relay = null;
|
|
17296
17396
|
heartbeatTimer = null;
|
|
17297
17397
|
/** Guards the one-shot 'connected' telemetry on the first heartbeat. */
|
|
@@ -17464,6 +17564,18 @@ var HostAgentSupervisor = class {
|
|
|
17464
17564
|
childEnv.PREVIEW_TUNNEL_TOKEN = payload.previewTunnelToken;
|
|
17465
17565
|
childEnv.PREVIEW_TUNNEL_HOSTNAME = payload.previewHostname;
|
|
17466
17566
|
}
|
|
17567
|
+
if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl) {
|
|
17568
|
+
report("headroom", "setting up Headroom proxy");
|
|
17569
|
+
const headroomOk = await this.setupHeadroom(payload.headroomAgent);
|
|
17570
|
+
if (headroomOk) {
|
|
17571
|
+
childEnv.HEADROOM_ENABLED = "1";
|
|
17572
|
+
childEnv.HEADROOM_AGENT = payload.headroomAgent;
|
|
17573
|
+
childEnv.HEADROOM_SAVINGS_INGEST_URL = payload.headroomSavingsIngestUrl;
|
|
17574
|
+
log.info("host-agent", "Headroom proxy ready; HEADROOM_* env injected into child");
|
|
17575
|
+
} else {
|
|
17576
|
+
log.warn("host-agent", "Headroom setup failed (best-effort) \u2014 child will run without Headroom");
|
|
17577
|
+
}
|
|
17578
|
+
}
|
|
17467
17579
|
report("spawning", "starting agent");
|
|
17468
17580
|
const proc = this.spawnChild(childEnv, cwd, extraArgs);
|
|
17469
17581
|
const child = { deployId: payload.deployId, proc };
|
|
@@ -27373,9 +27485,9 @@ async function probeCodeamPair(provider, workspace) {
|
|
|
27373
27485
|
}
|
|
27374
27486
|
async function stopWorkspaceFromLocal(target) {
|
|
27375
27487
|
if (target.provider.id === "github-codespaces") {
|
|
27376
|
-
const { execFile:
|
|
27488
|
+
const { execFile: execFile12 } = await import("child_process");
|
|
27377
27489
|
const { promisify: promisify11 } = await import("util");
|
|
27378
|
-
const execFileP10 = promisify11(
|
|
27490
|
+
const execFileP10 = promisify11(execFile12);
|
|
27379
27491
|
await execFileP10("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
|
|
27380
27492
|
return;
|
|
27381
27493
|
}
|
|
@@ -27599,7 +27711,7 @@ function checkChokidar() {
|
|
|
27599
27711
|
}
|
|
27600
27712
|
async function doctor(args2 = []) {
|
|
27601
27713
|
const json = args2.includes("--json");
|
|
27602
|
-
const cliVersion = true ? "2.39.
|
|
27714
|
+
const cliVersion = true ? "2.39.52" : "0.0.0-dev";
|
|
27603
27715
|
const apiBase2 = resolveApiBaseUrl();
|
|
27604
27716
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27605
27717
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27798,7 +27910,7 @@ async function completion(args2) {
|
|
|
27798
27910
|
// src/commands/version.ts
|
|
27799
27911
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27800
27912
|
function version2() {
|
|
27801
|
-
const v = true ? "2.39.
|
|
27913
|
+
const v = true ? "2.39.52" : "unknown";
|
|
27802
27914
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27803
27915
|
}
|
|
27804
27916
|
|
|
@@ -28084,7 +28196,7 @@ function checkForUpdates() {
|
|
|
28084
28196
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
28085
28197
|
if (process.env.CI) return;
|
|
28086
28198
|
if (!process.stdout.isTTY) return;
|
|
28087
|
-
const current = true ? "2.39.
|
|
28199
|
+
const current = true ? "2.39.52" : null;
|
|
28088
28200
|
if (!current) return;
|
|
28089
28201
|
const cache = readCache();
|
|
28090
28202
|
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.
|
|
3
|
+
"version": "2.39.52",
|
|
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",
|