codeam-cli 2.74.3 → 2.74.5
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 +13 -0
- package/dist/index.js +73 -32
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ 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.74.4] — 2026-09-04
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Transcript upload — size-bounded batches, 429-aware retry, one upload per conversation (#709)
|
|
12
|
+
|
|
13
|
+
## [2.74.3] — 2026-09-04
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Mcp-warm spawns its launcher through a shell on Windows (#706)
|
|
18
|
+
- **cli:** Expo preview — make sure @expo/ngrok exists before `expo start --tunnel` (#707)
|
|
19
|
+
|
|
7
20
|
## [2.74.2] — 2026-09-04
|
|
8
21
|
|
|
9
22
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -8136,7 +8136,7 @@ function readAnonId() {
|
|
|
8136
8136
|
}
|
|
8137
8137
|
function superProperties() {
|
|
8138
8138
|
return {
|
|
8139
|
-
cliVersion: true ? "2.74.
|
|
8139
|
+
cliVersion: true ? "2.74.5" : "0.0.0-dev",
|
|
8140
8140
|
nodeVersion: process.version,
|
|
8141
8141
|
platform: process.platform,
|
|
8142
8142
|
arch: process.arch,
|
|
@@ -8378,7 +8378,7 @@ var http = __toESM(require("http"));
|
|
|
8378
8378
|
// package.json
|
|
8379
8379
|
var package_default = {
|
|
8380
8380
|
name: "codeam-cli",
|
|
8381
|
-
version: "2.74.
|
|
8381
|
+
version: "2.74.5",
|
|
8382
8382
|
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.",
|
|
8383
8383
|
type: "commonjs",
|
|
8384
8384
|
main: "dist/index.js",
|
|
@@ -8451,7 +8451,7 @@ var package_default = {
|
|
|
8451
8451
|
node: ">=22.0.0"
|
|
8452
8452
|
},
|
|
8453
8453
|
dependencies: {
|
|
8454
|
-
"@agentclientprotocol/claude-agent-acp": "0.
|
|
8454
|
+
"@agentclientprotocol/claude-agent-acp": "0.74.0",
|
|
8455
8455
|
"@agentclientprotocol/codex-acp": "1.1.4",
|
|
8456
8456
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
8457
8457
|
"@clack/prompts": "^1.2.0",
|
|
@@ -9971,7 +9971,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9971
9971
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9972
9972
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9973
9973
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9974
|
-
..."2.74.
|
|
9974
|
+
..."2.74.5" ? { ideVersion: "2.74.5" } : {}
|
|
9975
9975
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9976
9976
|
}
|
|
9977
9977
|
/**
|
|
@@ -22272,7 +22272,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
22272
22272
|
if (process.env.NODE_ENV === "test") return;
|
|
22273
22273
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22274
22274
|
if (process.env.CI) return;
|
|
22275
|
-
const current2 = true ? "2.74.
|
|
22275
|
+
const current2 = true ? "2.74.5" : null;
|
|
22276
22276
|
if (!current2) return;
|
|
22277
22277
|
const cache = readCache();
|
|
22278
22278
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22289,7 +22289,7 @@ function checkForUpdates() {
|
|
|
22289
22289
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22290
22290
|
if (process.env.CI) return;
|
|
22291
22291
|
if (!process.stdout.isTTY) return;
|
|
22292
|
-
const current2 = true ? "2.74.
|
|
22292
|
+
const current2 = true ? "2.74.5" : null;
|
|
22293
22293
|
if (!current2) return;
|
|
22294
22294
|
const cache = readCache();
|
|
22295
22295
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22312,7 +22312,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
22312
22312
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
22313
22313
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
22314
22314
|
function currentCliVersion() {
|
|
22315
|
-
return true ? "2.74.
|
|
22315
|
+
return true ? "2.74.5" : null;
|
|
22316
22316
|
}
|
|
22317
22317
|
async function installedVersion(deps) {
|
|
22318
22318
|
const ls = await deps.run(
|
|
@@ -30993,7 +30993,27 @@ function extractText3(content) {
|
|
|
30993
30993
|
}
|
|
30994
30994
|
return "";
|
|
30995
30995
|
}
|
|
30996
|
-
var
|
|
30996
|
+
var CONVERSATION_BATCH_MAX_MESSAGES = 150;
|
|
30997
|
+
var CONVERSATION_BATCH_MAX_BYTES = 2 * 1024 * 1024;
|
|
30998
|
+
function batchConversation(messages, limits = {}) {
|
|
30999
|
+
const maxMessages = limits.maxMessages ?? CONVERSATION_BATCH_MAX_MESSAGES;
|
|
31000
|
+
const maxBytes = limits.maxBytes ?? CONVERSATION_BATCH_MAX_BYTES;
|
|
31001
|
+
const out2 = [];
|
|
31002
|
+
let cur = [];
|
|
31003
|
+
let curBytes = 0;
|
|
31004
|
+
for (const m of messages) {
|
|
31005
|
+
const size = Buffer.byteLength(JSON.stringify(m));
|
|
31006
|
+
if (cur.length > 0 && (cur.length >= maxMessages || curBytes + size > maxBytes)) {
|
|
31007
|
+
out2.push(cur);
|
|
31008
|
+
cur = [];
|
|
31009
|
+
curBytes = 0;
|
|
31010
|
+
}
|
|
31011
|
+
cur.push(m);
|
|
31012
|
+
curBytes += size;
|
|
31013
|
+
}
|
|
31014
|
+
if (cur.length > 0) out2.push(cur);
|
|
31015
|
+
return out2;
|
|
31016
|
+
}
|
|
30997
31017
|
function scrubSquadContext(messages) {
|
|
30998
31018
|
const out2 = [];
|
|
30999
31019
|
for (const m of messages) {
|
|
@@ -31052,7 +31072,7 @@ function parseJsonl(filePath) {
|
|
|
31052
31072
|
}
|
|
31053
31073
|
return messages;
|
|
31054
31074
|
}
|
|
31055
|
-
function
|
|
31075
|
+
function postWithStatus(endpoint, body, pluginAuthToken) {
|
|
31056
31076
|
return new Promise((resolve11) => {
|
|
31057
31077
|
const payload = JSON.stringify(body);
|
|
31058
31078
|
const u2 = new URL(`${API_BASE8}${endpoint}`);
|
|
@@ -31076,24 +31096,33 @@ function post(endpoint, body, pluginAuthToken) {
|
|
|
31076
31096
|
},
|
|
31077
31097
|
(res) => {
|
|
31078
31098
|
res.resume();
|
|
31079
|
-
const
|
|
31080
|
-
|
|
31081
|
-
|
|
31099
|
+
const status2 = res.statusCode ?? null;
|
|
31100
|
+
const ok = status2 !== null && status2 >= 200 && status2 < 300;
|
|
31101
|
+
if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${status2}`);
|
|
31102
|
+
let retryAfterMs = null;
|
|
31103
|
+
if (status2 === 429) {
|
|
31104
|
+
const ra = Number(res.headers["retry-after"]);
|
|
31105
|
+
retryAfterMs = Number.isFinite(ra) && ra > 0 ? ra * 1e3 : 2e4;
|
|
31106
|
+
}
|
|
31107
|
+
resolve11({ ok, status: status2, retryAfterMs });
|
|
31082
31108
|
}
|
|
31083
31109
|
);
|
|
31084
31110
|
req.on("error", (err) => {
|
|
31085
31111
|
log.warn("history:post", `${endpoint} network error`, err);
|
|
31086
|
-
resolve11(false);
|
|
31112
|
+
resolve11({ ok: false, status: null, retryAfterMs: null });
|
|
31087
31113
|
});
|
|
31088
31114
|
req.on("timeout", () => {
|
|
31089
31115
|
log.warn("history:post", `${endpoint} timeout after 15s`);
|
|
31090
31116
|
req.destroy();
|
|
31091
|
-
resolve11(false);
|
|
31117
|
+
resolve11({ ok: false, status: null, retryAfterMs: null });
|
|
31092
31118
|
});
|
|
31093
31119
|
req.write(payload);
|
|
31094
31120
|
req.end();
|
|
31095
31121
|
});
|
|
31096
31122
|
}
|
|
31123
|
+
function post(endpoint, body, pluginAuthToken) {
|
|
31124
|
+
return postWithStatus(endpoint, body, pluginAuthToken).then((r) => r.ok);
|
|
31125
|
+
}
|
|
31097
31126
|
var HistoryService = class _HistoryService {
|
|
31098
31127
|
constructor(runtime, pluginId, cwd, options) {
|
|
31099
31128
|
this.pluginId = pluginId;
|
|
@@ -31453,33 +31482,45 @@ var HistoryService = class _HistoryService {
|
|
|
31453
31482
|
}
|
|
31454
31483
|
return parseJsonl(path74.join(this.projectDir, `${sessionId}.jsonl`));
|
|
31455
31484
|
}
|
|
31485
|
+
/** One in-flight full upload per conversation — the baton mirror and a
|
|
31486
|
+
* `get_conversation` used to upload the same transcript concurrently. */
|
|
31487
|
+
uploadsInFlight = /* @__PURE__ */ new Map();
|
|
31456
31488
|
async loadConversation(sessionId) {
|
|
31489
|
+
const inFlight = this.uploadsInFlight.get(sessionId);
|
|
31490
|
+
if (inFlight) return inFlight;
|
|
31491
|
+
const run = this.loadConversationNow(sessionId).finally(() => {
|
|
31492
|
+
this.uploadsInFlight.delete(sessionId);
|
|
31493
|
+
});
|
|
31494
|
+
this.uploadsInFlight.set(sessionId, run);
|
|
31495
|
+
return run;
|
|
31496
|
+
}
|
|
31497
|
+
async loadConversationNow(sessionId) {
|
|
31457
31498
|
const messages = this.readConversation(sessionId);
|
|
31458
31499
|
if (messages.length === 0) return;
|
|
31459
|
-
const
|
|
31500
|
+
const batches = batchConversation(messages);
|
|
31460
31501
|
const RETRY_DELAYS = [500, 1e3, 2e3, 4e3, 8e3];
|
|
31461
|
-
for (let i = 0; i <
|
|
31462
|
-
const batch = messages.slice(i * CONVERSATION_BATCH_SIZE, (i + 1) * CONVERSATION_BATCH_SIZE);
|
|
31502
|
+
for (let i = 0; i < batches.length; i++) {
|
|
31463
31503
|
const body = {
|
|
31464
31504
|
pluginId: this.pluginId,
|
|
31465
|
-
// `agentId` keys the backend's per-agent conversation cache.
|
|
31466
|
-
// Older backends that don't recognise the field silently
|
|
31467
|
-
// ignore it and default to `claude-code` server-side — same
|
|
31468
|
-
// outcome as before the per-agent split.
|
|
31469
31505
|
agentId: this.runtime.id,
|
|
31470
31506
|
sessionId,
|
|
31471
|
-
messages:
|
|
31507
|
+
messages: batches[i],
|
|
31472
31508
|
batchIndex: i,
|
|
31473
|
-
totalBatches
|
|
31509
|
+
totalBatches: batches.length
|
|
31474
31510
|
};
|
|
31475
|
-
let
|
|
31476
|
-
|
|
31477
|
-
|
|
31478
|
-
|
|
31479
|
-
|
|
31480
|
-
|
|
31511
|
+
let res = await postWithStatus("/api/sessions/conversation", body, this.pluginAuthToken);
|
|
31512
|
+
let attempt = 0;
|
|
31513
|
+
let throttled = 0;
|
|
31514
|
+
while (!res.ok && (res.retryAfterMs !== null ? throttled < 6 : attempt < RETRY_DELAYS.length)) {
|
|
31515
|
+
const delay = res.retryAfterMs ?? RETRY_DELAYS[attempt];
|
|
31516
|
+
if (res.retryAfterMs !== null) throttled++;
|
|
31517
|
+
else attempt++;
|
|
31518
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
31519
|
+
res = await postWithStatus("/api/sessions/conversation", body, this.pluginAuthToken);
|
|
31520
|
+
}
|
|
31521
|
+
if (!res.ok) {
|
|
31481
31522
|
throw new Error(
|
|
31482
|
-
`Failed to upload conversation batch ${i + 1}/${
|
|
31523
|
+
`Failed to upload conversation batch ${i + 1}/${batches.length} after all retries (last HTTP ${res.status})`
|
|
31483
31524
|
);
|
|
31484
31525
|
}
|
|
31485
31526
|
}
|
|
@@ -47484,7 +47525,7 @@ function checkChokidar() {
|
|
|
47484
47525
|
}
|
|
47485
47526
|
async function doctor(args2 = []) {
|
|
47486
47527
|
const json = args2.includes("--json");
|
|
47487
|
-
const cliVersion = true ? "2.74.
|
|
47528
|
+
const cliVersion = true ? "2.74.5" : "0.0.0-dev";
|
|
47488
47529
|
const apiBase2 = resolveApiBaseUrl();
|
|
47489
47530
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
47490
47531
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -48008,7 +48049,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
48008
48049
|
// src/commands/version.ts
|
|
48009
48050
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
48010
48051
|
function version2() {
|
|
48011
|
-
const v = true ? "2.74.
|
|
48052
|
+
const v = true ? "2.74.5" : "unknown";
|
|
48012
48053
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
48013
48054
|
}
|
|
48014
48055
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.74.
|
|
3
|
+
"version": "2.74.5",
|
|
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",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"node": ">=22.0.0"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@agentclientprotocol/claude-agent-acp": "0.
|
|
76
|
+
"@agentclientprotocol/claude-agent-acp": "0.74.0",
|
|
77
77
|
"@agentclientprotocol/codex-acp": "1.1.4",
|
|
78
78
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
79
79
|
"@clack/prompts": "^1.2.0",
|