codeam-cli 2.39.30 → 2.39.32
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 +244 -62
- 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.31] — 2026-06-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Host-agent re-enrollment + self-heal on deleted host
|
|
12
|
+
|
|
13
|
+
## [2.39.30] — 2026-06-18
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Report real system metrics in host-agent heartbeat
|
|
18
|
+
|
|
7
19
|
## [2.39.29] — 2026-06-18
|
|
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.32",
|
|
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.32" : "0.0.0-dev",
|
|
5912
5912
|
nodeVersion: process.version,
|
|
5913
5913
|
platform: process.platform,
|
|
5914
5914
|
arch: process.arch,
|
|
@@ -26283,6 +26283,31 @@ function saveHostIdentity(identity) {
|
|
|
26283
26283
|
});
|
|
26284
26284
|
fs41.chmodSync(file, 384);
|
|
26285
26285
|
}
|
|
26286
|
+
var HostHttpError = class extends Error {
|
|
26287
|
+
constructor(message, status2) {
|
|
26288
|
+
super(message);
|
|
26289
|
+
this.status = status2;
|
|
26290
|
+
this.name = "HostHttpError";
|
|
26291
|
+
}
|
|
26292
|
+
status;
|
|
26293
|
+
/**
|
|
26294
|
+
* True iff this is a genuine auth-rejection of the host identity:
|
|
26295
|
+
* 401 (token invalid), 403 (forbidden), 404 (host not found / deleted).
|
|
26296
|
+
* Transient failures (5xx, timeouts, network errors) are NOT rejections.
|
|
26297
|
+
*/
|
|
26298
|
+
get isAuthRejection() {
|
|
26299
|
+
return this.status === 401 || this.status === 403 || this.status === 404;
|
|
26300
|
+
}
|
|
26301
|
+
};
|
|
26302
|
+
function isHostAuthRejection(err) {
|
|
26303
|
+
return err instanceof HostHttpError && err.isAuthRejection;
|
|
26304
|
+
}
|
|
26305
|
+
function deleteHostIdentity() {
|
|
26306
|
+
try {
|
|
26307
|
+
fs41.rmSync(hostIdentityPath(), { force: true });
|
|
26308
|
+
} catch {
|
|
26309
|
+
}
|
|
26310
|
+
}
|
|
26286
26311
|
async function postJson(pathname, body) {
|
|
26287
26312
|
const res = await fetch(`${apiBase()}${pathname}`, {
|
|
26288
26313
|
method: "POST",
|
|
@@ -26292,8 +26317,9 @@ async function postJson(pathname, body) {
|
|
|
26292
26317
|
const json = await res.json();
|
|
26293
26318
|
if (!res.ok || !json.success) {
|
|
26294
26319
|
const err = !json.success ? json.error : void 0;
|
|
26295
|
-
throw new
|
|
26296
|
-
`${pathname} failed (${err?.code ?? `HTTP_${res.status}`}): ${err?.message ?? res.statusText}
|
|
26320
|
+
throw new HostHttpError(
|
|
26321
|
+
`${pathname} failed (${err?.code ?? `HTTP_${res.status}`}): ${err?.message ?? res.statusText}`,
|
|
26322
|
+
res.status
|
|
26297
26323
|
);
|
|
26298
26324
|
}
|
|
26299
26325
|
return json.data;
|
|
@@ -26367,6 +26393,30 @@ async function reportProgress(auth, step, message) {
|
|
|
26367
26393
|
} catch {
|
|
26368
26394
|
}
|
|
26369
26395
|
}
|
|
26396
|
+
async function reportDeployProgress(auth, deployId, step, message, sessionId) {
|
|
26397
|
+
try {
|
|
26398
|
+
const controller = new AbortController();
|
|
26399
|
+
const timer = setTimeout(() => controller.abort(), PROGRESS_TIMEOUT_MS);
|
|
26400
|
+
timer.unref?.();
|
|
26401
|
+
try {
|
|
26402
|
+
await fetch(`${apiBase()}/api/self-hosted/deploy-progress`, {
|
|
26403
|
+
method: "POST",
|
|
26404
|
+
headers: { "Content-Type": "application/json", ...vercelBypassHeader() },
|
|
26405
|
+
body: JSON.stringify({
|
|
26406
|
+
...auth,
|
|
26407
|
+
deployId,
|
|
26408
|
+
step,
|
|
26409
|
+
message,
|
|
26410
|
+
...sessionId ? { sessionId } : {}
|
|
26411
|
+
}),
|
|
26412
|
+
signal: controller.signal
|
|
26413
|
+
});
|
|
26414
|
+
} finally {
|
|
26415
|
+
clearTimeout(timer);
|
|
26416
|
+
}
|
|
26417
|
+
} catch {
|
|
26418
|
+
}
|
|
26419
|
+
}
|
|
26370
26420
|
|
|
26371
26421
|
// src/commands/host.ts
|
|
26372
26422
|
function readTokenFlag(args2) {
|
|
@@ -26429,12 +26479,46 @@ function isAbsolutePathTarget(target) {
|
|
|
26429
26479
|
function selfHostedWorkspaceRoot() {
|
|
26430
26480
|
return path54.join(os33.homedir(), ".codeam", "self-hosted");
|
|
26431
26481
|
}
|
|
26432
|
-
function
|
|
26482
|
+
function nonInteractiveGitEnv() {
|
|
26483
|
+
return {
|
|
26484
|
+
...process.env,
|
|
26485
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
26486
|
+
GIT_ASKPASS: "",
|
|
26487
|
+
GCM_INTERACTIVE: "never"
|
|
26488
|
+
};
|
|
26489
|
+
}
|
|
26490
|
+
function githubOwnerRepo(repoRef) {
|
|
26433
26491
|
const trimmed = repoRef.trim();
|
|
26492
|
+
const shorthand = /^([^/\s]+)\/([^/\s]+?)(?:\.git)?$/.exec(trimmed);
|
|
26493
|
+
if (shorthand && !/^https?:\/\//.test(trimmed) && !trimmed.startsWith("git@")) {
|
|
26494
|
+
return { owner: shorthand[1], repo: shorthand[2] };
|
|
26495
|
+
}
|
|
26496
|
+
const httpsMatch = /^https?:\/\/github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
26497
|
+
if (httpsMatch) return { owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
26498
|
+
return null;
|
|
26499
|
+
}
|
|
26500
|
+
function repoCloneUrl(repoRef, cloneToken) {
|
|
26501
|
+
const trimmed = repoRef.trim();
|
|
26502
|
+
if (cloneToken) {
|
|
26503
|
+
const gh = githubOwnerRepo(trimmed);
|
|
26504
|
+
if (gh) {
|
|
26505
|
+
return `https://x-access-token:${cloneToken}@github.com/${gh.owner}/${gh.repo}.git`;
|
|
26506
|
+
}
|
|
26507
|
+
}
|
|
26434
26508
|
if (/^https?:\/\//.test(trimmed) || trimmed.startsWith("git@")) return trimmed;
|
|
26435
26509
|
return `https://github.com/${trimmed.replace(/\.git$/, "")}.git`;
|
|
26436
26510
|
}
|
|
26437
|
-
|
|
26511
|
+
function maskCloneUrl(url) {
|
|
26512
|
+
return url.replace(/(https?:\/\/)[^@/]+@/, "$1***@");
|
|
26513
|
+
}
|
|
26514
|
+
function maskToken(text, cloneToken) {
|
|
26515
|
+
const masked = maskCloneUrl(text);
|
|
26516
|
+
if (cloneToken && cloneToken.length > 0) {
|
|
26517
|
+
return masked.split(cloneToken).join("***");
|
|
26518
|
+
}
|
|
26519
|
+
return masked;
|
|
26520
|
+
}
|
|
26521
|
+
async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
|
|
26438
26522
|
if (isAbsolutePathTarget(repoOrPath)) {
|
|
26439
26523
|
if (!fs42.existsSync(repoOrPath)) {
|
|
26440
26524
|
throw new Error(`deploy target path does not exist: ${repoOrPath}`);
|
|
@@ -26446,10 +26530,17 @@ async function prepareWorkspace(repoOrPath, deployId) {
|
|
|
26446
26530
|
return dest;
|
|
26447
26531
|
}
|
|
26448
26532
|
fs42.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
|
|
26449
|
-
|
|
26450
|
-
|
|
26451
|
-
|
|
26452
|
-
|
|
26533
|
+
const cloneUrl = repoCloneUrl(repoOrPath, cloneToken);
|
|
26534
|
+
try {
|
|
26535
|
+
await execFileP9("git", ["clone", "--depth", "1", cloneUrl, dest], {
|
|
26536
|
+
timeout: 12e4,
|
|
26537
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
26538
|
+
env: nonInteractiveGitEnv()
|
|
26539
|
+
});
|
|
26540
|
+
} catch (err) {
|
|
26541
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
26542
|
+
throw new Error(`git clone failed for ${maskCloneUrl(cloneUrl)}: ${maskToken(reason, cloneToken)}`);
|
|
26543
|
+
}
|
|
26453
26544
|
return dest;
|
|
26454
26545
|
}
|
|
26455
26546
|
|
|
@@ -26534,6 +26625,9 @@ function isDeployPayload(p2) {
|
|
|
26534
26625
|
if (typeof p2.deployId !== "string" || typeof p2.repoOrPath !== "string" || typeof p2.agentId !== "string" || typeof p2.autoPairToken !== "string") {
|
|
26535
26626
|
return false;
|
|
26536
26627
|
}
|
|
26628
|
+
if (p2.cloneToken !== void 0 && typeof p2.cloneToken !== "string") {
|
|
26629
|
+
return false;
|
|
26630
|
+
}
|
|
26537
26631
|
const hasHouse = isHouseProxy(p2.houseProxy);
|
|
26538
26632
|
const hasSealed = typeof p2.sealedAgentAuth === "string";
|
|
26539
26633
|
return hasHouse || hasSealed;
|
|
@@ -26552,9 +26646,20 @@ var CONTROL_AGENT_META = {
|
|
|
26552
26646
|
var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
|
|
26553
26647
|
cwd,
|
|
26554
26648
|
env: { ...process.env, ...env },
|
|
26555
|
-
stdio: "ignore",
|
|
26649
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
26556
26650
|
detached: false
|
|
26557
26651
|
});
|
|
26652
|
+
var defaultOnIdentityRejected = () => {
|
|
26653
|
+
deleteHostIdentity();
|
|
26654
|
+
log.warn("host-agent", "host identity rejected by backend \u2014 wiped sealed identity, exiting");
|
|
26655
|
+
process.exit(1);
|
|
26656
|
+
};
|
|
26657
|
+
var defaultDisableService = () => {
|
|
26658
|
+
try {
|
|
26659
|
+
(0, import_node_child_process13.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
|
|
26660
|
+
} catch {
|
|
26661
|
+
}
|
|
26662
|
+
};
|
|
26558
26663
|
var HostAgentSupervisor = class {
|
|
26559
26664
|
constructor(identity, deps = {}) {
|
|
26560
26665
|
this.identity = identity;
|
|
@@ -26562,6 +26667,8 @@ var HostAgentSupervisor = class {
|
|
|
26562
26667
|
this.spawnChild = deps.spawnChild ?? defaultSpawner;
|
|
26563
26668
|
this.resolveAgentAuth = deps.resolveAgentAuth ?? unsealAgentAuth;
|
|
26564
26669
|
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
26670
|
+
this.onIdentityRejected = deps.onIdentityRejected ?? defaultOnIdentityRejected;
|
|
26671
|
+
this.disableService = deps.disableService ?? defaultDisableService;
|
|
26565
26672
|
}
|
|
26566
26673
|
identity;
|
|
26567
26674
|
deps;
|
|
@@ -26574,6 +26681,12 @@ var HostAgentSupervisor = class {
|
|
|
26574
26681
|
reportedConnected = false;
|
|
26575
26682
|
/** Live-metrics collector — stateful across beats (CPU delta + latency). */
|
|
26576
26683
|
metrics;
|
|
26684
|
+
/** Self-heal action when the backend rejects this identity. */
|
|
26685
|
+
onIdentityRejected;
|
|
26686
|
+
/** Best-effort systemd de-provision used by `self_hosted_wipe`. */
|
|
26687
|
+
disableService;
|
|
26688
|
+
/** Guards against firing the self-heal more than once. */
|
|
26689
|
+
healing = false;
|
|
26577
26690
|
/** Open the control channel (reusing the relay) + start heartbeats. */
|
|
26578
26691
|
start() {
|
|
26579
26692
|
const make = this.deps.makeRelay ?? ((pluginId, onCommand, meta) => new CommandRelayService(pluginId, onCommand, meta));
|
|
@@ -26622,6 +26735,14 @@ var HostAgentSupervisor = class {
|
|
|
26622
26735
|
);
|
|
26623
26736
|
}
|
|
26624
26737
|
} catch (err) {
|
|
26738
|
+
if (isHostAuthRejection(err)) {
|
|
26739
|
+
if (!this.healing) {
|
|
26740
|
+
this.healing = true;
|
|
26741
|
+
log.warn("host-agent", "heartbeat rejected \u2014 host deleted/revoked, self-healing", err);
|
|
26742
|
+
this.onIdentityRejected();
|
|
26743
|
+
}
|
|
26744
|
+
return;
|
|
26745
|
+
}
|
|
26625
26746
|
log.trace("host-agent", "heartbeat failed", err);
|
|
26626
26747
|
}
|
|
26627
26748
|
}
|
|
@@ -26651,6 +26772,16 @@ var HostAgentSupervisor = class {
|
|
|
26651
26772
|
this.stopChild(cmd.payload.sessionId);
|
|
26652
26773
|
return;
|
|
26653
26774
|
}
|
|
26775
|
+
if (cmd.type === "self_hosted_wipe") {
|
|
26776
|
+
log.warn("host-agent", `self_hosted_wipe received id=${cmd.id} \u2014 de-provisioning`);
|
|
26777
|
+
this.stop();
|
|
26778
|
+
this.disableService();
|
|
26779
|
+
if (!this.healing) {
|
|
26780
|
+
this.healing = true;
|
|
26781
|
+
this.onIdentityRejected();
|
|
26782
|
+
}
|
|
26783
|
+
return;
|
|
26784
|
+
}
|
|
26654
26785
|
log.trace("host-agent", `ignoring unsupported command type=${cmd.type}`);
|
|
26655
26786
|
}
|
|
26656
26787
|
/**
|
|
@@ -26668,43 +26799,86 @@ var HostAgentSupervisor = class {
|
|
|
26668
26799
|
"host-agent",
|
|
26669
26800
|
`deploy id=${payload.deployId.slice(0, 8)} agent=${payload.agentId} target=${payload.repoOrPath}`
|
|
26670
26801
|
);
|
|
26671
|
-
const
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
|
|
26675
|
-
|
|
26676
|
-
|
|
26677
|
-
|
|
26678
|
-
|
|
26679
|
-
|
|
26680
|
-
|
|
26681
|
-
|
|
26682
|
-
|
|
26683
|
-
|
|
26684
|
-
|
|
26685
|
-
|
|
26686
|
-
|
|
26687
|
-
|
|
26688
|
-
|
|
26689
|
-
|
|
26690
|
-
|
|
26691
|
-
|
|
26692
|
-
|
|
26693
|
-
|
|
26802
|
+
const report = (step, message) => {
|
|
26803
|
+
void reportDeployProgress(
|
|
26804
|
+
{ hostId: this.identity.hostId, hostToken: this.identity.hostToken },
|
|
26805
|
+
payload.deployId,
|
|
26806
|
+
step,
|
|
26807
|
+
message
|
|
26808
|
+
);
|
|
26809
|
+
};
|
|
26810
|
+
try {
|
|
26811
|
+
report("preparing", "preparing workspace");
|
|
26812
|
+
if (!isAbsolutePathTarget(payload.repoOrPath)) {
|
|
26813
|
+
report("cloning", "cloning repository");
|
|
26814
|
+
}
|
|
26815
|
+
const cwd = await prepareWorkspace(payload.repoOrPath, payload.deployId, payload.cloneToken);
|
|
26816
|
+
let childEnv;
|
|
26817
|
+
let extraArgs = [];
|
|
26818
|
+
if (payload.houseProxy) {
|
|
26819
|
+
const { baseUrl, token, agentKind } = payload.houseProxy;
|
|
26820
|
+
childEnv = {
|
|
26821
|
+
ANTHROPIC_BASE_URL: baseUrl,
|
|
26822
|
+
ANTHROPIC_AUTH_TOKEN: token,
|
|
26823
|
+
ANTHROPIC_MODEL: "MiniMax-M3",
|
|
26824
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "MiniMax-M3",
|
|
26825
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "MiniMax-M3",
|
|
26826
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: "MiniMax-M3",
|
|
26827
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: "512000",
|
|
26828
|
+
API_TIMEOUT_MS: "3000000",
|
|
26829
|
+
CODEAM_AUTO_TOKEN: payload.autoPairToken
|
|
26830
|
+
};
|
|
26831
|
+
extraArgs = [`--agent=${agentKind || "claude"}`];
|
|
26832
|
+
} else {
|
|
26833
|
+
const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
|
|
26834
|
+
const credEnv = provisionAgentCredentials(payload.agentId, auth, void 0);
|
|
26835
|
+
childEnv = {
|
|
26836
|
+
...credEnv,
|
|
26837
|
+
CODEAM_AUTO_TOKEN: payload.autoPairToken
|
|
26838
|
+
};
|
|
26839
|
+
}
|
|
26840
|
+
report("spawning", "starting agent");
|
|
26841
|
+
const proc = this.spawnChild(childEnv, cwd, extraArgs);
|
|
26842
|
+
const child = { deployId: payload.deployId, proc };
|
|
26843
|
+
this.children.set(payload.deployId, child);
|
|
26844
|
+
let tail = "";
|
|
26845
|
+
const appendTail = (buf) => {
|
|
26846
|
+
tail = (tail + buf.toString("utf8")).slice(-2e3);
|
|
26694
26847
|
};
|
|
26695
|
-
|
|
26696
|
-
|
|
26697
|
-
|
|
26698
|
-
|
|
26699
|
-
|
|
26700
|
-
|
|
26848
|
+
proc.stdout?.on("data", appendTail);
|
|
26849
|
+
proc.stderr?.on("data", appendTail);
|
|
26850
|
+
report("agent_starting", "agent process started");
|
|
26851
|
+
proc.once("exit", (code) => {
|
|
26852
|
+
const tracked = this.children.get(payload.deployId)?.proc === proc;
|
|
26853
|
+
if (tracked) {
|
|
26854
|
+
this.children.delete(payload.deployId);
|
|
26855
|
+
}
|
|
26856
|
+
if (tracked && typeof code === "number" && code !== 0) {
|
|
26857
|
+
const detail = tail.trim().slice(-500);
|
|
26858
|
+
report("failed", detail ? `agent exited (${code}): ${detail}` : `agent exited (${code})`);
|
|
26859
|
+
}
|
|
26860
|
+
});
|
|
26861
|
+
} catch (err) {
|
|
26862
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
26863
|
+
log.warn("host-agent", `deploy ${payload.deployId.slice(0, 8)} failed: ${message}`);
|
|
26864
|
+
const existing = this.children.get(payload.deployId);
|
|
26865
|
+
if (existing) {
|
|
26866
|
+
try {
|
|
26867
|
+
existing.proc.kill("SIGTERM");
|
|
26868
|
+
} catch {
|
|
26869
|
+
}
|
|
26701
26870
|
this.children.delete(payload.deployId);
|
|
26702
26871
|
}
|
|
26703
|
-
|
|
26872
|
+
report("failed", message);
|
|
26873
|
+
}
|
|
26704
26874
|
}
|
|
26705
|
-
/**
|
|
26875
|
+
/**
|
|
26876
|
+
* Kill the child for the given id. The backend correlates the session it
|
|
26877
|
+
* sends to this deploy, so the id matches the deployId we keyed on. No-op
|
|
26878
|
+
* if absent.
|
|
26879
|
+
*/
|
|
26706
26880
|
stopChild(sessionId) {
|
|
26707
|
-
const child = this.children.get(sessionId)
|
|
26881
|
+
const child = this.children.get(sessionId);
|
|
26708
26882
|
if (!child) {
|
|
26709
26883
|
log.trace("host-agent", `stop: no child for sessionId=${sessionId}`);
|
|
26710
26884
|
return;
|
|
@@ -26716,26 +26890,34 @@ var HostAgentSupervisor = class {
|
|
|
26716
26890
|
}
|
|
26717
26891
|
this.children.delete(child.deployId);
|
|
26718
26892
|
}
|
|
26719
|
-
findBySessionId(sessionId) {
|
|
26720
|
-
for (const child of this.children.values()) {
|
|
26721
|
-
if (child.sessionId === sessionId) return child;
|
|
26722
|
-
}
|
|
26723
|
-
return void 0;
|
|
26724
|
-
}
|
|
26725
26893
|
};
|
|
26726
26894
|
async function resolveHostIdentity(enrollToken) {
|
|
26727
26895
|
const existing = loadHostIdentity();
|
|
26896
|
+
if (enrollToken) {
|
|
26897
|
+
await reportProgress({ enrollToken }, "redeeming", "redeeming enrollment token\u2026");
|
|
26898
|
+
try {
|
|
26899
|
+
const identity = await redeemEnrollToken(enrollToken);
|
|
26900
|
+
saveHostIdentity(identity);
|
|
26901
|
+
await reportProgress(
|
|
26902
|
+
{ hostId: identity.hostId, hostToken: identity.hostToken },
|
|
26903
|
+
"enrolled",
|
|
26904
|
+
"host enrolled"
|
|
26905
|
+
);
|
|
26906
|
+
return identity;
|
|
26907
|
+
} catch (err) {
|
|
26908
|
+
if (existing) {
|
|
26909
|
+
log.trace(
|
|
26910
|
+
"host-agent",
|
|
26911
|
+
"enroll-token redeem failed; reusing sealed identity (likely a restart)",
|
|
26912
|
+
err
|
|
26913
|
+
);
|
|
26914
|
+
return existing;
|
|
26915
|
+
}
|
|
26916
|
+
throw err;
|
|
26917
|
+
}
|
|
26918
|
+
}
|
|
26728
26919
|
if (existing) return existing;
|
|
26729
|
-
|
|
26730
|
-
await reportProgress({ enrollToken }, "redeeming", "redeeming enrollment token\u2026");
|
|
26731
|
-
const identity = await redeemEnrollToken(enrollToken);
|
|
26732
|
-
saveHostIdentity(identity);
|
|
26733
|
-
await reportProgress(
|
|
26734
|
-
{ hostId: identity.hostId, hostToken: identity.hostToken },
|
|
26735
|
-
"enrolled",
|
|
26736
|
-
"host enrolled"
|
|
26737
|
-
);
|
|
26738
|
-
return identity;
|
|
26920
|
+
return null;
|
|
26739
26921
|
}
|
|
26740
26922
|
async function hostAgent(args2 = []) {
|
|
26741
26923
|
const tokenArg = args2.find((a) => a.startsWith("--token="));
|
|
@@ -26931,7 +27113,7 @@ function checkChokidar() {
|
|
|
26931
27113
|
}
|
|
26932
27114
|
async function doctor(args2 = []) {
|
|
26933
27115
|
const json = args2.includes("--json");
|
|
26934
|
-
const cliVersion = true ? "2.39.
|
|
27116
|
+
const cliVersion = true ? "2.39.32" : "0.0.0-dev";
|
|
26935
27117
|
const apiBase2 = resolveApiBaseUrl();
|
|
26936
27118
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
26937
27119
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27130,7 +27312,7 @@ async function completion(args2) {
|
|
|
27130
27312
|
// src/commands/version.ts
|
|
27131
27313
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27132
27314
|
function version2() {
|
|
27133
|
-
const v = true ? "2.39.
|
|
27315
|
+
const v = true ? "2.39.32" : "unknown";
|
|
27134
27316
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27135
27317
|
}
|
|
27136
27318
|
|
|
@@ -27416,7 +27598,7 @@ function checkForUpdates() {
|
|
|
27416
27598
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27417
27599
|
if (process.env.CI) return;
|
|
27418
27600
|
if (!process.stdout.isTTY) return;
|
|
27419
|
-
const current = true ? "2.39.
|
|
27601
|
+
const current = true ? "2.39.32" : null;
|
|
27420
27602
|
if (!current) return;
|
|
27421
27603
|
const cache = readCache();
|
|
27422
27604
|
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.32",
|
|
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",
|