codeam-cli 2.31.0 → 2.32.1
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 +278 -179
- 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.31.0] — 2026-06-07
|
|
8
|
+
|
|
9
|
+
### Chore
|
|
10
|
+
|
|
11
|
+
- **cli:** Drop originator-HMAC fields from /api/pairing/code
|
|
12
|
+
|
|
7
13
|
## [2.30.0] — 2026-06-06
|
|
8
14
|
|
|
9
15
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
498
498
|
// package.json
|
|
499
499
|
var package_default = {
|
|
500
500
|
name: "codeam-cli",
|
|
501
|
-
version: "2.
|
|
501
|
+
version: "2.32.1",
|
|
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",
|
|
@@ -706,12 +706,27 @@ async function requestCode(pluginId) {
|
|
|
706
706
|
});
|
|
707
707
|
const result = await Promise.race([post2, timeoutPromise]);
|
|
708
708
|
clearTimeout(timer);
|
|
709
|
-
if (result === timeoutSentinel) return
|
|
709
|
+
if (result === timeoutSentinel) return { ok: false, reason: "timeout" };
|
|
710
710
|
const data = result?.data;
|
|
711
|
-
if (!data?.code) return
|
|
712
|
-
return {
|
|
713
|
-
|
|
714
|
-
|
|
711
|
+
if (!data?.code) return { ok: false, reason: "network" };
|
|
712
|
+
return {
|
|
713
|
+
ok: true,
|
|
714
|
+
code: data.code,
|
|
715
|
+
expiresAt: data.expiresAt
|
|
716
|
+
};
|
|
717
|
+
} catch (err) {
|
|
718
|
+
const e = err;
|
|
719
|
+
if (e.statusCode === 429) {
|
|
720
|
+
return {
|
|
721
|
+
ok: false,
|
|
722
|
+
reason: "rate-limited",
|
|
723
|
+
retryAfterSeconds: typeof e.retryAfterSeconds === "number" && e.retryAfterSeconds > 0 ? e.retryAfterSeconds : 60
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
if (typeof e.statusCode === "number") {
|
|
727
|
+
return { ok: false, reason: "http", status: e.statusCode };
|
|
728
|
+
}
|
|
729
|
+
return { ok: false, reason: "network" };
|
|
715
730
|
}
|
|
716
731
|
}
|
|
717
732
|
async function fetchCurrentPluginAuthToken(sessionId, pluginId) {
|
|
@@ -857,9 +872,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
857
872
|
});
|
|
858
873
|
res.on("end", () => {
|
|
859
874
|
if (res.statusCode && res.statusCode >= 400) {
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
875
|
+
reject(
|
|
876
|
+
makeHttpError(res.statusCode, res.headers["retry-after"], responseBody)
|
|
877
|
+
);
|
|
863
878
|
return;
|
|
864
879
|
}
|
|
865
880
|
try {
|
|
@@ -879,6 +894,16 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
879
894
|
req.end();
|
|
880
895
|
});
|
|
881
896
|
}
|
|
897
|
+
function makeHttpError(statusCode, retryAfterHeader, responseBody) {
|
|
898
|
+
const raw = Array.isArray(retryAfterHeader) ? retryAfterHeader[0] : retryAfterHeader;
|
|
899
|
+
const retryAfterSeconds = raw && /^\d+$/.test(raw.trim()) ? Number.parseInt(raw, 10) : void 0;
|
|
900
|
+
const err = new Error(
|
|
901
|
+
`HTTP ${statusCode}${responseBody ? ": " + responseBody.slice(0, 200) : ""}`
|
|
902
|
+
);
|
|
903
|
+
err.statusCode = statusCode;
|
|
904
|
+
if (typeof retryAfterSeconds === "number") err.retryAfterSeconds = retryAfterSeconds;
|
|
905
|
+
return err;
|
|
906
|
+
}
|
|
882
907
|
async function _postJson(url, body) {
|
|
883
908
|
return new Promise((resolve6, reject) => {
|
|
884
909
|
const data = JSON.stringify(body);
|
|
@@ -905,7 +930,7 @@ async function _postJson(url, body) {
|
|
|
905
930
|
});
|
|
906
931
|
res.on("end", () => {
|
|
907
932
|
if (res.statusCode && res.statusCode >= 400) {
|
|
908
|
-
reject(
|
|
933
|
+
reject(makeHttpError(res.statusCode, res.headers["retry-after"], body2));
|
|
909
934
|
return;
|
|
910
935
|
}
|
|
911
936
|
try {
|
|
@@ -946,7 +971,7 @@ async function _getJson(url) {
|
|
|
946
971
|
});
|
|
947
972
|
res.on("end", () => {
|
|
948
973
|
if (res.statusCode && res.statusCode >= 400) {
|
|
949
|
-
reject(
|
|
974
|
+
reject(makeHttpError(res.statusCode, res.headers["retry-after"], body));
|
|
950
975
|
return;
|
|
951
976
|
}
|
|
952
977
|
try {
|
|
@@ -1130,8 +1155,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
1130
1155
|
return decodedFile;
|
|
1131
1156
|
};
|
|
1132
1157
|
}
|
|
1133
|
-
function normalizeWindowsPath(
|
|
1134
|
-
return
|
|
1158
|
+
function normalizeWindowsPath(path46) {
|
|
1159
|
+
return path46.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
1135
1160
|
}
|
|
1136
1161
|
|
|
1137
1162
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3611,9 +3636,9 @@ async function addSourceContext(frames) {
|
|
|
3611
3636
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3612
3637
|
return frames;
|
|
3613
3638
|
}
|
|
3614
|
-
function getContextLinesFromFile(
|
|
3639
|
+
function getContextLinesFromFile(path46, ranges, output) {
|
|
3615
3640
|
return new Promise((resolve6) => {
|
|
3616
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3641
|
+
const stream = (0, import_node_fs.createReadStream)(path46);
|
|
3617
3642
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3618
3643
|
input: stream
|
|
3619
3644
|
});
|
|
@@ -3628,7 +3653,7 @@ function getContextLinesFromFile(path45, ranges, output) {
|
|
|
3628
3653
|
let rangeStart = range[0];
|
|
3629
3654
|
let rangeEnd = range[1];
|
|
3630
3655
|
function onStreamError() {
|
|
3631
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3656
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path46, 1);
|
|
3632
3657
|
lineReaded.close();
|
|
3633
3658
|
lineReaded.removeAllListeners();
|
|
3634
3659
|
destroyStreamAndResolve();
|
|
@@ -3689,8 +3714,8 @@ function clearLineContext(frame) {
|
|
|
3689
3714
|
delete frame.context_line;
|
|
3690
3715
|
delete frame.post_context;
|
|
3691
3716
|
}
|
|
3692
|
-
function shouldSkipContextLinesForFile(
|
|
3693
|
-
return
|
|
3717
|
+
function shouldSkipContextLinesForFile(path46) {
|
|
3718
|
+
return path46.startsWith("node:") || path46.endsWith(".min.js") || path46.endsWith(".min.cjs") || path46.endsWith(".min.mjs") || path46.startsWith("data:");
|
|
3694
3719
|
}
|
|
3695
3720
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3696
3721
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5844,7 +5869,7 @@ function readAnonId() {
|
|
|
5844
5869
|
}
|
|
5845
5870
|
function superProperties() {
|
|
5846
5871
|
return {
|
|
5847
|
-
cliVersion: true ? "2.
|
|
5872
|
+
cliVersion: true ? "2.32.1" : "0.0.0-dev",
|
|
5848
5873
|
nodeVersion: process.version,
|
|
5849
5874
|
platform: process.platform,
|
|
5850
5875
|
arch: process.arch,
|
|
@@ -7186,10 +7211,10 @@ function buildForPlatform(platform2) {
|
|
|
7186
7211
|
var import_node_crypto4 = require("crypto");
|
|
7187
7212
|
|
|
7188
7213
|
// src/agents/claude/resolver.ts
|
|
7189
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
7190
|
-
const found =
|
|
7214
|
+
function buildClaudeLaunch(extraArgs = [], os29 = createOsStrategy()) {
|
|
7215
|
+
const found = os29.findInPath("claude") ?? os29.findInPath("claude-code");
|
|
7191
7216
|
if (!found) return null;
|
|
7192
|
-
return
|
|
7217
|
+
return os29.buildLaunch(found, extraArgs);
|
|
7193
7218
|
}
|
|
7194
7219
|
|
|
7195
7220
|
// src/agents/claude/installer.ts
|
|
@@ -9916,13 +9941,13 @@ function detectStartupBanner(lines) {
|
|
|
9916
9941
|
while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
|
|
9917
9942
|
if (metaIdx - artStart < 2) return null;
|
|
9918
9943
|
const pathLine = (lines[metaIdx + 1] ?? "").trim();
|
|
9919
|
-
const
|
|
9944
|
+
const path46 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
|
|
9920
9945
|
return {
|
|
9921
9946
|
title: "",
|
|
9922
9947
|
subtitle: lines[metaIdx].trim(),
|
|
9923
|
-
path:
|
|
9948
|
+
path: path46,
|
|
9924
9949
|
startIdx: artStart,
|
|
9925
|
-
endIdx: metaIdx + (
|
|
9950
|
+
endIdx: metaIdx + (path46 ? 1 : 0)
|
|
9926
9951
|
};
|
|
9927
9952
|
}
|
|
9928
9953
|
|
|
@@ -9932,8 +9957,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9932
9957
|
meta = getAgent("claude");
|
|
9933
9958
|
mode = "interactive";
|
|
9934
9959
|
os;
|
|
9935
|
-
constructor(
|
|
9936
|
-
this.os =
|
|
9960
|
+
constructor(os29) {
|
|
9961
|
+
this.os = os29;
|
|
9937
9962
|
}
|
|
9938
9963
|
/**
|
|
9939
9964
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -10941,8 +10966,8 @@ function codexCredentialLocator() {
|
|
|
10941
10966
|
function codexLoginLauncher() {
|
|
10942
10967
|
return {
|
|
10943
10968
|
async ensureInstalled() {
|
|
10944
|
-
const
|
|
10945
|
-
return
|
|
10969
|
+
const os29 = createOsStrategy();
|
|
10970
|
+
return os29.findInPath("codex") !== null;
|
|
10946
10971
|
},
|
|
10947
10972
|
launch() {
|
|
10948
10973
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -10965,8 +10990,8 @@ var CodexRuntimeStrategy = class {
|
|
|
10965
10990
|
meta = getAgent("codex");
|
|
10966
10991
|
mode = "interactive";
|
|
10967
10992
|
os;
|
|
10968
|
-
constructor(
|
|
10969
|
-
this.os =
|
|
10993
|
+
constructor(os29) {
|
|
10994
|
+
this.os = os29;
|
|
10970
10995
|
}
|
|
10971
10996
|
async prepareLaunch() {
|
|
10972
10997
|
let binary = this.os.findInPath("codex");
|
|
@@ -11072,12 +11097,12 @@ var CodexRuntimeStrategy = class {
|
|
|
11072
11097
|
});
|
|
11073
11098
|
}
|
|
11074
11099
|
};
|
|
11075
|
-
function resolveNpm(
|
|
11076
|
-
return
|
|
11100
|
+
function resolveNpm(os29) {
|
|
11101
|
+
return os29.id === "win32" ? "npm.cmd" : "npm";
|
|
11077
11102
|
}
|
|
11078
|
-
async function installCodexViaNpm(
|
|
11103
|
+
async function installCodexViaNpm(os29) {
|
|
11079
11104
|
return new Promise((resolve6, reject) => {
|
|
11080
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
11105
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os29), ["install", "-g", "@openai/codex"], {
|
|
11081
11106
|
stdio: "inherit"
|
|
11082
11107
|
});
|
|
11083
11108
|
proc.on("close", (code) => {
|
|
@@ -11094,16 +11119,16 @@ async function installCodexViaNpm(os28) {
|
|
|
11094
11119
|
});
|
|
11095
11120
|
});
|
|
11096
11121
|
}
|
|
11097
|
-
function augmentNpmGlobalBin(
|
|
11122
|
+
function augmentNpmGlobalBin(os29) {
|
|
11098
11123
|
try {
|
|
11099
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
11124
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os29), ["prefix", "-g"], {
|
|
11100
11125
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11101
11126
|
});
|
|
11102
11127
|
if (result.status !== 0) return;
|
|
11103
11128
|
const prefix = result.stdout.toString().trim();
|
|
11104
11129
|
if (!prefix) return;
|
|
11105
|
-
const binDir =
|
|
11106
|
-
|
|
11130
|
+
const binDir = os29.id === "win32" ? prefix : path17.join(prefix, "bin");
|
|
11131
|
+
os29.augmentPath([binDir]);
|
|
11107
11132
|
} catch {
|
|
11108
11133
|
}
|
|
11109
11134
|
}
|
|
@@ -11187,9 +11212,9 @@ var import_node_child_process7 = require("child_process");
|
|
|
11187
11212
|
// src/agents/coderabbit/installer.ts
|
|
11188
11213
|
var import_node_child_process5 = require("child_process");
|
|
11189
11214
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
11190
|
-
async function ensureCoderabbitInstalled(
|
|
11191
|
-
if (
|
|
11192
|
-
if (
|
|
11215
|
+
async function ensureCoderabbitInstalled(os29) {
|
|
11216
|
+
if (os29.findInPath("coderabbit")) return true;
|
|
11217
|
+
if (os29.id === "win32") {
|
|
11193
11218
|
console.error(
|
|
11194
11219
|
"\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"
|
|
11195
11220
|
);
|
|
@@ -11204,8 +11229,8 @@ async function ensureCoderabbitInstalled(os28) {
|
|
|
11204
11229
|
proc.on("error", () => resolve6(false));
|
|
11205
11230
|
});
|
|
11206
11231
|
if (!ok) return false;
|
|
11207
|
-
|
|
11208
|
-
return
|
|
11232
|
+
os29.augmentPath([`${os29.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
11233
|
+
return os29.findInPath("coderabbit") !== null;
|
|
11209
11234
|
}
|
|
11210
11235
|
|
|
11211
11236
|
// src/agents/coderabbit/link.ts
|
|
@@ -11232,10 +11257,10 @@ function coderabbitCredentialLocator() {
|
|
|
11232
11257
|
extract: extractLocalCoderabbitToken
|
|
11233
11258
|
};
|
|
11234
11259
|
}
|
|
11235
|
-
function coderabbitLoginLauncher(
|
|
11260
|
+
function coderabbitLoginLauncher(os29) {
|
|
11236
11261
|
return {
|
|
11237
11262
|
async ensureInstalled() {
|
|
11238
|
-
return ensureCoderabbitInstalled(
|
|
11263
|
+
return ensureCoderabbitInstalled(os29);
|
|
11239
11264
|
},
|
|
11240
11265
|
launch() {
|
|
11241
11266
|
return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
@@ -11258,11 +11283,11 @@ function parseReview(stdout) {
|
|
|
11258
11283
|
for (const line of lines) {
|
|
11259
11284
|
const m = line.match(HUNK_LINE_RE);
|
|
11260
11285
|
if (!m) continue;
|
|
11261
|
-
const [,
|
|
11262
|
-
if (!
|
|
11286
|
+
const [, path46, lineNo, sevToken, message] = m;
|
|
11287
|
+
if (!path46 || !lineNo || !message) continue;
|
|
11263
11288
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
11264
11289
|
hunks.push({
|
|
11265
|
-
path:
|
|
11290
|
+
path: path46.trim(),
|
|
11266
11291
|
line: Number(lineNo),
|
|
11267
11292
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
11268
11293
|
message: cleanedMessage
|
|
@@ -11281,8 +11306,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
11281
11306
|
meta = getAgent("coderabbit");
|
|
11282
11307
|
mode = "batch";
|
|
11283
11308
|
os;
|
|
11284
|
-
constructor(
|
|
11285
|
-
this.os =
|
|
11309
|
+
constructor(os29) {
|
|
11310
|
+
this.os = os29;
|
|
11286
11311
|
}
|
|
11287
11312
|
getDefaultArgs() {
|
|
11288
11313
|
return ["review"];
|
|
@@ -11397,10 +11422,10 @@ function cursorCredentialLocator() {
|
|
|
11397
11422
|
extract: extractLocalCursorToken
|
|
11398
11423
|
};
|
|
11399
11424
|
}
|
|
11400
|
-
function cursorLoginLauncher(
|
|
11425
|
+
function cursorLoginLauncher(os29) {
|
|
11401
11426
|
return {
|
|
11402
11427
|
async ensureInstalled() {
|
|
11403
|
-
if (
|
|
11428
|
+
if (os29.findInPath("cursor-agent")) return true;
|
|
11404
11429
|
console.error(
|
|
11405
11430
|
"\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"
|
|
11406
11431
|
);
|
|
@@ -11462,8 +11487,8 @@ var CursorRuntimeStrategy = class {
|
|
|
11462
11487
|
meta = getAgent("cursor");
|
|
11463
11488
|
mode = "interactive";
|
|
11464
11489
|
os;
|
|
11465
|
-
constructor(
|
|
11466
|
-
this.os =
|
|
11490
|
+
constructor(os29) {
|
|
11491
|
+
this.os = os29;
|
|
11467
11492
|
}
|
|
11468
11493
|
async prepareLaunch() {
|
|
11469
11494
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -11583,10 +11608,10 @@ function aiderCredentialLocator() {
|
|
|
11583
11608
|
extract: extractLocalAiderToken
|
|
11584
11609
|
};
|
|
11585
11610
|
}
|
|
11586
|
-
function aiderLoginLauncher(
|
|
11611
|
+
function aiderLoginLauncher(os29) {
|
|
11587
11612
|
return {
|
|
11588
11613
|
async ensureInstalled() {
|
|
11589
|
-
if (
|
|
11614
|
+
if (os29.findInPath("aider")) return true;
|
|
11590
11615
|
console.error(
|
|
11591
11616
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
11592
11617
|
);
|
|
@@ -11596,7 +11621,7 @@ function aiderLoginLauncher(os28) {
|
|
|
11596
11621
|
console.error(
|
|
11597
11622
|
"\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"
|
|
11598
11623
|
);
|
|
11599
|
-
return (0, import_node_child_process9.spawn)(
|
|
11624
|
+
return (0, import_node_child_process9.spawn)(os29.id === "win32" ? "cmd.exe" : "sh", os29.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
11600
11625
|
stdio: "ignore"
|
|
11601
11626
|
});
|
|
11602
11627
|
}
|
|
@@ -11668,8 +11693,8 @@ var AiderRuntimeStrategy = class {
|
|
|
11668
11693
|
meta = getAgent("aider");
|
|
11669
11694
|
mode = "interactive";
|
|
11670
11695
|
os;
|
|
11671
|
-
constructor(
|
|
11672
|
-
this.os =
|
|
11696
|
+
constructor(os29) {
|
|
11697
|
+
this.os = os29;
|
|
11673
11698
|
}
|
|
11674
11699
|
async prepareLaunch() {
|
|
11675
11700
|
const binary = this.os.findInPath("aider");
|
|
@@ -11792,8 +11817,8 @@ function geminiCredentialLocator() {
|
|
|
11792
11817
|
function geminiLoginLauncher() {
|
|
11793
11818
|
return {
|
|
11794
11819
|
async ensureInstalled() {
|
|
11795
|
-
const
|
|
11796
|
-
return
|
|
11820
|
+
const os29 = createOsStrategy();
|
|
11821
|
+
return os29.findInPath("gemini") !== null;
|
|
11797
11822
|
},
|
|
11798
11823
|
launch() {
|
|
11799
11824
|
return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -11826,8 +11851,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
11826
11851
|
meta = getAgent("gemini");
|
|
11827
11852
|
mode = "interactive";
|
|
11828
11853
|
os;
|
|
11829
|
-
constructor(
|
|
11830
|
-
this.os =
|
|
11854
|
+
constructor(os29) {
|
|
11855
|
+
this.os = os29;
|
|
11831
11856
|
}
|
|
11832
11857
|
async prepareLaunch() {
|
|
11833
11858
|
const binary = this.os.findInPath("gemini");
|
|
@@ -11927,18 +11952,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
11927
11952
|
|
|
11928
11953
|
// src/agents/registry.ts
|
|
11929
11954
|
var runtimeBuilders = {
|
|
11930
|
-
claude: (
|
|
11931
|
-
codex: (
|
|
11932
|
-
coderabbit: (
|
|
11933
|
-
cursor: (
|
|
11934
|
-
aider: (
|
|
11935
|
-
gemini: (
|
|
11955
|
+
claude: (os29) => new ClaudeRuntimeStrategy(os29),
|
|
11956
|
+
codex: (os29) => new CodexRuntimeStrategy(os29),
|
|
11957
|
+
coderabbit: (os29) => new CoderabbitRuntimeStrategy(os29),
|
|
11958
|
+
cursor: (os29) => new CursorRuntimeStrategy(os29),
|
|
11959
|
+
aider: (os29) => new AiderRuntimeStrategy(os29),
|
|
11960
|
+
gemini: (os29) => new GeminiRuntimeStrategy(os29)
|
|
11936
11961
|
};
|
|
11937
11962
|
var deployBuilders = {
|
|
11938
11963
|
claude: () => new ClaudeDeployStrategy(),
|
|
11939
11964
|
codex: () => new CodexDeployStrategy()
|
|
11940
11965
|
};
|
|
11941
|
-
function createAgentStrategy(agent,
|
|
11966
|
+
function createAgentStrategy(agent, os29 = createOsStrategy()) {
|
|
11942
11967
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
11943
11968
|
throw new Error(
|
|
11944
11969
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -11948,10 +11973,10 @@ function createAgentStrategy(agent, os28 = createOsStrategy()) {
|
|
|
11948
11973
|
if (!build) {
|
|
11949
11974
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
11950
11975
|
}
|
|
11951
|
-
return build(
|
|
11976
|
+
return build(os29);
|
|
11952
11977
|
}
|
|
11953
|
-
function createInteractiveAgentStrategy(agent,
|
|
11954
|
-
const s = createAgentStrategy(agent,
|
|
11978
|
+
function createInteractiveAgentStrategy(agent, os29 = createOsStrategy()) {
|
|
11979
|
+
const s = createAgentStrategy(agent, os29);
|
|
11955
11980
|
if (s.mode !== "interactive") {
|
|
11956
11981
|
throw new Error(
|
|
11957
11982
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -12036,7 +12061,15 @@ var REGISTRY = {
|
|
|
12036
12061
|
// resolved from PATH at spawn time instead of being absolute.
|
|
12037
12062
|
gemini: () => ({
|
|
12038
12063
|
command: "gemini",
|
|
12039
|
-
|
|
12064
|
+
// `--skip-trust` bypasses Gemini's headless-mode workspace-trust
|
|
12065
|
+
// gate. Without it the CLI refuses to start in `--acp` mode with
|
|
12066
|
+
// "Gemini CLI is not running in a trusted directory" and the
|
|
12067
|
+
// ACP newSession call never returns, leaving mobile chat stuck
|
|
12068
|
+
// on "thinking…" forever. The equivalent env var is
|
|
12069
|
+
// `GEMINI_CLI_TRUST_WORKSPACE=true`; passing the flag is
|
|
12070
|
+
// cleaner because it survives whatever shell env the parent
|
|
12071
|
+
// codeam was launched from.
|
|
12072
|
+
args: ["--skip-trust", "--acp"],
|
|
12040
12073
|
requiresAgentBinary: "gemini"
|
|
12041
12074
|
})
|
|
12042
12075
|
};
|
|
@@ -12051,6 +12084,9 @@ var import_node_crypto7 = require("crypto");
|
|
|
12051
12084
|
// src/agents/acp/client.ts
|
|
12052
12085
|
var import_node_child_process11 = require("child_process");
|
|
12053
12086
|
var fs21 = __toESM(require("fs/promises"));
|
|
12087
|
+
var fsSync = __toESM(require("fs"));
|
|
12088
|
+
var os22 = __toESM(require("os"));
|
|
12089
|
+
var path26 = __toESM(require("path"));
|
|
12054
12090
|
var import_node_stream = require("stream");
|
|
12055
12091
|
|
|
12056
12092
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -14529,13 +14565,14 @@ var AcpClient = class {
|
|
|
14529
14565
|
async start() {
|
|
14530
14566
|
if (this.child) throw new Error("AcpClient already started");
|
|
14531
14567
|
const { adapter, cwd } = this.opts;
|
|
14568
|
+
const augmentedPath = expandPathForAgentBinaries(process.env.PATH ?? "");
|
|
14532
14569
|
log.info(
|
|
14533
14570
|
"acpClient",
|
|
14534
14571
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
14535
14572
|
);
|
|
14536
14573
|
const child = (0, import_node_child_process11.spawn)(adapter.command, adapter.args, {
|
|
14537
14574
|
cwd,
|
|
14538
|
-
env: process.env,
|
|
14575
|
+
env: { ...process.env, PATH: augmentedPath },
|
|
14539
14576
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14540
14577
|
});
|
|
14541
14578
|
this.child = child;
|
|
@@ -14812,6 +14849,48 @@ function applyLineRange(content, line, limit) {
|
|
|
14812
14849
|
const end = limit !== null ? start2 + limit : lines.length;
|
|
14813
14850
|
return { content: lines.slice(start2, end).join("\n") };
|
|
14814
14851
|
}
|
|
14852
|
+
function knownAgentBinaryDirs() {
|
|
14853
|
+
const home = os22.homedir();
|
|
14854
|
+
const out2 = [];
|
|
14855
|
+
out2.push("/tmp/codeam-node20/bin");
|
|
14856
|
+
for (const root of [
|
|
14857
|
+
"/usr/local/share/nvm/versions/node",
|
|
14858
|
+
path26.join(home, ".nvm/versions/node")
|
|
14859
|
+
]) {
|
|
14860
|
+
try {
|
|
14861
|
+
for (const child of fsSync.readdirSync(root)) {
|
|
14862
|
+
out2.push(path26.join(root, child, "bin"));
|
|
14863
|
+
}
|
|
14864
|
+
} catch {
|
|
14865
|
+
}
|
|
14866
|
+
}
|
|
14867
|
+
out2.push(path26.join(home, ".volta/bin"));
|
|
14868
|
+
out2.push("/usr/local/bin");
|
|
14869
|
+
out2.push("/usr/bin");
|
|
14870
|
+
out2.push(path26.join(home, ".local/bin"));
|
|
14871
|
+
out2.push(path26.join(home, "bin"));
|
|
14872
|
+
return out2.filter((p2) => {
|
|
14873
|
+
try {
|
|
14874
|
+
return fsSync.statSync(p2).isDirectory();
|
|
14875
|
+
} catch {
|
|
14876
|
+
return false;
|
|
14877
|
+
}
|
|
14878
|
+
});
|
|
14879
|
+
}
|
|
14880
|
+
function expandPathForAgentBinaries(existingPath) {
|
|
14881
|
+
const existing = new Set(
|
|
14882
|
+
existingPath.split(path26.delimiter).filter((p2) => p2.length > 0)
|
|
14883
|
+
);
|
|
14884
|
+
const additions = [];
|
|
14885
|
+
for (const dir of knownAgentBinaryDirs()) {
|
|
14886
|
+
if (!existing.has(dir)) {
|
|
14887
|
+
additions.push(dir);
|
|
14888
|
+
existing.add(dir);
|
|
14889
|
+
}
|
|
14890
|
+
}
|
|
14891
|
+
if (additions.length === 0) return existingPath;
|
|
14892
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path26.delimiter);
|
|
14893
|
+
}
|
|
14815
14894
|
|
|
14816
14895
|
// src/services/streaming/transport.ts
|
|
14817
14896
|
var http3 = __toESM(require("http"));
|
|
@@ -15597,8 +15676,8 @@ function extractSelectPrompt(text) {
|
|
|
15597
15676
|
|
|
15598
15677
|
// src/commands/start/handlers.ts
|
|
15599
15678
|
var fs29 = __toESM(require("fs"));
|
|
15600
|
-
var
|
|
15601
|
-
var
|
|
15679
|
+
var os24 = __toESM(require("os"));
|
|
15680
|
+
var path35 = __toESM(require("path"));
|
|
15602
15681
|
var import_crypto3 = require("crypto");
|
|
15603
15682
|
var import_child_process12 = require("child_process");
|
|
15604
15683
|
|
|
@@ -15723,7 +15802,7 @@ function parsePayload2(schema, raw) {
|
|
|
15723
15802
|
|
|
15724
15803
|
// src/services/file-ops.service.ts
|
|
15725
15804
|
var fs22 = __toESM(require("fs/promises"));
|
|
15726
|
-
var
|
|
15805
|
+
var path28 = __toESM(require("path"));
|
|
15727
15806
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
15728
15807
|
var MAX_WALK_DEPTH = 6;
|
|
15729
15808
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -15758,8 +15837,8 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
15758
15837
|
"__pycache__"
|
|
15759
15838
|
]);
|
|
15760
15839
|
function isUnder(parent, candidate) {
|
|
15761
|
-
const rel =
|
|
15762
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
15840
|
+
const rel = path28.relative(parent, candidate);
|
|
15841
|
+
return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
|
|
15763
15842
|
}
|
|
15764
15843
|
async function isExistingFile(absPath) {
|
|
15765
15844
|
try {
|
|
@@ -15782,7 +15861,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
15782
15861
|
}
|
|
15783
15862
|
for (const e of entries) {
|
|
15784
15863
|
if (!e.isFile()) continue;
|
|
15785
|
-
const full =
|
|
15864
|
+
const full = path28.join(dir, e.name);
|
|
15786
15865
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
15787
15866
|
ctx.matches.push(full);
|
|
15788
15867
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -15792,21 +15871,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
15792
15871
|
if (!e.isDirectory()) continue;
|
|
15793
15872
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
15794
15873
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
15795
|
-
await walkForSuffix(
|
|
15874
|
+
await walkForSuffix(path28.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
15796
15875
|
if (ctx.matches.length >= ctx.cap) return;
|
|
15797
15876
|
}
|
|
15798
15877
|
}
|
|
15799
15878
|
async function findFile(rawPath) {
|
|
15800
15879
|
const cwd = process.cwd();
|
|
15801
|
-
if (
|
|
15802
|
-
const abs =
|
|
15880
|
+
if (path28.isAbsolute(rawPath)) {
|
|
15881
|
+
const abs = path28.normalize(rawPath);
|
|
15803
15882
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
15804
15883
|
}
|
|
15805
|
-
const direct =
|
|
15884
|
+
const direct = path28.resolve(cwd, rawPath);
|
|
15806
15885
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
15807
|
-
const normalized =
|
|
15886
|
+
const normalized = path28.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
15808
15887
|
const needles = [
|
|
15809
|
-
`${
|
|
15888
|
+
`${path28.sep}${normalized}`,
|
|
15810
15889
|
`/${normalized}`
|
|
15811
15890
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
15812
15891
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -15820,7 +15899,7 @@ async function findWriteTarget(rawPath) {
|
|
|
15820
15899
|
const found = await findFile(rawPath);
|
|
15821
15900
|
if (found) return found;
|
|
15822
15901
|
const cwd = process.cwd();
|
|
15823
|
-
const fallback =
|
|
15902
|
+
const fallback = path28.isAbsolute(rawPath) ? path28.normalize(rawPath) : path28.resolve(cwd, rawPath);
|
|
15824
15903
|
if (!isUnder(cwd, fallback)) return null;
|
|
15825
15904
|
return fallback;
|
|
15826
15905
|
}
|
|
@@ -15860,7 +15939,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
15860
15939
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
15861
15940
|
return { error: "Content too large." };
|
|
15862
15941
|
}
|
|
15863
|
-
await fs22.mkdir(
|
|
15942
|
+
await fs22.mkdir(path28.dirname(abs), { recursive: true });
|
|
15864
15943
|
await fs22.writeFile(abs, content, "utf-8");
|
|
15865
15944
|
return { ok: true };
|
|
15866
15945
|
} catch (e) {
|
|
@@ -15873,7 +15952,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
15873
15952
|
var import_child_process9 = require("child_process");
|
|
15874
15953
|
var import_util2 = require("util");
|
|
15875
15954
|
var fs23 = __toESM(require("fs/promises"));
|
|
15876
|
-
var
|
|
15955
|
+
var path29 = __toESM(require("path"));
|
|
15877
15956
|
var execFileP3 = (0, import_util2.promisify)(import_child_process9.execFile);
|
|
15878
15957
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
15879
15958
|
"node_modules",
|
|
@@ -15931,12 +16010,12 @@ async function listProjectFiles(opts = {}) {
|
|
|
15931
16010
|
return;
|
|
15932
16011
|
}
|
|
15933
16012
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
15934
|
-
const full =
|
|
16013
|
+
const full = path29.join(dir, e.name);
|
|
15935
16014
|
if (e.isDirectory()) {
|
|
15936
16015
|
if (depth >= 12) continue;
|
|
15937
16016
|
await walk(full, depth + 1);
|
|
15938
16017
|
} else if (e.isFile()) {
|
|
15939
|
-
const rel =
|
|
16018
|
+
const rel = path29.relative(root, full);
|
|
15940
16019
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
15941
16020
|
continue;
|
|
15942
16021
|
}
|
|
@@ -16044,7 +16123,7 @@ async function gitStatus(cwd) {
|
|
|
16044
16123
|
let hasMergeInProgress = false;
|
|
16045
16124
|
try {
|
|
16046
16125
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
16047
|
-
const mergeHead =
|
|
16126
|
+
const mergeHead = path29.isAbsolute(gitDir) ? path29.join(gitDir, "MERGE_HEAD") : path29.join(root, gitDir, "MERGE_HEAD");
|
|
16048
16127
|
await fs23.access(mergeHead);
|
|
16049
16128
|
hasMergeInProgress = true;
|
|
16050
16129
|
} catch {
|
|
@@ -16191,7 +16270,7 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
16191
16270
|
}
|
|
16192
16271
|
let content = "";
|
|
16193
16272
|
try {
|
|
16194
|
-
content = await fs23.readFile(
|
|
16273
|
+
content = await fs23.readFile(path29.join(cwd, f.path), "utf8");
|
|
16195
16274
|
} catch {
|
|
16196
16275
|
continue;
|
|
16197
16276
|
}
|
|
@@ -16216,13 +16295,13 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
16216
16295
|
// src/services/apply-file-review.service.ts
|
|
16217
16296
|
var import_child_process10 = require("child_process");
|
|
16218
16297
|
var fs24 = __toESM(require("fs"));
|
|
16219
|
-
var
|
|
16298
|
+
var path30 = __toESM(require("path"));
|
|
16220
16299
|
async function applyFileReview(workingDir, filePath, action) {
|
|
16221
|
-
if (filePath.includes("..") ||
|
|
16300
|
+
if (filePath.includes("..") || path30.isAbsolute(filePath)) {
|
|
16222
16301
|
return { ok: false, action, filePath, error: "invalid file path" };
|
|
16223
16302
|
}
|
|
16224
|
-
const absFile =
|
|
16225
|
-
const repoRoot = findGitRoot(
|
|
16303
|
+
const absFile = path30.resolve(workingDir, filePath);
|
|
16304
|
+
const repoRoot = findGitRoot(path30.dirname(absFile));
|
|
16226
16305
|
if (!repoRoot) {
|
|
16227
16306
|
return {
|
|
16228
16307
|
ok: false,
|
|
@@ -16231,7 +16310,7 @@ async function applyFileReview(workingDir, filePath, action) {
|
|
|
16231
16310
|
error: `no enclosing git repo for ${filePath}`
|
|
16232
16311
|
};
|
|
16233
16312
|
}
|
|
16234
|
-
const relInRepo =
|
|
16313
|
+
const relInRepo = path30.relative(repoRoot, absFile);
|
|
16235
16314
|
if (!relInRepo || relInRepo.startsWith("..")) {
|
|
16236
16315
|
return { ok: false, action, filePath, error: "path escapes repo root" };
|
|
16237
16316
|
}
|
|
@@ -16280,17 +16359,17 @@ function runGit(cwd, args2) {
|
|
|
16280
16359
|
});
|
|
16281
16360
|
}
|
|
16282
16361
|
function findGitRoot(startDir) {
|
|
16283
|
-
let dir =
|
|
16362
|
+
let dir = path30.resolve(startDir);
|
|
16284
16363
|
const seen = /* @__PURE__ */ new Set();
|
|
16285
16364
|
for (let i = 0; i < 256; i++) {
|
|
16286
16365
|
if (seen.has(dir)) return null;
|
|
16287
16366
|
seen.add(dir);
|
|
16288
16367
|
try {
|
|
16289
|
-
const stat3 = fs24.statSync(
|
|
16368
|
+
const stat3 = fs24.statSync(path30.join(dir, ".git"), { throwIfNoEntry: false });
|
|
16290
16369
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
16291
16370
|
} catch {
|
|
16292
16371
|
}
|
|
16293
|
-
const parent =
|
|
16372
|
+
const parent = path30.dirname(dir);
|
|
16294
16373
|
if (parent === dir) return null;
|
|
16295
16374
|
dir = parent;
|
|
16296
16375
|
}
|
|
@@ -16300,7 +16379,7 @@ function findGitRoot(startDir) {
|
|
|
16300
16379
|
// src/commands/link.ts
|
|
16301
16380
|
var import_node_crypto6 = require("crypto");
|
|
16302
16381
|
var fs25 = __toESM(require("fs"));
|
|
16303
|
-
var
|
|
16382
|
+
var path31 = __toESM(require("path"));
|
|
16304
16383
|
var import_chokidar = __toESM(require("chokidar"));
|
|
16305
16384
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
16306
16385
|
|
|
@@ -16479,7 +16558,7 @@ function parseLinkArgs(args2) {
|
|
|
16479
16558
|
if (apiKeyFileArg) {
|
|
16480
16559
|
const filePath = apiKeyFileArg.slice("--api-key-file=".length);
|
|
16481
16560
|
try {
|
|
16482
|
-
apiKey = fs25.readFileSync(
|
|
16561
|
+
apiKey = fs25.readFileSync(path31.resolve(filePath), "utf8").trim();
|
|
16483
16562
|
} catch (err) {
|
|
16484
16563
|
throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
|
|
16485
16564
|
}
|
|
@@ -16510,9 +16589,19 @@ async function link(args2 = []) {
|
|
|
16510
16589
|
const spin = dist_exports.spinner();
|
|
16511
16590
|
spin.start("Requesting pairing code...");
|
|
16512
16591
|
const pairing = await requestCode(pluginId);
|
|
16513
|
-
if (!pairing) {
|
|
16592
|
+
if (!pairing.ok) {
|
|
16514
16593
|
spin.stop("Failed");
|
|
16515
|
-
|
|
16594
|
+
if (pairing.reason === "rate-limited") {
|
|
16595
|
+
showError(
|
|
16596
|
+
`Server is rate-limiting this request (HTTP 429). Retry in ${pairing.retryAfterSeconds}s.`
|
|
16597
|
+
);
|
|
16598
|
+
} else if (pairing.reason === "timeout") {
|
|
16599
|
+
showError("Server took too long to respond. Check your connection and try again.");
|
|
16600
|
+
} else if (pairing.reason === "http") {
|
|
16601
|
+
showError(`Server returned HTTP ${pairing.status}. Try again later.`);
|
|
16602
|
+
} else {
|
|
16603
|
+
showError("Could not reach the server. Check your connection and try again.");
|
|
16604
|
+
}
|
|
16516
16605
|
process.exit(1);
|
|
16517
16606
|
}
|
|
16518
16607
|
spin.stop("Got pairing code");
|
|
@@ -16573,7 +16662,7 @@ async function link(args2 = []) {
|
|
|
16573
16662
|
return;
|
|
16574
16663
|
}
|
|
16575
16664
|
if (parsed.tokenFile) {
|
|
16576
|
-
const credential = fs25.readFileSync(
|
|
16665
|
+
const credential = fs25.readFileSync(path31.resolve(parsed.tokenFile), "utf8").trim();
|
|
16577
16666
|
if (!credential) {
|
|
16578
16667
|
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
16579
16668
|
process.exit(1);
|
|
@@ -17092,7 +17181,7 @@ function cleanupAttachmentTempFiles() {
|
|
|
17092
17181
|
function saveFilesTemp(files) {
|
|
17093
17182
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
17094
17183
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
17095
|
-
const tmpPath =
|
|
17184
|
+
const tmpPath = path35.join(os24.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
17096
17185
|
fs29.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
17097
17186
|
pendingAttachmentFiles.add(tmpPath);
|
|
17098
17187
|
return tmpPath;
|
|
@@ -18039,8 +18128,8 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
18039
18128
|
// src/services/file-watcher.service.ts
|
|
18040
18129
|
var import_child_process13 = require("child_process");
|
|
18041
18130
|
var fs30 = __toESM(require("fs"));
|
|
18042
|
-
var
|
|
18043
|
-
var
|
|
18131
|
+
var os25 = __toESM(require("os"));
|
|
18132
|
+
var path36 = __toESM(require("path"));
|
|
18044
18133
|
var import_ignore = __toESM(require("ignore"));
|
|
18045
18134
|
|
|
18046
18135
|
// src/services/file-watcher/diff-parser.ts
|
|
@@ -18199,10 +18288,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
18199
18288
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
18200
18289
|
/[\\/]Templates([\\/]|$)/i
|
|
18201
18290
|
];
|
|
18202
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
18291
|
+
function isUnsafeWindowsWatchRoot(dir, homedir21) {
|
|
18203
18292
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
18204
18293
|
const cwd = norm(dir);
|
|
18205
|
-
const home = norm(
|
|
18294
|
+
const home = norm(homedir21);
|
|
18206
18295
|
if (cwd === home) return true;
|
|
18207
18296
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
18208
18297
|
const sysRoots = [
|
|
@@ -18232,18 +18321,18 @@ var _findGitRootSeam = {
|
|
|
18232
18321
|
resolve: _defaultFindGitRoot
|
|
18233
18322
|
};
|
|
18234
18323
|
function _defaultFindGitRoot(startDir) {
|
|
18235
|
-
let dir =
|
|
18324
|
+
let dir = path36.resolve(startDir);
|
|
18236
18325
|
const seen = /* @__PURE__ */ new Set();
|
|
18237
18326
|
for (let i = 0; i < 256; i++) {
|
|
18238
18327
|
if (seen.has(dir)) return null;
|
|
18239
18328
|
seen.add(dir);
|
|
18240
18329
|
try {
|
|
18241
|
-
const gitPath =
|
|
18330
|
+
const gitPath = path36.join(dir, ".git");
|
|
18242
18331
|
const stat3 = fs30.statSync(gitPath, { throwIfNoEntry: false });
|
|
18243
18332
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
18244
18333
|
} catch {
|
|
18245
18334
|
}
|
|
18246
|
-
const parent =
|
|
18335
|
+
const parent = path36.dirname(dir);
|
|
18247
18336
|
if (parent === dir) return null;
|
|
18248
18337
|
dir = parent;
|
|
18249
18338
|
}
|
|
@@ -18301,7 +18390,7 @@ var FileWatcherService = class {
|
|
|
18301
18390
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
18302
18391
|
}
|
|
18303
18392
|
const isWin = process.platform === "win32";
|
|
18304
|
-
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir,
|
|
18393
|
+
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os25.homedir())) {
|
|
18305
18394
|
log.warn(
|
|
18306
18395
|
"fileWatcher",
|
|
18307
18396
|
`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.`
|
|
@@ -18488,7 +18577,7 @@ var FileWatcherService = class {
|
|
|
18488
18577
|
}
|
|
18489
18578
|
async emitForFile(absPath, changeType) {
|
|
18490
18579
|
if (this.stopped) return;
|
|
18491
|
-
const fileDir =
|
|
18580
|
+
const fileDir = path36.dirname(absPath);
|
|
18492
18581
|
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
18493
18582
|
if (gitRoot === void 0) {
|
|
18494
18583
|
gitRoot = findGitRoot2(fileDir);
|
|
@@ -18501,19 +18590,19 @@ var FileWatcherService = class {
|
|
|
18501
18590
|
);
|
|
18502
18591
|
return;
|
|
18503
18592
|
}
|
|
18504
|
-
const relPathInRepo =
|
|
18593
|
+
const relPathInRepo = path36.relative(gitRoot, absPath);
|
|
18505
18594
|
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
18506
18595
|
const matcher = this.getGitIgnoreMatcher(gitRoot);
|
|
18507
18596
|
if (matcher && matcher.ignores(relPathInRepo)) {
|
|
18508
18597
|
log.trace(
|
|
18509
18598
|
"fileWatcher",
|
|
18510
|
-
`${relPathInRepo} ignored by ${
|
|
18599
|
+
`${relPathInRepo} ignored by ${path36.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
|
|
18511
18600
|
);
|
|
18512
18601
|
return;
|
|
18513
18602
|
}
|
|
18514
18603
|
this.opts.onRepoDirty?.(gitRoot);
|
|
18515
|
-
const repoPath =
|
|
18516
|
-
const repoName =
|
|
18604
|
+
const repoPath = path36.relative(this.opts.workingDir, gitRoot);
|
|
18605
|
+
const repoName = path36.basename(gitRoot);
|
|
18517
18606
|
let diffText = "";
|
|
18518
18607
|
let fileStatus = "modified";
|
|
18519
18608
|
if (changeType === "unlink") {
|
|
@@ -18697,16 +18786,16 @@ var FileWatcherService = class {
|
|
|
18697
18786
|
);
|
|
18698
18787
|
if (gitignoreEntry) {
|
|
18699
18788
|
try {
|
|
18700
|
-
const body = fs30.readFileSync(
|
|
18701
|
-
const rel =
|
|
18789
|
+
const body = fs30.readFileSync(path36.join(dir, ".gitignore"), "utf8");
|
|
18790
|
+
const rel = path36.relative(repoRoot, dir).replace(/\\/g, "/");
|
|
18702
18791
|
const prefixed = body.split(/\r?\n/).map((line) => {
|
|
18703
18792
|
const trimmed = line.trim();
|
|
18704
18793
|
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
18705
18794
|
if (!rel) return line;
|
|
18706
18795
|
if (trimmed.startsWith("!")) {
|
|
18707
|
-
return "!" +
|
|
18796
|
+
return "!" + path36.posix.join(rel, trimmed.slice(1));
|
|
18708
18797
|
}
|
|
18709
|
-
return
|
|
18798
|
+
return path36.posix.join(rel, trimmed);
|
|
18710
18799
|
}).join("\n");
|
|
18711
18800
|
matcher.add(prefixed);
|
|
18712
18801
|
} catch {
|
|
@@ -18715,7 +18804,7 @@ var FileWatcherService = class {
|
|
|
18715
18804
|
for (const entry of entries) {
|
|
18716
18805
|
if (!entry.isDirectory()) continue;
|
|
18717
18806
|
if (entry.name === ".git") continue;
|
|
18718
|
-
const childAbs =
|
|
18807
|
+
const childAbs = path36.join(dir, entry.name);
|
|
18719
18808
|
if (isIgnoredFilePath(childAbs)) continue;
|
|
18720
18809
|
this.collectGitignoreFiles(repoRoot, childAbs, matcher);
|
|
18721
18810
|
}
|
|
@@ -18885,7 +18974,7 @@ var import_crypto4 = require("crypto");
|
|
|
18885
18974
|
|
|
18886
18975
|
// src/services/turn-files/git-changeset.ts
|
|
18887
18976
|
var import_child_process14 = require("child_process");
|
|
18888
|
-
var
|
|
18977
|
+
var path37 = __toESM(require("path"));
|
|
18889
18978
|
async function collectRepoChangeset(opts) {
|
|
18890
18979
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
18891
18980
|
if (status2 === null) return null;
|
|
@@ -19015,8 +19104,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19015
19104
|
if (hasGit) {
|
|
19016
19105
|
out2.push({
|
|
19017
19106
|
repoRoot: dir,
|
|
19018
|
-
repoPath:
|
|
19019
|
-
repoName:
|
|
19107
|
+
repoPath: path37.relative(workingDir, dir),
|
|
19108
|
+
repoName: path37.basename(dir)
|
|
19020
19109
|
});
|
|
19021
19110
|
return;
|
|
19022
19111
|
}
|
|
@@ -19024,14 +19113,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19024
19113
|
if (!entry.isDirectory) continue;
|
|
19025
19114
|
if (entry.name === "node_modules") continue;
|
|
19026
19115
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
19027
|
-
await walk(
|
|
19116
|
+
await walk(path37.join(dir, entry.name), depth + 1);
|
|
19028
19117
|
}
|
|
19029
19118
|
}
|
|
19030
19119
|
}
|
|
19031
19120
|
|
|
19032
19121
|
// src/services/turn-files/files-outbox.ts
|
|
19033
19122
|
var fs31 = __toESM(require("fs/promises"));
|
|
19034
|
-
var
|
|
19123
|
+
var path38 = __toESM(require("path"));
|
|
19035
19124
|
var import_os7 = require("os");
|
|
19036
19125
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
19037
19126
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -19064,15 +19153,15 @@ var FilesOutbox = class {
|
|
|
19064
19153
|
backoffIndex = 0;
|
|
19065
19154
|
stopped = false;
|
|
19066
19155
|
constructor(opts) {
|
|
19067
|
-
const base = opts.baseDir ??
|
|
19068
|
-
this.filePath =
|
|
19156
|
+
const base = opts.baseDir ?? path38.join(homeDir(), HOME_OUTBOX_DIR);
|
|
19157
|
+
this.filePath = path38.join(base, `${opts.sessionId}.jsonl`);
|
|
19069
19158
|
this.post = opts.post;
|
|
19070
19159
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
19071
19160
|
}
|
|
19072
19161
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
19073
19162
|
* line is durable on disk (not once the POST succeeds). */
|
|
19074
19163
|
async enqueue(entry) {
|
|
19075
|
-
await fs31.mkdir(
|
|
19164
|
+
await fs31.mkdir(path38.dirname(this.filePath), { recursive: true });
|
|
19076
19165
|
await fs31.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
19077
19166
|
this.backoffIndex = 0;
|
|
19078
19167
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
@@ -20927,8 +21016,8 @@ var OutputService = class _OutputService {
|
|
|
20927
21016
|
|
|
20928
21017
|
// src/services/history.service.ts
|
|
20929
21018
|
var fs32 = __toESM(require("fs"));
|
|
20930
|
-
var
|
|
20931
|
-
var
|
|
21019
|
+
var path39 = __toESM(require("path"));
|
|
21020
|
+
var os26 = __toESM(require("os"));
|
|
20932
21021
|
var https7 = __toESM(require("https"));
|
|
20933
21022
|
var http7 = __toESM(require("http"));
|
|
20934
21023
|
var import_zod2 = require("zod");
|
|
@@ -21090,7 +21179,7 @@ var HistoryService = class _HistoryService {
|
|
|
21090
21179
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
21091
21180
|
}
|
|
21092
21181
|
get projectDir() {
|
|
21093
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
21182
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path39.join(os26.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
21094
21183
|
}
|
|
21095
21184
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
21096
21185
|
setCurrentConversationId(id) {
|
|
@@ -21102,7 +21191,7 @@ var HistoryService = class _HistoryService {
|
|
|
21102
21191
|
/** Return the current message count in the active conversation. */
|
|
21103
21192
|
getCurrentMessageCount() {
|
|
21104
21193
|
if (!this.currentConversationId) return 0;
|
|
21105
|
-
const filePath =
|
|
21194
|
+
const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21106
21195
|
return parseJsonl(filePath).length;
|
|
21107
21196
|
}
|
|
21108
21197
|
/**
|
|
@@ -21113,7 +21202,7 @@ var HistoryService = class _HistoryService {
|
|
|
21113
21202
|
const deadline = Date.now() + timeoutMs;
|
|
21114
21203
|
while (Date.now() < deadline) {
|
|
21115
21204
|
if (!this.currentConversationId) return null;
|
|
21116
|
-
const filePath =
|
|
21205
|
+
const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21117
21206
|
const messages = parseJsonl(filePath);
|
|
21118
21207
|
if (messages.length > previousCount) {
|
|
21119
21208
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -21141,14 +21230,14 @@ var HistoryService = class _HistoryService {
|
|
|
21141
21230
|
try {
|
|
21142
21231
|
const files = fs32.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21143
21232
|
try {
|
|
21144
|
-
const stat3 = fs32.statSync(
|
|
21233
|
+
const stat3 = fs32.statSync(path39.join(dir, e.name));
|
|
21145
21234
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21146
21235
|
} catch {
|
|
21147
21236
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
21148
21237
|
}
|
|
21149
21238
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
21150
21239
|
if (files.length > 0) {
|
|
21151
|
-
this.currentConversationId =
|
|
21240
|
+
this.currentConversationId = path39.basename(files[0].name, ".jsonl");
|
|
21152
21241
|
}
|
|
21153
21242
|
} catch {
|
|
21154
21243
|
}
|
|
@@ -21188,7 +21277,7 @@ var HistoryService = class _HistoryService {
|
|
|
21188
21277
|
}
|
|
21189
21278
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21190
21279
|
try {
|
|
21191
|
-
const stat3 = fs32.statSync(
|
|
21280
|
+
const stat3 = fs32.statSync(path39.join(dir, e.name));
|
|
21192
21281
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21193
21282
|
} catch {
|
|
21194
21283
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -21197,7 +21286,7 @@ var HistoryService = class _HistoryService {
|
|
|
21197
21286
|
if (files.length === 0) return null;
|
|
21198
21287
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
21199
21288
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
21200
|
-
return this.extractUsageFromFile(
|
|
21289
|
+
return this.extractUsageFromFile(path39.join(dir, targetFile));
|
|
21201
21290
|
}
|
|
21202
21291
|
extractUsageFromFile(filePath) {
|
|
21203
21292
|
let raw;
|
|
@@ -21249,7 +21338,7 @@ var HistoryService = class _HistoryService {
|
|
|
21249
21338
|
try {
|
|
21250
21339
|
files = fs32.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
21251
21340
|
try {
|
|
21252
|
-
return fs32.statSync(
|
|
21341
|
+
return fs32.statSync(path39.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
21253
21342
|
} catch {
|
|
21254
21343
|
return false;
|
|
21255
21344
|
}
|
|
@@ -21260,7 +21349,7 @@ var HistoryService = class _HistoryService {
|
|
|
21260
21349
|
for (const file of files) {
|
|
21261
21350
|
let raw;
|
|
21262
21351
|
try {
|
|
21263
|
-
raw = fs32.readFileSync(
|
|
21352
|
+
raw = fs32.readFileSync(path39.join(projectDir, file), "utf8");
|
|
21264
21353
|
} catch {
|
|
21265
21354
|
continue;
|
|
21266
21355
|
}
|
|
@@ -21324,7 +21413,7 @@ var HistoryService = class _HistoryService {
|
|
|
21324
21413
|
* showing an empty conversation.
|
|
21325
21414
|
*/
|
|
21326
21415
|
async loadConversation(sessionId) {
|
|
21327
|
-
const filePath =
|
|
21416
|
+
const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21328
21417
|
const messages = parseJsonl(filePath);
|
|
21329
21418
|
if (messages.length === 0) return;
|
|
21330
21419
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -21378,7 +21467,7 @@ var HistoryService = class _HistoryService {
|
|
|
21378
21467
|
if (!this.currentConversationId) return 0;
|
|
21379
21468
|
}
|
|
21380
21469
|
const sessionId = this.currentConversationId;
|
|
21381
|
-
const filePath =
|
|
21470
|
+
const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21382
21471
|
const messages = parseJsonl(filePath);
|
|
21383
21472
|
if (messages.length === 0) return 0;
|
|
21384
21473
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -22135,9 +22224,19 @@ async function pair(args2 = []) {
|
|
|
22135
22224
|
const spin = dist_exports.spinner();
|
|
22136
22225
|
spin.start("Requesting pairing code...");
|
|
22137
22226
|
const result = await requestCode(pluginId);
|
|
22138
|
-
if (!result) {
|
|
22227
|
+
if (!result.ok) {
|
|
22139
22228
|
spin.stop("Failed");
|
|
22140
|
-
|
|
22229
|
+
if (result.reason === "rate-limited") {
|
|
22230
|
+
showError(
|
|
22231
|
+
`Server is rate-limiting this request (HTTP 429). Retry in ${result.retryAfterSeconds}s.`
|
|
22232
|
+
);
|
|
22233
|
+
} else if (result.reason === "timeout") {
|
|
22234
|
+
showError("Server took too long to respond. Check your connection and try again.");
|
|
22235
|
+
} else if (result.reason === "http") {
|
|
22236
|
+
showError(`Server returned HTTP ${result.status}. Try again later.`);
|
|
22237
|
+
} else {
|
|
22238
|
+
showError("Could not reach the server. Check your connection and try again.");
|
|
22239
|
+
}
|
|
22141
22240
|
process.exit(1);
|
|
22142
22241
|
}
|
|
22143
22242
|
spin.stop("Got pairing code");
|
|
@@ -22266,7 +22365,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
22266
22365
|
|
|
22267
22366
|
// src/commands/pair-auto.ts
|
|
22268
22367
|
var fs33 = __toESM(require("fs"));
|
|
22269
|
-
var
|
|
22368
|
+
var os27 = __toESM(require("os"));
|
|
22270
22369
|
var import_crypto7 = require("crypto");
|
|
22271
22370
|
|
|
22272
22371
|
// src/commands/start-infra-only.ts
|
|
@@ -22434,12 +22533,12 @@ function readTokenFromArgs(args2) {
|
|
|
22434
22533
|
}
|
|
22435
22534
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
22436
22535
|
if (fileFlag) {
|
|
22437
|
-
const
|
|
22536
|
+
const path46 = fileFlag.slice("--token-file=".length);
|
|
22438
22537
|
try {
|
|
22439
|
-
const content = fs33.readFileSync(
|
|
22440
|
-
if (content.length === 0) fail(`--token-file ${
|
|
22538
|
+
const content = fs33.readFileSync(path46, "utf8").trim();
|
|
22539
|
+
if (content.length === 0) fail(`--token-file ${path46} is empty`);
|
|
22441
22540
|
try {
|
|
22442
|
-
fs33.unlinkSync(
|
|
22541
|
+
fs33.unlinkSync(path46);
|
|
22443
22542
|
} catch {
|
|
22444
22543
|
}
|
|
22445
22544
|
return content;
|
|
@@ -22465,7 +22564,7 @@ async function claimOnce(token, pluginId) {
|
|
|
22465
22564
|
pluginId,
|
|
22466
22565
|
ideName: "codeam-cli (codespace)",
|
|
22467
22566
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
22468
|
-
hostname:
|
|
22567
|
+
hostname: os27.hostname(),
|
|
22469
22568
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
22470
22569
|
// Current git branch of the codespace's working directory, so the
|
|
22471
22570
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -22705,7 +22804,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
|
|
|
22705
22804
|
var import_child_process16 = require("child_process");
|
|
22706
22805
|
var import_util4 = require("util");
|
|
22707
22806
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
22708
|
-
var
|
|
22807
|
+
var path40 = __toESM(require("path"));
|
|
22709
22808
|
var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
|
|
22710
22809
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
22711
22810
|
function resetStdinForChild() {
|
|
@@ -23194,7 +23293,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23194
23293
|
});
|
|
23195
23294
|
}
|
|
23196
23295
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23197
|
-
const remoteDir =
|
|
23296
|
+
const remoteDir = path40.posix.dirname(remotePath);
|
|
23198
23297
|
const parts = [
|
|
23199
23298
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
23200
23299
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -23264,7 +23363,7 @@ function shellQuote(s) {
|
|
|
23264
23363
|
// src/services/providers/gitpod.ts
|
|
23265
23364
|
var import_child_process17 = require("child_process");
|
|
23266
23365
|
var import_util5 = require("util");
|
|
23267
|
-
var
|
|
23366
|
+
var path41 = __toESM(require("path"));
|
|
23268
23367
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
23269
23368
|
var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
|
|
23270
23369
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -23504,7 +23603,7 @@ var GitpodProvider = class {
|
|
|
23504
23603
|
});
|
|
23505
23604
|
}
|
|
23506
23605
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23507
|
-
const remoteDir =
|
|
23606
|
+
const remoteDir = path41.posix.dirname(remotePath);
|
|
23508
23607
|
const parts = [
|
|
23509
23608
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
23510
23609
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -23540,7 +23639,7 @@ function shellQuote2(s) {
|
|
|
23540
23639
|
// src/services/providers/gitlab-workspaces.ts
|
|
23541
23640
|
var import_child_process18 = require("child_process");
|
|
23542
23641
|
var import_util6 = require("util");
|
|
23543
|
-
var
|
|
23642
|
+
var path42 = __toESM(require("path"));
|
|
23544
23643
|
var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
|
|
23545
23644
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
23546
23645
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -23800,7 +23899,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23800
23899
|
}
|
|
23801
23900
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23802
23901
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
23803
|
-
const remoteDir =
|
|
23902
|
+
const remoteDir = path42.posix.dirname(remotePath);
|
|
23804
23903
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
23805
23904
|
if (options.mode != null) {
|
|
23806
23905
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -23868,7 +23967,7 @@ function shellQuote3(s) {
|
|
|
23868
23967
|
// src/services/providers/railway.ts
|
|
23869
23968
|
var import_child_process19 = require("child_process");
|
|
23870
23969
|
var import_util7 = require("util");
|
|
23871
|
-
var
|
|
23970
|
+
var path43 = __toESM(require("path"));
|
|
23872
23971
|
var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
|
|
23873
23972
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
23874
23973
|
function resetStdinForChild4() {
|
|
@@ -24104,7 +24203,7 @@ var RailwayProvider = class {
|
|
|
24104
24203
|
if (!projectId || !serviceId) {
|
|
24105
24204
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
24106
24205
|
}
|
|
24107
|
-
const remoteDir =
|
|
24206
|
+
const remoteDir = path43.posix.dirname(remotePath);
|
|
24108
24207
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
24109
24208
|
if (options.mode != null) {
|
|
24110
24209
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -24648,7 +24747,7 @@ var import_node_dns = require("dns");
|
|
|
24648
24747
|
var import_node_util4 = require("util");
|
|
24649
24748
|
var import_node_crypto8 = require("crypto");
|
|
24650
24749
|
var fs34 = __toESM(require("fs"));
|
|
24651
|
-
var
|
|
24750
|
+
var path44 = __toESM(require("path"));
|
|
24652
24751
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
24653
24752
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
24654
24753
|
async function checkDns(apiBase) {
|
|
@@ -24704,10 +24803,10 @@ async function checkHealth(apiBase) {
|
|
|
24704
24803
|
}
|
|
24705
24804
|
}
|
|
24706
24805
|
function checkConfigDir() {
|
|
24707
|
-
const dir =
|
|
24806
|
+
const dir = path44.join(require("os").homedir(), ".codeam");
|
|
24708
24807
|
try {
|
|
24709
24808
|
fs34.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
24710
|
-
const probe =
|
|
24809
|
+
const probe = path44.join(dir, ".doctor-probe");
|
|
24711
24810
|
fs34.writeFileSync(probe, "ok", { mode: 384 });
|
|
24712
24811
|
const read = fs34.readFileSync(probe, "utf8");
|
|
24713
24812
|
fs34.unlinkSync(probe);
|
|
@@ -24750,9 +24849,9 @@ function checkSessions() {
|
|
|
24750
24849
|
}
|
|
24751
24850
|
}
|
|
24752
24851
|
function checkAgentBinaries() {
|
|
24753
|
-
const
|
|
24852
|
+
const os29 = createOsStrategy();
|
|
24754
24853
|
return getEnabledAgents().map((meta) => {
|
|
24755
|
-
const found =
|
|
24854
|
+
const found = os29.findInPath(meta.binaryName);
|
|
24756
24855
|
return {
|
|
24757
24856
|
id: `agent-${meta.id}`,
|
|
24758
24857
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -24774,7 +24873,7 @@ function checkNodePty() {
|
|
|
24774
24873
|
detail: "not required on this platform"
|
|
24775
24874
|
};
|
|
24776
24875
|
}
|
|
24777
|
-
const vendoredPath =
|
|
24876
|
+
const vendoredPath = path44.join(__dirname, "vendor", "node-pty");
|
|
24778
24877
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
24779
24878
|
try {
|
|
24780
24879
|
require(target);
|
|
@@ -24816,7 +24915,7 @@ function checkChokidar() {
|
|
|
24816
24915
|
}
|
|
24817
24916
|
async function doctor(args2 = []) {
|
|
24818
24917
|
const json = args2.includes("--json");
|
|
24819
|
-
const cliVersion = true ? "2.
|
|
24918
|
+
const cliVersion = true ? "2.32.1" : "0.0.0-dev";
|
|
24820
24919
|
const apiBase = resolveApiBaseUrl();
|
|
24821
24920
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
24822
24921
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -25015,7 +25114,7 @@ async function completion(args2) {
|
|
|
25015
25114
|
// src/commands/version.ts
|
|
25016
25115
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
25017
25116
|
function version2() {
|
|
25018
|
-
const v = true ? "2.
|
|
25117
|
+
const v = true ? "2.32.1" : "unknown";
|
|
25019
25118
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
25020
25119
|
}
|
|
25021
25120
|
|
|
@@ -25144,8 +25243,8 @@ var _subcommandHelpKeys = Object.keys(HELPS);
|
|
|
25144
25243
|
|
|
25145
25244
|
// src/lib/updateNotifier.ts
|
|
25146
25245
|
var fs35 = __toESM(require("fs"));
|
|
25147
|
-
var
|
|
25148
|
-
var
|
|
25246
|
+
var os28 = __toESM(require("os"));
|
|
25247
|
+
var path45 = __toESM(require("path"));
|
|
25149
25248
|
var https8 = __toESM(require("https"));
|
|
25150
25249
|
var import_node_child_process12 = require("child_process");
|
|
25151
25250
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
@@ -25154,8 +25253,8 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
25154
25253
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
25155
25254
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
25156
25255
|
function cachePath() {
|
|
25157
|
-
const dir =
|
|
25158
|
-
return
|
|
25256
|
+
const dir = path45.join(os28.homedir(), ".codeam");
|
|
25257
|
+
return path45.join(dir, "update-check.json");
|
|
25159
25258
|
}
|
|
25160
25259
|
function readCache() {
|
|
25161
25260
|
try {
|
|
@@ -25170,7 +25269,7 @@ function readCache() {
|
|
|
25170
25269
|
function writeCache(cache) {
|
|
25171
25270
|
try {
|
|
25172
25271
|
const file = cachePath();
|
|
25173
|
-
fs35.mkdirSync(
|
|
25272
|
+
fs35.mkdirSync(path45.dirname(file), { recursive: true });
|
|
25174
25273
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
25175
25274
|
fs35.writeFileSync(tmp, JSON.stringify(cache));
|
|
25176
25275
|
fs35.renameSync(tmp, file);
|
|
@@ -25247,7 +25346,7 @@ function isLinkedInstall() {
|
|
|
25247
25346
|
timeout: 2e3
|
|
25248
25347
|
}).trim();
|
|
25249
25348
|
if (!root) return false;
|
|
25250
|
-
const pkgPath =
|
|
25349
|
+
const pkgPath = path45.join(root, PKG_NAME);
|
|
25251
25350
|
return fs35.lstatSync(pkgPath).isSymbolicLink();
|
|
25252
25351
|
} catch {
|
|
25253
25352
|
return false;
|
|
@@ -25301,7 +25400,7 @@ function checkForUpdates() {
|
|
|
25301
25400
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
25302
25401
|
if (process.env.CI) return;
|
|
25303
25402
|
if (!process.stdout.isTTY) return;
|
|
25304
|
-
const current = true ? "2.
|
|
25403
|
+
const current = true ? "2.32.1" : null;
|
|
25305
25404
|
if (!current) return;
|
|
25306
25405
|
const cache = readCache();
|
|
25307
25406
|
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.
|
|
3
|
+
"version": "2.32.1",
|
|
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",
|