codeam-cli 2.33.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/index.js +489 -339
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
498
498
|
// package.json
|
|
499
499
|
var package_default = {
|
|
500
500
|
name: "codeam-cli",
|
|
501
|
-
version: "2.
|
|
501
|
+
version: "2.35.0",
|
|
502
502
|
description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
|
|
503
503
|
type: "commonjs",
|
|
504
504
|
main: "dist/index.js",
|
|
@@ -852,6 +852,28 @@ async function postPreviewEvent(input) {
|
|
|
852
852
|
};
|
|
853
853
|
}
|
|
854
854
|
}
|
|
855
|
+
async function postBeadsProvisioning(input) {
|
|
856
|
+
try {
|
|
857
|
+
await _transport.postJsonAuthed(
|
|
858
|
+
`${API_BASE}/api/beads/provisioning`,
|
|
859
|
+
{
|
|
860
|
+
sessionId: input.sessionId,
|
|
861
|
+
pluginId: input.pluginId,
|
|
862
|
+
status: input.status,
|
|
863
|
+
...input.projectKey ? { projectKey: input.projectKey } : {}
|
|
864
|
+
},
|
|
865
|
+
input.pluginAuthToken
|
|
866
|
+
);
|
|
867
|
+
return { ok: true };
|
|
868
|
+
} catch (err) {
|
|
869
|
+
const e = err;
|
|
870
|
+
return {
|
|
871
|
+
ok: false,
|
|
872
|
+
status: typeof e.statusCode === "number" ? e.statusCode : 0,
|
|
873
|
+
message: e.message || "unknown"
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
}
|
|
855
877
|
async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
856
878
|
return new Promise((resolve7, reject) => {
|
|
857
879
|
const data = JSON.stringify(body);
|
|
@@ -1162,8 +1184,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
1162
1184
|
return decodedFile;
|
|
1163
1185
|
};
|
|
1164
1186
|
}
|
|
1165
|
-
function normalizeWindowsPath(
|
|
1166
|
-
return
|
|
1187
|
+
function normalizeWindowsPath(path50) {
|
|
1188
|
+
return path50.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
1167
1189
|
}
|
|
1168
1190
|
|
|
1169
1191
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3643,9 +3665,9 @@ async function addSourceContext(frames) {
|
|
|
3643
3665
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3644
3666
|
return frames;
|
|
3645
3667
|
}
|
|
3646
|
-
function getContextLinesFromFile(
|
|
3668
|
+
function getContextLinesFromFile(path50, ranges, output) {
|
|
3647
3669
|
return new Promise((resolve7) => {
|
|
3648
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3670
|
+
const stream = (0, import_node_fs.createReadStream)(path50);
|
|
3649
3671
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3650
3672
|
input: stream
|
|
3651
3673
|
});
|
|
@@ -3660,7 +3682,7 @@ function getContextLinesFromFile(path49, ranges, output) {
|
|
|
3660
3682
|
let rangeStart = range[0];
|
|
3661
3683
|
let rangeEnd = range[1];
|
|
3662
3684
|
function onStreamError() {
|
|
3663
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3685
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path50, 1);
|
|
3664
3686
|
lineReaded.close();
|
|
3665
3687
|
lineReaded.removeAllListeners();
|
|
3666
3688
|
destroyStreamAndResolve();
|
|
@@ -3721,8 +3743,8 @@ function clearLineContext(frame) {
|
|
|
3721
3743
|
delete frame.context_line;
|
|
3722
3744
|
delete frame.post_context;
|
|
3723
3745
|
}
|
|
3724
|
-
function shouldSkipContextLinesForFile(
|
|
3725
|
-
return
|
|
3746
|
+
function shouldSkipContextLinesForFile(path50) {
|
|
3747
|
+
return path50.startsWith("node:") || path50.endsWith(".min.js") || path50.endsWith(".min.cjs") || path50.endsWith(".min.mjs") || path50.startsWith("data:");
|
|
3726
3748
|
}
|
|
3727
3749
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3728
3750
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -5876,7 +5898,7 @@ function readAnonId() {
|
|
|
5876
5898
|
}
|
|
5877
5899
|
function superProperties() {
|
|
5878
5900
|
return {
|
|
5879
|
-
cliVersion: true ? "2.
|
|
5901
|
+
cliVersion: true ? "2.35.0" : "0.0.0-dev",
|
|
5880
5902
|
nodeVersion: process.version,
|
|
5881
5903
|
platform: process.platform,
|
|
5882
5904
|
arch: process.arch,
|
|
@@ -9948,13 +9970,13 @@ function detectStartupBanner(lines) {
|
|
|
9948
9970
|
while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
|
|
9949
9971
|
if (metaIdx - artStart < 2) return null;
|
|
9950
9972
|
const pathLine = (lines[metaIdx + 1] ?? "").trim();
|
|
9951
|
-
const
|
|
9973
|
+
const path50 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
|
|
9952
9974
|
return {
|
|
9953
9975
|
title: "",
|
|
9954
9976
|
subtitle: lines[metaIdx].trim(),
|
|
9955
|
-
path:
|
|
9977
|
+
path: path50,
|
|
9956
9978
|
startIdx: artStart,
|
|
9957
|
-
endIdx: metaIdx + (
|
|
9979
|
+
endIdx: metaIdx + (path50 ? 1 : 0)
|
|
9958
9980
|
};
|
|
9959
9981
|
}
|
|
9960
9982
|
|
|
@@ -11290,11 +11312,11 @@ function parseReview(stdout) {
|
|
|
11290
11312
|
for (const line of lines) {
|
|
11291
11313
|
const m = line.match(HUNK_LINE_RE);
|
|
11292
11314
|
if (!m) continue;
|
|
11293
|
-
const [,
|
|
11294
|
-
if (!
|
|
11315
|
+
const [, path50, lineNo, sevToken, message] = m;
|
|
11316
|
+
if (!path50 || !lineNo || !message) continue;
|
|
11295
11317
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
11296
11318
|
hunks.push({
|
|
11297
|
-
path:
|
|
11319
|
+
path: path50.trim(),
|
|
11298
11320
|
line: Number(lineNo),
|
|
11299
11321
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
11300
11322
|
message: cleanedMessage
|
|
@@ -15688,11 +15710,11 @@ function extractSelectPrompt(text) {
|
|
|
15688
15710
|
}
|
|
15689
15711
|
|
|
15690
15712
|
// src/commands/start/handlers.ts
|
|
15691
|
-
var
|
|
15713
|
+
var fs32 = __toESM(require("fs"));
|
|
15692
15714
|
var os25 = __toESM(require("os"));
|
|
15693
|
-
var
|
|
15715
|
+
var path39 = __toESM(require("path"));
|
|
15694
15716
|
var import_crypto3 = require("crypto");
|
|
15695
|
-
var
|
|
15717
|
+
var import_child_process16 = require("child_process");
|
|
15696
15718
|
|
|
15697
15719
|
// src/lib/payload.ts
|
|
15698
15720
|
var import_zod = require("zod");
|
|
@@ -17282,10 +17304,12 @@ var BdAdapter = class {
|
|
|
17282
17304
|
return this.resolveBinary() !== null;
|
|
17283
17305
|
}
|
|
17284
17306
|
/**
|
|
17285
|
-
* Run an arbitrary bd subcommand
|
|
17286
|
-
*
|
|
17287
|
-
*
|
|
17288
|
-
*
|
|
17307
|
+
* Run an arbitrary bd subcommand against the home brain. `BEADS_DIR` is set
|
|
17308
|
+
* to the configured `beadsDir` (tests) or `~/.beads` (the verified embedded
|
|
17309
|
+
* home brain) so every command resolves to the same single graph regardless
|
|
17310
|
+
* of the process cwd. Returns the raw result; callers decide how to interpret
|
|
17311
|
+
* exit codes — note bd exits 0 even for some error states (e.g. "no beads
|
|
17312
|
+
* database found"), so JSON-parsing callers must also inspect the payload.
|
|
17289
17313
|
*/
|
|
17290
17314
|
async run(args2) {
|
|
17291
17315
|
const binary = this.resolveBinary();
|
|
@@ -17293,14 +17317,9 @@ var BdAdapter = class {
|
|
|
17293
17317
|
return { code: -1, stdout: "", stderr: "bd binary not resolved" };
|
|
17294
17318
|
}
|
|
17295
17319
|
const env = { ...process.env };
|
|
17296
|
-
|
|
17297
|
-
|
|
17298
|
-
|
|
17299
|
-
} else if (!finalArgs.includes("--global")) {
|
|
17300
|
-
finalArgs.push("--global");
|
|
17301
|
-
}
|
|
17302
|
-
log.trace("beads", `bd ${finalArgs.join(" ")}`);
|
|
17303
|
-
return _spawnSeam.run(binary, finalArgs, { cwd: this.opts.cwd, env });
|
|
17320
|
+
env.BEADS_DIR = this.opts.beadsDir ?? defaultBeadsHomeDir();
|
|
17321
|
+
log.trace("beads", `bd ${args2.join(" ")} (BEADS_DIR=${env.BEADS_DIR})`);
|
|
17322
|
+
return _spawnSeam.run(binary, args2, { cwd: this.opts.cwd, env });
|
|
17304
17323
|
}
|
|
17305
17324
|
/**
|
|
17306
17325
|
* `bd ready --json` → typed issue array. `bd list --json` shares the shape,
|
|
@@ -17372,92 +17391,243 @@ function defaultBeadsHomeDir() {
|
|
|
17372
17391
|
return path35.join(os24.homedir(), ".beads");
|
|
17373
17392
|
}
|
|
17374
17393
|
|
|
17375
|
-
// src/beads/
|
|
17376
|
-
var
|
|
17394
|
+
// src/beads/provisioner.ts
|
|
17395
|
+
var import_child_process14 = require("child_process");
|
|
17396
|
+
var fs30 = __toESM(require("fs"));
|
|
17397
|
+
var path36 = __toESM(require("path"));
|
|
17398
|
+
|
|
17399
|
+
// src/beads/install-bd.ts
|
|
17400
|
+
var import_child_process13 = require("child_process");
|
|
17401
|
+
var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
|
|
17402
|
+
var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
|
|
17403
|
+
function resolveInstallStrategy(platform2) {
|
|
17404
|
+
if (platform2 === "win32") {
|
|
17405
|
+
return {
|
|
17406
|
+
command: "powershell.exe",
|
|
17407
|
+
args: [
|
|
17408
|
+
"-NoProfile",
|
|
17409
|
+
"-NonInteractive",
|
|
17410
|
+
"-ExecutionPolicy",
|
|
17411
|
+
"Bypass",
|
|
17412
|
+
"-Command",
|
|
17413
|
+
`irm ${INSTALL_PS1_URL} | iex`
|
|
17414
|
+
],
|
|
17415
|
+
description: `PowerShell: irm ${INSTALL_PS1_URL} | iex (requires Go 1.24+ and Git for Windows on PATH)`
|
|
17416
|
+
};
|
|
17417
|
+
}
|
|
17418
|
+
return {
|
|
17419
|
+
command: "bash",
|
|
17420
|
+
args: ["-c", `curl -fsSL ${INSTALL_SH_URL} | bash`],
|
|
17421
|
+
description: `curl -fsSL ${INSTALL_SH_URL} | bash`
|
|
17422
|
+
};
|
|
17423
|
+
}
|
|
17424
|
+
var _installSpawnSeam = {
|
|
17425
|
+
run: _defaultInstallSpawn
|
|
17426
|
+
};
|
|
17427
|
+
function _defaultInstallSpawn(strategy) {
|
|
17428
|
+
return new Promise((resolve7) => {
|
|
17429
|
+
let proc;
|
|
17430
|
+
try {
|
|
17431
|
+
proc = (0, import_child_process13.spawn)(strategy.command, strategy.args, { env: process.env });
|
|
17432
|
+
} catch (err) {
|
|
17433
|
+
resolve7({ ok: false, code: -1, stderr: err.message });
|
|
17434
|
+
return;
|
|
17435
|
+
}
|
|
17436
|
+
let stderr = "";
|
|
17437
|
+
proc.stderr?.on("data", (c2) => {
|
|
17438
|
+
stderr += c2.toString();
|
|
17439
|
+
});
|
|
17440
|
+
proc.on("error", (err) => resolve7({ ok: false, code: -1, stderr: err.message }));
|
|
17441
|
+
proc.on(
|
|
17442
|
+
"close",
|
|
17443
|
+
(code) => resolve7({ ok: code === 0, code: code ?? -1, stderr })
|
|
17444
|
+
);
|
|
17445
|
+
});
|
|
17446
|
+
}
|
|
17447
|
+
async function installBd(platform2 = process.platform) {
|
|
17448
|
+
const strategy = resolveInstallStrategy(platform2);
|
|
17449
|
+
log.info("beads", `installing bd via ${strategy.description}`);
|
|
17450
|
+
const result = await _installSpawnSeam.run(strategy);
|
|
17451
|
+
if (!result.ok) {
|
|
17452
|
+
log.warn(
|
|
17453
|
+
"beads",
|
|
17454
|
+
`bd install failed (code=${result.code}): ${result.stderr.slice(0, 200)}`
|
|
17455
|
+
);
|
|
17456
|
+
}
|
|
17457
|
+
return result;
|
|
17458
|
+
}
|
|
17459
|
+
|
|
17460
|
+
// src/beads/provisioner.ts
|
|
17461
|
+
var AGENT_SETUP_RECIPE = {
|
|
17377
17462
|
claude: "claude",
|
|
17378
17463
|
codex: "codex",
|
|
17464
|
+
copilot: "copilot",
|
|
17379
17465
|
cursor: "cursor",
|
|
17380
|
-
gemini: "gemini",
|
|
17381
17466
|
aider: "aider",
|
|
17382
|
-
|
|
17467
|
+
gemini: "gemini",
|
|
17468
|
+
coderabbit: null
|
|
17469
|
+
};
|
|
17470
|
+
var _provisionSeam = {
|
|
17471
|
+
install: installBd,
|
|
17472
|
+
homeBrainInitialized,
|
|
17473
|
+
/** GAP 1 — symlink the resolved bd onto PATH for the agent's own shell. */
|
|
17474
|
+
linkBdOntoPath,
|
|
17475
|
+
/** Silence bd's `beads.role not configured` warning. */
|
|
17476
|
+
setGitBeadsRole
|
|
17477
|
+
};
|
|
17478
|
+
var _linkSeam = {
|
|
17479
|
+
platform: () => process.platform,
|
|
17480
|
+
/**
|
|
17481
|
+
* The directory the `codeam` executable lives in — guaranteed on PATH (npm
|
|
17482
|
+
* puts global bins there, and that's how the user launched us). We symlink
|
|
17483
|
+
* `bd` alongside it so the AGENT's shell resolves `bd` natively. Derived from
|
|
17484
|
+
* `process.argv[1]` (the CLI entry script). Returns null when it can't be
|
|
17485
|
+
* determined.
|
|
17486
|
+
*/
|
|
17487
|
+
cliBinDir: () => {
|
|
17488
|
+
const entry = process.argv[1];
|
|
17489
|
+
if (!entry) return null;
|
|
17490
|
+
try {
|
|
17491
|
+
return path36.dirname(fs30.realpathSync(entry));
|
|
17492
|
+
} catch {
|
|
17493
|
+
return path36.dirname(entry);
|
|
17494
|
+
}
|
|
17495
|
+
},
|
|
17496
|
+
/** Current symlink target at `linkPath`, or null when absent / not a link. */
|
|
17497
|
+
readlink: (linkPath) => {
|
|
17498
|
+
try {
|
|
17499
|
+
return fs30.readlinkSync(linkPath);
|
|
17500
|
+
} catch {
|
|
17501
|
+
return null;
|
|
17502
|
+
}
|
|
17503
|
+
},
|
|
17504
|
+
unlink: (linkPath) => fs30.unlinkSync(linkPath),
|
|
17505
|
+
symlink: (target, linkPath) => fs30.symlinkSync(target, linkPath)
|
|
17383
17506
|
};
|
|
17384
|
-
|
|
17507
|
+
function linkBdOntoPath(binaryPath) {
|
|
17508
|
+
if (_linkSeam.platform() === "win32") return;
|
|
17509
|
+
const binDir = _linkSeam.cliBinDir();
|
|
17510
|
+
if (!binDir) return;
|
|
17511
|
+
const linkPath = path36.join(binDir, "bd");
|
|
17512
|
+
if (linkPath === binaryPath) return;
|
|
17513
|
+
const current = _linkSeam.readlink(linkPath);
|
|
17514
|
+
if (current === binaryPath) return;
|
|
17515
|
+
if (current !== null) _linkSeam.unlink(linkPath);
|
|
17516
|
+
_linkSeam.symlink(binaryPath, linkPath);
|
|
17517
|
+
log.info("beads", `linked bd onto PATH: ${linkPath} -> ${binaryPath}`);
|
|
17518
|
+
}
|
|
17519
|
+
function setGitBeadsRole() {
|
|
17520
|
+
(0, import_child_process14.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
|
|
17521
|
+
stdio: "ignore"
|
|
17522
|
+
});
|
|
17523
|
+
}
|
|
17524
|
+
function homeBrainInitialized(beadsDir) {
|
|
17525
|
+
try {
|
|
17526
|
+
return fs30.statSync(path36.join(beadsDir, "embeddeddolt")).isDirectory();
|
|
17527
|
+
} catch {
|
|
17528
|
+
return false;
|
|
17529
|
+
}
|
|
17530
|
+
}
|
|
17531
|
+
async function provisionBeads(opts = {}) {
|
|
17385
17532
|
const bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
|
|
17533
|
+
const beadsDir = opts.beadsDir ?? defaultBeadsHomeDir();
|
|
17386
17534
|
const result = {
|
|
17387
17535
|
bdAvailable: false,
|
|
17388
|
-
|
|
17389
|
-
|
|
17390
|
-
|
|
17536
|
+
initialized: false,
|
|
17537
|
+
exportEnabled: false,
|
|
17538
|
+
agentsWired: []
|
|
17391
17539
|
};
|
|
17392
17540
|
if (!bd.isAvailable()) {
|
|
17393
|
-
log.
|
|
17541
|
+
log.info("beads", "bd binary missing \u2014 running OS installer fallback");
|
|
17542
|
+
const install = await _provisionSeam.install();
|
|
17543
|
+
if (!install.ok) {
|
|
17544
|
+
log.warn("beads", `bd install failed (code=${install.code}) \u2014 beads disabled this run`);
|
|
17545
|
+
return result;
|
|
17546
|
+
}
|
|
17547
|
+
}
|
|
17548
|
+
if (!bd.isAvailable()) {
|
|
17549
|
+
log.warn("beads", "bd still unavailable after install \u2014 beads disabled this run");
|
|
17394
17550
|
return result;
|
|
17395
17551
|
}
|
|
17396
17552
|
result.bdAvailable = true;
|
|
17397
|
-
|
|
17398
|
-
if (
|
|
17399
|
-
|
|
17400
|
-
|
|
17553
|
+
const binaryPath = bd.resolveBinary();
|
|
17554
|
+
if (binaryPath) {
|
|
17555
|
+
try {
|
|
17556
|
+
_provisionSeam.linkBdOntoPath(binaryPath);
|
|
17557
|
+
} catch (err) {
|
|
17558
|
+
log.warn("beads", "linking bd onto PATH failed (non-fatal)", err);
|
|
17559
|
+
}
|
|
17401
17560
|
}
|
|
17402
|
-
|
|
17403
|
-
|
|
17404
|
-
|
|
17405
|
-
|
|
17406
|
-
|
|
17561
|
+
try {
|
|
17562
|
+
_provisionSeam.setGitBeadsRole();
|
|
17563
|
+
} catch (err) {
|
|
17564
|
+
log.trace("beads", `git config beads.role failed (non-fatal): ${err.message}`);
|
|
17565
|
+
}
|
|
17566
|
+
if (_provisionSeam.homeBrainInitialized(beadsDir)) {
|
|
17567
|
+
log.trace("beads", `home brain already initialized at ${beadsDir}`);
|
|
17568
|
+
result.initialized = true;
|
|
17569
|
+
} else {
|
|
17570
|
+
log.info("beads", `initializing home brain at ${beadsDir}`);
|
|
17571
|
+
const init = await bd.run(["init", "--skip-agents", "--skip-hooks", "--non-interactive"]);
|
|
17572
|
+
if (init.code !== 0) {
|
|
17573
|
+
log.warn("beads", `bd init failed (code=${init.code}): ${init.stderr.slice(0, 200)}`);
|
|
17574
|
+
return result;
|
|
17407
17575
|
}
|
|
17408
|
-
|
|
17409
|
-
if (applied) result.agentsConfigured.push(agent);
|
|
17576
|
+
result.initialized = true;
|
|
17410
17577
|
}
|
|
17411
|
-
|
|
17578
|
+
const exp = await bd.run(["config", "set", "export.auto", "true"]);
|
|
17579
|
+
result.exportEnabled = exp.code === 0;
|
|
17580
|
+
result.agentsWired = await setupAgents(bd, opts.agents ?? []);
|
|
17412
17581
|
log.info(
|
|
17413
17582
|
"beads",
|
|
17414
|
-
`
|
|
17583
|
+
`provision done initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
|
|
17415
17584
|
);
|
|
17416
17585
|
return result;
|
|
17417
17586
|
}
|
|
17418
|
-
async function
|
|
17419
|
-
const
|
|
17420
|
-
|
|
17421
|
-
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17425
|
-
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17587
|
+
async function setupAgents(bd, agents) {
|
|
17588
|
+
const wired = [];
|
|
17589
|
+
for (const recipe of dedupeRecipes(agents)) {
|
|
17590
|
+
try {
|
|
17591
|
+
const check = await bd.run(["setup", recipe, "--global", "--check"]);
|
|
17592
|
+
if (check.code === 0) {
|
|
17593
|
+
log.trace("beads", `bd setup ${recipe} --global already installed \u2014 skipping`);
|
|
17594
|
+
wired.push(recipe);
|
|
17595
|
+
continue;
|
|
17596
|
+
}
|
|
17597
|
+
log.info("beads", `wiring agent natively: bd setup ${recipe} --global`);
|
|
17598
|
+
const setup = await bd.run(["setup", recipe, "--global"]);
|
|
17599
|
+
if (setup.code === 0) {
|
|
17600
|
+
wired.push(recipe);
|
|
17601
|
+
} else {
|
|
17602
|
+
log.warn(
|
|
17603
|
+
"beads",
|
|
17604
|
+
`bd setup ${recipe} --global failed (code=${setup.code}): ${setup.stderr.slice(0, 200)} \u2014 non-fatal, agent runs without native bd wiring`
|
|
17605
|
+
);
|
|
17606
|
+
}
|
|
17607
|
+
} catch (err) {
|
|
17608
|
+
log.warn("beads", `bd setup ${recipe} --global threw (non-fatal)`, err);
|
|
17609
|
+
}
|
|
17429
17610
|
}
|
|
17430
|
-
|
|
17431
|
-
return recheck.code === 0;
|
|
17611
|
+
return wired;
|
|
17432
17612
|
}
|
|
17433
|
-
|
|
17434
|
-
const
|
|
17435
|
-
|
|
17436
|
-
|
|
17437
|
-
|
|
17438
|
-
}
|
|
17439
|
-
const setup = await bd.run(["setup", recipe]);
|
|
17440
|
-
if (setup.code !== 0) {
|
|
17441
|
-
log.warn("beads", `bd setup ${recipe} failed (code=${setup.code})`);
|
|
17442
|
-
return false;
|
|
17613
|
+
function dedupeRecipes(agents) {
|
|
17614
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17615
|
+
for (const agent of agents) {
|
|
17616
|
+
const recipe = AGENT_SETUP_RECIPE[agent];
|
|
17617
|
+
if (recipe) seen.add(recipe);
|
|
17443
17618
|
}
|
|
17444
|
-
|
|
17445
|
-
return true;
|
|
17446
|
-
}
|
|
17447
|
-
async function ensureAutoExport(bd) {
|
|
17448
|
-
const res = await bd.run(["config", "set", "export.jsonl", "true"]);
|
|
17449
|
-
return res.code === 0;
|
|
17619
|
+
return [...seen];
|
|
17450
17620
|
}
|
|
17451
17621
|
|
|
17452
17622
|
// src/beads/watcher.ts
|
|
17453
17623
|
var crypto3 = __toESM(require("crypto"));
|
|
17454
|
-
var
|
|
17624
|
+
var path38 = __toESM(require("path"));
|
|
17455
17625
|
|
|
17456
17626
|
// src/beads/project-key.ts
|
|
17457
|
-
var
|
|
17627
|
+
var import_child_process15 = require("child_process");
|
|
17458
17628
|
var crypto2 = __toESM(require("crypto"));
|
|
17459
|
-
var
|
|
17460
|
-
var
|
|
17629
|
+
var fs31 = __toESM(require("fs"));
|
|
17630
|
+
var path37 = __toESM(require("path"));
|
|
17461
17631
|
function normalizeOrigin(raw) {
|
|
17462
17632
|
const trimmed = raw.trim();
|
|
17463
17633
|
if (!trimmed) return null;
|
|
@@ -17483,17 +17653,17 @@ function normalizeOrigin(raw) {
|
|
|
17483
17653
|
return `${host}/${pathPart}`;
|
|
17484
17654
|
}
|
|
17485
17655
|
function findRepoRoot(cwd) {
|
|
17486
|
-
let dir =
|
|
17656
|
+
let dir = path37.resolve(cwd);
|
|
17487
17657
|
const seen = /* @__PURE__ */ new Set();
|
|
17488
17658
|
for (let i = 0; i < 256; i++) {
|
|
17489
17659
|
if (seen.has(dir)) return null;
|
|
17490
17660
|
seen.add(dir);
|
|
17491
17661
|
try {
|
|
17492
|
-
const stat3 =
|
|
17662
|
+
const stat3 = fs31.statSync(path37.join(dir, ".git"), { throwIfNoEntry: false });
|
|
17493
17663
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
17494
17664
|
} catch {
|
|
17495
17665
|
}
|
|
17496
|
-
const parent =
|
|
17666
|
+
const parent = path37.dirname(dir);
|
|
17497
17667
|
if (parent === dir) return null;
|
|
17498
17668
|
dir = parent;
|
|
17499
17669
|
}
|
|
@@ -17501,10 +17671,10 @@ function findRepoRoot(cwd) {
|
|
|
17501
17671
|
}
|
|
17502
17672
|
var _execSeam2 = {
|
|
17503
17673
|
exec: (file, args2, opts) => {
|
|
17504
|
-
const out2 = (0,
|
|
17674
|
+
const out2 = (0, import_child_process15.execFileSync)(file, args2, opts);
|
|
17505
17675
|
return typeof out2 === "string" ? out2 : out2.toString("utf8");
|
|
17506
17676
|
},
|
|
17507
|
-
realpath: (p2) =>
|
|
17677
|
+
realpath: (p2) => fs31.realpathSync(p2)
|
|
17508
17678
|
};
|
|
17509
17679
|
function readOrigin(cwd) {
|
|
17510
17680
|
try {
|
|
@@ -17533,7 +17703,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
|
|
|
17533
17703
|
} catch {
|
|
17534
17704
|
}
|
|
17535
17705
|
const hash = crypto2.createHash("sha256").update(real).digest("hex");
|
|
17536
|
-
return { projectKey: `path:${hash}`, projectLabel:
|
|
17706
|
+
return { projectKey: `path:${hash}`, projectLabel: path37.basename(real) || "project" };
|
|
17537
17707
|
}
|
|
17538
17708
|
|
|
17539
17709
|
// src/services/file-watcher/transport.ts
|
|
@@ -17588,6 +17758,14 @@ function _post2(url, headers, payload) {
|
|
|
17588
17758
|
// src/beads/watcher.ts
|
|
17589
17759
|
var API_BASE4 = resolveApiBaseUrl();
|
|
17590
17760
|
var DEBOUNCE_MS = 400;
|
|
17761
|
+
var ZERO_SUMMARY = {
|
|
17762
|
+
open_issues: 0,
|
|
17763
|
+
ready_issues: 0,
|
|
17764
|
+
blocked_issues: 0,
|
|
17765
|
+
in_progress_issues: 0,
|
|
17766
|
+
closed_issues: 0,
|
|
17767
|
+
total_issues: 0
|
|
17768
|
+
};
|
|
17591
17769
|
var _chokidarSeam = {
|
|
17592
17770
|
load: () => {
|
|
17593
17771
|
try {
|
|
@@ -17601,7 +17779,7 @@ var BeadsWatcher = class {
|
|
|
17601
17779
|
constructor(opts) {
|
|
17602
17780
|
this.opts = opts;
|
|
17603
17781
|
this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
|
|
17604
|
-
this.feedPath = opts.feedPath ??
|
|
17782
|
+
this.feedPath = opts.feedPath ?? path38.join(defaultBeadsHomeDir(), "issues.jsonl");
|
|
17605
17783
|
this.apiBase = opts.apiBaseUrl ?? API_BASE4;
|
|
17606
17784
|
}
|
|
17607
17785
|
opts;
|
|
@@ -17687,8 +17865,14 @@ var BeadsWatcher = class {
|
|
|
17687
17865
|
projectLabel,
|
|
17688
17866
|
fullSnapshot: true,
|
|
17689
17867
|
issues,
|
|
17868
|
+
// The backend DTO requires `dependencies` (not `deps`). We don't track
|
|
17869
|
+
// edges in the P0 snapshot yet, so always send an empty array rather than
|
|
17870
|
+
// omitting the field (an omitted/conditional field 400s the ingest).
|
|
17871
|
+
dependencies: [],
|
|
17690
17872
|
memories: [],
|
|
17691
|
-
|
|
17873
|
+
// Always send a summary — a null `bd status` yields a zeroed block rather
|
|
17874
|
+
// than an omitted field, so the backend never has to special-case it.
|
|
17875
|
+
summary: summary ?? ZERO_SUMMARY
|
|
17692
17876
|
};
|
|
17693
17877
|
const body = JSON.stringify(payload);
|
|
17694
17878
|
const hash = crypto3.createHash("sha256").update(body).digest("hex");
|
|
@@ -17772,85 +17956,12 @@ async function applyBeadsAction(action, deps) {
|
|
|
17772
17956
|
return { ok: true, action: action.kind, code: 0 };
|
|
17773
17957
|
}
|
|
17774
17958
|
|
|
17775
|
-
// src/beads/install-bd.ts
|
|
17776
|
-
var import_child_process14 = require("child_process");
|
|
17777
|
-
var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
|
|
17778
|
-
var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
|
|
17779
|
-
function resolveInstallStrategy(platform2) {
|
|
17780
|
-
if (platform2 === "win32") {
|
|
17781
|
-
return {
|
|
17782
|
-
command: "powershell.exe",
|
|
17783
|
-
args: [
|
|
17784
|
-
"-NoProfile",
|
|
17785
|
-
"-NonInteractive",
|
|
17786
|
-
"-ExecutionPolicy",
|
|
17787
|
-
"Bypass",
|
|
17788
|
-
"-Command",
|
|
17789
|
-
`irm ${INSTALL_PS1_URL} | iex`
|
|
17790
|
-
],
|
|
17791
|
-
description: `PowerShell: irm ${INSTALL_PS1_URL} | iex (requires Go 1.24+ and Git for Windows on PATH)`
|
|
17792
|
-
};
|
|
17793
|
-
}
|
|
17794
|
-
return {
|
|
17795
|
-
command: "bash",
|
|
17796
|
-
args: ["-c", `curl -fsSL ${INSTALL_SH_URL} | bash`],
|
|
17797
|
-
description: `curl -fsSL ${INSTALL_SH_URL} | bash`
|
|
17798
|
-
};
|
|
17799
|
-
}
|
|
17800
|
-
var _installSpawnSeam = {
|
|
17801
|
-
run: _defaultInstallSpawn
|
|
17802
|
-
};
|
|
17803
|
-
function _defaultInstallSpawn(strategy) {
|
|
17804
|
-
return new Promise((resolve7) => {
|
|
17805
|
-
let proc;
|
|
17806
|
-
try {
|
|
17807
|
-
proc = (0, import_child_process14.spawn)(strategy.command, strategy.args, { env: process.env });
|
|
17808
|
-
} catch (err) {
|
|
17809
|
-
resolve7({ ok: false, code: -1, stderr: err.message });
|
|
17810
|
-
return;
|
|
17811
|
-
}
|
|
17812
|
-
let stderr = "";
|
|
17813
|
-
proc.stderr?.on("data", (c2) => {
|
|
17814
|
-
stderr += c2.toString();
|
|
17815
|
-
});
|
|
17816
|
-
proc.on("error", (err) => resolve7({ ok: false, code: -1, stderr: err.message }));
|
|
17817
|
-
proc.on(
|
|
17818
|
-
"close",
|
|
17819
|
-
(code) => resolve7({ ok: code === 0, code: code ?? -1, stderr })
|
|
17820
|
-
);
|
|
17821
|
-
});
|
|
17822
|
-
}
|
|
17823
|
-
async function installBd(platform2 = process.platform) {
|
|
17824
|
-
const strategy = resolveInstallStrategy(platform2);
|
|
17825
|
-
log.info("beads", `installing bd via ${strategy.description}`);
|
|
17826
|
-
const result = await _installSpawnSeam.run(strategy);
|
|
17827
|
-
if (!result.ok) {
|
|
17828
|
-
log.warn(
|
|
17829
|
-
"beads",
|
|
17830
|
-
`bd install failed (code=${result.code}): ${result.stderr.slice(0, 200)}`
|
|
17831
|
-
);
|
|
17832
|
-
}
|
|
17833
|
-
return result;
|
|
17834
|
-
}
|
|
17835
|
-
|
|
17836
17959
|
// src/beads/index.ts
|
|
17837
|
-
async function
|
|
17838
|
-
if (!opts.enabled) {
|
|
17839
|
-
log.trace("beads", "beads flag off \u2014 skipping");
|
|
17840
|
-
return null;
|
|
17841
|
-
}
|
|
17960
|
+
async function startBeads(opts) {
|
|
17842
17961
|
const adapter = new BdAdapter({ cwd: opts.cwd });
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
}
|
|
17847
|
-
if (!adapter.isAvailable()) {
|
|
17848
|
-
log.warn("beads", "bd unavailable \u2014 beads disabled for this session");
|
|
17849
|
-
return null;
|
|
17850
|
-
}
|
|
17851
|
-
const boot = await bootstrapBeads({ cwd: opts.cwd, agents: opts.agents, adapter });
|
|
17852
|
-
if (!boot.serverUp) {
|
|
17853
|
-
log.warn("beads", "beads server not up \u2014 watcher not started this run");
|
|
17962
|
+
const provision = await provisionBeads({ cwd: opts.cwd, adapter, agents: opts.agents });
|
|
17963
|
+
if (!provision.bdAvailable || !provision.initialized) {
|
|
17964
|
+
log.warn("beads", "home brain not provisioned \u2014 watcher not started this run");
|
|
17854
17965
|
return null;
|
|
17855
17966
|
}
|
|
17856
17967
|
const watcher = new BeadsWatcher({
|
|
@@ -17876,28 +17987,43 @@ function beadsKilled() {
|
|
|
17876
17987
|
const v = process.env.CODEAM_BEADS_DISABLED;
|
|
17877
17988
|
return !!v && v !== "0" && v.toLowerCase() !== "false";
|
|
17878
17989
|
}
|
|
17879
|
-
async function
|
|
17990
|
+
async function provisionBeadsForStart(ctx) {
|
|
17880
17991
|
if (beadsKilled()) {
|
|
17881
|
-
log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off
|
|
17992
|
+
log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off this run");
|
|
17882
17993
|
return null;
|
|
17883
17994
|
}
|
|
17995
|
+
process.env.BEADS_DIR = defaultBeadsHomeDir();
|
|
17884
17996
|
if (!ctx.pluginAuthToken) {
|
|
17885
|
-
log.trace("beads", "no pluginAuthToken
|
|
17997
|
+
log.trace("beads", "no pluginAuthToken \u2014 beads off");
|
|
17886
17998
|
return null;
|
|
17887
17999
|
}
|
|
18000
|
+
const pluginAuthToken = ctx.pluginAuthToken;
|
|
18001
|
+
let started = null;
|
|
17888
18002
|
try {
|
|
17889
|
-
|
|
17890
|
-
enabled: true,
|
|
18003
|
+
started = await startBeads({
|
|
17891
18004
|
sessionId: ctx.sessionId,
|
|
17892
18005
|
pluginId: ctx.pluginId,
|
|
17893
|
-
pluginAuthToken
|
|
17894
|
-
|
|
17895
|
-
|
|
18006
|
+
pluginAuthToken,
|
|
18007
|
+
cwd: ctx.cwd,
|
|
18008
|
+
agents: ctx.agents
|
|
17896
18009
|
});
|
|
17897
18010
|
} catch (err) {
|
|
17898
|
-
log.warn("beads", "
|
|
17899
|
-
|
|
17900
|
-
}
|
|
18011
|
+
log.warn("beads", "provisionBeadsForStart failed (non-fatal)", err);
|
|
18012
|
+
started = null;
|
|
18013
|
+
}
|
|
18014
|
+
const { projectKey } = deriveProjectIdentity(ctx.cwd);
|
|
18015
|
+
void postBeadsProvisioning({
|
|
18016
|
+
sessionId: ctx.sessionId,
|
|
18017
|
+
pluginId: ctx.pluginId,
|
|
18018
|
+
pluginAuthToken,
|
|
18019
|
+
status: started ? "ready" : "failed",
|
|
18020
|
+
projectKey
|
|
18021
|
+
}).then((res) => {
|
|
18022
|
+
if (!res.ok) {
|
|
18023
|
+
log.trace("beads", `provisioning signal POST non-ok (status=${res.status}) \u2014 ignoring`);
|
|
18024
|
+
}
|
|
18025
|
+
});
|
|
18026
|
+
return started;
|
|
17901
18027
|
}
|
|
17902
18028
|
var ACTION_KINDS = /* @__PURE__ */ new Set([
|
|
17903
18029
|
"claim",
|
|
@@ -17930,7 +18056,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
|
|
|
17930
18056
|
function cleanupAttachmentTempFiles() {
|
|
17931
18057
|
for (const p2 of pendingAttachmentFiles) {
|
|
17932
18058
|
try {
|
|
17933
|
-
|
|
18059
|
+
fs32.unlinkSync(p2);
|
|
17934
18060
|
} catch {
|
|
17935
18061
|
}
|
|
17936
18062
|
}
|
|
@@ -17939,8 +18065,8 @@ function cleanupAttachmentTempFiles() {
|
|
|
17939
18065
|
function saveFilesTemp(files) {
|
|
17940
18066
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
17941
18067
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
17942
|
-
const tmpPath =
|
|
17943
|
-
|
|
18068
|
+
const tmpPath = path39.join(os25.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
18069
|
+
fs32.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
17944
18070
|
pendingAttachmentFiles.add(tmpPath);
|
|
17945
18071
|
return tmpPath;
|
|
17946
18072
|
});
|
|
@@ -17960,7 +18086,7 @@ var startTask = (ctx, _cmd, parsed) => {
|
|
|
17960
18086
|
setTimeout(() => {
|
|
17961
18087
|
for (const p2 of paths) {
|
|
17962
18088
|
try {
|
|
17963
|
-
|
|
18089
|
+
fs32.unlinkSync(p2);
|
|
17964
18090
|
} catch {
|
|
17965
18091
|
}
|
|
17966
18092
|
pendingAttachmentFiles.delete(p2);
|
|
@@ -18085,7 +18211,7 @@ var sessionTerminated = async (ctx, cmd) => {
|
|
|
18085
18211
|
} catch {
|
|
18086
18212
|
}
|
|
18087
18213
|
try {
|
|
18088
|
-
const proc = (0,
|
|
18214
|
+
const proc = (0, import_child_process16.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
18089
18215
|
detached: true,
|
|
18090
18216
|
stdio: "ignore"
|
|
18091
18217
|
});
|
|
@@ -18107,7 +18233,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
18107
18233
|
}
|
|
18108
18234
|
if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
|
|
18109
18235
|
try {
|
|
18110
|
-
const stopProc = (0,
|
|
18236
|
+
const stopProc = (0, import_child_process16.spawn)(
|
|
18111
18237
|
"bash",
|
|
18112
18238
|
["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
|
|
18113
18239
|
{ detached: true, stdio: "ignore" }
|
|
@@ -18117,7 +18243,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
18117
18243
|
}
|
|
18118
18244
|
}
|
|
18119
18245
|
try {
|
|
18120
|
-
const proc = (0,
|
|
18246
|
+
const proc = (0, import_child_process16.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
18121
18247
|
detached: true,
|
|
18122
18248
|
stdio: "ignore"
|
|
18123
18249
|
});
|
|
@@ -18533,8 +18659,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
|
|
|
18533
18659
|
if (args2.length === 0) return detection;
|
|
18534
18660
|
const binName = args2[0];
|
|
18535
18661
|
if (binName.startsWith("-")) return detection;
|
|
18536
|
-
const binPath =
|
|
18537
|
-
if (!
|
|
18662
|
+
const binPath = path39.join(cwd, "node_modules", ".bin", binName);
|
|
18663
|
+
if (!fs32.existsSync(binPath)) return detection;
|
|
18538
18664
|
return {
|
|
18539
18665
|
...detection,
|
|
18540
18666
|
command: binPath,
|
|
@@ -18624,7 +18750,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
18624
18750
|
"BOOT_SEQUENCE",
|
|
18625
18751
|
`${spawnable.command} ${spawnable.args.join(" ")}`
|
|
18626
18752
|
);
|
|
18627
|
-
const devServer = (0,
|
|
18753
|
+
const devServer = (0, import_child_process16.spawn)(spawnable.command, spawnable.args, {
|
|
18628
18754
|
cwd: process.cwd(),
|
|
18629
18755
|
env: { ...process.env, ...spawnable.env ?? {} },
|
|
18630
18756
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18750,7 +18876,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
18750
18876
|
});
|
|
18751
18877
|
return;
|
|
18752
18878
|
}
|
|
18753
|
-
tunnel = (0,
|
|
18879
|
+
tunnel = (0, import_child_process16.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
|
|
18754
18880
|
stdio: ["ignore", "pipe", "pipe"]
|
|
18755
18881
|
});
|
|
18756
18882
|
let parsedUrl = null;
|
|
@@ -18848,7 +18974,7 @@ var previewStopH = (ctx) => {
|
|
|
18848
18974
|
};
|
|
18849
18975
|
function runOnce(cmd, args2, cwd, env) {
|
|
18850
18976
|
return new Promise((resolve7) => {
|
|
18851
|
-
const child = (0,
|
|
18977
|
+
const child = (0, import_child_process16.spawn)(cmd, args2, {
|
|
18852
18978
|
cwd,
|
|
18853
18979
|
env: { ...process.env, ...env ?? {} },
|
|
18854
18980
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18944,10 +19070,10 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
18944
19070
|
}
|
|
18945
19071
|
|
|
18946
19072
|
// src/services/file-watcher.service.ts
|
|
18947
|
-
var
|
|
18948
|
-
var
|
|
19073
|
+
var import_child_process17 = require("child_process");
|
|
19074
|
+
var fs33 = __toESM(require("fs"));
|
|
18949
19075
|
var os26 = __toESM(require("os"));
|
|
18950
|
-
var
|
|
19076
|
+
var path40 = __toESM(require("path"));
|
|
18951
19077
|
var import_ignore = __toESM(require("ignore"));
|
|
18952
19078
|
|
|
18953
19079
|
// src/services/file-watcher/diff-parser.ts
|
|
@@ -19090,18 +19216,18 @@ var _findGitRootSeam = {
|
|
|
19090
19216
|
resolve: _defaultFindGitRoot
|
|
19091
19217
|
};
|
|
19092
19218
|
function _defaultFindGitRoot(startDir) {
|
|
19093
|
-
let dir =
|
|
19219
|
+
let dir = path40.resolve(startDir);
|
|
19094
19220
|
const seen = /* @__PURE__ */ new Set();
|
|
19095
19221
|
for (let i = 0; i < 256; i++) {
|
|
19096
19222
|
if (seen.has(dir)) return null;
|
|
19097
19223
|
seen.add(dir);
|
|
19098
19224
|
try {
|
|
19099
|
-
const gitPath =
|
|
19100
|
-
const stat3 =
|
|
19225
|
+
const gitPath = path40.join(dir, ".git");
|
|
19226
|
+
const stat3 = fs33.statSync(gitPath, { throwIfNoEntry: false });
|
|
19101
19227
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
19102
19228
|
} catch {
|
|
19103
19229
|
}
|
|
19104
|
-
const parent =
|
|
19230
|
+
const parent = path40.dirname(dir);
|
|
19105
19231
|
if (parent === dir) return null;
|
|
19106
19232
|
dir = parent;
|
|
19107
19233
|
}
|
|
@@ -19346,7 +19472,7 @@ var FileWatcherService = class {
|
|
|
19346
19472
|
}
|
|
19347
19473
|
async emitForFile(absPath, changeType) {
|
|
19348
19474
|
if (this.stopped) return;
|
|
19349
|
-
const fileDir =
|
|
19475
|
+
const fileDir = path40.dirname(absPath);
|
|
19350
19476
|
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
19351
19477
|
if (gitRoot === void 0) {
|
|
19352
19478
|
gitRoot = findGitRoot2(fileDir);
|
|
@@ -19359,19 +19485,19 @@ var FileWatcherService = class {
|
|
|
19359
19485
|
);
|
|
19360
19486
|
return;
|
|
19361
19487
|
}
|
|
19362
|
-
const relPathInRepo =
|
|
19488
|
+
const relPathInRepo = path40.relative(gitRoot, absPath);
|
|
19363
19489
|
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
19364
19490
|
const matcher = this.getGitIgnoreMatcher(gitRoot);
|
|
19365
19491
|
if (matcher && matcher.ignores(relPathInRepo)) {
|
|
19366
19492
|
log.trace(
|
|
19367
19493
|
"fileWatcher",
|
|
19368
|
-
`${relPathInRepo} ignored by ${
|
|
19494
|
+
`${relPathInRepo} ignored by ${path40.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
|
|
19369
19495
|
);
|
|
19370
19496
|
return;
|
|
19371
19497
|
}
|
|
19372
19498
|
this.opts.onRepoDirty?.(gitRoot);
|
|
19373
|
-
const repoPath =
|
|
19374
|
-
const repoName =
|
|
19499
|
+
const repoPath = path40.relative(this.opts.workingDir, gitRoot);
|
|
19500
|
+
const repoName = path40.basename(gitRoot);
|
|
19375
19501
|
let diffText = "";
|
|
19376
19502
|
let fileStatus = "modified";
|
|
19377
19503
|
if (changeType === "unlink") {
|
|
@@ -19546,7 +19672,7 @@ var FileWatcherService = class {
|
|
|
19546
19672
|
collectGitignoreFiles(repoRoot, dir, matcher) {
|
|
19547
19673
|
let entries;
|
|
19548
19674
|
try {
|
|
19549
|
-
entries =
|
|
19675
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
19550
19676
|
} catch {
|
|
19551
19677
|
return;
|
|
19552
19678
|
}
|
|
@@ -19555,16 +19681,16 @@ var FileWatcherService = class {
|
|
|
19555
19681
|
);
|
|
19556
19682
|
if (gitignoreEntry) {
|
|
19557
19683
|
try {
|
|
19558
|
-
const body =
|
|
19559
|
-
const rel =
|
|
19684
|
+
const body = fs33.readFileSync(path40.join(dir, ".gitignore"), "utf8");
|
|
19685
|
+
const rel = path40.relative(repoRoot, dir).replace(/\\/g, "/");
|
|
19560
19686
|
const prefixed = body.split(/\r?\n/).map((line) => {
|
|
19561
19687
|
const trimmed = line.trim();
|
|
19562
19688
|
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
19563
19689
|
if (!rel) return line;
|
|
19564
19690
|
if (trimmed.startsWith("!")) {
|
|
19565
|
-
return "!" +
|
|
19691
|
+
return "!" + path40.posix.join(rel, trimmed.slice(1));
|
|
19566
19692
|
}
|
|
19567
|
-
return
|
|
19693
|
+
return path40.posix.join(rel, trimmed);
|
|
19568
19694
|
}).join("\n");
|
|
19569
19695
|
matcher.add(prefixed);
|
|
19570
19696
|
} catch {
|
|
@@ -19573,7 +19699,7 @@ var FileWatcherService = class {
|
|
|
19573
19699
|
for (const entry of entries) {
|
|
19574
19700
|
if (!entry.isDirectory()) continue;
|
|
19575
19701
|
if (entry.name === ".git") continue;
|
|
19576
|
-
const childAbs =
|
|
19702
|
+
const childAbs = path40.join(dir, entry.name);
|
|
19577
19703
|
if (isIgnoredFilePath(childAbs)) continue;
|
|
19578
19704
|
this.collectGitignoreFiles(repoRoot, childAbs, matcher);
|
|
19579
19705
|
}
|
|
@@ -19710,7 +19836,7 @@ async function _runGitImpl(cwd, args2, opts = {}) {
|
|
|
19710
19836
|
return new Promise((resolve7) => {
|
|
19711
19837
|
let proc;
|
|
19712
19838
|
try {
|
|
19713
|
-
proc = (0,
|
|
19839
|
+
proc = (0, import_child_process17.spawn)("git", args2, { cwd, env: process.env });
|
|
19714
19840
|
} catch {
|
|
19715
19841
|
resolve7(null);
|
|
19716
19842
|
return;
|
|
@@ -19742,8 +19868,8 @@ function _runGit(cwd, args2, opts = {}) {
|
|
|
19742
19868
|
var import_crypto4 = require("crypto");
|
|
19743
19869
|
|
|
19744
19870
|
// src/services/turn-files/git-changeset.ts
|
|
19745
|
-
var
|
|
19746
|
-
var
|
|
19871
|
+
var import_child_process18 = require("child_process");
|
|
19872
|
+
var path41 = __toESM(require("path"));
|
|
19747
19873
|
async function collectRepoChangeset(opts) {
|
|
19748
19874
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
19749
19875
|
if (status2 === null) return null;
|
|
@@ -19826,7 +19952,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
19826
19952
|
return new Promise((resolve7) => {
|
|
19827
19953
|
let proc;
|
|
19828
19954
|
try {
|
|
19829
|
-
proc = (0,
|
|
19955
|
+
proc = (0, import_child_process18.spawn)("git", args2, { cwd, env: process.env });
|
|
19830
19956
|
} catch {
|
|
19831
19957
|
resolve7(null);
|
|
19832
19958
|
return;
|
|
@@ -19854,7 +19980,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
19854
19980
|
});
|
|
19855
19981
|
}
|
|
19856
19982
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
19857
|
-
const
|
|
19983
|
+
const fs39 = await import("fs/promises");
|
|
19858
19984
|
const out2 = [];
|
|
19859
19985
|
await walk(workingDir, 0);
|
|
19860
19986
|
return out2;
|
|
@@ -19862,7 +19988,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19862
19988
|
if (depth > maxDepth) return;
|
|
19863
19989
|
let entries = [];
|
|
19864
19990
|
try {
|
|
19865
|
-
const dirents = await
|
|
19991
|
+
const dirents = await fs39.readdir(dir, { withFileTypes: true });
|
|
19866
19992
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
19867
19993
|
} catch {
|
|
19868
19994
|
return;
|
|
@@ -19873,8 +19999,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19873
19999
|
if (hasGit) {
|
|
19874
20000
|
out2.push({
|
|
19875
20001
|
repoRoot: dir,
|
|
19876
|
-
repoPath:
|
|
19877
|
-
repoName:
|
|
20002
|
+
repoPath: path41.relative(workingDir, dir),
|
|
20003
|
+
repoName: path41.basename(dir)
|
|
19878
20004
|
});
|
|
19879
20005
|
return;
|
|
19880
20006
|
}
|
|
@@ -19882,14 +20008,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19882
20008
|
if (!entry.isDirectory) continue;
|
|
19883
20009
|
if (entry.name === "node_modules") continue;
|
|
19884
20010
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
19885
|
-
await walk(
|
|
20011
|
+
await walk(path41.join(dir, entry.name), depth + 1);
|
|
19886
20012
|
}
|
|
19887
20013
|
}
|
|
19888
20014
|
}
|
|
19889
20015
|
|
|
19890
20016
|
// src/services/turn-files/files-outbox.ts
|
|
19891
|
-
var
|
|
19892
|
-
var
|
|
20017
|
+
var fs34 = __toESM(require("fs/promises"));
|
|
20018
|
+
var path42 = __toESM(require("path"));
|
|
19893
20019
|
var import_os7 = require("os");
|
|
19894
20020
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
19895
20021
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -19922,16 +20048,16 @@ var FilesOutbox = class {
|
|
|
19922
20048
|
backoffIndex = 0;
|
|
19923
20049
|
stopped = false;
|
|
19924
20050
|
constructor(opts) {
|
|
19925
|
-
const base = opts.baseDir ??
|
|
19926
|
-
this.filePath =
|
|
20051
|
+
const base = opts.baseDir ?? path42.join(homeDir(), HOME_OUTBOX_DIR);
|
|
20052
|
+
this.filePath = path42.join(base, `${opts.sessionId}.jsonl`);
|
|
19927
20053
|
this.post = opts.post;
|
|
19928
20054
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
19929
20055
|
}
|
|
19930
20056
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
19931
20057
|
* line is durable on disk (not once the POST succeeds). */
|
|
19932
20058
|
async enqueue(entry) {
|
|
19933
|
-
await
|
|
19934
|
-
await
|
|
20059
|
+
await fs34.mkdir(path42.dirname(this.filePath), { recursive: true });
|
|
20060
|
+
await fs34.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
19935
20061
|
this.backoffIndex = 0;
|
|
19936
20062
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
19937
20063
|
}
|
|
@@ -20020,7 +20146,7 @@ var FilesOutbox = class {
|
|
|
20020
20146
|
async readAll() {
|
|
20021
20147
|
let raw = "";
|
|
20022
20148
|
try {
|
|
20023
|
-
raw = await
|
|
20149
|
+
raw = await fs34.readFile(this.filePath, "utf8");
|
|
20024
20150
|
} catch {
|
|
20025
20151
|
return [];
|
|
20026
20152
|
}
|
|
@@ -20044,12 +20170,12 @@ var FilesOutbox = class {
|
|
|
20044
20170
|
async rewrite(entries) {
|
|
20045
20171
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
20046
20172
|
if (entries.length === 0) {
|
|
20047
|
-
await
|
|
20173
|
+
await fs34.unlink(this.filePath).catch(() => void 0);
|
|
20048
20174
|
return;
|
|
20049
20175
|
}
|
|
20050
20176
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
20051
|
-
await
|
|
20052
|
-
await
|
|
20177
|
+
await fs34.writeFile(tmpPath, payload, "utf8");
|
|
20178
|
+
await fs34.rename(tmpPath, this.filePath);
|
|
20053
20179
|
}
|
|
20054
20180
|
};
|
|
20055
20181
|
function applyJitter(ms) {
|
|
@@ -20670,16 +20796,7 @@ async function runAcpSession(opts) {
|
|
|
20670
20796
|
}).catch((err) => {
|
|
20671
20797
|
log.warn("acpRunner", `fileWatcher.start failed: ${describeError(err)}`);
|
|
20672
20798
|
});
|
|
20673
|
-
|
|
20674
|
-
void startBeadsForSession({
|
|
20675
|
-
sessionId: opts.sessionId,
|
|
20676
|
-
pluginId: opts.pluginId,
|
|
20677
|
-
pluginAuthToken: opts.pluginAuthToken,
|
|
20678
|
-
agents: [opts.agent],
|
|
20679
|
-
cwd: opts.cwd
|
|
20680
|
-
}).then((started) => {
|
|
20681
|
-
beads = started;
|
|
20682
|
-
});
|
|
20799
|
+
const getBeads = opts.getBeads ?? (() => null);
|
|
20683
20800
|
const relay = new CommandRelayService(
|
|
20684
20801
|
opts.pluginId,
|
|
20685
20802
|
async (cmd) => {
|
|
@@ -20694,7 +20811,7 @@ async function runAcpSession(opts) {
|
|
|
20694
20811
|
history,
|
|
20695
20812
|
initialize.agentCapabilities,
|
|
20696
20813
|
turnFiles,
|
|
20697
|
-
|
|
20814
|
+
getBeads
|
|
20698
20815
|
);
|
|
20699
20816
|
},
|
|
20700
20817
|
{ id: opts.agent, name: opts.agent, displayName: opts.agent }
|
|
@@ -20705,7 +20822,6 @@ async function runAcpSession(opts) {
|
|
|
20705
20822
|
relay.stop();
|
|
20706
20823
|
void fileWatcher.stop();
|
|
20707
20824
|
turnFiles.stop();
|
|
20708
|
-
void beads?.watcher.stop();
|
|
20709
20825
|
closeAllTerminals();
|
|
20710
20826
|
await client2.stop();
|
|
20711
20827
|
process.exit(0);
|
|
@@ -21813,8 +21929,8 @@ var OutputService = class _OutputService {
|
|
|
21813
21929
|
};
|
|
21814
21930
|
|
|
21815
21931
|
// src/services/history.service.ts
|
|
21816
|
-
var
|
|
21817
|
-
var
|
|
21932
|
+
var fs35 = __toESM(require("fs"));
|
|
21933
|
+
var path43 = __toESM(require("path"));
|
|
21818
21934
|
var os27 = __toESM(require("os"));
|
|
21819
21935
|
var https7 = __toESM(require("https"));
|
|
21820
21936
|
var http7 = __toESM(require("http"));
|
|
@@ -21842,7 +21958,7 @@ function parseJsonl(filePath) {
|
|
|
21842
21958
|
const messages = [];
|
|
21843
21959
|
let raw;
|
|
21844
21960
|
try {
|
|
21845
|
-
raw =
|
|
21961
|
+
raw = fs35.readFileSync(filePath, "utf8");
|
|
21846
21962
|
} catch (err) {
|
|
21847
21963
|
if (err.code !== "ENOENT") {
|
|
21848
21964
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -21977,7 +22093,7 @@ var HistoryService = class _HistoryService {
|
|
|
21977
22093
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
21978
22094
|
}
|
|
21979
22095
|
get projectDir() {
|
|
21980
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
22096
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path43.join(os27.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
21981
22097
|
}
|
|
21982
22098
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
21983
22099
|
setCurrentConversationId(id) {
|
|
@@ -21989,7 +22105,7 @@ var HistoryService = class _HistoryService {
|
|
|
21989
22105
|
/** Return the current message count in the active conversation. */
|
|
21990
22106
|
getCurrentMessageCount() {
|
|
21991
22107
|
if (!this.currentConversationId) return 0;
|
|
21992
|
-
const filePath =
|
|
22108
|
+
const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21993
22109
|
return parseJsonl(filePath).length;
|
|
21994
22110
|
}
|
|
21995
22111
|
/**
|
|
@@ -22000,7 +22116,7 @@ var HistoryService = class _HistoryService {
|
|
|
22000
22116
|
const deadline = Date.now() + timeoutMs;
|
|
22001
22117
|
while (Date.now() < deadline) {
|
|
22002
22118
|
if (!this.currentConversationId) return null;
|
|
22003
|
-
const filePath =
|
|
22119
|
+
const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
22004
22120
|
const messages = parseJsonl(filePath);
|
|
22005
22121
|
if (messages.length > previousCount) {
|
|
22006
22122
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -22026,16 +22142,16 @@ var HistoryService = class _HistoryService {
|
|
|
22026
22142
|
const dir = this.projectDir;
|
|
22027
22143
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
22028
22144
|
try {
|
|
22029
|
-
const files =
|
|
22145
|
+
const files = fs35.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
22030
22146
|
try {
|
|
22031
|
-
const stat3 =
|
|
22147
|
+
const stat3 = fs35.statSync(path43.join(dir, e.name));
|
|
22032
22148
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
22033
22149
|
} catch {
|
|
22034
22150
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
22035
22151
|
}
|
|
22036
22152
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
22037
22153
|
if (files.length > 0) {
|
|
22038
|
-
this.currentConversationId =
|
|
22154
|
+
this.currentConversationId = path43.basename(files[0].name, ".jsonl");
|
|
22039
22155
|
}
|
|
22040
22156
|
} catch {
|
|
22041
22157
|
}
|
|
@@ -22069,13 +22185,13 @@ var HistoryService = class _HistoryService {
|
|
|
22069
22185
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
22070
22186
|
let entries;
|
|
22071
22187
|
try {
|
|
22072
|
-
entries =
|
|
22188
|
+
entries = fs35.readdirSync(dir, { withFileTypes: true });
|
|
22073
22189
|
} catch {
|
|
22074
22190
|
return null;
|
|
22075
22191
|
}
|
|
22076
22192
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
22077
22193
|
try {
|
|
22078
|
-
const stat3 =
|
|
22194
|
+
const stat3 = fs35.statSync(path43.join(dir, e.name));
|
|
22079
22195
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
22080
22196
|
} catch {
|
|
22081
22197
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -22084,12 +22200,12 @@ var HistoryService = class _HistoryService {
|
|
|
22084
22200
|
if (files.length === 0) return null;
|
|
22085
22201
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
22086
22202
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
22087
|
-
return this.extractUsageFromFile(
|
|
22203
|
+
return this.extractUsageFromFile(path43.join(dir, targetFile));
|
|
22088
22204
|
}
|
|
22089
22205
|
extractUsageFromFile(filePath) {
|
|
22090
22206
|
let raw;
|
|
22091
22207
|
try {
|
|
22092
|
-
raw =
|
|
22208
|
+
raw = fs35.readFileSync(filePath, "utf8");
|
|
22093
22209
|
} catch {
|
|
22094
22210
|
return null;
|
|
22095
22211
|
}
|
|
@@ -22134,9 +22250,9 @@ var HistoryService = class _HistoryService {
|
|
|
22134
22250
|
let totalCost = 0;
|
|
22135
22251
|
let files;
|
|
22136
22252
|
try {
|
|
22137
|
-
files =
|
|
22253
|
+
files = fs35.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
22138
22254
|
try {
|
|
22139
|
-
return
|
|
22255
|
+
return fs35.statSync(path43.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
22140
22256
|
} catch {
|
|
22141
22257
|
return false;
|
|
22142
22258
|
}
|
|
@@ -22147,7 +22263,7 @@ var HistoryService = class _HistoryService {
|
|
|
22147
22263
|
for (const file of files) {
|
|
22148
22264
|
let raw;
|
|
22149
22265
|
try {
|
|
22150
|
-
raw =
|
|
22266
|
+
raw = fs35.readFileSync(path43.join(projectDir, file), "utf8");
|
|
22151
22267
|
} catch {
|
|
22152
22268
|
continue;
|
|
22153
22269
|
}
|
|
@@ -22211,7 +22327,7 @@ var HistoryService = class _HistoryService {
|
|
|
22211
22327
|
* showing an empty conversation.
|
|
22212
22328
|
*/
|
|
22213
22329
|
async loadConversation(sessionId) {
|
|
22214
|
-
const filePath =
|
|
22330
|
+
const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
|
|
22215
22331
|
const messages = parseJsonl(filePath);
|
|
22216
22332
|
if (messages.length === 0) return;
|
|
22217
22333
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -22265,7 +22381,7 @@ var HistoryService = class _HistoryService {
|
|
|
22265
22381
|
if (!this.currentConversationId) return 0;
|
|
22266
22382
|
}
|
|
22267
22383
|
const sessionId = this.currentConversationId;
|
|
22268
|
-
const filePath =
|
|
22384
|
+
const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
|
|
22269
22385
|
const messages = parseJsonl(filePath);
|
|
22270
22386
|
if (messages.length === 0) return 0;
|
|
22271
22387
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -22691,13 +22807,13 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
22691
22807
|
}
|
|
22692
22808
|
|
|
22693
22809
|
// src/commands/start/keep-alive.ts
|
|
22694
|
-
var
|
|
22810
|
+
var import_child_process19 = require("child_process");
|
|
22695
22811
|
function buildKeepAlive(ctx) {
|
|
22696
22812
|
let timer = null;
|
|
22697
22813
|
async function setIdleTimeout(minutes) {
|
|
22698
22814
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
22699
22815
|
await new Promise((resolve7) => {
|
|
22700
|
-
const proc = (0,
|
|
22816
|
+
const proc = (0, import_child_process19.spawn)(
|
|
22701
22817
|
"gh",
|
|
22702
22818
|
[
|
|
22703
22819
|
"api",
|
|
@@ -22787,6 +22903,20 @@ async function start(requestedAgent) {
|
|
|
22787
22903
|
"pluginAuth",
|
|
22788
22904
|
`boot triple sessionId=${session.id} pluginId=${pluginId} tokenLen=${tokenForLog.length} tokenHead=${tokenForLog.slice(0, 12)} tokenTail=${tokenForLog.slice(-8)} mintedEqualsCached=${refreshed === session.pluginAuthToken}`
|
|
22789
22905
|
);
|
|
22906
|
+
let beads = null;
|
|
22907
|
+
const getBeads = () => beads;
|
|
22908
|
+
const beadsReady = provisionBeadsForStart({
|
|
22909
|
+
sessionId: session.id,
|
|
22910
|
+
pluginId,
|
|
22911
|
+
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
22912
|
+
cwd,
|
|
22913
|
+
// Wire this session's agent natively via `bd setup <recipe> --global` so
|
|
22914
|
+
// the agent actually uses bd (D12 — REVISED). Covers BOTH ACP and PTY.
|
|
22915
|
+
agents: [session.agent]
|
|
22916
|
+
}).then((started) => {
|
|
22917
|
+
beads = started;
|
|
22918
|
+
return started;
|
|
22919
|
+
});
|
|
22790
22920
|
const acpDisabled = process.env.CODEAM_ACP_DISABLED === "1";
|
|
22791
22921
|
if (!acpDisabled && session.pluginAuthToken) {
|
|
22792
22922
|
const adapter = getAcpAdapter(session.agent);
|
|
@@ -22797,7 +22927,8 @@ async function start(requestedAgent) {
|
|
|
22797
22927
|
pluginId,
|
|
22798
22928
|
pluginAuthToken: session.pluginAuthToken,
|
|
22799
22929
|
adapter,
|
|
22800
|
-
cwd
|
|
22930
|
+
cwd,
|
|
22931
|
+
getBeads
|
|
22801
22932
|
});
|
|
22802
22933
|
return;
|
|
22803
22934
|
}
|
|
@@ -22859,7 +22990,6 @@ async function start(requestedAgent) {
|
|
|
22859
22990
|
dirtyTracker: dirtyTracker ?? void 0
|
|
22860
22991
|
}) : null;
|
|
22861
22992
|
let streamingEmitter = null;
|
|
22862
|
-
let beads = null;
|
|
22863
22993
|
const agent = new AgentService(
|
|
22864
22994
|
runtime,
|
|
22865
22995
|
{
|
|
@@ -22910,14 +23040,7 @@ async function start(requestedAgent) {
|
|
|
22910
23040
|
await dispatchCommand(ctx, cmd);
|
|
22911
23041
|
}, runtime.meta);
|
|
22912
23042
|
ctx.relay = relay;
|
|
22913
|
-
void
|
|
22914
|
-
sessionId: session.id,
|
|
22915
|
-
pluginId,
|
|
22916
|
-
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
22917
|
-
agents: [session.agent],
|
|
22918
|
-
cwd
|
|
22919
|
-
}).then((started) => {
|
|
22920
|
-
beads = started;
|
|
23043
|
+
void beadsReady.then((started) => {
|
|
22921
23044
|
ctx.beads = started;
|
|
22922
23045
|
});
|
|
22923
23046
|
registerTerminalHandlers({
|
|
@@ -23175,7 +23298,7 @@ async function autoLinkAfterPair(opts) {
|
|
|
23175
23298
|
}
|
|
23176
23299
|
|
|
23177
23300
|
// src/commands/pair-auto.ts
|
|
23178
|
-
var
|
|
23301
|
+
var fs36 = __toESM(require("fs"));
|
|
23179
23302
|
var os28 = __toESM(require("os"));
|
|
23180
23303
|
var import_crypto7 = require("crypto");
|
|
23181
23304
|
|
|
@@ -23236,6 +23359,15 @@ async function startInfraOnly(agentId) {
|
|
|
23236
23359
|
pluginId,
|
|
23237
23360
|
pluginAuthToken: session.pluginAuthToken
|
|
23238
23361
|
}) : null;
|
|
23362
|
+
let beads = null;
|
|
23363
|
+
void provisionBeadsForStart({
|
|
23364
|
+
sessionId: session.id,
|
|
23365
|
+
pluginId,
|
|
23366
|
+
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
23367
|
+
cwd
|
|
23368
|
+
}).then((started) => {
|
|
23369
|
+
beads = started;
|
|
23370
|
+
});
|
|
23239
23371
|
let relayRef = null;
|
|
23240
23372
|
const ctx = {
|
|
23241
23373
|
// Agent-touching fields are not used by any of the commands
|
|
@@ -23257,6 +23389,23 @@ async function startInfraOnly(agentId) {
|
|
|
23257
23389
|
const relay = new CommandRelayService(
|
|
23258
23390
|
pluginId,
|
|
23259
23391
|
async (cmd) => {
|
|
23392
|
+
if (cmd.type === "beads_action") {
|
|
23393
|
+
if (!beads) {
|
|
23394
|
+
log.trace("infra-only", "beads_action received but beads not running \u2014 dropping");
|
|
23395
|
+
return;
|
|
23396
|
+
}
|
|
23397
|
+
const action = beadsActionFromPayload(cmd.payload);
|
|
23398
|
+
if (!action) {
|
|
23399
|
+
log.warn("infra-only", "malformed beads_action payload \u2014 dropping");
|
|
23400
|
+
return;
|
|
23401
|
+
}
|
|
23402
|
+
try {
|
|
23403
|
+
await handleBeadsActionCommand(action, beads);
|
|
23404
|
+
} catch (err) {
|
|
23405
|
+
log.warn("infra-only", "handleBeadsActionCommand failed (non-fatal)", err);
|
|
23406
|
+
}
|
|
23407
|
+
return;
|
|
23408
|
+
}
|
|
23260
23409
|
if (!INFRA_ONLY_COMMAND_TYPES.has(cmd.type)) {
|
|
23261
23410
|
log.trace("infra-only", `dropping agent-only command type=${cmd.type}`);
|
|
23262
23411
|
return;
|
|
@@ -23317,6 +23466,7 @@ async function startInfraOnly(agentId) {
|
|
|
23317
23466
|
} catch {
|
|
23318
23467
|
}
|
|
23319
23468
|
void fileWatcher?.stop();
|
|
23469
|
+
void beads?.watcher.stop();
|
|
23320
23470
|
closeAllTerminals();
|
|
23321
23471
|
cleanupAttachmentTempFiles();
|
|
23322
23472
|
process.exit(0);
|
|
@@ -23344,12 +23494,12 @@ function readTokenFromArgs(args2) {
|
|
|
23344
23494
|
}
|
|
23345
23495
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
23346
23496
|
if (fileFlag) {
|
|
23347
|
-
const
|
|
23497
|
+
const path50 = fileFlag.slice("--token-file=".length);
|
|
23348
23498
|
try {
|
|
23349
|
-
const content =
|
|
23350
|
-
if (content.length === 0) fail(`--token-file ${
|
|
23499
|
+
const content = fs36.readFileSync(path50, "utf8").trim();
|
|
23500
|
+
if (content.length === 0) fail(`--token-file ${path50} is empty`);
|
|
23351
23501
|
try {
|
|
23352
|
-
|
|
23502
|
+
fs36.unlinkSync(path50);
|
|
23353
23503
|
} catch {
|
|
23354
23504
|
}
|
|
23355
23505
|
return content;
|
|
@@ -23612,11 +23762,11 @@ async function logout() {
|
|
|
23612
23762
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
23613
23763
|
|
|
23614
23764
|
// src/services/providers/github-codespaces.ts
|
|
23615
|
-
var
|
|
23765
|
+
var import_child_process20 = require("child_process");
|
|
23616
23766
|
var import_util4 = require("util");
|
|
23617
23767
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
23618
|
-
var
|
|
23619
|
-
var execFileP5 = (0, import_util4.promisify)(
|
|
23768
|
+
var path44 = __toESM(require("path"));
|
|
23769
|
+
var execFileP5 = (0, import_util4.promisify)(import_child_process20.execFile);
|
|
23620
23770
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
23621
23771
|
function resetStdinForChild() {
|
|
23622
23772
|
if (process.stdin.isTTY) {
|
|
@@ -23660,7 +23810,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23660
23810
|
if (!isAuthed) {
|
|
23661
23811
|
resetStdinForChild();
|
|
23662
23812
|
await new Promise((resolve7, reject) => {
|
|
23663
|
-
const proc = (0,
|
|
23813
|
+
const proc = (0, import_child_process20.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
23664
23814
|
stdio: "inherit"
|
|
23665
23815
|
});
|
|
23666
23816
|
proc.on("exit", (code) => {
|
|
@@ -23694,7 +23844,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23694
23844
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
23695
23845
|
resetStdinForChild();
|
|
23696
23846
|
const refreshCode = await new Promise((resolve7, reject) => {
|
|
23697
|
-
const proc = (0,
|
|
23847
|
+
const proc = (0, import_child_process20.spawn)(
|
|
23698
23848
|
"gh",
|
|
23699
23849
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
23700
23850
|
{ stdio: "inherit" }
|
|
@@ -23844,7 +23994,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23844
23994
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
23845
23995
|
resetStdinForChild();
|
|
23846
23996
|
const ok = await new Promise((resolve7) => {
|
|
23847
|
-
const proc = (0,
|
|
23997
|
+
const proc = (0, import_child_process20.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
23848
23998
|
proc.on("exit", (code) => resolve7(code === 0));
|
|
23849
23999
|
proc.on("error", () => resolve7(false));
|
|
23850
24000
|
});
|
|
@@ -23871,7 +24021,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23871
24021
|
);
|
|
23872
24022
|
resetStdinForChild();
|
|
23873
24023
|
await new Promise((resolve7, reject) => {
|
|
23874
|
-
const proc = (0,
|
|
24024
|
+
const proc = (0, import_child_process20.spawn)(
|
|
23875
24025
|
"gh",
|
|
23876
24026
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
23877
24027
|
{ stdio: "inherit" }
|
|
@@ -24049,7 +24199,7 @@ var GitHubCodespacesProvider = class {
|
|
|
24049
24199
|
async streamCommand(workspaceId, command2) {
|
|
24050
24200
|
resetStdinForChild();
|
|
24051
24201
|
return new Promise((resolve7, reject) => {
|
|
24052
|
-
const proc = (0,
|
|
24202
|
+
const proc = (0, import_child_process20.spawn)(
|
|
24053
24203
|
"gh",
|
|
24054
24204
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
24055
24205
|
{ stdio: "inherit" }
|
|
@@ -24076,11 +24226,11 @@ var GitHubCodespacesProvider = class {
|
|
|
24076
24226
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
24077
24227
|
];
|
|
24078
24228
|
await new Promise((resolve7, reject) => {
|
|
24079
|
-
const tar = (0,
|
|
24229
|
+
const tar = (0, import_child_process20.spawn)("tar", tarArgs, {
|
|
24080
24230
|
stdio: ["ignore", "pipe", "pipe"],
|
|
24081
24231
|
env: tarEnv
|
|
24082
24232
|
});
|
|
24083
|
-
const ssh = (0,
|
|
24233
|
+
const ssh = (0, import_child_process20.spawn)("gh", sshArgs, {
|
|
24084
24234
|
stdio: [tar.stdout, "pipe", "pipe"]
|
|
24085
24235
|
});
|
|
24086
24236
|
let tarErr = "";
|
|
@@ -24104,7 +24254,7 @@ var GitHubCodespacesProvider = class {
|
|
|
24104
24254
|
});
|
|
24105
24255
|
}
|
|
24106
24256
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
24107
|
-
const remoteDir =
|
|
24257
|
+
const remoteDir = path44.posix.dirname(remotePath);
|
|
24108
24258
|
const parts = [
|
|
24109
24259
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
24110
24260
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -24114,7 +24264,7 @@ var GitHubCodespacesProvider = class {
|
|
|
24114
24264
|
}
|
|
24115
24265
|
const cmd = parts.join(" && ");
|
|
24116
24266
|
await new Promise((resolve7, reject) => {
|
|
24117
|
-
const proc = (0,
|
|
24267
|
+
const proc = (0, import_child_process20.spawn)(
|
|
24118
24268
|
"gh",
|
|
24119
24269
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
24120
24270
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -24172,11 +24322,11 @@ function shellQuote(s) {
|
|
|
24172
24322
|
}
|
|
24173
24323
|
|
|
24174
24324
|
// src/services/providers/gitpod.ts
|
|
24175
|
-
var
|
|
24325
|
+
var import_child_process21 = require("child_process");
|
|
24176
24326
|
var import_util5 = require("util");
|
|
24177
|
-
var
|
|
24327
|
+
var path45 = __toESM(require("path"));
|
|
24178
24328
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
24179
|
-
var execFileP6 = (0, import_util5.promisify)(
|
|
24329
|
+
var execFileP6 = (0, import_util5.promisify)(import_child_process21.execFile);
|
|
24180
24330
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
24181
24331
|
function resetStdinForChild2() {
|
|
24182
24332
|
if (process.stdin.isTTY) {
|
|
@@ -24216,7 +24366,7 @@ var GitpodProvider = class {
|
|
|
24216
24366
|
);
|
|
24217
24367
|
resetStdinForChild2();
|
|
24218
24368
|
await new Promise((resolve7, reject) => {
|
|
24219
|
-
const proc = (0,
|
|
24369
|
+
const proc = (0, import_child_process21.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
24220
24370
|
proc.on("exit", (code) => {
|
|
24221
24371
|
if (code === 0) resolve7();
|
|
24222
24372
|
else reject(new Error("gitpod login failed."));
|
|
@@ -24368,7 +24518,7 @@ var GitpodProvider = class {
|
|
|
24368
24518
|
async streamCommand(workspaceId, command2) {
|
|
24369
24519
|
resetStdinForChild2();
|
|
24370
24520
|
return new Promise((resolve7, reject) => {
|
|
24371
|
-
const proc = (0,
|
|
24521
|
+
const proc = (0, import_child_process21.spawn)(
|
|
24372
24522
|
"gitpod",
|
|
24373
24523
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
24374
24524
|
{ stdio: "inherit" }
|
|
@@ -24388,11 +24538,11 @@ var GitpodProvider = class {
|
|
|
24388
24538
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
24389
24539
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
24390
24540
|
await new Promise((resolve7, reject) => {
|
|
24391
|
-
const tar = (0,
|
|
24541
|
+
const tar = (0, import_child_process21.spawn)("tar", tarArgs, {
|
|
24392
24542
|
stdio: ["ignore", "pipe", "pipe"],
|
|
24393
24543
|
env: tarEnv
|
|
24394
24544
|
});
|
|
24395
|
-
const ssh = (0,
|
|
24545
|
+
const ssh = (0, import_child_process21.spawn)(
|
|
24396
24546
|
"gitpod",
|
|
24397
24547
|
["workspace", "ssh", workspaceId, "--", remoteCmd],
|
|
24398
24548
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -24414,7 +24564,7 @@ var GitpodProvider = class {
|
|
|
24414
24564
|
});
|
|
24415
24565
|
}
|
|
24416
24566
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
24417
|
-
const remoteDir =
|
|
24567
|
+
const remoteDir = path45.posix.dirname(remotePath);
|
|
24418
24568
|
const parts = [
|
|
24419
24569
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
24420
24570
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -24424,7 +24574,7 @@ var GitpodProvider = class {
|
|
|
24424
24574
|
}
|
|
24425
24575
|
const cmd = parts.join(" && ");
|
|
24426
24576
|
await new Promise((resolve7, reject) => {
|
|
24427
|
-
const proc = (0,
|
|
24577
|
+
const proc = (0, import_child_process21.spawn)(
|
|
24428
24578
|
"gitpod",
|
|
24429
24579
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
24430
24580
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -24448,10 +24598,10 @@ function shellQuote2(s) {
|
|
|
24448
24598
|
}
|
|
24449
24599
|
|
|
24450
24600
|
// src/services/providers/gitlab-workspaces.ts
|
|
24451
|
-
var
|
|
24601
|
+
var import_child_process22 = require("child_process");
|
|
24452
24602
|
var import_util6 = require("util");
|
|
24453
|
-
var
|
|
24454
|
-
var execFileP7 = (0, import_util6.promisify)(
|
|
24603
|
+
var path46 = __toESM(require("path"));
|
|
24604
|
+
var execFileP7 = (0, import_util6.promisify)(import_child_process22.execFile);
|
|
24455
24605
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
24456
24606
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
24457
24607
|
function resetStdinForChild3() {
|
|
@@ -24493,7 +24643,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
24493
24643
|
);
|
|
24494
24644
|
resetStdinForChild3();
|
|
24495
24645
|
await new Promise((resolve7, reject) => {
|
|
24496
|
-
const proc = (0,
|
|
24646
|
+
const proc = (0, import_child_process22.spawn)(
|
|
24497
24647
|
"glab",
|
|
24498
24648
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
24499
24649
|
{ stdio: "inherit" }
|
|
@@ -24665,7 +24815,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
24665
24815
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
24666
24816
|
resetStdinForChild3();
|
|
24667
24817
|
return new Promise((resolve7, reject) => {
|
|
24668
|
-
const proc = (0,
|
|
24818
|
+
const proc = (0, import_child_process22.spawn)(
|
|
24669
24819
|
"ssh",
|
|
24670
24820
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
24671
24821
|
{ stdio: "inherit" }
|
|
@@ -24686,8 +24836,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
24686
24836
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
24687
24837
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
24688
24838
|
await new Promise((resolve7, reject) => {
|
|
24689
|
-
const tar = (0,
|
|
24690
|
-
const ssh = (0,
|
|
24839
|
+
const tar = (0, import_child_process22.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
24840
|
+
const ssh = (0, import_child_process22.spawn)(
|
|
24691
24841
|
"ssh",
|
|
24692
24842
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
|
|
24693
24843
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -24710,14 +24860,14 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
24710
24860
|
}
|
|
24711
24861
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
24712
24862
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
24713
|
-
const remoteDir =
|
|
24863
|
+
const remoteDir = path46.posix.dirname(remotePath);
|
|
24714
24864
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
24715
24865
|
if (options.mode != null) {
|
|
24716
24866
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
24717
24867
|
}
|
|
24718
24868
|
const cmd = parts.join(" && ");
|
|
24719
24869
|
await new Promise((resolve7, reject) => {
|
|
24720
|
-
const proc = (0,
|
|
24870
|
+
const proc = (0, import_child_process22.spawn)(
|
|
24721
24871
|
"ssh",
|
|
24722
24872
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
24723
24873
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -24776,10 +24926,10 @@ function shellQuote3(s) {
|
|
|
24776
24926
|
}
|
|
24777
24927
|
|
|
24778
24928
|
// src/services/providers/railway.ts
|
|
24779
|
-
var
|
|
24929
|
+
var import_child_process23 = require("child_process");
|
|
24780
24930
|
var import_util7 = require("util");
|
|
24781
|
-
var
|
|
24782
|
-
var execFileP8 = (0, import_util7.promisify)(
|
|
24931
|
+
var path47 = __toESM(require("path"));
|
|
24932
|
+
var execFileP8 = (0, import_util7.promisify)(import_child_process23.execFile);
|
|
24783
24933
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
24784
24934
|
function resetStdinForChild4() {
|
|
24785
24935
|
if (process.stdin.isTTY) {
|
|
@@ -24820,7 +24970,7 @@ var RailwayProvider = class {
|
|
|
24820
24970
|
);
|
|
24821
24971
|
resetStdinForChild4();
|
|
24822
24972
|
await new Promise((resolve7, reject) => {
|
|
24823
|
-
const proc = (0,
|
|
24973
|
+
const proc = (0, import_child_process23.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
24824
24974
|
proc.on("exit", (code) => {
|
|
24825
24975
|
if (code === 0) resolve7();
|
|
24826
24976
|
else reject(new Error("railway login failed."));
|
|
@@ -24963,7 +25113,7 @@ var RailwayProvider = class {
|
|
|
24963
25113
|
}
|
|
24964
25114
|
resetStdinForChild4();
|
|
24965
25115
|
return new Promise((resolve7, reject) => {
|
|
24966
|
-
const proc = (0,
|
|
25116
|
+
const proc = (0, import_child_process23.spawn)(
|
|
24967
25117
|
"railway",
|
|
24968
25118
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
24969
25119
|
{ stdio: "inherit" }
|
|
@@ -24987,8 +25137,8 @@ var RailwayProvider = class {
|
|
|
24987
25137
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
24988
25138
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
24989
25139
|
await new Promise((resolve7, reject) => {
|
|
24990
|
-
const tar = (0,
|
|
24991
|
-
const sh = (0,
|
|
25140
|
+
const tar = (0, import_child_process23.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
25141
|
+
const sh = (0, import_child_process23.spawn)(
|
|
24992
25142
|
"railway",
|
|
24993
25143
|
["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
|
|
24994
25144
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -25014,14 +25164,14 @@ var RailwayProvider = class {
|
|
|
25014
25164
|
if (!projectId || !serviceId) {
|
|
25015
25165
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
25016
25166
|
}
|
|
25017
|
-
const remoteDir =
|
|
25167
|
+
const remoteDir = path47.posix.dirname(remotePath);
|
|
25018
25168
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
25019
25169
|
if (options.mode != null) {
|
|
25020
25170
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
25021
25171
|
}
|
|
25022
25172
|
const cmd = parts.join(" && ");
|
|
25023
25173
|
await new Promise((resolve7, reject) => {
|
|
25024
|
-
const proc = (0,
|
|
25174
|
+
const proc = (0, import_child_process23.spawn)(
|
|
25025
25175
|
"railway",
|
|
25026
25176
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
25027
25177
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -25557,8 +25707,8 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
25557
25707
|
var import_node_dns = require("dns");
|
|
25558
25708
|
var import_node_util4 = require("util");
|
|
25559
25709
|
var import_node_crypto8 = require("crypto");
|
|
25560
|
-
var
|
|
25561
|
-
var
|
|
25710
|
+
var fs37 = __toESM(require("fs"));
|
|
25711
|
+
var path48 = __toESM(require("path"));
|
|
25562
25712
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
25563
25713
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
25564
25714
|
async function checkDns(apiBase) {
|
|
@@ -25614,13 +25764,13 @@ async function checkHealth(apiBase) {
|
|
|
25614
25764
|
}
|
|
25615
25765
|
}
|
|
25616
25766
|
function checkConfigDir() {
|
|
25617
|
-
const dir =
|
|
25767
|
+
const dir = path48.join(require("os").homedir(), ".codeam");
|
|
25618
25768
|
try {
|
|
25619
|
-
|
|
25620
|
-
const probe =
|
|
25621
|
-
|
|
25622
|
-
const read =
|
|
25623
|
-
|
|
25769
|
+
fs37.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
25770
|
+
const probe = path48.join(dir, ".doctor-probe");
|
|
25771
|
+
fs37.writeFileSync(probe, "ok", { mode: 384 });
|
|
25772
|
+
const read = fs37.readFileSync(probe, "utf8");
|
|
25773
|
+
fs37.unlinkSync(probe);
|
|
25624
25774
|
if (read !== "ok") throw new Error("write/read round-trip mismatch");
|
|
25625
25775
|
return {
|
|
25626
25776
|
id: "config-dir",
|
|
@@ -25684,7 +25834,7 @@ function checkNodePty() {
|
|
|
25684
25834
|
detail: "not required on this platform"
|
|
25685
25835
|
};
|
|
25686
25836
|
}
|
|
25687
|
-
const vendoredPath =
|
|
25837
|
+
const vendoredPath = path48.join(__dirname, "vendor", "node-pty");
|
|
25688
25838
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
25689
25839
|
try {
|
|
25690
25840
|
require(target);
|
|
@@ -25726,7 +25876,7 @@ function checkChokidar() {
|
|
|
25726
25876
|
}
|
|
25727
25877
|
async function doctor(args2 = []) {
|
|
25728
25878
|
const json = args2.includes("--json");
|
|
25729
|
-
const cliVersion = true ? "2.
|
|
25879
|
+
const cliVersion = true ? "2.35.0" : "0.0.0-dev";
|
|
25730
25880
|
const apiBase = resolveApiBaseUrl();
|
|
25731
25881
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
25732
25882
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -25925,7 +26075,7 @@ async function completion(args2) {
|
|
|
25925
26075
|
// src/commands/version.ts
|
|
25926
26076
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
25927
26077
|
function version2() {
|
|
25928
|
-
const v = true ? "2.
|
|
26078
|
+
const v = true ? "2.35.0" : "unknown";
|
|
25929
26079
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
25930
26080
|
}
|
|
25931
26081
|
|
|
@@ -26053,9 +26203,9 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
26053
26203
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
26054
26204
|
|
|
26055
26205
|
// src/lib/updateNotifier.ts
|
|
26056
|
-
var
|
|
26206
|
+
var fs38 = __toESM(require("fs"));
|
|
26057
26207
|
var os29 = __toESM(require("os"));
|
|
26058
|
-
var
|
|
26208
|
+
var path49 = __toESM(require("path"));
|
|
26059
26209
|
var https8 = __toESM(require("https"));
|
|
26060
26210
|
var import_node_child_process12 = require("child_process");
|
|
26061
26211
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
@@ -26064,12 +26214,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
26064
26214
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
26065
26215
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
26066
26216
|
function cachePath() {
|
|
26067
|
-
const dir =
|
|
26068
|
-
return
|
|
26217
|
+
const dir = path49.join(os29.homedir(), ".codeam");
|
|
26218
|
+
return path49.join(dir, "update-check.json");
|
|
26069
26219
|
}
|
|
26070
26220
|
function readCache() {
|
|
26071
26221
|
try {
|
|
26072
|
-
const raw =
|
|
26222
|
+
const raw = fs38.readFileSync(cachePath(), "utf8");
|
|
26073
26223
|
const parsed = JSON.parse(raw);
|
|
26074
26224
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
26075
26225
|
return parsed;
|
|
@@ -26080,10 +26230,10 @@ function readCache() {
|
|
|
26080
26230
|
function writeCache(cache) {
|
|
26081
26231
|
try {
|
|
26082
26232
|
const file = cachePath();
|
|
26083
|
-
|
|
26233
|
+
fs38.mkdirSync(path49.dirname(file), { recursive: true });
|
|
26084
26234
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
26085
|
-
|
|
26086
|
-
|
|
26235
|
+
fs38.writeFileSync(tmp, JSON.stringify(cache));
|
|
26236
|
+
fs38.renameSync(tmp, file);
|
|
26087
26237
|
} catch {
|
|
26088
26238
|
}
|
|
26089
26239
|
}
|
|
@@ -26157,8 +26307,8 @@ function isLinkedInstall() {
|
|
|
26157
26307
|
timeout: 2e3
|
|
26158
26308
|
}).trim();
|
|
26159
26309
|
if (!root) return false;
|
|
26160
|
-
const pkgPath =
|
|
26161
|
-
return
|
|
26310
|
+
const pkgPath = path49.join(root, PKG_NAME);
|
|
26311
|
+
return fs38.lstatSync(pkgPath).isSymbolicLink();
|
|
26162
26312
|
} catch {
|
|
26163
26313
|
return false;
|
|
26164
26314
|
}
|
|
@@ -26194,7 +26344,7 @@ function maybeAutoUpdate(currentVersion, latest) {
|
|
|
26194
26344
|
return;
|
|
26195
26345
|
}
|
|
26196
26346
|
try {
|
|
26197
|
-
|
|
26347
|
+
fs38.unlinkSync(cachePath());
|
|
26198
26348
|
} catch {
|
|
26199
26349
|
}
|
|
26200
26350
|
process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
|
|
@@ -26211,7 +26361,7 @@ function checkForUpdates() {
|
|
|
26211
26361
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
26212
26362
|
if (process.env.CI) return;
|
|
26213
26363
|
if (!process.stdout.isTTY) return;
|
|
26214
|
-
const current = true ? "2.
|
|
26364
|
+
const current = true ? "2.35.0" : null;
|
|
26215
26365
|
if (!current) return;
|
|
26216
26366
|
const cache = readCache();
|
|
26217
26367
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|