codeam-cli 2.39.35 → 2.39.37
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 +16 -0
- package/dist/index.js +67 -107
- 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.36] — 2026-06-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Preview dev-server run command rewrites pnpm/bun → npm run
|
|
12
|
+
|
|
13
|
+
## [2.39.35] — 2026-06-18
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Preview pre-flight installs with npm --legacy-peer-deps (not pnpm)
|
|
18
|
+
|
|
19
|
+
### Tests
|
|
20
|
+
|
|
21
|
+
- **cli:** Integration regression for ACP reply-doubling (notification → mapper → runner)
|
|
22
|
+
|
|
7
23
|
## [2.39.34] — 2026-06-18
|
|
8
24
|
|
|
9
25
|
### 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.37",
|
|
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.37" : "0.0.0-dev",
|
|
5912
5912
|
nodeVersion: process.version,
|
|
5913
5913
|
platform: process.platform,
|
|
5914
5914
|
arch: process.arch,
|
|
@@ -16538,34 +16538,6 @@ function downloadUrlForPlatform() {
|
|
|
16538
16538
|
var import_child_process11 = require("child_process");
|
|
16539
16539
|
var import_util3 = require("util");
|
|
16540
16540
|
var execFileP4 = (0, import_util3.promisify)(import_child_process11.execFile);
|
|
16541
|
-
function isCodespaceSession(env = process.env) {
|
|
16542
|
-
return Boolean(env.CODESPACE_NAME);
|
|
16543
|
-
}
|
|
16544
|
-
function buildCodespaceUrl(codespaceName, port) {
|
|
16545
|
-
return `https://${codespaceName}-${port}.app.github.dev`;
|
|
16546
|
-
}
|
|
16547
|
-
async function setPortPublic(codespaceName, port) {
|
|
16548
|
-
await execFileP4("gh", [
|
|
16549
|
-
"codespace",
|
|
16550
|
-
"ports",
|
|
16551
|
-
"visibility",
|
|
16552
|
-
`${port}:public`,
|
|
16553
|
-
"-c",
|
|
16554
|
-
codespaceName
|
|
16555
|
-
]);
|
|
16556
|
-
}
|
|
16557
|
-
async function waitForCodespacePortReady(url, timeoutMs = 15e3) {
|
|
16558
|
-
const start2 = Date.now();
|
|
16559
|
-
while (Date.now() - start2 < timeoutMs) {
|
|
16560
|
-
try {
|
|
16561
|
-
const res = await fetch(url, { method: "HEAD" });
|
|
16562
|
-
if (res.status < 500) return;
|
|
16563
|
-
} catch {
|
|
16564
|
-
}
|
|
16565
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
16566
|
-
}
|
|
16567
|
-
throw new Error(`Codespace forwarded URL ${url} not reachable after ${timeoutMs}ms.`);
|
|
16568
|
-
}
|
|
16569
16541
|
|
|
16570
16542
|
// src/services/preview/config-file.ts
|
|
16571
16543
|
var import_promises4 = __toESM(require("fs/promises"));
|
|
@@ -18912,6 +18884,21 @@ async function waitForDevServerReady(devServer, readyRe, opts = {
|
|
|
18912
18884
|
return { kind: "timeout" };
|
|
18913
18885
|
}
|
|
18914
18886
|
function normalizeDetectionForSpawn(detection, cwd) {
|
|
18887
|
+
if (detection.command === "pnpm" || detection.command === "bun") {
|
|
18888
|
+
const raw = detection.args ?? [];
|
|
18889
|
+
const verb = raw[0];
|
|
18890
|
+
if (verb && !["exec", "dlx", "x"].includes(verb)) {
|
|
18891
|
+
const rest = verb === "run" ? raw.slice(1) : raw;
|
|
18892
|
+
const [script, ...extra] = rest;
|
|
18893
|
+
if (script && !script.startsWith("-")) {
|
|
18894
|
+
return {
|
|
18895
|
+
...detection,
|
|
18896
|
+
command: "npm",
|
|
18897
|
+
args: extra.length ? ["run", script, "--", ...extra] : ["run", script]
|
|
18898
|
+
};
|
|
18899
|
+
}
|
|
18900
|
+
}
|
|
18901
|
+
}
|
|
18915
18902
|
if (detection.command !== "npx") return detection;
|
|
18916
18903
|
const args2 = detection.args ?? [];
|
|
18917
18904
|
if (args2.length === 0) return detection;
|
|
@@ -19100,7 +19087,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
19100
19087
|
emitProgress("READY_DETECTED", `port ${detection.port}`);
|
|
19101
19088
|
emitProgress(
|
|
19102
19089
|
"TUNNEL_STARTING",
|
|
19103
|
-
detection.framework === "Expo" ? "Expo (self-tunnelled)" :
|
|
19090
|
+
detection.framework === "Expo" ? "Expo (self-tunnelled)" : "cloudflared quick tunnel"
|
|
19104
19091
|
);
|
|
19105
19092
|
let tunnel = null;
|
|
19106
19093
|
let url;
|
|
@@ -19126,41 +19113,6 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
19126
19113
|
return;
|
|
19127
19114
|
}
|
|
19128
19115
|
url = expoUrl;
|
|
19129
|
-
} else if (isCodespaceSession()) {
|
|
19130
|
-
const codespaceName = process.env.CODESPACE_NAME;
|
|
19131
|
-
try {
|
|
19132
|
-
await setPortPublic(codespaceName, detection.port);
|
|
19133
|
-
} catch (e) {
|
|
19134
|
-
try {
|
|
19135
|
-
devServer.kill("SIGTERM");
|
|
19136
|
-
} catch {
|
|
19137
|
-
}
|
|
19138
|
-
void postPreviewEvent({
|
|
19139
|
-
sessionId: ctx.sessionId,
|
|
19140
|
-
pluginId: ctx.pluginId,
|
|
19141
|
-
pluginAuthToken,
|
|
19142
|
-
type: "preview_error",
|
|
19143
|
-
payload: { stage: "tunnel", message: `Failed to flip port public: ${e.message}` }
|
|
19144
|
-
});
|
|
19145
|
-
return;
|
|
19146
|
-
}
|
|
19147
|
-
url = buildCodespaceUrl(codespaceName, detection.port);
|
|
19148
|
-
try {
|
|
19149
|
-
await waitForCodespacePortReady(url, 15e3);
|
|
19150
|
-
} catch (e) {
|
|
19151
|
-
try {
|
|
19152
|
-
devServer.kill("SIGTERM");
|
|
19153
|
-
} catch {
|
|
19154
|
-
}
|
|
19155
|
-
void postPreviewEvent({
|
|
19156
|
-
sessionId: ctx.sessionId,
|
|
19157
|
-
pluginId: ctx.pluginId,
|
|
19158
|
-
pluginAuthToken,
|
|
19159
|
-
type: "preview_error",
|
|
19160
|
-
payload: { stage: "tunnel", message: e.message }
|
|
19161
|
-
});
|
|
19162
|
-
return;
|
|
19163
|
-
}
|
|
19164
19116
|
} else {
|
|
19165
19117
|
let bin;
|
|
19166
19118
|
try {
|
|
@@ -19179,48 +19131,56 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
19179
19131
|
});
|
|
19180
19132
|
return;
|
|
19181
19133
|
}
|
|
19182
|
-
|
|
19183
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
19184
|
-
});
|
|
19134
|
+
const MAX_TUNNEL_ATTEMPTS = 3;
|
|
19185
19135
|
let parsedUrl = null;
|
|
19186
|
-
|
|
19187
|
-
|
|
19188
|
-
if (
|
|
19189
|
-
|
|
19190
|
-
|
|
19191
|
-
|
|
19192
|
-
|
|
19193
|
-
tunnel.stdout.on("data", onTunnelChunk);
|
|
19194
|
-
const tunnelDeadline = Date.now() + 45e3;
|
|
19195
|
-
while (!parsedUrl && Date.now() < tunnelDeadline) {
|
|
19196
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
19197
|
-
}
|
|
19198
|
-
if (!parsedUrl) {
|
|
19199
|
-
try {
|
|
19200
|
-
tunnel.kill("SIGTERM");
|
|
19201
|
-
} catch {
|
|
19136
|
+
let lastTunnelErr = "cloudflared did not emit a URL within 45s";
|
|
19137
|
+
for (let attempt = 1; attempt <= MAX_TUNNEL_ATTEMPTS && !parsedUrl; attempt += 1) {
|
|
19138
|
+
if (attempt > 1) {
|
|
19139
|
+
emitProgress(
|
|
19140
|
+
"TUNNEL_STARTING",
|
|
19141
|
+
`cloudflared quick tunnel (retry ${attempt}/${MAX_TUNNEL_ATTEMPTS})`
|
|
19142
|
+
);
|
|
19202
19143
|
}
|
|
19203
|
-
|
|
19204
|
-
|
|
19205
|
-
|
|
19144
|
+
const candidate = (0, import_child_process18.spawn)(
|
|
19145
|
+
bin,
|
|
19146
|
+
["tunnel", "--url", `http://localhost:${detection.port}`],
|
|
19147
|
+
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
19148
|
+
);
|
|
19149
|
+
let candidateUrl = null;
|
|
19150
|
+
const onTunnelChunk = (chunk) => {
|
|
19151
|
+
const s = chunk.toString();
|
|
19152
|
+
if (!candidateUrl) candidateUrl = parseCloudflaredUrl(s);
|
|
19153
|
+
const trimmed = s.replace(/\n+$/g, "");
|
|
19154
|
+
if (trimmed.length > 0) log.info("preview", `cloudflared: ${trimmed}`);
|
|
19155
|
+
};
|
|
19156
|
+
candidate.stderr.on("data", onTunnelChunk);
|
|
19157
|
+
candidate.stdout.on("data", onTunnelChunk);
|
|
19158
|
+
const urlDeadline = Date.now() + 45e3;
|
|
19159
|
+
while (!candidateUrl && Date.now() < urlDeadline) {
|
|
19160
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
19161
|
+
}
|
|
19162
|
+
if (!candidateUrl) {
|
|
19163
|
+
lastTunnelErr = "cloudflared did not emit a URL within 45s";
|
|
19164
|
+
try {
|
|
19165
|
+
candidate.kill("SIGTERM");
|
|
19166
|
+
} catch {
|
|
19167
|
+
}
|
|
19168
|
+
continue;
|
|
19206
19169
|
}
|
|
19207
|
-
void postPreviewEvent({
|
|
19208
|
-
sessionId: ctx.sessionId,
|
|
19209
|
-
pluginId: ctx.pluginId,
|
|
19210
|
-
pluginAuthToken,
|
|
19211
|
-
type: "preview_error",
|
|
19212
|
-
payload: { stage: "tunnel", message: "cloudflared did not emit a URL within 45s." }
|
|
19213
|
-
});
|
|
19214
|
-
return;
|
|
19215
|
-
}
|
|
19216
|
-
try {
|
|
19217
|
-
await waitForCloudflaredReady(parsedUrl, 6e4);
|
|
19218
|
-
log.info("preview", `cloudflared probe: ${parsedUrl} reachable from CLI host`);
|
|
19219
|
-
} catch (e) {
|
|
19220
19170
|
try {
|
|
19221
|
-
|
|
19222
|
-
|
|
19171
|
+
await waitForCloudflaredReady(candidateUrl, 4e4);
|
|
19172
|
+
log.info("preview", `cloudflared probe: ${candidateUrl} reachable from CLI host`);
|
|
19173
|
+
tunnel = candidate;
|
|
19174
|
+
parsedUrl = candidateUrl;
|
|
19175
|
+
} catch (e) {
|
|
19176
|
+
lastTunnelErr = e.message;
|
|
19177
|
+
try {
|
|
19178
|
+
candidate.kill("SIGTERM");
|
|
19179
|
+
} catch {
|
|
19180
|
+
}
|
|
19223
19181
|
}
|
|
19182
|
+
}
|
|
19183
|
+
if (!parsedUrl) {
|
|
19224
19184
|
try {
|
|
19225
19185
|
devServer.kill("SIGTERM");
|
|
19226
19186
|
} catch {
|
|
@@ -19232,7 +19192,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
19232
19192
|
type: "preview_error",
|
|
19233
19193
|
payload: {
|
|
19234
19194
|
stage: "tunnel",
|
|
19235
|
-
message: `Tunnel
|
|
19195
|
+
message: `Tunnel did not become reachable after ${MAX_TUNNEL_ATTEMPTS} attempts (${lastTunnelErr}). Cloudflare Quick Tunnels occasionally fail to register \u2014 please retry.`
|
|
19236
19196
|
}
|
|
19237
19197
|
});
|
|
19238
19198
|
return;
|
|
@@ -27172,7 +27132,7 @@ function checkChokidar() {
|
|
|
27172
27132
|
}
|
|
27173
27133
|
async function doctor(args2 = []) {
|
|
27174
27134
|
const json = args2.includes("--json");
|
|
27175
|
-
const cliVersion = true ? "2.39.
|
|
27135
|
+
const cliVersion = true ? "2.39.37" : "0.0.0-dev";
|
|
27176
27136
|
const apiBase2 = resolveApiBaseUrl();
|
|
27177
27137
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27178
27138
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27371,7 +27331,7 @@ async function completion(args2) {
|
|
|
27371
27331
|
// src/commands/version.ts
|
|
27372
27332
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27373
27333
|
function version2() {
|
|
27374
|
-
const v = true ? "2.39.
|
|
27334
|
+
const v = true ? "2.39.37" : "unknown";
|
|
27375
27335
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27376
27336
|
}
|
|
27377
27337
|
|
|
@@ -27657,7 +27617,7 @@ function checkForUpdates() {
|
|
|
27657
27617
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27658
27618
|
if (process.env.CI) return;
|
|
27659
27619
|
if (!process.stdout.isTTY) return;
|
|
27660
|
-
const current = true ? "2.39.
|
|
27620
|
+
const current = true ? "2.39.37" : null;
|
|
27661
27621
|
if (!current) return;
|
|
27662
27622
|
const cache = readCache();
|
|
27663
27623
|
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.37",
|
|
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",
|