codeam-cli 2.39.44 → 2.39.45
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 +50 -36
- 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.44] — 2026-06-19
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Surface untracked new files with real line counts in changeset
|
|
12
|
+
|
|
7
13
|
## [2.39.43] — 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.45",
|
|
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.45" : "0.0.0-dev",
|
|
5912
5912
|
nodeVersion: process.version,
|
|
5913
5913
|
platform: process.platform,
|
|
5914
5914
|
arch: process.arch,
|
|
@@ -16173,9 +16173,11 @@ async function link(args2 = []) {
|
|
|
16173
16173
|
return;
|
|
16174
16174
|
}
|
|
16175
16175
|
const pluginId = (0, import_node_crypto6.randomUUID)();
|
|
16176
|
+
const pollSecret = (0, import_node_crypto6.randomBytes)(32).toString("base64url");
|
|
16177
|
+
const pluginSecretHash = (0, import_node_crypto6.createHash)("sha256").update(pollSecret).digest("hex");
|
|
16176
16178
|
const spin = dist_exports.spinner();
|
|
16177
16179
|
spin.start("Requesting pairing code...");
|
|
16178
|
-
const pairing = await requestCode(pluginId);
|
|
16180
|
+
const pairing = await requestCode(pluginId, pluginSecretHash);
|
|
16179
16181
|
if (!pairing.ok) {
|
|
16180
16182
|
spin.stop("Failed");
|
|
16181
16183
|
if (pairing.reason === "rate-limited") {
|
|
@@ -16219,15 +16221,30 @@ async function link(args2 = []) {
|
|
|
16219
16221
|
clearInterval(countdown);
|
|
16220
16222
|
waitSpin.stop("Timed out");
|
|
16221
16223
|
reject(new Error("Pairing timed out after 5 minutes. Run codeam link again."));
|
|
16222
|
-
}
|
|
16224
|
+
},
|
|
16225
|
+
// SEC: replay the PoP secret so the pending-stream gate passes
|
|
16226
|
+
// under PoP enforcement.
|
|
16227
|
+
pollSecret
|
|
16223
16228
|
);
|
|
16224
16229
|
process.once("SIGINT", sigint);
|
|
16225
16230
|
});
|
|
16226
|
-
|
|
16227
|
-
|
|
16228
|
-
|
|
16229
|
-
);
|
|
16230
|
-
|
|
16231
|
+
let pluginAuthToken = paired.pluginAuthToken;
|
|
16232
|
+
if (!pluginAuthToken) {
|
|
16233
|
+
const fetchSpin = dist_exports.spinner();
|
|
16234
|
+
fetchSpin.start("Fetching plugin auth token via secure reconnect...");
|
|
16235
|
+
pluginAuthToken = await fetchCurrentPluginAuthToken(
|
|
16236
|
+
paired.sessionId,
|
|
16237
|
+
pluginId,
|
|
16238
|
+
pollSecret
|
|
16239
|
+
) ?? void 0;
|
|
16240
|
+
if (!pluginAuthToken) {
|
|
16241
|
+
fetchSpin.stop("Failed");
|
|
16242
|
+
showError(
|
|
16243
|
+
"Could not obtain a pluginAuthToken \u2014 the pairing did not supply one and the /api/pairing/reconnect fallback also failed. Ensure api-v2 is deployed and try running codeam link again."
|
|
16244
|
+
);
|
|
16245
|
+
process.exit(1);
|
|
16246
|
+
}
|
|
16247
|
+
fetchSpin.stop("Token retrieved");
|
|
16231
16248
|
}
|
|
16232
16249
|
addSession({
|
|
16233
16250
|
id: paired.sessionId,
|
|
@@ -16236,12 +16253,15 @@ async function link(args2 = []) {
|
|
|
16236
16253
|
userEmail: paired.userEmail,
|
|
16237
16254
|
plan: paired.plan,
|
|
16238
16255
|
pairedAt: Date.now(),
|
|
16239
|
-
pluginAuthToken
|
|
16256
|
+
pluginAuthToken,
|
|
16257
|
+
// SEC: persist so command-relay and future reconnects can prove
|
|
16258
|
+
// possession on the gated endpoint.
|
|
16259
|
+
pollSecret,
|
|
16240
16260
|
agent: ctx.runtime.id
|
|
16241
16261
|
});
|
|
16242
16262
|
saveCliConfig({ ...loadCliConfig(), preferredAgent: ctx.runtime.id });
|
|
16243
16263
|
if (parsed.apiKey) {
|
|
16244
|
-
await uploadAndSucceed(ctx, paired, pluginId, {
|
|
16264
|
+
await uploadAndSucceed(ctx, paired, pluginId, pluginAuthToken, {
|
|
16245
16265
|
method: "api_key",
|
|
16246
16266
|
credential: parsed.apiKey.trim(),
|
|
16247
16267
|
source: "manual"
|
|
@@ -16254,7 +16274,7 @@ async function link(args2 = []) {
|
|
|
16254
16274
|
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
16255
16275
|
process.exit(1);
|
|
16256
16276
|
}
|
|
16257
|
-
await uploadAndSucceed(ctx, paired, pluginId, {
|
|
16277
|
+
await uploadAndSucceed(ctx, paired, pluginId, pluginAuthToken, {
|
|
16258
16278
|
method: "oauth",
|
|
16259
16279
|
credential,
|
|
16260
16280
|
source: "manual"
|
|
@@ -16272,9 +16292,9 @@ async function link(args2 = []) {
|
|
|
16272
16292
|
installSpin.stop(`${ctx.displayName} is installed`);
|
|
16273
16293
|
const existing = await ctx.locator.extract();
|
|
16274
16294
|
if (existing) {
|
|
16275
|
-
if (await refuseIfStale(ctx, paired, pluginId, existing)) return;
|
|
16295
|
+
if (await refuseIfStale(ctx, paired, pluginId, pluginAuthToken, existing)) return;
|
|
16276
16296
|
showInfo(`Found existing ${ctx.displayName} credentials at ${import_picocolors2.default.bold(existing.source)}.`);
|
|
16277
|
-
await uploadAndSucceed(ctx, paired, pluginId, existing);
|
|
16297
|
+
await uploadAndSucceed(ctx, paired, pluginId, pluginAuthToken, existing);
|
|
16278
16298
|
return;
|
|
16279
16299
|
}
|
|
16280
16300
|
if (parsed.reuseExisting) {
|
|
@@ -16289,23 +16309,21 @@ async function link(args2 = []) {
|
|
|
16289
16309
|
console.log("");
|
|
16290
16310
|
const captured = await captureFreshCredentials(ctx);
|
|
16291
16311
|
console.log("");
|
|
16292
|
-
if (await refuseIfStale(ctx, paired, pluginId, captured)) return;
|
|
16293
|
-
await uploadAndSucceed(ctx, paired, pluginId, captured);
|
|
16312
|
+
if (await refuseIfStale(ctx, paired, pluginId, pluginAuthToken, captured)) return;
|
|
16313
|
+
await uploadAndSucceed(ctx, paired, pluginId, pluginAuthToken, captured);
|
|
16294
16314
|
}
|
|
16295
|
-
async function refuseIfStale(ctx, paired, pluginId, token) {
|
|
16315
|
+
async function refuseIfStale(ctx, paired, pluginId, pluginAuthToken, token) {
|
|
16296
16316
|
const verdict = ctx.locator.validate?.(token);
|
|
16297
16317
|
if (!verdict || verdict.status !== "expired") return false;
|
|
16298
16318
|
const reason = verdict.reason ?? "Token expired";
|
|
16299
|
-
|
|
16300
|
-
|
|
16301
|
-
|
|
16302
|
-
|
|
16303
|
-
|
|
16304
|
-
|
|
16305
|
-
|
|
16306
|
-
|
|
16307
|
-
});
|
|
16308
|
-
}
|
|
16319
|
+
await postLinkErrorSignal({
|
|
16320
|
+
agentId: ctx.locator.publicId,
|
|
16321
|
+
sessionId: paired.sessionId,
|
|
16322
|
+
pluginId,
|
|
16323
|
+
pluginAuthToken,
|
|
16324
|
+
code: "credentials_expired",
|
|
16325
|
+
reason
|
|
16326
|
+
});
|
|
16309
16327
|
showError(
|
|
16310
16328
|
`Your local ${ctx.displayName} credentials at ${import_picocolors2.default.bold(ctx.locator.hint)} are already expired:
|
|
16311
16329
|
${reason}
|
|
@@ -16394,18 +16412,14 @@ async function captureFreshCredentials(ctx) {
|
|
|
16394
16412
|
throw err;
|
|
16395
16413
|
}
|
|
16396
16414
|
}
|
|
16397
|
-
async function uploadAndSucceed(ctx, paired, pluginId, token) {
|
|
16398
|
-
if (!paired.pluginAuthToken) {
|
|
16399
|
-
showError("Missing pluginAuthToken; re-run codeam link.");
|
|
16400
|
-
process.exit(1);
|
|
16401
|
-
}
|
|
16415
|
+
async function uploadAndSucceed(ctx, paired, pluginId, pluginAuthToken, token) {
|
|
16402
16416
|
const uploadSpin = dist_exports.spinner();
|
|
16403
16417
|
uploadSpin.start("Sealing credential in your vault...");
|
|
16404
16418
|
const result = await postLinkCredential({
|
|
16405
16419
|
agentId: ctx.locator.publicId,
|
|
16406
16420
|
sessionId: paired.sessionId,
|
|
16407
16421
|
pluginId,
|
|
16408
|
-
pluginAuthToken
|
|
16422
|
+
pluginAuthToken,
|
|
16409
16423
|
method: token.method,
|
|
16410
16424
|
credential: token.credential,
|
|
16411
16425
|
agentState: token.agentState
|
|
@@ -27365,7 +27379,7 @@ function checkChokidar() {
|
|
|
27365
27379
|
}
|
|
27366
27380
|
async function doctor(args2 = []) {
|
|
27367
27381
|
const json = args2.includes("--json");
|
|
27368
|
-
const cliVersion = true ? "2.39.
|
|
27382
|
+
const cliVersion = true ? "2.39.45" : "0.0.0-dev";
|
|
27369
27383
|
const apiBase2 = resolveApiBaseUrl();
|
|
27370
27384
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27371
27385
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27564,7 +27578,7 @@ async function completion(args2) {
|
|
|
27564
27578
|
// src/commands/version.ts
|
|
27565
27579
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27566
27580
|
function version2() {
|
|
27567
|
-
const v = true ? "2.39.
|
|
27581
|
+
const v = true ? "2.39.45" : "unknown";
|
|
27568
27582
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27569
27583
|
}
|
|
27570
27584
|
|
|
@@ -27850,7 +27864,7 @@ function checkForUpdates() {
|
|
|
27850
27864
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27851
27865
|
if (process.env.CI) return;
|
|
27852
27866
|
if (!process.stdout.isTTY) return;
|
|
27853
|
-
const current = true ? "2.39.
|
|
27867
|
+
const current = true ? "2.39.45" : null;
|
|
27854
27868
|
if (!current) return;
|
|
27855
27869
|
const cache = readCache();
|
|
27856
27870
|
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.45",
|
|
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",
|