codeam-cli 2.49.4 → 2.50.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 +12 -0
- package/dist/index.js +463 -207
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -522,9 +522,9 @@ var _default = makeConfig();
|
|
|
522
522
|
var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
|
|
523
523
|
|
|
524
524
|
// src/commands/pair-auto.ts
|
|
525
|
-
var
|
|
526
|
-
var
|
|
527
|
-
var
|
|
525
|
+
var fs42 = __toESM(require("fs"));
|
|
526
|
+
var os35 = __toESM(require("os"));
|
|
527
|
+
var path48 = __toESM(require("path"));
|
|
528
528
|
var import_crypto4 = require("crypto");
|
|
529
529
|
|
|
530
530
|
// src/services/telemetry.service.ts
|
|
@@ -560,8 +560,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
560
560
|
return decodedFile;
|
|
561
561
|
};
|
|
562
562
|
}
|
|
563
|
-
function normalizeWindowsPath(
|
|
564
|
-
return
|
|
563
|
+
function normalizeWindowsPath(path61) {
|
|
564
|
+
return path61.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3041,9 +3041,9 @@ async function addSourceContext(frames) {
|
|
|
3041
3041
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3042
3042
|
return frames;
|
|
3043
3043
|
}
|
|
3044
|
-
function getContextLinesFromFile(
|
|
3044
|
+
function getContextLinesFromFile(path61, ranges, output) {
|
|
3045
3045
|
return new Promise((resolve7) => {
|
|
3046
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3046
|
+
const stream = (0, import_node_fs.createReadStream)(path61);
|
|
3047
3047
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3048
3048
|
input: stream
|
|
3049
3049
|
});
|
|
@@ -3058,7 +3058,7 @@ function getContextLinesFromFile(path60, ranges, output) {
|
|
|
3058
3058
|
let rangeStart = range[0];
|
|
3059
3059
|
let rangeEnd = range[1];
|
|
3060
3060
|
function onStreamError() {
|
|
3061
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3061
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path61, 1);
|
|
3062
3062
|
lineReaded.close();
|
|
3063
3063
|
lineReaded.removeAllListeners();
|
|
3064
3064
|
destroyStreamAndResolve();
|
|
@@ -3119,8 +3119,8 @@ function clearLineContext(frame) {
|
|
|
3119
3119
|
delete frame.context_line;
|
|
3120
3120
|
delete frame.post_context;
|
|
3121
3121
|
}
|
|
3122
|
-
function shouldSkipContextLinesForFile(
|
|
3123
|
-
return
|
|
3122
|
+
function shouldSkipContextLinesForFile(path61) {
|
|
3123
|
+
return path61.startsWith("node:") || path61.endsWith(".min.js") || path61.endsWith(".min.cjs") || path61.endsWith(".min.mjs") || path61.startsWith("data:");
|
|
3124
3124
|
}
|
|
3125
3125
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3126
3126
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5397,7 +5397,7 @@ function readAnonId() {
|
|
|
5397
5397
|
}
|
|
5398
5398
|
function superProperties() {
|
|
5399
5399
|
return {
|
|
5400
|
-
cliVersion: true ? "2.
|
|
5400
|
+
cliVersion: true ? "2.50.0" : "0.0.0-dev",
|
|
5401
5401
|
nodeVersion: process.version,
|
|
5402
5402
|
platform: process.platform,
|
|
5403
5403
|
arch: process.arch,
|
|
@@ -5578,7 +5578,7 @@ var os4 = __toESM(require("os"));
|
|
|
5578
5578
|
// package.json
|
|
5579
5579
|
var package_default = {
|
|
5580
5580
|
name: "codeam-cli",
|
|
5581
|
-
version: "2.
|
|
5581
|
+
version: "2.50.0",
|
|
5582
5582
|
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.",
|
|
5583
5583
|
type: "commonjs",
|
|
5584
5584
|
main: "dist/index.js",
|
|
@@ -5871,6 +5871,28 @@ async function postHeadroomEvent(input) {
|
|
|
5871
5871
|
};
|
|
5872
5872
|
}
|
|
5873
5873
|
}
|
|
5874
|
+
async function postBeadsEvent(input) {
|
|
5875
|
+
try {
|
|
5876
|
+
await _transport.postJsonAuthed(
|
|
5877
|
+
`${API_BASE}/api/beads/events`,
|
|
5878
|
+
{
|
|
5879
|
+
sessionId: input.sessionId,
|
|
5880
|
+
pluginId: input.pluginId,
|
|
5881
|
+
type: input.type,
|
|
5882
|
+
payload: input.payload ?? {}
|
|
5883
|
+
},
|
|
5884
|
+
input.pluginAuthToken
|
|
5885
|
+
);
|
|
5886
|
+
return { ok: true };
|
|
5887
|
+
} catch (err) {
|
|
5888
|
+
const e = err;
|
|
5889
|
+
return {
|
|
5890
|
+
ok: false,
|
|
5891
|
+
status: typeof e.statusCode === "number" ? e.statusCode : 0,
|
|
5892
|
+
message: e.message || "unknown"
|
|
5893
|
+
};
|
|
5894
|
+
}
|
|
5895
|
+
}
|
|
5874
5896
|
async function postBeadsProvisioning(input) {
|
|
5875
5897
|
try {
|
|
5876
5898
|
await _transport.postJsonAuthed(
|
|
@@ -7706,9 +7728,9 @@ function closeAllTerminals() {
|
|
|
7706
7728
|
}
|
|
7707
7729
|
|
|
7708
7730
|
// src/commands/start/handlers.ts
|
|
7709
|
-
var
|
|
7710
|
-
var
|
|
7711
|
-
var
|
|
7731
|
+
var fs41 = __toESM(require("fs"));
|
|
7732
|
+
var os34 = __toESM(require("os"));
|
|
7733
|
+
var path47 = __toESM(require("path"));
|
|
7712
7734
|
var import_crypto3 = require("crypto");
|
|
7713
7735
|
var import_child_process20 = require("child_process");
|
|
7714
7736
|
var import_which2 = __toESM(require("which"));
|
|
@@ -11142,10 +11164,10 @@ function buildForPlatform(platform3) {
|
|
|
11142
11164
|
var import_node_crypto4 = require("crypto");
|
|
11143
11165
|
|
|
11144
11166
|
// src/agents/claude/resolver.ts
|
|
11145
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
11146
|
-
const found =
|
|
11167
|
+
function buildClaudeLaunch(extraArgs = [], os41 = createOsStrategy()) {
|
|
11168
|
+
const found = os41.findInPath("claude") ?? os41.findInPath("claude-code");
|
|
11147
11169
|
if (!found) return null;
|
|
11148
|
-
return
|
|
11170
|
+
return os41.buildLaunch(found, extraArgs);
|
|
11149
11171
|
}
|
|
11150
11172
|
|
|
11151
11173
|
// src/agents/claude/installer.ts
|
|
@@ -11738,8 +11760,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
11738
11760
|
meta = getAgent("claude");
|
|
11739
11761
|
mode = "interactive";
|
|
11740
11762
|
os;
|
|
11741
|
-
constructor(
|
|
11742
|
-
this.os =
|
|
11763
|
+
constructor(os41) {
|
|
11764
|
+
this.os = os41;
|
|
11743
11765
|
}
|
|
11744
11766
|
/**
|
|
11745
11767
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -12416,8 +12438,8 @@ function codexCredentialLocator() {
|
|
|
12416
12438
|
function codexLoginLauncher() {
|
|
12417
12439
|
return {
|
|
12418
12440
|
async ensureInstalled() {
|
|
12419
|
-
const
|
|
12420
|
-
return
|
|
12441
|
+
const os41 = createOsStrategy();
|
|
12442
|
+
return os41.findInPath("codex") !== null;
|
|
12421
12443
|
},
|
|
12422
12444
|
launch() {
|
|
12423
12445
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -12440,8 +12462,8 @@ var CodexRuntimeStrategy = class {
|
|
|
12440
12462
|
meta = getAgent("codex");
|
|
12441
12463
|
mode = "interactive";
|
|
12442
12464
|
os;
|
|
12443
|
-
constructor(
|
|
12444
|
-
this.os =
|
|
12465
|
+
constructor(os41) {
|
|
12466
|
+
this.os = os41;
|
|
12445
12467
|
}
|
|
12446
12468
|
async prepareLaunch() {
|
|
12447
12469
|
let binary = this.os.findInPath("codex");
|
|
@@ -12540,12 +12562,12 @@ var CodexRuntimeStrategy = class {
|
|
|
12540
12562
|
});
|
|
12541
12563
|
}
|
|
12542
12564
|
};
|
|
12543
|
-
function resolveNpm(
|
|
12544
|
-
return
|
|
12565
|
+
function resolveNpm(os41) {
|
|
12566
|
+
return os41.id === "win32" ? "npm.cmd" : "npm";
|
|
12545
12567
|
}
|
|
12546
|
-
async function installCodexViaNpm(
|
|
12568
|
+
async function installCodexViaNpm(os41) {
|
|
12547
12569
|
return new Promise((resolve7, reject) => {
|
|
12548
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
12570
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os41), ["install", "-g", "@openai/codex"], {
|
|
12549
12571
|
stdio: "inherit"
|
|
12550
12572
|
});
|
|
12551
12573
|
proc.on("close", (code) => {
|
|
@@ -12562,16 +12584,16 @@ async function installCodexViaNpm(os40) {
|
|
|
12562
12584
|
});
|
|
12563
12585
|
});
|
|
12564
12586
|
}
|
|
12565
|
-
function augmentNpmGlobalBin(
|
|
12587
|
+
function augmentNpmGlobalBin(os41) {
|
|
12566
12588
|
try {
|
|
12567
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
12589
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os41), ["prefix", "-g"], {
|
|
12568
12590
|
stdio: ["ignore", "pipe", "ignore"]
|
|
12569
12591
|
});
|
|
12570
12592
|
if (result.status !== 0) return;
|
|
12571
12593
|
const prefix = result.stdout.toString().trim();
|
|
12572
12594
|
if (!prefix) return;
|
|
12573
|
-
const binDir =
|
|
12574
|
-
|
|
12595
|
+
const binDir = os41.id === "win32" ? prefix : path22.join(prefix, "bin");
|
|
12596
|
+
os41.augmentPath([binDir]);
|
|
12575
12597
|
} catch {
|
|
12576
12598
|
}
|
|
12577
12599
|
}
|
|
@@ -12655,9 +12677,9 @@ var import_node_child_process7 = require("child_process");
|
|
|
12655
12677
|
// src/agents/coderabbit/installer.ts
|
|
12656
12678
|
var import_node_child_process5 = require("child_process");
|
|
12657
12679
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
12658
|
-
async function ensureCoderabbitInstalled(
|
|
12659
|
-
if (
|
|
12660
|
-
if (
|
|
12680
|
+
async function ensureCoderabbitInstalled(os41) {
|
|
12681
|
+
if (os41.findInPath("coderabbit")) return true;
|
|
12682
|
+
if (os41.id === "win32") {
|
|
12661
12683
|
console.error(
|
|
12662
12684
|
"\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"
|
|
12663
12685
|
);
|
|
@@ -12672,8 +12694,8 @@ async function ensureCoderabbitInstalled(os40) {
|
|
|
12672
12694
|
proc.on("error", () => resolve7(false));
|
|
12673
12695
|
});
|
|
12674
12696
|
if (!ok) return false;
|
|
12675
|
-
|
|
12676
|
-
return
|
|
12697
|
+
os41.augmentPath([`${os41.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
12698
|
+
return os41.findInPath("coderabbit") !== null;
|
|
12677
12699
|
}
|
|
12678
12700
|
|
|
12679
12701
|
// src/agents/coderabbit/link.ts
|
|
@@ -12708,10 +12730,10 @@ function coderabbitCredentialLocator() {
|
|
|
12708
12730
|
validate: validateNonEmptyCredential
|
|
12709
12731
|
};
|
|
12710
12732
|
}
|
|
12711
|
-
function coderabbitLoginLauncher(
|
|
12733
|
+
function coderabbitLoginLauncher(os41) {
|
|
12712
12734
|
return {
|
|
12713
12735
|
async ensureInstalled() {
|
|
12714
|
-
return ensureCoderabbitInstalled(
|
|
12736
|
+
return ensureCoderabbitInstalled(os41);
|
|
12715
12737
|
},
|
|
12716
12738
|
launch() {
|
|
12717
12739
|
return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
@@ -12734,11 +12756,11 @@ function parseReview(stdout) {
|
|
|
12734
12756
|
for (const line of lines) {
|
|
12735
12757
|
const m = line.match(HUNK_LINE_RE);
|
|
12736
12758
|
if (!m) continue;
|
|
12737
|
-
const [,
|
|
12738
|
-
if (!
|
|
12759
|
+
const [, path61, lineNo, sevToken, message] = m;
|
|
12760
|
+
if (!path61 || !lineNo || !message) continue;
|
|
12739
12761
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
12740
12762
|
hunks.push({
|
|
12741
|
-
path:
|
|
12763
|
+
path: path61.trim(),
|
|
12742
12764
|
line: Number(lineNo),
|
|
12743
12765
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
12744
12766
|
message: cleanedMessage
|
|
@@ -12757,8 +12779,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
12757
12779
|
meta = getAgent("coderabbit");
|
|
12758
12780
|
mode = "batch";
|
|
12759
12781
|
os;
|
|
12760
|
-
constructor(
|
|
12761
|
-
this.os =
|
|
12782
|
+
constructor(os41) {
|
|
12783
|
+
this.os = os41;
|
|
12762
12784
|
}
|
|
12763
12785
|
getDefaultArgs() {
|
|
12764
12786
|
return ["review"];
|
|
@@ -12874,10 +12896,10 @@ function cursorCredentialLocator() {
|
|
|
12874
12896
|
validate: validateNonEmptyCredential
|
|
12875
12897
|
};
|
|
12876
12898
|
}
|
|
12877
|
-
function cursorLoginLauncher(
|
|
12899
|
+
function cursorLoginLauncher(os41) {
|
|
12878
12900
|
return {
|
|
12879
12901
|
async ensureInstalled() {
|
|
12880
|
-
if (
|
|
12902
|
+
if (os41.findInPath("cursor-agent")) return true;
|
|
12881
12903
|
console.error(
|
|
12882
12904
|
"\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"
|
|
12883
12905
|
);
|
|
@@ -12939,8 +12961,8 @@ var CursorRuntimeStrategy = class {
|
|
|
12939
12961
|
meta = getAgent("cursor");
|
|
12940
12962
|
mode = "interactive";
|
|
12941
12963
|
os;
|
|
12942
|
-
constructor(
|
|
12943
|
-
this.os =
|
|
12964
|
+
constructor(os41) {
|
|
12965
|
+
this.os = os41;
|
|
12944
12966
|
}
|
|
12945
12967
|
async prepareLaunch() {
|
|
12946
12968
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -13079,10 +13101,10 @@ function aiderCredentialLocator() {
|
|
|
13079
13101
|
validate: validateNonEmptyCredential
|
|
13080
13102
|
};
|
|
13081
13103
|
}
|
|
13082
|
-
function aiderLoginLauncher(
|
|
13104
|
+
function aiderLoginLauncher(os41) {
|
|
13083
13105
|
return {
|
|
13084
13106
|
async ensureInstalled() {
|
|
13085
|
-
if (
|
|
13107
|
+
if (os41.findInPath("aider")) return true;
|
|
13086
13108
|
console.error(
|
|
13087
13109
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
13088
13110
|
);
|
|
@@ -13092,7 +13114,7 @@ function aiderLoginLauncher(os40) {
|
|
|
13092
13114
|
console.error(
|
|
13093
13115
|
"\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"
|
|
13094
13116
|
);
|
|
13095
|
-
return (0, import_node_child_process9.spawn)(
|
|
13117
|
+
return (0, import_node_child_process9.spawn)(os41.id === "win32" ? "cmd.exe" : "sh", os41.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
13096
13118
|
stdio: "ignore"
|
|
13097
13119
|
});
|
|
13098
13120
|
}
|
|
@@ -13164,8 +13186,8 @@ var AiderRuntimeStrategy = class {
|
|
|
13164
13186
|
meta = getAgent("aider");
|
|
13165
13187
|
mode = "interactive";
|
|
13166
13188
|
os;
|
|
13167
|
-
constructor(
|
|
13168
|
-
this.os =
|
|
13189
|
+
constructor(os41) {
|
|
13190
|
+
this.os = os41;
|
|
13169
13191
|
}
|
|
13170
13192
|
async prepareLaunch() {
|
|
13171
13193
|
const binary = this.os.findInPath("aider");
|
|
@@ -13294,8 +13316,8 @@ function geminiCredentialLocator() {
|
|
|
13294
13316
|
function geminiLoginLauncher() {
|
|
13295
13317
|
return {
|
|
13296
13318
|
async ensureInstalled() {
|
|
13297
|
-
const
|
|
13298
|
-
return
|
|
13319
|
+
const os41 = createOsStrategy();
|
|
13320
|
+
return os41.findInPath("gemini") !== null;
|
|
13299
13321
|
},
|
|
13300
13322
|
launch() {
|
|
13301
13323
|
return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -13328,8 +13350,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
13328
13350
|
meta = getAgent("gemini");
|
|
13329
13351
|
mode = "interactive";
|
|
13330
13352
|
os;
|
|
13331
|
-
constructor(
|
|
13332
|
-
this.os =
|
|
13353
|
+
constructor(os41) {
|
|
13354
|
+
this.os = os41;
|
|
13333
13355
|
}
|
|
13334
13356
|
async prepareLaunch() {
|
|
13335
13357
|
const binary = this.os.findInPath("gemini");
|
|
@@ -13428,18 +13450,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
13428
13450
|
|
|
13429
13451
|
// src/agents/registry.ts
|
|
13430
13452
|
var runtimeBuilders = {
|
|
13431
|
-
claude: (
|
|
13432
|
-
codex: (
|
|
13433
|
-
coderabbit: (
|
|
13434
|
-
cursor: (
|
|
13435
|
-
aider: (
|
|
13436
|
-
gemini: (
|
|
13453
|
+
claude: (os41) => new ClaudeRuntimeStrategy(os41),
|
|
13454
|
+
codex: (os41) => new CodexRuntimeStrategy(os41),
|
|
13455
|
+
coderabbit: (os41) => new CoderabbitRuntimeStrategy(os41),
|
|
13456
|
+
cursor: (os41) => new CursorRuntimeStrategy(os41),
|
|
13457
|
+
aider: (os41) => new AiderRuntimeStrategy(os41),
|
|
13458
|
+
gemini: (os41) => new GeminiRuntimeStrategy(os41)
|
|
13437
13459
|
};
|
|
13438
13460
|
var deployBuilders = {
|
|
13439
13461
|
claude: () => new ClaudeDeployStrategy(),
|
|
13440
13462
|
codex: () => new CodexDeployStrategy()
|
|
13441
13463
|
};
|
|
13442
|
-
function createAgentStrategy(agent,
|
|
13464
|
+
function createAgentStrategy(agent, os41 = createOsStrategy()) {
|
|
13443
13465
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
13444
13466
|
throw new Error(
|
|
13445
13467
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -13449,10 +13471,10 @@ function createAgentStrategy(agent, os40 = createOsStrategy()) {
|
|
|
13449
13471
|
if (!build) {
|
|
13450
13472
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
13451
13473
|
}
|
|
13452
|
-
return build(
|
|
13474
|
+
return build(os41);
|
|
13453
13475
|
}
|
|
13454
|
-
function createInteractiveAgentStrategy(agent,
|
|
13455
|
-
const s = createAgentStrategy(agent,
|
|
13476
|
+
function createInteractiveAgentStrategy(agent, os41 = createOsStrategy()) {
|
|
13477
|
+
const s = createAgentStrategy(agent, os41);
|
|
13456
13478
|
if (s.mode !== "interactive") {
|
|
13457
13479
|
throw new Error(
|
|
13458
13480
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -14747,7 +14769,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
14747
14769
|
if (process.env.NODE_ENV === "test") return;
|
|
14748
14770
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
14749
14771
|
if (process.env.CI) return;
|
|
14750
|
-
const current = true ? "2.
|
|
14772
|
+
const current = true ? "2.50.0" : null;
|
|
14751
14773
|
if (!current) return;
|
|
14752
14774
|
const cache = readCache();
|
|
14753
14775
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -14764,7 +14786,7 @@ function checkForUpdates() {
|
|
|
14764
14786
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
14765
14787
|
if (process.env.CI) return;
|
|
14766
14788
|
if (!process.stdout.isTTY) return;
|
|
14767
|
-
const current = true ? "2.
|
|
14789
|
+
const current = true ? "2.50.0" : null;
|
|
14768
14790
|
if (!current) return;
|
|
14769
14791
|
const cache = readCache();
|
|
14770
14792
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -14827,6 +14849,51 @@ function maybeStartHeadroomReporter(ctx) {
|
|
|
14827
14849
|
return null;
|
|
14828
14850
|
}
|
|
14829
14851
|
}
|
|
14852
|
+
function maybeResumeLocalHeadroomReporter(ctx) {
|
|
14853
|
+
if (process.env["HEADROOM_ENABLED"] === "1") return null;
|
|
14854
|
+
try {
|
|
14855
|
+
const file = headroomConfigPath();
|
|
14856
|
+
if (!fs31.existsSync(file)) return null;
|
|
14857
|
+
const cfg = JSON.parse(fs31.readFileSync(file, "utf8"));
|
|
14858
|
+
if (!cfg?.enabled) return null;
|
|
14859
|
+
const agent = cfg.agent ?? "claude";
|
|
14860
|
+
const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
|
|
14861
|
+
const reporter = new HeadroomStatsReporter({
|
|
14862
|
+
inputPricePerMillionUsd: resolveInputPricePerMillion(agent),
|
|
14863
|
+
fetchStats: async () => {
|
|
14864
|
+
const res = await fetch("http://localhost:8787/stats");
|
|
14865
|
+
return res.json();
|
|
14866
|
+
},
|
|
14867
|
+
// Body MUST match HeadroomSavingsDto + PluginAuthGuard (sessionId +
|
|
14868
|
+
// pluginId in the body) — same shape as the codespace reporter above and
|
|
14869
|
+
// the on-demand `startReporter` in handlers.ts.
|
|
14870
|
+
postSavings: async (delta) => {
|
|
14871
|
+
await fetch(ingestUrl, {
|
|
14872
|
+
method: "POST",
|
|
14873
|
+
headers: {
|
|
14874
|
+
"Content-Type": "application/json",
|
|
14875
|
+
"X-Plugin-Auth-Token": ctx.pluginAuthToken
|
|
14876
|
+
},
|
|
14877
|
+
body: JSON.stringify({
|
|
14878
|
+
sessionId: ctx.sessionId,
|
|
14879
|
+
pluginId: ctx.pluginId,
|
|
14880
|
+
agentId: agent,
|
|
14881
|
+
savings: delta
|
|
14882
|
+
})
|
|
14883
|
+
});
|
|
14884
|
+
}
|
|
14885
|
+
});
|
|
14886
|
+
reporter.start();
|
|
14887
|
+
log.info("headroom", "resumed on-demand local savings reporter from config");
|
|
14888
|
+
return reporter;
|
|
14889
|
+
} catch (err) {
|
|
14890
|
+
log.warn(
|
|
14891
|
+
"headroom",
|
|
14892
|
+
`failed to resume local Headroom reporter (best-effort): ${err instanceof Error ? err.message : String(err)}`
|
|
14893
|
+
);
|
|
14894
|
+
return null;
|
|
14895
|
+
}
|
|
14896
|
+
}
|
|
14830
14897
|
function isRefreshCredentialsPayload(p2) {
|
|
14831
14898
|
return typeof p2.agentId === "string" && typeof p2.sealedAgentAuth === "string";
|
|
14832
14899
|
}
|
|
@@ -15400,7 +15467,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
|
|
|
15400
15467
|
detached: false
|
|
15401
15468
|
});
|
|
15402
15469
|
function currentCliVersion() {
|
|
15403
|
-
return true ? "2.
|
|
15470
|
+
return true ? "2.50.0" : null;
|
|
15404
15471
|
}
|
|
15405
15472
|
function runCmd(cmd, args2, timeoutMs) {
|
|
15406
15473
|
return new Promise((resolve7) => {
|
|
@@ -17081,11 +17148,11 @@ function resolveDoltInstallStrategy(platform3) {
|
|
|
17081
17148
|
}
|
|
17082
17149
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
17083
17150
|
function doltPlatformTuple(platform3, arch2) {
|
|
17084
|
-
const
|
|
17151
|
+
const os41 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
|
|
17085
17152
|
const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
|
|
17086
17153
|
if (!a) return null;
|
|
17087
|
-
if (
|
|
17088
|
-
return `${
|
|
17154
|
+
if (os41 === "windows" && a !== "amd64") return null;
|
|
17155
|
+
return `${os41}-${a}`;
|
|
17089
17156
|
}
|
|
17090
17157
|
function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
|
|
17091
17158
|
const tuple = doltPlatformTuple(platform3, arch2);
|
|
@@ -17964,6 +18031,30 @@ async function handleBeadsActionCommand(action, started) {
|
|
|
17964
18031
|
});
|
|
17965
18032
|
}
|
|
17966
18033
|
|
|
18034
|
+
// src/beads/config-store.ts
|
|
18035
|
+
var import_node_fs5 = __toESM(require("fs"));
|
|
18036
|
+
var import_node_os3 = __toESM(require("os"));
|
|
18037
|
+
var import_node_path4 = __toESM(require("path"));
|
|
18038
|
+
function beadsConfigPath() {
|
|
18039
|
+
return import_node_path4.default.join(import_node_os3.default.homedir(), ".codeam", "beads-config.json");
|
|
18040
|
+
}
|
|
18041
|
+
function readBeadsEnabled() {
|
|
18042
|
+
try {
|
|
18043
|
+
const raw = import_node_fs5.default.readFileSync(beadsConfigPath(), "utf8");
|
|
18044
|
+
const cfg = JSON.parse(raw);
|
|
18045
|
+
return cfg.enabled !== false;
|
|
18046
|
+
} catch {
|
|
18047
|
+
return true;
|
|
18048
|
+
}
|
|
18049
|
+
}
|
|
18050
|
+
function persistBeadsConfig(cfg) {
|
|
18051
|
+
const file = beadsConfigPath();
|
|
18052
|
+
import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
18053
|
+
const tmp = `${file}.tmp`;
|
|
18054
|
+
import_node_fs5.default.writeFileSync(tmp, JSON.stringify(cfg), { mode: 384 });
|
|
18055
|
+
import_node_fs5.default.renameSync(tmp, file);
|
|
18056
|
+
}
|
|
18057
|
+
|
|
17967
18058
|
// src/beads/wiring.ts
|
|
17968
18059
|
function beadsKilled() {
|
|
17969
18060
|
const v = process.env.CODEAM_BEADS_DISABLED;
|
|
@@ -17974,6 +18065,10 @@ async function provisionBeadsForStart(ctx) {
|
|
|
17974
18065
|
log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off this run");
|
|
17975
18066
|
return null;
|
|
17976
18067
|
}
|
|
18068
|
+
if (readBeadsEnabled() === false) {
|
|
18069
|
+
log.trace("beads", "beads disabled by persisted config \u2014 beads off this run");
|
|
18070
|
+
return null;
|
|
18071
|
+
}
|
|
17977
18072
|
delete process.env.BEADS_DIR;
|
|
17978
18073
|
process.env.BEADS_DOLT_SHARED_SERVER = "1";
|
|
17979
18074
|
if (!ctx.pluginAuthToken) {
|
|
@@ -18034,12 +18129,69 @@ function beadsActionFromPayload(payload) {
|
|
|
18034
18129
|
};
|
|
18035
18130
|
}
|
|
18036
18131
|
|
|
18132
|
+
// src/beads/configure.ts
|
|
18133
|
+
var _probeSeam = {
|
|
18134
|
+
resolveBd: (cwd) => new BdAdapter({ cwd }).isAvailable(),
|
|
18135
|
+
doltOnPath: () => ensureDoltResolvable(),
|
|
18136
|
+
ping: async (cwd) => {
|
|
18137
|
+
const adapter = new BdAdapter({ cwd });
|
|
18138
|
+
if (!adapter.isAvailable()) return false;
|
|
18139
|
+
const r = await adapter.run(["ping"]);
|
|
18140
|
+
return r.code === 0;
|
|
18141
|
+
},
|
|
18142
|
+
derivePrefix: (cwd) => {
|
|
18143
|
+
try {
|
|
18144
|
+
const { projectKey } = deriveProjectIdentity(cwd);
|
|
18145
|
+
return prefixForProjectKey(projectKey);
|
|
18146
|
+
} catch {
|
|
18147
|
+
return null;
|
|
18148
|
+
}
|
|
18149
|
+
}
|
|
18150
|
+
};
|
|
18151
|
+
async function probeBeadsStatus(cwd = process.cwd()) {
|
|
18152
|
+
const bdAvailable = _probeSeam.resolveBd(cwd);
|
|
18153
|
+
const doltAvailable = _probeSeam.doltOnPath();
|
|
18154
|
+
const serverUp = bdAvailable && doltAvailable ? await _probeSeam.ping(cwd) : false;
|
|
18155
|
+
const prefix = _probeSeam.derivePrefix(cwd);
|
|
18156
|
+
return { bdAvailable, doltAvailable, serverUp, prefix };
|
|
18157
|
+
}
|
|
18158
|
+
async function configureBeads(action, ctx, deps) {
|
|
18159
|
+
if (action === "status") {
|
|
18160
|
+
if (deps.readEnabled() === false) {
|
|
18161
|
+
deps.emit({ type: "beads_status", state: "disabled", running: false });
|
|
18162
|
+
return { enabled: false, running: false };
|
|
18163
|
+
}
|
|
18164
|
+
const p3 = await deps.probe();
|
|
18165
|
+
const running2 = p3.serverUp && p3.bdAvailable;
|
|
18166
|
+
deps.emit({ type: "beads_status", state: running2 ? "enabled" : "disabled", running: running2, ...p3 });
|
|
18167
|
+
return { enabled: running2, running: running2, ...p3 };
|
|
18168
|
+
}
|
|
18169
|
+
if (action === "disable") {
|
|
18170
|
+
deps.persist({ enabled: false });
|
|
18171
|
+
await deps.stopWatcher().catch(() => void 0);
|
|
18172
|
+
await deps.revertAgentHook(ctx.agent).catch(() => void 0);
|
|
18173
|
+
deps.emit({ type: "beads_status", state: "disabled" });
|
|
18174
|
+
return { enabled: false };
|
|
18175
|
+
}
|
|
18176
|
+
deps.persist({ enabled: true });
|
|
18177
|
+
deps.emit({ type: "beads_status", state: "provisioning" });
|
|
18178
|
+
const p2 = await deps.provision();
|
|
18179
|
+
if (!p2.serverUp || !p2.bdAvailable) {
|
|
18180
|
+
deps.emit({ type: "beads_status", state: "error", error: "Beads provisioning failed", ...p2 });
|
|
18181
|
+
return { enabled: false, ...p2 };
|
|
18182
|
+
}
|
|
18183
|
+
await deps.startWatcher().catch(() => void 0);
|
|
18184
|
+
const running = true;
|
|
18185
|
+
deps.emit({ type: "beads_status", state: "enabled", running, ...p2 });
|
|
18186
|
+
return { enabled: true, running, ...p2 };
|
|
18187
|
+
}
|
|
18188
|
+
|
|
18037
18189
|
// src/commands/start/handlers.ts
|
|
18038
18190
|
var pendingAttachmentFiles = /* @__PURE__ */ new Set();
|
|
18039
18191
|
function cleanupAttachmentTempFiles() {
|
|
18040
18192
|
for (const p2 of pendingAttachmentFiles) {
|
|
18041
18193
|
try {
|
|
18042
|
-
|
|
18194
|
+
fs41.unlinkSync(p2);
|
|
18043
18195
|
} catch {
|
|
18044
18196
|
}
|
|
18045
18197
|
}
|
|
@@ -18048,8 +18200,8 @@ function cleanupAttachmentTempFiles() {
|
|
|
18048
18200
|
function saveFilesTemp(files) {
|
|
18049
18201
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
18050
18202
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
18051
|
-
const tmpPath =
|
|
18052
|
-
|
|
18203
|
+
const tmpPath = path47.join(os34.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
18204
|
+
fs41.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
18053
18205
|
pendingAttachmentFiles.add(tmpPath);
|
|
18054
18206
|
return tmpPath;
|
|
18055
18207
|
});
|
|
@@ -18069,7 +18221,7 @@ var startTask = (ctx, _cmd, parsed) => {
|
|
|
18069
18221
|
setTimeout(() => {
|
|
18070
18222
|
for (const p2 of paths) {
|
|
18071
18223
|
try {
|
|
18072
|
-
|
|
18224
|
+
fs41.unlinkSync(p2);
|
|
18073
18225
|
} catch {
|
|
18074
18226
|
}
|
|
18075
18227
|
pendingAttachmentFiles.delete(p2);
|
|
@@ -18270,9 +18422,9 @@ var listFiles = async (ctx, cmd, parsed) => {
|
|
|
18270
18422
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18271
18423
|
};
|
|
18272
18424
|
var envReadH = async (ctx, cmd) => {
|
|
18273
|
-
const envPath =
|
|
18425
|
+
const envPath = path47.join(process.cwd(), ".env");
|
|
18274
18426
|
try {
|
|
18275
|
-
const raw = await
|
|
18427
|
+
const raw = await fs41.promises.readFile(envPath, "utf8");
|
|
18276
18428
|
await ctx.relay.sendResult(cmd.id, "completed", {
|
|
18277
18429
|
exists: true,
|
|
18278
18430
|
vars: parseDotenv(raw)
|
|
@@ -18303,14 +18455,14 @@ var envWriteH = async (ctx, cmd, parsed) => {
|
|
|
18303
18455
|
}
|
|
18304
18456
|
seen.add(v.key);
|
|
18305
18457
|
}
|
|
18306
|
-
const envPath =
|
|
18307
|
-
const tmpPath =
|
|
18458
|
+
const envPath = path47.join(process.cwd(), ".env");
|
|
18459
|
+
const tmpPath = path47.join(process.cwd(), ".env.codeam.tmp");
|
|
18308
18460
|
try {
|
|
18309
|
-
await
|
|
18310
|
-
await
|
|
18461
|
+
await fs41.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
|
|
18462
|
+
await fs41.promises.rename(tmpPath, envPath);
|
|
18311
18463
|
await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
|
|
18312
18464
|
} catch (err) {
|
|
18313
|
-
await
|
|
18465
|
+
await fs41.promises.rm(tmpPath, { force: true }).catch(() => void 0);
|
|
18314
18466
|
await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
|
|
18315
18467
|
}
|
|
18316
18468
|
};
|
|
@@ -18328,7 +18480,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18328
18480
|
let configuredAgent = rawAgentId;
|
|
18329
18481
|
if (!configuredAgent) {
|
|
18330
18482
|
try {
|
|
18331
|
-
const raw = JSON.parse(
|
|
18483
|
+
const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
|
|
18332
18484
|
configuredAgent = raw.agent ?? "";
|
|
18333
18485
|
} catch {
|
|
18334
18486
|
}
|
|
@@ -18362,7 +18514,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18362
18514
|
persist: persistHeadroomConfig,
|
|
18363
18515
|
readEnabled: () => {
|
|
18364
18516
|
try {
|
|
18365
|
-
const raw = JSON.parse(
|
|
18517
|
+
const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
|
|
18366
18518
|
return raw.enabled === true;
|
|
18367
18519
|
} catch {
|
|
18368
18520
|
return false;
|
|
@@ -18383,7 +18535,19 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18383
18535
|
"Content-Type": "application/json",
|
|
18384
18536
|
...opts.pluginAuthToken ? { "X-Plugin-Auth-Token": opts.pluginAuthToken } : {}
|
|
18385
18537
|
},
|
|
18386
|
-
|
|
18538
|
+
// Body MUST match HeadroomSavingsDto + PluginAuthGuard, which read
|
|
18539
|
+
// `sessionId` + `pluginId` from the body and 401 if either is
|
|
18540
|
+
// missing. Mirror the self-hosted reporter in host-agent.ts exactly.
|
|
18541
|
+
// Previously this sent `{ agentId, ...delta }` (no sessionId/pluginId,
|
|
18542
|
+
// delta spread flat instead of nested under `savings`) → every POST
|
|
18543
|
+
// was rejected 401 at the guard and silently swallowed (fetch status
|
|
18544
|
+
// unchecked), so local on-demand savings never reached the backend.
|
|
18545
|
+
body: JSON.stringify({
|
|
18546
|
+
sessionId: ctx.sessionId,
|
|
18547
|
+
pluginId: ctx.pluginId,
|
|
18548
|
+
agentId: opts.agent,
|
|
18549
|
+
savings: delta
|
|
18550
|
+
})
|
|
18387
18551
|
});
|
|
18388
18552
|
}
|
|
18389
18553
|
});
|
|
@@ -18423,6 +18587,65 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18423
18587
|
});
|
|
18424
18588
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18425
18589
|
};
|
|
18590
|
+
var _beadsEmitChain = Promise.resolve();
|
|
18591
|
+
var beadsConfigureH = async (ctx, cmd, parsed) => {
|
|
18592
|
+
const action = parsed.action;
|
|
18593
|
+
if (action !== "enable" && action !== "disable" && action !== "status") {
|
|
18594
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: "action must be enable|disable|status" });
|
|
18595
|
+
return;
|
|
18596
|
+
}
|
|
18597
|
+
let rawAgentId = ctx.agentId || (typeof parsed.agentId === "string" ? parsed.agentId : "");
|
|
18598
|
+
if (rawAgentId === "claude_code") rawAgentId = "claude";
|
|
18599
|
+
const agentIds = rawAgentId && isKnownAgentId(rawAgentId) ? [rawAgentId] : [];
|
|
18600
|
+
const deps = {
|
|
18601
|
+
provision: async () => {
|
|
18602
|
+
const r = await provisionBeads({ cwd: process.cwd(), agents: agentIds });
|
|
18603
|
+
return { bdAvailable: r.bdAvailable, doltAvailable: r.doltAvailable, serverUp: r.serverUp, prefix: r.prefix };
|
|
18604
|
+
},
|
|
18605
|
+
probe: async () => probeBeadsStatus(process.cwd()),
|
|
18606
|
+
startWatcher: async () => {
|
|
18607
|
+
if (!ctx.pluginAuthToken) return;
|
|
18608
|
+
const started = await startBeads({
|
|
18609
|
+
sessionId: ctx.sessionId,
|
|
18610
|
+
pluginId: ctx.pluginId,
|
|
18611
|
+
pluginAuthToken: ctx.pluginAuthToken,
|
|
18612
|
+
cwd: process.cwd(),
|
|
18613
|
+
agents: agentIds
|
|
18614
|
+
});
|
|
18615
|
+
if (started) {
|
|
18616
|
+
ctx.beads = started;
|
|
18617
|
+
}
|
|
18618
|
+
},
|
|
18619
|
+
stopWatcher: async () => {
|
|
18620
|
+
if (ctx.beads) {
|
|
18621
|
+
await ctx.beads.watcher.stop();
|
|
18622
|
+
ctx.beads = null;
|
|
18623
|
+
}
|
|
18624
|
+
},
|
|
18625
|
+
revertAgentHook: async (agent) => {
|
|
18626
|
+
log.info("beads", `revertAgentHook: bd has no --remove flag \u2014 leaving ${agent} hook in place (no-op disable path)`);
|
|
18627
|
+
},
|
|
18628
|
+
persist: (cfg) => persistBeadsConfig(cfg),
|
|
18629
|
+
readEnabled: () => readBeadsEnabled(),
|
|
18630
|
+
emit: (event) => {
|
|
18631
|
+
const token = ctx.pluginAuthToken;
|
|
18632
|
+
if (!token) return;
|
|
18633
|
+
_beadsEmitChain = _beadsEmitChain.then(
|
|
18634
|
+
() => postBeadsEvent({
|
|
18635
|
+
sessionId: ctx.sessionId,
|
|
18636
|
+
pluginId: ctx.pluginId,
|
|
18637
|
+
pluginAuthToken: token,
|
|
18638
|
+
type: "beads_status",
|
|
18639
|
+
payload: Object.fromEntries(
|
|
18640
|
+
Object.entries(event).filter(([k2]) => k2 !== "type")
|
|
18641
|
+
)
|
|
18642
|
+
})
|
|
18643
|
+
);
|
|
18644
|
+
}
|
|
18645
|
+
};
|
|
18646
|
+
const result = await configureBeads(action, { agent: rawAgentId, cwd: process.cwd(), pluginAuthToken: ctx.pluginAuthToken }, deps);
|
|
18647
|
+
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18648
|
+
};
|
|
18426
18649
|
var terminalOpenH = async (ctx, cmd, parsed) => {
|
|
18427
18650
|
const r = openTerminal({
|
|
18428
18651
|
cols: typeof parsed.cols === "number" ? parsed.cols : void 0,
|
|
@@ -18859,8 +19082,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
|
|
|
18859
19082
|
if (args2.length === 0) return detection;
|
|
18860
19083
|
const binName = args2[0];
|
|
18861
19084
|
if (binName.startsWith("-")) return detection;
|
|
18862
|
-
const binPath =
|
|
18863
|
-
if (!
|
|
19085
|
+
const binPath = path47.join(cwd, "node_modules", ".bin", binName);
|
|
19086
|
+
if (!fs41.existsSync(binPath)) return detection;
|
|
18864
19087
|
return {
|
|
18865
19088
|
...detection,
|
|
18866
19089
|
command: binPath,
|
|
@@ -19408,7 +19631,8 @@ var handlers = {
|
|
|
19408
19631
|
save_preview_config: savePreviewConfigH,
|
|
19409
19632
|
env_read: envReadH,
|
|
19410
19633
|
env_write: envWriteH,
|
|
19411
|
-
headroom_configure: headroomConfigureH
|
|
19634
|
+
headroom_configure: headroomConfigureH,
|
|
19635
|
+
beads_configure: beadsConfigureH
|
|
19412
19636
|
};
|
|
19413
19637
|
async function dispatchCommand(ctx, cmd) {
|
|
19414
19638
|
if (cmd.type === "beads_action") {
|
|
@@ -19676,12 +19900,12 @@ function readTokenFromArgs(args2) {
|
|
|
19676
19900
|
}
|
|
19677
19901
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
19678
19902
|
if (fileFlag) {
|
|
19679
|
-
const
|
|
19903
|
+
const path61 = fileFlag.slice("--token-file=".length);
|
|
19680
19904
|
try {
|
|
19681
|
-
const content =
|
|
19682
|
-
if (content.length === 0) fail(`--token-file ${
|
|
19905
|
+
const content = fs42.readFileSync(path61, "utf8").trim();
|
|
19906
|
+
if (content.length === 0) fail(`--token-file ${path61} is empty`);
|
|
19683
19907
|
try {
|
|
19684
|
-
|
|
19908
|
+
fs42.unlinkSync(path61);
|
|
19685
19909
|
} catch {
|
|
19686
19910
|
}
|
|
19687
19911
|
return content;
|
|
@@ -19707,7 +19931,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
19707
19931
|
pluginId,
|
|
19708
19932
|
ideName: "codeam-cli (codespace)",
|
|
19709
19933
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
19710
|
-
hostname:
|
|
19934
|
+
hostname: os35.hostname(),
|
|
19711
19935
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
19712
19936
|
// Current git branch of the codespace's working directory, so the
|
|
19713
19937
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -19768,7 +19992,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
19768
19992
|
}
|
|
19769
19993
|
}
|
|
19770
19994
|
function pairAutoLockPath() {
|
|
19771
|
-
return
|
|
19995
|
+
return path48.join(os35.homedir(), ".codeam", "pair-auto.lock");
|
|
19772
19996
|
}
|
|
19773
19997
|
function isLivePairAuto(pid) {
|
|
19774
19998
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -19778,7 +20002,7 @@ function isLivePairAuto(pid) {
|
|
|
19778
20002
|
if (e.code !== "EPERM") return false;
|
|
19779
20003
|
}
|
|
19780
20004
|
try {
|
|
19781
|
-
return
|
|
20005
|
+
return fs42.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
19782
20006
|
} catch {
|
|
19783
20007
|
return true;
|
|
19784
20008
|
}
|
|
@@ -19788,24 +20012,24 @@ function isLiveCodeam(pid) {
|
|
|
19788
20012
|
}
|
|
19789
20013
|
function daemonLockPath(sessionId) {
|
|
19790
20014
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
19791
|
-
return
|
|
20015
|
+
return path48.join(os35.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
19792
20016
|
}
|
|
19793
20017
|
function acquireDaemonLock(sessionId) {
|
|
19794
20018
|
const lockPath = daemonLockPath(sessionId);
|
|
19795
20019
|
try {
|
|
19796
|
-
|
|
20020
|
+
fs42.mkdirSync(path48.dirname(lockPath), { recursive: true });
|
|
19797
20021
|
try {
|
|
19798
|
-
|
|
20022
|
+
fs42.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
19799
20023
|
} catch (e) {
|
|
19800
20024
|
if (e.code !== "EEXIST") throw e;
|
|
19801
|
-
const holder = Number(
|
|
20025
|
+
const holder = Number(fs42.readFileSync(lockPath, "utf8").trim());
|
|
19802
20026
|
if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
|
|
19803
|
-
|
|
20027
|
+
fs42.writeFileSync(lockPath, String(process.pid));
|
|
19804
20028
|
}
|
|
19805
20029
|
const release3 = () => {
|
|
19806
20030
|
try {
|
|
19807
|
-
if (
|
|
19808
|
-
|
|
20031
|
+
if (fs42.existsSync(lockPath) && Number(fs42.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
20032
|
+
fs42.unlinkSync(lockPath);
|
|
19809
20033
|
}
|
|
19810
20034
|
} catch {
|
|
19811
20035
|
}
|
|
@@ -19827,19 +20051,19 @@ function acquireDaemonLock(sessionId) {
|
|
|
19827
20051
|
function acquireSingletonLock() {
|
|
19828
20052
|
const lockPath = pairAutoLockPath();
|
|
19829
20053
|
try {
|
|
19830
|
-
|
|
20054
|
+
fs42.mkdirSync(path48.dirname(lockPath), { recursive: true });
|
|
19831
20055
|
try {
|
|
19832
|
-
|
|
20056
|
+
fs42.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
19833
20057
|
} catch (e) {
|
|
19834
20058
|
if (e.code !== "EEXIST") throw e;
|
|
19835
|
-
const holder = Number(
|
|
20059
|
+
const holder = Number(fs42.readFileSync(lockPath, "utf8").trim());
|
|
19836
20060
|
if (isLivePairAuto(holder)) return false;
|
|
19837
|
-
|
|
20061
|
+
fs42.writeFileSync(lockPath, String(process.pid));
|
|
19838
20062
|
}
|
|
19839
20063
|
process.once("exit", () => {
|
|
19840
20064
|
try {
|
|
19841
|
-
if (
|
|
19842
|
-
|
|
20065
|
+
if (fs42.existsSync(lockPath) && Number(fs42.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
20066
|
+
fs42.unlinkSync(lockPath);
|
|
19843
20067
|
}
|
|
19844
20068
|
} catch {
|
|
19845
20069
|
}
|
|
@@ -20284,19 +20508,19 @@ var AgentService = class _AgentService {
|
|
|
20284
20508
|
};
|
|
20285
20509
|
|
|
20286
20510
|
// src/agents/acp/adapters.ts
|
|
20287
|
-
var
|
|
20511
|
+
var path49 = __toESM(require("path"));
|
|
20288
20512
|
var require_ = require;
|
|
20289
20513
|
function resolveBin(pkgName, binName) {
|
|
20290
20514
|
try {
|
|
20291
20515
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
20292
20516
|
const manifest = require_(`${pkgName}/package.json`);
|
|
20293
|
-
const pkgDir =
|
|
20517
|
+
const pkgDir = path49.dirname(manifestPath);
|
|
20294
20518
|
const bin = manifest.bin;
|
|
20295
20519
|
if (!bin) return null;
|
|
20296
|
-
if (typeof bin === "string") return
|
|
20520
|
+
if (typeof bin === "string") return path49.resolve(pkgDir, bin);
|
|
20297
20521
|
const target = binName ?? Object.keys(bin)[0];
|
|
20298
20522
|
if (!target || !bin[target]) return null;
|
|
20299
|
-
return
|
|
20523
|
+
return path49.resolve(pkgDir, bin[target]);
|
|
20300
20524
|
} catch {
|
|
20301
20525
|
return null;
|
|
20302
20526
|
}
|
|
@@ -20366,9 +20590,9 @@ function requiresAcp(agent) {
|
|
|
20366
20590
|
var import_node_crypto7 = require("crypto");
|
|
20367
20591
|
|
|
20368
20592
|
// src/services/history.service.ts
|
|
20369
|
-
var
|
|
20370
|
-
var
|
|
20371
|
-
var
|
|
20593
|
+
var fs43 = __toESM(require("fs"));
|
|
20594
|
+
var path50 = __toESM(require("path"));
|
|
20595
|
+
var os36 = __toESM(require("os"));
|
|
20372
20596
|
var https7 = __toESM(require("https"));
|
|
20373
20597
|
var http6 = __toESM(require("http"));
|
|
20374
20598
|
var import_zod2 = require("zod");
|
|
@@ -20395,7 +20619,7 @@ function parseJsonl(filePath) {
|
|
|
20395
20619
|
const messages = [];
|
|
20396
20620
|
let raw;
|
|
20397
20621
|
try {
|
|
20398
|
-
raw =
|
|
20622
|
+
raw = fs43.readFileSync(filePath, "utf8");
|
|
20399
20623
|
} catch (err) {
|
|
20400
20624
|
if (err.code !== "ENOENT") {
|
|
20401
20625
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -20536,7 +20760,7 @@ var HistoryService = class _HistoryService {
|
|
|
20536
20760
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
20537
20761
|
}
|
|
20538
20762
|
get projectDir() {
|
|
20539
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
20763
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path50.join(os36.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
20540
20764
|
}
|
|
20541
20765
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
20542
20766
|
setCurrentConversationId(id) {
|
|
@@ -20548,7 +20772,7 @@ var HistoryService = class _HistoryService {
|
|
|
20548
20772
|
/** Return the current message count in the active conversation. */
|
|
20549
20773
|
getCurrentMessageCount() {
|
|
20550
20774
|
if (!this.currentConversationId) return 0;
|
|
20551
|
-
const filePath =
|
|
20775
|
+
const filePath = path50.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
20552
20776
|
return parseJsonl(filePath).length;
|
|
20553
20777
|
}
|
|
20554
20778
|
/**
|
|
@@ -20559,7 +20783,7 @@ var HistoryService = class _HistoryService {
|
|
|
20559
20783
|
const deadline = Date.now() + timeoutMs;
|
|
20560
20784
|
while (Date.now() < deadline) {
|
|
20561
20785
|
if (!this.currentConversationId) return null;
|
|
20562
|
-
const filePath =
|
|
20786
|
+
const filePath = path50.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
20563
20787
|
const messages = parseJsonl(filePath);
|
|
20564
20788
|
if (messages.length > previousCount) {
|
|
20565
20789
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -20585,16 +20809,16 @@ var HistoryService = class _HistoryService {
|
|
|
20585
20809
|
const dir = this.projectDir;
|
|
20586
20810
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
20587
20811
|
try {
|
|
20588
|
-
const files =
|
|
20812
|
+
const files = fs43.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
20589
20813
|
try {
|
|
20590
|
-
const stat3 =
|
|
20814
|
+
const stat3 = fs43.statSync(path50.join(dir, e.name));
|
|
20591
20815
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
20592
20816
|
} catch {
|
|
20593
20817
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
20594
20818
|
}
|
|
20595
20819
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
20596
20820
|
if (files.length > 0) {
|
|
20597
|
-
this.currentConversationId =
|
|
20821
|
+
this.currentConversationId = path50.basename(files[0].name, ".jsonl");
|
|
20598
20822
|
}
|
|
20599
20823
|
} catch {
|
|
20600
20824
|
}
|
|
@@ -20628,13 +20852,13 @@ var HistoryService = class _HistoryService {
|
|
|
20628
20852
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
20629
20853
|
let entries;
|
|
20630
20854
|
try {
|
|
20631
|
-
entries =
|
|
20855
|
+
entries = fs43.readdirSync(dir, { withFileTypes: true });
|
|
20632
20856
|
} catch {
|
|
20633
20857
|
return null;
|
|
20634
20858
|
}
|
|
20635
20859
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
20636
20860
|
try {
|
|
20637
|
-
const stat3 =
|
|
20861
|
+
const stat3 = fs43.statSync(path50.join(dir, e.name));
|
|
20638
20862
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
20639
20863
|
} catch {
|
|
20640
20864
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -20643,12 +20867,12 @@ var HistoryService = class _HistoryService {
|
|
|
20643
20867
|
if (files.length === 0) return null;
|
|
20644
20868
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
20645
20869
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
20646
|
-
return this.extractUsageFromFile(
|
|
20870
|
+
return this.extractUsageFromFile(path50.join(dir, targetFile));
|
|
20647
20871
|
}
|
|
20648
20872
|
extractUsageFromFile(filePath) {
|
|
20649
20873
|
let raw;
|
|
20650
20874
|
try {
|
|
20651
|
-
raw =
|
|
20875
|
+
raw = fs43.readFileSync(filePath, "utf8");
|
|
20652
20876
|
} catch {
|
|
20653
20877
|
return null;
|
|
20654
20878
|
}
|
|
@@ -20693,9 +20917,9 @@ var HistoryService = class _HistoryService {
|
|
|
20693
20917
|
let totalCost = 0;
|
|
20694
20918
|
let files;
|
|
20695
20919
|
try {
|
|
20696
|
-
files =
|
|
20920
|
+
files = fs43.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
20697
20921
|
try {
|
|
20698
|
-
return
|
|
20922
|
+
return fs43.statSync(path50.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
20699
20923
|
} catch {
|
|
20700
20924
|
return false;
|
|
20701
20925
|
}
|
|
@@ -20706,7 +20930,7 @@ var HistoryService = class _HistoryService {
|
|
|
20706
20930
|
for (const file of files) {
|
|
20707
20931
|
let raw;
|
|
20708
20932
|
try {
|
|
20709
|
-
raw =
|
|
20933
|
+
raw = fs43.readFileSync(path50.join(projectDir, file), "utf8");
|
|
20710
20934
|
} catch {
|
|
20711
20935
|
continue;
|
|
20712
20936
|
}
|
|
@@ -20785,7 +21009,7 @@ var HistoryService = class _HistoryService {
|
|
|
20785
21009
|
if (this.runtime.resolveHistoryFile) {
|
|
20786
21010
|
return this.runtime.resolveHistoryFile(this.cwd, sessionId);
|
|
20787
21011
|
}
|
|
20788
|
-
return
|
|
21012
|
+
return path50.join(this.projectDir, `${sessionId}.jsonl`);
|
|
20789
21013
|
}
|
|
20790
21014
|
/**
|
|
20791
21015
|
* Parse a conversation's messages from disk, agent-aware. Claude uses the
|
|
@@ -20819,7 +21043,7 @@ var HistoryService = class _HistoryService {
|
|
|
20819
21043
|
};
|
|
20820
21044
|
});
|
|
20821
21045
|
}
|
|
20822
|
-
return parseJsonl(
|
|
21046
|
+
return parseJsonl(path50.join(this.projectDir, `${sessionId}.jsonl`));
|
|
20823
21047
|
}
|
|
20824
21048
|
async loadConversation(sessionId) {
|
|
20825
21049
|
const messages = this.readConversation(sessionId);
|
|
@@ -20875,7 +21099,7 @@ var HistoryService = class _HistoryService {
|
|
|
20875
21099
|
if (!filePath) return false;
|
|
20876
21100
|
let mtimeMs;
|
|
20877
21101
|
try {
|
|
20878
|
-
mtimeMs =
|
|
21102
|
+
mtimeMs = fs43.statSync(filePath).mtimeMs;
|
|
20879
21103
|
} catch {
|
|
20880
21104
|
return false;
|
|
20881
21105
|
}
|
|
@@ -20944,10 +21168,10 @@ var HistoryService = class _HistoryService {
|
|
|
20944
21168
|
|
|
20945
21169
|
// src/agents/acp/client.ts
|
|
20946
21170
|
var import_node_child_process16 = require("child_process");
|
|
20947
|
-
var
|
|
21171
|
+
var fs44 = __toESM(require("fs/promises"));
|
|
20948
21172
|
var fsSync = __toESM(require("fs"));
|
|
20949
|
-
var
|
|
20950
|
-
var
|
|
21173
|
+
var os37 = __toESM(require("os"));
|
|
21174
|
+
var path51 = __toESM(require("path"));
|
|
20951
21175
|
var import_node_stream = require("stream");
|
|
20952
21176
|
|
|
20953
21177
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -23780,7 +24004,7 @@ var AcpClient = class {
|
|
|
23780
24004
|
},
|
|
23781
24005
|
readTextFile: async (params) => {
|
|
23782
24006
|
try {
|
|
23783
|
-
const content = await
|
|
24007
|
+
const content = await fs44.readFile(params.path, "utf8");
|
|
23784
24008
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
23785
24009
|
} catch (err) {
|
|
23786
24010
|
const code = err.code;
|
|
@@ -23800,7 +24024,7 @@ var AcpClient = class {
|
|
|
23800
24024
|
},
|
|
23801
24025
|
writeTextFile: async (params) => {
|
|
23802
24026
|
try {
|
|
23803
|
-
await
|
|
24027
|
+
await fs44.writeFile(params.path, params.content, "utf8");
|
|
23804
24028
|
return {};
|
|
23805
24029
|
} catch (err) {
|
|
23806
24030
|
const code = err.code;
|
|
@@ -23849,25 +24073,25 @@ function applyLineRange(content, line, limit) {
|
|
|
23849
24073
|
return { content: lines.slice(start2, end).join("\n") };
|
|
23850
24074
|
}
|
|
23851
24075
|
function knownAgentBinaryDirs() {
|
|
23852
|
-
const home =
|
|
24076
|
+
const home = os37.homedir();
|
|
23853
24077
|
const out2 = [];
|
|
23854
24078
|
out2.push("/tmp/codeam-node20/bin");
|
|
23855
24079
|
for (const root of [
|
|
23856
24080
|
"/usr/local/share/nvm/versions/node",
|
|
23857
|
-
|
|
24081
|
+
path51.join(home, ".nvm/versions/node")
|
|
23858
24082
|
]) {
|
|
23859
24083
|
try {
|
|
23860
24084
|
for (const child of fsSync.readdirSync(root)) {
|
|
23861
|
-
out2.push(
|
|
24085
|
+
out2.push(path51.join(root, child, "bin"));
|
|
23862
24086
|
}
|
|
23863
24087
|
} catch {
|
|
23864
24088
|
}
|
|
23865
24089
|
}
|
|
23866
|
-
out2.push(
|
|
24090
|
+
out2.push(path51.join(home, ".volta/bin"));
|
|
23867
24091
|
out2.push("/usr/local/bin");
|
|
23868
24092
|
out2.push("/usr/bin");
|
|
23869
|
-
out2.push(
|
|
23870
|
-
out2.push(
|
|
24093
|
+
out2.push(path51.join(home, ".local/bin"));
|
|
24094
|
+
out2.push(path51.join(home, "bin"));
|
|
23871
24095
|
return out2.filter((p2) => {
|
|
23872
24096
|
try {
|
|
23873
24097
|
return fsSync.statSync(p2).isDirectory();
|
|
@@ -23878,7 +24102,7 @@ function knownAgentBinaryDirs() {
|
|
|
23878
24102
|
}
|
|
23879
24103
|
function expandPathForAgentBinaries(existingPath) {
|
|
23880
24104
|
const existing = new Set(
|
|
23881
|
-
existingPath.split(
|
|
24105
|
+
existingPath.split(path51.delimiter).filter((p2) => p2.length > 0)
|
|
23882
24106
|
);
|
|
23883
24107
|
const additions = [];
|
|
23884
24108
|
for (const dir of knownAgentBinaryDirs()) {
|
|
@@ -23888,7 +24112,7 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
23888
24112
|
}
|
|
23889
24113
|
}
|
|
23890
24114
|
if (additions.length === 0) return existingPath;
|
|
23891
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
24115
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path51.delimiter);
|
|
23892
24116
|
}
|
|
23893
24117
|
|
|
23894
24118
|
// src/services/streaming/transport.ts
|
|
@@ -24300,15 +24524,15 @@ function commonPrefixLength(a, b) {
|
|
|
24300
24524
|
|
|
24301
24525
|
// src/agents/acp/onboarding.ts
|
|
24302
24526
|
var import_child_process22 = require("child_process");
|
|
24303
|
-
var
|
|
24304
|
-
var
|
|
24305
|
-
var
|
|
24527
|
+
var fs45 = __toESM(require("fs"));
|
|
24528
|
+
var os38 = __toESM(require("os"));
|
|
24529
|
+
var path52 = __toESM(require("path"));
|
|
24306
24530
|
var _onboardingSeam = {
|
|
24307
|
-
markerPath: (sessionId) =>
|
|
24308
|
-
exists: (p2) =>
|
|
24531
|
+
markerPath: (sessionId) => path52.join(os38.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
24532
|
+
exists: (p2) => fs45.existsSync(p2),
|
|
24309
24533
|
write: (p2) => {
|
|
24310
|
-
|
|
24311
|
-
|
|
24534
|
+
fs45.mkdirSync(path52.dirname(p2), { recursive: true });
|
|
24535
|
+
fs45.writeFileSync(p2, "");
|
|
24312
24536
|
},
|
|
24313
24537
|
disabled: () => {
|
|
24314
24538
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -24345,7 +24569,7 @@ function resolveRepoName(cwd) {
|
|
|
24345
24569
|
if (name) return name;
|
|
24346
24570
|
}
|
|
24347
24571
|
}
|
|
24348
|
-
const base =
|
|
24572
|
+
const base = path52.basename(cwd || "");
|
|
24349
24573
|
if (base && !isUuid(base)) return base;
|
|
24350
24574
|
return "this project";
|
|
24351
24575
|
}
|
|
@@ -24618,13 +24842,28 @@ function extractSelectPrompt(text) {
|
|
|
24618
24842
|
};
|
|
24619
24843
|
}
|
|
24620
24844
|
|
|
24845
|
+
// src/agents/acp/inputSuggestion.ts
|
|
24846
|
+
var MIN_LEN = 8;
|
|
24847
|
+
var MAX_LEN = 200;
|
|
24848
|
+
function deriveInputSuggestion(finalText) {
|
|
24849
|
+
if (finalText.length === 0) return null;
|
|
24850
|
+
const lines = finalText.split("\n");
|
|
24851
|
+
let i = lines.length - 1;
|
|
24852
|
+
while (i >= 0 && lines[i].trim() === "") i--;
|
|
24853
|
+
if (i < 0) return null;
|
|
24854
|
+
const lastLine = lines[i].trim();
|
|
24855
|
+
if (!lastLine.endsWith("?")) return null;
|
|
24856
|
+
if (lastLine.length < MIN_LEN || lastLine.length > MAX_LEN) return null;
|
|
24857
|
+
return lastLine;
|
|
24858
|
+
}
|
|
24859
|
+
|
|
24621
24860
|
// src/services/turn-files/turn-file-aggregator.ts
|
|
24622
24861
|
var import_crypto5 = require("crypto");
|
|
24623
24862
|
|
|
24624
24863
|
// src/services/turn-files/git-changeset.ts
|
|
24625
24864
|
var import_child_process23 = require("child_process");
|
|
24626
|
-
var
|
|
24627
|
-
var
|
|
24865
|
+
var fs46 = __toESM(require("fs/promises"));
|
|
24866
|
+
var path53 = __toESM(require("path"));
|
|
24628
24867
|
async function collectRepoChangeset(opts) {
|
|
24629
24868
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
24630
24869
|
if (status2 === null) return null;
|
|
@@ -24642,7 +24881,7 @@ async function collectRepoChangeset(opts) {
|
|
|
24642
24881
|
let stats;
|
|
24643
24882
|
if (row.fileStatus === "added" && numstatEntry === void 0) {
|
|
24644
24883
|
const lineCount = await readUntrackedLineCount(
|
|
24645
|
-
|
|
24884
|
+
path53.join(opts.repoRoot, row.filePath)
|
|
24646
24885
|
);
|
|
24647
24886
|
stats = { added: lineCount, removed: 0 };
|
|
24648
24887
|
} else {
|
|
@@ -24673,7 +24912,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
24673
24912
|
}
|
|
24674
24913
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
24675
24914
|
try {
|
|
24676
|
-
const content = await
|
|
24915
|
+
const content = await fs46.readFile(absPath, "utf8");
|
|
24677
24916
|
let count = 0;
|
|
24678
24917
|
let pos = -1;
|
|
24679
24918
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -24765,7 +25004,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
24765
25004
|
});
|
|
24766
25005
|
}
|
|
24767
25006
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
24768
|
-
const
|
|
25007
|
+
const fs50 = await import("fs/promises");
|
|
24769
25008
|
const out2 = [];
|
|
24770
25009
|
await walk(workingDir, 0);
|
|
24771
25010
|
return out2;
|
|
@@ -24773,7 +25012,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
24773
25012
|
if (depth > maxDepth) return;
|
|
24774
25013
|
let entries = [];
|
|
24775
25014
|
try {
|
|
24776
|
-
const dirents = await
|
|
25015
|
+
const dirents = await fs50.readdir(dir, { withFileTypes: true });
|
|
24777
25016
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
24778
25017
|
} catch {
|
|
24779
25018
|
return;
|
|
@@ -24784,8 +25023,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
24784
25023
|
if (hasGit) {
|
|
24785
25024
|
out2.push({
|
|
24786
25025
|
repoRoot: dir,
|
|
24787
|
-
repoPath:
|
|
24788
|
-
repoName:
|
|
25026
|
+
repoPath: path53.relative(workingDir, dir),
|
|
25027
|
+
repoName: path53.basename(dir)
|
|
24789
25028
|
});
|
|
24790
25029
|
return;
|
|
24791
25030
|
}
|
|
@@ -24793,14 +25032,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
24793
25032
|
if (!entry.isDirectory) continue;
|
|
24794
25033
|
if (entry.name === "node_modules") continue;
|
|
24795
25034
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
24796
|
-
await walk(
|
|
25035
|
+
await walk(path53.join(dir, entry.name), depth + 1);
|
|
24797
25036
|
}
|
|
24798
25037
|
}
|
|
24799
25038
|
}
|
|
24800
25039
|
|
|
24801
25040
|
// src/services/turn-files/files-outbox.ts
|
|
24802
|
-
var
|
|
24803
|
-
var
|
|
25041
|
+
var fs47 = __toESM(require("fs/promises"));
|
|
25042
|
+
var path54 = __toESM(require("path"));
|
|
24804
25043
|
var import_os7 = require("os");
|
|
24805
25044
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
24806
25045
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -24833,16 +25072,16 @@ var FilesOutbox = class {
|
|
|
24833
25072
|
backoffIndex = 0;
|
|
24834
25073
|
stopped = false;
|
|
24835
25074
|
constructor(opts) {
|
|
24836
|
-
const base = opts.baseDir ??
|
|
24837
|
-
this.filePath =
|
|
25075
|
+
const base = opts.baseDir ?? path54.join(homeDir(), HOME_OUTBOX_DIR);
|
|
25076
|
+
this.filePath = path54.join(base, `${opts.sessionId}.jsonl`);
|
|
24838
25077
|
this.post = opts.post;
|
|
24839
25078
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
24840
25079
|
}
|
|
24841
25080
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
24842
25081
|
* line is durable on disk (not once the POST succeeds). */
|
|
24843
25082
|
async enqueue(entry) {
|
|
24844
|
-
await
|
|
24845
|
-
await
|
|
25083
|
+
await fs47.mkdir(path54.dirname(this.filePath), { recursive: true });
|
|
25084
|
+
await fs47.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
24846
25085
|
this.backoffIndex = 0;
|
|
24847
25086
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
24848
25087
|
}
|
|
@@ -24931,7 +25170,7 @@ var FilesOutbox = class {
|
|
|
24931
25170
|
async readAll() {
|
|
24932
25171
|
let raw = "";
|
|
24933
25172
|
try {
|
|
24934
|
-
raw = await
|
|
25173
|
+
raw = await fs47.readFile(this.filePath, "utf8");
|
|
24935
25174
|
} catch {
|
|
24936
25175
|
return [];
|
|
24937
25176
|
}
|
|
@@ -24955,12 +25194,12 @@ var FilesOutbox = class {
|
|
|
24955
25194
|
async rewrite(entries) {
|
|
24956
25195
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
24957
25196
|
if (entries.length === 0) {
|
|
24958
|
-
await
|
|
25197
|
+
await fs47.unlink(this.filePath).catch(() => void 0);
|
|
24959
25198
|
return;
|
|
24960
25199
|
}
|
|
24961
25200
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
24962
|
-
await
|
|
24963
|
-
await
|
|
25201
|
+
await fs47.writeFile(tmpPath, payload, "utf8");
|
|
25202
|
+
await fs47.rename(tmpPath, this.filePath);
|
|
24964
25203
|
}
|
|
24965
25204
|
};
|
|
24966
25205
|
function applyJitter(ms) {
|
|
@@ -25489,7 +25728,7 @@ var StreamingState = class {
|
|
|
25489
25728
|
this.publisher.publishOutput({ type: "text", content: finalText, done: true }),
|
|
25490
25729
|
flushSc
|
|
25491
25730
|
]);
|
|
25492
|
-
return;
|
|
25731
|
+
return false;
|
|
25493
25732
|
}
|
|
25494
25733
|
log.info(
|
|
25495
25734
|
"acpRunner",
|
|
@@ -25516,6 +25755,7 @@ var StreamingState = class {
|
|
|
25516
25755
|
done: true
|
|
25517
25756
|
});
|
|
25518
25757
|
await flushSc;
|
|
25758
|
+
return true;
|
|
25519
25759
|
}
|
|
25520
25760
|
};
|
|
25521
25761
|
var PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -25889,7 +26129,9 @@ async function runAcpSession(opts) {
|
|
|
25889
26129
|
flushHistory: () => void history.flush(),
|
|
25890
26130
|
beginTurn: () => streaming.beginTurn(),
|
|
25891
26131
|
getCurrentText: () => streaming.getCurrentText(),
|
|
25892
|
-
closeTurn: () =>
|
|
26132
|
+
closeTurn: async () => {
|
|
26133
|
+
await streaming.closeTurnWithInteractiveDetection();
|
|
26134
|
+
},
|
|
25893
26135
|
recoverFromFailedTurn: () => recoverFromFailedTurn(client2, streaming),
|
|
25894
26136
|
reconnectWith1mDisabled,
|
|
25895
26137
|
promptAgent: (blocks) => client2.prompt(blocks),
|
|
@@ -26090,13 +26332,19 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
26090
26332
|
} else if (shouldOfferOneMRecovery({ detail: "", recentStderr: recentStderr.join("\n"), finalText })) {
|
|
26091
26333
|
await oneMRecovery.offer(cmd.id, blocks);
|
|
26092
26334
|
} else {
|
|
26093
|
-
await streaming.closeTurnWithInteractiveDetection();
|
|
26335
|
+
const emittedSelectPrompt = await streaming.closeTurnWithInteractiveDetection();
|
|
26094
26336
|
const replyLine = formatAgentReplyLine(finalText);
|
|
26095
26337
|
if (replyLine.length > 0) {
|
|
26096
26338
|
showInfo(replyLine);
|
|
26097
26339
|
}
|
|
26098
26340
|
history.appendAgentReply(finalText);
|
|
26099
26341
|
void history.flush();
|
|
26342
|
+
if (!emittedSelectPrompt) {
|
|
26343
|
+
const suggestion = deriveInputSuggestion(finalText);
|
|
26344
|
+
if (suggestion !== null) {
|
|
26345
|
+
void publisher.publishOutput({ type: "input_suggestion", content: suggestion, done: true });
|
|
26346
|
+
}
|
|
26347
|
+
}
|
|
26100
26348
|
turnFiles.flushTurn().catch((err) => {
|
|
26101
26349
|
log.warn("acpRunner", `turnFiles.flushTurn failed: ${describeError(err)}`);
|
|
26102
26350
|
});
|
|
@@ -27470,15 +27718,15 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
27470
27718
|
}
|
|
27471
27719
|
|
|
27472
27720
|
// src/agents/claude/onboarding.ts
|
|
27473
|
-
var
|
|
27474
|
-
var
|
|
27475
|
-
var
|
|
27721
|
+
var fs48 = __toESM(require("fs"));
|
|
27722
|
+
var os39 = __toESM(require("os"));
|
|
27723
|
+
var path55 = __toESM(require("path"));
|
|
27476
27724
|
function ensureClaudeOnboarded() {
|
|
27477
27725
|
try {
|
|
27478
|
-
const file =
|
|
27726
|
+
const file = path55.join(os39.homedir(), ".claude.json");
|
|
27479
27727
|
let config = {};
|
|
27480
27728
|
try {
|
|
27481
|
-
config = JSON.parse(
|
|
27729
|
+
config = JSON.parse(fs48.readFileSync(file, "utf8"));
|
|
27482
27730
|
} catch {
|
|
27483
27731
|
}
|
|
27484
27732
|
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
@@ -27489,8 +27737,8 @@ function ensureClaudeOnboarded() {
|
|
|
27489
27737
|
if (typeof config.lastOnboardingVersion !== "string") {
|
|
27490
27738
|
config.lastOnboardingVersion = "2.1.177";
|
|
27491
27739
|
}
|
|
27492
|
-
|
|
27493
|
-
|
|
27740
|
+
fs48.mkdirSync(path55.dirname(file), { recursive: true });
|
|
27741
|
+
fs48.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
27494
27742
|
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
27495
27743
|
} catch (err) {
|
|
27496
27744
|
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
@@ -27568,6 +27816,14 @@ async function start(requestedAgent) {
|
|
|
27568
27816
|
process.once("exit", () => {
|
|
27569
27817
|
headroomReporter?.stop();
|
|
27570
27818
|
});
|
|
27819
|
+
const localHeadroomReporter = session.pluginAuthToken ? maybeResumeLocalHeadroomReporter({
|
|
27820
|
+
sessionId: session.id,
|
|
27821
|
+
pluginId,
|
|
27822
|
+
pluginAuthToken: session.pluginAuthToken
|
|
27823
|
+
}) : null;
|
|
27824
|
+
process.once("exit", () => {
|
|
27825
|
+
localHeadroomReporter?.stop();
|
|
27826
|
+
});
|
|
27571
27827
|
if (process.env.CODESPACES === "true") ensureClaudeOnboarded();
|
|
27572
27828
|
let beads = null;
|
|
27573
27829
|
const getBeads = () => beads;
|
|
@@ -28132,7 +28388,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
|
|
|
28132
28388
|
var import_child_process24 = require("child_process");
|
|
28133
28389
|
var import_util4 = require("util");
|
|
28134
28390
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
28135
|
-
var
|
|
28391
|
+
var path56 = __toESM(require("path"));
|
|
28136
28392
|
var execFileP6 = (0, import_util4.promisify)(import_child_process24.execFile);
|
|
28137
28393
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
28138
28394
|
function resetStdinForChild() {
|
|
@@ -28621,7 +28877,7 @@ var GitHubCodespacesProvider = class {
|
|
|
28621
28877
|
});
|
|
28622
28878
|
}
|
|
28623
28879
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
28624
|
-
const remoteDir =
|
|
28880
|
+
const remoteDir = path56.posix.dirname(remotePath);
|
|
28625
28881
|
const parts = [
|
|
28626
28882
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
28627
28883
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -28691,7 +28947,7 @@ function shellQuote(s) {
|
|
|
28691
28947
|
// src/services/providers/gitpod.ts
|
|
28692
28948
|
var import_child_process25 = require("child_process");
|
|
28693
28949
|
var import_util5 = require("util");
|
|
28694
|
-
var
|
|
28950
|
+
var path57 = __toESM(require("path"));
|
|
28695
28951
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
28696
28952
|
var execFileP7 = (0, import_util5.promisify)(import_child_process25.execFile);
|
|
28697
28953
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -28931,7 +29187,7 @@ var GitpodProvider = class {
|
|
|
28931
29187
|
});
|
|
28932
29188
|
}
|
|
28933
29189
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
28934
|
-
const remoteDir =
|
|
29190
|
+
const remoteDir = path57.posix.dirname(remotePath);
|
|
28935
29191
|
const parts = [
|
|
28936
29192
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
28937
29193
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -28967,7 +29223,7 @@ function shellQuote2(s) {
|
|
|
28967
29223
|
// src/services/providers/gitlab-workspaces.ts
|
|
28968
29224
|
var import_child_process26 = require("child_process");
|
|
28969
29225
|
var import_util6 = require("util");
|
|
28970
|
-
var
|
|
29226
|
+
var path58 = __toESM(require("path"));
|
|
28971
29227
|
var execFileP8 = (0, import_util6.promisify)(import_child_process26.execFile);
|
|
28972
29228
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
28973
29229
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -29227,7 +29483,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
29227
29483
|
}
|
|
29228
29484
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
29229
29485
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
29230
|
-
const remoteDir =
|
|
29486
|
+
const remoteDir = path58.posix.dirname(remotePath);
|
|
29231
29487
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
29232
29488
|
if (options.mode != null) {
|
|
29233
29489
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -29295,7 +29551,7 @@ function shellQuote3(s) {
|
|
|
29295
29551
|
// src/services/providers/railway.ts
|
|
29296
29552
|
var import_child_process27 = require("child_process");
|
|
29297
29553
|
var import_util7 = require("util");
|
|
29298
|
-
var
|
|
29554
|
+
var path59 = __toESM(require("path"));
|
|
29299
29555
|
var execFileP9 = (0, import_util7.promisify)(import_child_process27.execFile);
|
|
29300
29556
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
29301
29557
|
function resetStdinForChild4() {
|
|
@@ -29531,7 +29787,7 @@ var RailwayProvider = class {
|
|
|
29531
29787
|
if (!projectId || !serviceId) {
|
|
29532
29788
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
29533
29789
|
}
|
|
29534
|
-
const remoteDir =
|
|
29790
|
+
const remoteDir = path59.posix.dirname(remotePath);
|
|
29535
29791
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
29536
29792
|
if (options.mode != null) {
|
|
29537
29793
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -30177,8 +30433,8 @@ async function invite() {
|
|
|
30177
30433
|
var import_node_dns = require("dns");
|
|
30178
30434
|
var import_node_util5 = require("util");
|
|
30179
30435
|
var import_node_crypto8 = require("crypto");
|
|
30180
|
-
var
|
|
30181
|
-
var
|
|
30436
|
+
var fs49 = __toESM(require("fs"));
|
|
30437
|
+
var path60 = __toESM(require("path"));
|
|
30182
30438
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
30183
30439
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
30184
30440
|
async function checkDns(apiBase2) {
|
|
@@ -30234,13 +30490,13 @@ async function checkHealth(apiBase2) {
|
|
|
30234
30490
|
}
|
|
30235
30491
|
}
|
|
30236
30492
|
function checkConfigDir() {
|
|
30237
|
-
const dir =
|
|
30493
|
+
const dir = path60.join(require("os").homedir(), ".codeam");
|
|
30238
30494
|
try {
|
|
30239
|
-
|
|
30240
|
-
const probe =
|
|
30241
|
-
|
|
30242
|
-
const read2 =
|
|
30243
|
-
|
|
30495
|
+
fs49.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
30496
|
+
const probe = path60.join(dir, ".doctor-probe");
|
|
30497
|
+
fs49.writeFileSync(probe, "ok", { mode: 384 });
|
|
30498
|
+
const read2 = fs49.readFileSync(probe, "utf8");
|
|
30499
|
+
fs49.unlinkSync(probe);
|
|
30244
30500
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
30245
30501
|
return {
|
|
30246
30502
|
id: "config-dir",
|
|
@@ -30280,9 +30536,9 @@ function checkSessions() {
|
|
|
30280
30536
|
}
|
|
30281
30537
|
}
|
|
30282
30538
|
function checkAgentBinaries() {
|
|
30283
|
-
const
|
|
30539
|
+
const os41 = createOsStrategy();
|
|
30284
30540
|
return getEnabledAgents().map((meta) => {
|
|
30285
|
-
const found =
|
|
30541
|
+
const found = os41.findInPath(meta.binaryName);
|
|
30286
30542
|
return {
|
|
30287
30543
|
id: `agent-${meta.id}`,
|
|
30288
30544
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -30304,7 +30560,7 @@ function checkNodePty() {
|
|
|
30304
30560
|
detail: "not required on this platform"
|
|
30305
30561
|
};
|
|
30306
30562
|
}
|
|
30307
|
-
const vendoredPath =
|
|
30563
|
+
const vendoredPath = path60.join(__dirname, "vendor", "node-pty");
|
|
30308
30564
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
30309
30565
|
try {
|
|
30310
30566
|
require(target);
|
|
@@ -30346,7 +30602,7 @@ function checkChokidar() {
|
|
|
30346
30602
|
}
|
|
30347
30603
|
async function doctor(args2 = []) {
|
|
30348
30604
|
const json = args2.includes("--json");
|
|
30349
|
-
const cliVersion = true ? "2.
|
|
30605
|
+
const cliVersion = true ? "2.50.0" : "0.0.0-dev";
|
|
30350
30606
|
const apiBase2 = resolveApiBaseUrl();
|
|
30351
30607
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
30352
30608
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -30545,7 +30801,7 @@ async function completion(args2) {
|
|
|
30545
30801
|
// src/commands/version.ts
|
|
30546
30802
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
30547
30803
|
function version2() {
|
|
30548
|
-
const v = true ? "2.
|
|
30804
|
+
const v = true ? "2.50.0" : "unknown";
|
|
30549
30805
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
30550
30806
|
}
|
|
30551
30807
|
|
|
@@ -30694,10 +30950,10 @@ var EXIT_CODE_NAMES = {
|
|
|
30694
30950
|
};
|
|
30695
30951
|
|
|
30696
30952
|
// src/index.ts
|
|
30697
|
-
var
|
|
30953
|
+
var os40 = __toESM(require("os"));
|
|
30698
30954
|
if (!process.env.HOME) {
|
|
30699
30955
|
try {
|
|
30700
|
-
const home =
|
|
30956
|
+
const home = os40.homedir();
|
|
30701
30957
|
if (home) process.env.HOME = home;
|
|
30702
30958
|
} catch {
|
|
30703
30959
|
}
|