codeam-cli 2.73.2 → 2.73.4
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 +16 -0
- package/dist/index.js +140 -36
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ 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.73.3] — 2026-09-02
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Debounce MCP reprovisions so a run of changes costs ONE respawn (#684)
|
|
12
|
+
|
|
13
|
+
## [2.73.2] — 2026-09-02
|
|
14
|
+
|
|
15
|
+
### CI
|
|
16
|
+
|
|
17
|
+
- **release:** Publish the release notes to #changelog and Discussions (#680)
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **cli:** An MCP reprovision burst must not kill the session (#682)
|
|
22
|
+
|
|
7
23
|
## [2.73.1] — 2026-09-02
|
|
8
24
|
|
|
9
25
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -8097,7 +8097,7 @@ function readAnonId() {
|
|
|
8097
8097
|
}
|
|
8098
8098
|
function superProperties() {
|
|
8099
8099
|
return {
|
|
8100
|
-
cliVersion: true ? "2.73.
|
|
8100
|
+
cliVersion: true ? "2.73.4" : "0.0.0-dev",
|
|
8101
8101
|
nodeVersion: process.version,
|
|
8102
8102
|
platform: process.platform,
|
|
8103
8103
|
arch: process.arch,
|
|
@@ -8339,7 +8339,7 @@ var http = __toESM(require("http"));
|
|
|
8339
8339
|
// package.json
|
|
8340
8340
|
var package_default = {
|
|
8341
8341
|
name: "codeam-cli",
|
|
8342
|
-
version: "2.73.
|
|
8342
|
+
version: "2.73.4",
|
|
8343
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.",
|
|
8344
8344
|
type: "commonjs",
|
|
8345
8345
|
main: "dist/index.js",
|
|
@@ -9932,7 +9932,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9932
9932
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9933
9933
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9934
9934
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9935
|
-
..."2.73.
|
|
9935
|
+
..."2.73.4" ? { ideVersion: "2.73.4" } : {}
|
|
9936
9936
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9937
9937
|
}
|
|
9938
9938
|
/**
|
|
@@ -22208,7 +22208,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
22208
22208
|
if (process.env.NODE_ENV === "test") return;
|
|
22209
22209
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22210
22210
|
if (process.env.CI) return;
|
|
22211
|
-
const current2 = true ? "2.73.
|
|
22211
|
+
const current2 = true ? "2.73.4" : null;
|
|
22212
22212
|
if (!current2) return;
|
|
22213
22213
|
const cache = readCache();
|
|
22214
22214
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22225,7 +22225,7 @@ function checkForUpdates() {
|
|
|
22225
22225
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22226
22226
|
if (process.env.CI) return;
|
|
22227
22227
|
if (!process.stdout.isTTY) return;
|
|
22228
|
-
const current2 = true ? "2.73.
|
|
22228
|
+
const current2 = true ? "2.73.4" : null;
|
|
22229
22229
|
if (!current2) return;
|
|
22230
22230
|
const cache = readCache();
|
|
22231
22231
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22248,7 +22248,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
22248
22248
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
22249
22249
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
22250
22250
|
function currentCliVersion() {
|
|
22251
|
-
return true ? "2.73.
|
|
22251
|
+
return true ? "2.73.4" : null;
|
|
22252
22252
|
}
|
|
22253
22253
|
async function installedVersion(deps) {
|
|
22254
22254
|
const ls = await deps.run(
|
|
@@ -35677,6 +35677,7 @@ var _acpStartSeam = {
|
|
|
35677
35677
|
var PROTOCOL_VERSION3 = 1;
|
|
35678
35678
|
var FATAL_STARTUP_RE = /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist|Error authenticating|ProjectIdRequiredError/i;
|
|
35679
35679
|
var NEWSESSION_TIMEOUT_MS = 12e4;
|
|
35680
|
+
var MCP_STARTUP_TIMEOUT_MS = NEWSESSION_TIMEOUT_MS - 3e4;
|
|
35680
35681
|
var LOADSESSION_TIMEOUT_MS = 6e4;
|
|
35681
35682
|
var PROMPT_IDLE_TIMEOUT_MS = 9e4;
|
|
35682
35683
|
var PROMPT_ACTIVE_IDLE_TIMEOUT_MS = 6e5;
|
|
@@ -35684,6 +35685,7 @@ var CLIENT_CAPABILITIES = {
|
|
|
35684
35685
|
fs: { readTextFile: true, writeTextFile: true },
|
|
35685
35686
|
terminal: false
|
|
35686
35687
|
};
|
|
35688
|
+
var MCP_REPROVISION_DEBOUNCE_MS = 1e4;
|
|
35687
35689
|
var AcpClient = class {
|
|
35688
35690
|
constructor(opts) {
|
|
35689
35691
|
this.opts = opts;
|
|
@@ -35756,8 +35758,9 @@ var AcpClient = class {
|
|
|
35756
35758
|
/** True once a start has fully succeeded (handshake + session). Distinguishes
|
|
35757
35759
|
* "never started" (a programming error) from "the adapter died" (recoverable). */
|
|
35758
35760
|
startedOnce = false;
|
|
35759
|
-
mcpReprovisionQueued = false;
|
|
35760
35761
|
mcpReprovisionPending = null;
|
|
35762
|
+
mcpDebounceTimer = null;
|
|
35763
|
+
mcpDebounceWaiters = [];
|
|
35761
35764
|
/** Last few adapter stderr lines — so a startup failure surfaces the REAL
|
|
35762
35765
|
* cause (e.g. gemini's `IneligibleTierError`) instead of a bare timeout. */
|
|
35763
35766
|
recentStderr = [];
|
|
@@ -35853,7 +35856,15 @@ var AcpClient = class {
|
|
|
35853
35856
|
// extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
|
|
35854
35857
|
// re-spawn) layers over process.env; PATH stays last so the augmented
|
|
35855
35858
|
// PATH always wins.
|
|
35856
|
-
|
|
35859
|
+
//
|
|
35860
|
+
// MCP_TIMEOUT comes FIRST so the caller can still override it, and it is
|
|
35861
|
+
// load-bearing — see MCP_STARTUP_TIMEOUT_MS.
|
|
35862
|
+
env: {
|
|
35863
|
+
...process.env,
|
|
35864
|
+
MCP_TIMEOUT: String(MCP_STARTUP_TIMEOUT_MS),
|
|
35865
|
+
...this.opts.extraEnv ?? {},
|
|
35866
|
+
PATH: augmentedPath
|
|
35867
|
+
},
|
|
35857
35868
|
stdio: ["pipe", "pipe", "pipe"]
|
|
35858
35869
|
});
|
|
35859
35870
|
this.child = child;
|
|
@@ -36268,19 +36279,30 @@ var AcpClient = class {
|
|
|
36268
36279
|
this.opts.mcpServers = servers;
|
|
36269
36280
|
if (!this.connection || !this.sessionId) return "deferred";
|
|
36270
36281
|
this.mcpReprovisionPending = servers;
|
|
36271
|
-
if (this.
|
|
36272
|
-
|
|
36273
|
-
|
|
36274
|
-
|
|
36282
|
+
if (this.mcpDebounceTimer) clearTimeout(this.mcpDebounceTimer);
|
|
36283
|
+
const settled = new Promise((resolve11) => {
|
|
36284
|
+
this.mcpDebounceWaiters.push(resolve11);
|
|
36285
|
+
});
|
|
36286
|
+
this.mcpDebounceTimer = setTimeout(() => {
|
|
36287
|
+
this.mcpDebounceTimer = null;
|
|
36275
36288
|
const latest = this.mcpReprovisionPending ?? servers;
|
|
36276
36289
|
this.mcpReprovisionPending = null;
|
|
36277
|
-
|
|
36278
|
-
|
|
36279
|
-
|
|
36280
|
-
|
|
36281
|
-
|
|
36282
|
-
|
|
36283
|
-
|
|
36290
|
+
const waiters = this.mcpDebounceWaiters;
|
|
36291
|
+
this.mcpDebounceWaiters = [];
|
|
36292
|
+
const run = this.promptChain.then(() => this.runReprovisionMcp(latest));
|
|
36293
|
+
this.promptChain = run.then(
|
|
36294
|
+
() => void 0,
|
|
36295
|
+
() => void 0
|
|
36296
|
+
);
|
|
36297
|
+
run.then(
|
|
36298
|
+
(result) => waiters.forEach((w3) => w3(result)),
|
|
36299
|
+
// `runReprovisionMcp` already swallows its own failures into
|
|
36300
|
+
// 'deferred'; this is the belt for anything the chain itself throws.
|
|
36301
|
+
() => waiters.forEach((w3) => w3("deferred"))
|
|
36302
|
+
);
|
|
36303
|
+
}, this.opts.mcpReprovisionDebounceMs ?? MCP_REPROVISION_DEBOUNCE_MS);
|
|
36304
|
+
this.mcpDebounceTimer.unref?.();
|
|
36305
|
+
return settled;
|
|
36284
36306
|
}
|
|
36285
36307
|
/** The actual respawn. Only ever called from {@link reprovisionMcp}'s queued
|
|
36286
36308
|
* slot, so it can assume no turn and no other respawn is running. */
|
|
@@ -36480,6 +36502,14 @@ var AcpClient = class {
|
|
|
36480
36502
|
*/
|
|
36481
36503
|
async stop() {
|
|
36482
36504
|
this.stopping = true;
|
|
36505
|
+
if (this.mcpDebounceTimer) {
|
|
36506
|
+
clearTimeout(this.mcpDebounceTimer);
|
|
36507
|
+
this.mcpDebounceTimer = null;
|
|
36508
|
+
this.mcpReprovisionPending = null;
|
|
36509
|
+
const waiters = this.mcpDebounceWaiters;
|
|
36510
|
+
this.mcpDebounceWaiters = [];
|
|
36511
|
+
waiters.forEach((w3) => w3("deferred"));
|
|
36512
|
+
}
|
|
36483
36513
|
const child = this.child;
|
|
36484
36514
|
if (!child) return;
|
|
36485
36515
|
this.child = null;
|
|
@@ -43681,12 +43711,22 @@ var TranscriptMirror = class {
|
|
|
43681
43711
|
unwatch = null;
|
|
43682
43712
|
pollHandle = null;
|
|
43683
43713
|
attached = false;
|
|
43714
|
+
/** True while `start()`'s own synchronous attach attempt is running, so
|
|
43715
|
+
* `tryAttach` can tell "the file was already there" from "it appeared while
|
|
43716
|
+
* we waited". The distinction is the whole basis for whether the first
|
|
43717
|
+
* batch is history or live content. */
|
|
43718
|
+
attachingAtStart = false;
|
|
43684
43719
|
pollIntervalMs;
|
|
43685
43720
|
waitTimeoutMs;
|
|
43686
43721
|
setIntervalFn;
|
|
43687
43722
|
clearIntervalFn;
|
|
43688
43723
|
start() {
|
|
43689
|
-
|
|
43724
|
+
this.attachingAtStart = true;
|
|
43725
|
+
try {
|
|
43726
|
+
if (this.tryAttach()) return;
|
|
43727
|
+
} finally {
|
|
43728
|
+
this.attachingAtStart = false;
|
|
43729
|
+
}
|
|
43690
43730
|
let waited = 0;
|
|
43691
43731
|
this.pollHandle = this.setIntervalFn(() => {
|
|
43692
43732
|
waited += this.pollIntervalMs;
|
|
@@ -43709,7 +43749,7 @@ var TranscriptMirror = class {
|
|
|
43709
43749
|
const file = this.deps.runtime.resolveHistoryFile?.(this.deps.cwd, this.deps.conversationId);
|
|
43710
43750
|
if (!file) return false;
|
|
43711
43751
|
this.attached = true;
|
|
43712
|
-
this.emit(file);
|
|
43752
|
+
this.emit(file, this.attachingAtStart);
|
|
43713
43753
|
const watch4 = this.deps.watch ?? defaultWatch;
|
|
43714
43754
|
this.unwatch = watch4(file, () => this.emit(file));
|
|
43715
43755
|
return true;
|
|
@@ -43720,7 +43760,7 @@ var TranscriptMirror = class {
|
|
|
43720
43760
|
this.pollHandle = null;
|
|
43721
43761
|
}
|
|
43722
43762
|
}
|
|
43723
|
-
emit(file) {
|
|
43763
|
+
emit(file, preexisting = false) {
|
|
43724
43764
|
let all;
|
|
43725
43765
|
try {
|
|
43726
43766
|
all = this.deps.runtime.parseHistoryFile(file);
|
|
@@ -43730,7 +43770,7 @@ var TranscriptMirror = class {
|
|
|
43730
43770
|
if (all.length <= this.emitted) return;
|
|
43731
43771
|
const delta = all.slice(this.emitted);
|
|
43732
43772
|
this.emitted = all.length;
|
|
43733
|
-
this.deps.onNewMessages(delta);
|
|
43773
|
+
this.deps.onNewMessages(delta, { preexisting });
|
|
43734
43774
|
}
|
|
43735
43775
|
};
|
|
43736
43776
|
function defaultWatch(file, onChange) {
|
|
@@ -43782,10 +43822,9 @@ async function publishMirroredTurnsLive(publisher, messages) {
|
|
|
43782
43822
|
}
|
|
43783
43823
|
}
|
|
43784
43824
|
function makeMirrorOnNewMessages(deps) {
|
|
43785
|
-
let isFirstEmit = true;
|
|
43786
43825
|
let publishChain = Promise.resolve();
|
|
43787
43826
|
const conversation = [];
|
|
43788
|
-
return (messages) => {
|
|
43827
|
+
return (messages, meta) => {
|
|
43789
43828
|
const relevant = messages.filter((m) => m.role !== "system");
|
|
43790
43829
|
if (relevant.length === 0) return;
|
|
43791
43830
|
const mapped = relevant.map((m) => ({
|
|
@@ -43800,7 +43839,7 @@ function makeMirrorOnNewMessages(deps) {
|
|
|
43800
43839
|
sessionId: deps.conversationId,
|
|
43801
43840
|
messages: conversation.slice()
|
|
43802
43841
|
});
|
|
43803
|
-
if (
|
|
43842
|
+
if (meta?.preexisting !== true) {
|
|
43804
43843
|
publishChain = publishChain.then(() => publishMirroredTurnsLive(deps.publisher, relevant)).catch((err) => {
|
|
43805
43844
|
log.warn(
|
|
43806
43845
|
"wireBaton",
|
|
@@ -43808,7 +43847,6 @@ function makeMirrorOnNewMessages(deps) {
|
|
|
43808
43847
|
);
|
|
43809
43848
|
});
|
|
43810
43849
|
}
|
|
43811
|
-
isFirstEmit = false;
|
|
43812
43850
|
};
|
|
43813
43851
|
}
|
|
43814
43852
|
function makeSerializedBatonPoster(post2) {
|
|
@@ -43935,9 +43973,8 @@ async function runBatonSession(opts) {
|
|
|
43935
43973
|
onConversationSwitch: (id) => controller.switchConversation(id)
|
|
43936
43974
|
});
|
|
43937
43975
|
let mirror = null;
|
|
43938
|
-
let firstLocalDrive = true;
|
|
43939
43976
|
let lastPublished = null;
|
|
43940
|
-
const startMirror = (conversationId
|
|
43977
|
+
const startMirror = (conversationId) => {
|
|
43941
43978
|
mirror?.stop();
|
|
43942
43979
|
mirror = new TranscriptMirror({
|
|
43943
43980
|
runtime,
|
|
@@ -43946,8 +43983,7 @@ async function runBatonSession(opts) {
|
|
|
43946
43983
|
onNewMessages: makeMirrorOnNewMessages({
|
|
43947
43984
|
publisher,
|
|
43948
43985
|
agentId: opts.agent,
|
|
43949
|
-
conversationId
|
|
43950
|
-
fresh
|
|
43986
|
+
conversationId
|
|
43951
43987
|
})
|
|
43952
43988
|
});
|
|
43953
43989
|
mirror.start();
|
|
@@ -43969,9 +44005,7 @@ async function runBatonSession(opts) {
|
|
|
43969
44005
|
publishState: (state, driver, conversationId) => {
|
|
43970
44006
|
publishBatonState(state, driver, conversationId);
|
|
43971
44007
|
if (state === "LOCAL_DRIVE" && conversationId) {
|
|
43972
|
-
|
|
43973
|
-
startMirror(conversationId, firstLocalDrive || switched);
|
|
43974
|
-
firstLocalDrive = false;
|
|
44008
|
+
startMirror(conversationId);
|
|
43975
44009
|
} else if (state !== "LOCAL_DRIVE") {
|
|
43976
44010
|
mirror?.stop();
|
|
43977
44011
|
}
|
|
@@ -47065,7 +47099,7 @@ function checkChokidar() {
|
|
|
47065
47099
|
}
|
|
47066
47100
|
async function doctor(args2 = []) {
|
|
47067
47101
|
const json = args2.includes("--json");
|
|
47068
|
-
const cliVersion = true ? "2.73.
|
|
47102
|
+
const cliVersion = true ? "2.73.4" : "0.0.0-dev";
|
|
47069
47103
|
const apiBase2 = resolveApiBaseUrl();
|
|
47070
47104
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
47071
47105
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -47453,10 +47487,77 @@ async function mcpRun(args2) {
|
|
|
47453
47487
|
await proxy.start();
|
|
47454
47488
|
}
|
|
47455
47489
|
|
|
47490
|
+
// src/integrations/mcp-warm.ts
|
|
47491
|
+
var import_node_child_process35 = require("child_process");
|
|
47492
|
+
function specOf(delivery) {
|
|
47493
|
+
if (!delivery.command) return null;
|
|
47494
|
+
const spec = (delivery.args ?? []).find((a) => !a.startsWith("-"));
|
|
47495
|
+
return spec ?? null;
|
|
47496
|
+
}
|
|
47497
|
+
function warmTargets() {
|
|
47498
|
+
const bySpec = /* @__PURE__ */ new Map();
|
|
47499
|
+
for (const integration of getEnabledIntegrations()) {
|
|
47500
|
+
const delivery = integration.delivery?.mcp;
|
|
47501
|
+
if (!delivery) continue;
|
|
47502
|
+
const spec = specOf(delivery);
|
|
47503
|
+
if (!spec) continue;
|
|
47504
|
+
if (!bySpec.has(spec)) {
|
|
47505
|
+
bySpec.set(spec, { id: integration.id, launcher: delivery.command, spec });
|
|
47506
|
+
}
|
|
47507
|
+
}
|
|
47508
|
+
return [...bySpec.values()];
|
|
47509
|
+
}
|
|
47510
|
+
function warmCommand(target) {
|
|
47511
|
+
if (target.launcher === "npx") {
|
|
47512
|
+
return { command: "npx", args: ["-y", "--package", target.spec, "-c", "true"] };
|
|
47513
|
+
}
|
|
47514
|
+
if (target.launcher === "uvx") {
|
|
47515
|
+
return { command: "uv", args: ["tool", "install", target.spec] };
|
|
47516
|
+
}
|
|
47517
|
+
return null;
|
|
47518
|
+
}
|
|
47519
|
+
async function mcpWarm(argv = []) {
|
|
47520
|
+
const timeoutMs = 3e5;
|
|
47521
|
+
const targets = warmTargets();
|
|
47522
|
+
const only = argv.filter((a) => !a.startsWith("-"));
|
|
47523
|
+
const selected = only.length > 0 ? targets.filter((t2) => only.includes(t2.id)) : targets;
|
|
47524
|
+
const result = { warmed: [], skipped: [], failed: [] };
|
|
47525
|
+
console.log(`[codeam mcp-warm] ${selected.length} MCP package(s) to pre-fetch`);
|
|
47526
|
+
for (const target of selected) {
|
|
47527
|
+
const cmd = warmCommand(target);
|
|
47528
|
+
if (!cmd) {
|
|
47529
|
+
result.skipped.push(`${target.spec} (no warm recipe for '${target.launcher}')`);
|
|
47530
|
+
continue;
|
|
47531
|
+
}
|
|
47532
|
+
const started = Date.now();
|
|
47533
|
+
const run = (0, import_node_child_process35.spawnSync)(cmd.command, cmd.args, {
|
|
47534
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
47535
|
+
timeout: timeoutMs,
|
|
47536
|
+
encoding: "utf8"
|
|
47537
|
+
});
|
|
47538
|
+
const secs = ((Date.now() - started) / 1e3).toFixed(1);
|
|
47539
|
+
if (run.status === 0) {
|
|
47540
|
+
result.warmed.push(target.spec);
|
|
47541
|
+
console.log(` OK ${target.spec} (${secs}s)`);
|
|
47542
|
+
} else {
|
|
47543
|
+
const reason = run.error?.message ?? (run.stderr ?? "").trim().split("\n").slice(-1)[0] ?? `exit ${String(run.status)}`;
|
|
47544
|
+
result.failed.push({ spec: target.spec, reason });
|
|
47545
|
+
console.log(` MISS ${target.spec} (${secs}s) \u2014 fetched at runtime instead: ${reason}`);
|
|
47546
|
+
}
|
|
47547
|
+
}
|
|
47548
|
+
console.log(
|
|
47549
|
+
`[codeam mcp-warm] warmed=${result.warmed.length} failed=${result.failed.length} skipped=${result.skipped.length}`
|
|
47550
|
+
);
|
|
47551
|
+
log.info(
|
|
47552
|
+
"mcpWarm",
|
|
47553
|
+
`warmed=${result.warmed.length} failed=${result.failed.length} skipped=${result.skipped.length}`
|
|
47554
|
+
);
|
|
47555
|
+
}
|
|
47556
|
+
|
|
47456
47557
|
// src/commands/version.ts
|
|
47457
47558
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
47458
47559
|
function version2() {
|
|
47459
|
-
const v = true ? "2.73.
|
|
47560
|
+
const v = true ? "2.73.4" : "unknown";
|
|
47460
47561
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
47461
47562
|
}
|
|
47462
47563
|
|
|
@@ -47657,6 +47758,9 @@ async function main() {
|
|
|
47657
47758
|
if (command === "mcp-run") {
|
|
47658
47759
|
return mcpRun(args);
|
|
47659
47760
|
}
|
|
47761
|
+
if (command === "mcp-warm") {
|
|
47762
|
+
return mcpWarm(args);
|
|
47763
|
+
}
|
|
47660
47764
|
if (command === "deploy") {
|
|
47661
47765
|
if (args[0] === "ls" || args[0] === "list") return deployList();
|
|
47662
47766
|
if (args[0] === "stop" || args[0] === "remove") return deployStop();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.73.
|
|
3
|
+
"version": "2.73.4",
|
|
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",
|