codeam-cli 2.39.11 → 2.39.13
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 +17 -0
- package/dist/index.js +30 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ 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.12] — 2026-06-13
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **vsc-plugin,jetbrains-plugin:** Auto-reconnect the last session on IDE startup
|
|
12
|
+
|
|
13
|
+
## [2.39.11] — 2026-06-13
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Never let PostHog telemetry crash or spam the CLI session
|
|
18
|
+
|
|
19
|
+
### Tests
|
|
20
|
+
|
|
21
|
+
- **cli:** Fix Windows-only watcher path assertion (cross-platform path.join)
|
|
22
|
+
- **cli:** Import only join from path in the watcher test
|
|
23
|
+
|
|
7
24
|
## [2.39.10] — 2026-06-13
|
|
8
25
|
|
|
9
26
|
### 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.13",
|
|
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",
|
|
@@ -694,7 +694,7 @@ var _execSeam = {
|
|
|
694
694
|
// src/services/pairing.service.ts
|
|
695
695
|
var API_BASE = resolveApiBaseUrl();
|
|
696
696
|
var REQUEST_CODE_TIMEOUT_MS = 1e4;
|
|
697
|
-
async function requestCode(pluginId) {
|
|
697
|
+
async function requestCode(pluginId, pluginSecretHash) {
|
|
698
698
|
try {
|
|
699
699
|
const runtime = process.env.CODESPACES === "true" ? "github-codespaces" : "local";
|
|
700
700
|
const codespaceName = process.env.CODESPACE_NAME;
|
|
@@ -706,7 +706,11 @@ async function requestCode(pluginId) {
|
|
|
706
706
|
hostname: os2.hostname(),
|
|
707
707
|
runtime,
|
|
708
708
|
branch,
|
|
709
|
-
...codespaceName ? { codespaceName } : {}
|
|
709
|
+
...codespaceName ? { codespaceName } : {},
|
|
710
|
+
// SEC: proof-of-possession enrollment. Backend carries this hash
|
|
711
|
+
// onto the session and requires the raw secret on /status +
|
|
712
|
+
// /reconnect. Older backends ignore the unknown field.
|
|
713
|
+
...pluginSecretHash ? { pluginSecretHash } : {}
|
|
710
714
|
});
|
|
711
715
|
let timer;
|
|
712
716
|
const timeoutSentinel = /* @__PURE__ */ Symbol("request-code-timeout");
|
|
@@ -738,11 +742,14 @@ async function requestCode(pluginId) {
|
|
|
738
742
|
return { ok: false, reason: "network" };
|
|
739
743
|
}
|
|
740
744
|
}
|
|
741
|
-
async function fetchCurrentPluginAuthToken(sessionId, pluginId) {
|
|
745
|
+
async function fetchCurrentPluginAuthToken(sessionId, pluginId, pollSecret) {
|
|
742
746
|
try {
|
|
743
747
|
const result = await _transport.postJson(
|
|
744
748
|
`${API_BASE}/api/pairing/reconnect`,
|
|
745
|
-
{ sessionId, pluginId }
|
|
749
|
+
{ sessionId, pluginId },
|
|
750
|
+
// SEC: prove possession so the gated /reconnect returns the token.
|
|
751
|
+
// Omitted for legacy sessions (no secret) → backend legacy path.
|
|
752
|
+
pollSecret ? { "X-Plugin-Poll-Secret": pollSecret } : void 0
|
|
746
753
|
);
|
|
747
754
|
const data = result?.data;
|
|
748
755
|
if (!data?.paired) return null;
|
|
@@ -935,7 +942,7 @@ function makeHttpError(statusCode, retryAfterHeader, responseBody) {
|
|
|
935
942
|
if (typeof retryAfterSeconds === "number") err.retryAfterSeconds = retryAfterSeconds;
|
|
936
943
|
return err;
|
|
937
944
|
}
|
|
938
|
-
async function _postJson(url, body) {
|
|
945
|
+
async function _postJson(url, body, extraHeaders) {
|
|
939
946
|
return new Promise((resolve7, reject) => {
|
|
940
947
|
const data = JSON.stringify(body);
|
|
941
948
|
const u2 = new URL(url);
|
|
@@ -949,7 +956,8 @@ async function _postJson(url, body) {
|
|
|
949
956
|
headers: {
|
|
950
957
|
"Content-Type": "application/json",
|
|
951
958
|
"Content-Length": Buffer.byteLength(data),
|
|
952
|
-
...vercelBypassHeader()
|
|
959
|
+
...vercelBypassHeader(),
|
|
960
|
+
...extraHeaders ?? {}
|
|
953
961
|
},
|
|
954
962
|
timeout: 1e4
|
|
955
963
|
},
|
|
@@ -5900,7 +5908,7 @@ function readAnonId() {
|
|
|
5900
5908
|
}
|
|
5901
5909
|
function superProperties() {
|
|
5902
5910
|
return {
|
|
5903
|
-
cliVersion: true ? "2.39.
|
|
5911
|
+
cliVersion: true ? "2.39.13" : "0.0.0-dev",
|
|
5904
5912
|
nodeVersion: process.version,
|
|
5905
5913
|
platform: process.platform,
|
|
5906
5914
|
arch: process.arch,
|
|
@@ -23938,7 +23946,11 @@ async function start(requestedAgent) {
|
|
|
23938
23946
|
requestedAgent: requestedAgent ?? null
|
|
23939
23947
|
});
|
|
23940
23948
|
const cwd = process.cwd();
|
|
23941
|
-
const refreshed = await fetchCurrentPluginAuthToken(
|
|
23949
|
+
const refreshed = await fetchCurrentPluginAuthToken(
|
|
23950
|
+
session.id,
|
|
23951
|
+
pluginId,
|
|
23952
|
+
session.pollSecret
|
|
23953
|
+
);
|
|
23942
23954
|
if (refreshed && refreshed !== session.pluginAuthToken) {
|
|
23943
23955
|
addSession({ ...session, pluginAuthToken: refreshed });
|
|
23944
23956
|
session.pluginAuthToken = refreshed;
|
|
@@ -24223,10 +24235,12 @@ async function pair(args2 = []) {
|
|
|
24223
24235
|
const agentId = dryRun ? flagAgent ?? config.preferredAgent ?? "claude" : flagAgent ?? await promptForAgent(config.preferredAgent ?? "claude");
|
|
24224
24236
|
showIntro();
|
|
24225
24237
|
const pluginId = (0, import_crypto6.randomUUID)();
|
|
24238
|
+
const pollSecret = (0, import_crypto6.randomBytes)(32).toString("base64url");
|
|
24239
|
+
const pluginSecretHash = (0, import_crypto6.createHash)("sha256").update(pollSecret).digest("hex");
|
|
24226
24240
|
capture("pair_started", { agentId, pluginId, dryRun });
|
|
24227
24241
|
const spin = dist_exports.spinner();
|
|
24228
24242
|
spin.start("Requesting pairing code...");
|
|
24229
|
-
const result = await requestCode(pluginId);
|
|
24243
|
+
const result = await requestCode(pluginId, pluginSecretHash);
|
|
24230
24244
|
if (!result.ok) {
|
|
24231
24245
|
spin.stop("Failed");
|
|
24232
24246
|
if (result.reason === "rate-limited") {
|
|
@@ -24289,6 +24303,9 @@ async function pair(args2 = []) {
|
|
|
24289
24303
|
plan: info.plan,
|
|
24290
24304
|
pairedAt: Date.now(),
|
|
24291
24305
|
pluginAuthToken: info.pluginAuthToken,
|
|
24306
|
+
// SEC: persist the PoP secret so boot-time /reconnect can prove
|
|
24307
|
+
// possession and refresh the token on the gated endpoint.
|
|
24308
|
+
pollSecret,
|
|
24292
24309
|
agent: agentId
|
|
24293
24310
|
});
|
|
24294
24311
|
saveCliConfig({ ...loadCliConfig(), preferredAgent: agentId });
|
|
@@ -26992,7 +27009,7 @@ function checkChokidar() {
|
|
|
26992
27009
|
}
|
|
26993
27010
|
async function doctor(args2 = []) {
|
|
26994
27011
|
const json = args2.includes("--json");
|
|
26995
|
-
const cliVersion = true ? "2.39.
|
|
27012
|
+
const cliVersion = true ? "2.39.13" : "0.0.0-dev";
|
|
26996
27013
|
const apiBase = resolveApiBaseUrl();
|
|
26997
27014
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
26998
27015
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27191,7 +27208,7 @@ async function completion(args2) {
|
|
|
27191
27208
|
// src/commands/version.ts
|
|
27192
27209
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27193
27210
|
function version2() {
|
|
27194
|
-
const v = true ? "2.39.
|
|
27211
|
+
const v = true ? "2.39.13" : "unknown";
|
|
27195
27212
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27196
27213
|
}
|
|
27197
27214
|
|
|
@@ -27477,7 +27494,7 @@ function checkForUpdates() {
|
|
|
27477
27494
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27478
27495
|
if (process.env.CI) return;
|
|
27479
27496
|
if (!process.stdout.isTTY) return;
|
|
27480
|
-
const current = true ? "2.39.
|
|
27497
|
+
const current = true ? "2.39.13" : null;
|
|
27481
27498
|
if (!current) return;
|
|
27482
27499
|
const cache = readCache();
|
|
27483
27500
|
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.13",
|
|
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",
|