codeam-cli 2.76.31 → 2.76.33
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 +19 -0
- package/dist/index.js +102 -38
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ 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.32] — 2026-10-14
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Don't resume a session that was deleted from the app while the host slept (codeagent-xwoy)
|
|
12
|
+
|
|
13
|
+
## [2.76.31] — 2026-10-14
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Cap the chat-pipe text frame and never loop on a 413
|
|
18
|
+
- **cli:** Make a python static-site preview ready instead of timing out
|
|
19
|
+
- **cli:** Let codex one-shots run outside a git repo
|
|
20
|
+
- **cli:** A failed agent preview hands the agent the dev server's output
|
|
21
|
+
|
|
22
|
+
### Tests
|
|
23
|
+
|
|
24
|
+
- **cli:** Skip the POSIX-only preview subdir spawn test on Windows
|
|
25
|
+
|
|
7
26
|
## [2.76.30] — 2026-10-14
|
|
8
27
|
|
|
9
28
|
### CI
|
package/dist/index.js
CHANGED
|
@@ -3428,14 +3428,23 @@ Rules:
|
|
|
3428
3428
|
otherwise "python3".
|
|
3429
3429
|
- Prefer binding to 0.0.0.0 \u2014 most frameworks default to localhost which the tunnel cannot reach.
|
|
3430
3430
|
- For Expo: framework="Expo", command="npx", args=["expo","start","--tunnel"], port=8081, notes="Scan QR with Expo Go".
|
|
3431
|
+
- For PHP (composer.json / index.php): use PHP's built-in server bound to 0.0.0.0 with the
|
|
3432
|
+
web root as docroot \u2014 command="php", args=["-S","0.0.0.0:8080","-t","public"] (Yii3,
|
|
3433
|
+
Symfony, Slim, Mezzio; use the real docroot, e.g. "web" for Yii2, "." for plain PHP),
|
|
3434
|
+
port=8080, ready_pattern="Development Server". Laravel: command="php",
|
|
3435
|
+
args=["artisan","serve","--host=0.0.0.0","--port=8000"], port=8000,
|
|
3436
|
+
ready_pattern="Server running". Do NOT use "composer serve", "symfony serve" or a
|
|
3437
|
+
"./yii serve" wrapper \u2014 call php directly.
|
|
3431
3438
|
- If no dev server applies (CLI library, lambda, batch script): {"framework":"unsupported","notes":"<reason>"}.
|
|
3432
3439
|
|
|
3433
3440
|
CRITICAL \u2014 setup_commands:
|
|
3434
3441
|
- DO NOT include an install command (npm install, pnpm install, yarn install,
|
|
3435
|
-
yarn, bun install) in setup_commands.
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3442
|
+
yarn, bun install, composer install) in setup_commands. Pre-flight installers
|
|
3443
|
+
run BEFORE setup_commands: composer install whenever composer.json exists and
|
|
3444
|
+
vendor/ is missing, and a lockfile-aware Node installer that picks the
|
|
3445
|
+
correct package manager from the lockfile present (pnpm-lock.yaml -> pnpm,
|
|
3446
|
+
yarn.lock -> yarn, bun.lockb -> bun, else npm). Emitting an install here
|
|
3447
|
+
either duplicates that work or, worse,
|
|
3439
3448
|
uses the WRONG package manager on top of node_modules just populated by the
|
|
3440
3449
|
pre-flight, which crashes (e.g. npm errors with "Cannot read properties of
|
|
3441
3450
|
null (reading 'matches')" when run over pnpm's .pnpm/ layout).
|
|
@@ -10627,7 +10636,7 @@ function readAnonId() {
|
|
|
10627
10636
|
}
|
|
10628
10637
|
function superProperties() {
|
|
10629
10638
|
return {
|
|
10630
|
-
cliVersion: true ? "2.76.
|
|
10639
|
+
cliVersion: true ? "2.76.33" : "0.0.0-dev",
|
|
10631
10640
|
nodeVersion: process.version,
|
|
10632
10641
|
platform: process.platform,
|
|
10633
10642
|
arch: process.arch,
|
|
@@ -10876,7 +10885,7 @@ var http = __toESM(require("http"));
|
|
|
10876
10885
|
// package.json
|
|
10877
10886
|
var package_default = {
|
|
10878
10887
|
name: "codeam-cli",
|
|
10879
|
-
version: "2.76.
|
|
10888
|
+
version: "2.76.33",
|
|
10880
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.",
|
|
10881
10890
|
type: "commonjs",
|
|
10882
10891
|
main: "dist/index.js",
|
|
@@ -11038,7 +11047,7 @@ async function requestCode(pluginId, pluginSecretHash) {
|
|
|
11038
11047
|
return { ok: false, reason: "network" };
|
|
11039
11048
|
}
|
|
11040
11049
|
}
|
|
11041
|
-
async function fetchCurrentPluginAuthToken(sessionId, pluginId, pollSecret, onUserId) {
|
|
11050
|
+
async function fetchCurrentPluginAuthToken(sessionId, pluginId, pollSecret, onUserId, onSessionGone) {
|
|
11042
11051
|
try {
|
|
11043
11052
|
const result = await _transport.postJson(
|
|
11044
11053
|
`${API_BASE}/api/pairing/reconnect`,
|
|
@@ -11070,10 +11079,21 @@ async function fetchCurrentPluginAuthToken(sessionId, pluginId, pollSecret, onUs
|
|
|
11070
11079
|
}
|
|
11071
11080
|
const token = data.pluginAuthToken;
|
|
11072
11081
|
return typeof token === "string" && token.length > 0 ? token : null;
|
|
11073
|
-
} catch {
|
|
11082
|
+
} catch (err) {
|
|
11083
|
+
if (onSessionGone && isSessionNotFound(err)) onSessionGone();
|
|
11074
11084
|
return null;
|
|
11075
11085
|
}
|
|
11076
11086
|
}
|
|
11087
|
+
function isSessionNotFound(err) {
|
|
11088
|
+
const e = err;
|
|
11089
|
+
if (!e || e.statusCode !== 404 || typeof e.body !== "string") return false;
|
|
11090
|
+
try {
|
|
11091
|
+
const parsed = JSON.parse(e.body);
|
|
11092
|
+
return parsed?.code === "SESSION_NOT_FOUND" || parsed?.error?.code === "SESSION_NOT_FOUND";
|
|
11093
|
+
} catch {
|
|
11094
|
+
return false;
|
|
11095
|
+
}
|
|
11096
|
+
}
|
|
11077
11097
|
var _transport = {
|
|
11078
11098
|
postJson: _postJson,
|
|
11079
11099
|
getJson: _getJson,
|
|
@@ -12241,7 +12261,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12241
12261
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12242
12262
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12243
12263
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12244
|
-
..."2.76.
|
|
12264
|
+
..."2.76.33" ? { ideVersion: "2.76.33" } : {}
|
|
12245
12265
|
};
|
|
12246
12266
|
try {
|
|
12247
12267
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -24646,6 +24666,24 @@ function isJsInstallCommand(cmd, args2) {
|
|
|
24646
24666
|
const verb = args2[0];
|
|
24647
24667
|
return verb === "install" || verb === "i" || verb === "ci";
|
|
24648
24668
|
}
|
|
24669
|
+
function detectMissingPhpDeps(cwd) {
|
|
24670
|
+
if (!import_fs5.default.existsSync(import_path8.default.join(cwd, "composer.json"))) return null;
|
|
24671
|
+
if (import_fs5.default.existsSync(import_path8.default.join(cwd, "vendor"))) return null;
|
|
24672
|
+
return {
|
|
24673
|
+
cmd: "composer",
|
|
24674
|
+
args: [
|
|
24675
|
+
"install",
|
|
24676
|
+
"--no-interaction",
|
|
24677
|
+
"--no-progress",
|
|
24678
|
+
"--prefer-dist",
|
|
24679
|
+
"--ignore-platform-req=ext-*"
|
|
24680
|
+
]
|
|
24681
|
+
};
|
|
24682
|
+
}
|
|
24683
|
+
function isComposerInstallCommand(cmd, args2) {
|
|
24684
|
+
if (cmd !== "composer") return false;
|
|
24685
|
+
return args2[0] === "install" || args2[0] === "i";
|
|
24686
|
+
}
|
|
24649
24687
|
|
|
24650
24688
|
// src/services/preview/script-candidates.ts
|
|
24651
24689
|
var fs47 = __toESM(require("fs"));
|
|
@@ -27108,6 +27146,29 @@ function announceReady(ctx, dev, tun) {
|
|
|
27108
27146
|
port: detection.port
|
|
27109
27147
|
});
|
|
27110
27148
|
}
|
|
27149
|
+
async function runPreflightInstall(ctx, install, why) {
|
|
27150
|
+
const { detection, cwd, emit: emit2, emitProgress } = ctx;
|
|
27151
|
+
const label = `${install.cmd} ${install.args.join(" ")}`;
|
|
27152
|
+
emitProgress("SETUP_RUN", `${label} (pre-flight \u2014 ${why})`);
|
|
27153
|
+
const result = await runSetupCommand(install.cmd, install.args, cwd, detection.env, {
|
|
27154
|
+
timeoutMs: INSTALL_TIMEOUT_MS2
|
|
27155
|
+
});
|
|
27156
|
+
if (result.status === "timeout") {
|
|
27157
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27158
|
+
stage: "ready_timeout",
|
|
27159
|
+
message: `Dependency install (${label}) didn't finish within ${Math.round(INSTALL_TIMEOUT_MS2 / 1e3)}s and was stopped. Run it manually in this project, then try the preview again.`
|
|
27160
|
+
});
|
|
27161
|
+
return false;
|
|
27162
|
+
}
|
|
27163
|
+
if (result.status === "failed") {
|
|
27164
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27165
|
+
stage: "spawn",
|
|
27166
|
+
message: `Dependency install failed (${label}, exit ${result.code}). Run it manually in this project and try again.`
|
|
27167
|
+
});
|
|
27168
|
+
return false;
|
|
27169
|
+
}
|
|
27170
|
+
return true;
|
|
27171
|
+
}
|
|
27111
27172
|
async function provisionDeps(ctx) {
|
|
27112
27173
|
const { detection, cwd, emit: emit2, emitProgress } = ctx;
|
|
27113
27174
|
if (ctx.projectEnvAuth?.pluginAuthToken) {
|
|
@@ -27144,32 +27205,21 @@ async function provisionDeps(ctx) {
|
|
|
27144
27205
|
return false;
|
|
27145
27206
|
}
|
|
27146
27207
|
}
|
|
27147
|
-
|
|
27148
|
-
|
|
27149
|
-
|
|
27150
|
-
|
|
27151
|
-
|
|
27152
|
-
|
|
27153
|
-
|
|
27154
|
-
cwd,
|
|
27155
|
-
detection.env,
|
|
27156
|
-
{ timeoutMs: INSTALL_TIMEOUT_MS2 }
|
|
27157
|
-
);
|
|
27158
|
-
if (result.status === "timeout") {
|
|
27159
|
-
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27160
|
-
stage: "ready_timeout",
|
|
27161
|
-
message: `Dependency install (${missingDeps.cmd} ${missingDeps.args.join(" ")}) didn't finish within ${Math.round(INSTALL_TIMEOUT_MS2 / 1e3)}s and was stopped. Run it manually in this project, then try the preview again.`
|
|
27162
|
-
});
|
|
27163
|
-
return false;
|
|
27164
|
-
}
|
|
27165
|
-
if (result.status === "failed") {
|
|
27208
|
+
if (!await runPreflightInstall(ctx, missingDeps, "node_modules missing")) return false;
|
|
27209
|
+
preflightRan = true;
|
|
27210
|
+
}
|
|
27211
|
+
const missingPhpDeps = detectMissingPhpDeps(cwd);
|
|
27212
|
+
let composerPreflightRan = false;
|
|
27213
|
+
if (missingPhpDeps) {
|
|
27214
|
+
if (!await (0, import_which3.default)("composer", { nothrow: true })) {
|
|
27166
27215
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27167
27216
|
stage: "spawn",
|
|
27168
|
-
message:
|
|
27217
|
+
message: "This is a PHP project (composer.json) but Composer isn't installed in this environment, so its dependencies (vendor/) can't be installed. Install PHP and Composer, then try the preview again."
|
|
27169
27218
|
});
|
|
27170
27219
|
return false;
|
|
27171
27220
|
}
|
|
27172
|
-
|
|
27221
|
+
if (!await runPreflightInstall(ctx, missingPhpDeps, "vendor/ missing")) return false;
|
|
27222
|
+
composerPreflightRan = true;
|
|
27173
27223
|
}
|
|
27174
27224
|
const normalizedSetup = (detection.setup_commands ?? []).map((entry) => {
|
|
27175
27225
|
if (typeof entry === "string") {
|
|
@@ -27182,10 +27232,12 @@ async function provisionDeps(ctx) {
|
|
|
27182
27232
|
args: Array.isArray(o.args) ? o.args.filter((a) => typeof a === "string") : []
|
|
27183
27233
|
};
|
|
27184
27234
|
}).filter((s) => s.cmd.length > 0);
|
|
27185
|
-
const agentSetupCommands =
|
|
27235
|
+
const agentSetupCommands = normalizedSetup.filter(
|
|
27236
|
+
(s) => !(preflightRan && isJsInstallCommand(s.cmd, s.args)) && !(composerPreflightRan && isComposerInstallCommand(s.cmd, s.args))
|
|
27237
|
+
);
|
|
27186
27238
|
for (const setup of agentSetupCommands) {
|
|
27187
27239
|
emitProgress("SETUP_RUN", `${setup.cmd} ${setup.args.join(" ")}`);
|
|
27188
|
-
const timeoutMs = isJsInstallCommand(setup.cmd, setup.args) ? INSTALL_TIMEOUT_MS2 : SETUP_TIMEOUT_MS;
|
|
27240
|
+
const timeoutMs = isJsInstallCommand(setup.cmd, setup.args) || isComposerInstallCommand(setup.cmd, setup.args) ? INSTALL_TIMEOUT_MS2 : SETUP_TIMEOUT_MS;
|
|
27189
27241
|
const result = await runSetupCommand(setup.cmd, setup.args, cwd, detection.env, {
|
|
27190
27242
|
timeoutMs
|
|
27191
27243
|
});
|
|
@@ -47853,6 +47905,7 @@ async function start(requestedAgent, presetSession) {
|
|
|
47853
47905
|
const cwd = process.cwd();
|
|
47854
47906
|
let reconnectUserId;
|
|
47855
47907
|
let reconnectPlan;
|
|
47908
|
+
let sessionGone = false;
|
|
47856
47909
|
const refreshed = await fetchCurrentPluginAuthToken(
|
|
47857
47910
|
session.id,
|
|
47858
47911
|
pluginId,
|
|
@@ -47860,8 +47913,19 @@ async function start(requestedAgent, presetSession) {
|
|
|
47860
47913
|
(userId, plan) => {
|
|
47861
47914
|
reconnectUserId = userId;
|
|
47862
47915
|
reconnectPlan = plan;
|
|
47916
|
+
},
|
|
47917
|
+
() => {
|
|
47918
|
+
sessionGone = true;
|
|
47863
47919
|
}
|
|
47864
47920
|
);
|
|
47921
|
+
if (sessionGone) {
|
|
47922
|
+
showInfo("This session was deleted from the app \u2014 not resuming it.");
|
|
47923
|
+
try {
|
|
47924
|
+
removeSession(session.id);
|
|
47925
|
+
} catch {
|
|
47926
|
+
}
|
|
47927
|
+
process.exit(0);
|
|
47928
|
+
}
|
|
47865
47929
|
if (refreshed && refreshed !== session.pluginAuthToken) {
|
|
47866
47930
|
addSession({ ...session, pluginAuthToken: refreshed });
|
|
47867
47931
|
session.pluginAuthToken = refreshed;
|
|
@@ -51478,7 +51542,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51478
51542
|
if (process.env.NODE_ENV === "test") return;
|
|
51479
51543
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51480
51544
|
if (process.env.CI) return;
|
|
51481
|
-
const current2 = true ? "2.76.
|
|
51545
|
+
const current2 = true ? "2.76.33" : null;
|
|
51482
51546
|
if (!current2) return;
|
|
51483
51547
|
const cache = readCache();
|
|
51484
51548
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51495,7 +51559,7 @@ function checkForUpdates() {
|
|
|
51495
51559
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51496
51560
|
if (process.env.CI) return;
|
|
51497
51561
|
if (!process.stdout.isTTY) return;
|
|
51498
|
-
const current2 = true ? "2.76.
|
|
51562
|
+
const current2 = true ? "2.76.33" : null;
|
|
51499
51563
|
if (!current2) return;
|
|
51500
51564
|
const cache = readCache();
|
|
51501
51565
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51778,7 +51842,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51778
51842
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51779
51843
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51780
51844
|
function currentCliVersion() {
|
|
51781
|
-
return true ? "2.76.
|
|
51845
|
+
return true ? "2.76.33" : null;
|
|
51782
51846
|
}
|
|
51783
51847
|
async function installedVersion(deps) {
|
|
51784
51848
|
const ls = await deps.run(
|
|
@@ -51989,7 +52053,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
51989
52053
|
}
|
|
51990
52054
|
function defaultDeps() {
|
|
51991
52055
|
return {
|
|
51992
|
-
ownVersion: true ? "2.76.
|
|
52056
|
+
ownVersion: true ? "2.76.33" : null,
|
|
51993
52057
|
root: cliVersionsRoot(),
|
|
51994
52058
|
args: process.argv.slice(3),
|
|
51995
52059
|
execPath: process.execPath,
|
|
@@ -54527,7 +54591,7 @@ function checkChokidar() {
|
|
|
54527
54591
|
}
|
|
54528
54592
|
async function doctor(args2 = []) {
|
|
54529
54593
|
const json = args2.includes("--json");
|
|
54530
|
-
const cliVersion = true ? "2.76.
|
|
54594
|
+
const cliVersion = true ? "2.76.33" : "0.0.0-dev";
|
|
54531
54595
|
const apiBase2 = resolveApiBaseUrl();
|
|
54532
54596
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54533
54597
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -55063,7 +55127,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
55063
55127
|
// src/commands/version.ts
|
|
55064
55128
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
55065
55129
|
function version2() {
|
|
55066
|
-
const v = true ? "2.76.
|
|
55130
|
+
const v = true ? "2.76.33" : "unknown";
|
|
55067
55131
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
55068
55132
|
}
|
|
55069
55133
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.76.
|
|
3
|
+
"version": "2.76.33",
|
|
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",
|