codeam-cli 2.63.1 → 2.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/index.js +714 -284
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2789,6 +2789,17 @@ function resolveApiBaseUrl() {
|
|
|
2789
2789
|
return DEFAULT_API_BASE_URL;
|
|
2790
2790
|
}
|
|
2791
2791
|
|
|
2792
|
+
// ../../packages/shared/src/types/agent-squad.ts
|
|
2793
|
+
var HANDOFF_FENCE_TAG = "codeam-handoff";
|
|
2794
|
+
var SQUAD_SPECIALTIES = {
|
|
2795
|
+
claude: "deep reasoning, refactors, and multi-step architecture work",
|
|
2796
|
+
codex: "fast, focused implementation and test fixing",
|
|
2797
|
+
cursor: "multi-file edits and codebase-wide changes",
|
|
2798
|
+
gemini: "large-context analysis across big files and logs",
|
|
2799
|
+
kimi: "long-context code reading and summarization",
|
|
2800
|
+
opencode: "general implementation tasks"
|
|
2801
|
+
};
|
|
2802
|
+
|
|
2792
2803
|
// ../../packages/shared/src/headroom/manifest.ts
|
|
2793
2804
|
var HEADROOM_PROXY_PORT = 8787;
|
|
2794
2805
|
var HEADROOM_PIP_COMPANIONS = [
|
|
@@ -2921,6 +2932,9 @@ var USER_EVENTS = {
|
|
|
2921
2932
|
// the backend re-publishes them on the per-user SSE bus (mirrored in repo A).
|
|
2922
2933
|
SWITCH_AGENT_PROGRESS: "switch_agent_progress",
|
|
2923
2934
|
SWITCH_AGENT_STATUS: "switch_agent_status",
|
|
2935
|
+
// Agent Squad — the CLI posts these to /api/agent-switch/events; PRO-gated.
|
|
2936
|
+
HANDOFF_PROPOSED: "handoff_proposed",
|
|
2937
|
+
HANDOFF_RESOLVED: "handoff_resolved",
|
|
2924
2938
|
// VCS / PR Command Center — the backend publishes this after an agent finishes
|
|
2925
2939
|
// reviewing a PR (verdict + comment count + findings), driving the mobile
|
|
2926
2940
|
// completion screen + push. Mirrored in repo A's app-shared events.ts.
|
|
@@ -3125,11 +3139,11 @@ function quiet(fn) {
|
|
|
3125
3139
|
log.debug(TAG, "ignored sync error", err);
|
|
3126
3140
|
}
|
|
3127
3141
|
}
|
|
3128
|
-
function rmIfExistsQuiet(
|
|
3142
|
+
function rmIfExistsQuiet(path91) {
|
|
3129
3143
|
try {
|
|
3130
|
-
fs2.rmSync(
|
|
3144
|
+
fs2.rmSync(path91, { force: true });
|
|
3131
3145
|
} catch (err) {
|
|
3132
|
-
log.debug(TAG, `rmIfExists failed for ${
|
|
3146
|
+
log.debug(TAG, `rmIfExists failed for ${path91}`, err);
|
|
3133
3147
|
}
|
|
3134
3148
|
}
|
|
3135
3149
|
function killQuiet(target, signal = "SIGTERM") {
|
|
@@ -3320,8 +3334,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
3320
3334
|
return decodedFile;
|
|
3321
3335
|
};
|
|
3322
3336
|
}
|
|
3323
|
-
function normalizeWindowsPath(
|
|
3324
|
-
return
|
|
3337
|
+
function normalizeWindowsPath(path91) {
|
|
3338
|
+
return path91.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
3325
3339
|
}
|
|
3326
3340
|
|
|
3327
3341
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -5801,9 +5815,9 @@ async function addSourceContext(frames) {
|
|
|
5801
5815
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
5802
5816
|
return frames;
|
|
5803
5817
|
}
|
|
5804
|
-
function getContextLinesFromFile(
|
|
5818
|
+
function getContextLinesFromFile(path91, ranges, output) {
|
|
5805
5819
|
return new Promise((resolve9) => {
|
|
5806
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
5820
|
+
const stream = (0, import_node_fs.createReadStream)(path91);
|
|
5807
5821
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
5808
5822
|
input: stream
|
|
5809
5823
|
});
|
|
@@ -5818,7 +5832,7 @@ function getContextLinesFromFile(path90, ranges, output) {
|
|
|
5818
5832
|
let rangeStart = range[0];
|
|
5819
5833
|
let rangeEnd = range[1];
|
|
5820
5834
|
function onStreamError() {
|
|
5821
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
5835
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path91, 1);
|
|
5822
5836
|
lineReaded.close();
|
|
5823
5837
|
lineReaded.removeAllListeners();
|
|
5824
5838
|
destroyStreamAndResolve();
|
|
@@ -5879,8 +5893,8 @@ function clearLineContext(frame) {
|
|
|
5879
5893
|
delete frame.context_line;
|
|
5880
5894
|
delete frame.post_context;
|
|
5881
5895
|
}
|
|
5882
|
-
function shouldSkipContextLinesForFile(
|
|
5883
|
-
return
|
|
5896
|
+
function shouldSkipContextLinesForFile(path91) {
|
|
5897
|
+
return path91.startsWith("node:") || path91.endsWith(".min.js") || path91.endsWith(".min.cjs") || path91.endsWith(".min.mjs") || path91.startsWith("data:");
|
|
5884
5898
|
}
|
|
5885
5899
|
function shouldSkipContextLinesForFrame(frame) {
|
|
5886
5900
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -8034,7 +8048,7 @@ function readAnonId() {
|
|
|
8034
8048
|
}
|
|
8035
8049
|
function superProperties() {
|
|
8036
8050
|
return {
|
|
8037
|
-
cliVersion: true ? "2.
|
|
8051
|
+
cliVersion: true ? "2.64.0" : "0.0.0-dev",
|
|
8038
8052
|
nodeVersion: process.version,
|
|
8039
8053
|
platform: process.platform,
|
|
8040
8054
|
arch: process.arch,
|
|
@@ -8215,7 +8229,7 @@ var os4 = __toESM(require("os"));
|
|
|
8215
8229
|
// package.json
|
|
8216
8230
|
var package_default = {
|
|
8217
8231
|
name: "codeam-cli",
|
|
8218
|
-
version: "2.
|
|
8232
|
+
version: "2.64.0",
|
|
8219
8233
|
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.",
|
|
8220
8234
|
type: "commonjs",
|
|
8221
8235
|
main: "dist/index.js",
|
|
@@ -8611,6 +8625,20 @@ async function fetchProvisionCredential(input) {
|
|
|
8611
8625
|
return null;
|
|
8612
8626
|
}
|
|
8613
8627
|
}
|
|
8628
|
+
async function fetchSquadRoster(input) {
|
|
8629
|
+
try {
|
|
8630
|
+
const res = await _transport.postJsonAuthed(
|
|
8631
|
+
`${API_BASE}/api/plugin/agents/roster`,
|
|
8632
|
+
{ sessionId: input.sessionId, pluginId: input.pluginId },
|
|
8633
|
+
input.pluginAuthToken
|
|
8634
|
+
);
|
|
8635
|
+
const data = res?.data;
|
|
8636
|
+
if (!data || !Array.isArray(data.agents)) return null;
|
|
8637
|
+
return { agents: data.agents, handoffsEnabled: data.handoffsEnabled === true };
|
|
8638
|
+
} catch {
|
|
8639
|
+
return null;
|
|
8640
|
+
}
|
|
8641
|
+
}
|
|
8614
8642
|
async function postAgentSwitchEvent(input) {
|
|
8615
8643
|
try {
|
|
8616
8644
|
await _transport.postJsonAuthed(
|
|
@@ -8773,9 +8801,7 @@ async function _postJsonAuthed(url2, body, pluginAuthToken) {
|
|
|
8773
8801
|
});
|
|
8774
8802
|
res.on("end", () => {
|
|
8775
8803
|
if (res.statusCode && res.statusCode >= 400) {
|
|
8776
|
-
reject(
|
|
8777
|
-
makeHttpError(res.statusCode, res.headers["retry-after"], responseBody)
|
|
8778
|
-
);
|
|
8804
|
+
reject(makeHttpError(res.statusCode, res.headers["retry-after"], responseBody));
|
|
8779
8805
|
return;
|
|
8780
8806
|
}
|
|
8781
8807
|
try {
|
|
@@ -9655,7 +9681,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9655
9681
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9656
9682
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9657
9683
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9658
|
-
..."2.
|
|
9684
|
+
..."2.64.0" ? { ideVersion: "2.64.0" } : {}
|
|
9659
9685
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9660
9686
|
}
|
|
9661
9687
|
/**
|
|
@@ -9680,7 +9706,8 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9680
9706
|
];
|
|
9681
9707
|
_postJson(`${API_BASE2}/api/plugin/agents`, {
|
|
9682
9708
|
pluginId: this.pluginId,
|
|
9683
|
-
agents
|
|
9709
|
+
agents,
|
|
9710
|
+
capabilities: { squad: true }
|
|
9684
9711
|
}).then(() => {
|
|
9685
9712
|
this.agentsRegistered = true;
|
|
9686
9713
|
}).catch(() => {
|
|
@@ -9899,10 +9926,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
9899
9926
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
9900
9927
|
/[\\/]Templates([\\/]|$)/i
|
|
9901
9928
|
];
|
|
9902
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
9929
|
+
function isUnsafeWindowsWatchRoot(dir, homedir53) {
|
|
9903
9930
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
9904
9931
|
const cwd = norm(dir);
|
|
9905
|
-
const home = norm(
|
|
9932
|
+
const home = norm(homedir53);
|
|
9906
9933
|
if (cwd === home) return true;
|
|
9907
9934
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
9908
9935
|
const sysRoots = [
|
|
@@ -14558,10 +14585,10 @@ function buildForPlatform(platform3) {
|
|
|
14558
14585
|
var import_node_crypto4 = require("crypto");
|
|
14559
14586
|
|
|
14560
14587
|
// src/agents/claude/resolver.ts
|
|
14561
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
14562
|
-
const found =
|
|
14588
|
+
function buildClaudeLaunch(extraArgs = [], os66 = createOsStrategy()) {
|
|
14589
|
+
const found = os66.findInPath("claude") ?? os66.findInPath("claude-code");
|
|
14563
14590
|
if (!found) return null;
|
|
14564
|
-
return
|
|
14591
|
+
return os66.buildLaunch(found, extraArgs);
|
|
14565
14592
|
}
|
|
14566
14593
|
|
|
14567
14594
|
// src/agents/claude/installer.ts
|
|
@@ -15151,8 +15178,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
15151
15178
|
meta = getAgent("claude");
|
|
15152
15179
|
mode = "interactive";
|
|
15153
15180
|
os;
|
|
15154
|
-
constructor(
|
|
15155
|
-
this.os =
|
|
15181
|
+
constructor(os66) {
|
|
15182
|
+
this.os = os66;
|
|
15156
15183
|
}
|
|
15157
15184
|
/**
|
|
15158
15185
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -15932,8 +15959,8 @@ function codexCredentialLocator() {
|
|
|
15932
15959
|
function codexLoginLauncher() {
|
|
15933
15960
|
return {
|
|
15934
15961
|
async ensureInstalled() {
|
|
15935
|
-
const
|
|
15936
|
-
return
|
|
15962
|
+
const os66 = createOsStrategy();
|
|
15963
|
+
return os66.findInPath("codex") !== null;
|
|
15937
15964
|
},
|
|
15938
15965
|
launch() {
|
|
15939
15966
|
return (0, import_node_child_process4.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -15956,8 +15983,8 @@ var CodexRuntimeStrategy = class {
|
|
|
15956
15983
|
meta = getAgent("codex");
|
|
15957
15984
|
mode = "interactive";
|
|
15958
15985
|
os;
|
|
15959
|
-
constructor(
|
|
15960
|
-
this.os =
|
|
15986
|
+
constructor(os66) {
|
|
15987
|
+
this.os = os66;
|
|
15961
15988
|
}
|
|
15962
15989
|
async prepareLaunch() {
|
|
15963
15990
|
let binary = this.os.findInPath("codex");
|
|
@@ -16066,12 +16093,12 @@ var CodexRuntimeStrategy = class {
|
|
|
16066
16093
|
});
|
|
16067
16094
|
}
|
|
16068
16095
|
};
|
|
16069
|
-
function resolveNpm(
|
|
16070
|
-
return
|
|
16096
|
+
function resolveNpm(os66) {
|
|
16097
|
+
return os66.id === "win32" ? "npm.cmd" : "npm";
|
|
16071
16098
|
}
|
|
16072
|
-
async function installCodexViaNpm(
|
|
16099
|
+
async function installCodexViaNpm(os66) {
|
|
16073
16100
|
return new Promise((resolve9, reject) => {
|
|
16074
|
-
const proc = (0, import_node_child_process5.spawn)(resolveNpm(
|
|
16101
|
+
const proc = (0, import_node_child_process5.spawn)(resolveNpm(os66), ["install", "-g", "@openai/codex"], {
|
|
16075
16102
|
stdio: "inherit"
|
|
16076
16103
|
});
|
|
16077
16104
|
proc.on("close", (code) => {
|
|
@@ -16088,16 +16115,16 @@ async function installCodexViaNpm(os65) {
|
|
|
16088
16115
|
});
|
|
16089
16116
|
});
|
|
16090
16117
|
}
|
|
16091
|
-
function augmentNpmGlobalBin(
|
|
16118
|
+
function augmentNpmGlobalBin(os66) {
|
|
16092
16119
|
try {
|
|
16093
|
-
const result = (0, import_node_child_process5.spawnSync)(resolveNpm(
|
|
16120
|
+
const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os66), ["prefix", "-g"], {
|
|
16094
16121
|
stdio: ["ignore", "pipe", "ignore"]
|
|
16095
16122
|
});
|
|
16096
16123
|
if (result.status !== 0) return;
|
|
16097
16124
|
const prefix = result.stdout.toString().trim();
|
|
16098
16125
|
if (!prefix) return;
|
|
16099
|
-
const binDir =
|
|
16100
|
-
|
|
16126
|
+
const binDir = os66.id === "win32" ? prefix : path25.join(prefix, "bin");
|
|
16127
|
+
os66.augmentPath([binDir]);
|
|
16101
16128
|
} catch {
|
|
16102
16129
|
}
|
|
16103
16130
|
}
|
|
@@ -16496,10 +16523,10 @@ function manualInstallHint(runner, tools) {
|
|
|
16496
16523
|
const argv = osPackageInstallArgv(detectPackageManager(runner), [...tools]);
|
|
16497
16524
|
return argv ? `\`sudo ${argv.join(" ")}\`` : `your package manager (e.g. \`${pkgs}\`)`;
|
|
16498
16525
|
}
|
|
16499
|
-
function writeUnzipShim(
|
|
16526
|
+
function writeUnzipShim(os66, runner) {
|
|
16500
16527
|
const python = ["python3", "python"].find((p2) => runner.which(p2));
|
|
16501
16528
|
if (!python) return null;
|
|
16502
|
-
const dir =
|
|
16529
|
+
const dir = os66.scratchPath("codeam-cr-prereq");
|
|
16503
16530
|
const shim = path27.join(dir, "unzip");
|
|
16504
16531
|
const script = `#!/bin/sh
|
|
16505
16532
|
set -e
|
|
@@ -16521,9 +16548,9 @@ exec ${python} -m zipfile -e "$archive" "$dest"
|
|
|
16521
16548
|
(0, import_node_fs5.chmodSync)(shim, 448);
|
|
16522
16549
|
return dir;
|
|
16523
16550
|
}
|
|
16524
|
-
async function ensureInstallPrerequisites(
|
|
16551
|
+
async function ensureInstallPrerequisites(os66, deps = {}) {
|
|
16525
16552
|
const runner = deps.runner ?? defaultHeadroomRunner;
|
|
16526
|
-
const missing = REQUIRED_TOOLS.filter((t2) =>
|
|
16553
|
+
const missing = REQUIRED_TOOLS.filter((t2) => os66.findInPath(t2) === null);
|
|
16527
16554
|
if (missing.length === 0) return { ok: true, extraPath: [] };
|
|
16528
16555
|
log.info(
|
|
16529
16556
|
"coderabbit",
|
|
@@ -16542,10 +16569,10 @@ async function ensureInstallPrerequisites(os65, deps = {}) {
|
|
|
16542
16569
|
);
|
|
16543
16570
|
}
|
|
16544
16571
|
}
|
|
16545
|
-
const stillMissing = REQUIRED_TOOLS.filter((t2) =>
|
|
16572
|
+
const stillMissing = REQUIRED_TOOLS.filter((t2) => os66.findInPath(t2) === null);
|
|
16546
16573
|
if (stillMissing.length === 0) return { ok: true, extraPath: [] };
|
|
16547
16574
|
if (stillMissing.length === 1 && stillMissing[0] === "unzip") {
|
|
16548
|
-
const shimDir = writeUnzipShim(
|
|
16575
|
+
const shimDir = writeUnzipShim(os66, runner);
|
|
16549
16576
|
if (shimDir) {
|
|
16550
16577
|
log.info("coderabbit", "unzip is unavailable \u2014 using a scoped python zipfile shim");
|
|
16551
16578
|
return { ok: true, extraPath: [shimDir] };
|
|
@@ -16608,15 +16635,15 @@ function summarizeInstallFailure(output) {
|
|
|
16608
16635
|
}
|
|
16609
16636
|
return lines.length > 0 ? lines[lines.length - 1] : null;
|
|
16610
16637
|
}
|
|
16611
|
-
async function ensureCoderabbitInstalled(
|
|
16612
|
-
if (
|
|
16613
|
-
if (
|
|
16638
|
+
async function ensureCoderabbitInstalled(os66, deps = {}) {
|
|
16639
|
+
if (os66.findInPath("coderabbit")) return { ok: true };
|
|
16640
|
+
if (os66.id === "win32") {
|
|
16614
16641
|
return {
|
|
16615
16642
|
ok: false,
|
|
16616
16643
|
error: "CodeRabbit on Windows requires WSL. Install the CLI inside your WSL distribution (curl -fsSL https://cli.coderabbit.ai/install.sh | sh), then try again."
|
|
16617
16644
|
};
|
|
16618
16645
|
}
|
|
16619
|
-
const prereq = await ensureInstallPrerequisites(
|
|
16646
|
+
const prereq = await ensureInstallPrerequisites(os66, deps);
|
|
16620
16647
|
if (!prereq.ok) return { ok: false, error: prereq.error };
|
|
16621
16648
|
const env = { ...process.env };
|
|
16622
16649
|
if (prereq.extraPath.length > 0) {
|
|
@@ -16632,8 +16659,8 @@ async function ensureCoderabbitInstalled(os65, deps = {}) {
|
|
|
16632
16659
|
error: detail ? `CodeRabbit CLI install failed: ${detail}` : "CodeRabbit CLI install failed \u2014 check this machine's network egress and try again."
|
|
16633
16660
|
};
|
|
16634
16661
|
}
|
|
16635
|
-
|
|
16636
|
-
if (
|
|
16662
|
+
os66.augmentPath([`${os66.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
16663
|
+
if (os66.findInPath("coderabbit") === null) {
|
|
16637
16664
|
const detail = summarizeInstallFailure(output);
|
|
16638
16665
|
return {
|
|
16639
16666
|
ok: false,
|
|
@@ -16675,10 +16702,10 @@ function coderabbitCredentialLocator() {
|
|
|
16675
16702
|
validate: validateNonEmptyCredential
|
|
16676
16703
|
};
|
|
16677
16704
|
}
|
|
16678
|
-
function coderabbitLoginLauncher(
|
|
16705
|
+
function coderabbitLoginLauncher(os66) {
|
|
16679
16706
|
return {
|
|
16680
16707
|
async ensureInstalled() {
|
|
16681
|
-
const result = await ensureCoderabbitInstalled(
|
|
16708
|
+
const result = await ensureCoderabbitInstalled(os66);
|
|
16682
16709
|
if (!result.ok && result.error) console.error(`
|
|
16683
16710
|
\u2717 ${result.error}
|
|
16684
16711
|
`);
|
|
@@ -16738,8 +16765,8 @@ function pickLine(obj) {
|
|
|
16738
16765
|
function toHunk(raw, groupSeverity) {
|
|
16739
16766
|
if (!raw || typeof raw !== "object") return null;
|
|
16740
16767
|
const o = raw;
|
|
16741
|
-
const
|
|
16742
|
-
if (!
|
|
16768
|
+
const path91 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
|
|
16769
|
+
if (!path91) return null;
|
|
16743
16770
|
const message = asString(
|
|
16744
16771
|
pick(o, [
|
|
16745
16772
|
"comment",
|
|
@@ -16756,7 +16783,7 @@ function toHunk(raw, groupSeverity) {
|
|
|
16756
16783
|
const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
|
|
16757
16784
|
const locObj = pick(o, ["location"]) ?? o;
|
|
16758
16785
|
return {
|
|
16759
|
-
path:
|
|
16786
|
+
path: path91.trim(),
|
|
16760
16787
|
line: pickLine(o) ?? pickLine(locObj),
|
|
16761
16788
|
severity,
|
|
16762
16789
|
message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
|
|
@@ -16839,10 +16866,10 @@ function parsePlain(stdout) {
|
|
|
16839
16866
|
for (const line of stdout.split(/\r?\n/)) {
|
|
16840
16867
|
const m = line.match(HUNK_LINE_RE);
|
|
16841
16868
|
if (!m) continue;
|
|
16842
|
-
const [,
|
|
16843
|
-
if (!
|
|
16869
|
+
const [, path91, lineNo, sevToken, message] = m;
|
|
16870
|
+
if (!path91 || !lineNo || !message) continue;
|
|
16844
16871
|
hunks.push({
|
|
16845
|
-
path:
|
|
16872
|
+
path: path91.trim(),
|
|
16846
16873
|
line: Number(lineNo),
|
|
16847
16874
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
16848
16875
|
message: message.trim().replace(/^[*-]\s+/, "")
|
|
@@ -16902,8 +16929,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
16902
16929
|
meta = getAgent("coderabbit");
|
|
16903
16930
|
mode = "batch";
|
|
16904
16931
|
os;
|
|
16905
|
-
constructor(
|
|
16906
|
-
this.os =
|
|
16932
|
+
constructor(os66) {
|
|
16933
|
+
this.os = os66;
|
|
16907
16934
|
}
|
|
16908
16935
|
getDefaultArgs() {
|
|
16909
16936
|
return ["review", "--agent"];
|
|
@@ -17174,10 +17201,10 @@ function cursorCredentialLocator() {
|
|
|
17174
17201
|
validate: validateNonEmptyCredential
|
|
17175
17202
|
};
|
|
17176
17203
|
}
|
|
17177
|
-
function cursorLoginLauncher(
|
|
17204
|
+
function cursorLoginLauncher(os66) {
|
|
17178
17205
|
return {
|
|
17179
17206
|
async ensureInstalled() {
|
|
17180
|
-
if (
|
|
17207
|
+
if (os66.findInPath("cursor-agent")) return true;
|
|
17181
17208
|
console.error(
|
|
17182
17209
|
"\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"
|
|
17183
17210
|
);
|
|
@@ -17241,8 +17268,8 @@ var CursorRuntimeStrategy = class {
|
|
|
17241
17268
|
meta = getAgent("cursor");
|
|
17242
17269
|
mode = "interactive";
|
|
17243
17270
|
os;
|
|
17244
|
-
constructor(
|
|
17245
|
-
this.os =
|
|
17271
|
+
constructor(os66) {
|
|
17272
|
+
this.os = os66;
|
|
17246
17273
|
}
|
|
17247
17274
|
async prepareLaunch() {
|
|
17248
17275
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -17458,10 +17485,10 @@ function aiderCredentialLocator() {
|
|
|
17458
17485
|
validate: validateNonEmptyCredential
|
|
17459
17486
|
};
|
|
17460
17487
|
}
|
|
17461
|
-
function aiderLoginLauncher(
|
|
17488
|
+
function aiderLoginLauncher(os66) {
|
|
17462
17489
|
return {
|
|
17463
17490
|
async ensureInstalled() {
|
|
17464
|
-
if (
|
|
17491
|
+
if (os66.findInPath("aider")) return true;
|
|
17465
17492
|
console.error(
|
|
17466
17493
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
17467
17494
|
);
|
|
@@ -17471,7 +17498,7 @@ function aiderLoginLauncher(os65) {
|
|
|
17471
17498
|
console.error(
|
|
17472
17499
|
"\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"
|
|
17473
17500
|
);
|
|
17474
|
-
return (0, import_node_child_process12.spawn)(
|
|
17501
|
+
return (0, import_node_child_process12.spawn)(os66.id === "win32" ? "cmd.exe" : "sh", os66.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
17475
17502
|
stdio: "ignore"
|
|
17476
17503
|
});
|
|
17477
17504
|
}
|
|
@@ -17543,8 +17570,8 @@ var AiderRuntimeStrategy = class {
|
|
|
17543
17570
|
meta = getAgent("aider");
|
|
17544
17571
|
mode = "interactive";
|
|
17545
17572
|
os;
|
|
17546
|
-
constructor(
|
|
17547
|
-
this.os =
|
|
17573
|
+
constructor(os66) {
|
|
17574
|
+
this.os = os66;
|
|
17548
17575
|
}
|
|
17549
17576
|
async prepareLaunch() {
|
|
17550
17577
|
const binary = this.os.findInPath("aider");
|
|
@@ -17676,8 +17703,8 @@ function geminiCredentialLocator() {
|
|
|
17676
17703
|
function geminiLoginLauncher() {
|
|
17677
17704
|
return {
|
|
17678
17705
|
async ensureInstalled() {
|
|
17679
|
-
const
|
|
17680
|
-
return
|
|
17706
|
+
const os66 = createOsStrategy();
|
|
17707
|
+
return os66.findInPath("gemini") !== null;
|
|
17681
17708
|
},
|
|
17682
17709
|
launch() {
|
|
17683
17710
|
return (0, import_node_child_process13.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -17867,8 +17894,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
17867
17894
|
meta = getAgent("gemini");
|
|
17868
17895
|
mode = "interactive";
|
|
17869
17896
|
os;
|
|
17870
|
-
constructor(
|
|
17871
|
-
this.os =
|
|
17897
|
+
constructor(os66) {
|
|
17898
|
+
this.os = os66;
|
|
17872
17899
|
}
|
|
17873
17900
|
async prepareLaunch() {
|
|
17874
17901
|
const binary = this.os.findInPath("gemini");
|
|
@@ -18159,8 +18186,8 @@ var KimiRuntimeStrategy = class {
|
|
|
18159
18186
|
meta = getAgent("kimi");
|
|
18160
18187
|
mode = "interactive";
|
|
18161
18188
|
os;
|
|
18162
|
-
constructor(
|
|
18163
|
-
this.os =
|
|
18189
|
+
constructor(os66) {
|
|
18190
|
+
this.os = os66;
|
|
18164
18191
|
}
|
|
18165
18192
|
async prepareLaunch() {
|
|
18166
18193
|
const binary = this.os.findInPath("kimi");
|
|
@@ -18302,8 +18329,8 @@ var OpencodeRuntimeStrategy = class {
|
|
|
18302
18329
|
meta = getAgent("opencode");
|
|
18303
18330
|
mode = "interactive";
|
|
18304
18331
|
os;
|
|
18305
|
-
constructor(
|
|
18306
|
-
this.os =
|
|
18332
|
+
constructor(os66) {
|
|
18333
|
+
this.os = os66;
|
|
18307
18334
|
}
|
|
18308
18335
|
async prepareLaunch() {
|
|
18309
18336
|
const binary = this.os.findInPath("opencode");
|
|
@@ -18387,20 +18414,20 @@ var OpencodeRuntimeStrategy = class {
|
|
|
18387
18414
|
|
|
18388
18415
|
// src/agents/registry.ts
|
|
18389
18416
|
var runtimeBuilders = {
|
|
18390
|
-
claude: (
|
|
18391
|
-
codex: (
|
|
18392
|
-
coderabbit: (
|
|
18393
|
-
cursor: (
|
|
18394
|
-
aider: (
|
|
18395
|
-
gemini: (
|
|
18396
|
-
kimi: (
|
|
18397
|
-
opencode: (
|
|
18417
|
+
claude: (os66) => new ClaudeRuntimeStrategy(os66),
|
|
18418
|
+
codex: (os66) => new CodexRuntimeStrategy(os66),
|
|
18419
|
+
coderabbit: (os66) => new CoderabbitRuntimeStrategy(os66),
|
|
18420
|
+
cursor: (os66) => new CursorRuntimeStrategy(os66),
|
|
18421
|
+
aider: (os66) => new AiderRuntimeStrategy(os66),
|
|
18422
|
+
gemini: (os66) => new GeminiRuntimeStrategy(os66),
|
|
18423
|
+
kimi: (os66) => new KimiRuntimeStrategy(os66),
|
|
18424
|
+
opencode: (os66) => new OpencodeRuntimeStrategy(os66)
|
|
18398
18425
|
};
|
|
18399
18426
|
var deployBuilders = {
|
|
18400
18427
|
claude: () => new ClaudeDeployStrategy(),
|
|
18401
18428
|
codex: () => new CodexDeployStrategy()
|
|
18402
18429
|
};
|
|
18403
|
-
function createAgentStrategy(agent,
|
|
18430
|
+
function createAgentStrategy(agent, os66 = createOsStrategy()) {
|
|
18404
18431
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
18405
18432
|
throw new Error(
|
|
18406
18433
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -18410,10 +18437,10 @@ function createAgentStrategy(agent, os65 = createOsStrategy()) {
|
|
|
18410
18437
|
if (!build) {
|
|
18411
18438
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
18412
18439
|
}
|
|
18413
|
-
return build(
|
|
18440
|
+
return build(os66);
|
|
18414
18441
|
}
|
|
18415
|
-
function createInteractiveAgentStrategy(agent,
|
|
18416
|
-
const s = createAgentStrategy(agent,
|
|
18442
|
+
function createInteractiveAgentStrategy(agent, os66 = createOsStrategy()) {
|
|
18443
|
+
const s = createAgentStrategy(agent, os66);
|
|
18417
18444
|
if (s.mode !== "interactive") {
|
|
18418
18445
|
throw new Error(
|
|
18419
18446
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -19091,8 +19118,8 @@ function collectChangedFiles(cwd) {
|
|
|
19091
19118
|
}
|
|
19092
19119
|
return [...byPath.values()];
|
|
19093
19120
|
}
|
|
19094
|
-
function restoreCoderabbitOauthBlob(
|
|
19095
|
-
const dir = path38.join(
|
|
19121
|
+
function restoreCoderabbitOauthBlob(os66, value) {
|
|
19122
|
+
const dir = path38.join(os66.homeDir(), ".coderabbit");
|
|
19096
19123
|
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
19097
19124
|
let file = "auth.json";
|
|
19098
19125
|
let contents = value.trim();
|
|
@@ -19112,26 +19139,26 @@ function installFailureMessage(result) {
|
|
|
19112
19139
|
return result.error ?? "CodeRabbit CLI could not be installed";
|
|
19113
19140
|
}
|
|
19114
19141
|
async function configureCoderabbit(input, deps = {}) {
|
|
19115
|
-
const
|
|
19142
|
+
const os66 = deps.os ?? createOsStrategy();
|
|
19116
19143
|
const ensureInstalled = deps.ensureInstalled ?? ensureCoderabbitInstalled;
|
|
19117
19144
|
const isLoggedIn = deps.isLoggedIn ?? defaultIsLoggedIn;
|
|
19118
19145
|
const runOAuth = deps.runOAuthLogin ?? runCoderabbitOAuthLogin;
|
|
19119
19146
|
const snapshot = deps.snapshotDir ?? (() => snapshotCredentialDir());
|
|
19120
19147
|
const capture2 = deps.captureCredential ?? ((b) => diffCapturedCredential(b));
|
|
19121
19148
|
const loginWithApiKey = deps.loginWithApiKey ?? defaultLoginWithApiKey;
|
|
19122
|
-
const home =
|
|
19123
|
-
|
|
19124
|
-
|
|
19149
|
+
const home = os66.homeDir();
|
|
19150
|
+
os66.augmentPath(
|
|
19151
|
+
os66.id === "win32" ? [
|
|
19125
19152
|
path38.join(home, ".local", "bin"),
|
|
19126
19153
|
path38.join(process.env.APPDATA ?? path38.join(home, "AppData", "Roaming"), "npm"),
|
|
19127
19154
|
path38.join(home, "scoop", "shims")
|
|
19128
19155
|
] : [path38.join(home, ".local", "bin"), "/opt/homebrew/bin", "/usr/local/bin"]
|
|
19129
19156
|
);
|
|
19130
|
-
const installed2 =
|
|
19157
|
+
const installed2 = os66.findInPath("coderabbit") !== null;
|
|
19131
19158
|
const base = () => ({
|
|
19132
19159
|
action: input.action,
|
|
19133
19160
|
supported: true,
|
|
19134
|
-
installed:
|
|
19161
|
+
installed: os66.findInPath("coderabbit") !== null,
|
|
19135
19162
|
loggedIn: false
|
|
19136
19163
|
});
|
|
19137
19164
|
if (input.action === "status") {
|
|
@@ -19145,7 +19172,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
19145
19172
|
const key = (input.apiKey ?? "").trim();
|
|
19146
19173
|
if (!key) return { ...res2, error: "No API key provided" };
|
|
19147
19174
|
if (!res2.installed) {
|
|
19148
|
-
const inst = await ensureInstalled(
|
|
19175
|
+
const inst = await ensureInstalled(os66);
|
|
19149
19176
|
res2.installed = inst.ok;
|
|
19150
19177
|
if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
|
|
19151
19178
|
}
|
|
@@ -19169,7 +19196,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
19169
19196
|
}
|
|
19170
19197
|
if (!res2.installed) {
|
|
19171
19198
|
deps.onEvent?.({ kind: "installing" });
|
|
19172
|
-
const inst = await ensureInstalled(
|
|
19199
|
+
const inst = await ensureInstalled(os66);
|
|
19173
19200
|
res2.installed = inst.ok;
|
|
19174
19201
|
if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
|
|
19175
19202
|
}
|
|
@@ -19186,7 +19213,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
19186
19213
|
return { ...res2, loggedIn: true, linked: true };
|
|
19187
19214
|
}
|
|
19188
19215
|
try {
|
|
19189
|
-
restoreCoderabbitOauthBlob(
|
|
19216
|
+
restoreCoderabbitOauthBlob(os66, cred.credential);
|
|
19190
19217
|
} catch (err) {
|
|
19191
19218
|
return {
|
|
19192
19219
|
...res2,
|
|
@@ -19210,7 +19237,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
19210
19237
|
const res2 = base();
|
|
19211
19238
|
if (!installed2) {
|
|
19212
19239
|
deps.onEvent?.({ kind: "installing" });
|
|
19213
|
-
const inst = await ensureInstalled(
|
|
19240
|
+
const inst = await ensureInstalled(os66);
|
|
19214
19241
|
res2.installed = inst.ok;
|
|
19215
19242
|
if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
|
|
19216
19243
|
}
|
|
@@ -19250,7 +19277,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
19250
19277
|
}
|
|
19251
19278
|
const res = base();
|
|
19252
19279
|
if (!res.installed) {
|
|
19253
|
-
const inst = await ensureInstalled(
|
|
19280
|
+
const inst = await ensureInstalled(os66);
|
|
19254
19281
|
res.installed = inst.ok;
|
|
19255
19282
|
if (!inst.ok) return { ...res, error: installFailureMessage(inst) };
|
|
19256
19283
|
}
|
|
@@ -21073,7 +21100,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
21073
21100
|
if (process.env.NODE_ENV === "test") return;
|
|
21074
21101
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
21075
21102
|
if (process.env.CI) return;
|
|
21076
|
-
const current2 = true ? "2.
|
|
21103
|
+
const current2 = true ? "2.64.0" : null;
|
|
21077
21104
|
if (!current2) return;
|
|
21078
21105
|
const cache = readCache();
|
|
21079
21106
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -21090,7 +21117,7 @@ function checkForUpdates() {
|
|
|
21090
21117
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
21091
21118
|
if (process.env.CI) return;
|
|
21092
21119
|
if (!process.stdout.isTTY) return;
|
|
21093
|
-
const current2 = true ? "2.
|
|
21120
|
+
const current2 = true ? "2.64.0" : null;
|
|
21094
21121
|
if (!current2) return;
|
|
21095
21122
|
const cache = readCache();
|
|
21096
21123
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -21110,7 +21137,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
21110
21137
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
21111
21138
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
21112
21139
|
function currentCliVersion() {
|
|
21113
|
-
return true ? "2.
|
|
21140
|
+
return true ? "2.64.0" : null;
|
|
21114
21141
|
}
|
|
21115
21142
|
function runCmd(cmd, args2, timeoutMs) {
|
|
21116
21143
|
return new Promise((resolve9) => {
|
|
@@ -22779,7 +22806,7 @@ async function defaultFetchJson(url2) {
|
|
|
22779
22806
|
async function readUsageReport(deps = {}) {
|
|
22780
22807
|
const port = deps.port ?? HEADROOM_PROXY_PORT;
|
|
22781
22808
|
const base = `http://127.0.0.1:${port}`;
|
|
22782
|
-
const get2 = deps.fetchJson ?? ((
|
|
22809
|
+
const get2 = deps.fetchJson ?? ((path91) => defaultFetchJson(`${base}${path91}`));
|
|
22783
22810
|
let history;
|
|
22784
22811
|
try {
|
|
22785
22812
|
history = await get2("/stats-history");
|
|
@@ -24696,11 +24723,11 @@ function resolveDoltInstallStrategy(platform3) {
|
|
|
24696
24723
|
}
|
|
24697
24724
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
24698
24725
|
function doltPlatformTuple(platform3, arch2) {
|
|
24699
|
-
const
|
|
24726
|
+
const os66 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
|
|
24700
24727
|
const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
|
|
24701
24728
|
if (!a) return null;
|
|
24702
|
-
if (
|
|
24703
|
-
return `${
|
|
24729
|
+
if (os66 === "windows" && a !== "amd64") return null;
|
|
24730
|
+
return `${os66}-${a}`;
|
|
24704
24731
|
}
|
|
24705
24732
|
function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
|
|
24706
24733
|
const tuple = doltPlatformTuple(platform3, arch2);
|
|
@@ -25761,8 +25788,14 @@ function dispatchPrompt(ctx, prompt) {
|
|
|
25761
25788
|
ctx.outputSvc.newTurn();
|
|
25762
25789
|
ctx.agent.sendCommand(prompt);
|
|
25763
25790
|
}
|
|
25764
|
-
var startTask = (ctx,
|
|
25791
|
+
var startTask = async (ctx, cmd, parsed) => {
|
|
25765
25792
|
const { prompt, files } = parsed;
|
|
25793
|
+
if (parsed.agentId && parsed.agentId !== ctx.agentId) {
|
|
25794
|
+
await ctx.relay.sendResult(cmd.id, "failed", {
|
|
25795
|
+
error: "Switching agents isn't supported on this session."
|
|
25796
|
+
});
|
|
25797
|
+
return;
|
|
25798
|
+
}
|
|
25766
25799
|
const effectivePrompt = prompt ?? "";
|
|
25767
25800
|
if (files && files.length > 0) {
|
|
25768
25801
|
const paths = saveFilesTemp(files);
|
|
@@ -26346,7 +26379,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
|
|
|
26346
26379
|
});
|
|
26347
26380
|
const token = ctx.pluginAuthToken;
|
|
26348
26381
|
void (async () => {
|
|
26349
|
-
const
|
|
26382
|
+
const os66 = createOsStrategy();
|
|
26350
26383
|
try {
|
|
26351
26384
|
const report = await reviewPullRequest(
|
|
26352
26385
|
{
|
|
@@ -26355,7 +26388,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
|
|
|
26355
26388
|
baseBranch: parsed.baseBranch
|
|
26356
26389
|
},
|
|
26357
26390
|
{
|
|
26358
|
-
runReview: (input) => new CoderabbitRuntimeStrategy(
|
|
26391
|
+
runReview: (input) => new CoderabbitRuntimeStrategy(os66).runOneShot(input),
|
|
26359
26392
|
runGh: (args2) => defaultRunGh(args2),
|
|
26360
26393
|
postReport: async (r) => {
|
|
26361
26394
|
if (!token) return;
|
|
@@ -27458,11 +27491,11 @@ function resolveTokenValue(args2) {
|
|
|
27458
27491
|
}
|
|
27459
27492
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
27460
27493
|
if (fileFlag) {
|
|
27461
|
-
const
|
|
27494
|
+
const path91 = fileFlag.slice("--token-file=".length);
|
|
27462
27495
|
try {
|
|
27463
|
-
const content = fs63.readFileSync(
|
|
27464
|
-
if (content.length === 0) fail(`--token-file ${
|
|
27465
|
-
rmIfExistsQuiet(
|
|
27496
|
+
const content = fs63.readFileSync(path91, "utf8").trim();
|
|
27497
|
+
if (content.length === 0) fail(`--token-file ${path91} is empty`);
|
|
27498
|
+
rmIfExistsQuiet(path91);
|
|
27466
27499
|
return content;
|
|
27467
27500
|
} catch (err) {
|
|
27468
27501
|
fail(`Could not read --token-file: ${err.message}`);
|
|
@@ -34370,7 +34403,7 @@ function makeSerializedSwitchEmitter(post2) {
|
|
|
34370
34403
|
return chain;
|
|
34371
34404
|
};
|
|
34372
34405
|
}
|
|
34373
|
-
async function performAgentSwitch(deps, rawAgentId) {
|
|
34406
|
+
async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
34374
34407
|
const from = deps.currentAgent();
|
|
34375
34408
|
const target = resolveSwitchTarget(rawAgentId, from);
|
|
34376
34409
|
if (!target.ok) {
|
|
@@ -34386,22 +34419,28 @@ async function performAgentSwitch(deps, rawAgentId) {
|
|
|
34386
34419
|
};
|
|
34387
34420
|
log.info("switchAgent", `switch requested ${from} \u2192 ${agentId}`);
|
|
34388
34421
|
void emitStatus({ state: "switching", agentId, fromAgentId: from });
|
|
34389
|
-
|
|
34390
|
-
|
|
34391
|
-
|
|
34392
|
-
|
|
34393
|
-
|
|
34394
|
-
|
|
34422
|
+
let installScript;
|
|
34423
|
+
if (!fastPath.skipProvision) {
|
|
34424
|
+
void emitStep("credential");
|
|
34425
|
+
const cred = await deps.fetchCredential(agentId);
|
|
34426
|
+
if (!cred) {
|
|
34427
|
+
return fail2(
|
|
34428
|
+
`No linked credential for ${displayName(agentId)}. Link it in Profile \u203A Agents first.`
|
|
34429
|
+
);
|
|
34430
|
+
}
|
|
34431
|
+
try {
|
|
34432
|
+
deps.provisionCredential(agentId, toAgentAuth(cred.method, cred.credential));
|
|
34433
|
+
} catch (err) {
|
|
34434
|
+
log.warn("switchAgent", `credential provisioning failed: ${err.message}`);
|
|
34435
|
+
return fail2(`Couldn't write the ${displayName(agentId)} credential on this machine.`);
|
|
34436
|
+
}
|
|
34437
|
+
installScript = cred.installScript;
|
|
34395
34438
|
}
|
|
34396
|
-
|
|
34397
|
-
|
|
34398
|
-
|
|
34399
|
-
|
|
34400
|
-
return fail2(`Couldn't write the ${displayName(agentId)} credential on this machine.`);
|
|
34439
|
+
if (!fastPath.skipInstall) {
|
|
34440
|
+
void emitStep("install");
|
|
34441
|
+
const bin = await deps.ensureBinary(agentId, installScript);
|
|
34442
|
+
if (!bin.ok) return fail2(bin.error);
|
|
34401
34443
|
}
|
|
34402
|
-
void emitStep("install");
|
|
34403
|
-
const bin = await deps.ensureBinary(agentId, cred.installScript);
|
|
34404
|
-
if (!bin.ok) return fail2(bin.error);
|
|
34405
34444
|
void emitStep("restart");
|
|
34406
34445
|
try {
|
|
34407
34446
|
await deps.swapRuntime(agentId);
|
|
@@ -34428,6 +34467,121 @@ async function performAgentSwitch(deps, rawAgentId) {
|
|
|
34428
34467
|
return { ok: true, agentId };
|
|
34429
34468
|
}
|
|
34430
34469
|
|
|
34470
|
+
// src/agents/acp/squad-roster.ts
|
|
34471
|
+
var fs67 = __toESM(require("fs"));
|
|
34472
|
+
var os58 = __toESM(require("os"));
|
|
34473
|
+
var path74 = __toESM(require("path"));
|
|
34474
|
+
var PROMPT_MAX = 500;
|
|
34475
|
+
var REPLY_SUMMARY_MAX = 1e3;
|
|
34476
|
+
var PREAMBLE_MAX = 2e3;
|
|
34477
|
+
var BRIEFING_DEFAULT_MAX = 8e3;
|
|
34478
|
+
var GENERIC_SPECIALTY = "general implementation tasks";
|
|
34479
|
+
function clip(s, max) {
|
|
34480
|
+
return s.length > max ? s.slice(0, max) : s;
|
|
34481
|
+
}
|
|
34482
|
+
function defaultMember() {
|
|
34483
|
+
return { acpSessionId: null, provisioned: false, binaryVerified: false, lastTurnIndex: 0 };
|
|
34484
|
+
}
|
|
34485
|
+
function journalPathFor(homeDir2, sessionId) {
|
|
34486
|
+
return path74.join(homeDir2, ".codeam", `squad-journal-${sessionId}.json`);
|
|
34487
|
+
}
|
|
34488
|
+
function loadJournal(journalPath) {
|
|
34489
|
+
try {
|
|
34490
|
+
const raw = JSON.parse(fs67.readFileSync(journalPath, "utf-8"));
|
|
34491
|
+
return Array.isArray(raw.turns) ? raw.turns : [];
|
|
34492
|
+
} catch {
|
|
34493
|
+
return [];
|
|
34494
|
+
}
|
|
34495
|
+
}
|
|
34496
|
+
var SquadState = class {
|
|
34497
|
+
/** Set by the caller after fetchSquadRoster; null until then. */
|
|
34498
|
+
roster = null;
|
|
34499
|
+
journalPath;
|
|
34500
|
+
turns;
|
|
34501
|
+
members = /* @__PURE__ */ new Map();
|
|
34502
|
+
constructor(opts) {
|
|
34503
|
+
this.journalPath = journalPathFor(opts.homeDir ?? os58.homedir(), opts.sessionId);
|
|
34504
|
+
this.turns = loadJournal(this.journalPath);
|
|
34505
|
+
}
|
|
34506
|
+
/** Returns (creating on first access) the mutable per-agent state. */
|
|
34507
|
+
member(agentId) {
|
|
34508
|
+
let m = this.members.get(agentId);
|
|
34509
|
+
if (!m) {
|
|
34510
|
+
m = defaultMember();
|
|
34511
|
+
this.members.set(agentId, m);
|
|
34512
|
+
}
|
|
34513
|
+
return m;
|
|
34514
|
+
}
|
|
34515
|
+
/** Appends a journal entry and persists (fire-and-forget durability). */
|
|
34516
|
+
recordTurn(entry) {
|
|
34517
|
+
const turn = {
|
|
34518
|
+
turn: this.turns.length + 1,
|
|
34519
|
+
agentId: entry.agentId,
|
|
34520
|
+
prompt: clip(entry.prompt, PROMPT_MAX),
|
|
34521
|
+
replySummary: clip(entry.replySummary, REPLY_SUMMARY_MAX),
|
|
34522
|
+
filesTouched: entry.filesTouched
|
|
34523
|
+
};
|
|
34524
|
+
this.turns.push(turn);
|
|
34525
|
+
this.persist();
|
|
34526
|
+
}
|
|
34527
|
+
turnCount() {
|
|
34528
|
+
return this.turns.length;
|
|
34529
|
+
}
|
|
34530
|
+
entriesSince(turnIndex) {
|
|
34531
|
+
return this.turns.filter((t2) => t2.turn > turnIndex);
|
|
34532
|
+
}
|
|
34533
|
+
persist() {
|
|
34534
|
+
try {
|
|
34535
|
+
fs67.mkdirSync(path74.dirname(this.journalPath), { recursive: true, mode: 448 });
|
|
34536
|
+
fs67.writeFileSync(this.journalPath, JSON.stringify({ turns: this.turns }), { mode: 384 });
|
|
34537
|
+
} catch {
|
|
34538
|
+
}
|
|
34539
|
+
}
|
|
34540
|
+
};
|
|
34541
|
+
function specialtyFor(agentId) {
|
|
34542
|
+
return SQUAD_SPECIALTIES[agentId] ?? GENERIC_SPECIALTY;
|
|
34543
|
+
}
|
|
34544
|
+
function buildTeamPreamble(roster, currentAgent, opts) {
|
|
34545
|
+
const others = roster.agents.filter((a) => a.agentId !== currentAgent);
|
|
34546
|
+
if (others.length === 0) return null;
|
|
34547
|
+
const lines = [
|
|
34548
|
+
"[Team context] You are the active agent in a CodeAgent Mobile session where the user",
|
|
34549
|
+
"has a squad of agents and can pass work between them. Your available teammates:",
|
|
34550
|
+
...others.map((a) => `- ${a.displayName} \u2014 best at: ${specialtyFor(a.agentId)}`)
|
|
34551
|
+
];
|
|
34552
|
+
if (opts.handoffInstructions) {
|
|
34553
|
+
lines.push(
|
|
34554
|
+
"If a task clearly fits a teammate better than you, you MAY propose a handoff by ending",
|
|
34555
|
+
`your reply with a fenced code block tagged ${HANDOFF_FENCE_TAG} containing ONE JSON object:`,
|
|
34556
|
+
'{"to":"<teammate id>","reason":"<one sentence>","prompt":"<the prompt they should run>"}',
|
|
34557
|
+
"Propose at most one handoff per reply, only when genuinely better, and never announce",
|
|
34558
|
+
"the block in prose \u2014 the app renders it as a card the user can accept."
|
|
34559
|
+
);
|
|
34560
|
+
}
|
|
34561
|
+
return clip(lines.join("\n"), PREAMBLE_MAX);
|
|
34562
|
+
}
|
|
34563
|
+
function renderJournalEntry(e) {
|
|
34564
|
+
const filesClause = e.filesTouched.length > 0 ? ` (files: ${e.filesTouched.join(", ")})` : "";
|
|
34565
|
+
return `- turn ${e.turn} (${e.agentId}): ${e.prompt} \u2192 ${e.replySummary}${filesClause}`;
|
|
34566
|
+
}
|
|
34567
|
+
function buildDeltaBriefing(entries, maxChars = BRIEFING_DEFAULT_MAX) {
|
|
34568
|
+
if (entries.length === 0) return null;
|
|
34569
|
+
const header = "[Team update] While you were away, other agents worked on this session:";
|
|
34570
|
+
const footer = "Continue from the CURRENT state of the working tree.";
|
|
34571
|
+
const envelope = header.length + 1 + footer.length + 1;
|
|
34572
|
+
const sorted = [...entries].sort((a, b) => a.turn - b.turn);
|
|
34573
|
+
const lines = [];
|
|
34574
|
+
let bodyLen = 0;
|
|
34575
|
+
for (let i = sorted.length - 1; i >= 0; i--) {
|
|
34576
|
+
const line = renderJournalEntry(sorted[i]);
|
|
34577
|
+
const addedLen = line.length + (lines.length > 0 ? 1 : 0);
|
|
34578
|
+
if (lines.length > 0 && envelope + bodyLen + addedLen > maxChars) break;
|
|
34579
|
+
lines.unshift(line);
|
|
34580
|
+
bodyLen += addedLen;
|
|
34581
|
+
}
|
|
34582
|
+
return [header, lines.join("\n"), footer].join("\n");
|
|
34583
|
+
}
|
|
34584
|
+
|
|
34431
34585
|
// src/services/streaming/transport.ts
|
|
34432
34586
|
var http7 = __toESM(require("http"));
|
|
34433
34587
|
var https8 = __toESM(require("https"));
|
|
@@ -34873,17 +35027,95 @@ function commonPrefixLength(a, b) {
|
|
|
34873
35027
|
return i;
|
|
34874
35028
|
}
|
|
34875
35029
|
|
|
35030
|
+
// src/agents/acp/handoff-protocol.ts
|
|
35031
|
+
var REASON_MAX = 1e3;
|
|
35032
|
+
var PROMPT_MAX2 = 8e3;
|
|
35033
|
+
var FENCE_OPEN = "```" + HANDOFF_FENCE_TAG;
|
|
35034
|
+
var FENCE_RE = new RegExp("```" + HANDOFF_FENCE_TAG + "\\s*\\n([\\s\\S]*?)\\n?```", "g");
|
|
35035
|
+
var OUTER_FENCE_RE = /(`{4,})[\s\S]*?\1/g;
|
|
35036
|
+
var outerFencePlaceholder = (i) => `@@HANDOFF_MASK_${i}@@`;
|
|
35037
|
+
function maskOuterFences(text) {
|
|
35038
|
+
const spans = [];
|
|
35039
|
+
const masked = text.replace(OUTER_FENCE_RE, (m) => {
|
|
35040
|
+
const token = outerFencePlaceholder(spans.length);
|
|
35041
|
+
spans.push(m);
|
|
35042
|
+
return token;
|
|
35043
|
+
});
|
|
35044
|
+
const restore = (s) => spans.reduce((acc, span, i) => acc.split(outerFencePlaceholder(i)).join(span), s);
|
|
35045
|
+
return { masked, restore };
|
|
35046
|
+
}
|
|
35047
|
+
function parseProposal(raw, currentAgent, validTargets) {
|
|
35048
|
+
let parsed;
|
|
35049
|
+
try {
|
|
35050
|
+
parsed = JSON.parse(raw);
|
|
35051
|
+
} catch {
|
|
35052
|
+
log.debug("handoffProtocol", "dropped proposal: malformed JSON");
|
|
35053
|
+
return null;
|
|
35054
|
+
}
|
|
35055
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
35056
|
+
log.debug("handoffProtocol", "dropped proposal: not a JSON object");
|
|
35057
|
+
return null;
|
|
35058
|
+
}
|
|
35059
|
+
const { to, reason, prompt } = parsed;
|
|
35060
|
+
if (typeof to !== "string" || to.length === 0) {
|
|
35061
|
+
log.debug("handoffProtocol", 'dropped proposal: missing/invalid "to"');
|
|
35062
|
+
return null;
|
|
35063
|
+
}
|
|
35064
|
+
if (!validTargets.has(to)) {
|
|
35065
|
+
log.debug("handoffProtocol", `dropped proposal: unknown target "${to}"`);
|
|
35066
|
+
return null;
|
|
35067
|
+
}
|
|
35068
|
+
if (to === currentAgent) {
|
|
35069
|
+
log.debug("handoffProtocol", "dropped proposal: target is the current agent");
|
|
35070
|
+
return null;
|
|
35071
|
+
}
|
|
35072
|
+
if (typeof reason !== "string" || reason.length === 0 || reason.length > REASON_MAX) {
|
|
35073
|
+
log.debug("handoffProtocol", 'dropped proposal: invalid "reason"');
|
|
35074
|
+
return null;
|
|
35075
|
+
}
|
|
35076
|
+
if (typeof prompt !== "string" || prompt.length === 0 || prompt.length > PROMPT_MAX2) {
|
|
35077
|
+
log.debug("handoffProtocol", 'dropped proposal: invalid "prompt"');
|
|
35078
|
+
return null;
|
|
35079
|
+
}
|
|
35080
|
+
return { to, reason, prompt };
|
|
35081
|
+
}
|
|
35082
|
+
function stripFences(masked) {
|
|
35083
|
+
const stripped = masked.replace(FENCE_RE, "");
|
|
35084
|
+
return stripped.replace(/(?:\r?\n){3,}/g, "\n\n").trim();
|
|
35085
|
+
}
|
|
35086
|
+
function extractHandoffProposal(text, currentAgent, validTargets) {
|
|
35087
|
+
const { masked, restore } = maskOuterFences(text);
|
|
35088
|
+
const matches = [...masked.matchAll(FENCE_RE)];
|
|
35089
|
+
if (matches.length === 0) {
|
|
35090
|
+
return { cleanText: text, proposal: null };
|
|
35091
|
+
}
|
|
35092
|
+
const last = matches[matches.length - 1];
|
|
35093
|
+
const proposal = parseProposal(last[1].trim(), currentAgent, validTargets);
|
|
35094
|
+
const cleanText = restore(stripFences(masked));
|
|
35095
|
+
return { cleanText, proposal };
|
|
35096
|
+
}
|
|
35097
|
+
function stripHandoffFences(text) {
|
|
35098
|
+
const { masked, restore } = maskOuterFences(text);
|
|
35099
|
+
if (masked.search(FENCE_RE) === -1) {
|
|
35100
|
+
return text;
|
|
35101
|
+
}
|
|
35102
|
+
return restore(stripFences(masked));
|
|
35103
|
+
}
|
|
35104
|
+
function handoffFenceStart(text) {
|
|
35105
|
+
return text.indexOf(FENCE_OPEN);
|
|
35106
|
+
}
|
|
35107
|
+
|
|
34876
35108
|
// src/agents/acp/onboarding.ts
|
|
34877
35109
|
var import_child_process28 = require("child_process");
|
|
34878
|
-
var
|
|
34879
|
-
var
|
|
34880
|
-
var
|
|
35110
|
+
var fs68 = __toESM(require("fs"));
|
|
35111
|
+
var os59 = __toESM(require("os"));
|
|
35112
|
+
var path75 = __toESM(require("path"));
|
|
34881
35113
|
var _onboardingSeam = {
|
|
34882
|
-
markerPath: (sessionId) =>
|
|
34883
|
-
exists: (p2) =>
|
|
35114
|
+
markerPath: (sessionId) => path75.join(os59.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
35115
|
+
exists: (p2) => fs68.existsSync(p2),
|
|
34884
35116
|
write: (p2) => {
|
|
34885
|
-
|
|
34886
|
-
|
|
35117
|
+
fs68.mkdirSync(path75.dirname(p2), { recursive: true });
|
|
35118
|
+
fs68.writeFileSync(p2, "");
|
|
34887
35119
|
},
|
|
34888
35120
|
disabled: () => {
|
|
34889
35121
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -34920,7 +35152,7 @@ function resolveRepoName(cwd) {
|
|
|
34920
35152
|
if (name) return name;
|
|
34921
35153
|
}
|
|
34922
35154
|
}
|
|
34923
|
-
const base =
|
|
35155
|
+
const base = path75.basename(cwd || "");
|
|
34924
35156
|
if (base && !isUuid(base)) return base;
|
|
34925
35157
|
return "this project";
|
|
34926
35158
|
}
|
|
@@ -35178,13 +35410,13 @@ var import_crypto5 = require("crypto");
|
|
|
35178
35410
|
|
|
35179
35411
|
// src/services/turn-files/git-changeset.ts
|
|
35180
35412
|
var import_child_process29 = require("child_process");
|
|
35181
|
-
var
|
|
35182
|
-
var
|
|
35413
|
+
var fs70 = __toESM(require("fs/promises"));
|
|
35414
|
+
var path77 = __toESM(require("path"));
|
|
35183
35415
|
|
|
35184
35416
|
// src/services/turn-files/review-ignore.ts
|
|
35185
35417
|
var import_ignore2 = __toESM(require("ignore"));
|
|
35186
|
-
var
|
|
35187
|
-
var
|
|
35418
|
+
var fs69 = __toESM(require("fs"));
|
|
35419
|
+
var path76 = __toESM(require("path"));
|
|
35188
35420
|
var CURATED_REVIEW_IGNORE = [
|
|
35189
35421
|
// Google Cloud SDK (the incident) — installs a huge python tree.
|
|
35190
35422
|
"google-cloud-sdk/",
|
|
@@ -35223,7 +35455,7 @@ var CURATED_REVIEW_IGNORE = [
|
|
|
35223
35455
|
function makeReviewIgnore(repoRoot) {
|
|
35224
35456
|
const ig = (0, import_ignore2.default)().add(CURATED_REVIEW_IGNORE);
|
|
35225
35457
|
try {
|
|
35226
|
-
const custom =
|
|
35458
|
+
const custom = fs69.readFileSync(path76.join(repoRoot, ".codeam", "reviewignore"), "utf8");
|
|
35227
35459
|
ig.add(custom);
|
|
35228
35460
|
} catch {
|
|
35229
35461
|
}
|
|
@@ -35268,7 +35500,7 @@ async function collectRepoChangeset(opts) {
|
|
|
35268
35500
|
let stats;
|
|
35269
35501
|
if (!truncated && row.fileStatus === "added" && numstatEntry === void 0) {
|
|
35270
35502
|
const lineCount = await readUntrackedLineCount(
|
|
35271
|
-
|
|
35503
|
+
path77.join(opts.repoRoot, row.filePath)
|
|
35272
35504
|
);
|
|
35273
35505
|
stats = { added: lineCount, removed: 0 };
|
|
35274
35506
|
} else {
|
|
@@ -35299,7 +35531,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
35299
35531
|
}
|
|
35300
35532
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
35301
35533
|
try {
|
|
35302
|
-
const content = await
|
|
35534
|
+
const content = await fs70.readFile(absPath, "utf8");
|
|
35303
35535
|
let count = 0;
|
|
35304
35536
|
let pos = -1;
|
|
35305
35537
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -35391,7 +35623,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
35391
35623
|
});
|
|
35392
35624
|
}
|
|
35393
35625
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
35394
|
-
const
|
|
35626
|
+
const fs80 = await import("fs/promises");
|
|
35395
35627
|
const out2 = [];
|
|
35396
35628
|
await walk(workingDir, 0);
|
|
35397
35629
|
return out2;
|
|
@@ -35399,7 +35631,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
35399
35631
|
if (depth > maxDepth) return;
|
|
35400
35632
|
let entries = [];
|
|
35401
35633
|
try {
|
|
35402
|
-
const dirents = await
|
|
35634
|
+
const dirents = await fs80.readdir(dir, { withFileTypes: true });
|
|
35403
35635
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
35404
35636
|
} catch {
|
|
35405
35637
|
return;
|
|
@@ -35410,8 +35642,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
35410
35642
|
if (hasGit) {
|
|
35411
35643
|
out2.push({
|
|
35412
35644
|
repoRoot: dir,
|
|
35413
|
-
repoPath:
|
|
35414
|
-
repoName:
|
|
35645
|
+
repoPath: path77.relative(workingDir, dir),
|
|
35646
|
+
repoName: path77.basename(dir)
|
|
35415
35647
|
});
|
|
35416
35648
|
return;
|
|
35417
35649
|
}
|
|
@@ -35419,14 +35651,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
35419
35651
|
if (!entry.isDirectory) continue;
|
|
35420
35652
|
if (entry.name === "node_modules") continue;
|
|
35421
35653
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
35422
|
-
await walk(
|
|
35654
|
+
await walk(path77.join(dir, entry.name), depth + 1);
|
|
35423
35655
|
}
|
|
35424
35656
|
}
|
|
35425
35657
|
}
|
|
35426
35658
|
|
|
35427
35659
|
// src/services/turn-files/files-outbox.ts
|
|
35428
|
-
var
|
|
35429
|
-
var
|
|
35660
|
+
var fs71 = __toESM(require("fs/promises"));
|
|
35661
|
+
var path78 = __toESM(require("path"));
|
|
35430
35662
|
var import_os12 = require("os");
|
|
35431
35663
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
35432
35664
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -35459,16 +35691,16 @@ var FilesOutbox = class {
|
|
|
35459
35691
|
backoffIndex = 0;
|
|
35460
35692
|
stopped = false;
|
|
35461
35693
|
constructor(opts) {
|
|
35462
|
-
const base = opts.baseDir ??
|
|
35463
|
-
this.filePath =
|
|
35694
|
+
const base = opts.baseDir ?? path78.join(homeDir(), HOME_OUTBOX_DIR);
|
|
35695
|
+
this.filePath = path78.join(base, `${opts.sessionId}.jsonl`);
|
|
35464
35696
|
this.post = opts.post;
|
|
35465
35697
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
35466
35698
|
}
|
|
35467
35699
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
35468
35700
|
* line is durable on disk (not once the POST succeeds). */
|
|
35469
35701
|
async enqueue(entry) {
|
|
35470
|
-
await
|
|
35471
|
-
await
|
|
35702
|
+
await fs71.mkdir(path78.dirname(this.filePath), { recursive: true });
|
|
35703
|
+
await fs71.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
35472
35704
|
this.backoffIndex = 0;
|
|
35473
35705
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
35474
35706
|
}
|
|
@@ -35559,7 +35791,7 @@ var FilesOutbox = class {
|
|
|
35559
35791
|
async readAll() {
|
|
35560
35792
|
let raw = "";
|
|
35561
35793
|
try {
|
|
35562
|
-
raw = await
|
|
35794
|
+
raw = await fs71.readFile(this.filePath, "utf8");
|
|
35563
35795
|
} catch {
|
|
35564
35796
|
return [];
|
|
35565
35797
|
}
|
|
@@ -35583,12 +35815,12 @@ var FilesOutbox = class {
|
|
|
35583
35815
|
async rewrite(entries) {
|
|
35584
35816
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
35585
35817
|
if (entries.length === 0) {
|
|
35586
|
-
await
|
|
35818
|
+
await fs71.unlink(this.filePath).catch(() => void 0);
|
|
35587
35819
|
return;
|
|
35588
35820
|
}
|
|
35589
35821
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
35590
|
-
await
|
|
35591
|
-
await
|
|
35822
|
+
await fs71.writeFile(tmpPath, payload, "utf8");
|
|
35823
|
+
await fs71.rename(tmpPath, this.filePath);
|
|
35592
35824
|
}
|
|
35593
35825
|
};
|
|
35594
35826
|
function applyJitter(ms) {
|
|
@@ -36044,8 +36276,8 @@ async function postBudgetReached(opts, fetchImpl = fetch) {
|
|
|
36044
36276
|
|
|
36045
36277
|
// src/packs/gates.ts
|
|
36046
36278
|
var import_node_child_process30 = require("child_process");
|
|
36047
|
-
var
|
|
36048
|
-
var
|
|
36279
|
+
var fs72 = __toESM(require("fs"));
|
|
36280
|
+
var path79 = __toESM(require("path"));
|
|
36049
36281
|
var defaultCommandRunner = (file, args2, cwd, timeoutMs) => new Promise((resolve9) => {
|
|
36050
36282
|
(0, import_node_child_process30.execFile)(
|
|
36051
36283
|
file,
|
|
@@ -36082,14 +36314,14 @@ var NO_TEST_PLACEHOLDER = 'echo "Error: no test specified"';
|
|
|
36082
36314
|
var CHECKS_TIMEOUT_MS = 5 * 6e4;
|
|
36083
36315
|
function detectChecksCommand(cwd) {
|
|
36084
36316
|
try {
|
|
36085
|
-
const cfg = JSON.parse(
|
|
36317
|
+
const cfg = JSON.parse(fs72.readFileSync(path79.join(cwd, ".codeam", "pack.json"), "utf8"));
|
|
36086
36318
|
if (typeof cfg.checksCommand === "string" && cfg.checksCommand.trim().length > 0) {
|
|
36087
36319
|
return cfg.checksCommand.trim();
|
|
36088
36320
|
}
|
|
36089
36321
|
} catch {
|
|
36090
36322
|
}
|
|
36091
36323
|
try {
|
|
36092
|
-
const pkg = JSON.parse(
|
|
36324
|
+
const pkg = JSON.parse(fs72.readFileSync(path79.join(cwd, "package.json"), "utf8"));
|
|
36093
36325
|
const test = pkg.scripts?.test;
|
|
36094
36326
|
if (typeof test === "string" && test.trim().length > 0 && !test.includes(NO_TEST_PLACEHOLDER)) {
|
|
36095
36327
|
return "npm test";
|
|
@@ -36107,39 +36339,39 @@ ${res.stderr}`.trim();
|
|
|
36107
36339
|
}
|
|
36108
36340
|
|
|
36109
36341
|
// src/packs/run-store.ts
|
|
36110
|
-
var
|
|
36111
|
-
var
|
|
36342
|
+
var fs73 = __toESM(require("fs"));
|
|
36343
|
+
var path80 = __toESM(require("path"));
|
|
36112
36344
|
var crypto5 = __toESM(require("crypto"));
|
|
36113
36345
|
function packsDir(cwd) {
|
|
36114
|
-
return
|
|
36346
|
+
return path80.join(cwd, ".codeam", "packs");
|
|
36115
36347
|
}
|
|
36116
36348
|
function runDir(cwd, runId) {
|
|
36117
|
-
return
|
|
36349
|
+
return path80.join(packsDir(cwd), runId);
|
|
36118
36350
|
}
|
|
36119
36351
|
function newRunId() {
|
|
36120
36352
|
return `pk_${Date.now().toString(36)}_${crypto5.randomBytes(4).toString("hex")}`;
|
|
36121
36353
|
}
|
|
36122
36354
|
function writeJsonAtomic(file, value) {
|
|
36123
|
-
|
|
36355
|
+
fs73.mkdirSync(path80.dirname(file), { recursive: true });
|
|
36124
36356
|
const tmp = `${file}.tmp`;
|
|
36125
|
-
|
|
36126
|
-
|
|
36357
|
+
fs73.writeFileSync(tmp, JSON.stringify(value, null, 2));
|
|
36358
|
+
fs73.renameSync(tmp, file);
|
|
36127
36359
|
}
|
|
36128
36360
|
function saveRun(cwd, state) {
|
|
36129
|
-
writeJsonAtomic(
|
|
36361
|
+
writeJsonAtomic(path80.join(runDir(cwd, state.runId), "run.json"), state);
|
|
36130
36362
|
}
|
|
36131
36363
|
function saveStageHandoff(cwd, runId, stageIndex, role, handoff) {
|
|
36132
36364
|
const name = `${String(stageIndex + 1).padStart(2, "0")}-${role}.json`;
|
|
36133
|
-
writeJsonAtomic(
|
|
36365
|
+
writeJsonAtomic(path80.join(runDir(cwd, runId), name), handoff);
|
|
36134
36366
|
}
|
|
36135
36367
|
function loadLatestRun(cwd) {
|
|
36136
36368
|
try {
|
|
36137
36369
|
const dir = packsDir(cwd);
|
|
36138
|
-
const entries =
|
|
36370
|
+
const entries = fs73.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
36139
36371
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
36140
|
-
const file =
|
|
36372
|
+
const file = path80.join(dir, entries[i], "run.json");
|
|
36141
36373
|
try {
|
|
36142
|
-
const parsed = JSON.parse(
|
|
36374
|
+
const parsed = JSON.parse(fs73.readFileSync(file, "utf8"));
|
|
36143
36375
|
if (parsed && typeof parsed.runId === "string") return parsed;
|
|
36144
36376
|
} catch {
|
|
36145
36377
|
}
|
|
@@ -36150,17 +36382,17 @@ function loadLatestRun(cwd) {
|
|
|
36150
36382
|
}
|
|
36151
36383
|
function ensureLedgerIgnored(cwd) {
|
|
36152
36384
|
try {
|
|
36153
|
-
const gitDir =
|
|
36154
|
-
if (!
|
|
36155
|
-
const exclude =
|
|
36385
|
+
const gitDir = path80.join(cwd, ".git");
|
|
36386
|
+
if (!fs73.existsSync(gitDir)) return;
|
|
36387
|
+
const exclude = path80.join(gitDir, "info", "exclude");
|
|
36156
36388
|
let existing = "";
|
|
36157
36389
|
try {
|
|
36158
|
-
existing =
|
|
36390
|
+
existing = fs73.readFileSync(exclude, "utf8");
|
|
36159
36391
|
} catch {
|
|
36160
36392
|
}
|
|
36161
36393
|
if (existing.includes(".codeam/packs/")) return;
|
|
36162
|
-
|
|
36163
|
-
|
|
36394
|
+
fs73.mkdirSync(path80.dirname(exclude), { recursive: true });
|
|
36395
|
+
fs73.writeFileSync(exclude, `${existing.trimEnd()}
|
|
36164
36396
|
.codeam/packs/
|
|
36165
36397
|
`.trimStart());
|
|
36166
36398
|
} catch {
|
|
@@ -36751,35 +36983,35 @@ function buildAcpPromptBlocks(payload) {
|
|
|
36751
36983
|
}
|
|
36752
36984
|
|
|
36753
36985
|
// src/agents/agent-standard.ts
|
|
36754
|
-
var
|
|
36755
|
-
var
|
|
36756
|
-
var
|
|
36757
|
-
function ensureAgentStandard(homeDir2 =
|
|
36986
|
+
var fs75 = __toESM(require("fs"));
|
|
36987
|
+
var path82 = __toESM(require("path"));
|
|
36988
|
+
var os60 = __toESM(require("os"));
|
|
36989
|
+
function ensureAgentStandard(homeDir2 = os60.homedir()) {
|
|
36758
36990
|
try {
|
|
36759
|
-
const file =
|
|
36991
|
+
const file = path82.join(homeDir2, ".claude", "CLAUDE.md");
|
|
36760
36992
|
let existing = "";
|
|
36761
36993
|
try {
|
|
36762
|
-
existing =
|
|
36994
|
+
existing = fs75.readFileSync(file, "utf8");
|
|
36763
36995
|
} catch {
|
|
36764
36996
|
}
|
|
36765
36997
|
if (existing.includes(AGENT_STANDARD_MARKER)) return;
|
|
36766
|
-
|
|
36998
|
+
fs75.mkdirSync(path82.dirname(file), { recursive: true });
|
|
36767
36999
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
36768
37000
|
|
|
36769
37001
|
${AGENT_STANDARD_BLOCK}
|
|
36770
37002
|
` : `${AGENT_STANDARD_BLOCK}
|
|
36771
37003
|
`;
|
|
36772
|
-
|
|
37004
|
+
fs75.writeFileSync(file, next);
|
|
36773
37005
|
} catch {
|
|
36774
37006
|
}
|
|
36775
37007
|
}
|
|
36776
37008
|
var _agentStandardSeam = {
|
|
36777
37009
|
isLocalSession: () => isLocalSession(),
|
|
36778
|
-
markerPath: (sessionId) =>
|
|
36779
|
-
exists: (p2) =>
|
|
37010
|
+
markerPath: (sessionId) => path82.join(os60.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
|
|
37011
|
+
exists: (p2) => fs75.existsSync(p2),
|
|
36780
37012
|
write: (p2) => {
|
|
36781
|
-
|
|
36782
|
-
|
|
37013
|
+
fs75.mkdirSync(path82.dirname(p2), { recursive: true });
|
|
37014
|
+
fs75.writeFileSync(p2, "");
|
|
36783
37015
|
}
|
|
36784
37016
|
};
|
|
36785
37017
|
function isClaude(agent) {
|
|
@@ -36883,20 +37115,111 @@ async function beadsActionH(ctx) {
|
|
|
36883
37115
|
}
|
|
36884
37116
|
return;
|
|
36885
37117
|
}
|
|
37118
|
+
function rebindSessionHandles(ctx, outcome) {
|
|
37119
|
+
Object.assign(ctx, outcome.handles);
|
|
37120
|
+
return outcome;
|
|
37121
|
+
}
|
|
37122
|
+
async function routeSquadTask(ctx, target) {
|
|
37123
|
+
const { squad, routeToAgent } = ctx;
|
|
37124
|
+
if (!routeToAgent) {
|
|
37125
|
+
return { ok: false, error: "Routing to another agent is not supported on this session." };
|
|
37126
|
+
}
|
|
37127
|
+
const roster = squad?.roster;
|
|
37128
|
+
if (roster && !roster.agents.some((a) => a.agentId === target)) {
|
|
37129
|
+
return { ok: false, error: `Unknown agent '${target}' \u2014 not in your squad.` };
|
|
37130
|
+
}
|
|
37131
|
+
const member = squad?.member(target);
|
|
37132
|
+
const fastPathArmed = Boolean(member && (member.provisioned || member.binaryVerified));
|
|
37133
|
+
let { result } = rebindSessionHandles(ctx, await routeToAgent(target));
|
|
37134
|
+
if (!result.ok && fastPathArmed) {
|
|
37135
|
+
log.warn(
|
|
37136
|
+
"acpRunner",
|
|
37137
|
+
`squad: fast-path route to ${target} failed (${result.error}) \u2014 retrying full path`
|
|
37138
|
+
);
|
|
37139
|
+
({ result } = rebindSessionHandles(ctx, await routeToAgent(target, { skipFastPath: true })));
|
|
37140
|
+
}
|
|
37141
|
+
if (!result.ok) {
|
|
37142
|
+
return { ok: false, error: result.error ?? `Couldn't switch to ${target}.` };
|
|
37143
|
+
}
|
|
37144
|
+
return { ok: true };
|
|
37145
|
+
}
|
|
37146
|
+
function prefixSquadContext(ctx, blocks) {
|
|
37147
|
+
if (ctx.pendingHandoff?.current) {
|
|
37148
|
+
blocks.unshift({ type: "text", text: ctx.pendingHandoff.current });
|
|
37149
|
+
ctx.pendingHandoff.current = null;
|
|
37150
|
+
}
|
|
37151
|
+
const { squad, opts } = ctx;
|
|
37152
|
+
if (!squad) return;
|
|
37153
|
+
const member = squad.member(opts.agent);
|
|
37154
|
+
if (squad.turnCount() > member.lastTurnIndex) {
|
|
37155
|
+
const otherEntries = squad.entriesSince(member.lastTurnIndex).filter((e) => e.agentId !== opts.agent);
|
|
37156
|
+
const briefing = buildDeltaBriefing(otherEntries);
|
|
37157
|
+
if (briefing) blocks.unshift({ type: "text", text: briefing });
|
|
37158
|
+
}
|
|
37159
|
+
const roster = squad.roster;
|
|
37160
|
+
if (roster && member.lastTurnIndex === 0) {
|
|
37161
|
+
const preamble = buildTeamPreamble(roster, opts.agent, {
|
|
37162
|
+
handoffInstructions: roster.handoffsEnabled === true
|
|
37163
|
+
});
|
|
37164
|
+
if (preamble) blocks.unshift({ type: "text", text: preamble });
|
|
37165
|
+
}
|
|
37166
|
+
}
|
|
37167
|
+
function recordSquadTurn(ctx, prompt, replySummary) {
|
|
37168
|
+
const { squad, opts } = ctx;
|
|
37169
|
+
if (!squad) return;
|
|
37170
|
+
squad.recordTurn({
|
|
37171
|
+
agentId: opts.agent,
|
|
37172
|
+
prompt,
|
|
37173
|
+
replySummary,
|
|
37174
|
+
// TurnFileAggregator owns per-turn file changesets end-to-end (git diff →
|
|
37175
|
+
// outbox POST) and exposes no path list, and its flush is fire-and-forget,
|
|
37176
|
+
// so there is nothing accurate to attribute synchronously here. The
|
|
37177
|
+
// briefing simply omits the files clause rather than guessing.
|
|
37178
|
+
filesTouched: []
|
|
37179
|
+
});
|
|
37180
|
+
squad.member(opts.agent).lastTurnIndex = squad.turnCount();
|
|
37181
|
+
}
|
|
37182
|
+
function handoffTargets(ctx) {
|
|
37183
|
+
const roster = ctx.squad?.roster;
|
|
37184
|
+
if (!roster) return /* @__PURE__ */ new Set();
|
|
37185
|
+
return new Set(roster.agents.map((a) => a.agentId).filter((id) => id !== ctx.opts.agent));
|
|
37186
|
+
}
|
|
37187
|
+
function resolvePendingProposal(ctx, requestedAgentId) {
|
|
37188
|
+
const slot = ctx.pendingProposal;
|
|
37189
|
+
const pending = slot?.current;
|
|
37190
|
+
if (!slot || !pending) return;
|
|
37191
|
+
slot.current = null;
|
|
37192
|
+
const accepted = requestedAgentId === pending.toAgentId;
|
|
37193
|
+
log.info(
|
|
37194
|
+
"acpRunner",
|
|
37195
|
+
`squad: handoff ${pending.proposalId} ${accepted ? "accepted" : "declined"}`
|
|
37196
|
+
);
|
|
37197
|
+
void ctx.postSquadEvent?.("handoff_resolved", {
|
|
37198
|
+
proposalId: pending.proposalId,
|
|
37199
|
+
accepted
|
|
37200
|
+
});
|
|
37201
|
+
}
|
|
37202
|
+
function emitHandoffProposal(ctx, proposal) {
|
|
37203
|
+
const { squad, pendingProposal, postSquadEvent, opts, cmd } = ctx;
|
|
37204
|
+
if (!proposal || !pendingProposal || !postSquadEvent) return;
|
|
37205
|
+
if (squad?.roster?.handoffsEnabled !== true) return;
|
|
37206
|
+
if (pendingProposal.current) {
|
|
37207
|
+
log.info("acpRunner", "squad: dropping handoff proposal \u2014 one is already pending");
|
|
37208
|
+
return;
|
|
37209
|
+
}
|
|
37210
|
+
const record2 = {
|
|
37211
|
+
proposalId: `hp-${cmd.id}`,
|
|
37212
|
+
fromAgentId: opts.agent,
|
|
37213
|
+
toAgentId: proposal.to,
|
|
37214
|
+
reason: proposal.reason,
|
|
37215
|
+
prompt: proposal.prompt
|
|
37216
|
+
};
|
|
37217
|
+
pendingProposal.current = record2;
|
|
37218
|
+
log.info("acpRunner", `squad: handoff proposed ${opts.agent} \u2192 ${record2.toAgentId}`);
|
|
37219
|
+
void postSquadEvent("handoff_proposed", { ...record2 });
|
|
37220
|
+
}
|
|
36886
37221
|
async function startTaskH(ctx) {
|
|
36887
|
-
const {
|
|
36888
|
-
cmd,
|
|
36889
|
-
client: client3,
|
|
36890
|
-
relay,
|
|
36891
|
-
streaming,
|
|
36892
|
-
opts,
|
|
36893
|
-
history,
|
|
36894
|
-
turnFiles,
|
|
36895
|
-
publisher,
|
|
36896
|
-
recentStderr,
|
|
36897
|
-
budgetRecovery,
|
|
36898
|
-
budgetReachedFlag
|
|
36899
|
-
} = ctx;
|
|
37222
|
+
const { cmd, relay, streaming, opts, turnFiles, publisher, recentStderr, budgetReachedFlag } = ctx;
|
|
36900
37223
|
const payload = cmd.payload;
|
|
36901
37224
|
const blocks = buildAcpPromptBlocks(payload ?? {});
|
|
36902
37225
|
if (blocks.length === 0) {
|
|
@@ -36904,6 +37227,17 @@ async function startTaskH(ctx) {
|
|
|
36904
37227
|
await relay.sendResult(cmd.id, "failed", { error: "empty prompt" });
|
|
36905
37228
|
return;
|
|
36906
37229
|
}
|
|
37230
|
+
const requestedAgentId = typeof payload?.agentId === "string" ? payload.agentId.trim() : "";
|
|
37231
|
+
resolvePendingProposal(ctx, requestedAgentId);
|
|
37232
|
+
if (requestedAgentId.length > 0 && requestedAgentId !== opts.agent) {
|
|
37233
|
+
const routed = await routeSquadTask(ctx, requestedAgentId);
|
|
37234
|
+
if (!routed.ok) {
|
|
37235
|
+
log.warn("acpRunner", `start_task routing to ${requestedAgentId} failed: ${routed.error}`);
|
|
37236
|
+
await relay.sendResult(cmd.id, "failed", { error: routed.error });
|
|
37237
|
+
return;
|
|
37238
|
+
}
|
|
37239
|
+
}
|
|
37240
|
+
const { client: client3, history, budgetRecovery } = ctx;
|
|
36907
37241
|
const promptText = blocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
36908
37242
|
const imageCount = blocks.filter((b) => b.type === "image").length;
|
|
36909
37243
|
log.info(
|
|
@@ -36917,10 +37251,7 @@ async function startTaskH(ctx) {
|
|
|
36917
37251
|
await streaming.beginTurn();
|
|
36918
37252
|
history.appendUserPrompt(promptText);
|
|
36919
37253
|
maybePrefaceAgentStandard(blocks, opts.agent, opts.sessionId);
|
|
36920
|
-
|
|
36921
|
-
blocks.unshift({ type: "text", text: ctx.pendingHandoff.current });
|
|
36922
|
-
ctx.pendingHandoff.current = null;
|
|
36923
|
-
}
|
|
37254
|
+
prefixSquadContext(ctx, blocks);
|
|
36924
37255
|
let turnClosed = false;
|
|
36925
37256
|
try {
|
|
36926
37257
|
const reply = await client3.prompt(blocks);
|
|
@@ -36972,12 +37303,19 @@ async function startTaskH(ctx) {
|
|
|
36972
37303
|
} else {
|
|
36973
37304
|
await streaming.closeTurnWithInteractiveDetection();
|
|
36974
37305
|
turnClosed = true;
|
|
36975
|
-
const
|
|
37306
|
+
const { cleanText, proposal } = extractHandoffProposal(
|
|
37307
|
+
finalText,
|
|
37308
|
+
opts.agent,
|
|
37309
|
+
handoffTargets(ctx)
|
|
37310
|
+
);
|
|
37311
|
+
const replyLine = formatAgentReplyLine(cleanText);
|
|
36976
37312
|
if (replyLine.length > 0) {
|
|
36977
37313
|
showInfo(replyLine);
|
|
36978
37314
|
}
|
|
36979
|
-
history.appendAgentReply(
|
|
37315
|
+
history.appendAgentReply(cleanText);
|
|
36980
37316
|
void history.flush();
|
|
37317
|
+
recordSquadTurn(ctx, promptText, cleanText);
|
|
37318
|
+
emitHandoffProposal(ctx, proposal);
|
|
36981
37319
|
void publisher.publishOutput({
|
|
36982
37320
|
type: "input_suggestion",
|
|
36983
37321
|
content: ACP_QUICK_REPLIES,
|
|
@@ -37776,14 +38114,18 @@ var StreamingState = class {
|
|
|
37776
38114
|
}
|
|
37777
38115
|
const cumulativeContent = reconcileCumulative(existing?.content ?? "", delta.delta);
|
|
37778
38116
|
this.streamingChunks.set(chunkId, { kind: delta.kind, content: cumulativeContent });
|
|
38117
|
+
let fenceCut = -1;
|
|
37779
38118
|
if (delta.kind === "text") {
|
|
37780
38119
|
this.recomputeText();
|
|
37781
|
-
|
|
38120
|
+
fenceCut = handoffFenceStart(this.text);
|
|
38121
|
+
const visibleText = fenceCut === -1 ? this.text : this.text.slice(0, fenceCut).trimEnd();
|
|
38122
|
+
void this.publisher.publishOutput({ type: "text", content: visibleText, done: false });
|
|
37782
38123
|
}
|
|
38124
|
+
const visibleChunkContent = delta.kind === "text" && fenceCut !== -1 ? cumulativeContent.slice(0, fenceCut).trimEnd() : cumulativeContent;
|
|
37783
38125
|
void this.publisher.publishStreamingChunk({
|
|
37784
38126
|
chunkId,
|
|
37785
38127
|
kind: delta.kind,
|
|
37786
|
-
content:
|
|
38128
|
+
content: visibleChunkContent,
|
|
37787
38129
|
isFinal: false
|
|
37788
38130
|
});
|
|
37789
38131
|
}
|
|
@@ -37813,8 +38155,27 @@ var StreamingState = class {
|
|
|
37813
38155
|
* spuriously and strand the runner with a free-form pending state
|
|
37814
38156
|
* the user can't see / answer.
|
|
37815
38157
|
*/
|
|
38158
|
+
/**
|
|
38159
|
+
* Presentation-only view of a text buffer: everything BEFORE a
|
|
38160
|
+
* ```codeam-handoff fence. The fence is protocol litter the app renders as
|
|
38161
|
+
* a proposal card (see `handoff-protocol.ts`) — it must never reach the
|
|
38162
|
+
* user, and the TERMINAL frames (`done:true` / `isFinal:true`) are the ones
|
|
38163
|
+
* that persist, so suppressing it only while streaming would still leave it
|
|
38164
|
+
* pinned on the finished bubble. Internal state is untouched:
|
|
38165
|
+
* {@link getCurrentText} keeps returning the RAW text so the turn-close
|
|
38166
|
+
* extraction can parse the proposal out of it.
|
|
38167
|
+
*
|
|
38168
|
+
* Masked-aware (`stripHandoffFences`), unlike the live-stream `append()`
|
|
38169
|
+
* cut (`handoffFenceStart`, unmasked): a TERMINAL frame is the one that
|
|
38170
|
+
* PERSISTS, so cutting on a fence quoted as an example inside a
|
|
38171
|
+
* 4+-backtick block here would permanently truncate the bubble. The live
|
|
38172
|
+
* cut stays unmasked/cheap — a mid-stream example is never terminal.
|
|
38173
|
+
*/
|
|
38174
|
+
visible(text) {
|
|
38175
|
+
return stripHandoffFences(text);
|
|
38176
|
+
}
|
|
37816
38177
|
async closeAll() {
|
|
37817
|
-
const finalText = this.text;
|
|
38178
|
+
const finalText = this.visible(this.text);
|
|
37818
38179
|
this.text = "";
|
|
37819
38180
|
await Promise.all([
|
|
37820
38181
|
this.publisher.publishOutput({ type: "text", content: finalText, done: true }),
|
|
@@ -37858,7 +38219,9 @@ var StreamingState = class {
|
|
|
37858
38219
|
([chunkId, { kind, content }]) => this.publisher.publishStreamingChunk({
|
|
37859
38220
|
chunkId,
|
|
37860
38221
|
kind,
|
|
37861
|
-
|
|
38222
|
+
// Terminal frame — same fence suppression the live deltas apply, so
|
|
38223
|
+
// a proposal fence never survives on the finalised bubble.
|
|
38224
|
+
content: kind === "text" ? this.visible(content) : content,
|
|
37862
38225
|
isFinal: true
|
|
37863
38226
|
})
|
|
37864
38227
|
)
|
|
@@ -37885,7 +38248,7 @@ var StreamingState = class {
|
|
|
37885
38248
|
* text done:true chunk with the full cumulative).
|
|
37886
38249
|
*/
|
|
37887
38250
|
async closeTurnWithInteractiveDetection() {
|
|
37888
|
-
const finalText = this.text;
|
|
38251
|
+
const finalText = this.visible(this.text);
|
|
37889
38252
|
this.text = "";
|
|
37890
38253
|
const flushSc = this.flushStreamingChunks();
|
|
37891
38254
|
const extracted = extractSelectPrompt(finalText);
|
|
@@ -38388,13 +38751,32 @@ async function runAcpSession(opts) {
|
|
|
38388
38751
|
acpSessionId = id;
|
|
38389
38752
|
},
|
|
38390
38753
|
switchAgentForSession,
|
|
38391
|
-
pendingHandoff
|
|
38754
|
+
pendingHandoff,
|
|
38755
|
+
// Agent Squad: roster/journal state, the @-mention route, the
|
|
38756
|
+
// single-slot proposal, and the SAME serialized event chain the
|
|
38757
|
+
// switch uses (so proposal events can't overtake switch events).
|
|
38758
|
+
squad,
|
|
38759
|
+
routeToAgent,
|
|
38760
|
+
pendingProposal,
|
|
38761
|
+
emitSwitchEvent
|
|
38392
38762
|
);
|
|
38393
38763
|
},
|
|
38394
38764
|
{ id: opts.agent, name: opts.agent, displayName: opts.agent }
|
|
38395
38765
|
);
|
|
38396
38766
|
const HANDOFF_MAX_CHARS = 16e3;
|
|
38397
38767
|
const pendingHandoff = { current: null };
|
|
38768
|
+
const squad = new SquadState({ sessionId: opts.sessionId });
|
|
38769
|
+
const refreshSquadRoster = () => {
|
|
38770
|
+
void fetchSquadRoster({
|
|
38771
|
+
sessionId: opts.sessionId,
|
|
38772
|
+
pluginId: opts.pluginId,
|
|
38773
|
+
pluginAuthToken: opts.pluginAuthToken
|
|
38774
|
+
}).then((roster) => {
|
|
38775
|
+
if (roster) squad.roster = roster;
|
|
38776
|
+
});
|
|
38777
|
+
};
|
|
38778
|
+
refreshSquadRoster();
|
|
38779
|
+
const pendingProposal = { current: null };
|
|
38398
38780
|
let switchCredentialEnv = {};
|
|
38399
38781
|
const relaunchWith = async (nextAgent) => {
|
|
38400
38782
|
try {
|
|
@@ -38404,6 +38786,7 @@ async function runAcpSession(opts) {
|
|
|
38404
38786
|
await streaming.closeAll();
|
|
38405
38787
|
const prevAgent = opts.agent;
|
|
38406
38788
|
const transcript = history.recentTranscript(HANDOFF_MAX_CHARS);
|
|
38789
|
+
squad.member(prevAgent).acpSessionId = acpSessionId;
|
|
38407
38790
|
await client3.stop();
|
|
38408
38791
|
const adapter = await resolveAcpAdapterWithRetry(nextAgent);
|
|
38409
38792
|
if (!adapter) throw new Error(`no ACP adapter available for ${nextAgent}`);
|
|
@@ -38453,31 +38836,74 @@ async function runAcpSession(opts) {
|
|
|
38453
38836
|
payload
|
|
38454
38837
|
})
|
|
38455
38838
|
);
|
|
38456
|
-
const
|
|
38457
|
-
|
|
38458
|
-
|
|
38459
|
-
|
|
38460
|
-
|
|
38461
|
-
|
|
38462
|
-
|
|
38463
|
-
|
|
38464
|
-
|
|
38465
|
-
|
|
38466
|
-
|
|
38467
|
-
|
|
38468
|
-
switchCredentialEnv = provisionAgentCredentials(agentId, auth);
|
|
38469
|
-
},
|
|
38470
|
-
ensureBinary: (agentId, installScript) => ensureAgentBinaryForSwitch(agentId, installScript),
|
|
38471
|
-
swapRuntime: relaunchWith,
|
|
38472
|
-
revertRuntime: relaunchWith,
|
|
38473
|
-
persistAgent: (agentId) => setSessionAgent(opts.pluginId, agentId),
|
|
38474
|
-
reannounce: (agentId) => {
|
|
38475
|
-
relay.setAgentMeta({ id: agentId, name: agentId, displayName: agentId });
|
|
38476
|
-
relay.reannounceAgents();
|
|
38477
|
-
}
|
|
38839
|
+
const switchDeps = {
|
|
38840
|
+
currentAgent: () => opts.agent,
|
|
38841
|
+
postEvent: emitSwitchEvent,
|
|
38842
|
+
fetchCredential: (agentId) => fetchProvisionCredential({
|
|
38843
|
+
agentId,
|
|
38844
|
+
sessionId: opts.sessionId,
|
|
38845
|
+
pluginId: opts.pluginId,
|
|
38846
|
+
pluginAuthToken: opts.pluginAuthToken,
|
|
38847
|
+
includeInstallScript: true
|
|
38848
|
+
}),
|
|
38849
|
+
provisionCredential: (agentId, auth) => {
|
|
38850
|
+
switchCredentialEnv = provisionAgentCredentials(agentId, auth);
|
|
38478
38851
|
},
|
|
38479
|
-
|
|
38480
|
-
|
|
38852
|
+
ensureBinary: (agentId, installScript) => ensureAgentBinaryForSwitch(agentId, installScript),
|
|
38853
|
+
swapRuntime: relaunchWith,
|
|
38854
|
+
revertRuntime: relaunchWith,
|
|
38855
|
+
persistAgent: (agentId) => setSessionAgent(opts.pluginId, agentId),
|
|
38856
|
+
reannounce: (agentId) => {
|
|
38857
|
+
relay.setAgentMeta({ id: agentId, name: agentId, displayName: agentId });
|
|
38858
|
+
relay.reannounceAgents();
|
|
38859
|
+
}
|
|
38860
|
+
};
|
|
38861
|
+
const switchAgentForSession = async (rawAgentId) => {
|
|
38862
|
+
const result = await performAgentSwitch(switchDeps, rawAgentId);
|
|
38863
|
+
if (result.ok) refreshSquadRoster();
|
|
38864
|
+
return result;
|
|
38865
|
+
};
|
|
38866
|
+
const sessionHandles = () => ({
|
|
38867
|
+
client: client3,
|
|
38868
|
+
acpSessionId,
|
|
38869
|
+
history,
|
|
38870
|
+
jsonlHistory,
|
|
38871
|
+
agentCaps,
|
|
38872
|
+
budgetRecovery
|
|
38873
|
+
});
|
|
38874
|
+
const routeToAgent = async (target, routeOpts = {}) => {
|
|
38875
|
+
const m = squad.member(target);
|
|
38876
|
+
const fast = routeOpts.skipFastPath !== true;
|
|
38877
|
+
const result = await performAgentSwitch(switchDeps, target, {
|
|
38878
|
+
skipProvision: fast && m.provisioned,
|
|
38879
|
+
skipInstall: fast && m.binaryVerified
|
|
38880
|
+
});
|
|
38881
|
+
if (!result.ok) {
|
|
38882
|
+
if (fast) {
|
|
38883
|
+
m.provisioned = false;
|
|
38884
|
+
m.binaryVerified = false;
|
|
38885
|
+
}
|
|
38886
|
+
return { result, handles: sessionHandles() };
|
|
38887
|
+
}
|
|
38888
|
+
m.provisioned = true;
|
|
38889
|
+
m.binaryVerified = true;
|
|
38890
|
+
if (m.acpSessionId && agentCaps?.loadSession) {
|
|
38891
|
+
try {
|
|
38892
|
+
await client3.loadSession(m.acpSessionId);
|
|
38893
|
+
acpSessionId = m.acpSessionId;
|
|
38894
|
+
history.switchActiveSession(m.acpSessionId);
|
|
38895
|
+
pendingHandoff.current = null;
|
|
38896
|
+
log.info(
|
|
38897
|
+
"acpRunner",
|
|
38898
|
+
`squad: resumed ${target}'s conversation ${m.acpSessionId.slice(0, 8)}`
|
|
38899
|
+
);
|
|
38900
|
+
} catch (err) {
|
|
38901
|
+
log.warn("acpRunner", `squad: resume for ${target} failed: ${describeError(err)}`);
|
|
38902
|
+
}
|
|
38903
|
+
}
|
|
38904
|
+
refreshSquadRoster();
|
|
38905
|
+
return { result, handles: sessionHandles() };
|
|
38906
|
+
};
|
|
38481
38907
|
await onboardingWelcomeDone;
|
|
38482
38908
|
relay.start();
|
|
38483
38909
|
void createWakeCredentialProbe({
|
|
@@ -38508,7 +38934,7 @@ async function runAcpSession(opts) {
|
|
|
38508
38934
|
await new Promise(() => {
|
|
38509
38935
|
});
|
|
38510
38936
|
}
|
|
38511
|
-
async function handleCommand(cmd, client3, relay, acpSessionId, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag, onActiveSessionChanged, switchAgent, pendingHandoff) {
|
|
38937
|
+
async function handleCommand(cmd, client3, relay, acpSessionId, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag, onActiveSessionChanged, switchAgent, pendingHandoff, squad, routeToAgent, pendingProposal, postSquadEvent) {
|
|
38512
38938
|
const session = {
|
|
38513
38939
|
client: client3,
|
|
38514
38940
|
relay,
|
|
@@ -38526,7 +38952,11 @@ async function handleCommand(cmd, client3, relay, acpSessionId, streaming, opts,
|
|
|
38526
38952
|
budgetReachedFlag,
|
|
38527
38953
|
onActiveSessionChanged,
|
|
38528
38954
|
switchAgent,
|
|
38529
|
-
pendingHandoff
|
|
38955
|
+
pendingHandoff,
|
|
38956
|
+
squad,
|
|
38957
|
+
routeToAgent,
|
|
38958
|
+
pendingProposal,
|
|
38959
|
+
postSquadEvent
|
|
38530
38960
|
};
|
|
38531
38961
|
await dispatchAcpCommand(assembleAcpCommandContext(session, cmd));
|
|
38532
38962
|
}
|
|
@@ -39586,9 +40016,9 @@ function startClaudeCredentialSync(opts) {
|
|
|
39586
40016
|
}
|
|
39587
40017
|
|
|
39588
40018
|
// src/beads/workflow-hint.ts
|
|
39589
|
-
var
|
|
39590
|
-
var
|
|
39591
|
-
var
|
|
40019
|
+
var fs76 = __toESM(require("fs"));
|
|
40020
|
+
var path83 = __toESM(require("path"));
|
|
40021
|
+
var os61 = __toESM(require("os"));
|
|
39592
40022
|
var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
|
|
39593
40023
|
var BEADS_HINT = `${BEADS_HINT_MARKER}
|
|
39594
40024
|
# Beads (bd) \u2014 task tracking + persistent memory (ALWAYS use it)
|
|
@@ -39602,22 +40032,22 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
|
|
|
39602
40032
|
- \`bd ready\` (available work) \xB7 \`bd show <id>\` \xB7 \`bd update <id> --claim\` \xB7 \`bd close <id>\`.
|
|
39603
40033
|
- Use \`bd remember "..."\` for persistent knowledge \u2014 do NOT use MEMORY.md files.
|
|
39604
40034
|
${BEADS_HINT_MARKER}`;
|
|
39605
|
-
function ensureBeadsWorkflowHint(homeDir2 =
|
|
40035
|
+
function ensureBeadsWorkflowHint(homeDir2 = os61.homedir()) {
|
|
39606
40036
|
try {
|
|
39607
|
-
const file =
|
|
40037
|
+
const file = path83.join(homeDir2, ".claude", "CLAUDE.md");
|
|
39608
40038
|
let existing = "";
|
|
39609
40039
|
try {
|
|
39610
|
-
existing =
|
|
40040
|
+
existing = fs76.readFileSync(file, "utf8");
|
|
39611
40041
|
} catch {
|
|
39612
40042
|
}
|
|
39613
40043
|
if (existing.includes(BEADS_HINT_MARKER)) return;
|
|
39614
|
-
|
|
40044
|
+
fs76.mkdirSync(path83.dirname(file), { recursive: true });
|
|
39615
40045
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
39616
40046
|
|
|
39617
40047
|
${BEADS_HINT}
|
|
39618
40048
|
` : `${BEADS_HINT}
|
|
39619
40049
|
`;
|
|
39620
|
-
|
|
40050
|
+
fs76.writeFileSync(file, next);
|
|
39621
40051
|
} catch {
|
|
39622
40052
|
}
|
|
39623
40053
|
}
|
|
@@ -39989,7 +40419,7 @@ var AcpDriver = class {
|
|
|
39989
40419
|
};
|
|
39990
40420
|
|
|
39991
40421
|
// src/baton/transcript-mirror.ts
|
|
39992
|
-
var
|
|
40422
|
+
var fs77 = __toESM(require("fs"));
|
|
39993
40423
|
var TranscriptMirror = class {
|
|
39994
40424
|
constructor(deps) {
|
|
39995
40425
|
this.deps = deps;
|
|
@@ -40056,7 +40486,7 @@ var TranscriptMirror = class {
|
|
|
40056
40486
|
}
|
|
40057
40487
|
};
|
|
40058
40488
|
function defaultWatch(file, onChange) {
|
|
40059
|
-
const w3 =
|
|
40489
|
+
const w3 = fs77.watch(file, { persistent: false }, () => onChange());
|
|
40060
40490
|
return () => w3.close();
|
|
40061
40491
|
}
|
|
40062
40492
|
|
|
@@ -40354,16 +40784,16 @@ function keepDeviceAwake(deps = {}) {
|
|
|
40354
40784
|
}
|
|
40355
40785
|
|
|
40356
40786
|
// src/agents/claude/onboarding.ts
|
|
40357
|
-
var
|
|
40358
|
-
var
|
|
40359
|
-
var
|
|
40787
|
+
var fs78 = __toESM(require("fs"));
|
|
40788
|
+
var os63 = __toESM(require("os"));
|
|
40789
|
+
var path84 = __toESM(require("path"));
|
|
40360
40790
|
var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
|
|
40361
40791
|
function ensureClaudeOnboarded(cwd) {
|
|
40362
40792
|
try {
|
|
40363
|
-
const file =
|
|
40793
|
+
const file = path84.join(os63.homedir(), ".claude.json");
|
|
40364
40794
|
let config = {};
|
|
40365
40795
|
try {
|
|
40366
|
-
config = JSON.parse(
|
|
40796
|
+
config = JSON.parse(fs78.readFileSync(file, "utf8"));
|
|
40367
40797
|
} catch {
|
|
40368
40798
|
}
|
|
40369
40799
|
let changed = false;
|
|
@@ -40388,8 +40818,8 @@ function ensureClaudeOnboarded(cwd) {
|
|
|
40388
40818
|
}
|
|
40389
40819
|
}
|
|
40390
40820
|
if (!changed) return;
|
|
40391
|
-
|
|
40392
|
-
|
|
40821
|
+
fs78.mkdirSync(path84.dirname(file), { recursive: true });
|
|
40822
|
+
fs78.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
40393
40823
|
log.info(
|
|
40394
40824
|
"claude",
|
|
40395
40825
|
`pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
|
|
@@ -41121,7 +41551,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
|
|
|
41121
41551
|
var import_child_process30 = require("child_process");
|
|
41122
41552
|
var import_util4 = require("util");
|
|
41123
41553
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
41124
|
-
var
|
|
41554
|
+
var path85 = __toESM(require("path"));
|
|
41125
41555
|
var execFileP6 = (0, import_util4.promisify)(import_child_process30.execFile);
|
|
41126
41556
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
41127
41557
|
function resetStdinForChild() {
|
|
@@ -41610,7 +42040,7 @@ var GitHubCodespacesProvider = class {
|
|
|
41610
42040
|
});
|
|
41611
42041
|
}
|
|
41612
42042
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
41613
|
-
const remoteDir =
|
|
42043
|
+
const remoteDir = path85.posix.dirname(remotePath);
|
|
41614
42044
|
const parts = [
|
|
41615
42045
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
41616
42046
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -41680,7 +42110,7 @@ function shellQuote(s) {
|
|
|
41680
42110
|
// src/services/providers/gitpod.ts
|
|
41681
42111
|
var import_child_process31 = require("child_process");
|
|
41682
42112
|
var import_util5 = require("util");
|
|
41683
|
-
var
|
|
42113
|
+
var path86 = __toESM(require("path"));
|
|
41684
42114
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
41685
42115
|
var execFileP7 = (0, import_util5.promisify)(import_child_process31.execFile);
|
|
41686
42116
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -41920,7 +42350,7 @@ var GitpodProvider = class {
|
|
|
41920
42350
|
});
|
|
41921
42351
|
}
|
|
41922
42352
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
41923
|
-
const remoteDir =
|
|
42353
|
+
const remoteDir = path86.posix.dirname(remotePath);
|
|
41924
42354
|
const parts = [
|
|
41925
42355
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
41926
42356
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -41956,7 +42386,7 @@ function shellQuote2(s) {
|
|
|
41956
42386
|
// src/services/providers/gitlab-workspaces.ts
|
|
41957
42387
|
var import_child_process32 = require("child_process");
|
|
41958
42388
|
var import_util6 = require("util");
|
|
41959
|
-
var
|
|
42389
|
+
var path87 = __toESM(require("path"));
|
|
41960
42390
|
var execFileP8 = (0, import_util6.promisify)(import_child_process32.execFile);
|
|
41961
42391
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
41962
42392
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -42216,7 +42646,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
42216
42646
|
}
|
|
42217
42647
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
42218
42648
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
42219
|
-
const remoteDir =
|
|
42649
|
+
const remoteDir = path87.posix.dirname(remotePath);
|
|
42220
42650
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
42221
42651
|
if (options.mode != null) {
|
|
42222
42652
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -42284,7 +42714,7 @@ function shellQuote3(s) {
|
|
|
42284
42714
|
// src/services/providers/railway.ts
|
|
42285
42715
|
var import_child_process33 = require("child_process");
|
|
42286
42716
|
var import_util7 = require("util");
|
|
42287
|
-
var
|
|
42717
|
+
var path88 = __toESM(require("path"));
|
|
42288
42718
|
var execFileP9 = (0, import_util7.promisify)(import_child_process33.execFile);
|
|
42289
42719
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
42290
42720
|
function resetStdinForChild4() {
|
|
@@ -42520,7 +42950,7 @@ var RailwayProvider = class {
|
|
|
42520
42950
|
if (!projectId || !serviceId) {
|
|
42521
42951
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
42522
42952
|
}
|
|
42523
|
-
const remoteDir =
|
|
42953
|
+
const remoteDir = path88.posix.dirname(remotePath);
|
|
42524
42954
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
42525
42955
|
if (options.mode != null) {
|
|
42526
42956
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -43166,8 +43596,8 @@ async function invite() {
|
|
|
43166
43596
|
var import_node_dns = require("dns");
|
|
43167
43597
|
var import_node_util5 = require("util");
|
|
43168
43598
|
var import_node_crypto13 = require("crypto");
|
|
43169
|
-
var
|
|
43170
|
-
var
|
|
43599
|
+
var fs79 = __toESM(require("fs"));
|
|
43600
|
+
var path89 = __toESM(require("path"));
|
|
43171
43601
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
43172
43602
|
var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
|
|
43173
43603
|
async function checkDns(apiBase2) {
|
|
@@ -43223,13 +43653,13 @@ async function checkHealth(apiBase2) {
|
|
|
43223
43653
|
}
|
|
43224
43654
|
}
|
|
43225
43655
|
function checkConfigDir() {
|
|
43226
|
-
const dir =
|
|
43656
|
+
const dir = path89.join(require("os").homedir(), ".codeam");
|
|
43227
43657
|
try {
|
|
43228
|
-
|
|
43229
|
-
const probe =
|
|
43230
|
-
|
|
43231
|
-
const read2 =
|
|
43232
|
-
|
|
43658
|
+
fs79.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
43659
|
+
const probe = path89.join(dir, ".doctor-probe");
|
|
43660
|
+
fs79.writeFileSync(probe, "ok", { mode: 384 });
|
|
43661
|
+
const read2 = fs79.readFileSync(probe, "utf8");
|
|
43662
|
+
fs79.unlinkSync(probe);
|
|
43233
43663
|
if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
|
|
43234
43664
|
return {
|
|
43235
43665
|
id: "config-dir",
|
|
@@ -43269,9 +43699,9 @@ function checkSessions() {
|
|
|
43269
43699
|
}
|
|
43270
43700
|
}
|
|
43271
43701
|
function checkAgentBinaries() {
|
|
43272
|
-
const
|
|
43702
|
+
const os66 = createOsStrategy();
|
|
43273
43703
|
return getEnabledAgents().map((meta) => {
|
|
43274
|
-
const found =
|
|
43704
|
+
const found = os66.findInPath(meta.binaryName);
|
|
43275
43705
|
return {
|
|
43276
43706
|
id: `agent-${meta.id}`,
|
|
43277
43707
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -43293,7 +43723,7 @@ function checkNodePty() {
|
|
|
43293
43723
|
detail: "not required on this platform"
|
|
43294
43724
|
};
|
|
43295
43725
|
}
|
|
43296
|
-
const vendoredPath =
|
|
43726
|
+
const vendoredPath = path89.join(__dirname, "vendor", "node-pty");
|
|
43297
43727
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
43298
43728
|
try {
|
|
43299
43729
|
require(target);
|
|
@@ -43335,7 +43765,7 @@ function checkChokidar() {
|
|
|
43335
43765
|
}
|
|
43336
43766
|
async function doctor(args2 = []) {
|
|
43337
43767
|
const json = args2.includes("--json");
|
|
43338
|
-
const cliVersion = true ? "2.
|
|
43768
|
+
const cliVersion = true ? "2.64.0" : "0.0.0-dev";
|
|
43339
43769
|
const apiBase2 = resolveApiBaseUrl();
|
|
43340
43770
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
43341
43771
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -43726,7 +44156,7 @@ async function mcpRun(args2) {
|
|
|
43726
44156
|
// src/commands/version.ts
|
|
43727
44157
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
43728
44158
|
function version2() {
|
|
43729
|
-
const v = true ? "2.
|
|
44159
|
+
const v = true ? "2.64.0" : "unknown";
|
|
43730
44160
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
43731
44161
|
}
|
|
43732
44162
|
|
|
@@ -43875,10 +44305,10 @@ var EXIT_CODE_NAMES = {
|
|
|
43875
44305
|
};
|
|
43876
44306
|
|
|
43877
44307
|
// src/index.ts
|
|
43878
|
-
var
|
|
44308
|
+
var os65 = __toESM(require("os"));
|
|
43879
44309
|
if (!process.env.HOME) {
|
|
43880
44310
|
try {
|
|
43881
|
-
const home =
|
|
44311
|
+
const home = os65.homedir();
|
|
43882
44312
|
if (home) process.env.HOME = home;
|
|
43883
44313
|
} catch {
|
|
43884
44314
|
}
|