codeam-cli 2.39.28 → 2.39.30
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 +99 -8
- 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.39.29] — 2026-06-18
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Report host-agent enrollment progress to backend
|
|
12
|
+
|
|
13
|
+
## [2.39.28] — 2026-06-18
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli,vsc-plugin,jetbrains-plugin:** Add show_install_command relay handler (#355)
|
|
18
|
+
|
|
7
19
|
## [2.39.27] — 2026-06-17
|
|
8
20
|
|
|
9
21
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
498
498
|
// package.json
|
|
499
499
|
var package_default = {
|
|
500
500
|
name: "codeam-cli",
|
|
501
|
-
version: "2.39.
|
|
501
|
+
version: "2.39.30",
|
|
502
502
|
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.",
|
|
503
503
|
type: "commonjs",
|
|
504
504
|
main: "dist/index.js",
|
|
@@ -5908,7 +5908,7 @@ function readAnonId() {
|
|
|
5908
5908
|
}
|
|
5909
5909
|
function superProperties() {
|
|
5910
5910
|
return {
|
|
5911
|
-
cliVersion: true ? "2.39.
|
|
5911
|
+
cliVersion: true ? "2.39.30" : "0.0.0-dev",
|
|
5912
5912
|
nodeVersion: process.version,
|
|
5913
5913
|
platform: process.platform,
|
|
5914
5914
|
arch: process.arch,
|
|
@@ -26205,6 +26205,48 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
26205
26205
|
var fs41 = __toESM(require("fs"));
|
|
26206
26206
|
var os32 = __toESM(require("os"));
|
|
26207
26207
|
var path53 = __toESM(require("path"));
|
|
26208
|
+
function sampleCpuTimes() {
|
|
26209
|
+
let idle = 0;
|
|
26210
|
+
let total = 0;
|
|
26211
|
+
for (const cpu of os32.cpus()) {
|
|
26212
|
+
const t2 = cpu.times;
|
|
26213
|
+
idle += t2.idle;
|
|
26214
|
+
total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
|
|
26215
|
+
}
|
|
26216
|
+
return { idle, total };
|
|
26217
|
+
}
|
|
26218
|
+
var MetricsCollector = class {
|
|
26219
|
+
prevCpu = null;
|
|
26220
|
+
lastLatencyMs = 0;
|
|
26221
|
+
/** Record the measured round-trip of the heartbeat just sent. */
|
|
26222
|
+
recordLatency(latencyMs) {
|
|
26223
|
+
this.lastLatencyMs = Math.max(0, Math.round(latencyMs));
|
|
26224
|
+
}
|
|
26225
|
+
cpuPct() {
|
|
26226
|
+
const current = sampleCpuTimes();
|
|
26227
|
+
const prev = this.prevCpu;
|
|
26228
|
+
this.prevCpu = current;
|
|
26229
|
+
if (!prev) {
|
|
26230
|
+
const cores = os32.cpus().length || 1;
|
|
26231
|
+
const proxy = os32.loadavg()[0] / cores * 100;
|
|
26232
|
+
return Math.min(100, Math.max(0, Math.round(proxy)));
|
|
26233
|
+
}
|
|
26234
|
+
const idleDelta = current.idle - prev.idle;
|
|
26235
|
+
const totalDelta = current.total - prev.total;
|
|
26236
|
+
if (totalDelta <= 0) return 0;
|
|
26237
|
+
const busy = (1 - idleDelta / totalDelta) * 100;
|
|
26238
|
+
return Math.min(100, Math.max(0, Math.round(busy)));
|
|
26239
|
+
}
|
|
26240
|
+
/** Collect the current metrics snapshot for this beat. */
|
|
26241
|
+
collect() {
|
|
26242
|
+
return {
|
|
26243
|
+
cpuPct: this.cpuPct(),
|
|
26244
|
+
ramUsedMb: Math.round((os32.totalmem() - os32.freemem()) / 1048576),
|
|
26245
|
+
ramTotalMb: Math.round(os32.totalmem() / 1048576),
|
|
26246
|
+
latencyMs: this.lastLatencyMs
|
|
26247
|
+
};
|
|
26248
|
+
}
|
|
26249
|
+
};
|
|
26208
26250
|
function apiBase() {
|
|
26209
26251
|
return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
|
|
26210
26252
|
}
|
|
@@ -26268,11 +26310,15 @@ async function redeemEnrollToken(token, label) {
|
|
|
26268
26310
|
controlPluginId: data.controlPluginId
|
|
26269
26311
|
};
|
|
26270
26312
|
}
|
|
26271
|
-
async function sendHostHeartbeat(identity) {
|
|
26313
|
+
async function sendHostHeartbeat(identity, metrics) {
|
|
26314
|
+
const start2 = process.hrtime.bigint();
|
|
26272
26315
|
await postJson("/api/self-hosted/heartbeat", {
|
|
26273
26316
|
hostId: identity.hostId,
|
|
26274
|
-
hostToken: identity.hostToken
|
|
26317
|
+
hostToken: identity.hostToken,
|
|
26318
|
+
...metrics ? { metrics } : {}
|
|
26275
26319
|
});
|
|
26320
|
+
const elapsedNs = process.hrtime.bigint() - start2;
|
|
26321
|
+
return Math.round(Number(elapsedNs) / 1e6);
|
|
26276
26322
|
}
|
|
26277
26323
|
function isSealedEnvelope(v) {
|
|
26278
26324
|
if (typeof v !== "object" || v === null) return false;
|
|
@@ -26302,6 +26348,25 @@ async function unsealAgentAuth(identity, sealedAgentAuth) {
|
|
|
26302
26348
|
}
|
|
26303
26349
|
return data;
|
|
26304
26350
|
}
|
|
26351
|
+
var PROGRESS_TIMEOUT_MS = 3e3;
|
|
26352
|
+
async function reportProgress(auth, step, message) {
|
|
26353
|
+
try {
|
|
26354
|
+
const controller = new AbortController();
|
|
26355
|
+
const timer = setTimeout(() => controller.abort(), PROGRESS_TIMEOUT_MS);
|
|
26356
|
+
timer.unref?.();
|
|
26357
|
+
try {
|
|
26358
|
+
await fetch(`${apiBase()}/api/self-hosted/enroll-progress`, {
|
|
26359
|
+
method: "POST",
|
|
26360
|
+
headers: { "Content-Type": "application/json", ...vercelBypassHeader() },
|
|
26361
|
+
body: JSON.stringify({ ...auth, step, message }),
|
|
26362
|
+
signal: controller.signal
|
|
26363
|
+
});
|
|
26364
|
+
} finally {
|
|
26365
|
+
clearTimeout(timer);
|
|
26366
|
+
}
|
|
26367
|
+
} catch {
|
|
26368
|
+
}
|
|
26369
|
+
}
|
|
26305
26370
|
|
|
26306
26371
|
// src/commands/host.ts
|
|
26307
26372
|
function readTokenFlag(args2) {
|
|
@@ -26496,6 +26561,7 @@ var HostAgentSupervisor = class {
|
|
|
26496
26561
|
this.deps = deps;
|
|
26497
26562
|
this.spawnChild = deps.spawnChild ?? defaultSpawner;
|
|
26498
26563
|
this.resolveAgentAuth = deps.resolveAgentAuth ?? unsealAgentAuth;
|
|
26564
|
+
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
26499
26565
|
}
|
|
26500
26566
|
identity;
|
|
26501
26567
|
deps;
|
|
@@ -26504,6 +26570,10 @@ var HostAgentSupervisor = class {
|
|
|
26504
26570
|
resolveAgentAuth;
|
|
26505
26571
|
relay = null;
|
|
26506
26572
|
heartbeatTimer = null;
|
|
26573
|
+
/** Guards the one-shot 'connected' telemetry on the first heartbeat. */
|
|
26574
|
+
reportedConnected = false;
|
|
26575
|
+
/** Live-metrics collector — stateful across beats (CPU delta + latency). */
|
|
26576
|
+
metrics;
|
|
26507
26577
|
/** Open the control channel (reusing the relay) + start heartbeats. */
|
|
26508
26578
|
start() {
|
|
26509
26579
|
const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
|
|
@@ -26535,7 +26605,22 @@ var HostAgentSupervisor = class {
|
|
|
26535
26605
|
}
|
|
26536
26606
|
async beat() {
|
|
26537
26607
|
try {
|
|
26538
|
-
|
|
26608
|
+
let metrics;
|
|
26609
|
+
try {
|
|
26610
|
+
metrics = this.metrics.collect();
|
|
26611
|
+
} catch (err) {
|
|
26612
|
+
log.trace("host-agent", "metrics collection failed", err);
|
|
26613
|
+
}
|
|
26614
|
+
const latencyMs = await sendHostHeartbeat(this.identity, metrics);
|
|
26615
|
+
this.metrics.recordLatency(latencyMs);
|
|
26616
|
+
if (!this.reportedConnected) {
|
|
26617
|
+
this.reportedConnected = true;
|
|
26618
|
+
void reportProgress(
|
|
26619
|
+
{ hostId: this.identity.hostId, hostToken: this.identity.hostToken },
|
|
26620
|
+
"connected",
|
|
26621
|
+
"host-agent connected"
|
|
26622
|
+
);
|
|
26623
|
+
}
|
|
26539
26624
|
} catch (err) {
|
|
26540
26625
|
log.trace("host-agent", "heartbeat failed", err);
|
|
26541
26626
|
}
|
|
@@ -26642,8 +26727,14 @@ async function resolveHostIdentity(enrollToken) {
|
|
|
26642
26727
|
const existing = loadHostIdentity();
|
|
26643
26728
|
if (existing) return existing;
|
|
26644
26729
|
if (!enrollToken) return null;
|
|
26730
|
+
await reportProgress({ enrollToken }, "redeeming", "redeeming enrollment token\u2026");
|
|
26645
26731
|
const identity = await redeemEnrollToken(enrollToken);
|
|
26646
26732
|
saveHostIdentity(identity);
|
|
26733
|
+
await reportProgress(
|
|
26734
|
+
{ hostId: identity.hostId, hostToken: identity.hostToken },
|
|
26735
|
+
"enrolled",
|
|
26736
|
+
"host enrolled"
|
|
26737
|
+
);
|
|
26647
26738
|
return identity;
|
|
26648
26739
|
}
|
|
26649
26740
|
async function hostAgent(args2 = []) {
|
|
@@ -26840,7 +26931,7 @@ function checkChokidar() {
|
|
|
26840
26931
|
}
|
|
26841
26932
|
async function doctor(args2 = []) {
|
|
26842
26933
|
const json = args2.includes("--json");
|
|
26843
|
-
const cliVersion = true ? "2.39.
|
|
26934
|
+
const cliVersion = true ? "2.39.30" : "0.0.0-dev";
|
|
26844
26935
|
const apiBase2 = resolveApiBaseUrl();
|
|
26845
26936
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
26846
26937
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27039,7 +27130,7 @@ async function completion(args2) {
|
|
|
27039
27130
|
// src/commands/version.ts
|
|
27040
27131
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27041
27132
|
function version2() {
|
|
27042
|
-
const v = true ? "2.39.
|
|
27133
|
+
const v = true ? "2.39.30" : "unknown";
|
|
27043
27134
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27044
27135
|
}
|
|
27045
27136
|
|
|
@@ -27325,7 +27416,7 @@ function checkForUpdates() {
|
|
|
27325
27416
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27326
27417
|
if (process.env.CI) return;
|
|
27327
27418
|
if (!process.stdout.isTTY) return;
|
|
27328
|
-
const current = true ? "2.39.
|
|
27419
|
+
const current = true ? "2.39.30" : null;
|
|
27329
27420
|
if (!current) return;
|
|
27330
27421
|
const cache = readCache();
|
|
27331
27422
|
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.39.
|
|
3
|
+
"version": "2.39.30",
|
|
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",
|