codeam-cli 2.60.4 → 2.60.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 +12 -0
- package/dist/index.js +89 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.60.4] — 2026-07-08
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Serialize baton state POSTs so handback never sticks on "Switching…"
|
|
12
|
+
|
|
13
|
+
## [2.60.3] — 2026-07-08
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Clean up terminal + mobile activity on baton Take Control
|
|
18
|
+
|
|
7
19
|
## [2.60.2] — 2026-07-08
|
|
8
20
|
|
|
9
21
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -5653,7 +5653,7 @@ function readAnonId() {
|
|
|
5653
5653
|
}
|
|
5654
5654
|
function superProperties() {
|
|
5655
5655
|
return {
|
|
5656
|
-
cliVersion: true ? "2.60.
|
|
5656
|
+
cliVersion: true ? "2.60.5" : "0.0.0-dev",
|
|
5657
5657
|
nodeVersion: process.version,
|
|
5658
5658
|
platform: process.platform,
|
|
5659
5659
|
arch: process.arch,
|
|
@@ -5834,7 +5834,7 @@ var os4 = __toESM(require("os"));
|
|
|
5834
5834
|
// package.json
|
|
5835
5835
|
var package_default = {
|
|
5836
5836
|
name: "codeam-cli",
|
|
5837
|
-
version: "2.60.
|
|
5837
|
+
version: "2.60.5",
|
|
5838
5838
|
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.",
|
|
5839
5839
|
type: "commonjs",
|
|
5840
5840
|
main: "dist/index.js",
|
|
@@ -6905,7 +6905,7 @@ var CommandRelayService = class {
|
|
|
6905
6905
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
6906
6906
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
6907
6907
|
// pair/reconnect). Older backends ignore the extra field.
|
|
6908
|
-
..."2.60.
|
|
6908
|
+
..."2.60.5" ? { ideVersion: "2.60.5" } : {}
|
|
6909
6909
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
6910
6910
|
}
|
|
6911
6911
|
/**
|
|
@@ -13399,13 +13399,71 @@ var fs23 = __toESM(require("fs"));
|
|
|
13399
13399
|
var os21 = __toESM(require("os"));
|
|
13400
13400
|
var path27 = __toESM(require("path"));
|
|
13401
13401
|
var HISTORY_ROOT = path27.join(os21.homedir(), ".cursor", "projects");
|
|
13402
|
+
function encodeCursorCwd(cwd) {
|
|
13403
|
+
return cwd.replace(/^[/\\]+/, "").replace(/[/\\:]/g, "-");
|
|
13404
|
+
}
|
|
13405
|
+
function resolveHistoryFile3(cwd, sessionId, root = HISTORY_ROOT) {
|
|
13406
|
+
const rel = path27.join("agent-transcripts", sessionId, `${sessionId}.jsonl`);
|
|
13407
|
+
const primary = path27.join(root, encodeCursorCwd(cwd), rel);
|
|
13408
|
+
if (fs23.existsSync(primary)) return primary;
|
|
13409
|
+
let entries;
|
|
13410
|
+
try {
|
|
13411
|
+
entries = fs23.readdirSync(root, { withFileTypes: true });
|
|
13412
|
+
} catch {
|
|
13413
|
+
return null;
|
|
13414
|
+
}
|
|
13415
|
+
for (const e of entries) {
|
|
13416
|
+
if (!e.isDirectory()) continue;
|
|
13417
|
+
const candidate = path27.join(root, e.name, rel);
|
|
13418
|
+
if (fs23.existsSync(candidate)) return candidate;
|
|
13419
|
+
}
|
|
13420
|
+
return null;
|
|
13421
|
+
}
|
|
13402
13422
|
function resolveHistoryDir3(cwd) {
|
|
13403
13423
|
if (!fs23.existsSync(HISTORY_ROOT)) return null;
|
|
13404
|
-
|
|
13405
|
-
return
|
|
13424
|
+
const dir = path27.join(HISTORY_ROOT, encodeCursorCwd(cwd));
|
|
13425
|
+
return fs23.existsSync(dir) ? dir : null;
|
|
13406
13426
|
}
|
|
13407
|
-
function
|
|
13408
|
-
return
|
|
13427
|
+
function extractText2(content) {
|
|
13428
|
+
if (!Array.isArray(content)) return "";
|
|
13429
|
+
return content.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("");
|
|
13430
|
+
}
|
|
13431
|
+
function unwrapUserQuery(text) {
|
|
13432
|
+
const m = text.match(/<user_query>\s*([\s\S]*?)\s*<\/user_query>/);
|
|
13433
|
+
return (m ? m[1] : text).trim();
|
|
13434
|
+
}
|
|
13435
|
+
function parseHistoryFile3(filePath) {
|
|
13436
|
+
let raw;
|
|
13437
|
+
try {
|
|
13438
|
+
raw = fs23.readFileSync(filePath, "utf8");
|
|
13439
|
+
} catch {
|
|
13440
|
+
return [];
|
|
13441
|
+
}
|
|
13442
|
+
const out2 = [];
|
|
13443
|
+
let idx = 0;
|
|
13444
|
+
for (const line of raw.split("\n")) {
|
|
13445
|
+
if (!line.trim()) continue;
|
|
13446
|
+
let rec;
|
|
13447
|
+
try {
|
|
13448
|
+
rec = JSON.parse(line);
|
|
13449
|
+
} catch {
|
|
13450
|
+
continue;
|
|
13451
|
+
}
|
|
13452
|
+
if (rec.role !== "user" && rec.role !== "assistant") continue;
|
|
13453
|
+
const blockText = extractText2(rec.message?.content);
|
|
13454
|
+
const text = rec.role === "user" ? unwrapUserQuery(blockText) : blockText.trim();
|
|
13455
|
+
if (!text) continue;
|
|
13456
|
+
out2.push({
|
|
13457
|
+
id: `cursor:${idx}`,
|
|
13458
|
+
role: rec.role === "user" ? "user" : "agent",
|
|
13459
|
+
text,
|
|
13460
|
+
// Cursor records carry no per-message timestamp; order is preserved by
|
|
13461
|
+
// file position, so a stable epoch keeps the shape valid without lying.
|
|
13462
|
+
timestamp: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
13463
|
+
});
|
|
13464
|
+
idx += 1;
|
|
13465
|
+
}
|
|
13466
|
+
return out2;
|
|
13409
13467
|
}
|
|
13410
13468
|
function getCurrentUsage3(_historyDir) {
|
|
13411
13469
|
return null;
|
|
@@ -13527,6 +13585,13 @@ var CursorRuntimeStrategy = class {
|
|
|
13527
13585
|
resolveHistoryDir(cwd) {
|
|
13528
13586
|
return resolveHistoryDir3(cwd);
|
|
13529
13587
|
}
|
|
13588
|
+
/** Session transcript at
|
|
13589
|
+
* `~/.cursor/projects/<encoded-cwd>/agent-transcripts/<id>/<id>.jsonl`.
|
|
13590
|
+
* Presence of this method is what lets the baton engage for Cursor
|
|
13591
|
+
* (`runtimeSupportsBaton`), so the LOCAL_DRIVE mirror can tail it. */
|
|
13592
|
+
resolveHistoryFile(cwd, sessionId) {
|
|
13593
|
+
return resolveHistoryFile3(cwd, sessionId);
|
|
13594
|
+
}
|
|
13530
13595
|
parseHistoryFile(filePath) {
|
|
13531
13596
|
return parseHistoryFile3(filePath);
|
|
13532
13597
|
}
|
|
@@ -15921,7 +15986,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
15921
15986
|
if (process.env.NODE_ENV === "test") return;
|
|
15922
15987
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15923
15988
|
if (process.env.CI) return;
|
|
15924
|
-
const current = true ? "2.60.
|
|
15989
|
+
const current = true ? "2.60.5" : null;
|
|
15925
15990
|
if (!current) return;
|
|
15926
15991
|
const cache = readCache();
|
|
15927
15992
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -15938,7 +16003,7 @@ function checkForUpdates() {
|
|
|
15938
16003
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15939
16004
|
if (process.env.CI) return;
|
|
15940
16005
|
if (!process.stdout.isTTY) return;
|
|
15941
|
-
const current = true ? "2.60.
|
|
16006
|
+
const current = true ? "2.60.5" : null;
|
|
15942
16007
|
if (!current) return;
|
|
15943
16008
|
const cache = readCache();
|
|
15944
16009
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -15958,7 +16023,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
15958
16023
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
15959
16024
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
15960
16025
|
function currentCliVersion() {
|
|
15961
|
-
return true ? "2.60.
|
|
16026
|
+
return true ? "2.60.5" : null;
|
|
15962
16027
|
}
|
|
15963
16028
|
function runCmd(cmd, args2, timeoutMs) {
|
|
15964
16029
|
return new Promise((resolve7) => {
|
|
@@ -21728,7 +21793,7 @@ var historyRecordSchema = import_zod2.z.object({
|
|
|
21728
21793
|
}).passthrough().optional()
|
|
21729
21794
|
}).passthrough();
|
|
21730
21795
|
var API_BASE8 = resolveApiBaseUrl();
|
|
21731
|
-
function
|
|
21796
|
+
function extractText3(content) {
|
|
21732
21797
|
if (typeof content === "string") return content;
|
|
21733
21798
|
if (Array.isArray(content)) {
|
|
21734
21799
|
return content.filter((b) => b["type"] === "text").map((b) => b["text"]).join("\n");
|
|
@@ -21767,10 +21832,10 @@ function parseJsonl(filePath) {
|
|
|
21767
21832
|
const uuid = record.uuid ?? `${Date.now()}-${Math.random()}`;
|
|
21768
21833
|
const msg = record.message;
|
|
21769
21834
|
if (record.type === "user" && msg) {
|
|
21770
|
-
const text =
|
|
21835
|
+
const text = extractText3(msg.content).trim();
|
|
21771
21836
|
if (text) messages.push({ id: uuid, role: "user", text, timestamp });
|
|
21772
21837
|
} else if (record.type === "assistant" && msg) {
|
|
21773
|
-
const text =
|
|
21838
|
+
const text = extractText3(msg.content).trim();
|
|
21774
21839
|
if (text) messages.push({ id: uuid, role: "agent", text, timestamp });
|
|
21775
21840
|
}
|
|
21776
21841
|
}
|
|
@@ -25853,12 +25918,12 @@ function mapSessionUpdate(notification) {
|
|
|
25853
25918
|
const update = notification.update;
|
|
25854
25919
|
switch (update.sessionUpdate) {
|
|
25855
25920
|
case "agent_message_chunk": {
|
|
25856
|
-
const text =
|
|
25921
|
+
const text = extractText4(update.content);
|
|
25857
25922
|
if (!text) return [];
|
|
25858
25923
|
return [{ chunkId: messageChunkId(update.messageId), kind: "text", delta: text }];
|
|
25859
25924
|
}
|
|
25860
25925
|
case "agent_thought_chunk": {
|
|
25861
|
-
const text =
|
|
25926
|
+
const text = extractText4(update.content);
|
|
25862
25927
|
if (!text) return [];
|
|
25863
25928
|
return [
|
|
25864
25929
|
{
|
|
@@ -25923,7 +25988,7 @@ function messageChunkId(messageId) {
|
|
|
25923
25988
|
if (typeof messageId === "string" && messageId.length > 0) return messageId;
|
|
25924
25989
|
return (0, import_node_crypto6.randomUUID)();
|
|
25925
25990
|
}
|
|
25926
|
-
function
|
|
25991
|
+
function extractText4(content) {
|
|
25927
25992
|
if (!content || typeof content !== "object") return null;
|
|
25928
25993
|
if ("type" in content && content.type === "text") {
|
|
25929
25994
|
const t2 = content.text;
|
|
@@ -25953,7 +26018,7 @@ function describeToolCallUpdate(update) {
|
|
|
25953
26018
|
for (const item of update.content) {
|
|
25954
26019
|
if (!item || typeof item !== "object") continue;
|
|
25955
26020
|
if (item.type === "content" && item.content) {
|
|
25956
|
-
const text =
|
|
26021
|
+
const text = extractText4(item.content);
|
|
25957
26022
|
if (text) parts.push(text);
|
|
25958
26023
|
} else if (item.type === "diff") {
|
|
25959
26024
|
const p2 = item.path;
|
|
@@ -29131,6 +29196,9 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
29131
29196
|
}
|
|
29132
29197
|
|
|
29133
29198
|
// src/baton/gate.ts
|
|
29199
|
+
function runtimeSupportsBaton(runtime) {
|
|
29200
|
+
return typeof runtime.resolveHistoryFile === "function";
|
|
29201
|
+
}
|
|
29134
29202
|
function isLocalSession(env = process.env) {
|
|
29135
29203
|
return env.CODESPACES !== "true" && env.CODEAM_AUTO_APPROVE !== "1" && env.HEADROOM_ENABLED !== "1" && !env.CODEAM_AUTO_TOKEN && !env.CODEAM_ENROLL_TOKEN;
|
|
29136
29204
|
}
|
|
@@ -29911,7 +29979,8 @@ async function start(requestedAgent) {
|
|
|
29911
29979
|
}
|
|
29912
29980
|
if (isLocalSession() && requiresAcp(session.agent)) {
|
|
29913
29981
|
const adapter = getAcpAdapter(session.agent);
|
|
29914
|
-
|
|
29982
|
+
const batonCapable = runtimeSupportsBaton(createRuntimeStrategy(session.agent));
|
|
29983
|
+
if (batonCapable && adapter && session.pluginAuthToken) {
|
|
29915
29984
|
await runBatonSession({
|
|
29916
29985
|
agent: session.agent,
|
|
29917
29986
|
sessionId: session.id,
|
|
@@ -32672,7 +32741,7 @@ function checkChokidar() {
|
|
|
32672
32741
|
}
|
|
32673
32742
|
async function doctor(args2 = []) {
|
|
32674
32743
|
const json = args2.includes("--json");
|
|
32675
|
-
const cliVersion = true ? "2.60.
|
|
32744
|
+
const cliVersion = true ? "2.60.5" : "0.0.0-dev";
|
|
32676
32745
|
const apiBase2 = resolveApiBaseUrl();
|
|
32677
32746
|
const diagnosticId = (0, import_node_crypto9.randomUUID)();
|
|
32678
32747
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -32871,7 +32940,7 @@ async function completion(args2) {
|
|
|
32871
32940
|
// src/commands/version.ts
|
|
32872
32941
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
32873
32942
|
function version2() {
|
|
32874
|
-
const v = true ? "2.60.
|
|
32943
|
+
const v = true ? "2.60.5" : "unknown";
|
|
32875
32944
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
32876
32945
|
}
|
|
32877
32946
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.60.
|
|
3
|
+
"version": "2.60.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",
|