codeam-cli 2.23.29 → 2.23.31
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 +28 -0
- package/dist/index.js +104 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,34 @@ 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.23.30] — 2026-05-30
|
|
8
|
+
|
|
9
|
+
### Chore
|
|
10
|
+
|
|
11
|
+
- **cli:** Info-level logging for AI summary/insight pipeline
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **cli:** DetectInputSuggestion skips Claude TUI box borders
|
|
16
|
+
|
|
17
|
+
## [2.23.29] — 2026-05-30
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **cli:** DetectInputSuggestion skips Claude TUI box borders
|
|
22
|
+
|
|
23
|
+
## [2.23.28] — 2026-05-30
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **cli:** Gate idle-suggestion seed on per-agent opt-in
|
|
28
|
+
|
|
29
|
+
## [2.23.27] — 2026-05-30
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **cli:** Seed idle-suggestion detector with the established screen
|
|
34
|
+
|
|
7
35
|
## [2.23.26] — 2026-05-30
|
|
8
36
|
|
|
9
37
|
### Chore
|
package/dist/index.js
CHANGED
|
@@ -441,7 +441,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
441
441
|
// package.json
|
|
442
442
|
var package_default = {
|
|
443
443
|
name: "codeam-cli",
|
|
444
|
-
version: "2.23.
|
|
444
|
+
version: "2.23.31",
|
|
445
445
|
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.",
|
|
446
446
|
type: "commonjs",
|
|
447
447
|
main: "dist/index.js",
|
|
@@ -5774,7 +5774,7 @@ function readAnonId() {
|
|
|
5774
5774
|
}
|
|
5775
5775
|
function superProperties() {
|
|
5776
5776
|
return {
|
|
5777
|
-
cliVersion: true ? "2.23.
|
|
5777
|
+
cliVersion: true ? "2.23.31" : "0.0.0-dev",
|
|
5778
5778
|
nodeVersion: process.version,
|
|
5779
5779
|
platform: process.platform,
|
|
5780
5780
|
arch: process.arch,
|
|
@@ -13611,6 +13611,28 @@ var TurnFileAggregator = class {
|
|
|
13611
13611
|
repos = [];
|
|
13612
13612
|
discovering = null;
|
|
13613
13613
|
stopped = false;
|
|
13614
|
+
/**
|
|
13615
|
+
* Pre-pair worktree baseline. Captured lazily on the first
|
|
13616
|
+
* `flushTurn()` call by running the same `git status` / `git diff`
|
|
13617
|
+
* scan the regular flush uses, then stashing the result here
|
|
13618
|
+
* WITHOUT enqueuing the outbox. Every subsequent flush diff-checks
|
|
13619
|
+
* its entries against this map and only emits files that are
|
|
13620
|
+
* absent from the baseline OR whose `linesAdded` / `linesRemoved`
|
|
13621
|
+
* have moved.
|
|
13622
|
+
*
|
|
13623
|
+
* Why: the legacy first-flush behaviour shipped the entire dirty
|
|
13624
|
+
* worktree at session start, which attributed pre-existing
|
|
13625
|
+
* uncommitted edits to the brand-new sessionId (and confusingly
|
|
13626
|
+
* showed them on the new session's rail with zero hunks, because
|
|
13627
|
+
* the chokidar watcher never saw the changes — they happened
|
|
13628
|
+
* before the watcher booted). Capturing the baseline silently
|
|
13629
|
+
* keeps the rail honest: it now means "files THIS session changed".
|
|
13630
|
+
*
|
|
13631
|
+
* Key is `${repoPath}|${filePath}` so a sibling repo with the same
|
|
13632
|
+
* relative path doesn't collide with another one.
|
|
13633
|
+
*/
|
|
13634
|
+
baselineByKey = /* @__PURE__ */ new Map();
|
|
13635
|
+
baselineCaptured = false;
|
|
13614
13636
|
/** Stop the outbox scheduler. Idempotent. */
|
|
13615
13637
|
stop() {
|
|
13616
13638
|
this.stopped = true;
|
|
@@ -13642,11 +13664,28 @@ var TurnFileAggregator = class {
|
|
|
13642
13664
|
const entries = await collectRepoChangeset(repo);
|
|
13643
13665
|
if (entries) files.push(...entries);
|
|
13644
13666
|
}
|
|
13645
|
-
if (
|
|
13646
|
-
|
|
13667
|
+
if (!this.baselineCaptured) {
|
|
13668
|
+
this.baselineByKey = new Map(files.map((f) => [baselineKey(f), f]));
|
|
13669
|
+
this.baselineCaptured = true;
|
|
13670
|
+
log.info(
|
|
13671
|
+
"turnFiles",
|
|
13672
|
+
`baseline captured: ${files.length} pre-pair file(s) \u2014 suppressing initial POST`
|
|
13673
|
+
);
|
|
13647
13674
|
return;
|
|
13648
13675
|
}
|
|
13649
|
-
const
|
|
13676
|
+
const novel = files.filter((f) => {
|
|
13677
|
+
const base = this.baselineByKey.get(baselineKey(f));
|
|
13678
|
+
if (!base) return true;
|
|
13679
|
+
return base.linesAdded !== f.linesAdded || base.linesRemoved !== f.linesRemoved || base.fileStatus !== f.fileStatus;
|
|
13680
|
+
});
|
|
13681
|
+
if (novel.length === 0) {
|
|
13682
|
+
log.trace(
|
|
13683
|
+
"turnFiles",
|
|
13684
|
+
`flush matched baseline exactly \u2014 skipping POST (scanned=${files.length})`
|
|
13685
|
+
);
|
|
13686
|
+
return;
|
|
13687
|
+
}
|
|
13688
|
+
const chunks = chunkArray(novel, MAX_BATCH_SIZE);
|
|
13650
13689
|
for (const chunk of chunks) {
|
|
13651
13690
|
const entry = {
|
|
13652
13691
|
turnId: (0, import_crypto2.randomUUID)(),
|
|
@@ -13711,6 +13750,9 @@ function chunkArray(arr, size) {
|
|
|
13711
13750
|
}
|
|
13712
13751
|
return out2;
|
|
13713
13752
|
}
|
|
13753
|
+
function baselineKey(entry) {
|
|
13754
|
+
return `${entry.repoPath}|${entry.filePath}`;
|
|
13755
|
+
}
|
|
13714
13756
|
|
|
13715
13757
|
// src/services/turn-files/repo-dirty-tracker.ts
|
|
13716
13758
|
var RepoDirtyTracker = class {
|
|
@@ -15893,10 +15935,19 @@ var requestLinkCredentialsH = (ctx, _cmd, parsed) => {
|
|
|
15893
15935
|
})();
|
|
15894
15936
|
};
|
|
15895
15937
|
var requestAiSummaryH = (ctx, _cmd, parsed) => {
|
|
15896
|
-
if (!ctx.pluginAuthToken)
|
|
15897
|
-
|
|
15938
|
+
if (!ctx.pluginAuthToken) {
|
|
15939
|
+
log.info("ai-summary", "no pluginAuthToken \u2014 skipping");
|
|
15940
|
+
return;
|
|
15941
|
+
}
|
|
15942
|
+
if (typeof ctx.runtime.generateOneShot !== "function") {
|
|
15943
|
+
log.info("ai-summary", `runtime ${ctx.runtime.id} has no generateOneShot \u2014 skipping`);
|
|
15944
|
+
return;
|
|
15945
|
+
}
|
|
15898
15946
|
if (!parsed.prompt || !parsed.turnId || !parsed.stats) {
|
|
15899
|
-
log.
|
|
15947
|
+
log.info(
|
|
15948
|
+
"ai-summary",
|
|
15949
|
+
`missing fields \u2014 prompt=${!!parsed.prompt} turnId=${!!parsed.turnId} stats=${!!parsed.stats}`
|
|
15950
|
+
);
|
|
15900
15951
|
return;
|
|
15901
15952
|
}
|
|
15902
15953
|
const prompt = parsed.prompt;
|
|
@@ -15904,12 +15955,19 @@ var requestAiSummaryH = (ctx, _cmd, parsed) => {
|
|
|
15904
15955
|
const stats = parsed.stats;
|
|
15905
15956
|
const pluginAuthToken = ctx.pluginAuthToken;
|
|
15906
15957
|
void (async () => {
|
|
15958
|
+
log.info("ai-summary", `generateOneShot start turnId=${turnId} promptLen=${prompt.length}`);
|
|
15959
|
+
const startedAt = Date.now();
|
|
15907
15960
|
const text = await ctx.runtime.generateOneShot(prompt).catch((err) => {
|
|
15908
|
-
log.
|
|
15961
|
+
log.info("ai-summary", `generateOneShot threw: ${String(err)}`);
|
|
15909
15962
|
return null;
|
|
15910
15963
|
});
|
|
15911
|
-
|
|
15912
|
-
|
|
15964
|
+
const tookMs = Date.now() - startedAt;
|
|
15965
|
+
if (!text) {
|
|
15966
|
+
log.info("ai-summary", `generateOneShot returned null after ${tookMs}ms \u2014 skipping POST`);
|
|
15967
|
+
return;
|
|
15968
|
+
}
|
|
15969
|
+
log.info("ai-summary", `generateOneShot ok turnId=${turnId} took=${tookMs}ms textLen=${text.length}`);
|
|
15970
|
+
const result = await postAiResult({
|
|
15913
15971
|
sessionId: ctx.sessionId,
|
|
15914
15972
|
pluginId: ctx.pluginId,
|
|
15915
15973
|
pluginAuthToken,
|
|
@@ -15918,26 +15976,47 @@ var requestAiSummaryH = (ctx, _cmd, parsed) => {
|
|
|
15918
15976
|
summary: text,
|
|
15919
15977
|
stats
|
|
15920
15978
|
});
|
|
15979
|
+
if (result.ok) {
|
|
15980
|
+
log.info("ai-summary", `postAiResult ok turnId=${turnId}`);
|
|
15981
|
+
} else {
|
|
15982
|
+
log.info("ai-summary", `postAiResult failed status=${result.status} msg=${result.message}`);
|
|
15983
|
+
}
|
|
15921
15984
|
})();
|
|
15922
15985
|
};
|
|
15923
15986
|
var requestAiInsightH = (ctx, _cmd, parsed) => {
|
|
15924
|
-
if (!ctx.pluginAuthToken)
|
|
15925
|
-
|
|
15987
|
+
if (!ctx.pluginAuthToken) {
|
|
15988
|
+
log.info("ai-insight", "no pluginAuthToken \u2014 skipping");
|
|
15989
|
+
return;
|
|
15990
|
+
}
|
|
15991
|
+
if (typeof ctx.runtime.generateOneShot !== "function") {
|
|
15992
|
+
log.info("ai-insight", `runtime ${ctx.runtime.id} has no generateOneShot \u2014 skipping`);
|
|
15993
|
+
return;
|
|
15994
|
+
}
|
|
15926
15995
|
if (!parsed.prompt || !parsed.fileChangeId) {
|
|
15927
|
-
log.
|
|
15996
|
+
log.info(
|
|
15997
|
+
"ai-insight",
|
|
15998
|
+
`missing fields \u2014 prompt=${!!parsed.prompt} fileChangeId=${!!parsed.fileChangeId}`
|
|
15999
|
+
);
|
|
15928
16000
|
return;
|
|
15929
16001
|
}
|
|
15930
16002
|
const prompt = parsed.prompt;
|
|
15931
16003
|
const fileChangeId = parsed.fileChangeId;
|
|
15932
16004
|
const pluginAuthToken = ctx.pluginAuthToken;
|
|
15933
16005
|
void (async () => {
|
|
16006
|
+
log.info("ai-insight", `generateOneShot start fileChangeId=${fileChangeId} promptLen=${prompt.length}`);
|
|
16007
|
+
const startedAt = Date.now();
|
|
15934
16008
|
const text = await ctx.runtime.generateOneShot(prompt).catch((err) => {
|
|
15935
|
-
log.
|
|
16009
|
+
log.info("ai-insight", `generateOneShot threw: ${String(err)}`);
|
|
15936
16010
|
return null;
|
|
15937
16011
|
});
|
|
15938
|
-
|
|
16012
|
+
const tookMs = Date.now() - startedAt;
|
|
16013
|
+
if (!text) {
|
|
16014
|
+
log.info("ai-insight", `generateOneShot returned null after ${tookMs}ms \u2014 skipping POST`);
|
|
16015
|
+
return;
|
|
16016
|
+
}
|
|
16017
|
+
log.info("ai-insight", `generateOneShot ok fileChangeId=${fileChangeId} took=${tookMs}ms textLen=${text.length}`);
|
|
15939
16018
|
const { summary, reasoning, securityNote } = parseInsightText(text);
|
|
15940
|
-
await postAiResult({
|
|
16019
|
+
const result = await postAiResult({
|
|
15941
16020
|
sessionId: ctx.sessionId,
|
|
15942
16021
|
pluginId: ctx.pluginId,
|
|
15943
16022
|
pluginAuthToken,
|
|
@@ -15947,6 +16026,11 @@ var requestAiInsightH = (ctx, _cmd, parsed) => {
|
|
|
15947
16026
|
reasoning,
|
|
15948
16027
|
securityNote
|
|
15949
16028
|
});
|
|
16029
|
+
if (result.ok) {
|
|
16030
|
+
log.info("ai-insight", `postAiResult ok fileChangeId=${fileChangeId}`);
|
|
16031
|
+
} else {
|
|
16032
|
+
log.info("ai-insight", `postAiResult failed status=${result.status} msg=${result.message}`);
|
|
16033
|
+
}
|
|
15950
16034
|
})();
|
|
15951
16035
|
};
|
|
15952
16036
|
function parseInsightText(text) {
|
|
@@ -18917,7 +19001,7 @@ function checkChokidar() {
|
|
|
18917
19001
|
}
|
|
18918
19002
|
async function doctor(args2 = []) {
|
|
18919
19003
|
const json = args2.includes("--json");
|
|
18920
|
-
const cliVersion = true ? "2.23.
|
|
19004
|
+
const cliVersion = true ? "2.23.31" : "0.0.0-dev";
|
|
18921
19005
|
const apiBase = resolveApiBaseUrl();
|
|
18922
19006
|
const diagnosticId = (0, import_node_crypto6.randomUUID)();
|
|
18923
19007
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -19116,7 +19200,7 @@ async function completion(args2) {
|
|
|
19116
19200
|
// src/commands/version.ts
|
|
19117
19201
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
19118
19202
|
function version2() {
|
|
19119
|
-
const v = true ? "2.23.
|
|
19203
|
+
const v = true ? "2.23.31" : "unknown";
|
|
19120
19204
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
19121
19205
|
}
|
|
19122
19206
|
|
|
@@ -19344,7 +19428,7 @@ function checkForUpdates() {
|
|
|
19344
19428
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
19345
19429
|
if (process.env.CI) return;
|
|
19346
19430
|
if (!process.stdout.isTTY) return;
|
|
19347
|
-
const current = true ? "2.23.
|
|
19431
|
+
const current = true ? "2.23.31" : null;
|
|
19348
19432
|
if (!current) return;
|
|
19349
19433
|
const cache = readCache();
|
|
19350
19434
|
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.23.
|
|
3
|
+
"version": "2.23.31",
|
|
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",
|