codeam-cli 2.30.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 +19 -0
- package/dist/index.js +272 -191
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ 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
|
+
|
|
13
|
+
## [2.30.0] — 2026-06-06
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **vsc-plugin:** Banner recommends update when marketplace ships a fix
|
|
18
|
+
- **jetbrains-plugin:** Banner recommends update when marketplace ships a fix
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **cli:** Forward mobile image attachments to ACP as image blocks (QA #290)
|
|
23
|
+
- **cli, vsc-plugin:** Echo mobile prompts + clear Reconnecting UX (QA #287/#291)
|
|
24
|
+
- **cli:** Replace pair pollStatus with SSE pair_completed event (QA #285)
|
|
25
|
+
|
|
7
26
|
## [2.29.0] — 2026-06-06
|
|
8
27
|
|
|
9
28
|
### 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",
|
|
@@ -685,7 +685,7 @@ var _execSeam = {
|
|
|
685
685
|
// src/services/pairing.service.ts
|
|
686
686
|
var API_BASE = resolveApiBaseUrl();
|
|
687
687
|
var REQUEST_CODE_TIMEOUT_MS = 1e4;
|
|
688
|
-
async function requestCode(pluginId
|
|
688
|
+
async function requestCode(pluginId) {
|
|
689
689
|
try {
|
|
690
690
|
const runtime = process.env.CODESPACES === "true" ? "github-codespaces" : "local";
|
|
691
691
|
const codespaceName = process.env.CODESPACE_NAME;
|
|
@@ -697,12 +697,7 @@ async function requestCode(pluginId, options = {}) {
|
|
|
697
697
|
hostname: os2.hostname(),
|
|
698
698
|
runtime,
|
|
699
699
|
branch,
|
|
700
|
-
...codespaceName ? { codespaceName } : {}
|
|
701
|
-
...options.originatorSessionId && options.originatorPluginId && options.originatorAuthToken ? {
|
|
702
|
-
originatorSessionId: options.originatorSessionId,
|
|
703
|
-
originatorPluginId: options.originatorPluginId,
|
|
704
|
-
originatorAuthToken: options.originatorAuthToken
|
|
705
|
-
} : {}
|
|
700
|
+
...codespaceName ? { codespaceName } : {}
|
|
706
701
|
});
|
|
707
702
|
let timer;
|
|
708
703
|
const timeoutSentinel = /* @__PURE__ */ Symbol("request-code-timeout");
|
|
@@ -711,12 +706,27 @@ async function requestCode(pluginId, options = {}) {
|
|
|
711
706
|
});
|
|
712
707
|
const result = await Promise.race([post2, timeoutPromise]);
|
|
713
708
|
clearTimeout(timer);
|
|
714
|
-
if (result === timeoutSentinel) return
|
|
709
|
+
if (result === timeoutSentinel) return { ok: false, reason: "timeout" };
|
|
715
710
|
const data = result?.data;
|
|
716
|
-
if (!data?.code) return
|
|
717
|
-
return {
|
|
718
|
-
|
|
719
|
-
|
|
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" };
|
|
720
730
|
}
|
|
721
731
|
}
|
|
722
732
|
async function fetchCurrentPluginAuthToken(sessionId, pluginId) {
|
|
@@ -862,9 +872,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
862
872
|
});
|
|
863
873
|
res.on("end", () => {
|
|
864
874
|
if (res.statusCode && res.statusCode >= 400) {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
875
|
+
reject(
|
|
876
|
+
makeHttpError(res.statusCode, res.headers["retry-after"], responseBody)
|
|
877
|
+
);
|
|
868
878
|
return;
|
|
869
879
|
}
|
|
870
880
|
try {
|
|
@@ -884,6 +894,16 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
884
894
|
req.end();
|
|
885
895
|
});
|
|
886
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
|
+
}
|
|
887
907
|
async function _postJson(url, body) {
|
|
888
908
|
return new Promise((resolve6, reject) => {
|
|
889
909
|
const data = JSON.stringify(body);
|
|
@@ -910,7 +930,7 @@ async function _postJson(url, body) {
|
|
|
910
930
|
});
|
|
911
931
|
res.on("end", () => {
|
|
912
932
|
if (res.statusCode && res.statusCode >= 400) {
|
|
913
|
-
reject(
|
|
933
|
+
reject(makeHttpError(res.statusCode, res.headers["retry-after"], body2));
|
|
914
934
|
return;
|
|
915
935
|
}
|
|
916
936
|
try {
|
|
@@ -951,7 +971,7 @@ async function _getJson(url) {
|
|
|
951
971
|
});
|
|
952
972
|
res.on("end", () => {
|
|
953
973
|
if (res.statusCode && res.statusCode >= 400) {
|
|
954
|
-
reject(
|
|
974
|
+
reject(makeHttpError(res.statusCode, res.headers["retry-after"], body));
|
|
955
975
|
return;
|
|
956
976
|
}
|
|
957
977
|
try {
|
|
@@ -1135,8 +1155,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
1135
1155
|
return decodedFile;
|
|
1136
1156
|
};
|
|
1137
1157
|
}
|
|
1138
|
-
function normalizeWindowsPath(
|
|
1139
|
-
return
|
|
1158
|
+
function normalizeWindowsPath(path46) {
|
|
1159
|
+
return path46.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
1140
1160
|
}
|
|
1141
1161
|
|
|
1142
1162
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3616,9 +3636,9 @@ async function addSourceContext(frames) {
|
|
|
3616
3636
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3617
3637
|
return frames;
|
|
3618
3638
|
}
|
|
3619
|
-
function getContextLinesFromFile(
|
|
3639
|
+
function getContextLinesFromFile(path46, ranges, output) {
|
|
3620
3640
|
return new Promise((resolve6) => {
|
|
3621
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3641
|
+
const stream = (0, import_node_fs.createReadStream)(path46);
|
|
3622
3642
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3623
3643
|
input: stream
|
|
3624
3644
|
});
|
|
@@ -3633,7 +3653,7 @@ function getContextLinesFromFile(path45, ranges, output) {
|
|
|
3633
3653
|
let rangeStart = range[0];
|
|
3634
3654
|
let rangeEnd = range[1];
|
|
3635
3655
|
function onStreamError() {
|
|
3636
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3656
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path46, 1);
|
|
3637
3657
|
lineReaded.close();
|
|
3638
3658
|
lineReaded.removeAllListeners();
|
|
3639
3659
|
destroyStreamAndResolve();
|
|
@@ -3694,8 +3714,8 @@ function clearLineContext(frame) {
|
|
|
3694
3714
|
delete frame.context_line;
|
|
3695
3715
|
delete frame.post_context;
|
|
3696
3716
|
}
|
|
3697
|
-
function shouldSkipContextLinesForFile(
|
|
3698
|
-
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:");
|
|
3699
3719
|
}
|
|
3700
3720
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3701
3721
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5849,7 +5869,7 @@ function readAnonId() {
|
|
|
5849
5869
|
}
|
|
5850
5870
|
function superProperties() {
|
|
5851
5871
|
return {
|
|
5852
|
-
cliVersion: true ? "2.
|
|
5872
|
+
cliVersion: true ? "2.32.0" : "0.0.0-dev",
|
|
5853
5873
|
nodeVersion: process.version,
|
|
5854
5874
|
platform: process.platform,
|
|
5855
5875
|
arch: process.arch,
|
|
@@ -7191,10 +7211,10 @@ function buildForPlatform(platform2) {
|
|
|
7191
7211
|
var import_node_crypto4 = require("crypto");
|
|
7192
7212
|
|
|
7193
7213
|
// src/agents/claude/resolver.ts
|
|
7194
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
7195
|
-
const found =
|
|
7214
|
+
function buildClaudeLaunch(extraArgs = [], os29 = createOsStrategy()) {
|
|
7215
|
+
const found = os29.findInPath("claude") ?? os29.findInPath("claude-code");
|
|
7196
7216
|
if (!found) return null;
|
|
7197
|
-
return
|
|
7217
|
+
return os29.buildLaunch(found, extraArgs);
|
|
7198
7218
|
}
|
|
7199
7219
|
|
|
7200
7220
|
// src/agents/claude/installer.ts
|
|
@@ -9921,13 +9941,13 @@ function detectStartupBanner(lines) {
|
|
|
9921
9941
|
while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
|
|
9922
9942
|
if (metaIdx - artStart < 2) return null;
|
|
9923
9943
|
const pathLine = (lines[metaIdx + 1] ?? "").trim();
|
|
9924
|
-
const
|
|
9944
|
+
const path46 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
|
|
9925
9945
|
return {
|
|
9926
9946
|
title: "",
|
|
9927
9947
|
subtitle: lines[metaIdx].trim(),
|
|
9928
|
-
path:
|
|
9948
|
+
path: path46,
|
|
9929
9949
|
startIdx: artStart,
|
|
9930
|
-
endIdx: metaIdx + (
|
|
9950
|
+
endIdx: metaIdx + (path46 ? 1 : 0)
|
|
9931
9951
|
};
|
|
9932
9952
|
}
|
|
9933
9953
|
|
|
@@ -9937,8 +9957,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9937
9957
|
meta = getAgent("claude");
|
|
9938
9958
|
mode = "interactive";
|
|
9939
9959
|
os;
|
|
9940
|
-
constructor(
|
|
9941
|
-
this.os =
|
|
9960
|
+
constructor(os29) {
|
|
9961
|
+
this.os = os29;
|
|
9942
9962
|
}
|
|
9943
9963
|
/**
|
|
9944
9964
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -10946,8 +10966,8 @@ function codexCredentialLocator() {
|
|
|
10946
10966
|
function codexLoginLauncher() {
|
|
10947
10967
|
return {
|
|
10948
10968
|
async ensureInstalled() {
|
|
10949
|
-
const
|
|
10950
|
-
return
|
|
10969
|
+
const os29 = createOsStrategy();
|
|
10970
|
+
return os29.findInPath("codex") !== null;
|
|
10951
10971
|
},
|
|
10952
10972
|
launch() {
|
|
10953
10973
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -10970,8 +10990,8 @@ var CodexRuntimeStrategy = class {
|
|
|
10970
10990
|
meta = getAgent("codex");
|
|
10971
10991
|
mode = "interactive";
|
|
10972
10992
|
os;
|
|
10973
|
-
constructor(
|
|
10974
|
-
this.os =
|
|
10993
|
+
constructor(os29) {
|
|
10994
|
+
this.os = os29;
|
|
10975
10995
|
}
|
|
10976
10996
|
async prepareLaunch() {
|
|
10977
10997
|
let binary = this.os.findInPath("codex");
|
|
@@ -11077,12 +11097,12 @@ var CodexRuntimeStrategy = class {
|
|
|
11077
11097
|
});
|
|
11078
11098
|
}
|
|
11079
11099
|
};
|
|
11080
|
-
function resolveNpm(
|
|
11081
|
-
return
|
|
11100
|
+
function resolveNpm(os29) {
|
|
11101
|
+
return os29.id === "win32" ? "npm.cmd" : "npm";
|
|
11082
11102
|
}
|
|
11083
|
-
async function installCodexViaNpm(
|
|
11103
|
+
async function installCodexViaNpm(os29) {
|
|
11084
11104
|
return new Promise((resolve6, reject) => {
|
|
11085
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
11105
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os29), ["install", "-g", "@openai/codex"], {
|
|
11086
11106
|
stdio: "inherit"
|
|
11087
11107
|
});
|
|
11088
11108
|
proc.on("close", (code) => {
|
|
@@ -11099,16 +11119,16 @@ async function installCodexViaNpm(os28) {
|
|
|
11099
11119
|
});
|
|
11100
11120
|
});
|
|
11101
11121
|
}
|
|
11102
|
-
function augmentNpmGlobalBin(
|
|
11122
|
+
function augmentNpmGlobalBin(os29) {
|
|
11103
11123
|
try {
|
|
11104
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
11124
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os29), ["prefix", "-g"], {
|
|
11105
11125
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11106
11126
|
});
|
|
11107
11127
|
if (result.status !== 0) return;
|
|
11108
11128
|
const prefix = result.stdout.toString().trim();
|
|
11109
11129
|
if (!prefix) return;
|
|
11110
|
-
const binDir =
|
|
11111
|
-
|
|
11130
|
+
const binDir = os29.id === "win32" ? prefix : path17.join(prefix, "bin");
|
|
11131
|
+
os29.augmentPath([binDir]);
|
|
11112
11132
|
} catch {
|
|
11113
11133
|
}
|
|
11114
11134
|
}
|
|
@@ -11192,9 +11212,9 @@ var import_node_child_process7 = require("child_process");
|
|
|
11192
11212
|
// src/agents/coderabbit/installer.ts
|
|
11193
11213
|
var import_node_child_process5 = require("child_process");
|
|
11194
11214
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
11195
|
-
async function ensureCoderabbitInstalled(
|
|
11196
|
-
if (
|
|
11197
|
-
if (
|
|
11215
|
+
async function ensureCoderabbitInstalled(os29) {
|
|
11216
|
+
if (os29.findInPath("coderabbit")) return true;
|
|
11217
|
+
if (os29.id === "win32") {
|
|
11198
11218
|
console.error(
|
|
11199
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"
|
|
11200
11220
|
);
|
|
@@ -11209,8 +11229,8 @@ async function ensureCoderabbitInstalled(os28) {
|
|
|
11209
11229
|
proc.on("error", () => resolve6(false));
|
|
11210
11230
|
});
|
|
11211
11231
|
if (!ok) return false;
|
|
11212
|
-
|
|
11213
|
-
return
|
|
11232
|
+
os29.augmentPath([`${os29.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
11233
|
+
return os29.findInPath("coderabbit") !== null;
|
|
11214
11234
|
}
|
|
11215
11235
|
|
|
11216
11236
|
// src/agents/coderabbit/link.ts
|
|
@@ -11237,10 +11257,10 @@ function coderabbitCredentialLocator() {
|
|
|
11237
11257
|
extract: extractLocalCoderabbitToken
|
|
11238
11258
|
};
|
|
11239
11259
|
}
|
|
11240
|
-
function coderabbitLoginLauncher(
|
|
11260
|
+
function coderabbitLoginLauncher(os29) {
|
|
11241
11261
|
return {
|
|
11242
11262
|
async ensureInstalled() {
|
|
11243
|
-
return ensureCoderabbitInstalled(
|
|
11263
|
+
return ensureCoderabbitInstalled(os29);
|
|
11244
11264
|
},
|
|
11245
11265
|
launch() {
|
|
11246
11266
|
return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
@@ -11263,11 +11283,11 @@ function parseReview(stdout) {
|
|
|
11263
11283
|
for (const line of lines) {
|
|
11264
11284
|
const m = line.match(HUNK_LINE_RE);
|
|
11265
11285
|
if (!m) continue;
|
|
11266
|
-
const [,
|
|
11267
|
-
if (!
|
|
11286
|
+
const [, path46, lineNo, sevToken, message] = m;
|
|
11287
|
+
if (!path46 || !lineNo || !message) continue;
|
|
11268
11288
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
11269
11289
|
hunks.push({
|
|
11270
|
-
path:
|
|
11290
|
+
path: path46.trim(),
|
|
11271
11291
|
line: Number(lineNo),
|
|
11272
11292
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
11273
11293
|
message: cleanedMessage
|
|
@@ -11286,8 +11306,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
11286
11306
|
meta = getAgent("coderabbit");
|
|
11287
11307
|
mode = "batch";
|
|
11288
11308
|
os;
|
|
11289
|
-
constructor(
|
|
11290
|
-
this.os =
|
|
11309
|
+
constructor(os29) {
|
|
11310
|
+
this.os = os29;
|
|
11291
11311
|
}
|
|
11292
11312
|
getDefaultArgs() {
|
|
11293
11313
|
return ["review"];
|
|
@@ -11402,10 +11422,10 @@ function cursorCredentialLocator() {
|
|
|
11402
11422
|
extract: extractLocalCursorToken
|
|
11403
11423
|
};
|
|
11404
11424
|
}
|
|
11405
|
-
function cursorLoginLauncher(
|
|
11425
|
+
function cursorLoginLauncher(os29) {
|
|
11406
11426
|
return {
|
|
11407
11427
|
async ensureInstalled() {
|
|
11408
|
-
if (
|
|
11428
|
+
if (os29.findInPath("cursor-agent")) return true;
|
|
11409
11429
|
console.error(
|
|
11410
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"
|
|
11411
11431
|
);
|
|
@@ -11467,8 +11487,8 @@ var CursorRuntimeStrategy = class {
|
|
|
11467
11487
|
meta = getAgent("cursor");
|
|
11468
11488
|
mode = "interactive";
|
|
11469
11489
|
os;
|
|
11470
|
-
constructor(
|
|
11471
|
-
this.os =
|
|
11490
|
+
constructor(os29) {
|
|
11491
|
+
this.os = os29;
|
|
11472
11492
|
}
|
|
11473
11493
|
async prepareLaunch() {
|
|
11474
11494
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -11588,10 +11608,10 @@ function aiderCredentialLocator() {
|
|
|
11588
11608
|
extract: extractLocalAiderToken
|
|
11589
11609
|
};
|
|
11590
11610
|
}
|
|
11591
|
-
function aiderLoginLauncher(
|
|
11611
|
+
function aiderLoginLauncher(os29) {
|
|
11592
11612
|
return {
|
|
11593
11613
|
async ensureInstalled() {
|
|
11594
|
-
if (
|
|
11614
|
+
if (os29.findInPath("aider")) return true;
|
|
11595
11615
|
console.error(
|
|
11596
11616
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
11597
11617
|
);
|
|
@@ -11601,7 +11621,7 @@ function aiderLoginLauncher(os28) {
|
|
|
11601
11621
|
console.error(
|
|
11602
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"
|
|
11603
11623
|
);
|
|
11604
|
-
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"], {
|
|
11605
11625
|
stdio: "ignore"
|
|
11606
11626
|
});
|
|
11607
11627
|
}
|
|
@@ -11673,8 +11693,8 @@ var AiderRuntimeStrategy = class {
|
|
|
11673
11693
|
meta = getAgent("aider");
|
|
11674
11694
|
mode = "interactive";
|
|
11675
11695
|
os;
|
|
11676
|
-
constructor(
|
|
11677
|
-
this.os =
|
|
11696
|
+
constructor(os29) {
|
|
11697
|
+
this.os = os29;
|
|
11678
11698
|
}
|
|
11679
11699
|
async prepareLaunch() {
|
|
11680
11700
|
const binary = this.os.findInPath("aider");
|
|
@@ -11797,8 +11817,8 @@ function geminiCredentialLocator() {
|
|
|
11797
11817
|
function geminiLoginLauncher() {
|
|
11798
11818
|
return {
|
|
11799
11819
|
async ensureInstalled() {
|
|
11800
|
-
const
|
|
11801
|
-
return
|
|
11820
|
+
const os29 = createOsStrategy();
|
|
11821
|
+
return os29.findInPath("gemini") !== null;
|
|
11802
11822
|
},
|
|
11803
11823
|
launch() {
|
|
11804
11824
|
return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -11831,8 +11851,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
11831
11851
|
meta = getAgent("gemini");
|
|
11832
11852
|
mode = "interactive";
|
|
11833
11853
|
os;
|
|
11834
|
-
constructor(
|
|
11835
|
-
this.os =
|
|
11854
|
+
constructor(os29) {
|
|
11855
|
+
this.os = os29;
|
|
11836
11856
|
}
|
|
11837
11857
|
async prepareLaunch() {
|
|
11838
11858
|
const binary = this.os.findInPath("gemini");
|
|
@@ -11932,18 +11952,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
11932
11952
|
|
|
11933
11953
|
// src/agents/registry.ts
|
|
11934
11954
|
var runtimeBuilders = {
|
|
11935
|
-
claude: (
|
|
11936
|
-
codex: (
|
|
11937
|
-
coderabbit: (
|
|
11938
|
-
cursor: (
|
|
11939
|
-
aider: (
|
|
11940
|
-
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)
|
|
11941
11961
|
};
|
|
11942
11962
|
var deployBuilders = {
|
|
11943
11963
|
claude: () => new ClaudeDeployStrategy(),
|
|
11944
11964
|
codex: () => new CodexDeployStrategy()
|
|
11945
11965
|
};
|
|
11946
|
-
function createAgentStrategy(agent,
|
|
11966
|
+
function createAgentStrategy(agent, os29 = createOsStrategy()) {
|
|
11947
11967
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
11948
11968
|
throw new Error(
|
|
11949
11969
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -11953,10 +11973,10 @@ function createAgentStrategy(agent, os28 = createOsStrategy()) {
|
|
|
11953
11973
|
if (!build) {
|
|
11954
11974
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
11955
11975
|
}
|
|
11956
|
-
return build(
|
|
11976
|
+
return build(os29);
|
|
11957
11977
|
}
|
|
11958
|
-
function createInteractiveAgentStrategy(agent,
|
|
11959
|
-
const s = createAgentStrategy(agent,
|
|
11978
|
+
function createInteractiveAgentStrategy(agent, os29 = createOsStrategy()) {
|
|
11979
|
+
const s = createAgentStrategy(agent, os29);
|
|
11960
11980
|
if (s.mode !== "interactive") {
|
|
11961
11981
|
throw new Error(
|
|
11962
11982
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -12056,6 +12076,9 @@ var import_node_crypto7 = require("crypto");
|
|
|
12056
12076
|
// src/agents/acp/client.ts
|
|
12057
12077
|
var import_node_child_process11 = require("child_process");
|
|
12058
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"));
|
|
12059
12082
|
var import_node_stream = require("stream");
|
|
12060
12083
|
|
|
12061
12084
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -14534,13 +14557,14 @@ var AcpClient = class {
|
|
|
14534
14557
|
async start() {
|
|
14535
14558
|
if (this.child) throw new Error("AcpClient already started");
|
|
14536
14559
|
const { adapter, cwd } = this.opts;
|
|
14560
|
+
const augmentedPath = expandPathForAgentBinaries(process.env.PATH ?? "");
|
|
14537
14561
|
log.info(
|
|
14538
14562
|
"acpClient",
|
|
14539
14563
|
`spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
|
|
14540
14564
|
);
|
|
14541
14565
|
const child = (0, import_node_child_process11.spawn)(adapter.command, adapter.args, {
|
|
14542
14566
|
cwd,
|
|
14543
|
-
env: process.env,
|
|
14567
|
+
env: { ...process.env, PATH: augmentedPath },
|
|
14544
14568
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14545
14569
|
});
|
|
14546
14570
|
this.child = child;
|
|
@@ -14817,6 +14841,48 @@ function applyLineRange(content, line, limit) {
|
|
|
14817
14841
|
const end = limit !== null ? start2 + limit : lines.length;
|
|
14818
14842
|
return { content: lines.slice(start2, end).join("\n") };
|
|
14819
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
|
+
}
|
|
14820
14886
|
|
|
14821
14887
|
// src/services/streaming/transport.ts
|
|
14822
14888
|
var http3 = __toESM(require("http"));
|
|
@@ -15602,8 +15668,8 @@ function extractSelectPrompt(text) {
|
|
|
15602
15668
|
|
|
15603
15669
|
// src/commands/start/handlers.ts
|
|
15604
15670
|
var fs29 = __toESM(require("fs"));
|
|
15605
|
-
var
|
|
15606
|
-
var
|
|
15671
|
+
var os24 = __toESM(require("os"));
|
|
15672
|
+
var path35 = __toESM(require("path"));
|
|
15607
15673
|
var import_crypto3 = require("crypto");
|
|
15608
15674
|
var import_child_process12 = require("child_process");
|
|
15609
15675
|
|
|
@@ -15728,7 +15794,7 @@ function parsePayload2(schema, raw) {
|
|
|
15728
15794
|
|
|
15729
15795
|
// src/services/file-ops.service.ts
|
|
15730
15796
|
var fs22 = __toESM(require("fs/promises"));
|
|
15731
|
-
var
|
|
15797
|
+
var path28 = __toESM(require("path"));
|
|
15732
15798
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
15733
15799
|
var MAX_WALK_DEPTH = 6;
|
|
15734
15800
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -15763,8 +15829,8 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
15763
15829
|
"__pycache__"
|
|
15764
15830
|
]);
|
|
15765
15831
|
function isUnder(parent, candidate) {
|
|
15766
|
-
const rel =
|
|
15767
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
15832
|
+
const rel = path28.relative(parent, candidate);
|
|
15833
|
+
return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
|
|
15768
15834
|
}
|
|
15769
15835
|
async function isExistingFile(absPath) {
|
|
15770
15836
|
try {
|
|
@@ -15787,7 +15853,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
15787
15853
|
}
|
|
15788
15854
|
for (const e of entries) {
|
|
15789
15855
|
if (!e.isFile()) continue;
|
|
15790
|
-
const full =
|
|
15856
|
+
const full = path28.join(dir, e.name);
|
|
15791
15857
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
15792
15858
|
ctx.matches.push(full);
|
|
15793
15859
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -15797,21 +15863,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
15797
15863
|
if (!e.isDirectory()) continue;
|
|
15798
15864
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
15799
15865
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
15800
|
-
await walkForSuffix(
|
|
15866
|
+
await walkForSuffix(path28.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
15801
15867
|
if (ctx.matches.length >= ctx.cap) return;
|
|
15802
15868
|
}
|
|
15803
15869
|
}
|
|
15804
15870
|
async function findFile(rawPath) {
|
|
15805
15871
|
const cwd = process.cwd();
|
|
15806
|
-
if (
|
|
15807
|
-
const abs =
|
|
15872
|
+
if (path28.isAbsolute(rawPath)) {
|
|
15873
|
+
const abs = path28.normalize(rawPath);
|
|
15808
15874
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
15809
15875
|
}
|
|
15810
|
-
const direct =
|
|
15876
|
+
const direct = path28.resolve(cwd, rawPath);
|
|
15811
15877
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
15812
|
-
const normalized =
|
|
15878
|
+
const normalized = path28.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
15813
15879
|
const needles = [
|
|
15814
|
-
`${
|
|
15880
|
+
`${path28.sep}${normalized}`,
|
|
15815
15881
|
`/${normalized}`
|
|
15816
15882
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
15817
15883
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -15825,7 +15891,7 @@ async function findWriteTarget(rawPath) {
|
|
|
15825
15891
|
const found = await findFile(rawPath);
|
|
15826
15892
|
if (found) return found;
|
|
15827
15893
|
const cwd = process.cwd();
|
|
15828
|
-
const fallback =
|
|
15894
|
+
const fallback = path28.isAbsolute(rawPath) ? path28.normalize(rawPath) : path28.resolve(cwd, rawPath);
|
|
15829
15895
|
if (!isUnder(cwd, fallback)) return null;
|
|
15830
15896
|
return fallback;
|
|
15831
15897
|
}
|
|
@@ -15865,7 +15931,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
15865
15931
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
15866
15932
|
return { error: "Content too large." };
|
|
15867
15933
|
}
|
|
15868
|
-
await fs22.mkdir(
|
|
15934
|
+
await fs22.mkdir(path28.dirname(abs), { recursive: true });
|
|
15869
15935
|
await fs22.writeFile(abs, content, "utf-8");
|
|
15870
15936
|
return { ok: true };
|
|
15871
15937
|
} catch (e) {
|
|
@@ -15878,7 +15944,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
15878
15944
|
var import_child_process9 = require("child_process");
|
|
15879
15945
|
var import_util2 = require("util");
|
|
15880
15946
|
var fs23 = __toESM(require("fs/promises"));
|
|
15881
|
-
var
|
|
15947
|
+
var path29 = __toESM(require("path"));
|
|
15882
15948
|
var execFileP3 = (0, import_util2.promisify)(import_child_process9.execFile);
|
|
15883
15949
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
15884
15950
|
"node_modules",
|
|
@@ -15936,12 +16002,12 @@ async function listProjectFiles(opts = {}) {
|
|
|
15936
16002
|
return;
|
|
15937
16003
|
}
|
|
15938
16004
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
15939
|
-
const full =
|
|
16005
|
+
const full = path29.join(dir, e.name);
|
|
15940
16006
|
if (e.isDirectory()) {
|
|
15941
16007
|
if (depth >= 12) continue;
|
|
15942
16008
|
await walk(full, depth + 1);
|
|
15943
16009
|
} else if (e.isFile()) {
|
|
15944
|
-
const rel =
|
|
16010
|
+
const rel = path29.relative(root, full);
|
|
15945
16011
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
15946
16012
|
continue;
|
|
15947
16013
|
}
|
|
@@ -16049,7 +16115,7 @@ async function gitStatus(cwd) {
|
|
|
16049
16115
|
let hasMergeInProgress = false;
|
|
16050
16116
|
try {
|
|
16051
16117
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
16052
|
-
const mergeHead =
|
|
16118
|
+
const mergeHead = path29.isAbsolute(gitDir) ? path29.join(gitDir, "MERGE_HEAD") : path29.join(root, gitDir, "MERGE_HEAD");
|
|
16053
16119
|
await fs23.access(mergeHead);
|
|
16054
16120
|
hasMergeInProgress = true;
|
|
16055
16121
|
} catch {
|
|
@@ -16196,7 +16262,7 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
16196
16262
|
}
|
|
16197
16263
|
let content = "";
|
|
16198
16264
|
try {
|
|
16199
|
-
content = await fs23.readFile(
|
|
16265
|
+
content = await fs23.readFile(path29.join(cwd, f.path), "utf8");
|
|
16200
16266
|
} catch {
|
|
16201
16267
|
continue;
|
|
16202
16268
|
}
|
|
@@ -16221,13 +16287,13 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
16221
16287
|
// src/services/apply-file-review.service.ts
|
|
16222
16288
|
var import_child_process10 = require("child_process");
|
|
16223
16289
|
var fs24 = __toESM(require("fs"));
|
|
16224
|
-
var
|
|
16290
|
+
var path30 = __toESM(require("path"));
|
|
16225
16291
|
async function applyFileReview(workingDir, filePath, action) {
|
|
16226
|
-
if (filePath.includes("..") ||
|
|
16292
|
+
if (filePath.includes("..") || path30.isAbsolute(filePath)) {
|
|
16227
16293
|
return { ok: false, action, filePath, error: "invalid file path" };
|
|
16228
16294
|
}
|
|
16229
|
-
const absFile =
|
|
16230
|
-
const repoRoot = findGitRoot(
|
|
16295
|
+
const absFile = path30.resolve(workingDir, filePath);
|
|
16296
|
+
const repoRoot = findGitRoot(path30.dirname(absFile));
|
|
16231
16297
|
if (!repoRoot) {
|
|
16232
16298
|
return {
|
|
16233
16299
|
ok: false,
|
|
@@ -16236,7 +16302,7 @@ async function applyFileReview(workingDir, filePath, action) {
|
|
|
16236
16302
|
error: `no enclosing git repo for ${filePath}`
|
|
16237
16303
|
};
|
|
16238
16304
|
}
|
|
16239
|
-
const relInRepo =
|
|
16305
|
+
const relInRepo = path30.relative(repoRoot, absFile);
|
|
16240
16306
|
if (!relInRepo || relInRepo.startsWith("..")) {
|
|
16241
16307
|
return { ok: false, action, filePath, error: "path escapes repo root" };
|
|
16242
16308
|
}
|
|
@@ -16285,17 +16351,17 @@ function runGit(cwd, args2) {
|
|
|
16285
16351
|
});
|
|
16286
16352
|
}
|
|
16287
16353
|
function findGitRoot(startDir) {
|
|
16288
|
-
let dir =
|
|
16354
|
+
let dir = path30.resolve(startDir);
|
|
16289
16355
|
const seen = /* @__PURE__ */ new Set();
|
|
16290
16356
|
for (let i = 0; i < 256; i++) {
|
|
16291
16357
|
if (seen.has(dir)) return null;
|
|
16292
16358
|
seen.add(dir);
|
|
16293
16359
|
try {
|
|
16294
|
-
const stat3 = fs24.statSync(
|
|
16360
|
+
const stat3 = fs24.statSync(path30.join(dir, ".git"), { throwIfNoEntry: false });
|
|
16295
16361
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
16296
16362
|
} catch {
|
|
16297
16363
|
}
|
|
16298
|
-
const parent =
|
|
16364
|
+
const parent = path30.dirname(dir);
|
|
16299
16365
|
if (parent === dir) return null;
|
|
16300
16366
|
dir = parent;
|
|
16301
16367
|
}
|
|
@@ -16305,7 +16371,7 @@ function findGitRoot(startDir) {
|
|
|
16305
16371
|
// src/commands/link.ts
|
|
16306
16372
|
var import_node_crypto6 = require("crypto");
|
|
16307
16373
|
var fs25 = __toESM(require("fs"));
|
|
16308
|
-
var
|
|
16374
|
+
var path31 = __toESM(require("path"));
|
|
16309
16375
|
var import_chokidar = __toESM(require("chokidar"));
|
|
16310
16376
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
16311
16377
|
|
|
@@ -16484,7 +16550,7 @@ function parseLinkArgs(args2) {
|
|
|
16484
16550
|
if (apiKeyFileArg) {
|
|
16485
16551
|
const filePath = apiKeyFileArg.slice("--api-key-file=".length);
|
|
16486
16552
|
try {
|
|
16487
|
-
apiKey = fs25.readFileSync(
|
|
16553
|
+
apiKey = fs25.readFileSync(path31.resolve(filePath), "utf8").trim();
|
|
16488
16554
|
} catch (err) {
|
|
16489
16555
|
throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
|
|
16490
16556
|
}
|
|
@@ -16514,15 +16580,20 @@ async function link(args2 = []) {
|
|
|
16514
16580
|
const pluginId = (0, import_node_crypto6.randomUUID)();
|
|
16515
16581
|
const spin = dist_exports.spinner();
|
|
16516
16582
|
spin.start("Requesting pairing code...");
|
|
16517
|
-
const
|
|
16518
|
-
|
|
16519
|
-
originatorSessionId: originator?.id,
|
|
16520
|
-
originatorPluginId: originator?.pluginId,
|
|
16521
|
-
originatorAuthToken: originator?.pluginAuthToken
|
|
16522
|
-
});
|
|
16523
|
-
if (!pairing) {
|
|
16583
|
+
const pairing = await requestCode(pluginId);
|
|
16584
|
+
if (!pairing.ok) {
|
|
16524
16585
|
spin.stop("Failed");
|
|
16525
|
-
|
|
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
|
+
}
|
|
16526
16597
|
process.exit(1);
|
|
16527
16598
|
}
|
|
16528
16599
|
spin.stop("Got pairing code");
|
|
@@ -16583,7 +16654,7 @@ async function link(args2 = []) {
|
|
|
16583
16654
|
return;
|
|
16584
16655
|
}
|
|
16585
16656
|
if (parsed.tokenFile) {
|
|
16586
|
-
const credential = fs25.readFileSync(
|
|
16657
|
+
const credential = fs25.readFileSync(path31.resolve(parsed.tokenFile), "utf8").trim();
|
|
16587
16658
|
if (!credential) {
|
|
16588
16659
|
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
16589
16660
|
process.exit(1);
|
|
@@ -17102,7 +17173,7 @@ function cleanupAttachmentTempFiles() {
|
|
|
17102
17173
|
function saveFilesTemp(files) {
|
|
17103
17174
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
17104
17175
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
17105
|
-
const tmpPath =
|
|
17176
|
+
const tmpPath = path35.join(os24.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
17106
17177
|
fs29.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
17107
17178
|
pendingAttachmentFiles.add(tmpPath);
|
|
17108
17179
|
return tmpPath;
|
|
@@ -18049,8 +18120,8 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
18049
18120
|
// src/services/file-watcher.service.ts
|
|
18050
18121
|
var import_child_process13 = require("child_process");
|
|
18051
18122
|
var fs30 = __toESM(require("fs"));
|
|
18052
|
-
var
|
|
18053
|
-
var
|
|
18123
|
+
var os25 = __toESM(require("os"));
|
|
18124
|
+
var path36 = __toESM(require("path"));
|
|
18054
18125
|
var import_ignore = __toESM(require("ignore"));
|
|
18055
18126
|
|
|
18056
18127
|
// src/services/file-watcher/diff-parser.ts
|
|
@@ -18209,10 +18280,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
18209
18280
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
18210
18281
|
/[\\/]Templates([\\/]|$)/i
|
|
18211
18282
|
];
|
|
18212
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
18283
|
+
function isUnsafeWindowsWatchRoot(dir, homedir21) {
|
|
18213
18284
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
18214
18285
|
const cwd = norm(dir);
|
|
18215
|
-
const home = norm(
|
|
18286
|
+
const home = norm(homedir21);
|
|
18216
18287
|
if (cwd === home) return true;
|
|
18217
18288
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
18218
18289
|
const sysRoots = [
|
|
@@ -18242,18 +18313,18 @@ var _findGitRootSeam = {
|
|
|
18242
18313
|
resolve: _defaultFindGitRoot
|
|
18243
18314
|
};
|
|
18244
18315
|
function _defaultFindGitRoot(startDir) {
|
|
18245
|
-
let dir =
|
|
18316
|
+
let dir = path36.resolve(startDir);
|
|
18246
18317
|
const seen = /* @__PURE__ */ new Set();
|
|
18247
18318
|
for (let i = 0; i < 256; i++) {
|
|
18248
18319
|
if (seen.has(dir)) return null;
|
|
18249
18320
|
seen.add(dir);
|
|
18250
18321
|
try {
|
|
18251
|
-
const gitPath =
|
|
18322
|
+
const gitPath = path36.join(dir, ".git");
|
|
18252
18323
|
const stat3 = fs30.statSync(gitPath, { throwIfNoEntry: false });
|
|
18253
18324
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
18254
18325
|
} catch {
|
|
18255
18326
|
}
|
|
18256
|
-
const parent =
|
|
18327
|
+
const parent = path36.dirname(dir);
|
|
18257
18328
|
if (parent === dir) return null;
|
|
18258
18329
|
dir = parent;
|
|
18259
18330
|
}
|
|
@@ -18311,7 +18382,7 @@ var FileWatcherService = class {
|
|
|
18311
18382
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
18312
18383
|
}
|
|
18313
18384
|
const isWin = process.platform === "win32";
|
|
18314
|
-
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir,
|
|
18385
|
+
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os25.homedir())) {
|
|
18315
18386
|
log.warn(
|
|
18316
18387
|
"fileWatcher",
|
|
18317
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.`
|
|
@@ -18498,7 +18569,7 @@ var FileWatcherService = class {
|
|
|
18498
18569
|
}
|
|
18499
18570
|
async emitForFile(absPath, changeType) {
|
|
18500
18571
|
if (this.stopped) return;
|
|
18501
|
-
const fileDir =
|
|
18572
|
+
const fileDir = path36.dirname(absPath);
|
|
18502
18573
|
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
18503
18574
|
if (gitRoot === void 0) {
|
|
18504
18575
|
gitRoot = findGitRoot2(fileDir);
|
|
@@ -18511,19 +18582,19 @@ var FileWatcherService = class {
|
|
|
18511
18582
|
);
|
|
18512
18583
|
return;
|
|
18513
18584
|
}
|
|
18514
|
-
const relPathInRepo =
|
|
18585
|
+
const relPathInRepo = path36.relative(gitRoot, absPath);
|
|
18515
18586
|
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
18516
18587
|
const matcher = this.getGitIgnoreMatcher(gitRoot);
|
|
18517
18588
|
if (matcher && matcher.ignores(relPathInRepo)) {
|
|
18518
18589
|
log.trace(
|
|
18519
18590
|
"fileWatcher",
|
|
18520
|
-
`${relPathInRepo} ignored by ${
|
|
18591
|
+
`${relPathInRepo} ignored by ${path36.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
|
|
18521
18592
|
);
|
|
18522
18593
|
return;
|
|
18523
18594
|
}
|
|
18524
18595
|
this.opts.onRepoDirty?.(gitRoot);
|
|
18525
|
-
const repoPath =
|
|
18526
|
-
const repoName =
|
|
18596
|
+
const repoPath = path36.relative(this.opts.workingDir, gitRoot);
|
|
18597
|
+
const repoName = path36.basename(gitRoot);
|
|
18527
18598
|
let diffText = "";
|
|
18528
18599
|
let fileStatus = "modified";
|
|
18529
18600
|
if (changeType === "unlink") {
|
|
@@ -18707,16 +18778,16 @@ var FileWatcherService = class {
|
|
|
18707
18778
|
);
|
|
18708
18779
|
if (gitignoreEntry) {
|
|
18709
18780
|
try {
|
|
18710
|
-
const body = fs30.readFileSync(
|
|
18711
|
-
const rel =
|
|
18781
|
+
const body = fs30.readFileSync(path36.join(dir, ".gitignore"), "utf8");
|
|
18782
|
+
const rel = path36.relative(repoRoot, dir).replace(/\\/g, "/");
|
|
18712
18783
|
const prefixed = body.split(/\r?\n/).map((line) => {
|
|
18713
18784
|
const trimmed = line.trim();
|
|
18714
18785
|
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
18715
18786
|
if (!rel) return line;
|
|
18716
18787
|
if (trimmed.startsWith("!")) {
|
|
18717
|
-
return "!" +
|
|
18788
|
+
return "!" + path36.posix.join(rel, trimmed.slice(1));
|
|
18718
18789
|
}
|
|
18719
|
-
return
|
|
18790
|
+
return path36.posix.join(rel, trimmed);
|
|
18720
18791
|
}).join("\n");
|
|
18721
18792
|
matcher.add(prefixed);
|
|
18722
18793
|
} catch {
|
|
@@ -18725,7 +18796,7 @@ var FileWatcherService = class {
|
|
|
18725
18796
|
for (const entry of entries) {
|
|
18726
18797
|
if (!entry.isDirectory()) continue;
|
|
18727
18798
|
if (entry.name === ".git") continue;
|
|
18728
|
-
const childAbs =
|
|
18799
|
+
const childAbs = path36.join(dir, entry.name);
|
|
18729
18800
|
if (isIgnoredFilePath(childAbs)) continue;
|
|
18730
18801
|
this.collectGitignoreFiles(repoRoot, childAbs, matcher);
|
|
18731
18802
|
}
|
|
@@ -18895,7 +18966,7 @@ var import_crypto4 = require("crypto");
|
|
|
18895
18966
|
|
|
18896
18967
|
// src/services/turn-files/git-changeset.ts
|
|
18897
18968
|
var import_child_process14 = require("child_process");
|
|
18898
|
-
var
|
|
18969
|
+
var path37 = __toESM(require("path"));
|
|
18899
18970
|
async function collectRepoChangeset(opts) {
|
|
18900
18971
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
18901
18972
|
if (status2 === null) return null;
|
|
@@ -19025,8 +19096,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19025
19096
|
if (hasGit) {
|
|
19026
19097
|
out2.push({
|
|
19027
19098
|
repoRoot: dir,
|
|
19028
|
-
repoPath:
|
|
19029
|
-
repoName:
|
|
19099
|
+
repoPath: path37.relative(workingDir, dir),
|
|
19100
|
+
repoName: path37.basename(dir)
|
|
19030
19101
|
});
|
|
19031
19102
|
return;
|
|
19032
19103
|
}
|
|
@@ -19034,14 +19105,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19034
19105
|
if (!entry.isDirectory) continue;
|
|
19035
19106
|
if (entry.name === "node_modules") continue;
|
|
19036
19107
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
19037
|
-
await walk(
|
|
19108
|
+
await walk(path37.join(dir, entry.name), depth + 1);
|
|
19038
19109
|
}
|
|
19039
19110
|
}
|
|
19040
19111
|
}
|
|
19041
19112
|
|
|
19042
19113
|
// src/services/turn-files/files-outbox.ts
|
|
19043
19114
|
var fs31 = __toESM(require("fs/promises"));
|
|
19044
|
-
var
|
|
19115
|
+
var path38 = __toESM(require("path"));
|
|
19045
19116
|
var import_os7 = require("os");
|
|
19046
19117
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
19047
19118
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -19074,15 +19145,15 @@ var FilesOutbox = class {
|
|
|
19074
19145
|
backoffIndex = 0;
|
|
19075
19146
|
stopped = false;
|
|
19076
19147
|
constructor(opts) {
|
|
19077
|
-
const base = opts.baseDir ??
|
|
19078
|
-
this.filePath =
|
|
19148
|
+
const base = opts.baseDir ?? path38.join(homeDir(), HOME_OUTBOX_DIR);
|
|
19149
|
+
this.filePath = path38.join(base, `${opts.sessionId}.jsonl`);
|
|
19079
19150
|
this.post = opts.post;
|
|
19080
19151
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
19081
19152
|
}
|
|
19082
19153
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
19083
19154
|
* line is durable on disk (not once the POST succeeds). */
|
|
19084
19155
|
async enqueue(entry) {
|
|
19085
|
-
await fs31.mkdir(
|
|
19156
|
+
await fs31.mkdir(path38.dirname(this.filePath), { recursive: true });
|
|
19086
19157
|
await fs31.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
19087
19158
|
this.backoffIndex = 0;
|
|
19088
19159
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
@@ -20937,8 +21008,8 @@ var OutputService = class _OutputService {
|
|
|
20937
21008
|
|
|
20938
21009
|
// src/services/history.service.ts
|
|
20939
21010
|
var fs32 = __toESM(require("fs"));
|
|
20940
|
-
var
|
|
20941
|
-
var
|
|
21011
|
+
var path39 = __toESM(require("path"));
|
|
21012
|
+
var os26 = __toESM(require("os"));
|
|
20942
21013
|
var https7 = __toESM(require("https"));
|
|
20943
21014
|
var http7 = __toESM(require("http"));
|
|
20944
21015
|
var import_zod2 = require("zod");
|
|
@@ -21100,7 +21171,7 @@ var HistoryService = class _HistoryService {
|
|
|
21100
21171
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
21101
21172
|
}
|
|
21102
21173
|
get projectDir() {
|
|
21103
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
21174
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path39.join(os26.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
21104
21175
|
}
|
|
21105
21176
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
21106
21177
|
setCurrentConversationId(id) {
|
|
@@ -21112,7 +21183,7 @@ var HistoryService = class _HistoryService {
|
|
|
21112
21183
|
/** Return the current message count in the active conversation. */
|
|
21113
21184
|
getCurrentMessageCount() {
|
|
21114
21185
|
if (!this.currentConversationId) return 0;
|
|
21115
|
-
const filePath =
|
|
21186
|
+
const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21116
21187
|
return parseJsonl(filePath).length;
|
|
21117
21188
|
}
|
|
21118
21189
|
/**
|
|
@@ -21123,7 +21194,7 @@ var HistoryService = class _HistoryService {
|
|
|
21123
21194
|
const deadline = Date.now() + timeoutMs;
|
|
21124
21195
|
while (Date.now() < deadline) {
|
|
21125
21196
|
if (!this.currentConversationId) return null;
|
|
21126
|
-
const filePath =
|
|
21197
|
+
const filePath = path39.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21127
21198
|
const messages = parseJsonl(filePath);
|
|
21128
21199
|
if (messages.length > previousCount) {
|
|
21129
21200
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -21151,14 +21222,14 @@ var HistoryService = class _HistoryService {
|
|
|
21151
21222
|
try {
|
|
21152
21223
|
const files = fs32.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21153
21224
|
try {
|
|
21154
|
-
const stat3 = fs32.statSync(
|
|
21225
|
+
const stat3 = fs32.statSync(path39.join(dir, e.name));
|
|
21155
21226
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21156
21227
|
} catch {
|
|
21157
21228
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
21158
21229
|
}
|
|
21159
21230
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
21160
21231
|
if (files.length > 0) {
|
|
21161
|
-
this.currentConversationId =
|
|
21232
|
+
this.currentConversationId = path39.basename(files[0].name, ".jsonl");
|
|
21162
21233
|
}
|
|
21163
21234
|
} catch {
|
|
21164
21235
|
}
|
|
@@ -21198,7 +21269,7 @@ var HistoryService = class _HistoryService {
|
|
|
21198
21269
|
}
|
|
21199
21270
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21200
21271
|
try {
|
|
21201
|
-
const stat3 = fs32.statSync(
|
|
21272
|
+
const stat3 = fs32.statSync(path39.join(dir, e.name));
|
|
21202
21273
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21203
21274
|
} catch {
|
|
21204
21275
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -21207,7 +21278,7 @@ var HistoryService = class _HistoryService {
|
|
|
21207
21278
|
if (files.length === 0) return null;
|
|
21208
21279
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
21209
21280
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
21210
|
-
return this.extractUsageFromFile(
|
|
21281
|
+
return this.extractUsageFromFile(path39.join(dir, targetFile));
|
|
21211
21282
|
}
|
|
21212
21283
|
extractUsageFromFile(filePath) {
|
|
21213
21284
|
let raw;
|
|
@@ -21259,7 +21330,7 @@ var HistoryService = class _HistoryService {
|
|
|
21259
21330
|
try {
|
|
21260
21331
|
files = fs32.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
21261
21332
|
try {
|
|
21262
|
-
return fs32.statSync(
|
|
21333
|
+
return fs32.statSync(path39.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
21263
21334
|
} catch {
|
|
21264
21335
|
return false;
|
|
21265
21336
|
}
|
|
@@ -21270,7 +21341,7 @@ var HistoryService = class _HistoryService {
|
|
|
21270
21341
|
for (const file of files) {
|
|
21271
21342
|
let raw;
|
|
21272
21343
|
try {
|
|
21273
|
-
raw = fs32.readFileSync(
|
|
21344
|
+
raw = fs32.readFileSync(path39.join(projectDir, file), "utf8");
|
|
21274
21345
|
} catch {
|
|
21275
21346
|
continue;
|
|
21276
21347
|
}
|
|
@@ -21334,7 +21405,7 @@ var HistoryService = class _HistoryService {
|
|
|
21334
21405
|
* showing an empty conversation.
|
|
21335
21406
|
*/
|
|
21336
21407
|
async loadConversation(sessionId) {
|
|
21337
|
-
const filePath =
|
|
21408
|
+
const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21338
21409
|
const messages = parseJsonl(filePath);
|
|
21339
21410
|
if (messages.length === 0) return;
|
|
21340
21411
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -21388,7 +21459,7 @@ var HistoryService = class _HistoryService {
|
|
|
21388
21459
|
if (!this.currentConversationId) return 0;
|
|
21389
21460
|
}
|
|
21390
21461
|
const sessionId = this.currentConversationId;
|
|
21391
|
-
const filePath =
|
|
21462
|
+
const filePath = path39.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21392
21463
|
const messages = parseJsonl(filePath);
|
|
21393
21464
|
if (messages.length === 0) return 0;
|
|
21394
21465
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -22145,9 +22216,19 @@ async function pair(args2 = []) {
|
|
|
22145
22216
|
const spin = dist_exports.spinner();
|
|
22146
22217
|
spin.start("Requesting pairing code...");
|
|
22147
22218
|
const result = await requestCode(pluginId);
|
|
22148
|
-
if (!result) {
|
|
22219
|
+
if (!result.ok) {
|
|
22149
22220
|
spin.stop("Failed");
|
|
22150
|
-
|
|
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
|
+
}
|
|
22151
22232
|
process.exit(1);
|
|
22152
22233
|
}
|
|
22153
22234
|
spin.stop("Got pairing code");
|
|
@@ -22276,7 +22357,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
22276
22357
|
|
|
22277
22358
|
// src/commands/pair-auto.ts
|
|
22278
22359
|
var fs33 = __toESM(require("fs"));
|
|
22279
|
-
var
|
|
22360
|
+
var os27 = __toESM(require("os"));
|
|
22280
22361
|
var import_crypto7 = require("crypto");
|
|
22281
22362
|
|
|
22282
22363
|
// src/commands/start-infra-only.ts
|
|
@@ -22444,12 +22525,12 @@ function readTokenFromArgs(args2) {
|
|
|
22444
22525
|
}
|
|
22445
22526
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
22446
22527
|
if (fileFlag) {
|
|
22447
|
-
const
|
|
22528
|
+
const path46 = fileFlag.slice("--token-file=".length);
|
|
22448
22529
|
try {
|
|
22449
|
-
const content = fs33.readFileSync(
|
|
22450
|
-
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`);
|
|
22451
22532
|
try {
|
|
22452
|
-
fs33.unlinkSync(
|
|
22533
|
+
fs33.unlinkSync(path46);
|
|
22453
22534
|
} catch {
|
|
22454
22535
|
}
|
|
22455
22536
|
return content;
|
|
@@ -22475,7 +22556,7 @@ async function claimOnce(token, pluginId) {
|
|
|
22475
22556
|
pluginId,
|
|
22476
22557
|
ideName: "codeam-cli (codespace)",
|
|
22477
22558
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
22478
|
-
hostname:
|
|
22559
|
+
hostname: os27.hostname(),
|
|
22479
22560
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
22480
22561
|
// Current git branch of the codespace's working directory, so the
|
|
22481
22562
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -22715,7 +22796,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
|
|
|
22715
22796
|
var import_child_process16 = require("child_process");
|
|
22716
22797
|
var import_util4 = require("util");
|
|
22717
22798
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
22718
|
-
var
|
|
22799
|
+
var path40 = __toESM(require("path"));
|
|
22719
22800
|
var execFileP5 = (0, import_util4.promisify)(import_child_process16.execFile);
|
|
22720
22801
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
22721
22802
|
function resetStdinForChild() {
|
|
@@ -23204,7 +23285,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23204
23285
|
});
|
|
23205
23286
|
}
|
|
23206
23287
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23207
|
-
const remoteDir =
|
|
23288
|
+
const remoteDir = path40.posix.dirname(remotePath);
|
|
23208
23289
|
const parts = [
|
|
23209
23290
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
23210
23291
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -23274,7 +23355,7 @@ function shellQuote(s) {
|
|
|
23274
23355
|
// src/services/providers/gitpod.ts
|
|
23275
23356
|
var import_child_process17 = require("child_process");
|
|
23276
23357
|
var import_util5 = require("util");
|
|
23277
|
-
var
|
|
23358
|
+
var path41 = __toESM(require("path"));
|
|
23278
23359
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
23279
23360
|
var execFileP6 = (0, import_util5.promisify)(import_child_process17.execFile);
|
|
23280
23361
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -23514,7 +23595,7 @@ var GitpodProvider = class {
|
|
|
23514
23595
|
});
|
|
23515
23596
|
}
|
|
23516
23597
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23517
|
-
const remoteDir =
|
|
23598
|
+
const remoteDir = path41.posix.dirname(remotePath);
|
|
23518
23599
|
const parts = [
|
|
23519
23600
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
23520
23601
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -23550,7 +23631,7 @@ function shellQuote2(s) {
|
|
|
23550
23631
|
// src/services/providers/gitlab-workspaces.ts
|
|
23551
23632
|
var import_child_process18 = require("child_process");
|
|
23552
23633
|
var import_util6 = require("util");
|
|
23553
|
-
var
|
|
23634
|
+
var path42 = __toESM(require("path"));
|
|
23554
23635
|
var execFileP7 = (0, import_util6.promisify)(import_child_process18.execFile);
|
|
23555
23636
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
23556
23637
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -23810,7 +23891,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23810
23891
|
}
|
|
23811
23892
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23812
23893
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
23813
|
-
const remoteDir =
|
|
23894
|
+
const remoteDir = path42.posix.dirname(remotePath);
|
|
23814
23895
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
23815
23896
|
if (options.mode != null) {
|
|
23816
23897
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -23878,7 +23959,7 @@ function shellQuote3(s) {
|
|
|
23878
23959
|
// src/services/providers/railway.ts
|
|
23879
23960
|
var import_child_process19 = require("child_process");
|
|
23880
23961
|
var import_util7 = require("util");
|
|
23881
|
-
var
|
|
23962
|
+
var path43 = __toESM(require("path"));
|
|
23882
23963
|
var execFileP8 = (0, import_util7.promisify)(import_child_process19.execFile);
|
|
23883
23964
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
23884
23965
|
function resetStdinForChild4() {
|
|
@@ -24114,7 +24195,7 @@ var RailwayProvider = class {
|
|
|
24114
24195
|
if (!projectId || !serviceId) {
|
|
24115
24196
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
24116
24197
|
}
|
|
24117
|
-
const remoteDir =
|
|
24198
|
+
const remoteDir = path43.posix.dirname(remotePath);
|
|
24118
24199
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
24119
24200
|
if (options.mode != null) {
|
|
24120
24201
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -24658,7 +24739,7 @@ var import_node_dns = require("dns");
|
|
|
24658
24739
|
var import_node_util4 = require("util");
|
|
24659
24740
|
var import_node_crypto8 = require("crypto");
|
|
24660
24741
|
var fs34 = __toESM(require("fs"));
|
|
24661
|
-
var
|
|
24742
|
+
var path44 = __toESM(require("path"));
|
|
24662
24743
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
24663
24744
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
24664
24745
|
async function checkDns(apiBase) {
|
|
@@ -24714,10 +24795,10 @@ async function checkHealth(apiBase) {
|
|
|
24714
24795
|
}
|
|
24715
24796
|
}
|
|
24716
24797
|
function checkConfigDir() {
|
|
24717
|
-
const dir =
|
|
24798
|
+
const dir = path44.join(require("os").homedir(), ".codeam");
|
|
24718
24799
|
try {
|
|
24719
24800
|
fs34.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
24720
|
-
const probe =
|
|
24801
|
+
const probe = path44.join(dir, ".doctor-probe");
|
|
24721
24802
|
fs34.writeFileSync(probe, "ok", { mode: 384 });
|
|
24722
24803
|
const read = fs34.readFileSync(probe, "utf8");
|
|
24723
24804
|
fs34.unlinkSync(probe);
|
|
@@ -24760,9 +24841,9 @@ function checkSessions() {
|
|
|
24760
24841
|
}
|
|
24761
24842
|
}
|
|
24762
24843
|
function checkAgentBinaries() {
|
|
24763
|
-
const
|
|
24844
|
+
const os29 = createOsStrategy();
|
|
24764
24845
|
return getEnabledAgents().map((meta) => {
|
|
24765
|
-
const found =
|
|
24846
|
+
const found = os29.findInPath(meta.binaryName);
|
|
24766
24847
|
return {
|
|
24767
24848
|
id: `agent-${meta.id}`,
|
|
24768
24849
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -24784,7 +24865,7 @@ function checkNodePty() {
|
|
|
24784
24865
|
detail: "not required on this platform"
|
|
24785
24866
|
};
|
|
24786
24867
|
}
|
|
24787
|
-
const vendoredPath =
|
|
24868
|
+
const vendoredPath = path44.join(__dirname, "vendor", "node-pty");
|
|
24788
24869
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
24789
24870
|
try {
|
|
24790
24871
|
require(target);
|
|
@@ -24826,7 +24907,7 @@ function checkChokidar() {
|
|
|
24826
24907
|
}
|
|
24827
24908
|
async function doctor(args2 = []) {
|
|
24828
24909
|
const json = args2.includes("--json");
|
|
24829
|
-
const cliVersion = true ? "2.
|
|
24910
|
+
const cliVersion = true ? "2.32.0" : "0.0.0-dev";
|
|
24830
24911
|
const apiBase = resolveApiBaseUrl();
|
|
24831
24912
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
24832
24913
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -25025,7 +25106,7 @@ async function completion(args2) {
|
|
|
25025
25106
|
// src/commands/version.ts
|
|
25026
25107
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
25027
25108
|
function version2() {
|
|
25028
|
-
const v = true ? "2.
|
|
25109
|
+
const v = true ? "2.32.0" : "unknown";
|
|
25029
25110
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
25030
25111
|
}
|
|
25031
25112
|
|
|
@@ -25154,8 +25235,8 @@ var _subcommandHelpKeys = Object.keys(HELPS);
|
|
|
25154
25235
|
|
|
25155
25236
|
// src/lib/updateNotifier.ts
|
|
25156
25237
|
var fs35 = __toESM(require("fs"));
|
|
25157
|
-
var
|
|
25158
|
-
var
|
|
25238
|
+
var os28 = __toESM(require("os"));
|
|
25239
|
+
var path45 = __toESM(require("path"));
|
|
25159
25240
|
var https8 = __toESM(require("https"));
|
|
25160
25241
|
var import_node_child_process12 = require("child_process");
|
|
25161
25242
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
@@ -25164,8 +25245,8 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
25164
25245
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
25165
25246
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
25166
25247
|
function cachePath() {
|
|
25167
|
-
const dir =
|
|
25168
|
-
return
|
|
25248
|
+
const dir = path45.join(os28.homedir(), ".codeam");
|
|
25249
|
+
return path45.join(dir, "update-check.json");
|
|
25169
25250
|
}
|
|
25170
25251
|
function readCache() {
|
|
25171
25252
|
try {
|
|
@@ -25180,7 +25261,7 @@ function readCache() {
|
|
|
25180
25261
|
function writeCache(cache) {
|
|
25181
25262
|
try {
|
|
25182
25263
|
const file = cachePath();
|
|
25183
|
-
fs35.mkdirSync(
|
|
25264
|
+
fs35.mkdirSync(path45.dirname(file), { recursive: true });
|
|
25184
25265
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
25185
25266
|
fs35.writeFileSync(tmp, JSON.stringify(cache));
|
|
25186
25267
|
fs35.renameSync(tmp, file);
|
|
@@ -25257,7 +25338,7 @@ function isLinkedInstall() {
|
|
|
25257
25338
|
timeout: 2e3
|
|
25258
25339
|
}).trim();
|
|
25259
25340
|
if (!root) return false;
|
|
25260
|
-
const pkgPath =
|
|
25341
|
+
const pkgPath = path45.join(root, PKG_NAME);
|
|
25261
25342
|
return fs35.lstatSync(pkgPath).isSymbolicLink();
|
|
25262
25343
|
} catch {
|
|
25263
25344
|
return false;
|
|
@@ -25311,7 +25392,7 @@ function checkForUpdates() {
|
|
|
25311
25392
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
25312
25393
|
if (process.env.CI) return;
|
|
25313
25394
|
if (!process.stdout.isTTY) return;
|
|
25314
|
-
const current = true ? "2.
|
|
25395
|
+
const current = true ? "2.32.0" : null;
|
|
25315
25396
|
if (!current) return;
|
|
25316
25397
|
const cache = readCache();
|
|
25317
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",
|