codeam-cli 2.49.5 → 2.51.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 +26 -0
- package/dist/index.js +729 -222
- 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.51.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.51.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.`
|
|
@@ -14556,6 +14578,14 @@ function mapStatsToSavings(stats, prev, inputPricePerMillion = DEFAULT_INPUT_PRI
|
|
|
14556
14578
|
};
|
|
14557
14579
|
return { next, delta };
|
|
14558
14580
|
}
|
|
14581
|
+
function defaultGetBudgetEnv() {
|
|
14582
|
+
const raw = process.env["HEADROOM_BUDGET"];
|
|
14583
|
+
if (!raw) return null;
|
|
14584
|
+
const budgetUsd = Number(raw);
|
|
14585
|
+
if (!isFinite(budgetUsd) || budgetUsd <= 0) return null;
|
|
14586
|
+
const budgetPeriod = process.env["HEADROOM_BUDGET_PERIOD"] ?? "daily";
|
|
14587
|
+
return { budgetUsd, budgetPeriod };
|
|
14588
|
+
}
|
|
14559
14589
|
var HeadroomStatsReporter = class {
|
|
14560
14590
|
constructor(deps) {
|
|
14561
14591
|
this.deps = deps;
|
|
@@ -14569,14 +14599,22 @@ var HeadroomStatsReporter = class {
|
|
|
14569
14599
|
}
|
|
14570
14600
|
async tick() {
|
|
14571
14601
|
try {
|
|
14602
|
+
const stats = await this.deps.fetchStats();
|
|
14572
14603
|
const { next, delta } = mapStatsToSavings(
|
|
14573
|
-
|
|
14604
|
+
stats,
|
|
14574
14605
|
this.prev,
|
|
14575
14606
|
this.deps.inputPricePerMillionUsd ?? DEFAULT_INPUT_PRICE_PER_MILLION
|
|
14576
14607
|
);
|
|
14577
14608
|
this.prev = next;
|
|
14578
14609
|
if (delta.compressionTokens > 0 || delta.compressionSavingsUsd > 0 || delta.rawTokensEst > 0 || delta.cacheReadTokens > 0 || delta.cacheSavingsUsd > 0) {
|
|
14579
|
-
|
|
14610
|
+
const getBudgetEnv = this.deps.getBudgetEnv ?? defaultGetBudgetEnv;
|
|
14611
|
+
const budgetEnv = getBudgetEnv();
|
|
14612
|
+
const budget = budgetEnv ? {
|
|
14613
|
+
periodSpendUsd: stats.cost?.cost_with_headroom_usd ?? 0,
|
|
14614
|
+
budgetUsd: budgetEnv.budgetUsd,
|
|
14615
|
+
budgetPeriod: budgetEnv.budgetPeriod
|
|
14616
|
+
} : void 0;
|
|
14617
|
+
await this.deps.postSavings(delta, budget);
|
|
14580
14618
|
}
|
|
14581
14619
|
} catch {
|
|
14582
14620
|
}
|
|
@@ -14589,6 +14627,14 @@ var HeadroomStatsReporter = class {
|
|
|
14589
14627
|
}
|
|
14590
14628
|
};
|
|
14591
14629
|
|
|
14630
|
+
// src/services/headroom/budget-args.ts
|
|
14631
|
+
function buildBudgetProxyArgs(env) {
|
|
14632
|
+
const budget = env["HEADROOM_BUDGET"];
|
|
14633
|
+
if (!budget) return [];
|
|
14634
|
+
const period = env["HEADROOM_BUDGET_PERIOD"] ?? "daily";
|
|
14635
|
+
return ["--budget", budget, "--budget-period", period];
|
|
14636
|
+
}
|
|
14637
|
+
|
|
14592
14638
|
// src/lib/updateNotifier.ts
|
|
14593
14639
|
var fs30 = __toESM(require("fs"));
|
|
14594
14640
|
var os27 = __toESM(require("os"));
|
|
@@ -14747,7 +14793,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
14747
14793
|
if (process.env.NODE_ENV === "test") return;
|
|
14748
14794
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
14749
14795
|
if (process.env.CI) return;
|
|
14750
|
-
const current = true ? "2.
|
|
14796
|
+
const current = true ? "2.51.0" : null;
|
|
14751
14797
|
if (!current) return;
|
|
14752
14798
|
const cache = readCache();
|
|
14753
14799
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -14764,7 +14810,7 @@ function checkForUpdates() {
|
|
|
14764
14810
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
14765
14811
|
if (process.env.CI) return;
|
|
14766
14812
|
if (!process.stdout.isTTY) return;
|
|
14767
|
-
const current = true ? "2.
|
|
14813
|
+
const current = true ? "2.51.0" : null;
|
|
14768
14814
|
if (!current) return;
|
|
14769
14815
|
const cache = readCache();
|
|
14770
14816
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -14801,7 +14847,7 @@ function maybeStartHeadroomReporter(ctx) {
|
|
|
14801
14847
|
const res = await fetch("http://localhost:8787/stats");
|
|
14802
14848
|
return res.json();
|
|
14803
14849
|
},
|
|
14804
|
-
postSavings: async (delta) => {
|
|
14850
|
+
postSavings: async (delta, budget) => {
|
|
14805
14851
|
await fetch(ingestUrl, {
|
|
14806
14852
|
method: "POST",
|
|
14807
14853
|
headers: {
|
|
@@ -14812,7 +14858,12 @@ function maybeStartHeadroomReporter(ctx) {
|
|
|
14812
14858
|
sessionId: ctx.sessionId,
|
|
14813
14859
|
pluginId: ctx.pluginId,
|
|
14814
14860
|
agentId: process.env["HEADROOM_AGENT"] ?? "claude",
|
|
14815
|
-
savings: delta
|
|
14861
|
+
savings: delta,
|
|
14862
|
+
...budget ? {
|
|
14863
|
+
periodSpendUsd: budget.periodSpendUsd,
|
|
14864
|
+
budgetUsd: budget.budgetUsd,
|
|
14865
|
+
budgetPeriod: budget.budgetPeriod
|
|
14866
|
+
} : {}
|
|
14816
14867
|
})
|
|
14817
14868
|
});
|
|
14818
14869
|
}
|
|
@@ -14845,7 +14896,7 @@ function maybeResumeLocalHeadroomReporter(ctx) {
|
|
|
14845
14896
|
// Body MUST match HeadroomSavingsDto + PluginAuthGuard (sessionId +
|
|
14846
14897
|
// pluginId in the body) — same shape as the codespace reporter above and
|
|
14847
14898
|
// the on-demand `startReporter` in handlers.ts.
|
|
14848
|
-
postSavings: async (delta) => {
|
|
14899
|
+
postSavings: async (delta, budget) => {
|
|
14849
14900
|
await fetch(ingestUrl, {
|
|
14850
14901
|
method: "POST",
|
|
14851
14902
|
headers: {
|
|
@@ -14856,7 +14907,12 @@ function maybeResumeLocalHeadroomReporter(ctx) {
|
|
|
14856
14907
|
sessionId: ctx.sessionId,
|
|
14857
14908
|
pluginId: ctx.pluginId,
|
|
14858
14909
|
agentId: agent,
|
|
14859
|
-
savings: delta
|
|
14910
|
+
savings: delta,
|
|
14911
|
+
...budget ? {
|
|
14912
|
+
periodSpendUsd: budget.periodSpendUsd,
|
|
14913
|
+
budgetUsd: budget.budgetUsd,
|
|
14914
|
+
budgetPeriod: budget.budgetPeriod
|
|
14915
|
+
} : {}
|
|
14860
14916
|
})
|
|
14861
14917
|
});
|
|
14862
14918
|
}
|
|
@@ -15157,11 +15213,16 @@ function readHeadroomChildEnv() {
|
|
|
15157
15213
|
if (typeof parsed !== "object" || parsed === null) return {};
|
|
15158
15214
|
const o = parsed;
|
|
15159
15215
|
if (o.enabled === true && typeof o.agent === "string" && o.agent.length > 0 && typeof o.ingestUrl === "string" && o.ingestUrl.length > 0) {
|
|
15160
|
-
|
|
15216
|
+
const env = {
|
|
15161
15217
|
HEADROOM_ENABLED: "1",
|
|
15162
15218
|
HEADROOM_AGENT: o.agent,
|
|
15163
15219
|
HEADROOM_SAVINGS_INGEST_URL: o.ingestUrl
|
|
15164
15220
|
};
|
|
15221
|
+
if (o.budgetEnabled === true && typeof o.budgetUsd === "number") {
|
|
15222
|
+
env["HEADROOM_BUDGET"] = String(o.budgetUsd);
|
|
15223
|
+
env["HEADROOM_BUDGET_PERIOD"] = typeof o.budgetPeriod === "string" ? o.budgetPeriod : "daily";
|
|
15224
|
+
}
|
|
15225
|
+
return env;
|
|
15165
15226
|
}
|
|
15166
15227
|
return {};
|
|
15167
15228
|
} catch {
|
|
@@ -15417,11 +15478,16 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
|
|
|
15417
15478
|
}
|
|
15418
15479
|
onProgress("proxy");
|
|
15419
15480
|
try {
|
|
15420
|
-
const
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15481
|
+
const proxyEnv = { ...process.env, HEADROOM_KOMPRESS_BACKEND: "onnx_cpu" };
|
|
15482
|
+
const proxy = (0, import_node_child_process14.spawn)(
|
|
15483
|
+
"headroom",
|
|
15484
|
+
["proxy", "--port", "8787", ...buildBudgetProxyArgs(proxyEnv)],
|
|
15485
|
+
{
|
|
15486
|
+
stdio: "ignore",
|
|
15487
|
+
detached: true,
|
|
15488
|
+
env: proxyEnv
|
|
15489
|
+
}
|
|
15490
|
+
);
|
|
15425
15491
|
proxy.once("error", (e) => {
|
|
15426
15492
|
log.warn(
|
|
15427
15493
|
"host-agent",
|
|
@@ -15445,7 +15511,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
|
|
|
15445
15511
|
detached: false
|
|
15446
15512
|
});
|
|
15447
15513
|
function currentCliVersion() {
|
|
15448
|
-
return true ? "2.
|
|
15514
|
+
return true ? "2.51.0" : null;
|
|
15449
15515
|
}
|
|
15450
15516
|
function runCmd(cmd, args2, timeoutMs) {
|
|
15451
15517
|
return new Promise((resolve7) => {
|
|
@@ -17126,11 +17192,11 @@ function resolveDoltInstallStrategy(platform3) {
|
|
|
17126
17192
|
}
|
|
17127
17193
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
17128
17194
|
function doltPlatformTuple(platform3, arch2) {
|
|
17129
|
-
const
|
|
17195
|
+
const os41 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
|
|
17130
17196
|
const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
|
|
17131
17197
|
if (!a) return null;
|
|
17132
|
-
if (
|
|
17133
|
-
return `${
|
|
17198
|
+
if (os41 === "windows" && a !== "amd64") return null;
|
|
17199
|
+
return `${os41}-${a}`;
|
|
17134
17200
|
}
|
|
17135
17201
|
function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
|
|
17136
17202
|
const tuple = doltPlatformTuple(platform3, arch2);
|
|
@@ -18009,6 +18075,30 @@ async function handleBeadsActionCommand(action, started) {
|
|
|
18009
18075
|
});
|
|
18010
18076
|
}
|
|
18011
18077
|
|
|
18078
|
+
// src/beads/config-store.ts
|
|
18079
|
+
var import_node_fs5 = __toESM(require("fs"));
|
|
18080
|
+
var import_node_os3 = __toESM(require("os"));
|
|
18081
|
+
var import_node_path4 = __toESM(require("path"));
|
|
18082
|
+
function beadsConfigPath() {
|
|
18083
|
+
return import_node_path4.default.join(import_node_os3.default.homedir(), ".codeam", "beads-config.json");
|
|
18084
|
+
}
|
|
18085
|
+
function readBeadsEnabled() {
|
|
18086
|
+
try {
|
|
18087
|
+
const raw = import_node_fs5.default.readFileSync(beadsConfigPath(), "utf8");
|
|
18088
|
+
const cfg = JSON.parse(raw);
|
|
18089
|
+
return cfg.enabled !== false;
|
|
18090
|
+
} catch {
|
|
18091
|
+
return true;
|
|
18092
|
+
}
|
|
18093
|
+
}
|
|
18094
|
+
function persistBeadsConfig(cfg) {
|
|
18095
|
+
const file = beadsConfigPath();
|
|
18096
|
+
import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
18097
|
+
const tmp = `${file}.tmp`;
|
|
18098
|
+
import_node_fs5.default.writeFileSync(tmp, JSON.stringify(cfg), { mode: 384 });
|
|
18099
|
+
import_node_fs5.default.renameSync(tmp, file);
|
|
18100
|
+
}
|
|
18101
|
+
|
|
18012
18102
|
// src/beads/wiring.ts
|
|
18013
18103
|
function beadsKilled() {
|
|
18014
18104
|
const v = process.env.CODEAM_BEADS_DISABLED;
|
|
@@ -18019,6 +18109,10 @@ async function provisionBeadsForStart(ctx) {
|
|
|
18019
18109
|
log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off this run");
|
|
18020
18110
|
return null;
|
|
18021
18111
|
}
|
|
18112
|
+
if (readBeadsEnabled() === false) {
|
|
18113
|
+
log.trace("beads", "beads disabled by persisted config \u2014 beads off this run");
|
|
18114
|
+
return null;
|
|
18115
|
+
}
|
|
18022
18116
|
delete process.env.BEADS_DIR;
|
|
18023
18117
|
process.env.BEADS_DOLT_SHARED_SERVER = "1";
|
|
18024
18118
|
if (!ctx.pluginAuthToken) {
|
|
@@ -18079,12 +18173,69 @@ function beadsActionFromPayload(payload) {
|
|
|
18079
18173
|
};
|
|
18080
18174
|
}
|
|
18081
18175
|
|
|
18176
|
+
// src/beads/configure.ts
|
|
18177
|
+
var _probeSeam = {
|
|
18178
|
+
resolveBd: (cwd) => new BdAdapter({ cwd }).isAvailable(),
|
|
18179
|
+
doltOnPath: () => ensureDoltResolvable(),
|
|
18180
|
+
ping: async (cwd) => {
|
|
18181
|
+
const adapter = new BdAdapter({ cwd });
|
|
18182
|
+
if (!adapter.isAvailable()) return false;
|
|
18183
|
+
const r = await adapter.run(["ping"]);
|
|
18184
|
+
return r.code === 0;
|
|
18185
|
+
},
|
|
18186
|
+
derivePrefix: (cwd) => {
|
|
18187
|
+
try {
|
|
18188
|
+
const { projectKey } = deriveProjectIdentity(cwd);
|
|
18189
|
+
return prefixForProjectKey(projectKey);
|
|
18190
|
+
} catch {
|
|
18191
|
+
return null;
|
|
18192
|
+
}
|
|
18193
|
+
}
|
|
18194
|
+
};
|
|
18195
|
+
async function probeBeadsStatus(cwd = process.cwd()) {
|
|
18196
|
+
const bdAvailable = _probeSeam.resolveBd(cwd);
|
|
18197
|
+
const doltAvailable = _probeSeam.doltOnPath();
|
|
18198
|
+
const serverUp = bdAvailable && doltAvailable ? await _probeSeam.ping(cwd) : false;
|
|
18199
|
+
const prefix = _probeSeam.derivePrefix(cwd);
|
|
18200
|
+
return { bdAvailable, doltAvailable, serverUp, prefix };
|
|
18201
|
+
}
|
|
18202
|
+
async function configureBeads(action, ctx, deps) {
|
|
18203
|
+
if (action === "status") {
|
|
18204
|
+
if (deps.readEnabled() === false) {
|
|
18205
|
+
deps.emit({ type: "beads_status", state: "disabled", running: false });
|
|
18206
|
+
return { enabled: false, running: false };
|
|
18207
|
+
}
|
|
18208
|
+
const p3 = await deps.probe();
|
|
18209
|
+
const running2 = p3.serverUp && p3.bdAvailable;
|
|
18210
|
+
deps.emit({ type: "beads_status", state: running2 ? "enabled" : "disabled", running: running2, ...p3 });
|
|
18211
|
+
return { enabled: running2, running: running2, ...p3 };
|
|
18212
|
+
}
|
|
18213
|
+
if (action === "disable") {
|
|
18214
|
+
deps.persist({ enabled: false });
|
|
18215
|
+
await deps.stopWatcher().catch(() => void 0);
|
|
18216
|
+
await deps.revertAgentHook(ctx.agent).catch(() => void 0);
|
|
18217
|
+
deps.emit({ type: "beads_status", state: "disabled" });
|
|
18218
|
+
return { enabled: false };
|
|
18219
|
+
}
|
|
18220
|
+
deps.persist({ enabled: true });
|
|
18221
|
+
deps.emit({ type: "beads_status", state: "provisioning" });
|
|
18222
|
+
const p2 = await deps.provision();
|
|
18223
|
+
if (!p2.serverUp || !p2.bdAvailable) {
|
|
18224
|
+
deps.emit({ type: "beads_status", state: "error", error: "Beads provisioning failed", ...p2 });
|
|
18225
|
+
return { enabled: false, ...p2 };
|
|
18226
|
+
}
|
|
18227
|
+
await deps.startWatcher().catch(() => void 0);
|
|
18228
|
+
const running = true;
|
|
18229
|
+
deps.emit({ type: "beads_status", state: "enabled", running, ...p2 });
|
|
18230
|
+
return { enabled: true, running, ...p2 };
|
|
18231
|
+
}
|
|
18232
|
+
|
|
18082
18233
|
// src/commands/start/handlers.ts
|
|
18083
18234
|
var pendingAttachmentFiles = /* @__PURE__ */ new Set();
|
|
18084
18235
|
function cleanupAttachmentTempFiles() {
|
|
18085
18236
|
for (const p2 of pendingAttachmentFiles) {
|
|
18086
18237
|
try {
|
|
18087
|
-
|
|
18238
|
+
fs41.unlinkSync(p2);
|
|
18088
18239
|
} catch {
|
|
18089
18240
|
}
|
|
18090
18241
|
}
|
|
@@ -18093,8 +18244,8 @@ function cleanupAttachmentTempFiles() {
|
|
|
18093
18244
|
function saveFilesTemp(files) {
|
|
18094
18245
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
18095
18246
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
18096
|
-
const tmpPath =
|
|
18097
|
-
|
|
18247
|
+
const tmpPath = path47.join(os34.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
18248
|
+
fs41.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
18098
18249
|
pendingAttachmentFiles.add(tmpPath);
|
|
18099
18250
|
return tmpPath;
|
|
18100
18251
|
});
|
|
@@ -18114,7 +18265,7 @@ var startTask = (ctx, _cmd, parsed) => {
|
|
|
18114
18265
|
setTimeout(() => {
|
|
18115
18266
|
for (const p2 of paths) {
|
|
18116
18267
|
try {
|
|
18117
|
-
|
|
18268
|
+
fs41.unlinkSync(p2);
|
|
18118
18269
|
} catch {
|
|
18119
18270
|
}
|
|
18120
18271
|
pendingAttachmentFiles.delete(p2);
|
|
@@ -18315,9 +18466,9 @@ var listFiles = async (ctx, cmd, parsed) => {
|
|
|
18315
18466
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18316
18467
|
};
|
|
18317
18468
|
var envReadH = async (ctx, cmd) => {
|
|
18318
|
-
const envPath =
|
|
18469
|
+
const envPath = path47.join(process.cwd(), ".env");
|
|
18319
18470
|
try {
|
|
18320
|
-
const raw = await
|
|
18471
|
+
const raw = await fs41.promises.readFile(envPath, "utf8");
|
|
18321
18472
|
await ctx.relay.sendResult(cmd.id, "completed", {
|
|
18322
18473
|
exists: true,
|
|
18323
18474
|
vars: parseDotenv(raw)
|
|
@@ -18348,14 +18499,14 @@ var envWriteH = async (ctx, cmd, parsed) => {
|
|
|
18348
18499
|
}
|
|
18349
18500
|
seen.add(v.key);
|
|
18350
18501
|
}
|
|
18351
|
-
const envPath =
|
|
18352
|
-
const tmpPath =
|
|
18502
|
+
const envPath = path47.join(process.cwd(), ".env");
|
|
18503
|
+
const tmpPath = path47.join(process.cwd(), ".env.codeam.tmp");
|
|
18353
18504
|
try {
|
|
18354
|
-
await
|
|
18355
|
-
await
|
|
18505
|
+
await fs41.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
|
|
18506
|
+
await fs41.promises.rename(tmpPath, envPath);
|
|
18356
18507
|
await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
|
|
18357
18508
|
} catch (err) {
|
|
18358
|
-
await
|
|
18509
|
+
await fs41.promises.rm(tmpPath, { force: true }).catch(() => void 0);
|
|
18359
18510
|
await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
|
|
18360
18511
|
}
|
|
18361
18512
|
};
|
|
@@ -18373,7 +18524,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18373
18524
|
let configuredAgent = rawAgentId;
|
|
18374
18525
|
if (!configuredAgent) {
|
|
18375
18526
|
try {
|
|
18376
|
-
const raw = JSON.parse(
|
|
18527
|
+
const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
|
|
18377
18528
|
configuredAgent = raw.agent ?? "";
|
|
18378
18529
|
} catch {
|
|
18379
18530
|
}
|
|
@@ -18407,7 +18558,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18407
18558
|
persist: persistHeadroomConfig,
|
|
18408
18559
|
readEnabled: () => {
|
|
18409
18560
|
try {
|
|
18410
|
-
const raw = JSON.parse(
|
|
18561
|
+
const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
|
|
18411
18562
|
return raw.enabled === true;
|
|
18412
18563
|
} catch {
|
|
18413
18564
|
return false;
|
|
@@ -18420,7 +18571,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18420
18571
|
const res = await fetch("http://localhost:8787/stats");
|
|
18421
18572
|
return res.json();
|
|
18422
18573
|
},
|
|
18423
|
-
postSavings: async (delta) => {
|
|
18574
|
+
postSavings: async (delta, budget) => {
|
|
18424
18575
|
if (!opts.ingestUrl) return;
|
|
18425
18576
|
await fetch(opts.ingestUrl, {
|
|
18426
18577
|
method: "POST",
|
|
@@ -18439,7 +18590,12 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18439
18590
|
sessionId: ctx.sessionId,
|
|
18440
18591
|
pluginId: ctx.pluginId,
|
|
18441
18592
|
agentId: opts.agent,
|
|
18442
|
-
savings: delta
|
|
18593
|
+
savings: delta,
|
|
18594
|
+
...budget ? {
|
|
18595
|
+
periodSpendUsd: budget.periodSpendUsd,
|
|
18596
|
+
budgetUsd: budget.budgetUsd,
|
|
18597
|
+
budgetPeriod: budget.budgetPeriod
|
|
18598
|
+
} : {}
|
|
18443
18599
|
})
|
|
18444
18600
|
});
|
|
18445
18601
|
}
|
|
@@ -18480,6 +18636,148 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
|
|
|
18480
18636
|
});
|
|
18481
18637
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18482
18638
|
};
|
|
18639
|
+
var headroomBudgetH = async (ctx, cmd) => {
|
|
18640
|
+
const payload = cmd.payload;
|
|
18641
|
+
let rawAgentId = ctx.agentId || (typeof payload.agentId === "string" ? payload.agentId : "");
|
|
18642
|
+
if (rawAgentId === "claude_code") rawAgentId = "claude";
|
|
18643
|
+
let payloadAgentId = typeof payload.agentId === "string" ? payload.agentId : "";
|
|
18644
|
+
if (payloadAgentId === "claude_code") payloadAgentId = "claude";
|
|
18645
|
+
if (!rawAgentId || !isHeadroomSupportedAgent(rawAgentId)) {
|
|
18646
|
+
await ctx.relay.sendResult(cmd.id, "completed", { applied: false });
|
|
18647
|
+
return;
|
|
18648
|
+
}
|
|
18649
|
+
if (!payloadAgentId || payloadAgentId !== rawAgentId) {
|
|
18650
|
+
await ctx.relay.sendResult(cmd.id, "completed", { applied: false });
|
|
18651
|
+
return;
|
|
18652
|
+
}
|
|
18653
|
+
let headroomActive = false;
|
|
18654
|
+
try {
|
|
18655
|
+
const raw = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
|
|
18656
|
+
headroomActive = raw.enabled === true;
|
|
18657
|
+
} catch {
|
|
18658
|
+
}
|
|
18659
|
+
if (!headroomActive) {
|
|
18660
|
+
await ctx.relay.sendResult(cmd.id, "completed", { applied: false });
|
|
18661
|
+
return;
|
|
18662
|
+
}
|
|
18663
|
+
let existingConfig = { enabled: true };
|
|
18664
|
+
try {
|
|
18665
|
+
existingConfig = JSON.parse(fs41.readFileSync(headroomConfigPath(), "utf8"));
|
|
18666
|
+
} catch {
|
|
18667
|
+
}
|
|
18668
|
+
if (payload.budgetEnabled && payload.budgetUsd != null) {
|
|
18669
|
+
persistHeadroomConfig({
|
|
18670
|
+
...existingConfig,
|
|
18671
|
+
enabled: existingConfig.enabled ?? true,
|
|
18672
|
+
budgetEnabled: true,
|
|
18673
|
+
budgetUsd: payload.budgetUsd,
|
|
18674
|
+
budgetPeriod: payload.budgetPeriod ?? "daily"
|
|
18675
|
+
});
|
|
18676
|
+
process.env["HEADROOM_BUDGET"] = String(payload.budgetUsd);
|
|
18677
|
+
process.env["HEADROOM_BUDGET_PERIOD"] = payload.budgetPeriod ?? "daily";
|
|
18678
|
+
} else {
|
|
18679
|
+
persistHeadroomConfig({
|
|
18680
|
+
...existingConfig,
|
|
18681
|
+
enabled: existingConfig.enabled ?? true,
|
|
18682
|
+
budgetEnabled: false,
|
|
18683
|
+
budgetUsd: void 0,
|
|
18684
|
+
budgetPeriod: void 0
|
|
18685
|
+
});
|
|
18686
|
+
delete process.env["HEADROOM_BUDGET"];
|
|
18687
|
+
delete process.env["HEADROOM_BUDGET_PERIOD"];
|
|
18688
|
+
}
|
|
18689
|
+
try {
|
|
18690
|
+
const killer = (0, import_child_process20.spawn)("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
18691
|
+
detached: true,
|
|
18692
|
+
stdio: "ignore"
|
|
18693
|
+
});
|
|
18694
|
+
killer.once("error", () => {
|
|
18695
|
+
});
|
|
18696
|
+
killer.unref();
|
|
18697
|
+
} catch {
|
|
18698
|
+
}
|
|
18699
|
+
try {
|
|
18700
|
+
const proxyEnv = { ...process.env, HEADROOM_KOMPRESS_BACKEND: "onnx_cpu" };
|
|
18701
|
+
const proxy = (0, import_child_process20.spawn)(
|
|
18702
|
+
"headroom",
|
|
18703
|
+
["proxy", "--port", "8787", ...buildBudgetProxyArgs(proxyEnv)],
|
|
18704
|
+
{
|
|
18705
|
+
stdio: "ignore",
|
|
18706
|
+
detached: true,
|
|
18707
|
+
env: proxyEnv
|
|
18708
|
+
}
|
|
18709
|
+
);
|
|
18710
|
+
proxy.once("error", (e) => {
|
|
18711
|
+
log.warn("headroom-budget", `proxy relaunch error (best-effort): ${e.message}`);
|
|
18712
|
+
});
|
|
18713
|
+
proxy.unref();
|
|
18714
|
+
} catch (e) {
|
|
18715
|
+
log.warn(
|
|
18716
|
+
"headroom-budget",
|
|
18717
|
+
`proxy relaunch failed (best-effort): ${e instanceof Error ? e.message : String(e)}`
|
|
18718
|
+
);
|
|
18719
|
+
}
|
|
18720
|
+
await ctx.relay.sendResult(cmd.id, "completed", { applied: true });
|
|
18721
|
+
};
|
|
18722
|
+
var _beadsEmitChain = Promise.resolve();
|
|
18723
|
+
var beadsConfigureH = async (ctx, cmd, parsed) => {
|
|
18724
|
+
const action = parsed.action;
|
|
18725
|
+
if (action !== "enable" && action !== "disable" && action !== "status") {
|
|
18726
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: "action must be enable|disable|status" });
|
|
18727
|
+
return;
|
|
18728
|
+
}
|
|
18729
|
+
let rawAgentId = ctx.agentId || (typeof parsed.agentId === "string" ? parsed.agentId : "");
|
|
18730
|
+
if (rawAgentId === "claude_code") rawAgentId = "claude";
|
|
18731
|
+
const agentIds = rawAgentId && isKnownAgentId(rawAgentId) ? [rawAgentId] : [];
|
|
18732
|
+
const deps = {
|
|
18733
|
+
provision: async () => {
|
|
18734
|
+
const r = await provisionBeads({ cwd: process.cwd(), agents: agentIds });
|
|
18735
|
+
return { bdAvailable: r.bdAvailable, doltAvailable: r.doltAvailable, serverUp: r.serverUp, prefix: r.prefix };
|
|
18736
|
+
},
|
|
18737
|
+
probe: async () => probeBeadsStatus(process.cwd()),
|
|
18738
|
+
startWatcher: async () => {
|
|
18739
|
+
if (!ctx.pluginAuthToken) return;
|
|
18740
|
+
const started = await startBeads({
|
|
18741
|
+
sessionId: ctx.sessionId,
|
|
18742
|
+
pluginId: ctx.pluginId,
|
|
18743
|
+
pluginAuthToken: ctx.pluginAuthToken,
|
|
18744
|
+
cwd: process.cwd(),
|
|
18745
|
+
agents: agentIds
|
|
18746
|
+
});
|
|
18747
|
+
if (started) {
|
|
18748
|
+
ctx.beads = started;
|
|
18749
|
+
}
|
|
18750
|
+
},
|
|
18751
|
+
stopWatcher: async () => {
|
|
18752
|
+
if (ctx.beads) {
|
|
18753
|
+
await ctx.beads.watcher.stop();
|
|
18754
|
+
ctx.beads = null;
|
|
18755
|
+
}
|
|
18756
|
+
},
|
|
18757
|
+
revertAgentHook: async (agent) => {
|
|
18758
|
+
log.info("beads", `revertAgentHook: bd has no --remove flag \u2014 leaving ${agent} hook in place (no-op disable path)`);
|
|
18759
|
+
},
|
|
18760
|
+
persist: (cfg) => persistBeadsConfig(cfg),
|
|
18761
|
+
readEnabled: () => readBeadsEnabled(),
|
|
18762
|
+
emit: (event) => {
|
|
18763
|
+
const token = ctx.pluginAuthToken;
|
|
18764
|
+
if (!token) return;
|
|
18765
|
+
_beadsEmitChain = _beadsEmitChain.then(
|
|
18766
|
+
() => postBeadsEvent({
|
|
18767
|
+
sessionId: ctx.sessionId,
|
|
18768
|
+
pluginId: ctx.pluginId,
|
|
18769
|
+
pluginAuthToken: token,
|
|
18770
|
+
type: "beads_status",
|
|
18771
|
+
payload: Object.fromEntries(
|
|
18772
|
+
Object.entries(event).filter(([k2]) => k2 !== "type")
|
|
18773
|
+
)
|
|
18774
|
+
})
|
|
18775
|
+
);
|
|
18776
|
+
}
|
|
18777
|
+
};
|
|
18778
|
+
const result = await configureBeads(action, { agent: rawAgentId, cwd: process.cwd(), pluginAuthToken: ctx.pluginAuthToken }, deps);
|
|
18779
|
+
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18780
|
+
};
|
|
18483
18781
|
var terminalOpenH = async (ctx, cmd, parsed) => {
|
|
18484
18782
|
const r = openTerminal({
|
|
18485
18783
|
cols: typeof parsed.cols === "number" ? parsed.cols : void 0,
|
|
@@ -18916,8 +19214,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
|
|
|
18916
19214
|
if (args2.length === 0) return detection;
|
|
18917
19215
|
const binName = args2[0];
|
|
18918
19216
|
if (binName.startsWith("-")) return detection;
|
|
18919
|
-
const binPath =
|
|
18920
|
-
if (!
|
|
19217
|
+
const binPath = path47.join(cwd, "node_modules", ".bin", binName);
|
|
19218
|
+
if (!fs41.existsSync(binPath)) return detection;
|
|
18921
19219
|
return {
|
|
18922
19220
|
...detection,
|
|
18923
19221
|
command: binPath,
|
|
@@ -19465,7 +19763,9 @@ var handlers = {
|
|
|
19465
19763
|
save_preview_config: savePreviewConfigH,
|
|
19466
19764
|
env_read: envReadH,
|
|
19467
19765
|
env_write: envWriteH,
|
|
19468
|
-
headroom_configure: headroomConfigureH
|
|
19766
|
+
headroom_configure: headroomConfigureH,
|
|
19767
|
+
headroom_budget: headroomBudgetH,
|
|
19768
|
+
beads_configure: beadsConfigureH
|
|
19469
19769
|
};
|
|
19470
19770
|
async function dispatchCommand(ctx, cmd) {
|
|
19471
19771
|
if (cmd.type === "beads_action") {
|
|
@@ -19733,12 +20033,12 @@ function readTokenFromArgs(args2) {
|
|
|
19733
20033
|
}
|
|
19734
20034
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
19735
20035
|
if (fileFlag) {
|
|
19736
|
-
const
|
|
20036
|
+
const path61 = fileFlag.slice("--token-file=".length);
|
|
19737
20037
|
try {
|
|
19738
|
-
const content =
|
|
19739
|
-
if (content.length === 0) fail(`--token-file ${
|
|
20038
|
+
const content = fs42.readFileSync(path61, "utf8").trim();
|
|
20039
|
+
if (content.length === 0) fail(`--token-file ${path61} is empty`);
|
|
19740
20040
|
try {
|
|
19741
|
-
|
|
20041
|
+
fs42.unlinkSync(path61);
|
|
19742
20042
|
} catch {
|
|
19743
20043
|
}
|
|
19744
20044
|
return content;
|
|
@@ -19764,7 +20064,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
|
|
|
19764
20064
|
pluginId,
|
|
19765
20065
|
ideName: "codeam-cli (codespace)",
|
|
19766
20066
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
19767
|
-
hostname:
|
|
20067
|
+
hostname: os35.hostname(),
|
|
19768
20068
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
19769
20069
|
// Current git branch of the codespace's working directory, so the
|
|
19770
20070
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -19825,7 +20125,7 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
19825
20125
|
}
|
|
19826
20126
|
}
|
|
19827
20127
|
function pairAutoLockPath() {
|
|
19828
|
-
return
|
|
20128
|
+
return path48.join(os35.homedir(), ".codeam", "pair-auto.lock");
|
|
19829
20129
|
}
|
|
19830
20130
|
function isLivePairAuto(pid) {
|
|
19831
20131
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
@@ -19835,7 +20135,7 @@ function isLivePairAuto(pid) {
|
|
|
19835
20135
|
if (e.code !== "EPERM") return false;
|
|
19836
20136
|
}
|
|
19837
20137
|
try {
|
|
19838
|
-
return
|
|
20138
|
+
return fs42.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
|
|
19839
20139
|
} catch {
|
|
19840
20140
|
return true;
|
|
19841
20141
|
}
|
|
@@ -19845,24 +20145,24 @@ function isLiveCodeam(pid) {
|
|
|
19845
20145
|
}
|
|
19846
20146
|
function daemonLockPath(sessionId) {
|
|
19847
20147
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
19848
|
-
return
|
|
20148
|
+
return path48.join(os35.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
19849
20149
|
}
|
|
19850
20150
|
function acquireDaemonLock(sessionId) {
|
|
19851
20151
|
const lockPath = daemonLockPath(sessionId);
|
|
19852
20152
|
try {
|
|
19853
|
-
|
|
20153
|
+
fs42.mkdirSync(path48.dirname(lockPath), { recursive: true });
|
|
19854
20154
|
try {
|
|
19855
|
-
|
|
20155
|
+
fs42.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
19856
20156
|
} catch (e) {
|
|
19857
20157
|
if (e.code !== "EEXIST") throw e;
|
|
19858
|
-
const holder = Number(
|
|
20158
|
+
const holder = Number(fs42.readFileSync(lockPath, "utf8").trim());
|
|
19859
20159
|
if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
|
|
19860
|
-
|
|
20160
|
+
fs42.writeFileSync(lockPath, String(process.pid));
|
|
19861
20161
|
}
|
|
19862
20162
|
const release3 = () => {
|
|
19863
20163
|
try {
|
|
19864
|
-
if (
|
|
19865
|
-
|
|
20164
|
+
if (fs42.existsSync(lockPath) && Number(fs42.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
20165
|
+
fs42.unlinkSync(lockPath);
|
|
19866
20166
|
}
|
|
19867
20167
|
} catch {
|
|
19868
20168
|
}
|
|
@@ -19884,19 +20184,19 @@ function acquireDaemonLock(sessionId) {
|
|
|
19884
20184
|
function acquireSingletonLock() {
|
|
19885
20185
|
const lockPath = pairAutoLockPath();
|
|
19886
20186
|
try {
|
|
19887
|
-
|
|
20187
|
+
fs42.mkdirSync(path48.dirname(lockPath), { recursive: true });
|
|
19888
20188
|
try {
|
|
19889
|
-
|
|
20189
|
+
fs42.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
19890
20190
|
} catch (e) {
|
|
19891
20191
|
if (e.code !== "EEXIST") throw e;
|
|
19892
|
-
const holder = Number(
|
|
20192
|
+
const holder = Number(fs42.readFileSync(lockPath, "utf8").trim());
|
|
19893
20193
|
if (isLivePairAuto(holder)) return false;
|
|
19894
|
-
|
|
20194
|
+
fs42.writeFileSync(lockPath, String(process.pid));
|
|
19895
20195
|
}
|
|
19896
20196
|
process.once("exit", () => {
|
|
19897
20197
|
try {
|
|
19898
|
-
if (
|
|
19899
|
-
|
|
20198
|
+
if (fs42.existsSync(lockPath) && Number(fs42.readFileSync(lockPath, "utf8").trim()) === process.pid) {
|
|
20199
|
+
fs42.unlinkSync(lockPath);
|
|
19900
20200
|
}
|
|
19901
20201
|
} catch {
|
|
19902
20202
|
}
|
|
@@ -20341,19 +20641,19 @@ var AgentService = class _AgentService {
|
|
|
20341
20641
|
};
|
|
20342
20642
|
|
|
20343
20643
|
// src/agents/acp/adapters.ts
|
|
20344
|
-
var
|
|
20644
|
+
var path49 = __toESM(require("path"));
|
|
20345
20645
|
var require_ = require;
|
|
20346
20646
|
function resolveBin(pkgName, binName) {
|
|
20347
20647
|
try {
|
|
20348
20648
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
20349
20649
|
const manifest = require_(`${pkgName}/package.json`);
|
|
20350
|
-
const pkgDir =
|
|
20650
|
+
const pkgDir = path49.dirname(manifestPath);
|
|
20351
20651
|
const bin = manifest.bin;
|
|
20352
20652
|
if (!bin) return null;
|
|
20353
|
-
if (typeof bin === "string") return
|
|
20653
|
+
if (typeof bin === "string") return path49.resolve(pkgDir, bin);
|
|
20354
20654
|
const target = binName ?? Object.keys(bin)[0];
|
|
20355
20655
|
if (!target || !bin[target]) return null;
|
|
20356
|
-
return
|
|
20656
|
+
return path49.resolve(pkgDir, bin[target]);
|
|
20357
20657
|
} catch {
|
|
20358
20658
|
return null;
|
|
20359
20659
|
}
|
|
@@ -20423,9 +20723,9 @@ function requiresAcp(agent) {
|
|
|
20423
20723
|
var import_node_crypto7 = require("crypto");
|
|
20424
20724
|
|
|
20425
20725
|
// src/services/history.service.ts
|
|
20426
|
-
var
|
|
20427
|
-
var
|
|
20428
|
-
var
|
|
20726
|
+
var fs43 = __toESM(require("fs"));
|
|
20727
|
+
var path50 = __toESM(require("path"));
|
|
20728
|
+
var os36 = __toESM(require("os"));
|
|
20429
20729
|
var https7 = __toESM(require("https"));
|
|
20430
20730
|
var http6 = __toESM(require("http"));
|
|
20431
20731
|
var import_zod2 = require("zod");
|
|
@@ -20452,7 +20752,7 @@ function parseJsonl(filePath) {
|
|
|
20452
20752
|
const messages = [];
|
|
20453
20753
|
let raw;
|
|
20454
20754
|
try {
|
|
20455
|
-
raw =
|
|
20755
|
+
raw = fs43.readFileSync(filePath, "utf8");
|
|
20456
20756
|
} catch (err) {
|
|
20457
20757
|
if (err.code !== "ENOENT") {
|
|
20458
20758
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -20593,7 +20893,7 @@ var HistoryService = class _HistoryService {
|
|
|
20593
20893
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
20594
20894
|
}
|
|
20595
20895
|
get projectDir() {
|
|
20596
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
20896
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path50.join(os36.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
20597
20897
|
}
|
|
20598
20898
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
20599
20899
|
setCurrentConversationId(id) {
|
|
@@ -20605,7 +20905,7 @@ var HistoryService = class _HistoryService {
|
|
|
20605
20905
|
/** Return the current message count in the active conversation. */
|
|
20606
20906
|
getCurrentMessageCount() {
|
|
20607
20907
|
if (!this.currentConversationId) return 0;
|
|
20608
|
-
const filePath =
|
|
20908
|
+
const filePath = path50.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
20609
20909
|
return parseJsonl(filePath).length;
|
|
20610
20910
|
}
|
|
20611
20911
|
/**
|
|
@@ -20616,7 +20916,7 @@ var HistoryService = class _HistoryService {
|
|
|
20616
20916
|
const deadline = Date.now() + timeoutMs;
|
|
20617
20917
|
while (Date.now() < deadline) {
|
|
20618
20918
|
if (!this.currentConversationId) return null;
|
|
20619
|
-
const filePath =
|
|
20919
|
+
const filePath = path50.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
20620
20920
|
const messages = parseJsonl(filePath);
|
|
20621
20921
|
if (messages.length > previousCount) {
|
|
20622
20922
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -20642,16 +20942,16 @@ var HistoryService = class _HistoryService {
|
|
|
20642
20942
|
const dir = this.projectDir;
|
|
20643
20943
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
20644
20944
|
try {
|
|
20645
|
-
const files =
|
|
20945
|
+
const files = fs43.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
20646
20946
|
try {
|
|
20647
|
-
const stat3 =
|
|
20947
|
+
const stat3 = fs43.statSync(path50.join(dir, e.name));
|
|
20648
20948
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
20649
20949
|
} catch {
|
|
20650
20950
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
20651
20951
|
}
|
|
20652
20952
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
20653
20953
|
if (files.length > 0) {
|
|
20654
|
-
this.currentConversationId =
|
|
20954
|
+
this.currentConversationId = path50.basename(files[0].name, ".jsonl");
|
|
20655
20955
|
}
|
|
20656
20956
|
} catch {
|
|
20657
20957
|
}
|
|
@@ -20685,13 +20985,13 @@ var HistoryService = class _HistoryService {
|
|
|
20685
20985
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
20686
20986
|
let entries;
|
|
20687
20987
|
try {
|
|
20688
|
-
entries =
|
|
20988
|
+
entries = fs43.readdirSync(dir, { withFileTypes: true });
|
|
20689
20989
|
} catch {
|
|
20690
20990
|
return null;
|
|
20691
20991
|
}
|
|
20692
20992
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
20693
20993
|
try {
|
|
20694
|
-
const stat3 =
|
|
20994
|
+
const stat3 = fs43.statSync(path50.join(dir, e.name));
|
|
20695
20995
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
20696
20996
|
} catch {
|
|
20697
20997
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -20700,12 +21000,12 @@ var HistoryService = class _HistoryService {
|
|
|
20700
21000
|
if (files.length === 0) return null;
|
|
20701
21001
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
20702
21002
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
20703
|
-
return this.extractUsageFromFile(
|
|
21003
|
+
return this.extractUsageFromFile(path50.join(dir, targetFile));
|
|
20704
21004
|
}
|
|
20705
21005
|
extractUsageFromFile(filePath) {
|
|
20706
21006
|
let raw;
|
|
20707
21007
|
try {
|
|
20708
|
-
raw =
|
|
21008
|
+
raw = fs43.readFileSync(filePath, "utf8");
|
|
20709
21009
|
} catch {
|
|
20710
21010
|
return null;
|
|
20711
21011
|
}
|
|
@@ -20750,9 +21050,9 @@ var HistoryService = class _HistoryService {
|
|
|
20750
21050
|
let totalCost = 0;
|
|
20751
21051
|
let files;
|
|
20752
21052
|
try {
|
|
20753
|
-
files =
|
|
21053
|
+
files = fs43.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
20754
21054
|
try {
|
|
20755
|
-
return
|
|
21055
|
+
return fs43.statSync(path50.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
20756
21056
|
} catch {
|
|
20757
21057
|
return false;
|
|
20758
21058
|
}
|
|
@@ -20763,7 +21063,7 @@ var HistoryService = class _HistoryService {
|
|
|
20763
21063
|
for (const file of files) {
|
|
20764
21064
|
let raw;
|
|
20765
21065
|
try {
|
|
20766
|
-
raw =
|
|
21066
|
+
raw = fs43.readFileSync(path50.join(projectDir, file), "utf8");
|
|
20767
21067
|
} catch {
|
|
20768
21068
|
continue;
|
|
20769
21069
|
}
|
|
@@ -20842,7 +21142,7 @@ var HistoryService = class _HistoryService {
|
|
|
20842
21142
|
if (this.runtime.resolveHistoryFile) {
|
|
20843
21143
|
return this.runtime.resolveHistoryFile(this.cwd, sessionId);
|
|
20844
21144
|
}
|
|
20845
|
-
return
|
|
21145
|
+
return path50.join(this.projectDir, `${sessionId}.jsonl`);
|
|
20846
21146
|
}
|
|
20847
21147
|
/**
|
|
20848
21148
|
* Parse a conversation's messages from disk, agent-aware. Claude uses the
|
|
@@ -20876,7 +21176,7 @@ var HistoryService = class _HistoryService {
|
|
|
20876
21176
|
};
|
|
20877
21177
|
});
|
|
20878
21178
|
}
|
|
20879
|
-
return parseJsonl(
|
|
21179
|
+
return parseJsonl(path50.join(this.projectDir, `${sessionId}.jsonl`));
|
|
20880
21180
|
}
|
|
20881
21181
|
async loadConversation(sessionId) {
|
|
20882
21182
|
const messages = this.readConversation(sessionId);
|
|
@@ -20932,7 +21232,7 @@ var HistoryService = class _HistoryService {
|
|
|
20932
21232
|
if (!filePath) return false;
|
|
20933
21233
|
let mtimeMs;
|
|
20934
21234
|
try {
|
|
20935
|
-
mtimeMs =
|
|
21235
|
+
mtimeMs = fs43.statSync(filePath).mtimeMs;
|
|
20936
21236
|
} catch {
|
|
20937
21237
|
return false;
|
|
20938
21238
|
}
|
|
@@ -21001,10 +21301,10 @@ var HistoryService = class _HistoryService {
|
|
|
21001
21301
|
|
|
21002
21302
|
// src/agents/acp/client.ts
|
|
21003
21303
|
var import_node_child_process16 = require("child_process");
|
|
21004
|
-
var
|
|
21304
|
+
var fs44 = __toESM(require("fs/promises"));
|
|
21005
21305
|
var fsSync = __toESM(require("fs"));
|
|
21006
|
-
var
|
|
21007
|
-
var
|
|
21306
|
+
var os37 = __toESM(require("os"));
|
|
21307
|
+
var path51 = __toESM(require("path"));
|
|
21008
21308
|
var import_node_stream = require("stream");
|
|
21009
21309
|
|
|
21010
21310
|
// ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
|
|
@@ -23837,7 +24137,7 @@ var AcpClient = class {
|
|
|
23837
24137
|
},
|
|
23838
24138
|
readTextFile: async (params) => {
|
|
23839
24139
|
try {
|
|
23840
|
-
const content = await
|
|
24140
|
+
const content = await fs44.readFile(params.path, "utf8");
|
|
23841
24141
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
23842
24142
|
} catch (err) {
|
|
23843
24143
|
const code = err.code;
|
|
@@ -23857,7 +24157,7 @@ var AcpClient = class {
|
|
|
23857
24157
|
},
|
|
23858
24158
|
writeTextFile: async (params) => {
|
|
23859
24159
|
try {
|
|
23860
|
-
await
|
|
24160
|
+
await fs44.writeFile(params.path, params.content, "utf8");
|
|
23861
24161
|
return {};
|
|
23862
24162
|
} catch (err) {
|
|
23863
24163
|
const code = err.code;
|
|
@@ -23906,25 +24206,25 @@ function applyLineRange(content, line, limit) {
|
|
|
23906
24206
|
return { content: lines.slice(start2, end).join("\n") };
|
|
23907
24207
|
}
|
|
23908
24208
|
function knownAgentBinaryDirs() {
|
|
23909
|
-
const home =
|
|
24209
|
+
const home = os37.homedir();
|
|
23910
24210
|
const out2 = [];
|
|
23911
24211
|
out2.push("/tmp/codeam-node20/bin");
|
|
23912
24212
|
for (const root of [
|
|
23913
24213
|
"/usr/local/share/nvm/versions/node",
|
|
23914
|
-
|
|
24214
|
+
path51.join(home, ".nvm/versions/node")
|
|
23915
24215
|
]) {
|
|
23916
24216
|
try {
|
|
23917
24217
|
for (const child of fsSync.readdirSync(root)) {
|
|
23918
|
-
out2.push(
|
|
24218
|
+
out2.push(path51.join(root, child, "bin"));
|
|
23919
24219
|
}
|
|
23920
24220
|
} catch {
|
|
23921
24221
|
}
|
|
23922
24222
|
}
|
|
23923
|
-
out2.push(
|
|
24223
|
+
out2.push(path51.join(home, ".volta/bin"));
|
|
23924
24224
|
out2.push("/usr/local/bin");
|
|
23925
24225
|
out2.push("/usr/bin");
|
|
23926
|
-
out2.push(
|
|
23927
|
-
out2.push(
|
|
24226
|
+
out2.push(path51.join(home, ".local/bin"));
|
|
24227
|
+
out2.push(path51.join(home, "bin"));
|
|
23928
24228
|
return out2.filter((p2) => {
|
|
23929
24229
|
try {
|
|
23930
24230
|
return fsSync.statSync(p2).isDirectory();
|
|
@@ -23935,7 +24235,7 @@ function knownAgentBinaryDirs() {
|
|
|
23935
24235
|
}
|
|
23936
24236
|
function expandPathForAgentBinaries(existingPath) {
|
|
23937
24237
|
const existing = new Set(
|
|
23938
|
-
existingPath.split(
|
|
24238
|
+
existingPath.split(path51.delimiter).filter((p2) => p2.length > 0)
|
|
23939
24239
|
);
|
|
23940
24240
|
const additions = [];
|
|
23941
24241
|
for (const dir of knownAgentBinaryDirs()) {
|
|
@@ -23945,7 +24245,7 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
23945
24245
|
}
|
|
23946
24246
|
}
|
|
23947
24247
|
if (additions.length === 0) return existingPath;
|
|
23948
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
24248
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path51.delimiter);
|
|
23949
24249
|
}
|
|
23950
24250
|
|
|
23951
24251
|
// src/services/streaming/transport.ts
|
|
@@ -24337,6 +24637,79 @@ function createOneMRecovery(deps) {
|
|
|
24337
24637
|
};
|
|
24338
24638
|
}
|
|
24339
24639
|
|
|
24640
|
+
// src/agents/acp/budgetRecovery.ts
|
|
24641
|
+
var BUDGET_EXCEEDED_RE = /budget exceeded for (\w+) period/i;
|
|
24642
|
+
function looksLikeBudgetExceeded(text) {
|
|
24643
|
+
return BUDGET_EXCEEDED_RE.test(text);
|
|
24644
|
+
}
|
|
24645
|
+
function extractBudgetPeriod(text) {
|
|
24646
|
+
const m = BUDGET_EXCEEDED_RE.exec(text);
|
|
24647
|
+
return m ? m[1] ?? "current" : "current";
|
|
24648
|
+
}
|
|
24649
|
+
var BUDGET_PAUSE_OPTION = "Pause budget this session";
|
|
24650
|
+
var BUDGET_RAISE_OPTION = "Raise budget";
|
|
24651
|
+
function createBudgetRecovery(deps) {
|
|
24652
|
+
let pending = null;
|
|
24653
|
+
const buildQuestion = (period) => `\u{1F4B8} **Headroom budget reached for the ${period} period.**
|
|
24654
|
+
|
|
24655
|
+
You have two options:
|
|
24656
|
+
\u2022 **Pause budget this session** \u2014 removes the spending cap for this session only (the proxy restarts without a budget limit).
|
|
24657
|
+
\u2022 **Raise budget** \u2014 open your agent budget settings to increase the cap.`;
|
|
24658
|
+
return {
|
|
24659
|
+
offer: async (commandId, blocks, detail) => {
|
|
24660
|
+
const period = extractBudgetPeriod(detail);
|
|
24661
|
+
pending = { blocks, period };
|
|
24662
|
+
const question = buildQuestion(period);
|
|
24663
|
+
const options = [BUDGET_PAUSE_OPTION, BUDGET_RAISE_OPTION];
|
|
24664
|
+
await deps.publishText(question);
|
|
24665
|
+
await deps.publishSelectPrompt(question, options);
|
|
24666
|
+
await deps.publishAwaitingAnswer(question, options);
|
|
24667
|
+
deps.appendAgentReply(question);
|
|
24668
|
+
deps.flushHistory();
|
|
24669
|
+
deps.log?.(`budget-exceeded recovery offered period=${period} id=${commandId.slice(0, 8)}`);
|
|
24670
|
+
await deps.sendResult(commandId, "failed", {
|
|
24671
|
+
error: `Headroom budget exceeded (${period}) \u2014 recovery offered`
|
|
24672
|
+
});
|
|
24673
|
+
},
|
|
24674
|
+
tryRecover: async (commandId, optionIndex) => {
|
|
24675
|
+
if (!pending) return false;
|
|
24676
|
+
const { blocks, period } = pending;
|
|
24677
|
+
pending = null;
|
|
24678
|
+
if (optionIndex === 0) {
|
|
24679
|
+
deps.log?.("budget recovery \u2192 pause: relaunching proxy without budget");
|
|
24680
|
+
try {
|
|
24681
|
+
await deps.relaunchProxyWithoutBudget();
|
|
24682
|
+
} catch (err) {
|
|
24683
|
+
deps.log?.(`budget recovery \u2192 relaunch failed (best-effort): ${String(err)}`);
|
|
24684
|
+
}
|
|
24685
|
+
await deps.sendResult(commandId, "completed", {
|
|
24686
|
+
action: "pause",
|
|
24687
|
+
period,
|
|
24688
|
+
note: "Headroom proxy relaunched without budget limit for this session. Send your message again."
|
|
24689
|
+
});
|
|
24690
|
+
const note = "\u2705 **Budget paused for this session.** The proxy is running without a spending cap \u2014 send your message again.";
|
|
24691
|
+
await deps.publishText(note);
|
|
24692
|
+
deps.appendAgentReply(note);
|
|
24693
|
+
deps.flushHistory();
|
|
24694
|
+
deps.log?.(`budget recovery \u2192 pause complete id=${commandId.slice(0, 8)}`);
|
|
24695
|
+
} else {
|
|
24696
|
+
deps.log?.(`budget recovery \u2192 raise: emitting deep-link for agent=${deps.agentId}`);
|
|
24697
|
+
await deps.publishRawChunk({
|
|
24698
|
+
type: "open_agent_budget_settings",
|
|
24699
|
+
agentId: deps.agentId,
|
|
24700
|
+
done: true
|
|
24701
|
+
});
|
|
24702
|
+
await deps.sendResult(commandId, "completed", {
|
|
24703
|
+
action: "raise",
|
|
24704
|
+
agentId: deps.agentId
|
|
24705
|
+
});
|
|
24706
|
+
deps.log?.(`budget recovery \u2192 raise emitted id=${commandId.slice(0, 8)}`);
|
|
24707
|
+
}
|
|
24708
|
+
return true;
|
|
24709
|
+
}
|
|
24710
|
+
};
|
|
24711
|
+
}
|
|
24712
|
+
|
|
24340
24713
|
// src/agents/acp/reconcileDelta.ts
|
|
24341
24714
|
function reconcileCumulative(existing, incoming) {
|
|
24342
24715
|
if (incoming.length === 0) return existing;
|
|
@@ -24357,15 +24730,15 @@ function commonPrefixLength(a, b) {
|
|
|
24357
24730
|
|
|
24358
24731
|
// src/agents/acp/onboarding.ts
|
|
24359
24732
|
var import_child_process22 = require("child_process");
|
|
24360
|
-
var
|
|
24361
|
-
var
|
|
24362
|
-
var
|
|
24733
|
+
var fs45 = __toESM(require("fs"));
|
|
24734
|
+
var os38 = __toESM(require("os"));
|
|
24735
|
+
var path52 = __toESM(require("path"));
|
|
24363
24736
|
var _onboardingSeam = {
|
|
24364
|
-
markerPath: (sessionId) =>
|
|
24365
|
-
exists: (p2) =>
|
|
24737
|
+
markerPath: (sessionId) => path52.join(os38.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
24738
|
+
exists: (p2) => fs45.existsSync(p2),
|
|
24366
24739
|
write: (p2) => {
|
|
24367
|
-
|
|
24368
|
-
|
|
24740
|
+
fs45.mkdirSync(path52.dirname(p2), { recursive: true });
|
|
24741
|
+
fs45.writeFileSync(p2, "");
|
|
24369
24742
|
},
|
|
24370
24743
|
disabled: () => {
|
|
24371
24744
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -24402,7 +24775,7 @@ function resolveRepoName(cwd) {
|
|
|
24402
24775
|
if (name) return name;
|
|
24403
24776
|
}
|
|
24404
24777
|
}
|
|
24405
|
-
const base =
|
|
24778
|
+
const base = path52.basename(cwd || "");
|
|
24406
24779
|
if (base && !isUuid(base)) return base;
|
|
24407
24780
|
return "this project";
|
|
24408
24781
|
}
|
|
@@ -24675,13 +25048,28 @@ function extractSelectPrompt(text) {
|
|
|
24675
25048
|
};
|
|
24676
25049
|
}
|
|
24677
25050
|
|
|
25051
|
+
// src/agents/acp/inputSuggestion.ts
|
|
25052
|
+
var MIN_LEN = 8;
|
|
25053
|
+
var MAX_LEN = 200;
|
|
25054
|
+
function deriveInputSuggestion(finalText) {
|
|
25055
|
+
if (finalText.length === 0) return null;
|
|
25056
|
+
const lines = finalText.split("\n");
|
|
25057
|
+
let i = lines.length - 1;
|
|
25058
|
+
while (i >= 0 && lines[i].trim() === "") i--;
|
|
25059
|
+
if (i < 0) return null;
|
|
25060
|
+
const lastLine = lines[i].trim();
|
|
25061
|
+
if (!lastLine.endsWith("?")) return null;
|
|
25062
|
+
if (lastLine.length < MIN_LEN || lastLine.length > MAX_LEN) return null;
|
|
25063
|
+
return lastLine;
|
|
25064
|
+
}
|
|
25065
|
+
|
|
24678
25066
|
// src/services/turn-files/turn-file-aggregator.ts
|
|
24679
25067
|
var import_crypto5 = require("crypto");
|
|
24680
25068
|
|
|
24681
25069
|
// src/services/turn-files/git-changeset.ts
|
|
24682
25070
|
var import_child_process23 = require("child_process");
|
|
24683
|
-
var
|
|
24684
|
-
var
|
|
25071
|
+
var fs46 = __toESM(require("fs/promises"));
|
|
25072
|
+
var path53 = __toESM(require("path"));
|
|
24685
25073
|
async function collectRepoChangeset(opts) {
|
|
24686
25074
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
24687
25075
|
if (status2 === null) return null;
|
|
@@ -24699,7 +25087,7 @@ async function collectRepoChangeset(opts) {
|
|
|
24699
25087
|
let stats;
|
|
24700
25088
|
if (row.fileStatus === "added" && numstatEntry === void 0) {
|
|
24701
25089
|
const lineCount = await readUntrackedLineCount(
|
|
24702
|
-
|
|
25090
|
+
path53.join(opts.repoRoot, row.filePath)
|
|
24703
25091
|
);
|
|
24704
25092
|
stats = { added: lineCount, removed: 0 };
|
|
24705
25093
|
} else {
|
|
@@ -24730,7 +25118,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
24730
25118
|
}
|
|
24731
25119
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
24732
25120
|
try {
|
|
24733
|
-
const content = await
|
|
25121
|
+
const content = await fs46.readFile(absPath, "utf8");
|
|
24734
25122
|
let count = 0;
|
|
24735
25123
|
let pos = -1;
|
|
24736
25124
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -24822,7 +25210,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
24822
25210
|
});
|
|
24823
25211
|
}
|
|
24824
25212
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
24825
|
-
const
|
|
25213
|
+
const fs50 = await import("fs/promises");
|
|
24826
25214
|
const out2 = [];
|
|
24827
25215
|
await walk(workingDir, 0);
|
|
24828
25216
|
return out2;
|
|
@@ -24830,7 +25218,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
24830
25218
|
if (depth > maxDepth) return;
|
|
24831
25219
|
let entries = [];
|
|
24832
25220
|
try {
|
|
24833
|
-
const dirents = await
|
|
25221
|
+
const dirents = await fs50.readdir(dir, { withFileTypes: true });
|
|
24834
25222
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
24835
25223
|
} catch {
|
|
24836
25224
|
return;
|
|
@@ -24841,8 +25229,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
24841
25229
|
if (hasGit) {
|
|
24842
25230
|
out2.push({
|
|
24843
25231
|
repoRoot: dir,
|
|
24844
|
-
repoPath:
|
|
24845
|
-
repoName:
|
|
25232
|
+
repoPath: path53.relative(workingDir, dir),
|
|
25233
|
+
repoName: path53.basename(dir)
|
|
24846
25234
|
});
|
|
24847
25235
|
return;
|
|
24848
25236
|
}
|
|
@@ -24850,14 +25238,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
24850
25238
|
if (!entry.isDirectory) continue;
|
|
24851
25239
|
if (entry.name === "node_modules") continue;
|
|
24852
25240
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
24853
|
-
await walk(
|
|
25241
|
+
await walk(path53.join(dir, entry.name), depth + 1);
|
|
24854
25242
|
}
|
|
24855
25243
|
}
|
|
24856
25244
|
}
|
|
24857
25245
|
|
|
24858
25246
|
// src/services/turn-files/files-outbox.ts
|
|
24859
|
-
var
|
|
24860
|
-
var
|
|
25247
|
+
var fs47 = __toESM(require("fs/promises"));
|
|
25248
|
+
var path54 = __toESM(require("path"));
|
|
24861
25249
|
var import_os7 = require("os");
|
|
24862
25250
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
24863
25251
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -24890,16 +25278,16 @@ var FilesOutbox = class {
|
|
|
24890
25278
|
backoffIndex = 0;
|
|
24891
25279
|
stopped = false;
|
|
24892
25280
|
constructor(opts) {
|
|
24893
|
-
const base = opts.baseDir ??
|
|
24894
|
-
this.filePath =
|
|
25281
|
+
const base = opts.baseDir ?? path54.join(homeDir(), HOME_OUTBOX_DIR);
|
|
25282
|
+
this.filePath = path54.join(base, `${opts.sessionId}.jsonl`);
|
|
24895
25283
|
this.post = opts.post;
|
|
24896
25284
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
24897
25285
|
}
|
|
24898
25286
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
24899
25287
|
* line is durable on disk (not once the POST succeeds). */
|
|
24900
25288
|
async enqueue(entry) {
|
|
24901
|
-
await
|
|
24902
|
-
await
|
|
25289
|
+
await fs47.mkdir(path54.dirname(this.filePath), { recursive: true });
|
|
25290
|
+
await fs47.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
24903
25291
|
this.backoffIndex = 0;
|
|
24904
25292
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
24905
25293
|
}
|
|
@@ -24988,7 +25376,7 @@ var FilesOutbox = class {
|
|
|
24988
25376
|
async readAll() {
|
|
24989
25377
|
let raw = "";
|
|
24990
25378
|
try {
|
|
24991
|
-
raw = await
|
|
25379
|
+
raw = await fs47.readFile(this.filePath, "utf8");
|
|
24992
25380
|
} catch {
|
|
24993
25381
|
return [];
|
|
24994
25382
|
}
|
|
@@ -25012,12 +25400,12 @@ var FilesOutbox = class {
|
|
|
25012
25400
|
async rewrite(entries) {
|
|
25013
25401
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
25014
25402
|
if (entries.length === 0) {
|
|
25015
|
-
await
|
|
25403
|
+
await fs47.unlink(this.filePath).catch(() => void 0);
|
|
25016
25404
|
return;
|
|
25017
25405
|
}
|
|
25018
25406
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
25019
|
-
await
|
|
25020
|
-
await
|
|
25407
|
+
await fs47.writeFile(tmpPath, payload, "utf8");
|
|
25408
|
+
await fs47.rename(tmpPath, this.filePath);
|
|
25021
25409
|
}
|
|
25022
25410
|
};
|
|
25023
25411
|
function applyJitter(ms) {
|
|
@@ -25546,7 +25934,7 @@ var StreamingState = class {
|
|
|
25546
25934
|
this.publisher.publishOutput({ type: "text", content: finalText, done: true }),
|
|
25547
25935
|
flushSc
|
|
25548
25936
|
]);
|
|
25549
|
-
return;
|
|
25937
|
+
return false;
|
|
25550
25938
|
}
|
|
25551
25939
|
log.info(
|
|
25552
25940
|
"acpRunner",
|
|
@@ -25573,6 +25961,7 @@ var StreamingState = class {
|
|
|
25573
25961
|
done: true
|
|
25574
25962
|
});
|
|
25575
25963
|
await flushSc;
|
|
25964
|
+
return true;
|
|
25576
25965
|
}
|
|
25577
25966
|
};
|
|
25578
25967
|
var PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -25755,10 +26144,26 @@ async function surfaceStartupFailure(opts) {
|
|
|
25755
26144
|
);
|
|
25756
26145
|
errRelay.start();
|
|
25757
26146
|
}
|
|
26147
|
+
function budgetBubbleMessage(agent, period) {
|
|
26148
|
+
return `\u{1F4B8} **Headroom budget reached for the ${period} period.**
|
|
26149
|
+
|
|
26150
|
+
The local Headroom proxy rejected the ${agent} request because the configured spending cap was hit. Choose an option below to continue.`;
|
|
26151
|
+
}
|
|
26152
|
+
function buildRelaunchProxyEnv(baseEnv) {
|
|
26153
|
+
const env = { ...baseEnv, HEADROOM_KOMPRESS_BACKEND: "onnx_cpu" };
|
|
26154
|
+
delete env["HEADROOM_BUDGET"];
|
|
26155
|
+
delete env["HEADROOM_BUDGET_PERIOD"];
|
|
26156
|
+
return env;
|
|
26157
|
+
}
|
|
25758
26158
|
function failureBubble(opts) {
|
|
25759
26159
|
if (looksLikeAuthFailure(opts.detail) || looksLikeAuthFailure(opts.recentStderr)) {
|
|
25760
26160
|
return AUTH_FAILURE_MESSAGE;
|
|
25761
26161
|
}
|
|
26162
|
+
const budgetHaystack = `${opts.detail}
|
|
26163
|
+
${opts.recentStderr}`;
|
|
26164
|
+
if (looksLikeBudgetExceeded(budgetHaystack)) {
|
|
26165
|
+
return budgetBubbleMessage(opts.agent, extractBudgetPeriod(budgetHaystack));
|
|
26166
|
+
}
|
|
25762
26167
|
if (looksLikeProviderOutage(opts.detail) || looksLikeProviderOutage(opts.recentStderr)) {
|
|
25763
26168
|
return providerOutageMessage(opts.agent);
|
|
25764
26169
|
}
|
|
@@ -25791,6 +26196,25 @@ async function reportCredentialInvalid(opts, fetchImpl = fetch) {
|
|
|
25791
26196
|
} catch {
|
|
25792
26197
|
}
|
|
25793
26198
|
}
|
|
26199
|
+
async function postBudgetReached(opts, fetchImpl = fetch) {
|
|
26200
|
+
const url = `${resolveApiBaseUrl()}/api/sessions/${encodeURIComponent(opts.sessionId)}/headroom-budget-reached`;
|
|
26201
|
+
try {
|
|
26202
|
+
await fetchImpl(url, {
|
|
26203
|
+
method: "POST",
|
|
26204
|
+
headers: {
|
|
26205
|
+
"Content-Type": "application/json",
|
|
26206
|
+
"X-Plugin-Auth-Token": opts.pluginAuthToken
|
|
26207
|
+
},
|
|
26208
|
+
body: JSON.stringify({
|
|
26209
|
+
sessionId: opts.sessionId,
|
|
26210
|
+
pluginId: opts.pluginId,
|
|
26211
|
+
agent: opts.agent,
|
|
26212
|
+
period: opts.period
|
|
26213
|
+
})
|
|
26214
|
+
});
|
|
26215
|
+
} catch {
|
|
26216
|
+
}
|
|
26217
|
+
}
|
|
25794
26218
|
async function handleGetConversation(args2) {
|
|
25795
26219
|
const { relay, commandId, jsonlHistory, acpSessionId } = args2;
|
|
25796
26220
|
try {
|
|
@@ -25946,7 +26370,9 @@ async function runAcpSession(opts) {
|
|
|
25946
26370
|
flushHistory: () => void history.flush(),
|
|
25947
26371
|
beginTurn: () => streaming.beginTurn(),
|
|
25948
26372
|
getCurrentText: () => streaming.getCurrentText(),
|
|
25949
|
-
closeTurn: () =>
|
|
26373
|
+
closeTurn: async () => {
|
|
26374
|
+
await streaming.closeTurnWithInteractiveDetection();
|
|
26375
|
+
},
|
|
25950
26376
|
recoverFromFailedTurn: () => recoverFromFailedTurn(client2, streaming),
|
|
25951
26377
|
reconnectWith1mDisabled,
|
|
25952
26378
|
promptAgent: (blocks) => client2.prompt(blocks),
|
|
@@ -25954,6 +26380,58 @@ async function runAcpSession(opts) {
|
|
|
25954
26380
|
describeError,
|
|
25955
26381
|
log: (msg) => log.info("acpRunner", msg)
|
|
25956
26382
|
});
|
|
26383
|
+
let _budgetReachedPosted = false;
|
|
26384
|
+
const relaunchProxyWithoutBudget = async () => {
|
|
26385
|
+
const { spawn: spawn32 } = await import("child_process");
|
|
26386
|
+
try {
|
|
26387
|
+
const killer = spawn32("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
26388
|
+
detached: true,
|
|
26389
|
+
stdio: "ignore"
|
|
26390
|
+
});
|
|
26391
|
+
killer.once("error", () => {
|
|
26392
|
+
});
|
|
26393
|
+
killer.unref();
|
|
26394
|
+
} catch {
|
|
26395
|
+
}
|
|
26396
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
26397
|
+
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
26398
|
+
try {
|
|
26399
|
+
const proxy = spawn32(
|
|
26400
|
+
"headroom",
|
|
26401
|
+
["proxy", "--port", "8787"],
|
|
26402
|
+
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
26403
|
+
);
|
|
26404
|
+
proxy.once("error", (e) => {
|
|
26405
|
+
log.warn("acpRunner", `budget recovery proxy relaunch error (best-effort): ${e.message}`);
|
|
26406
|
+
});
|
|
26407
|
+
proxy.unref();
|
|
26408
|
+
} catch (e) {
|
|
26409
|
+
log.warn(
|
|
26410
|
+
"acpRunner",
|
|
26411
|
+
`budget recovery proxy relaunch failed (best-effort): ${e instanceof Error ? e.message : String(e)}`
|
|
26412
|
+
);
|
|
26413
|
+
}
|
|
26414
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
26415
|
+
};
|
|
26416
|
+
const budgetRecovery = createBudgetRecovery({
|
|
26417
|
+
publishText: (text) => publisher.publishOutput({ type: "text", content: text, done: true }),
|
|
26418
|
+
publishSelectPrompt: (question, options) => publisher.publishOutput({
|
|
26419
|
+
type: "select_prompt",
|
|
26420
|
+
content: question,
|
|
26421
|
+
options,
|
|
26422
|
+
optionDescriptions: options.map(() => ""),
|
|
26423
|
+
currentIndex: 0,
|
|
26424
|
+
done: true
|
|
26425
|
+
}),
|
|
26426
|
+
publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto7.randomUUID)(), prompt, options }),
|
|
26427
|
+
publishRawChunk: (chunk) => publisher.publishOutput(chunk),
|
|
26428
|
+
sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
|
|
26429
|
+
appendAgentReply: (text) => history.appendAgentReply(text),
|
|
26430
|
+
flushHistory: () => void history.flush(),
|
|
26431
|
+
relaunchProxyWithoutBudget,
|
|
26432
|
+
agentId: opts.agent,
|
|
26433
|
+
log: (msg) => log.info("acpRunner", msg)
|
|
26434
|
+
});
|
|
25957
26435
|
showInfo(`Starting ${opts.agent} via ACP adapter (${opts.adapter.requiresAgentBinary})\u2026`);
|
|
25958
26436
|
let handshake;
|
|
25959
26437
|
try {
|
|
@@ -26063,7 +26541,11 @@ async function runAcpSession(opts) {
|
|
|
26063
26541
|
getBeads,
|
|
26064
26542
|
publisher,
|
|
26065
26543
|
recentStderr,
|
|
26066
|
-
oneMRecovery
|
|
26544
|
+
oneMRecovery,
|
|
26545
|
+
budgetRecovery,
|
|
26546
|
+
{ get: () => _budgetReachedPosted, set: (v) => {
|
|
26547
|
+
_budgetReachedPosted = v;
|
|
26548
|
+
} }
|
|
26067
26549
|
);
|
|
26068
26550
|
},
|
|
26069
26551
|
{ id: opts.agent, name: opts.agent, displayName: opts.agent }
|
|
@@ -26087,7 +26569,7 @@ async function runAcpSession(opts) {
|
|
|
26087
26569
|
await new Promise(() => {
|
|
26088
26570
|
});
|
|
26089
26571
|
}
|
|
26090
|
-
async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, oneMRecovery) {
|
|
26572
|
+
async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, oneMRecovery, budgetRecovery, budgetReachedFlag) {
|
|
26091
26573
|
switch (cmd.type) {
|
|
26092
26574
|
case "beads_action": {
|
|
26093
26575
|
const beads = getBeads();
|
|
@@ -26147,13 +26629,19 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
26147
26629
|
} else if (shouldOfferOneMRecovery({ detail: "", recentStderr: recentStderr.join("\n"), finalText })) {
|
|
26148
26630
|
await oneMRecovery.offer(cmd.id, blocks);
|
|
26149
26631
|
} else {
|
|
26150
|
-
await streaming.closeTurnWithInteractiveDetection();
|
|
26632
|
+
const emittedSelectPrompt = await streaming.closeTurnWithInteractiveDetection();
|
|
26151
26633
|
const replyLine = formatAgentReplyLine(finalText);
|
|
26152
26634
|
if (replyLine.length > 0) {
|
|
26153
26635
|
showInfo(replyLine);
|
|
26154
26636
|
}
|
|
26155
26637
|
history.appendAgentReply(finalText);
|
|
26156
26638
|
void history.flush();
|
|
26639
|
+
if (!emittedSelectPrompt) {
|
|
26640
|
+
const suggestion = deriveInputSuggestion(finalText);
|
|
26641
|
+
if (suggestion !== null) {
|
|
26642
|
+
void publisher.publishOutput({ type: "input_suggestion", content: suggestion, done: true });
|
|
26643
|
+
}
|
|
26644
|
+
}
|
|
26157
26645
|
turnFiles.flushTurn().catch((err) => {
|
|
26158
26646
|
log.warn("acpRunner", `turnFiles.flushTurn failed: ${describeError(err)}`);
|
|
26159
26647
|
});
|
|
@@ -26165,6 +26653,24 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
26165
26653
|
const detail = describeError(err);
|
|
26166
26654
|
log.warn("acpRunner", `prompt failed: ${detail}`);
|
|
26167
26655
|
await cancelStuckTurn(client2);
|
|
26656
|
+
if (looksLikeBudgetExceeded(`${detail}
|
|
26657
|
+
${recentStderr.join("\n")}`)) {
|
|
26658
|
+
await streaming.closeAll();
|
|
26659
|
+
if (!budgetReachedFlag.get()) {
|
|
26660
|
+
budgetReachedFlag.set(true);
|
|
26661
|
+
void postBudgetReached({
|
|
26662
|
+
sessionId: opts.sessionId,
|
|
26663
|
+
pluginId: opts.pluginId,
|
|
26664
|
+
pluginAuthToken: opts.pluginAuthToken,
|
|
26665
|
+
agent: opts.agent,
|
|
26666
|
+
period: extractBudgetPeriod(`${detail}
|
|
26667
|
+
${recentStderr.join("\n")}`)
|
|
26668
|
+
});
|
|
26669
|
+
}
|
|
26670
|
+
await budgetRecovery.offer(cmd.id, blocks, `${detail}
|
|
26671
|
+
${recentStderr.join("\n")}`);
|
|
26672
|
+
return;
|
|
26673
|
+
}
|
|
26168
26674
|
if (shouldOfferOneMRecovery({ detail, recentStderr: recentStderr.join("\n"), finalText: "" })) {
|
|
26169
26675
|
await streaming.closeAll();
|
|
26170
26676
|
await oneMRecovery.offer(cmd.id, blocks);
|
|
@@ -26271,6 +26777,7 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
26271
26777
|
const index = typeof payload?.index === "number" ? payload.index : 0;
|
|
26272
26778
|
const offset = typeof payload?.from === "number" ? payload.from : 0;
|
|
26273
26779
|
const absoluteIndex = index + offset;
|
|
26780
|
+
if (await budgetRecovery.tryRecover(cmd.id, absoluteIndex)) return;
|
|
26274
26781
|
const result = streaming.resolveSelection(absoluteIndex);
|
|
26275
26782
|
switch (result.kind) {
|
|
26276
26783
|
case "resolved":
|
|
@@ -27527,15 +28034,15 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
27527
28034
|
}
|
|
27528
28035
|
|
|
27529
28036
|
// src/agents/claude/onboarding.ts
|
|
27530
|
-
var
|
|
27531
|
-
var
|
|
27532
|
-
var
|
|
28037
|
+
var fs48 = __toESM(require("fs"));
|
|
28038
|
+
var os39 = __toESM(require("os"));
|
|
28039
|
+
var path55 = __toESM(require("path"));
|
|
27533
28040
|
function ensureClaudeOnboarded() {
|
|
27534
28041
|
try {
|
|
27535
|
-
const file =
|
|
28042
|
+
const file = path55.join(os39.homedir(), ".claude.json");
|
|
27536
28043
|
let config = {};
|
|
27537
28044
|
try {
|
|
27538
|
-
config = JSON.parse(
|
|
28045
|
+
config = JSON.parse(fs48.readFileSync(file, "utf8"));
|
|
27539
28046
|
} catch {
|
|
27540
28047
|
}
|
|
27541
28048
|
if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
|
|
@@ -27546,8 +28053,8 @@ function ensureClaudeOnboarded() {
|
|
|
27546
28053
|
if (typeof config.lastOnboardingVersion !== "string") {
|
|
27547
28054
|
config.lastOnboardingVersion = "2.1.177";
|
|
27548
28055
|
}
|
|
27549
|
-
|
|
27550
|
-
|
|
28056
|
+
fs48.mkdirSync(path55.dirname(file), { recursive: true });
|
|
28057
|
+
fs48.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
27551
28058
|
log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
|
|
27552
28059
|
} catch (err) {
|
|
27553
28060
|
log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
|
|
@@ -28197,7 +28704,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
|
|
|
28197
28704
|
var import_child_process24 = require("child_process");
|
|
28198
28705
|
var import_util4 = require("util");
|
|
28199
28706
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
28200
|
-
var
|
|
28707
|
+
var path56 = __toESM(require("path"));
|
|
28201
28708
|
var execFileP6 = (0, import_util4.promisify)(import_child_process24.execFile);
|
|
28202
28709
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
28203
28710
|
function resetStdinForChild() {
|
|
@@ -28686,7 +29193,7 @@ var GitHubCodespacesProvider = class {
|
|
|
28686
29193
|
});
|
|
28687
29194
|
}
|
|
28688
29195
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
28689
|
-
const remoteDir =
|
|
29196
|
+
const remoteDir = path56.posix.dirname(remotePath);
|
|
28690
29197
|
const parts = [
|
|
28691
29198
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
28692
29199
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -28756,7 +29263,7 @@ function shellQuote(s) {
|
|
|
28756
29263
|
// src/services/providers/gitpod.ts
|
|
28757
29264
|
var import_child_process25 = require("child_process");
|
|
28758
29265
|
var import_util5 = require("util");
|
|
28759
|
-
var
|
|
29266
|
+
var path57 = __toESM(require("path"));
|
|
28760
29267
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
28761
29268
|
var execFileP7 = (0, import_util5.promisify)(import_child_process25.execFile);
|
|
28762
29269
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -28996,7 +29503,7 @@ var GitpodProvider = class {
|
|
|
28996
29503
|
});
|
|
28997
29504
|
}
|
|
28998
29505
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
28999
|
-
const remoteDir =
|
|
29506
|
+
const remoteDir = path57.posix.dirname(remotePath);
|
|
29000
29507
|
const parts = [
|
|
29001
29508
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
29002
29509
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -29032,7 +29539,7 @@ function shellQuote2(s) {
|
|
|
29032
29539
|
// src/services/providers/gitlab-workspaces.ts
|
|
29033
29540
|
var import_child_process26 = require("child_process");
|
|
29034
29541
|
var import_util6 = require("util");
|
|
29035
|
-
var
|
|
29542
|
+
var path58 = __toESM(require("path"));
|
|
29036
29543
|
var execFileP8 = (0, import_util6.promisify)(import_child_process26.execFile);
|
|
29037
29544
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
29038
29545
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -29292,7 +29799,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
29292
29799
|
}
|
|
29293
29800
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
29294
29801
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
29295
|
-
const remoteDir =
|
|
29802
|
+
const remoteDir = path58.posix.dirname(remotePath);
|
|
29296
29803
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
29297
29804
|
if (options.mode != null) {
|
|
29298
29805
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -29360,7 +29867,7 @@ function shellQuote3(s) {
|
|
|
29360
29867
|
// src/services/providers/railway.ts
|
|
29361
29868
|
var import_child_process27 = require("child_process");
|
|
29362
29869
|
var import_util7 = require("util");
|
|
29363
|
-
var
|
|
29870
|
+
var path59 = __toESM(require("path"));
|
|
29364
29871
|
var execFileP9 = (0, import_util7.promisify)(import_child_process27.execFile);
|
|
29365
29872
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
29366
29873
|
function resetStdinForChild4() {
|
|
@@ -29596,7 +30103,7 @@ var RailwayProvider = class {
|
|
|
29596
30103
|
if (!projectId || !serviceId) {
|
|
29597
30104
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
29598
30105
|
}
|
|
29599
|
-
const remoteDir =
|
|
30106
|
+
const remoteDir = path59.posix.dirname(remotePath);
|
|
29600
30107
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
29601
30108
|
if (options.mode != null) {
|
|
29602
30109
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -30242,8 +30749,8 @@ async function invite() {
|
|
|
30242
30749
|
var import_node_dns = require("dns");
|
|
30243
30750
|
var import_node_util5 = require("util");
|
|
30244
30751
|
var import_node_crypto8 = require("crypto");
|
|
30245
|
-
var
|
|
30246
|
-
var
|
|
30752
|
+
var fs49 = __toESM(require("fs"));
|
|
30753
|
+
var path60 = __toESM(require("path"));
|
|
30247
30754
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
30248
30755
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
30249
30756
|
async function checkDns(apiBase2) {
|
|
@@ -30299,13 +30806,13 @@ async function checkHealth(apiBase2) {
|
|
|
30299
30806
|
}
|
|
30300
30807
|
}
|
|
30301
30808
|
function checkConfigDir() {
|
|
30302
|
-
const dir =
|
|
30809
|
+
const dir = path60.join(require("os").homedir(), ".codeam");
|
|
30303
30810
|
try {
|
|
30304
|
-
|
|
30305
|
-
const probe =
|
|
30306
|
-
|
|
30307
|
-
const read2 =
|
|
30308
|
-
|
|
30811
|
+
fs49.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
30812
|
+
const probe = path60.join(dir, ".doctor-probe");
|
|
30813
|
+
fs49.writeFileSync(probe, "ok", { mode: 384 });
|
|
30814
|
+
const read2 = fs49.readFileSync(probe, "utf8");
|
|
30815
|
+
fs49.unlinkSync(probe);
|
|
30309
30816
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
30310
30817
|
return {
|
|
30311
30818
|
id: "config-dir",
|
|
@@ -30345,9 +30852,9 @@ function checkSessions() {
|
|
|
30345
30852
|
}
|
|
30346
30853
|
}
|
|
30347
30854
|
function checkAgentBinaries() {
|
|
30348
|
-
const
|
|
30855
|
+
const os41 = createOsStrategy();
|
|
30349
30856
|
return getEnabledAgents().map((meta) => {
|
|
30350
|
-
const found =
|
|
30857
|
+
const found = os41.findInPath(meta.binaryName);
|
|
30351
30858
|
return {
|
|
30352
30859
|
id: `agent-${meta.id}`,
|
|
30353
30860
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -30369,7 +30876,7 @@ function checkNodePty() {
|
|
|
30369
30876
|
detail: "not required on this platform"
|
|
30370
30877
|
};
|
|
30371
30878
|
}
|
|
30372
|
-
const vendoredPath =
|
|
30879
|
+
const vendoredPath = path60.join(__dirname, "vendor", "node-pty");
|
|
30373
30880
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
30374
30881
|
try {
|
|
30375
30882
|
require(target);
|
|
@@ -30411,7 +30918,7 @@ function checkChokidar() {
|
|
|
30411
30918
|
}
|
|
30412
30919
|
async function doctor(args2 = []) {
|
|
30413
30920
|
const json = args2.includes("--json");
|
|
30414
|
-
const cliVersion = true ? "2.
|
|
30921
|
+
const cliVersion = true ? "2.51.0" : "0.0.0-dev";
|
|
30415
30922
|
const apiBase2 = resolveApiBaseUrl();
|
|
30416
30923
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
30417
30924
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -30610,7 +31117,7 @@ async function completion(args2) {
|
|
|
30610
31117
|
// src/commands/version.ts
|
|
30611
31118
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
30612
31119
|
function version2() {
|
|
30613
|
-
const v = true ? "2.
|
|
31120
|
+
const v = true ? "2.51.0" : "unknown";
|
|
30614
31121
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
30615
31122
|
}
|
|
30616
31123
|
|
|
@@ -30759,10 +31266,10 @@ var EXIT_CODE_NAMES = {
|
|
|
30759
31266
|
};
|
|
30760
31267
|
|
|
30761
31268
|
// src/index.ts
|
|
30762
|
-
var
|
|
31269
|
+
var os40 = __toESM(require("os"));
|
|
30763
31270
|
if (!process.env.HOME) {
|
|
30764
31271
|
try {
|
|
30765
|
-
const home =
|
|
31272
|
+
const home = os40.homedir();
|
|
30766
31273
|
if (home) process.env.HOME = home;
|
|
30767
31274
|
} catch {
|
|
30768
31275
|
}
|