codeam-cli 2.32.10 → 2.34.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 +17 -0
- package/dist/index.js +1386 -559
- package/package.json +2 -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.34.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",
|
|
@@ -569,6 +569,7 @@ var package_default = {
|
|
|
569
569
|
},
|
|
570
570
|
dependencies: {
|
|
571
571
|
"@agentclientprotocol/claude-agent-acp": "^0.42.0",
|
|
572
|
+
"@beads/bd": "1.0.5",
|
|
572
573
|
"@agentclientprotocol/codex-acp": "^0.0.45",
|
|
573
574
|
"@agentclientprotocol/sdk": "^0.25.0",
|
|
574
575
|
"@clack/prompts": "^1.2.0",
|
|
@@ -707,8 +708,8 @@ async function requestCode(pluginId) {
|
|
|
707
708
|
});
|
|
708
709
|
let timer;
|
|
709
710
|
const timeoutSentinel = /* @__PURE__ */ Symbol("request-code-timeout");
|
|
710
|
-
const timeoutPromise = new Promise((
|
|
711
|
-
timer = setTimeout(() =>
|
|
711
|
+
const timeoutPromise = new Promise((resolve7) => {
|
|
712
|
+
timer = setTimeout(() => resolve7(timeoutSentinel), REQUEST_CODE_TIMEOUT_MS);
|
|
712
713
|
});
|
|
713
714
|
const result = await Promise.race([post2, timeoutPromise]);
|
|
714
715
|
clearTimeout(timer);
|
|
@@ -851,8 +852,30 @@ async function postPreviewEvent(input) {
|
|
|
851
852
|
};
|
|
852
853
|
}
|
|
853
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
|
+
}
|
|
854
877
|
async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
855
|
-
return new Promise((
|
|
878
|
+
return new Promise((resolve7, reject) => {
|
|
856
879
|
const data = JSON.stringify(body);
|
|
857
880
|
const u2 = new URL(url);
|
|
858
881
|
const transport = u2.protocol === "https:" ? https : http;
|
|
@@ -884,9 +907,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
884
907
|
return;
|
|
885
908
|
}
|
|
886
909
|
try {
|
|
887
|
-
|
|
910
|
+
resolve7(JSON.parse(responseBody));
|
|
888
911
|
} catch {
|
|
889
|
-
|
|
912
|
+
resolve7(null);
|
|
890
913
|
}
|
|
891
914
|
});
|
|
892
915
|
}
|
|
@@ -911,7 +934,7 @@ function makeHttpError(statusCode, retryAfterHeader, responseBody) {
|
|
|
911
934
|
return err;
|
|
912
935
|
}
|
|
913
936
|
async function _postJson(url, body) {
|
|
914
|
-
return new Promise((
|
|
937
|
+
return new Promise((resolve7, reject) => {
|
|
915
938
|
const data = JSON.stringify(body);
|
|
916
939
|
const u2 = new URL(url);
|
|
917
940
|
const transport = u2.protocol === "https:" ? https : http;
|
|
@@ -940,9 +963,9 @@ async function _postJson(url, body) {
|
|
|
940
963
|
return;
|
|
941
964
|
}
|
|
942
965
|
try {
|
|
943
|
-
|
|
966
|
+
resolve7(JSON.parse(body2));
|
|
944
967
|
} catch {
|
|
945
|
-
|
|
968
|
+
resolve7(null);
|
|
946
969
|
}
|
|
947
970
|
});
|
|
948
971
|
}
|
|
@@ -957,7 +980,7 @@ async function _postJson(url, body) {
|
|
|
957
980
|
});
|
|
958
981
|
}
|
|
959
982
|
async function _getJson(url) {
|
|
960
|
-
return new Promise((
|
|
983
|
+
return new Promise((resolve7, reject) => {
|
|
961
984
|
const u2 = new URL(url);
|
|
962
985
|
const transport = u2.protocol === "https:" ? https : http;
|
|
963
986
|
const req = transport.request(
|
|
@@ -981,9 +1004,9 @@ async function _getJson(url) {
|
|
|
981
1004
|
return;
|
|
982
1005
|
}
|
|
983
1006
|
try {
|
|
984
|
-
|
|
1007
|
+
resolve7(JSON.parse(body));
|
|
985
1008
|
} catch {
|
|
986
|
-
|
|
1009
|
+
resolve7(null);
|
|
987
1010
|
}
|
|
988
1011
|
});
|
|
989
1012
|
}
|
|
@@ -1161,8 +1184,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
1161
1184
|
return decodedFile;
|
|
1162
1185
|
};
|
|
1163
1186
|
}
|
|
1164
|
-
function normalizeWindowsPath(
|
|
1165
|
-
return
|
|
1187
|
+
function normalizeWindowsPath(path50) {
|
|
1188
|
+
return path50.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
1166
1189
|
}
|
|
1167
1190
|
|
|
1168
1191
|
// ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
|
|
@@ -3642,15 +3665,15 @@ async function addSourceContext(frames) {
|
|
|
3642
3665
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
3643
3666
|
return frames;
|
|
3644
3667
|
}
|
|
3645
|
-
function getContextLinesFromFile(
|
|
3646
|
-
return new Promise((
|
|
3647
|
-
const stream = (0, import_node_fs.createReadStream)(
|
|
3668
|
+
function getContextLinesFromFile(path50, ranges, output) {
|
|
3669
|
+
return new Promise((resolve7) => {
|
|
3670
|
+
const stream = (0, import_node_fs.createReadStream)(path50);
|
|
3648
3671
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3649
3672
|
input: stream
|
|
3650
3673
|
});
|
|
3651
3674
|
function destroyStreamAndResolve() {
|
|
3652
3675
|
stream.destroy();
|
|
3653
|
-
|
|
3676
|
+
resolve7();
|
|
3654
3677
|
}
|
|
3655
3678
|
let lineNumber = 0;
|
|
3656
3679
|
let currentRangeIndex = 0;
|
|
@@ -3659,7 +3682,7 @@ function getContextLinesFromFile(path46, ranges, output) {
|
|
|
3659
3682
|
let rangeStart = range[0];
|
|
3660
3683
|
let rangeEnd = range[1];
|
|
3661
3684
|
function onStreamError() {
|
|
3662
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
3685
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path50, 1);
|
|
3663
3686
|
lineReaded.close();
|
|
3664
3687
|
lineReaded.removeAllListeners();
|
|
3665
3688
|
destroyStreamAndResolve();
|
|
@@ -3720,8 +3743,8 @@ function clearLineContext(frame) {
|
|
|
3720
3743
|
delete frame.context_line;
|
|
3721
3744
|
delete frame.post_context;
|
|
3722
3745
|
}
|
|
3723
|
-
function shouldSkipContextLinesForFile(
|
|
3724
|
-
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:");
|
|
3725
3748
|
}
|
|
3726
3749
|
function shouldSkipContextLinesForFrame(frame) {
|
|
3727
3750
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -4937,9 +4960,9 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4937
4960
|
if (!waitUntil) return;
|
|
4938
4961
|
if (this.disabled || this.optedOut) return;
|
|
4939
4962
|
if (!this._waitUntilCycle) {
|
|
4940
|
-
let
|
|
4963
|
+
let resolve7;
|
|
4941
4964
|
const promise = new Promise((r) => {
|
|
4942
|
-
|
|
4965
|
+
resolve7 = r;
|
|
4943
4966
|
});
|
|
4944
4967
|
try {
|
|
4945
4968
|
waitUntil(promise);
|
|
@@ -4947,7 +4970,7 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4947
4970
|
return;
|
|
4948
4971
|
}
|
|
4949
4972
|
this._waitUntilCycle = {
|
|
4950
|
-
resolve:
|
|
4973
|
+
resolve: resolve7,
|
|
4951
4974
|
startedAt: Date.now(),
|
|
4952
4975
|
timer: void 0
|
|
4953
4976
|
};
|
|
@@ -4971,12 +4994,12 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4971
4994
|
return cycle?.resolve;
|
|
4972
4995
|
}
|
|
4973
4996
|
async resolveWaitUntilFlush() {
|
|
4974
|
-
const
|
|
4997
|
+
const resolve7 = this._consumeWaitUntilCycle();
|
|
4975
4998
|
try {
|
|
4976
4999
|
await super.flush();
|
|
4977
5000
|
} catch {
|
|
4978
5001
|
} finally {
|
|
4979
|
-
|
|
5002
|
+
resolve7?.();
|
|
4980
5003
|
}
|
|
4981
5004
|
}
|
|
4982
5005
|
getPersistedProperty(key) {
|
|
@@ -5068,15 +5091,15 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
5068
5091
|
async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
|
|
5069
5092
|
if (this.isLocalEvaluationReady()) return true;
|
|
5070
5093
|
if (void 0 === this.featureFlagsPoller) return false;
|
|
5071
|
-
return new Promise((
|
|
5094
|
+
return new Promise((resolve7) => {
|
|
5072
5095
|
const timeout = setTimeout(() => {
|
|
5073
5096
|
cleanup();
|
|
5074
|
-
|
|
5097
|
+
resolve7(false);
|
|
5075
5098
|
}, timeoutMs);
|
|
5076
5099
|
const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
|
|
5077
5100
|
clearTimeout(timeout);
|
|
5078
5101
|
cleanup();
|
|
5079
|
-
|
|
5102
|
+
resolve7(count > 0);
|
|
5080
5103
|
});
|
|
5081
5104
|
});
|
|
5082
5105
|
}
|
|
@@ -5513,13 +5536,13 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
5513
5536
|
this.context?.enter(data, options);
|
|
5514
5537
|
}
|
|
5515
5538
|
async _shutdown(shutdownTimeoutMs) {
|
|
5516
|
-
const
|
|
5539
|
+
const resolve7 = this._consumeWaitUntilCycle();
|
|
5517
5540
|
await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
|
|
5518
5541
|
this.errorTracking.shutdown();
|
|
5519
5542
|
try {
|
|
5520
5543
|
return await super._shutdown(shutdownTimeoutMs);
|
|
5521
5544
|
} finally {
|
|
5522
|
-
|
|
5545
|
+
resolve7?.();
|
|
5523
5546
|
}
|
|
5524
5547
|
}
|
|
5525
5548
|
async _requestRemoteConfigPayload(flagKey) {
|
|
@@ -5875,7 +5898,7 @@ function readAnonId() {
|
|
|
5875
5898
|
}
|
|
5876
5899
|
function superProperties() {
|
|
5877
5900
|
return {
|
|
5878
|
-
cliVersion: true ? "2.
|
|
5901
|
+
cliVersion: true ? "2.34.0" : "0.0.0-dev",
|
|
5879
5902
|
nodeVersion: process.version,
|
|
5880
5903
|
platform: process.platform,
|
|
5881
5904
|
arch: process.arch,
|
|
@@ -7217,10 +7240,10 @@ function buildForPlatform(platform2) {
|
|
|
7217
7240
|
var import_node_crypto4 = require("crypto");
|
|
7218
7241
|
|
|
7219
7242
|
// src/agents/claude/resolver.ts
|
|
7220
|
-
function buildClaudeLaunch(extraArgs = [],
|
|
7221
|
-
const found =
|
|
7243
|
+
function buildClaudeLaunch(extraArgs = [], os30 = createOsStrategy()) {
|
|
7244
|
+
const found = os30.findInPath("claude") ?? os30.findInPath("claude-code");
|
|
7222
7245
|
if (!found) return null;
|
|
7223
|
-
return
|
|
7246
|
+
return os30.buildLaunch(found, extraArgs);
|
|
7224
7247
|
}
|
|
7225
7248
|
|
|
7226
7249
|
// src/agents/claude/installer.ts
|
|
@@ -9176,15 +9199,15 @@ function runInstaller() {
|
|
|
9176
9199
|
"-Command",
|
|
9177
9200
|
"irm https://claude.ai/install.ps1 | iex"
|
|
9178
9201
|
] : ["-c", "curl -fsSL https://claude.ai/install.sh | bash"];
|
|
9179
|
-
return new Promise((
|
|
9202
|
+
return new Promise((resolve7) => {
|
|
9180
9203
|
const proc = (0, import_child_process4.spawn)(cmd, args2, { stdio: "inherit" });
|
|
9181
9204
|
proc.on("error", (err) => {
|
|
9182
9205
|
console.error(`
|
|
9183
9206
|
\u2717 Installer failed to launch: ${err.message}`);
|
|
9184
|
-
|
|
9207
|
+
resolve7(false);
|
|
9185
9208
|
});
|
|
9186
9209
|
proc.on("exit", (code) => {
|
|
9187
|
-
|
|
9210
|
+
resolve7(code === 0);
|
|
9188
9211
|
});
|
|
9189
9212
|
});
|
|
9190
9213
|
}
|
|
@@ -9361,17 +9384,17 @@ function parseUsageOutput(raw) {
|
|
|
9361
9384
|
return { percent, resetAt };
|
|
9362
9385
|
}
|
|
9363
9386
|
async function fetchClaudeQuota() {
|
|
9364
|
-
return new Promise((
|
|
9387
|
+
return new Promise((resolve7) => {
|
|
9365
9388
|
const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
|
|
9366
9389
|
if (!claudeCmd) {
|
|
9367
|
-
|
|
9390
|
+
resolve7(null);
|
|
9368
9391
|
return;
|
|
9369
9392
|
}
|
|
9370
9393
|
const helperPath = path11.join(os10.tmpdir(), "codeam-quota-helper.py");
|
|
9371
9394
|
fs8.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
|
|
9372
9395
|
const python = findInPath("python3") ?? findInPath("python");
|
|
9373
9396
|
if (!python) {
|
|
9374
|
-
|
|
9397
|
+
resolve7(null);
|
|
9375
9398
|
return;
|
|
9376
9399
|
}
|
|
9377
9400
|
const proc = (0, import_child_process5.spawn)(python, [helperPath, claudeCmd, "--tools", ""], {
|
|
@@ -9398,13 +9421,13 @@ async function fetchClaudeQuota() {
|
|
|
9398
9421
|
fs8.unlinkSync(helperPath);
|
|
9399
9422
|
} catch {
|
|
9400
9423
|
}
|
|
9401
|
-
|
|
9424
|
+
resolve7(result);
|
|
9402
9425
|
}, 5e3);
|
|
9403
9426
|
}, 8e3);
|
|
9404
9427
|
setTimeout(() => {
|
|
9405
9428
|
if (!resolved) {
|
|
9406
9429
|
resolved = true;
|
|
9407
|
-
|
|
9430
|
+
resolve7(null);
|
|
9408
9431
|
}
|
|
9409
9432
|
try {
|
|
9410
9433
|
proc.kill();
|
|
@@ -9435,12 +9458,12 @@ function killActiveSpawnAndCaptureChildren() {
|
|
|
9435
9458
|
}
|
|
9436
9459
|
async function spawnAndCapture(cmd, args2, opts = {}) {
|
|
9437
9460
|
const timeoutMs = opts.timeoutMs ?? 6e4;
|
|
9438
|
-
return new Promise((
|
|
9461
|
+
return new Promise((resolve7) => {
|
|
9439
9462
|
let settled = false;
|
|
9440
9463
|
const settle = (value) => {
|
|
9441
9464
|
if (settled) return;
|
|
9442
9465
|
settled = true;
|
|
9443
|
-
|
|
9466
|
+
resolve7(value);
|
|
9444
9467
|
};
|
|
9445
9468
|
let child;
|
|
9446
9469
|
try {
|
|
@@ -9947,13 +9970,13 @@ function detectStartupBanner(lines) {
|
|
|
9947
9970
|
while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
|
|
9948
9971
|
if (metaIdx - artStart < 2) return null;
|
|
9949
9972
|
const pathLine = (lines[metaIdx + 1] ?? "").trim();
|
|
9950
|
-
const
|
|
9973
|
+
const path50 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
|
|
9951
9974
|
return {
|
|
9952
9975
|
title: "",
|
|
9953
9976
|
subtitle: lines[metaIdx].trim(),
|
|
9954
|
-
path:
|
|
9977
|
+
path: path50,
|
|
9955
9978
|
startIdx: artStart,
|
|
9956
|
-
endIdx: metaIdx + (
|
|
9979
|
+
endIdx: metaIdx + (path50 ? 1 : 0)
|
|
9957
9980
|
};
|
|
9958
9981
|
}
|
|
9959
9982
|
|
|
@@ -9963,8 +9986,8 @@ var ClaudeRuntimeStrategy = class {
|
|
|
9963
9986
|
meta = getAgent("claude");
|
|
9964
9987
|
mode = "interactive";
|
|
9965
9988
|
os;
|
|
9966
|
-
constructor(
|
|
9967
|
-
this.os =
|
|
9989
|
+
constructor(os30) {
|
|
9990
|
+
this.os = os30;
|
|
9968
9991
|
}
|
|
9969
9992
|
/**
|
|
9970
9993
|
* Claude Code's react-ink TUI enables bracketed-paste mode at
|
|
@@ -10972,8 +10995,8 @@ function codexCredentialLocator() {
|
|
|
10972
10995
|
function codexLoginLauncher() {
|
|
10973
10996
|
return {
|
|
10974
10997
|
async ensureInstalled() {
|
|
10975
|
-
const
|
|
10976
|
-
return
|
|
10998
|
+
const os30 = createOsStrategy();
|
|
10999
|
+
return os30.findInPath("codex") !== null;
|
|
10977
11000
|
},
|
|
10978
11001
|
launch() {
|
|
10979
11002
|
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
@@ -10996,8 +11019,8 @@ var CodexRuntimeStrategy = class {
|
|
|
10996
11019
|
meta = getAgent("codex");
|
|
10997
11020
|
mode = "interactive";
|
|
10998
11021
|
os;
|
|
10999
|
-
constructor(
|
|
11000
|
-
this.os =
|
|
11022
|
+
constructor(os30) {
|
|
11023
|
+
this.os = os30;
|
|
11001
11024
|
}
|
|
11002
11025
|
async prepareLaunch() {
|
|
11003
11026
|
let binary = this.os.findInPath("codex");
|
|
@@ -11103,16 +11126,16 @@ var CodexRuntimeStrategy = class {
|
|
|
11103
11126
|
});
|
|
11104
11127
|
}
|
|
11105
11128
|
};
|
|
11106
|
-
function resolveNpm(
|
|
11107
|
-
return
|
|
11129
|
+
function resolveNpm(os30) {
|
|
11130
|
+
return os30.id === "win32" ? "npm.cmd" : "npm";
|
|
11108
11131
|
}
|
|
11109
|
-
async function installCodexViaNpm(
|
|
11110
|
-
return new Promise((
|
|
11111
|
-
const proc = (0, import_node_child_process4.spawn)(resolveNpm(
|
|
11132
|
+
async function installCodexViaNpm(os30) {
|
|
11133
|
+
return new Promise((resolve7, reject) => {
|
|
11134
|
+
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os30), ["install", "-g", "@openai/codex"], {
|
|
11112
11135
|
stdio: "inherit"
|
|
11113
11136
|
});
|
|
11114
11137
|
proc.on("close", (code) => {
|
|
11115
|
-
if (code === 0)
|
|
11138
|
+
if (code === 0) resolve7();
|
|
11116
11139
|
else reject(new Error(`npm install -g @openai/codex exited ${code}`));
|
|
11117
11140
|
});
|
|
11118
11141
|
proc.on("error", (err) => {
|
|
@@ -11125,16 +11148,16 @@ async function installCodexViaNpm(os29) {
|
|
|
11125
11148
|
});
|
|
11126
11149
|
});
|
|
11127
11150
|
}
|
|
11128
|
-
function augmentNpmGlobalBin(
|
|
11151
|
+
function augmentNpmGlobalBin(os30) {
|
|
11129
11152
|
try {
|
|
11130
|
-
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(
|
|
11153
|
+
const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os30), ["prefix", "-g"], {
|
|
11131
11154
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11132
11155
|
});
|
|
11133
11156
|
if (result.status !== 0) return;
|
|
11134
11157
|
const prefix = result.stdout.toString().trim();
|
|
11135
11158
|
if (!prefix) return;
|
|
11136
|
-
const binDir =
|
|
11137
|
-
|
|
11159
|
+
const binDir = os30.id === "win32" ? prefix : path17.join(prefix, "bin");
|
|
11160
|
+
os30.augmentPath([binDir]);
|
|
11138
11161
|
} catch {
|
|
11139
11162
|
}
|
|
11140
11163
|
}
|
|
@@ -11218,25 +11241,25 @@ var import_node_child_process7 = require("child_process");
|
|
|
11218
11241
|
// src/agents/coderabbit/installer.ts
|
|
11219
11242
|
var import_node_child_process5 = require("child_process");
|
|
11220
11243
|
var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
|
|
11221
|
-
async function ensureCoderabbitInstalled(
|
|
11222
|
-
if (
|
|
11223
|
-
if (
|
|
11244
|
+
async function ensureCoderabbitInstalled(os30) {
|
|
11245
|
+
if (os30.findInPath("coderabbit")) return true;
|
|
11246
|
+
if (os30.id === "win32") {
|
|
11224
11247
|
console.error(
|
|
11225
11248
|
"\n \u2717 CodeRabbit on Windows requires WSL.\n Install the CLI inside your WSL distribution\n (curl -fsSL https://cli.coderabbit.ai/install.sh | sh)\n then re-run `codeam link coderabbit` from WSL.\n"
|
|
11226
11249
|
);
|
|
11227
11250
|
return false;
|
|
11228
11251
|
}
|
|
11229
11252
|
console.log("\n CodeRabbit CLI not found \u2014 installing via the official script\u2026\n");
|
|
11230
|
-
const ok = await new Promise((
|
|
11253
|
+
const ok = await new Promise((resolve7) => {
|
|
11231
11254
|
const proc = (0, import_node_child_process5.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL} | sh`], {
|
|
11232
11255
|
stdio: "inherit"
|
|
11233
11256
|
});
|
|
11234
|
-
proc.on("close", (code) =>
|
|
11235
|
-
proc.on("error", () =>
|
|
11257
|
+
proc.on("close", (code) => resolve7(code === 0));
|
|
11258
|
+
proc.on("error", () => resolve7(false));
|
|
11236
11259
|
});
|
|
11237
11260
|
if (!ok) return false;
|
|
11238
|
-
|
|
11239
|
-
return
|
|
11261
|
+
os30.augmentPath([`${os30.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
11262
|
+
return os30.findInPath("coderabbit") !== null;
|
|
11240
11263
|
}
|
|
11241
11264
|
|
|
11242
11265
|
// src/agents/coderabbit/link.ts
|
|
@@ -11263,10 +11286,10 @@ function coderabbitCredentialLocator() {
|
|
|
11263
11286
|
extract: extractLocalCoderabbitToken
|
|
11264
11287
|
};
|
|
11265
11288
|
}
|
|
11266
|
-
function coderabbitLoginLauncher(
|
|
11289
|
+
function coderabbitLoginLauncher(os30) {
|
|
11267
11290
|
return {
|
|
11268
11291
|
async ensureInstalled() {
|
|
11269
|
-
return ensureCoderabbitInstalled(
|
|
11292
|
+
return ensureCoderabbitInstalled(os30);
|
|
11270
11293
|
},
|
|
11271
11294
|
launch() {
|
|
11272
11295
|
return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
|
|
@@ -11289,11 +11312,11 @@ function parseReview(stdout) {
|
|
|
11289
11312
|
for (const line of lines) {
|
|
11290
11313
|
const m = line.match(HUNK_LINE_RE);
|
|
11291
11314
|
if (!m) continue;
|
|
11292
|
-
const [,
|
|
11293
|
-
if (!
|
|
11315
|
+
const [, path50, lineNo, sevToken, message] = m;
|
|
11316
|
+
if (!path50 || !lineNo || !message) continue;
|
|
11294
11317
|
const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
|
|
11295
11318
|
hunks.push({
|
|
11296
|
-
path:
|
|
11319
|
+
path: path50.trim(),
|
|
11297
11320
|
line: Number(lineNo),
|
|
11298
11321
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
11299
11322
|
message: cleanedMessage
|
|
@@ -11312,8 +11335,8 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
11312
11335
|
meta = getAgent("coderabbit");
|
|
11313
11336
|
mode = "batch";
|
|
11314
11337
|
os;
|
|
11315
|
-
constructor(
|
|
11316
|
-
this.os =
|
|
11338
|
+
constructor(os30) {
|
|
11339
|
+
this.os = os30;
|
|
11317
11340
|
}
|
|
11318
11341
|
getDefaultArgs() {
|
|
11319
11342
|
return ["review"];
|
|
@@ -11351,7 +11374,7 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
11351
11374
|
}
|
|
11352
11375
|
async runOneShot(input) {
|
|
11353
11376
|
const launch = await this.prepareInvocation(input);
|
|
11354
|
-
return new Promise((
|
|
11377
|
+
return new Promise((resolve7, reject) => {
|
|
11355
11378
|
const stdoutBuf = [];
|
|
11356
11379
|
const stderrBuf = [];
|
|
11357
11380
|
const proc = (0, import_node_child_process7.spawn)(launch.cmd, launch.args, {
|
|
@@ -11362,7 +11385,7 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
11362
11385
|
proc.stderr?.on("data", (b) => stderrBuf.push(b));
|
|
11363
11386
|
proc.on("error", (err) => reject(err));
|
|
11364
11387
|
proc.on("close", (code) => {
|
|
11365
|
-
|
|
11388
|
+
resolve7(
|
|
11366
11389
|
this.parseOutput({
|
|
11367
11390
|
exitCode: code ?? 0,
|
|
11368
11391
|
stdout: Buffer.concat(stdoutBuf).toString("utf8"),
|
|
@@ -11428,10 +11451,10 @@ function cursorCredentialLocator() {
|
|
|
11428
11451
|
extract: extractLocalCursorToken
|
|
11429
11452
|
};
|
|
11430
11453
|
}
|
|
11431
|
-
function cursorLoginLauncher(
|
|
11454
|
+
function cursorLoginLauncher(os30) {
|
|
11432
11455
|
return {
|
|
11433
11456
|
async ensureInstalled() {
|
|
11434
|
-
if (
|
|
11457
|
+
if (os30.findInPath("cursor-agent")) return true;
|
|
11435
11458
|
console.error(
|
|
11436
11459
|
"\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"
|
|
11437
11460
|
);
|
|
@@ -11493,8 +11516,8 @@ var CursorRuntimeStrategy = class {
|
|
|
11493
11516
|
meta = getAgent("cursor");
|
|
11494
11517
|
mode = "interactive";
|
|
11495
11518
|
os;
|
|
11496
|
-
constructor(
|
|
11497
|
-
this.os =
|
|
11519
|
+
constructor(os30) {
|
|
11520
|
+
this.os = os30;
|
|
11498
11521
|
}
|
|
11499
11522
|
async prepareLaunch() {
|
|
11500
11523
|
const binary = this.os.findInPath("cursor-agent");
|
|
@@ -11614,10 +11637,10 @@ function aiderCredentialLocator() {
|
|
|
11614
11637
|
extract: extractLocalAiderToken
|
|
11615
11638
|
};
|
|
11616
11639
|
}
|
|
11617
|
-
function aiderLoginLauncher(
|
|
11640
|
+
function aiderLoginLauncher(os30) {
|
|
11618
11641
|
return {
|
|
11619
11642
|
async ensureInstalled() {
|
|
11620
|
-
if (
|
|
11643
|
+
if (os30.findInPath("aider")) return true;
|
|
11621
11644
|
console.error(
|
|
11622
11645
|
"\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
|
|
11623
11646
|
);
|
|
@@ -11627,7 +11650,7 @@ function aiderLoginLauncher(os29) {
|
|
|
11627
11650
|
console.error(
|
|
11628
11651
|
"\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"
|
|
11629
11652
|
);
|
|
11630
|
-
return (0, import_node_child_process9.spawn)(
|
|
11653
|
+
return (0, import_node_child_process9.spawn)(os30.id === "win32" ? "cmd.exe" : "sh", os30.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
|
|
11631
11654
|
stdio: "ignore"
|
|
11632
11655
|
});
|
|
11633
11656
|
}
|
|
@@ -11699,8 +11722,8 @@ var AiderRuntimeStrategy = class {
|
|
|
11699
11722
|
meta = getAgent("aider");
|
|
11700
11723
|
mode = "interactive";
|
|
11701
11724
|
os;
|
|
11702
|
-
constructor(
|
|
11703
|
-
this.os =
|
|
11725
|
+
constructor(os30) {
|
|
11726
|
+
this.os = os30;
|
|
11704
11727
|
}
|
|
11705
11728
|
async prepareLaunch() {
|
|
11706
11729
|
const binary = this.os.findInPath("aider");
|
|
@@ -11829,8 +11852,8 @@ function geminiCredentialLocator() {
|
|
|
11829
11852
|
function geminiLoginLauncher() {
|
|
11830
11853
|
return {
|
|
11831
11854
|
async ensureInstalled() {
|
|
11832
|
-
const
|
|
11833
|
-
return
|
|
11855
|
+
const os30 = createOsStrategy();
|
|
11856
|
+
return os30.findInPath("gemini") !== null;
|
|
11834
11857
|
},
|
|
11835
11858
|
launch() {
|
|
11836
11859
|
return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
@@ -11863,8 +11886,8 @@ var GeminiRuntimeStrategy = class {
|
|
|
11863
11886
|
meta = getAgent("gemini");
|
|
11864
11887
|
mode = "interactive";
|
|
11865
11888
|
os;
|
|
11866
|
-
constructor(
|
|
11867
|
-
this.os =
|
|
11889
|
+
constructor(os30) {
|
|
11890
|
+
this.os = os30;
|
|
11868
11891
|
}
|
|
11869
11892
|
async prepareLaunch() {
|
|
11870
11893
|
const binary = this.os.findInPath("gemini");
|
|
@@ -11964,18 +11987,18 @@ var GeminiRuntimeStrategy = class {
|
|
|
11964
11987
|
|
|
11965
11988
|
// src/agents/registry.ts
|
|
11966
11989
|
var runtimeBuilders = {
|
|
11967
|
-
claude: (
|
|
11968
|
-
codex: (
|
|
11969
|
-
coderabbit: (
|
|
11970
|
-
cursor: (
|
|
11971
|
-
aider: (
|
|
11972
|
-
gemini: (
|
|
11990
|
+
claude: (os30) => new ClaudeRuntimeStrategy(os30),
|
|
11991
|
+
codex: (os30) => new CodexRuntimeStrategy(os30),
|
|
11992
|
+
coderabbit: (os30) => new CoderabbitRuntimeStrategy(os30),
|
|
11993
|
+
cursor: (os30) => new CursorRuntimeStrategy(os30),
|
|
11994
|
+
aider: (os30) => new AiderRuntimeStrategy(os30),
|
|
11995
|
+
gemini: (os30) => new GeminiRuntimeStrategy(os30)
|
|
11973
11996
|
};
|
|
11974
11997
|
var deployBuilders = {
|
|
11975
11998
|
claude: () => new ClaudeDeployStrategy(),
|
|
11976
11999
|
codex: () => new CodexDeployStrategy()
|
|
11977
12000
|
};
|
|
11978
|
-
function createAgentStrategy(agent,
|
|
12001
|
+
function createAgentStrategy(agent, os30 = createOsStrategy()) {
|
|
11979
12002
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
11980
12003
|
throw new Error(
|
|
11981
12004
|
`Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
|
|
@@ -11985,10 +12008,10 @@ function createAgentStrategy(agent, os29 = createOsStrategy()) {
|
|
|
11985
12008
|
if (!build) {
|
|
11986
12009
|
throw new Error(`No runtime strategy registered for agent "${agent}"`);
|
|
11987
12010
|
}
|
|
11988
|
-
return build(
|
|
12011
|
+
return build(os30);
|
|
11989
12012
|
}
|
|
11990
|
-
function createInteractiveAgentStrategy(agent,
|
|
11991
|
-
const s = createAgentStrategy(agent,
|
|
12013
|
+
function createInteractiveAgentStrategy(agent, os30 = createOsStrategy()) {
|
|
12014
|
+
const s = createAgentStrategy(agent, os30);
|
|
11992
12015
|
if (s.mode !== "interactive") {
|
|
11993
12016
|
throw new Error(
|
|
11994
12017
|
`Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
|
|
@@ -14268,8 +14291,8 @@ var Connection = class {
|
|
|
14268
14291
|
this.requestHandler = requestHandler;
|
|
14269
14292
|
this.notificationHandler = notificationHandler;
|
|
14270
14293
|
this.stream = stream;
|
|
14271
|
-
this.closedPromise = new Promise((
|
|
14272
|
-
this.abortController.signal.addEventListener("abort", () =>
|
|
14294
|
+
this.closedPromise = new Promise((resolve7) => {
|
|
14295
|
+
this.abortController.signal.addEventListener("abort", () => resolve7());
|
|
14273
14296
|
});
|
|
14274
14297
|
void this.receive();
|
|
14275
14298
|
}
|
|
@@ -14439,11 +14462,11 @@ var Connection = class {
|
|
|
14439
14462
|
return rejectedPromise(this.closedReason());
|
|
14440
14463
|
}
|
|
14441
14464
|
const id = this.nextRequestId++;
|
|
14442
|
-
const responsePromise = new Promise((
|
|
14465
|
+
const responsePromise = new Promise((resolve7, reject) => {
|
|
14443
14466
|
this.pendingResponses.set(id, {
|
|
14444
14467
|
resolve: (response) => {
|
|
14445
14468
|
try {
|
|
14446
|
-
|
|
14469
|
+
resolve7(mapResponse ? mapResponse(response) : response);
|
|
14447
14470
|
} catch (error) {
|
|
14448
14471
|
reject(error);
|
|
14449
14472
|
}
|
|
@@ -14764,17 +14787,17 @@ var AcpClient = class {
|
|
|
14764
14787
|
this.sessionId = null;
|
|
14765
14788
|
try {
|
|
14766
14789
|
child.kill("SIGTERM");
|
|
14767
|
-
const grace = new Promise((
|
|
14790
|
+
const grace = new Promise((resolve7) => {
|
|
14768
14791
|
const t2 = setTimeout(() => {
|
|
14769
14792
|
try {
|
|
14770
14793
|
child.kill("SIGKILL");
|
|
14771
14794
|
} catch {
|
|
14772
14795
|
}
|
|
14773
|
-
|
|
14796
|
+
resolve7();
|
|
14774
14797
|
}, 2e3);
|
|
14775
14798
|
child.once("exit", () => {
|
|
14776
14799
|
clearTimeout(t2);
|
|
14777
|
-
|
|
14800
|
+
resolve7();
|
|
14778
14801
|
});
|
|
14779
14802
|
});
|
|
14780
14803
|
await grace;
|
|
@@ -14912,7 +14935,7 @@ var _transport2 = {
|
|
|
14912
14935
|
get: _get
|
|
14913
14936
|
};
|
|
14914
14937
|
function _post(url, headers, payload) {
|
|
14915
|
-
return new Promise((
|
|
14938
|
+
return new Promise((resolve7, reject) => {
|
|
14916
14939
|
let settled = false;
|
|
14917
14940
|
const u2 = new URL(url);
|
|
14918
14941
|
const lib = u2.protocol === "https:" ? https3 : http3;
|
|
@@ -14937,7 +14960,7 @@ function _post(url, headers, payload) {
|
|
|
14937
14960
|
res.on("end", () => {
|
|
14938
14961
|
if (settled) return;
|
|
14939
14962
|
settled = true;
|
|
14940
|
-
|
|
14963
|
+
resolve7({ statusCode: res.statusCode ?? 0, body });
|
|
14941
14964
|
});
|
|
14942
14965
|
}
|
|
14943
14966
|
);
|
|
@@ -14954,7 +14977,7 @@ function _post(url, headers, payload) {
|
|
|
14954
14977
|
});
|
|
14955
14978
|
}
|
|
14956
14979
|
function _get(url, headers) {
|
|
14957
|
-
return new Promise((
|
|
14980
|
+
return new Promise((resolve7, reject) => {
|
|
14958
14981
|
let settled = false;
|
|
14959
14982
|
const u2 = new URL(url);
|
|
14960
14983
|
const lib = u2.protocol === "https:" ? https3 : http3;
|
|
@@ -14978,7 +15001,7 @@ function _get(url, headers) {
|
|
|
14978
15001
|
res.on("end", () => {
|
|
14979
15002
|
if (settled) return;
|
|
14980
15003
|
settled = true;
|
|
14981
|
-
|
|
15004
|
+
resolve7({ statusCode: res.statusCode ?? 0, body });
|
|
14982
15005
|
});
|
|
14983
15006
|
}
|
|
14984
15007
|
);
|
|
@@ -15687,11 +15710,11 @@ function extractSelectPrompt(text) {
|
|
|
15687
15710
|
}
|
|
15688
15711
|
|
|
15689
15712
|
// src/commands/start/handlers.ts
|
|
15690
|
-
var
|
|
15691
|
-
var
|
|
15692
|
-
var
|
|
15713
|
+
var fs32 = __toESM(require("fs"));
|
|
15714
|
+
var os25 = __toESM(require("os"));
|
|
15715
|
+
var path39 = __toESM(require("path"));
|
|
15693
15716
|
var import_crypto3 = require("crypto");
|
|
15694
|
-
var
|
|
15717
|
+
var import_child_process15 = require("child_process");
|
|
15695
15718
|
|
|
15696
15719
|
// src/lib/payload.ts
|
|
15697
15720
|
var import_zod = require("zod");
|
|
@@ -16344,12 +16367,12 @@ async function applyFileReview(workingDir, filePath, action) {
|
|
|
16344
16367
|
return { ok: true, action, filePath, repoRoot };
|
|
16345
16368
|
}
|
|
16346
16369
|
function runGit(cwd, args2) {
|
|
16347
|
-
return new Promise((
|
|
16370
|
+
return new Promise((resolve7) => {
|
|
16348
16371
|
let proc;
|
|
16349
16372
|
try {
|
|
16350
16373
|
proc = (0, import_child_process10.spawn)("git", args2, { cwd, env: process.env });
|
|
16351
16374
|
} catch (err) {
|
|
16352
|
-
|
|
16375
|
+
resolve7({ ok: false, code: -1, stdout: "", stderr: err.message });
|
|
16353
16376
|
return;
|
|
16354
16377
|
}
|
|
16355
16378
|
let stdout = "";
|
|
@@ -16362,11 +16385,11 @@ function runGit(cwd, args2) {
|
|
|
16362
16385
|
});
|
|
16363
16386
|
proc.on(
|
|
16364
16387
|
"error",
|
|
16365
|
-
(err) =>
|
|
16388
|
+
(err) => resolve7({ ok: false, code: -1, stdout, stderr: stderr + err.message })
|
|
16366
16389
|
);
|
|
16367
16390
|
proc.on(
|
|
16368
16391
|
"close",
|
|
16369
|
-
(code) =>
|
|
16392
|
+
(code) => resolve7({ ok: code === 0, code: code ?? -1, stdout, stderr })
|
|
16370
16393
|
);
|
|
16371
16394
|
});
|
|
16372
16395
|
}
|
|
@@ -16625,7 +16648,7 @@ async function link(args2 = []) {
|
|
|
16625
16648
|
waitSpin.start(waitMsg());
|
|
16626
16649
|
const countdown = setInterval(() => waitSpin.message(waitMsg()), 1e3);
|
|
16627
16650
|
countdown.unref?.();
|
|
16628
|
-
const paired = await new Promise((
|
|
16651
|
+
const paired = await new Promise((resolve7, reject) => {
|
|
16629
16652
|
let stopPoll = null;
|
|
16630
16653
|
const sigint = () => {
|
|
16631
16654
|
clearInterval(countdown);
|
|
@@ -16638,7 +16661,7 @@ async function link(args2 = []) {
|
|
|
16638
16661
|
process.removeListener("SIGINT", sigint);
|
|
16639
16662
|
clearInterval(countdown);
|
|
16640
16663
|
waitSpin.stop("Paired");
|
|
16641
|
-
|
|
16664
|
+
resolve7(info);
|
|
16642
16665
|
},
|
|
16643
16666
|
() => {
|
|
16644
16667
|
clearInterval(countdown);
|
|
@@ -16773,14 +16796,14 @@ async function captureFreshCredentials(ctx) {
|
|
|
16773
16796
|
}
|
|
16774
16797
|
};
|
|
16775
16798
|
try {
|
|
16776
|
-
const token = await new Promise((
|
|
16799
|
+
const token = await new Promise((resolve7, reject) => {
|
|
16777
16800
|
let settled = false;
|
|
16778
16801
|
const tryExtract = async () => {
|
|
16779
16802
|
if (settled) return;
|
|
16780
16803
|
const t2 = await ctx.locator.extract();
|
|
16781
16804
|
if (t2 && !settled) {
|
|
16782
16805
|
settled = true;
|
|
16783
|
-
|
|
16806
|
+
resolve7(t2);
|
|
16784
16807
|
}
|
|
16785
16808
|
};
|
|
16786
16809
|
watcher.on("add", () => void tryExtract());
|
|
@@ -17178,167 +17201,938 @@ function activePreviewSessionIds() {
|
|
|
17178
17201
|
return Array.from(activePreviews.keys());
|
|
17179
17202
|
}
|
|
17180
17203
|
|
|
17181
|
-
// src/
|
|
17182
|
-
var
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
}
|
|
17190
|
-
pendingAttachmentFiles.clear();
|
|
17204
|
+
// src/beads/bd-adapter.ts
|
|
17205
|
+
var import_child_process12 = require("child_process");
|
|
17206
|
+
var fs29 = __toESM(require("fs"));
|
|
17207
|
+
var os24 = __toESM(require("os"));
|
|
17208
|
+
var path35 = __toESM(require("path"));
|
|
17209
|
+
var BD_PACKAGE = "@beads/bd";
|
|
17210
|
+
function resolveBundledBdBinary() {
|
|
17211
|
+
return _resolveSeam.resolveBundled();
|
|
17191
17212
|
}
|
|
17192
|
-
function
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
|
|
17198
|
-
|
|
17199
|
-
|
|
17213
|
+
function _defaultResolveBundled() {
|
|
17214
|
+
let pkgJsonPath;
|
|
17215
|
+
try {
|
|
17216
|
+
pkgJsonPath = require.resolve(`${BD_PACKAGE}/package.json`);
|
|
17217
|
+
} catch {
|
|
17218
|
+
return null;
|
|
17219
|
+
}
|
|
17220
|
+
const binDir = path35.join(path35.dirname(pkgJsonPath), "bin");
|
|
17221
|
+
const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
|
|
17222
|
+
const binaryPath = path35.join(binDir, binaryName);
|
|
17223
|
+
try {
|
|
17224
|
+
fs29.accessSync(binaryPath, fs29.constants.F_OK);
|
|
17225
|
+
return binaryPath;
|
|
17226
|
+
} catch {
|
|
17227
|
+
return null;
|
|
17228
|
+
}
|
|
17200
17229
|
}
|
|
17201
|
-
function
|
|
17202
|
-
|
|
17203
|
-
ctx.agent.sendCommand(prompt);
|
|
17230
|
+
function resolveBdOnPath() {
|
|
17231
|
+
return _resolveSeam.resolveOnPath();
|
|
17204
17232
|
}
|
|
17205
|
-
|
|
17206
|
-
const
|
|
17207
|
-
const
|
|
17208
|
-
|
|
17209
|
-
const
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17213
|
-
|
|
17214
|
-
|
|
17215
|
-
try {
|
|
17216
|
-
fs29.unlinkSync(p2);
|
|
17217
|
-
} catch {
|
|
17218
|
-
}
|
|
17219
|
-
pendingAttachmentFiles.delete(p2);
|
|
17233
|
+
function _defaultResolveOnPath() {
|
|
17234
|
+
const dirs = (process.env.PATH ?? "").split(path35.delimiter).filter(Boolean);
|
|
17235
|
+
const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
|
|
17236
|
+
for (const dir of dirs) {
|
|
17237
|
+
for (const candidate of candidates) {
|
|
17238
|
+
const full = path35.join(dir, candidate);
|
|
17239
|
+
try {
|
|
17240
|
+
fs29.accessSync(full, fs29.constants.F_OK);
|
|
17241
|
+
return full;
|
|
17242
|
+
} catch {
|
|
17220
17243
|
}
|
|
17221
|
-
}
|
|
17222
|
-
} else if (effectivePrompt) {
|
|
17223
|
-
dispatchPrompt(ctx, effectivePrompt);
|
|
17244
|
+
}
|
|
17224
17245
|
}
|
|
17246
|
+
return null;
|
|
17247
|
+
}
|
|
17248
|
+
var _resolveSeam = {
|
|
17249
|
+
resolveBundled: _defaultResolveBundled,
|
|
17250
|
+
resolveOnPath: _defaultResolveOnPath
|
|
17225
17251
|
};
|
|
17226
|
-
var
|
|
17227
|
-
|
|
17228
|
-
};
|
|
17229
|
-
var selectOption = (ctx, _cmd, parsed) => {
|
|
17230
|
-
const index = parsed.index ?? 0;
|
|
17231
|
-
const from = parsed.from ?? 0;
|
|
17232
|
-
ctx.outputSvc.newTurn();
|
|
17233
|
-
ctx.agent.selectOption(index, from);
|
|
17234
|
-
};
|
|
17235
|
-
var escapeKey = (ctx) => {
|
|
17236
|
-
ctx.outputSvc.newTurn();
|
|
17237
|
-
ctx.agent.sendEscape();
|
|
17238
|
-
};
|
|
17239
|
-
var stopTask = (ctx) => {
|
|
17240
|
-
ctx.agent.interrupt();
|
|
17241
|
-
};
|
|
17242
|
-
var resumeSession = async (ctx, _cmd, parsed) => {
|
|
17243
|
-
const { id, auto } = parsed;
|
|
17244
|
-
if (!id) return;
|
|
17245
|
-
ctx.historySvc.setCurrentConversationId(id);
|
|
17246
|
-
await ctx.historySvc.loadConversation(id);
|
|
17247
|
-
await ctx.outputSvc.newTurnResume(id);
|
|
17248
|
-
ctx.agent.restart(id, auto ?? false);
|
|
17249
|
-
};
|
|
17250
|
-
var getContext = async (ctx, cmd) => {
|
|
17251
|
-
const usage = ctx.historySvc.getCurrentUsage();
|
|
17252
|
-
const monthlyCost = ctx.historySvc.getMonthlyEstimatedCost();
|
|
17253
|
-
const rateLimitReset = ctx.historySvc.getRateLimitReset();
|
|
17254
|
-
const quotaPercent = ctx.historySvc.getQuotaPercent();
|
|
17255
|
-
const base = usage ? { ...usage, monthlyCost } : { used: 0, total: 2e5, percent: 0, model: null, outputTokens: 0, cacheReadTokens: 0, monthlyCost, error: "No usage data found" };
|
|
17256
|
-
const result = {
|
|
17257
|
-
...base,
|
|
17258
|
-
...rateLimitReset ? { rateLimitReset } : {},
|
|
17259
|
-
...quotaPercent !== null ? { quotaPercent } : {}
|
|
17260
|
-
};
|
|
17261
|
-
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
17252
|
+
var _spawnSeam = {
|
|
17253
|
+
run: _defaultSpawn
|
|
17262
17254
|
};
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17255
|
+
function _defaultSpawn(binaryPath, args2, opts) {
|
|
17256
|
+
return new Promise((resolve7) => {
|
|
17257
|
+
let proc;
|
|
17258
|
+
try {
|
|
17259
|
+
proc = (0, import_child_process12.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
|
|
17260
|
+
} catch (err) {
|
|
17261
|
+
resolve7({ code: -1, stdout: "", stderr: err.message });
|
|
17262
|
+
return;
|
|
17263
|
+
}
|
|
17264
|
+
let stdout = "";
|
|
17265
|
+
let stderr = "";
|
|
17266
|
+
proc.stdout?.on("data", (c2) => {
|
|
17267
|
+
stdout += c2.toString();
|
|
17268
|
+
});
|
|
17269
|
+
proc.stderr?.on("data", (c2) => {
|
|
17270
|
+
stderr += c2.toString();
|
|
17271
|
+
});
|
|
17272
|
+
proc.on("error", (err) => resolve7({ code: -1, stdout, stderr: err.message }));
|
|
17273
|
+
proc.on("close", (code) => resolve7({ code: code ?? -1, stdout, stderr }));
|
|
17274
|
+
});
|
|
17275
|
+
}
|
|
17276
|
+
var BdAdapter = class {
|
|
17277
|
+
constructor(opts = {}) {
|
|
17278
|
+
this.opts = opts;
|
|
17279
|
+
this.resolved = opts.binaryPath ?? null;
|
|
17268
17280
|
}
|
|
17269
|
-
|
|
17270
|
-
|
|
17271
|
-
|
|
17281
|
+
opts;
|
|
17282
|
+
resolved;
|
|
17283
|
+
/**
|
|
17284
|
+
* Resolve the bd binary lazily, caching the result. Order:
|
|
17285
|
+
* bundled @beads/bd → PATH. Returns null when neither is available — the
|
|
17286
|
+
* caller offers the consented installer (`install-bd.ts`).
|
|
17287
|
+
*/
|
|
17288
|
+
resolveBinary() {
|
|
17289
|
+
if (this.resolved) return this.resolved;
|
|
17290
|
+
const bundled = resolveBundledBdBinary();
|
|
17291
|
+
if (bundled) {
|
|
17292
|
+
this.resolved = bundled;
|
|
17293
|
+
return bundled;
|
|
17294
|
+
}
|
|
17295
|
+
const onPath = resolveBdOnPath();
|
|
17296
|
+
if (onPath) {
|
|
17297
|
+
this.resolved = onPath;
|
|
17298
|
+
return onPath;
|
|
17299
|
+
}
|
|
17300
|
+
return null;
|
|
17272
17301
|
}
|
|
17273
|
-
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
} catch {
|
|
17277
|
-
await ctx.relay.sendResult(cmd.id, "failed", {});
|
|
17302
|
+
/** True when a bd binary is resolvable without installing. */
|
|
17303
|
+
isAvailable() {
|
|
17304
|
+
return this.resolveBinary() !== null;
|
|
17278
17305
|
}
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
|
|
17284
|
-
|
|
17285
|
-
|
|
17286
|
-
|
|
17287
|
-
|
|
17288
|
-
|
|
17306
|
+
/**
|
|
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.
|
|
17313
|
+
*/
|
|
17314
|
+
async run(args2) {
|
|
17315
|
+
const binary = this.resolveBinary();
|
|
17316
|
+
if (!binary) {
|
|
17317
|
+
return { code: -1, stdout: "", stderr: "bd binary not resolved" };
|
|
17318
|
+
}
|
|
17319
|
+
const env = { ...process.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 });
|
|
17289
17323
|
}
|
|
17290
|
-
|
|
17291
|
-
|
|
17292
|
-
|
|
17293
|
-
|
|
17294
|
-
|
|
17324
|
+
/**
|
|
17325
|
+
* `bd ready --json` → typed issue array. `bd list --json` shares the shape,
|
|
17326
|
+
* so `listIssues` reuses the same parser. Bad JSON / non-zero exit → [].
|
|
17327
|
+
*/
|
|
17328
|
+
async readyIssues(projectKey) {
|
|
17329
|
+
const res = await this.run(["ready", "--json"]);
|
|
17330
|
+
return parseIssues(res, projectKey);
|
|
17331
|
+
}
|
|
17332
|
+
async listIssues(projectKey) {
|
|
17333
|
+
const res = await this.run(["list", "--json"]);
|
|
17334
|
+
return parseIssues(res, projectKey);
|
|
17335
|
+
}
|
|
17336
|
+
/** `bd status --json` → summary block, or null on failure. */
|
|
17337
|
+
async statusSummary() {
|
|
17338
|
+
const res = await this.run(["status", "--json"]);
|
|
17339
|
+
if (res.code !== 0) return null;
|
|
17340
|
+
try {
|
|
17341
|
+
const parsed = JSON.parse(res.stdout);
|
|
17342
|
+
return parsed.summary ?? null;
|
|
17343
|
+
} catch {
|
|
17344
|
+
return null;
|
|
17295
17345
|
}
|
|
17296
|
-
ctx.agent.sendRawPtyInput(instr.ptyInput);
|
|
17297
|
-
} else if (instr.type === "restart") {
|
|
17298
|
-
await ctx.relay.sendResult(cmd.id, "failed", { error: "restart-mode change_model not supported in Phase 1" });
|
|
17299
|
-
return;
|
|
17300
17346
|
}
|
|
17301
|
-
await ctx.relay.sendResult(cmd.id, "completed", {});
|
|
17302
|
-
};
|
|
17303
|
-
var summarize = async (ctx, cmd) => {
|
|
17304
|
-
const params = cmd.payload;
|
|
17305
|
-
const mode = params.mode === "auto" ? "auto" : "normal";
|
|
17306
|
-
const instr = ctx.runtime.summarizeInstruction(mode);
|
|
17307
|
-
ctx.agent.sendRawPtyInput(instr.ptyInput);
|
|
17308
|
-
await ctx.relay.sendResult(cmd.id, "completed", {});
|
|
17309
17347
|
};
|
|
17310
|
-
var
|
|
17311
|
-
|
|
17312
|
-
|
|
17348
|
+
var VALID_STATUS = /* @__PURE__ */ new Set([
|
|
17349
|
+
"open",
|
|
17350
|
+
"in_progress",
|
|
17351
|
+
"blocked",
|
|
17352
|
+
"closed"
|
|
17353
|
+
]);
|
|
17354
|
+
function parseIssues(res, projectKey) {
|
|
17355
|
+
if (res.code !== 0) return [];
|
|
17356
|
+
let parsed;
|
|
17313
17357
|
try {
|
|
17314
|
-
|
|
17315
|
-
cmd.id,
|
|
17316
|
-
"success",
|
|
17317
|
-
{
|
|
17318
|
-
enabled,
|
|
17319
|
-
applied: enabled && ctx.keepAliveCtx.inCodespace,
|
|
17320
|
-
runtime: ctx.keepAliveCtx.inCodespace ? "github-codespaces" : "local"
|
|
17321
|
-
}
|
|
17322
|
-
);
|
|
17358
|
+
parsed = JSON.parse(res.stdout);
|
|
17323
17359
|
} catch {
|
|
17360
|
+
return [];
|
|
17324
17361
|
}
|
|
17325
|
-
|
|
17326
|
-
|
|
17327
|
-
|
|
17328
|
-
|
|
17329
|
-
|
|
17330
|
-
} catch {
|
|
17362
|
+
if (!Array.isArray(parsed)) return [];
|
|
17363
|
+
const out2 = [];
|
|
17364
|
+
for (const row of parsed) {
|
|
17365
|
+
const issue = coerceIssue(row, projectKey);
|
|
17366
|
+
if (issue) out2.push(issue);
|
|
17331
17367
|
}
|
|
17332
|
-
|
|
17333
|
-
|
|
17334
|
-
|
|
17368
|
+
return out2;
|
|
17369
|
+
}
|
|
17370
|
+
function coerceIssue(row, projectKey) {
|
|
17371
|
+
if (typeof row !== "object" || row === null) return null;
|
|
17372
|
+
const r = row;
|
|
17373
|
+
if (typeof r.id !== "string" || typeof r.title !== "string") return null;
|
|
17374
|
+
const status2 = typeof r.status === "string" && VALID_STATUS.has(r.status) ? r.status : "open";
|
|
17375
|
+
return {
|
|
17376
|
+
id: r.id,
|
|
17377
|
+
title: r.title,
|
|
17378
|
+
status: status2,
|
|
17379
|
+
priority: typeof r.priority === "number" ? r.priority : null,
|
|
17380
|
+
issue_type: typeof r.issue_type === "string" ? r.issue_type : "task",
|
|
17381
|
+
owner: typeof r.owner === "string" && r.owner.length > 0 ? r.owner : null,
|
|
17382
|
+
created_at: typeof r.created_at === "string" ? r.created_at : "",
|
|
17383
|
+
updated_at: typeof r.updated_at === "string" ? r.updated_at : "",
|
|
17384
|
+
dependency_count: typeof r.dependency_count === "number" ? r.dependency_count : void 0,
|
|
17385
|
+
dependent_count: typeof r.dependent_count === "number" ? r.dependent_count : void 0,
|
|
17386
|
+
comment_count: typeof r.comment_count === "number" ? r.comment_count : void 0,
|
|
17387
|
+
projectKey
|
|
17388
|
+
};
|
|
17389
|
+
}
|
|
17390
|
+
function defaultBeadsHomeDir() {
|
|
17391
|
+
return path35.join(os24.homedir(), ".beads");
|
|
17392
|
+
}
|
|
17393
|
+
|
|
17394
|
+
// src/beads/provisioner.ts
|
|
17395
|
+
var fs30 = __toESM(require("fs"));
|
|
17396
|
+
var path36 = __toESM(require("path"));
|
|
17397
|
+
|
|
17398
|
+
// src/beads/install-bd.ts
|
|
17399
|
+
var import_child_process13 = require("child_process");
|
|
17400
|
+
var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
|
|
17401
|
+
var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
|
|
17402
|
+
function resolveInstallStrategy(platform2) {
|
|
17403
|
+
if (platform2 === "win32") {
|
|
17404
|
+
return {
|
|
17405
|
+
command: "powershell.exe",
|
|
17406
|
+
args: [
|
|
17407
|
+
"-NoProfile",
|
|
17408
|
+
"-NonInteractive",
|
|
17409
|
+
"-ExecutionPolicy",
|
|
17410
|
+
"Bypass",
|
|
17411
|
+
"-Command",
|
|
17412
|
+
`irm ${INSTALL_PS1_URL} | iex`
|
|
17413
|
+
],
|
|
17414
|
+
description: `PowerShell: irm ${INSTALL_PS1_URL} | iex (requires Go 1.24+ and Git for Windows on PATH)`
|
|
17415
|
+
};
|
|
17416
|
+
}
|
|
17417
|
+
return {
|
|
17418
|
+
command: "bash",
|
|
17419
|
+
args: ["-c", `curl -fsSL ${INSTALL_SH_URL} | bash`],
|
|
17420
|
+
description: `curl -fsSL ${INSTALL_SH_URL} | bash`
|
|
17421
|
+
};
|
|
17422
|
+
}
|
|
17423
|
+
var _installSpawnSeam = {
|
|
17424
|
+
run: _defaultInstallSpawn
|
|
17425
|
+
};
|
|
17426
|
+
function _defaultInstallSpawn(strategy) {
|
|
17427
|
+
return new Promise((resolve7) => {
|
|
17428
|
+
let proc;
|
|
17429
|
+
try {
|
|
17430
|
+
proc = (0, import_child_process13.spawn)(strategy.command, strategy.args, { env: process.env });
|
|
17431
|
+
} catch (err) {
|
|
17432
|
+
resolve7({ ok: false, code: -1, stderr: err.message });
|
|
17433
|
+
return;
|
|
17434
|
+
}
|
|
17435
|
+
let stderr = "";
|
|
17436
|
+
proc.stderr?.on("data", (c2) => {
|
|
17437
|
+
stderr += c2.toString();
|
|
17438
|
+
});
|
|
17439
|
+
proc.on("error", (err) => resolve7({ ok: false, code: -1, stderr: err.message }));
|
|
17440
|
+
proc.on(
|
|
17441
|
+
"close",
|
|
17442
|
+
(code) => resolve7({ ok: code === 0, code: code ?? -1, stderr })
|
|
17443
|
+
);
|
|
17444
|
+
});
|
|
17445
|
+
}
|
|
17446
|
+
async function installBd(platform2 = process.platform) {
|
|
17447
|
+
const strategy = resolveInstallStrategy(platform2);
|
|
17448
|
+
log.info("beads", `installing bd via ${strategy.description}`);
|
|
17449
|
+
const result = await _installSpawnSeam.run(strategy);
|
|
17450
|
+
if (!result.ok) {
|
|
17451
|
+
log.warn(
|
|
17452
|
+
"beads",
|
|
17453
|
+
`bd install failed (code=${result.code}): ${result.stderr.slice(0, 200)}`
|
|
17454
|
+
);
|
|
17335
17455
|
}
|
|
17456
|
+
return result;
|
|
17457
|
+
}
|
|
17458
|
+
|
|
17459
|
+
// src/beads/provisioner.ts
|
|
17460
|
+
var AGENT_SETUP_RECIPE = {
|
|
17461
|
+
claude: "claude",
|
|
17462
|
+
codex: "codex",
|
|
17463
|
+
copilot: "copilot",
|
|
17464
|
+
cursor: "cursor",
|
|
17465
|
+
aider: "aider",
|
|
17466
|
+
gemini: "gemini",
|
|
17467
|
+
coderabbit: null
|
|
17468
|
+
};
|
|
17469
|
+
var _provisionSeam = {
|
|
17470
|
+
install: installBd,
|
|
17471
|
+
homeBrainInitialized
|
|
17472
|
+
};
|
|
17473
|
+
function homeBrainInitialized(beadsDir) {
|
|
17336
17474
|
try {
|
|
17337
|
-
|
|
17475
|
+
return fs30.statSync(path36.join(beadsDir, "embeddeddolt")).isDirectory();
|
|
17338
17476
|
} catch {
|
|
17477
|
+
return false;
|
|
17339
17478
|
}
|
|
17340
|
-
|
|
17341
|
-
|
|
17479
|
+
}
|
|
17480
|
+
async function provisionBeads(opts = {}) {
|
|
17481
|
+
const bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
|
|
17482
|
+
const beadsDir = opts.beadsDir ?? defaultBeadsHomeDir();
|
|
17483
|
+
const result = {
|
|
17484
|
+
bdAvailable: false,
|
|
17485
|
+
initialized: false,
|
|
17486
|
+
exportEnabled: false,
|
|
17487
|
+
agentsWired: []
|
|
17488
|
+
};
|
|
17489
|
+
if (!bd.isAvailable()) {
|
|
17490
|
+
log.info("beads", "bd binary missing \u2014 running OS installer fallback");
|
|
17491
|
+
const install = await _provisionSeam.install();
|
|
17492
|
+
if (!install.ok) {
|
|
17493
|
+
log.warn("beads", `bd install failed (code=${install.code}) \u2014 beads disabled this run`);
|
|
17494
|
+
return result;
|
|
17495
|
+
}
|
|
17496
|
+
}
|
|
17497
|
+
if (!bd.isAvailable()) {
|
|
17498
|
+
log.warn("beads", "bd still unavailable after install \u2014 beads disabled this run");
|
|
17499
|
+
return result;
|
|
17500
|
+
}
|
|
17501
|
+
result.bdAvailable = true;
|
|
17502
|
+
if (_provisionSeam.homeBrainInitialized(beadsDir)) {
|
|
17503
|
+
log.trace("beads", `home brain already initialized at ${beadsDir}`);
|
|
17504
|
+
result.initialized = true;
|
|
17505
|
+
} else {
|
|
17506
|
+
log.info("beads", `initializing home brain at ${beadsDir}`);
|
|
17507
|
+
const init = await bd.run(["init", "--skip-agents", "--skip-hooks", "--non-interactive"]);
|
|
17508
|
+
if (init.code !== 0) {
|
|
17509
|
+
log.warn("beads", `bd init failed (code=${init.code}): ${init.stderr.slice(0, 200)}`);
|
|
17510
|
+
return result;
|
|
17511
|
+
}
|
|
17512
|
+
result.initialized = true;
|
|
17513
|
+
}
|
|
17514
|
+
const exp = await bd.run(["config", "set", "export.auto", "true"]);
|
|
17515
|
+
result.exportEnabled = exp.code === 0;
|
|
17516
|
+
result.agentsWired = await setupAgents(bd, opts.agents ?? []);
|
|
17517
|
+
log.info(
|
|
17518
|
+
"beads",
|
|
17519
|
+
`provision done initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
|
|
17520
|
+
);
|
|
17521
|
+
return result;
|
|
17522
|
+
}
|
|
17523
|
+
async function setupAgents(bd, agents) {
|
|
17524
|
+
const wired = [];
|
|
17525
|
+
for (const recipe of dedupeRecipes(agents)) {
|
|
17526
|
+
try {
|
|
17527
|
+
const check = await bd.run(["setup", recipe, "--global", "--check"]);
|
|
17528
|
+
if (check.code === 0) {
|
|
17529
|
+
log.trace("beads", `bd setup ${recipe} --global already installed \u2014 skipping`);
|
|
17530
|
+
wired.push(recipe);
|
|
17531
|
+
continue;
|
|
17532
|
+
}
|
|
17533
|
+
log.info("beads", `wiring agent natively: bd setup ${recipe} --global`);
|
|
17534
|
+
const setup = await bd.run(["setup", recipe, "--global"]);
|
|
17535
|
+
if (setup.code === 0) {
|
|
17536
|
+
wired.push(recipe);
|
|
17537
|
+
} else {
|
|
17538
|
+
log.warn(
|
|
17539
|
+
"beads",
|
|
17540
|
+
`bd setup ${recipe} --global failed (code=${setup.code}): ${setup.stderr.slice(0, 200)} \u2014 non-fatal, agent runs without native bd wiring`
|
|
17541
|
+
);
|
|
17542
|
+
}
|
|
17543
|
+
} catch (err) {
|
|
17544
|
+
log.warn("beads", `bd setup ${recipe} --global threw (non-fatal)`, err);
|
|
17545
|
+
}
|
|
17546
|
+
}
|
|
17547
|
+
return wired;
|
|
17548
|
+
}
|
|
17549
|
+
function dedupeRecipes(agents) {
|
|
17550
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17551
|
+
for (const agent of agents) {
|
|
17552
|
+
const recipe = AGENT_SETUP_RECIPE[agent];
|
|
17553
|
+
if (recipe) seen.add(recipe);
|
|
17554
|
+
}
|
|
17555
|
+
return [...seen];
|
|
17556
|
+
}
|
|
17557
|
+
|
|
17558
|
+
// src/beads/watcher.ts
|
|
17559
|
+
var crypto3 = __toESM(require("crypto"));
|
|
17560
|
+
var path38 = __toESM(require("path"));
|
|
17561
|
+
|
|
17562
|
+
// src/beads/project-key.ts
|
|
17563
|
+
var import_child_process14 = require("child_process");
|
|
17564
|
+
var crypto2 = __toESM(require("crypto"));
|
|
17565
|
+
var fs31 = __toESM(require("fs"));
|
|
17566
|
+
var path37 = __toESM(require("path"));
|
|
17567
|
+
function normalizeOrigin(raw) {
|
|
17568
|
+
const trimmed = raw.trim();
|
|
17569
|
+
if (!trimmed) return null;
|
|
17570
|
+
let host;
|
|
17571
|
+
let pathPart;
|
|
17572
|
+
const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
|
|
17573
|
+
if (scpLike && !trimmed.includes("://")) {
|
|
17574
|
+
host = scpLike[1];
|
|
17575
|
+
pathPart = scpLike[2];
|
|
17576
|
+
} else {
|
|
17577
|
+
let url;
|
|
17578
|
+
try {
|
|
17579
|
+
url = new URL(trimmed);
|
|
17580
|
+
} catch {
|
|
17581
|
+
return null;
|
|
17582
|
+
}
|
|
17583
|
+
host = url.hostname;
|
|
17584
|
+
pathPart = url.pathname;
|
|
17585
|
+
}
|
|
17586
|
+
host = host.toLowerCase();
|
|
17587
|
+
pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
17588
|
+
if (!host || !pathPart) return null;
|
|
17589
|
+
return `${host}/${pathPart}`;
|
|
17590
|
+
}
|
|
17591
|
+
function findRepoRoot(cwd) {
|
|
17592
|
+
let dir = path37.resolve(cwd);
|
|
17593
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17594
|
+
for (let i = 0; i < 256; i++) {
|
|
17595
|
+
if (seen.has(dir)) return null;
|
|
17596
|
+
seen.add(dir);
|
|
17597
|
+
try {
|
|
17598
|
+
const stat3 = fs31.statSync(path37.join(dir, ".git"), { throwIfNoEntry: false });
|
|
17599
|
+
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
17600
|
+
} catch {
|
|
17601
|
+
}
|
|
17602
|
+
const parent = path37.dirname(dir);
|
|
17603
|
+
if (parent === dir) return null;
|
|
17604
|
+
dir = parent;
|
|
17605
|
+
}
|
|
17606
|
+
return null;
|
|
17607
|
+
}
|
|
17608
|
+
var _execSeam2 = {
|
|
17609
|
+
exec: (file, args2, opts) => {
|
|
17610
|
+
const out2 = (0, import_child_process14.execFileSync)(file, args2, opts);
|
|
17611
|
+
return typeof out2 === "string" ? out2 : out2.toString("utf8");
|
|
17612
|
+
},
|
|
17613
|
+
realpath: (p2) => fs31.realpathSync(p2)
|
|
17614
|
+
};
|
|
17615
|
+
function readOrigin(cwd) {
|
|
17616
|
+
try {
|
|
17617
|
+
const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
|
|
17618
|
+
cwd,
|
|
17619
|
+
timeout: 1e3,
|
|
17620
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
17621
|
+
encoding: "utf8"
|
|
17622
|
+
});
|
|
17623
|
+
return raw.trim() || null;
|
|
17624
|
+
} catch {
|
|
17625
|
+
return null;
|
|
17626
|
+
}
|
|
17627
|
+
}
|
|
17628
|
+
function deriveProjectIdentity(cwd = process.cwd()) {
|
|
17629
|
+
const repoRoot = findRepoRoot(cwd) ?? cwd;
|
|
17630
|
+
const origin = readOrigin(repoRoot);
|
|
17631
|
+
const normalized = origin ? normalizeOrigin(origin) : null;
|
|
17632
|
+
if (normalized) {
|
|
17633
|
+
const label = normalized.split("/").pop() || normalized;
|
|
17634
|
+
return { projectKey: normalized, projectLabel: label };
|
|
17635
|
+
}
|
|
17636
|
+
let real = repoRoot;
|
|
17637
|
+
try {
|
|
17638
|
+
real = _execSeam2.realpath(repoRoot);
|
|
17639
|
+
} catch {
|
|
17640
|
+
}
|
|
17641
|
+
const hash = crypto2.createHash("sha256").update(real).digest("hex");
|
|
17642
|
+
return { projectKey: `path:${hash}`, projectLabel: path37.basename(real) || "project" };
|
|
17643
|
+
}
|
|
17644
|
+
|
|
17645
|
+
// src/services/file-watcher/transport.ts
|
|
17646
|
+
var http5 = __toESM(require("http"));
|
|
17647
|
+
var https5 = __toESM(require("https"));
|
|
17648
|
+
var _transport3 = {
|
|
17649
|
+
post: _post2
|
|
17650
|
+
};
|
|
17651
|
+
function _post2(url, headers, payload) {
|
|
17652
|
+
return new Promise((resolve7, reject) => {
|
|
17653
|
+
let settled = false;
|
|
17654
|
+
const u2 = new URL(url);
|
|
17655
|
+
const lib = u2.protocol === "https:" ? https5 : http5;
|
|
17656
|
+
const req = lib.request(
|
|
17657
|
+
{
|
|
17658
|
+
hostname: u2.hostname,
|
|
17659
|
+
port: u2.port || (u2.protocol === "https:" ? 443 : 80),
|
|
17660
|
+
path: u2.pathname + u2.search,
|
|
17661
|
+
method: "POST",
|
|
17662
|
+
headers: {
|
|
17663
|
+
...headers,
|
|
17664
|
+
...vercelBypassHeader(),
|
|
17665
|
+
"Content-Length": Buffer.byteLength(payload)
|
|
17666
|
+
},
|
|
17667
|
+
timeout: 8e3
|
|
17668
|
+
},
|
|
17669
|
+
(res) => {
|
|
17670
|
+
let body = "";
|
|
17671
|
+
res.on("data", (c2) => {
|
|
17672
|
+
body += c2.toString();
|
|
17673
|
+
});
|
|
17674
|
+
res.on("end", () => {
|
|
17675
|
+
if (settled) return;
|
|
17676
|
+
settled = true;
|
|
17677
|
+
resolve7({ statusCode: res.statusCode ?? 0, body });
|
|
17678
|
+
});
|
|
17679
|
+
}
|
|
17680
|
+
);
|
|
17681
|
+
req.on("error", (err) => {
|
|
17682
|
+
if (settled) return;
|
|
17683
|
+
settled = true;
|
|
17684
|
+
reject(err);
|
|
17685
|
+
});
|
|
17686
|
+
req.on("timeout", () => {
|
|
17687
|
+
req.destroy();
|
|
17688
|
+
});
|
|
17689
|
+
req.write(payload);
|
|
17690
|
+
req.end();
|
|
17691
|
+
});
|
|
17692
|
+
}
|
|
17693
|
+
|
|
17694
|
+
// src/beads/watcher.ts
|
|
17695
|
+
var API_BASE4 = resolveApiBaseUrl();
|
|
17696
|
+
var DEBOUNCE_MS = 400;
|
|
17697
|
+
var _chokidarSeam = {
|
|
17698
|
+
load: () => {
|
|
17699
|
+
try {
|
|
17700
|
+
return require("chokidar");
|
|
17701
|
+
} catch {
|
|
17702
|
+
return null;
|
|
17703
|
+
}
|
|
17704
|
+
}
|
|
17705
|
+
};
|
|
17706
|
+
var BeadsWatcher = class {
|
|
17707
|
+
constructor(opts) {
|
|
17708
|
+
this.opts = opts;
|
|
17709
|
+
this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
|
|
17710
|
+
this.feedPath = opts.feedPath ?? path38.join(defaultBeadsHomeDir(), "issues.jsonl");
|
|
17711
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE4;
|
|
17712
|
+
}
|
|
17713
|
+
opts;
|
|
17714
|
+
watcher = null;
|
|
17715
|
+
debounceTimer = null;
|
|
17716
|
+
stopped = false;
|
|
17717
|
+
lastPushedHash = null;
|
|
17718
|
+
bd;
|
|
17719
|
+
feedPath;
|
|
17720
|
+
apiBase;
|
|
17721
|
+
/** Start tailing the change feed. Idempotent (second call is a no-op). */
|
|
17722
|
+
start() {
|
|
17723
|
+
if (this.watcher || this.stopped) return;
|
|
17724
|
+
const chokidar2 = _chokidarSeam.load();
|
|
17725
|
+
if (!chokidar2) {
|
|
17726
|
+
log.warn("beads", "chokidar unavailable \u2014 beads watcher disabled");
|
|
17727
|
+
return;
|
|
17728
|
+
}
|
|
17729
|
+
const watcher = chokidar2.watch(this.feedPath, {
|
|
17730
|
+
ignoreInitial: false,
|
|
17731
|
+
// push the current state once on start
|
|
17732
|
+
persistent: true,
|
|
17733
|
+
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 100 }
|
|
17734
|
+
});
|
|
17735
|
+
watcher.on("add", () => this.scheduleSync());
|
|
17736
|
+
watcher.on("change", () => this.scheduleSync());
|
|
17737
|
+
watcher.on(
|
|
17738
|
+
"error",
|
|
17739
|
+
(err) => log.warn("beads", `feed watcher error \u2014 continuing: ${err}`)
|
|
17740
|
+
);
|
|
17741
|
+
this.watcher = watcher;
|
|
17742
|
+
log.info("beads", `watching ${this.feedPath} for session=${this.opts.sessionId.slice(0, 8)}`);
|
|
17743
|
+
}
|
|
17744
|
+
async stop() {
|
|
17745
|
+
if (this.stopped) return;
|
|
17746
|
+
this.stopped = true;
|
|
17747
|
+
if (this.debounceTimer) {
|
|
17748
|
+
clearTimeout(this.debounceTimer);
|
|
17749
|
+
this.debounceTimer = null;
|
|
17750
|
+
}
|
|
17751
|
+
if (this.watcher) {
|
|
17752
|
+
try {
|
|
17753
|
+
await this.watcher.close();
|
|
17754
|
+
} catch (err) {
|
|
17755
|
+
log.warn("beads", "error closing feed watcher", err);
|
|
17756
|
+
}
|
|
17757
|
+
this.watcher = null;
|
|
17758
|
+
}
|
|
17759
|
+
}
|
|
17760
|
+
/**
|
|
17761
|
+
* Debounce the filesystem event. Each fresh write resets the timer so a
|
|
17762
|
+
* burst of bd mutations coalesces into one snapshot push. NOT polling — the
|
|
17763
|
+
* timer only fires off the back of a real fs event.
|
|
17764
|
+
*/
|
|
17765
|
+
scheduleSync() {
|
|
17766
|
+
if (this.stopped) return;
|
|
17767
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
17768
|
+
this.debounceTimer = setTimeout(() => {
|
|
17769
|
+
this.debounceTimer = null;
|
|
17770
|
+
void this.syncNow();
|
|
17771
|
+
}, DEBOUNCE_MS);
|
|
17772
|
+
}
|
|
17773
|
+
/** Visible for tests — pump a synthetic feed event through debounce → push. */
|
|
17774
|
+
/* @internal */
|
|
17775
|
+
_emitForTest() {
|
|
17776
|
+
this.scheduleSync();
|
|
17777
|
+
}
|
|
17778
|
+
/**
|
|
17779
|
+
* Build the full snapshot from bd and push it. Diffs against the last
|
|
17780
|
+
* pushed content hash so an identical rewrite is a no-op.
|
|
17781
|
+
*/
|
|
17782
|
+
async syncNow() {
|
|
17783
|
+
if (this.stopped) return;
|
|
17784
|
+
const { projectKey, projectLabel } = deriveProjectIdentity(this.opts.cwd);
|
|
17785
|
+
const [issues, summary] = await Promise.all([
|
|
17786
|
+
this.bd.listIssues(projectKey),
|
|
17787
|
+
this.bd.statusSummary()
|
|
17788
|
+
]);
|
|
17789
|
+
const payload = {
|
|
17790
|
+
sessionId: this.opts.sessionId,
|
|
17791
|
+
pluginId: this.opts.pluginId,
|
|
17792
|
+
projectKey,
|
|
17793
|
+
projectLabel,
|
|
17794
|
+
fullSnapshot: true,
|
|
17795
|
+
issues,
|
|
17796
|
+
memories: [],
|
|
17797
|
+
...summary ? { summary } : {}
|
|
17798
|
+
};
|
|
17799
|
+
const body = JSON.stringify(payload);
|
|
17800
|
+
const hash = crypto3.createHash("sha256").update(body).digest("hex");
|
|
17801
|
+
if (hash === this.lastPushedHash) {
|
|
17802
|
+
log.trace("beads", "snapshot unchanged \u2014 skipping push");
|
|
17803
|
+
return;
|
|
17804
|
+
}
|
|
17805
|
+
try {
|
|
17806
|
+
const res = await _transport3.post(`${this.apiBase}/api/beads/ingest`, this.headers(), body);
|
|
17807
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
17808
|
+
this.lastPushedHash = hash;
|
|
17809
|
+
log.trace("beads", `pushed ${issues.length} issue(s) project=${projectLabel}`);
|
|
17810
|
+
} else if (res.statusCode === 404 || res.statusCode === 410) {
|
|
17811
|
+
log.warn("beads", `session dead (status=${res.statusCode}) \u2014 stopping watcher`);
|
|
17812
|
+
this.stopped = true;
|
|
17813
|
+
} else {
|
|
17814
|
+
log.warn("beads", `ingest failed status=${res.statusCode} body=${res.body.slice(0, 200)}`);
|
|
17815
|
+
}
|
|
17816
|
+
} catch (err) {
|
|
17817
|
+
log.warn("beads", "ingest POST error", err);
|
|
17818
|
+
}
|
|
17819
|
+
}
|
|
17820
|
+
headers() {
|
|
17821
|
+
return {
|
|
17822
|
+
"Content-Type": "application/json",
|
|
17823
|
+
"X-Codeam-Protocol-Version": "2.0.0",
|
|
17824
|
+
"X-Plugin-Auth-Token": this.opts.pluginAuthToken
|
|
17825
|
+
};
|
|
17826
|
+
}
|
|
17827
|
+
};
|
|
17828
|
+
|
|
17829
|
+
// src/beads/apply-actions.ts
|
|
17830
|
+
function buildBdArgs(action) {
|
|
17831
|
+
switch (action.kind) {
|
|
17832
|
+
case "claim": {
|
|
17833
|
+
if (!action.issueId) return null;
|
|
17834
|
+
const args2 = ["update", action.issueId, "--claim"];
|
|
17835
|
+
if (action.owner) args2.push("--owner", action.owner);
|
|
17836
|
+
return args2;
|
|
17837
|
+
}
|
|
17838
|
+
case "close": {
|
|
17839
|
+
if (!action.issueId) return null;
|
|
17840
|
+
const args2 = ["close", action.issueId];
|
|
17841
|
+
if (action.reason) args2.push("--reason", action.reason);
|
|
17842
|
+
return args2;
|
|
17843
|
+
}
|
|
17844
|
+
case "create": {
|
|
17845
|
+
const title = action.text?.trim();
|
|
17846
|
+
if (!title) return null;
|
|
17847
|
+
return ["create", title];
|
|
17848
|
+
}
|
|
17849
|
+
case "remember": {
|
|
17850
|
+
const body = action.text?.trim();
|
|
17851
|
+
if (!body) return null;
|
|
17852
|
+
return ["remember", body];
|
|
17853
|
+
}
|
|
17854
|
+
default:
|
|
17855
|
+
return null;
|
|
17856
|
+
}
|
|
17857
|
+
}
|
|
17858
|
+
async function applyBeadsAction(action, deps) {
|
|
17859
|
+
const args2 = buildBdArgs(action);
|
|
17860
|
+
if (!args2) {
|
|
17861
|
+
log.warn("beads", `malformed beads action: kind=${action.kind}`);
|
|
17862
|
+
return { ok: false, action: action.kind, code: -1, error: "malformed action" };
|
|
17863
|
+
}
|
|
17864
|
+
if (!deps.adapter.isAvailable()) {
|
|
17865
|
+
return { ok: false, action: action.kind, code: -1, error: "bd unavailable" };
|
|
17866
|
+
}
|
|
17867
|
+
const res = await deps.adapter.run(args2);
|
|
17868
|
+
if (res.code !== 0) {
|
|
17869
|
+
log.warn("beads", `bd ${args2.join(" ")} failed (code=${res.code}): ${res.stderr.slice(0, 200)}`);
|
|
17870
|
+
return { ok: false, action: action.kind, code: res.code, error: res.stderr };
|
|
17871
|
+
}
|
|
17872
|
+
log.info("beads", `applied action ${action.kind}${action.issueId ? ` (${action.issueId})` : ""}`);
|
|
17873
|
+
try {
|
|
17874
|
+
await deps.onApplied();
|
|
17875
|
+
} catch (err) {
|
|
17876
|
+
log.warn("beads", "post-action push failed (state still applied locally)", err);
|
|
17877
|
+
}
|
|
17878
|
+
return { ok: true, action: action.kind, code: 0 };
|
|
17879
|
+
}
|
|
17880
|
+
|
|
17881
|
+
// src/beads/index.ts
|
|
17882
|
+
async function startBeads(opts) {
|
|
17883
|
+
const adapter = new BdAdapter({ cwd: opts.cwd });
|
|
17884
|
+
const provision = await provisionBeads({ cwd: opts.cwd, adapter, agents: opts.agents });
|
|
17885
|
+
if (!provision.bdAvailable || !provision.initialized) {
|
|
17886
|
+
log.warn("beads", "home brain not provisioned \u2014 watcher not started this run");
|
|
17887
|
+
return null;
|
|
17888
|
+
}
|
|
17889
|
+
const watcher = new BeadsWatcher({
|
|
17890
|
+
sessionId: opts.sessionId,
|
|
17891
|
+
pluginId: opts.pluginId,
|
|
17892
|
+
pluginAuthToken: opts.pluginAuthToken,
|
|
17893
|
+
cwd: opts.cwd,
|
|
17894
|
+
adapter
|
|
17895
|
+
});
|
|
17896
|
+
watcher.start();
|
|
17897
|
+
void watcher.syncNow();
|
|
17898
|
+
return { watcher, adapter };
|
|
17899
|
+
}
|
|
17900
|
+
async function handleBeadsActionCommand(action, started) {
|
|
17901
|
+
await applyBeadsAction(action, {
|
|
17902
|
+
adapter: started.adapter,
|
|
17903
|
+
onApplied: () => started.watcher.syncNow()
|
|
17904
|
+
});
|
|
17905
|
+
}
|
|
17906
|
+
|
|
17907
|
+
// src/beads/wiring.ts
|
|
17908
|
+
function beadsKilled() {
|
|
17909
|
+
const v = process.env.CODEAM_BEADS_DISABLED;
|
|
17910
|
+
return !!v && v !== "0" && v.toLowerCase() !== "false";
|
|
17911
|
+
}
|
|
17912
|
+
async function provisionBeadsForStart(ctx) {
|
|
17913
|
+
if (beadsKilled()) {
|
|
17914
|
+
log.trace("beads", "CODEAM_BEADS_DISABLED set \u2014 beads off this run");
|
|
17915
|
+
return null;
|
|
17916
|
+
}
|
|
17917
|
+
if (!ctx.pluginAuthToken) {
|
|
17918
|
+
log.trace("beads", "no pluginAuthToken \u2014 beads off");
|
|
17919
|
+
return null;
|
|
17920
|
+
}
|
|
17921
|
+
const pluginAuthToken = ctx.pluginAuthToken;
|
|
17922
|
+
let started = null;
|
|
17923
|
+
try {
|
|
17924
|
+
started = await startBeads({
|
|
17925
|
+
sessionId: ctx.sessionId,
|
|
17926
|
+
pluginId: ctx.pluginId,
|
|
17927
|
+
pluginAuthToken,
|
|
17928
|
+
cwd: ctx.cwd,
|
|
17929
|
+
agents: ctx.agents
|
|
17930
|
+
});
|
|
17931
|
+
} catch (err) {
|
|
17932
|
+
log.warn("beads", "provisionBeadsForStart failed (non-fatal)", err);
|
|
17933
|
+
started = null;
|
|
17934
|
+
}
|
|
17935
|
+
const { projectKey } = deriveProjectIdentity(ctx.cwd);
|
|
17936
|
+
void postBeadsProvisioning({
|
|
17937
|
+
sessionId: ctx.sessionId,
|
|
17938
|
+
pluginId: ctx.pluginId,
|
|
17939
|
+
pluginAuthToken,
|
|
17940
|
+
status: started ? "ready" : "failed",
|
|
17941
|
+
projectKey
|
|
17942
|
+
}).then((res) => {
|
|
17943
|
+
if (!res.ok) {
|
|
17944
|
+
log.trace("beads", `provisioning signal POST non-ok (status=${res.status}) \u2014 ignoring`);
|
|
17945
|
+
}
|
|
17946
|
+
});
|
|
17947
|
+
return started;
|
|
17948
|
+
}
|
|
17949
|
+
var ACTION_KINDS = /* @__PURE__ */ new Set([
|
|
17950
|
+
"claim",
|
|
17951
|
+
"close",
|
|
17952
|
+
"create",
|
|
17953
|
+
"remember"
|
|
17954
|
+
]);
|
|
17955
|
+
function isBeadsActionKind(v) {
|
|
17956
|
+
return typeof v === "string" && ACTION_KINDS.has(v);
|
|
17957
|
+
}
|
|
17958
|
+
function strOrUndefined(v) {
|
|
17959
|
+
return typeof v === "string" ? v : void 0;
|
|
17960
|
+
}
|
|
17961
|
+
function beadsActionFromPayload(payload) {
|
|
17962
|
+
const { action, args: args2 } = payload;
|
|
17963
|
+
if (!isBeadsActionKind(action)) return null;
|
|
17964
|
+
const a = args2 && typeof args2 === "object" ? args2 : {};
|
|
17965
|
+
return {
|
|
17966
|
+
kind: action,
|
|
17967
|
+
issueId: strOrUndefined(a.issueId),
|
|
17968
|
+
text: strOrUndefined(a.text),
|
|
17969
|
+
reason: strOrUndefined(a.reason),
|
|
17970
|
+
owner: strOrUndefined(a.owner),
|
|
17971
|
+
projectKey: strOrUndefined(a.projectKey)
|
|
17972
|
+
};
|
|
17973
|
+
}
|
|
17974
|
+
|
|
17975
|
+
// src/commands/start/handlers.ts
|
|
17976
|
+
var pendingAttachmentFiles = /* @__PURE__ */ new Set();
|
|
17977
|
+
function cleanupAttachmentTempFiles() {
|
|
17978
|
+
for (const p2 of pendingAttachmentFiles) {
|
|
17979
|
+
try {
|
|
17980
|
+
fs32.unlinkSync(p2);
|
|
17981
|
+
} catch {
|
|
17982
|
+
}
|
|
17983
|
+
}
|
|
17984
|
+
pendingAttachmentFiles.clear();
|
|
17985
|
+
}
|
|
17986
|
+
function saveFilesTemp(files) {
|
|
17987
|
+
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
17988
|
+
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
17989
|
+
const tmpPath = path39.join(os25.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
|
|
17990
|
+
fs32.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
17991
|
+
pendingAttachmentFiles.add(tmpPath);
|
|
17992
|
+
return tmpPath;
|
|
17993
|
+
});
|
|
17994
|
+
}
|
|
17995
|
+
function dispatchPrompt(ctx, prompt) {
|
|
17996
|
+
ctx.outputSvc.newTurn();
|
|
17997
|
+
ctx.agent.sendCommand(prompt);
|
|
17998
|
+
}
|
|
17999
|
+
var startTask = (ctx, _cmd, parsed) => {
|
|
18000
|
+
const { prompt, files } = parsed;
|
|
18001
|
+
const effectivePrompt = prompt ?? "";
|
|
18002
|
+
if (files && files.length > 0) {
|
|
18003
|
+
const paths = saveFilesTemp(files);
|
|
18004
|
+
const atRefs = paths.map((p2) => `@${p2}`).join(" ");
|
|
18005
|
+
ctx.outputSvc.newTurn();
|
|
18006
|
+
ctx.agent.sendCommand(`${atRefs} ${effectivePrompt}`.trim());
|
|
18007
|
+
setTimeout(() => {
|
|
18008
|
+
for (const p2 of paths) {
|
|
18009
|
+
try {
|
|
18010
|
+
fs32.unlinkSync(p2);
|
|
18011
|
+
} catch {
|
|
18012
|
+
}
|
|
18013
|
+
pendingAttachmentFiles.delete(p2);
|
|
18014
|
+
}
|
|
18015
|
+
}, 12e4);
|
|
18016
|
+
} else if (effectivePrompt) {
|
|
18017
|
+
dispatchPrompt(ctx, effectivePrompt);
|
|
18018
|
+
}
|
|
18019
|
+
};
|
|
18020
|
+
var provideInput = (ctx, _cmd, parsed) => {
|
|
18021
|
+
if (parsed.input) dispatchPrompt(ctx, parsed.input);
|
|
18022
|
+
};
|
|
18023
|
+
var selectOption = (ctx, _cmd, parsed) => {
|
|
18024
|
+
const index = parsed.index ?? 0;
|
|
18025
|
+
const from = parsed.from ?? 0;
|
|
18026
|
+
ctx.outputSvc.newTurn();
|
|
18027
|
+
ctx.agent.selectOption(index, from);
|
|
18028
|
+
};
|
|
18029
|
+
var escapeKey = (ctx) => {
|
|
18030
|
+
ctx.outputSvc.newTurn();
|
|
18031
|
+
ctx.agent.sendEscape();
|
|
18032
|
+
};
|
|
18033
|
+
var stopTask = (ctx) => {
|
|
18034
|
+
ctx.agent.interrupt();
|
|
18035
|
+
};
|
|
18036
|
+
var resumeSession = async (ctx, _cmd, parsed) => {
|
|
18037
|
+
const { id, auto } = parsed;
|
|
18038
|
+
if (!id) return;
|
|
18039
|
+
ctx.historySvc.setCurrentConversationId(id);
|
|
18040
|
+
await ctx.historySvc.loadConversation(id);
|
|
18041
|
+
await ctx.outputSvc.newTurnResume(id);
|
|
18042
|
+
ctx.agent.restart(id, auto ?? false);
|
|
18043
|
+
};
|
|
18044
|
+
var getContext = async (ctx, cmd) => {
|
|
18045
|
+
const usage = ctx.historySvc.getCurrentUsage();
|
|
18046
|
+
const monthlyCost = ctx.historySvc.getMonthlyEstimatedCost();
|
|
18047
|
+
const rateLimitReset = ctx.historySvc.getRateLimitReset();
|
|
18048
|
+
const quotaPercent = ctx.historySvc.getQuotaPercent();
|
|
18049
|
+
const base = usage ? { ...usage, monthlyCost } : { used: 0, total: 2e5, percent: 0, model: null, outputTokens: 0, cacheReadTokens: 0, monthlyCost, error: "No usage data found" };
|
|
18050
|
+
const result = {
|
|
18051
|
+
...base,
|
|
18052
|
+
...rateLimitReset ? { rateLimitReset } : {},
|
|
18053
|
+
...quotaPercent !== null ? { quotaPercent } : {}
|
|
18054
|
+
};
|
|
18055
|
+
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
18056
|
+
};
|
|
18057
|
+
var getConversation = async (ctx, cmd) => {
|
|
18058
|
+
let currentId = ctx.historySvc.getCurrentConversationId();
|
|
18059
|
+
if (!currentId) {
|
|
18060
|
+
ctx.historySvc.detectCurrentConversation();
|
|
18061
|
+
currentId = ctx.historySvc.getCurrentConversationId();
|
|
18062
|
+
}
|
|
18063
|
+
if (!currentId) {
|
|
18064
|
+
await ctx.relay.sendResult(cmd.id, "completed", { conversationId: null });
|
|
18065
|
+
return;
|
|
18066
|
+
}
|
|
18067
|
+
try {
|
|
18068
|
+
await ctx.historySvc.loadConversation(currentId);
|
|
18069
|
+
await ctx.relay.sendResult(cmd.id, "completed", { conversationId: currentId });
|
|
18070
|
+
} catch {
|
|
18071
|
+
await ctx.relay.sendResult(cmd.id, "failed", {});
|
|
18072
|
+
}
|
|
18073
|
+
};
|
|
18074
|
+
var listModels = async (ctx, cmd) => {
|
|
18075
|
+
const models = await ctx.runtime.listModels();
|
|
18076
|
+
await ctx.relay.sendResult(cmd.id, "completed", { models });
|
|
18077
|
+
};
|
|
18078
|
+
var changeModel = async (ctx, cmd) => {
|
|
18079
|
+
const params = cmd.payload;
|
|
18080
|
+
if (typeof params.modelId !== "string" || !params.modelId) {
|
|
18081
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: "modelId required" });
|
|
18082
|
+
return;
|
|
18083
|
+
}
|
|
18084
|
+
const instr = ctx.runtime.changeModelInstruction(params.modelId);
|
|
18085
|
+
if (instr.type === "pty") {
|
|
18086
|
+
if (!instr.ptyInput) {
|
|
18087
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: "no pty input for this agent" });
|
|
18088
|
+
return;
|
|
18089
|
+
}
|
|
18090
|
+
ctx.agent.sendRawPtyInput(instr.ptyInput);
|
|
18091
|
+
} else if (instr.type === "restart") {
|
|
18092
|
+
await ctx.relay.sendResult(cmd.id, "failed", { error: "restart-mode change_model not supported in Phase 1" });
|
|
18093
|
+
return;
|
|
18094
|
+
}
|
|
18095
|
+
await ctx.relay.sendResult(cmd.id, "completed", {});
|
|
18096
|
+
};
|
|
18097
|
+
var summarize = async (ctx, cmd) => {
|
|
18098
|
+
const params = cmd.payload;
|
|
18099
|
+
const mode = params.mode === "auto" ? "auto" : "normal";
|
|
18100
|
+
const instr = ctx.runtime.summarizeInstruction(mode);
|
|
18101
|
+
ctx.agent.sendRawPtyInput(instr.ptyInput);
|
|
18102
|
+
await ctx.relay.sendResult(cmd.id, "completed", {});
|
|
18103
|
+
};
|
|
18104
|
+
var setKeepAlive = async (ctx, cmd) => {
|
|
18105
|
+
const enabled = !!cmd.payload.enabled;
|
|
18106
|
+
ctx.setKeepAlive(enabled);
|
|
18107
|
+
try {
|
|
18108
|
+
await ctx.relay.sendResult(
|
|
18109
|
+
cmd.id,
|
|
18110
|
+
"success",
|
|
18111
|
+
{
|
|
18112
|
+
enabled,
|
|
18113
|
+
applied: enabled && ctx.keepAliveCtx.inCodespace,
|
|
18114
|
+
runtime: ctx.keepAliveCtx.inCodespace ? "github-codespaces" : "local"
|
|
18115
|
+
}
|
|
18116
|
+
);
|
|
18117
|
+
} catch {
|
|
18118
|
+
}
|
|
18119
|
+
};
|
|
18120
|
+
var sessionTerminated = async (ctx, cmd) => {
|
|
18121
|
+
showInfo("Session was deleted from the app \u2014 exiting.");
|
|
18122
|
+
try {
|
|
18123
|
+
await ctx.relay.sendResult(cmd.id, "success", { ok: true });
|
|
18124
|
+
} catch {
|
|
18125
|
+
}
|
|
18126
|
+
try {
|
|
18127
|
+
removeSession(ctx.sessionId);
|
|
18128
|
+
} catch {
|
|
18129
|
+
}
|
|
18130
|
+
try {
|
|
18131
|
+
ctx.agent.kill();
|
|
18132
|
+
} catch {
|
|
18133
|
+
}
|
|
18134
|
+
try {
|
|
18135
|
+
const proc = (0, import_child_process15.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
17342
18136
|
detached: true,
|
|
17343
18137
|
stdio: "ignore"
|
|
17344
18138
|
});
|
|
@@ -17360,7 +18154,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
17360
18154
|
}
|
|
17361
18155
|
if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
|
|
17362
18156
|
try {
|
|
17363
|
-
const stopProc = (0,
|
|
18157
|
+
const stopProc = (0, import_child_process15.spawn)(
|
|
17364
18158
|
"bash",
|
|
17365
18159
|
["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
|
|
17366
18160
|
{ detached: true, stdio: "ignore" }
|
|
@@ -17370,7 +18164,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
17370
18164
|
}
|
|
17371
18165
|
}
|
|
17372
18166
|
try {
|
|
17373
|
-
const proc = (0,
|
|
18167
|
+
const proc = (0, import_child_process15.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
17374
18168
|
detached: true,
|
|
17375
18169
|
stdio: "ignore"
|
|
17376
18170
|
});
|
|
@@ -17786,8 +18580,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
|
|
|
17786
18580
|
if (args2.length === 0) return detection;
|
|
17787
18581
|
const binName = args2[0];
|
|
17788
18582
|
if (binName.startsWith("-")) return detection;
|
|
17789
|
-
const binPath =
|
|
17790
|
-
if (!
|
|
18583
|
+
const binPath = path39.join(cwd, "node_modules", ".bin", binName);
|
|
18584
|
+
if (!fs32.existsSync(binPath)) return detection;
|
|
17791
18585
|
return {
|
|
17792
18586
|
...detection,
|
|
17793
18587
|
command: binPath,
|
|
@@ -17877,7 +18671,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
17877
18671
|
"BOOT_SEQUENCE",
|
|
17878
18672
|
`${spawnable.command} ${spawnable.args.join(" ")}`
|
|
17879
18673
|
);
|
|
17880
|
-
const devServer = (0,
|
|
18674
|
+
const devServer = (0, import_child_process15.spawn)(spawnable.command, spawnable.args, {
|
|
17881
18675
|
cwd: process.cwd(),
|
|
17882
18676
|
env: { ...process.env, ...spawnable.env ?? {} },
|
|
17883
18677
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18003,7 +18797,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
|
|
|
18003
18797
|
});
|
|
18004
18798
|
return;
|
|
18005
18799
|
}
|
|
18006
|
-
tunnel = (0,
|
|
18800
|
+
tunnel = (0, import_child_process15.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
|
|
18007
18801
|
stdio: ["ignore", "pipe", "pipe"]
|
|
18008
18802
|
});
|
|
18009
18803
|
let parsedUrl = null;
|
|
@@ -18100,8 +18894,8 @@ var previewStopH = (ctx) => {
|
|
|
18100
18894
|
})();
|
|
18101
18895
|
};
|
|
18102
18896
|
function runOnce(cmd, args2, cwd, env) {
|
|
18103
|
-
return new Promise((
|
|
18104
|
-
const child = (0,
|
|
18897
|
+
return new Promise((resolve7) => {
|
|
18898
|
+
const child = (0, import_child_process15.spawn)(cmd, args2, {
|
|
18105
18899
|
cwd,
|
|
18106
18900
|
env: { ...process.env, ...env ?? {} },
|
|
18107
18901
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -18114,8 +18908,8 @@ function runOnce(cmd, args2, cwd, env) {
|
|
|
18114
18908
|
};
|
|
18115
18909
|
child.stdout?.on("data", onChunk);
|
|
18116
18910
|
child.stderr?.on("data", onChunk);
|
|
18117
|
-
child.once("exit", (code) =>
|
|
18118
|
-
child.once("error", () =>
|
|
18911
|
+
child.once("exit", (code) => resolve7(code));
|
|
18912
|
+
child.once("error", () => resolve7(-1));
|
|
18119
18913
|
});
|
|
18120
18914
|
}
|
|
18121
18915
|
var savePreviewConfigH = (_ctx, _cmd, parsed) => {
|
|
@@ -18169,6 +18963,23 @@ var handlers = {
|
|
|
18169
18963
|
save_preview_config: savePreviewConfigH
|
|
18170
18964
|
};
|
|
18171
18965
|
async function dispatchCommand(ctx, cmd) {
|
|
18966
|
+
if (cmd.type === "beads_action") {
|
|
18967
|
+
if (!ctx.beads) {
|
|
18968
|
+
log.trace("beads", "beads_action received but beads not running this session \u2014 dropping");
|
|
18969
|
+
return;
|
|
18970
|
+
}
|
|
18971
|
+
const action = beadsActionFromPayload(cmd.payload);
|
|
18972
|
+
if (!action) {
|
|
18973
|
+
log.warn("beads", "malformed beads_action payload \u2014 dropping");
|
|
18974
|
+
return;
|
|
18975
|
+
}
|
|
18976
|
+
try {
|
|
18977
|
+
await handleBeadsActionCommand(action, ctx.beads);
|
|
18978
|
+
} catch (err) {
|
|
18979
|
+
log.warn("beads", "handleBeadsActionCommand failed (non-fatal)", err);
|
|
18980
|
+
}
|
|
18981
|
+
return;
|
|
18982
|
+
}
|
|
18172
18983
|
const parsed = parsePayload2(startCommandSchema, cmd.payload);
|
|
18173
18984
|
if (!parsed) {
|
|
18174
18985
|
showInfo(`Ignoring malformed ${cmd.type} payload.`);
|
|
@@ -18180,10 +18991,10 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
18180
18991
|
}
|
|
18181
18992
|
|
|
18182
18993
|
// src/services/file-watcher.service.ts
|
|
18183
|
-
var
|
|
18184
|
-
var
|
|
18185
|
-
var
|
|
18186
|
-
var
|
|
18994
|
+
var import_child_process16 = require("child_process");
|
|
18995
|
+
var fs33 = __toESM(require("fs"));
|
|
18996
|
+
var os26 = __toESM(require("os"));
|
|
18997
|
+
var path40 = __toESM(require("path"));
|
|
18187
18998
|
var import_ignore = __toESM(require("ignore"));
|
|
18188
18999
|
|
|
18189
19000
|
// src/services/file-watcher/diff-parser.ts
|
|
@@ -18272,58 +19083,9 @@ function isIgnoredFilePath(filePath) {
|
|
|
18272
19083
|
return IGNORED_PATH_PATTERN.test(filePath);
|
|
18273
19084
|
}
|
|
18274
19085
|
|
|
18275
|
-
// src/services/file-watcher/transport.ts
|
|
18276
|
-
var http5 = __toESM(require("http"));
|
|
18277
|
-
var https5 = __toESM(require("https"));
|
|
18278
|
-
var _transport3 = {
|
|
18279
|
-
post: _post2
|
|
18280
|
-
};
|
|
18281
|
-
function _post2(url, headers, payload) {
|
|
18282
|
-
return new Promise((resolve6, reject) => {
|
|
18283
|
-
let settled = false;
|
|
18284
|
-
const u2 = new URL(url);
|
|
18285
|
-
const lib = u2.protocol === "https:" ? https5 : http5;
|
|
18286
|
-
const req = lib.request(
|
|
18287
|
-
{
|
|
18288
|
-
hostname: u2.hostname,
|
|
18289
|
-
port: u2.port || (u2.protocol === "https:" ? 443 : 80),
|
|
18290
|
-
path: u2.pathname + u2.search,
|
|
18291
|
-
method: "POST",
|
|
18292
|
-
headers: {
|
|
18293
|
-
...headers,
|
|
18294
|
-
...vercelBypassHeader(),
|
|
18295
|
-
"Content-Length": Buffer.byteLength(payload)
|
|
18296
|
-
},
|
|
18297
|
-
timeout: 8e3
|
|
18298
|
-
},
|
|
18299
|
-
(res) => {
|
|
18300
|
-
let body = "";
|
|
18301
|
-
res.on("data", (c2) => {
|
|
18302
|
-
body += c2.toString();
|
|
18303
|
-
});
|
|
18304
|
-
res.on("end", () => {
|
|
18305
|
-
if (settled) return;
|
|
18306
|
-
settled = true;
|
|
18307
|
-
resolve6({ statusCode: res.statusCode ?? 0, body });
|
|
18308
|
-
});
|
|
18309
|
-
}
|
|
18310
|
-
);
|
|
18311
|
-
req.on("error", (err) => {
|
|
18312
|
-
if (settled) return;
|
|
18313
|
-
settled = true;
|
|
18314
|
-
reject(err);
|
|
18315
|
-
});
|
|
18316
|
-
req.on("timeout", () => {
|
|
18317
|
-
req.destroy();
|
|
18318
|
-
});
|
|
18319
|
-
req.write(payload);
|
|
18320
|
-
req.end();
|
|
18321
|
-
});
|
|
18322
|
-
}
|
|
18323
|
-
|
|
18324
19086
|
// src/services/file-watcher.service.ts
|
|
18325
|
-
var
|
|
18326
|
-
var
|
|
19087
|
+
var API_BASE5 = resolveApiBaseUrl();
|
|
19088
|
+
var DEBOUNCE_MS2 = 250;
|
|
18327
19089
|
var COALESCE_WINDOW_MS = 250;
|
|
18328
19090
|
var COALESCE_MAX_HOLD_MS = 2e3;
|
|
18329
19091
|
var MAX_RETRIES = 2;
|
|
@@ -18342,10 +19104,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
|
|
|
18342
19104
|
/[\\/]Start Menu([\\/]|$)/i,
|
|
18343
19105
|
/[\\/]Templates([\\/]|$)/i
|
|
18344
19106
|
];
|
|
18345
|
-
function isUnsafeWindowsWatchRoot(dir,
|
|
19107
|
+
function isUnsafeWindowsWatchRoot(dir, homedir22) {
|
|
18346
19108
|
const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
18347
19109
|
const cwd = norm(dir);
|
|
18348
|
-
const home = norm(
|
|
19110
|
+
const home = norm(homedir22);
|
|
18349
19111
|
if (cwd === home) return true;
|
|
18350
19112
|
if (/^[a-z]:$/.test(cwd)) return true;
|
|
18351
19113
|
const sysRoots = [
|
|
@@ -18359,7 +19121,7 @@ function isUnsafeWindowsWatchRoot(dir, homedir21) {
|
|
|
18359
19121
|
}
|
|
18360
19122
|
return false;
|
|
18361
19123
|
}
|
|
18362
|
-
var
|
|
19124
|
+
var _chokidarSeam2 = {
|
|
18363
19125
|
load: () => {
|
|
18364
19126
|
try {
|
|
18365
19127
|
return require("chokidar");
|
|
@@ -18375,18 +19137,18 @@ var _findGitRootSeam = {
|
|
|
18375
19137
|
resolve: _defaultFindGitRoot
|
|
18376
19138
|
};
|
|
18377
19139
|
function _defaultFindGitRoot(startDir) {
|
|
18378
|
-
let dir =
|
|
19140
|
+
let dir = path40.resolve(startDir);
|
|
18379
19141
|
const seen = /* @__PURE__ */ new Set();
|
|
18380
19142
|
for (let i = 0; i < 256; i++) {
|
|
18381
19143
|
if (seen.has(dir)) return null;
|
|
18382
19144
|
seen.add(dir);
|
|
18383
19145
|
try {
|
|
18384
|
-
const gitPath =
|
|
18385
|
-
const stat3 =
|
|
19146
|
+
const gitPath = path40.join(dir, ".git");
|
|
19147
|
+
const stat3 = fs33.statSync(gitPath, { throwIfNoEntry: false });
|
|
18386
19148
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
18387
19149
|
} catch {
|
|
18388
19150
|
}
|
|
18389
|
-
const parent =
|
|
19151
|
+
const parent = path40.dirname(dir);
|
|
18390
19152
|
if (parent === dir) return null;
|
|
18391
19153
|
dir = parent;
|
|
18392
19154
|
}
|
|
@@ -18395,7 +19157,7 @@ function _defaultFindGitRoot(startDir) {
|
|
|
18395
19157
|
var FileWatcherService = class {
|
|
18396
19158
|
constructor(opts) {
|
|
18397
19159
|
this.opts = opts;
|
|
18398
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
19160
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE5;
|
|
18399
19161
|
}
|
|
18400
19162
|
opts;
|
|
18401
19163
|
watcher = null;
|
|
@@ -18444,14 +19206,14 @@ var FileWatcherService = class {
|
|
|
18444
19206
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
18445
19207
|
}
|
|
18446
19208
|
const isWin = process.platform === "win32";
|
|
18447
|
-
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir,
|
|
19209
|
+
if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os26.homedir())) {
|
|
18448
19210
|
log.warn(
|
|
18449
19211
|
"fileWatcher",
|
|
18450
19212
|
`refusing to watch ${this.opts.workingDir} \u2014 looks like a Windows user-profile or system path. Run codeam from your project folder to enable file change emission.`
|
|
18451
19213
|
);
|
|
18452
19214
|
return;
|
|
18453
19215
|
}
|
|
18454
|
-
const chokidar2 =
|
|
19216
|
+
const chokidar2 = _chokidarSeam2.load();
|
|
18455
19217
|
if (!chokidar2) {
|
|
18456
19218
|
log.warn(
|
|
18457
19219
|
"fileWatcher",
|
|
@@ -18570,7 +19332,7 @@ var FileWatcherService = class {
|
|
|
18570
19332
|
const timer = setTimeout(() => {
|
|
18571
19333
|
this.pending.delete(absPath);
|
|
18572
19334
|
this.enqueueForCoalesce(absPath, changeType);
|
|
18573
|
-
},
|
|
19335
|
+
}, DEBOUNCE_MS2);
|
|
18574
19336
|
this.pending.set(absPath, {
|
|
18575
19337
|
lastEventAt: Date.now(),
|
|
18576
19338
|
timer,
|
|
@@ -18631,7 +19393,7 @@ var FileWatcherService = class {
|
|
|
18631
19393
|
}
|
|
18632
19394
|
async emitForFile(absPath, changeType) {
|
|
18633
19395
|
if (this.stopped) return;
|
|
18634
|
-
const fileDir =
|
|
19396
|
+
const fileDir = path40.dirname(absPath);
|
|
18635
19397
|
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
18636
19398
|
if (gitRoot === void 0) {
|
|
18637
19399
|
gitRoot = findGitRoot2(fileDir);
|
|
@@ -18644,19 +19406,19 @@ var FileWatcherService = class {
|
|
|
18644
19406
|
);
|
|
18645
19407
|
return;
|
|
18646
19408
|
}
|
|
18647
|
-
const relPathInRepo =
|
|
19409
|
+
const relPathInRepo = path40.relative(gitRoot, absPath);
|
|
18648
19410
|
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
18649
19411
|
const matcher = this.getGitIgnoreMatcher(gitRoot);
|
|
18650
19412
|
if (matcher && matcher.ignores(relPathInRepo)) {
|
|
18651
19413
|
log.trace(
|
|
18652
19414
|
"fileWatcher",
|
|
18653
|
-
`${relPathInRepo} ignored by ${
|
|
19415
|
+
`${relPathInRepo} ignored by ${path40.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
|
|
18654
19416
|
);
|
|
18655
19417
|
return;
|
|
18656
19418
|
}
|
|
18657
19419
|
this.opts.onRepoDirty?.(gitRoot);
|
|
18658
|
-
const repoPath =
|
|
18659
|
-
const repoName =
|
|
19420
|
+
const repoPath = path40.relative(this.opts.workingDir, gitRoot);
|
|
19421
|
+
const repoName = path40.basename(gitRoot);
|
|
18660
19422
|
let diffText = "";
|
|
18661
19423
|
let fileStatus = "modified";
|
|
18662
19424
|
if (changeType === "unlink") {
|
|
@@ -18831,7 +19593,7 @@ var FileWatcherService = class {
|
|
|
18831
19593
|
collectGitignoreFiles(repoRoot, dir, matcher) {
|
|
18832
19594
|
let entries;
|
|
18833
19595
|
try {
|
|
18834
|
-
entries =
|
|
19596
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
18835
19597
|
} catch {
|
|
18836
19598
|
return;
|
|
18837
19599
|
}
|
|
@@ -18840,16 +19602,16 @@ var FileWatcherService = class {
|
|
|
18840
19602
|
);
|
|
18841
19603
|
if (gitignoreEntry) {
|
|
18842
19604
|
try {
|
|
18843
|
-
const body =
|
|
18844
|
-
const rel =
|
|
19605
|
+
const body = fs33.readFileSync(path40.join(dir, ".gitignore"), "utf8");
|
|
19606
|
+
const rel = path40.relative(repoRoot, dir).replace(/\\/g, "/");
|
|
18845
19607
|
const prefixed = body.split(/\r?\n/).map((line) => {
|
|
18846
19608
|
const trimmed = line.trim();
|
|
18847
19609
|
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
18848
19610
|
if (!rel) return line;
|
|
18849
19611
|
if (trimmed.startsWith("!")) {
|
|
18850
|
-
return "!" +
|
|
19612
|
+
return "!" + path40.posix.join(rel, trimmed.slice(1));
|
|
18851
19613
|
}
|
|
18852
|
-
return
|
|
19614
|
+
return path40.posix.join(rel, trimmed);
|
|
18853
19615
|
}).join("\n");
|
|
18854
19616
|
matcher.add(prefixed);
|
|
18855
19617
|
} catch {
|
|
@@ -18858,7 +19620,7 @@ var FileWatcherService = class {
|
|
|
18858
19620
|
for (const entry of entries) {
|
|
18859
19621
|
if (!entry.isDirectory()) continue;
|
|
18860
19622
|
if (entry.name === ".git") continue;
|
|
18861
|
-
const childAbs =
|
|
19623
|
+
const childAbs = path40.join(dir, entry.name);
|
|
18862
19624
|
if (isIgnoredFilePath(childAbs)) continue;
|
|
18863
19625
|
this.collectGitignoreFiles(repoRoot, childAbs, matcher);
|
|
18864
19626
|
}
|
|
@@ -18992,12 +19754,12 @@ var _gitSeam = {
|
|
|
18992
19754
|
run: _runGitImpl
|
|
18993
19755
|
};
|
|
18994
19756
|
async function _runGitImpl(cwd, args2, opts = {}) {
|
|
18995
|
-
return new Promise((
|
|
19757
|
+
return new Promise((resolve7) => {
|
|
18996
19758
|
let proc;
|
|
18997
19759
|
try {
|
|
18998
|
-
proc = (0,
|
|
19760
|
+
proc = (0, import_child_process16.spawn)("git", args2, { cwd, env: process.env });
|
|
18999
19761
|
} catch {
|
|
19000
|
-
|
|
19762
|
+
resolve7(null);
|
|
19001
19763
|
return;
|
|
19002
19764
|
}
|
|
19003
19765
|
let stdout = "";
|
|
@@ -19008,13 +19770,13 @@ async function _runGitImpl(cwd, args2, opts = {}) {
|
|
|
19008
19770
|
proc.stderr?.on("data", (c2) => {
|
|
19009
19771
|
stderr += c2.toString();
|
|
19010
19772
|
});
|
|
19011
|
-
proc.on("error", () =>
|
|
19773
|
+
proc.on("error", () => resolve7(null));
|
|
19012
19774
|
proc.on("close", (code) => {
|
|
19013
19775
|
if (code === 0 || opts.allowNonZeroExit) {
|
|
19014
|
-
|
|
19776
|
+
resolve7(stdout);
|
|
19015
19777
|
} else {
|
|
19016
19778
|
log.trace("fileWatcher", `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`);
|
|
19017
|
-
|
|
19779
|
+
resolve7(null);
|
|
19018
19780
|
}
|
|
19019
19781
|
});
|
|
19020
19782
|
});
|
|
@@ -19027,8 +19789,8 @@ function _runGit(cwd, args2, opts = {}) {
|
|
|
19027
19789
|
var import_crypto4 = require("crypto");
|
|
19028
19790
|
|
|
19029
19791
|
// src/services/turn-files/git-changeset.ts
|
|
19030
|
-
var
|
|
19031
|
-
var
|
|
19792
|
+
var import_child_process17 = require("child_process");
|
|
19793
|
+
var path41 = __toESM(require("path"));
|
|
19032
19794
|
async function collectRepoChangeset(opts) {
|
|
19033
19795
|
const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
|
|
19034
19796
|
if (status2 === null) return null;
|
|
@@ -19108,12 +19870,12 @@ function runGit3(cwd, args2) {
|
|
|
19108
19870
|
return _runGitImpl2.run(cwd, args2);
|
|
19109
19871
|
}
|
|
19110
19872
|
function defaultRunGit(cwd, args2) {
|
|
19111
|
-
return new Promise((
|
|
19873
|
+
return new Promise((resolve7) => {
|
|
19112
19874
|
let proc;
|
|
19113
19875
|
try {
|
|
19114
|
-
proc = (0,
|
|
19876
|
+
proc = (0, import_child_process17.spawn)("git", args2, { cwd, env: process.env });
|
|
19115
19877
|
} catch {
|
|
19116
|
-
|
|
19878
|
+
resolve7(null);
|
|
19117
19879
|
return;
|
|
19118
19880
|
}
|
|
19119
19881
|
let stdout = "";
|
|
@@ -19124,22 +19886,22 @@ function defaultRunGit(cwd, args2) {
|
|
|
19124
19886
|
proc.stderr?.on("data", (c2) => {
|
|
19125
19887
|
stderr += c2.toString();
|
|
19126
19888
|
});
|
|
19127
|
-
proc.on("error", () =>
|
|
19889
|
+
proc.on("error", () => resolve7(null));
|
|
19128
19890
|
proc.on("close", (code) => {
|
|
19129
19891
|
if (code === 0) {
|
|
19130
|
-
|
|
19892
|
+
resolve7(stdout);
|
|
19131
19893
|
} else {
|
|
19132
19894
|
log.trace(
|
|
19133
19895
|
"turnFiles",
|
|
19134
19896
|
`git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`
|
|
19135
19897
|
);
|
|
19136
|
-
|
|
19898
|
+
resolve7(null);
|
|
19137
19899
|
}
|
|
19138
19900
|
});
|
|
19139
19901
|
});
|
|
19140
19902
|
}
|
|
19141
19903
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
19142
|
-
const
|
|
19904
|
+
const fs39 = await import("fs/promises");
|
|
19143
19905
|
const out2 = [];
|
|
19144
19906
|
await walk(workingDir, 0);
|
|
19145
19907
|
return out2;
|
|
@@ -19147,7 +19909,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19147
19909
|
if (depth > maxDepth) return;
|
|
19148
19910
|
let entries = [];
|
|
19149
19911
|
try {
|
|
19150
|
-
const dirents = await
|
|
19912
|
+
const dirents = await fs39.readdir(dir, { withFileTypes: true });
|
|
19151
19913
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
19152
19914
|
} catch {
|
|
19153
19915
|
return;
|
|
@@ -19158,8 +19920,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19158
19920
|
if (hasGit) {
|
|
19159
19921
|
out2.push({
|
|
19160
19922
|
repoRoot: dir,
|
|
19161
|
-
repoPath:
|
|
19162
|
-
repoName:
|
|
19923
|
+
repoPath: path41.relative(workingDir, dir),
|
|
19924
|
+
repoName: path41.basename(dir)
|
|
19163
19925
|
});
|
|
19164
19926
|
return;
|
|
19165
19927
|
}
|
|
@@ -19167,14 +19929,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
19167
19929
|
if (!entry.isDirectory) continue;
|
|
19168
19930
|
if (entry.name === "node_modules") continue;
|
|
19169
19931
|
if (entry.name === "dist" || entry.name === "build") continue;
|
|
19170
|
-
await walk(
|
|
19932
|
+
await walk(path41.join(dir, entry.name), depth + 1);
|
|
19171
19933
|
}
|
|
19172
19934
|
}
|
|
19173
19935
|
}
|
|
19174
19936
|
|
|
19175
19937
|
// src/services/turn-files/files-outbox.ts
|
|
19176
|
-
var
|
|
19177
|
-
var
|
|
19938
|
+
var fs34 = __toESM(require("fs/promises"));
|
|
19939
|
+
var path42 = __toESM(require("path"));
|
|
19178
19940
|
var import_os7 = require("os");
|
|
19179
19941
|
var HOME_OUTBOX_DIR = ".codeam/outbox";
|
|
19180
19942
|
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -19207,16 +19969,16 @@ var FilesOutbox = class {
|
|
|
19207
19969
|
backoffIndex = 0;
|
|
19208
19970
|
stopped = false;
|
|
19209
19971
|
constructor(opts) {
|
|
19210
|
-
const base = opts.baseDir ??
|
|
19211
|
-
this.filePath =
|
|
19972
|
+
const base = opts.baseDir ?? path42.join(homeDir(), HOME_OUTBOX_DIR);
|
|
19973
|
+
this.filePath = path42.join(base, `${opts.sessionId}.jsonl`);
|
|
19212
19974
|
this.post = opts.post;
|
|
19213
19975
|
this.autoSchedule = opts.autoSchedule !== false;
|
|
19214
19976
|
}
|
|
19215
19977
|
/** Persist the entry to disk and trigger a flush. Returns once the
|
|
19216
19978
|
* line is durable on disk (not once the POST succeeds). */
|
|
19217
19979
|
async enqueue(entry) {
|
|
19218
|
-
await
|
|
19219
|
-
await
|
|
19980
|
+
await fs34.mkdir(path42.dirname(this.filePath), { recursive: true });
|
|
19981
|
+
await fs34.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
|
|
19220
19982
|
this.backoffIndex = 0;
|
|
19221
19983
|
if (this.autoSchedule) this.scheduleFlush(0);
|
|
19222
19984
|
}
|
|
@@ -19305,7 +20067,7 @@ var FilesOutbox = class {
|
|
|
19305
20067
|
async readAll() {
|
|
19306
20068
|
let raw = "";
|
|
19307
20069
|
try {
|
|
19308
|
-
raw = await
|
|
20070
|
+
raw = await fs34.readFile(this.filePath, "utf8");
|
|
19309
20071
|
} catch {
|
|
19310
20072
|
return [];
|
|
19311
20073
|
}
|
|
@@ -19329,12 +20091,12 @@ var FilesOutbox = class {
|
|
|
19329
20091
|
async rewrite(entries) {
|
|
19330
20092
|
const tmpPath = `${this.filePath}.${process.pid}.tmp`;
|
|
19331
20093
|
if (entries.length === 0) {
|
|
19332
|
-
await
|
|
20094
|
+
await fs34.unlink(this.filePath).catch(() => void 0);
|
|
19333
20095
|
return;
|
|
19334
20096
|
}
|
|
19335
20097
|
const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
19336
|
-
await
|
|
19337
|
-
await
|
|
20098
|
+
await fs34.writeFile(tmpPath, payload, "utf8");
|
|
20099
|
+
await fs34.rename(tmpPath, this.filePath);
|
|
19338
20100
|
}
|
|
19339
20101
|
};
|
|
19340
20102
|
function applyJitter(ms) {
|
|
@@ -19346,13 +20108,13 @@ function homeDir() {
|
|
|
19346
20108
|
}
|
|
19347
20109
|
|
|
19348
20110
|
// src/services/turn-files/turn-file-aggregator.ts
|
|
19349
|
-
var
|
|
20111
|
+
var API_BASE6 = resolveApiBaseUrl();
|
|
19350
20112
|
var ENDPOINT = "/api/files/batch";
|
|
19351
20113
|
var MAX_BATCH_SIZE = 1e3;
|
|
19352
20114
|
var TurnFileAggregator = class {
|
|
19353
20115
|
constructor(opts) {
|
|
19354
20116
|
this.opts = opts;
|
|
19355
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
20117
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE6;
|
|
19356
20118
|
this.outbox = new FilesOutbox({
|
|
19357
20119
|
sessionId: opts.sessionId,
|
|
19358
20120
|
baseDir: opts.outboxDir,
|
|
@@ -19544,7 +20306,7 @@ var StreamingState = class {
|
|
|
19544
20306
|
* default-reject. Caller is the SDK's `onRequestPermission`.
|
|
19545
20307
|
*/
|
|
19546
20308
|
registerPermission(args2) {
|
|
19547
|
-
return new Promise((
|
|
20309
|
+
return new Promise((resolve7) => {
|
|
19548
20310
|
const timeoutTimer = setTimeout(() => {
|
|
19549
20311
|
if (this.pending?.kind === "permission" && this.pending.questionId === args2.questionId) {
|
|
19550
20312
|
log.warn(
|
|
@@ -19552,7 +20314,7 @@ var StreamingState = class {
|
|
|
19552
20314
|
`permission ${args2.questionId.slice(0, 8)} TTL expired \u2014 auto-cancel`
|
|
19553
20315
|
);
|
|
19554
20316
|
this.pending = null;
|
|
19555
|
-
|
|
20317
|
+
resolve7({ outcome: { outcome: "cancelled" } });
|
|
19556
20318
|
}
|
|
19557
20319
|
}, PERMISSION_TIMEOUT_MS);
|
|
19558
20320
|
this.pending = {
|
|
@@ -19560,7 +20322,7 @@ var StreamingState = class {
|
|
|
19560
20322
|
questionId: args2.questionId,
|
|
19561
20323
|
labels: args2.labels,
|
|
19562
20324
|
optionIdByLabel: args2.optionIdByLabel,
|
|
19563
|
-
resolve:
|
|
20325
|
+
resolve: resolve7,
|
|
19564
20326
|
timeoutTimer
|
|
19565
20327
|
};
|
|
19566
20328
|
});
|
|
@@ -19592,14 +20354,14 @@ var StreamingState = class {
|
|
|
19592
20354
|
const label = this.pending.labels[index];
|
|
19593
20355
|
const optionId = label ? this.pending.optionIdByLabel[label] : void 0;
|
|
19594
20356
|
clearTimeout(this.pending.timeoutTimer);
|
|
19595
|
-
const
|
|
20357
|
+
const resolve7 = this.pending.resolve;
|
|
19596
20358
|
this.pending = null;
|
|
19597
20359
|
if (!optionId) {
|
|
19598
20360
|
log.warn("acpRunner", `select_option index=${index} out of bounds \u2014 cancel`);
|
|
19599
|
-
|
|
20361
|
+
resolve7({ outcome: { outcome: "cancelled" } });
|
|
19600
20362
|
return { kind: "resolved" };
|
|
19601
20363
|
}
|
|
19602
|
-
|
|
20364
|
+
resolve7({ outcome: { outcome: "selected", optionId } });
|
|
19603
20365
|
return { kind: "resolved" };
|
|
19604
20366
|
}
|
|
19605
20367
|
const text = this.pending.options[index];
|
|
@@ -19955,6 +20717,7 @@ async function runAcpSession(opts) {
|
|
|
19955
20717
|
}).catch((err) => {
|
|
19956
20718
|
log.warn("acpRunner", `fileWatcher.start failed: ${describeError(err)}`);
|
|
19957
20719
|
});
|
|
20720
|
+
const getBeads = opts.getBeads ?? (() => null);
|
|
19958
20721
|
const relay = new CommandRelayService(
|
|
19959
20722
|
opts.pluginId,
|
|
19960
20723
|
async (cmd) => {
|
|
@@ -19968,7 +20731,8 @@ async function runAcpSession(opts) {
|
|
|
19968
20731
|
opts,
|
|
19969
20732
|
history,
|
|
19970
20733
|
initialize.agentCapabilities,
|
|
19971
|
-
turnFiles
|
|
20734
|
+
turnFiles,
|
|
20735
|
+
getBeads
|
|
19972
20736
|
);
|
|
19973
20737
|
},
|
|
19974
20738
|
{ id: opts.agent, name: opts.agent, displayName: opts.agent }
|
|
@@ -19989,8 +20753,24 @@ async function runAcpSession(opts) {
|
|
|
19989
20753
|
await new Promise(() => {
|
|
19990
20754
|
});
|
|
19991
20755
|
}
|
|
19992
|
-
async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, agentCaps, turnFiles) {
|
|
20756
|
+
async function handleCommand(cmd, client2, relay, acpSessionId, models, streaming, opts, history, agentCaps, turnFiles, getBeads) {
|
|
19993
20757
|
switch (cmd.type) {
|
|
20758
|
+
case "beads_action": {
|
|
20759
|
+
const beads = getBeads();
|
|
20760
|
+
const action = beadsActionFromPayload(cmd.payload);
|
|
20761
|
+
if (!beads || !action) {
|
|
20762
|
+
await relay.sendResult(cmd.id, "completed", { applied: false });
|
|
20763
|
+
return;
|
|
20764
|
+
}
|
|
20765
|
+
try {
|
|
20766
|
+
await handleBeadsActionCommand(action, beads);
|
|
20767
|
+
await relay.sendResult(cmd.id, "completed", { applied: true });
|
|
20768
|
+
} catch (err) {
|
|
20769
|
+
log.warn("acpRunner", `beads_action failed (non-fatal): ${describeError(err)}`);
|
|
20770
|
+
await relay.sendResult(cmd.id, "failed", { error: describeError(err) });
|
|
20771
|
+
}
|
|
20772
|
+
return;
|
|
20773
|
+
}
|
|
19994
20774
|
case "start_task": {
|
|
19995
20775
|
const payload = cmd.payload;
|
|
19996
20776
|
const blocks = buildAcpPromptBlocks(payload ?? {});
|
|
@@ -20349,11 +21129,11 @@ var ChromeStepTracker = class {
|
|
|
20349
21129
|
// src/services/output/chunk-emitter.ts
|
|
20350
21130
|
var https6 = __toESM(require("https"));
|
|
20351
21131
|
var http6 = __toESM(require("http"));
|
|
20352
|
-
var
|
|
21132
|
+
var API_BASE7 = resolveApiBaseUrl();
|
|
20353
21133
|
async function refreshAuthToken(sessionId, pluginId) {
|
|
20354
21134
|
try {
|
|
20355
21135
|
const { statusCode, body } = await _transport4.post(
|
|
20356
|
-
`${
|
|
21136
|
+
`${API_BASE7}/api/pairing/reconnect`,
|
|
20357
21137
|
{
|
|
20358
21138
|
"Content-Type": "application/json",
|
|
20359
21139
|
"X-Codeam-Protocol-Version": PROTOCOL_VERSION,
|
|
@@ -20394,7 +21174,7 @@ var ChunkEmitter = class {
|
|
|
20394
21174
|
}
|
|
20395
21175
|
}
|
|
20396
21176
|
opts;
|
|
20397
|
-
url = `${
|
|
21177
|
+
url = `${API_BASE7}/api/commands/output`;
|
|
20398
21178
|
headers;
|
|
20399
21179
|
/**
|
|
20400
21180
|
* Send a chunk. `body` is the chunk fields minus `sessionId` /
|
|
@@ -20415,14 +21195,14 @@ var ChunkEmitter = class {
|
|
|
20415
21195
|
"chunkEmitter",
|
|
20416
21196
|
`send type=${body.type ?? "(clear)"} bytes=${payload.length} done=${body.done === true}`
|
|
20417
21197
|
);
|
|
20418
|
-
return new Promise((
|
|
21198
|
+
return new Promise((resolve7) => {
|
|
20419
21199
|
const attempt = (attemptsLeft) => {
|
|
20420
21200
|
_transport4.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
|
|
20421
21201
|
const tookMs = Date.now() - t0;
|
|
20422
21202
|
if (statusCode === 410 || statusCode === 404 && /SESSION_NOT_FOUND|SESSION_GONE/.test(resBody)) {
|
|
20423
21203
|
process.stderr.write("[codeam] session was deleted/disconnected \u2014 stopping output stream.\n");
|
|
20424
21204
|
log.info("chunkEmitter", `dead status=${statusCode} took=${tookMs}ms`);
|
|
20425
|
-
|
|
21205
|
+
resolve7({ dead: true });
|
|
20426
21206
|
return;
|
|
20427
21207
|
}
|
|
20428
21208
|
if (statusCode === 401) {
|
|
@@ -20438,7 +21218,7 @@ var ChunkEmitter = class {
|
|
|
20438
21218
|
return;
|
|
20439
21219
|
}
|
|
20440
21220
|
}
|
|
20441
|
-
|
|
21221
|
+
resolve7({ dead: false });
|
|
20442
21222
|
})();
|
|
20443
21223
|
return;
|
|
20444
21224
|
}
|
|
@@ -20449,7 +21229,7 @@ var ChunkEmitter = class {
|
|
|
20449
21229
|
} else {
|
|
20450
21230
|
log.info("chunkEmitter", `ok status=${statusCode} took=${tookMs}ms`);
|
|
20451
21231
|
}
|
|
20452
|
-
|
|
21232
|
+
resolve7({ dead: false });
|
|
20453
21233
|
}).catch((err) => {
|
|
20454
21234
|
log.warn(
|
|
20455
21235
|
"chunkEmitter",
|
|
@@ -20460,7 +21240,7 @@ var ChunkEmitter = class {
|
|
|
20460
21240
|
const delay = 200 * (maxRetries - attemptsLeft + 1);
|
|
20461
21241
|
setTimeout(() => attempt(attemptsLeft - 1), delay);
|
|
20462
21242
|
} else {
|
|
20463
|
-
|
|
21243
|
+
resolve7({ dead: false });
|
|
20464
21244
|
}
|
|
20465
21245
|
});
|
|
20466
21246
|
};
|
|
@@ -20472,7 +21252,7 @@ var _transport4 = {
|
|
|
20472
21252
|
post: _post3
|
|
20473
21253
|
};
|
|
20474
21254
|
function _post3(url, headers, payload) {
|
|
20475
|
-
return new Promise((
|
|
21255
|
+
return new Promise((resolve7, reject) => {
|
|
20476
21256
|
let settled = false;
|
|
20477
21257
|
const u2 = new URL(url);
|
|
20478
21258
|
const transport = u2.protocol === "https:" ? https6 : http6;
|
|
@@ -20496,7 +21276,7 @@ function _post3(url, headers, payload) {
|
|
|
20496
21276
|
res.on("end", () => {
|
|
20497
21277
|
if (settled) return;
|
|
20498
21278
|
settled = true;
|
|
20499
|
-
|
|
21279
|
+
resolve7({ statusCode: res.statusCode ?? 0, body: resData });
|
|
20500
21280
|
});
|
|
20501
21281
|
}
|
|
20502
21282
|
);
|
|
@@ -21070,9 +21850,9 @@ var OutputService = class _OutputService {
|
|
|
21070
21850
|
};
|
|
21071
21851
|
|
|
21072
21852
|
// src/services/history.service.ts
|
|
21073
|
-
var
|
|
21074
|
-
var
|
|
21075
|
-
var
|
|
21853
|
+
var fs35 = __toESM(require("fs"));
|
|
21854
|
+
var path43 = __toESM(require("path"));
|
|
21855
|
+
var os27 = __toESM(require("os"));
|
|
21076
21856
|
var https7 = __toESM(require("https"));
|
|
21077
21857
|
var http7 = __toESM(require("http"));
|
|
21078
21858
|
var import_zod2 = require("zod");
|
|
@@ -21086,7 +21866,7 @@ var historyRecordSchema = import_zod2.z.object({
|
|
|
21086
21866
|
content: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.unknown())]).optional()
|
|
21087
21867
|
}).passthrough().optional()
|
|
21088
21868
|
}).passthrough();
|
|
21089
|
-
var
|
|
21869
|
+
var API_BASE8 = resolveApiBaseUrl();
|
|
21090
21870
|
function extractText3(content) {
|
|
21091
21871
|
if (typeof content === "string") return content;
|
|
21092
21872
|
if (Array.isArray(content)) {
|
|
@@ -21099,7 +21879,7 @@ function parseJsonl(filePath) {
|
|
|
21099
21879
|
const messages = [];
|
|
21100
21880
|
let raw;
|
|
21101
21881
|
try {
|
|
21102
|
-
raw =
|
|
21882
|
+
raw = fs35.readFileSync(filePath, "utf8");
|
|
21103
21883
|
} catch (err) {
|
|
21104
21884
|
if (err.code !== "ENOENT") {
|
|
21105
21885
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -21136,9 +21916,9 @@ function parseJsonl(filePath) {
|
|
|
21136
21916
|
return messages;
|
|
21137
21917
|
}
|
|
21138
21918
|
function post(endpoint, body) {
|
|
21139
|
-
return new Promise((
|
|
21919
|
+
return new Promise((resolve7) => {
|
|
21140
21920
|
const payload = JSON.stringify(body);
|
|
21141
|
-
const u2 = new URL(`${
|
|
21921
|
+
const u2 = new URL(`${API_BASE8}${endpoint}`);
|
|
21142
21922
|
const transport = u2.protocol === "https:" ? https7 : http7;
|
|
21143
21923
|
const req = transport.request(
|
|
21144
21924
|
{
|
|
@@ -21157,17 +21937,17 @@ function post(endpoint, body) {
|
|
|
21157
21937
|
res.resume();
|
|
21158
21938
|
const ok = res.statusCode !== void 0 && res.statusCode >= 200 && res.statusCode < 300;
|
|
21159
21939
|
if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${res.statusCode}`);
|
|
21160
|
-
|
|
21940
|
+
resolve7(ok);
|
|
21161
21941
|
}
|
|
21162
21942
|
);
|
|
21163
21943
|
req.on("error", (err) => {
|
|
21164
21944
|
log.warn("history:post", `${endpoint} network error`, err);
|
|
21165
|
-
|
|
21945
|
+
resolve7(false);
|
|
21166
21946
|
});
|
|
21167
21947
|
req.on("timeout", () => {
|
|
21168
21948
|
log.warn("history:post", `${endpoint} timeout after 15s`);
|
|
21169
21949
|
req.destroy();
|
|
21170
|
-
|
|
21950
|
+
resolve7(false);
|
|
21171
21951
|
});
|
|
21172
21952
|
req.write(payload);
|
|
21173
21953
|
req.end();
|
|
@@ -21234,7 +22014,7 @@ var HistoryService = class _HistoryService {
|
|
|
21234
22014
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
21235
22015
|
}
|
|
21236
22016
|
get projectDir() {
|
|
21237
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
22017
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path43.join(os27.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
21238
22018
|
}
|
|
21239
22019
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
21240
22020
|
setCurrentConversationId(id) {
|
|
@@ -21246,7 +22026,7 @@ var HistoryService = class _HistoryService {
|
|
|
21246
22026
|
/** Return the current message count in the active conversation. */
|
|
21247
22027
|
getCurrentMessageCount() {
|
|
21248
22028
|
if (!this.currentConversationId) return 0;
|
|
21249
|
-
const filePath =
|
|
22029
|
+
const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21250
22030
|
return parseJsonl(filePath).length;
|
|
21251
22031
|
}
|
|
21252
22032
|
/**
|
|
@@ -21257,7 +22037,7 @@ var HistoryService = class _HistoryService {
|
|
|
21257
22037
|
const deadline = Date.now() + timeoutMs;
|
|
21258
22038
|
while (Date.now() < deadline) {
|
|
21259
22039
|
if (!this.currentConversationId) return null;
|
|
21260
|
-
const filePath =
|
|
22040
|
+
const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
21261
22041
|
const messages = parseJsonl(filePath);
|
|
21262
22042
|
if (messages.length > previousCount) {
|
|
21263
22043
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -21283,16 +22063,16 @@ var HistoryService = class _HistoryService {
|
|
|
21283
22063
|
const dir = this.projectDir;
|
|
21284
22064
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
21285
22065
|
try {
|
|
21286
|
-
const files =
|
|
22066
|
+
const files = fs35.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21287
22067
|
try {
|
|
21288
|
-
const stat3 =
|
|
22068
|
+
const stat3 = fs35.statSync(path43.join(dir, e.name));
|
|
21289
22069
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21290
22070
|
} catch {
|
|
21291
22071
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
21292
22072
|
}
|
|
21293
22073
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
21294
22074
|
if (files.length > 0) {
|
|
21295
|
-
this.currentConversationId =
|
|
22075
|
+
this.currentConversationId = path43.basename(files[0].name, ".jsonl");
|
|
21296
22076
|
}
|
|
21297
22077
|
} catch {
|
|
21298
22078
|
}
|
|
@@ -21326,13 +22106,13 @@ var HistoryService = class _HistoryService {
|
|
|
21326
22106
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
21327
22107
|
let entries;
|
|
21328
22108
|
try {
|
|
21329
|
-
entries =
|
|
22109
|
+
entries = fs35.readdirSync(dir, { withFileTypes: true });
|
|
21330
22110
|
} catch {
|
|
21331
22111
|
return null;
|
|
21332
22112
|
}
|
|
21333
22113
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
21334
22114
|
try {
|
|
21335
|
-
const stat3 =
|
|
22115
|
+
const stat3 = fs35.statSync(path43.join(dir, e.name));
|
|
21336
22116
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
21337
22117
|
} catch {
|
|
21338
22118
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -21341,12 +22121,12 @@ var HistoryService = class _HistoryService {
|
|
|
21341
22121
|
if (files.length === 0) return null;
|
|
21342
22122
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
21343
22123
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
21344
|
-
return this.extractUsageFromFile(
|
|
22124
|
+
return this.extractUsageFromFile(path43.join(dir, targetFile));
|
|
21345
22125
|
}
|
|
21346
22126
|
extractUsageFromFile(filePath) {
|
|
21347
22127
|
let raw;
|
|
21348
22128
|
try {
|
|
21349
|
-
raw =
|
|
22129
|
+
raw = fs35.readFileSync(filePath, "utf8");
|
|
21350
22130
|
} catch {
|
|
21351
22131
|
return null;
|
|
21352
22132
|
}
|
|
@@ -21391,9 +22171,9 @@ var HistoryService = class _HistoryService {
|
|
|
21391
22171
|
let totalCost = 0;
|
|
21392
22172
|
let files;
|
|
21393
22173
|
try {
|
|
21394
|
-
files =
|
|
22174
|
+
files = fs35.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
21395
22175
|
try {
|
|
21396
|
-
return
|
|
22176
|
+
return fs35.statSync(path43.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
21397
22177
|
} catch {
|
|
21398
22178
|
return false;
|
|
21399
22179
|
}
|
|
@@ -21404,7 +22184,7 @@ var HistoryService = class _HistoryService {
|
|
|
21404
22184
|
for (const file of files) {
|
|
21405
22185
|
let raw;
|
|
21406
22186
|
try {
|
|
21407
|
-
raw =
|
|
22187
|
+
raw = fs35.readFileSync(path43.join(projectDir, file), "utf8");
|
|
21408
22188
|
} catch {
|
|
21409
22189
|
continue;
|
|
21410
22190
|
}
|
|
@@ -21468,7 +22248,7 @@ var HistoryService = class _HistoryService {
|
|
|
21468
22248
|
* showing an empty conversation.
|
|
21469
22249
|
*/
|
|
21470
22250
|
async loadConversation(sessionId) {
|
|
21471
|
-
const filePath =
|
|
22251
|
+
const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21472
22252
|
const messages = parseJsonl(filePath);
|
|
21473
22253
|
if (messages.length === 0) return;
|
|
21474
22254
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -21522,7 +22302,7 @@ var HistoryService = class _HistoryService {
|
|
|
21522
22302
|
if (!this.currentConversationId) return 0;
|
|
21523
22303
|
}
|
|
21524
22304
|
const sessionId = this.currentConversationId;
|
|
21525
|
-
const filePath =
|
|
22305
|
+
const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
|
|
21526
22306
|
const messages = parseJsonl(filePath);
|
|
21527
22307
|
if (messages.length === 0) return 0;
|
|
21528
22308
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -21587,7 +22367,7 @@ var RepoDirtyTracker = class {
|
|
|
21587
22367
|
|
|
21588
22368
|
// src/services/streaming-emitter.service.ts
|
|
21589
22369
|
var import_crypto5 = require("crypto");
|
|
21590
|
-
var
|
|
22370
|
+
var API_BASE9 = resolveApiBaseUrl();
|
|
21591
22371
|
var TICK_MS = 50;
|
|
21592
22372
|
var ANSWER_POLL_MS = 1500;
|
|
21593
22373
|
var SELECTOR_STABLE_MS = 800;
|
|
@@ -21598,7 +22378,7 @@ var TAIL_KEEP_BYTES2 = 1.5 * 1024 * 1024;
|
|
|
21598
22378
|
var StreamingEmitterService = class {
|
|
21599
22379
|
constructor(opts) {
|
|
21600
22380
|
this.opts = opts;
|
|
21601
|
-
this.apiBase = opts.apiBaseUrl ??
|
|
22381
|
+
this.apiBase = opts.apiBaseUrl ?? API_BASE9;
|
|
21602
22382
|
this.headers = {
|
|
21603
22383
|
"Content-Type": "application/json",
|
|
21604
22384
|
"X-Codeam-Protocol-Version": "2.0.0",
|
|
@@ -21948,13 +22728,13 @@ function fetchQuotaUsage(runtime, historySvc) {
|
|
|
21948
22728
|
}
|
|
21949
22729
|
|
|
21950
22730
|
// src/commands/start/keep-alive.ts
|
|
21951
|
-
var
|
|
22731
|
+
var import_child_process18 = require("child_process");
|
|
21952
22732
|
function buildKeepAlive(ctx) {
|
|
21953
22733
|
let timer = null;
|
|
21954
22734
|
async function setIdleTimeout(minutes) {
|
|
21955
22735
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
21956
|
-
await new Promise((
|
|
21957
|
-
const proc = (0,
|
|
22736
|
+
await new Promise((resolve7) => {
|
|
22737
|
+
const proc = (0, import_child_process18.spawn)(
|
|
21958
22738
|
"gh",
|
|
21959
22739
|
[
|
|
21960
22740
|
"api",
|
|
@@ -21967,8 +22747,8 @@ function buildKeepAlive(ctx) {
|
|
|
21967
22747
|
{ stdio: "ignore", detached: true }
|
|
21968
22748
|
);
|
|
21969
22749
|
proc.unref();
|
|
21970
|
-
proc.on("exit", () =>
|
|
21971
|
-
proc.on("error", () =>
|
|
22750
|
+
proc.on("exit", () => resolve7());
|
|
22751
|
+
proc.on("error", () => resolve7());
|
|
21972
22752
|
});
|
|
21973
22753
|
}
|
|
21974
22754
|
return {
|
|
@@ -22044,6 +22824,20 @@ async function start(requestedAgent) {
|
|
|
22044
22824
|
"pluginAuth",
|
|
22045
22825
|
`boot triple sessionId=${session.id} pluginId=${pluginId} tokenLen=${tokenForLog.length} tokenHead=${tokenForLog.slice(0, 12)} tokenTail=${tokenForLog.slice(-8)} mintedEqualsCached=${refreshed === session.pluginAuthToken}`
|
|
22046
22826
|
);
|
|
22827
|
+
let beads = null;
|
|
22828
|
+
const getBeads = () => beads;
|
|
22829
|
+
const beadsReady = provisionBeadsForStart({
|
|
22830
|
+
sessionId: session.id,
|
|
22831
|
+
pluginId,
|
|
22832
|
+
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
22833
|
+
cwd,
|
|
22834
|
+
// Wire this session's agent natively via `bd setup <recipe> --global` so
|
|
22835
|
+
// the agent actually uses bd (D12 — REVISED). Covers BOTH ACP and PTY.
|
|
22836
|
+
agents: [session.agent]
|
|
22837
|
+
}).then((started) => {
|
|
22838
|
+
beads = started;
|
|
22839
|
+
return started;
|
|
22840
|
+
});
|
|
22047
22841
|
const acpDisabled = process.env.CODEAM_ACP_DISABLED === "1";
|
|
22048
22842
|
if (!acpDisabled && session.pluginAuthToken) {
|
|
22049
22843
|
const adapter = getAcpAdapter(session.agent);
|
|
@@ -22054,7 +22848,8 @@ async function start(requestedAgent) {
|
|
|
22054
22848
|
pluginId,
|
|
22055
22849
|
pluginAuthToken: session.pluginAuthToken,
|
|
22056
22850
|
adapter,
|
|
22057
|
-
cwd
|
|
22851
|
+
cwd,
|
|
22852
|
+
getBeads
|
|
22058
22853
|
});
|
|
22059
22854
|
return;
|
|
22060
22855
|
}
|
|
@@ -22132,6 +22927,7 @@ async function start(requestedAgent) {
|
|
|
22132
22927
|
relay.stop();
|
|
22133
22928
|
void fileWatcher?.stop();
|
|
22134
22929
|
turnFiles?.stop();
|
|
22930
|
+
void beads?.watcher.stop();
|
|
22135
22931
|
void streamingEmitter?.stop();
|
|
22136
22932
|
closeAllTerminals();
|
|
22137
22933
|
cleanupAttachmentTempFiles();
|
|
@@ -22165,6 +22961,9 @@ async function start(requestedAgent) {
|
|
|
22165
22961
|
await dispatchCommand(ctx, cmd);
|
|
22166
22962
|
}, runtime.meta);
|
|
22167
22963
|
ctx.relay = relay;
|
|
22964
|
+
void beadsReady.then((started) => {
|
|
22965
|
+
ctx.beads = started;
|
|
22966
|
+
});
|
|
22168
22967
|
registerTerminalHandlers({
|
|
22169
22968
|
onData: ({ sessionId, data }) => {
|
|
22170
22969
|
void outputSvc.sendTerminalChunk(sessionId, data);
|
|
@@ -22181,6 +22980,7 @@ async function start(requestedAgent) {
|
|
|
22181
22980
|
outputSvc.dispose();
|
|
22182
22981
|
relay.stop();
|
|
22183
22982
|
void fileWatcher?.stop();
|
|
22983
|
+
void beads?.watcher.stop();
|
|
22184
22984
|
void streamingEmitter?.stop();
|
|
22185
22985
|
closeAllTerminals();
|
|
22186
22986
|
cleanupAttachmentTempFiles();
|
|
@@ -22319,7 +23119,7 @@ async function pair(args2 = []) {
|
|
|
22319
23119
|
waitSpin.message(waitMessage());
|
|
22320
23120
|
}, 1e3);
|
|
22321
23121
|
countdownInterval.unref?.();
|
|
22322
|
-
await new Promise((
|
|
23122
|
+
await new Promise((resolve7) => {
|
|
22323
23123
|
let stopPolling = null;
|
|
22324
23124
|
function sigintHandler() {
|
|
22325
23125
|
clearInterval(countdownInterval);
|
|
@@ -22367,7 +23167,7 @@ async function pair(args2 = []) {
|
|
|
22367
23167
|
pluginAuthToken: info.pluginAuthToken
|
|
22368
23168
|
});
|
|
22369
23169
|
}
|
|
22370
|
-
|
|
23170
|
+
resolve7();
|
|
22371
23171
|
},
|
|
22372
23172
|
() => {
|
|
22373
23173
|
clearInterval(countdownInterval);
|
|
@@ -22419,8 +23219,8 @@ async function autoLinkAfterPair(opts) {
|
|
|
22419
23219
|
}
|
|
22420
23220
|
|
|
22421
23221
|
// src/commands/pair-auto.ts
|
|
22422
|
-
var
|
|
22423
|
-
var
|
|
23222
|
+
var fs36 = __toESM(require("fs"));
|
|
23223
|
+
var os28 = __toESM(require("os"));
|
|
22424
23224
|
var import_crypto7 = require("crypto");
|
|
22425
23225
|
|
|
22426
23226
|
// src/commands/start-infra-only.ts
|
|
@@ -22480,6 +23280,15 @@ async function startInfraOnly(agentId) {
|
|
|
22480
23280
|
pluginId,
|
|
22481
23281
|
pluginAuthToken: session.pluginAuthToken
|
|
22482
23282
|
}) : null;
|
|
23283
|
+
let beads = null;
|
|
23284
|
+
void provisionBeadsForStart({
|
|
23285
|
+
sessionId: session.id,
|
|
23286
|
+
pluginId,
|
|
23287
|
+
pluginAuthToken: session.pluginAuthToken ?? void 0,
|
|
23288
|
+
cwd
|
|
23289
|
+
}).then((started) => {
|
|
23290
|
+
beads = started;
|
|
23291
|
+
});
|
|
22483
23292
|
let relayRef = null;
|
|
22484
23293
|
const ctx = {
|
|
22485
23294
|
// Agent-touching fields are not used by any of the commands
|
|
@@ -22501,6 +23310,23 @@ async function startInfraOnly(agentId) {
|
|
|
22501
23310
|
const relay = new CommandRelayService(
|
|
22502
23311
|
pluginId,
|
|
22503
23312
|
async (cmd) => {
|
|
23313
|
+
if (cmd.type === "beads_action") {
|
|
23314
|
+
if (!beads) {
|
|
23315
|
+
log.trace("infra-only", "beads_action received but beads not running \u2014 dropping");
|
|
23316
|
+
return;
|
|
23317
|
+
}
|
|
23318
|
+
const action = beadsActionFromPayload(cmd.payload);
|
|
23319
|
+
if (!action) {
|
|
23320
|
+
log.warn("infra-only", "malformed beads_action payload \u2014 dropping");
|
|
23321
|
+
return;
|
|
23322
|
+
}
|
|
23323
|
+
try {
|
|
23324
|
+
await handleBeadsActionCommand(action, beads);
|
|
23325
|
+
} catch (err) {
|
|
23326
|
+
log.warn("infra-only", "handleBeadsActionCommand failed (non-fatal)", err);
|
|
23327
|
+
}
|
|
23328
|
+
return;
|
|
23329
|
+
}
|
|
22504
23330
|
if (!INFRA_ONLY_COMMAND_TYPES.has(cmd.type)) {
|
|
22505
23331
|
log.trace("infra-only", `dropping agent-only command type=${cmd.type}`);
|
|
22506
23332
|
return;
|
|
@@ -22561,6 +23387,7 @@ async function startInfraOnly(agentId) {
|
|
|
22561
23387
|
} catch {
|
|
22562
23388
|
}
|
|
22563
23389
|
void fileWatcher?.stop();
|
|
23390
|
+
void beads?.watcher.stop();
|
|
22564
23391
|
closeAllTerminals();
|
|
22565
23392
|
cleanupAttachmentTempFiles();
|
|
22566
23393
|
process.exit(0);
|
|
@@ -22573,7 +23400,7 @@ async function startInfraOnly(agentId) {
|
|
|
22573
23400
|
}
|
|
22574
23401
|
|
|
22575
23402
|
// src/commands/pair-auto.ts
|
|
22576
|
-
var
|
|
23403
|
+
var API_BASE10 = resolveApiBaseUrl();
|
|
22577
23404
|
function fail(msg) {
|
|
22578
23405
|
console.error(`
|
|
22579
23406
|
${msg}
|
|
@@ -22588,12 +23415,12 @@ function readTokenFromArgs(args2) {
|
|
|
22588
23415
|
}
|
|
22589
23416
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
22590
23417
|
if (fileFlag) {
|
|
22591
|
-
const
|
|
23418
|
+
const path50 = fileFlag.slice("--token-file=".length);
|
|
22592
23419
|
try {
|
|
22593
|
-
const content =
|
|
22594
|
-
if (content.length === 0) fail(`--token-file ${
|
|
23420
|
+
const content = fs36.readFileSync(path50, "utf8").trim();
|
|
23421
|
+
if (content.length === 0) fail(`--token-file ${path50} is empty`);
|
|
22595
23422
|
try {
|
|
22596
|
-
|
|
23423
|
+
fs36.unlinkSync(path50);
|
|
22597
23424
|
} catch {
|
|
22598
23425
|
}
|
|
22599
23426
|
return content;
|
|
@@ -22613,13 +23440,13 @@ function networkError(msg, cause) {
|
|
|
22613
23440
|
return err;
|
|
22614
23441
|
}
|
|
22615
23442
|
async function claimOnce(token, pluginId) {
|
|
22616
|
-
const url = `${
|
|
23443
|
+
const url = `${API_BASE10}/api/pairing/claim-auto-token`;
|
|
22617
23444
|
const body = {
|
|
22618
23445
|
token,
|
|
22619
23446
|
pluginId,
|
|
22620
23447
|
ideName: "codeam-cli (codespace)",
|
|
22621
23448
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
22622
|
-
hostname:
|
|
23449
|
+
hostname: os28.hostname(),
|
|
22623
23450
|
codespaceName: process.env.CODESPACE_NAME ?? "",
|
|
22624
23451
|
// Current git branch of the codespace's working directory, so the
|
|
22625
23452
|
// backend can populate `PairedSession.branch` for the codespace pair.
|
|
@@ -22816,7 +23643,7 @@ function status() {
|
|
|
22816
23643
|
|
|
22817
23644
|
// src/commands/logout.ts
|
|
22818
23645
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
22819
|
-
var
|
|
23646
|
+
var API_BASE11 = resolveApiBaseUrl();
|
|
22820
23647
|
async function notifyBackendOffline() {
|
|
22821
23648
|
const cfg = loadCliConfig();
|
|
22822
23649
|
const pluginIds = /* @__PURE__ */ new Set([
|
|
@@ -22828,7 +23655,7 @@ async function notifyBackendOffline() {
|
|
|
22828
23655
|
try {
|
|
22829
23656
|
await Promise.all(
|
|
22830
23657
|
Array.from(pluginIds).map(
|
|
22831
|
-
(pluginId) => _postJson(`${
|
|
23658
|
+
(pluginId) => _postJson(`${API_BASE11}/api/plugin/heartbeat`, {
|
|
22832
23659
|
pluginId,
|
|
22833
23660
|
online: false
|
|
22834
23661
|
}).catch((err) => {
|
|
@@ -22856,11 +23683,11 @@ async function logout() {
|
|
|
22856
23683
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
22857
23684
|
|
|
22858
23685
|
// src/services/providers/github-codespaces.ts
|
|
22859
|
-
var
|
|
23686
|
+
var import_child_process19 = require("child_process");
|
|
22860
23687
|
var import_util4 = require("util");
|
|
22861
23688
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
22862
|
-
var
|
|
22863
|
-
var execFileP5 = (0, import_util4.promisify)(
|
|
23689
|
+
var path44 = __toESM(require("path"));
|
|
23690
|
+
var execFileP5 = (0, import_util4.promisify)(import_child_process19.execFile);
|
|
22864
23691
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
22865
23692
|
function resetStdinForChild() {
|
|
22866
23693
|
if (process.stdin.isTTY) {
|
|
@@ -22903,12 +23730,12 @@ var GitHubCodespacesProvider = class {
|
|
|
22903
23730
|
}
|
|
22904
23731
|
if (!isAuthed) {
|
|
22905
23732
|
resetStdinForChild();
|
|
22906
|
-
await new Promise((
|
|
22907
|
-
const proc = (0,
|
|
23733
|
+
await new Promise((resolve7, reject) => {
|
|
23734
|
+
const proc = (0, import_child_process19.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
22908
23735
|
stdio: "inherit"
|
|
22909
23736
|
});
|
|
22910
23737
|
proc.on("exit", (code) => {
|
|
22911
|
-
if (code === 0)
|
|
23738
|
+
if (code === 0) resolve7();
|
|
22912
23739
|
else reject(new Error("gh auth login failed."));
|
|
22913
23740
|
});
|
|
22914
23741
|
proc.on("error", reject);
|
|
@@ -22937,13 +23764,13 @@ var GitHubCodespacesProvider = class {
|
|
|
22937
23764
|
}
|
|
22938
23765
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
22939
23766
|
resetStdinForChild();
|
|
22940
|
-
const refreshCode = await new Promise((
|
|
22941
|
-
const proc = (0,
|
|
23767
|
+
const refreshCode = await new Promise((resolve7, reject) => {
|
|
23768
|
+
const proc = (0, import_child_process19.spawn)(
|
|
22942
23769
|
"gh",
|
|
22943
23770
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
22944
23771
|
{ stdio: "inherit" }
|
|
22945
23772
|
);
|
|
22946
|
-
proc.on("exit", (code) =>
|
|
23773
|
+
proc.on("exit", (code) => resolve7(code ?? 1));
|
|
22947
23774
|
proc.on("error", reject);
|
|
22948
23775
|
});
|
|
22949
23776
|
if (refreshCode !== 0) {
|
|
@@ -23087,10 +23914,10 @@ var GitHubCodespacesProvider = class {
|
|
|
23087
23914
|
if (q(proceed) || !proceed) return;
|
|
23088
23915
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
23089
23916
|
resetStdinForChild();
|
|
23090
|
-
const ok = await new Promise((
|
|
23091
|
-
const proc = (0,
|
|
23092
|
-
proc.on("exit", (code) =>
|
|
23093
|
-
proc.on("error", () =>
|
|
23917
|
+
const ok = await new Promise((resolve7) => {
|
|
23918
|
+
const proc = (0, import_child_process19.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
23919
|
+
proc.on("exit", (code) => resolve7(code === 0));
|
|
23920
|
+
proc.on("error", () => resolve7(false));
|
|
23094
23921
|
});
|
|
23095
23922
|
if (ok) O2.success("gh installed");
|
|
23096
23923
|
else O2.error("gh install failed");
|
|
@@ -23114,14 +23941,14 @@ var GitHubCodespacesProvider = class {
|
|
|
23114
23941
|
"Expanding GitHub scopes"
|
|
23115
23942
|
);
|
|
23116
23943
|
resetStdinForChild();
|
|
23117
|
-
await new Promise((
|
|
23118
|
-
const proc = (0,
|
|
23944
|
+
await new Promise((resolve7, reject) => {
|
|
23945
|
+
const proc = (0, import_child_process19.spawn)(
|
|
23119
23946
|
"gh",
|
|
23120
23947
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
23121
23948
|
{ stdio: "inherit" }
|
|
23122
23949
|
);
|
|
23123
23950
|
proc.on("exit", (code) => {
|
|
23124
|
-
if (code === 0)
|
|
23951
|
+
if (code === 0) resolve7();
|
|
23125
23952
|
else reject(new Error(
|
|
23126
23953
|
"gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
|
|
23127
23954
|
));
|
|
@@ -23292,13 +24119,13 @@ var GitHubCodespacesProvider = class {
|
|
|
23292
24119
|
}
|
|
23293
24120
|
async streamCommand(workspaceId, command2) {
|
|
23294
24121
|
resetStdinForChild();
|
|
23295
|
-
return new Promise((
|
|
23296
|
-
const proc = (0,
|
|
24122
|
+
return new Promise((resolve7, reject) => {
|
|
24123
|
+
const proc = (0, import_child_process19.spawn)(
|
|
23297
24124
|
"gh",
|
|
23298
24125
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
23299
24126
|
{ stdio: "inherit" }
|
|
23300
24127
|
);
|
|
23301
|
-
proc.on("exit", (code) =>
|
|
24128
|
+
proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
|
|
23302
24129
|
proc.on("error", reject);
|
|
23303
24130
|
});
|
|
23304
24131
|
}
|
|
@@ -23319,12 +24146,12 @@ var GitHubCodespacesProvider = class {
|
|
|
23319
24146
|
"--",
|
|
23320
24147
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
23321
24148
|
];
|
|
23322
|
-
await new Promise((
|
|
23323
|
-
const tar = (0,
|
|
24149
|
+
await new Promise((resolve7, reject) => {
|
|
24150
|
+
const tar = (0, import_child_process19.spawn)("tar", tarArgs, {
|
|
23324
24151
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23325
24152
|
env: tarEnv
|
|
23326
24153
|
});
|
|
23327
|
-
const ssh = (0,
|
|
24154
|
+
const ssh = (0, import_child_process19.spawn)("gh", sshArgs, {
|
|
23328
24155
|
stdio: [tar.stdout, "pipe", "pipe"]
|
|
23329
24156
|
});
|
|
23330
24157
|
let tarErr = "";
|
|
@@ -23339,7 +24166,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23339
24166
|
ssh.on("error", reject);
|
|
23340
24167
|
ssh.on("exit", (code) => {
|
|
23341
24168
|
if (code === 0) {
|
|
23342
|
-
|
|
24169
|
+
resolve7();
|
|
23343
24170
|
} else {
|
|
23344
24171
|
const reason = (sshErr || tarErr || `exit ${code}`).trim().slice(0, 500);
|
|
23345
24172
|
reject(new Error(`Remote tar failed: ${reason}`));
|
|
@@ -23348,7 +24175,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23348
24175
|
});
|
|
23349
24176
|
}
|
|
23350
24177
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23351
|
-
const remoteDir =
|
|
24178
|
+
const remoteDir = path44.posix.dirname(remotePath);
|
|
23352
24179
|
const parts = [
|
|
23353
24180
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
23354
24181
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -23357,8 +24184,8 @@ var GitHubCodespacesProvider = class {
|
|
|
23357
24184
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
|
|
23358
24185
|
}
|
|
23359
24186
|
const cmd = parts.join(" && ");
|
|
23360
|
-
await new Promise((
|
|
23361
|
-
const proc = (0,
|
|
24187
|
+
await new Promise((resolve7, reject) => {
|
|
24188
|
+
const proc = (0, import_child_process19.spawn)(
|
|
23362
24189
|
"gh",
|
|
23363
24190
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
23364
24191
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -23369,7 +24196,7 @@ var GitHubCodespacesProvider = class {
|
|
|
23369
24196
|
});
|
|
23370
24197
|
proc.on("error", reject);
|
|
23371
24198
|
proc.on("exit", (code) => {
|
|
23372
|
-
if (code === 0)
|
|
24199
|
+
if (code === 0) resolve7();
|
|
23373
24200
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
23374
24201
|
});
|
|
23375
24202
|
proc.stdin?.write(contents);
|
|
@@ -23416,11 +24243,11 @@ function shellQuote(s) {
|
|
|
23416
24243
|
}
|
|
23417
24244
|
|
|
23418
24245
|
// src/services/providers/gitpod.ts
|
|
23419
|
-
var
|
|
24246
|
+
var import_child_process20 = require("child_process");
|
|
23420
24247
|
var import_util5 = require("util");
|
|
23421
|
-
var
|
|
24248
|
+
var path45 = __toESM(require("path"));
|
|
23422
24249
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
23423
|
-
var execFileP6 = (0, import_util5.promisify)(
|
|
24250
|
+
var execFileP6 = (0, import_util5.promisify)(import_child_process20.execFile);
|
|
23424
24251
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
23425
24252
|
function resetStdinForChild2() {
|
|
23426
24253
|
if (process.stdin.isTTY) {
|
|
@@ -23459,10 +24286,10 @@ var GitpodProvider = class {
|
|
|
23459
24286
|
"Authenticating Gitpod"
|
|
23460
24287
|
);
|
|
23461
24288
|
resetStdinForChild2();
|
|
23462
|
-
await new Promise((
|
|
23463
|
-
const proc = (0,
|
|
24289
|
+
await new Promise((resolve7, reject) => {
|
|
24290
|
+
const proc = (0, import_child_process20.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
23464
24291
|
proc.on("exit", (code) => {
|
|
23465
|
-
if (code === 0)
|
|
24292
|
+
if (code === 0) resolve7();
|
|
23466
24293
|
else reject(new Error("gitpod login failed."));
|
|
23467
24294
|
});
|
|
23468
24295
|
proc.on("error", reject);
|
|
@@ -23611,13 +24438,13 @@ var GitpodProvider = class {
|
|
|
23611
24438
|
}
|
|
23612
24439
|
async streamCommand(workspaceId, command2) {
|
|
23613
24440
|
resetStdinForChild2();
|
|
23614
|
-
return new Promise((
|
|
23615
|
-
const proc = (0,
|
|
24441
|
+
return new Promise((resolve7, reject) => {
|
|
24442
|
+
const proc = (0, import_child_process20.spawn)(
|
|
23616
24443
|
"gitpod",
|
|
23617
24444
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
23618
24445
|
{ stdio: "inherit" }
|
|
23619
24446
|
);
|
|
23620
|
-
proc.on("exit", (code) =>
|
|
24447
|
+
proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
|
|
23621
24448
|
proc.on("error", reject);
|
|
23622
24449
|
});
|
|
23623
24450
|
}
|
|
@@ -23631,12 +24458,12 @@ var GitpodProvider = class {
|
|
|
23631
24458
|
tarArgs.push(".");
|
|
23632
24459
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
23633
24460
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
23634
|
-
await new Promise((
|
|
23635
|
-
const tar = (0,
|
|
24461
|
+
await new Promise((resolve7, reject) => {
|
|
24462
|
+
const tar = (0, import_child_process20.spawn)("tar", tarArgs, {
|
|
23636
24463
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23637
24464
|
env: tarEnv
|
|
23638
24465
|
});
|
|
23639
|
-
const ssh = (0,
|
|
24466
|
+
const ssh = (0, import_child_process20.spawn)(
|
|
23640
24467
|
"gitpod",
|
|
23641
24468
|
["workspace", "ssh", workspaceId, "--", remoteCmd],
|
|
23642
24469
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -23652,13 +24479,13 @@ var GitpodProvider = class {
|
|
|
23652
24479
|
tar.on("error", reject);
|
|
23653
24480
|
ssh.on("error", reject);
|
|
23654
24481
|
ssh.on("exit", (code) => {
|
|
23655
|
-
if (code === 0)
|
|
24482
|
+
if (code === 0) resolve7();
|
|
23656
24483
|
else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
23657
24484
|
});
|
|
23658
24485
|
});
|
|
23659
24486
|
}
|
|
23660
24487
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23661
|
-
const remoteDir =
|
|
24488
|
+
const remoteDir = path45.posix.dirname(remotePath);
|
|
23662
24489
|
const parts = [
|
|
23663
24490
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
23664
24491
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -23667,8 +24494,8 @@ var GitpodProvider = class {
|
|
|
23667
24494
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote2(remotePath)}`);
|
|
23668
24495
|
}
|
|
23669
24496
|
const cmd = parts.join(" && ");
|
|
23670
|
-
await new Promise((
|
|
23671
|
-
const proc = (0,
|
|
24497
|
+
await new Promise((resolve7, reject) => {
|
|
24498
|
+
const proc = (0, import_child_process20.spawn)(
|
|
23672
24499
|
"gitpod",
|
|
23673
24500
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
23674
24501
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -23679,7 +24506,7 @@ var GitpodProvider = class {
|
|
|
23679
24506
|
});
|
|
23680
24507
|
proc.on("error", reject);
|
|
23681
24508
|
proc.on("exit", (code) => {
|
|
23682
|
-
if (code === 0)
|
|
24509
|
+
if (code === 0) resolve7();
|
|
23683
24510
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
23684
24511
|
});
|
|
23685
24512
|
proc.stdin?.write(contents);
|
|
@@ -23692,10 +24519,10 @@ function shellQuote2(s) {
|
|
|
23692
24519
|
}
|
|
23693
24520
|
|
|
23694
24521
|
// src/services/providers/gitlab-workspaces.ts
|
|
23695
|
-
var
|
|
24522
|
+
var import_child_process21 = require("child_process");
|
|
23696
24523
|
var import_util6 = require("util");
|
|
23697
|
-
var
|
|
23698
|
-
var execFileP7 = (0, import_util6.promisify)(
|
|
24524
|
+
var path46 = __toESM(require("path"));
|
|
24525
|
+
var execFileP7 = (0, import_util6.promisify)(import_child_process21.execFile);
|
|
23699
24526
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
23700
24527
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
23701
24528
|
function resetStdinForChild3() {
|
|
@@ -23736,14 +24563,14 @@ var GitLabWorkspacesProvider = class {
|
|
|
23736
24563
|
"Authenticating GitLab"
|
|
23737
24564
|
);
|
|
23738
24565
|
resetStdinForChild3();
|
|
23739
|
-
await new Promise((
|
|
23740
|
-
const proc = (0,
|
|
24566
|
+
await new Promise((resolve7, reject) => {
|
|
24567
|
+
const proc = (0, import_child_process21.spawn)(
|
|
23741
24568
|
"glab",
|
|
23742
24569
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
23743
24570
|
{ stdio: "inherit" }
|
|
23744
24571
|
);
|
|
23745
24572
|
proc.on("exit", (code) => {
|
|
23746
|
-
if (code === 0)
|
|
24573
|
+
if (code === 0) resolve7();
|
|
23747
24574
|
else reject(new Error("glab auth login failed."));
|
|
23748
24575
|
});
|
|
23749
24576
|
proc.on("error", reject);
|
|
@@ -23908,13 +24735,13 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23908
24735
|
async streamCommand(workspaceId, command2) {
|
|
23909
24736
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
23910
24737
|
resetStdinForChild3();
|
|
23911
|
-
return new Promise((
|
|
23912
|
-
const proc = (0,
|
|
24738
|
+
return new Promise((resolve7, reject) => {
|
|
24739
|
+
const proc = (0, import_child_process21.spawn)(
|
|
23913
24740
|
"ssh",
|
|
23914
24741
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
23915
24742
|
{ stdio: "inherit" }
|
|
23916
24743
|
);
|
|
23917
|
-
proc.on("exit", (code) =>
|
|
24744
|
+
proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
|
|
23918
24745
|
proc.on("error", reject);
|
|
23919
24746
|
});
|
|
23920
24747
|
}
|
|
@@ -23929,9 +24756,9 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23929
24756
|
tarArgs.push(".");
|
|
23930
24757
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
23931
24758
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
23932
|
-
await new Promise((
|
|
23933
|
-
const tar = (0,
|
|
23934
|
-
const ssh = (0,
|
|
24759
|
+
await new Promise((resolve7, reject) => {
|
|
24760
|
+
const tar = (0, import_child_process21.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
24761
|
+
const ssh = (0, import_child_process21.spawn)(
|
|
23935
24762
|
"ssh",
|
|
23936
24763
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
|
|
23937
24764
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -23947,21 +24774,21 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23947
24774
|
tar.on("error", reject);
|
|
23948
24775
|
ssh.on("error", reject);
|
|
23949
24776
|
ssh.on("exit", (code) => {
|
|
23950
|
-
if (code === 0)
|
|
24777
|
+
if (code === 0) resolve7();
|
|
23951
24778
|
else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
23952
24779
|
});
|
|
23953
24780
|
});
|
|
23954
24781
|
}
|
|
23955
24782
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
23956
24783
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
23957
|
-
const remoteDir =
|
|
24784
|
+
const remoteDir = path46.posix.dirname(remotePath);
|
|
23958
24785
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
23959
24786
|
if (options.mode != null) {
|
|
23960
24787
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
23961
24788
|
}
|
|
23962
24789
|
const cmd = parts.join(" && ");
|
|
23963
|
-
await new Promise((
|
|
23964
|
-
const proc = (0,
|
|
24790
|
+
await new Promise((resolve7, reject) => {
|
|
24791
|
+
const proc = (0, import_child_process21.spawn)(
|
|
23965
24792
|
"ssh",
|
|
23966
24793
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
23967
24794
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -23972,7 +24799,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
23972
24799
|
});
|
|
23973
24800
|
proc.on("error", reject);
|
|
23974
24801
|
proc.on("exit", (code) => {
|
|
23975
|
-
if (code === 0)
|
|
24802
|
+
if (code === 0) resolve7();
|
|
23976
24803
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
23977
24804
|
});
|
|
23978
24805
|
proc.stdin?.write(contents);
|
|
@@ -24020,10 +24847,10 @@ function shellQuote3(s) {
|
|
|
24020
24847
|
}
|
|
24021
24848
|
|
|
24022
24849
|
// src/services/providers/railway.ts
|
|
24023
|
-
var
|
|
24850
|
+
var import_child_process22 = require("child_process");
|
|
24024
24851
|
var import_util7 = require("util");
|
|
24025
|
-
var
|
|
24026
|
-
var execFileP8 = (0, import_util7.promisify)(
|
|
24852
|
+
var path47 = __toESM(require("path"));
|
|
24853
|
+
var execFileP8 = (0, import_util7.promisify)(import_child_process22.execFile);
|
|
24027
24854
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
24028
24855
|
function resetStdinForChild4() {
|
|
24029
24856
|
if (process.stdin.isTTY) {
|
|
@@ -24063,10 +24890,10 @@ var RailwayProvider = class {
|
|
|
24063
24890
|
"Authenticating Railway"
|
|
24064
24891
|
);
|
|
24065
24892
|
resetStdinForChild4();
|
|
24066
|
-
await new Promise((
|
|
24067
|
-
const proc = (0,
|
|
24893
|
+
await new Promise((resolve7, reject) => {
|
|
24894
|
+
const proc = (0, import_child_process22.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
24068
24895
|
proc.on("exit", (code) => {
|
|
24069
|
-
if (code === 0)
|
|
24896
|
+
if (code === 0) resolve7();
|
|
24070
24897
|
else reject(new Error("railway login failed."));
|
|
24071
24898
|
});
|
|
24072
24899
|
proc.on("error", reject);
|
|
@@ -24206,13 +25033,13 @@ var RailwayProvider = class {
|
|
|
24206
25033
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
24207
25034
|
}
|
|
24208
25035
|
resetStdinForChild4();
|
|
24209
|
-
return new Promise((
|
|
24210
|
-
const proc = (0,
|
|
25036
|
+
return new Promise((resolve7, reject) => {
|
|
25037
|
+
const proc = (0, import_child_process22.spawn)(
|
|
24211
25038
|
"railway",
|
|
24212
25039
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
24213
25040
|
{ stdio: "inherit" }
|
|
24214
25041
|
);
|
|
24215
|
-
proc.on("exit", (code) =>
|
|
25042
|
+
proc.on("exit", (code) => resolve7({ code: code ?? 0 }));
|
|
24216
25043
|
proc.on("error", reject);
|
|
24217
25044
|
});
|
|
24218
25045
|
}
|
|
@@ -24230,9 +25057,9 @@ var RailwayProvider = class {
|
|
|
24230
25057
|
tarArgs.push(".");
|
|
24231
25058
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
24232
25059
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
24233
|
-
await new Promise((
|
|
24234
|
-
const tar = (0,
|
|
24235
|
-
const sh = (0,
|
|
25060
|
+
await new Promise((resolve7, reject) => {
|
|
25061
|
+
const tar = (0, import_child_process22.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
25062
|
+
const sh = (0, import_child_process22.spawn)(
|
|
24236
25063
|
"railway",
|
|
24237
25064
|
["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
|
|
24238
25065
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -24248,7 +25075,7 @@ var RailwayProvider = class {
|
|
|
24248
25075
|
tar.on("error", reject);
|
|
24249
25076
|
sh.on("error", reject);
|
|
24250
25077
|
sh.on("exit", (code) => {
|
|
24251
|
-
if (code === 0)
|
|
25078
|
+
if (code === 0) resolve7();
|
|
24252
25079
|
else reject(new Error(`Remote tar failed: ${(shErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
24253
25080
|
});
|
|
24254
25081
|
});
|
|
@@ -24258,14 +25085,14 @@ var RailwayProvider = class {
|
|
|
24258
25085
|
if (!projectId || !serviceId) {
|
|
24259
25086
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
24260
25087
|
}
|
|
24261
|
-
const remoteDir =
|
|
25088
|
+
const remoteDir = path47.posix.dirname(remotePath);
|
|
24262
25089
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
24263
25090
|
if (options.mode != null) {
|
|
24264
25091
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
24265
25092
|
}
|
|
24266
25093
|
const cmd = parts.join(" && ");
|
|
24267
|
-
await new Promise((
|
|
24268
|
-
const proc = (0,
|
|
25094
|
+
await new Promise((resolve7, reject) => {
|
|
25095
|
+
const proc = (0, import_child_process22.spawn)(
|
|
24269
25096
|
"railway",
|
|
24270
25097
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
24271
25098
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -24276,7 +25103,7 @@ var RailwayProvider = class {
|
|
|
24276
25103
|
});
|
|
24277
25104
|
proc.on("error", reject);
|
|
24278
25105
|
proc.on("exit", (code) => {
|
|
24279
|
-
if (code === 0)
|
|
25106
|
+
if (code === 0) resolve7();
|
|
24280
25107
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
24281
25108
|
});
|
|
24282
25109
|
proc.stdin?.write(contents);
|
|
@@ -24801,8 +25628,8 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
24801
25628
|
var import_node_dns = require("dns");
|
|
24802
25629
|
var import_node_util4 = require("util");
|
|
24803
25630
|
var import_node_crypto8 = require("crypto");
|
|
24804
|
-
var
|
|
24805
|
-
var
|
|
25631
|
+
var fs37 = __toESM(require("fs"));
|
|
25632
|
+
var path48 = __toESM(require("path"));
|
|
24806
25633
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
24807
25634
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
24808
25635
|
async function checkDns(apiBase) {
|
|
@@ -24858,13 +25685,13 @@ async function checkHealth(apiBase) {
|
|
|
24858
25685
|
}
|
|
24859
25686
|
}
|
|
24860
25687
|
function checkConfigDir() {
|
|
24861
|
-
const dir =
|
|
25688
|
+
const dir = path48.join(require("os").homedir(), ".codeam");
|
|
24862
25689
|
try {
|
|
24863
|
-
|
|
24864
|
-
const probe =
|
|
24865
|
-
|
|
24866
|
-
const read =
|
|
24867
|
-
|
|
25690
|
+
fs37.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
25691
|
+
const probe = path48.join(dir, ".doctor-probe");
|
|
25692
|
+
fs37.writeFileSync(probe, "ok", { mode: 384 });
|
|
25693
|
+
const read = fs37.readFileSync(probe, "utf8");
|
|
25694
|
+
fs37.unlinkSync(probe);
|
|
24868
25695
|
if (read !== "ok") throw new Error("write/read round-trip mismatch");
|
|
24869
25696
|
return {
|
|
24870
25697
|
id: "config-dir",
|
|
@@ -24904,9 +25731,9 @@ function checkSessions() {
|
|
|
24904
25731
|
}
|
|
24905
25732
|
}
|
|
24906
25733
|
function checkAgentBinaries() {
|
|
24907
|
-
const
|
|
25734
|
+
const os30 = createOsStrategy();
|
|
24908
25735
|
return getEnabledAgents().map((meta) => {
|
|
24909
|
-
const found =
|
|
25736
|
+
const found = os30.findInPath(meta.binaryName);
|
|
24910
25737
|
return {
|
|
24911
25738
|
id: `agent-${meta.id}`,
|
|
24912
25739
|
label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
|
|
@@ -24928,7 +25755,7 @@ function checkNodePty() {
|
|
|
24928
25755
|
detail: "not required on this platform"
|
|
24929
25756
|
};
|
|
24930
25757
|
}
|
|
24931
|
-
const vendoredPath =
|
|
25758
|
+
const vendoredPath = path48.join(__dirname, "vendor", "node-pty");
|
|
24932
25759
|
for (const target of [vendoredPath, "node-pty"]) {
|
|
24933
25760
|
try {
|
|
24934
25761
|
require(target);
|
|
@@ -24970,7 +25797,7 @@ function checkChokidar() {
|
|
|
24970
25797
|
}
|
|
24971
25798
|
async function doctor(args2 = []) {
|
|
24972
25799
|
const json = args2.includes("--json");
|
|
24973
|
-
const cliVersion = true ? "2.
|
|
25800
|
+
const cliVersion = true ? "2.34.0" : "0.0.0-dev";
|
|
24974
25801
|
const apiBase = resolveApiBaseUrl();
|
|
24975
25802
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
24976
25803
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -25169,7 +25996,7 @@ async function completion(args2) {
|
|
|
25169
25996
|
// src/commands/version.ts
|
|
25170
25997
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
25171
25998
|
function version2() {
|
|
25172
|
-
const v = true ? "2.
|
|
25999
|
+
const v = true ? "2.34.0" : "unknown";
|
|
25173
26000
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
25174
26001
|
}
|
|
25175
26002
|
|
|
@@ -25297,9 +26124,9 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
25297
26124
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
25298
26125
|
|
|
25299
26126
|
// src/lib/updateNotifier.ts
|
|
25300
|
-
var
|
|
25301
|
-
var
|
|
25302
|
-
var
|
|
26127
|
+
var fs38 = __toESM(require("fs"));
|
|
26128
|
+
var os29 = __toESM(require("os"));
|
|
26129
|
+
var path49 = __toESM(require("path"));
|
|
25303
26130
|
var https8 = __toESM(require("https"));
|
|
25304
26131
|
var import_node_child_process12 = require("child_process");
|
|
25305
26132
|
var import_picocolors16 = __toESM(require("picocolors"));
|
|
@@ -25308,12 +26135,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
25308
26135
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
25309
26136
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
25310
26137
|
function cachePath() {
|
|
25311
|
-
const dir =
|
|
25312
|
-
return
|
|
26138
|
+
const dir = path49.join(os29.homedir(), ".codeam");
|
|
26139
|
+
return path49.join(dir, "update-check.json");
|
|
25313
26140
|
}
|
|
25314
26141
|
function readCache() {
|
|
25315
26142
|
try {
|
|
25316
|
-
const raw =
|
|
26143
|
+
const raw = fs38.readFileSync(cachePath(), "utf8");
|
|
25317
26144
|
const parsed = JSON.parse(raw);
|
|
25318
26145
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
25319
26146
|
return parsed;
|
|
@@ -25324,10 +26151,10 @@ function readCache() {
|
|
|
25324
26151
|
function writeCache(cache) {
|
|
25325
26152
|
try {
|
|
25326
26153
|
const file = cachePath();
|
|
25327
|
-
|
|
26154
|
+
fs38.mkdirSync(path49.dirname(file), { recursive: true });
|
|
25328
26155
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
25329
|
-
|
|
25330
|
-
|
|
26156
|
+
fs38.writeFileSync(tmp, JSON.stringify(cache));
|
|
26157
|
+
fs38.renameSync(tmp, file);
|
|
25331
26158
|
} catch {
|
|
25332
26159
|
}
|
|
25333
26160
|
}
|
|
@@ -25345,14 +26172,14 @@ function compareSemver(a, b) {
|
|
|
25345
26172
|
return 0;
|
|
25346
26173
|
}
|
|
25347
26174
|
function fetchLatest() {
|
|
25348
|
-
return new Promise((
|
|
26175
|
+
return new Promise((resolve7) => {
|
|
25349
26176
|
const req = https8.get(
|
|
25350
26177
|
REGISTRY_URL,
|
|
25351
26178
|
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
25352
26179
|
(res) => {
|
|
25353
26180
|
if (res.statusCode !== 200) {
|
|
25354
26181
|
res.resume();
|
|
25355
|
-
|
|
26182
|
+
resolve7(null);
|
|
25356
26183
|
return;
|
|
25357
26184
|
}
|
|
25358
26185
|
let buf = "";
|
|
@@ -25364,21 +26191,21 @@ function fetchLatest() {
|
|
|
25364
26191
|
try {
|
|
25365
26192
|
const json = JSON.parse(buf);
|
|
25366
26193
|
if (typeof json.version === "string") {
|
|
25367
|
-
|
|
26194
|
+
resolve7(json.version);
|
|
25368
26195
|
} else {
|
|
25369
|
-
|
|
26196
|
+
resolve7(null);
|
|
25370
26197
|
}
|
|
25371
26198
|
} catch {
|
|
25372
|
-
|
|
26199
|
+
resolve7(null);
|
|
25373
26200
|
}
|
|
25374
26201
|
});
|
|
25375
26202
|
}
|
|
25376
26203
|
);
|
|
25377
26204
|
req.on("timeout", () => {
|
|
25378
26205
|
req.destroy();
|
|
25379
|
-
|
|
26206
|
+
resolve7(null);
|
|
25380
26207
|
});
|
|
25381
|
-
req.on("error", () =>
|
|
26208
|
+
req.on("error", () => resolve7(null));
|
|
25382
26209
|
});
|
|
25383
26210
|
}
|
|
25384
26211
|
function notifyIfStale(currentVersion, latest) {
|
|
@@ -25401,8 +26228,8 @@ function isLinkedInstall() {
|
|
|
25401
26228
|
timeout: 2e3
|
|
25402
26229
|
}).trim();
|
|
25403
26230
|
if (!root) return false;
|
|
25404
|
-
const pkgPath =
|
|
25405
|
-
return
|
|
26231
|
+
const pkgPath = path49.join(root, PKG_NAME);
|
|
26232
|
+
return fs38.lstatSync(pkgPath).isSymbolicLink();
|
|
25406
26233
|
} catch {
|
|
25407
26234
|
return false;
|
|
25408
26235
|
}
|
|
@@ -25438,7 +26265,7 @@ function maybeAutoUpdate(currentVersion, latest) {
|
|
|
25438
26265
|
return;
|
|
25439
26266
|
}
|
|
25440
26267
|
try {
|
|
25441
|
-
|
|
26268
|
+
fs38.unlinkSync(cachePath());
|
|
25442
26269
|
} catch {
|
|
25443
26270
|
}
|
|
25444
26271
|
process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
|
|
@@ -25455,7 +26282,7 @@ function checkForUpdates() {
|
|
|
25455
26282
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
25456
26283
|
if (process.env.CI) return;
|
|
25457
26284
|
if (!process.stdout.isTTY) return;
|
|
25458
|
-
const current = true ? "2.
|
|
26285
|
+
const current = true ? "2.34.0" : null;
|
|
25459
26286
|
if (!current) return;
|
|
25460
26287
|
const cache = readCache();
|
|
25461
26288
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|