codeam-cli 2.26.13 → 2.26.15
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 +92 -9
- package/package.json +2 -2
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.26.14] — 2026-06-04
|
|
8
|
+
|
|
9
|
+
### Chore
|
|
10
|
+
|
|
11
|
+
- **deps:** Bump actions/setup-node from 4 to 6 (#246)
|
|
12
|
+
- **deps:** Bump actions/checkout from 4 to 6 (#247)
|
|
13
|
+
- **deps:** Bump org.jetbrains.kotlin.jvm in /apps/jetbrains-plugin (#248)
|
|
14
|
+
- **cli:** Bump which 2.0.2 → 5.0.0 (#251)
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **cli:** Drop redundant install from agent setup_commands + warn agent (#256)
|
|
19
|
+
|
|
20
|
+
## [2.26.13] — 2026-06-04
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **cli:** Pre-flight install for missing node_modules before preview (#250)
|
|
25
|
+
|
|
7
26
|
## [2.26.12] — 2026-06-04
|
|
8
27
|
|
|
9
28
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -344,7 +344,7 @@ Return ONLY a JSON object on stdout (no prose, no markdown fences):
|
|
|
344
344
|
"port": <number>,
|
|
345
345
|
"ready_pattern": "<regex matching the server-ready stdout line>",
|
|
346
346
|
"env": { "HOST": "0.0.0.0" },
|
|
347
|
-
"setup_commands": [
|
|
347
|
+
"setup_commands": [],
|
|
348
348
|
"notes": "<one-line caveat or null>"
|
|
349
349
|
}
|
|
350
350
|
|
|
@@ -354,6 +354,20 @@ Rules:
|
|
|
354
354
|
- For Expo: framework="Expo", command="npx", args=["expo","start","--tunnel"], port=8081, notes="Scan QR with Expo Go".
|
|
355
355
|
- If no dev server applies (CLI library, lambda, batch script): {"framework":"unsupported","notes":"<reason>"}.
|
|
356
356
|
|
|
357
|
+
CRITICAL \u2014 setup_commands:
|
|
358
|
+
- DO NOT include an install command (npm install, pnpm install, yarn install,
|
|
359
|
+
yarn, bun install) in setup_commands. A lockfile-aware pre-flight installer
|
|
360
|
+
runs BEFORE setup_commands and picks the correct package manager from the
|
|
361
|
+
lockfile present (pnpm-lock.yaml -> pnpm, yarn.lock -> yarn, bun.lockb -> bun,
|
|
362
|
+
else npm). Emitting an install here either duplicates that work or, worse,
|
|
363
|
+
uses the WRONG package manager on top of node_modules just populated by the
|
|
364
|
+
pre-flight, which crashes (e.g. npm errors with "Cannot read properties of
|
|
365
|
+
null (reading 'matches')" when run over pnpm's .pnpm/ layout).
|
|
366
|
+
- ONLY include setup_commands for genuinely non-install work the project needs
|
|
367
|
+
before its dev server can boot: prisma generate, codegen, prebuild scripts,
|
|
368
|
+
database migrations against a local SQLite, etc.
|
|
369
|
+
- For most projects, setup_commands should be an empty array [].
|
|
370
|
+
|
|
357
371
|
OUTPUT JSON ONLY. NO MARKDOWN. NO COMMENTARY.
|
|
358
372
|
`.trim();
|
|
359
373
|
|
|
@@ -472,7 +486,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
472
486
|
// package.json
|
|
473
487
|
var package_default = {
|
|
474
488
|
name: "codeam-cli",
|
|
475
|
-
version: "2.26.
|
|
489
|
+
version: "2.26.15",
|
|
476
490
|
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.",
|
|
477
491
|
type: "commonjs",
|
|
478
492
|
main: "dist/index.js",
|
|
@@ -546,7 +560,7 @@ var package_default = {
|
|
|
546
560
|
chokidar: "^3.6.0",
|
|
547
561
|
picocolors: "^1.1.0",
|
|
548
562
|
"qrcode-terminal": "^0.12.0",
|
|
549
|
-
which: "^
|
|
563
|
+
which: "^5.0.0",
|
|
550
564
|
ws: "^8.18.0",
|
|
551
565
|
zod: "^4.3.6"
|
|
552
566
|
},
|
|
@@ -5829,7 +5843,7 @@ function readAnonId() {
|
|
|
5829
5843
|
}
|
|
5830
5844
|
function superProperties() {
|
|
5831
5845
|
return {
|
|
5832
|
-
cliVersion: true ? "2.26.
|
|
5846
|
+
cliVersion: true ? "2.26.15" : "0.0.0-dev",
|
|
5833
5847
|
nodeVersion: process.version,
|
|
5834
5848
|
platform: process.platform,
|
|
5835
5849
|
arch: process.arch,
|
|
@@ -10874,6 +10888,40 @@ async function extractLocalCodexToken() {
|
|
|
10874
10888
|
function codexCredentialsPaths() {
|
|
10875
10889
|
return [codexCredentialsPath()];
|
|
10876
10890
|
}
|
|
10891
|
+
function validateLocalCodexToken(credential) {
|
|
10892
|
+
let parsed;
|
|
10893
|
+
try {
|
|
10894
|
+
parsed = JSON.parse(credential);
|
|
10895
|
+
} catch {
|
|
10896
|
+
return { status: "unknown" };
|
|
10897
|
+
}
|
|
10898
|
+
const directExp = typeof parsed.expires_at === "number" ? parsed.expires_at : typeof parsed.tokens?.expires_at === "number" ? parsed.tokens.expires_at : void 0;
|
|
10899
|
+
const jwtExp = decodeJwtExp(parsed.tokens?.id_token);
|
|
10900
|
+
const exp = directExp ?? jwtExp;
|
|
10901
|
+
if (exp === void 0) return { status: "unknown" };
|
|
10902
|
+
const expiresAt = exp < 1e12 ? exp * 1e3 : exp;
|
|
10903
|
+
if (Date.now() >= expiresAt) {
|
|
10904
|
+
return {
|
|
10905
|
+
status: "expired",
|
|
10906
|
+
reason: "Codex OAuth access token expired",
|
|
10907
|
+
expiresAt
|
|
10908
|
+
};
|
|
10909
|
+
}
|
|
10910
|
+
return { status: "valid", expiresAt };
|
|
10911
|
+
}
|
|
10912
|
+
function decodeJwtExp(jwt) {
|
|
10913
|
+
if (!jwt) return void 0;
|
|
10914
|
+
const parts = jwt.split(".");
|
|
10915
|
+
if (parts.length !== 3) return void 0;
|
|
10916
|
+
try {
|
|
10917
|
+
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
10918
|
+
const padded = base64 + "===".slice((base64.length + 3) % 4);
|
|
10919
|
+
const payload = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
|
|
10920
|
+
return typeof payload.exp === "number" ? payload.exp : void 0;
|
|
10921
|
+
} catch {
|
|
10922
|
+
return void 0;
|
|
10923
|
+
}
|
|
10924
|
+
}
|
|
10877
10925
|
|
|
10878
10926
|
// src/agents/codex/link.ts
|
|
10879
10927
|
function codexCredentialLocator() {
|
|
@@ -10882,7 +10930,11 @@ function codexCredentialLocator() {
|
|
|
10882
10930
|
vendor: "OpenAI",
|
|
10883
10931
|
hint: "~/.codex/auth.json",
|
|
10884
10932
|
watchPaths: codexCredentialsPaths,
|
|
10885
|
-
extract: extractLocalCodexToken
|
|
10933
|
+
extract: extractLocalCodexToken,
|
|
10934
|
+
validate: (token) => {
|
|
10935
|
+
const result = validateLocalCodexToken(token.credential);
|
|
10936
|
+
return { status: result.status, reason: result.reason };
|
|
10937
|
+
}
|
|
10886
10938
|
};
|
|
10887
10939
|
}
|
|
10888
10940
|
function codexLoginLauncher() {
|
|
@@ -15893,6 +15945,7 @@ async function link(args2 = []) {
|
|
|
15893
15945
|
installSpin.stop(`${ctx.displayName} is installed`);
|
|
15894
15946
|
const existing = await ctx.locator.extract();
|
|
15895
15947
|
if (existing) {
|
|
15948
|
+
if (refuseIfStale(ctx, existing)) return;
|
|
15896
15949
|
showInfo(`Found existing ${ctx.displayName} credentials at ${import_picocolors2.default.bold(existing.source)}.`);
|
|
15897
15950
|
await uploadAndSucceed(ctx, paired, pluginId, existing);
|
|
15898
15951
|
return;
|
|
@@ -15909,8 +15962,26 @@ async function link(args2 = []) {
|
|
|
15909
15962
|
console.log("");
|
|
15910
15963
|
const captured = await captureFreshCredentials(ctx);
|
|
15911
15964
|
console.log("");
|
|
15965
|
+
if (refuseIfStale(ctx, captured)) return;
|
|
15912
15966
|
await uploadAndSucceed(ctx, paired, pluginId, captured);
|
|
15913
15967
|
}
|
|
15968
|
+
function refuseIfStale(ctx, token) {
|
|
15969
|
+
const verdict = ctx.locator.validate?.(token);
|
|
15970
|
+
if (!verdict || verdict.status !== "expired") return false;
|
|
15971
|
+
const reason = verdict.reason ?? "Token expired";
|
|
15972
|
+
showError(
|
|
15973
|
+
`Your local ${ctx.displayName} credentials at ${import_picocolors2.default.bold(ctx.locator.hint)} are already expired:
|
|
15974
|
+
${reason}
|
|
15975
|
+
|
|
15976
|
+
Uploading them would land a dead snapshot in the vault \u2014 every codespace bootstrapped from it would immediately return 401.
|
|
15977
|
+
|
|
15978
|
+
Run on your machine, then re-link:
|
|
15979
|
+
${import_picocolors2.default.cyan(`${ctx.binary} logout`)}
|
|
15980
|
+
${import_picocolors2.default.cyan(`${ctx.binary} login`)}
|
|
15981
|
+
${import_picocolors2.default.cyan(`codeam link ${ctx.locator.publicId}`)}`
|
|
15982
|
+
);
|
|
15983
|
+
process.exit(1);
|
|
15984
|
+
}
|
|
15914
15985
|
async function captureFreshCredentials(ctx) {
|
|
15915
15986
|
const isWin = ctx.runtime.os.id === "win32";
|
|
15916
15987
|
const watcher = import_chokidar.default.watch(ctx.locator.watchPaths(), {
|
|
@@ -16298,6 +16369,13 @@ function detectMissingNodeDeps(cwd) {
|
|
|
16298
16369
|
}
|
|
16299
16370
|
return { cmd: "npm", args: ["install"] };
|
|
16300
16371
|
}
|
|
16372
|
+
function isJsInstallCommand(cmd, args2) {
|
|
16373
|
+
const known = ["npm", "pnpm", "yarn", "bun"];
|
|
16374
|
+
if (!known.includes(cmd)) return false;
|
|
16375
|
+
if (cmd === "yarn" && args2.length === 0) return true;
|
|
16376
|
+
const verb = args2[0];
|
|
16377
|
+
return verb === "install" || verb === "i" || verb === "ci";
|
|
16378
|
+
}
|
|
16301
16379
|
|
|
16302
16380
|
// src/services/preview/index.ts
|
|
16303
16381
|
var activePreviews = /* @__PURE__ */ new Map();
|
|
@@ -16940,6 +17018,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
16940
17018
|
});
|
|
16941
17019
|
emitProgress("ENV_DETECTED", `${detection.framework}`);
|
|
16942
17020
|
const missingDeps = detectMissingNodeDeps(process.cwd());
|
|
17021
|
+
let preflightRan = false;
|
|
16943
17022
|
if (missingDeps) {
|
|
16944
17023
|
emitProgress(
|
|
16945
17024
|
"SETUP_RUN",
|
|
@@ -16964,8 +17043,12 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
16964
17043
|
});
|
|
16965
17044
|
return;
|
|
16966
17045
|
}
|
|
17046
|
+
preflightRan = true;
|
|
16967
17047
|
}
|
|
16968
|
-
|
|
17048
|
+
const agentSetupCommands = preflightRan ? (detection.setup_commands ?? []).filter(
|
|
17049
|
+
(s) => !isJsInstallCommand(s.cmd, s.args)
|
|
17050
|
+
) : detection.setup_commands ?? [];
|
|
17051
|
+
for (const setup of agentSetupCommands) {
|
|
16969
17052
|
emitProgress("SETUP_RUN", `${setup.cmd} ${setup.args.join(" ")}`);
|
|
16970
17053
|
const exitCode = await runOnce(setup.cmd, setup.args, process.cwd(), detection.env);
|
|
16971
17054
|
if (exitCode !== 0) {
|
|
@@ -20231,7 +20314,7 @@ function checkChokidar() {
|
|
|
20231
20314
|
}
|
|
20232
20315
|
async function doctor(args2 = []) {
|
|
20233
20316
|
const json = args2.includes("--json");
|
|
20234
|
-
const cliVersion = true ? "2.26.
|
|
20317
|
+
const cliVersion = true ? "2.26.15" : "0.0.0-dev";
|
|
20235
20318
|
const apiBase = resolveApiBaseUrl();
|
|
20236
20319
|
const diagnosticId = (0, import_node_crypto6.randomUUID)();
|
|
20237
20320
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -20430,7 +20513,7 @@ async function completion(args2) {
|
|
|
20430
20513
|
// src/commands/version.ts
|
|
20431
20514
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
20432
20515
|
function version2() {
|
|
20433
|
-
const v = true ? "2.26.
|
|
20516
|
+
const v = true ? "2.26.15" : "unknown";
|
|
20434
20517
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
20435
20518
|
}
|
|
20436
20519
|
|
|
@@ -20658,7 +20741,7 @@ function checkForUpdates() {
|
|
|
20658
20741
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
20659
20742
|
if (process.env.CI) return;
|
|
20660
20743
|
if (!process.stdout.isTTY) return;
|
|
20661
|
-
const current = true ? "2.26.
|
|
20744
|
+
const current = true ? "2.26.15" : null;
|
|
20662
20745
|
if (!current) return;
|
|
20663
20746
|
const cache = readCache();
|
|
20664
20747
|
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.26.
|
|
3
|
+
"version": "2.26.15",
|
|
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",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"chokidar": "^3.6.0",
|
|
75
75
|
"picocolors": "^1.1.0",
|
|
76
76
|
"qrcode-terminal": "^0.12.0",
|
|
77
|
-
"which": "^
|
|
77
|
+
"which": "^5.0.0",
|
|
78
78
|
"ws": "^8.18.0",
|
|
79
79
|
"zod": "^4.3.6"
|
|
80
80
|
},
|