codeam-cli 2.72.0 → 2.73.0
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/dist/index.js +117 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1750,7 +1750,12 @@ var INTEGRATION_REGISTRY = {
|
|
|
1750
1750
|
label: "Token",
|
|
1751
1751
|
placeholder: "Your Trello token",
|
|
1752
1752
|
secret: true,
|
|
1753
|
-
|
|
1753
|
+
// WARNING - the Power-Up API-key page also shows a "Secret", and it is
|
|
1754
|
+
// NOT the token: both are 64 hex characters and look identical, so it
|
|
1755
|
+
// is the natural thing to copy. Pasting the Secret fails with Trello's
|
|
1756
|
+
// misleading `invalid key`, which then sends the user to regenerate a
|
|
1757
|
+
// perfectly good API key (owner report, 2026-09-01). Say so here.
|
|
1758
|
+
help: 'On that same API-key page, click the "Token" link to authorize and generate a token (read,write, never-expiring). NOT the "Secret" on that page - it looks identical but will not work.'
|
|
1754
1759
|
}
|
|
1755
1760
|
]
|
|
1756
1761
|
},
|
|
@@ -8092,7 +8097,7 @@ function readAnonId() {
|
|
|
8092
8097
|
}
|
|
8093
8098
|
function superProperties() {
|
|
8094
8099
|
return {
|
|
8095
|
-
cliVersion: true ? "2.
|
|
8100
|
+
cliVersion: true ? "2.73.0" : "0.0.0-dev",
|
|
8096
8101
|
nodeVersion: process.version,
|
|
8097
8102
|
platform: process.platform,
|
|
8098
8103
|
arch: process.arch,
|
|
@@ -8334,7 +8339,7 @@ var http = __toESM(require("http"));
|
|
|
8334
8339
|
// package.json
|
|
8335
8340
|
var package_default = {
|
|
8336
8341
|
name: "codeam-cli",
|
|
8337
|
-
version: "2.
|
|
8342
|
+
version: "2.73.0",
|
|
8338
8343
|
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.",
|
|
8339
8344
|
type: "commonjs",
|
|
8340
8345
|
main: "dist/index.js",
|
|
@@ -9927,7 +9932,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9927
9932
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9928
9933
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9929
9934
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9930
|
-
..."2.
|
|
9935
|
+
..."2.73.0" ? { ideVersion: "2.73.0" } : {}
|
|
9931
9936
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9932
9937
|
}
|
|
9933
9938
|
/**
|
|
@@ -22193,7 +22198,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
22193
22198
|
if (process.env.NODE_ENV === "test") return;
|
|
22194
22199
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22195
22200
|
if (process.env.CI) return;
|
|
22196
|
-
const current2 = true ? "2.
|
|
22201
|
+
const current2 = true ? "2.73.0" : null;
|
|
22197
22202
|
if (!current2) return;
|
|
22198
22203
|
const cache = readCache();
|
|
22199
22204
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22210,7 +22215,7 @@ function checkForUpdates() {
|
|
|
22210
22215
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22211
22216
|
if (process.env.CI) return;
|
|
22212
22217
|
if (!process.stdout.isTTY) return;
|
|
22213
|
-
const current2 = true ? "2.
|
|
22218
|
+
const current2 = true ? "2.73.0" : null;
|
|
22214
22219
|
if (!current2) return;
|
|
22215
22220
|
const cache = readCache();
|
|
22216
22221
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22233,7 +22238,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
22233
22238
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
22234
22239
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
22235
22240
|
function currentCliVersion() {
|
|
22236
|
-
return true ? "2.
|
|
22241
|
+
return true ? "2.73.0" : null;
|
|
22237
22242
|
}
|
|
22238
22243
|
async function installedVersion(deps) {
|
|
22239
22244
|
const ls = await deps.run(
|
|
@@ -22526,6 +22531,14 @@ function isFleetLimits(v) {
|
|
|
22526
22531
|
function isFleetCreateBoxPayload(p2) {
|
|
22527
22532
|
return typeof p2.boxId === "string" && isFleetContainerName(p2.containerName) && typeof p2.enrollToken === "string" && p2.enrollToken.length > 0 && typeof p2.apiOrigin === "string" && p2.apiOrigin.length > 0 && isFleetLimits(p2.limits);
|
|
22528
22533
|
}
|
|
22534
|
+
function isFleetMigrateBoxImagePayload(p2) {
|
|
22535
|
+
return typeof p2.boxId === "string" && isFleetContainerName(p2.containerName) && typeof p2.apiOrigin === "string" && p2.apiOrigin.length > 0 && isFleetLimits(p2.limits) && // ⚠️ REJECT a token outright rather than ignoring it. A migrate that
|
|
22536
|
+
// carried one would bake a 15-minute credential into a container that may
|
|
22537
|
+
// not start for days — a terminal 4xx at boot, i.e. a box that never comes
|
|
22538
|
+
// back. If a future backend starts sending one, this must fail loudly here
|
|
22539
|
+
// rather than silently produce that box.
|
|
22540
|
+
p2.enrollToken === void 0;
|
|
22541
|
+
}
|
|
22529
22542
|
function isFleetBoxRefPayload(p2) {
|
|
22530
22543
|
if (typeof p2.boxId !== "string") return false;
|
|
22531
22544
|
if (!isFleetContainerName(p2.containerName)) return false;
|
|
@@ -22557,6 +22570,9 @@ function isMissingVolumeError(stderr) {
|
|
|
22557
22570
|
function resolveFleetBoxImage() {
|
|
22558
22571
|
return process.env.CODEAM_FLEET_BOX_IMAGE || "ghcr.io/edgar-durand/codeam-box:latest";
|
|
22559
22572
|
}
|
|
22573
|
+
function buildFleetBoxMigrateArgs(p2) {
|
|
22574
|
+
return buildFleetBoxRunArgs(p2).map((a) => a === "run" ? "create" : a).filter((a) => a !== "--pull=always" && a !== "-d");
|
|
22575
|
+
}
|
|
22560
22576
|
function buildFleetBoxRunArgs(p2) {
|
|
22561
22577
|
const userId = fleetUserIdFromContainerName(p2.containerName);
|
|
22562
22578
|
const image = resolveFleetBoxImage();
|
|
@@ -22956,6 +22972,14 @@ var HostAgentSupervisor = class {
|
|
|
22956
22972
|
await this.fleetCreateBox(cmd.payload);
|
|
22957
22973
|
return;
|
|
22958
22974
|
}
|
|
22975
|
+
if (cmd.type === "fleet_migrate_box_image") {
|
|
22976
|
+
if (!isFleetMigrateBoxImagePayload(cmd.payload)) {
|
|
22977
|
+
log.warn("host-agent", `ignoring malformed fleet_migrate_box_image id=${cmd.id}`);
|
|
22978
|
+
return;
|
|
22979
|
+
}
|
|
22980
|
+
await this.fleetMigrateBoxImage(cmd.payload);
|
|
22981
|
+
return;
|
|
22982
|
+
}
|
|
22959
22983
|
if (cmd.type === "fleet_start_box") {
|
|
22960
22984
|
if (!isFleetBoxRefPayload(cmd.payload)) {
|
|
22961
22985
|
log.warn("host-agent", `ignoring malformed fleet_start_box id=${cmd.id}`);
|
|
@@ -23126,6 +23150,90 @@ var HostAgentSupervisor = class {
|
|
|
23126
23150
|
}
|
|
23127
23151
|
/** `fleet_start_box` — wake a sleeping box (`docker start`). Idempotent: a
|
|
23128
23152
|
* container the host already removed is treated as success. */
|
|
23153
|
+
/**
|
|
23154
|
+
* `fleet_migrate_box_image` — re-point a SLEEPING box at the current
|
|
23155
|
+
* `:latest` without waking it, so the version it was pinned to becomes
|
|
23156
|
+
* reclaimable by the (already automated) dangling-image prune.
|
|
23157
|
+
*
|
|
23158
|
+
* WHY THIS IS NEEDED AT ALL. Boxes are created with `--pull=always` on
|
|
23159
|
+
* purpose, so each stays pinned to the image it was born on, and Docker
|
|
23160
|
+
* refuses to delete an image any container references INCLUDING stopped
|
|
23161
|
+
* ones — which is precisely what stops the prune from destroying a sleeping
|
|
23162
|
+
* user's box. So every image release strands ~7.7 GB per lagging box until it
|
|
23163
|
+
* wakes or is reaped on day 7 (fleet-1, 2026-09-02: 9 boxes across 4
|
|
23164
|
+
* versions, ~31 GB held).
|
|
23165
|
+
*
|
|
23166
|
+
* ⚠️ THE HOST RE-CHECKS THAT THE BOX IS STOPPED, even though the backend only
|
|
23167
|
+
* selects `status: 'SLEEPING'`. The DB's view can lag the host by a sweep —
|
|
23168
|
+
* a box that woke seconds ago is still SLEEPING in the row — and re-creating
|
|
23169
|
+
* a RUNNING container kills a live agent mid-turn. The authority on whether a
|
|
23170
|
+
* container is running is the daemon, so we ask it here and refuse rather
|
|
23171
|
+
* than trust the payload.
|
|
23172
|
+
*
|
|
23173
|
+
* ⚠️ `docker create`, and NO enroll token. `run` would start the container,
|
|
23174
|
+
* so migrating the sleeping set in a batch would wake all of them (9 ×
|
|
23175
|
+
* 1536 MB on a 16 GB host) only for the sleep sweep to re-sleep them 30
|
|
23176
|
+
* minutes later. And a token would be a 15-minute credential baked into a
|
|
23177
|
+
* container that may not start for days — a terminal 4xx at boot, i.e. a box
|
|
23178
|
+
* that never comes back. The sealed identity is in the named volume, which
|
|
23179
|
+
* `rm` WITHOUT `-v` preserves.
|
|
23180
|
+
*
|
|
23181
|
+
* Idempotent and best-effort: a box already on `:latest` is skipped, a
|
|
23182
|
+
* missing container is success (a concurrent reap), and nothing here may
|
|
23183
|
+
* throw into the relay — this is housekeeping.
|
|
23184
|
+
*/
|
|
23185
|
+
async fleetMigrateBoxImage(payload) {
|
|
23186
|
+
const { containerName } = payload;
|
|
23187
|
+
const state = await this.docker.run([
|
|
23188
|
+
"inspect",
|
|
23189
|
+
"--format",
|
|
23190
|
+
"{{.State.Running}}",
|
|
23191
|
+
containerName
|
|
23192
|
+
]);
|
|
23193
|
+
if (state.code !== 0) {
|
|
23194
|
+
if (isMissingContainerError(state.stderr)) return;
|
|
23195
|
+
log.warn(
|
|
23196
|
+
"host-agent",
|
|
23197
|
+
`fleet_migrate_box_image: inspect of ${containerName} failed (code=${state.code}) \u2014 skipping`
|
|
23198
|
+
);
|
|
23199
|
+
return;
|
|
23200
|
+
}
|
|
23201
|
+
if (state.stdout.trim() === "true") {
|
|
23202
|
+
log.info(
|
|
23203
|
+
"host-agent",
|
|
23204
|
+
`fleet_migrate_box_image: ${containerName} is RUNNING \u2014 skipping (never touch a live box)`
|
|
23205
|
+
);
|
|
23206
|
+
return;
|
|
23207
|
+
}
|
|
23208
|
+
if (!await this.fleetBoxImageStale(containerName)) {
|
|
23209
|
+
log.info("host-agent", `fleet_migrate_box_image: ${containerName} already current`);
|
|
23210
|
+
return;
|
|
23211
|
+
}
|
|
23212
|
+
const rm = await this.docker.run(["rm", "-f", containerName], {
|
|
23213
|
+
timeoutMs: DOCKER_RUN_TIMEOUT_MS
|
|
23214
|
+
});
|
|
23215
|
+
if (rm.code !== 0 && !isMissingContainerError(rm.stderr)) {
|
|
23216
|
+
log.warn(
|
|
23217
|
+
"host-agent",
|
|
23218
|
+
`fleet_migrate_box_image: rm of ${containerName} failed (code=${rm.code}): ${rm.stderr.trim().slice(-200)} \u2014 NOT creating a replacement`
|
|
23219
|
+
);
|
|
23220
|
+
return;
|
|
23221
|
+
}
|
|
23222
|
+
const res = await this.docker.run(buildFleetBoxMigrateArgs(payload), {
|
|
23223
|
+
timeoutMs: DOCKER_RUN_TIMEOUT_MS
|
|
23224
|
+
});
|
|
23225
|
+
if (res.code !== 0) {
|
|
23226
|
+
log.warn(
|
|
23227
|
+
"host-agent",
|
|
23228
|
+
`fleet_migrate_box_image: create of ${containerName} failed (code=${res.code}): ${res.stderr.trim().slice(-200)}`
|
|
23229
|
+
);
|
|
23230
|
+
return;
|
|
23231
|
+
}
|
|
23232
|
+
log.info(
|
|
23233
|
+
"host-agent",
|
|
23234
|
+
`fleet_migrate_box_image: ${containerName} re-pointed at :latest (still stopped)`
|
|
23235
|
+
);
|
|
23236
|
+
}
|
|
23129
23237
|
async fleetStartBox(payload) {
|
|
23130
23238
|
const { containerName } = payload;
|
|
23131
23239
|
if (fleetRefCanRecreate(payload) && await this.fleetBoxImageStale(containerName)) {
|
|
@@ -46905,7 +47013,7 @@ function checkChokidar() {
|
|
|
46905
47013
|
}
|
|
46906
47014
|
async function doctor(args2 = []) {
|
|
46907
47015
|
const json = args2.includes("--json");
|
|
46908
|
-
const cliVersion = true ? "2.
|
|
47016
|
+
const cliVersion = true ? "2.73.0" : "0.0.0-dev";
|
|
46909
47017
|
const apiBase2 = resolveApiBaseUrl();
|
|
46910
47018
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
46911
47019
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -47296,7 +47404,7 @@ async function mcpRun(args2) {
|
|
|
47296
47404
|
// src/commands/version.ts
|
|
47297
47405
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
47298
47406
|
function version2() {
|
|
47299
|
-
const v = true ? "2.
|
|
47407
|
+
const v = true ? "2.73.0" : "unknown";
|
|
47300
47408
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
47301
47409
|
}
|
|
47302
47410
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.73.0",
|
|
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",
|