codeam-cli 2.75.25 → 2.75.27
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 +14 -0
- package/dist/index.js +1563 -765
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -357,8 +357,8 @@ function defaultSpawn(timeoutMs) {
|
|
|
357
357
|
});
|
|
358
358
|
}
|
|
359
359
|
function resolveConvexBin(cwd) {
|
|
360
|
-
const local =
|
|
361
|
-
if (
|
|
360
|
+
const local = path95.join(cwd, "node_modules", ".bin", process.platform === "win32" ? "convex.cmd" : "convex");
|
|
361
|
+
if (fs81.existsSync(local)) return { cmd: local, args: [] };
|
|
362
362
|
return { cmd: "npx", args: ["--yes", "convex"] };
|
|
363
363
|
}
|
|
364
364
|
function redact(text, key) {
|
|
@@ -489,13 +489,13 @@ async function runConvexAdminMcp(client3, id) {
|
|
|
489
489
|
});
|
|
490
490
|
await server.connect(new StdioServerTransport());
|
|
491
491
|
}
|
|
492
|
-
var import_node_child_process32,
|
|
492
|
+
var import_node_child_process32, fs81, path95, TOOLS;
|
|
493
493
|
var init_convex_admin_mcp = __esm({
|
|
494
494
|
"src/integrations/convex-admin-mcp.ts"() {
|
|
495
495
|
"use strict";
|
|
496
496
|
import_node_child_process32 = require("child_process");
|
|
497
|
-
|
|
498
|
-
|
|
497
|
+
fs81 = __toESM(require("fs"));
|
|
498
|
+
path95 = __toESM(require("path"));
|
|
499
499
|
TOOLS = [
|
|
500
500
|
{
|
|
501
501
|
name: "tables",
|
|
@@ -3248,6 +3248,9 @@ var USER_EVENTS = {
|
|
|
3248
3248
|
PREVIEW_STOPPED: "preview_stopped",
|
|
3249
3249
|
PREVIEW_ERROR: "preview_error",
|
|
3250
3250
|
PREVIEW_PROGRESS: "preview_progress",
|
|
3251
|
+
/** The agent points at an element of the running preview (`highlight_element`
|
|
3252
|
+
* MCP tool) — the inspector client draws the agent's mark over it. */
|
|
3253
|
+
PREVIEW_AGENT_HIGHLIGHT: "preview_agent_highlight",
|
|
3251
3254
|
BEADS_STATE_CHANGED: "beads_state_changed",
|
|
3252
3255
|
BEADS_PROVISIONING: "beads_provisioning",
|
|
3253
3256
|
BEADS_TEAM_MEMORY_CHANGED: "beads_team_memory_changed",
|
|
@@ -3428,6 +3431,9 @@ function maybeRotate() {
|
|
|
3428
3431
|
} catch {
|
|
3429
3432
|
return;
|
|
3430
3433
|
}
|
|
3434
|
+
rotateNow();
|
|
3435
|
+
}
|
|
3436
|
+
function rotateNow() {
|
|
3431
3437
|
const archivePath = (n) => n === 0 ? `${debugFilePath}.old` : `${debugFilePath}.${n}`;
|
|
3432
3438
|
for (let i = MAX_ARCHIVES - 1; i >= 0; i--) {
|
|
3433
3439
|
const src = archivePath(i);
|
|
@@ -3451,6 +3457,7 @@ function appendToFile(line) {
|
|
|
3451
3457
|
try {
|
|
3452
3458
|
if (!fileInitialized) {
|
|
3453
3459
|
fs.mkdirSync(path.dirname(debugFilePath), { recursive: true, mode: 448 });
|
|
3460
|
+
if (fs.existsSync(debugFilePath)) rotateNow();
|
|
3454
3461
|
const header = jsonMode ? `${JSON.stringify({
|
|
3455
3462
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3456
3463
|
level: "info",
|
|
@@ -3525,11 +3532,11 @@ function quiet(fn) {
|
|
|
3525
3532
|
log.debug(TAG, "ignored sync error", err);
|
|
3526
3533
|
}
|
|
3527
3534
|
}
|
|
3528
|
-
function rmIfExistsQuiet(
|
|
3535
|
+
function rmIfExistsQuiet(path97) {
|
|
3529
3536
|
try {
|
|
3530
|
-
fs2.rmSync(
|
|
3537
|
+
fs2.rmSync(path97, { force: true });
|
|
3531
3538
|
} catch (err) {
|
|
3532
|
-
log.debug(TAG, `rmIfExists failed for ${
|
|
3539
|
+
log.debug(TAG, `rmIfExists failed for ${path97}`, err);
|
|
3533
3540
|
}
|
|
3534
3541
|
}
|
|
3535
3542
|
function killQuiet(target, signal = "SIGTERM") {
|
|
@@ -3733,8 +3740,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
3733
3740
|
return decodedFile;
|
|
3734
3741
|
};
|
|
3735
3742
|
}
|
|
3736
|
-
function normalizeWindowsPath(
|
|
3737
|
-
return
|
|
3743
|
+
function normalizeWindowsPath(path97) {
|
|
3744
|
+
return path97.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
3738
3745
|
}
|
|
3739
3746
|
|
|
3740
3747
|
// ../../node_modules/@posthog/core/dist/error-tracking/index.mjs
|
|
@@ -6467,13 +6474,13 @@ var PostHogCoreStateless = class {
|
|
|
6467
6474
|
sentFromRoute += batchMessages.length;
|
|
6468
6475
|
}
|
|
6469
6476
|
}
|
|
6470
|
-
async _sendOtlpBatch({ path:
|
|
6477
|
+
async _sendOtlpBatch({ path: path97, payload }) {
|
|
6471
6478
|
if (this.disabled) return {
|
|
6472
6479
|
kind: "fatal",
|
|
6473
6480
|
error: new Error("The client is disabled")
|
|
6474
6481
|
};
|
|
6475
6482
|
const serialized = JSON.stringify(payload);
|
|
6476
|
-
const url2 = `${this.host}/i/v1/${
|
|
6483
|
+
const url2 = `${this.host}/i/v1/${path97}?token=${encodeURIComponent(this.apiKey)}`;
|
|
6477
6484
|
const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
|
|
6478
6485
|
const fetchOptions = {
|
|
6479
6486
|
method: "POST",
|
|
@@ -7713,14 +7720,14 @@ async function addSourceContext(frames, openSourceFile = import_promises.open, l
|
|
|
7713
7720
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
7714
7721
|
return frames;
|
|
7715
7722
|
}
|
|
7716
|
-
async function openRegularSourceFile(
|
|
7723
|
+
async function openRegularSourceFile(path97, openSourceFile, logger) {
|
|
7717
7724
|
let fileHandle;
|
|
7718
7725
|
let isValid = false;
|
|
7719
7726
|
try {
|
|
7720
|
-
fileHandle = await openSourceFile(
|
|
7727
|
+
fileHandle = await openSourceFile(path97, import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NONBLOCK);
|
|
7721
7728
|
const fileStat = await fileHandle.stat();
|
|
7722
7729
|
if (!fileStat.isFile()) return;
|
|
7723
|
-
if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${
|
|
7730
|
+
if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${path97}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
|
|
7724
7731
|
isValid = true;
|
|
7725
7732
|
return fileHandle;
|
|
7726
7733
|
} catch {
|
|
@@ -7730,8 +7737,8 @@ async function openRegularSourceFile(path96, openSourceFile, logger) {
|
|
|
7730
7737
|
});
|
|
7731
7738
|
}
|
|
7732
7739
|
}
|
|
7733
|
-
async function getContextLinesFromFile(
|
|
7734
|
-
const fileHandle = await openRegularSourceFile(
|
|
7740
|
+
async function getContextLinesFromFile(path97, ranges, output, cacheKey, openSourceFile, logger) {
|
|
7741
|
+
const fileHandle = await openRegularSourceFile(path97, openSourceFile, logger);
|
|
7735
7742
|
if (void 0 === fileHandle) return void LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
|
|
7736
7743
|
const openedFileHandle = fileHandle;
|
|
7737
7744
|
return new Promise((resolve12) => {
|
|
@@ -7833,22 +7840,22 @@ function clearLineContext(frame) {
|
|
|
7833
7840
|
delete frame.context_line;
|
|
7834
7841
|
delete frame.post_context;
|
|
7835
7842
|
}
|
|
7836
|
-
function shouldSkipContextLinesForFile(
|
|
7837
|
-
return
|
|
7843
|
+
function shouldSkipContextLinesForFile(path97) {
|
|
7844
|
+
return path97.startsWith("node:") || path97.endsWith(".min.js") || path97.endsWith(".min.cjs") || path97.endsWith(".min.mjs") || path97.startsWith("data:");
|
|
7838
7845
|
}
|
|
7839
7846
|
function shouldSkipContextLinesForFrame(frame) {
|
|
7840
7847
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
7841
7848
|
if (void 0 !== frame.colno && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
|
|
7842
7849
|
return false;
|
|
7843
7850
|
}
|
|
7844
|
-
function makeSourceCacheKey(
|
|
7845
|
-
if ((0, import_node_path.isAbsolute)(
|
|
7851
|
+
function makeSourceCacheKey(path97, basePath) {
|
|
7852
|
+
if ((0, import_node_path.isAbsolute)(path97)) return JSON.stringify([
|
|
7846
7853
|
null,
|
|
7847
|
-
|
|
7854
|
+
path97
|
|
7848
7855
|
]);
|
|
7849
7856
|
return void 0 === basePath ? void 0 : JSON.stringify([
|
|
7850
7857
|
basePath,
|
|
7851
|
-
|
|
7858
|
+
path97
|
|
7852
7859
|
]);
|
|
7853
7860
|
}
|
|
7854
7861
|
function rangeExistsInContentCache(cacheKey, range) {
|
|
@@ -10509,7 +10516,7 @@ function readAnonId() {
|
|
|
10509
10516
|
}
|
|
10510
10517
|
function superProperties() {
|
|
10511
10518
|
return {
|
|
10512
|
-
cliVersion: true ? "2.75.
|
|
10519
|
+
cliVersion: true ? "2.75.27" : "0.0.0-dev",
|
|
10513
10520
|
nodeVersion: process.version,
|
|
10514
10521
|
platform: process.platform,
|
|
10515
10522
|
arch: process.arch,
|
|
@@ -10751,7 +10758,7 @@ var http = __toESM(require("http"));
|
|
|
10751
10758
|
// package.json
|
|
10752
10759
|
var package_default = {
|
|
10753
10760
|
name: "codeam-cli",
|
|
10754
|
-
version: "2.75.
|
|
10761
|
+
version: "2.75.27",
|
|
10755
10762
|
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.",
|
|
10756
10763
|
type: "commonjs",
|
|
10757
10764
|
main: "dist/index.js",
|
|
@@ -12081,7 +12088,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12081
12088
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12082
12089
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12083
12090
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12084
|
-
..."2.75.
|
|
12091
|
+
..."2.75.27" ? { ideVersion: "2.75.27" } : {}
|
|
12085
12092
|
};
|
|
12086
12093
|
try {
|
|
12087
12094
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body);
|
|
@@ -12387,10 +12394,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
12387
12394
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
12388
12395
|
/[\\/]Templates([\\/]|$)/i
|
|
12389
12396
|
];
|
|
12390
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
12397
|
+
function isUnsafeWindowsWatchRoot(dir, homedir52) {
|
|
12391
12398
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
12392
12399
|
const cwd = norm(dir);
|
|
12393
|
-
const home = norm(
|
|
12400
|
+
const home = norm(homedir52);
|
|
12394
12401
|
if (cwd === home) return true;
|
|
12395
12402
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
12396
12403
|
const sysRoots = [
|
|
@@ -17120,10 +17127,10 @@ function buildForPlatform(platform3) {
|
|
|
17120
17127
|
var import_node_crypto4 = require("crypto");
|
|
17121
17128
|
|
|
17122
17129
|
// src/agents/claude/resolver.ts
|
|
17123
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
17124
|
-
const found =
|
|
17130
|
+
function buildClaudeLaunch(extraArgs = [], os66 = createOsStrategy()) {
|
|
17131
|
+
const found = os66.findInPath("claude") ?? os66.findInPath("claude-code");
|
|
17125
17132
|
if (!found) return null;
|
|
17126
|
-
return
|
|
17133
|
+
return os66.buildLaunch(found, extraArgs);
|
|
17127
17134
|
}
|
|
17128
17135
|
|
|
17129
17136
|
// src/agents/claude/installer.ts
|
|
@@ -17901,8 +17908,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
17901
17908
|
meta = getAgent("claude");
|
|
17902
17909
|
mode = "interactive";
|
|
17903
17910
|
os;
|
|
17904
|
-
constructor(
|
|
17905
|
-
this.os =
|
|
17911
|
+
constructor(os66) {
|
|
17912
|
+
this.os = os66;
|
|
17906
17913
|
}
|
|
17907
17914
|
/**
|
|
17908
17915
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -18996,8 +19003,8 @@ function codexCredentialLocator() {
|
|
|
18996
19003
|
function codexLoginLauncher() {
|
|
18997
19004
|
return {
|
|
18998
19005
|
async ensureInstalled() {
|
|
18999
|
-
const
|
|
19000
|
-
return
|
|
19006
|
+
const os66 = createOsStrategy();
|
|
19007
|
+
return os66.findInPath("codex") !== null;
|
|
19001
19008
|
},
|
|
19002
19009
|
launch() {
|
|
19003
19010
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -19020,8 +19027,8 @@ var CodexRuntimeStrategy = class {
|
|
|
19020
19027
|
meta = getAgent("codex");
|
|
19021
19028
|
mode = "interactive";
|
|
19022
19029
|
os;
|
|
19023
|
-
constructor(
|
|
19024
|
-
this.os =
|
|
19030
|
+
constructor(os66) {
|
|
19031
|
+
this.os = os66;
|
|
19025
19032
|
}
|
|
19026
19033
|
async prepareLaunch() {
|
|
19027
19034
|
let binary = this.os.findInPath("codex");
|
|
@@ -19131,12 +19138,12 @@ var CodexRuntimeStrategy = class {
|
|
|
19131
19138
|
});
|
|
19132
19139
|
}
|
|
19133
19140
|
};
|
|
19134
|
-
function resolveNpm(
|
|
19135
|
-
return
|
|
19141
|
+
function resolveNpm(os66) {
|
|
19142
|
+
return os66.id === "win32" ? "npm.cmd" : "npm";
|
|
19136
19143
|
}
|
|
19137
|
-
async function installCodexViaNpm(
|
|
19144
|
+
async function installCodexViaNpm(os66) {
|
|
19138
19145
|
return new Promise((resolve12, reject) => {
|
|
19139
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
19146
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os66), ["install", "-g", "@openai/codex"], {
|
|
19140
19147
|
stdio: "inherit"
|
|
19141
19148
|
});
|
|
19142
19149
|
proc.on("close", (code) => {
|
|
@@ -19153,16 +19160,16 @@ async function installCodexViaNpm(os65) {
|
|
|
19153
19160
|
});
|
|
19154
19161
|
});
|
|
19155
19162
|
}
|
|
19156
|
-
function augmentNpmGlobalBin(
|
|
19163
|
+
function augmentNpmGlobalBin(os66) {
|
|
19157
19164
|
try {
|
|
19158
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
19165
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os66), ["prefix", "-g"], {
|
|
19159
19166
|
stdio: ["ignore", "pipe", "ignore"]
|
|
19160
19167
|
});
|
|
19161
19168
|
if (result.status !== 0) return;
|
|
19162
19169
|
const prefix = result.stdout.toString().trim();
|
|
19163
19170
|
if (!prefix) return;
|
|
19164
|
-
const binDir =
|
|
19165
|
-
|
|
19171
|
+
const binDir = os66.id === "win32" ? prefix : path24.join(prefix, "bin");
|
|
19172
|
+
os66.augmentPath([binDir]);
|
|
19166
19173
|
} catch {
|
|
19167
19174
|
}
|
|
19168
19175
|
}
|
|
@@ -19356,10 +19363,10 @@ function manualInstallHint(runner, tools) {
|
|
|
19356
19363
|
const argv = osPackageInstallArgv(detectPackageManager(runner), [...tools]);
|
|
19357
19364
|
return argv ? `\`sudo ${argv.join(" ")}\`` : `your package manager (e.g. \`${pkgs}\`)`;
|
|
19358
19365
|
}
|
|
19359
|
-
function writeUnzipShim(
|
|
19366
|
+
function writeUnzipShim(os66, runner) {
|
|
19360
19367
|
const python = ["python3", "python"].find((p2) => runner.which(p2));
|
|
19361
19368
|
if (!python) return null;
|
|
19362
|
-
const dir =
|
|
19369
|
+
const dir = os66.scratchPath("codeam-cr-prereq");
|
|
19363
19370
|
const shim = path26.join(dir, "unzip");
|
|
19364
19371
|
const script = `#!/bin/sh
|
|
19365
19372
|
set -e
|
|
@@ -19381,9 +19388,9 @@ exec ${python} -m zipfile -e "$archive" "$dest"
|
|
|
19381
19388
|
(0, import_node_fs5.chmodSync)(shim, 448);
|
|
19382
19389
|
return dir;
|
|
19383
19390
|
}
|
|
19384
|
-
async function ensureInstallPrerequisites(
|
|
19391
|
+
async function ensureInstallPrerequisites(os66, deps = {}) {
|
|
19385
19392
|
const runner = deps.runner ?? defaultOsRunner;
|
|
19386
|
-
const missing = REQUIRED_TOOLS.filter((t2) =>
|
|
19393
|
+
const missing = REQUIRED_TOOLS.filter((t2) => os66.findInPath(t2) === null);
|
|
19387
19394
|
if (missing.length === 0) return { ok: true, extraPath: [] };
|
|
19388
19395
|
log.info(
|
|
19389
19396
|
"coderabbit",
|
|
@@ -19402,10 +19409,10 @@ async function ensureInstallPrerequisites(os65, deps = {}) {
|
|
|
19402
19409
|
);
|
|
19403
19410
|
}
|
|
19404
19411
|
}
|
|
19405
|
-
const stillMissing = REQUIRED_TOOLS.filter((t2) =>
|
|
19412
|
+
const stillMissing = REQUIRED_TOOLS.filter((t2) => os66.findInPath(t2) === null);
|
|
19406
19413
|
if (stillMissing.length === 0) return { ok: true, extraPath: [] };
|
|
19407
19414
|
if (stillMissing.length === 1 && stillMissing[0] === "unzip") {
|
|
19408
|
-
const shimDir = writeUnzipShim(
|
|
19415
|
+
const shimDir = writeUnzipShim(os66, runner);
|
|
19409
19416
|
if (shimDir) {
|
|
19410
19417
|
log.info("coderabbit", "unzip is unavailable \u2014 using a scoped python zipfile shim");
|
|
19411
19418
|
return { ok: true, extraPath: [shimDir] };
|
|
@@ -19468,15 +19475,15 @@ function summarizeInstallFailure(output) {
|
|
|
19468
19475
|
}
|
|
19469
19476
|
return lines.length > 0 ? lines[lines.length - 1] : null;
|
|
19470
19477
|
}
|
|
19471
|
-
async function ensureCoderabbitInstalled(
|
|
19472
|
-
if (
|
|
19473
|
-
if (
|
|
19478
|
+
async function ensureCoderabbitInstalled(os66, deps = {}) {
|
|
19479
|
+
if (os66.findInPath("coderabbit")) return { ok: true };
|
|
19480
|
+
if (os66.id === "win32") {
|
|
19474
19481
|
return {
|
|
19475
19482
|
ok: false,
|
|
19476
19483
|
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."
|
|
19477
19484
|
};
|
|
19478
19485
|
}
|
|
19479
|
-
const prereq = await ensureInstallPrerequisites(
|
|
19486
|
+
const prereq = await ensureInstallPrerequisites(os66, deps);
|
|
19480
19487
|
if (!prereq.ok) return { ok: false, error: prereq.error };
|
|
19481
19488
|
const env = { ...process.env };
|
|
19482
19489
|
if (prereq.extraPath.length > 0) {
|
|
@@ -19485,8 +19492,8 @@ async function ensureCoderabbitInstalled(os65, deps = {}) {
|
|
|
19485
19492
|
log.info("coderabbit", "CodeRabbit CLI not found \u2014 installing via the official script");
|
|
19486
19493
|
const run = deps.runInstallScript ?? defaultRunInstallScript;
|
|
19487
19494
|
const { code, output } = await run(env);
|
|
19488
|
-
|
|
19489
|
-
const binary =
|
|
19495
|
+
os66.augmentPath([`${os66.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
19496
|
+
const binary = os66.findInPath("coderabbit");
|
|
19490
19497
|
const detail = summarizeInstallFailure(output);
|
|
19491
19498
|
if (binary !== null) {
|
|
19492
19499
|
if (code === 0) return { ok: true };
|
|
@@ -19540,10 +19547,10 @@ function coderabbitCredentialLocator() {
|
|
|
19540
19547
|
validate: validateNonEmptyCredential
|
|
19541
19548
|
};
|
|
19542
19549
|
}
|
|
19543
|
-
function coderabbitLoginLauncher(
|
|
19550
|
+
function coderabbitLoginLauncher(os66) {
|
|
19544
19551
|
return {
|
|
19545
19552
|
async ensureInstalled() {
|
|
19546
|
-
const result = await ensureCoderabbitInstalled(
|
|
19553
|
+
const result = await ensureCoderabbitInstalled(os66);
|
|
19547
19554
|
if (!result.ok && result.error) console.error(`
|
|
19548
19555
|
\u2717 ${result.error}
|
|
19549
19556
|
`);
|
|
@@ -19603,8 +19610,8 @@ function pickLine(obj) {
|
|
|
19603
19610
|
function toHunk(raw, groupSeverity) {
|
|
19604
19611
|
if (!raw || typeof raw !== "object") return null;
|
|
19605
19612
|
const o = raw;
|
|
19606
|
-
const
|
|
19607
|
-
if (!
|
|
19613
|
+
const path97 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
|
|
19614
|
+
if (!path97) return null;
|
|
19608
19615
|
const message = asString(
|
|
19609
19616
|
pick(o, [
|
|
19610
19617
|
"comment",
|
|
@@ -19621,7 +19628,7 @@ function toHunk(raw, groupSeverity) {
|
|
|
19621
19628
|
const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
|
|
19622
19629
|
const locObj = pick(o, ["location"]) ?? o;
|
|
19623
19630
|
return {
|
|
19624
|
-
path:
|
|
19631
|
+
path: path97.trim(),
|
|
19625
19632
|
line: pickLine(o) ?? pickLine(locObj),
|
|
19626
19633
|
severity,
|
|
19627
19634
|
message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
|
|
@@ -19704,10 +19711,10 @@ function parsePlain(stdout) {
|
|
|
19704
19711
|
for (const line of stdout.split(/\r?\n/)) {
|
|
19705
19712
|
const m = line.match(HUNK_LINE_RE);
|
|
19706
19713
|
if (!m) continue;
|
|
19707
|
-
const [,
|
|
19708
|
-
if (!
|
|
19714
|
+
const [, path97, lineNo, sevToken, message] = m;
|
|
19715
|
+
if (!path97 || !lineNo || !message) continue;
|
|
19709
19716
|
hunks.push({
|
|
19710
|
-
path:
|
|
19717
|
+
path: path97.trim(),
|
|
19711
19718
|
line: Number(lineNo),
|
|
19712
19719
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
19713
19720
|
message: message.trim().replace(/^[*-]\s+/, "")
|
|
@@ -19767,8 +19774,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
19767
19774
|
meta = getAgent("coderabbit");
|
|
19768
19775
|
mode = "batch";
|
|
19769
19776
|
os;
|
|
19770
|
-
constructor(
|
|
19771
|
-
this.os =
|
|
19777
|
+
constructor(os66) {
|
|
19778
|
+
this.os = os66;
|
|
19772
19779
|
}
|
|
19773
19780
|
getDefaultArgs() {
|
|
19774
19781
|
return ["review", "--agent"];
|
|
@@ -20039,10 +20046,10 @@ function cursorCredentialLocator() {
|
|
|
20039
20046
|
validate: validateNonEmptyCredential
|
|
20040
20047
|
};
|
|
20041
20048
|
}
|
|
20042
|
-
function cursorLoginLauncher(
|
|
20049
|
+
function cursorLoginLauncher(os66) {
|
|
20043
20050
|
return {
|
|
20044
20051
|
async ensureInstalled() {
|
|
20045
|
-
if (
|
|
20052
|
+
if (os66.findInPath("cursor-agent")) return true;
|
|
20046
20053
|
console.error(
|
|
20047
20054
|
"\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"
|
|
20048
20055
|
);
|
|
@@ -20106,8 +20113,8 @@ var CursorRuntimeStrategy = class {
|
|
|
20106
20113
|
meta = getAgent("cursor");
|
|
20107
20114
|
mode = "interactive";
|
|
20108
20115
|
os;
|
|
20109
|
-
constructor(
|
|
20110
|
-
this.os =
|
|
20116
|
+
constructor(os66) {
|
|
20117
|
+
this.os = os66;
|
|
20111
20118
|
}
|
|
20112
20119
|
async prepareLaunch() {
|
|
20113
20120
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -20324,10 +20331,10 @@ function aiderCredentialLocator() {
|
|
|
20324
20331
|
validate: validateNonEmptyCredential
|
|
20325
20332
|
};
|
|
20326
20333
|
}
|
|
20327
|
-
function aiderLoginLauncher(
|
|
20334
|
+
function aiderLoginLauncher(os66) {
|
|
20328
20335
|
return {
|
|
20329
20336
|
async ensureInstalled() {
|
|
20330
|
-
if (
|
|
20337
|
+
if (os66.findInPath("aider")) return true;
|
|
20331
20338
|
console.error(
|
|
20332
20339
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
20333
20340
|
);
|
|
@@ -20337,7 +20344,7 @@ function aiderLoginLauncher(os65) {
|
|
|
20337
20344
|
console.error(
|
|
20338
20345
|
"\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"
|
|
20339
20346
|
);
|
|
20340
|
-
return (0, import_node_child_process11.spawn)(
|
|
20347
|
+
return (0, import_node_child_process11.spawn)(os66.id === "win32" ? "cmd.exe" : "sh", os66.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
20341
20348
|
stdio: "ignore"
|
|
20342
20349
|
});
|
|
20343
20350
|
}
|
|
@@ -20426,14 +20433,14 @@ function defaultSdkDir() {
|
|
|
20426
20433
|
return resolveSdkDirViaRequire();
|
|
20427
20434
|
}
|
|
20428
20435
|
function resolveClaudeNativeBinary(deps = {}) {
|
|
20429
|
-
const
|
|
20436
|
+
const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
|
|
20430
20437
|
const platformKey = deps.platformKey ?? currentPlatformKey();
|
|
20431
20438
|
const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
|
|
20432
20439
|
if (!sdkDir) return null;
|
|
20433
20440
|
const scopeDir = import_path4.default.dirname(sdkDir);
|
|
20434
20441
|
const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
|
|
20435
20442
|
const candidate = import_path4.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
|
|
20436
|
-
return
|
|
20443
|
+
return existsSync30(candidate) ? candidate : null;
|
|
20437
20444
|
}
|
|
20438
20445
|
var realSleep = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
20439
20446
|
async function waitForClaudeNativeBinary(opts = {}) {
|
|
@@ -20515,18 +20522,18 @@ function augmentUserLocalBinPaths(deps = {}) {
|
|
|
20515
20522
|
env.PATH = [...additions, ...parts].join(p2.delimiter);
|
|
20516
20523
|
}
|
|
20517
20524
|
function resolveCursorAgentBinary(deps = {}) {
|
|
20518
|
-
const
|
|
20525
|
+
const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
|
|
20519
20526
|
const platform3 = deps.platform ?? process.platform;
|
|
20520
20527
|
const env = deps.env ?? process.env;
|
|
20521
20528
|
if (platform3 === "win32") {
|
|
20522
20529
|
const localAppData = env.LOCALAPPDATA;
|
|
20523
20530
|
if (!localAppData) return null;
|
|
20524
20531
|
const exe = import_path4.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
|
|
20525
|
-
return
|
|
20532
|
+
return existsSync30(exe) ? exe : null;
|
|
20526
20533
|
}
|
|
20527
20534
|
const home = deps.homedir ?? import_os4.default.homedir();
|
|
20528
20535
|
const unix = import_path4.default.posix.join(home, ".local", "bin", "cursor-agent");
|
|
20529
|
-
return
|
|
20536
|
+
return existsSync30(unix) ? unix : null;
|
|
20530
20537
|
}
|
|
20531
20538
|
async function waitForCursorAgent(opts = {}) {
|
|
20532
20539
|
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
@@ -20612,8 +20619,8 @@ var AiderRuntimeStrategy = class {
|
|
|
20612
20619
|
meta = getAgent("aider");
|
|
20613
20620
|
mode = "interactive";
|
|
20614
20621
|
os;
|
|
20615
|
-
constructor(
|
|
20616
|
-
this.os =
|
|
20622
|
+
constructor(os66) {
|
|
20623
|
+
this.os = os66;
|
|
20617
20624
|
}
|
|
20618
20625
|
async prepareLaunch() {
|
|
20619
20626
|
augmentUserLocalBinPaths();
|
|
@@ -20746,8 +20753,8 @@ function geminiCredentialLocator() {
|
|
|
20746
20753
|
function geminiLoginLauncher() {
|
|
20747
20754
|
return {
|
|
20748
20755
|
async ensureInstalled() {
|
|
20749
|
-
const
|
|
20750
|
-
return
|
|
20756
|
+
const os66 = createOsStrategy();
|
|
20757
|
+
return os66.findInPath("gemini") !== null;
|
|
20751
20758
|
},
|
|
20752
20759
|
launch() {
|
|
20753
20760
|
return (0, import_node_child_process12.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -20937,8 +20944,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
20937
20944
|
meta = getAgent("gemini");
|
|
20938
20945
|
mode = "interactive";
|
|
20939
20946
|
os;
|
|
20940
|
-
constructor(
|
|
20941
|
-
this.os =
|
|
20947
|
+
constructor(os66) {
|
|
20948
|
+
this.os = os66;
|
|
20942
20949
|
}
|
|
20943
20950
|
async prepareLaunch() {
|
|
20944
20951
|
const binary = this.os.findInPath("gemini");
|
|
@@ -21230,8 +21237,8 @@ var KimiRuntimeStrategy = class {
|
|
|
21230
21237
|
meta = getAgent("kimi");
|
|
21231
21238
|
mode = "interactive";
|
|
21232
21239
|
os;
|
|
21233
|
-
constructor(
|
|
21234
|
-
this.os =
|
|
21240
|
+
constructor(os66) {
|
|
21241
|
+
this.os = os66;
|
|
21235
21242
|
}
|
|
21236
21243
|
async prepareLaunch() {
|
|
21237
21244
|
const binary = this.os.findInPath("kimi");
|
|
@@ -21374,8 +21381,8 @@ var OpencodeRuntimeStrategy = class {
|
|
|
21374
21381
|
meta = getAgent("opencode");
|
|
21375
21382
|
mode = "interactive";
|
|
21376
21383
|
os;
|
|
21377
|
-
constructor(
|
|
21378
|
-
this.os =
|
|
21384
|
+
constructor(os66) {
|
|
21385
|
+
this.os = os66;
|
|
21379
21386
|
}
|
|
21380
21387
|
async prepareLaunch() {
|
|
21381
21388
|
const binary = this.os.findInPath("opencode");
|
|
@@ -21460,20 +21467,20 @@ var OpencodeRuntimeStrategy = class {
|
|
|
21460
21467
|
|
|
21461
21468
|
// src/agents/registry.ts
|
|
21462
21469
|
var runtimeBuilders = {
|
|
21463
|
-
claude: (
|
|
21464
|
-
codex: (
|
|
21465
|
-
coderabbit: (
|
|
21466
|
-
cursor: (
|
|
21467
|
-
aider: (
|
|
21468
|
-
gemini: (
|
|
21469
|
-
kimi: (
|
|
21470
|
-
opencode: (
|
|
21470
|
+
claude: (os66) => new ClaudeRuntimeStrategy(os66),
|
|
21471
|
+
codex: (os66) => new CodexRuntimeStrategy(os66),
|
|
21472
|
+
coderabbit: (os66) => new CoderabbitRuntimeStrategy(os66),
|
|
21473
|
+
cursor: (os66) => new CursorRuntimeStrategy(os66),
|
|
21474
|
+
aider: (os66) => new AiderRuntimeStrategy(os66),
|
|
21475
|
+
gemini: (os66) => new GeminiRuntimeStrategy(os66),
|
|
21476
|
+
kimi: (os66) => new KimiRuntimeStrategy(os66),
|
|
21477
|
+
opencode: (os66) => new OpencodeRuntimeStrategy(os66)
|
|
21471
21478
|
};
|
|
21472
21479
|
var deployBuilders = {
|
|
21473
21480
|
claude: () => new ClaudeDeployStrategy(),
|
|
21474
21481
|
codex: () => new CodexDeployStrategy()
|
|
21475
21482
|
};
|
|
21476
|
-
function createAgentStrategy(agent,
|
|
21483
|
+
function createAgentStrategy(agent, os66 = createOsStrategy()) {
|
|
21477
21484
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
21478
21485
|
throw new Error(
|
|
21479
21486
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -21483,10 +21490,10 @@ function createAgentStrategy(agent, os65 = createOsStrategy()) {
|
|
|
21483
21490
|
if (!build) {
|
|
21484
21491
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
21485
21492
|
}
|
|
21486
|
-
return build(
|
|
21493
|
+
return build(os66);
|
|
21487
21494
|
}
|
|
21488
|
-
function createInteractiveAgentStrategy(agent,
|
|
21489
|
-
const s = createAgentStrategy(agent,
|
|
21495
|
+
function createInteractiveAgentStrategy(agent, os66 = createOsStrategy()) {
|
|
21496
|
+
const s = createAgentStrategy(agent, os66);
|
|
21490
21497
|
if (s.mode !== "interactive") {
|
|
21491
21498
|
throw new Error(
|
|
21492
21499
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -22196,8 +22203,8 @@ function collectChangedFiles(cwd) {
|
|
|
22196
22203
|
}
|
|
22197
22204
|
return [...byPath.values()];
|
|
22198
22205
|
}
|
|
22199
|
-
function restoreCoderabbitOauthBlob(
|
|
22200
|
-
const dir = path38.join(
|
|
22206
|
+
function restoreCoderabbitOauthBlob(os66, value) {
|
|
22207
|
+
const dir = path38.join(os66.homeDir(), ".coderabbit");
|
|
22201
22208
|
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
22202
22209
|
let file = "auth.json";
|
|
22203
22210
|
let contents = value.trim();
|
|
@@ -22217,26 +22224,26 @@ function installFailureMessage(result) {
|
|
|
22217
22224
|
return result.error ?? "CodeRabbit CLI could not be installed";
|
|
22218
22225
|
}
|
|
22219
22226
|
async function configureCoderabbit(input, deps = {}) {
|
|
22220
|
-
const
|
|
22227
|
+
const os66 = deps.os ?? createOsStrategy();
|
|
22221
22228
|
const ensureInstalled = deps.ensureInstalled ?? ensureCoderabbitInstalled;
|
|
22222
22229
|
const isLoggedIn = deps.isLoggedIn ?? defaultIsLoggedIn;
|
|
22223
22230
|
const runOAuth = deps.runOAuthLogin ?? runCoderabbitOAuthLogin;
|
|
22224
22231
|
const snapshot = deps.snapshotDir ?? (() => snapshotCredentialDir());
|
|
22225
22232
|
const capture2 = deps.captureCredential ?? ((b) => diffCapturedCredential(b));
|
|
22226
22233
|
const loginWithApiKey = deps.loginWithApiKey ?? defaultLoginWithApiKey;
|
|
22227
|
-
const home =
|
|
22228
|
-
|
|
22229
|
-
|
|
22234
|
+
const home = os66.homeDir();
|
|
22235
|
+
os66.augmentPath(
|
|
22236
|
+
os66.id === "win32" ? [
|
|
22230
22237
|
path38.join(home, ".local", "bin"),
|
|
22231
22238
|
path38.join(process.env.APPDATA ?? path38.join(home, "AppData", "Roaming"), "npm"),
|
|
22232
22239
|
path38.join(home, "scoop", "shims")
|
|
22233
22240
|
] : [path38.join(home, ".local", "bin"), "/opt/homebrew/bin", "/usr/local/bin"]
|
|
22234
22241
|
);
|
|
22235
|
-
const installed2 =
|
|
22242
|
+
const installed2 = os66.findInPath("coderabbit") !== null;
|
|
22236
22243
|
const base = () => ({
|
|
22237
22244
|
action: input.action,
|
|
22238
22245
|
supported: true,
|
|
22239
|
-
installed:
|
|
22246
|
+
installed: os66.findInPath("coderabbit") !== null,
|
|
22240
22247
|
loggedIn: false
|
|
22241
22248
|
});
|
|
22242
22249
|
if (input.action === "status") {
|
|
@@ -22250,7 +22257,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
22250
22257
|
const key = (input.apiKey ?? "").trim();
|
|
22251
22258
|
if (!key) return { ...res2, error: "No API key provided" };
|
|
22252
22259
|
if (!res2.installed) {
|
|
22253
|
-
const inst = await ensureInstalled(
|
|
22260
|
+
const inst = await ensureInstalled(os66);
|
|
22254
22261
|
res2.installed = inst.ok;
|
|
22255
22262
|
if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
|
|
22256
22263
|
}
|
|
@@ -22274,7 +22281,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
22274
22281
|
}
|
|
22275
22282
|
if (!res2.installed) {
|
|
22276
22283
|
deps.onEvent?.({ kind: "installing" });
|
|
22277
|
-
const inst = await ensureInstalled(
|
|
22284
|
+
const inst = await ensureInstalled(os66);
|
|
22278
22285
|
res2.installed = inst.ok;
|
|
22279
22286
|
if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
|
|
22280
22287
|
}
|
|
@@ -22291,7 +22298,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
22291
22298
|
return { ...res2, loggedIn: true, linked: true };
|
|
22292
22299
|
}
|
|
22293
22300
|
try {
|
|
22294
|
-
restoreCoderabbitOauthBlob(
|
|
22301
|
+
restoreCoderabbitOauthBlob(os66, cred.credential);
|
|
22295
22302
|
} catch (err) {
|
|
22296
22303
|
return {
|
|
22297
22304
|
...res2,
|
|
@@ -22315,7 +22322,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
22315
22322
|
const res2 = base();
|
|
22316
22323
|
if (!installed2) {
|
|
22317
22324
|
deps.onEvent?.({ kind: "installing" });
|
|
22318
|
-
const inst = await ensureInstalled(
|
|
22325
|
+
const inst = await ensureInstalled(os66);
|
|
22319
22326
|
res2.installed = inst.ok;
|
|
22320
22327
|
if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
|
|
22321
22328
|
}
|
|
@@ -22355,7 +22362,7 @@ async function configureCoderabbit(input, deps = {}) {
|
|
|
22355
22362
|
}
|
|
22356
22363
|
const res = base();
|
|
22357
22364
|
if (!res.installed) {
|
|
22358
|
-
const inst = await ensureInstalled(
|
|
22365
|
+
const inst = await ensureInstalled(os66);
|
|
22359
22366
|
res.installed = inst.ok;
|
|
22360
22367
|
if (!inst.ok) return { ...res, error: installFailureMessage(inst) };
|
|
22361
22368
|
}
|
|
@@ -24628,6 +24635,145 @@ function inspectorClientSource(opts) {
|
|
|
24628
24635
|
redrawMarks();
|
|
24629
24636
|
}
|
|
24630
24637
|
|
|
24638
|
+
/**
|
|
24639
|
+
* Las marcas del AGENTE \u2014 la herramienta highlight_element.
|
|
24640
|
+
*
|
|
24641
|
+
* Van aparte de las del usuario a proposito: no se numeran, no se pueden
|
|
24642
|
+
* borrar desde el composer y no dependen de que el modo inspector este
|
|
24643
|
+
* encendido. Son el agente SE\xD1ALANDO algo, y el usuario las ve aunque no
|
|
24644
|
+
* haya tocado nada: un cursor que viaja hasta el elemento, lo centra en
|
|
24645
|
+
* pantalla y deja una caja con su etiqueta.
|
|
24646
|
+
*
|
|
24647
|
+
* Mismo anclaje que las marcas fijadas (coordenadas de documento), asi que
|
|
24648
|
+
* acompa\xF1an al scroll. Un selector que no encuentra nada no pinta nada: el
|
|
24649
|
+
* agente ya sabe por la herramienta que puede fallar.
|
|
24650
|
+
*/
|
|
24651
|
+
var AGENT = '#22d3ee';
|
|
24652
|
+
var agentMarks = [];
|
|
24653
|
+
var agentHost = null;
|
|
24654
|
+
var agentCursor = null;
|
|
24655
|
+
var agentStyle = null;
|
|
24656
|
+
var agentListening = false;
|
|
24657
|
+
|
|
24658
|
+
function ensureAgentStyle() {
|
|
24659
|
+
if (agentStyle && agentStyle.parentNode) return;
|
|
24660
|
+
agentStyle = document.createElement('style');
|
|
24661
|
+
agentStyle.setAttribute('data-codeam', 'agent-style');
|
|
24662
|
+
agentStyle.textContent =
|
|
24663
|
+
'@keyframes codeam-agent-pulse{0%{box-shadow:0 0 0 0 rgba(34,211,238,.55)}' +
|
|
24664
|
+
'70%{box-shadow:0 0 0 10px rgba(34,211,238,0)}100%{box-shadow:0 0 0 0 rgba(34,211,238,0)}}' +
|
|
24665
|
+
'@keyframes codeam-agent-in{from{opacity:0;transform:scale(1.06)}to{opacity:1;transform:scale(1)}}';
|
|
24666
|
+
(document.head || document.documentElement).appendChild(agentStyle);
|
|
24667
|
+
}
|
|
24668
|
+
|
|
24669
|
+
function ensureAgentCursor() {
|
|
24670
|
+
if (agentCursor && agentCursor.parentNode) return agentCursor;
|
|
24671
|
+
agentCursor = document.createElement('div');
|
|
24672
|
+
agentCursor.setAttribute('data-codeam', 'agent-cursor');
|
|
24673
|
+
agentCursor.style.cssText = [
|
|
24674
|
+
'position:fixed', 'pointer-events:none', 'z-index:2147483647',
|
|
24675
|
+
'left:' + Math.round(window.innerWidth / 2) + 'px', 'top:' + Math.round(window.innerHeight - 40) + 'px',
|
|
24676
|
+
'transition:left .6s cubic-bezier(.22,1,.36,1),top .6s cubic-bezier(.22,1,.36,1),opacity .3s',
|
|
24677
|
+
'opacity:0'
|
|
24678
|
+
].join(';');
|
|
24679
|
+
agentCursor.innerHTML =
|
|
24680
|
+
'<svg width="22" height="22" viewBox="0 0 24 24" style="display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))">' +
|
|
24681
|
+
'<path d="M4 2l15 8.5-6.6 1.6L9 18.5z" fill="' + AGENT + '" stroke="#000" stroke-width="1.2"/></svg>' +
|
|
24682
|
+
'<div style="margin:2px 0 0 14px;background:' + AGENT + ';color:#000;font:700 10px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;' +
|
|
24683
|
+
'padding:1px 6px;border-radius:8px;white-space:nowrap">Agent</div>';
|
|
24684
|
+
document.body.appendChild(agentCursor);
|
|
24685
|
+
return agentCursor;
|
|
24686
|
+
}
|
|
24687
|
+
|
|
24688
|
+
function redrawAgentMarks() {
|
|
24689
|
+
if (agentMarks.length === 0) {
|
|
24690
|
+
if (agentHost && agentHost.parentNode) agentHost.parentNode.removeChild(agentHost);
|
|
24691
|
+
agentHost = null;
|
|
24692
|
+
return;
|
|
24693
|
+
}
|
|
24694
|
+
if (!agentHost || !agentHost.parentNode) {
|
|
24695
|
+
agentHost = document.createElement('div');
|
|
24696
|
+
agentHost.setAttribute('data-codeam', 'agent-marks');
|
|
24697
|
+
agentHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
24698
|
+
document.body.appendChild(agentHost);
|
|
24699
|
+
}
|
|
24700
|
+
agentHost.innerHTML = '';
|
|
24701
|
+
var sx = window.scrollX || window.pageXOffset || 0;
|
|
24702
|
+
var sy = window.scrollY || window.pageYOffset || 0;
|
|
24703
|
+
for (var i = 0; i < agentMarks.length; i++) {
|
|
24704
|
+
var m = agentMarks[i];
|
|
24705
|
+
if (!m.el.isConnected) continue;
|
|
24706
|
+
var r = m.el.getBoundingClientRect();
|
|
24707
|
+
var box = document.createElement('div');
|
|
24708
|
+
box.setAttribute('data-codeam', 'agent-mark');
|
|
24709
|
+
box.style.cssText = [
|
|
24710
|
+
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
24711
|
+
'border:2px solid ' + AGENT, 'background:rgba(34,211,238,0.10)', 'border-radius:4px',
|
|
24712
|
+
'left:' + (r.left + sx - 3) + 'px', 'top:' + (r.top + sy - 3) + 'px',
|
|
24713
|
+
'width:' + (r.width + 6) + 'px', 'height:' + (r.height + 6) + 'px',
|
|
24714
|
+
'animation:codeam-agent-in .25s ease-out,codeam-agent-pulse 1.6s ease-out 3'
|
|
24715
|
+
].join(';');
|
|
24716
|
+
if (m.label) {
|
|
24717
|
+
var tag = document.createElement('div');
|
|
24718
|
+
tag.setAttribute('data-codeam', 'agent-mark-label');
|
|
24719
|
+
tag.style.cssText = [
|
|
24720
|
+
'position:absolute', 'left:-2px', (r.top >= 22 ? 'top:-22px' : 'bottom:-22px'),
|
|
24721
|
+
'background:' + AGENT, 'color:#000', 'font:700 11px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
24722
|
+
'padding:0 6px', 'border-radius:3px', 'white-space:nowrap', 'max-width:260px',
|
|
24723
|
+
'overflow:hidden', 'text-overflow:ellipsis'
|
|
24724
|
+
].join(';');
|
|
24725
|
+
tag.textContent = m.label;
|
|
24726
|
+
box.appendChild(tag);
|
|
24727
|
+
}
|
|
24728
|
+
agentHost.appendChild(box);
|
|
24729
|
+
}
|
|
24730
|
+
}
|
|
24731
|
+
|
|
24732
|
+
function listenAgentLayout() {
|
|
24733
|
+
if (agentListening) return;
|
|
24734
|
+
agentListening = true;
|
|
24735
|
+
window.addEventListener('scroll', redrawAgentMarks, true);
|
|
24736
|
+
window.addEventListener('resize', redrawAgentMarks);
|
|
24737
|
+
}
|
|
24738
|
+
|
|
24739
|
+
function agentHighlight(selector, labelText) {
|
|
24740
|
+
var el = null;
|
|
24741
|
+
try { el = document.querySelector(String(selector)); } catch (e) { el = null; }
|
|
24742
|
+
if (!el || !el.getBoundingClientRect) return false;
|
|
24743
|
+
ensureAgentStyle();
|
|
24744
|
+
listenAgentLayout();
|
|
24745
|
+
try { el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' }); } catch (e) { /* viejo */ }
|
|
24746
|
+
var cursor = ensureAgentCursor();
|
|
24747
|
+
// Tras el scroll suave: el cursor viaja al centro del elemento y, al
|
|
24748
|
+
// llegar, aparece la caja. El orden es lo que se lee como \xABel agente
|
|
24749
|
+
// lo esta se\xF1alando\xBB y no como un recuadro que salta.
|
|
24750
|
+
setTimeout(function () {
|
|
24751
|
+
var r = el.getBoundingClientRect();
|
|
24752
|
+
cursor.style.opacity = '1';
|
|
24753
|
+
cursor.style.left = Math.round(r.left + Math.min(r.width / 2, 40)) + 'px';
|
|
24754
|
+
cursor.style.top = Math.round(r.top + Math.min(r.height / 2, 24)) + 'px';
|
|
24755
|
+
setTimeout(function () {
|
|
24756
|
+
agentMarks.push({ el: el, label: labelText ? String(labelText).slice(0, 80) : '' });
|
|
24757
|
+
redrawAgentMarks();
|
|
24758
|
+
}, 620);
|
|
24759
|
+
}, 380);
|
|
24760
|
+
return true;
|
|
24761
|
+
}
|
|
24762
|
+
|
|
24763
|
+
function agentClear() {
|
|
24764
|
+
agentMarks = [];
|
|
24765
|
+
redrawAgentMarks();
|
|
24766
|
+
if (agentCursor && agentCursor.parentNode) agentCursor.parentNode.removeChild(agentCursor);
|
|
24767
|
+
agentCursor = null;
|
|
24768
|
+
if (agentStyle && agentStyle.parentNode) agentStyle.parentNode.removeChild(agentStyle);
|
|
24769
|
+
agentStyle = null;
|
|
24770
|
+
if (agentListening) {
|
|
24771
|
+
window.removeEventListener('scroll', redrawAgentMarks, true);
|
|
24772
|
+
window.removeEventListener('resize', redrawAgentMarks);
|
|
24773
|
+
agentListening = false;
|
|
24774
|
+
}
|
|
24775
|
+
}
|
|
24776
|
+
|
|
24631
24777
|
function enable(origin) {
|
|
24632
24778
|
if (enabled) return;
|
|
24633
24779
|
enabled = true;
|
|
@@ -24661,6 +24807,8 @@ function inspectorClientSource(opts) {
|
|
|
24661
24807
|
if (data.type === 'enable') enable(e.origin);
|
|
24662
24808
|
else if (data.type === 'disable') disable();
|
|
24663
24809
|
else if (data.type === 'marks' && data.ids) syncMarks(data.ids);
|
|
24810
|
+
else if (data.type === 'agent-highlight' && data.selector) agentHighlight(data.selector, data.label);
|
|
24811
|
+
else if (data.type === 'agent-clear') agentClear();
|
|
24664
24812
|
});
|
|
24665
24813
|
|
|
24666
24814
|
/**
|
|
@@ -24679,6 +24827,11 @@ function inspectorClientSource(opts) {
|
|
|
24679
24827
|
window.__codeamInspector = {
|
|
24680
24828
|
enable: function () { enable('react-native'); },
|
|
24681
24829
|
disable: disable,
|
|
24830
|
+
// La app movil ya llamaba \`marks\` al borrar un chip y no existia:
|
|
24831
|
+
// la marca se quedaba pintada en la pagina.
|
|
24832
|
+
marks: function (ids) { if (ids && ids.length !== undefined) syncMarks(ids); },
|
|
24833
|
+
highlight: function (selector, text) { return agentHighlight(selector, text); },
|
|
24834
|
+
clear: agentClear,
|
|
24682
24835
|
};
|
|
24683
24836
|
}
|
|
24684
24837
|
} catch (e) {
|
|
@@ -25518,11 +25671,11 @@ function resolveDoltInstallStrategy(platform3) {
|
|
|
25518
25671
|
}
|
|
25519
25672
|
var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
|
|
25520
25673
|
function doltPlatformTuple(platform3, arch2) {
|
|
25521
|
-
const
|
|
25674
|
+
const os66 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
|
|
25522
25675
|
const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
|
|
25523
25676
|
if (!a) return null;
|
|
25524
|
-
if (
|
|
25525
|
-
return `${
|
|
25677
|
+
if (os66 === "windows" && a !== "amd64") return null;
|
|
25678
|
+
return `${os66}-${a}`;
|
|
25526
25679
|
}
|
|
25527
25680
|
function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
|
|
25528
25681
|
const tuple = doltPlatformTuple(platform3, arch2);
|
|
@@ -26518,9 +26671,9 @@ async function configureBeads(action, ctx, deps) {
|
|
|
26518
26671
|
return { enabled: false, running: false };
|
|
26519
26672
|
}
|
|
26520
26673
|
const p3 = await deps.probe();
|
|
26521
|
-
const
|
|
26522
|
-
deps.emit({ type: "beads_status", state:
|
|
26523
|
-
return { enabled:
|
|
26674
|
+
const running3 = p3.serverUp && p3.bdAvailable;
|
|
26675
|
+
deps.emit({ type: "beads_status", state: running3 ? "enabled" : "disabled", running: running3, ...p3 });
|
|
26676
|
+
return { enabled: running3, running: running3, ...p3 };
|
|
26524
26677
|
}
|
|
26525
26678
|
if (action === "disable") {
|
|
26526
26679
|
deps.persist({ enabled: false });
|
|
@@ -26537,9 +26690,9 @@ async function configureBeads(action, ctx, deps) {
|
|
|
26537
26690
|
return { enabled: false, ...p2 };
|
|
26538
26691
|
}
|
|
26539
26692
|
await deps.startWatcher().catch(() => void 0);
|
|
26540
|
-
const
|
|
26541
|
-
deps.emit({ type: "beads_status", state: "enabled", running, ...p2 });
|
|
26542
|
-
return { enabled: true, running, ...p2 };
|
|
26693
|
+
const running2 = true;
|
|
26694
|
+
deps.emit({ type: "beads_status", state: "enabled", running: running2, ...p2 });
|
|
26695
|
+
return { enabled: true, running: running2, ...p2 };
|
|
26543
26696
|
}
|
|
26544
26697
|
|
|
26545
26698
|
// src/skills/configure.ts
|
|
@@ -27211,7 +27364,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
|
|
|
27211
27364
|
});
|
|
27212
27365
|
const token = ctx.pluginAuthToken;
|
|
27213
27366
|
void (async () => {
|
|
27214
|
-
const
|
|
27367
|
+
const os66 = createOsStrategy();
|
|
27215
27368
|
try {
|
|
27216
27369
|
const report = await reviewPullRequest(
|
|
27217
27370
|
{
|
|
@@ -27220,7 +27373,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
|
|
|
27220
27373
|
baseBranch: parsed.baseBranch
|
|
27221
27374
|
},
|
|
27222
27375
|
{
|
|
27223
|
-
runReview: (input) => new CoderabbitRuntimeStrategy(
|
|
27376
|
+
runReview: (input) => new CoderabbitRuntimeStrategy(os66).runOneShot(input),
|
|
27224
27377
|
runGh: (args2) => defaultRunGh(args2),
|
|
27225
27378
|
postReport: async (r) => {
|
|
27226
27379
|
if (!token) return;
|
|
@@ -27358,13 +27511,13 @@ function resolveGlobalNodeModulesDir(opts) {
|
|
|
27358
27511
|
var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
|
|
27359
27512
|
function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
|
|
27360
27513
|
if (!nodeModulesDir) return 0;
|
|
27361
|
-
const
|
|
27514
|
+
const readdirSync14 = deps?.readdirSync ?? fs51.readdirSync;
|
|
27362
27515
|
const statSync15 = deps?.statSync ?? fs51.statSync;
|
|
27363
27516
|
const rmSync9 = deps?.rmSync ?? fs51.rmSync;
|
|
27364
27517
|
let removed = 0;
|
|
27365
27518
|
let entries;
|
|
27366
27519
|
try {
|
|
27367
|
-
entries =
|
|
27520
|
+
entries = readdirSync14(nodeModulesDir);
|
|
27368
27521
|
} catch {
|
|
27369
27522
|
return 0;
|
|
27370
27523
|
}
|
|
@@ -27759,105 +27912,88 @@ async function runDetectOneShot(generate, timeoutMs = PREVIEW_DETECT_TIMEOUT_MS)
|
|
|
27759
27912
|
if (timer) clearTimeout(timer);
|
|
27760
27913
|
}
|
|
27761
27914
|
}
|
|
27762
|
-
|
|
27763
|
-
if (
|
|
27764
|
-
|
|
27765
|
-
|
|
27766
|
-
|
|
27767
|
-
|
|
27768
|
-
|
|
27915
|
+
function originPayload(payload, origin) {
|
|
27916
|
+
if (origin !== "agent") return payload;
|
|
27917
|
+
return { ...payload ?? {}, origin };
|
|
27918
|
+
}
|
|
27919
|
+
async function resolvePreviewDetection(args2) {
|
|
27920
|
+
const { ctx, runtime, pluginAuthToken, origin } = args2;
|
|
27921
|
+
const emit2 = (type, payload) => {
|
|
27769
27922
|
emitPreviewEvent({
|
|
27770
27923
|
sessionId: ctx.sessionId,
|
|
27771
27924
|
pluginId: ctx.pluginId,
|
|
27772
|
-
pluginAuthToken
|
|
27773
|
-
type
|
|
27774
|
-
payload:
|
|
27775
|
-
stage: "detection",
|
|
27776
|
-
message: `Preview detection isn't available on ${ctx.runtime.id} sessions yet \u2014 link a Claude or Codex agent.`
|
|
27777
|
-
}
|
|
27925
|
+
pluginAuthToken,
|
|
27926
|
+
type,
|
|
27927
|
+
payload: originPayload(payload, origin)
|
|
27778
27928
|
});
|
|
27779
|
-
|
|
27929
|
+
};
|
|
27930
|
+
if (typeof runtime.generateOneShot !== "function") {
|
|
27931
|
+
log.info("preview", `runtime ${runtime.id} has no generateOneShot \u2014 emitting unsupported`);
|
|
27932
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27933
|
+
stage: "detection",
|
|
27934
|
+
message: `Preview detection isn't available on ${runtime.id} sessions yet \u2014 link a Claude or Codex agent.`
|
|
27935
|
+
});
|
|
27936
|
+
return null;
|
|
27780
27937
|
}
|
|
27781
|
-
const
|
|
27782
|
-
const
|
|
27783
|
-
|
|
27784
|
-
|
|
27785
|
-
|
|
27786
|
-
|
|
27787
|
-
|
|
27788
|
-
|
|
27789
|
-
|
|
27790
|
-
|
|
27791
|
-
|
|
27792
|
-
|
|
27793
|
-
|
|
27794
|
-
|
|
27795
|
-
|
|
27796
|
-
|
|
27797
|
-
sessionId: ctx.sessionId,
|
|
27798
|
-
pluginId: ctx.pluginId,
|
|
27799
|
-
pluginAuthToken,
|
|
27800
|
-
type: USER_EVENTS.PREVIEW_DETECTION_PENDING
|
|
27938
|
+
const generateOneShot = runtime.generateOneShot.bind(runtime);
|
|
27939
|
+
const fromFile = await readPreviewConfig(process.cwd());
|
|
27940
|
+
if (fromFile) {
|
|
27941
|
+
log.info("preview", `detect: using .codeam/preview.json (${fromFile.framework})`);
|
|
27942
|
+
return fromFile;
|
|
27943
|
+
}
|
|
27944
|
+
emit2(USER_EVENTS.PREVIEW_DETECTION_PENDING);
|
|
27945
|
+
log.info("preview", "detect: invoking generateOneShot");
|
|
27946
|
+
const startedAt = Date.now();
|
|
27947
|
+
const { raw, timedOut, stderr } = await runDetectOneShot(generateOneShot);
|
|
27948
|
+
const tookMs = Date.now() - startedAt;
|
|
27949
|
+
if (timedOut) {
|
|
27950
|
+
log.info("preview", `detect: timed out after ${tookMs}ms \u2014 emitting preview_error`);
|
|
27951
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27952
|
+
stage: "detection",
|
|
27953
|
+
message: `Project detection timed out after ${Math.round(PREVIEW_DETECT_TIMEOUT_MS / 1e3)} s \u2014 the agent did not answer. Try again, or add a .codeam/preview.json override.`
|
|
27801
27954
|
});
|
|
27802
|
-
|
|
27803
|
-
|
|
27804
|
-
|
|
27805
|
-
|
|
27806
|
-
|
|
27807
|
-
|
|
27808
|
-
|
|
27809
|
-
|
|
27810
|
-
pluginId: ctx.pluginId,
|
|
27811
|
-
pluginAuthToken,
|
|
27812
|
-
type: USER_EVENTS.PREVIEW_ERROR,
|
|
27813
|
-
payload: {
|
|
27814
|
-
stage: "detection",
|
|
27815
|
-
message: `Project detection timed out after ${Math.round(PREVIEW_DETECT_TIMEOUT_MS / 1e3)} s \u2014 the agent did not answer. Try again, or add a .codeam/preview.json override.`
|
|
27816
|
-
}
|
|
27817
|
-
});
|
|
27818
|
-
return;
|
|
27819
|
-
}
|
|
27820
|
-
const detection = safeParseDetection(raw);
|
|
27821
|
-
if (!detection) {
|
|
27822
|
-
const failure = describeDetectionFailure(raw);
|
|
27823
|
-
log.info(
|
|
27824
|
-
"preview",
|
|
27825
|
-
`detect: failed after ${tookMs}ms reason=${failure?.reason ?? "unknown"}` + (failure?.missing ? ` missing=${failure.missing.join(",")}` : "") + `
|
|
27955
|
+
return null;
|
|
27956
|
+
}
|
|
27957
|
+
const detection = safeParseDetection(raw);
|
|
27958
|
+
if (!detection) {
|
|
27959
|
+
const failure = describeDetectionFailure(raw);
|
|
27960
|
+
log.info(
|
|
27961
|
+
"preview",
|
|
27962
|
+
`detect: failed after ${tookMs}ms reason=${failure?.reason ?? "unknown"}` + (failure?.missing ? ` missing=${failure.missing.join(",")}` : "") + `
|
|
27826
27963
|
--- salida cruda del agente (acotada) ---
|
|
27827
27964
|
${failure?.rawExcerpt ?? ""}`
|
|
27828
|
-
|
|
27829
|
-
|
|
27830
|
-
|
|
27831
|
-
|
|
27832
|
-
|
|
27833
|
-
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
27837
|
-
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
}
|
|
27843
|
-
if (isUnsupportedDetection(detection)) {
|
|
27844
|
-
log.info("preview", "detect: framework=unsupported");
|
|
27845
|
-
emitPreviewEvent({
|
|
27846
|
-
sessionId: ctx.sessionId,
|
|
27847
|
-
pluginId: ctx.pluginId,
|
|
27848
|
-
pluginAuthToken,
|
|
27849
|
-
type: USER_EVENTS.PREVIEW_ERROR,
|
|
27850
|
-
payload: {
|
|
27851
|
-
stage: "unsupported",
|
|
27852
|
-
message: detection.notes ?? "No dev server applies to this project."
|
|
27853
|
-
}
|
|
27854
|
-
});
|
|
27855
|
-
return;
|
|
27856
|
-
}
|
|
27857
|
-
log.info("preview", `detect: ${detection.framework} on :${detection.port} (took ${tookMs}ms)`);
|
|
27858
|
-
void writePreviewConfig(process.cwd(), detection).catch((err) => {
|
|
27859
|
-
log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
|
|
27965
|
+
);
|
|
27966
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27967
|
+
stage: "detection",
|
|
27968
|
+
// El mensaje sale del diagnostico: decir "JSON invalido" cuando el
|
|
27969
|
+
// agente no contesto manda al usuario a mirar un JSON que no existe.
|
|
27970
|
+
message: (failure?.reason === "no_output" ? describeOneShotAgentError(stderr) : null) ?? failure?.message ?? "Agent returned invalid JSON. Try again, or add a .codeam/preview.json override."
|
|
27971
|
+
});
|
|
27972
|
+
return null;
|
|
27973
|
+
}
|
|
27974
|
+
if (isUnsupportedDetection(detection)) {
|
|
27975
|
+
log.info("preview", "detect: framework=unsupported");
|
|
27976
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
27977
|
+
stage: "unsupported",
|
|
27978
|
+
message: detection.notes ?? "No dev server applies to this project."
|
|
27860
27979
|
});
|
|
27980
|
+
return null;
|
|
27981
|
+
}
|
|
27982
|
+
log.info("preview", `detect: ${detection.framework} on :${detection.port} (took ${tookMs}ms)`);
|
|
27983
|
+
void writePreviewConfig(process.cwd(), detection).catch((err) => {
|
|
27984
|
+
log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
|
|
27985
|
+
});
|
|
27986
|
+
return detection;
|
|
27987
|
+
}
|
|
27988
|
+
var requestPreviewDetectH = (ctx) => {
|
|
27989
|
+
if (!ctx.pluginAuthToken) {
|
|
27990
|
+
log.info("preview", "no pluginAuthToken \u2014 skipping detect");
|
|
27991
|
+
return;
|
|
27992
|
+
}
|
|
27993
|
+
const pluginAuthToken = ctx.pluginAuthToken;
|
|
27994
|
+
void (async () => {
|
|
27995
|
+
const detection = await resolvePreviewDetection({ ctx, runtime: ctx.runtime, pluginAuthToken });
|
|
27996
|
+
if (!detection) return;
|
|
27861
27997
|
emitPreviewEvent({
|
|
27862
27998
|
sessionId: ctx.sessionId,
|
|
27863
27999
|
pluginId: ctx.pluginId,
|
|
@@ -27940,19 +28076,21 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
27940
28076
|
log.info("preview", "start: no detection in payload");
|
|
27941
28077
|
return;
|
|
27942
28078
|
}
|
|
27943
|
-
startPreviewFromDetection(ctx, rawDetection, ctx.pluginAuthToken);
|
|
28079
|
+
void startPreviewFromDetection(ctx, rawDetection, ctx.pluginAuthToken);
|
|
27944
28080
|
};
|
|
27945
|
-
function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
|
|
28081
|
+
function startPreviewFromDetection(ctx, detection, pluginAuthToken, opts = {}) {
|
|
27946
28082
|
const emit2 = (type, payload) => {
|
|
28083
|
+
const tagged = originPayload(payload, opts.origin) ?? {};
|
|
28084
|
+
opts.onEvent?.(type, tagged);
|
|
27947
28085
|
emitPreviewEvent({
|
|
27948
28086
|
sessionId: ctx.sessionId,
|
|
27949
28087
|
pluginId: ctx.pluginId,
|
|
27950
28088
|
pluginAuthToken,
|
|
27951
28089
|
type,
|
|
27952
|
-
payload
|
|
28090
|
+
payload: tagged
|
|
27953
28091
|
});
|
|
27954
28092
|
};
|
|
27955
|
-
runPreviewStart({
|
|
28093
|
+
return runPreviewStart({
|
|
27956
28094
|
sessionId: ctx.sessionId,
|
|
27957
28095
|
detection,
|
|
27958
28096
|
cwd: process.cwd(),
|
|
@@ -27983,7 +28121,7 @@ function maybeAttachBuildHeal(ctx, pluginAuthToken) {
|
|
|
27983
28121
|
if (!activePreviews.has(ctx.sessionId)) return;
|
|
27984
28122
|
await killPreview(ctx.sessionId);
|
|
27985
28123
|
await new Promise((r) => setTimeout(r, 150));
|
|
27986
|
-
startPreviewFromDetection(ctx, preview.detection, pluginAuthToken);
|
|
28124
|
+
void startPreviewFromDetection(ctx, preview.detection, pluginAuthToken);
|
|
27987
28125
|
})();
|
|
27988
28126
|
},
|
|
27989
28127
|
notify: (message) => {
|
|
@@ -28029,7 +28167,7 @@ var previewRestartH = async (ctx, cmd) => {
|
|
|
28029
28167
|
}
|
|
28030
28168
|
await killPreview(ctx.sessionId);
|
|
28031
28169
|
await new Promise((r) => setTimeout(r, 150));
|
|
28032
|
-
startPreviewFromDetection(ctx, preview.detection, ctx.pluginAuthToken);
|
|
28170
|
+
void startPreviewFromDetection(ctx, preview.detection, ctx.pluginAuthToken);
|
|
28033
28171
|
await ctx.relay.sendResult(cmd.id, "completed", { restarted: true });
|
|
28034
28172
|
};
|
|
28035
28173
|
var savePreviewConfigH = (_ctx, _cmd, parsed) => {
|
|
@@ -28402,11 +28540,11 @@ function resolveTokenValue(args2) {
|
|
|
28402
28540
|
}
|
|
28403
28541
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
28404
28542
|
if (fileFlag) {
|
|
28405
|
-
const
|
|
28543
|
+
const path97 = fileFlag.slice("--token-file=".length);
|
|
28406
28544
|
try {
|
|
28407
|
-
const content = fs52.readFileSync(
|
|
28408
|
-
if (content.length === 0) fail(`--token-file ${
|
|
28409
|
-
rmIfExistsQuiet(
|
|
28545
|
+
const content = fs52.readFileSync(path97, "utf8").trim();
|
|
28546
|
+
if (content.length === 0) fail(`--token-file ${path97} is empty`);
|
|
28547
|
+
rmIfExistsQuiet(path97);
|
|
28410
28548
|
return content;
|
|
28411
28549
|
} catch (err) {
|
|
28412
28550
|
fail(`Could not read --token-file: ${err.message}`);
|
|
@@ -29338,32 +29476,200 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
|
|
|
29338
29476
|
return null;
|
|
29339
29477
|
}
|
|
29340
29478
|
|
|
29479
|
+
// src/commands/host/workspace.ts
|
|
29480
|
+
var fs53 = __toESM(require("fs"));
|
|
29481
|
+
var os41 = __toESM(require("os"));
|
|
29482
|
+
var path62 = __toESM(require("path"));
|
|
29483
|
+
var import_node_child_process21 = require("child_process");
|
|
29484
|
+
var import_node_util5 = require("util");
|
|
29485
|
+
var execFileP5 = (0, import_node_util5.promisify)(import_node_child_process21.execFile);
|
|
29486
|
+
function isAbsolutePathTarget(target) {
|
|
29487
|
+
return path62.isAbsolute(target);
|
|
29488
|
+
}
|
|
29489
|
+
function selfHostedWorkspaceRoot() {
|
|
29490
|
+
return path62.join(os41.homedir(), ".codeam", "self-hosted");
|
|
29491
|
+
}
|
|
29492
|
+
function deployIdFromWorkspace(cwd) {
|
|
29493
|
+
if (!cwd) return null;
|
|
29494
|
+
const root = selfHostedWorkspaceRoot();
|
|
29495
|
+
const resolved = path62.resolve(cwd);
|
|
29496
|
+
const rel = path62.relative(root, resolved);
|
|
29497
|
+
if (!rel || rel.startsWith("..") || path62.isAbsolute(rel)) return null;
|
|
29498
|
+
const parts = rel.split(path62.sep).filter(Boolean);
|
|
29499
|
+
if (parts.length !== 1) return null;
|
|
29500
|
+
return parts[0];
|
|
29501
|
+
}
|
|
29502
|
+
function nonInteractiveGitEnv() {
|
|
29503
|
+
return {
|
|
29504
|
+
...process.env,
|
|
29505
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
29506
|
+
GIT_ASKPASS: "",
|
|
29507
|
+
GCM_INTERACTIVE: "never"
|
|
29508
|
+
};
|
|
29509
|
+
}
|
|
29510
|
+
function githubOwnerRepo(repoRef) {
|
|
29511
|
+
const trimmed = repoRef.trim();
|
|
29512
|
+
const shorthand = /^([^/\s]+)\/([^/\s]+?)(?:\.git)?$/.exec(trimmed);
|
|
29513
|
+
if (shorthand && !/^https?:\/\//.test(trimmed) && !trimmed.startsWith("git@")) {
|
|
29514
|
+
return { owner: shorthand[1], repo: shorthand[2] };
|
|
29515
|
+
}
|
|
29516
|
+
const httpsMatch = /^https?:\/\/github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
29517
|
+
if (httpsMatch) return { owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
29518
|
+
return null;
|
|
29519
|
+
}
|
|
29520
|
+
function gitlabProjectPath(repoRef) {
|
|
29521
|
+
const trimmed = repoRef.trim();
|
|
29522
|
+
const https9 = /^https?:\/\/gitlab\.com\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
29523
|
+
if (https9) return https9[1];
|
|
29524
|
+
if (!/^https?:\/\//.test(trimmed) && !trimmed.startsWith("git@") && trimmed.includes("/")) {
|
|
29525
|
+
return trimmed.replace(/\.git$/, "");
|
|
29526
|
+
}
|
|
29527
|
+
return null;
|
|
29528
|
+
}
|
|
29529
|
+
function repoCloneUrl(repoRef, cloneToken, provider = "github") {
|
|
29530
|
+
const trimmed = repoRef.trim();
|
|
29531
|
+
if (provider === "gitlab") {
|
|
29532
|
+
const glPath = gitlabProjectPath(trimmed);
|
|
29533
|
+
if (glPath) {
|
|
29534
|
+
return cloneToken ? `https://oauth2:${cloneToken}@gitlab.com/${glPath}.git` : `https://gitlab.com/${glPath}.git`;
|
|
29535
|
+
}
|
|
29536
|
+
if (/^https?:\/\//.test(trimmed) || trimmed.startsWith("git@")) return trimmed;
|
|
29537
|
+
}
|
|
29538
|
+
if (cloneToken) {
|
|
29539
|
+
const gh = githubOwnerRepo(trimmed);
|
|
29540
|
+
if (gh) {
|
|
29541
|
+
return `https://x-access-token:${cloneToken}@github.com/${gh.owner}/${gh.repo}.git`;
|
|
29542
|
+
}
|
|
29543
|
+
}
|
|
29544
|
+
if (/^https?:\/\//.test(trimmed) || trimmed.startsWith("git@")) return trimmed;
|
|
29545
|
+
return `https://github.com/${trimmed.replace(/\.git$/, "")}.git`;
|
|
29546
|
+
}
|
|
29547
|
+
function maskCloneUrl(url2) {
|
|
29548
|
+
return url2.replace(/(https?:\/\/)[^@/]+@/, "$1***@");
|
|
29549
|
+
}
|
|
29550
|
+
async function fetchGithubIdentity(token) {
|
|
29551
|
+
try {
|
|
29552
|
+
const res = await fetch("https://api.github.com/user", {
|
|
29553
|
+
headers: {
|
|
29554
|
+
Authorization: `Bearer ${token}`,
|
|
29555
|
+
"User-Agent": "codeam-cli",
|
|
29556
|
+
Accept: "application/vnd.github+json"
|
|
29557
|
+
}
|
|
29558
|
+
});
|
|
29559
|
+
if (!res.ok) return null;
|
|
29560
|
+
const body = await res.json();
|
|
29561
|
+
return { login: body.login, email: body.email ?? void 0 };
|
|
29562
|
+
} catch {
|
|
29563
|
+
return null;
|
|
29564
|
+
}
|
|
29565
|
+
}
|
|
29566
|
+
async function configureGitCredentials(dest, repoRef, cloneToken, provider = "github") {
|
|
29567
|
+
const isGitlab = provider === "gitlab";
|
|
29568
|
+
if (isGitlab ? !gitlabProjectPath(repoRef.trim()) : !githubOwnerRepo(repoRef.trim())) return;
|
|
29569
|
+
if (!cloneToken) return;
|
|
29570
|
+
const credFile = path62.join(dest, ".git", "codeam-credentials");
|
|
29571
|
+
const credLine = isGitlab ? `https://oauth2:${cloneToken}@gitlab.com
|
|
29572
|
+
` : `https://x-access-token:${cloneToken}@github.com
|
|
29573
|
+
`;
|
|
29574
|
+
fs53.writeFileSync(credFile, credLine, { mode: 384 });
|
|
29575
|
+
restrictToOwner(credFile);
|
|
29576
|
+
const env = nonInteractiveGitEnv();
|
|
29577
|
+
const git2 = (args2) => execFileP5("git", ["-C", dest, ...args2], { timeout: 3e4, env });
|
|
29578
|
+
const credFilePosix = credFile.split(path62.sep).join("/");
|
|
29579
|
+
await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
|
|
29580
|
+
});
|
|
29581
|
+
await git2([
|
|
29582
|
+
"config",
|
|
29583
|
+
"--local",
|
|
29584
|
+
"--add",
|
|
29585
|
+
"credential.helper",
|
|
29586
|
+
`store --file=${credFilePosix}`
|
|
29587
|
+
]).catch(() => {
|
|
29588
|
+
});
|
|
29589
|
+
await git2(["remote", "set-url", "origin", repoCloneUrl(repoRef, void 0, provider)]).catch(() => {
|
|
29590
|
+
});
|
|
29591
|
+
const hasIdentity = await git2(["config", "user.email"]).then(() => true).catch(() => false);
|
|
29592
|
+
if (!hasIdentity) {
|
|
29593
|
+
const who = isGitlab ? null : await fetchGithubIdentity(cloneToken);
|
|
29594
|
+
const login = who?.login ?? "CodeAgent";
|
|
29595
|
+
await git2(["config", "--local", "user.name", login]).catch(() => {
|
|
29596
|
+
});
|
|
29597
|
+
const email = who?.email ?? (isGitlab ? "agent@codeagent-mobile.com" : `${login}@users.noreply.github.com`);
|
|
29598
|
+
await git2(["config", "--local", "user.email", email]).catch(() => {
|
|
29599
|
+
});
|
|
29600
|
+
}
|
|
29601
|
+
}
|
|
29602
|
+
function maskToken(text, cloneToken) {
|
|
29603
|
+
const masked = maskCloneUrl(text);
|
|
29604
|
+
if (cloneToken && cloneToken.length > 0) {
|
|
29605
|
+
return masked.split(cloneToken).join("***");
|
|
29606
|
+
}
|
|
29607
|
+
return masked;
|
|
29608
|
+
}
|
|
29609
|
+
async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "github", branch) {
|
|
29610
|
+
if (isAbsolutePathTarget(repoOrPath)) {
|
|
29611
|
+
if (!fs53.existsSync(repoOrPath)) {
|
|
29612
|
+
throw new Error(`deploy target path does not exist: ${repoOrPath}`);
|
|
29613
|
+
}
|
|
29614
|
+
return repoOrPath;
|
|
29615
|
+
}
|
|
29616
|
+
const dest = path62.join(selfHostedWorkspaceRoot(), deployId);
|
|
29617
|
+
if (fs53.existsSync(path62.join(dest, ".git"))) {
|
|
29618
|
+
if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
|
|
29619
|
+
return dest;
|
|
29620
|
+
}
|
|
29621
|
+
fs53.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
|
|
29622
|
+
const cloneUrl = repoCloneUrl(repoOrPath, cloneToken, provider);
|
|
29623
|
+
const cloneArgs = branch ? ["clone", "--depth", "1", "--branch", branch, cloneUrl, dest] : ["clone", "--depth", "1", cloneUrl, dest];
|
|
29624
|
+
try {
|
|
29625
|
+
await execFileP5("git", cloneArgs, {
|
|
29626
|
+
timeout: 12e4,
|
|
29627
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
29628
|
+
env: nonInteractiveGitEnv()
|
|
29629
|
+
});
|
|
29630
|
+
} catch (err) {
|
|
29631
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
29632
|
+
throw new Error(`git clone failed for ${maskCloneUrl(cloneUrl)}: ${maskToken(reason, cloneToken)}`);
|
|
29633
|
+
}
|
|
29634
|
+
if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
|
|
29635
|
+
return dest;
|
|
29636
|
+
}
|
|
29637
|
+
|
|
29341
29638
|
// src/agents/acp/runner.ts
|
|
29342
|
-
var
|
|
29343
|
-
var
|
|
29344
|
-
var
|
|
29345
|
-
var
|
|
29639
|
+
var import_node_crypto11 = require("crypto");
|
|
29640
|
+
var fs71 = __toESM(require("fs"));
|
|
29641
|
+
var os55 = __toESM(require("os"));
|
|
29642
|
+
var path82 = __toESM(require("path"));
|
|
29346
29643
|
|
|
29347
29644
|
// src/lib/provider-routing.ts
|
|
29645
|
+
var fs55 = __toESM(require("fs"));
|
|
29646
|
+
var os43 = __toESM(require("os"));
|
|
29647
|
+
var path64 = __toESM(require("path"));
|
|
29648
|
+
|
|
29649
|
+
// src/commands/host/house-proxy-config.ts
|
|
29348
29650
|
var fs54 = __toESM(require("fs"));
|
|
29349
29651
|
var os42 = __toESM(require("os"));
|
|
29350
29652
|
var path63 = __toESM(require("path"));
|
|
29351
|
-
|
|
29352
|
-
// src/commands/host/house-proxy-config.ts
|
|
29353
|
-
var fs53 = __toESM(require("fs"));
|
|
29354
|
-
var os41 = __toESM(require("os"));
|
|
29355
|
-
var path62 = __toESM(require("path"));
|
|
29356
29653
|
function houseProxyConfigPath() {
|
|
29357
|
-
return
|
|
29654
|
+
return path63.join(os42.homedir(), ".codeam", "house-proxy.json");
|
|
29655
|
+
}
|
|
29656
|
+
var DEPLOY_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
29657
|
+
function deployHouseProxyConfigPath(deployId) {
|
|
29658
|
+
if (!DEPLOY_ID_RE.test(deployId) || deployId.includes("..")) return null;
|
|
29659
|
+
return path63.join(os42.homedir(), ".codeam", "house-proxy", `${deployId}.json`);
|
|
29660
|
+
}
|
|
29661
|
+
function writeJson0600(file, value) {
|
|
29662
|
+
fs54.mkdirSync(path63.dirname(file), { recursive: true, mode: 448 });
|
|
29663
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
29664
|
+
fs54.writeFileSync(tmp, JSON.stringify(value, null, 2), { encoding: "utf8", mode: 384 });
|
|
29665
|
+
fs54.renameSync(tmp, file);
|
|
29666
|
+
restrictToOwner(file);
|
|
29358
29667
|
}
|
|
29359
|
-
function persistHouseProxyConfig(config) {
|
|
29668
|
+
function persistHouseProxyConfig(config, deployId) {
|
|
29360
29669
|
try {
|
|
29361
|
-
const
|
|
29362
|
-
|
|
29363
|
-
|
|
29364
|
-
fs53.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
|
|
29365
|
-
fs53.renameSync(tmp, file);
|
|
29366
|
-
restrictToOwner(file);
|
|
29670
|
+
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
29671
|
+
if (perDeploy) writeJson0600(perDeploy, config);
|
|
29672
|
+
writeJson0600(houseProxyConfigPath(), config);
|
|
29367
29673
|
} catch (err) {
|
|
29368
29674
|
log.warn(
|
|
29369
29675
|
"host-agent",
|
|
@@ -29371,18 +29677,23 @@ function persistHouseProxyConfig(config) {
|
|
|
29371
29677
|
);
|
|
29372
29678
|
}
|
|
29373
29679
|
}
|
|
29374
|
-
function clearHouseProxyConfig() {
|
|
29680
|
+
function clearHouseProxyConfig(deployId) {
|
|
29375
29681
|
try {
|
|
29376
|
-
|
|
29682
|
+
fs54.rmSync(houseProxyConfigPath(), { force: true });
|
|
29683
|
+
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
29684
|
+
if (perDeploy) writeJson0600(perDeploy, { none: true });
|
|
29377
29685
|
} catch {
|
|
29378
29686
|
}
|
|
29379
29687
|
}
|
|
29380
|
-
function readHouseProxyChildEnv() {
|
|
29688
|
+
function readHouseProxyChildEnv(deployId) {
|
|
29381
29689
|
try {
|
|
29382
|
-
const
|
|
29690
|
+
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
29691
|
+
const file = perDeploy && fs54.existsSync(perDeploy) ? perDeploy : houseProxyConfigPath();
|
|
29692
|
+
const raw = fs54.readFileSync(file, "utf8");
|
|
29383
29693
|
const parsed = JSON.parse(raw);
|
|
29384
29694
|
if (typeof parsed !== "object" || parsed === null) return {};
|
|
29385
29695
|
const o = parsed;
|
|
29696
|
+
if (o.none === true) return {};
|
|
29386
29697
|
if (typeof o.baseUrl !== "string" || !o.baseUrl) return {};
|
|
29387
29698
|
if (typeof o.token !== "string" || !o.token) return {};
|
|
29388
29699
|
return buildHouseProxyChildEnv({
|
|
@@ -29505,15 +29816,15 @@ function redactUrlToOrigin(raw) {
|
|
|
29505
29816
|
}
|
|
29506
29817
|
}
|
|
29507
29818
|
function readOpencodeProviderOrigins(opts = {}) {
|
|
29508
|
-
const home = opts.homeDir ??
|
|
29509
|
-
const readFile7 = opts.readFile ?? ((f) =>
|
|
29819
|
+
const home = opts.homeDir ?? os43.homedir();
|
|
29820
|
+
const readFile7 = opts.readFile ?? ((f) => fs55.readFileSync(f, "utf8"));
|
|
29510
29821
|
const candidates = [];
|
|
29511
29822
|
if (opts.cwd) {
|
|
29512
|
-
candidates.push(
|
|
29823
|
+
candidates.push(path64.join(opts.cwd, "opencode.json"), path64.join(opts.cwd, "opencode.jsonc"));
|
|
29513
29824
|
}
|
|
29514
29825
|
candidates.push(
|
|
29515
|
-
|
|
29516
|
-
|
|
29826
|
+
path64.join(home, ".config", "opencode", "opencode.json"),
|
|
29827
|
+
path64.join(home, ".config", "opencode", "opencode.jsonc")
|
|
29517
29828
|
);
|
|
29518
29829
|
const out2 = [];
|
|
29519
29830
|
const seen2 = /* @__PURE__ */ new Set();
|
|
@@ -29620,9 +29931,9 @@ function noteProviderBillingSignal(opts) {
|
|
|
29620
29931
|
}
|
|
29621
29932
|
|
|
29622
29933
|
// src/services/history.service.ts
|
|
29623
|
-
var
|
|
29624
|
-
var
|
|
29625
|
-
var
|
|
29934
|
+
var fs56 = __toESM(require("fs"));
|
|
29935
|
+
var path65 = __toESM(require("path"));
|
|
29936
|
+
var os44 = __toESM(require("os"));
|
|
29626
29937
|
var https6 = __toESM(require("https"));
|
|
29627
29938
|
var http9 = __toESM(require("http"));
|
|
29628
29939
|
var import_zod2 = require("zod");
|
|
@@ -29683,7 +29994,7 @@ function parseJsonl(filePath) {
|
|
|
29683
29994
|
const messages = [];
|
|
29684
29995
|
let raw;
|
|
29685
29996
|
try {
|
|
29686
|
-
raw =
|
|
29997
|
+
raw = fs56.readFileSync(filePath, "utf8");
|
|
29687
29998
|
} catch (err) {
|
|
29688
29999
|
if (err.code !== "ENOENT") {
|
|
29689
30000
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -29837,7 +30148,7 @@ var HistoryService = class _HistoryService {
|
|
|
29837
30148
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
29838
30149
|
}
|
|
29839
30150
|
get projectDir() {
|
|
29840
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
30151
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path65.join(os44.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
29841
30152
|
}
|
|
29842
30153
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
29843
30154
|
setCurrentConversationId(id) {
|
|
@@ -29849,7 +30160,7 @@ var HistoryService = class _HistoryService {
|
|
|
29849
30160
|
/** Return the current message count in the active conversation. */
|
|
29850
30161
|
getCurrentMessageCount() {
|
|
29851
30162
|
if (!this.currentConversationId) return 0;
|
|
29852
|
-
const filePath =
|
|
30163
|
+
const filePath = path65.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
29853
30164
|
return parseJsonl(filePath).length;
|
|
29854
30165
|
}
|
|
29855
30166
|
/**
|
|
@@ -29860,7 +30171,7 @@ var HistoryService = class _HistoryService {
|
|
|
29860
30171
|
const deadline = Date.now() + timeoutMs;
|
|
29861
30172
|
while (Date.now() < deadline) {
|
|
29862
30173
|
if (!this.currentConversationId) return null;
|
|
29863
|
-
const filePath =
|
|
30174
|
+
const filePath = path65.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
29864
30175
|
const messages = parseJsonl(filePath);
|
|
29865
30176
|
if (messages.length > previousCount) {
|
|
29866
30177
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -29886,16 +30197,16 @@ var HistoryService = class _HistoryService {
|
|
|
29886
30197
|
const dir = this.projectDir;
|
|
29887
30198
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
29888
30199
|
try {
|
|
29889
|
-
const files =
|
|
30200
|
+
const files = fs56.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
29890
30201
|
try {
|
|
29891
|
-
const stat3 =
|
|
30202
|
+
const stat3 = fs56.statSync(path65.join(dir, e.name));
|
|
29892
30203
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
29893
30204
|
} catch {
|
|
29894
30205
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
29895
30206
|
}
|
|
29896
30207
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
29897
30208
|
if (files.length > 0) {
|
|
29898
|
-
this.currentConversationId =
|
|
30209
|
+
this.currentConversationId = path65.basename(files[0].name, ".jsonl");
|
|
29899
30210
|
}
|
|
29900
30211
|
} catch {
|
|
29901
30212
|
}
|
|
@@ -29929,13 +30240,13 @@ var HistoryService = class _HistoryService {
|
|
|
29929
30240
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
29930
30241
|
let entries;
|
|
29931
30242
|
try {
|
|
29932
|
-
entries =
|
|
30243
|
+
entries = fs56.readdirSync(dir, { withFileTypes: true });
|
|
29933
30244
|
} catch {
|
|
29934
30245
|
return null;
|
|
29935
30246
|
}
|
|
29936
30247
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
29937
30248
|
try {
|
|
29938
|
-
const stat3 =
|
|
30249
|
+
const stat3 = fs56.statSync(path65.join(dir, e.name));
|
|
29939
30250
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
29940
30251
|
} catch {
|
|
29941
30252
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -29944,12 +30255,12 @@ var HistoryService = class _HistoryService {
|
|
|
29944
30255
|
if (files.length === 0) return null;
|
|
29945
30256
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
29946
30257
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
29947
|
-
return this.extractUsageFromFile(
|
|
30258
|
+
return this.extractUsageFromFile(path65.join(dir, targetFile));
|
|
29948
30259
|
}
|
|
29949
30260
|
extractUsageFromFile(filePath) {
|
|
29950
30261
|
let raw;
|
|
29951
30262
|
try {
|
|
29952
|
-
raw =
|
|
30263
|
+
raw = fs56.readFileSync(filePath, "utf8");
|
|
29953
30264
|
} catch {
|
|
29954
30265
|
return null;
|
|
29955
30266
|
}
|
|
@@ -30001,9 +30312,9 @@ var HistoryService = class _HistoryService {
|
|
|
30001
30312
|
let totalCost = 0;
|
|
30002
30313
|
let files;
|
|
30003
30314
|
try {
|
|
30004
|
-
files =
|
|
30315
|
+
files = fs56.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
30005
30316
|
try {
|
|
30006
|
-
return
|
|
30317
|
+
return fs56.statSync(path65.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
30007
30318
|
} catch {
|
|
30008
30319
|
return false;
|
|
30009
30320
|
}
|
|
@@ -30014,7 +30325,7 @@ var HistoryService = class _HistoryService {
|
|
|
30014
30325
|
for (const file of files) {
|
|
30015
30326
|
let raw;
|
|
30016
30327
|
try {
|
|
30017
|
-
raw =
|
|
30328
|
+
raw = fs56.readFileSync(path65.join(projectDir, file), "utf8");
|
|
30018
30329
|
} catch {
|
|
30019
30330
|
continue;
|
|
30020
30331
|
}
|
|
@@ -30093,7 +30404,7 @@ var HistoryService = class _HistoryService {
|
|
|
30093
30404
|
if (this.runtime.resolveHistoryFile) {
|
|
30094
30405
|
return this.runtime.resolveHistoryFile(this.cwd, sessionId);
|
|
30095
30406
|
}
|
|
30096
|
-
return
|
|
30407
|
+
return path65.join(this.projectDir, `${sessionId}.jsonl`);
|
|
30097
30408
|
}
|
|
30098
30409
|
/**
|
|
30099
30410
|
* Parse a conversation's messages from disk, agent-aware. Claude uses the
|
|
@@ -30131,7 +30442,7 @@ var HistoryService = class _HistoryService {
|
|
|
30131
30442
|
};
|
|
30132
30443
|
});
|
|
30133
30444
|
}
|
|
30134
|
-
return parseJsonl(
|
|
30445
|
+
return parseJsonl(path65.join(this.projectDir, `${sessionId}.jsonl`));
|
|
30135
30446
|
}
|
|
30136
30447
|
/** One in-flight full upload per conversation — the baton mirror and a
|
|
30137
30448
|
* `get_conversation` used to upload the same transcript concurrently. */
|
|
@@ -30213,7 +30524,7 @@ var HistoryService = class _HistoryService {
|
|
|
30213
30524
|
if (!filePath) return false;
|
|
30214
30525
|
let mtimeMs;
|
|
30215
30526
|
try {
|
|
30216
|
-
mtimeMs =
|
|
30527
|
+
mtimeMs = fs56.statSync(filePath).mtimeMs;
|
|
30217
30528
|
} catch {
|
|
30218
30529
|
return false;
|
|
30219
30530
|
}
|
|
@@ -30287,11 +30598,11 @@ var HistoryService = class _HistoryService {
|
|
|
30287
30598
|
};
|
|
30288
30599
|
|
|
30289
30600
|
// src/agents/acp/client.ts
|
|
30290
|
-
var
|
|
30291
|
-
var
|
|
30601
|
+
var import_node_child_process22 = require("child_process");
|
|
30602
|
+
var fs57 = __toESM(require("fs/promises"));
|
|
30292
30603
|
var fsSync = __toESM(require("fs"));
|
|
30293
|
-
var
|
|
30294
|
-
var
|
|
30604
|
+
var os46 = __toESM(require("os"));
|
|
30605
|
+
var path67 = __toESM(require("path"));
|
|
30295
30606
|
var import_node_stream = require("stream");
|
|
30296
30607
|
|
|
30297
30608
|
// ../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
@@ -34317,8 +34628,8 @@ function createIdleTimeout(idleMs, makeError, activeIdleMs = idleMs) {
|
|
|
34317
34628
|
}
|
|
34318
34629
|
|
|
34319
34630
|
// src/agents/acp/internal-paths.ts
|
|
34320
|
-
var
|
|
34321
|
-
var
|
|
34631
|
+
var path66 = __toESM(require("path"));
|
|
34632
|
+
var os45 = __toESM(require("os"));
|
|
34322
34633
|
var INTERNAL_TOKENS = [".codeam", "house-claude"];
|
|
34323
34634
|
var PROSE_ONLY_TOOL_KINDS = /* @__PURE__ */ new Set(["think", "switch_mode"]);
|
|
34324
34635
|
function isProseOnlyToolKind(kind) {
|
|
@@ -34330,13 +34641,13 @@ function textReferencesInternal(text) {
|
|
|
34330
34641
|
const scrubbed = text.replace(SELF_HOSTED_WORKSPACE_RE, " ");
|
|
34331
34642
|
return INTERNAL_TOKENS.some((t2) => scrubbed.includes(t2));
|
|
34332
34643
|
}
|
|
34333
|
-
function pathIsInternal(p2, homeDir2 =
|
|
34644
|
+
function pathIsInternal(p2, homeDir2 = os45.homedir()) {
|
|
34334
34645
|
if (!p2) return false;
|
|
34335
|
-
const abs =
|
|
34336
|
-
const home =
|
|
34337
|
-
const within = (root) => abs === root || abs.startsWith(root +
|
|
34338
|
-
if (within(
|
|
34339
|
-
return within(
|
|
34646
|
+
const abs = path66.resolve(p2);
|
|
34647
|
+
const home = path66.resolve(homeDir2);
|
|
34648
|
+
const within = (root) => abs === root || abs.startsWith(root + path66.sep);
|
|
34649
|
+
if (within(path66.join(home, ".codeam", "self-hosted"))) return false;
|
|
34650
|
+
return within(path66.join(home, ".codeam")) || within(path66.join(home, ".beads")) || abs === path66.join(home, ".codeam-host.log") || abs.includes(`${path66.sep}house-claude${path66.sep}`) || abs.endsWith(`${path66.sep}house-claude`);
|
|
34340
34651
|
}
|
|
34341
34652
|
function toolCallReferencesInternal(call, homeDir2) {
|
|
34342
34653
|
if (call.locations?.some((l) => pathIsInternal(l.path, homeDir2))) return true;
|
|
@@ -34664,7 +34975,7 @@ var AcpClient = class {
|
|
|
34664
34975
|
"acpClient",
|
|
34665
34976
|
`provider routing ${formatProviderRouting(describeProviderRouting(childEnv, { cwd }), adapter.command)}`
|
|
34666
34977
|
);
|
|
34667
|
-
const child = (0,
|
|
34978
|
+
const child = (0, import_node_child_process22.spawn)(adapter.command, adapter.args, {
|
|
34668
34979
|
cwd,
|
|
34669
34980
|
env: childEnv,
|
|
34670
34981
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -35349,7 +35660,7 @@ var AcpClient = class {
|
|
|
35349
35660
|
try {
|
|
35350
35661
|
const pid = child.pid;
|
|
35351
35662
|
if (process.platform === "win32") {
|
|
35352
|
-
if (pid) (0,
|
|
35663
|
+
if (pid) (0, import_node_child_process22.spawnSync)("taskkill", ["/F", "/T", "/PID", String(pid)], { stdio: "ignore" });
|
|
35353
35664
|
} else if (pid) {
|
|
35354
35665
|
killQuiet(-pid, "SIGTERM");
|
|
35355
35666
|
} else {
|
|
@@ -35431,7 +35742,7 @@ var AcpClient = class {
|
|
|
35431
35742
|
throw new RequestError(-32002, GUARDRAIL_SECRET_READ_BLOCK_REASON, { uri: params.path });
|
|
35432
35743
|
}
|
|
35433
35744
|
try {
|
|
35434
|
-
const content = await
|
|
35745
|
+
const content = await fs57.readFile(params.path, "utf8");
|
|
35435
35746
|
return applyLineRange(content, params.line ?? null, params.limit ?? null);
|
|
35436
35747
|
} catch (err) {
|
|
35437
35748
|
const code = err.code;
|
|
@@ -35452,7 +35763,7 @@ var AcpClient = class {
|
|
|
35452
35763
|
throw new RequestError(-32002, INTERNAL_BLOCK_REASON, { uri: params.path });
|
|
35453
35764
|
}
|
|
35454
35765
|
try {
|
|
35455
|
-
await
|
|
35766
|
+
await fs57.writeFile(params.path, params.content, "utf8");
|
|
35456
35767
|
return {};
|
|
35457
35768
|
} catch (err) {
|
|
35458
35769
|
const code = err.code;
|
|
@@ -35540,30 +35851,30 @@ function applyLineRange(content, line, limit) {
|
|
|
35540
35851
|
return { content: lines.slice(start2, end).join("\n") };
|
|
35541
35852
|
}
|
|
35542
35853
|
function knownAgentBinaryDirs() {
|
|
35543
|
-
const home =
|
|
35854
|
+
const home = os46.homedir();
|
|
35544
35855
|
const out2 = [];
|
|
35545
35856
|
out2.push("/tmp/codeam-node20/bin");
|
|
35546
35857
|
for (const root of [
|
|
35547
35858
|
"/usr/local/share/nvm/versions/node",
|
|
35548
|
-
|
|
35859
|
+
path67.join(home, ".nvm/versions/node")
|
|
35549
35860
|
]) {
|
|
35550
35861
|
try {
|
|
35551
35862
|
for (const child of fsSync.readdirSync(root)) {
|
|
35552
|
-
out2.push(
|
|
35863
|
+
out2.push(path67.join(root, child, "bin"));
|
|
35553
35864
|
}
|
|
35554
35865
|
} catch {
|
|
35555
35866
|
}
|
|
35556
35867
|
}
|
|
35557
|
-
out2.push(
|
|
35868
|
+
out2.push(path67.join(home, ".volta/bin"));
|
|
35558
35869
|
out2.push("/usr/local/bin");
|
|
35559
35870
|
out2.push("/usr/bin");
|
|
35560
|
-
out2.push(
|
|
35561
|
-
out2.push(
|
|
35871
|
+
out2.push(path67.join(home, ".local/bin"));
|
|
35872
|
+
out2.push(path67.join(home, "bin"));
|
|
35562
35873
|
out2.push(...agentInstallBinDirs());
|
|
35563
35874
|
if (process.platform === "win32") {
|
|
35564
35875
|
const { LOCALAPPDATA, APPDATA } = process.env;
|
|
35565
|
-
if (LOCALAPPDATA) out2.push(
|
|
35566
|
-
if (APPDATA) out2.push(
|
|
35876
|
+
if (LOCALAPPDATA) out2.push(path67.join(LOCALAPPDATA, "cursor-agent"));
|
|
35877
|
+
if (APPDATA) out2.push(path67.join(APPDATA, "npm"));
|
|
35567
35878
|
}
|
|
35568
35879
|
return out2.filter((p2) => {
|
|
35569
35880
|
try {
|
|
@@ -35574,7 +35885,7 @@ function knownAgentBinaryDirs() {
|
|
|
35574
35885
|
});
|
|
35575
35886
|
}
|
|
35576
35887
|
function expandPathForAgentBinaries(existingPath) {
|
|
35577
|
-
const existing = new Set(existingPath.split(
|
|
35888
|
+
const existing = new Set(existingPath.split(path67.delimiter).filter((p2) => p2.length > 0));
|
|
35578
35889
|
const additions = [];
|
|
35579
35890
|
for (const dir of knownAgentBinaryDirs()) {
|
|
35580
35891
|
if (!existing.has(dir)) {
|
|
@@ -35583,17 +35894,17 @@ function expandPathForAgentBinaries(existingPath) {
|
|
|
35583
35894
|
}
|
|
35584
35895
|
}
|
|
35585
35896
|
if (additions.length === 0) return existingPath;
|
|
35586
|
-
return [...additions, existingPath].filter((p2) => p2.length > 0).join(
|
|
35897
|
+
return [...additions, existingPath].filter((p2) => p2.length > 0).join(path67.delimiter);
|
|
35587
35898
|
}
|
|
35588
35899
|
|
|
35589
35900
|
// src/commands/host/agent-install.ts
|
|
35590
35901
|
var import_child_process27 = require("child_process");
|
|
35591
|
-
var
|
|
35902
|
+
var os47 = __toESM(require("os"));
|
|
35592
35903
|
function runAgentInstallScript(script, opts = {}) {
|
|
35593
35904
|
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
35594
35905
|
const scope = opts.logScope ?? "agent-install";
|
|
35595
35906
|
return new Promise((resolve12) => {
|
|
35596
|
-
const home = process.env.HOME ||
|
|
35907
|
+
const home = process.env.HOME || os47.homedir();
|
|
35597
35908
|
const child = (0, import_child_process27.spawn)("sh", ["-c", script], {
|
|
35598
35909
|
env: { ...process.env, HOME: home },
|
|
35599
35910
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -35855,9 +36166,9 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
|
35855
36166
|
}
|
|
35856
36167
|
|
|
35857
36168
|
// src/commands/host/agent-provisioning.ts
|
|
35858
|
-
var
|
|
35859
|
-
var
|
|
35860
|
-
var
|
|
36169
|
+
var fs58 = __toESM(require("fs"));
|
|
36170
|
+
var os48 = __toESM(require("os"));
|
|
36171
|
+
var path68 = __toESM(require("path"));
|
|
35861
36172
|
var PUBLIC_TO_INTERNAL_AGENT = {
|
|
35862
36173
|
claude_code: "claude",
|
|
35863
36174
|
claude: "claude",
|
|
@@ -35874,22 +36185,22 @@ function toInternalAgentId(publicAgentId) {
|
|
|
35874
36185
|
return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
|
|
35875
36186
|
}
|
|
35876
36187
|
function ensureDir(dir) {
|
|
35877
|
-
|
|
36188
|
+
fs58.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
35878
36189
|
}
|
|
35879
36190
|
function writeFile0600(filePath, contents) {
|
|
35880
|
-
ensureDir(
|
|
35881
|
-
|
|
36191
|
+
ensureDir(path68.dirname(filePath));
|
|
36192
|
+
fs58.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
|
|
35882
36193
|
restrictToOwner(filePath);
|
|
35883
36194
|
}
|
|
35884
36195
|
function rmIfExists(filePath) {
|
|
35885
36196
|
try {
|
|
35886
|
-
|
|
36197
|
+
fs58.rmSync(filePath, { force: true });
|
|
35887
36198
|
} catch {
|
|
35888
36199
|
}
|
|
35889
36200
|
}
|
|
35890
36201
|
var claudeProvisioner = {
|
|
35891
36202
|
write(auth, home) {
|
|
35892
|
-
const credentialsJson =
|
|
36203
|
+
const credentialsJson = path68.join(home, ".claude", ".credentials.json");
|
|
35893
36204
|
if (auth.kind === "api_key") {
|
|
35894
36205
|
rmIfExists(credentialsJson);
|
|
35895
36206
|
return { ANTHROPIC_API_KEY: auth.value };
|
|
@@ -35901,8 +36212,8 @@ var claudeProvisioner = {
|
|
|
35901
36212
|
} else {
|
|
35902
36213
|
rmIfExists(credentialsJson);
|
|
35903
36214
|
}
|
|
35904
|
-
const claudeJson =
|
|
35905
|
-
if (!
|
|
36215
|
+
const claudeJson = path68.join(home, ".claude.json");
|
|
36216
|
+
if (!fs58.existsSync(claudeJson)) {
|
|
35906
36217
|
writeFile0600(
|
|
35907
36218
|
claudeJson,
|
|
35908
36219
|
JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
|
|
@@ -35913,7 +36224,7 @@ var claudeProvisioner = {
|
|
|
35913
36224
|
};
|
|
35914
36225
|
var codexProvisioner = {
|
|
35915
36226
|
write(auth, home) {
|
|
35916
|
-
const authJson =
|
|
36227
|
+
const authJson = path68.join(home, ".codex", "auth.json");
|
|
35917
36228
|
if (auth.kind === "api_key") {
|
|
35918
36229
|
writeFile0600(authJson, JSON.stringify({ auth_mode: "apikey", OPENAI_API_KEY: auth.value }));
|
|
35919
36230
|
return { OPENAI_API_KEY: auth.value };
|
|
@@ -35924,8 +36235,8 @@ var codexProvisioner = {
|
|
|
35924
36235
|
};
|
|
35925
36236
|
var geminiProvisioner = {
|
|
35926
36237
|
write(auth, home) {
|
|
35927
|
-
const settingsJson =
|
|
35928
|
-
const oauthCreds =
|
|
36238
|
+
const settingsJson = path68.join(home, ".gemini", "settings.json");
|
|
36239
|
+
const oauthCreds = path68.join(home, ".gemini", "oauth_creds.json");
|
|
35929
36240
|
if (auth.kind === "api_key") {
|
|
35930
36241
|
rmIfExists(oauthCreds);
|
|
35931
36242
|
writeFile0600(settingsJson, '{"security":{"auth":{"selectedType":"gemini-api-key"}}}');
|
|
@@ -35938,7 +36249,7 @@ var geminiProvisioner = {
|
|
|
35938
36249
|
};
|
|
35939
36250
|
var cursorProvisioner = {
|
|
35940
36251
|
write(auth, home) {
|
|
35941
|
-
const authJson =
|
|
36252
|
+
const authJson = path68.join(home, ".config", "cursor", "auth.json");
|
|
35942
36253
|
if (auth.kind === "api_key") {
|
|
35943
36254
|
rmIfExists(authJson);
|
|
35944
36255
|
return { CURSOR_API_KEY: auth.value };
|
|
@@ -35980,22 +36291,22 @@ max_context_size = 262144
|
|
|
35980
36291
|
var kimiProvisioner = {
|
|
35981
36292
|
write(auth, home) {
|
|
35982
36293
|
const credentialsFiles = [
|
|
35983
|
-
|
|
35984
|
-
|
|
36294
|
+
path68.join(home, ".kimi", "credentials", "kimi-code.json"),
|
|
36295
|
+
path68.join(home, ".kimi-code", "credentials", "kimi-code.json")
|
|
35985
36296
|
];
|
|
35986
36297
|
if (auth.kind === "api_key") {
|
|
35987
36298
|
credentialsFiles.forEach(rmIfExists);
|
|
35988
36299
|
return { KIMI_API_KEY: auth.value };
|
|
35989
36300
|
}
|
|
35990
36301
|
credentialsFiles.forEach((f) => writeFile0600(f, auth.value));
|
|
35991
|
-
writeFile0600(
|
|
36302
|
+
writeFile0600(path68.join(home, ".kimi-code", "config.toml"), KIMI_MANAGED_CONFIG_TOML);
|
|
35992
36303
|
return {};
|
|
35993
36304
|
}
|
|
35994
36305
|
};
|
|
35995
36306
|
var coderabbitProvisioner = {
|
|
35996
36307
|
write(auth, home) {
|
|
35997
|
-
const dir =
|
|
35998
|
-
const authJson =
|
|
36308
|
+
const dir = path68.join(home, ".coderabbit");
|
|
36309
|
+
const authJson = path68.join(dir, "auth.json");
|
|
35999
36310
|
if (auth.kind === "api_key") {
|
|
36000
36311
|
rmIfExists(authJson);
|
|
36001
36312
|
return { CODERABBIT_API_KEY: auth.value };
|
|
@@ -36007,13 +36318,13 @@ var coderabbitProvisioner = {
|
|
|
36007
36318
|
try {
|
|
36008
36319
|
const parsed = JSON.parse(value);
|
|
36009
36320
|
if (typeof parsed.file === "string" && typeof parsed.contents === "string") {
|
|
36010
|
-
file =
|
|
36321
|
+
file = path68.basename(parsed.file);
|
|
36011
36322
|
contents = parsed.contents;
|
|
36012
36323
|
}
|
|
36013
36324
|
} catch {
|
|
36014
36325
|
}
|
|
36015
36326
|
}
|
|
36016
|
-
writeFile0600(
|
|
36327
|
+
writeFile0600(path68.join(dir, file), contents);
|
|
36017
36328
|
return {};
|
|
36018
36329
|
}
|
|
36019
36330
|
};
|
|
@@ -36041,7 +36352,7 @@ var UnsupportedAgentError = class extends Error {
|
|
|
36041
36352
|
this.agentId = agentId;
|
|
36042
36353
|
}
|
|
36043
36354
|
};
|
|
36044
|
-
function provisionAgentCredentials(publicAgentId, auth, homeDir2 =
|
|
36355
|
+
function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os48.homedir()) {
|
|
36045
36356
|
const internal = toInternalAgentId(publicAgentId);
|
|
36046
36357
|
if (!internal) throw new UnsupportedAgentError(publicAgentId);
|
|
36047
36358
|
const provisioner = PROVISIONERS[internal];
|
|
@@ -36050,16 +36361,16 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os47.homedir(
|
|
|
36050
36361
|
}
|
|
36051
36362
|
|
|
36052
36363
|
// src/beads/workflow-hint.ts
|
|
36053
|
-
var
|
|
36054
|
-
var
|
|
36364
|
+
var fs59 = __toESM(require("fs"));
|
|
36365
|
+
var path70 = __toESM(require("path"));
|
|
36055
36366
|
|
|
36056
36367
|
// src/agents/claude-memory-file.ts
|
|
36057
|
-
var
|
|
36058
|
-
var
|
|
36368
|
+
var os49 = __toESM(require("os"));
|
|
36369
|
+
var path69 = __toESM(require("path"));
|
|
36059
36370
|
function claudeMemoryFile(homeDir2, env = process.env) {
|
|
36060
|
-
if (homeDir2) return
|
|
36371
|
+
if (homeDir2) return path69.join(homeDir2, ".claude", "CLAUDE.md");
|
|
36061
36372
|
const configDir = env.CLAUDE_CONFIG_DIR?.trim();
|
|
36062
|
-
return configDir ?
|
|
36373
|
+
return configDir ? path69.join(configDir, "CLAUDE.md") : path69.join(os49.homedir(), ".claude", "CLAUDE.md");
|
|
36063
36374
|
}
|
|
36064
36375
|
|
|
36065
36376
|
// src/beads/workflow-hint.ts
|
|
@@ -36089,11 +36400,11 @@ function ensureBeadsWorkflowHint(homeDir2, file = claudeMemoryFile(homeDir2)) {
|
|
|
36089
36400
|
try {
|
|
36090
36401
|
let existing = "";
|
|
36091
36402
|
try {
|
|
36092
|
-
existing =
|
|
36403
|
+
existing = fs59.readFileSync(file, "utf8");
|
|
36093
36404
|
} catch {
|
|
36094
36405
|
}
|
|
36095
36406
|
if (existing.includes(BEADS_HINT)) return;
|
|
36096
|
-
|
|
36407
|
+
fs59.mkdirSync(path70.dirname(file), { recursive: true });
|
|
36097
36408
|
let next;
|
|
36098
36409
|
const open = existing.indexOf(BEADS_HINT_MARKER);
|
|
36099
36410
|
const close = open === -1 ? -1 : existing.indexOf(BEADS_HINT_MARKER, open + BEADS_HINT_MARKER.length);
|
|
@@ -36106,40 +36417,40 @@ ${BEADS_HINT}
|
|
|
36106
36417
|
` : `${BEADS_HINT}
|
|
36107
36418
|
`;
|
|
36108
36419
|
}
|
|
36109
|
-
|
|
36420
|
+
fs59.writeFileSync(file, next);
|
|
36110
36421
|
} catch {
|
|
36111
36422
|
}
|
|
36112
36423
|
}
|
|
36113
36424
|
|
|
36114
36425
|
// src/agents/agent-standard.ts
|
|
36115
|
-
var
|
|
36116
|
-
var
|
|
36117
|
-
var
|
|
36426
|
+
var fs60 = __toESM(require("fs"));
|
|
36427
|
+
var path71 = __toESM(require("path"));
|
|
36428
|
+
var os50 = __toESM(require("os"));
|
|
36118
36429
|
function ensureAgentStandard(homeDir2, file = claudeMemoryFile(homeDir2)) {
|
|
36119
36430
|
try {
|
|
36120
36431
|
let existing = "";
|
|
36121
36432
|
try {
|
|
36122
|
-
existing =
|
|
36433
|
+
existing = fs60.readFileSync(file, "utf8");
|
|
36123
36434
|
} catch {
|
|
36124
36435
|
}
|
|
36125
36436
|
if (existing.includes(AGENT_STANDARD_MARKER)) return;
|
|
36126
|
-
|
|
36437
|
+
fs60.mkdirSync(path71.dirname(file), { recursive: true });
|
|
36127
36438
|
const next = existing.trim() ? `${existing.trimEnd()}
|
|
36128
36439
|
|
|
36129
36440
|
${AGENT_STANDARD_BLOCK}
|
|
36130
36441
|
` : `${AGENT_STANDARD_BLOCK}
|
|
36131
36442
|
`;
|
|
36132
|
-
|
|
36443
|
+
fs60.writeFileSync(file, next);
|
|
36133
36444
|
} catch {
|
|
36134
36445
|
}
|
|
36135
36446
|
}
|
|
36136
36447
|
var _agentStandardSeam = {
|
|
36137
36448
|
isLocalSession: () => isLocalSession(),
|
|
36138
|
-
markerPath: (sessionId) =>
|
|
36139
|
-
exists: (p2) =>
|
|
36449
|
+
markerPath: (sessionId) => path71.join(os50.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
|
|
36450
|
+
exists: (p2) => fs60.existsSync(p2),
|
|
36140
36451
|
write: (p2) => {
|
|
36141
|
-
|
|
36142
|
-
|
|
36452
|
+
fs60.mkdirSync(path71.dirname(p2), { recursive: true });
|
|
36453
|
+
fs60.writeFileSync(p2, "");
|
|
36143
36454
|
}
|
|
36144
36455
|
};
|
|
36145
36456
|
function isClaude(agent) {
|
|
@@ -36832,15 +37143,15 @@ function withholdTrailingPartialFenceMarker(text) {
|
|
|
36832
37143
|
|
|
36833
37144
|
// src/agents/acp/onboarding.ts
|
|
36834
37145
|
var import_child_process28 = require("child_process");
|
|
36835
|
-
var
|
|
36836
|
-
var
|
|
36837
|
-
var
|
|
37146
|
+
var fs61 = __toESM(require("fs"));
|
|
37147
|
+
var os51 = __toESM(require("os"));
|
|
37148
|
+
var path72 = __toESM(require("path"));
|
|
36838
37149
|
var _onboardingSeam = {
|
|
36839
|
-
markerPath: (sessionId) =>
|
|
36840
|
-
exists: (p2) =>
|
|
37150
|
+
markerPath: (sessionId) => path72.join(os51.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
|
|
37151
|
+
exists: (p2) => fs61.existsSync(p2),
|
|
36841
37152
|
write: (p2) => {
|
|
36842
|
-
|
|
36843
|
-
|
|
37153
|
+
fs61.mkdirSync(path72.dirname(p2), { recursive: true });
|
|
37154
|
+
fs61.writeFileSync(p2, "");
|
|
36844
37155
|
},
|
|
36845
37156
|
disabled: () => {
|
|
36846
37157
|
const v = process.env.CODEAM_ONBOARDING_DISABLED;
|
|
@@ -36877,7 +37188,7 @@ function resolveRepoName(cwd) {
|
|
|
36877
37188
|
if (name) return name;
|
|
36878
37189
|
}
|
|
36879
37190
|
}
|
|
36880
|
-
const base =
|
|
37191
|
+
const base = path72.basename(cwd || "");
|
|
36881
37192
|
if (base && !isUuid(base)) return base;
|
|
36882
37193
|
return "this project";
|
|
36883
37194
|
}
|
|
@@ -37269,13 +37580,13 @@ var import_crypto4 = require("crypto");
|
|
|
37269
37580
|
|
|
37270
37581
|
// src/services/turn-files/git-changeset.ts
|
|
37271
37582
|
var import_child_process29 = require("child_process");
|
|
37272
|
-
var
|
|
37273
|
-
var
|
|
37583
|
+
var fs63 = __toESM(require("fs/promises"));
|
|
37584
|
+
var path74 = __toESM(require("path"));
|
|
37274
37585
|
|
|
37275
37586
|
// src/services/turn-files/review-ignore.ts
|
|
37276
37587
|
var import_ignore2 = __toESM(require("ignore"));
|
|
37277
|
-
var
|
|
37278
|
-
var
|
|
37588
|
+
var fs62 = __toESM(require("fs"));
|
|
37589
|
+
var path73 = __toESM(require("path"));
|
|
37279
37590
|
var CURATED_REVIEW_IGNORE = [
|
|
37280
37591
|
// Google Cloud SDK (the incident) — installs a huge python tree.
|
|
37281
37592
|
"google-cloud-sdk/",
|
|
@@ -37314,7 +37625,7 @@ var CURATED_REVIEW_IGNORE = [
|
|
|
37314
37625
|
function makeReviewIgnore(repoRoot) {
|
|
37315
37626
|
const ig = (0, import_ignore2.default)().add(CURATED_REVIEW_IGNORE);
|
|
37316
37627
|
try {
|
|
37317
|
-
const custom =
|
|
37628
|
+
const custom = fs62.readFileSync(path73.join(repoRoot, ".codeam", "reviewignore"), "utf8");
|
|
37318
37629
|
ig.add(custom);
|
|
37319
37630
|
} catch {
|
|
37320
37631
|
}
|
|
@@ -37359,7 +37670,7 @@ async function collectRepoChangeset(opts) {
|
|
|
37359
37670
|
let stats;
|
|
37360
37671
|
if (!truncated && row.fileStatus === "added" && numstatEntry === void 0) {
|
|
37361
37672
|
const lineCount = await readUntrackedLineCount(
|
|
37362
|
-
|
|
37673
|
+
path74.join(opts.repoRoot, row.filePath)
|
|
37363
37674
|
);
|
|
37364
37675
|
stats = { added: lineCount, removed: 0 };
|
|
37365
37676
|
} else {
|
|
@@ -37390,7 +37701,7 @@ function readUntrackedLineCount(absPath) {
|
|
|
37390
37701
|
}
|
|
37391
37702
|
async function defaultReadUntrackedLineCount(absPath) {
|
|
37392
37703
|
try {
|
|
37393
|
-
const content = await
|
|
37704
|
+
const content = await fs63.readFile(absPath, "utf8");
|
|
37394
37705
|
let count = 0;
|
|
37395
37706
|
let pos = -1;
|
|
37396
37707
|
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
|
|
@@ -37482,7 +37793,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
37482
37793
|
});
|
|
37483
37794
|
}
|
|
37484
37795
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
37485
|
-
const
|
|
37796
|
+
const fs82 = await import("fs/promises");
|
|
37486
37797
|
const out2 = [];
|
|
37487
37798
|
await walk(workingDir, 0);
|
|
37488
37799
|
return out2;
|
|
@@ -37490,7 +37801,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
37490
37801
|
if (depth > maxDepth) return;
|
|
37491
37802
|
let entries = [];
|
|
37492
37803
|
try {
|
|
37493
|
-
const dirents = await
|
|
37804
|
+
const dirents = await fs82.readdir(dir, { withFileTypes: true });
|
|
37494
37805
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
37495
37806
|
} catch {
|
|
37496
37807
|
return;
|
|
@@ -37501,8 +37812,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
37501
37812
|
if (hasGit) {
|
|
37502
37813
|
out2.push({
|
|
37503
37814
|
repoRoot: dir,
|
|
37504
|
-
repoPath:
|
|
37505
|
-
repoName:
|
|
37815
|
+
repoPath: path74.relative(workingDir, dir),
|
|
37816
|
+
repoName: path74.basename(dir)
|
|
37506
37817
|
});
|
|
37507
37818
|
return;
|
|
37508
37819
|
}
|
|
@@ -37510,14 +37821,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
37510
37821
|
if (!entry.isDirectory) continue;
|
|
37511
37822
|
if (entry.name === "node_modules") continue;
|
|
37512
37823
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
37513
|
-
await walk(
|
|
37824
|
+
await walk(path74.join(dir, entry.name), depth + 1);
|
|
37514
37825
|
}
|
|
37515
37826
|
}
|
|
37516
37827
|
}
|
|
37517
37828
|
|
|
37518
37829
|
// src/services/turn-files/files-outbox.ts
|
|
37519
|
-
var
|
|
37520
|
-
var
|
|
37830
|
+
var fs64 = __toESM(require("fs/promises"));
|
|
37831
|
+
var path75 = __toESM(require("path"));
|
|
37521
37832
|
var import_os12 = require("os");
|
|
37522
37833
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
37523
37834
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -37550,16 +37861,16 @@ var FilesOutbox = class {
|
|
|
37550
37861
|
backoffIndex = 0;
|
|
37551
37862
|
stopped = false;
|
|
37552
37863
|
constructor(opts) {
|
|
37553
|
-
const base = opts.baseDir ??
|
|
37554
|
-
this.filePath =
|
|
37864
|
+
const base = opts.baseDir ?? path75.join(homeDir(), HOME_OUTBOX_DIR);
|
|
37865
|
+
this.filePath = path75.join(base, `${opts.sessionId}.jsonl`);
|
|
37555
37866
|
this.post = opts.post;
|
|
37556
37867
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
37557
37868
|
}
|
|
37558
37869
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
37559
37870
|
* line is durable on disk (not once the POST succeeds). */
|
|
37560
37871
|
async enqueue(entry) {
|
|
37561
|
-
await
|
|
37562
|
-
await
|
|
37872
|
+
await fs64.mkdir(path75.dirname(this.filePath), { recursive: true });
|
|
37873
|
+
await fs64.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
37563
37874
|
this.backoffIndex = 0;
|
|
37564
37875
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
37565
37876
|
}
|
|
@@ -37650,7 +37961,7 @@ var FilesOutbox = class {
|
|
|
37650
37961
|
async readAll() {
|
|
37651
37962
|
let raw = "";
|
|
37652
37963
|
try {
|
|
37653
|
-
raw = await
|
|
37964
|
+
raw = await fs64.readFile(this.filePath, "utf8");
|
|
37654
37965
|
} catch {
|
|
37655
37966
|
return [];
|
|
37656
37967
|
}
|
|
@@ -37674,12 +37985,12 @@ var FilesOutbox = class {
|
|
|
37674
37985
|
async rewrite(entries) {
|
|
37675
37986
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
37676
37987
|
if (entries.length === 0) {
|
|
37677
|
-
await
|
|
37988
|
+
await fs64.unlink(this.filePath).catch(() => void 0);
|
|
37678
37989
|
return;
|
|
37679
37990
|
}
|
|
37680
37991
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
37681
|
-
await
|
|
37682
|
-
await
|
|
37992
|
+
await fs64.writeFile(tmpPath, payload, "utf8");
|
|
37993
|
+
await fs64.rename(tmpPath, this.filePath);
|
|
37683
37994
|
}
|
|
37684
37995
|
};
|
|
37685
37996
|
function applyJitter(ms) {
|
|
@@ -38226,11 +38537,11 @@ async function postCredentialSync(opts, fetchImpl = fetch) {
|
|
|
38226
38537
|
}
|
|
38227
38538
|
|
|
38228
38539
|
// src/packs/gates.ts
|
|
38229
|
-
var
|
|
38230
|
-
var
|
|
38231
|
-
var
|
|
38540
|
+
var import_node_child_process23 = require("child_process");
|
|
38541
|
+
var fs65 = __toESM(require("fs"));
|
|
38542
|
+
var path76 = __toESM(require("path"));
|
|
38232
38543
|
var defaultCommandRunner = (file, args2, cwd, timeoutMs, env) => new Promise((resolve12) => {
|
|
38233
|
-
(0,
|
|
38544
|
+
(0, import_node_child_process23.execFile)(
|
|
38234
38545
|
file,
|
|
38235
38546
|
args2,
|
|
38236
38547
|
{
|
|
@@ -38278,7 +38589,7 @@ async function changedFiles(run, cwd, from, to) {
|
|
|
38278
38589
|
}
|
|
38279
38590
|
function readWorkspaceFile(cwd, relPath) {
|
|
38280
38591
|
try {
|
|
38281
|
-
return
|
|
38592
|
+
return fs65.readFileSync(path76.join(cwd, relPath), "utf8");
|
|
38282
38593
|
} catch {
|
|
38283
38594
|
return null;
|
|
38284
38595
|
}
|
|
@@ -38287,14 +38598,14 @@ var NO_TEST_PLACEHOLDER = 'echo "Error: no test specified"';
|
|
|
38287
38598
|
var CHECKS_TIMEOUT_MS = 5 * 6e4;
|
|
38288
38599
|
function detectChecksCommand(cwd) {
|
|
38289
38600
|
try {
|
|
38290
|
-
const cfg = JSON.parse(
|
|
38601
|
+
const cfg = JSON.parse(fs65.readFileSync(path76.join(cwd, ".codeam", "pack.json"), "utf8"));
|
|
38291
38602
|
if (typeof cfg.checksCommand === "string" && cfg.checksCommand.trim().length > 0) {
|
|
38292
38603
|
return cfg.checksCommand.trim();
|
|
38293
38604
|
}
|
|
38294
38605
|
} catch {
|
|
38295
38606
|
}
|
|
38296
38607
|
try {
|
|
38297
|
-
const pkg = JSON.parse(
|
|
38608
|
+
const pkg = JSON.parse(fs65.readFileSync(path76.join(cwd, "package.json"), "utf8"));
|
|
38298
38609
|
const test = pkg.scripts?.test;
|
|
38299
38610
|
if (typeof test === "string" && test.trim().length > 0 && !test.includes(NO_TEST_PLACEHOLDER)) {
|
|
38300
38611
|
return "npm test";
|
|
@@ -38312,39 +38623,39 @@ ${res.stderr}`.trim();
|
|
|
38312
38623
|
}
|
|
38313
38624
|
|
|
38314
38625
|
// src/packs/run-store.ts
|
|
38315
|
-
var
|
|
38316
|
-
var
|
|
38626
|
+
var fs66 = __toESM(require("fs"));
|
|
38627
|
+
var path77 = __toESM(require("path"));
|
|
38317
38628
|
var crypto5 = __toESM(require("crypto"));
|
|
38318
38629
|
function packsDir(cwd) {
|
|
38319
|
-
return
|
|
38630
|
+
return path77.join(cwd, ".codeam", "packs");
|
|
38320
38631
|
}
|
|
38321
38632
|
function runDir(cwd, runId) {
|
|
38322
|
-
return
|
|
38633
|
+
return path77.join(packsDir(cwd), runId);
|
|
38323
38634
|
}
|
|
38324
38635
|
function newRunId() {
|
|
38325
38636
|
return `pk_${Date.now().toString(36)}_${crypto5.randomBytes(4).toString("hex")}`;
|
|
38326
38637
|
}
|
|
38327
38638
|
function writeJsonAtomic(file, value) {
|
|
38328
|
-
|
|
38639
|
+
fs66.mkdirSync(path77.dirname(file), { recursive: true });
|
|
38329
38640
|
const tmp = `${file}.tmp`;
|
|
38330
|
-
|
|
38331
|
-
|
|
38641
|
+
fs66.writeFileSync(tmp, JSON.stringify(value, null, 2));
|
|
38642
|
+
fs66.renameSync(tmp, file);
|
|
38332
38643
|
}
|
|
38333
38644
|
function saveRun(cwd, state) {
|
|
38334
|
-
writeJsonAtomic(
|
|
38645
|
+
writeJsonAtomic(path77.join(runDir(cwd, state.runId), "run.json"), state);
|
|
38335
38646
|
}
|
|
38336
38647
|
function saveStageHandoff(cwd, runId, stageIndex, role, handoff) {
|
|
38337
38648
|
const name = `${String(stageIndex + 1).padStart(2, "0")}-${role}.json`;
|
|
38338
|
-
writeJsonAtomic(
|
|
38649
|
+
writeJsonAtomic(path77.join(runDir(cwd, runId), name), handoff);
|
|
38339
38650
|
}
|
|
38340
38651
|
function loadLatestRun(cwd) {
|
|
38341
38652
|
try {
|
|
38342
38653
|
const dir = packsDir(cwd);
|
|
38343
|
-
const entries =
|
|
38654
|
+
const entries = fs66.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
38344
38655
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
38345
|
-
const file =
|
|
38656
|
+
const file = path77.join(dir, entries[i], "run.json");
|
|
38346
38657
|
try {
|
|
38347
|
-
const parsed = JSON.parse(
|
|
38658
|
+
const parsed = JSON.parse(fs66.readFileSync(file, "utf8"));
|
|
38348
38659
|
if (parsed && typeof parsed.runId === "string") return parsed;
|
|
38349
38660
|
} catch {
|
|
38350
38661
|
}
|
|
@@ -38355,17 +38666,17 @@ function loadLatestRun(cwd) {
|
|
|
38355
38666
|
}
|
|
38356
38667
|
function ensureLedgerIgnored(cwd) {
|
|
38357
38668
|
try {
|
|
38358
|
-
const gitDir =
|
|
38359
|
-
if (!
|
|
38360
|
-
const exclude =
|
|
38669
|
+
const gitDir = path77.join(cwd, ".git");
|
|
38670
|
+
if (!fs66.existsSync(gitDir)) return;
|
|
38671
|
+
const exclude = path77.join(gitDir, "info", "exclude");
|
|
38361
38672
|
let existing = "";
|
|
38362
38673
|
try {
|
|
38363
|
-
existing =
|
|
38674
|
+
existing = fs66.readFileSync(exclude, "utf8");
|
|
38364
38675
|
} catch {
|
|
38365
38676
|
}
|
|
38366
38677
|
if (existing.includes(".codeam/packs/")) return;
|
|
38367
|
-
|
|
38368
|
-
|
|
38678
|
+
fs66.mkdirSync(path77.dirname(exclude), { recursive: true });
|
|
38679
|
+
fs66.writeFileSync(exclude, `${existing.trimEnd()}
|
|
38369
38680
|
.codeam/packs/
|
|
38370
38681
|
`.trimStart());
|
|
38371
38682
|
} catch {
|
|
@@ -39345,8 +39656,267 @@ async function mcpRouter() {
|
|
|
39345
39656
|
});
|
|
39346
39657
|
}
|
|
39347
39658
|
|
|
39659
|
+
// src/integrations/mcp-secrets.ts
|
|
39660
|
+
var fs68 = __toESM(require("fs"));
|
|
39661
|
+
var os53 = __toESM(require("os"));
|
|
39662
|
+
var path79 = __toESM(require("path"));
|
|
39663
|
+
var MCP_SECRETS_FILE_ENV = "CODEAM_MCP_SECRETS_FILE";
|
|
39664
|
+
function mcpSecretsDir() {
|
|
39665
|
+
return path79.join(os53.homedir(), ".codeam", "mcp-secrets");
|
|
39666
|
+
}
|
|
39667
|
+
function mcpSecretsPath(scope, pid = process.pid) {
|
|
39668
|
+
return path79.join(mcpSecretsDir(), `${pid}-${scope}.json`);
|
|
39669
|
+
}
|
|
39670
|
+
var registeredForCleanup = /* @__PURE__ */ new Set();
|
|
39671
|
+
function readFileVars(file) {
|
|
39672
|
+
try {
|
|
39673
|
+
const parsed = JSON.parse(fs68.readFileSync(file, "utf8"));
|
|
39674
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
39675
|
+
const out2 = {};
|
|
39676
|
+
for (const [k2, v] of Object.entries(parsed)) {
|
|
39677
|
+
if (typeof v === "string") out2[k2] = v;
|
|
39678
|
+
}
|
|
39679
|
+
return out2;
|
|
39680
|
+
} catch {
|
|
39681
|
+
return {};
|
|
39682
|
+
}
|
|
39683
|
+
}
|
|
39684
|
+
function pidAlive(pid) {
|
|
39685
|
+
try {
|
|
39686
|
+
process.kill(pid, 0);
|
|
39687
|
+
return true;
|
|
39688
|
+
} catch (err) {
|
|
39689
|
+
return err.code === "EPERM";
|
|
39690
|
+
}
|
|
39691
|
+
}
|
|
39692
|
+
function pruneStale(dir) {
|
|
39693
|
+
let names = [];
|
|
39694
|
+
try {
|
|
39695
|
+
names = fs68.readdirSync(dir);
|
|
39696
|
+
} catch {
|
|
39697
|
+
return;
|
|
39698
|
+
}
|
|
39699
|
+
for (const name of names) {
|
|
39700
|
+
const m = /^(\d+)-[a-z]+\.json$/.exec(name);
|
|
39701
|
+
if (!m) continue;
|
|
39702
|
+
const pid = Number(m[1]);
|
|
39703
|
+
if (pid === process.pid || pidAlive(pid)) continue;
|
|
39704
|
+
try {
|
|
39705
|
+
fs68.unlinkSync(path79.join(dir, name));
|
|
39706
|
+
} catch {
|
|
39707
|
+
}
|
|
39708
|
+
}
|
|
39709
|
+
}
|
|
39710
|
+
function writeMcpSecrets(vars, file) {
|
|
39711
|
+
try {
|
|
39712
|
+
const dir = path79.dirname(file);
|
|
39713
|
+
fs68.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
39714
|
+
pruneStale(dir);
|
|
39715
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
39716
|
+
fs68.writeFileSync(tmp, JSON.stringify(vars), { mode: 384 });
|
|
39717
|
+
fs68.renameSync(tmp, file);
|
|
39718
|
+
fs68.chmodSync(file, 384);
|
|
39719
|
+
if (!registeredForCleanup.has(file)) {
|
|
39720
|
+
registeredForCleanup.add(file);
|
|
39721
|
+
process.once("exit", () => {
|
|
39722
|
+
try {
|
|
39723
|
+
fs68.unlinkSync(file);
|
|
39724
|
+
} catch {
|
|
39725
|
+
}
|
|
39726
|
+
});
|
|
39727
|
+
}
|
|
39728
|
+
return file;
|
|
39729
|
+
} catch {
|
|
39730
|
+
return null;
|
|
39731
|
+
}
|
|
39732
|
+
}
|
|
39733
|
+
function mcpSecretEnv(scope, vars) {
|
|
39734
|
+
const file = writeMcpSecrets(vars, mcpSecretsPath(scope));
|
|
39735
|
+
if (file) return [{ name: MCP_SECRETS_FILE_ENV, value: file }];
|
|
39736
|
+
return Object.entries(vars).map(([name, value]) => ({ name, value }));
|
|
39737
|
+
}
|
|
39738
|
+
function loadMcpSecrets(env = process.env) {
|
|
39739
|
+
const file = env[MCP_SECRETS_FILE_ENV];
|
|
39740
|
+
if (!file) return;
|
|
39741
|
+
for (const [k2, v] of Object.entries(readFileVars(file))) {
|
|
39742
|
+
if (env[k2] === void 0) env[k2] = v;
|
|
39743
|
+
}
|
|
39744
|
+
}
|
|
39745
|
+
|
|
39746
|
+
// src/commands/preview-mcp.ts
|
|
39747
|
+
var PREVIEW_MCP_SERVER_NAME = "codeagent_preview";
|
|
39748
|
+
var PREVIEW_IPC_URL_ENV = "CODEAM_PREVIEW_IPC_URL";
|
|
39749
|
+
var PREVIEW_IPC_TOKEN_ENV = "CODEAM_PREVIEW_IPC_TOKEN";
|
|
39750
|
+
var START_TIMEOUT_MS = 27e4;
|
|
39751
|
+
var SHORT_TIMEOUT_MS = 2e4;
|
|
39752
|
+
var PREVIEW_TOOLS = [
|
|
39753
|
+
{
|
|
39754
|
+
name: "start_preview",
|
|
39755
|
+
description: "Open this project's live Preview in the user's CodeAgent app \u2014 the same thing as their Preview button: it installs dependencies if needed, starts the dev server, publishes it on a public URL and switches the user's screen to it. Use it after you change anything visual (UI, styles, layout, copy) so you and the user can check the result, or whenever the user asks to see the app. Returns the public URL (you can curl it) or the exact error. Reuses a preview that is already running. Usually leave the arguments out: the project is detected automatically. Pass command/args/port only if you know the exact dev command.",
|
|
39756
|
+
inputSchema: {
|
|
39757
|
+
type: "object",
|
|
39758
|
+
properties: {
|
|
39759
|
+
command: { type: "string", description: 'Dev server executable, e.g. "npm". Optional.' },
|
|
39760
|
+
args: { type: "array", items: { type: "string" }, description: 'e.g. ["run","dev"]. Optional.' },
|
|
39761
|
+
port: { type: "number", description: "Port the dev server listens on. Required with command." },
|
|
39762
|
+
framework: { type: "string", description: 'Label shown to the user, e.g. "next". Optional.' }
|
|
39763
|
+
},
|
|
39764
|
+
additionalProperties: false
|
|
39765
|
+
}
|
|
39766
|
+
},
|
|
39767
|
+
{
|
|
39768
|
+
name: "preview_status",
|
|
39769
|
+
description: "Current state of the Preview: running (with its URL), starting, error (with the reason) or idle. Use it when start_preview answered that the preview is still starting.",
|
|
39770
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
39771
|
+
},
|
|
39772
|
+
{
|
|
39773
|
+
name: "highlight_element",
|
|
39774
|
+
description: 'Point at an element in the running Preview: the user sees your cursor move to it and a labelled box drawn around it, scrolled into view. Use it to show the user exactly what you changed or what you are talking about ("this button", "the header spacing"). Takes a CSS selector (prefer ids, data-testid or specific classes you saw in the code). Several calls add several marks; clear_highlights removes them.',
|
|
39775
|
+
inputSchema: {
|
|
39776
|
+
type: "object",
|
|
39777
|
+
properties: {
|
|
39778
|
+
selector: { type: "string", description: 'CSS selector, e.g. "#checkout" or "[data-testid=hero-cta]".' },
|
|
39779
|
+
label: { type: "string", description: 'Short caption on the mark, e.g. "New CTA". Optional.' }
|
|
39780
|
+
},
|
|
39781
|
+
required: ["selector"],
|
|
39782
|
+
additionalProperties: false
|
|
39783
|
+
}
|
|
39784
|
+
},
|
|
39785
|
+
{
|
|
39786
|
+
name: "clear_highlights",
|
|
39787
|
+
description: "Remove every mark you drew in the Preview with highlight_element.",
|
|
39788
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
39789
|
+
},
|
|
39790
|
+
{
|
|
39791
|
+
name: "stop_preview",
|
|
39792
|
+
description: "Stop the Preview (dev server + public URL). Only when the user asks, or to restart it cleanly.",
|
|
39793
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
39794
|
+
}
|
|
39795
|
+
];
|
|
39796
|
+
function previewMcpServer(bridge) {
|
|
39797
|
+
if (!bridge) return null;
|
|
39798
|
+
return {
|
|
39799
|
+
name: PREVIEW_MCP_SERVER_NAME,
|
|
39800
|
+
// Same runtime + entrypoint as this CLI — never trust the agent's PATH.
|
|
39801
|
+
command: process.execPath,
|
|
39802
|
+
args: [process.argv[1], "preview-mcp"],
|
|
39803
|
+
// The token rides the owner-only secrets file, never this env: the
|
|
39804
|
+
// claude ACP adapter copies MCP env onto argv (codeagent-5bew).
|
|
39805
|
+
env: [{ name: PREVIEW_IPC_URL_ENV, value: bridge.url }, ...mcpSecretEnv("preview", { [PREVIEW_IPC_TOKEN_ENV]: bridge.token })]
|
|
39806
|
+
};
|
|
39807
|
+
}
|
|
39808
|
+
function httpCall(baseUrl, token) {
|
|
39809
|
+
return async (path97, method, body, timeoutMs) => {
|
|
39810
|
+
const ac = new AbortController();
|
|
39811
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
39812
|
+
try {
|
|
39813
|
+
const res = await fetch(`${baseUrl}${path97}`, {
|
|
39814
|
+
method,
|
|
39815
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
39816
|
+
...method === "POST" ? { body: JSON.stringify(body ?? {}) } : {},
|
|
39817
|
+
signal: ac.signal
|
|
39818
|
+
});
|
|
39819
|
+
return await res.json();
|
|
39820
|
+
} finally {
|
|
39821
|
+
clearTimeout(timer);
|
|
39822
|
+
}
|
|
39823
|
+
};
|
|
39824
|
+
}
|
|
39825
|
+
async function runPreviewTool(name, args2, call) {
|
|
39826
|
+
switch (name) {
|
|
39827
|
+
case "start_preview":
|
|
39828
|
+
return describeResult(await call("/preview/start", "POST", args2, START_TIMEOUT_MS));
|
|
39829
|
+
case "preview_status":
|
|
39830
|
+
return describeResult(await call("/preview/status", "GET", void 0, SHORT_TIMEOUT_MS));
|
|
39831
|
+
case "highlight_element":
|
|
39832
|
+
return describeAck(await call("/preview/highlight", "POST", args2, SHORT_TIMEOUT_MS));
|
|
39833
|
+
case "clear_highlights":
|
|
39834
|
+
return describeAck(await call("/preview/highlight", "POST", { clear: true }, SHORT_TIMEOUT_MS));
|
|
39835
|
+
case "stop_preview":
|
|
39836
|
+
return describeAck(await call("/preview/stop", "POST", {}, SHORT_TIMEOUT_MS));
|
|
39837
|
+
default:
|
|
39838
|
+
return { text: `Unknown tool: ${name}`, isError: true };
|
|
39839
|
+
}
|
|
39840
|
+
}
|
|
39841
|
+
function describeResult(raw) {
|
|
39842
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
39843
|
+
switch (r.status) {
|
|
39844
|
+
case "running": {
|
|
39845
|
+
const inspector = r.inspector ? " You can point at elements with highlight_element." : " (No element highlighting for this framework.)";
|
|
39846
|
+
return {
|
|
39847
|
+
text: `Preview ${r.reused ? "already running" : "is live"}: ${String(r.url)} (${String(r.framework)}). The user's app is showing it now.${inspector}`,
|
|
39848
|
+
isError: false
|
|
39849
|
+
};
|
|
39850
|
+
}
|
|
39851
|
+
case "starting":
|
|
39852
|
+
return { text: String(r.message ?? "The preview is starting."), isError: false };
|
|
39853
|
+
case "idle":
|
|
39854
|
+
return { text: "No preview is running.", isError: false };
|
|
39855
|
+
case "error":
|
|
39856
|
+
return {
|
|
39857
|
+
text: `Preview failed at ${String(r.stage)}: ${String(r.message)}`,
|
|
39858
|
+
isError: true
|
|
39859
|
+
};
|
|
39860
|
+
default:
|
|
39861
|
+
return { text: `Unexpected answer from the preview bridge: ${JSON.stringify(raw)}`, isError: true };
|
|
39862
|
+
}
|
|
39863
|
+
}
|
|
39864
|
+
function describeAck(raw) {
|
|
39865
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
39866
|
+
return { text: String(r.message ?? r.error ?? "done"), isError: r.ok !== true };
|
|
39867
|
+
}
|
|
39868
|
+
async function previewMcp() {
|
|
39869
|
+
const url2 = process.env[PREVIEW_IPC_URL_ENV];
|
|
39870
|
+
const token = process.env[PREVIEW_IPC_TOKEN_ENV];
|
|
39871
|
+
const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
|
|
39872
|
+
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
39873
|
+
const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
|
|
39874
|
+
const call = url2 && token ? httpCall(url2, token) : null;
|
|
39875
|
+
const server = new Server({ name: PREVIEW_MCP_SERVER_NAME, version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
39876
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: PREVIEW_TOOLS }));
|
|
39877
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
39878
|
+
if (!call) {
|
|
39879
|
+
return {
|
|
39880
|
+
content: [{ type: "text", text: "Preview is not available in this session." }],
|
|
39881
|
+
isError: true
|
|
39882
|
+
};
|
|
39883
|
+
}
|
|
39884
|
+
try {
|
|
39885
|
+
const { text, isError: isError2 } = await runPreviewTool(
|
|
39886
|
+
req.params.name,
|
|
39887
|
+
req.params.arguments ?? {},
|
|
39888
|
+
call
|
|
39889
|
+
);
|
|
39890
|
+
return { content: [{ type: "text", text }], isError: isError2 };
|
|
39891
|
+
} catch (err) {
|
|
39892
|
+
const aborted = err instanceof Error && err.name === "AbortError";
|
|
39893
|
+
return {
|
|
39894
|
+
content: [
|
|
39895
|
+
{
|
|
39896
|
+
type: "text",
|
|
39897
|
+
text: aborted ? "The preview is taking long \u2014 it keeps going in the background; call preview_status shortly." : `Preview bridge unreachable: ${err instanceof Error ? err.message : String(err)}`
|
|
39898
|
+
}
|
|
39899
|
+
],
|
|
39900
|
+
isError: !aborted
|
|
39901
|
+
};
|
|
39902
|
+
}
|
|
39903
|
+
});
|
|
39904
|
+
await server.connect(new StdioServerTransport());
|
|
39905
|
+
}
|
|
39906
|
+
|
|
39348
39907
|
// src/integrations/provision.ts
|
|
39908
|
+
function secretVars(ctx) {
|
|
39909
|
+
return {
|
|
39910
|
+
...ctx.pluginAuthToken ? { CODEAM_MCP_PLUGIN_TOKEN: ctx.pluginAuthToken } : {},
|
|
39911
|
+
...ctx.pollSecret ? { CODEAM_MCP_POLL_SECRET: ctx.pollSecret } : {}
|
|
39912
|
+
};
|
|
39913
|
+
}
|
|
39349
39914
|
function buildMcpServersForStart(ctx) {
|
|
39915
|
+
const servers = buildIntegrationMcpServers(ctx);
|
|
39916
|
+
const preview = previewMcpServer(ctx.preview ?? null);
|
|
39917
|
+
return preview ? [...servers, preview] : servers;
|
|
39918
|
+
}
|
|
39919
|
+
function buildIntegrationMcpServers(ctx) {
|
|
39350
39920
|
const manifest = readIntegrationsManifest();
|
|
39351
39921
|
if (!manifest || manifest.integrations.length === 0) return [];
|
|
39352
39922
|
if (!ctx.pluginAuthToken) {
|
|
@@ -39360,9 +39930,10 @@ function buildMcpServersForStart(ctx) {
|
|
|
39360
39930
|
{ name: "CODEAM_MCP_INTEGRATION_ID", value: entry.id },
|
|
39361
39931
|
{ name: "CODEAM_MCP_SESSION_ID", value: ctx.sessionId },
|
|
39362
39932
|
{ name: "CODEAM_MCP_PLUGIN_ID", value: ctx.pluginId },
|
|
39363
|
-
//
|
|
39364
|
-
|
|
39365
|
-
|
|
39933
|
+
// ⚠️ Secrets via an owner-only FILE, not env values: the claude ACP
|
|
39934
|
+
// adapter copies this env onto the agent's argv (`--mcp-config`), where
|
|
39935
|
+
// `ps` shows it (codeagent-5bew). See `mcp-secrets.ts`.
|
|
39936
|
+
...mcpSecretEnv("integrations", secretVars(ctx))
|
|
39366
39937
|
];
|
|
39367
39938
|
servers.push({
|
|
39368
39939
|
name: entry.id,
|
|
@@ -39391,8 +39962,7 @@ function buildMcpServersForStart(ctx) {
|
|
|
39391
39962
|
env: [
|
|
39392
39963
|
{ name: "CODEAM_MCP_SESSION_ID", value: ctx.sessionId },
|
|
39393
39964
|
{ name: "CODEAM_MCP_PLUGIN_ID", value: ctx.pluginId },
|
|
39394
|
-
|
|
39395
|
-
...ctx.pollSecret ? [{ name: "CODEAM_MCP_POLL_SECRET", value: ctx.pollSecret }] : []
|
|
39965
|
+
...mcpSecretEnv("integrations", secretVars(ctx))
|
|
39396
39966
|
]
|
|
39397
39967
|
}
|
|
39398
39968
|
];
|
|
@@ -39518,6 +40088,299 @@ function mergeWithLocalMcpServers(integrationServers) {
|
|
|
39518
40088
|
return merged;
|
|
39519
40089
|
}
|
|
39520
40090
|
|
|
40091
|
+
// src/commands/start/agent-preview-bridge.ts
|
|
40092
|
+
var http11 = __toESM(require("http"));
|
|
40093
|
+
var import_node_crypto10 = require("crypto");
|
|
40094
|
+
var START_WAIT_MS = 24e4;
|
|
40095
|
+
var MAX_SELECTOR = 500;
|
|
40096
|
+
var MAX_LABEL = 80;
|
|
40097
|
+
var AgentPreviewBridge = class {
|
|
40098
|
+
server = null;
|
|
40099
|
+
listening = null;
|
|
40100
|
+
token = (0, import_node_crypto10.randomBytes)(24).toString("hex");
|
|
40101
|
+
ctx = null;
|
|
40102
|
+
/** The bring-up in flight, so two tool calls never start two dev servers. */
|
|
40103
|
+
inflight = null;
|
|
40104
|
+
lastError = null;
|
|
40105
|
+
bound = null;
|
|
40106
|
+
/** Start the loopback server once. `null` when it could not bind — the
|
|
40107
|
+
* preview tools are then simply absent, never a failed session. */
|
|
40108
|
+
listen() {
|
|
40109
|
+
if (this.listening) return this.listening;
|
|
40110
|
+
this.listening = new Promise((resolve12) => {
|
|
40111
|
+
const server = http11.createServer((req, res) => {
|
|
40112
|
+
void this.handle(req, res);
|
|
40113
|
+
});
|
|
40114
|
+
server.on("error", (err) => {
|
|
40115
|
+
log.warn("agent-preview", `bridge failed to listen: ${String(err)}`);
|
|
40116
|
+
resolve12(null);
|
|
40117
|
+
});
|
|
40118
|
+
server.listen(0, "127.0.0.1", () => {
|
|
40119
|
+
const addr = server.address();
|
|
40120
|
+
if (!addr || typeof addr === "string") {
|
|
40121
|
+
resolve12(null);
|
|
40122
|
+
return;
|
|
40123
|
+
}
|
|
40124
|
+
server.unref();
|
|
40125
|
+
this.server = server;
|
|
40126
|
+
this.bound = { url: `http://127.0.0.1:${addr.port}`, token: this.token };
|
|
40127
|
+
resolve12(this.bound);
|
|
40128
|
+
});
|
|
40129
|
+
});
|
|
40130
|
+
return this.listening;
|
|
40131
|
+
}
|
|
40132
|
+
/** The bound address once {@link listen} resolved, else null (sync, for
|
|
40133
|
+
* the MCP list rebuilds that happen mid-session). */
|
|
40134
|
+
address() {
|
|
40135
|
+
return this.bound;
|
|
40136
|
+
}
|
|
40137
|
+
/** Bind the live session. Tool calls before this answer "still starting". */
|
|
40138
|
+
attach(ctx) {
|
|
40139
|
+
this.ctx = ctx;
|
|
40140
|
+
}
|
|
40141
|
+
close() {
|
|
40142
|
+
this.server?.close();
|
|
40143
|
+
this.server = null;
|
|
40144
|
+
}
|
|
40145
|
+
// ─── Operations (public for tests) ─────────────────────────────────────
|
|
40146
|
+
async start(override, waitMs = START_WAIT_MS) {
|
|
40147
|
+
const ctx = this.ctx;
|
|
40148
|
+
if (!ctx?.pluginAuthToken) {
|
|
40149
|
+
return {
|
|
40150
|
+
status: "error",
|
|
40151
|
+
stage: "session",
|
|
40152
|
+
message: "The session is still starting (or has no pairing token) \u2014 try again in a few seconds."
|
|
40153
|
+
};
|
|
40154
|
+
}
|
|
40155
|
+
if (!this.inflight) {
|
|
40156
|
+
const run = this.launch(ctx, ctx.pluginAuthToken, override);
|
|
40157
|
+
this.inflight = run;
|
|
40158
|
+
void run.finally(() => {
|
|
40159
|
+
if (this.inflight === run) this.inflight = null;
|
|
40160
|
+
});
|
|
40161
|
+
}
|
|
40162
|
+
const inflight = this.inflight;
|
|
40163
|
+
let timer;
|
|
40164
|
+
const pending = new Promise((resolve12) => {
|
|
40165
|
+
timer = setTimeout(
|
|
40166
|
+
() => resolve12({
|
|
40167
|
+
status: "starting",
|
|
40168
|
+
message: "The preview is still coming up (dependencies or a slow dev server). It keeps going in the background \u2014 call preview_status in a minute."
|
|
40169
|
+
}),
|
|
40170
|
+
waitMs
|
|
40171
|
+
);
|
|
40172
|
+
timer.unref?.();
|
|
40173
|
+
});
|
|
40174
|
+
try {
|
|
40175
|
+
return await Promise.race([inflight, pending]);
|
|
40176
|
+
} finally {
|
|
40177
|
+
if (timer) clearTimeout(timer);
|
|
40178
|
+
}
|
|
40179
|
+
}
|
|
40180
|
+
status() {
|
|
40181
|
+
const ctx = this.ctx;
|
|
40182
|
+
if (!ctx) return { status: "idle" };
|
|
40183
|
+
const active2 = serving(ctx.sessionId);
|
|
40184
|
+
if (active2) return running(active2, true);
|
|
40185
|
+
if (this.inflight) return { status: "starting", message: "The preview is starting." };
|
|
40186
|
+
if (this.lastError) return { status: "error", ...this.lastError };
|
|
40187
|
+
return { status: "idle" };
|
|
40188
|
+
}
|
|
40189
|
+
async highlight(input) {
|
|
40190
|
+
const ctx = this.ctx;
|
|
40191
|
+
if (!ctx?.pluginAuthToken) return { ok: false, message: "The session is still starting." };
|
|
40192
|
+
const active2 = serving(ctx.sessionId);
|
|
40193
|
+
if (!active2) {
|
|
40194
|
+
return { ok: false, message: "No preview is running \u2014 call start_preview first." };
|
|
40195
|
+
}
|
|
40196
|
+
if (!active2.inspector) {
|
|
40197
|
+
return {
|
|
40198
|
+
ok: false,
|
|
40199
|
+
message: `Element highlighting needs the web inspector, which ${active2.framework} previews don't have.`
|
|
40200
|
+
};
|
|
40201
|
+
}
|
|
40202
|
+
let payload;
|
|
40203
|
+
if (input.clear === true) {
|
|
40204
|
+
payload = { clear: true };
|
|
40205
|
+
} else {
|
|
40206
|
+
const selector = typeof input.selector === "string" ? input.selector.trim() : "";
|
|
40207
|
+
if (!selector || selector.length > MAX_SELECTOR) {
|
|
40208
|
+
return { ok: false, message: `selector must be a CSS selector of 1-${MAX_SELECTOR} characters.` };
|
|
40209
|
+
}
|
|
40210
|
+
const label = typeof input.label === "string" ? input.label.trim().slice(0, MAX_LABEL) : "";
|
|
40211
|
+
payload = label ? { selector, label } : { selector };
|
|
40212
|
+
}
|
|
40213
|
+
const res = await postPreviewEvent({
|
|
40214
|
+
sessionId: ctx.sessionId,
|
|
40215
|
+
pluginId: ctx.pluginId,
|
|
40216
|
+
pluginAuthToken: ctx.pluginAuthToken,
|
|
40217
|
+
type: USER_EVENTS.PREVIEW_AGENT_HIGHLIGHT,
|
|
40218
|
+
payload
|
|
40219
|
+
});
|
|
40220
|
+
if (!res.ok) {
|
|
40221
|
+
return { ok: false, message: `Could not reach the app (${res.status}): ${res.message}` };
|
|
40222
|
+
}
|
|
40223
|
+
return {
|
|
40224
|
+
ok: true,
|
|
40225
|
+
message: payload.clear === true ? "Cleared your marks from the preview." : `Marked ${String(payload.selector)} in the user's preview. If the selector matches nothing, no mark appears.`
|
|
40226
|
+
};
|
|
40227
|
+
}
|
|
40228
|
+
async stop() {
|
|
40229
|
+
const ctx = this.ctx;
|
|
40230
|
+
if (!ctx?.pluginAuthToken) return { ok: false, message: "The session is still starting." };
|
|
40231
|
+
if (!activePreviews.has(ctx.sessionId)) return { ok: true, message: "No preview was running." };
|
|
40232
|
+
await killPreview(ctx.sessionId);
|
|
40233
|
+
resetBuildHealState(ctx.sessionId);
|
|
40234
|
+
await postPreviewEvent({
|
|
40235
|
+
sessionId: ctx.sessionId,
|
|
40236
|
+
pluginId: ctx.pluginId,
|
|
40237
|
+
pluginAuthToken: ctx.pluginAuthToken,
|
|
40238
|
+
type: USER_EVENTS.PREVIEW_STOPPED,
|
|
40239
|
+
payload: { reason: "user", origin: "agent" }
|
|
40240
|
+
});
|
|
40241
|
+
return { ok: true, message: "Preview stopped." };
|
|
40242
|
+
}
|
|
40243
|
+
// ─── Internals ─────────────────────────────────────────────────────────
|
|
40244
|
+
async launch(ctx, pluginAuthToken, override) {
|
|
40245
|
+
this.lastError = null;
|
|
40246
|
+
const already = serving(ctx.sessionId);
|
|
40247
|
+
if (already) {
|
|
40248
|
+
await postPreviewEvent({
|
|
40249
|
+
sessionId: ctx.sessionId,
|
|
40250
|
+
pluginId: ctx.pluginId,
|
|
40251
|
+
pluginAuthToken,
|
|
40252
|
+
type: USER_EVENTS.PREVIEW_READY,
|
|
40253
|
+
payload: {
|
|
40254
|
+
url: already.url,
|
|
40255
|
+
framework: already.framework,
|
|
40256
|
+
port: already.detection.port,
|
|
40257
|
+
origin: "agent"
|
|
40258
|
+
}
|
|
40259
|
+
});
|
|
40260
|
+
return running(already, true);
|
|
40261
|
+
}
|
|
40262
|
+
void postPreviewEvent({
|
|
40263
|
+
sessionId: ctx.sessionId,
|
|
40264
|
+
pluginId: ctx.pluginId,
|
|
40265
|
+
pluginAuthToken,
|
|
40266
|
+
type: USER_EVENTS.PREVIEW_DETECTION_PENDING,
|
|
40267
|
+
payload: { origin: "agent" }
|
|
40268
|
+
});
|
|
40269
|
+
const detection = (override && detectionFromOverride(override)) ?? await resolvePreviewDetection({ ctx, runtime: ctx.getRuntime(), pluginAuthToken, origin: "agent" });
|
|
40270
|
+
if (!detection) {
|
|
40271
|
+
const err2 = { stage: "detection", message: "Could not work out how to start this project." };
|
|
40272
|
+
this.lastError = err2;
|
|
40273
|
+
return { status: "error", ...err2 };
|
|
40274
|
+
}
|
|
40275
|
+
let failure = null;
|
|
40276
|
+
await startPreviewFromDetection(ctx, detection, pluginAuthToken, {
|
|
40277
|
+
origin: "agent",
|
|
40278
|
+
onEvent: (type, payload) => {
|
|
40279
|
+
if (type === USER_EVENTS.PREVIEW_ERROR) {
|
|
40280
|
+
failure = {
|
|
40281
|
+
stage: String(payload.stage ?? "spawn"),
|
|
40282
|
+
message: String(payload.message ?? "The preview failed to start.")
|
|
40283
|
+
};
|
|
40284
|
+
}
|
|
40285
|
+
}
|
|
40286
|
+
});
|
|
40287
|
+
const up = serving(ctx.sessionId);
|
|
40288
|
+
if (up) return running(up, false);
|
|
40289
|
+
const err = failure ?? { stage: "spawn", message: "The preview did not come up." };
|
|
40290
|
+
this.lastError = err;
|
|
40291
|
+
return { status: "error", ...err };
|
|
40292
|
+
}
|
|
40293
|
+
async handle(req, res) {
|
|
40294
|
+
const reply = (code, body) => {
|
|
40295
|
+
res.writeHead(code, { "content-type": "application/json" });
|
|
40296
|
+
res.end(JSON.stringify(body));
|
|
40297
|
+
};
|
|
40298
|
+
if (!authorized(req.headers.authorization, this.token)) return reply(401, { error: "unauthorized" });
|
|
40299
|
+
try {
|
|
40300
|
+
const body = req.method === "POST" ? await readJson(req) : {};
|
|
40301
|
+
switch (`${req.method} ${req.url}`) {
|
|
40302
|
+
case "POST /preview/start":
|
|
40303
|
+
return reply(200, await this.start(overrideFrom(body)));
|
|
40304
|
+
case "GET /preview/status":
|
|
40305
|
+
return reply(200, this.status());
|
|
40306
|
+
case "POST /preview/highlight":
|
|
40307
|
+
return reply(200, await this.highlight(body));
|
|
40308
|
+
case "POST /preview/stop":
|
|
40309
|
+
return reply(200, await this.stop());
|
|
40310
|
+
default:
|
|
40311
|
+
return reply(404, { error: "not found" });
|
|
40312
|
+
}
|
|
40313
|
+
} catch (err) {
|
|
40314
|
+
log.warn("agent-preview", `bridge request failed: ${String(err)}`);
|
|
40315
|
+
return reply(500, { error: err instanceof Error ? err.message : String(err) });
|
|
40316
|
+
}
|
|
40317
|
+
}
|
|
40318
|
+
};
|
|
40319
|
+
function serving(sessionId) {
|
|
40320
|
+
const active2 = activePreviews.get(sessionId);
|
|
40321
|
+
if (!active2 || active2.devServer && active2.devServer.exitCode !== null) return null;
|
|
40322
|
+
return active2;
|
|
40323
|
+
}
|
|
40324
|
+
function running(active2, reused) {
|
|
40325
|
+
return {
|
|
40326
|
+
status: "running",
|
|
40327
|
+
url: active2.url,
|
|
40328
|
+
framework: active2.framework,
|
|
40329
|
+
...reused ? { reused: true } : {},
|
|
40330
|
+
inspector: Boolean(active2.inspector)
|
|
40331
|
+
};
|
|
40332
|
+
}
|
|
40333
|
+
function detectionFromOverride(o) {
|
|
40334
|
+
if (!o.command || !Number.isInteger(o.port) || o.port <= 0 || o.port > 65535) return null;
|
|
40335
|
+
return {
|
|
40336
|
+
framework: o.framework?.trim() || "custom",
|
|
40337
|
+
command: o.command,
|
|
40338
|
+
args: Array.isArray(o.args) ? o.args.map(String) : [],
|
|
40339
|
+
port: o.port,
|
|
40340
|
+
// Any Local/ready/listening line; the TCP probe is the real fallback.
|
|
40341
|
+
ready_pattern: o.ready_pattern?.trim() || "(ready|local:|listening|started server|compiled)"
|
|
40342
|
+
};
|
|
40343
|
+
}
|
|
40344
|
+
function overrideFrom(body) {
|
|
40345
|
+
if (typeof body.command !== "string" || typeof body.port !== "number") return void 0;
|
|
40346
|
+
return {
|
|
40347
|
+
command: body.command,
|
|
40348
|
+
args: Array.isArray(body.args) ? body.args.map(String) : void 0,
|
|
40349
|
+
port: body.port,
|
|
40350
|
+
framework: typeof body.framework === "string" ? body.framework : void 0,
|
|
40351
|
+
ready_pattern: typeof body.ready_pattern === "string" ? body.ready_pattern : void 0
|
|
40352
|
+
};
|
|
40353
|
+
}
|
|
40354
|
+
function authorized(header, token) {
|
|
40355
|
+
const presented = Buffer.from((header ?? "").replace(/^Bearer\s+/i, ""));
|
|
40356
|
+
const expected = Buffer.from(token);
|
|
40357
|
+
return presented.length === expected.length && (0, import_node_crypto10.timingSafeEqual)(presented, expected);
|
|
40358
|
+
}
|
|
40359
|
+
function readJson(req) {
|
|
40360
|
+
return new Promise((resolve12, reject) => {
|
|
40361
|
+
let raw = "";
|
|
40362
|
+
req.setEncoding("utf8");
|
|
40363
|
+
req.on("data", (chunk) => {
|
|
40364
|
+
raw += chunk;
|
|
40365
|
+
if (raw.length > 64e3) {
|
|
40366
|
+
reject(new Error("body too large"));
|
|
40367
|
+
req.destroy();
|
|
40368
|
+
}
|
|
40369
|
+
});
|
|
40370
|
+
req.on("end", () => {
|
|
40371
|
+
if (!raw) return resolve12({});
|
|
40372
|
+
try {
|
|
40373
|
+
const parsed = JSON.parse(raw);
|
|
40374
|
+
resolve12(parsed && typeof parsed === "object" ? parsed : {});
|
|
40375
|
+
} catch {
|
|
40376
|
+
reject(new Error("invalid JSON"));
|
|
40377
|
+
}
|
|
40378
|
+
});
|
|
40379
|
+
req.on("error", reject);
|
|
40380
|
+
});
|
|
40381
|
+
}
|
|
40382
|
+
var agentPreviewBridge = new AgentPreviewBridge();
|
|
40383
|
+
|
|
39521
40384
|
// src/integrations/detect-stack.ts
|
|
39522
40385
|
var import_node_fs13 = __toESM(require("fs"));
|
|
39523
40386
|
var import_node_path13 = __toESM(require("path"));
|
|
@@ -39669,7 +40532,7 @@ function logMentionOutcome(result) {
|
|
|
39669
40532
|
}
|
|
39670
40533
|
|
|
39671
40534
|
// src/agents/acp/command-handlers.ts
|
|
39672
|
-
var
|
|
40535
|
+
var import_node_child_process24 = require("child_process");
|
|
39673
40536
|
|
|
39674
40537
|
// src/agents/acp/buildAcpPromptBlocks.ts
|
|
39675
40538
|
var MIME_FROM_EXT = {
|
|
@@ -40631,7 +41494,7 @@ async function prewarmNewMcpEntries(manifest, previousIds) {
|
|
|
40631
41494
|
fresh.map(
|
|
40632
41495
|
(e) => new Promise((resolve12) => {
|
|
40633
41496
|
const mcp = e.delivery.mcp;
|
|
40634
|
-
const child = (0,
|
|
41497
|
+
const child = (0, import_node_child_process24.execFile)(
|
|
40635
41498
|
mcp.command,
|
|
40636
41499
|
[...mcp.args, "--help"],
|
|
40637
41500
|
{ timeout: 9e4 },
|
|
@@ -40658,7 +41521,8 @@ async function integrationsSyncH(ctx) {
|
|
|
40658
41521
|
sessionId: opts.sessionId,
|
|
40659
41522
|
pluginId: opts.pluginId,
|
|
40660
41523
|
pluginAuthToken: opts.pluginAuthToken,
|
|
40661
|
-
pollSecret: opts.pollSecret
|
|
41524
|
+
pollSecret: opts.pollSecret,
|
|
41525
|
+
preview: agentPreviewBridge.address()
|
|
40662
41526
|
})
|
|
40663
41527
|
);
|
|
40664
41528
|
const applied = await client3.reprovisionMcp(servers);
|
|
@@ -41295,7 +42159,7 @@ var AcpHistory = class {
|
|
|
41295
42159
|
this.summary = trimmed.length > 120 ? trimmed.slice(0, 117) + "\u2026" : trimmed;
|
|
41296
42160
|
}
|
|
41297
42161
|
this.messages.push({
|
|
41298
|
-
id: (0,
|
|
42162
|
+
id: (0, import_node_crypto11.randomUUID)(),
|
|
41299
42163
|
role: "user",
|
|
41300
42164
|
text,
|
|
41301
42165
|
timestamp: Date.now(),
|
|
@@ -41311,7 +42175,7 @@ var AcpHistory = class {
|
|
|
41311
42175
|
appendAgentReply(text, agentId = this.opts.agent) {
|
|
41312
42176
|
if (text.length === 0) return;
|
|
41313
42177
|
this.messages.push({
|
|
41314
|
-
id: (0,
|
|
42178
|
+
id: (0, import_node_crypto11.randomUUID)(),
|
|
41315
42179
|
role: "agent",
|
|
41316
42180
|
text,
|
|
41317
42181
|
timestamp: Date.now(),
|
|
@@ -41799,11 +42663,11 @@ async function runAcpSession(opts) {
|
|
|
41799
42663
|
if (swapOpts.house) {
|
|
41800
42664
|
houseWireId = swapOpts.wireId ?? HOUSE_AGENT_ID;
|
|
41801
42665
|
if (pendingHouseConfig) {
|
|
41802
|
-
persistHouseProxyConfig(pendingHouseConfig);
|
|
42666
|
+
persistHouseProxyConfig(pendingHouseConfig, deployIdFromWorkspace(process.cwd()) ?? void 0);
|
|
41803
42667
|
pendingHouseConfig = null;
|
|
41804
42668
|
}
|
|
41805
42669
|
} else if (wasHouse) {
|
|
41806
|
-
clearHouseProxyConfig();
|
|
42670
|
+
clearHouseProxyConfig(deployIdFromWorkspace(process.cwd()) ?? void 0);
|
|
41807
42671
|
}
|
|
41808
42672
|
const managedBanner = swapOpts.house && isManagedProviderId(houseWireId) ? houseWireId : null;
|
|
41809
42673
|
void publisher.publishOutput({
|
|
@@ -41842,17 +42706,17 @@ async function runAcpSession(opts) {
|
|
|
41842
42706
|
switchCredentialEnv = provisionAgentCredentials(agentId, auth);
|
|
41843
42707
|
},
|
|
41844
42708
|
provisionHouseProxy: ({ baseUrl, token, model, managedAgentId }) => {
|
|
41845
|
-
const claudeConfigDir =
|
|
41846
|
-
|
|
42709
|
+
const claudeConfigDir = path82.join(
|
|
42710
|
+
os55.homedir(),
|
|
41847
42711
|
".codeam",
|
|
41848
42712
|
"house-claude",
|
|
41849
42713
|
`switch-${opts.pluginId}`
|
|
41850
42714
|
);
|
|
41851
42715
|
try {
|
|
41852
|
-
|
|
42716
|
+
fs71.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
|
|
41853
42717
|
} catch {
|
|
41854
42718
|
}
|
|
41855
|
-
const memoryFile =
|
|
42719
|
+
const memoryFile = path82.join(claudeConfigDir, "CLAUDE.md");
|
|
41856
42720
|
ensureBeadsWorkflowHint(void 0, memoryFile);
|
|
41857
42721
|
ensureAgentStandard(void 0, memoryFile);
|
|
41858
42722
|
const cfg = {
|
|
@@ -43075,9 +43939,9 @@ function pickPinnedSession(pinnedId, listSessions2) {
|
|
|
43075
43939
|
}
|
|
43076
43940
|
|
|
43077
43941
|
// src/agents/retired-proxy-cleanup.ts
|
|
43078
|
-
var
|
|
43079
|
-
var
|
|
43080
|
-
var
|
|
43942
|
+
var fs72 = __toESM(require("fs"));
|
|
43943
|
+
var path83 = __toESM(require("path"));
|
|
43944
|
+
var os56 = __toESM(require("os"));
|
|
43081
43945
|
var RETIRED_PROXY_RE = /^https?:\/\/(?:127\.0\.0\.1|localhost|\[::1\]):8787(?:[/?#]|$)/i;
|
|
43082
43946
|
var HEADROOM_CMD_RE = /(^|[\s/"'])headroom(\s|$)/i;
|
|
43083
43947
|
var MARKETPLACE_KEY = "headroom-marketplace";
|
|
@@ -43086,12 +43950,12 @@ function isHeadroomHook(group) {
|
|
|
43086
43950
|
(h) => typeof h?.command === "string" && HEADROOM_CMD_RE.test(h.command)
|
|
43087
43951
|
);
|
|
43088
43952
|
}
|
|
43089
|
-
function sanitizeRetiredProxyConfig(homeDir2 =
|
|
43953
|
+
function sanitizeRetiredProxyConfig(homeDir2 = os56.homedir()) {
|
|
43090
43954
|
const out2 = { inspected: false, changed: false, removed: [] };
|
|
43091
|
-
const file =
|
|
43955
|
+
const file = path83.join(homeDir2, ".claude", "settings.json");
|
|
43092
43956
|
let parsed;
|
|
43093
43957
|
try {
|
|
43094
|
-
parsed = JSON.parse(
|
|
43958
|
+
parsed = JSON.parse(fs72.readFileSync(file, "utf8"));
|
|
43095
43959
|
} catch {
|
|
43096
43960
|
return out2;
|
|
43097
43961
|
}
|
|
@@ -43133,9 +43997,9 @@ function sanitizeRetiredProxyConfig(homeDir2 = os54.homedir()) {
|
|
|
43133
43997
|
if (!out2.changed) return out2;
|
|
43134
43998
|
try {
|
|
43135
43999
|
const tmp = `${file}.codeam.tmp`;
|
|
43136
|
-
|
|
44000
|
+
fs72.writeFileSync(tmp, `${JSON.stringify(parsed, null, 2)}
|
|
43137
44001
|
`, { mode: 384 });
|
|
43138
|
-
|
|
44002
|
+
fs72.renameSync(tmp, file);
|
|
43139
44003
|
} catch {
|
|
43140
44004
|
out2.changed = false;
|
|
43141
44005
|
}
|
|
@@ -43667,7 +44531,7 @@ var AcpDriver = class {
|
|
|
43667
44531
|
};
|
|
43668
44532
|
|
|
43669
44533
|
// src/baton/transcript-mirror.ts
|
|
43670
|
-
var
|
|
44534
|
+
var fs73 = __toESM(require("fs"));
|
|
43671
44535
|
var TranscriptMirror = class {
|
|
43672
44536
|
constructor(deps) {
|
|
43673
44537
|
this.deps = deps;
|
|
@@ -43761,7 +44625,7 @@ var TranscriptMirror = class {
|
|
|
43761
44625
|
}
|
|
43762
44626
|
};
|
|
43763
44627
|
function defaultWatch(file, onChange) {
|
|
43764
|
-
const w3 =
|
|
44628
|
+
const w3 = fs73.watch(file, { persistent: false }, () => onChange());
|
|
43765
44629
|
return () => w3.close();
|
|
43766
44630
|
}
|
|
43767
44631
|
|
|
@@ -44071,7 +44935,7 @@ function toEpochMs(ts) {
|
|
|
44071
44935
|
}
|
|
44072
44936
|
|
|
44073
44937
|
// src/services/keep-awake.ts
|
|
44074
|
-
var
|
|
44938
|
+
var import_node_child_process25 = require("child_process");
|
|
44075
44939
|
function keepDeviceAwake(deps = {}) {
|
|
44076
44940
|
const env = deps.env ?? process.env;
|
|
44077
44941
|
const isLocal = deps.isLocal ?? isLocalSession(env);
|
|
@@ -44081,7 +44945,7 @@ function keepDeviceAwake(deps = {}) {
|
|
|
44081
44945
|
if (env.CODEAM_NO_KEEP_AWAKE === "1") return noop;
|
|
44082
44946
|
const command2 = deps.command !== void 0 ? deps.command : createOsStrategy().keepAwakeCommand(deps.pid ?? process.pid);
|
|
44083
44947
|
if (!command2) return noop;
|
|
44084
|
-
const spawnFn = deps.spawnFn ??
|
|
44948
|
+
const spawnFn = deps.spawnFn ?? import_node_child_process25.spawn;
|
|
44085
44949
|
let child = null;
|
|
44086
44950
|
try {
|
|
44087
44951
|
child = spawnFn(command2.cmd, command2.args, { stdio: "ignore", detached: true });
|
|
@@ -44107,16 +44971,16 @@ function keepDeviceAwake(deps = {}) {
|
|
|
44107
44971
|
}
|
|
44108
44972
|
|
|
44109
44973
|
// src/agents/claude/onboarding.ts
|
|
44110
|
-
var
|
|
44111
|
-
var
|
|
44112
|
-
var
|
|
44974
|
+
var fs74 = __toESM(require("fs"));
|
|
44975
|
+
var os58 = __toESM(require("os"));
|
|
44976
|
+
var path84 = __toESM(require("path"));
|
|
44113
44977
|
var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
|
|
44114
44978
|
function ensureClaudeOnboarded(cwd) {
|
|
44115
44979
|
try {
|
|
44116
|
-
const file =
|
|
44980
|
+
const file = path84.join(os58.homedir(), ".claude.json");
|
|
44117
44981
|
let config = {};
|
|
44118
44982
|
try {
|
|
44119
|
-
config = JSON.parse(
|
|
44983
|
+
config = JSON.parse(fs74.readFileSync(file, "utf8"));
|
|
44120
44984
|
} catch {
|
|
44121
44985
|
}
|
|
44122
44986
|
let changed = false;
|
|
@@ -44141,8 +45005,8 @@ function ensureClaudeOnboarded(cwd) {
|
|
|
44141
45005
|
}
|
|
44142
45006
|
}
|
|
44143
45007
|
if (!changed) return;
|
|
44144
|
-
|
|
44145
|
-
|
|
45008
|
+
fs74.mkdirSync(path84.dirname(file), { recursive: true });
|
|
45009
|
+
fs74.writeFileSync(file, JSON.stringify(config, null, 2));
|
|
44146
45010
|
log.info(
|
|
44147
45011
|
"claude",
|
|
44148
45012
|
`pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
|
|
@@ -44265,12 +45129,20 @@ async function start(requestedAgent, presetSession) {
|
|
|
44265
45129
|
agent: isHouseProxyEnv(process.env) ? houseRailWireId(process.env) : session.agent
|
|
44266
45130
|
});
|
|
44267
45131
|
}
|
|
45132
|
+
const previewBridge = await agentPreviewBridge.listen();
|
|
45133
|
+
agentPreviewBridge.attach({
|
|
45134
|
+
sessionId: session.id,
|
|
45135
|
+
pluginId,
|
|
45136
|
+
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
45137
|
+
getRuntime: () => createInteractiveAgentStrategy(session.agent, createOsStrategy())
|
|
45138
|
+
});
|
|
44268
45139
|
const mcpServers = mergeWithLocalMcpServers(
|
|
44269
45140
|
buildMcpServersForStart({
|
|
44270
45141
|
sessionId: session.id,
|
|
44271
45142
|
pluginId,
|
|
44272
45143
|
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
44273
|
-
pollSecret: session.pollSecret
|
|
45144
|
+
pollSecret: session.pollSecret,
|
|
45145
|
+
preview: previewBridge
|
|
44274
45146
|
})
|
|
44275
45147
|
);
|
|
44276
45148
|
provisionSkillsForStart();
|
|
@@ -44911,8 +45783,8 @@ var import_picocolors10 = __toESM(require("picocolors"));
|
|
|
44911
45783
|
var import_child_process30 = require("child_process");
|
|
44912
45784
|
var import_util4 = require("util");
|
|
44913
45785
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
44914
|
-
var
|
|
44915
|
-
var
|
|
45786
|
+
var path85 = __toESM(require("path"));
|
|
45787
|
+
var execFileP6 = (0, import_util4.promisify)(import_child_process30.execFile);
|
|
44916
45788
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
44917
45789
|
function resetStdinForChild() {
|
|
44918
45790
|
if (process.stdin.isTTY) {
|
|
@@ -44929,11 +45801,11 @@ var GitHubCodespacesProvider = class {
|
|
|
44929
45801
|
available = true;
|
|
44930
45802
|
async authorize() {
|
|
44931
45803
|
try {
|
|
44932
|
-
await
|
|
45804
|
+
await execFileP6("gh", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
44933
45805
|
} catch {
|
|
44934
45806
|
await this.tryInstallGh();
|
|
44935
45807
|
try {
|
|
44936
|
-
await
|
|
45808
|
+
await execFileP6("gh", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
44937
45809
|
} catch {
|
|
44938
45810
|
throw new Error(
|
|
44939
45811
|
[
|
|
@@ -44949,7 +45821,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44949
45821
|
}
|
|
44950
45822
|
let isAuthed = false;
|
|
44951
45823
|
try {
|
|
44952
|
-
await
|
|
45824
|
+
await execFileP6("gh", ["auth", "status"], { maxBuffer: MAX_BUFFER });
|
|
44953
45825
|
isAuthed = true;
|
|
44954
45826
|
} catch {
|
|
44955
45827
|
}
|
|
@@ -45025,7 +45897,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45025
45897
|
*/
|
|
45026
45898
|
async getActiveGhUser() {
|
|
45027
45899
|
try {
|
|
45028
|
-
const { stdout } = await
|
|
45900
|
+
const { stdout } = await execFileP6(
|
|
45029
45901
|
"gh",
|
|
45030
45902
|
["api", "user", "--jq", ".login"],
|
|
45031
45903
|
{ maxBuffer: MAX_BUFFER }
|
|
@@ -45045,7 +45917,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45045
45917
|
*/
|
|
45046
45918
|
async hasCodespaceScope() {
|
|
45047
45919
|
try {
|
|
45048
|
-
const { stdout } = await
|
|
45920
|
+
const { stdout } = await execFileP6(
|
|
45049
45921
|
"gh",
|
|
45050
45922
|
["api", "-i", "user"],
|
|
45051
45923
|
{ maxBuffer: MAX_BUFFER }
|
|
@@ -45094,7 +45966,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45094
45966
|
let installCmd = null;
|
|
45095
45967
|
if (platform3 === "darwin") {
|
|
45096
45968
|
try {
|
|
45097
|
-
await
|
|
45969
|
+
await execFileP6("brew", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
45098
45970
|
} catch {
|
|
45099
45971
|
wt(
|
|
45100
45972
|
[
|
|
@@ -45113,7 +45985,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45113
45985
|
};
|
|
45114
45986
|
} else if (platform3 === "win32") {
|
|
45115
45987
|
try {
|
|
45116
|
-
await
|
|
45988
|
+
await execFileP6("winget", ["--version"], { maxBuffer: MAX_BUFFER });
|
|
45117
45989
|
} catch {
|
|
45118
45990
|
wt(
|
|
45119
45991
|
[
|
|
@@ -45192,7 +46064,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45192
46064
|
"200"
|
|
45193
46065
|
);
|
|
45194
46066
|
try {
|
|
45195
|
-
const { stdout } = await
|
|
46067
|
+
const { stdout } = await execFileP6("gh", args2, { maxBuffer: MAX_BUFFER });
|
|
45196
46068
|
return JSON.parse(stdout);
|
|
45197
46069
|
} catch {
|
|
45198
46070
|
return [];
|
|
@@ -45201,7 +46073,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45201
46073
|
const own = await fetchRepos();
|
|
45202
46074
|
let orgRepos = [];
|
|
45203
46075
|
try {
|
|
45204
|
-
const { stdout } = await
|
|
46076
|
+
const { stdout } = await execFileP6(
|
|
45205
46077
|
"gh",
|
|
45206
46078
|
["api", "--paginate", "user/orgs", "--jq", ".[].login"],
|
|
45207
46079
|
{ maxBuffer: MAX_BUFFER }
|
|
@@ -45238,7 +46110,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45238
46110
|
*/
|
|
45239
46111
|
async listMachineTypes(projectId) {
|
|
45240
46112
|
try {
|
|
45241
|
-
const { stdout } = await
|
|
46113
|
+
const { stdout } = await execFileP6(
|
|
45242
46114
|
"gh",
|
|
45243
46115
|
["api", `/repos/${projectId}/codespaces/machines`],
|
|
45244
46116
|
{ maxBuffer: MAX_BUFFER }
|
|
@@ -45269,7 +46141,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45269
46141
|
const machine = machineTypeId ?? await this.pickDefaultMachine(projectId);
|
|
45270
46142
|
const args2 = ["codespace", "create", "-R", projectId, "--default-permissions"];
|
|
45271
46143
|
if (machine) args2.push("-m", machine);
|
|
45272
|
-
const { stdout } = await
|
|
46144
|
+
const { stdout } = await execFileP6(
|
|
45273
46145
|
"gh",
|
|
45274
46146
|
args2,
|
|
45275
46147
|
{ maxBuffer: MAX_BUFFER, timeout: 12e4 }
|
|
@@ -45309,7 +46181,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45309
46181
|
async waitUntilAvailable(name) {
|
|
45310
46182
|
const deadline = Date.now() + 5 * 60 * 1e3;
|
|
45311
46183
|
while (Date.now() < deadline) {
|
|
45312
|
-
const { stdout } = await
|
|
46184
|
+
const { stdout } = await execFileP6(
|
|
45313
46185
|
"gh",
|
|
45314
46186
|
["codespace", "list", "--json", "name,state"],
|
|
45315
46187
|
{ maxBuffer: MAX_BUFFER }
|
|
@@ -45327,7 +46199,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45327
46199
|
}
|
|
45328
46200
|
async exec(workspaceId, command2) {
|
|
45329
46201
|
try {
|
|
45330
|
-
const { stdout, stderr } = await
|
|
46202
|
+
const { stdout, stderr } = await execFileP6(
|
|
45331
46203
|
"gh",
|
|
45332
46204
|
["codespace", "ssh", "-c", workspaceId, "--", command2],
|
|
45333
46205
|
{ maxBuffer: MAX_BUFFER, timeout: 6e5 }
|
|
@@ -45400,7 +46272,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45400
46272
|
});
|
|
45401
46273
|
}
|
|
45402
46274
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
45403
|
-
const remoteDir =
|
|
46275
|
+
const remoteDir = path85.posix.dirname(remotePath);
|
|
45404
46276
|
const parts = [
|
|
45405
46277
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
45406
46278
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -45432,7 +46304,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45432
46304
|
try {
|
|
45433
46305
|
const args2 = ["codespace", "list", "--json", "name,displayName,state,lastUsedAt"];
|
|
45434
46306
|
if (projectId) args2.push("--repo", projectId);
|
|
45435
|
-
const { stdout } = await
|
|
46307
|
+
const { stdout } = await execFileP6("gh", args2, { maxBuffer: MAX_BUFFER });
|
|
45436
46308
|
const list = JSON.parse(stdout);
|
|
45437
46309
|
return list.map((c2) => ({
|
|
45438
46310
|
id: c2.name,
|
|
@@ -45447,7 +46319,7 @@ var GitHubCodespacesProvider = class {
|
|
|
45447
46319
|
}
|
|
45448
46320
|
async startWorkspace(workspaceId) {
|
|
45449
46321
|
try {
|
|
45450
|
-
await
|
|
46322
|
+
await execFileP6(
|
|
45451
46323
|
"gh",
|
|
45452
46324
|
["api", "-X", "POST", `/user/codespaces/${workspaceId}/start`],
|
|
45453
46325
|
{ maxBuffer: MAX_BUFFER, timeout: 6e4 }
|
|
@@ -45470,9 +46342,9 @@ function shellQuote(s) {
|
|
|
45470
46342
|
// src/services/providers/gitpod.ts
|
|
45471
46343
|
var import_child_process31 = require("child_process");
|
|
45472
46344
|
var import_util5 = require("util");
|
|
45473
|
-
var
|
|
46345
|
+
var path86 = __toESM(require("path"));
|
|
45474
46346
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
45475
|
-
var
|
|
46347
|
+
var execFileP7 = (0, import_util5.promisify)(import_child_process31.execFile);
|
|
45476
46348
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
45477
46349
|
function resetStdinForChild2() {
|
|
45478
46350
|
if (process.stdin.isTTY) {
|
|
@@ -45489,7 +46361,7 @@ var GitpodProvider = class {
|
|
|
45489
46361
|
available = true;
|
|
45490
46362
|
async authorize() {
|
|
45491
46363
|
try {
|
|
45492
|
-
await
|
|
46364
|
+
await execFileP7("gitpod", ["--version"], { maxBuffer: MAX_BUFFER2 });
|
|
45493
46365
|
} catch {
|
|
45494
46366
|
throw new Error(
|
|
45495
46367
|
[
|
|
@@ -45502,7 +46374,7 @@ var GitpodProvider = class {
|
|
|
45502
46374
|
);
|
|
45503
46375
|
}
|
|
45504
46376
|
try {
|
|
45505
|
-
await
|
|
46377
|
+
await execFileP7("gitpod", ["whoami"], { maxBuffer: MAX_BUFFER2 });
|
|
45506
46378
|
return;
|
|
45507
46379
|
} catch {
|
|
45508
46380
|
}
|
|
@@ -45522,7 +46394,7 @@ var GitpodProvider = class {
|
|
|
45522
46394
|
}
|
|
45523
46395
|
async listProjects() {
|
|
45524
46396
|
try {
|
|
45525
|
-
const { stdout } = await
|
|
46397
|
+
const { stdout } = await execFileP7(
|
|
45526
46398
|
"gitpod",
|
|
45527
46399
|
["workspace", "list", "--output", "json", "--limit", "200"],
|
|
45528
46400
|
{ maxBuffer: MAX_BUFFER2 }
|
|
@@ -45555,7 +46427,7 @@ var GitpodProvider = class {
|
|
|
45555
46427
|
async createWorkspace(projectId, machineTypeId) {
|
|
45556
46428
|
const args2 = ["workspace", "create", projectId, "--start", "--output", "json"];
|
|
45557
46429
|
if (machineTypeId) args2.push("--class", machineTypeId);
|
|
45558
|
-
const { stdout } = await
|
|
46430
|
+
const { stdout } = await execFileP7("gitpod", args2, {
|
|
45559
46431
|
maxBuffer: MAX_BUFFER2,
|
|
45560
46432
|
timeout: 3e5
|
|
45561
46433
|
});
|
|
@@ -45579,7 +46451,7 @@ var GitpodProvider = class {
|
|
|
45579
46451
|
const deadline = Date.now() + 5 * 60 * 1e3;
|
|
45580
46452
|
while (Date.now() < deadline) {
|
|
45581
46453
|
try {
|
|
45582
|
-
const { stdout } = await
|
|
46454
|
+
const { stdout } = await execFileP7(
|
|
45583
46455
|
"gitpod",
|
|
45584
46456
|
["workspace", "get", workspaceId, "--output", "json"],
|
|
45585
46457
|
{ maxBuffer: MAX_BUFFER2 }
|
|
@@ -45597,7 +46469,7 @@ var GitpodProvider = class {
|
|
|
45597
46469
|
}
|
|
45598
46470
|
async listMachineTypes(_projectId) {
|
|
45599
46471
|
try {
|
|
45600
|
-
const { stdout } = await
|
|
46472
|
+
const { stdout } = await execFileP7(
|
|
45601
46473
|
"gitpod",
|
|
45602
46474
|
["organization", "list-classes", "--output", "json"],
|
|
45603
46475
|
{ maxBuffer: MAX_BUFFER2 }
|
|
@@ -45615,7 +46487,7 @@ var GitpodProvider = class {
|
|
|
45615
46487
|
async listExistingWorkspaces(projectId) {
|
|
45616
46488
|
try {
|
|
45617
46489
|
const args2 = ["workspace", "list", "--output", "json", "--limit", "200"];
|
|
45618
|
-
const { stdout } = await
|
|
46490
|
+
const { stdout } = await execFileP7("gitpod", args2, { maxBuffer: MAX_BUFFER2 });
|
|
45619
46491
|
const list = JSON.parse(stdout);
|
|
45620
46492
|
return list.filter((w3) => !projectId || w3.contextUrl === projectId).map((w3) => ({
|
|
45621
46493
|
id: w3.id,
|
|
@@ -45630,7 +46502,7 @@ var GitpodProvider = class {
|
|
|
45630
46502
|
}
|
|
45631
46503
|
async startWorkspace(workspaceId) {
|
|
45632
46504
|
try {
|
|
45633
|
-
await
|
|
46505
|
+
await execFileP7(
|
|
45634
46506
|
"gitpod",
|
|
45635
46507
|
["workspace", "start", workspaceId],
|
|
45636
46508
|
{ maxBuffer: MAX_BUFFER2, timeout: 6e4 }
|
|
@@ -45646,7 +46518,7 @@ var GitpodProvider = class {
|
|
|
45646
46518
|
}
|
|
45647
46519
|
async exec(workspaceId, command2) {
|
|
45648
46520
|
try {
|
|
45649
|
-
const { stdout, stderr } = await
|
|
46521
|
+
const { stdout, stderr } = await execFileP7(
|
|
45650
46522
|
"gitpod",
|
|
45651
46523
|
["workspace", "ssh", workspaceId, "--", command2],
|
|
45652
46524
|
{ maxBuffer: MAX_BUFFER2, timeout: 6e5 }
|
|
@@ -45710,7 +46582,7 @@ var GitpodProvider = class {
|
|
|
45710
46582
|
});
|
|
45711
46583
|
}
|
|
45712
46584
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
45713
|
-
const remoteDir =
|
|
46585
|
+
const remoteDir = path86.posix.dirname(remotePath);
|
|
45714
46586
|
const parts = [
|
|
45715
46587
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
45716
46588
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -45746,8 +46618,8 @@ function shellQuote2(s) {
|
|
|
45746
46618
|
// src/services/providers/gitlab-workspaces.ts
|
|
45747
46619
|
var import_child_process32 = require("child_process");
|
|
45748
46620
|
var import_util6 = require("util");
|
|
45749
|
-
var
|
|
45750
|
-
var
|
|
46621
|
+
var path87 = __toESM(require("path"));
|
|
46622
|
+
var execFileP8 = (0, import_util6.promisify)(import_child_process32.execFile);
|
|
45751
46623
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
45752
46624
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
45753
46625
|
function resetStdinForChild3() {
|
|
@@ -45765,7 +46637,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
45765
46637
|
available = true;
|
|
45766
46638
|
async authorize() {
|
|
45767
46639
|
try {
|
|
45768
|
-
await
|
|
46640
|
+
await execFileP8("glab", ["--version"], { maxBuffer: MAX_BUFFER3 });
|
|
45769
46641
|
} catch {
|
|
45770
46642
|
throw new Error(
|
|
45771
46643
|
[
|
|
@@ -45779,7 +46651,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
45779
46651
|
);
|
|
45780
46652
|
}
|
|
45781
46653
|
try {
|
|
45782
|
-
await
|
|
46654
|
+
await execFileP8("glab", ["auth", "status"], { maxBuffer: MAX_BUFFER3 });
|
|
45783
46655
|
return;
|
|
45784
46656
|
} catch {
|
|
45785
46657
|
}
|
|
@@ -45803,7 +46675,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
45803
46675
|
}
|
|
45804
46676
|
async listProjects() {
|
|
45805
46677
|
try {
|
|
45806
|
-
const { stdout } = await
|
|
46678
|
+
const { stdout } = await execFileP8(
|
|
45807
46679
|
"glab",
|
|
45808
46680
|
["repo", "list", "--per-page", "200", "--output", "json"],
|
|
45809
46681
|
{ maxBuffer: MAX_BUFFER3 }
|
|
@@ -45935,7 +46807,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45935
46807
|
async exec(workspaceId, command2) {
|
|
45936
46808
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
45937
46809
|
try {
|
|
45938
|
-
const { stdout, stderr } = await
|
|
46810
|
+
const { stdout, stderr } = await execFileP8(
|
|
45939
46811
|
"ssh",
|
|
45940
46812
|
[
|
|
45941
46813
|
"-o",
|
|
@@ -46006,7 +46878,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
46006
46878
|
}
|
|
46007
46879
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
46008
46880
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
46009
|
-
const remoteDir =
|
|
46881
|
+
const remoteDir = path87.posix.dirname(remotePath);
|
|
46010
46882
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
46011
46883
|
if (options.mode != null) {
|
|
46012
46884
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -46038,7 +46910,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
46038
46910
|
*/
|
|
46039
46911
|
async getGlabToken() {
|
|
46040
46912
|
try {
|
|
46041
|
-
const { stdout, stderr } = await
|
|
46913
|
+
const { stdout, stderr } = await execFileP8(
|
|
46042
46914
|
"glab",
|
|
46043
46915
|
["auth", "status", "--show-token"],
|
|
46044
46916
|
{ maxBuffer: MAX_BUFFER3 }
|
|
@@ -46074,8 +46946,8 @@ function shellQuote3(s) {
|
|
|
46074
46946
|
// src/services/providers/railway.ts
|
|
46075
46947
|
var import_child_process33 = require("child_process");
|
|
46076
46948
|
var import_util7 = require("util");
|
|
46077
|
-
var
|
|
46078
|
-
var
|
|
46949
|
+
var path88 = __toESM(require("path"));
|
|
46950
|
+
var execFileP9 = (0, import_util7.promisify)(import_child_process33.execFile);
|
|
46079
46951
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
46080
46952
|
function resetStdinForChild4() {
|
|
46081
46953
|
if (process.stdin.isTTY) {
|
|
@@ -46092,7 +46964,7 @@ var RailwayProvider = class {
|
|
|
46092
46964
|
available = true;
|
|
46093
46965
|
async authorize() {
|
|
46094
46966
|
try {
|
|
46095
|
-
await
|
|
46967
|
+
await execFileP9("railway", ["--version"], { maxBuffer: MAX_BUFFER4 });
|
|
46096
46968
|
} catch {
|
|
46097
46969
|
throw new Error(
|
|
46098
46970
|
[
|
|
@@ -46106,7 +46978,7 @@ var RailwayProvider = class {
|
|
|
46106
46978
|
);
|
|
46107
46979
|
}
|
|
46108
46980
|
try {
|
|
46109
|
-
await
|
|
46981
|
+
await execFileP9("railway", ["whoami"], { maxBuffer: MAX_BUFFER4 });
|
|
46110
46982
|
return;
|
|
46111
46983
|
} catch {
|
|
46112
46984
|
}
|
|
@@ -46126,7 +46998,7 @@ var RailwayProvider = class {
|
|
|
46126
46998
|
}
|
|
46127
46999
|
async listProjects() {
|
|
46128
47000
|
try {
|
|
46129
|
-
const { stdout } = await
|
|
47001
|
+
const { stdout } = await execFileP9(
|
|
46130
47002
|
"railway",
|
|
46131
47003
|
["list", "--json"],
|
|
46132
47004
|
{ maxBuffer: MAX_BUFFER4 }
|
|
@@ -46142,7 +47014,7 @@ var RailwayProvider = class {
|
|
|
46142
47014
|
}));
|
|
46143
47015
|
} catch {
|
|
46144
47016
|
try {
|
|
46145
|
-
const { stdout } = await
|
|
47017
|
+
const { stdout } = await execFileP9("railway", ["list"], { maxBuffer: MAX_BUFFER4 });
|
|
46146
47018
|
const projects = [];
|
|
46147
47019
|
for (const line of stdout.split("\n")) {
|
|
46148
47020
|
const trimmed = line.trim();
|
|
@@ -46193,7 +47065,7 @@ var RailwayProvider = class {
|
|
|
46193
47065
|
async listExistingWorkspaces(projectId) {
|
|
46194
47066
|
if (!projectId) return [];
|
|
46195
47067
|
try {
|
|
46196
|
-
const { stdout } = await
|
|
47068
|
+
const { stdout } = await execFileP9(
|
|
46197
47069
|
"railway",
|
|
46198
47070
|
["service", "list", "--project", projectId, "--json"],
|
|
46199
47071
|
{ maxBuffer: MAX_BUFFER4 }
|
|
@@ -46218,7 +47090,7 @@ var RailwayProvider = class {
|
|
|
46218
47090
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
46219
47091
|
}
|
|
46220
47092
|
try {
|
|
46221
|
-
await
|
|
47093
|
+
await execFileP9(
|
|
46222
47094
|
"railway",
|
|
46223
47095
|
["service", "restart", "--service", serviceId, "--project", projectId],
|
|
46224
47096
|
{ maxBuffer: MAX_BUFFER4, timeout: 6e4 }
|
|
@@ -46237,7 +47109,7 @@ var RailwayProvider = class {
|
|
|
46237
47109
|
};
|
|
46238
47110
|
}
|
|
46239
47111
|
try {
|
|
46240
|
-
const { stdout, stderr } = await
|
|
47112
|
+
const { stdout, stderr } = await execFileP9(
|
|
46241
47113
|
"railway",
|
|
46242
47114
|
["run", "--project", projectId, "--service", serviceId, "--", "bash", "-lc", command2],
|
|
46243
47115
|
{ maxBuffer: MAX_BUFFER4, timeout: 6e5 }
|
|
@@ -46310,7 +47182,7 @@ var RailwayProvider = class {
|
|
|
46310
47182
|
if (!projectId || !serviceId) {
|
|
46311
47183
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
46312
47184
|
}
|
|
46313
|
-
const remoteDir =
|
|
47185
|
+
const remoteDir = path88.posix.dirname(remotePath);
|
|
46314
47186
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
46315
47187
|
if (options.mode != null) {
|
|
46316
47188
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -46850,14 +47722,14 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
46850
47722
|
}
|
|
46851
47723
|
|
|
46852
47724
|
// src/commands/host/host-client.ts
|
|
46853
|
-
var
|
|
46854
|
-
var
|
|
46855
|
-
var
|
|
46856
|
-
var
|
|
47725
|
+
var fs75 = __toESM(require("fs"));
|
|
47726
|
+
var os59 = __toESM(require("os"));
|
|
47727
|
+
var path89 = __toESM(require("path"));
|
|
47728
|
+
var import_node_crypto12 = require("crypto");
|
|
46857
47729
|
function sampleCpuTimes() {
|
|
46858
47730
|
let idle = 0;
|
|
46859
47731
|
let total = 0;
|
|
46860
|
-
for (const cpu of
|
|
47732
|
+
for (const cpu of os59.cpus()) {
|
|
46861
47733
|
const t2 = cpu.times;
|
|
46862
47734
|
idle += t2.idle;
|
|
46863
47735
|
total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
|
|
@@ -46876,8 +47748,8 @@ var MetricsCollector = class {
|
|
|
46876
47748
|
const prev = this.prevCpu;
|
|
46877
47749
|
this.prevCpu = current2;
|
|
46878
47750
|
if (!prev) {
|
|
46879
|
-
const cores =
|
|
46880
|
-
const proxy =
|
|
47751
|
+
const cores = os59.cpus().length || 1;
|
|
47752
|
+
const proxy = os59.loadavg()[0] / cores * 100;
|
|
46881
47753
|
return Math.min(100, Math.max(0, Math.round(proxy)));
|
|
46882
47754
|
}
|
|
46883
47755
|
const idleDelta = current2.idle - prev.idle;
|
|
@@ -46890,8 +47762,8 @@ var MetricsCollector = class {
|
|
|
46890
47762
|
collect() {
|
|
46891
47763
|
return {
|
|
46892
47764
|
cpuPct: this.cpuPct(),
|
|
46893
|
-
ramUsedMb: Math.round((
|
|
46894
|
-
ramTotalMb: Math.round(
|
|
47765
|
+
ramUsedMb: Math.round((os59.totalmem() - os59.freemem()) / 1048576),
|
|
47766
|
+
ramTotalMb: Math.round(os59.totalmem() / 1048576),
|
|
46895
47767
|
latencyMs: this.lastLatencyMs
|
|
46896
47768
|
};
|
|
46897
47769
|
}
|
|
@@ -46900,19 +47772,19 @@ function apiBase() {
|
|
|
46900
47772
|
return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
|
|
46901
47773
|
}
|
|
46902
47774
|
function hostIdentityPath() {
|
|
46903
|
-
return
|
|
47775
|
+
return path89.join(os59.homedir(), ".codeam", "host-agent.json");
|
|
46904
47776
|
}
|
|
46905
47777
|
function collectOsInfo() {
|
|
46906
47778
|
return {
|
|
46907
|
-
distro:
|
|
46908
|
-
arch:
|
|
46909
|
-
kernel:
|
|
47779
|
+
distro: os59.platform(),
|
|
47780
|
+
arch: os59.arch(),
|
|
47781
|
+
kernel: os59.release(),
|
|
46910
47782
|
nodeVersion: process.versions.node
|
|
46911
47783
|
};
|
|
46912
47784
|
}
|
|
46913
47785
|
function loadHostIdentity() {
|
|
46914
47786
|
try {
|
|
46915
|
-
const raw =
|
|
47787
|
+
const raw = fs75.readFileSync(hostIdentityPath(), "utf8");
|
|
46916
47788
|
const parsed = JSON.parse(raw);
|
|
46917
47789
|
if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
|
|
46918
47790
|
const p2 = parsed;
|
|
@@ -46931,8 +47803,8 @@ function loadHostIdentity() {
|
|
|
46931
47803
|
}
|
|
46932
47804
|
function saveHostIdentity(identity) {
|
|
46933
47805
|
const file = hostIdentityPath();
|
|
46934
|
-
|
|
46935
|
-
|
|
47806
|
+
fs75.mkdirSync(path89.dirname(file), { recursive: true, mode: 448 });
|
|
47807
|
+
fs75.writeFileSync(file, JSON.stringify(identity, null, 2), {
|
|
46936
47808
|
encoding: "utf8",
|
|
46937
47809
|
mode: 384
|
|
46938
47810
|
});
|
|
@@ -46977,7 +47849,7 @@ function isTerminalEnrollError(err) {
|
|
|
46977
47849
|
}
|
|
46978
47850
|
function deleteHostIdentity() {
|
|
46979
47851
|
try {
|
|
46980
|
-
|
|
47852
|
+
fs75.rmSync(hostIdentityPath(), { force: true });
|
|
46981
47853
|
} catch {
|
|
46982
47854
|
}
|
|
46983
47855
|
}
|
|
@@ -47001,12 +47873,12 @@ async function postJson(pathname, body) {
|
|
|
47001
47873
|
function resolveHostLabel(label) {
|
|
47002
47874
|
const explicit = label?.trim();
|
|
47003
47875
|
const envLabel = process.env.CODEAM_HOST_LABEL?.trim();
|
|
47004
|
-
const resolved = explicit || envLabel ||
|
|
47876
|
+
const resolved = explicit || envLabel || os59.hostname();
|
|
47005
47877
|
return resolved.slice(0, 80);
|
|
47006
47878
|
}
|
|
47007
47879
|
async function redeemEnrollToken(token, label) {
|
|
47008
|
-
const controlPollSecret = (0,
|
|
47009
|
-
const pluginSecretHash = (0,
|
|
47880
|
+
const controlPollSecret = (0, import_node_crypto12.randomBytes)(32).toString("base64url");
|
|
47881
|
+
const pluginSecretHash = (0, import_node_crypto12.createHash)("sha256").update(controlPollSecret).digest("hex");
|
|
47010
47882
|
const data = await postJson("/api/self-hosted/redeem", {
|
|
47011
47883
|
token,
|
|
47012
47884
|
label: resolveHostLabel(label),
|
|
@@ -47190,9 +48062,9 @@ async function host(args2) {
|
|
|
47190
48062
|
|
|
47191
48063
|
// src/commands/host-agent.ts
|
|
47192
48064
|
var import_node_child_process30 = require("child_process");
|
|
47193
|
-
var
|
|
47194
|
-
var
|
|
47195
|
-
var
|
|
48065
|
+
var os63 = __toESM(require("os"));
|
|
48066
|
+
var fs79 = __toESM(require("fs"));
|
|
48067
|
+
var path93 = __toESM(require("path"));
|
|
47196
48068
|
|
|
47197
48069
|
// src/skills/persist-from-payload.ts
|
|
47198
48070
|
function persistOrClearSkillsFromPayload(skills) {
|
|
@@ -47201,13 +48073,13 @@ function persistOrClearSkillsFromPayload(skills) {
|
|
|
47201
48073
|
}
|
|
47202
48074
|
|
|
47203
48075
|
// src/commands/host/session-state.ts
|
|
47204
|
-
var
|
|
47205
|
-
var
|
|
47206
|
-
var
|
|
48076
|
+
var fs76 = __toESM(require("fs"));
|
|
48077
|
+
var os60 = __toESM(require("os"));
|
|
48078
|
+
var path90 = __toESM(require("path"));
|
|
47207
48079
|
function hostSessionStatePath(env = process.env) {
|
|
47208
48080
|
const override = env.CODEAM_HOST_SESSION_STATE_FILE;
|
|
47209
48081
|
if (override && override.trim()) return override.trim();
|
|
47210
|
-
return
|
|
48082
|
+
return path90.join(os60.homedir(), ".codeam", "host-agent-sessions.json");
|
|
47211
48083
|
}
|
|
47212
48084
|
function isRecord5(v) {
|
|
47213
48085
|
if (typeof v !== "object" || v === null) return false;
|
|
@@ -47218,7 +48090,7 @@ function fileSessionChildStore(file = hostSessionStatePath()) {
|
|
|
47218
48090
|
return {
|
|
47219
48091
|
load() {
|
|
47220
48092
|
try {
|
|
47221
|
-
const raw = JSON.parse(
|
|
48093
|
+
const raw = JSON.parse(fs76.readFileSync(file, "utf8"));
|
|
47222
48094
|
return Array.isArray(raw?.sessions) ? raw.sessions.filter(isRecord5) : [];
|
|
47223
48095
|
} catch {
|
|
47224
48096
|
return [];
|
|
@@ -47226,18 +48098,18 @@ function fileSessionChildStore(file = hostSessionStatePath()) {
|
|
|
47226
48098
|
},
|
|
47227
48099
|
save(list) {
|
|
47228
48100
|
try {
|
|
47229
|
-
|
|
48101
|
+
fs76.mkdirSync(path90.dirname(file), { recursive: true, mode: 448 });
|
|
47230
48102
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
47231
|
-
|
|
48103
|
+
fs76.writeFileSync(tmp, JSON.stringify({ version: 1, sessions: list }, null, 2), {
|
|
47232
48104
|
mode: 384
|
|
47233
48105
|
});
|
|
47234
|
-
|
|
48106
|
+
fs76.renameSync(tmp, file);
|
|
47235
48107
|
} catch {
|
|
47236
48108
|
}
|
|
47237
48109
|
},
|
|
47238
48110
|
clear() {
|
|
47239
48111
|
try {
|
|
47240
|
-
|
|
48112
|
+
fs76.rmSync(file, { force: true });
|
|
47241
48113
|
} catch {
|
|
47242
48114
|
}
|
|
47243
48115
|
}
|
|
@@ -47260,181 +48132,22 @@ function planSessionResume(records, max) {
|
|
|
47260
48132
|
return { resume: ordered.slice(0, bound), dropped: ordered.slice(bound) };
|
|
47261
48133
|
}
|
|
47262
48134
|
function pickSavedSessionForWorkspace(sessions3, cwd) {
|
|
47263
|
-
const target =
|
|
48135
|
+
const target = path90.resolve(cwd);
|
|
47264
48136
|
const matches = sessions3.filter(
|
|
47265
|
-
(s) => !!s.cwd &&
|
|
48137
|
+
(s) => !!s.cwd && path90.resolve(s.cwd) === target && !!s.pluginId && !!s.pollSecret && !!s.agent
|
|
47266
48138
|
);
|
|
47267
48139
|
if (matches.length === 0) return null;
|
|
47268
48140
|
matches.sort((a, b) => b.pairedAt - a.pairedAt);
|
|
47269
48141
|
return matches[0];
|
|
47270
48142
|
}
|
|
47271
48143
|
|
|
47272
|
-
// src/commands/host/workspace.ts
|
|
47273
|
-
var fs75 = __toESM(require("fs"));
|
|
47274
|
-
var os59 = __toESM(require("os"));
|
|
47275
|
-
var path89 = __toESM(require("path"));
|
|
47276
|
-
var import_node_child_process25 = require("child_process");
|
|
47277
|
-
var import_node_util5 = require("util");
|
|
47278
|
-
var execFileP9 = (0, import_node_util5.promisify)(import_node_child_process25.execFile);
|
|
47279
|
-
function isAbsolutePathTarget(target) {
|
|
47280
|
-
return path89.isAbsolute(target);
|
|
47281
|
-
}
|
|
47282
|
-
function selfHostedWorkspaceRoot() {
|
|
47283
|
-
return path89.join(os59.homedir(), ".codeam", "self-hosted");
|
|
47284
|
-
}
|
|
47285
|
-
function deployIdFromWorkspace(cwd) {
|
|
47286
|
-
if (!cwd) return null;
|
|
47287
|
-
const root = selfHostedWorkspaceRoot();
|
|
47288
|
-
const resolved = path89.resolve(cwd);
|
|
47289
|
-
const rel = path89.relative(root, resolved);
|
|
47290
|
-
if (!rel || rel.startsWith("..") || path89.isAbsolute(rel)) return null;
|
|
47291
|
-
const parts = rel.split(path89.sep).filter(Boolean);
|
|
47292
|
-
if (parts.length !== 1) return null;
|
|
47293
|
-
return parts[0];
|
|
47294
|
-
}
|
|
47295
|
-
function nonInteractiveGitEnv() {
|
|
47296
|
-
return {
|
|
47297
|
-
...process.env,
|
|
47298
|
-
GIT_TERMINAL_PROMPT: "0",
|
|
47299
|
-
GIT_ASKPASS: "",
|
|
47300
|
-
GCM_INTERACTIVE: "never"
|
|
47301
|
-
};
|
|
47302
|
-
}
|
|
47303
|
-
function githubOwnerRepo(repoRef) {
|
|
47304
|
-
const trimmed = repoRef.trim();
|
|
47305
|
-
const shorthand = /^([^/\s]+)\/([^/\s]+?)(?:\.git)?$/.exec(trimmed);
|
|
47306
|
-
if (shorthand && !/^https?:\/\//.test(trimmed) && !trimmed.startsWith("git@")) {
|
|
47307
|
-
return { owner: shorthand[1], repo: shorthand[2] };
|
|
47308
|
-
}
|
|
47309
|
-
const httpsMatch = /^https?:\/\/github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
47310
|
-
if (httpsMatch) return { owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
47311
|
-
return null;
|
|
47312
|
-
}
|
|
47313
|
-
function gitlabProjectPath(repoRef) {
|
|
47314
|
-
const trimmed = repoRef.trim();
|
|
47315
|
-
const https9 = /^https?:\/\/gitlab\.com\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
47316
|
-
if (https9) return https9[1];
|
|
47317
|
-
if (!/^https?:\/\//.test(trimmed) && !trimmed.startsWith("git@") && trimmed.includes("/")) {
|
|
47318
|
-
return trimmed.replace(/\.git$/, "");
|
|
47319
|
-
}
|
|
47320
|
-
return null;
|
|
47321
|
-
}
|
|
47322
|
-
function repoCloneUrl(repoRef, cloneToken, provider = "github") {
|
|
47323
|
-
const trimmed = repoRef.trim();
|
|
47324
|
-
if (provider === "gitlab") {
|
|
47325
|
-
const glPath = gitlabProjectPath(trimmed);
|
|
47326
|
-
if (glPath) {
|
|
47327
|
-
return cloneToken ? `https://oauth2:${cloneToken}@gitlab.com/${glPath}.git` : `https://gitlab.com/${glPath}.git`;
|
|
47328
|
-
}
|
|
47329
|
-
if (/^https?:\/\//.test(trimmed) || trimmed.startsWith("git@")) return trimmed;
|
|
47330
|
-
}
|
|
47331
|
-
if (cloneToken) {
|
|
47332
|
-
const gh = githubOwnerRepo(trimmed);
|
|
47333
|
-
if (gh) {
|
|
47334
|
-
return `https://x-access-token:${cloneToken}@github.com/${gh.owner}/${gh.repo}.git`;
|
|
47335
|
-
}
|
|
47336
|
-
}
|
|
47337
|
-
if (/^https?:\/\//.test(trimmed) || trimmed.startsWith("git@")) return trimmed;
|
|
47338
|
-
return `https://github.com/${trimmed.replace(/\.git$/, "")}.git`;
|
|
47339
|
-
}
|
|
47340
|
-
function maskCloneUrl(url2) {
|
|
47341
|
-
return url2.replace(/(https?:\/\/)[^@/]+@/, "$1***@");
|
|
47342
|
-
}
|
|
47343
|
-
async function fetchGithubIdentity(token) {
|
|
47344
|
-
try {
|
|
47345
|
-
const res = await fetch("https://api.github.com/user", {
|
|
47346
|
-
headers: {
|
|
47347
|
-
Authorization: `Bearer ${token}`,
|
|
47348
|
-
"User-Agent": "codeam-cli",
|
|
47349
|
-
Accept: "application/vnd.github+json"
|
|
47350
|
-
}
|
|
47351
|
-
});
|
|
47352
|
-
if (!res.ok) return null;
|
|
47353
|
-
const body = await res.json();
|
|
47354
|
-
return { login: body.login, email: body.email ?? void 0 };
|
|
47355
|
-
} catch {
|
|
47356
|
-
return null;
|
|
47357
|
-
}
|
|
47358
|
-
}
|
|
47359
|
-
async function configureGitCredentials(dest, repoRef, cloneToken, provider = "github") {
|
|
47360
|
-
const isGitlab = provider === "gitlab";
|
|
47361
|
-
if (isGitlab ? !gitlabProjectPath(repoRef.trim()) : !githubOwnerRepo(repoRef.trim())) return;
|
|
47362
|
-
if (!cloneToken) return;
|
|
47363
|
-
const credFile = path89.join(dest, ".git", "codeam-credentials");
|
|
47364
|
-
const credLine = isGitlab ? `https://oauth2:${cloneToken}@gitlab.com
|
|
47365
|
-
` : `https://x-access-token:${cloneToken}@github.com
|
|
47366
|
-
`;
|
|
47367
|
-
fs75.writeFileSync(credFile, credLine, { mode: 384 });
|
|
47368
|
-
restrictToOwner(credFile);
|
|
47369
|
-
const env = nonInteractiveGitEnv();
|
|
47370
|
-
const git2 = (args2) => execFileP9("git", ["-C", dest, ...args2], { timeout: 3e4, env });
|
|
47371
|
-
const credFilePosix = credFile.split(path89.sep).join("/");
|
|
47372
|
-
await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
|
|
47373
|
-
});
|
|
47374
|
-
await git2([
|
|
47375
|
-
"config",
|
|
47376
|
-
"--local",
|
|
47377
|
-
"--add",
|
|
47378
|
-
"credential.helper",
|
|
47379
|
-
`store --file=${credFilePosix}`
|
|
47380
|
-
]).catch(() => {
|
|
47381
|
-
});
|
|
47382
|
-
await git2(["remote", "set-url", "origin", repoCloneUrl(repoRef, void 0, provider)]).catch(() => {
|
|
47383
|
-
});
|
|
47384
|
-
const hasIdentity = await git2(["config", "user.email"]).then(() => true).catch(() => false);
|
|
47385
|
-
if (!hasIdentity) {
|
|
47386
|
-
const who = isGitlab ? null : await fetchGithubIdentity(cloneToken);
|
|
47387
|
-
const login = who?.login ?? "CodeAgent";
|
|
47388
|
-
await git2(["config", "--local", "user.name", login]).catch(() => {
|
|
47389
|
-
});
|
|
47390
|
-
const email = who?.email ?? (isGitlab ? "agent@codeagent-mobile.com" : `${login}@users.noreply.github.com`);
|
|
47391
|
-
await git2(["config", "--local", "user.email", email]).catch(() => {
|
|
47392
|
-
});
|
|
47393
|
-
}
|
|
47394
|
-
}
|
|
47395
|
-
function maskToken(text, cloneToken) {
|
|
47396
|
-
const masked = maskCloneUrl(text);
|
|
47397
|
-
if (cloneToken && cloneToken.length > 0) {
|
|
47398
|
-
return masked.split(cloneToken).join("***");
|
|
47399
|
-
}
|
|
47400
|
-
return masked;
|
|
47401
|
-
}
|
|
47402
|
-
async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "github", branch) {
|
|
47403
|
-
if (isAbsolutePathTarget(repoOrPath)) {
|
|
47404
|
-
if (!fs75.existsSync(repoOrPath)) {
|
|
47405
|
-
throw new Error(`deploy target path does not exist: ${repoOrPath}`);
|
|
47406
|
-
}
|
|
47407
|
-
return repoOrPath;
|
|
47408
|
-
}
|
|
47409
|
-
const dest = path89.join(selfHostedWorkspaceRoot(), deployId);
|
|
47410
|
-
if (fs75.existsSync(path89.join(dest, ".git"))) {
|
|
47411
|
-
if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
|
|
47412
|
-
return dest;
|
|
47413
|
-
}
|
|
47414
|
-
fs75.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
|
|
47415
|
-
const cloneUrl = repoCloneUrl(repoOrPath, cloneToken, provider);
|
|
47416
|
-
const cloneArgs = branch ? ["clone", "--depth", "1", "--branch", branch, cloneUrl, dest] : ["clone", "--depth", "1", cloneUrl, dest];
|
|
47417
|
-
try {
|
|
47418
|
-
await execFileP9("git", cloneArgs, {
|
|
47419
|
-
timeout: 12e4,
|
|
47420
|
-
maxBuffer: 16 * 1024 * 1024,
|
|
47421
|
-
env: nonInteractiveGitEnv()
|
|
47422
|
-
});
|
|
47423
|
-
} catch (err) {
|
|
47424
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
47425
|
-
throw new Error(`git clone failed for ${maskCloneUrl(cloneUrl)}: ${maskToken(reason, cloneToken)}`);
|
|
47426
|
-
}
|
|
47427
|
-
if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
|
|
47428
|
-
return dest;
|
|
47429
|
-
}
|
|
47430
|
-
|
|
47431
48144
|
// src/commands/host/git-tooling.ts
|
|
47432
48145
|
var import_node_child_process26 = require("child_process");
|
|
47433
|
-
var
|
|
47434
|
-
var
|
|
47435
|
-
var
|
|
48146
|
+
var fs77 = __toESM(require("fs"));
|
|
48147
|
+
var os61 = __toESM(require("os"));
|
|
48148
|
+
var path91 = __toESM(require("path"));
|
|
47436
48149
|
function codeamBinDir() {
|
|
47437
|
-
return process.env.CODEAM_BIN_DIR ??
|
|
48150
|
+
return process.env.CODEAM_BIN_DIR ?? path91.join(os61.homedir(), ".codeam", "bin");
|
|
47438
48151
|
}
|
|
47439
48152
|
var FALLBACK_GH_VERSION = "2.62.0";
|
|
47440
48153
|
var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
|
|
@@ -47466,7 +48179,7 @@ async function download(url2, dest) {
|
|
|
47466
48179
|
const res = await fetch(url2, { headers: { "User-Agent": "codeam-cli" } });
|
|
47467
48180
|
if (!res.ok || !res.body) return false;
|
|
47468
48181
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
47469
|
-
|
|
48182
|
+
fs77.writeFileSync(dest, buf);
|
|
47470
48183
|
return true;
|
|
47471
48184
|
} catch {
|
|
47472
48185
|
return false;
|
|
@@ -47489,8 +48202,8 @@ async function ensureGhCli(runner, token, deps = {}) {
|
|
|
47489
48202
|
const version3 = await resolveVersionFn(token);
|
|
47490
48203
|
const asset = `gh_${version3}_${osToken}_${arch2}`;
|
|
47491
48204
|
const url2 = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
|
|
47492
|
-
const tmpRoot =
|
|
47493
|
-
const archive =
|
|
48205
|
+
const tmpRoot = fs77.mkdtempSync(path91.join(os61.tmpdir(), "codeam-gh-"));
|
|
48206
|
+
const archive = path91.join(tmpRoot, `${asset}.${ext}`);
|
|
47494
48207
|
if (!await downloadFn(url2, archive)) {
|
|
47495
48208
|
log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
|
|
47496
48209
|
return null;
|
|
@@ -47500,16 +48213,16 @@ async function ensureGhCli(runner, token, deps = {}) {
|
|
|
47500
48213
|
log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
|
|
47501
48214
|
return null;
|
|
47502
48215
|
}
|
|
47503
|
-
const extractedBin =
|
|
47504
|
-
if (!
|
|
48216
|
+
const extractedBin = path91.join(tmpRoot, asset, "bin", binaryName);
|
|
48217
|
+
if (!fs77.existsSync(extractedBin)) {
|
|
47505
48218
|
log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
|
|
47506
48219
|
return null;
|
|
47507
48220
|
}
|
|
47508
48221
|
const binDir = codeamBinDir();
|
|
47509
|
-
|
|
47510
|
-
const target =
|
|
47511
|
-
|
|
47512
|
-
|
|
48222
|
+
fs77.mkdirSync(binDir, { recursive: true });
|
|
48223
|
+
const target = path91.join(binDir, binaryName);
|
|
48224
|
+
fs77.copyFileSync(extractedBin, target);
|
|
48225
|
+
fs77.chmodSync(target, 493);
|
|
47513
48226
|
log.info("host-agent", `gh installed to ${target} (v${version3})`);
|
|
47514
48227
|
return target;
|
|
47515
48228
|
} catch (e) {
|
|
@@ -47546,19 +48259,19 @@ async function ensureGhAuth(runner, ghCmd, token) {
|
|
|
47546
48259
|
}
|
|
47547
48260
|
function ghConfigDir() {
|
|
47548
48261
|
if (process.env.GH_CONFIG_DIR) return process.env.GH_CONFIG_DIR;
|
|
47549
|
-
if (process.env.XDG_CONFIG_HOME) return
|
|
48262
|
+
if (process.env.XDG_CONFIG_HOME) return path91.join(process.env.XDG_CONFIG_HOME, "gh");
|
|
47550
48263
|
if (process.platform === "win32" && process.env.APPDATA) {
|
|
47551
|
-
return
|
|
48264
|
+
return path91.join(process.env.APPDATA, "GitHub CLI");
|
|
47552
48265
|
}
|
|
47553
|
-
return
|
|
48266
|
+
return path91.join(os61.homedir(), ".config", "gh");
|
|
47554
48267
|
}
|
|
47555
48268
|
function writeGhHostsToken(token) {
|
|
47556
48269
|
try {
|
|
47557
48270
|
const dir = ghConfigDir();
|
|
47558
|
-
const file =
|
|
47559
|
-
if (
|
|
47560
|
-
|
|
47561
|
-
|
|
48271
|
+
const file = path91.join(dir, "hosts.yml");
|
|
48272
|
+
if (fs77.existsSync(file)) return false;
|
|
48273
|
+
fs77.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
48274
|
+
fs77.writeFileSync(
|
|
47562
48275
|
file,
|
|
47563
48276
|
`github.com:
|
|
47564
48277
|
oauth_token: ${token}
|
|
@@ -47601,8 +48314,8 @@ async function ensureGlabCli(runner, deps = {}) {
|
|
|
47601
48314
|
const version3 = await resolveLatestGlabVersion();
|
|
47602
48315
|
const asset = `glab_${version3}_${osToken}_${arch2}`;
|
|
47603
48316
|
const url2 = `https://gitlab.com/gitlab-org/cli/-/releases/v${version3}/downloads/${asset}.${ext}`;
|
|
47604
|
-
const tmpRoot =
|
|
47605
|
-
const archive =
|
|
48317
|
+
const tmpRoot = fs77.mkdtempSync(path91.join(os61.tmpdir(), "codeam-glab-"));
|
|
48318
|
+
const archive = path91.join(tmpRoot, `${asset}.${ext}`);
|
|
47606
48319
|
if (!await downloadFn(url2, archive)) {
|
|
47607
48320
|
log.warn("host-agent", "glab download failed \u2014 skipping (git push/pull still work)");
|
|
47608
48321
|
return null;
|
|
@@ -47613,20 +48326,20 @@ async function ensureGlabCli(runner, deps = {}) {
|
|
|
47613
48326
|
return null;
|
|
47614
48327
|
}
|
|
47615
48328
|
const candidates = [
|
|
47616
|
-
|
|
47617
|
-
|
|
47618
|
-
|
|
48329
|
+
path91.join(tmpRoot, "bin", binaryName),
|
|
48330
|
+
path91.join(tmpRoot, asset, "bin", binaryName),
|
|
48331
|
+
path91.join(tmpRoot, binaryName)
|
|
47619
48332
|
];
|
|
47620
|
-
const extractedBin = candidates.find((c2) =>
|
|
48333
|
+
const extractedBin = candidates.find((c2) => fs77.existsSync(c2));
|
|
47621
48334
|
if (!extractedBin) {
|
|
47622
48335
|
log.warn("host-agent", "glab binary not found in the extracted archive \u2014 skipping");
|
|
47623
48336
|
return null;
|
|
47624
48337
|
}
|
|
47625
48338
|
const binDir = codeamBinDir();
|
|
47626
|
-
|
|
47627
|
-
const target =
|
|
47628
|
-
|
|
47629
|
-
|
|
48339
|
+
fs77.mkdirSync(binDir, { recursive: true });
|
|
48340
|
+
const target = path91.join(binDir, binaryName);
|
|
48341
|
+
fs77.copyFileSync(extractedBin, target);
|
|
48342
|
+
fs77.chmodSync(target, 493);
|
|
47630
48343
|
log.info("host-agent", `glab installed to ${target} (v${version3})`);
|
|
47631
48344
|
return target;
|
|
47632
48345
|
} catch (e) {
|
|
@@ -47708,9 +48421,9 @@ var defaultGitToolingRunner = {
|
|
|
47708
48421
|
var import_node_child_process28 = require("child_process");
|
|
47709
48422
|
|
|
47710
48423
|
// src/lib/updateNotifier.ts
|
|
47711
|
-
var
|
|
47712
|
-
var
|
|
47713
|
-
var
|
|
48424
|
+
var fs78 = __toESM(require("fs"));
|
|
48425
|
+
var os62 = __toESM(require("os"));
|
|
48426
|
+
var path92 = __toESM(require("path"));
|
|
47714
48427
|
var https8 = __toESM(require("https"));
|
|
47715
48428
|
var import_node_child_process27 = require("child_process");
|
|
47716
48429
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
@@ -47719,12 +48432,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
47719
48432
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
47720
48433
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
47721
48434
|
function cachePath() {
|
|
47722
|
-
const dir =
|
|
47723
|
-
return
|
|
48435
|
+
const dir = path92.join(os62.homedir(), ".codeam");
|
|
48436
|
+
return path92.join(dir, "update-check.json");
|
|
47724
48437
|
}
|
|
47725
48438
|
function readCache() {
|
|
47726
48439
|
try {
|
|
47727
|
-
const raw =
|
|
48440
|
+
const raw = fs78.readFileSync(cachePath(), "utf8");
|
|
47728
48441
|
const parsed = JSON.parse(raw);
|
|
47729
48442
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
47730
48443
|
return parsed;
|
|
@@ -47735,10 +48448,10 @@ function readCache() {
|
|
|
47735
48448
|
function writeCache(cache) {
|
|
47736
48449
|
try {
|
|
47737
48450
|
const file = cachePath();
|
|
47738
|
-
|
|
48451
|
+
fs78.mkdirSync(path92.dirname(file), { recursive: true });
|
|
47739
48452
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
47740
|
-
|
|
47741
|
-
|
|
48453
|
+
fs78.writeFileSync(tmp, JSON.stringify(cache));
|
|
48454
|
+
fs78.renameSync(tmp, file);
|
|
47742
48455
|
} catch {
|
|
47743
48456
|
}
|
|
47744
48457
|
}
|
|
@@ -47812,8 +48525,8 @@ function isLinkedInstall() {
|
|
|
47812
48525
|
timeout: 2e3
|
|
47813
48526
|
}).trim();
|
|
47814
48527
|
if (!root) return false;
|
|
47815
|
-
const pkgPath =
|
|
47816
|
-
return
|
|
48528
|
+
const pkgPath = path92.join(root, PKG_NAME);
|
|
48529
|
+
return fs78.lstatSync(pkgPath).isSymbolicLink();
|
|
47817
48530
|
} catch {
|
|
47818
48531
|
return false;
|
|
47819
48532
|
}
|
|
@@ -47849,7 +48562,7 @@ function maybeAutoUpdate(currentVersion, latest) {
|
|
|
47849
48562
|
return;
|
|
47850
48563
|
}
|
|
47851
48564
|
try {
|
|
47852
|
-
|
|
48565
|
+
fs78.unlinkSync(cachePath());
|
|
47853
48566
|
} catch {
|
|
47854
48567
|
}
|
|
47855
48568
|
process.stderr.write(` ${import_picocolors12.default.green("\u2713")} Updated. Resuming session...
|
|
@@ -47865,7 +48578,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
47865
48578
|
if (process.env.NODE_ENV === "test") return;
|
|
47866
48579
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
47867
48580
|
if (process.env.CI) return;
|
|
47868
|
-
const current2 = true ? "2.75.
|
|
48581
|
+
const current2 = true ? "2.75.27" : null;
|
|
47869
48582
|
if (!current2) return;
|
|
47870
48583
|
const cache = readCache();
|
|
47871
48584
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -47882,7 +48595,7 @@ function checkForUpdates() {
|
|
|
47882
48595
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
47883
48596
|
if (process.env.CI) return;
|
|
47884
48597
|
if (!process.stdout.isTTY) return;
|
|
47885
|
-
const current2 = true ? "2.75.
|
|
48598
|
+
const current2 = true ? "2.75.27" : null;
|
|
47886
48599
|
if (!current2) return;
|
|
47887
48600
|
const cache = readCache();
|
|
47888
48601
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -47905,7 +48618,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
47905
48618
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
47906
48619
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
47907
48620
|
function currentCliVersion() {
|
|
47908
|
-
return true ? "2.75.
|
|
48621
|
+
return true ? "2.75.27" : null;
|
|
47909
48622
|
}
|
|
47910
48623
|
async function installedVersion(deps) {
|
|
47911
48624
|
const ls = await deps.run(
|
|
@@ -48054,6 +48767,9 @@ function isDeployPayload(p2) {
|
|
|
48054
48767
|
function isStopPayload(p2) {
|
|
48055
48768
|
return typeof p2.sessionId === "string";
|
|
48056
48769
|
}
|
|
48770
|
+
function isResumePayload(p2) {
|
|
48771
|
+
return typeof p2.sessionId === "string" && p2.sessionId.length > 0;
|
|
48772
|
+
}
|
|
48057
48773
|
function isCleanupPayload(p2) {
|
|
48058
48774
|
return typeof p2.deployId === "string" && p2.deployId.length > 0;
|
|
48059
48775
|
}
|
|
@@ -48342,10 +49058,7 @@ var HostAgentSupervisor = class {
|
|
|
48342
49058
|
this.heartbeatTimer = setInterval(() => void this.beat(), HEARTBEAT_INTERVAL_MS);
|
|
48343
49059
|
this.heartbeatTimer.unref?.();
|
|
48344
49060
|
this.resumePersistedSessions();
|
|
48345
|
-
|
|
48346
|
-
{ hostId: this.identity.hostId, hostToken: this.identity.hostToken },
|
|
48347
|
-
{ event: "reconcile", activeDeployIds: this.activeSessions().map((s) => s.id) }
|
|
48348
|
-
).catch((err) => log.trace("host-agent", "boot reconcile failed (best-effort)", err));
|
|
49061
|
+
this.reportLiveSet("boot");
|
|
48349
49062
|
const updateMs = this.selfUpdateIntervalMs();
|
|
48350
49063
|
if (updateMs > 0) {
|
|
48351
49064
|
this.selfUpdateTimer = setInterval(() => void this.selfUpdateTick(), updateMs);
|
|
@@ -48591,6 +49304,14 @@ var HostAgentSupervisor = class {
|
|
|
48591
49304
|
this.stopChild(cmd.payload.sessionId);
|
|
48592
49305
|
return;
|
|
48593
49306
|
}
|
|
49307
|
+
if (cmd.type === "self_hosted_resume") {
|
|
49308
|
+
if (!isResumePayload(cmd.payload)) {
|
|
49309
|
+
log.warn("host-agent", `ignoring malformed self_hosted_resume id=${cmd.id}`);
|
|
49310
|
+
return;
|
|
49311
|
+
}
|
|
49312
|
+
this.resumeSavedSession(cmd.payload.sessionId);
|
|
49313
|
+
return;
|
|
49314
|
+
}
|
|
48594
49315
|
if (cmd.type === "self_hosted_cleanup") {
|
|
48595
49316
|
if (!isCleanupPayload(cmd.payload)) {
|
|
48596
49317
|
log.warn("host-agent", `ignoring malformed self_hosted_cleanup id=${cmd.id}`);
|
|
@@ -48638,13 +49359,13 @@ var HostAgentSupervisor = class {
|
|
|
48638
49359
|
const relay = this.relay;
|
|
48639
49360
|
if (!relay) return;
|
|
48640
49361
|
const raw = cmd.payload?.path;
|
|
48641
|
-
const target = typeof raw === "string" && raw.trim() ?
|
|
49362
|
+
const target = typeof raw === "string" && raw.trim() ? path93.resolve(raw.trim()) : os63.homedir();
|
|
48642
49363
|
try {
|
|
48643
|
-
const dirents = await
|
|
49364
|
+
const dirents = await fs79.promises.readdir(target, { withFileTypes: true });
|
|
48644
49365
|
const entries = dirents.filter((d3) => !d3.name.startsWith(".")).map((d3) => ({ name: d3.name, isDir: d3.isDirectory() })).sort(
|
|
48645
49366
|
(a, b) => a.isDir === b.isDir ? a.name.localeCompare(b.name) : a.isDir ? -1 : 1
|
|
48646
49367
|
);
|
|
48647
|
-
const parent =
|
|
49368
|
+
const parent = path93.dirname(target);
|
|
48648
49369
|
await relay.sendResult(cmd.id, "completed", {
|
|
48649
49370
|
path: target,
|
|
48650
49371
|
// null at the filesystem root so the UI can hide the ".." affordance.
|
|
@@ -48991,14 +49712,14 @@ var HostAgentSupervisor = class {
|
|
|
48991
49712
|
...buildHouseProxyChildEnv({ baseUrl, token, openRouter: openRouter === true }),
|
|
48992
49713
|
CODEAM_AUTO_TOKEN: payload.autoPairToken
|
|
48993
49714
|
};
|
|
48994
|
-
const houseConfigDir =
|
|
48995
|
-
|
|
49715
|
+
const houseConfigDir = path93.join(
|
|
49716
|
+
os63.homedir(),
|
|
48996
49717
|
".codeam",
|
|
48997
49718
|
"house-claude",
|
|
48998
49719
|
payload.deployId
|
|
48999
49720
|
);
|
|
49000
49721
|
try {
|
|
49001
|
-
|
|
49722
|
+
fs79.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
|
|
49002
49723
|
} catch {
|
|
49003
49724
|
}
|
|
49004
49725
|
childEnv.CLAUDE_CONFIG_DIR = houseConfigDir;
|
|
@@ -49008,7 +49729,7 @@ var HostAgentSupervisor = class {
|
|
|
49008
49729
|
token,
|
|
49009
49730
|
openRouter: !!openRouter,
|
|
49010
49731
|
claudeConfigDir: houseConfigDir
|
|
49011
|
-
});
|
|
49732
|
+
}, payload.deployId);
|
|
49012
49733
|
} else {
|
|
49013
49734
|
const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
|
|
49014
49735
|
const credEnv = provisionAgentCredentials(payload.agentId, auth, void 0);
|
|
@@ -49016,7 +49737,7 @@ var HostAgentSupervisor = class {
|
|
|
49016
49737
|
...credEnv,
|
|
49017
49738
|
CODEAM_AUTO_TOKEN: payload.autoPairToken
|
|
49018
49739
|
};
|
|
49019
|
-
clearHouseProxyConfig();
|
|
49740
|
+
clearHouseProxyConfig(payload.deployId);
|
|
49020
49741
|
}
|
|
49021
49742
|
childEnv = { ...childEnv, CODEAM_AUTO_APPROVE: "1" };
|
|
49022
49743
|
childEnv = { ...childEnv, CODEAM_HOST_AGENT_CHILD: "1" };
|
|
@@ -49024,7 +49745,7 @@ var HostAgentSupervisor = class {
|
|
|
49024
49745
|
report("installing", "installing agent CLI");
|
|
49025
49746
|
await this.runAgentInstall(payload.agentInstallScript);
|
|
49026
49747
|
}
|
|
49027
|
-
const home = process.env.HOME ||
|
|
49748
|
+
const home = process.env.HOME || os63.homedir();
|
|
49028
49749
|
childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
|
|
49029
49750
|
if (payload.cloneToken) {
|
|
49030
49751
|
try {
|
|
@@ -49032,13 +49753,13 @@ var HostAgentSupervisor = class {
|
|
|
49032
49753
|
if ((payload.repoProvider ?? "github") === "gitlab") {
|
|
49033
49754
|
const glabCmd = await ensureGlabCli(defaultGitToolingRunner);
|
|
49034
49755
|
if (glabCmd) {
|
|
49035
|
-
childEnv.PATH = `${codeamBinDir()}${
|
|
49756
|
+
childEnv.PATH = `${codeamBinDir()}${path93.delimiter}${childEnv.PATH}`;
|
|
49036
49757
|
await ensureGlabAuth(defaultGitToolingRunner, glabCmd, payload.cloneToken);
|
|
49037
49758
|
}
|
|
49038
49759
|
} else {
|
|
49039
49760
|
const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
|
|
49040
49761
|
if (ghCmd) {
|
|
49041
|
-
childEnv.PATH = `${codeamBinDir()}${
|
|
49762
|
+
childEnv.PATH = `${codeamBinDir()}${path93.delimiter}${childEnv.PATH}`;
|
|
49042
49763
|
await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
|
|
49043
49764
|
}
|
|
49044
49765
|
}
|
|
@@ -49066,9 +49787,9 @@ var HostAgentSupervisor = class {
|
|
|
49066
49787
|
);
|
|
49067
49788
|
if (!payload.suppressOnboardingWelcome) {
|
|
49068
49789
|
try {
|
|
49069
|
-
const cfgDir = childEnv.CLAUDE_CONFIG_DIR ||
|
|
49070
|
-
const projectDir =
|
|
49071
|
-
const hasPriorConversation =
|
|
49790
|
+
const cfgDir = childEnv.CLAUDE_CONFIG_DIR || path93.join(os63.homedir(), ".claude");
|
|
49791
|
+
const projectDir = path93.join(cfgDir, "projects", encodeCwd(cwd));
|
|
49792
|
+
const hasPriorConversation = fs79.existsSync(projectDir) && fs79.readdirSync(projectDir).some((f) => f.endsWith(".jsonl"));
|
|
49072
49793
|
if (hasPriorConversation) {
|
|
49073
49794
|
childEnv.CODEAM_RESUME_LATEST = "1";
|
|
49074
49795
|
log.info(
|
|
@@ -49196,7 +49917,7 @@ var HostAgentSupervisor = class {
|
|
|
49196
49917
|
);
|
|
49197
49918
|
continue;
|
|
49198
49919
|
}
|
|
49199
|
-
this.resumeOne({ deployId: rec.deployId, cwd: rec.cwd, session });
|
|
49920
|
+
this.resumeOne({ deployId: rec.deployId, cwd: rec.cwd, session, agent: rec.agent });
|
|
49200
49921
|
resumed += 1;
|
|
49201
49922
|
}
|
|
49202
49923
|
log.info(
|
|
@@ -49219,7 +49940,7 @@ var HostAgentSupervisor = class {
|
|
|
49219
49940
|
fallbackResumeTarget() {
|
|
49220
49941
|
const session = getActiveSession();
|
|
49221
49942
|
if (!session || !session.pluginId || !session.pollSecret || !session.agent) return null;
|
|
49222
|
-
const cwd = session.cwd &&
|
|
49943
|
+
const cwd = session.cwd && fs79.existsSync(session.cwd) ? session.cwd : process.cwd();
|
|
49223
49944
|
const deployId = deployIdFromWorkspace(session.cwd) ?? session.id;
|
|
49224
49945
|
return { deployId, cwd, session };
|
|
49225
49946
|
}
|
|
@@ -49233,23 +49954,94 @@ var HostAgentSupervisor = class {
|
|
|
49233
49954
|
}
|
|
49234
49955
|
return st3;
|
|
49235
49956
|
}
|
|
49957
|
+
/**
|
|
49958
|
+
* `self_hosted_resume` — the user opened (or reconnected) a session this box
|
|
49959
|
+
* is not running. A boot resumes only the children that were LIVE when the
|
|
49960
|
+
* box went down, so any other saved session was a dead card: the app said
|
|
49961
|
+
* "waking up — your message is queued", the box woke, and the session never
|
|
49962
|
+
* came back (codeagent-o7lm, QA box 2026-09-25: 4 saved sessions, 2 resumed).
|
|
49963
|
+
*
|
|
49964
|
+
* Resumes it through the same `resumeOne` a boot uses (bounded retries,
|
|
49965
|
+
* house-proxy env, persisted into the live set), then re-reports the live
|
|
49966
|
+
* set so the backend restores the session's host link. No-op when the
|
|
49967
|
+
* session is unknown, lacks its pairing, or its workspace is gone — the app
|
|
49968
|
+
* then keeps its offline state instead of a phantom "waking".
|
|
49969
|
+
*/
|
|
49970
|
+
resumeSavedSession(sessionId) {
|
|
49971
|
+
const session = this.listSavedSessions().find((s) => s.id === sessionId);
|
|
49972
|
+
if (!session || !session.pluginId || !session.pollSecret || !session.agent) {
|
|
49973
|
+
log.warn("host-agent", `self_hosted_resume ${sessionId.slice(0, 8)}: no saved pairing on this box`);
|
|
49974
|
+
return;
|
|
49975
|
+
}
|
|
49976
|
+
if (!session.cwd || !fs79.existsSync(session.cwd)) {
|
|
49977
|
+
log.warn("host-agent", `self_hosted_resume ${sessionId.slice(0, 8)}: workspace is gone`);
|
|
49978
|
+
return;
|
|
49979
|
+
}
|
|
49980
|
+
const deployId = deployIdFromWorkspace(session.cwd) ?? session.id;
|
|
49981
|
+
if (this.children.has(deployId)) {
|
|
49982
|
+
log.info("host-agent", `self_hosted_resume ${sessionId.slice(0, 8)}: already live`);
|
|
49983
|
+
return;
|
|
49984
|
+
}
|
|
49985
|
+
this.resumeOne({ deployId, cwd: session.cwd, session });
|
|
49986
|
+
this.reportLiveSet("resume");
|
|
49987
|
+
}
|
|
49988
|
+
/**
|
|
49989
|
+
* Tell the backend exactly which sessions this host runs. `activeSessions`
|
|
49990
|
+
* (additive) carries the PairedSession id of every child that knows it, so a
|
|
49991
|
+
* link lost to host-identity churn is rebuilt instead of the session
|
|
49992
|
+
* rendering as LOCAL with a reconnect the user cannot perform.
|
|
49993
|
+
*/
|
|
49994
|
+
reportLiveSet(why) {
|
|
49995
|
+
const children = [...this.children.values()];
|
|
49996
|
+
void reportSessionEvent(
|
|
49997
|
+
{ hostId: this.identity.hostId, hostToken: this.identity.hostToken },
|
|
49998
|
+
{
|
|
49999
|
+
event: "reconcile",
|
|
50000
|
+
activeDeployIds: children.map((c2) => c2.deployId),
|
|
50001
|
+
activeSessions: children.filter((c2) => typeof c2.sessionId === "string").map((c2) => ({ deployId: c2.deployId, sessionId: c2.sessionId, agent: c2.agent })),
|
|
50002
|
+
knownSessions: this.knownSavedSessions()
|
|
50003
|
+
}
|
|
50004
|
+
).catch((err) => log.trace("host-agent", `${why} reconcile failed (best-effort)`, err));
|
|
50005
|
+
}
|
|
50006
|
+
/**
|
|
50007
|
+
* Every saved session this host could resume — a pairing whose deploy
|
|
50008
|
+
* workspace is still on disk — live or not. The backend links the non-live
|
|
50009
|
+
* ones too, so the app knows they belong to THIS box and wakes + resumes it
|
|
50010
|
+
* when the user opens one, instead of showing a LOCAL session with a
|
|
50011
|
+
* "run codeam in your terminal" the user cannot do (codeagent-bbou).
|
|
50012
|
+
*/
|
|
50013
|
+
knownSavedSessions() {
|
|
50014
|
+
try {
|
|
50015
|
+
const persisted = new Map(this.sessionStore.load().map((r) => [r.deployId, r.agent]));
|
|
50016
|
+
for (const c2 of this.children.values()) persisted.set(c2.deployId, c2.agent);
|
|
50017
|
+
return this.listSavedSessions().map((s) => ({ s, deployId: deployIdFromWorkspace(s.cwd) })).filter(
|
|
50018
|
+
(x) => x.deployId !== null && !!x.s.cwd && fs79.existsSync(x.s.cwd)
|
|
50019
|
+
).map(({ s, deployId }) => {
|
|
50020
|
+
const agent = persisted.get(deployId);
|
|
50021
|
+
return { deployId, sessionId: s.id, ...agent ? { agent } : {} };
|
|
50022
|
+
});
|
|
50023
|
+
} catch {
|
|
50024
|
+
return [];
|
|
50025
|
+
}
|
|
50026
|
+
}
|
|
49236
50027
|
/** Spawn ONE resume child for `target` (boot, retry, or re-probe). */
|
|
49237
50028
|
resumeOne(target) {
|
|
49238
50029
|
const { session, deployId } = target;
|
|
49239
50030
|
if (this.children.has(deployId)) return;
|
|
49240
50031
|
const st3 = this.resumeStateFor(target);
|
|
49241
50032
|
try {
|
|
49242
|
-
const cwd =
|
|
50033
|
+
const cwd = fs79.existsSync(target.cwd) ? target.cwd : process.cwd();
|
|
49243
50034
|
const proc = this.resumeSpawner(
|
|
49244
|
-
{ ...readHouseProxyChildEnv(), CODEAM_RESUME_SESSION_ID: session.id },
|
|
50035
|
+
{ ...readHouseProxyChildEnv(deployId), CODEAM_RESUME_SESSION_ID: session.id },
|
|
49245
50036
|
cwd
|
|
49246
50037
|
);
|
|
49247
50038
|
const child = {
|
|
49248
50039
|
deployId,
|
|
49249
50040
|
proc,
|
|
49250
50041
|
cwd,
|
|
49251
|
-
agent: session.agent,
|
|
49252
|
-
startedAt: Date.now()
|
|
50042
|
+
agent: target.agent ?? session.agent,
|
|
50043
|
+
startedAt: Date.now(),
|
|
50044
|
+
sessionId: session.id
|
|
49253
50045
|
};
|
|
49254
50046
|
this.trackChild(child);
|
|
49255
50047
|
let tail = "";
|
|
@@ -49265,7 +50057,7 @@ var HostAgentSupervisor = class {
|
|
|
49265
50057
|
return;
|
|
49266
50058
|
}
|
|
49267
50059
|
if (tracked && signal) {
|
|
49268
|
-
this.onResumeChildExit(target, 128 + (
|
|
50060
|
+
this.onResumeChildExit(target, 128 + (os63.constants.signals[signal] ?? 9), `signal ${signal}`);
|
|
49269
50061
|
return;
|
|
49270
50062
|
}
|
|
49271
50063
|
log.warn(
|
|
@@ -49308,7 +50100,7 @@ var HostAgentSupervisor = class {
|
|
|
49308
50100
|
if (Date.now() - child.startedAt < CRASH_RESPAWN_MIN_UPTIME_MS) return false;
|
|
49309
50101
|
const session = pickSavedSessionForWorkspace(this.listSavedSessions(), child.cwd);
|
|
49310
50102
|
if (!session) return false;
|
|
49311
|
-
const exitCode = typeof code === "number" ? code : 128 + (signal ?
|
|
50103
|
+
const exitCode = typeof code === "number" ? code : 128 + (signal ? os63.constants.signals[signal] ?? 9 : 9);
|
|
49312
50104
|
log.warn(
|
|
49313
50105
|
"host-agent",
|
|
49314
50106
|
`session deploy=${child.deployId.slice(0, 8)} died (${signal ?? code}) after ${Math.round((Date.now() - child.startedAt) / 1e3)}s \u2014 respawning it (resume)`
|
|
@@ -49457,12 +50249,12 @@ var HostAgentSupervisor = class {
|
|
|
49457
50249
|
this.untrackChild(deployId);
|
|
49458
50250
|
}
|
|
49459
50251
|
const dirs = [
|
|
49460
|
-
|
|
49461
|
-
|
|
50252
|
+
path93.join(selfHostedWorkspaceRoot(), deployId),
|
|
50253
|
+
path93.join(os63.homedir(), ".codeam", "house-claude", deployId)
|
|
49462
50254
|
];
|
|
49463
50255
|
for (const dir of dirs) {
|
|
49464
50256
|
try {
|
|
49465
|
-
|
|
50257
|
+
fs79.rmSync(dir, { recursive: true, force: true });
|
|
49466
50258
|
} catch (err) {
|
|
49467
50259
|
log.warn(
|
|
49468
50260
|
"host-agent",
|
|
@@ -49621,9 +50413,9 @@ async function invite() {
|
|
|
49621
50413
|
// src/commands/doctor.ts
|
|
49622
50414
|
var import_node_dns = require("dns");
|
|
49623
50415
|
var import_node_util6 = require("util");
|
|
49624
|
-
var
|
|
49625
|
-
var
|
|
49626
|
-
var
|
|
50416
|
+
var import_node_crypto13 = require("crypto");
|
|
50417
|
+
var fs80 = __toESM(require("fs"));
|
|
50418
|
+
var path94 = __toESM(require("path"));
|
|
49627
50419
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
49628
50420
|
var dnsResolveP = (0, import_node_util6.promisify)(import_node_dns.resolve);
|
|
49629
50421
|
async function checkDns(apiBase2) {
|
|
@@ -49679,13 +50471,13 @@ async function checkHealth(apiBase2) {
|
|
|
49679
50471
|
}
|
|
49680
50472
|
}
|
|
49681
50473
|
function checkConfigDir() {
|
|
49682
|
-
const dir =
|
|
50474
|
+
const dir = path94.join(require("os").homedir(), ".codeam");
|
|
49683
50475
|
try {
|
|
49684
|
-
|
|
49685
|
-
const probe =
|
|
49686
|
-
|
|
49687
|
-
const read =
|
|
49688
|
-
|
|
50476
|
+
fs80.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
50477
|
+
const probe = path94.join(dir, ".doctor-probe");
|
|
50478
|
+
fs80.writeFileSync(probe, "ok", { mode: 384 });
|
|
50479
|
+
const read = fs80.readFileSync(probe, "utf8");
|
|
50480
|
+
fs80.unlinkSync(probe);
|
|
49689
50481
|
if (read !== "ok") throw new Error("write/read round-trip mismatch");
|
|
49690
50482
|
return {
|
|
49691
50483
|
id: "config-dir",
|
|
@@ -49725,9 +50517,9 @@ function checkSessions() {
|
|
|
49725
50517
|
}
|
|
49726
50518
|
}
|
|
49727
50519
|
function checkAgentBinaries() {
|
|
49728
|
-
const
|
|
50520
|
+
const os66 = createOsStrategy();
|
|
49729
50521
|
return getEnabledAgents().map((meta) => {
|
|
49730
|
-
const found =
|
|
50522
|
+
const found = os66.findInPath(meta.binaryName);
|
|
49731
50523
|
return {
|
|
49732
50524
|
id: `agent-${meta.id}`,
|
|
49733
50525
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -49749,7 +50541,7 @@ function checkNodePty() {
|
|
|
49749
50541
|
detail: "not required on this platform"
|
|
49750
50542
|
};
|
|
49751
50543
|
}
|
|
49752
|
-
const vendoredPath =
|
|
50544
|
+
const vendoredPath = path94.join(__dirname, "vendor", "node-pty");
|
|
49753
50545
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
49754
50546
|
try {
|
|
49755
50547
|
require(target);
|
|
@@ -49791,9 +50583,9 @@ function checkChokidar() {
|
|
|
49791
50583
|
}
|
|
49792
50584
|
async function doctor(args2 = []) {
|
|
49793
50585
|
const json = args2.includes("--json");
|
|
49794
|
-
const cliVersion = true ? "2.75.
|
|
50586
|
+
const cliVersion = true ? "2.75.27" : "0.0.0-dev";
|
|
49795
50587
|
const apiBase2 = resolveApiBaseUrl();
|
|
49796
|
-
const diagnosticId = (0,
|
|
50588
|
+
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
49797
50589
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
49798
50590
|
const [dns, health] = await Promise.all([
|
|
49799
50591
|
checkDns(apiBase2),
|
|
@@ -50315,7 +51107,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
50315
51107
|
// src/commands/version.ts
|
|
50316
51108
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
50317
51109
|
function version2() {
|
|
50318
|
-
const v = true ? "2.75.
|
|
51110
|
+
const v = true ? "2.75.27" : "unknown";
|
|
50319
51111
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
50320
51112
|
}
|
|
50321
51113
|
|
|
@@ -50464,10 +51256,10 @@ var EXIT_CODE_NAMES = {
|
|
|
50464
51256
|
};
|
|
50465
51257
|
|
|
50466
51258
|
// src/index.ts
|
|
50467
|
-
var
|
|
51259
|
+
var os65 = __toESM(require("os"));
|
|
50468
51260
|
if (!process.env.HOME) {
|
|
50469
51261
|
try {
|
|
50470
|
-
const home =
|
|
51262
|
+
const home = os65.homedir();
|
|
50471
51263
|
if (home) process.env.HOME = home;
|
|
50472
51264
|
} catch {
|
|
50473
51265
|
}
|
|
@@ -50513,9 +51305,15 @@ async function main() {
|
|
|
50513
51305
|
await commands[command]();
|
|
50514
51306
|
return;
|
|
50515
51307
|
}
|
|
51308
|
+
if (command === "mcp-run" || command === "mcp-router" || command === "preview-mcp") {
|
|
51309
|
+
loadMcpSecrets();
|
|
51310
|
+
}
|
|
50516
51311
|
if (command === "mcp-run") {
|
|
50517
51312
|
return mcpRun(args);
|
|
50518
51313
|
}
|
|
51314
|
+
if (command === "preview-mcp") {
|
|
51315
|
+
return previewMcp();
|
|
51316
|
+
}
|
|
50519
51317
|
if (command === "mcp-warm") {
|
|
50520
51318
|
await mcpWarm(args);
|
|
50521
51319
|
return;
|