codeam-cli 2.39.38 → 2.39.39
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 +24 -48
- 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.38] — 2026-06-19
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Host-agent runs the per-agent install script before spawning
|
|
12
|
+
|
|
7
13
|
## [2.39.37] — 2026-06-19
|
|
8
14
|
|
|
9
15
|
### Fixed
|
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.
|
|
501
|
+
version: "2.39.39",
|
|
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",
|
|
@@ -5908,7 +5908,7 @@ function readAnonId() {
|
|
|
5908
5908
|
}
|
|
5909
5909
|
function superProperties() {
|
|
5910
5910
|
return {
|
|
5911
|
-
cliVersion: true ? "2.39.
|
|
5911
|
+
cliVersion: true ? "2.39.39" : "0.0.0-dev",
|
|
5912
5912
|
nodeVersion: process.version,
|
|
5913
5913
|
platform: process.platform,
|
|
5914
5914
|
arch: process.arch,
|
|
@@ -16464,37 +16464,20 @@ async function linkDryRunPreflight(ctx) {
|
|
|
16464
16464
|
}
|
|
16465
16465
|
|
|
16466
16466
|
// src/services/preview/cloudflared.ts
|
|
16467
|
-
var import_promises = __toESM(require("dns/promises"));
|
|
16468
16467
|
var import_fs = require("fs");
|
|
16469
|
-
var
|
|
16468
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
16470
16469
|
var import_os6 = __toESM(require("os"));
|
|
16471
16470
|
var import_path4 = __toESM(require("path"));
|
|
16472
|
-
var
|
|
16471
|
+
var import_promises2 = require("stream/promises");
|
|
16473
16472
|
var import_which = __toESM(require("which"));
|
|
16474
16473
|
var CACHED_BINARY = import_path4.default.join(import_os6.default.homedir(), ".codeam", "bin", "cloudflared");
|
|
16475
|
-
async function waitForCloudflaredReady(url, timeoutMs = 6e4) {
|
|
16476
|
-
const hostname3 = new URL(url).hostname;
|
|
16477
|
-
const cares = new import_promises.Resolver();
|
|
16478
|
-
const start2 = Date.now();
|
|
16479
|
-
while (Date.now() - start2 < timeoutMs) {
|
|
16480
|
-
const lookup = import_promises.default.lookup(hostname3, { all: true }).then((addrs) => addrs.length > 0, () => false);
|
|
16481
|
-
const v4 = cares.resolve4(hostname3).then((addrs) => addrs.length > 0, () => false);
|
|
16482
|
-
const v6 = cares.resolve6(hostname3).then((addrs) => addrs.length > 0, () => false);
|
|
16483
|
-
const results = await Promise.all([lookup, v4, v6]);
|
|
16484
|
-
if (results.some((ok) => ok)) return;
|
|
16485
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
16486
|
-
}
|
|
16487
|
-
throw new Error(
|
|
16488
|
-
`DNS for ${hostname3} did not resolve within ${timeoutMs}ms (Cloudflare Quick Tunnel registration may have failed).`
|
|
16489
|
-
);
|
|
16490
|
-
}
|
|
16491
16474
|
async function resolveCloudflared(opts = {}) {
|
|
16492
16475
|
try {
|
|
16493
16476
|
return await (0, import_which.default)("cloudflared");
|
|
16494
16477
|
} catch {
|
|
16495
16478
|
}
|
|
16496
16479
|
try {
|
|
16497
|
-
await
|
|
16480
|
+
await import_promises.default.access(CACHED_BINARY);
|
|
16498
16481
|
return CACHED_BINARY;
|
|
16499
16482
|
} catch {
|
|
16500
16483
|
}
|
|
@@ -16508,14 +16491,14 @@ async function resolveCloudflared(opts = {}) {
|
|
|
16508
16491
|
}
|
|
16509
16492
|
async function downloadCloudflared(target) {
|
|
16510
16493
|
const url = downloadUrlForPlatform();
|
|
16511
|
-
await
|
|
16494
|
+
await import_promises.default.mkdir(import_path4.default.dirname(target), { recursive: true });
|
|
16512
16495
|
const response = await fetch(url);
|
|
16513
16496
|
if (!response.ok || !response.body) {
|
|
16514
16497
|
throw new Error(
|
|
16515
16498
|
`Failed to download cloudflared from ${url}: HTTP ${response.status}. Install manually from https://github.com/cloudflare/cloudflared/releases.`
|
|
16516
16499
|
);
|
|
16517
16500
|
}
|
|
16518
|
-
await (0,
|
|
16501
|
+
await (0, import_promises2.pipeline)(
|
|
16519
16502
|
response.body,
|
|
16520
16503
|
(0, import_fs.createWriteStream)(target, { mode: 493 })
|
|
16521
16504
|
);
|
|
@@ -16540,7 +16523,7 @@ var import_util3 = require("util");
|
|
|
16540
16523
|
var execFileP4 = (0, import_util3.promisify)(import_child_process11.execFile);
|
|
16541
16524
|
|
|
16542
16525
|
// src/services/preview/config-file.ts
|
|
16543
|
-
var
|
|
16526
|
+
var import_promises3 = __toESM(require("fs/promises"));
|
|
16544
16527
|
var import_path5 = __toESM(require("path"));
|
|
16545
16528
|
var CONFIG_DIR = ".codeam";
|
|
16546
16529
|
var CONFIG_FILE = "preview.json";
|
|
@@ -16557,7 +16540,7 @@ var REQUIRED_FIELDS = [
|
|
|
16557
16540
|
async function readPreviewConfig(cwd) {
|
|
16558
16541
|
let raw;
|
|
16559
16542
|
try {
|
|
16560
|
-
raw = await
|
|
16543
|
+
raw = await import_promises3.default.readFile(configPath(cwd), "utf-8");
|
|
16561
16544
|
} catch {
|
|
16562
16545
|
return null;
|
|
16563
16546
|
}
|
|
@@ -16576,8 +16559,8 @@ async function readPreviewConfig(cwd) {
|
|
|
16576
16559
|
}
|
|
16577
16560
|
async function writePreviewConfig(cwd, detection) {
|
|
16578
16561
|
const filePath = configPath(cwd);
|
|
16579
|
-
await
|
|
16580
|
-
await
|
|
16562
|
+
await import_promises3.default.mkdir(import_path5.default.dirname(filePath), { recursive: true });
|
|
16563
|
+
await import_promises3.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
|
|
16581
16564
|
}
|
|
16582
16565
|
|
|
16583
16566
|
// src/services/preview/parser.ts
|
|
@@ -19147,33 +19130,26 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
19147
19130
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
19148
19131
|
);
|
|
19149
19132
|
let candidateUrl = null;
|
|
19133
|
+
let registered = false;
|
|
19150
19134
|
const onTunnelChunk = (chunk) => {
|
|
19151
19135
|
const s = chunk.toString();
|
|
19152
19136
|
if (!candidateUrl) candidateUrl = parseCloudflaredUrl(s);
|
|
19137
|
+
if (/Registered tunnel connection/i.test(s)) registered = true;
|
|
19153
19138
|
const trimmed = s.replace(/\n+$/g, "");
|
|
19154
19139
|
if (trimmed.length > 0) log.info("preview", `cloudflared: ${trimmed}`);
|
|
19155
19140
|
};
|
|
19156
19141
|
candidate.stderr.on("data", onTunnelChunk);
|
|
19157
19142
|
candidate.stdout.on("data", onTunnelChunk);
|
|
19158
|
-
const
|
|
19159
|
-
while (!candidateUrl && Date.now() <
|
|
19143
|
+
const deadline = Date.now() + 45e3;
|
|
19144
|
+
while ((!candidateUrl || !registered) && Date.now() < deadline) {
|
|
19160
19145
|
await new Promise((r) => setTimeout(r, 250));
|
|
19161
19146
|
}
|
|
19162
|
-
if (
|
|
19163
|
-
|
|
19164
|
-
try {
|
|
19165
|
-
candidate.kill("SIGTERM");
|
|
19166
|
-
} catch {
|
|
19167
|
-
}
|
|
19168
|
-
continue;
|
|
19169
|
-
}
|
|
19170
|
-
try {
|
|
19171
|
-
await waitForCloudflaredReady(candidateUrl, 4e4);
|
|
19172
|
-
log.info("preview", `cloudflared probe: ${candidateUrl} reachable from CLI host`);
|
|
19147
|
+
if (candidateUrl && registered) {
|
|
19148
|
+
log.info("preview", `cloudflared tunnel registered: ${candidateUrl}`);
|
|
19173
19149
|
tunnel = candidate;
|
|
19174
19150
|
parsedUrl = candidateUrl;
|
|
19175
|
-
}
|
|
19176
|
-
lastTunnelErr =
|
|
19151
|
+
} else {
|
|
19152
|
+
lastTunnelErr = candidateUrl ? "cloudflared did not register a tunnel connection within 45s" : "cloudflared did not emit a URL within 45s";
|
|
19177
19153
|
try {
|
|
19178
19154
|
candidate.kill("SIGTERM");
|
|
19179
19155
|
} catch {
|
|
@@ -27191,16 +27167,16 @@ function checkChokidar() {
|
|
|
27191
27167
|
}
|
|
27192
27168
|
async function doctor(args2 = []) {
|
|
27193
27169
|
const json = args2.includes("--json");
|
|
27194
|
-
const cliVersion = true ? "2.39.
|
|
27170
|
+
const cliVersion = true ? "2.39.39" : "0.0.0-dev";
|
|
27195
27171
|
const apiBase2 = resolveApiBaseUrl();
|
|
27196
27172
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27197
27173
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
27198
|
-
const [
|
|
27174
|
+
const [dns, health] = await Promise.all([
|
|
27199
27175
|
checkDns(apiBase2),
|
|
27200
27176
|
checkHealth(apiBase2)
|
|
27201
27177
|
]);
|
|
27202
27178
|
const checks = [
|
|
27203
|
-
|
|
27179
|
+
dns,
|
|
27204
27180
|
health,
|
|
27205
27181
|
checkConfigDir(),
|
|
27206
27182
|
checkSessions(),
|
|
@@ -27390,7 +27366,7 @@ async function completion(args2) {
|
|
|
27390
27366
|
// src/commands/version.ts
|
|
27391
27367
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27392
27368
|
function version2() {
|
|
27393
|
-
const v = true ? "2.39.
|
|
27369
|
+
const v = true ? "2.39.39" : "unknown";
|
|
27394
27370
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27395
27371
|
}
|
|
27396
27372
|
|
|
@@ -27676,7 +27652,7 @@ function checkForUpdates() {
|
|
|
27676
27652
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27677
27653
|
if (process.env.CI) return;
|
|
27678
27654
|
if (!process.stdout.isTTY) return;
|
|
27679
|
-
const current = true ? "2.39.
|
|
27655
|
+
const current = true ? "2.39.39" : null;
|
|
27680
27656
|
if (!current) return;
|
|
27681
27657
|
const cache = readCache();
|
|
27682
27658
|
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.39",
|
|
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",
|