codeam-cli 2.39.32 → 2.39.34
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 +6 -0
- package/dist/index.js +174 -101
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ 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.32] — 2026-06-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Host-agent deploy clones private repos + reports progress, no silent hang
|
|
12
|
+
|
|
7
13
|
## [2.39.31] — 2026-06-18
|
|
8
14
|
|
|
9
15
|
### Fixed
|
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.34",
|
|
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.34" : "0.0.0-dev",
|
|
5912
5912
|
nodeVersion: process.version,
|
|
5913
5913
|
platform: process.platform,
|
|
5914
5914
|
arch: process.arch,
|
|
@@ -7302,10 +7302,10 @@ function buildForPlatform(platform3) {
|
|
|
7302
7302
|
var import_node_crypto4 = require("crypto");
|
|
7303
7303
|
|
|
7304
7304
|
// src/agents/claude/resolver.ts
|
|
7305
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
7306
|
-
const found =
|
|
7305
|
+
function buildClaudeLaunch(extraArgs = [], os38 = createOsStrategy()) {
|
|
7306
|
+
const found = os38.findInPath("claude") ?? os38.findInPath("claude-code");
|
|
7307
7307
|
if (!found) return null;
|
|
7308
|
-
return
|
|
7308
|
+
return os38.buildLaunch(found, extraArgs);
|
|
7309
7309
|
}
|
|
7310
7310
|
|
|
7311
7311
|
// src/agents/claude/installer.ts
|
|
@@ -9754,8 +9754,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9754
9754
|
meta = getAgent("claude");
|
|
9755
9755
|
mode = "interactive";
|
|
9756
9756
|
os;
|
|
9757
|
-
constructor(
|
|
9758
|
-
this.os =
|
|
9757
|
+
constructor(os38) {
|
|
9758
|
+
this.os = os38;
|
|
9759
9759
|
}
|
|
9760
9760
|
/**
|
|
9761
9761
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -10374,8 +10374,8 @@ function codexCredentialLocator() {
|
|
|
10374
10374
|
function codexLoginLauncher() {
|
|
10375
10375
|
return {
|
|
10376
10376
|
async ensureInstalled() {
|
|
10377
|
-
const
|
|
10378
|
-
return
|
|
10377
|
+
const os38 = createOsStrategy();
|
|
10378
|
+
return os38.findInPath("codex") !== null;
|
|
10379
10379
|
},
|
|
10380
10380
|
launch() {
|
|
10381
10381
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -10398,8 +10398,8 @@ var CodexRuntimeStrategy = class {
|
|
|
10398
10398
|
meta = getAgent("codex");
|
|
10399
10399
|
mode = "interactive";
|
|
10400
10400
|
os;
|
|
10401
|
-
constructor(
|
|
10402
|
-
this.os =
|
|
10401
|
+
constructor(os38) {
|
|
10402
|
+
this.os = os38;
|
|
10403
10403
|
}
|
|
10404
10404
|
async prepareLaunch() {
|
|
10405
10405
|
let binary = this.os.findInPath("codex");
|
|
@@ -10495,12 +10495,12 @@ var CodexRuntimeStrategy = class {
|
|
|
10495
10495
|
});
|
|
10496
10496
|
}
|
|
10497
10497
|
};
|
|
10498
|
-
function resolveNpm(
|
|
10499
|
-
return
|
|
10498
|
+
function resolveNpm(os38) {
|
|
10499
|
+
return os38.id === "win32" ? "npm.cmd" : "npm";
|
|
10500
10500
|
}
|
|
10501
|
-
async function installCodexViaNpm(
|
|
10501
|
+
async function installCodexViaNpm(os38) {
|
|
10502
10502
|
return new Promise((resolve7, reject) => {
|
|
10503
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
10503
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os38), ["install", "-g", "@openai/codex"], {
|
|
10504
10504
|
stdio: "inherit"
|
|
10505
10505
|
});
|
|
10506
10506
|
proc.on("close", (code) => {
|
|
@@ -10517,16 +10517,16 @@ async function installCodexViaNpm(os36) {
|
|
|
10517
10517
|
});
|
|
10518
10518
|
});
|
|
10519
10519
|
}
|
|
10520
|
-
function augmentNpmGlobalBin(
|
|
10520
|
+
function augmentNpmGlobalBin(os38) {
|
|
10521
10521
|
try {
|
|
10522
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
10522
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os38), ["prefix", "-g"], {
|
|
10523
10523
|
stdio: ["ignore", "pipe", "ignore"]
|
|
10524
10524
|
});
|
|
10525
10525
|
if (result.status !== 0) return;
|
|
10526
10526
|
const prefix = result.stdout.toString().trim();
|
|
10527
10527
|
if (!prefix) return;
|
|
10528
|
-
const binDir =
|
|
10529
|
-
|
|
10528
|
+
const binDir = os38.id === "win32" ? prefix : path17.join(prefix, "bin");
|
|
10529
|
+
os38.augmentPath([binDir]);
|
|
10530
10530
|
} catch {
|
|
10531
10531
|
}
|
|
10532
10532
|
}
|
|
@@ -10610,9 +10610,9 @@ var import_node_child_process7 = require("child_process");
|
|
|
10610
10610
|
// src/agents/coderabbit/installer.ts
|
|
10611
10611
|
var import_node_child_process5 = require("child_process");
|
|
10612
10612
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
10613
|
-
async function ensureCoderabbitInstalled(
|
|
10614
|
-
if (
|
|
10615
|
-
if (
|
|
10613
|
+
async function ensureCoderabbitInstalled(os38) {
|
|
10614
|
+
if (os38.findInPath("coderabbit")) return true;
|
|
10615
|
+
if (os38.id === "win32") {
|
|
10616
10616
|
console.error(
|
|
10617
10617
|
"\n \u2717 CodeRabbit on Windows requires WSL.\n Install the CLI inside your WSL distribution\n (curl -fsSL https://cli.coderabbit.ai/install.sh | sh)\n then re-run `codeam link coderabbit` from WSL.\n"
|
|
10618
10618
|
);
|
|
@@ -10627,8 +10627,8 @@ async function ensureCoderabbitInstalled(os36) {
|
|
|
10627
10627
|
proc.on("error", () => resolve7(false));
|
|
10628
10628
|
});
|
|
10629
10629
|
if (!ok) return false;
|
|
10630
|
-
|
|
10631
|
-
return
|
|
10630
|
+
os38.augmentPath([`${os38.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
10631
|
+
return os38.findInPath("coderabbit") !== null;
|
|
10632
10632
|
}
|
|
10633
10633
|
|
|
10634
10634
|
// src/agents/coderabbit/link.ts
|
|
@@ -10655,10 +10655,10 @@ function coderabbitCredentialLocator() {
|
|
|
10655
10655
|
extract: extractLocalCoderabbitToken
|
|
10656
10656
|
};
|
|
10657
10657
|
}
|
|
10658
|
-
function coderabbitLoginLauncher(
|
|
10658
|
+
function coderabbitLoginLauncher(os38) {
|
|
10659
10659
|
return {
|
|
10660
10660
|
async ensureInstalled() {
|
|
10661
|
-
return ensureCoderabbitInstalled(
|
|
10661
|
+
return ensureCoderabbitInstalled(os38);
|
|
10662
10662
|
},
|
|
10663
10663
|
launch() {
|
|
10664
10664
|
return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
@@ -10704,8 +10704,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
10704
10704
|
meta = getAgent("coderabbit");
|
|
10705
10705
|
mode = "batch";
|
|
10706
10706
|
os;
|
|
10707
|
-
constructor(
|
|
10708
|
-
this.os =
|
|
10707
|
+
constructor(os38) {
|
|
10708
|
+
this.os = os38;
|
|
10709
10709
|
}
|
|
10710
10710
|
getDefaultArgs() {
|
|
10711
10711
|
return ["review"];
|
|
@@ -10820,10 +10820,10 @@ function cursorCredentialLocator() {
|
|
|
10820
10820
|
extract: extractLocalCursorToken
|
|
10821
10821
|
};
|
|
10822
10822
|
}
|
|
10823
|
-
function cursorLoginLauncher(
|
|
10823
|
+
function cursorLoginLauncher(os38) {
|
|
10824
10824
|
return {
|
|
10825
10825
|
async ensureInstalled() {
|
|
10826
|
-
if (
|
|
10826
|
+
if (os38.findInPath("cursor-agent")) return true;
|
|
10827
10827
|
console.error(
|
|
10828
10828
|
"\n \u2717 cursor-agent binary not on PATH.\n Install Cursor (https://cursor.com/) and ensure the CLI\n plugin is enabled, then re-run `codeam link cursor`.\n"
|
|
10829
10829
|
);
|
|
@@ -10885,8 +10885,8 @@ var CursorRuntimeStrategy = class {
|
|
|
10885
10885
|
meta = getAgent("cursor");
|
|
10886
10886
|
mode = "interactive";
|
|
10887
10887
|
os;
|
|
10888
|
-
constructor(
|
|
10889
|
-
this.os =
|
|
10888
|
+
constructor(os38) {
|
|
10889
|
+
this.os = os38;
|
|
10890
10890
|
}
|
|
10891
10891
|
async prepareLaunch() {
|
|
10892
10892
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -11006,10 +11006,10 @@ function aiderCredentialLocator() {
|
|
|
11006
11006
|
extract: extractLocalAiderToken
|
|
11007
11007
|
};
|
|
11008
11008
|
}
|
|
11009
|
-
function aiderLoginLauncher(
|
|
11009
|
+
function aiderLoginLauncher(os38) {
|
|
11010
11010
|
return {
|
|
11011
11011
|
async ensureInstalled() {
|
|
11012
|
-
if (
|
|
11012
|
+
if (os38.findInPath("aider")) return true;
|
|
11013
11013
|
console.error(
|
|
11014
11014
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
11015
11015
|
);
|
|
@@ -11019,7 +11019,7 @@ function aiderLoginLauncher(os36) {
|
|
|
11019
11019
|
console.error(
|
|
11020
11020
|
"\n Aider has no interactive login flow.\n Set ANTHROPIC_API_KEY or OPENAI_API_KEY in your shell,\n or re-run `codeam link aider --api-key=<your-key>`.\n"
|
|
11021
11021
|
);
|
|
11022
|
-
return (0, import_node_child_process9.spawn)(
|
|
11022
|
+
return (0, import_node_child_process9.spawn)(os38.id === "win32" ? "cmd.exe" : "sh", os38.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
11023
11023
|
stdio: "ignore"
|
|
11024
11024
|
});
|
|
11025
11025
|
}
|
|
@@ -11091,8 +11091,8 @@ var AiderRuntimeStrategy = class {
|
|
|
11091
11091
|
meta = getAgent("aider");
|
|
11092
11092
|
mode = "interactive";
|
|
11093
11093
|
os;
|
|
11094
|
-
constructor(
|
|
11095
|
-
this.os =
|
|
11094
|
+
constructor(os38) {
|
|
11095
|
+
this.os = os38;
|
|
11096
11096
|
}
|
|
11097
11097
|
async prepareLaunch() {
|
|
11098
11098
|
const binary = this.os.findInPath("aider");
|
|
@@ -11221,8 +11221,8 @@ function geminiCredentialLocator() {
|
|
|
11221
11221
|
function geminiLoginLauncher() {
|
|
11222
11222
|
return {
|
|
11223
11223
|
async ensureInstalled() {
|
|
11224
|
-
const
|
|
11225
|
-
return
|
|
11224
|
+
const os38 = createOsStrategy();
|
|
11225
|
+
return os38.findInPath("gemini") !== null;
|
|
11226
11226
|
},
|
|
11227
11227
|
launch() {
|
|
11228
11228
|
return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -11255,8 +11255,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
11255
11255
|
meta = getAgent("gemini");
|
|
11256
11256
|
mode = "interactive";
|
|
11257
11257
|
os;
|
|
11258
|
-
constructor(
|
|
11259
|
-
this.os =
|
|
11258
|
+
constructor(os38) {
|
|
11259
|
+
this.os = os38;
|
|
11260
11260
|
}
|
|
11261
11261
|
async prepareLaunch() {
|
|
11262
11262
|
const binary = this.os.findInPath("gemini");
|
|
@@ -11355,18 +11355,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
11355
11355
|
|
|
11356
11356
|
// src/agents/registry.ts
|
|
11357
11357
|
var runtimeBuilders = {
|
|
11358
|
-
claude: (
|
|
11359
|
-
codex: (
|
|
11360
|
-
coderabbit: (
|
|
11361
|
-
cursor: (
|
|
11362
|
-
aider: (
|
|
11363
|
-
gemini: (
|
|
11358
|
+
claude: (os38) => new ClaudeRuntimeStrategy(os38),
|
|
11359
|
+
codex: (os38) => new CodexRuntimeStrategy(os38),
|
|
11360
|
+
coderabbit: (os38) => new CoderabbitRuntimeStrategy(os38),
|
|
11361
|
+
cursor: (os38) => new CursorRuntimeStrategy(os38),
|
|
11362
|
+
aider: (os38) => new AiderRuntimeStrategy(os38),
|
|
11363
|
+
gemini: (os38) => new GeminiRuntimeStrategy(os38)
|
|
11364
11364
|
};
|
|
11365
11365
|
var deployBuilders = {
|
|
11366
11366
|
claude: () => new ClaudeDeployStrategy(),
|
|
11367
11367
|
codex: () => new CodexDeployStrategy()
|
|
11368
11368
|
};
|
|
11369
|
-
function createAgentStrategy(agent,
|
|
11369
|
+
function createAgentStrategy(agent, os38 = createOsStrategy()) {
|
|
11370
11370
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
11371
11371
|
throw new Error(
|
|
11372
11372
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -11376,10 +11376,10 @@ function createAgentStrategy(agent, os36 = createOsStrategy()) {
|
|
|
11376
11376
|
if (!build) {
|
|
11377
11377
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
11378
11378
|
}
|
|
11379
|
-
return build(
|
|
11379
|
+
return build(os38);
|
|
11380
11380
|
}
|
|
11381
|
-
function createInteractiveAgentStrategy(agent,
|
|
11382
|
-
const s = createAgentStrategy(agent,
|
|
11381
|
+
function createInteractiveAgentStrategy(agent, os38 = createOsStrategy()) {
|
|
11382
|
+
const s = createAgentStrategy(agent, os38);
|
|
11383
11383
|
if (s.mode !== "interactive") {
|
|
11384
11384
|
throw new Error(
|
|
11385
11385
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -14705,6 +14705,14 @@ function buildAcpPromptBlocks(payload) {
|
|
|
14705
14705
|
return blocks;
|
|
14706
14706
|
}
|
|
14707
14707
|
|
|
14708
|
+
// src/agents/acp/reconcileDelta.ts
|
|
14709
|
+
function reconcileCumulative(existing, incoming) {
|
|
14710
|
+
if (incoming.length === 0) return existing;
|
|
14711
|
+
if (incoming.startsWith(existing)) return incoming;
|
|
14712
|
+
if (existing.startsWith(incoming)) return existing;
|
|
14713
|
+
return existing + incoming;
|
|
14714
|
+
}
|
|
14715
|
+
|
|
14708
14716
|
// src/agents/acp/onboarding.ts
|
|
14709
14717
|
var fs22 = __toESM(require("fs"));
|
|
14710
14718
|
var os23 = __toESM(require("os"));
|
|
@@ -15248,7 +15256,7 @@ function extractSelectPrompt(text) {
|
|
|
15248
15256
|
|
|
15249
15257
|
// src/commands/start/handlers.ts
|
|
15250
15258
|
var fs35 = __toESM(require("fs"));
|
|
15251
|
-
var
|
|
15259
|
+
var os28 = __toESM(require("os"));
|
|
15252
15260
|
var path42 = __toESM(require("path"));
|
|
15253
15261
|
var import_crypto3 = require("crypto");
|
|
15254
15262
|
var import_child_process18 = require("child_process");
|
|
@@ -17019,6 +17027,7 @@ function activePreviewSessionIds() {
|
|
|
17019
17027
|
// src/beads/bd-adapter.ts
|
|
17020
17028
|
var import_child_process13 = require("child_process");
|
|
17021
17029
|
var fs31 = __toESM(require("fs"));
|
|
17030
|
+
var os25 = __toESM(require("os"));
|
|
17022
17031
|
var path37 = __toESM(require("path"));
|
|
17023
17032
|
var BD_PACKAGE = "@beads/bd";
|
|
17024
17033
|
function resolveBundledBdBinary() {
|
|
@@ -17134,6 +17143,13 @@ var BdAdapter = class {
|
|
|
17134
17143
|
return { code: -1, stdout: "", stderr: "bd binary not resolved" };
|
|
17135
17144
|
}
|
|
17136
17145
|
const env = { ...process.env };
|
|
17146
|
+
if (!env.HOME) {
|
|
17147
|
+
try {
|
|
17148
|
+
const home = os25.homedir();
|
|
17149
|
+
if (home) env.HOME = home;
|
|
17150
|
+
} catch {
|
|
17151
|
+
}
|
|
17152
|
+
}
|
|
17137
17153
|
env.BEADS_DOLT_SHARED_SERVER = "1";
|
|
17138
17154
|
delete env.BEADS_DIR;
|
|
17139
17155
|
log.trace(
|
|
@@ -17219,7 +17235,7 @@ function coerceIssue(row, projectKey) {
|
|
|
17219
17235
|
// src/beads/provisioner.ts
|
|
17220
17236
|
var import_child_process17 = require("child_process");
|
|
17221
17237
|
var fs34 = __toESM(require("fs"));
|
|
17222
|
-
var
|
|
17238
|
+
var os27 = __toESM(require("os"));
|
|
17223
17239
|
var path40 = __toESM(require("path"));
|
|
17224
17240
|
|
|
17225
17241
|
// src/beads/install-bd.ts
|
|
@@ -17286,7 +17302,7 @@ async function installBd(platform3 = process.platform) {
|
|
|
17286
17302
|
// src/beads/install-dolt.ts
|
|
17287
17303
|
var import_child_process15 = require("child_process");
|
|
17288
17304
|
var fs32 = __toESM(require("fs"));
|
|
17289
|
-
var
|
|
17305
|
+
var os26 = __toESM(require("os"));
|
|
17290
17306
|
var path38 = __toESM(require("path"));
|
|
17291
17307
|
var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
|
|
17292
17308
|
var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
|
|
@@ -17327,11 +17343,11 @@ function resolveDoltInstallStrategy(platform3) {
|
|
|
17327
17343
|
}
|
|
17328
17344
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
17329
17345
|
function doltPlatformTuple(platform3, arch2) {
|
|
17330
|
-
const
|
|
17346
|
+
const os38 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
|
|
17331
17347
|
const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
|
|
17332
17348
|
if (!a) return null;
|
|
17333
|
-
if (
|
|
17334
|
-
return `${
|
|
17349
|
+
if (os38 === "windows" && a !== "amd64") return null;
|
|
17350
|
+
return `${os38}-${a}`;
|
|
17335
17351
|
}
|
|
17336
17352
|
function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
|
|
17337
17353
|
const tuple = doltPlatformTuple(platform3, arch2);
|
|
@@ -17376,7 +17392,7 @@ async function installDoltToDir(targetDir, platform3 = process.platform, arch2 =
|
|
|
17376
17392
|
return result;
|
|
17377
17393
|
}
|
|
17378
17394
|
var _doltPathSeam = {
|
|
17379
|
-
homedir: () =>
|
|
17395
|
+
homedir: () => os26.homedir(),
|
|
17380
17396
|
getPath: () => process.env.PATH ?? "",
|
|
17381
17397
|
setPath: (p2) => {
|
|
17382
17398
|
process.env.PATH = p2;
|
|
@@ -17640,7 +17656,7 @@ var _provisionSeam = {
|
|
|
17640
17656
|
};
|
|
17641
17657
|
var _linkSeam = {
|
|
17642
17658
|
platform: () => process.platform,
|
|
17643
|
-
homedir: () =>
|
|
17659
|
+
homedir: () => os27.homedir(),
|
|
17644
17660
|
isWritableDir: (dir) => {
|
|
17645
17661
|
try {
|
|
17646
17662
|
fs34.accessSync(dir, fs34.constants.W_OK);
|
|
@@ -18266,7 +18282,7 @@ function cleanupAttachmentTempFiles() {
|
|
|
18266
18282
|
function saveFilesTemp(files) {
|
|
18267
18283
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
18268
18284
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
18269
|
-
const tmpPath = path42.join(
|
|
18285
|
+
const tmpPath = path42.join(os28.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
18270
18286
|
fs35.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
18271
18287
|
pendingAttachmentFiles.add(tmpPath);
|
|
18272
18288
|
return tmpPath;
|
|
@@ -19347,7 +19363,7 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
19347
19363
|
// src/services/file-watcher.service.ts
|
|
19348
19364
|
var import_child_process19 = require("child_process");
|
|
19349
19365
|
var fs36 = __toESM(require("fs"));
|
|
19350
|
-
var
|
|
19366
|
+
var os29 = __toESM(require("os"));
|
|
19351
19367
|
var path43 = __toESM(require("path"));
|
|
19352
19368
|
var import_ignore = __toESM(require("ignore"));
|
|
19353
19369
|
|
|
@@ -19458,10 +19474,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
19458
19474
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
19459
19475
|
/[\\/]Templates([\\/]|$)/i
|
|
19460
19476
|
];
|
|
19461
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
19477
|
+
function isUnsafeWindowsWatchRoot(dir, homedir31) {
|
|
19462
19478
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
19463
19479
|
const cwd = norm(dir);
|
|
19464
|
-
const home = norm(
|
|
19480
|
+
const home = norm(homedir31);
|
|
19465
19481
|
if (cwd === home) return true;
|
|
19466
19482
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
19467
19483
|
const sysRoots = [
|
|
@@ -19560,7 +19576,7 @@ var FileWatcherService = class {
|
|
|
19560
19576
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
19561
19577
|
}
|
|
19562
19578
|
const isWin = process.platform === "win32";
|
|
19563
|
-
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir,
|
|
19579
|
+
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os29.homedir())) {
|
|
19564
19580
|
log.warn(
|
|
19565
19581
|
"fileWatcher",
|
|
19566
19582
|
`refusing to watch ${this.opts.workingDir} \u2014 looks like a Windows user-profile or system path. Run codeam from your project folder to enable file change emission.`
|
|
@@ -20639,6 +20655,18 @@ var StreamingState = class {
|
|
|
20639
20655
|
this.publisher = publisher;
|
|
20640
20656
|
}
|
|
20641
20657
|
publisher;
|
|
20658
|
+
/**
|
|
20659
|
+
* Cumulative agent reply for the in-progress turn — the body of the
|
|
20660
|
+
* chat bubble (`/api/commands/output` text events). DERIVED from the
|
|
20661
|
+
* per-chunkId text buffers in {@link streamingChunks} via
|
|
20662
|
+
* {@link recomputeText} on every `append`, NOT accumulated with a
|
|
20663
|
+
* blind `+=`. That derivation is what makes the chat pipe correct for
|
|
20664
|
+
* adapters that send cumulative snapshots (a self-hosted MiniMax proxy
|
|
20665
|
+
* behind claude-agent-acp) as well as true-delta adapters (Anthropic
|
|
20666
|
+
* Claude): `reconcileCumulative` collapses a re-sent snapshot instead
|
|
20667
|
+
* of concatenating the reply with itself (the "…hoy?¡Hola!…hoy?"
|
|
20668
|
+
* intra-reply duplication bug).
|
|
20669
|
+
*/
|
|
20642
20670
|
text = "";
|
|
20643
20671
|
pending = null;
|
|
20644
20672
|
/**
|
|
@@ -20653,6 +20681,27 @@ var StreamingState = class {
|
|
|
20653
20681
|
* chunk is done streaming.
|
|
20654
20682
|
*/
|
|
20655
20683
|
streamingChunks = /* @__PURE__ */ new Map();
|
|
20684
|
+
/**
|
|
20685
|
+
* Stable chunkId that ALL `text` segments of the current turn collapse
|
|
20686
|
+
* onto (set to the first text chunk's id, reset each {@link beginTurn}).
|
|
20687
|
+
*
|
|
20688
|
+
* Why: `claude-agent-acp` (≥0.47) streams the reply live as
|
|
20689
|
+
* `agent_message_chunk` deltas under one message id, then — when its
|
|
20690
|
+
* own streamed-vs-consolidated dedupe misfires (the live path keys
|
|
20691
|
+
* `streamedTextIds` off the stream message id while consolidation
|
|
20692
|
+
* checks `messageIdForGrouping`, which can differ per gateway) —
|
|
20693
|
+
* RE-EMITS the complete assistant message as a fresh
|
|
20694
|
+
* `agent_message_chunk` under a DIFFERENT message id. Keying our buffer
|
|
20695
|
+
* off the adapter's chunkId then lands the two copies in two buckets,
|
|
20696
|
+
* and `recomputeText` concatenates them → the whole reply doubles
|
|
20697
|
+
* ("…del proyecto.¡Perfecto!…del proyecto."). Observed on BOTH real
|
|
20698
|
+
* Claude (codespace) and the MiniMax proxy (self-hosted) — anything
|
|
20699
|
+
* behind this adapter. Collapsing every text segment of a turn into one
|
|
20700
|
+
* reconcile buffer makes the re-emit a `reconcileCumulative` REPLACE
|
|
20701
|
+
* (identical snapshot) instead of an APPEND, so the reply can't double
|
|
20702
|
+
* no matter how many message ids the adapter spreads it across.
|
|
20703
|
+
*/
|
|
20704
|
+
turnTextChunkId = null;
|
|
20656
20705
|
/**
|
|
20657
20706
|
* Register a permission Promise. The Promise stays pending until
|
|
20658
20707
|
* `resolveSelection(index)` is called from the relay handler, OR
|
|
@@ -20744,6 +20793,7 @@ var StreamingState = class {
|
|
|
20744
20793
|
async beginTurn(opts) {
|
|
20745
20794
|
this.text = "";
|
|
20746
20795
|
this.streamingChunks.clear();
|
|
20796
|
+
this.turnTextChunkId = null;
|
|
20747
20797
|
if (this.pending?.kind === "permission") {
|
|
20748
20798
|
clearTimeout(this.pending.timeoutTimer);
|
|
20749
20799
|
}
|
|
@@ -20754,26 +20804,41 @@ var StreamingState = class {
|
|
|
20754
20804
|
await this.publisher.publishOutput({ type: "new_turn", done: false });
|
|
20755
20805
|
}
|
|
20756
20806
|
append(delta) {
|
|
20757
|
-
|
|
20758
|
-
|
|
20759
|
-
void this.publisher.publishOutput({ type: "text", content: this.text, done: false });
|
|
20760
|
-
}
|
|
20761
|
-
const existing = this.streamingChunks.get(delta.chunkId);
|
|
20762
|
-
const cumulativeContent = (existing?.content ?? "") + delta.delta;
|
|
20807
|
+
const chunkId = delta.kind === "text" ? this.turnTextChunkId ??= delta.chunkId : delta.chunkId;
|
|
20808
|
+
const existing = this.streamingChunks.get(chunkId);
|
|
20763
20809
|
if (existing && existing.kind !== delta.kind) {
|
|
20764
20810
|
log.warn(
|
|
20765
20811
|
"acpRunner",
|
|
20766
|
-
`streaming-chunk kind flip chunkId=${
|
|
20812
|
+
`streaming-chunk kind flip chunkId=${chunkId.slice(0, 8)} from=${existing.kind} to=${delta.kind}`
|
|
20767
20813
|
);
|
|
20768
20814
|
}
|
|
20769
|
-
|
|
20815
|
+
const cumulativeContent = reconcileCumulative(existing?.content ?? "", delta.delta);
|
|
20816
|
+
this.streamingChunks.set(chunkId, { kind: delta.kind, content: cumulativeContent });
|
|
20817
|
+
if (delta.kind === "text") {
|
|
20818
|
+
this.recomputeText();
|
|
20819
|
+
void this.publisher.publishOutput({ type: "text", content: this.text, done: false });
|
|
20820
|
+
}
|
|
20770
20821
|
void this.publisher.publishStreamingChunk({
|
|
20771
|
-
chunkId
|
|
20822
|
+
chunkId,
|
|
20772
20823
|
kind: delta.kind,
|
|
20773
20824
|
content: cumulativeContent,
|
|
20774
20825
|
isFinal: false
|
|
20775
20826
|
});
|
|
20776
20827
|
}
|
|
20828
|
+
/**
|
|
20829
|
+
* Rebuild the cumulative chat-bubble text from the per-chunkId text
|
|
20830
|
+
* buffers, in arrival order (Map preserves insertion order). Source
|
|
20831
|
+
* of truth for the `text` field — never accumulated incrementally, so
|
|
20832
|
+
* a re-sent snapshot updates its own chunk in place rather than
|
|
20833
|
+
* lengthening the reply.
|
|
20834
|
+
*/
|
|
20835
|
+
recomputeText() {
|
|
20836
|
+
let next = "";
|
|
20837
|
+
for (const { kind, content } of this.streamingChunks.values()) {
|
|
20838
|
+
if (kind === "text") next += content;
|
|
20839
|
+
}
|
|
20840
|
+
this.text = next;
|
|
20841
|
+
}
|
|
20777
20842
|
/**
|
|
20778
20843
|
* Flip the chat out of "Thinking…" with one final cumulative
|
|
20779
20844
|
* `done: true`. Idempotent — safe to call from happy + error +
|
|
@@ -22301,7 +22366,7 @@ var OutputService = class _OutputService {
|
|
|
22301
22366
|
// src/services/history.service.ts
|
|
22302
22367
|
var fs38 = __toESM(require("fs"));
|
|
22303
22368
|
var path46 = __toESM(require("path"));
|
|
22304
|
-
var
|
|
22369
|
+
var os30 = __toESM(require("os"));
|
|
22305
22370
|
var https7 = __toESM(require("https"));
|
|
22306
22371
|
var http7 = __toESM(require("http"));
|
|
22307
22372
|
var import_zod2 = require("zod");
|
|
@@ -22469,7 +22534,7 @@ var HistoryService = class _HistoryService {
|
|
|
22469
22534
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
22470
22535
|
}
|
|
22471
22536
|
get projectDir() {
|
|
22472
|
-
return this.runtime.resolveHistoryDir(this.cwd) ?? path46.join(
|
|
22537
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path46.join(os30.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
22473
22538
|
}
|
|
22474
22539
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
22475
22540
|
setCurrentConversationId(id) {
|
|
@@ -23231,11 +23296,11 @@ function buildKeepAlive(ctx) {
|
|
|
23231
23296
|
|
|
23232
23297
|
// src/agents/claude/onboarding.ts
|
|
23233
23298
|
var fs39 = __toESM(require("fs"));
|
|
23234
|
-
var
|
|
23299
|
+
var os31 = __toESM(require("os"));
|
|
23235
23300
|
var path47 = __toESM(require("path"));
|
|
23236
23301
|
function ensureClaudeOnboarded() {
|
|
23237
23302
|
try {
|
|
23238
|
-
const file = path47.join(
|
|
23303
|
+
const file = path47.join(os31.homedir(), ".claude.json");
|
|
23239
23304
|
let config = {};
|
|
23240
23305
|
try {
|
|
23241
23306
|
config = JSON.parse(fs39.readFileSync(file, "utf8"));
|
|
@@ -23742,7 +23807,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
23742
23807
|
|
|
23743
23808
|
// src/commands/pair-auto.ts
|
|
23744
23809
|
var fs40 = __toESM(require("fs"));
|
|
23745
|
-
var
|
|
23810
|
+
var os32 = __toESM(require("os"));
|
|
23746
23811
|
var path48 = __toESM(require("path"));
|
|
23747
23812
|
var import_crypto7 = require("crypto");
|
|
23748
23813
|
|
|
@@ -23969,7 +24034,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
23969
24034
|
pluginId,
|
|
23970
24035
|
ideName: "codeam-cli (codespace)",
|
|
23971
24036
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
23972
|
-
hostname:
|
|
24037
|
+
hostname: os32.hostname(),
|
|
23973
24038
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
23974
24039
|
// Current git branch of the codespace's working directory, so the
|
|
23975
24040
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -24030,7 +24095,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
24030
24095
|
}
|
|
24031
24096
|
}
|
|
24032
24097
|
function pairAutoLockPath() {
|
|
24033
|
-
return path48.join(
|
|
24098
|
+
return path48.join(os32.homedir(), ".codeam", "pair-auto.lock");
|
|
24034
24099
|
}
|
|
24035
24100
|
function isLivePairAuto(pid) {
|
|
24036
24101
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -26203,12 +26268,12 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
26203
26268
|
|
|
26204
26269
|
// src/commands/host/host-client.ts
|
|
26205
26270
|
var fs41 = __toESM(require("fs"));
|
|
26206
|
-
var
|
|
26271
|
+
var os33 = __toESM(require("os"));
|
|
26207
26272
|
var path53 = __toESM(require("path"));
|
|
26208
26273
|
function sampleCpuTimes() {
|
|
26209
26274
|
let idle = 0;
|
|
26210
26275
|
let total = 0;
|
|
26211
|
-
for (const cpu of
|
|
26276
|
+
for (const cpu of os33.cpus()) {
|
|
26212
26277
|
const t2 = cpu.times;
|
|
26213
26278
|
idle += t2.idle;
|
|
26214
26279
|
total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
|
|
@@ -26227,8 +26292,8 @@ var MetricsCollector = class {
|
|
|
26227
26292
|
const prev = this.prevCpu;
|
|
26228
26293
|
this.prevCpu = current;
|
|
26229
26294
|
if (!prev) {
|
|
26230
|
-
const cores =
|
|
26231
|
-
const proxy =
|
|
26295
|
+
const cores = os33.cpus().length || 1;
|
|
26296
|
+
const proxy = os33.loadavg()[0] / cores * 100;
|
|
26232
26297
|
return Math.min(100, Math.max(0, Math.round(proxy)));
|
|
26233
26298
|
}
|
|
26234
26299
|
const idleDelta = current.idle - prev.idle;
|
|
@@ -26241,8 +26306,8 @@ var MetricsCollector = class {
|
|
|
26241
26306
|
collect() {
|
|
26242
26307
|
return {
|
|
26243
26308
|
cpuPct: this.cpuPct(),
|
|
26244
|
-
ramUsedMb: Math.round((
|
|
26245
|
-
ramTotalMb: Math.round(
|
|
26309
|
+
ramUsedMb: Math.round((os33.totalmem() - os33.freemem()) / 1048576),
|
|
26310
|
+
ramTotalMb: Math.round(os33.totalmem() / 1048576),
|
|
26246
26311
|
latencyMs: this.lastLatencyMs
|
|
26247
26312
|
};
|
|
26248
26313
|
}
|
|
@@ -26251,13 +26316,13 @@ function apiBase() {
|
|
|
26251
26316
|
return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
|
|
26252
26317
|
}
|
|
26253
26318
|
function hostIdentityPath() {
|
|
26254
|
-
return path53.join(
|
|
26319
|
+
return path53.join(os33.homedir(), ".codeam", "host-agent.json");
|
|
26255
26320
|
}
|
|
26256
26321
|
function collectOsInfo() {
|
|
26257
26322
|
return {
|
|
26258
|
-
distro:
|
|
26259
|
-
arch:
|
|
26260
|
-
kernel:
|
|
26323
|
+
distro: os33.platform(),
|
|
26324
|
+
arch: os33.arch(),
|
|
26325
|
+
kernel: os33.release(),
|
|
26261
26326
|
nodeVersion: process.versions.node
|
|
26262
26327
|
};
|
|
26263
26328
|
}
|
|
@@ -26468,7 +26533,7 @@ var import_node_child_process13 = require("child_process");
|
|
|
26468
26533
|
|
|
26469
26534
|
// src/commands/host/workspace.ts
|
|
26470
26535
|
var fs42 = __toESM(require("fs"));
|
|
26471
|
-
var
|
|
26536
|
+
var os34 = __toESM(require("os"));
|
|
26472
26537
|
var path54 = __toESM(require("path"));
|
|
26473
26538
|
var import_node_child_process12 = require("child_process");
|
|
26474
26539
|
var import_node_util4 = require("util");
|
|
@@ -26477,7 +26542,7 @@ function isAbsolutePathTarget(target) {
|
|
|
26477
26542
|
return path54.isAbsolute(target);
|
|
26478
26543
|
}
|
|
26479
26544
|
function selfHostedWorkspaceRoot() {
|
|
26480
|
-
return path54.join(
|
|
26545
|
+
return path54.join(os34.homedir(), ".codeam", "self-hosted");
|
|
26481
26546
|
}
|
|
26482
26547
|
function nonInteractiveGitEnv() {
|
|
26483
26548
|
return {
|
|
@@ -26546,7 +26611,7 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
|
|
|
26546
26611
|
|
|
26547
26612
|
// src/commands/host/agent-provisioning.ts
|
|
26548
26613
|
var fs43 = __toESM(require("fs"));
|
|
26549
|
-
var
|
|
26614
|
+
var os35 = __toESM(require("os"));
|
|
26550
26615
|
var path55 = __toESM(require("path"));
|
|
26551
26616
|
var PUBLIC_TO_INTERNAL_AGENT = {
|
|
26552
26617
|
claude_code: "claude",
|
|
@@ -26606,7 +26671,7 @@ var UnsupportedAgentError = class extends Error {
|
|
|
26606
26671
|
this.agentId = agentId;
|
|
26607
26672
|
}
|
|
26608
26673
|
};
|
|
26609
|
-
function provisionAgentCredentials(publicAgentId, auth, homeDir2 =
|
|
26674
|
+
function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os35.homedir()) {
|
|
26610
26675
|
const internal = toInternalAgentId(publicAgentId);
|
|
26611
26676
|
if (!internal) throw new UnsupportedAgentError(publicAgentId);
|
|
26612
26677
|
const provisioner = PROVISIONERS[internal];
|
|
@@ -27047,9 +27112,9 @@ function checkSessions() {
|
|
|
27047
27112
|
}
|
|
27048
27113
|
}
|
|
27049
27114
|
function checkAgentBinaries() {
|
|
27050
|
-
const
|
|
27115
|
+
const os38 = createOsStrategy();
|
|
27051
27116
|
return getEnabledAgents().map((meta) => {
|
|
27052
|
-
const found =
|
|
27117
|
+
const found = os38.findInPath(meta.binaryName);
|
|
27053
27118
|
return {
|
|
27054
27119
|
id: `agent-${meta.id}`,
|
|
27055
27120
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -27113,7 +27178,7 @@ function checkChokidar() {
|
|
|
27113
27178
|
}
|
|
27114
27179
|
async function doctor(args2 = []) {
|
|
27115
27180
|
const json = args2.includes("--json");
|
|
27116
|
-
const cliVersion = true ? "2.39.
|
|
27181
|
+
const cliVersion = true ? "2.39.34" : "0.0.0-dev";
|
|
27117
27182
|
const apiBase2 = resolveApiBaseUrl();
|
|
27118
27183
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
27119
27184
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27312,7 +27377,7 @@ async function completion(args2) {
|
|
|
27312
27377
|
// src/commands/version.ts
|
|
27313
27378
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27314
27379
|
function version2() {
|
|
27315
|
-
const v = true ? "2.39.
|
|
27380
|
+
const v = true ? "2.39.34" : "unknown";
|
|
27316
27381
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27317
27382
|
}
|
|
27318
27383
|
|
|
@@ -27441,7 +27506,7 @@ var _subcommandHelpKeys = Object.keys(HELPS);
|
|
|
27441
27506
|
|
|
27442
27507
|
// src/lib/updateNotifier.ts
|
|
27443
27508
|
var fs45 = __toESM(require("fs"));
|
|
27444
|
-
var
|
|
27509
|
+
var os36 = __toESM(require("os"));
|
|
27445
27510
|
var path57 = __toESM(require("path"));
|
|
27446
27511
|
var https8 = __toESM(require("https"));
|
|
27447
27512
|
var import_node_child_process14 = require("child_process");
|
|
@@ -27451,7 +27516,7 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
27451
27516
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
27452
27517
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
27453
27518
|
function cachePath() {
|
|
27454
|
-
const dir = path57.join(
|
|
27519
|
+
const dir = path57.join(os36.homedir(), ".codeam");
|
|
27455
27520
|
return path57.join(dir, "update-check.json");
|
|
27456
27521
|
}
|
|
27457
27522
|
function readCache() {
|
|
@@ -27598,7 +27663,7 @@ function checkForUpdates() {
|
|
|
27598
27663
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27599
27664
|
if (process.env.CI) return;
|
|
27600
27665
|
if (!process.stdout.isTTY) return;
|
|
27601
|
-
const current = true ? "2.39.
|
|
27666
|
+
const current = true ? "2.39.34" : null;
|
|
27602
27667
|
if (!current) return;
|
|
27603
27668
|
const cache = readCache();
|
|
27604
27669
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -27629,6 +27694,14 @@ var EXIT_CODE_NAMES = {
|
|
|
27629
27694
|
};
|
|
27630
27695
|
|
|
27631
27696
|
// src/index.ts
|
|
27697
|
+
var os37 = __toESM(require("os"));
|
|
27698
|
+
if (!process.env.HOME) {
|
|
27699
|
+
try {
|
|
27700
|
+
const home = os37.homedir();
|
|
27701
|
+
if (home) process.env.HOME = home;
|
|
27702
|
+
} catch {
|
|
27703
|
+
}
|
|
27704
|
+
}
|
|
27632
27705
|
var [, , command, ...args] = process.argv;
|
|
27633
27706
|
async function main() {
|
|
27634
27707
|
const isMetaCommand = command === "--version" || command === "-v" || command === "version" || command === "--help" || command === "-h" || command === "help";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.39.
|
|
3
|
+
"version": "2.39.34",
|
|
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",
|