codeam-cli 2.60.51 → 2.60.52
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 +10 -0
- package/dist/index.js +61 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ 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.51] — 2026-07-12
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Recover kimi ACP 'Session is closed' by re-establishing the session + retry (multi-turn)
|
|
12
|
+
|
|
13
|
+
### Tests
|
|
14
|
+
|
|
15
|
+
- **cli:** Reusable ACP-provision smoke harness (per-agent real handshake auth check; automates CLAUDE.md Step 8)
|
|
16
|
+
|
|
7
17
|
## [2.60.50] — 2026-07-11
|
|
8
18
|
|
|
9
19
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -478,13 +478,27 @@ function headroomKindFor(agentId) {
|
|
|
478
478
|
// ../../packages/shared/src/integrations/registry.ts
|
|
479
479
|
var INTEGRATION_REGISTRY = {
|
|
480
480
|
jira: {
|
|
481
|
+
// Registry id kept 'jira' for id-stability (existing LinkedIntegration rows
|
|
482
|
+
// stay valid — zero data migration); only the DISPLAY is "Atlassian". The
|
|
483
|
+
// one mcp-atlassian server serves BOTH Jira and Confluence, so the same
|
|
484
|
+
// entry now requests Confluence scopes too.
|
|
481
485
|
id: "jira",
|
|
482
|
-
name: "
|
|
486
|
+
name: "Atlassian",
|
|
483
487
|
icon: "jira",
|
|
484
488
|
enabled: true,
|
|
485
489
|
auth: {
|
|
486
490
|
kind: "oauth_redirect",
|
|
487
|
-
scopes
|
|
491
|
+
// Jira + Confluence 3LO granular scopes. The Confluence pair
|
|
492
|
+
// (read:confluence-content.all / write:confluence-content) is the set
|
|
493
|
+
// mcp-atlassian's own Authentication docs recommend for full read+write
|
|
494
|
+
// Confluence (matches its documented env scope string).
|
|
495
|
+
scopes: [
|
|
496
|
+
"read:jira-work",
|
|
497
|
+
"write:jira-work",
|
|
498
|
+
"read:confluence-content.all",
|
|
499
|
+
"write:confluence-content",
|
|
500
|
+
"offline_access"
|
|
501
|
+
]
|
|
488
502
|
},
|
|
489
503
|
delivery: {
|
|
490
504
|
mcp: {
|
|
@@ -5733,7 +5747,7 @@ function readAnonId() {
|
|
|
5733
5747
|
}
|
|
5734
5748
|
function superProperties() {
|
|
5735
5749
|
return {
|
|
5736
|
-
cliVersion: true ? "2.60.
|
|
5750
|
+
cliVersion: true ? "2.60.52" : "0.0.0-dev",
|
|
5737
5751
|
nodeVersion: process.version,
|
|
5738
5752
|
platform: process.platform,
|
|
5739
5753
|
arch: process.arch,
|
|
@@ -5914,7 +5928,7 @@ var os4 = __toESM(require("os"));
|
|
|
5914
5928
|
// package.json
|
|
5915
5929
|
var package_default = {
|
|
5916
5930
|
name: "codeam-cli",
|
|
5917
|
-
version: "2.60.
|
|
5931
|
+
version: "2.60.52",
|
|
5918
5932
|
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.",
|
|
5919
5933
|
type: "commonjs",
|
|
5920
5934
|
main: "dist/index.js",
|
|
@@ -7023,7 +7037,7 @@ var CommandRelayService = class {
|
|
|
7023
7037
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
7024
7038
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
7025
7039
|
// pair/reconnect). Older backends ignore the extra field.
|
|
7026
|
-
..."2.60.
|
|
7040
|
+
..."2.60.52" ? { ideVersion: "2.60.52" } : {}
|
|
7027
7041
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
7028
7042
|
}
|
|
7029
7043
|
/**
|
|
@@ -17592,7 +17606,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
17592
17606
|
if (process.env.NODE_ENV === "test") return;
|
|
17593
17607
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17594
17608
|
if (process.env.CI) return;
|
|
17595
|
-
const current = true ? "2.60.
|
|
17609
|
+
const current = true ? "2.60.52" : null;
|
|
17596
17610
|
if (!current) return;
|
|
17597
17611
|
const cache = readCache();
|
|
17598
17612
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17609,7 +17623,7 @@ function checkForUpdates() {
|
|
|
17609
17623
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17610
17624
|
if (process.env.CI) return;
|
|
17611
17625
|
if (!process.stdout.isTTY) return;
|
|
17612
|
-
const current = true ? "2.60.
|
|
17626
|
+
const current = true ? "2.60.52" : null;
|
|
17613
17627
|
if (!current) return;
|
|
17614
17628
|
const cache = readCache();
|
|
17615
17629
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17629,7 +17643,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
17629
17643
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
17630
17644
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
17631
17645
|
function currentCliVersion() {
|
|
17632
|
-
return true ? "2.60.
|
|
17646
|
+
return true ? "2.60.52" : null;
|
|
17633
17647
|
}
|
|
17634
17648
|
function runCmd(cmd, args2, timeoutMs) {
|
|
17635
17649
|
return new Promise((resolve7) => {
|
|
@@ -27136,13 +27150,22 @@ var AcpClient = class {
|
|
|
27136
27150
|
* on the SAME still-running adapter process, so the pending prompt can be
|
|
27137
27151
|
* retried. Prefers `session/load` (resume) when the agent advertised
|
|
27138
27152
|
* `loadSession` — proven live to re-open kimi's closed session with the
|
|
27139
|
-
* conversation context intact
|
|
27140
|
-
*
|
|
27141
|
-
*
|
|
27142
|
-
*
|
|
27143
|
-
*
|
|
27144
|
-
*
|
|
27145
|
-
* `session/
|
|
27153
|
+
* conversation context intact. Calls `connection.loadSession` DIRECTLY — the
|
|
27154
|
+
* public {@link loadSession} skips a same-id load (a Claude relaunch-wedge
|
|
27155
|
+
* guard), which is exactly the load we MUST perform here (the closed id IS the
|
|
27156
|
+
* active id). Falls back to a fresh `session/new` (context lost) only when the
|
|
27157
|
+
* agent can't resume.
|
|
27158
|
+
*
|
|
27159
|
+
* ⚠️ kimi's `session/load` (0.23.6, live-verified) REPLAYS the ENTIRE prior
|
|
27160
|
+
* conversation as `session/update` notifications BEFORE it resolves — the
|
|
27161
|
+
* earlier assumption that it emitted no replay was wrong and caused a P0: the
|
|
27162
|
+
* replayed prior-turn text was published as live chunks and prepended to the
|
|
27163
|
+
* recovered turn's real reply. So the load is bracketed with
|
|
27164
|
+
* `beginLoadReplay()/endLoadReplay()` (wired by the runner to StreamingState)
|
|
27165
|
+
* so those replay updates are swallowed, exactly like the baton's load. The
|
|
27166
|
+
* retried `session/prompt` (after the load resolves) then streams the REAL new
|
|
27167
|
+
* reply cleanly. The `finally` guarantees the guard clears even if the load
|
|
27168
|
+
* throws, so a failed recovery can't wedge streaming off.
|
|
27146
27169
|
*/
|
|
27147
27170
|
async reestablishSession() {
|
|
27148
27171
|
if (!this.connection) throw new Error("AcpClient.reestablishSession: no connection");
|
|
@@ -27151,7 +27174,12 @@ var AcpClient = class {
|
|
|
27151
27174
|
const closedSid = this.sessionId;
|
|
27152
27175
|
if (this.supportsLoadSession && closedSid) {
|
|
27153
27176
|
log.info("acpClient", `reestablish \u2192 loadSession(resume) sid=${closedSid.slice(0, 8)}`);
|
|
27154
|
-
|
|
27177
|
+
this.opts.beginLoadReplay?.();
|
|
27178
|
+
try {
|
|
27179
|
+
await this.connection.loadSession({ sessionId: closedSid, cwd, mcpServers });
|
|
27180
|
+
} finally {
|
|
27181
|
+
this.opts.endLoadReplay?.();
|
|
27182
|
+
}
|
|
27155
27183
|
log.info("acpClient", "reestablish \u2190 loadSession ok");
|
|
27156
27184
|
return;
|
|
27157
27185
|
}
|
|
@@ -30048,6 +30076,13 @@ async function runAcpSession(opts) {
|
|
|
30048
30076
|
streaming.append(delta);
|
|
30049
30077
|
}
|
|
30050
30078
|
},
|
|
30079
|
+
// kimi post-turn "Session is closed" recovery brackets its `session/load`
|
|
30080
|
+
// with these so the conversation history the load REPLAYS as session/update
|
|
30081
|
+
// notifications is swallowed by StreamingState instead of published as live
|
|
30082
|
+
// chunks (which prepended a prior turn's text to the recovered reply — P0).
|
|
30083
|
+
// Same guard the baton uses; the happy path never calls loadSession.
|
|
30084
|
+
beginLoadReplay: () => streaming.beginLoadReplay(),
|
|
30085
|
+
endLoadReplay: () => streaming.endLoadReplay(),
|
|
30051
30086
|
onRequestPermission: async (request) => {
|
|
30052
30087
|
if (opts.autoApprovePermissions) {
|
|
30053
30088
|
const allow = pickAllowOption(request.options);
|
|
@@ -31845,6 +31880,14 @@ async function runBatonSession(opts) {
|
|
|
31845
31880
|
onSessionUpdate: (notification) => {
|
|
31846
31881
|
for (const delta of mapSessionUpdate(notification)) streaming.append(delta);
|
|
31847
31882
|
},
|
|
31883
|
+
// Swallow the ACP session/load history replay during the kimi "Session is
|
|
31884
|
+
// closed" recovery (AcpClient.reestablishSession) — kimi 0.23.6 replays the
|
|
31885
|
+
// whole conversation as session/update, which would otherwise prepend a
|
|
31886
|
+
// prior turn's text to the recovered reply on the baton's mobile stream too
|
|
31887
|
+
// (same leak the plain ACP runner wires at runner.ts). Same `streaming`
|
|
31888
|
+
// instance the baton's own AcpDriver.start bracketing uses.
|
|
31889
|
+
beginLoadReplay: () => streaming.beginLoadReplay(),
|
|
31890
|
+
endLoadReplay: () => streaming.endLoadReplay(),
|
|
31848
31891
|
onRequestPermission: async (request) => {
|
|
31849
31892
|
const { event, optionIdByLabel } = mapPermissionRequest(request);
|
|
31850
31893
|
await publisher.publishAwaitingAnswer(event);
|
|
@@ -34928,7 +34971,7 @@ function checkChokidar() {
|
|
|
34928
34971
|
}
|
|
34929
34972
|
async function doctor(args2 = []) {
|
|
34930
34973
|
const json = args2.includes("--json");
|
|
34931
|
-
const cliVersion = true ? "2.60.
|
|
34974
|
+
const cliVersion = true ? "2.60.52" : "0.0.0-dev";
|
|
34932
34975
|
const apiBase2 = resolveApiBaseUrl();
|
|
34933
34976
|
const diagnosticId = (0, import_node_crypto12.randomUUID)();
|
|
34934
34977
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -35405,7 +35448,7 @@ async function mcpRun(args2) {
|
|
|
35405
35448
|
// src/commands/version.ts
|
|
35406
35449
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
35407
35450
|
function version2() {
|
|
35408
|
-
const v = true ? "2.60.
|
|
35451
|
+
const v = true ? "2.60.52" : "unknown";
|
|
35409
35452
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
35410
35453
|
}
|
|
35411
35454
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.60.
|
|
3
|
+
"version": "2.60.52",
|
|
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",
|