codeam-cli 2.39.9 → 2.39.10
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 +153 -121
- 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.9] — 2026-06-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Auto-provision project deps (docker compose) gated before the agent
|
|
12
|
+
|
|
7
13
|
## [2.39.8] — 2026-06-13
|
|
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.10",
|
|
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",
|
|
@@ -1186,8 +1186,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
1186
1186
|
return decodedFile;
|
|
1187
1187
|
};
|
|
1188
1188
|
}
|
|
1189
|
-
function normalizeWindowsPath(
|
|
1190
|
-
return
|
|
1189
|
+
function normalizeWindowsPath(path55) {
|
|
1190
|
+
return path55.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
1191
1191
|
}
|
|
1192
1192
|
|
|
1193
1193
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3667,9 +3667,9 @@ async function addSourceContext(frames) {
|
|
|
3667
3667
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3668
3668
|
return frames;
|
|
3669
3669
|
}
|
|
3670
|
-
function getContextLinesFromFile(
|
|
3670
|
+
function getContextLinesFromFile(path55, ranges, output) {
|
|
3671
3671
|
return new Promise((resolve7) => {
|
|
3672
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3672
|
+
const stream = (0, import_node_fs.createReadStream)(path55);
|
|
3673
3673
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3674
3674
|
input: stream
|
|
3675
3675
|
});
|
|
@@ -3684,7 +3684,7 @@ function getContextLinesFromFile(path54, ranges, output) {
|
|
|
3684
3684
|
let rangeStart = range[0];
|
|
3685
3685
|
let rangeEnd = range[1];
|
|
3686
3686
|
function onStreamError() {
|
|
3687
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3687
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path55, 1);
|
|
3688
3688
|
lineReaded.close();
|
|
3689
3689
|
lineReaded.removeAllListeners();
|
|
3690
3690
|
destroyStreamAndResolve();
|
|
@@ -3745,8 +3745,8 @@ function clearLineContext(frame) {
|
|
|
3745
3745
|
delete frame.context_line;
|
|
3746
3746
|
delete frame.post_context;
|
|
3747
3747
|
}
|
|
3748
|
-
function shouldSkipContextLinesForFile(
|
|
3749
|
-
return
|
|
3748
|
+
function shouldSkipContextLinesForFile(path55) {
|
|
3749
|
+
return path55.startsWith("node:") || path55.endsWith(".min.js") || path55.endsWith(".min.cjs") || path55.endsWith(".min.mjs") || path55.startsWith("data:");
|
|
3750
3750
|
}
|
|
3751
3751
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3752
3752
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5900,7 +5900,7 @@ function readAnonId() {
|
|
|
5900
5900
|
}
|
|
5901
5901
|
function superProperties() {
|
|
5902
5902
|
return {
|
|
5903
|
-
cliVersion: true ? "2.39.
|
|
5903
|
+
cliVersion: true ? "2.39.10" : "0.0.0-dev",
|
|
5904
5904
|
nodeVersion: process.version,
|
|
5905
5905
|
platform: process.platform,
|
|
5906
5906
|
arch: process.arch,
|
|
@@ -7248,10 +7248,10 @@ function buildForPlatform(platform2) {
|
|
|
7248
7248
|
var import_node_crypto4 = require("crypto");
|
|
7249
7249
|
|
|
7250
7250
|
// src/agents/claude/resolver.ts
|
|
7251
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
7252
|
-
const found =
|
|
7251
|
+
function buildClaudeLaunch(extraArgs = [], os33 = createOsStrategy()) {
|
|
7252
|
+
const found = os33.findInPath("claude") ?? os33.findInPath("claude-code");
|
|
7253
7253
|
if (!found) return null;
|
|
7254
|
-
return
|
|
7254
|
+
return os33.buildLaunch(found, extraArgs);
|
|
7255
7255
|
}
|
|
7256
7256
|
|
|
7257
7257
|
// src/agents/claude/installer.ts
|
|
@@ -9978,13 +9978,13 @@ function detectStartupBanner(lines) {
|
|
|
9978
9978
|
while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
|
|
9979
9979
|
if (metaIdx - artStart < 2) return null;
|
|
9980
9980
|
const pathLine = (lines[metaIdx + 1] ?? "").trim();
|
|
9981
|
-
const
|
|
9981
|
+
const path55 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
|
|
9982
9982
|
return {
|
|
9983
9983
|
title: "",
|
|
9984
9984
|
subtitle: lines[metaIdx].trim(),
|
|
9985
|
-
path:
|
|
9985
|
+
path: path55,
|
|
9986
9986
|
startIdx: artStart,
|
|
9987
|
-
endIdx: metaIdx + (
|
|
9987
|
+
endIdx: metaIdx + (path55 ? 1 : 0)
|
|
9988
9988
|
};
|
|
9989
9989
|
}
|
|
9990
9990
|
|
|
@@ -9994,8 +9994,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9994
9994
|
meta = getAgent("claude");
|
|
9995
9995
|
mode = "interactive";
|
|
9996
9996
|
os;
|
|
9997
|
-
constructor(
|
|
9998
|
-
this.os =
|
|
9997
|
+
constructor(os33) {
|
|
9998
|
+
this.os = os33;
|
|
9999
9999
|
}
|
|
10000
10000
|
/**
|
|
10001
10001
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -11025,8 +11025,8 @@ function codexCredentialLocator() {
|
|
|
11025
11025
|
function codexLoginLauncher() {
|
|
11026
11026
|
return {
|
|
11027
11027
|
async ensureInstalled() {
|
|
11028
|
-
const
|
|
11029
|
-
return
|
|
11028
|
+
const os33 = createOsStrategy();
|
|
11029
|
+
return os33.findInPath("codex") !== null;
|
|
11030
11030
|
},
|
|
11031
11031
|
launch() {
|
|
11032
11032
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -11049,8 +11049,8 @@ var CodexRuntimeStrategy = class {
|
|
|
11049
11049
|
meta = getAgent("codex");
|
|
11050
11050
|
mode = "interactive";
|
|
11051
11051
|
os;
|
|
11052
|
-
constructor(
|
|
11053
|
-
this.os =
|
|
11052
|
+
constructor(os33) {
|
|
11053
|
+
this.os = os33;
|
|
11054
11054
|
}
|
|
11055
11055
|
async prepareLaunch() {
|
|
11056
11056
|
let binary = this.os.findInPath("codex");
|
|
@@ -11156,12 +11156,12 @@ var CodexRuntimeStrategy = class {
|
|
|
11156
11156
|
});
|
|
11157
11157
|
}
|
|
11158
11158
|
};
|
|
11159
|
-
function resolveNpm(
|
|
11160
|
-
return
|
|
11159
|
+
function resolveNpm(os33) {
|
|
11160
|
+
return os33.id === "win32" ? "npm.cmd" : "npm";
|
|
11161
11161
|
}
|
|
11162
|
-
async function installCodexViaNpm(
|
|
11162
|
+
async function installCodexViaNpm(os33) {
|
|
11163
11163
|
return new Promise((resolve7, reject) => {
|
|
11164
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
11164
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os33), ["install", "-g", "@openai/codex"], {
|
|
11165
11165
|
stdio: "inherit"
|
|
11166
11166
|
});
|
|
11167
11167
|
proc.on("close", (code) => {
|
|
@@ -11178,16 +11178,16 @@ async function installCodexViaNpm(os32) {
|
|
|
11178
11178
|
});
|
|
11179
11179
|
});
|
|
11180
11180
|
}
|
|
11181
|
-
function augmentNpmGlobalBin(
|
|
11181
|
+
function augmentNpmGlobalBin(os33) {
|
|
11182
11182
|
try {
|
|
11183
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
11183
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os33), ["prefix", "-g"], {
|
|
11184
11184
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11185
11185
|
});
|
|
11186
11186
|
if (result.status !== 0) return;
|
|
11187
11187
|
const prefix = result.stdout.toString().trim();
|
|
11188
11188
|
if (!prefix) return;
|
|
11189
|
-
const binDir =
|
|
11190
|
-
|
|
11189
|
+
const binDir = os33.id === "win32" ? prefix : path17.join(prefix, "bin");
|
|
11190
|
+
os33.augmentPath([binDir]);
|
|
11191
11191
|
} catch {
|
|
11192
11192
|
}
|
|
11193
11193
|
}
|
|
@@ -11271,9 +11271,9 @@ var import_node_child_process7 = require("child_process");
|
|
|
11271
11271
|
// src/agents/coderabbit/installer.ts
|
|
11272
11272
|
var import_node_child_process5 = require("child_process");
|
|
11273
11273
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
11274
|
-
async function ensureCoderabbitInstalled(
|
|
11275
|
-
if (
|
|
11276
|
-
if (
|
|
11274
|
+
async function ensureCoderabbitInstalled(os33) {
|
|
11275
|
+
if (os33.findInPath("coderabbit")) return true;
|
|
11276
|
+
if (os33.id === "win32") {
|
|
11277
11277
|
console.error(
|
|
11278
11278
|
"\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"
|
|
11279
11279
|
);
|
|
@@ -11288,8 +11288,8 @@ async function ensureCoderabbitInstalled(os32) {
|
|
|
11288
11288
|
proc.on("error", () => resolve7(false));
|
|
11289
11289
|
});
|
|
11290
11290
|
if (!ok) return false;
|
|
11291
|
-
|
|
11292
|
-
return
|
|
11291
|
+
os33.augmentPath([`${os33.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
11292
|
+
return os33.findInPath("coderabbit") !== null;
|
|
11293
11293
|
}
|
|
11294
11294
|
|
|
11295
11295
|
// src/agents/coderabbit/link.ts
|
|
@@ -11316,10 +11316,10 @@ function coderabbitCredentialLocator() {
|
|
|
11316
11316
|
extract: extractLocalCoderabbitToken
|
|
11317
11317
|
};
|
|
11318
11318
|
}
|
|
11319
|
-
function coderabbitLoginLauncher(
|
|
11319
|
+
function coderabbitLoginLauncher(os33) {
|
|
11320
11320
|
return {
|
|
11321
11321
|
async ensureInstalled() {
|
|
11322
|
-
return ensureCoderabbitInstalled(
|
|
11322
|
+
return ensureCoderabbitInstalled(os33);
|
|
11323
11323
|
},
|
|
11324
11324
|
launch() {
|
|
11325
11325
|
return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
@@ -11342,11 +11342,11 @@ function parseReview(stdout) {
|
|
|
11342
11342
|
for (const line of lines) {
|
|
11343
11343
|
const m = line.match(HUNK_LINE_RE);
|
|
11344
11344
|
if (!m) continue;
|
|
11345
|
-
const [,
|
|
11346
|
-
if (!
|
|
11345
|
+
const [, path55, lineNo, sevToken, message] = m;
|
|
11346
|
+
if (!path55 || !lineNo || !message) continue;
|
|
11347
11347
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
11348
11348
|
hunks.push({
|
|
11349
|
-
path:
|
|
11349
|
+
path: path55.trim(),
|
|
11350
11350
|
line: Number(lineNo),
|
|
11351
11351
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
11352
11352
|
message: cleanedMessage
|
|
@@ -11365,8 +11365,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
11365
11365
|
meta = getAgent("coderabbit");
|
|
11366
11366
|
mode = "batch";
|
|
11367
11367
|
os;
|
|
11368
|
-
constructor(
|
|
11369
|
-
this.os =
|
|
11368
|
+
constructor(os33) {
|
|
11369
|
+
this.os = os33;
|
|
11370
11370
|
}
|
|
11371
11371
|
getDefaultArgs() {
|
|
11372
11372
|
return ["review"];
|
|
@@ -11481,10 +11481,10 @@ function cursorCredentialLocator() {
|
|
|
11481
11481
|
extract: extractLocalCursorToken
|
|
11482
11482
|
};
|
|
11483
11483
|
}
|
|
11484
|
-
function cursorLoginLauncher(
|
|
11484
|
+
function cursorLoginLauncher(os33) {
|
|
11485
11485
|
return {
|
|
11486
11486
|
async ensureInstalled() {
|
|
11487
|
-
if (
|
|
11487
|
+
if (os33.findInPath("cursor-agent")) return true;
|
|
11488
11488
|
console.error(
|
|
11489
11489
|
"\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"
|
|
11490
11490
|
);
|
|
@@ -11546,8 +11546,8 @@ var CursorRuntimeStrategy = class {
|
|
|
11546
11546
|
meta = getAgent("cursor");
|
|
11547
11547
|
mode = "interactive";
|
|
11548
11548
|
os;
|
|
11549
|
-
constructor(
|
|
11550
|
-
this.os =
|
|
11549
|
+
constructor(os33) {
|
|
11550
|
+
this.os = os33;
|
|
11551
11551
|
}
|
|
11552
11552
|
async prepareLaunch() {
|
|
11553
11553
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -11667,10 +11667,10 @@ function aiderCredentialLocator() {
|
|
|
11667
11667
|
extract: extractLocalAiderToken
|
|
11668
11668
|
};
|
|
11669
11669
|
}
|
|
11670
|
-
function aiderLoginLauncher(
|
|
11670
|
+
function aiderLoginLauncher(os33) {
|
|
11671
11671
|
return {
|
|
11672
11672
|
async ensureInstalled() {
|
|
11673
|
-
if (
|
|
11673
|
+
if (os33.findInPath("aider")) return true;
|
|
11674
11674
|
console.error(
|
|
11675
11675
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
11676
11676
|
);
|
|
@@ -11680,7 +11680,7 @@ function aiderLoginLauncher(os32) {
|
|
|
11680
11680
|
console.error(
|
|
11681
11681
|
"\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"
|
|
11682
11682
|
);
|
|
11683
|
-
return (0, import_node_child_process9.spawn)(
|
|
11683
|
+
return (0, import_node_child_process9.spawn)(os33.id === "win32" ? "cmd.exe" : "sh", os33.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
11684
11684
|
stdio: "ignore"
|
|
11685
11685
|
});
|
|
11686
11686
|
}
|
|
@@ -11752,8 +11752,8 @@ var AiderRuntimeStrategy = class {
|
|
|
11752
11752
|
meta = getAgent("aider");
|
|
11753
11753
|
mode = "interactive";
|
|
11754
11754
|
os;
|
|
11755
|
-
constructor(
|
|
11756
|
-
this.os =
|
|
11755
|
+
constructor(os33) {
|
|
11756
|
+
this.os = os33;
|
|
11757
11757
|
}
|
|
11758
11758
|
async prepareLaunch() {
|
|
11759
11759
|
const binary = this.os.findInPath("aider");
|
|
@@ -11882,8 +11882,8 @@ function geminiCredentialLocator() {
|
|
|
11882
11882
|
function geminiLoginLauncher() {
|
|
11883
11883
|
return {
|
|
11884
11884
|
async ensureInstalled() {
|
|
11885
|
-
const
|
|
11886
|
-
return
|
|
11885
|
+
const os33 = createOsStrategy();
|
|
11886
|
+
return os33.findInPath("gemini") !== null;
|
|
11887
11887
|
},
|
|
11888
11888
|
launch() {
|
|
11889
11889
|
return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -11916,8 +11916,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
11916
11916
|
meta = getAgent("gemini");
|
|
11917
11917
|
mode = "interactive";
|
|
11918
11918
|
os;
|
|
11919
|
-
constructor(
|
|
11920
|
-
this.os =
|
|
11919
|
+
constructor(os33) {
|
|
11920
|
+
this.os = os33;
|
|
11921
11921
|
}
|
|
11922
11922
|
async prepareLaunch() {
|
|
11923
11923
|
const binary = this.os.findInPath("gemini");
|
|
@@ -12017,18 +12017,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
12017
12017
|
|
|
12018
12018
|
// src/agents/registry.ts
|
|
12019
12019
|
var runtimeBuilders = {
|
|
12020
|
-
claude: (
|
|
12021
|
-
codex: (
|
|
12022
|
-
coderabbit: (
|
|
12023
|
-
cursor: (
|
|
12024
|
-
aider: (
|
|
12025
|
-
gemini: (
|
|
12020
|
+
claude: (os33) => new ClaudeRuntimeStrategy(os33),
|
|
12021
|
+
codex: (os33) => new CodexRuntimeStrategy(os33),
|
|
12022
|
+
coderabbit: (os33) => new CoderabbitRuntimeStrategy(os33),
|
|
12023
|
+
cursor: (os33) => new CursorRuntimeStrategy(os33),
|
|
12024
|
+
aider: (os33) => new AiderRuntimeStrategy(os33),
|
|
12025
|
+
gemini: (os33) => new GeminiRuntimeStrategy(os33)
|
|
12026
12026
|
};
|
|
12027
12027
|
var deployBuilders = {
|
|
12028
12028
|
claude: () => new ClaudeDeployStrategy(),
|
|
12029
12029
|
codex: () => new CodexDeployStrategy()
|
|
12030
12030
|
};
|
|
12031
|
-
function createAgentStrategy(agent,
|
|
12031
|
+
function createAgentStrategy(agent, os33 = createOsStrategy()) {
|
|
12032
12032
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
12033
12033
|
throw new Error(
|
|
12034
12034
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -12038,10 +12038,10 @@ function createAgentStrategy(agent, os32 = createOsStrategy()) {
|
|
|
12038
12038
|
if (!build) {
|
|
12039
12039
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
12040
12040
|
}
|
|
12041
|
-
return build(
|
|
12041
|
+
return build(os33);
|
|
12042
12042
|
}
|
|
12043
|
-
function createInteractiveAgentStrategy(agent,
|
|
12044
|
-
const s = createAgentStrategy(agent,
|
|
12043
|
+
function createInteractiveAgentStrategy(agent, os33 = createOsStrategy()) {
|
|
12044
|
+
const s = createAgentStrategy(agent, os33);
|
|
12045
12045
|
if (s.mode !== "interactive") {
|
|
12046
12046
|
throw new Error(
|
|
12047
12047
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -17970,11 +17970,11 @@ function resolveDoltInstallStrategy(platform2) {
|
|
|
17970
17970
|
}
|
|
17971
17971
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
17972
17972
|
function doltPlatformTuple(platform2, arch) {
|
|
17973
|
-
const
|
|
17973
|
+
const os33 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
|
|
17974
17974
|
const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : null;
|
|
17975
17975
|
if (!a) return null;
|
|
17976
|
-
if (
|
|
17977
|
-
return `${
|
|
17976
|
+
if (os33 === "windows" && a !== "amd64") return null;
|
|
17977
|
+
return `${os33}-${a}`;
|
|
17978
17978
|
}
|
|
17979
17979
|
function resolveDoltTarballStrategy(targetDir, platform2, arch) {
|
|
17980
17980
|
const tuple = doltPlatformTuple(platform2, arch);
|
|
@@ -19457,6 +19457,9 @@ var requestPreviewDetectH = (ctx) => {
|
|
|
19457
19457
|
return;
|
|
19458
19458
|
}
|
|
19459
19459
|
log.info("preview", `detect: ${detection.framework} on :${detection.port} (took ${tookMs}ms)`);
|
|
19460
|
+
void writePreviewConfig(process.cwd(), detection).catch((err) => {
|
|
19461
|
+
log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
|
|
19462
|
+
});
|
|
19460
19463
|
void postPreviewEvent({
|
|
19461
19464
|
sessionId: ctx.sessionId,
|
|
19462
19465
|
pluginId: ctx.pluginId,
|
|
@@ -20085,10 +20088,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
20085
20088
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
20086
20089
|
/[\\/]Templates([\\/]|$)/i
|
|
20087
20090
|
];
|
|
20088
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
20091
|
+
function isUnsafeWindowsWatchRoot(dir, homedir26) {
|
|
20089
20092
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
20090
20093
|
const cwd = norm(dir);
|
|
20091
|
-
const home = norm(
|
|
20094
|
+
const home = norm(homedir26);
|
|
20092
20095
|
if (cwd === home) return true;
|
|
20093
20096
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
20094
20097
|
const sysRoots = [
|
|
@@ -20882,7 +20885,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
20882
20885
|
});
|
|
20883
20886
|
}
|
|
20884
20887
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
20885
|
-
const
|
|
20888
|
+
const fs43 = await import("fs/promises");
|
|
20886
20889
|
const out2 = [];
|
|
20887
20890
|
await walk(workingDir, 0);
|
|
20888
20891
|
return out2;
|
|
@@ -20890,7 +20893,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
20890
20893
|
if (depth > maxDepth) return;
|
|
20891
20894
|
let entries = [];
|
|
20892
20895
|
try {
|
|
20893
|
-
const dirents = await
|
|
20896
|
+
const dirents = await fs43.readdir(dir, { withFileTypes: true });
|
|
20894
20897
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
20895
20898
|
} catch {
|
|
20896
20899
|
return;
|
|
@@ -23843,6 +23846,34 @@ function buildKeepAlive(ctx) {
|
|
|
23843
23846
|
};
|
|
23844
23847
|
}
|
|
23845
23848
|
|
|
23849
|
+
// src/agents/claude/onboarding.ts
|
|
23850
|
+
var fs39 = __toESM(require("fs"));
|
|
23851
|
+
var os30 = __toESM(require("os"));
|
|
23852
|
+
var path47 = __toESM(require("path"));
|
|
23853
|
+
function ensureClaudeOnboarded() {
|
|
23854
|
+
try {
|
|
23855
|
+
const file = path47.join(os30.homedir(), ".claude.json");
|
|
23856
|
+
let config = {};
|
|
23857
|
+
try {
|
|
23858
|
+
config = JSON.parse(fs39.readFileSync(file, "utf8"));
|
|
23859
|
+
} catch {
|
|
23860
|
+
}
|
|
23861
|
+
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
23862
|
+
return;
|
|
23863
|
+
}
|
|
23864
|
+
config.hasCompletedOnboarding = true;
|
|
23865
|
+
config.theme = typeof config.theme === "string" ? config.theme : "dark";
|
|
23866
|
+
if (typeof config.lastOnboardingVersion !== "string") {
|
|
23867
|
+
config.lastOnboardingVersion = "2.1.177";
|
|
23868
|
+
}
|
|
23869
|
+
fs39.mkdirSync(path47.dirname(file), { recursive: true });
|
|
23870
|
+
fs39.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
23871
|
+
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
23872
|
+
} catch (err) {
|
|
23873
|
+
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
23874
|
+
}
|
|
23875
|
+
}
|
|
23876
|
+
|
|
23846
23877
|
// src/commands/start.ts
|
|
23847
23878
|
async function start(requestedAgent) {
|
|
23848
23879
|
showIntro();
|
|
@@ -23897,6 +23928,7 @@ async function start(requestedAgent) {
|
|
|
23897
23928
|
"pluginAuth",
|
|
23898
23929
|
`boot triple sessionId=${session.id} pluginId=${pluginId} tokenLen=${tokenForLog.length} tokenHead=${tokenForLog.slice(0, 12)} tokenTail=${tokenForLog.slice(-8)} mintedEqualsCached=${refreshed === session.pluginAuthToken}`
|
|
23899
23930
|
);
|
|
23931
|
+
if (process.env.CODESPACES === "true") ensureClaudeOnboarded();
|
|
23900
23932
|
let beads = null;
|
|
23901
23933
|
const getBeads = () => beads;
|
|
23902
23934
|
const beadsReady = provisionBeadsForStart({
|
|
@@ -24312,9 +24344,9 @@ async function autoLinkAfterPair(opts) {
|
|
|
24312
24344
|
}
|
|
24313
24345
|
|
|
24314
24346
|
// src/commands/pair-auto.ts
|
|
24315
|
-
var
|
|
24316
|
-
var
|
|
24317
|
-
var
|
|
24347
|
+
var fs40 = __toESM(require("fs"));
|
|
24348
|
+
var os31 = __toESM(require("os"));
|
|
24349
|
+
var path48 = __toESM(require("path"));
|
|
24318
24350
|
var import_crypto7 = require("crypto");
|
|
24319
24351
|
|
|
24320
24352
|
// src/commands/start-infra-only.ts
|
|
@@ -24509,12 +24541,12 @@ function readTokenFromArgs(args2) {
|
|
|
24509
24541
|
}
|
|
24510
24542
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
24511
24543
|
if (fileFlag) {
|
|
24512
|
-
const
|
|
24544
|
+
const path55 = fileFlag.slice("--token-file=".length);
|
|
24513
24545
|
try {
|
|
24514
|
-
const content =
|
|
24515
|
-
if (content.length === 0) fail(`--token-file ${
|
|
24546
|
+
const content = fs40.readFileSync(path55, "utf8").trim();
|
|
24547
|
+
if (content.length === 0) fail(`--token-file ${path55} is empty`);
|
|
24516
24548
|
try {
|
|
24517
|
-
|
|
24549
|
+
fs40.unlinkSync(path55);
|
|
24518
24550
|
} catch {
|
|
24519
24551
|
}
|
|
24520
24552
|
return content;
|
|
@@ -24540,7 +24572,7 @@ async function claimOnce(token, pluginId) {
|
|
|
24540
24572
|
pluginId,
|
|
24541
24573
|
ideName: "codeam-cli (codespace)",
|
|
24542
24574
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
24543
|
-
hostname:
|
|
24575
|
+
hostname: os31.hostname(),
|
|
24544
24576
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
24545
24577
|
// Current git branch of the codespace's working directory, so the
|
|
24546
24578
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -24597,7 +24629,7 @@ async function claim(token, pluginId) {
|
|
|
24597
24629
|
}
|
|
24598
24630
|
}
|
|
24599
24631
|
function pairAutoLockPath() {
|
|
24600
|
-
return
|
|
24632
|
+
return path48.join(os31.homedir(), ".codeam", "pair-auto.lock");
|
|
24601
24633
|
}
|
|
24602
24634
|
function isLivePairAuto(pid) {
|
|
24603
24635
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -24607,7 +24639,7 @@ function isLivePairAuto(pid) {
|
|
|
24607
24639
|
if (e.code !== "EPERM") return false;
|
|
24608
24640
|
}
|
|
24609
24641
|
try {
|
|
24610
|
-
return
|
|
24642
|
+
return fs40.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
24611
24643
|
} catch {
|
|
24612
24644
|
return true;
|
|
24613
24645
|
}
|
|
@@ -24615,19 +24647,19 @@ function isLivePairAuto(pid) {
|
|
|
24615
24647
|
function acquireSingletonLock() {
|
|
24616
24648
|
const lockPath = pairAutoLockPath();
|
|
24617
24649
|
try {
|
|
24618
|
-
|
|
24650
|
+
fs40.mkdirSync(path48.dirname(lockPath), { recursive: true });
|
|
24619
24651
|
try {
|
|
24620
|
-
|
|
24652
|
+
fs40.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
24621
24653
|
} catch (e) {
|
|
24622
24654
|
if (e.code !== "EEXIST") throw e;
|
|
24623
|
-
const holder = Number(
|
|
24655
|
+
const holder = Number(fs40.readFileSync(lockPath, "utf8").trim());
|
|
24624
24656
|
if (isLivePairAuto(holder)) return false;
|
|
24625
|
-
|
|
24657
|
+
fs40.writeFileSync(lockPath, String(process.pid));
|
|
24626
24658
|
}
|
|
24627
24659
|
process.once("exit", () => {
|
|
24628
24660
|
try {
|
|
24629
|
-
if (
|
|
24630
|
-
|
|
24661
|
+
if (fs40.existsSync(lockPath) && Number(fs40.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
24662
|
+
fs40.unlinkSync(lockPath);
|
|
24631
24663
|
}
|
|
24632
24664
|
} catch {
|
|
24633
24665
|
}
|
|
@@ -24826,7 +24858,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
|
|
|
24826
24858
|
var import_child_process22 = require("child_process");
|
|
24827
24859
|
var import_util4 = require("util");
|
|
24828
24860
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
24829
|
-
var
|
|
24861
|
+
var path49 = __toESM(require("path"));
|
|
24830
24862
|
var execFileP5 = (0, import_util4.promisify)(import_child_process22.execFile);
|
|
24831
24863
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
24832
24864
|
function resetStdinForChild() {
|
|
@@ -25315,7 +25347,7 @@ var GitHubCodespacesProvider = class {
|
|
|
25315
25347
|
});
|
|
25316
25348
|
}
|
|
25317
25349
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
25318
|
-
const remoteDir =
|
|
25350
|
+
const remoteDir = path49.posix.dirname(remotePath);
|
|
25319
25351
|
const parts = [
|
|
25320
25352
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
25321
25353
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -25385,7 +25417,7 @@ function shellQuote(s) {
|
|
|
25385
25417
|
// src/services/providers/gitpod.ts
|
|
25386
25418
|
var import_child_process23 = require("child_process");
|
|
25387
25419
|
var import_util5 = require("util");
|
|
25388
|
-
var
|
|
25420
|
+
var path50 = __toESM(require("path"));
|
|
25389
25421
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
25390
25422
|
var execFileP6 = (0, import_util5.promisify)(import_child_process23.execFile);
|
|
25391
25423
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -25625,7 +25657,7 @@ var GitpodProvider = class {
|
|
|
25625
25657
|
});
|
|
25626
25658
|
}
|
|
25627
25659
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
25628
|
-
const remoteDir =
|
|
25660
|
+
const remoteDir = path50.posix.dirname(remotePath);
|
|
25629
25661
|
const parts = [
|
|
25630
25662
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
25631
25663
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -25661,7 +25693,7 @@ function shellQuote2(s) {
|
|
|
25661
25693
|
// src/services/providers/gitlab-workspaces.ts
|
|
25662
25694
|
var import_child_process24 = require("child_process");
|
|
25663
25695
|
var import_util6 = require("util");
|
|
25664
|
-
var
|
|
25696
|
+
var path51 = __toESM(require("path"));
|
|
25665
25697
|
var execFileP7 = (0, import_util6.promisify)(import_child_process24.execFile);
|
|
25666
25698
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
25667
25699
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -25921,7 +25953,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
25921
25953
|
}
|
|
25922
25954
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
25923
25955
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
25924
|
-
const remoteDir =
|
|
25956
|
+
const remoteDir = path51.posix.dirname(remotePath);
|
|
25925
25957
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
25926
25958
|
if (options.mode != null) {
|
|
25927
25959
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -25989,7 +26021,7 @@ function shellQuote3(s) {
|
|
|
25989
26021
|
// src/services/providers/railway.ts
|
|
25990
26022
|
var import_child_process25 = require("child_process");
|
|
25991
26023
|
var import_util7 = require("util");
|
|
25992
|
-
var
|
|
26024
|
+
var path52 = __toESM(require("path"));
|
|
25993
26025
|
var execFileP8 = (0, import_util7.promisify)(import_child_process25.execFile);
|
|
25994
26026
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
25995
26027
|
function resetStdinForChild4() {
|
|
@@ -26225,7 +26257,7 @@ var RailwayProvider = class {
|
|
|
26225
26257
|
if (!projectId || !serviceId) {
|
|
26226
26258
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
26227
26259
|
}
|
|
26228
|
-
const remoteDir =
|
|
26260
|
+
const remoteDir = path52.posix.dirname(remotePath);
|
|
26229
26261
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
26230
26262
|
if (options.mode != null) {
|
|
26231
26263
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -26768,8 +26800,8 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
26768
26800
|
var import_node_dns = require("dns");
|
|
26769
26801
|
var import_node_util4 = require("util");
|
|
26770
26802
|
var import_node_crypto8 = require("crypto");
|
|
26771
|
-
var
|
|
26772
|
-
var
|
|
26803
|
+
var fs41 = __toESM(require("fs"));
|
|
26804
|
+
var path53 = __toESM(require("path"));
|
|
26773
26805
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
26774
26806
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
26775
26807
|
async function checkDns(apiBase) {
|
|
@@ -26825,13 +26857,13 @@ async function checkHealth(apiBase) {
|
|
|
26825
26857
|
}
|
|
26826
26858
|
}
|
|
26827
26859
|
function checkConfigDir() {
|
|
26828
|
-
const dir =
|
|
26860
|
+
const dir = path53.join(require("os").homedir(), ".codeam");
|
|
26829
26861
|
try {
|
|
26830
|
-
|
|
26831
|
-
const probe =
|
|
26832
|
-
|
|
26833
|
-
const read =
|
|
26834
|
-
|
|
26862
|
+
fs41.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
26863
|
+
const probe = path53.join(dir, ".doctor-probe");
|
|
26864
|
+
fs41.writeFileSync(probe, "ok", { mode: 384 });
|
|
26865
|
+
const read = fs41.readFileSync(probe, "utf8");
|
|
26866
|
+
fs41.unlinkSync(probe);
|
|
26835
26867
|
if (read !== "ok") throw new Error("write/read round-trip mismatch");
|
|
26836
26868
|
return {
|
|
26837
26869
|
id: "config-dir",
|
|
@@ -26871,9 +26903,9 @@ function checkSessions() {
|
|
|
26871
26903
|
}
|
|
26872
26904
|
}
|
|
26873
26905
|
function checkAgentBinaries() {
|
|
26874
|
-
const
|
|
26906
|
+
const os33 = createOsStrategy();
|
|
26875
26907
|
return getEnabledAgents().map((meta) => {
|
|
26876
|
-
const found =
|
|
26908
|
+
const found = os33.findInPath(meta.binaryName);
|
|
26877
26909
|
return {
|
|
26878
26910
|
id: `agent-${meta.id}`,
|
|
26879
26911
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -26895,7 +26927,7 @@ function checkNodePty() {
|
|
|
26895
26927
|
detail: "not required on this platform"
|
|
26896
26928
|
};
|
|
26897
26929
|
}
|
|
26898
|
-
const vendoredPath =
|
|
26930
|
+
const vendoredPath = path53.join(__dirname, "vendor", "node-pty");
|
|
26899
26931
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
26900
26932
|
try {
|
|
26901
26933
|
require(target);
|
|
@@ -26937,7 +26969,7 @@ function checkChokidar() {
|
|
|
26937
26969
|
}
|
|
26938
26970
|
async function doctor(args2 = []) {
|
|
26939
26971
|
const json = args2.includes("--json");
|
|
26940
|
-
const cliVersion = true ? "2.39.
|
|
26972
|
+
const cliVersion = true ? "2.39.10" : "0.0.0-dev";
|
|
26941
26973
|
const apiBase = resolveApiBaseUrl();
|
|
26942
26974
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
26943
26975
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -27136,7 +27168,7 @@ async function completion(args2) {
|
|
|
27136
27168
|
// src/commands/version.ts
|
|
27137
27169
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
27138
27170
|
function version2() {
|
|
27139
|
-
const v = true ? "2.39.
|
|
27171
|
+
const v = true ? "2.39.10" : "unknown";
|
|
27140
27172
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
27141
27173
|
}
|
|
27142
27174
|
|
|
@@ -27264,9 +27296,9 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
27264
27296
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
27265
27297
|
|
|
27266
27298
|
// src/lib/updateNotifier.ts
|
|
27267
|
-
var
|
|
27268
|
-
var
|
|
27269
|
-
var
|
|
27299
|
+
var fs42 = __toESM(require("fs"));
|
|
27300
|
+
var os32 = __toESM(require("os"));
|
|
27301
|
+
var path54 = __toESM(require("path"));
|
|
27270
27302
|
var https8 = __toESM(require("https"));
|
|
27271
27303
|
var import_node_child_process12 = require("child_process");
|
|
27272
27304
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
@@ -27275,12 +27307,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
27275
27307
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
27276
27308
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
27277
27309
|
function cachePath() {
|
|
27278
|
-
const dir =
|
|
27279
|
-
return
|
|
27310
|
+
const dir = path54.join(os32.homedir(), ".codeam");
|
|
27311
|
+
return path54.join(dir, "update-check.json");
|
|
27280
27312
|
}
|
|
27281
27313
|
function readCache() {
|
|
27282
27314
|
try {
|
|
27283
|
-
const raw =
|
|
27315
|
+
const raw = fs42.readFileSync(cachePath(), "utf8");
|
|
27284
27316
|
const parsed = JSON.parse(raw);
|
|
27285
27317
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
27286
27318
|
return parsed;
|
|
@@ -27291,10 +27323,10 @@ function readCache() {
|
|
|
27291
27323
|
function writeCache(cache) {
|
|
27292
27324
|
try {
|
|
27293
27325
|
const file = cachePath();
|
|
27294
|
-
|
|
27326
|
+
fs42.mkdirSync(path54.dirname(file), { recursive: true });
|
|
27295
27327
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
27296
|
-
|
|
27297
|
-
|
|
27328
|
+
fs42.writeFileSync(tmp, JSON.stringify(cache));
|
|
27329
|
+
fs42.renameSync(tmp, file);
|
|
27298
27330
|
} catch {
|
|
27299
27331
|
}
|
|
27300
27332
|
}
|
|
@@ -27368,8 +27400,8 @@ function isLinkedInstall() {
|
|
|
27368
27400
|
timeout: 2e3
|
|
27369
27401
|
}).trim();
|
|
27370
27402
|
if (!root) return false;
|
|
27371
|
-
const pkgPath =
|
|
27372
|
-
return
|
|
27403
|
+
const pkgPath = path54.join(root, PKG_NAME);
|
|
27404
|
+
return fs42.lstatSync(pkgPath).isSymbolicLink();
|
|
27373
27405
|
} catch {
|
|
27374
27406
|
return false;
|
|
27375
27407
|
}
|
|
@@ -27405,7 +27437,7 @@ function maybeAutoUpdate(currentVersion, latest) {
|
|
|
27405
27437
|
return;
|
|
27406
27438
|
}
|
|
27407
27439
|
try {
|
|
27408
|
-
|
|
27440
|
+
fs42.unlinkSync(cachePath());
|
|
27409
27441
|
} catch {
|
|
27410
27442
|
}
|
|
27411
27443
|
process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
|
|
@@ -27422,7 +27454,7 @@ function checkForUpdates() {
|
|
|
27422
27454
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
27423
27455
|
if (process.env.CI) return;
|
|
27424
27456
|
if (!process.stdout.isTTY) return;
|
|
27425
|
-
const current = true ? "2.39.
|
|
27457
|
+
const current = true ? "2.39.10" : null;
|
|
27426
27458
|
if (!current) return;
|
|
27427
27459
|
const cache = readCache();
|
|
27428
27460
|
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.10",
|
|
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",
|