codeam-cli 2.31.0 → 2.32.0
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 +269 -178
- 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.0",
|
|
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.0" : "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.`
|
|
@@ -12051,6 +12076,9 @@ var import_node_crypto7 = require("crypto");
|
|
|
12051
12076
|
// src/agents/acp/client.ts
|
|
12052
12077
|
var import_node_child_process11 = require("child_process");
|
|
12053
12078
|
var fs21 = __toESM(require("fs/promises"));
|
|
12079
|
+
var fsSync = __toESM(require("fs"));
|
|
12080
|
+
var os22 = __toESM(require("os"));
|
|
12081
|
+
var path26 = __toESM(require("path"));
|
|
12054
12082
|
var import_node_stream = require("stream");
|
|
12055
12083
|
|
|
12056
12084
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -14529,13 +14557,14 @@ var AcpClient = class {
|
|
|
14529
14557
|
async start() {
|
|
14530
14558
|
if (this.child) throw new Error("AcpClient already started");
|
|
14531
14559
|
const { adapter, cwd } = this.opts;
|
|
14560
|
+
const augmentedPath = expandPathForAgentBinaries(process.env.PATH ?? "");
|
|
14532
14561
|
log.info(
|
|
14533
14562
|
"acpClient",
|
|
14534
14563
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
14535
14564
|
);
|
|
14536
14565
|
const child = (0, import_node_child_process11.spawn)(adapter.command, adapter.args, {
|
|
14537
14566
|
cwd,
|
|
14538
|
-
env: process.env,
|
|
14567
|
+
env: { ...process.env, PATH: augmentedPath },
|
|
14539
14568
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14540
14569
|
});
|
|
14541
14570
|
this.child = child;
|
|
@@ -14812,6 +14841,48 @@ function applyLineRange(content, line, limit) {
|
|
|
14812
14841
|
const end = limit !== null ? start2 + limit : lines.length;
|
|
14813
14842
|
return { content: lines.slice(start2, end).join("\n") };
|
|
14814
14843
|
}
|
|
14844
|
+
function knownAgentBinaryDirs() {
|
|
14845
|
+
const home = os22.homedir();
|
|
14846
|
+
const out2 = [];
|
|
14847
|
+
out2.push("/tmp/codeam-node20/bin");
|
|
14848
|
+
for (const root of [
|
|
14849
|
+
"/usr/local/share/nvm/versions/node",
|
|
14850
|
+
path26.join(home, ".nvm/versions/node")
|
|
14851
|
+
]) {
|
|
14852
|
+
try {
|
|
14853
|
+
for (const child of fsSync.readdirSync(root)) {
|
|
14854
|
+
out2.push(path26.join(root, child, "bin"));
|
|
14855
|
+
}
|
|
14856
|
+
} catch {
|
|
14857
|
+
}
|
|
14858
|
+
}
|
|
14859
|
+
out2.push(path26.join(home, ".volta/bin"));
|
|
14860
|
+
out2.push("/usr/local/bin");
|
|
14861
|
+
out2.push("/usr/bin");
|
|
14862
|
+
out2.push(path26.join(home, ".local/bin"));
|
|
14863
|
+
out2.push(path26.join(home, "bin"));
|
|
14864
|
+
return out2.filter((p2) => {
|
|
14865
|
+
try {
|
|
14866
|
+
return fsSync.statSync(p2).isDirectory();
|
|
14867
|
+
} catch {
|
|
14868
|
+
return false;
|
|
14869
|
+
}
|
|
14870
|
+
});
|
|
14871
|
+
}
|
|
14872
|
+
function expandPathForAgentBinaries(existingPath) {
|
|
14873
|
+
const existing = new Set(
|
|
14874
|
+
existingPath.split(path26.delimiter).filter((p2) => p2.length > 0)
|
|
14875
|
+
);
|
|
14876
|
+
const additions = [];
|
|
14877
|
+
for (const dir of knownAgentBinaryDirs()) {
|
|
14878
|
+
if (!existing.has(dir)) {
|
|
14879
|
+
additions.push(dir);
|
|
14880
|
+
existing.add(dir);
|
|
14881
|
+
}
|
|
14882
|
+
}
|
|
14883
|
+
if (additions.length === 0) return existingPath;
|
|
14884
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path26.delimiter);
|
|
14885
|
+
}
|
|
14815
14886
|
|
|
14816
14887
|
// src/services/streaming/transport.ts
|
|
14817
14888
|
var http3 = __toESM(require("http"));
|
|
@@ -15597,8 +15668,8 @@ function extractSelectPrompt(text) {
|
|
|
15597
15668
|
|
|
15598
15669
|
// src/commands/start/handlers.ts
|
|
15599
15670
|
var fs29 = __toESM(require("fs"));
|
|
15600
|
-
var
|
|
15601
|
-
var
|
|
15671
|
+
var os24 = __toESM(require("os"));
|
|
15672
|
+
var path35 = __toESM(require("path"));
|
|
15602
15673
|
var import_crypto3 = require("crypto");
|
|
15603
15674
|
var import_child_process12 = require("child_process");
|
|
15604
15675
|
|
|
@@ -15723,7 +15794,7 @@ function parsePayload2(schema, raw) {
|
|
|
15723
15794
|
|
|
15724
15795
|
// src/services/file-ops.service.ts
|
|
15725
15796
|
var fs22 = __toESM(require("fs/promises"));
|
|
15726
|
-
var
|
|
15797
|
+
var path28 = __toESM(require("path"));
|
|
15727
15798
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
15728
15799
|
var MAX_WALK_DEPTH = 6;
|
|
15729
15800
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -15758,8 +15829,8 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
15758
15829
|
"__pycache__"
|
|
15759
15830
|
]);
|
|
15760
15831
|
function isUnder(parent, candidate) {
|
|
15761
|
-
const rel =
|
|
15762
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
15832
|
+
const rel = path28.relative(parent, candidate);
|
|
15833
|
+
return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
|
|
15763
15834
|
}
|
|
15764
15835
|
async function isExistingFile(absPath) {
|
|
15765
15836
|
try {
|
|
@@ -15782,7 +15853,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
15782
15853
|
}
|
|
15783
15854
|
for (const e of entries) {
|
|
15784
15855
|
if (!e.isFile()) continue;
|
|
15785
|
-
const full =
|
|
15856
|
+
const full = path28.join(dir, e.name);
|
|
15786
15857
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
15787
15858
|
ctx.matches.push(full);
|
|
15788
15859
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -15792,21 +15863,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
15792
15863
|
if (!e.isDirectory()) continue;
|
|
15793
15864
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
15794
15865
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
15795
|
-
await walkForSuffix(
|
|
15866
|
+
await walkForSuffix(path28.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
15796
15867
|
if (ctx.matches.length >= ctx.cap) return;
|
|
15797
15868
|
}
|
|
15798
15869
|
}
|
|
15799
15870
|
async function findFile(rawPath) {
|
|
15800
15871
|
const cwd = process.cwd();
|
|
15801
|
-
if (
|
|
15802
|
-
const abs =
|
|
15872
|
+
if (path28.isAbsolute(rawPath)) {
|
|
15873
|
+
const abs = path28.normalize(rawPath);
|
|
15803
15874
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
15804
15875
|
}
|
|
15805
|
-
const direct =
|
|
15876
|
+
const direct = path28.resolve(cwd, rawPath);
|
|
15806
15877
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
15807
|
-
const normalized =
|
|
15878
|
+
const normalized = path28.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
15808
15879
|
const needles = [
|
|
15809
|
-
`${
|
|
15880
|
+
`${path28.sep}${normalized}`,
|
|
15810
15881
|
`/${normalized}`
|
|
15811
15882
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
15812
15883
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -15820,7 +15891,7 @@ async function findWriteTarget(rawPath) {
|
|
|
15820
15891
|
const found = await findFile(rawPath);
|
|
15821
15892
|
if (found) return found;
|
|
15822
15893
|
const cwd = process.cwd();
|
|
15823
|
-
const fallback =
|
|
15894
|
+
const fallback = path28.isAbsolute(rawPath) ? path28.normalize(rawPath) : path28.resolve(cwd, rawPath);
|
|
15824
15895
|
if (!isUnder(cwd, fallback)) return null;
|
|
15825
15896
|
return fallback;
|
|
15826
15897
|
}
|
|
@@ -15860,7 +15931,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
15860
15931
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
15861
15932
|
return { error: "Content too large." };
|
|
15862
15933
|
}
|
|
15863
|
-
await fs22.mkdir(
|
|
15934
|
+
await fs22.mkdir(path28.dirname(abs), { recursive: true });
|
|
15864
15935
|
await fs22.writeFile(abs, content, "utf-8");
|
|
15865
15936
|
return { ok: true };
|
|
15866
15937
|
} catch (e) {
|
|
@@ -15873,7 +15944,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
15873
15944
|
var import_child_process9 = require("child_process");
|
|
15874
15945
|
var import_util2 = require("util");
|
|
15875
15946
|
var fs23 = __toESM(require("fs/promises"));
|
|
15876
|
-
var
|
|
15947
|
+
var path29 = __toESM(require("path"));
|
|
15877
15948
|
var execFileP3 = (0, import_util2.promisify)(import_child_process9.execFile);
|
|
15878
15949
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
15879
15950
|
"node_modules",
|
|
@@ -15931,12 +16002,12 @@ async function listProjectFiles(opts = {}) {
|
|
|
15931
16002
|
return;
|
|
15932
16003
|
}
|
|
15933
16004
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
15934
|
-
const full =
|
|
16005
|
+
const full = path29.join(dir, e.name);
|
|
15935
16006
|
if (e.isDirectory()) {
|
|
15936
16007
|
if (depth >= 12) continue;
|
|
15937
16008
|
await walk(full, depth + 1);
|
|
15938
16009
|
} else if (e.isFile()) {
|
|
15939
|
-
const rel =
|
|
16010
|
+
const rel = path29.relative(root, full);
|
|
15940
16011
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
15941
16012
|
continue;
|
|
15942
16013
|
}
|
|
@@ -16044,7 +16115,7 @@ async function gitStatus(cwd) {
|
|
|
16044
16115
|
let hasMergeInProgress = false;
|
|
16045
16116
|
try {
|
|
16046
16117
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
16047
|
-
const mergeHead =
|
|
16118
|
+
const mergeHead = path29.isAbsolute(gitDir) ? path29.join(gitDir, "MERGE_HEAD") : path29.join(root, gitDir, "MERGE_HEAD");
|
|
16048
16119
|
await fs23.access(mergeHead);
|
|
16049
16120
|
hasMergeInProgress = true;
|
|
16050
16121
|
} catch {
|
|
@@ -16191,7 +16262,7 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
16191
16262
|
}
|
|
16192
16263
|
let content = "";
|
|
16193
16264
|
try {
|
|
16194
|
-
content = await fs23.readFile(
|
|
16265
|
+
content = await fs23.readFile(path29.join(cwd, f.path), "utf8");
|
|
16195
16266
|
} catch {
|
|
16196
16267
|
continue;
|
|
16197
16268
|
}
|
|
@@ -16216,13 +16287,13 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
16216
16287
|
// src/services/apply-file-review.service.ts
|
|
16217
16288
|
var import_child_process10 = require("child_process");
|
|
16218
16289
|
var fs24 = __toESM(require("fs"));
|
|
16219
|
-
var
|
|
16290
|
+
var path30 = __toESM(require("path"));
|
|
16220
16291
|
async function applyFileReview(workingDir, filePath, action) {
|
|
16221
|
-
if (filePath.includes("..") ||
|
|
16292
|
+
if (filePath.includes("..") || path30.isAbsolute(filePath)) {
|
|
16222
16293
|
return { ok: false, action, filePath, error: "invalid file path" };
|
|
16223
16294
|
}
|
|
16224
|
-
const absFile =
|
|
16225
|
-
const repoRoot = findGitRoot(
|
|
16295
|
+
const absFile = path30.resolve(workingDir, filePath);
|
|
16296
|
+
const repoRoot = findGitRoot(path30.dirname(absFile));
|
|
16226
16297
|
if (!repoRoot) {
|
|
16227
16298
|
return {
|
|
16228
16299
|
ok: false,
|
|
@@ -16231,7 +16302,7 @@ async function applyFileReview(workingDir, filePath, action) {
|
|
|
16231
16302
|
error: `no enclosing git repo for ${filePath}`
|
|
16232
16303
|
};
|
|
16233
16304
|
}
|
|
16234
|
-
const relInRepo =
|
|
16305
|
+
const relInRepo = path30.relative(repoRoot, absFile);
|
|
16235
16306
|
if (!relInRepo || relInRepo.startsWith("..")) {
|
|
16236
16307
|
return { ok: false, action, filePath, error: "path escapes repo root" };
|
|
16237
16308
|
}
|
|
@@ -16280,17 +16351,17 @@ function runGit(cwd, args2) {
|
|
|
16280
16351
|
});
|
|
16281
16352
|
}
|
|
16282
16353
|
function findGitRoot(startDir) {
|
|
16283
|
-
let dir =
|
|
16354
|
+
let dir = path30.resolve(startDir);
|
|
16284
16355
|
const seen = /* @__PURE__ */ new Set();
|
|
16285
16356
|
for (let i = 0; i < 256; i++) {
|
|
16286
16357
|
if (seen.has(dir)) return null;
|
|
16287
16358
|
seen.add(dir);
|
|
16288
16359
|
try {
|
|
16289
|
-
const stat3 = fs24.statSync(
|
|
16360
|
+
const stat3 = fs24.statSync(path30.join(dir, ".git"), { throwIfNoEntry: false });
|
|
16290
16361
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
16291
16362
|
} catch {
|
|
16292
16363
|
}
|
|
16293
|
-
const parent =
|
|
16364
|
+
const parent = path30.dirname(dir);
|
|
16294
16365
|
if (parent === dir) return null;
|
|
16295
16366
|
dir = parent;
|
|
16296
16367
|
}
|
|
@@ -16300,7 +16371,7 @@ function findGitRoot(startDir) {
|
|
|
16300
16371
|
// src/commands/link.ts
|
|
16301
16372
|
var import_node_crypto6 = require("crypto");
|
|
16302
16373
|
var fs25 = __toESM(require("fs"));
|
|
16303
|
-
var
|
|
16374
|
+
var path31 = __toESM(require("path"));
|
|
16304
16375
|
var import_chokidar = __toESM(require("chokidar"));
|
|
16305
16376
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
16306
16377
|
|
|
@@ -16479,7 +16550,7 @@ function parseLinkArgs(args2) {
|
|
|
16479
16550
|
if (apiKeyFileArg) {
|
|
16480
16551
|
const filePath = apiKeyFileArg.slice("--api-key-file=".length);
|
|
16481
16552
|
try {
|
|
16482
|
-
apiKey = fs25.readFileSync(
|
|
16553
|
+
apiKey = fs25.readFileSync(path31.resolve(filePath), "utf8").trim();
|
|
16483
16554
|
} catch (err) {
|
|
16484
16555
|
throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
|
|
16485
16556
|
}
|
|
@@ -16510,9 +16581,19 @@ async function link(args2 = []) {
|
|
|
16510
16581
|
const spin = dist_exports.spinner();
|
|
16511
16582
|
spin.start("Requesting pairing code...");
|
|
16512
16583
|
const pairing = await requestCode(pluginId);
|
|
16513
|
-
if (!pairing) {
|
|
16584
|
+
if (!pairing.ok) {
|
|
16514
16585
|
spin.stop("Failed");
|
|
16515
|
-
|
|
16586
|
+
if (pairing.reason === "rate-limited") {
|
|
16587
|
+
showError(
|
|
16588
|
+
`Server is rate-limiting this request (HTTP 429). Retry in ${pairing.retryAfterSeconds}s.`
|
|
16589
|
+
);
|
|
16590
|
+
} else if (pairing.reason === "timeout") {
|
|
16591
|
+
showError("Server took too long to respond. Check your connection and try again.");
|
|
16592
|
+
} else if (pairing.reason === "http") {
|
|
16593
|
+
showError(`Server returned HTTP ${pairing.status}. Try again later.`);
|
|
16594
|
+
} else {
|
|
16595
|
+
showError("Could not reach the server. Check your connection and try again.");
|
|
16596
|
+
}
|
|
16516
16597
|
process.exit(1);
|
|
16517
16598
|
}
|
|
16518
16599
|
spin.stop("Got pairing code");
|
|
@@ -16573,7 +16654,7 @@ async function link(args2 = []) {
|
|
|
16573
16654
|
return;
|
|
16574
16655
|
}
|
|
16575
16656
|
if (parsed.tokenFile) {
|
|
16576
|
-
const credential = fs25.readFileSync(
|
|
16657
|
+
const credential = fs25.readFileSync(path31.resolve(parsed.tokenFile), "utf8").trim();
|
|
16577
16658
|
if (!credential) {
|
|
16578
16659
|
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
16579
16660
|
process.exit(1);
|
|
@@ -17092,7 +17173,7 @@ function cleanupAttachmentTempFiles() {
|
|
|
17092
17173
|
function saveFilesTemp(files) {
|
|
17093
17174
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
17094
17175
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
17095
|
-
const tmpPath =
|
|
17176
|
+
const tmpPath = path35.join(os24.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
17096
17177
|
fs29.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
17097
17178
|
pendingAttachmentFiles.add(tmpPath);
|
|
17098
17179
|
return tmpPath;
|
|
@@ -18039,8 +18120,8 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
18039
18120
|
// src/services/file-watcher.service.ts
|
|
18040
18121
|
var import_child_process13 = require("child_process");
|
|
18041
18122
|
var fs30 = __toESM(require("fs"));
|
|
18042
|
-
var
|
|
18043
|
-
var
|
|
18123
|
+
var os25 = __toESM(require("os"));
|
|
18124
|
+
var path36 = __toESM(require("path"));
|
|
18044
18125
|
var import_ignore = __toESM(require("ignore"));
|
|
18045
18126
|
|
|
18046
18127
|
// src/services/file-watcher/diff-parser.ts
|
|
@@ -18199,10 +18280,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
18199
18280
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
18200
18281
|
/[\\/]Templates([\\/]|$)/i
|
|
18201
18282
|
];
|
|
18202
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
18283
|
+
function isUnsafeWindowsWatchRoot(dir, homedir21) {
|
|
18203
18284
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
18204
18285
|
const cwd = norm(dir);
|
|
18205
|
-
const home = norm(
|
|
18286
|
+
const home = norm(homedir21);
|
|
18206
18287
|
if (cwd === home) return true;
|
|
18207
18288
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
18208
18289
|
const sysRoots = [
|
|
@@ -18232,18 +18313,18 @@ var _findGitRootSeam = {
|
|
|
18232
18313
|
resolve: _defaultFindGitRoot
|
|
18233
18314
|
};
|
|
18234
18315
|
function _defaultFindGitRoot(startDir) {
|
|
18235
|
-
let dir =
|
|
18316
|
+
let dir = path36.resolve(startDir);
|
|
18236
18317
|
const seen = /* @__PURE__ */ new Set();
|
|
18237
18318
|
for (let i = 0; i < 256; i++) {
|
|
18238
18319
|
if (seen.has(dir)) return null;
|
|
18239
18320
|
seen.add(dir);
|
|
18240
18321
|
try {
|
|
18241
|
-
const gitPath =
|
|
18322
|
+
const gitPath = path36.join(dir, ".git");
|
|
18242
18323
|
const stat3 = fs30.statSync(gitPath, { throwIfNoEntry: false });
|
|
18243
18324
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
18244
18325
|
} catch {
|
|
18245
18326
|
}
|
|
18246
|
-
const parent =
|
|
18327
|
+
const parent = path36.dirname(dir);
|
|
18247
18328
|
if (parent === dir) return null;
|
|
18248
18329
|
dir = parent;
|
|
18249
18330
|
}
|
|
@@ -18301,7 +18382,7 @@ var FileWatcherService = class {
|
|
|
18301
18382
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
18302
18383
|
}
|
|
18303
18384
|
const isWin = process.platform === "win32";
|
|
18304
|
-
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir,
|
|
18385
|
+
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os25.homedir())) {
|
|
18305
18386
|
log.warn(
|
|
18306
18387
|
"fileWatcher",
|
|
18307
18388
|
`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 +18569,7 @@ var FileWatcherService = class {
|
|
|
18488
18569
|
}
|
|
18489
18570
|
async emitForFile(absPath, changeType) {
|
|
18490
18571
|
if (this.stopped) return;
|
|
18491
|
-
const fileDir =
|
|
18572
|
+
const fileDir = path36.dirname(absPath);
|
|
18492
18573
|
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
18493
18574
|
if (gitRoot === void 0) {
|
|
18494
18575
|
gitRoot = findGitRoot2(fileDir);
|
|
@@ -18501,19 +18582,19 @@ var FileWatcherService = class {
|
|
|
18501
18582
|
);
|
|
18502
18583
|
return;
|
|
18503
18584
|
}
|
|
18504
|
-
const relPathInRepo =
|
|
18585
|
+
const relPathInRepo = path36.relative(gitRoot, absPath);
|
|
18505
18586
|
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
18506
18587
|
const matcher = this.getGitIgnoreMatcher(gitRoot);
|
|
18507
18588
|
if (matcher && matcher.ignores(relPathInRepo)) {
|
|
18508
18589
|
log.trace(
|
|
18509
18590
|
"fileWatcher",
|
|
18510
|
-
`${relPathInRepo} ignored by ${
|
|
18591
|
+
`${relPathInRepo} ignored by ${path36.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
|
|
18511
18592
|
);
|
|
18512
18593
|
return;
|
|
18513
18594
|
}
|
|
18514
18595
|
this.opts.onRepoDirty?.(gitRoot);
|
|
18515
|
-
const repoPath =
|
|
18516
|
-
const repoName =
|
|
18596
|
+
const repoPath = path36.relative(this.opts.workingDir, gitRoot);
|
|
18597
|
+
const repoName = path36.basename(gitRoot);
|
|
18517
18598
|
let diffText = "";
|
|
18518
18599
|
let fileStatus = "modified";
|
|
18519
18600
|
if (changeType === "unlink") {
|
|
@@ -18697,16 +18778,16 @@ var FileWatcherService = class {
|
|
|
18697
18778
|
);
|
|
18698
18779
|
if (gitignoreEntry) {
|
|
18699
18780
|
try {
|
|
18700
|
-
const body = fs30.readFileSync(
|
|
18701
|
-
const rel =
|
|
18781
|
+
const body = fs30.readFileSync(path36.join(dir, ".gitignore"), "utf8");
|
|
18782
|
+
const rel = path36.relative(repoRoot, dir).replace(/\\/g, "/");
|
|
18702
18783
|
const prefixed = body.split(/\r?\n/).map((line) => {
|
|
18703
18784
|
const trimmed = line.trim();
|
|
18704
18785
|
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
18705
18786
|
if (!rel) return line;
|
|
18706
18787
|
if (trimmed.startsWith("!")) {
|
|
18707
|
-
return "!" +
|
|
18788
|
+
return "!" + path36.posix.join(rel, trimmed.slice(1));
|
|
18708
18789
|
}
|
|
18709
|
-
return
|
|
18790
|
+
return path36.posix.join(rel, trimmed);
|
|
18710
18791
|
}).join("\n");
|
|
18711
18792
|
matcher.add(prefixed);
|
|
18712
18793
|
} catch {
|
|
@@ -18715,7 +18796,7 @@ var FileWatcherService = class {
|
|
|
18715
18796
|
for (const entry of entries) {
|
|
18716
18797
|
if (!entry.isDirectory()) continue;
|
|
18717
18798
|
if (entry.name === ".git") continue;
|
|
18718
|
-
const childAbs =
|
|
18799
|
+
const childAbs = path36.join(dir, entry.name);
|
|
18719
18800
|
if (isIgnoredFilePath(childAbs)) continue;
|
|
18720
18801
|
this.collectGitignoreFiles(repoRoot, childAbs, matcher);
|
|
18721
18802
|
}
|
|
@@ -18885,7 +18966,7 @@ var import_crypto4 = require("crypto");
|
|
|
18885
18966
|
|
|
18886
18967
|
// src/services/turn-files/git-changeset.ts
|
|
18887
18968
|
var import_child_process14 = require("child_process");
|
|
18888
|
-
var
|
|
18969
|
+
var path37 = __toESM(require("path"));
|
|
18889
18970
|
async function collectRepoChangeset(opts) {
|
|
18890
18971
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
18891
18972
|
if (status2 === null) return null;
|
|
@@ -19015,8 +19096,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19015
19096
|
if (hasGit) {
|
|
19016
19097
|
out2.push({
|
|
19017
19098
|
repoRoot: dir,
|
|
19018
|
-
repoPath:
|
|
19019
|
-
repoName:
|
|
19099
|
+
repoPath: path37.relative(workingDir, dir),
|
|
19100
|
+
repoName: path37.basename(dir)
|
|
19020
19101
|
});
|
|
19021
19102
|
return;
|
|
19022
19103
|
}
|
|
@@ -19024,14 +19105,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19024
19105
|
if (!entry.isDirectory) continue;
|
|
19025
19106
|
if (entry.name === "node_modules") continue;
|
|
19026
19107
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
19027
|
-
await walk(
|
|
19108
|
+
await walk(path37.join(dir, entry.name), depth + 1);
|
|
19028
19109
|
}
|
|
19029
19110
|
}
|
|
19030
19111
|
}
|
|
19031
19112
|
|
|
19032
19113
|
// src/services/turn-files/files-outbox.ts
|
|
19033
19114
|
var fs31 = __toESM(require("fs/promises"));
|
|
19034
|
-
var
|
|
19115
|
+
var path38 = __toESM(require("path"));
|
|
19035
19116
|
var import_os7 = require("os");
|
|
19036
19117
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
19037
19118
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -19064,15 +19145,15 @@ var FilesOutbox = class {
|
|
|
19064
19145
|
backoffIndex = 0;
|
|
19065
19146
|
stopped = false;
|
|
19066
19147
|
constructor(opts) {
|
|
19067
|
-
const base = opts.baseDir ??
|
|
19068
|
-
this.filePath =
|
|
19148
|
+
const base = opts.baseDir ?? path38.join(homeDir(), HOME_OUTBOX_DIR);
|
|
19149
|
+
this.filePath = path38.join(base, `${opts.sessionId}.jsonl`);
|
|
19069
19150
|
this.post = opts.post;
|
|
19070
19151
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
19071
19152
|
}
|
|
19072
19153
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
19073
19154
|
* line is durable on disk (not once the POST succeeds). */
|
|
19074
19155
|
async enqueue(entry) {
|
|
19075
|
-
await fs31.mkdir(
|
|
19156
|
+
await fs31.mkdir(path38.dirname(this.filePath), { recursive: true });
|
|
19076
19157
|
await fs31.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
19077
19158
|
this.backoffIndex = 0;
|
|
19078
19159
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
@@ -20927,8 +21008,8 @@ var OutputService = class _OutputService {
|
|
|
20927
21008
|
|
|
20928
21009
|
// src/services/history.service.ts
|
|
20929
21010
|
var fs32 = __toESM(require("fs"));
|
|
20930
|
-
var
|
|
20931
|
-
var
|
|
21011
|
+
var path39 = __toESM(require("path"));
|
|
21012
|
+
var os26 = __toESM(require("os"));
|
|
20932
21013
|
var https7 = __toESM(require("https"));
|
|
20933
21014
|
var http7 = __toESM(require("http"));
|
|
20934
21015
|
var import_zod2 = require("zod");
|
|
@@ -21090,7 +21171,7 @@ var HistoryService = class _HistoryService {
|
|
|
21090
21171
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
21091
21172
|
}
|
|
21092
21173
|
get projectDir() {
|
|
21093
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
21174
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path39.join(os26.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
21094
21175
|
}
|
|
21095
21176
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
21096
21177
|
setCurrentConversationId(id) {
|
|
@@ -21102,7 +21183,7 @@ var HistoryService = class _HistoryService {
|
|
|
21102
21183
|
/** Return the current message count in the active conversation. */
|
|
21103
21184
|
getCurrentMessageCount() {
|
|
21104
21185
|
if (!this.currentConversationId) return 0;
|
|
21105
|
-
const filePath =
|
|
21186
|
+
const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21106
21187
|
return parseJsonl(filePath).length;
|
|
21107
21188
|
}
|
|
21108
21189
|
/**
|
|
@@ -21113,7 +21194,7 @@ var HistoryService = class _HistoryService {
|
|
|
21113
21194
|
const deadline = Date.now() + timeoutMs;
|
|
21114
21195
|
while (Date.now() < deadline) {
|
|
21115
21196
|
if (!this.currentConversationId) return null;
|
|
21116
|
-
const filePath =
|
|
21197
|
+
const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21117
21198
|
const messages = parseJsonl(filePath);
|
|
21118
21199
|
if (messages.length > previousCount) {
|
|
21119
21200
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -21141,14 +21222,14 @@ var HistoryService = class _HistoryService {
|
|
|
21141
21222
|
try {
|
|
21142
21223
|
const files = fs32.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21143
21224
|
try {
|
|
21144
|
-
const stat3 = fs32.statSync(
|
|
21225
|
+
const stat3 = fs32.statSync(path39.join(dir, e.name));
|
|
21145
21226
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21146
21227
|
} catch {
|
|
21147
21228
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
21148
21229
|
}
|
|
21149
21230
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
21150
21231
|
if (files.length > 0) {
|
|
21151
|
-
this.currentConversationId =
|
|
21232
|
+
this.currentConversationId = path39.basename(files[0].name, ".jsonl");
|
|
21152
21233
|
}
|
|
21153
21234
|
} catch {
|
|
21154
21235
|
}
|
|
@@ -21188,7 +21269,7 @@ var HistoryService = class _HistoryService {
|
|
|
21188
21269
|
}
|
|
21189
21270
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21190
21271
|
try {
|
|
21191
|
-
const stat3 = fs32.statSync(
|
|
21272
|
+
const stat3 = fs32.statSync(path39.join(dir, e.name));
|
|
21192
21273
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21193
21274
|
} catch {
|
|
21194
21275
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -21197,7 +21278,7 @@ var HistoryService = class _HistoryService {
|
|
|
21197
21278
|
if (files.length === 0) return null;
|
|
21198
21279
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
21199
21280
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
21200
|
-
return this.extractUsageFromFile(
|
|
21281
|
+
return this.extractUsageFromFile(path39.join(dir, targetFile));
|
|
21201
21282
|
}
|
|
21202
21283
|
extractUsageFromFile(filePath) {
|
|
21203
21284
|
let raw;
|
|
@@ -21249,7 +21330,7 @@ var HistoryService = class _HistoryService {
|
|
|
21249
21330
|
try {
|
|
21250
21331
|
files = fs32.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
21251
21332
|
try {
|
|
21252
|
-
return fs32.statSync(
|
|
21333
|
+
return fs32.statSync(path39.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
21253
21334
|
} catch {
|
|
21254
21335
|
return false;
|
|
21255
21336
|
}
|
|
@@ -21260,7 +21341,7 @@ var HistoryService = class _HistoryService {
|
|
|
21260
21341
|
for (const file of files) {
|
|
21261
21342
|
let raw;
|
|
21262
21343
|
try {
|
|
21263
|
-
raw = fs32.readFileSync(
|
|
21344
|
+
raw = fs32.readFileSync(path39.join(projectDir, file), "utf8");
|
|
21264
21345
|
} catch {
|
|
21265
21346
|
continue;
|
|
21266
21347
|
}
|
|
@@ -21324,7 +21405,7 @@ var HistoryService = class _HistoryService {
|
|
|
21324
21405
|
* showing an empty conversation.
|
|
21325
21406
|
*/
|
|
21326
21407
|
async loadConversation(sessionId) {
|
|
21327
|
-
const filePath =
|
|
21408
|
+
const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21328
21409
|
const messages = parseJsonl(filePath);
|
|
21329
21410
|
if (messages.length === 0) return;
|
|
21330
21411
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -21378,7 +21459,7 @@ var HistoryService = class _HistoryService {
|
|
|
21378
21459
|
if (!this.currentConversationId) return 0;
|
|
21379
21460
|
}
|
|
21380
21461
|
const sessionId = this.currentConversationId;
|
|
21381
|
-
const filePath =
|
|
21462
|
+
const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21382
21463
|
const messages = parseJsonl(filePath);
|
|
21383
21464
|
if (messages.length === 0) return 0;
|
|
21384
21465
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -22135,9 +22216,19 @@ async function pair(args2 = []) {
|
|
|
22135
22216
|
const spin = dist_exports.spinner();
|
|
22136
22217
|
spin.start("Requesting pairing code...");
|
|
22137
22218
|
const result = await requestCode(pluginId);
|
|
22138
|
-
if (!result) {
|
|
22219
|
+
if (!result.ok) {
|
|
22139
22220
|
spin.stop("Failed");
|
|
22140
|
-
|
|
22221
|
+
if (result.reason === "rate-limited") {
|
|
22222
|
+
showError(
|
|
22223
|
+
`Server is rate-limiting this request (HTTP 429). Retry in ${result.retryAfterSeconds}s.`
|
|
22224
|
+
);
|
|
22225
|
+
} else if (result.reason === "timeout") {
|
|
22226
|
+
showError("Server took too long to respond. Check your connection and try again.");
|
|
22227
|
+
} else if (result.reason === "http") {
|
|
22228
|
+
showError(`Server returned HTTP ${result.status}. Try again later.`);
|
|
22229
|
+
} else {
|
|
22230
|
+
showError("Could not reach the server. Check your connection and try again.");
|
|
22231
|
+
}
|
|
22141
22232
|
process.exit(1);
|
|
22142
22233
|
}
|
|
22143
22234
|
spin.stop("Got pairing code");
|
|
@@ -22266,7 +22357,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
22266
22357
|
|
|
22267
22358
|
// src/commands/pair-auto.ts
|
|
22268
22359
|
var fs33 = __toESM(require("fs"));
|
|
22269
|
-
var
|
|
22360
|
+
var os27 = __toESM(require("os"));
|
|
22270
22361
|
var import_crypto7 = require("crypto");
|
|
22271
22362
|
|
|
22272
22363
|
// src/commands/start-infra-only.ts
|
|
@@ -22434,12 +22525,12 @@ function readTokenFromArgs(args2) {
|
|
|
22434
22525
|
}
|
|
22435
22526
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
22436
22527
|
if (fileFlag) {
|
|
22437
|
-
const
|
|
22528
|
+
const path46 = fileFlag.slice("--token-file=".length);
|
|
22438
22529
|
try {
|
|
22439
|
-
const content = fs33.readFileSync(
|
|
22440
|
-
if (content.length === 0) fail(`--token-file ${
|
|
22530
|
+
const content = fs33.readFileSync(path46, "utf8").trim();
|
|
22531
|
+
if (content.length === 0) fail(`--token-file ${path46} is empty`);
|
|
22441
22532
|
try {
|
|
22442
|
-
fs33.unlinkSync(
|
|
22533
|
+
fs33.unlinkSync(path46);
|
|
22443
22534
|
} catch {
|
|
22444
22535
|
}
|
|
22445
22536
|
return content;
|
|
@@ -22465,7 +22556,7 @@ async function claimOnce(token, pluginId) {
|
|
|
22465
22556
|
pluginId,
|
|
22466
22557
|
ideName: "codeam-cli (codespace)",
|
|
22467
22558
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
22468
|
-
hostname:
|
|
22559
|
+
hostname: os27.hostname(),
|
|
22469
22560
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
22470
22561
|
// Current git branch of the codespace's working directory, so the
|
|
22471
22562
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -22705,7 +22796,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
|
|
|
22705
22796
|
var import_child_process16 = require("child_process");
|
|
22706
22797
|
var import_util4 = require("util");
|
|
22707
22798
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
22708
|
-
var
|
|
22799
|
+
var path40 = __toESM(require("path"));
|
|
22709
22800
|
var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
|
|
22710
22801
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
22711
22802
|
function resetStdinForChild() {
|
|
@@ -23194,7 +23285,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23194
23285
|
});
|
|
23195
23286
|
}
|
|
23196
23287
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23197
|
-
const remoteDir =
|
|
23288
|
+
const remoteDir = path40.posix.dirname(remotePath);
|
|
23198
23289
|
const parts = [
|
|
23199
23290
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
23200
23291
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -23264,7 +23355,7 @@ function shellQuote(s) {
|
|
|
23264
23355
|
// src/services/providers/gitpod.ts
|
|
23265
23356
|
var import_child_process17 = require("child_process");
|
|
23266
23357
|
var import_util5 = require("util");
|
|
23267
|
-
var
|
|
23358
|
+
var path41 = __toESM(require("path"));
|
|
23268
23359
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
23269
23360
|
var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
|
|
23270
23361
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -23504,7 +23595,7 @@ var GitpodProvider = class {
|
|
|
23504
23595
|
});
|
|
23505
23596
|
}
|
|
23506
23597
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23507
|
-
const remoteDir =
|
|
23598
|
+
const remoteDir = path41.posix.dirname(remotePath);
|
|
23508
23599
|
const parts = [
|
|
23509
23600
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
23510
23601
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -23540,7 +23631,7 @@ function shellQuote2(s) {
|
|
|
23540
23631
|
// src/services/providers/gitlab-workspaces.ts
|
|
23541
23632
|
var import_child_process18 = require("child_process");
|
|
23542
23633
|
var import_util6 = require("util");
|
|
23543
|
-
var
|
|
23634
|
+
var path42 = __toESM(require("path"));
|
|
23544
23635
|
var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
|
|
23545
23636
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
23546
23637
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -23800,7 +23891,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23800
23891
|
}
|
|
23801
23892
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23802
23893
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
23803
|
-
const remoteDir =
|
|
23894
|
+
const remoteDir = path42.posix.dirname(remotePath);
|
|
23804
23895
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
23805
23896
|
if (options.mode != null) {
|
|
23806
23897
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -23868,7 +23959,7 @@ function shellQuote3(s) {
|
|
|
23868
23959
|
// src/services/providers/railway.ts
|
|
23869
23960
|
var import_child_process19 = require("child_process");
|
|
23870
23961
|
var import_util7 = require("util");
|
|
23871
|
-
var
|
|
23962
|
+
var path43 = __toESM(require("path"));
|
|
23872
23963
|
var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
|
|
23873
23964
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
23874
23965
|
function resetStdinForChild4() {
|
|
@@ -24104,7 +24195,7 @@ var RailwayProvider = class {
|
|
|
24104
24195
|
if (!projectId || !serviceId) {
|
|
24105
24196
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
24106
24197
|
}
|
|
24107
|
-
const remoteDir =
|
|
24198
|
+
const remoteDir = path43.posix.dirname(remotePath);
|
|
24108
24199
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
24109
24200
|
if (options.mode != null) {
|
|
24110
24201
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -24648,7 +24739,7 @@ var import_node_dns = require("dns");
|
|
|
24648
24739
|
var import_node_util4 = require("util");
|
|
24649
24740
|
var import_node_crypto8 = require("crypto");
|
|
24650
24741
|
var fs34 = __toESM(require("fs"));
|
|
24651
|
-
var
|
|
24742
|
+
var path44 = __toESM(require("path"));
|
|
24652
24743
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
24653
24744
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
24654
24745
|
async function checkDns(apiBase) {
|
|
@@ -24704,10 +24795,10 @@ async function checkHealth(apiBase) {
|
|
|
24704
24795
|
}
|
|
24705
24796
|
}
|
|
24706
24797
|
function checkConfigDir() {
|
|
24707
|
-
const dir =
|
|
24798
|
+
const dir = path44.join(require("os").homedir(), ".codeam");
|
|
24708
24799
|
try {
|
|
24709
24800
|
fs34.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
24710
|
-
const probe =
|
|
24801
|
+
const probe = path44.join(dir, ".doctor-probe");
|
|
24711
24802
|
fs34.writeFileSync(probe, "ok", { mode: 384 });
|
|
24712
24803
|
const read = fs34.readFileSync(probe, "utf8");
|
|
24713
24804
|
fs34.unlinkSync(probe);
|
|
@@ -24750,9 +24841,9 @@ function checkSessions() {
|
|
|
24750
24841
|
}
|
|
24751
24842
|
}
|
|
24752
24843
|
function checkAgentBinaries() {
|
|
24753
|
-
const
|
|
24844
|
+
const os29 = createOsStrategy();
|
|
24754
24845
|
return getEnabledAgents().map((meta) => {
|
|
24755
|
-
const found =
|
|
24846
|
+
const found = os29.findInPath(meta.binaryName);
|
|
24756
24847
|
return {
|
|
24757
24848
|
id: `agent-${meta.id}`,
|
|
24758
24849
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -24774,7 +24865,7 @@ function checkNodePty() {
|
|
|
24774
24865
|
detail: "not required on this platform"
|
|
24775
24866
|
};
|
|
24776
24867
|
}
|
|
24777
|
-
const vendoredPath =
|
|
24868
|
+
const vendoredPath = path44.join(__dirname, "vendor", "node-pty");
|
|
24778
24869
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
24779
24870
|
try {
|
|
24780
24871
|
require(target);
|
|
@@ -24816,7 +24907,7 @@ function checkChokidar() {
|
|
|
24816
24907
|
}
|
|
24817
24908
|
async function doctor(args2 = []) {
|
|
24818
24909
|
const json = args2.includes("--json");
|
|
24819
|
-
const cliVersion = true ? "2.
|
|
24910
|
+
const cliVersion = true ? "2.32.0" : "0.0.0-dev";
|
|
24820
24911
|
const apiBase = resolveApiBaseUrl();
|
|
24821
24912
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
24822
24913
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -25015,7 +25106,7 @@ async function completion(args2) {
|
|
|
25015
25106
|
// src/commands/version.ts
|
|
25016
25107
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
25017
25108
|
function version2() {
|
|
25018
|
-
const v = true ? "2.
|
|
25109
|
+
const v = true ? "2.32.0" : "unknown";
|
|
25019
25110
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
25020
25111
|
}
|
|
25021
25112
|
|
|
@@ -25144,8 +25235,8 @@ var _subcommandHelpKeys = Object.keys(HELPS);
|
|
|
25144
25235
|
|
|
25145
25236
|
// src/lib/updateNotifier.ts
|
|
25146
25237
|
var fs35 = __toESM(require("fs"));
|
|
25147
|
-
var
|
|
25148
|
-
var
|
|
25238
|
+
var os28 = __toESM(require("os"));
|
|
25239
|
+
var path45 = __toESM(require("path"));
|
|
25149
25240
|
var https8 = __toESM(require("https"));
|
|
25150
25241
|
var import_node_child_process12 = require("child_process");
|
|
25151
25242
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
@@ -25154,8 +25245,8 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
25154
25245
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
25155
25246
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
25156
25247
|
function cachePath() {
|
|
25157
|
-
const dir =
|
|
25158
|
-
return
|
|
25248
|
+
const dir = path45.join(os28.homedir(), ".codeam");
|
|
25249
|
+
return path45.join(dir, "update-check.json");
|
|
25159
25250
|
}
|
|
25160
25251
|
function readCache() {
|
|
25161
25252
|
try {
|
|
@@ -25170,7 +25261,7 @@ function readCache() {
|
|
|
25170
25261
|
function writeCache(cache) {
|
|
25171
25262
|
try {
|
|
25172
25263
|
const file = cachePath();
|
|
25173
|
-
fs35.mkdirSync(
|
|
25264
|
+
fs35.mkdirSync(path45.dirname(file), { recursive: true });
|
|
25174
25265
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
25175
25266
|
fs35.writeFileSync(tmp, JSON.stringify(cache));
|
|
25176
25267
|
fs35.renameSync(tmp, file);
|
|
@@ -25247,7 +25338,7 @@ function isLinkedInstall() {
|
|
|
25247
25338
|
timeout: 2e3
|
|
25248
25339
|
}).trim();
|
|
25249
25340
|
if (!root) return false;
|
|
25250
|
-
const pkgPath =
|
|
25341
|
+
const pkgPath = path45.join(root, PKG_NAME);
|
|
25251
25342
|
return fs35.lstatSync(pkgPath).isSymbolicLink();
|
|
25252
25343
|
} catch {
|
|
25253
25344
|
return false;
|
|
@@ -25301,7 +25392,7 @@ function checkForUpdates() {
|
|
|
25301
25392
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
25302
25393
|
if (process.env.CI) return;
|
|
25303
25394
|
if (!process.stdout.isTTY) return;
|
|
25304
|
-
const current = true ? "2.
|
|
25395
|
+
const current = true ? "2.32.0" : null;
|
|
25305
25396
|
if (!current) return;
|
|
25306
25397
|
const cache = readCache();
|
|
25307
25398
|
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.0",
|
|
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",
|