codeam-cli 2.60.21 → 2.60.23
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 +207 -33
- 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.22] — 2026-07-09
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Baton — late-bind Codex's session id instead of blocking start()
|
|
12
|
+
|
|
13
|
+
## [2.60.21] — 2026-07-09
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Baton — discover Codex's self-minted session id (first-turn aware)
|
|
18
|
+
|
|
7
19
|
## [2.60.20] — 2026-07-09
|
|
8
20
|
|
|
9
21
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -5680,7 +5680,7 @@ function readAnonId() {
|
|
|
5680
5680
|
}
|
|
5681
5681
|
function superProperties() {
|
|
5682
5682
|
return {
|
|
5683
|
-
cliVersion: true ? "2.60.
|
|
5683
|
+
cliVersion: true ? "2.60.23" : "0.0.0-dev",
|
|
5684
5684
|
nodeVersion: process.version,
|
|
5685
5685
|
platform: process.platform,
|
|
5686
5686
|
arch: process.arch,
|
|
@@ -5861,7 +5861,7 @@ var os4 = __toESM(require("os"));
|
|
|
5861
5861
|
// package.json
|
|
5862
5862
|
var package_default = {
|
|
5863
5863
|
name: "codeam-cli",
|
|
5864
|
-
version: "2.60.
|
|
5864
|
+
version: "2.60.23",
|
|
5865
5865
|
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.",
|
|
5866
5866
|
type: "commonjs",
|
|
5867
5867
|
main: "dist/index.js",
|
|
@@ -6932,7 +6932,7 @@ var CommandRelayService = class {
|
|
|
6932
6932
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
6933
6933
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
6934
6934
|
// pair/reconnect). Older backends ignore the extra field.
|
|
6935
|
-
..."2.60.
|
|
6935
|
+
..."2.60.23" ? { ideVersion: "2.60.23" } : {}
|
|
6936
6936
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
6937
6937
|
}
|
|
6938
6938
|
/**
|
|
@@ -13420,7 +13420,7 @@ function coderabbitLoginLauncher(os49) {
|
|
|
13420
13420
|
return ensureCoderabbitInstalled(os49);
|
|
13421
13421
|
},
|
|
13422
13422
|
launch() {
|
|
13423
|
-
return (0, import_node_child_process7.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
13423
|
+
return (0, import_node_child_process7.spawn)("coderabbit", ["auth", "login"], { stdio: "inherit" });
|
|
13424
13424
|
}
|
|
13425
13425
|
};
|
|
13426
13426
|
}
|
|
@@ -13429,31 +13429,166 @@ function coderabbitLoginLauncher(os49) {
|
|
|
13429
13429
|
var HUNK_LINE_RE = /^([^\s:][^:]*?):(\d+)[\s:—-]+(?:\[?(info|warn|warning|error|critical)\]?[:\s—-]+)?(.+)$/i;
|
|
13430
13430
|
var SEVERITY_MAP = {
|
|
13431
13431
|
info: "info",
|
|
13432
|
+
note: "info",
|
|
13433
|
+
low: "info",
|
|
13434
|
+
minor: "info",
|
|
13432
13435
|
warn: "warn",
|
|
13433
13436
|
warning: "warn",
|
|
13437
|
+
medium: "warn",
|
|
13438
|
+
major: "warn",
|
|
13434
13439
|
error: "error",
|
|
13435
|
-
critical: "error"
|
|
13440
|
+
critical: "error",
|
|
13441
|
+
high: "error",
|
|
13442
|
+
blocker: "error"
|
|
13436
13443
|
};
|
|
13437
|
-
function
|
|
13444
|
+
function normSeverity(v) {
|
|
13445
|
+
if (typeof v !== "string") return void 0;
|
|
13446
|
+
return SEVERITY_MAP[v.trim().toLowerCase()];
|
|
13447
|
+
}
|
|
13448
|
+
function pick(obj, keys) {
|
|
13449
|
+
for (const k2 of keys) {
|
|
13450
|
+
if (obj[k2] !== void 0 && obj[k2] !== null) return obj[k2];
|
|
13451
|
+
}
|
|
13452
|
+
return void 0;
|
|
13453
|
+
}
|
|
13454
|
+
function asString(v) {
|
|
13455
|
+
return typeof v === "string" && v.trim().length > 0 ? v : void 0;
|
|
13456
|
+
}
|
|
13457
|
+
function pickLine(obj) {
|
|
13458
|
+
const direct = pick(obj, ["line", "start_line", "startLine", "line_number", "lineNumber"]);
|
|
13459
|
+
if (typeof direct === "number") return direct;
|
|
13460
|
+
if (typeof direct === "string" && /^\d+$/.test(direct)) return Number(direct);
|
|
13461
|
+
const range = pick(obj, ["line_range", "lineRange", "range", "lines"]);
|
|
13462
|
+
if (Array.isArray(range) && typeof range[0] === "number") return range[0];
|
|
13463
|
+
if (range && typeof range === "object") {
|
|
13464
|
+
const start2 = pick(range, ["start", "begin", "from"]);
|
|
13465
|
+
if (typeof start2 === "number") return start2;
|
|
13466
|
+
if (start2 && typeof start2 === "object") {
|
|
13467
|
+
const l = start2.line;
|
|
13468
|
+
if (typeof l === "number") return l;
|
|
13469
|
+
}
|
|
13470
|
+
}
|
|
13471
|
+
return void 0;
|
|
13472
|
+
}
|
|
13473
|
+
function toHunk(raw, groupSeverity) {
|
|
13474
|
+
if (!raw || typeof raw !== "object") return null;
|
|
13475
|
+
const o = raw;
|
|
13476
|
+
const path70 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename"])) ?? asString(pick(o, ["location"])?.path);
|
|
13477
|
+
if (!path70) return null;
|
|
13478
|
+
const message = asString(pick(o, ["comment", "message", "body", "description", "summary", "markdown", "text"])) ?? "";
|
|
13479
|
+
const title = asString(pick(o, ["title", "rule", "category", "check"]));
|
|
13480
|
+
const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
|
|
13481
|
+
const locObj = pick(o, ["location"]) ?? o;
|
|
13482
|
+
return {
|
|
13483
|
+
path: path70.trim(),
|
|
13484
|
+
line: pickLine(o) ?? pickLine(locObj),
|
|
13485
|
+
severity,
|
|
13486
|
+
message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
|
|
13487
|
+
};
|
|
13488
|
+
}
|
|
13489
|
+
function findingsFrom(value) {
|
|
13490
|
+
const out2 = [];
|
|
13491
|
+
if (!value || typeof value !== "object") return out2;
|
|
13492
|
+
const root = value;
|
|
13493
|
+
const flat = pick(root, ["findings", "comments", "issues", "results", "review_comments", "reviewComments"]);
|
|
13494
|
+
if (Array.isArray(flat)) {
|
|
13495
|
+
for (const f of flat) {
|
|
13496
|
+
const h = toHunk(f);
|
|
13497
|
+
if (h) out2.push(h);
|
|
13498
|
+
}
|
|
13499
|
+
}
|
|
13500
|
+
const grouped = flat && !Array.isArray(flat) ? flat : root;
|
|
13501
|
+
for (const sev of ["critical", "warning", "warn", "error", "info", "note"]) {
|
|
13502
|
+
const bucket = grouped[sev];
|
|
13503
|
+
if (Array.isArray(bucket)) {
|
|
13504
|
+
for (const f of bucket) {
|
|
13505
|
+
const h = toHunk(f, sev);
|
|
13506
|
+
if (h) out2.push(h);
|
|
13507
|
+
}
|
|
13508
|
+
}
|
|
13509
|
+
}
|
|
13510
|
+
return out2;
|
|
13511
|
+
}
|
|
13512
|
+
function errorFrom(obj) {
|
|
13513
|
+
if (obj.type !== "error") return void 0;
|
|
13514
|
+
return asString(pick(obj, ["message", "error"]));
|
|
13515
|
+
}
|
|
13516
|
+
function isControlEvent(obj) {
|
|
13517
|
+
return obj.type === "review_context" || obj.type === "status" || obj.type === "progress" || obj.type === "error";
|
|
13518
|
+
}
|
|
13519
|
+
function parseStructured(stdout) {
|
|
13520
|
+
const trimmed = stdout.trim();
|
|
13521
|
+
if (!trimmed || trimmed[0] !== "{" && trimmed[0] !== "[") return null;
|
|
13522
|
+
try {
|
|
13523
|
+
const doc = JSON.parse(trimmed);
|
|
13524
|
+
const hunks2 = findingsFrom(Array.isArray(doc) ? { findings: doc } : doc);
|
|
13525
|
+
const summary2 = asString(
|
|
13526
|
+
pick(Array.isArray(doc) ? {} : doc, ["summary", "markdown", "report", "overview"])
|
|
13527
|
+
);
|
|
13528
|
+
if (hunks2.length > 0 || summary2) return { hunks: hunks2, summary: summary2 };
|
|
13529
|
+
} catch {
|
|
13530
|
+
}
|
|
13438
13531
|
const hunks = [];
|
|
13439
|
-
|
|
13440
|
-
|
|
13532
|
+
let summary;
|
|
13533
|
+
let error;
|
|
13534
|
+
let sawJson = false;
|
|
13535
|
+
for (const line of trimmed.split(/\r?\n/)) {
|
|
13536
|
+
const l = line.trim();
|
|
13537
|
+
if (!l || l[0] !== "{" && l[0] !== "[") continue;
|
|
13538
|
+
try {
|
|
13539
|
+
const obj = JSON.parse(l);
|
|
13540
|
+
sawJson = true;
|
|
13541
|
+
const rec = Array.isArray(obj) ? {} : obj;
|
|
13542
|
+
error ??= errorFrom(rec);
|
|
13543
|
+
if (isControlEvent(rec)) continue;
|
|
13544
|
+
const found = findingsFrom(Array.isArray(obj) ? { findings: obj } : obj);
|
|
13545
|
+
if (found.length > 0) hunks.push(...found);
|
|
13546
|
+
else {
|
|
13547
|
+
const single = toHunk(obj);
|
|
13548
|
+
if (single) hunks.push(single);
|
|
13549
|
+
}
|
|
13550
|
+
summary ??= asString(pick(rec, ["summary", "markdown", "report"]));
|
|
13551
|
+
} catch {
|
|
13552
|
+
}
|
|
13553
|
+
}
|
|
13554
|
+
return sawJson ? { hunks, summary, error } : null;
|
|
13555
|
+
}
|
|
13556
|
+
function parsePlain(stdout) {
|
|
13557
|
+
const hunks = [];
|
|
13558
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
13441
13559
|
const m = line.match(HUNK_LINE_RE);
|
|
13442
13560
|
if (!m) continue;
|
|
13443
13561
|
const [, path70, lineNo, sevToken, message] = m;
|
|
13444
13562
|
if (!path70 || !lineNo || !message) continue;
|
|
13445
|
-
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
13446
13563
|
hunks.push({
|
|
13447
13564
|
path: path70.trim(),
|
|
13448
13565
|
line: Number(lineNo),
|
|
13449
13566
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
13450
|
-
message:
|
|
13567
|
+
message: message.trim().replace(/^[*-]\s+/, "")
|
|
13451
13568
|
});
|
|
13452
13569
|
}
|
|
13570
|
+
return hunks;
|
|
13571
|
+
}
|
|
13572
|
+
function severityCounts(hunks) {
|
|
13573
|
+
const c2 = { error: 0, warn: 0, info: 0 };
|
|
13574
|
+
for (const h of hunks) if (h.severity) c2[h.severity] += 1;
|
|
13575
|
+
return c2;
|
|
13576
|
+
}
|
|
13577
|
+
function parseReview(stdout) {
|
|
13578
|
+
const structured = parseStructured(stdout);
|
|
13579
|
+
const hunks = structured && structured.hunks.length > 0 ? structured.hunks : parsePlain(stdout);
|
|
13580
|
+
const counts = severityCounts(hunks);
|
|
13581
|
+
const markdown = (structured?.summary ?? (hunks.length === 0 && structured?.error ? structured.error : stdout)).trim();
|
|
13453
13582
|
return {
|
|
13454
|
-
markdown
|
|
13583
|
+
markdown,
|
|
13455
13584
|
hunks,
|
|
13456
|
-
stats: {
|
|
13585
|
+
stats: {
|
|
13586
|
+
findingCount: hunks.length,
|
|
13587
|
+
critical: counts.error,
|
|
13588
|
+
warning: counts.warn,
|
|
13589
|
+
info: counts.info,
|
|
13590
|
+
...structured?.error ? { error: structured.error } : {}
|
|
13591
|
+
}
|
|
13457
13592
|
};
|
|
13458
13593
|
}
|
|
13459
13594
|
|
|
@@ -13467,7 +13602,7 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
13467
13602
|
this.os = os49;
|
|
13468
13603
|
}
|
|
13469
13604
|
getDefaultArgs() {
|
|
13470
|
-
return ["review"];
|
|
13605
|
+
return ["review", "--agent"];
|
|
13471
13606
|
}
|
|
13472
13607
|
async prepareInvocation(input) {
|
|
13473
13608
|
const binary = this.os.findInPath(this.meta.binaryName);
|
|
@@ -13476,14 +13611,12 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
13476
13611
|
`CodeRabbit binary "${this.meta.binaryName}" not on PATH. Run \`codeam link coderabbit\` to install it first.`
|
|
13477
13612
|
);
|
|
13478
13613
|
}
|
|
13479
|
-
const args2 = this.getDefaultArgs();
|
|
13480
|
-
if (input.
|
|
13481
|
-
if (input.
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
if (input.
|
|
13485
|
-
args2.push("--message", input.prompt);
|
|
13486
|
-
}
|
|
13614
|
+
const args2 = input.structured === false ? ["review", "--plain"] : this.getDefaultArgs();
|
|
13615
|
+
if (input.changeSet) args2.push("--type", input.changeSet);
|
|
13616
|
+
if (input.base) args2.push("--base", input.base);
|
|
13617
|
+
if (input.baseCommit) args2.push("--base-commit", input.baseCommit);
|
|
13618
|
+
if (input.dir) args2.push("--dir", input.dir);
|
|
13619
|
+
if (input.apiKey) args2.push("--api-key", input.apiKey);
|
|
13487
13620
|
if (input.extraArgs && input.extraArgs.length > 0) {
|
|
13488
13621
|
args2.push(...input.extraArgs);
|
|
13489
13622
|
}
|
|
@@ -13791,10 +13924,20 @@ var CursorRuntimeStrategy = class {
|
|
|
13791
13924
|
* failure. `cursor-agent create-chat` prints a bare UUID and exits 0 (verified
|
|
13792
13925
|
* on cursor-agent 2026.06.24). Synchronous + bounded so prepareLaunch stays a
|
|
13793
13926
|
* single deterministic step; a timeout/parse failure just disables pre-mint.
|
|
13927
|
+
*
|
|
13928
|
+
* ⚠️ Windows: `findInPath` resolves `cursor-agent.cmd` (or `.ps1`) via PATHEXT,
|
|
13929
|
+
* and Windows CANNOT spawn a `.cmd`/`.bat`/`.ps1` directly — it needs
|
|
13930
|
+
* `cmd.exe /c` / `powershell -File`. Spawning `binary` raw (as this used to)
|
|
13931
|
+
* failed with EINVAL on Windows → null id → no pre-mint → the baton threw
|
|
13932
|
+
* "agent did not expose a session id after spawn" (Windows-only). Route the
|
|
13933
|
+
* spawn through `os.buildLaunch`, exactly like the TUI launch above, so the
|
|
13934
|
+
* command is wrapped correctly per-platform. On macOS/Linux buildLaunch returns
|
|
13935
|
+
* the bare `{cmd: binary, args: ['create-chat']}` → behaviour unchanged.
|
|
13794
13936
|
*/
|
|
13795
13937
|
mintChatId(binary) {
|
|
13796
13938
|
try {
|
|
13797
|
-
const
|
|
13939
|
+
const launch = this.os.buildLaunch(binary, ["create-chat"]);
|
|
13940
|
+
const r = (0, import_node_child_process10.spawnSync)(launch.cmd, launch.args, {
|
|
13798
13941
|
encoding: "utf8",
|
|
13799
13942
|
timeout: 2e4,
|
|
13800
13943
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -16733,7 +16876,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
16733
16876
|
if (process.env.NODE_ENV === "test") return;
|
|
16734
16877
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
16735
16878
|
if (process.env.CI) return;
|
|
16736
|
-
const current = true ? "2.60.
|
|
16879
|
+
const current = true ? "2.60.23" : null;
|
|
16737
16880
|
if (!current) return;
|
|
16738
16881
|
const cache = readCache();
|
|
16739
16882
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -16750,7 +16893,7 @@ function checkForUpdates() {
|
|
|
16750
16893
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
16751
16894
|
if (process.env.CI) return;
|
|
16752
16895
|
if (!process.stdout.isTTY) return;
|
|
16753
|
-
const current = true ? "2.60.
|
|
16896
|
+
const current = true ? "2.60.23" : null;
|
|
16754
16897
|
if (!current) return;
|
|
16755
16898
|
const cache = readCache();
|
|
16756
16899
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -16770,7 +16913,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
16770
16913
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
16771
16914
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
16772
16915
|
function currentCliVersion() {
|
|
16773
|
-
return true ? "2.60.
|
|
16916
|
+
return true ? "2.60.23" : null;
|
|
16774
16917
|
}
|
|
16775
16918
|
function runCmd(cmd, args2, timeoutMs) {
|
|
16776
16919
|
return new Promise((resolve7) => {
|
|
@@ -30118,6 +30261,20 @@ var BatonController = class {
|
|
|
30118
30261
|
this._active = "local_tui";
|
|
30119
30262
|
this.setState("LOCAL_DRIVE");
|
|
30120
30263
|
}
|
|
30264
|
+
/**
|
|
30265
|
+
* Late-bind the conversation id for an agent (Codex) that minted it only on the
|
|
30266
|
+
* user's first turn, so `begin()` returned null. Fires from the native driver's
|
|
30267
|
+
* background discovery. Idempotent + guarded: only binds while we're still in
|
|
30268
|
+
* the INITIAL, id-less LOCAL_DRIVE — if the user already took control (which
|
|
30269
|
+
* started its own session) or an id is already set, it's a no-op, so a stray
|
|
30270
|
+
* native id can never clobber the live conversation. Re-publishes LOCAL_DRIVE so
|
|
30271
|
+
* the read-only mirror arms on the now-known id.
|
|
30272
|
+
*/
|
|
30273
|
+
rebindConversation(conversationId) {
|
|
30274
|
+
if (this._conversationId !== null || this._state !== "LOCAL_DRIVE") return;
|
|
30275
|
+
this._conversationId = conversationId;
|
|
30276
|
+
this.setState("LOCAL_DRIVE");
|
|
30277
|
+
}
|
|
30121
30278
|
async takeControl() {
|
|
30122
30279
|
await this.switchDriver(
|
|
30123
30280
|
"LOCAL_DRIVE",
|
|
@@ -30179,7 +30336,7 @@ function parkTerminalForReadonly(term = {}) {
|
|
|
30179
30336
|
}
|
|
30180
30337
|
|
|
30181
30338
|
// src/baton/native-tui-driver.ts
|
|
30182
|
-
var NativeTuiDriver = class {
|
|
30339
|
+
var NativeTuiDriver = class _NativeTuiDriver {
|
|
30183
30340
|
constructor(deps) {
|
|
30184
30341
|
this.deps = deps;
|
|
30185
30342
|
this.agent = deps.agent;
|
|
@@ -30208,6 +30365,9 @@ var NativeTuiDriver = class {
|
|
|
30208
30365
|
idleMs;
|
|
30209
30366
|
now;
|
|
30210
30367
|
lastOutput;
|
|
30368
|
+
/** How long `start()` waits for a boot-time session store (Kimi) before
|
|
30369
|
+
* falling back to background/late-bind discovery (Codex, first-turn store). */
|
|
30370
|
+
static QUICK_DISCOVER_MS = 8e3;
|
|
30211
30371
|
outputSvc;
|
|
30212
30372
|
historySvc;
|
|
30213
30373
|
setKeepAlive;
|
|
@@ -30222,11 +30382,20 @@ var NativeTuiDriver = class {
|
|
|
30222
30382
|
await this.agent.spawn();
|
|
30223
30383
|
const preMinted = this.agent.spawnedSessionId;
|
|
30224
30384
|
if (preMinted) return preMinted;
|
|
30225
|
-
const
|
|
30226
|
-
|
|
30385
|
+
const discover = this.deps.runtime.discoverSessionId;
|
|
30386
|
+
if (!discover) {
|
|
30387
|
+
throw new Error("NativeTuiDriver: agent did not expose a session id after spawn");
|
|
30388
|
+
}
|
|
30389
|
+
const quick = await discover(this.deps.opts.cwd, {
|
|
30390
|
+
sinceMs: spawnedAt,
|
|
30391
|
+
timeoutMs: _NativeTuiDriver.QUICK_DISCOVER_MS
|
|
30227
30392
|
});
|
|
30228
|
-
if (
|
|
30229
|
-
|
|
30393
|
+
if (quick) return quick;
|
|
30394
|
+
void discover(this.deps.opts.cwd, { sinceMs: spawnedAt }).then((id) => {
|
|
30395
|
+
if (id) this.deps.onLateBind?.(id);
|
|
30396
|
+
}).catch(() => {
|
|
30397
|
+
});
|
|
30398
|
+
return null;
|
|
30230
30399
|
}
|
|
30231
30400
|
async stop() {
|
|
30232
30401
|
this.agent.kill();
|
|
@@ -30640,7 +30809,12 @@ async function runBatonSession(opts) {
|
|
|
30640
30809
|
cwd: opts.cwd
|
|
30641
30810
|
},
|
|
30642
30811
|
getRelay: () => relay,
|
|
30643
|
-
getBeads: opts.getBeads ?? (() => null)
|
|
30812
|
+
getBeads: opts.getBeads ?? (() => null),
|
|
30813
|
+
// Late-bind for first-turn-minted ids (Codex): the background discovery
|
|
30814
|
+
// calls this once the user's first terminal turn creates the transcript.
|
|
30815
|
+
// Safe forward-ref — `controller` is initialised long before `begin()` runs,
|
|
30816
|
+
// and onLateBind only fires from inside `begin()`'s spawn.
|
|
30817
|
+
onLateBind: (id) => controller.rebindConversation(id)
|
|
30644
30818
|
});
|
|
30645
30819
|
let mirror = null;
|
|
30646
30820
|
let firstLocalDrive = true;
|
|
@@ -33632,7 +33806,7 @@ function checkChokidar() {
|
|
|
33632
33806
|
}
|
|
33633
33807
|
async function doctor(args2 = []) {
|
|
33634
33808
|
const json = args2.includes("--json");
|
|
33635
|
-
const cliVersion = true ? "2.60.
|
|
33809
|
+
const cliVersion = true ? "2.60.23" : "0.0.0-dev";
|
|
33636
33810
|
const apiBase2 = resolveApiBaseUrl();
|
|
33637
33811
|
const diagnosticId = (0, import_node_crypto12.randomUUID)();
|
|
33638
33812
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -33831,7 +34005,7 @@ async function completion(args2) {
|
|
|
33831
34005
|
// src/commands/version.ts
|
|
33832
34006
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
33833
34007
|
function version2() {
|
|
33834
|
-
const v = true ? "2.60.
|
|
34008
|
+
const v = true ? "2.60.23" : "unknown";
|
|
33835
34009
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
33836
34010
|
}
|
|
33837
34011
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.60.
|
|
3
|
+
"version": "2.60.23",
|
|
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",
|