codeam-cli 2.75.10 → 2.75.12
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 +111 -19
- 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.75.11] — 2026-09-24
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Bound streaming-chunk snapshots under the API cap and coalesce big re-sends
|
|
12
|
+
|
|
13
|
+
## [2.75.10] — 2026-09-23
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Guardrails judge a write by its target; pack stage shows a mid-turn permission as awaiting
|
|
18
|
+
|
|
7
19
|
## [2.75.9] — 2026-09-23
|
|
8
20
|
|
|
9
21
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -10509,7 +10509,7 @@ function readAnonId() {
|
|
|
10509
10509
|
}
|
|
10510
10510
|
function superProperties() {
|
|
10511
10511
|
return {
|
|
10512
|
-
cliVersion: true ? "2.75.
|
|
10512
|
+
cliVersion: true ? "2.75.12" : "0.0.0-dev",
|
|
10513
10513
|
nodeVersion: process.version,
|
|
10514
10514
|
platform: process.platform,
|
|
10515
10515
|
arch: process.arch,
|
|
@@ -10751,7 +10751,7 @@ var http = __toESM(require("http"));
|
|
|
10751
10751
|
// package.json
|
|
10752
10752
|
var package_default = {
|
|
10753
10753
|
name: "codeam-cli",
|
|
10754
|
-
version: "2.75.
|
|
10754
|
+
version: "2.75.12",
|
|
10755
10755
|
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.",
|
|
10756
10756
|
type: "commonjs",
|
|
10757
10757
|
main: "dist/index.js",
|
|
@@ -12081,7 +12081,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12081
12081
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12082
12082
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12083
12083
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12084
|
-
..."2.75.
|
|
12084
|
+
..."2.75.12" ? { ideVersion: "2.75.12" } : {}
|
|
12085
12085
|
};
|
|
12086
12086
|
try {
|
|
12087
12087
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body);
|
|
@@ -18511,6 +18511,9 @@ function resolveHistoryDir2(_cwd, homeOverride) {
|
|
|
18511
18511
|
if (!import_node_fs3.default.existsSync(todayDir)) return null;
|
|
18512
18512
|
return todayDir;
|
|
18513
18513
|
}
|
|
18514
|
+
function isHeadlessOneShotMeta(meta) {
|
|
18515
|
+
return meta.source === "exec" || meta.originator === "codex_exec";
|
|
18516
|
+
}
|
|
18514
18517
|
function parseLine(line) {
|
|
18515
18518
|
try {
|
|
18516
18519
|
const parsed = JSON.parse(line);
|
|
@@ -18790,6 +18793,7 @@ function newestRolloutIdSince(sessionsRoot, resolvedCwd, floorMs) {
|
|
|
18790
18793
|
if (mtime < floorMs || mtime <= bestMtime) continue;
|
|
18791
18794
|
let metaCwd;
|
|
18792
18795
|
let metaId;
|
|
18796
|
+
let headlessOneShot = false;
|
|
18793
18797
|
try {
|
|
18794
18798
|
const raw = import_node_fs3.default.readFileSync(filePath, "utf8");
|
|
18795
18799
|
for (const line of raw.split("\n")) {
|
|
@@ -18800,13 +18804,14 @@ function newestRolloutIdSince(sessionsRoot, resolvedCwd, floorMs) {
|
|
|
18800
18804
|
const meta = rec.payload;
|
|
18801
18805
|
metaCwd = typeof meta?.cwd === "string" ? meta.cwd : void 0;
|
|
18802
18806
|
metaId = typeof meta?.id === "string" ? meta.id : void 0;
|
|
18807
|
+
headlessOneShot = meta !== void 0 && isHeadlessOneShotMeta(meta);
|
|
18803
18808
|
}
|
|
18804
18809
|
break;
|
|
18805
18810
|
}
|
|
18806
18811
|
} catch {
|
|
18807
18812
|
continue;
|
|
18808
18813
|
}
|
|
18809
|
-
if (!metaId || !metaCwd) continue;
|
|
18814
|
+
if (!metaId || !metaCwd || headlessOneShot) continue;
|
|
18810
18815
|
let resolvedMeta;
|
|
18811
18816
|
try {
|
|
18812
18817
|
resolvedMeta = import_node_fs3.default.realpathSync(metaCwd);
|
|
@@ -27496,6 +27501,26 @@ var emitPreviewEvent = (args2) => {
|
|
|
27496
27501
|
payload: { ...args2.payload ?? {}, missingServices: missing }
|
|
27497
27502
|
});
|
|
27498
27503
|
};
|
|
27504
|
+
var PREVIEW_DETECT_TIMEOUT_MS = 12e4;
|
|
27505
|
+
async function runDetectOneShot(generate, timeoutMs = PREVIEW_DETECT_TIMEOUT_MS) {
|
|
27506
|
+
let timer;
|
|
27507
|
+
const deadline = new Promise((resolve11) => {
|
|
27508
|
+
timer = setTimeout(() => resolve11({ raw: null, timedOut: true }), timeoutMs);
|
|
27509
|
+
timer.unref?.();
|
|
27510
|
+
});
|
|
27511
|
+
const oneShot = generate(PREVIEW_DETECT_PROMPT, { timeoutMs }).then(
|
|
27512
|
+
(raw) => ({ raw, timedOut: false }),
|
|
27513
|
+
(err) => {
|
|
27514
|
+
log.info("preview", `detect: generateOneShot threw: ${String(err)}`);
|
|
27515
|
+
return { raw: null, timedOut: false };
|
|
27516
|
+
}
|
|
27517
|
+
);
|
|
27518
|
+
try {
|
|
27519
|
+
return await Promise.race([oneShot, deadline]);
|
|
27520
|
+
} finally {
|
|
27521
|
+
if (timer) clearTimeout(timer);
|
|
27522
|
+
}
|
|
27523
|
+
}
|
|
27499
27524
|
var requestPreviewDetectH = (ctx) => {
|
|
27500
27525
|
if (!ctx.pluginAuthToken) {
|
|
27501
27526
|
log.info("preview", "no pluginAuthToken \u2014 skipping detect");
|
|
@@ -27516,6 +27541,7 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
27516
27541
|
return;
|
|
27517
27542
|
}
|
|
27518
27543
|
const pluginAuthToken = ctx.pluginAuthToken;
|
|
27544
|
+
const generateOneShot = ctx.runtime.generateOneShot.bind(ctx.runtime);
|
|
27519
27545
|
void (async () => {
|
|
27520
27546
|
const fromFile = await readPreviewConfig(process.cwd());
|
|
27521
27547
|
if (fromFile) {
|
|
@@ -27537,11 +27563,22 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
27537
27563
|
});
|
|
27538
27564
|
log.info("preview", "detect: invoking generateOneShot");
|
|
27539
27565
|
const startedAt = Date.now();
|
|
27540
|
-
const raw = await
|
|
27541
|
-
log.info("preview", `detect: generateOneShot threw: ${String(err)}`);
|
|
27542
|
-
return null;
|
|
27543
|
-
});
|
|
27566
|
+
const { raw, timedOut } = await runDetectOneShot(generateOneShot);
|
|
27544
27567
|
const tookMs = Date.now() - startedAt;
|
|
27568
|
+
if (timedOut) {
|
|
27569
|
+
log.info("preview", `detect: timed out after ${tookMs}ms \u2014 emitting preview_error`);
|
|
27570
|
+
emitPreviewEvent({
|
|
27571
|
+
sessionId: ctx.sessionId,
|
|
27572
|
+
pluginId: ctx.pluginId,
|
|
27573
|
+
pluginAuthToken,
|
|
27574
|
+
type: USER_EVENTS.PREVIEW_ERROR,
|
|
27575
|
+
payload: {
|
|
27576
|
+
stage: "detection",
|
|
27577
|
+
message: `Project detection timed out after ${Math.round(PREVIEW_DETECT_TIMEOUT_MS / 1e3)} s \u2014 the agent did not answer. Try again, or add a .codeam/preview.json override.`
|
|
27578
|
+
}
|
|
27579
|
+
});
|
|
27580
|
+
return;
|
|
27581
|
+
}
|
|
27545
27582
|
const detection = safeParseDetection(raw);
|
|
27546
27583
|
if (!detection) {
|
|
27547
27584
|
const failure = describeDetectionFailure(raw);
|
|
@@ -27622,11 +27659,12 @@ function prewarmPreviewDetection(runtime) {
|
|
|
27622
27659
|
if (previewPrewarmStarted) return;
|
|
27623
27660
|
previewPrewarmStarted = true;
|
|
27624
27661
|
if (typeof runtime.generateOneShot !== "function") return;
|
|
27662
|
+
const generateOneShot = runtime.generateOneShot.bind(runtime);
|
|
27625
27663
|
void (async () => {
|
|
27626
27664
|
try {
|
|
27627
27665
|
const cwd = process.cwd();
|
|
27628
27666
|
if (await readPreviewConfig(cwd)) return;
|
|
27629
|
-
const raw = await
|
|
27667
|
+
const { raw } = await runDetectOneShot(generateOneShot);
|
|
27630
27668
|
const detection = safeParseDetection(raw);
|
|
27631
27669
|
if (!detection) {
|
|
27632
27670
|
const failure = describeDetectionFailure(raw);
|
|
@@ -35576,6 +35614,18 @@ function _get(url2, headers) {
|
|
|
35576
35614
|
}
|
|
35577
35615
|
|
|
35578
35616
|
// src/agents/acp/publisher.ts
|
|
35617
|
+
var STREAMING_CHUNK_SNAPSHOT_MAX_CHARS = 56 * 1024;
|
|
35618
|
+
var STREAMING_CHUNK_COALESCE_MIN_CHARS = 8 * 1024;
|
|
35619
|
+
var STREAMING_CHUNK_COALESCE_WINDOW_MS = 300;
|
|
35620
|
+
function boundStreamingChunkContent(content, max = STREAMING_CHUNK_SNAPSHOT_MAX_CHARS) {
|
|
35621
|
+
if (content.length <= max) return { content, truncated: false };
|
|
35622
|
+
const dropped = content.length - max;
|
|
35623
|
+
return {
|
|
35624
|
+
content: `${content.slice(0, max)}
|
|
35625
|
+
\u2026 [output truncated: ${dropped} more characters \u2014 the full text is in the conversation transcript]`,
|
|
35626
|
+
truncated: true
|
|
35627
|
+
};
|
|
35628
|
+
}
|
|
35579
35629
|
var AcpPublisher = class {
|
|
35580
35630
|
constructor(opts) {
|
|
35581
35631
|
this.opts = opts;
|
|
@@ -35585,6 +35635,11 @@ var AcpPublisher = class {
|
|
|
35585
35635
|
opts;
|
|
35586
35636
|
apiBase;
|
|
35587
35637
|
token;
|
|
35638
|
+
/** chunkIds whose truncated snapshot already went out — nothing new to show
|
|
35639
|
+
* until the terminal frame. */
|
|
35640
|
+
truncatedChunks = /* @__PURE__ */ new Set();
|
|
35641
|
+
lastChunkPostAt = /* @__PURE__ */ new Map();
|
|
35642
|
+
pendingChunkPosts = /* @__PURE__ */ new Map();
|
|
35588
35643
|
/** Latched on an unrecoverable 401/403 — every surface stops posting
|
|
35589
35644
|
* (2026-06-28 incident: a dead-token publisher spammed 401 ×34 while
|
|
35590
35645
|
* the agent's replies silently never reached the phone). */
|
|
@@ -35613,7 +35668,10 @@ var AcpPublisher = class {
|
|
|
35613
35668
|
const fresh = await this.opts.refreshAuthToken();
|
|
35614
35669
|
if (fresh) {
|
|
35615
35670
|
this.token = fresh;
|
|
35616
|
-
log.info(
|
|
35671
|
+
log.info(
|
|
35672
|
+
"acpPublisher",
|
|
35673
|
+
`plugin-auth token refreshed after ${first.statusCode}; retrying POST`
|
|
35674
|
+
);
|
|
35617
35675
|
const second = await _transport4.post(url2, this.authHeaders(), payload);
|
|
35618
35676
|
if (second.statusCode !== 401 && second.statusCode !== 403) return second;
|
|
35619
35677
|
this.markPairingInvalid(second.statusCode);
|
|
@@ -35722,17 +35780,51 @@ var AcpPublisher = class {
|
|
|
35722
35780
|
* richer SessionDetail surface.
|
|
35723
35781
|
*/
|
|
35724
35782
|
async publishStreamingChunk(event) {
|
|
35783
|
+
const { chunkId, isFinal } = event;
|
|
35784
|
+
const pending = this.pendingChunkPosts.get(chunkId);
|
|
35785
|
+
if (pending) {
|
|
35786
|
+
clearTimeout(pending.timer);
|
|
35787
|
+
this.pendingChunkPosts.delete(chunkId);
|
|
35788
|
+
}
|
|
35789
|
+
const bounded = boundStreamingChunkContent(event.content);
|
|
35790
|
+
if (bounded.truncated) {
|
|
35791
|
+
if (!isFinal && this.truncatedChunks.has(chunkId)) return;
|
|
35792
|
+
if (!this.truncatedChunks.has(chunkId)) {
|
|
35793
|
+
log.warn(
|
|
35794
|
+
"acpPublisher",
|
|
35795
|
+
`streaming-chunk ${chunkId.slice(0, 12)} (${event.kind}) exceeds ${STREAMING_CHUNK_SNAPSHOT_MAX_CHARS} chars \u2014 sending a truncated snapshot once`
|
|
35796
|
+
);
|
|
35797
|
+
}
|
|
35798
|
+
this.truncatedChunks.add(chunkId);
|
|
35799
|
+
}
|
|
35800
|
+
if (isFinal) {
|
|
35801
|
+
this.truncatedChunks.delete(chunkId);
|
|
35802
|
+
this.lastChunkPostAt.delete(chunkId);
|
|
35803
|
+
} else if (!bounded.truncated && bounded.content.length >= STREAMING_CHUNK_COALESCE_MIN_CHARS) {
|
|
35804
|
+
const last = this.lastChunkPostAt.get(chunkId) ?? 0;
|
|
35805
|
+
const wait = STREAMING_CHUNK_COALESCE_WINDOW_MS - (Date.now() - last);
|
|
35806
|
+
if (wait > 0) {
|
|
35807
|
+
const timer = setTimeout(() => {
|
|
35808
|
+
const latest = this.pendingChunkPosts.get(chunkId);
|
|
35809
|
+
this.pendingChunkPosts.delete(chunkId);
|
|
35810
|
+
if (latest) void this.postStreamingChunk(latest.event);
|
|
35811
|
+
}, wait);
|
|
35812
|
+
this.pendingChunkPosts.set(chunkId, { timer, event });
|
|
35813
|
+
return;
|
|
35814
|
+
}
|
|
35815
|
+
}
|
|
35816
|
+
await this.postStreamingChunk({ ...event, content: bounded.content });
|
|
35817
|
+
}
|
|
35818
|
+
async postStreamingChunk(event) {
|
|
35725
35819
|
const url2 = `${this.apiBase}/api/sessions/${encodeURIComponent(this.opts.sessionId)}/streaming-chunk`;
|
|
35820
|
+
if (!event.isFinal) this.lastChunkPostAt.set(event.chunkId, Date.now());
|
|
35726
35821
|
try {
|
|
35727
35822
|
const { statusCode, body } = await this.postWithReauth(
|
|
35728
35823
|
url2,
|
|
35729
35824
|
this.envelope(event)
|
|
35730
35825
|
);
|
|
35731
35826
|
if (statusCode < 200 || statusCode >= 300) {
|
|
35732
|
-
log.warn(
|
|
35733
|
-
"acpPublisher",
|
|
35734
|
-
`streaming-chunk status=${statusCode} body=${body.slice(0, 200)}`
|
|
35735
|
-
);
|
|
35827
|
+
log.warn("acpPublisher", `streaming-chunk status=${statusCode} body=${body.slice(0, 200)}`);
|
|
35736
35828
|
}
|
|
35737
35829
|
} catch (err) {
|
|
35738
35830
|
log.trace("acpPublisher", "streaming-chunk post failed", err);
|
|
@@ -47060,7 +47152,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
47060
47152
|
if (process.env.NODE_ENV === "test") return;
|
|
47061
47153
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
47062
47154
|
if (process.env.CI) return;
|
|
47063
|
-
const current2 = true ? "2.75.
|
|
47155
|
+
const current2 = true ? "2.75.12" : null;
|
|
47064
47156
|
if (!current2) return;
|
|
47065
47157
|
const cache = readCache();
|
|
47066
47158
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -47077,7 +47169,7 @@ function checkForUpdates() {
|
|
|
47077
47169
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
47078
47170
|
if (process.env.CI) return;
|
|
47079
47171
|
if (!process.stdout.isTTY) return;
|
|
47080
|
-
const current2 = true ? "2.75.
|
|
47172
|
+
const current2 = true ? "2.75.12" : null;
|
|
47081
47173
|
if (!current2) return;
|
|
47082
47174
|
const cache = readCache();
|
|
47083
47175
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -47100,7 +47192,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
47100
47192
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
47101
47193
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
47102
47194
|
function currentCliVersion() {
|
|
47103
|
-
return true ? "2.75.
|
|
47195
|
+
return true ? "2.75.12" : null;
|
|
47104
47196
|
}
|
|
47105
47197
|
async function installedVersion(deps) {
|
|
47106
47198
|
const ls = await deps.run(
|
|
@@ -48840,7 +48932,7 @@ function checkChokidar() {
|
|
|
48840
48932
|
}
|
|
48841
48933
|
async function doctor(args2 = []) {
|
|
48842
48934
|
const json = args2.includes("--json");
|
|
48843
|
-
const cliVersion = true ? "2.75.
|
|
48935
|
+
const cliVersion = true ? "2.75.12" : "0.0.0-dev";
|
|
48844
48936
|
const apiBase2 = resolveApiBaseUrl();
|
|
48845
48937
|
const diagnosticId = (0, import_node_crypto12.randomUUID)();
|
|
48846
48938
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -49364,7 +49456,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
49364
49456
|
// src/commands/version.ts
|
|
49365
49457
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
49366
49458
|
function version2() {
|
|
49367
|
-
const v = true ? "2.75.
|
|
49459
|
+
const v = true ? "2.75.12" : "unknown";
|
|
49368
49460
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
49369
49461
|
}
|
|
49370
49462
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.75.
|
|
3
|
+
"version": "2.75.12",
|
|
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",
|