repowisestage 0.0.67 → 0.0.69
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/dist/bin/repowise.js +1148 -986
- package/package.json +1 -1
package/dist/bin/repowise.js
CHANGED
|
@@ -620,325 +620,6 @@ var init_process_manager = __esm({
|
|
|
620
620
|
}
|
|
621
621
|
});
|
|
622
622
|
|
|
623
|
-
// ../listener/dist/service-installer.js
|
|
624
|
-
var service_installer_exports = {};
|
|
625
|
-
__export(service_installer_exports, {
|
|
626
|
-
install: () => install,
|
|
627
|
-
isInstalled: () => isInstalled,
|
|
628
|
-
isServiceRunning: () => isServiceRunning,
|
|
629
|
-
stopService: () => stopService,
|
|
630
|
-
uninstall: () => uninstall
|
|
631
|
-
});
|
|
632
|
-
import { execFile as execFile4 } from "child_process";
|
|
633
|
-
import { writeFile as writeFile8, mkdir as mkdir8, unlink as unlink6 } from "fs/promises";
|
|
634
|
-
import { homedir as homedir3 } from "os";
|
|
635
|
-
import { join as join13 } from "path";
|
|
636
|
-
function exec(cmd, args) {
|
|
637
|
-
return new Promise((resolve5, reject) => {
|
|
638
|
-
execFile4(cmd, args, (err, stdout) => {
|
|
639
|
-
if (err) {
|
|
640
|
-
reject(err);
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
resolve5(String(stdout ?? ""));
|
|
644
|
-
});
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
function plistPath() {
|
|
648
|
-
return join13(homedir3(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
649
|
-
}
|
|
650
|
-
function logDir() {
|
|
651
|
-
return join13(getConfigDir(), "logs");
|
|
652
|
-
}
|
|
653
|
-
function buildPlist() {
|
|
654
|
-
const cmd = resolveListenerCommand();
|
|
655
|
-
const logs = logDir();
|
|
656
|
-
const programArgs = [process.execPath, cmd.script, ...cmd.args].map((a) => ` <string>${a}</string>`).join("\n");
|
|
657
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
658
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
659
|
-
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
660
|
-
<plist version="1.0">
|
|
661
|
-
<dict>
|
|
662
|
-
<key>Label</key>
|
|
663
|
-
<string>${PLIST_LABEL}</string>
|
|
664
|
-
<key>ProgramArguments</key>
|
|
665
|
-
<array>
|
|
666
|
-
${programArgs}
|
|
667
|
-
</array>
|
|
668
|
-
<key>RunAtLoad</key>
|
|
669
|
-
<true/>
|
|
670
|
-
<key>KeepAlive</key>
|
|
671
|
-
<true/>
|
|
672
|
-
<key>StandardOutPath</key>
|
|
673
|
-
<string>${join13(logs, "listener-stdout.log")}</string>
|
|
674
|
-
<key>StandardErrorPath</key>
|
|
675
|
-
<string>${join13(logs, "listener-stderr.log")}</string>
|
|
676
|
-
<key>ProcessType</key>
|
|
677
|
-
<string>Background</string>
|
|
678
|
-
<!--
|
|
679
|
-
SoftResourceLimits: raise the open-file descriptor limit from the macOS
|
|
680
|
-
default of 256 to 4096. When multiple LSP child processes (rust-analyzer,
|
|
681
|
-
jdtls, etc.) share the listener's fd budget they can exhaust the default
|
|
682
|
-
very quickly, causing EMFILE errors. 4096 matches the system-wide default
|
|
683
|
-
set by /etc/launchd.conf on modern macOS and gives enough headroom for
|
|
684
|
-
~10 concurrent LSP servers each opening ~300 fds.
|
|
685
|
-
|
|
686
|
-
MemoryLimit: intentionally NOT set here. The launchd MemoryLimit key
|
|
687
|
-
(available since macOS 12.3) terminates the entire LaunchAgent when RSS
|
|
688
|
-
exceeds the threshold \u2014 it cannot be scoped to individual child processes.
|
|
689
|
-
Killing the listener to evict a memory-hungry rust-analyzer instance is
|
|
690
|
-
undesirable. Per-child memory pressure is better handled by the LSP
|
|
691
|
-
process manager (process-manager.ts) or by OS-level memory pressure
|
|
692
|
-
signals (SIGTERM on macOS, OOM killer on Linux).
|
|
693
|
-
-->
|
|
694
|
-
<key>SoftResourceLimits</key>
|
|
695
|
-
<dict>
|
|
696
|
-
<key>NumberOfFiles</key>
|
|
697
|
-
<integer>4096</integer>
|
|
698
|
-
</dict>
|
|
699
|
-
</dict>
|
|
700
|
-
</plist>`;
|
|
701
|
-
}
|
|
702
|
-
async function darwinInstall() {
|
|
703
|
-
await mkdir8(logDir(), { recursive: true });
|
|
704
|
-
await mkdir8(join13(homedir3(), "Library", "LaunchAgents"), { recursive: true });
|
|
705
|
-
try {
|
|
706
|
-
await exec("launchctl", ["unload", plistPath()]);
|
|
707
|
-
} catch {
|
|
708
|
-
}
|
|
709
|
-
await writeFile8(plistPath(), buildPlist());
|
|
710
|
-
await exec("launchctl", ["load", plistPath()]);
|
|
711
|
-
}
|
|
712
|
-
async function darwinUninstall() {
|
|
713
|
-
try {
|
|
714
|
-
await exec("launchctl", ["unload", plistPath()]);
|
|
715
|
-
} catch {
|
|
716
|
-
}
|
|
717
|
-
try {
|
|
718
|
-
await unlink6(plistPath());
|
|
719
|
-
} catch {
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
async function darwinIsInstalled() {
|
|
723
|
-
try {
|
|
724
|
-
const stdout = await exec("launchctl", ["list"]);
|
|
725
|
-
return stdout.includes(PLIST_LABEL);
|
|
726
|
-
} catch {
|
|
727
|
-
return false;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
function unitPath() {
|
|
731
|
-
return join13(homedir3(), ".config", "systemd", "user", `${SYSTEMD_SERVICE}.service`);
|
|
732
|
-
}
|
|
733
|
-
function buildUnit() {
|
|
734
|
-
const cmd = resolveListenerCommand();
|
|
735
|
-
const execStart = [process.execPath, cmd.script, ...cmd.args].join(" ");
|
|
736
|
-
const logs = logDir();
|
|
737
|
-
return `[Unit]
|
|
738
|
-
Description=RepoWise Listener
|
|
739
|
-
After=network-online.target
|
|
740
|
-
Wants=network-online.target
|
|
741
|
-
|
|
742
|
-
[Service]
|
|
743
|
-
Type=simple
|
|
744
|
-
ExecStart=${execStart}
|
|
745
|
-
Restart=always
|
|
746
|
-
RestartSec=10
|
|
747
|
-
StandardOutput=append:${join13(logs, "listener-stdout.log")}
|
|
748
|
-
StandardError=append:${join13(logs, "listener-stderr.log")}
|
|
749
|
-
|
|
750
|
-
[Install]
|
|
751
|
-
WantedBy=default.target`;
|
|
752
|
-
}
|
|
753
|
-
async function linuxInstall() {
|
|
754
|
-
await mkdir8(logDir(), { recursive: true });
|
|
755
|
-
await mkdir8(join13(homedir3(), ".config", "systemd", "user"), { recursive: true });
|
|
756
|
-
await writeFile8(unitPath(), buildUnit());
|
|
757
|
-
await exec("systemctl", ["--user", "daemon-reload"]);
|
|
758
|
-
await exec("systemctl", ["--user", "enable", SYSTEMD_SERVICE]);
|
|
759
|
-
await exec("systemctl", ["--user", "start", SYSTEMD_SERVICE]);
|
|
760
|
-
}
|
|
761
|
-
async function linuxUninstall() {
|
|
762
|
-
try {
|
|
763
|
-
await exec("systemctl", ["--user", "stop", SYSTEMD_SERVICE]);
|
|
764
|
-
} catch {
|
|
765
|
-
}
|
|
766
|
-
try {
|
|
767
|
-
await exec("systemctl", ["--user", "disable", SYSTEMD_SERVICE]);
|
|
768
|
-
} catch {
|
|
769
|
-
}
|
|
770
|
-
try {
|
|
771
|
-
await unlink6(unitPath());
|
|
772
|
-
} catch {
|
|
773
|
-
}
|
|
774
|
-
try {
|
|
775
|
-
await exec("systemctl", ["--user", "daemon-reload"]);
|
|
776
|
-
} catch {
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
async function linuxIsInstalled() {
|
|
780
|
-
try {
|
|
781
|
-
const stdout = await exec("systemctl", ["--user", "is-enabled", SYSTEMD_SERVICE]);
|
|
782
|
-
return stdout.trim() === "enabled";
|
|
783
|
-
} catch {
|
|
784
|
-
return false;
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
async function win32Install() {
|
|
788
|
-
await mkdir8(logDir(), { recursive: true });
|
|
789
|
-
const cmd = resolveListenerCommand();
|
|
790
|
-
const taskCmd = [process.execPath, cmd.script, ...cmd.args].map((a) => `"${a}"`).join(" ");
|
|
791
|
-
await exec("schtasks", [
|
|
792
|
-
"/create",
|
|
793
|
-
"/tn",
|
|
794
|
-
TASK_NAME,
|
|
795
|
-
"/tr",
|
|
796
|
-
taskCmd,
|
|
797
|
-
"/sc",
|
|
798
|
-
"onlogon",
|
|
799
|
-
"/ru",
|
|
800
|
-
process.env.USERNAME ?? "",
|
|
801
|
-
"/f"
|
|
802
|
-
]);
|
|
803
|
-
await exec("schtasks", ["/run", "/tn", TASK_NAME]);
|
|
804
|
-
}
|
|
805
|
-
async function win32Uninstall() {
|
|
806
|
-
try {
|
|
807
|
-
await exec("schtasks", ["/end", "/tn", TASK_NAME]);
|
|
808
|
-
} catch {
|
|
809
|
-
}
|
|
810
|
-
try {
|
|
811
|
-
await exec("schtasks", ["/delete", "/tn", TASK_NAME, "/f"]);
|
|
812
|
-
} catch {
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
async function win32IsInstalled() {
|
|
816
|
-
try {
|
|
817
|
-
await exec("schtasks", ["/query", "/tn", TASK_NAME]);
|
|
818
|
-
return true;
|
|
819
|
-
} catch {
|
|
820
|
-
return false;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
async function darwinStop() {
|
|
824
|
-
try {
|
|
825
|
-
await exec("launchctl", ["unload", plistPath()]);
|
|
826
|
-
} catch {
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
async function linuxStop() {
|
|
830
|
-
await exec("systemctl", ["--user", "stop", SYSTEMD_SERVICE]);
|
|
831
|
-
}
|
|
832
|
-
async function win32Stop() {
|
|
833
|
-
await exec("schtasks", ["/end", "/tn", TASK_NAME]);
|
|
834
|
-
}
|
|
835
|
-
async function darwinIsServiceRunning() {
|
|
836
|
-
try {
|
|
837
|
-
const stdout = await exec("launchctl", ["list", PLIST_LABEL]);
|
|
838
|
-
const pidMatch = stdout.match(/"PID"\s*=\s*(\d+)/);
|
|
839
|
-
return pidMatch !== null && parseInt(pidMatch[1], 10) > 0;
|
|
840
|
-
} catch {
|
|
841
|
-
return false;
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
async function linuxIsServiceRunning() {
|
|
845
|
-
try {
|
|
846
|
-
const stdout = await exec("systemctl", ["--user", "is-active", SYSTEMD_SERVICE]);
|
|
847
|
-
return stdout.trim() === "active";
|
|
848
|
-
} catch {
|
|
849
|
-
return false;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
async function win32IsServiceRunning() {
|
|
853
|
-
try {
|
|
854
|
-
const stdout = await exec("schtasks", ["/query", "/tn", TASK_NAME, "/fo", "CSV"]);
|
|
855
|
-
return stdout.includes("Running");
|
|
856
|
-
} catch {
|
|
857
|
-
return false;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
async function stopService() {
|
|
861
|
-
switch (process.platform) {
|
|
862
|
-
case "darwin":
|
|
863
|
-
await darwinStop();
|
|
864
|
-
break;
|
|
865
|
-
case "linux":
|
|
866
|
-
await linuxStop();
|
|
867
|
-
break;
|
|
868
|
-
case "win32":
|
|
869
|
-
await win32Stop();
|
|
870
|
-
break;
|
|
871
|
-
default:
|
|
872
|
-
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
async function install() {
|
|
876
|
-
switch (process.platform) {
|
|
877
|
-
case "darwin":
|
|
878
|
-
await darwinInstall();
|
|
879
|
-
break;
|
|
880
|
-
case "linux":
|
|
881
|
-
await linuxInstall();
|
|
882
|
-
break;
|
|
883
|
-
case "win32":
|
|
884
|
-
await win32Install();
|
|
885
|
-
break;
|
|
886
|
-
default:
|
|
887
|
-
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
async function uninstall() {
|
|
891
|
-
switch (process.platform) {
|
|
892
|
-
case "darwin":
|
|
893
|
-
await darwinUninstall();
|
|
894
|
-
break;
|
|
895
|
-
case "linux":
|
|
896
|
-
await linuxUninstall();
|
|
897
|
-
break;
|
|
898
|
-
case "win32":
|
|
899
|
-
await win32Uninstall();
|
|
900
|
-
break;
|
|
901
|
-
default:
|
|
902
|
-
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
async function isInstalled() {
|
|
906
|
-
switch (process.platform) {
|
|
907
|
-
case "darwin":
|
|
908
|
-
return darwinIsInstalled();
|
|
909
|
-
case "linux":
|
|
910
|
-
return linuxIsInstalled();
|
|
911
|
-
case "win32":
|
|
912
|
-
return win32IsInstalled();
|
|
913
|
-
default:
|
|
914
|
-
return false;
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
async function isServiceRunning() {
|
|
918
|
-
switch (process.platform) {
|
|
919
|
-
case "darwin":
|
|
920
|
-
return darwinIsServiceRunning();
|
|
921
|
-
case "linux":
|
|
922
|
-
return linuxIsServiceRunning();
|
|
923
|
-
case "win32":
|
|
924
|
-
return win32IsServiceRunning();
|
|
925
|
-
default:
|
|
926
|
-
return false;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
var IS_STAGING, PLIST_LABEL, SYSTEMD_SERVICE, TASK_NAME;
|
|
930
|
-
var init_service_installer = __esm({
|
|
931
|
-
"../listener/dist/service-installer.js"() {
|
|
932
|
-
"use strict";
|
|
933
|
-
init_config_dir();
|
|
934
|
-
init_process_manager();
|
|
935
|
-
IS_STAGING = true ? true : false;
|
|
936
|
-
PLIST_LABEL = IS_STAGING ? "com.repowise-staging.listener" : "com.repowise.listener";
|
|
937
|
-
SYSTEMD_SERVICE = IS_STAGING ? "repowise-staging-listener" : "repowise-listener";
|
|
938
|
-
TASK_NAME = IS_STAGING ? "RepoWise Staging Listener" : "RepoWise Listener";
|
|
939
|
-
}
|
|
940
|
-
});
|
|
941
|
-
|
|
942
623
|
// ../listener/dist/lsp/registry.js
|
|
943
624
|
function resolvePhpLspOverride(env = process.env, configOverrides) {
|
|
944
625
|
const envChoice = env["PHP_LSP"];
|
|
@@ -1415,7 +1096,7 @@ var init_registry = __esm({
|
|
|
1415
1096
|
});
|
|
1416
1097
|
|
|
1417
1098
|
// ../listener/dist/lsp/jdk-probe.js
|
|
1418
|
-
import { spawn as
|
|
1099
|
+
import { spawn as spawn2 } from "child_process";
|
|
1419
1100
|
function parseJavaMajorVersion(stderr) {
|
|
1420
1101
|
const modernMatch = /\b(?:openjdk|java) version "(\d+)(?:\.\d+)*(?:[._]\w+)?"/.exec(stderr);
|
|
1421
1102
|
if (!modernMatch?.[1])
|
|
@@ -1437,7 +1118,7 @@ async function probeJdk(options = {}) {
|
|
|
1437
1118
|
return new Promise((resolve5) => {
|
|
1438
1119
|
let stderr = "";
|
|
1439
1120
|
let settled = false;
|
|
1440
|
-
const child =
|
|
1121
|
+
const child = spawn2("java", ["-version"], { stdio: ["ignore", "pipe", "pipe"] });
|
|
1441
1122
|
const timer = setTimeout(() => {
|
|
1442
1123
|
if (settled)
|
|
1443
1124
|
return;
|
|
@@ -1486,15 +1167,15 @@ var init_jdk_probe = __esm({
|
|
|
1486
1167
|
import { createWriteStream } from "fs";
|
|
1487
1168
|
import { promises as fs } from "fs";
|
|
1488
1169
|
import { createGunzip } from "zlib";
|
|
1489
|
-
import { spawn as
|
|
1170
|
+
import { spawn as spawn3 } from "child_process";
|
|
1490
1171
|
import { pipeline } from "stream/promises";
|
|
1491
1172
|
import { createHash as createHash3 } from "crypto";
|
|
1492
|
-
import { join as
|
|
1173
|
+
import { join as join13, dirname as dirname5 } from "path";
|
|
1493
1174
|
function getNativeLspDir() {
|
|
1494
|
-
return
|
|
1175
|
+
return join13(getLspInstallDir(), "native");
|
|
1495
1176
|
}
|
|
1496
1177
|
function getNativeLspBinDir() {
|
|
1497
|
-
return
|
|
1178
|
+
return join13(getNativeLspDir(), "bin");
|
|
1498
1179
|
}
|
|
1499
1180
|
async function ensureNativeLspInstalled(lspKey) {
|
|
1500
1181
|
const entry = NATIVE_LSP_VERSIONS[lspKey];
|
|
@@ -1520,15 +1201,15 @@ async function ensureNativeLspInstalled(lspKey) {
|
|
|
1520
1201
|
}
|
|
1521
1202
|
}
|
|
1522
1203
|
const usesWrapper = Boolean(asset.launcherJarGlob && asset.wrapperBinaryName);
|
|
1523
|
-
const versionDir =
|
|
1204
|
+
const versionDir = join13(getNativeLspDir(), lspKey, entry.version);
|
|
1524
1205
|
if (usesWrapper && asset.launcherJarGlob && asset.wrapperBinaryName) {
|
|
1525
1206
|
const jarPath = await resolveGlobInsideDir(versionDir, asset.launcherJarGlob);
|
|
1526
|
-
const shimPath =
|
|
1207
|
+
const shimPath = join13(getNativeLspBinDir(), asset.wrapperBinaryName);
|
|
1527
1208
|
if (jarPath && await pathExists(shimPath)) {
|
|
1528
1209
|
return { installed: false, alreadyPresent: true, binaryPath: shimPath };
|
|
1529
1210
|
}
|
|
1530
1211
|
} else {
|
|
1531
|
-
const installedBinary =
|
|
1212
|
+
const installedBinary = join13(versionDir, asset.binaryPath);
|
|
1532
1213
|
if (await pathExists(installedBinary)) {
|
|
1533
1214
|
await ensureSymlinkInBin(lspKey, installedBinary, asset.binaryPath);
|
|
1534
1215
|
return { installed: false, alreadyPresent: true, binaryPath: installedBinary };
|
|
@@ -1536,7 +1217,7 @@ async function ensureNativeLspInstalled(lspKey) {
|
|
|
1536
1217
|
}
|
|
1537
1218
|
try {
|
|
1538
1219
|
await fs.mkdir(versionDir, { recursive: true });
|
|
1539
|
-
const tmpDownload =
|
|
1220
|
+
const tmpDownload = join13(versionDir, `.${asset.filename}.download`);
|
|
1540
1221
|
const downloadUrl = entry.source.kind === "github-release" ? `https://github.com/${entry.source.repo}/releases/download/${entry.version}/${asset.filename}` : asset.url ?? "";
|
|
1541
1222
|
if (!downloadUrl) {
|
|
1542
1223
|
return {
|
|
@@ -1578,7 +1259,7 @@ async function ensureNativeLspInstalled(lspKey) {
|
|
|
1578
1259
|
await pruneStaleVersions(lspKey, entry.version);
|
|
1579
1260
|
return { installed: true, alreadyPresent: false, binaryPath: shimPath };
|
|
1580
1261
|
}
|
|
1581
|
-
const installedBinary =
|
|
1262
|
+
const installedBinary = join13(versionDir, asset.binaryPath);
|
|
1582
1263
|
if (!await pathExists(installedBinary)) {
|
|
1583
1264
|
return {
|
|
1584
1265
|
installed: false,
|
|
@@ -1602,7 +1283,7 @@ async function resolveGlobInsideDir(versionDir, glob) {
|
|
|
1602
1283
|
const parts = glob.split("/");
|
|
1603
1284
|
let dir = versionDir;
|
|
1604
1285
|
for (let i = 0; i < parts.length - 1; i += 1) {
|
|
1605
|
-
dir =
|
|
1286
|
+
dir = join13(dir, parts[i]);
|
|
1606
1287
|
}
|
|
1607
1288
|
const pattern = parts[parts.length - 1];
|
|
1608
1289
|
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
@@ -1615,10 +1296,10 @@ async function resolveGlobInsideDir(versionDir, glob) {
|
|
|
1615
1296
|
}
|
|
1616
1297
|
const matches = entries.filter((e) => re.test(e)).sort();
|
|
1617
1298
|
const last = matches[matches.length - 1];
|
|
1618
|
-
return last ?
|
|
1299
|
+
return last ? join13(dir, last) : null;
|
|
1619
1300
|
}
|
|
1620
1301
|
async function pruneStaleVersions(lspKey, currentVersion) {
|
|
1621
|
-
const lspDir =
|
|
1302
|
+
const lspDir = join13(getNativeLspDir(), lspKey);
|
|
1622
1303
|
let entries;
|
|
1623
1304
|
try {
|
|
1624
1305
|
entries = await fs.readdir(lspDir);
|
|
@@ -1627,7 +1308,7 @@ async function pruneStaleVersions(lspKey, currentVersion) {
|
|
|
1627
1308
|
}
|
|
1628
1309
|
await Promise.all(entries.filter((name) => name !== currentVersion).map(async (name) => {
|
|
1629
1310
|
try {
|
|
1630
|
-
await fs.rm(
|
|
1311
|
+
await fs.rm(join13(lspDir, name), { recursive: true, force: true });
|
|
1631
1312
|
} catch {
|
|
1632
1313
|
}
|
|
1633
1314
|
}));
|
|
@@ -1641,9 +1322,9 @@ function cmdQuote(value) {
|
|
|
1641
1322
|
async function writeJdtlsWrapper(input) {
|
|
1642
1323
|
const binDir = getNativeLspBinDir();
|
|
1643
1324
|
await fs.mkdir(binDir, { recursive: true });
|
|
1644
|
-
const shimPath =
|
|
1325
|
+
const shimPath = join13(binDir, input.binaryName);
|
|
1645
1326
|
const platformCfgDir = process.platform === "darwin" ? "config_mac" : process.platform === "win32" ? "config_win" : "config_linux";
|
|
1646
|
-
const workspaceBase =
|
|
1327
|
+
const workspaceBase = join13(input.versionDir, "workspaces");
|
|
1647
1328
|
const qLauncher = shQuote(input.launcherJarPath);
|
|
1648
1329
|
const qConfig = shQuote(`${input.versionDir}/${platformCfgDir}`);
|
|
1649
1330
|
const qWorkspaceBase = shQuote(workspaceBase);
|
|
@@ -1703,7 +1384,7 @@ async function ensureSymlinkInBin(lspKey, target, sourceAssetPath) {
|
|
|
1703
1384
|
await fs.mkdir(binDir, { recursive: true });
|
|
1704
1385
|
const winExtMatch = process.platform === "win32" && sourceAssetPath ? /\.(exe|bat|cmd|ps1)$/i.exec(sourceAssetPath) : null;
|
|
1705
1386
|
const linkName = winExtMatch ? `${lspKey}${winExtMatch[0].toLowerCase()}` : lspKey;
|
|
1706
|
-
const linkPath =
|
|
1387
|
+
const linkPath = join13(binDir, linkName);
|
|
1707
1388
|
try {
|
|
1708
1389
|
await fs.unlink(linkPath);
|
|
1709
1390
|
} catch {
|
|
@@ -1752,16 +1433,16 @@ async function extractAsset(source, destDir, asset) {
|
|
|
1752
1433
|
return;
|
|
1753
1434
|
}
|
|
1754
1435
|
if (filename.endsWith(".gz")) {
|
|
1755
|
-
const outPath =
|
|
1436
|
+
const outPath = join13(destDir, asset.binaryPath);
|
|
1756
1437
|
await fs.mkdir(dirname5(outPath), { recursive: true });
|
|
1757
1438
|
await pipeline((await fs.open(source)).createReadStream(), createGunzip(), createWriteStream(outPath));
|
|
1758
1439
|
return;
|
|
1759
1440
|
}
|
|
1760
|
-
await fs.copyFile(source,
|
|
1441
|
+
await fs.copyFile(source, join13(destDir, asset.binaryPath));
|
|
1761
1442
|
}
|
|
1762
1443
|
async function runExternal(cmd, args) {
|
|
1763
1444
|
return new Promise((resolve5, reject) => {
|
|
1764
|
-
const child =
|
|
1445
|
+
const child = spawn3(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1765
1446
|
let stderr = "";
|
|
1766
1447
|
child.stderr.on("data", (chunk) => {
|
|
1767
1448
|
stderr += chunk.toString();
|
|
@@ -1794,10 +1475,10 @@ var init_native_installer = __esm({
|
|
|
1794
1475
|
|
|
1795
1476
|
// ../listener/dist/lsp/coursier-installer.js
|
|
1796
1477
|
import { promises as fs2 } from "fs";
|
|
1797
|
-
import { spawn as
|
|
1798
|
-
import { join as
|
|
1478
|
+
import { spawn as spawn4 } from "child_process";
|
|
1479
|
+
import { join as join14 } from "path";
|
|
1799
1480
|
function getCoursierBinDir() {
|
|
1800
|
-
return
|
|
1481
|
+
return join14(getLspInstallDir(), "coursier-bin");
|
|
1801
1482
|
}
|
|
1802
1483
|
async function ensureCoursierLspInstalled(key) {
|
|
1803
1484
|
const entry = COURSIER_LSPS[key];
|
|
@@ -1805,8 +1486,8 @@ async function ensureCoursierLspInstalled(key) {
|
|
|
1805
1486
|
return { installed: false, alreadyPresent: false, skipped: "no-coursier-entry" };
|
|
1806
1487
|
}
|
|
1807
1488
|
const binDir = getCoursierBinDir();
|
|
1808
|
-
const binaryPath =
|
|
1809
|
-
const binaryPathExe =
|
|
1489
|
+
const binaryPath = join14(binDir, entry.appName);
|
|
1490
|
+
const binaryPathExe = join14(binDir, `${entry.appName}.bat`);
|
|
1810
1491
|
if (await pathExists2(binaryPath) || await pathExists2(binaryPathExe)) {
|
|
1811
1492
|
return { installed: false, alreadyPresent: true, binaryPath };
|
|
1812
1493
|
}
|
|
@@ -1819,492 +1500,881 @@ async function ensureCoursierLspInstalled(key) {
|
|
|
1819
1500
|
error: csBootstrap.error ?? csBootstrap.skipped
|
|
1820
1501
|
};
|
|
1821
1502
|
}
|
|
1822
|
-
const csPath =
|
|
1823
|
-
const csPathExe =
|
|
1824
|
-
const cs = await pathExists2(csPath) ? csPath : await pathExists2(csPathExe) ? csPathExe : null;
|
|
1825
|
-
if (!cs) {
|
|
1826
|
-
return {
|
|
1827
|
-
installed: false,
|
|
1828
|
-
alreadyPresent: false,
|
|
1829
|
-
skipped: "coursier-bootstrap-failed",
|
|
1830
|
-
error: `coursier launcher not found at ${csPath} after bootstrap`
|
|
1831
|
-
};
|
|
1503
|
+
const csPath = join14(getNativeLspBinDir(), "coursier");
|
|
1504
|
+
const csPathExe = join14(getNativeLspBinDir(), "coursier.exe");
|
|
1505
|
+
const cs = await pathExists2(csPath) ? csPath : await pathExists2(csPathExe) ? csPathExe : null;
|
|
1506
|
+
if (!cs) {
|
|
1507
|
+
return {
|
|
1508
|
+
installed: false,
|
|
1509
|
+
alreadyPresent: false,
|
|
1510
|
+
skipped: "coursier-bootstrap-failed",
|
|
1511
|
+
error: `coursier launcher not found at ${csPath} after bootstrap`
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
try {
|
|
1515
|
+
await fs2.mkdir(binDir, { recursive: true });
|
|
1516
|
+
await runCs(cs, ["install", "--install-dir", binDir, entry.appName]);
|
|
1517
|
+
if (!await pathExists2(binaryPath) && !await pathExists2(binaryPathExe)) {
|
|
1518
|
+
return {
|
|
1519
|
+
installed: false,
|
|
1520
|
+
alreadyPresent: false,
|
|
1521
|
+
error: `cs install ${entry.appName} completed but launcher missing at ${binaryPath}`
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
return { installed: true, alreadyPresent: false, binaryPath };
|
|
1525
|
+
} catch (err) {
|
|
1526
|
+
return {
|
|
1527
|
+
installed: false,
|
|
1528
|
+
alreadyPresent: false,
|
|
1529
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
async function runCs(cs, args) {
|
|
1534
|
+
return new Promise((resolve5, reject) => {
|
|
1535
|
+
const child = spawn4(cs, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1536
|
+
let stderr = "";
|
|
1537
|
+
child.stderr.on("data", (chunk) => {
|
|
1538
|
+
stderr += chunk.toString();
|
|
1539
|
+
});
|
|
1540
|
+
child.on("error", reject);
|
|
1541
|
+
child.on("close", (code) => {
|
|
1542
|
+
if (code === 0)
|
|
1543
|
+
resolve5();
|
|
1544
|
+
else
|
|
1545
|
+
reject(new Error(`cs ${args.join(" ")} exited ${(code ?? -1).toString()}: ${stderr.split("\n").slice(0, 3).join(" ")}`));
|
|
1546
|
+
});
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
async function pathExists2(p) {
|
|
1550
|
+
try {
|
|
1551
|
+
await fs2.access(p);
|
|
1552
|
+
return true;
|
|
1553
|
+
} catch {
|
|
1554
|
+
return false;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
var init_coursier_installer = __esm({
|
|
1558
|
+
"../listener/dist/lsp/coursier-installer.js"() {
|
|
1559
|
+
"use strict";
|
|
1560
|
+
init_src();
|
|
1561
|
+
init_installer();
|
|
1562
|
+
init_native_installer();
|
|
1563
|
+
}
|
|
1564
|
+
});
|
|
1565
|
+
|
|
1566
|
+
// ../listener/dist/lsp/toolchain-installer.js
|
|
1567
|
+
import { spawn as spawn5 } from "child_process";
|
|
1568
|
+
import { promises as fs3 } from "fs";
|
|
1569
|
+
import { homedir as homedir3 } from "os";
|
|
1570
|
+
import { join as join15 } from "path";
|
|
1571
|
+
async function ensureToolchainLspInstalled(key) {
|
|
1572
|
+
const entry = TOOLCHAIN_LSPS[key];
|
|
1573
|
+
if (!entry) {
|
|
1574
|
+
return { installed: false, alreadyPresent: false, skipped: "no-toolchain-entry" };
|
|
1575
|
+
}
|
|
1576
|
+
if (entry.bundled) {
|
|
1577
|
+
const found = await isCommandOnPath(entry.binaryName);
|
|
1578
|
+
if (found)
|
|
1579
|
+
return { installed: false, alreadyPresent: true };
|
|
1580
|
+
return { installed: false, alreadyPresent: false, skipped: "bundled-not-installable" };
|
|
1581
|
+
}
|
|
1582
|
+
if (await isCommandOnPath(entry.binaryName)) {
|
|
1583
|
+
return { installed: false, alreadyPresent: true, skipped: "already-on-path" };
|
|
1584
|
+
}
|
|
1585
|
+
if (!entry.toolchain) {
|
|
1586
|
+
return { installed: false, alreadyPresent: false, skipped: "toolchain-missing" };
|
|
1587
|
+
}
|
|
1588
|
+
if (!await isCommandOnPath(entry.toolchain)) {
|
|
1589
|
+
return {
|
|
1590
|
+
installed: false,
|
|
1591
|
+
alreadyPresent: false,
|
|
1592
|
+
skipped: "toolchain-missing",
|
|
1593
|
+
error: `${entry.toolchain} toolchain not on PATH`
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
let binDir;
|
|
1597
|
+
try {
|
|
1598
|
+
binDir = await resolveToolchainBinDir(entry);
|
|
1599
|
+
} catch (err) {
|
|
1600
|
+
return {
|
|
1601
|
+
installed: false,
|
|
1602
|
+
alreadyPresent: false,
|
|
1603
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
try {
|
|
1607
|
+
if (!entry.installArgs) {
|
|
1608
|
+
return { installed: false, alreadyPresent: false, skipped: "toolchain-missing" };
|
|
1609
|
+
}
|
|
1610
|
+
await runToolchain(entry.toolchain, entry.installArgs);
|
|
1611
|
+
} catch (err) {
|
|
1612
|
+
return {
|
|
1613
|
+
installed: false,
|
|
1614
|
+
alreadyPresent: false,
|
|
1615
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
const binaryPath = join15(binDir, entry.binaryName);
|
|
1619
|
+
if (!await pathExists3(binaryPath)) {
|
|
1620
|
+
return {
|
|
1621
|
+
installed: false,
|
|
1622
|
+
alreadyPresent: false,
|
|
1623
|
+
error: `${entry.toolchain} install of ${entry.binaryName} completed but binary missing at ${binaryPath}`,
|
|
1624
|
+
binDir
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
return { installed: true, alreadyPresent: false, binaryPath, binDir };
|
|
1628
|
+
}
|
|
1629
|
+
async function resolveToolchainBinDir(entry) {
|
|
1630
|
+
if (!entry.toolchain) {
|
|
1631
|
+
throw new Error("cannot resolve bin dir for entry without toolchain");
|
|
1632
|
+
}
|
|
1633
|
+
if (entry.toolchainBinDir) {
|
|
1634
|
+
if (entry.toolchain === "go") {
|
|
1635
|
+
const gopath = process.env["GOPATH"] ?? join15(homedir3(), "go");
|
|
1636
|
+
return join15(gopath, "bin");
|
|
1637
|
+
}
|
|
1638
|
+
return join15(homedir3(), entry.toolchainBinDir);
|
|
1639
|
+
}
|
|
1640
|
+
if (entry.toolchain === "gem") {
|
|
1641
|
+
const userdir = await captureStdout("gem", ["env", "userdir"]);
|
|
1642
|
+
return join15(userdir.trim(), "bin");
|
|
1643
|
+
}
|
|
1644
|
+
throw new Error(`no bin-dir resolution for toolchain ${entry.toolchain}`);
|
|
1645
|
+
}
|
|
1646
|
+
function getToolchainBinDirs() {
|
|
1647
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
1648
|
+
for (const entry of Object.values(TOOLCHAIN_LSPS)) {
|
|
1649
|
+
if (entry.bundled || !entry.toolchain || !entry.toolchainBinDir)
|
|
1650
|
+
continue;
|
|
1651
|
+
if (entry.toolchain === "go") {
|
|
1652
|
+
const gopath = process.env["GOPATH"] ?? join15(homedir3(), "go");
|
|
1653
|
+
dirs.add(join15(gopath, "bin"));
|
|
1654
|
+
} else {
|
|
1655
|
+
dirs.add(join15(homedir3(), entry.toolchainBinDir));
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
return [...dirs];
|
|
1659
|
+
}
|
|
1660
|
+
function runToolchain(cmd, args) {
|
|
1661
|
+
return new Promise((resolve5, reject) => {
|
|
1662
|
+
const child = spawn5(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1663
|
+
let stderr = "";
|
|
1664
|
+
child.stderr.on("data", (chunk) => {
|
|
1665
|
+
stderr += chunk.toString();
|
|
1666
|
+
});
|
|
1667
|
+
child.on("error", reject);
|
|
1668
|
+
child.on("close", (code) => {
|
|
1669
|
+
if (code === 0)
|
|
1670
|
+
resolve5();
|
|
1671
|
+
else
|
|
1672
|
+
reject(new Error(`${cmd} ${args.join(" ")} exited ${(code ?? -1).toString()}: ${stderr.split("\n").slice(0, 3).join(" ")}`));
|
|
1673
|
+
});
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
function captureStdout(cmd, args) {
|
|
1677
|
+
return new Promise((resolve5, reject) => {
|
|
1678
|
+
const child = spawn5(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1679
|
+
let stdout = "";
|
|
1680
|
+
let stderr = "";
|
|
1681
|
+
child.stdout.on("data", (chunk) => {
|
|
1682
|
+
stdout += chunk.toString();
|
|
1683
|
+
});
|
|
1684
|
+
child.stderr.on("data", (chunk) => {
|
|
1685
|
+
stderr += chunk.toString();
|
|
1686
|
+
});
|
|
1687
|
+
child.on("error", reject);
|
|
1688
|
+
child.on("close", (code) => {
|
|
1689
|
+
if (code === 0)
|
|
1690
|
+
resolve5(stdout);
|
|
1691
|
+
else
|
|
1692
|
+
reject(new Error(`${cmd} ${args.join(" ")} exited ${(code ?? -1).toString()}: ${stderr}`));
|
|
1693
|
+
});
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
async function isCommandOnPath(command) {
|
|
1697
|
+
if (/[^\w./+-]/.test(command))
|
|
1698
|
+
return false;
|
|
1699
|
+
const probeCmd = process.platform === "win32" ? "where" : "which";
|
|
1700
|
+
return new Promise((resolve5) => {
|
|
1701
|
+
const child = spawn5(probeCmd, [command], { stdio: "ignore", timeout: 5e3 });
|
|
1702
|
+
child.on("error", () => resolve5(false));
|
|
1703
|
+
child.on("close", (code) => resolve5(code === 0));
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
async function pathExists3(p) {
|
|
1707
|
+
try {
|
|
1708
|
+
await fs3.access(p);
|
|
1709
|
+
return true;
|
|
1710
|
+
} catch {
|
|
1711
|
+
return false;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
var init_toolchain_installer = __esm({
|
|
1715
|
+
"../listener/dist/lsp/toolchain-installer.js"() {
|
|
1716
|
+
"use strict";
|
|
1717
|
+
init_src();
|
|
1718
|
+
}
|
|
1719
|
+
});
|
|
1720
|
+
|
|
1721
|
+
// ../listener/dist/lsp/installer.js
|
|
1722
|
+
import { promises as fs4 } from "fs";
|
|
1723
|
+
import { join as join16, dirname as dirname6 } from "path";
|
|
1724
|
+
import { spawn as spawn6 } from "child_process";
|
|
1725
|
+
import lockfile3 from "proper-lockfile";
|
|
1726
|
+
function getLspInstallDir() {
|
|
1727
|
+
return join16(getConfigDir(), "lsp-servers");
|
|
1728
|
+
}
|
|
1729
|
+
function getLspBinDir() {
|
|
1730
|
+
return join16(getLspInstallDir(), "node_modules", ".bin");
|
|
1731
|
+
}
|
|
1732
|
+
async function ensureNpmLspInstalled(config2) {
|
|
1733
|
+
if (!config2.npmPackage)
|
|
1734
|
+
return { installed: false, skipped: "no-npm-package" };
|
|
1735
|
+
const installDir = getLspInstallDir();
|
|
1736
|
+
const binPath = join16(installDir, "node_modules", ".bin", config2.command);
|
|
1737
|
+
if (await pathExists4(binPath)) {
|
|
1738
|
+
return { installed: false, skipped: "already-present" };
|
|
1832
1739
|
}
|
|
1833
1740
|
try {
|
|
1834
|
-
await
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
};
|
|
1741
|
+
await fs4.mkdir(installDir, { recursive: true });
|
|
1742
|
+
let release = null;
|
|
1743
|
+
try {
|
|
1744
|
+
release = await lockfile3.lock(installDir, {
|
|
1745
|
+
stale: 18e4,
|
|
1746
|
+
retries: { retries: 20, factor: 1.5, minTimeout: 500, maxTimeout: 5e3 },
|
|
1747
|
+
realpath: false
|
|
1748
|
+
});
|
|
1749
|
+
} catch {
|
|
1750
|
+
if (await pathExists4(binPath)) {
|
|
1751
|
+
return { installed: false, skipped: "already-present" };
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
try {
|
|
1755
|
+
if (await pathExists4(binPath)) {
|
|
1756
|
+
return { installed: false, skipped: "already-present" };
|
|
1757
|
+
}
|
|
1758
|
+
const pkgJsonPath = join16(installDir, "package.json");
|
|
1759
|
+
if (!await pathExists4(pkgJsonPath)) {
|
|
1760
|
+
await fs4.writeFile(pkgJsonPath, JSON.stringify({ name: "repowise-lsp-servers", private: true, version: "0.0.0" }, null, 2), "utf-8");
|
|
1761
|
+
}
|
|
1762
|
+
await runNpmInstall(installDir, config2.npmPackage);
|
|
1763
|
+
if (!await pathExists4(binPath)) {
|
|
1764
|
+
return {
|
|
1765
|
+
installed: false,
|
|
1766
|
+
error: `npm install completed but ${config2.command} still not at ${binPath}`
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1769
|
+
return { installed: true };
|
|
1770
|
+
} finally {
|
|
1771
|
+
if (release) {
|
|
1772
|
+
try {
|
|
1773
|
+
await release();
|
|
1774
|
+
} catch {
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1842
1777
|
}
|
|
1843
|
-
return { installed: true, alreadyPresent: false, binaryPath };
|
|
1844
1778
|
} catch (err) {
|
|
1845
1779
|
return {
|
|
1846
1780
|
installed: false,
|
|
1847
|
-
alreadyPresent: false,
|
|
1848
1781
|
error: err instanceof Error ? err.message : String(err)
|
|
1849
1782
|
};
|
|
1850
1783
|
}
|
|
1851
1784
|
}
|
|
1852
|
-
async function
|
|
1785
|
+
async function resolveNpmCommand() {
|
|
1786
|
+
const nodeDir = dirname6(process.execPath);
|
|
1787
|
+
for (const candidate of [join16(nodeDir, "npm"), join16(nodeDir, "npm.cmd")]) {
|
|
1788
|
+
try {
|
|
1789
|
+
await fs4.access(candidate);
|
|
1790
|
+
return candidate;
|
|
1791
|
+
} catch {
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
for (const candidate of ["/opt/homebrew/bin/npm", "/usr/local/bin/npm", "/usr/bin/npm"]) {
|
|
1795
|
+
try {
|
|
1796
|
+
await fs4.access(candidate);
|
|
1797
|
+
return candidate;
|
|
1798
|
+
} catch {
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
return "npm";
|
|
1802
|
+
}
|
|
1803
|
+
async function runNpmInstall(cwd, pkg2) {
|
|
1804
|
+
const npmCmd = await resolveNpmCommand();
|
|
1805
|
+
const nodeDir = dirname6(process.execPath);
|
|
1806
|
+
const augmentedPath = process.env.PATH ? `${nodeDir}:${process.env.PATH}` : nodeDir;
|
|
1853
1807
|
return new Promise((resolve5, reject) => {
|
|
1854
|
-
const child =
|
|
1808
|
+
const child = spawn6(npmCmd, ["install", "--no-audit", "--no-fund", "--silent", pkg2], {
|
|
1809
|
+
cwd,
|
|
1810
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1811
|
+
env: { ...process.env, PATH: augmentedPath }
|
|
1812
|
+
});
|
|
1855
1813
|
let stderr = "";
|
|
1856
1814
|
child.stderr.on("data", (chunk) => {
|
|
1857
1815
|
stderr += chunk.toString();
|
|
1858
1816
|
});
|
|
1859
|
-
child.on("error", reject);
|
|
1817
|
+
child.on("error", (err) => reject(err));
|
|
1860
1818
|
child.on("close", (code) => {
|
|
1861
|
-
if (code === 0)
|
|
1819
|
+
if (code === 0) {
|
|
1862
1820
|
resolve5();
|
|
1863
|
-
else
|
|
1864
|
-
reject(new Error(`
|
|
1821
|
+
} else {
|
|
1822
|
+
reject(new Error(`npm install ${pkg2} exited ${(code ?? -1).toString()}: ${sanitizeNpmStderr(stderr)}`));
|
|
1823
|
+
}
|
|
1865
1824
|
});
|
|
1866
1825
|
});
|
|
1867
1826
|
}
|
|
1868
|
-
|
|
1827
|
+
function sanitizeNpmStderr(raw) {
|
|
1828
|
+
const truncated = raw.split("\n").slice(0, 3).join(" ").trim();
|
|
1829
|
+
return truncated.replace(/(https?:\/\/)[^@\s/]*@/g, (_match, scheme) => `${scheme}<redacted>@`);
|
|
1830
|
+
}
|
|
1831
|
+
async function pathExists4(p) {
|
|
1869
1832
|
try {
|
|
1870
|
-
await
|
|
1833
|
+
await fs4.access(p);
|
|
1871
1834
|
return true;
|
|
1872
1835
|
} catch {
|
|
1873
1836
|
return false;
|
|
1874
1837
|
}
|
|
1875
1838
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1839
|
+
async function detectRepoLanguages(repoRoot) {
|
|
1840
|
+
const found = /* @__PURE__ */ new Set();
|
|
1841
|
+
let inspected = 0;
|
|
1842
|
+
const MAX_INSPECT = 200;
|
|
1843
|
+
async function inspect(dir) {
|
|
1844
|
+
if (inspected >= MAX_INSPECT)
|
|
1845
|
+
return;
|
|
1846
|
+
let entries;
|
|
1847
|
+
try {
|
|
1848
|
+
entries = await fs4.readdir(dir);
|
|
1849
|
+
} catch {
|
|
1850
|
+
return;
|
|
1851
|
+
}
|
|
1852
|
+
for (const name of entries) {
|
|
1853
|
+
if (inspected >= MAX_INSPECT)
|
|
1854
|
+
return;
|
|
1855
|
+
if (name.startsWith("."))
|
|
1856
|
+
continue;
|
|
1857
|
+
if (name === "node_modules" || name === "dist" || name === "build")
|
|
1858
|
+
continue;
|
|
1859
|
+
const lang = detectLanguage(name);
|
|
1860
|
+
if (lang) {
|
|
1861
|
+
found.add(lang);
|
|
1862
|
+
inspected += 1;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
await inspect(repoRoot);
|
|
1867
|
+
let topEntries = [];
|
|
1868
|
+
try {
|
|
1869
|
+
topEntries = await fs4.readdir(repoRoot);
|
|
1870
|
+
} catch {
|
|
1871
|
+
return found;
|
|
1872
|
+
}
|
|
1873
|
+
for (const name of topEntries) {
|
|
1874
|
+
if (name.startsWith("."))
|
|
1875
|
+
continue;
|
|
1876
|
+
if (name === "node_modules" || name === "dist" || name === "build")
|
|
1877
|
+
continue;
|
|
1878
|
+
const sub = join16(repoRoot, name);
|
|
1879
|
+
try {
|
|
1880
|
+
const stat8 = await fs4.stat(sub);
|
|
1881
|
+
if (stat8.isDirectory())
|
|
1882
|
+
await inspect(sub);
|
|
1883
|
+
} catch {
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
return found;
|
|
1887
|
+
}
|
|
1888
|
+
async function prepareLspServersForRepos(repos, options = {}) {
|
|
1889
|
+
const detected = /* @__PURE__ */ new Set();
|
|
1890
|
+
for (const r of repos) {
|
|
1891
|
+
if (!r.localPath)
|
|
1892
|
+
continue;
|
|
1893
|
+
try {
|
|
1894
|
+
const stat8 = await fs4.stat(r.localPath);
|
|
1895
|
+
if (!stat8.isDirectory())
|
|
1896
|
+
continue;
|
|
1897
|
+
} catch {
|
|
1898
|
+
continue;
|
|
1899
|
+
}
|
|
1900
|
+
try {
|
|
1901
|
+
const langs = await detectRepoLanguages(r.localPath);
|
|
1902
|
+
for (const l of langs)
|
|
1903
|
+
detected.add(l);
|
|
1904
|
+
} catch {
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
const results = [];
|
|
1908
|
+
for (const language of detected) {
|
|
1909
|
+
const configs = getEffectiveConfigList(language, process.env, options.lspOverrides);
|
|
1910
|
+
const npmConfig = configs.find((c) => c.npmPackage);
|
|
1911
|
+
if (npmConfig) {
|
|
1912
|
+
const outcome = await ensureNpmLspInstalled(npmConfig);
|
|
1913
|
+
results.push({
|
|
1914
|
+
language,
|
|
1915
|
+
installed: outcome.installed,
|
|
1916
|
+
alreadyPresent: outcome.skipped === "already-present",
|
|
1917
|
+
skippedNoNpmPackage: false,
|
|
1918
|
+
installMethod: "npm",
|
|
1919
|
+
error: outcome.error
|
|
1920
|
+
});
|
|
1921
|
+
continue;
|
|
1922
|
+
}
|
|
1923
|
+
const nativeConfig = configs.find((c) => c.nativeInstallKey);
|
|
1924
|
+
if (nativeConfig?.nativeInstallKey) {
|
|
1925
|
+
const outcome = await ensureNativeLspInstalled(nativeConfig.nativeInstallKey);
|
|
1926
|
+
results.push({
|
|
1927
|
+
language,
|
|
1928
|
+
installed: outcome.installed,
|
|
1929
|
+
alreadyPresent: outcome.alreadyPresent,
|
|
1930
|
+
skippedNoNpmPackage: false,
|
|
1931
|
+
installMethod: "native",
|
|
1932
|
+
skipped: outcome.skipped,
|
|
1933
|
+
hint: outcome.skipped ? nativeConfig.installHint : void 0,
|
|
1934
|
+
error: outcome.error
|
|
1935
|
+
});
|
|
1936
|
+
continue;
|
|
1937
|
+
}
|
|
1938
|
+
const coursierConfig = configs.find((c) => c.coursierInstallKey);
|
|
1939
|
+
if (coursierConfig?.coursierInstallKey) {
|
|
1940
|
+
const outcome = await ensureCoursierLspInstalled(coursierConfig.coursierInstallKey);
|
|
1941
|
+
results.push({
|
|
1942
|
+
language,
|
|
1943
|
+
installed: outcome.installed,
|
|
1944
|
+
alreadyPresent: outcome.alreadyPresent,
|
|
1945
|
+
skippedNoNpmPackage: false,
|
|
1946
|
+
installMethod: "coursier",
|
|
1947
|
+
skipped: outcome.skipped,
|
|
1948
|
+
hint: outcome.skipped ? coursierConfig.installHint : void 0,
|
|
1949
|
+
error: outcome.error
|
|
1950
|
+
});
|
|
1951
|
+
continue;
|
|
1952
|
+
}
|
|
1953
|
+
const toolchainConfig = configs.find((c) => c.toolchainInstallKey);
|
|
1954
|
+
if (toolchainConfig?.toolchainInstallKey) {
|
|
1955
|
+
const outcome = await ensureToolchainLspInstalled(toolchainConfig.toolchainInstallKey);
|
|
1956
|
+
results.push({
|
|
1957
|
+
language,
|
|
1958
|
+
installed: outcome.installed,
|
|
1959
|
+
alreadyPresent: outcome.alreadyPresent,
|
|
1960
|
+
skippedNoNpmPackage: false,
|
|
1961
|
+
installMethod: "toolchain",
|
|
1962
|
+
skipped: outcome.skipped,
|
|
1963
|
+
// Surface the install hint for any skip reason — toolchain
|
|
1964
|
+
// missing means user needs to install it; bundled SDK means
|
|
1965
|
+
// user needs the SDK.
|
|
1966
|
+
hint: outcome.skipped ? toolchainConfig.installHint : void 0,
|
|
1967
|
+
error: outcome.error
|
|
1968
|
+
});
|
|
1969
|
+
continue;
|
|
1970
|
+
}
|
|
1971
|
+
results.push({
|
|
1972
|
+
language,
|
|
1973
|
+
installed: false,
|
|
1974
|
+
alreadyPresent: false,
|
|
1975
|
+
skippedNoNpmPackage: true,
|
|
1976
|
+
hint: configs[0]?.installHint
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
return results;
|
|
1980
|
+
}
|
|
1981
|
+
var init_installer = __esm({
|
|
1982
|
+
"../listener/dist/lsp/installer.js"() {
|
|
1878
1983
|
"use strict";
|
|
1879
|
-
|
|
1880
|
-
|
|
1984
|
+
init_config_dir();
|
|
1985
|
+
init_registry();
|
|
1881
1986
|
init_native_installer();
|
|
1987
|
+
init_coursier_installer();
|
|
1988
|
+
init_toolchain_installer();
|
|
1882
1989
|
}
|
|
1883
1990
|
});
|
|
1884
1991
|
|
|
1885
|
-
// ../listener/dist/lsp/
|
|
1886
|
-
import { spawn as spawn6 } from "child_process";
|
|
1887
|
-
import { promises as fs3 } from "fs";
|
|
1992
|
+
// ../listener/dist/lsp/daemon-path.js
|
|
1888
1993
|
import { homedir as homedir4 } from "os";
|
|
1889
|
-
import { join as join17 } from "path";
|
|
1890
|
-
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1994
|
+
import { delimiter, dirname as dirname7, join as join17 } from "path";
|
|
1995
|
+
function commonBinDirs() {
|
|
1996
|
+
const home = homedir4();
|
|
1997
|
+
return [
|
|
1998
|
+
"/opt/homebrew/bin",
|
|
1999
|
+
// Apple Silicon Homebrew
|
|
2000
|
+
"/opt/homebrew/sbin",
|
|
2001
|
+
"/usr/local/bin",
|
|
2002
|
+
// Intel Homebrew / common installs
|
|
2003
|
+
"/usr/bin",
|
|
2004
|
+
"/bin",
|
|
2005
|
+
"/usr/sbin",
|
|
2006
|
+
"/sbin",
|
|
2007
|
+
join17(home, ".local", "bin"),
|
|
2008
|
+
// pipx / pip --user / uv
|
|
2009
|
+
join17(home, ".npm-global", "bin"),
|
|
2010
|
+
// common npm global prefix
|
|
2011
|
+
join17(home, "go", "bin"),
|
|
2012
|
+
// gopls
|
|
2013
|
+
join17(home, ".cargo", "bin")
|
|
2014
|
+
// rust-analyzer via cargo
|
|
2015
|
+
];
|
|
2016
|
+
}
|
|
2017
|
+
function managedBinDirs() {
|
|
2018
|
+
return [getLspBinDir(), getNativeLspBinDir(), getCoursierBinDir(), ...getToolchainBinDirs()];
|
|
2019
|
+
}
|
|
2020
|
+
function dedup(dirs) {
|
|
2021
|
+
return [...new Set(dirs.filter((d) => d.length > 0))];
|
|
2022
|
+
}
|
|
2023
|
+
function daemonPathDirs() {
|
|
2024
|
+
return dedup([dirname7(process.execPath), ...commonBinDirs(), ...managedBinDirs()]);
|
|
2025
|
+
}
|
|
2026
|
+
function buildDaemonPath() {
|
|
2027
|
+
return daemonPathDirs().join(delimiter);
|
|
2028
|
+
}
|
|
2029
|
+
var init_daemon_path = __esm({
|
|
2030
|
+
"../listener/dist/lsp/daemon-path.js"() {
|
|
2031
|
+
"use strict";
|
|
2032
|
+
init_installer();
|
|
2033
|
+
init_native_installer();
|
|
2034
|
+
init_coursier_installer();
|
|
2035
|
+
init_toolchain_installer();
|
|
1924
2036
|
}
|
|
2037
|
+
});
|
|
2038
|
+
|
|
2039
|
+
// ../listener/dist/service-installer.js
|
|
2040
|
+
var service_installer_exports = {};
|
|
2041
|
+
__export(service_installer_exports, {
|
|
2042
|
+
install: () => install,
|
|
2043
|
+
isInstalled: () => isInstalled,
|
|
2044
|
+
isServiceRunning: () => isServiceRunning,
|
|
2045
|
+
stopService: () => stopService,
|
|
2046
|
+
uninstall: () => uninstall
|
|
2047
|
+
});
|
|
2048
|
+
import { execFile as execFile4 } from "child_process";
|
|
2049
|
+
import { writeFile as writeFile8, mkdir as mkdir8, unlink as unlink6 } from "fs/promises";
|
|
2050
|
+
import { homedir as homedir5 } from "os";
|
|
2051
|
+
import { join as join18 } from "path";
|
|
2052
|
+
function exec(cmd, args) {
|
|
2053
|
+
return new Promise((resolve5, reject) => {
|
|
2054
|
+
execFile4(cmd, args, (err, stdout) => {
|
|
2055
|
+
if (err) {
|
|
2056
|
+
reject(err);
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
resolve5(String(stdout ?? ""));
|
|
2060
|
+
});
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
function xmlEscape(value) {
|
|
2064
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
2065
|
+
}
|
|
2066
|
+
function sanitizeEnvValue(value) {
|
|
2067
|
+
return Array.from(value).filter((ch) => ch.charCodeAt(0) >= 32).join("");
|
|
2068
|
+
}
|
|
2069
|
+
function plistPath() {
|
|
2070
|
+
return join18(homedir5(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
2071
|
+
}
|
|
2072
|
+
function logDir() {
|
|
2073
|
+
return join18(getConfigDir(), "logs");
|
|
2074
|
+
}
|
|
2075
|
+
function buildPlist() {
|
|
2076
|
+
const cmd = resolveListenerCommand();
|
|
2077
|
+
const logs = logDir();
|
|
2078
|
+
const programArgs = [process.execPath, cmd.script, ...cmd.args].map((a) => ` <string>${xmlEscape(a)}</string>`).join("\n");
|
|
2079
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
2080
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
2081
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2082
|
+
<plist version="1.0">
|
|
2083
|
+
<dict>
|
|
2084
|
+
<key>Label</key>
|
|
2085
|
+
<string>${xmlEscape(PLIST_LABEL)}</string>
|
|
2086
|
+
<key>ProgramArguments</key>
|
|
2087
|
+
<array>
|
|
2088
|
+
${programArgs}
|
|
2089
|
+
</array>
|
|
2090
|
+
<key>RunAtLoad</key>
|
|
2091
|
+
<true/>
|
|
2092
|
+
<key>KeepAlive</key>
|
|
2093
|
+
<true/>
|
|
2094
|
+
<!--
|
|
2095
|
+
FIX-8: launchd inherits a minimal PATH (/usr/bin:/bin:\u2026) that excludes
|
|
2096
|
+
/opt/homebrew/bin + the npm-global bin, so user-installed LSP servers
|
|
2097
|
+
(pyright, rust-analyzer, \u2026) cannot be spawned and the typed-resolution
|
|
2098
|
+
which-probe fails. Inject a rich PATH (single source of truth:
|
|
2099
|
+
buildDaemonPath in lsp/daemon-path.ts) so the daemon resolves them.
|
|
2100
|
+
-->
|
|
2101
|
+
<key>EnvironmentVariables</key>
|
|
2102
|
+
<dict>
|
|
2103
|
+
<key>PATH</key>
|
|
2104
|
+
<string>${xmlEscape(buildDaemonPath())}</string>
|
|
2105
|
+
</dict>
|
|
2106
|
+
<key>StandardOutPath</key>
|
|
2107
|
+
<string>${xmlEscape(join18(logs, "listener-stdout.log"))}</string>
|
|
2108
|
+
<key>StandardErrorPath</key>
|
|
2109
|
+
<string>${xmlEscape(join18(logs, "listener-stderr.log"))}</string>
|
|
2110
|
+
<key>ProcessType</key>
|
|
2111
|
+
<string>Background</string>
|
|
2112
|
+
<!--
|
|
2113
|
+
SoftResourceLimits: raise the open-file descriptor limit from the macOS
|
|
2114
|
+
default of 256 to 4096. When multiple LSP child processes (rust-analyzer,
|
|
2115
|
+
jdtls, etc.) share the listener's fd budget they can exhaust the default
|
|
2116
|
+
very quickly, causing EMFILE errors. 4096 matches the system-wide default
|
|
2117
|
+
set by /etc/launchd.conf on modern macOS and gives enough headroom for
|
|
2118
|
+
~10 concurrent LSP servers each opening ~300 fds.
|
|
2119
|
+
|
|
2120
|
+
MemoryLimit: intentionally NOT set here. The launchd MemoryLimit key
|
|
2121
|
+
(available since macOS 12.3) terminates the entire LaunchAgent when RSS
|
|
2122
|
+
exceeds the threshold \u2014 it cannot be scoped to individual child processes.
|
|
2123
|
+
Killing the listener to evict a memory-hungry rust-analyzer instance is
|
|
2124
|
+
undesirable. Per-child memory pressure is better handled by the LSP
|
|
2125
|
+
process manager (process-manager.ts) or by OS-level memory pressure
|
|
2126
|
+
signals (SIGTERM on macOS, OOM killer on Linux).
|
|
2127
|
+
-->
|
|
2128
|
+
<key>SoftResourceLimits</key>
|
|
2129
|
+
<dict>
|
|
2130
|
+
<key>NumberOfFiles</key>
|
|
2131
|
+
<integer>4096</integer>
|
|
2132
|
+
</dict>
|
|
2133
|
+
</dict>
|
|
2134
|
+
</plist>`;
|
|
2135
|
+
}
|
|
2136
|
+
async function darwinInstall() {
|
|
2137
|
+
await mkdir8(logDir(), { recursive: true });
|
|
2138
|
+
await mkdir8(join18(homedir5(), "Library", "LaunchAgents"), { recursive: true });
|
|
1925
2139
|
try {
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
}
|
|
1929
|
-
await runToolchain(entry.toolchain, entry.installArgs);
|
|
1930
|
-
} catch (err) {
|
|
1931
|
-
return {
|
|
1932
|
-
installed: false,
|
|
1933
|
-
alreadyPresent: false,
|
|
1934
|
-
error: err instanceof Error ? err.message : String(err)
|
|
1935
|
-
};
|
|
1936
|
-
}
|
|
1937
|
-
const binaryPath = join17(binDir, entry.binaryName);
|
|
1938
|
-
if (!await pathExists3(binaryPath)) {
|
|
1939
|
-
return {
|
|
1940
|
-
installed: false,
|
|
1941
|
-
alreadyPresent: false,
|
|
1942
|
-
error: `${entry.toolchain} install of ${entry.binaryName} completed but binary missing at ${binaryPath}`,
|
|
1943
|
-
binDir
|
|
1944
|
-
};
|
|
2140
|
+
await exec("launchctl", ["unload", plistPath()]);
|
|
2141
|
+
} catch {
|
|
1945
2142
|
}
|
|
1946
|
-
|
|
2143
|
+
await writeFile8(plistPath(), buildPlist());
|
|
2144
|
+
await exec("launchctl", ["load", plistPath()]);
|
|
1947
2145
|
}
|
|
1948
|
-
async function
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
}
|
|
1952
|
-
if (entry.toolchainBinDir) {
|
|
1953
|
-
if (entry.toolchain === "go") {
|
|
1954
|
-
const gopath = process.env["GOPATH"] ?? join17(homedir4(), "go");
|
|
1955
|
-
return join17(gopath, "bin");
|
|
1956
|
-
}
|
|
1957
|
-
return join17(homedir4(), entry.toolchainBinDir);
|
|
2146
|
+
async function darwinUninstall() {
|
|
2147
|
+
try {
|
|
2148
|
+
await exec("launchctl", ["unload", plistPath()]);
|
|
2149
|
+
} catch {
|
|
1958
2150
|
}
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
2151
|
+
try {
|
|
2152
|
+
await unlink6(plistPath());
|
|
2153
|
+
} catch {
|
|
1962
2154
|
}
|
|
1963
|
-
throw new Error(`no bin-dir resolution for toolchain ${entry.toolchain}`);
|
|
1964
2155
|
}
|
|
1965
|
-
function
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
const gopath = process.env["GOPATH"] ?? join17(homedir4(), "go");
|
|
1972
|
-
dirs.add(join17(gopath, "bin"));
|
|
1973
|
-
} else {
|
|
1974
|
-
dirs.add(join17(homedir4(), entry.toolchainBinDir));
|
|
1975
|
-
}
|
|
2156
|
+
async function darwinIsInstalled() {
|
|
2157
|
+
try {
|
|
2158
|
+
const stdout = await exec("launchctl", ["list"]);
|
|
2159
|
+
return stdout.includes(PLIST_LABEL);
|
|
2160
|
+
} catch {
|
|
2161
|
+
return false;
|
|
1976
2162
|
}
|
|
1977
|
-
return [...dirs];
|
|
1978
|
-
}
|
|
1979
|
-
function runToolchain(cmd, args) {
|
|
1980
|
-
return new Promise((resolve5, reject) => {
|
|
1981
|
-
const child = spawn6(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1982
|
-
let stderr = "";
|
|
1983
|
-
child.stderr.on("data", (chunk) => {
|
|
1984
|
-
stderr += chunk.toString();
|
|
1985
|
-
});
|
|
1986
|
-
child.on("error", reject);
|
|
1987
|
-
child.on("close", (code) => {
|
|
1988
|
-
if (code === 0)
|
|
1989
|
-
resolve5();
|
|
1990
|
-
else
|
|
1991
|
-
reject(new Error(`${cmd} ${args.join(" ")} exited ${(code ?? -1).toString()}: ${stderr.split("\n").slice(0, 3).join(" ")}`));
|
|
1992
|
-
});
|
|
1993
|
-
});
|
|
1994
2163
|
}
|
|
1995
|
-
function
|
|
1996
|
-
return
|
|
1997
|
-
const child = spawn6(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1998
|
-
let stdout = "";
|
|
1999
|
-
let stderr = "";
|
|
2000
|
-
child.stdout.on("data", (chunk) => {
|
|
2001
|
-
stdout += chunk.toString();
|
|
2002
|
-
});
|
|
2003
|
-
child.stderr.on("data", (chunk) => {
|
|
2004
|
-
stderr += chunk.toString();
|
|
2005
|
-
});
|
|
2006
|
-
child.on("error", reject);
|
|
2007
|
-
child.on("close", (code) => {
|
|
2008
|
-
if (code === 0)
|
|
2009
|
-
resolve5(stdout);
|
|
2010
|
-
else
|
|
2011
|
-
reject(new Error(`${cmd} ${args.join(" ")} exited ${(code ?? -1).toString()}: ${stderr}`));
|
|
2012
|
-
});
|
|
2013
|
-
});
|
|
2164
|
+
function unitPath() {
|
|
2165
|
+
return join18(homedir5(), ".config", "systemd", "user", `${SYSTEMD_SERVICE}.service`);
|
|
2014
2166
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
const
|
|
2019
|
-
return
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2167
|
+
function buildUnit() {
|
|
2168
|
+
const cmd = resolveListenerCommand();
|
|
2169
|
+
const execStart = [process.execPath, cmd.script, ...cmd.args].join(" ");
|
|
2170
|
+
const logs = logDir();
|
|
2171
|
+
return `[Unit]
|
|
2172
|
+
Description=RepoWise Listener
|
|
2173
|
+
After=network-online.target
|
|
2174
|
+
Wants=network-online.target
|
|
2175
|
+
|
|
2176
|
+
[Service]
|
|
2177
|
+
Type=simple
|
|
2178
|
+
# FIX-8: systemd user services run with a minimal PATH and don't load shell
|
|
2179
|
+
# profiles. Inject a rich PATH so LSP servers + the typed-resolution probe
|
|
2180
|
+
# resolve (single source of truth: buildDaemonPath() in lsp/daemon-path.ts).
|
|
2181
|
+
Environment=PATH=${sanitizeEnvValue(buildDaemonPath())}
|
|
2182
|
+
ExecStart=${execStart}
|
|
2183
|
+
Restart=always
|
|
2184
|
+
RestartSec=10
|
|
2185
|
+
StandardOutput=append:${join18(logs, "listener-stdout.log")}
|
|
2186
|
+
StandardError=append:${join18(logs, "listener-stderr.log")}
|
|
2187
|
+
|
|
2188
|
+
[Install]
|
|
2189
|
+
WantedBy=default.target`;
|
|
2024
2190
|
}
|
|
2025
|
-
async function
|
|
2191
|
+
async function linuxInstall() {
|
|
2192
|
+
await mkdir8(logDir(), { recursive: true });
|
|
2193
|
+
await mkdir8(join18(homedir5(), ".config", "systemd", "user"), { recursive: true });
|
|
2194
|
+
await writeFile8(unitPath(), buildUnit());
|
|
2195
|
+
await exec("systemctl", ["--user", "daemon-reload"]);
|
|
2196
|
+
await exec("systemctl", ["--user", "enable", SYSTEMD_SERVICE]);
|
|
2197
|
+
await exec("systemctl", ["--user", "start", SYSTEMD_SERVICE]);
|
|
2198
|
+
}
|
|
2199
|
+
async function linuxUninstall() {
|
|
2026
2200
|
try {
|
|
2027
|
-
await
|
|
2028
|
-
|
|
2201
|
+
await exec("systemctl", ["--user", "stop", SYSTEMD_SERVICE]);
|
|
2202
|
+
} catch {
|
|
2203
|
+
}
|
|
2204
|
+
try {
|
|
2205
|
+
await exec("systemctl", ["--user", "disable", SYSTEMD_SERVICE]);
|
|
2206
|
+
} catch {
|
|
2207
|
+
}
|
|
2208
|
+
try {
|
|
2209
|
+
await unlink6(unitPath());
|
|
2210
|
+
} catch {
|
|
2211
|
+
}
|
|
2212
|
+
try {
|
|
2213
|
+
await exec("systemctl", ["--user", "daemon-reload"]);
|
|
2029
2214
|
} catch {
|
|
2030
|
-
return false;
|
|
2031
2215
|
}
|
|
2032
2216
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
"
|
|
2036
|
-
|
|
2217
|
+
async function linuxIsInstalled() {
|
|
2218
|
+
try {
|
|
2219
|
+
const stdout = await exec("systemctl", ["--user", "is-enabled", SYSTEMD_SERVICE]);
|
|
2220
|
+
return stdout.trim() === "enabled";
|
|
2221
|
+
} catch {
|
|
2222
|
+
return false;
|
|
2037
2223
|
}
|
|
2038
|
-
});
|
|
2039
|
-
|
|
2040
|
-
// ../listener/dist/lsp/installer.js
|
|
2041
|
-
import { promises as fs4 } from "fs";
|
|
2042
|
-
import { join as join18, dirname as dirname6 } from "path";
|
|
2043
|
-
import { spawn as spawn7 } from "child_process";
|
|
2044
|
-
import lockfile3 from "proper-lockfile";
|
|
2045
|
-
function getLspInstallDir() {
|
|
2046
|
-
return join18(getConfigDir(), "lsp-servers");
|
|
2047
2224
|
}
|
|
2048
|
-
function
|
|
2049
|
-
|
|
2225
|
+
async function win32Install() {
|
|
2226
|
+
await mkdir8(logDir(), { recursive: true });
|
|
2227
|
+
const cmd = resolveListenerCommand();
|
|
2228
|
+
const taskCmd = [process.execPath, cmd.script, ...cmd.args].map((a) => `"${a}"`).join(" ");
|
|
2229
|
+
await exec("schtasks", [
|
|
2230
|
+
"/create",
|
|
2231
|
+
"/tn",
|
|
2232
|
+
TASK_NAME,
|
|
2233
|
+
"/tr",
|
|
2234
|
+
taskCmd,
|
|
2235
|
+
"/sc",
|
|
2236
|
+
"onlogon",
|
|
2237
|
+
"/ru",
|
|
2238
|
+
process.env.USERNAME ?? "",
|
|
2239
|
+
"/f"
|
|
2240
|
+
]);
|
|
2241
|
+
await exec("schtasks", ["/run", "/tn", TASK_NAME]);
|
|
2050
2242
|
}
|
|
2051
|
-
async function
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
const binPath = join18(installDir, "node_modules", ".bin", config2.command);
|
|
2056
|
-
if (await pathExists4(binPath)) {
|
|
2057
|
-
return { installed: false, skipped: "already-present" };
|
|
2243
|
+
async function win32Uninstall() {
|
|
2244
|
+
try {
|
|
2245
|
+
await exec("schtasks", ["/end", "/tn", TASK_NAME]);
|
|
2246
|
+
} catch {
|
|
2058
2247
|
}
|
|
2059
2248
|
try {
|
|
2060
|
-
await
|
|
2061
|
-
|
|
2062
|
-
try {
|
|
2063
|
-
release = await lockfile3.lock(installDir, {
|
|
2064
|
-
stale: 18e4,
|
|
2065
|
-
retries: { retries: 20, factor: 1.5, minTimeout: 500, maxTimeout: 5e3 },
|
|
2066
|
-
realpath: false
|
|
2067
|
-
});
|
|
2068
|
-
} catch {
|
|
2069
|
-
if (await pathExists4(binPath)) {
|
|
2070
|
-
return { installed: false, skipped: "already-present" };
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
try {
|
|
2074
|
-
if (await pathExists4(binPath)) {
|
|
2075
|
-
return { installed: false, skipped: "already-present" };
|
|
2076
|
-
}
|
|
2077
|
-
const pkgJsonPath = join18(installDir, "package.json");
|
|
2078
|
-
if (!await pathExists4(pkgJsonPath)) {
|
|
2079
|
-
await fs4.writeFile(pkgJsonPath, JSON.stringify({ name: "repowise-lsp-servers", private: true, version: "0.0.0" }, null, 2), "utf-8");
|
|
2080
|
-
}
|
|
2081
|
-
await runNpmInstall(installDir, config2.npmPackage);
|
|
2082
|
-
if (!await pathExists4(binPath)) {
|
|
2083
|
-
return {
|
|
2084
|
-
installed: false,
|
|
2085
|
-
error: `npm install completed but ${config2.command} still not at ${binPath}`
|
|
2086
|
-
};
|
|
2087
|
-
}
|
|
2088
|
-
return { installed: true };
|
|
2089
|
-
} finally {
|
|
2090
|
-
if (release) {
|
|
2091
|
-
try {
|
|
2092
|
-
await release();
|
|
2093
|
-
} catch {
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
} catch (err) {
|
|
2098
|
-
return {
|
|
2099
|
-
installed: false,
|
|
2100
|
-
error: err instanceof Error ? err.message : String(err)
|
|
2101
|
-
};
|
|
2249
|
+
await exec("schtasks", ["/delete", "/tn", TASK_NAME, "/f"]);
|
|
2250
|
+
} catch {
|
|
2102
2251
|
}
|
|
2103
2252
|
}
|
|
2104
|
-
async function
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
} catch {
|
|
2111
|
-
}
|
|
2253
|
+
async function win32IsInstalled() {
|
|
2254
|
+
try {
|
|
2255
|
+
await exec("schtasks", ["/query", "/tn", TASK_NAME]);
|
|
2256
|
+
return true;
|
|
2257
|
+
} catch {
|
|
2258
|
+
return false;
|
|
2112
2259
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
}
|
|
2260
|
+
}
|
|
2261
|
+
async function darwinStop() {
|
|
2262
|
+
try {
|
|
2263
|
+
await exec("launchctl", ["unload", plistPath()]);
|
|
2264
|
+
} catch {
|
|
2119
2265
|
}
|
|
2120
|
-
return "npm";
|
|
2121
2266
|
}
|
|
2122
|
-
async function
|
|
2123
|
-
|
|
2124
|
-
const nodeDir = dirname6(process.execPath);
|
|
2125
|
-
const augmentedPath = process.env.PATH ? `${nodeDir}:${process.env.PATH}` : nodeDir;
|
|
2126
|
-
return new Promise((resolve5, reject) => {
|
|
2127
|
-
const child = spawn7(npmCmd, ["install", "--no-audit", "--no-fund", "--silent", pkg2], {
|
|
2128
|
-
cwd,
|
|
2129
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
2130
|
-
env: { ...process.env, PATH: augmentedPath }
|
|
2131
|
-
});
|
|
2132
|
-
let stderr = "";
|
|
2133
|
-
child.stderr.on("data", (chunk) => {
|
|
2134
|
-
stderr += chunk.toString();
|
|
2135
|
-
});
|
|
2136
|
-
child.on("error", (err) => reject(err));
|
|
2137
|
-
child.on("close", (code) => {
|
|
2138
|
-
if (code === 0) {
|
|
2139
|
-
resolve5();
|
|
2140
|
-
} else {
|
|
2141
|
-
reject(new Error(`npm install ${pkg2} exited ${(code ?? -1).toString()}: ${sanitizeNpmStderr(stderr)}`));
|
|
2142
|
-
}
|
|
2143
|
-
});
|
|
2144
|
-
});
|
|
2267
|
+
async function linuxStop() {
|
|
2268
|
+
await exec("systemctl", ["--user", "stop", SYSTEMD_SERVICE]);
|
|
2145
2269
|
}
|
|
2146
|
-
function
|
|
2147
|
-
|
|
2148
|
-
return truncated.replace(/(https?:\/\/)[^@\s/]*@/g, (_match, scheme) => `${scheme}<redacted>@`);
|
|
2270
|
+
async function win32Stop() {
|
|
2271
|
+
await exec("schtasks", ["/end", "/tn", TASK_NAME]);
|
|
2149
2272
|
}
|
|
2150
|
-
async function
|
|
2273
|
+
async function darwinIsServiceRunning() {
|
|
2151
2274
|
try {
|
|
2152
|
-
await
|
|
2153
|
-
|
|
2275
|
+
const stdout = await exec("launchctl", ["list", PLIST_LABEL]);
|
|
2276
|
+
const pidMatch = stdout.match(/"PID"\s*=\s*(\d+)/);
|
|
2277
|
+
return pidMatch !== null && parseInt(pidMatch[1], 10) > 0;
|
|
2154
2278
|
} catch {
|
|
2155
2279
|
return false;
|
|
2156
2280
|
}
|
|
2157
2281
|
}
|
|
2158
|
-
async function
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
return;
|
|
2165
|
-
let entries;
|
|
2166
|
-
try {
|
|
2167
|
-
entries = await fs4.readdir(dir);
|
|
2168
|
-
} catch {
|
|
2169
|
-
return;
|
|
2170
|
-
}
|
|
2171
|
-
for (const name of entries) {
|
|
2172
|
-
if (inspected >= MAX_INSPECT)
|
|
2173
|
-
return;
|
|
2174
|
-
if (name.startsWith("."))
|
|
2175
|
-
continue;
|
|
2176
|
-
if (name === "node_modules" || name === "dist" || name === "build")
|
|
2177
|
-
continue;
|
|
2178
|
-
const lang = detectLanguage(name);
|
|
2179
|
-
if (lang) {
|
|
2180
|
-
found.add(lang);
|
|
2181
|
-
inspected += 1;
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2282
|
+
async function linuxIsServiceRunning() {
|
|
2283
|
+
try {
|
|
2284
|
+
const stdout = await exec("systemctl", ["--user", "is-active", SYSTEMD_SERVICE]);
|
|
2285
|
+
return stdout.trim() === "active";
|
|
2286
|
+
} catch {
|
|
2287
|
+
return false;
|
|
2184
2288
|
}
|
|
2185
|
-
|
|
2186
|
-
|
|
2289
|
+
}
|
|
2290
|
+
async function win32IsServiceRunning() {
|
|
2187
2291
|
try {
|
|
2188
|
-
|
|
2292
|
+
const stdout = await exec("schtasks", ["/query", "/tn", TASK_NAME, "/fo", "CSV"]);
|
|
2293
|
+
return stdout.includes("Running");
|
|
2189
2294
|
} catch {
|
|
2190
|
-
return
|
|
2295
|
+
return false;
|
|
2191
2296
|
}
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2297
|
+
}
|
|
2298
|
+
async function stopService() {
|
|
2299
|
+
switch (process.platform) {
|
|
2300
|
+
case "darwin":
|
|
2301
|
+
await darwinStop();
|
|
2302
|
+
break;
|
|
2303
|
+
case "linux":
|
|
2304
|
+
await linuxStop();
|
|
2305
|
+
break;
|
|
2306
|
+
case "win32":
|
|
2307
|
+
await win32Stop();
|
|
2308
|
+
break;
|
|
2309
|
+
default:
|
|
2310
|
+
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
async function install() {
|
|
2314
|
+
switch (process.platform) {
|
|
2315
|
+
case "darwin":
|
|
2316
|
+
await darwinInstall();
|
|
2317
|
+
break;
|
|
2318
|
+
case "linux":
|
|
2319
|
+
await linuxInstall();
|
|
2320
|
+
break;
|
|
2321
|
+
case "win32":
|
|
2322
|
+
await win32Install();
|
|
2323
|
+
break;
|
|
2324
|
+
default:
|
|
2325
|
+
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
2204
2326
|
}
|
|
2205
|
-
return found;
|
|
2206
2327
|
}
|
|
2207
|
-
async function
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
const langs = await detectRepoLanguages(r.localPath);
|
|
2221
|
-
for (const l of langs)
|
|
2222
|
-
detected.add(l);
|
|
2223
|
-
} catch {
|
|
2224
|
-
}
|
|
2328
|
+
async function uninstall() {
|
|
2329
|
+
switch (process.platform) {
|
|
2330
|
+
case "darwin":
|
|
2331
|
+
await darwinUninstall();
|
|
2332
|
+
break;
|
|
2333
|
+
case "linux":
|
|
2334
|
+
await linuxUninstall();
|
|
2335
|
+
break;
|
|
2336
|
+
case "win32":
|
|
2337
|
+
await win32Uninstall();
|
|
2338
|
+
break;
|
|
2339
|
+
default:
|
|
2340
|
+
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
2225
2341
|
}
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
installMethod: "npm",
|
|
2238
|
-
error: outcome.error
|
|
2239
|
-
});
|
|
2240
|
-
continue;
|
|
2241
|
-
}
|
|
2242
|
-
const nativeConfig = configs.find((c) => c.nativeInstallKey);
|
|
2243
|
-
if (nativeConfig?.nativeInstallKey) {
|
|
2244
|
-
const outcome = await ensureNativeLspInstalled(nativeConfig.nativeInstallKey);
|
|
2245
|
-
results.push({
|
|
2246
|
-
language,
|
|
2247
|
-
installed: outcome.installed,
|
|
2248
|
-
alreadyPresent: outcome.alreadyPresent,
|
|
2249
|
-
skippedNoNpmPackage: false,
|
|
2250
|
-
installMethod: "native",
|
|
2251
|
-
skipped: outcome.skipped,
|
|
2252
|
-
hint: outcome.skipped ? nativeConfig.installHint : void 0,
|
|
2253
|
-
error: outcome.error
|
|
2254
|
-
});
|
|
2255
|
-
continue;
|
|
2256
|
-
}
|
|
2257
|
-
const coursierConfig = configs.find((c) => c.coursierInstallKey);
|
|
2258
|
-
if (coursierConfig?.coursierInstallKey) {
|
|
2259
|
-
const outcome = await ensureCoursierLspInstalled(coursierConfig.coursierInstallKey);
|
|
2260
|
-
results.push({
|
|
2261
|
-
language,
|
|
2262
|
-
installed: outcome.installed,
|
|
2263
|
-
alreadyPresent: outcome.alreadyPresent,
|
|
2264
|
-
skippedNoNpmPackage: false,
|
|
2265
|
-
installMethod: "coursier",
|
|
2266
|
-
skipped: outcome.skipped,
|
|
2267
|
-
hint: outcome.skipped ? coursierConfig.installHint : void 0,
|
|
2268
|
-
error: outcome.error
|
|
2269
|
-
});
|
|
2270
|
-
continue;
|
|
2271
|
-
}
|
|
2272
|
-
const toolchainConfig = configs.find((c) => c.toolchainInstallKey);
|
|
2273
|
-
if (toolchainConfig?.toolchainInstallKey) {
|
|
2274
|
-
const outcome = await ensureToolchainLspInstalled(toolchainConfig.toolchainInstallKey);
|
|
2275
|
-
results.push({
|
|
2276
|
-
language,
|
|
2277
|
-
installed: outcome.installed,
|
|
2278
|
-
alreadyPresent: outcome.alreadyPresent,
|
|
2279
|
-
skippedNoNpmPackage: false,
|
|
2280
|
-
installMethod: "toolchain",
|
|
2281
|
-
skipped: outcome.skipped,
|
|
2282
|
-
// Surface the install hint for any skip reason — toolchain
|
|
2283
|
-
// missing means user needs to install it; bundled SDK means
|
|
2284
|
-
// user needs the SDK.
|
|
2285
|
-
hint: outcome.skipped ? toolchainConfig.installHint : void 0,
|
|
2286
|
-
error: outcome.error
|
|
2287
|
-
});
|
|
2288
|
-
continue;
|
|
2289
|
-
}
|
|
2290
|
-
results.push({
|
|
2291
|
-
language,
|
|
2292
|
-
installed: false,
|
|
2293
|
-
alreadyPresent: false,
|
|
2294
|
-
skippedNoNpmPackage: true,
|
|
2295
|
-
hint: configs[0]?.installHint
|
|
2296
|
-
});
|
|
2342
|
+
}
|
|
2343
|
+
async function isInstalled() {
|
|
2344
|
+
switch (process.platform) {
|
|
2345
|
+
case "darwin":
|
|
2346
|
+
return darwinIsInstalled();
|
|
2347
|
+
case "linux":
|
|
2348
|
+
return linuxIsInstalled();
|
|
2349
|
+
case "win32":
|
|
2350
|
+
return win32IsInstalled();
|
|
2351
|
+
default:
|
|
2352
|
+
return false;
|
|
2297
2353
|
}
|
|
2298
|
-
return results;
|
|
2299
2354
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
2355
|
+
async function isServiceRunning() {
|
|
2356
|
+
switch (process.platform) {
|
|
2357
|
+
case "darwin":
|
|
2358
|
+
return darwinIsServiceRunning();
|
|
2359
|
+
case "linux":
|
|
2360
|
+
return linuxIsServiceRunning();
|
|
2361
|
+
case "win32":
|
|
2362
|
+
return win32IsServiceRunning();
|
|
2363
|
+
default:
|
|
2364
|
+
return false;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
var IS_STAGING, PLIST_LABEL, SYSTEMD_SERVICE, TASK_NAME;
|
|
2368
|
+
var init_service_installer = __esm({
|
|
2369
|
+
"../listener/dist/service-installer.js"() {
|
|
2302
2370
|
"use strict";
|
|
2303
2371
|
init_config_dir();
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2372
|
+
init_process_manager();
|
|
2373
|
+
init_daemon_path();
|
|
2374
|
+
IS_STAGING = true ? true : false;
|
|
2375
|
+
PLIST_LABEL = IS_STAGING ? "com.repowise-staging.listener" : "com.repowise.listener";
|
|
2376
|
+
SYSTEMD_SERVICE = IS_STAGING ? "repowise-staging-listener" : "repowise-listener";
|
|
2377
|
+
TASK_NAME = IS_STAGING ? "RepoWise Staging Listener" : "RepoWise Listener";
|
|
2308
2378
|
}
|
|
2309
2379
|
});
|
|
2310
2380
|
|
|
@@ -2316,7 +2386,7 @@ __export(sidecar_cache_exports, {
|
|
|
2316
2386
|
sidecarCachePaths: () => sidecarCachePaths
|
|
2317
2387
|
});
|
|
2318
2388
|
import { mkdir as mkdir9, readFile as readFile8, readdir as readdir3, stat as stat2, unlink as unlink8, writeFile as writeFile9 } from "fs/promises";
|
|
2319
|
-
import { dirname as
|
|
2389
|
+
import { dirname as dirname9, join as join20 } from "path";
|
|
2320
2390
|
function repoIdSafe(repoId) {
|
|
2321
2391
|
return /^[A-Za-z0-9_.-]{1,128}$/.test(repoId) && !repoId.startsWith(".");
|
|
2322
2392
|
}
|
|
@@ -2330,8 +2400,8 @@ function sidecarCachePaths(repoId, commitSha) {
|
|
|
2330
2400
|
if (!commitShaSafe(commitSha)) {
|
|
2331
2401
|
throw new Error(`unsafe commitSha: ${commitSha}`);
|
|
2332
2402
|
}
|
|
2333
|
-
const repoDir =
|
|
2334
|
-
const fullPath =
|
|
2403
|
+
const repoDir = join20(getConfigDir(), "typed-resolution", repoId);
|
|
2404
|
+
const fullPath = join20(repoDir, `${commitSha}.jsonl`);
|
|
2335
2405
|
return { fullPath, repoDir };
|
|
2336
2406
|
}
|
|
2337
2407
|
async function persistMergedSidecar(repoId, commitSha, sidecar) {
|
|
@@ -2354,7 +2424,7 @@ async function sweepSidecarDir(repoDir) {
|
|
|
2354
2424
|
const withMtime = [];
|
|
2355
2425
|
for (const name of jsonlFiles) {
|
|
2356
2426
|
try {
|
|
2357
|
-
const s = await stat2(
|
|
2427
|
+
const s = await stat2(join20(repoDir, name));
|
|
2358
2428
|
withMtime.push({ name, mtimeMs: s.mtimeMs });
|
|
2359
2429
|
} catch {
|
|
2360
2430
|
}
|
|
@@ -2365,7 +2435,7 @@ async function sweepSidecarDir(repoDir) {
|
|
|
2365
2435
|
for (const { name, mtimeMs } of candidates) {
|
|
2366
2436
|
if (now - mtimeMs >= SWEEP_MAX_AGE_MS) {
|
|
2367
2437
|
try {
|
|
2368
|
-
await unlink8(
|
|
2438
|
+
await unlink8(join20(repoDir, name));
|
|
2369
2439
|
} catch {
|
|
2370
2440
|
}
|
|
2371
2441
|
}
|
|
@@ -2469,7 +2539,10 @@ async function uploadSidecar(req, fetchImpl = fetch) {
|
|
|
2469
2539
|
throw new Error("upload-url response missing `data.url`");
|
|
2470
2540
|
const putRes = await fetchImpl(presignedUrl, {
|
|
2471
2541
|
method: "PUT",
|
|
2472
|
-
headers: {
|
|
2542
|
+
headers: {
|
|
2543
|
+
"content-type": "application/json",
|
|
2544
|
+
"x-amz-server-side-encryption": "aws:kms"
|
|
2545
|
+
},
|
|
2473
2546
|
body
|
|
2474
2547
|
});
|
|
2475
2548
|
if (!putRes.ok) {
|
|
@@ -3060,13 +3133,13 @@ var init_telemetry = __esm({
|
|
|
3060
3133
|
// bin/repowise.ts
|
|
3061
3134
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3062
3135
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3063
|
-
import { dirname as
|
|
3136
|
+
import { dirname as dirname23, join as join61 } from "path";
|
|
3064
3137
|
import { Command } from "commander";
|
|
3065
3138
|
|
|
3066
3139
|
// ../listener/dist/main.js
|
|
3067
3140
|
init_config_dir();
|
|
3068
3141
|
import { readFile as readFile13, writeFile as writeFile15, mkdir as mkdir16, stat as fsStat } from "fs/promises";
|
|
3069
|
-
import { join as
|
|
3142
|
+
import { join as join41, dirname as dirname17 } from "path";
|
|
3070
3143
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3071
3144
|
import lockfile4 from "proper-lockfile";
|
|
3072
3145
|
|
|
@@ -4877,7 +4950,7 @@ init_config_dir();
|
|
|
4877
4950
|
init_process_manager();
|
|
4878
4951
|
init_service_installer();
|
|
4879
4952
|
import { unlink as unlink7 } from "fs/promises";
|
|
4880
|
-
import { join as
|
|
4953
|
+
import { join as join19 } from "path";
|
|
4881
4954
|
async function getListenerStatus() {
|
|
4882
4955
|
const pid = await readPid();
|
|
4883
4956
|
if (pid !== null) {
|
|
@@ -4886,7 +4959,7 @@ async function getListenerStatus() {
|
|
|
4886
4959
|
return { running: true, method: "pid", pid, serviceInstalled: serviceInstalled2 };
|
|
4887
4960
|
}
|
|
4888
4961
|
try {
|
|
4889
|
-
await unlink7(
|
|
4962
|
+
await unlink7(join19(getConfigDir(), "listener.pid"));
|
|
4890
4963
|
} catch {
|
|
4891
4964
|
}
|
|
4892
4965
|
}
|
|
@@ -4931,15 +5004,15 @@ async function stopListener() {
|
|
|
4931
5004
|
|
|
4932
5005
|
// ../listener/dist/mcp/bootstrap.js
|
|
4933
5006
|
init_config_dir();
|
|
4934
|
-
import { join as
|
|
5007
|
+
import { join as join23 } from "path";
|
|
4935
5008
|
|
|
4936
5009
|
// ../listener/dist/lsp/workspace-session.js
|
|
4937
5010
|
import { pathToFileURL } from "url";
|
|
4938
5011
|
import { readFile as readFile7 } from "fs/promises";
|
|
4939
|
-
import { resolve as pathResolve2, sep as pathSep, dirname as
|
|
5012
|
+
import { resolve as pathResolve2, sep as pathSep, dirname as dirname8, delimiter as delimiter2 } from "path";
|
|
4940
5013
|
|
|
4941
5014
|
// ../listener/dist/lsp/lsp-client.js
|
|
4942
|
-
import { spawn as
|
|
5015
|
+
import { spawn as spawn7 } from "child_process";
|
|
4943
5016
|
import { EventEmitter, once } from "events";
|
|
4944
5017
|
import { Buffer as Buffer2 } from "buffer";
|
|
4945
5018
|
var LspTimeoutError = class extends Error {
|
|
@@ -4984,7 +5057,7 @@ var LspClient = class extends EventEmitter {
|
|
|
4984
5057
|
closed = false;
|
|
4985
5058
|
constructor(options) {
|
|
4986
5059
|
super();
|
|
4987
|
-
this.child = options.spawn ? options.spawn() :
|
|
5060
|
+
this.child = options.spawn ? options.spawn() : spawn7(options.command, [...options.args ?? []], {
|
|
4988
5061
|
cwd: options.cwd,
|
|
4989
5062
|
env: options.env ?? process.env,
|
|
4990
5063
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -5207,10 +5280,7 @@ var LspClient = class extends EventEmitter {
|
|
|
5207
5280
|
};
|
|
5208
5281
|
|
|
5209
5282
|
// ../listener/dist/lsp/workspace-session.js
|
|
5210
|
-
|
|
5211
|
-
init_native_installer();
|
|
5212
|
-
init_coursier_installer();
|
|
5213
|
-
init_toolchain_installer();
|
|
5283
|
+
init_daemon_path();
|
|
5214
5284
|
|
|
5215
5285
|
// ../listener/dist/lsp/bloop-lifecycle.js
|
|
5216
5286
|
import { spawn as spawn8 } from "child_process";
|
|
@@ -5270,13 +5340,7 @@ var WorkspaceManager = class {
|
|
|
5270
5340
|
this.rssSampler = opts.rssSampler ?? (() => process.memoryUsage().rss);
|
|
5271
5341
|
this.clientFactory = opts.clientFactory ?? ((config2, cwd) => {
|
|
5272
5342
|
const env = { ...process.env };
|
|
5273
|
-
|
|
5274
|
-
getLspBinDir(),
|
|
5275
|
-
getNativeLspBinDir(),
|
|
5276
|
-
getCoursierBinDir(),
|
|
5277
|
-
...getToolchainBinDirs()
|
|
5278
|
-
];
|
|
5279
|
-
env.PATH = buildLspSpawnPath(env.PATH, dirname7(process.execPath), lspBinDirs);
|
|
5343
|
+
env.PATH = buildLspSpawnPath(env.PATH, dirname8(process.execPath), managedBinDirs());
|
|
5280
5344
|
const client = new LspClient({
|
|
5281
5345
|
command: config2.command,
|
|
5282
5346
|
args: config2.args,
|
|
@@ -5645,14 +5709,19 @@ var PathEscapeError = class extends Error {
|
|
|
5645
5709
|
}
|
|
5646
5710
|
};
|
|
5647
5711
|
function buildLspSpawnPath(basePath, nodeDir, lspBinDirs) {
|
|
5648
|
-
const
|
|
5649
|
-
|
|
5712
|
+
const parts = [
|
|
5713
|
+
nodeDir,
|
|
5714
|
+
...basePath ? basePath.split(delimiter2) : [],
|
|
5715
|
+
...commonBinDirs(),
|
|
5716
|
+
...lspBinDirs
|
|
5717
|
+
];
|
|
5718
|
+
return [...new Set(parts.filter((d) => d.length > 0))].join(delimiter2);
|
|
5650
5719
|
}
|
|
5651
5720
|
|
|
5652
5721
|
// ../listener/dist/mcp/graph-cache.js
|
|
5653
5722
|
init_config_dir();
|
|
5654
5723
|
import { readFile as readFile9, stat as stat3 } from "fs/promises";
|
|
5655
|
-
import { join as
|
|
5724
|
+
import { join as join21 } from "path";
|
|
5656
5725
|
var EVICT_DEBOUNCE_MS = 6e4;
|
|
5657
5726
|
function assertSafeRepoId(repoId) {
|
|
5658
5727
|
if (!repoId || typeof repoId !== "string") {
|
|
@@ -5667,7 +5736,7 @@ function assertSafeRepoId(repoId) {
|
|
|
5667
5736
|
}
|
|
5668
5737
|
function createGraphCache(options = {}) {
|
|
5669
5738
|
const evictMs = options.evictDebounceMs ?? EVICT_DEBOUNCE_MS;
|
|
5670
|
-
const resolvePath = options.resolveGraphPath ?? ((repoId) =>
|
|
5739
|
+
const resolvePath = options.resolveGraphPath ?? ((repoId) => join21(defaultRepoWiseHome(), "graphs", `${repoId}.json`));
|
|
5671
5740
|
const entries = /* @__PURE__ */ new Map();
|
|
5672
5741
|
const inFlight = /* @__PURE__ */ new Map();
|
|
5673
5742
|
async function loadFromDisk(repoId) {
|
|
@@ -5761,7 +5830,7 @@ function defaultRepoWiseHome() {
|
|
|
5761
5830
|
|
|
5762
5831
|
// ../listener/dist/mcp/graph-downloader.js
|
|
5763
5832
|
import { mkdir as mkdir10, rename as rename3, writeFile as writeFile10 } from "fs/promises";
|
|
5764
|
-
import { dirname as
|
|
5833
|
+
import { dirname as dirname10 } from "path";
|
|
5765
5834
|
function createGraphDownloader(options) {
|
|
5766
5835
|
const fetchFn = options.fetchImpl ?? fetch;
|
|
5767
5836
|
let lastSha = null;
|
|
@@ -5812,7 +5881,7 @@ function createGraphDownloader(options) {
|
|
|
5812
5881
|
message: `graph parse: ${err instanceof Error ? err.message : String(err)}`
|
|
5813
5882
|
};
|
|
5814
5883
|
}
|
|
5815
|
-
await mkdir10(
|
|
5884
|
+
await mkdir10(dirname10(options.targetPath), { recursive: true });
|
|
5816
5885
|
const tmpPath = `${options.targetPath}.${Date.now()}.tmp`;
|
|
5817
5886
|
await writeFile10(tmpPath, body, { encoding: "utf-8", mode: 384 });
|
|
5818
5887
|
await rename3(tmpPath, options.targetPath);
|
|
@@ -5838,7 +5907,7 @@ function createGraphDownloader(options) {
|
|
|
5838
5907
|
// ../listener/dist/mcp/log-encryption.js
|
|
5839
5908
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
5840
5909
|
import { mkdir as mkdir11, readFile as readFile10, stat as stat4, writeFile as writeFile11 } from "fs/promises";
|
|
5841
|
-
import { dirname as
|
|
5910
|
+
import { dirname as dirname11 } from "path";
|
|
5842
5911
|
var KEY_BYTES = 32;
|
|
5843
5912
|
var IV_BYTES = 12;
|
|
5844
5913
|
var TAG_BYTES = 16;
|
|
@@ -5885,7 +5954,7 @@ function createFileKeyStore(keyPath) {
|
|
|
5885
5954
|
return parsed;
|
|
5886
5955
|
}
|
|
5887
5956
|
const fresh = randomBytes(KEY_BYTES);
|
|
5888
|
-
await mkdir11(
|
|
5957
|
+
await mkdir11(dirname11(keyPath), { recursive: true });
|
|
5889
5958
|
const tmp = `${keyPath}.tmp`;
|
|
5890
5959
|
await writeFile11(tmp, fresh.toString("base64") + "\n", {
|
|
5891
5960
|
encoding: "utf-8",
|
|
@@ -5927,7 +5996,7 @@ function decryptLine(encoded, key) {
|
|
|
5927
5996
|
|
|
5928
5997
|
// ../listener/dist/mcp/mcp-logger.js
|
|
5929
5998
|
import { appendFile, mkdir as mkdir12, stat as stat5, unlink as unlink9, writeFile as writeFile12, readFile as readFile11 } from "fs/promises";
|
|
5930
|
-
import { dirname as
|
|
5999
|
+
import { dirname as dirname12 } from "path";
|
|
5931
6000
|
var DEFAULT_MAX_BYTES = 100 * 1024 * 1024;
|
|
5932
6001
|
function createMcpLogger(options) {
|
|
5933
6002
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
@@ -5950,7 +6019,7 @@ function createMcpLogger(options) {
|
|
|
5950
6019
|
await migrateLegacyPlaintext();
|
|
5951
6020
|
const key = await options.keyStore.getKey();
|
|
5952
6021
|
const encoded = encryptLine(JSON.stringify(entry), key) + "\n";
|
|
5953
|
-
await mkdir12(
|
|
6022
|
+
await mkdir12(dirname12(options.filePath), { recursive: true });
|
|
5954
6023
|
await appendFile(options.filePath, encoded, { encoding: "utf-8", mode: 384 });
|
|
5955
6024
|
try {
|
|
5956
6025
|
const s = await stat5(options.filePath);
|
|
@@ -5984,7 +6053,7 @@ async function rotate(path, size) {
|
|
|
5984
6053
|
// ../listener/dist/mcp/mcp-log-uploader.js
|
|
5985
6054
|
import { randomUUID } from "crypto";
|
|
5986
6055
|
import { readFile as readFile12, writeFile as writeFile13, mkdir as mkdir13 } from "fs/promises";
|
|
5987
|
-
import { dirname as
|
|
6056
|
+
import { dirname as dirname13 } from "path";
|
|
5988
6057
|
var DEFAULT_MAX_ENTRIES = 5e3;
|
|
5989
6058
|
var DEFAULT_MAX_BYTES2 = 1 * 1024 * 1024;
|
|
5990
6059
|
function createMcpLogUploader(options) {
|
|
@@ -6134,7 +6203,7 @@ async function readPendingBatch(watermarkPath) {
|
|
|
6134
6203
|
}
|
|
6135
6204
|
}
|
|
6136
6205
|
async function writePendingBatch(watermarkPath, batchId) {
|
|
6137
|
-
await mkdir13(
|
|
6206
|
+
await mkdir13(dirname13(watermarkPath), { recursive: true });
|
|
6138
6207
|
await writeFile13(pendingPath(watermarkPath), batchId, { encoding: "utf-8", mode: 384 });
|
|
6139
6208
|
}
|
|
6140
6209
|
async function clearPendingBatch(watermarkPath) {
|
|
@@ -6156,7 +6225,7 @@ async function readWatermark(path) {
|
|
|
6156
6225
|
}
|
|
6157
6226
|
}
|
|
6158
6227
|
async function writeWatermark(path, offset) {
|
|
6159
|
-
await mkdir13(
|
|
6228
|
+
await mkdir13(dirname13(path), { recursive: true });
|
|
6160
6229
|
const tmp = `${path}.tmp`;
|
|
6161
6230
|
await writeFile13(tmp, offset.toString() + "\n", { encoding: "utf-8", mode: 384 });
|
|
6162
6231
|
const { rename: rename5 } = await import("fs/promises");
|
|
@@ -6176,7 +6245,7 @@ async function isLocallyConsented(flagPath2) {
|
|
|
6176
6245
|
init_config_dir();
|
|
6177
6246
|
import { createServer } from "http";
|
|
6178
6247
|
import { mkdir as mkdir14, writeFile as writeFile14 } from "fs/promises";
|
|
6179
|
-
import { dirname as
|
|
6248
|
+
import { dirname as dirname14, join as join22 } from "path";
|
|
6180
6249
|
import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
|
|
6181
6250
|
|
|
6182
6251
|
// ../listener/dist/mcp/sanitize.js
|
|
@@ -7694,7 +7763,7 @@ async function readJson(req) {
|
|
|
7694
7763
|
}
|
|
7695
7764
|
}
|
|
7696
7765
|
async function writeEndpointFile(path, endpoint, secret) {
|
|
7697
|
-
await mkdir14(
|
|
7766
|
+
await mkdir14(dirname14(path), { recursive: true });
|
|
7698
7767
|
await writeFile14(path, formatEndpointFile({ endpoint, secret }), {
|
|
7699
7768
|
encoding: "utf-8",
|
|
7700
7769
|
mode: 384
|
|
@@ -7708,7 +7777,7 @@ function extractBearer(header) {
|
|
|
7708
7777
|
return m ? m[1] : null;
|
|
7709
7778
|
}
|
|
7710
7779
|
function defaultEndpointFile() {
|
|
7711
|
-
return
|
|
7780
|
+
return join22(getConfigDir(), "listener.endpoint");
|
|
7712
7781
|
}
|
|
7713
7782
|
|
|
7714
7783
|
// ../listener/dist/mcp/bootstrap.js
|
|
@@ -7716,7 +7785,7 @@ async function startMcp(options) {
|
|
|
7716
7785
|
const disabled = process.env.REPOWISE_MCP_DISABLED === "true";
|
|
7717
7786
|
const graphsDir = options.graphsDir ?? defaultGraphsDir();
|
|
7718
7787
|
const graphCache = createGraphCache({
|
|
7719
|
-
resolveGraphPath: (repoId) =>
|
|
7788
|
+
resolveGraphPath: (repoId) => join23(graphsDir, `${repoId}.json`)
|
|
7720
7789
|
});
|
|
7721
7790
|
if (disabled) {
|
|
7722
7791
|
return {
|
|
@@ -7739,12 +7808,12 @@ async function startMcp(options) {
|
|
|
7739
7808
|
}
|
|
7740
7809
|
const firstRepoLocal = options.repos.find((r) => r.localPath)?.localPath;
|
|
7741
7810
|
const mcpHome = defaultMcpHome();
|
|
7742
|
-
const logFilePath =
|
|
7743
|
-
const keyStore = createFileKeyStore(
|
|
7811
|
+
const logFilePath = join23(mcpHome, "mcp-log.jsonl.enc");
|
|
7812
|
+
const keyStore = createFileKeyStore(join23(mcpHome, "mcp-log.key"));
|
|
7744
7813
|
const mcpLogger = createMcpLogger({ filePath: logFilePath, keyStore });
|
|
7745
|
-
const flagFilePath =
|
|
7746
|
-
const watermarkFilePath =
|
|
7747
|
-
const consentSentMarkerPath =
|
|
7814
|
+
const flagFilePath = join23(mcpHome, "mcp-log.flag");
|
|
7815
|
+
const watermarkFilePath = join23(mcpHome, "mcp-log.watermark");
|
|
7816
|
+
const consentSentMarkerPath = join23(mcpHome, "mcp-log.consent-sent");
|
|
7748
7817
|
let uploader = null;
|
|
7749
7818
|
let lastConsentState = false;
|
|
7750
7819
|
let serverConsentEnsuredThisProcess = false;
|
|
@@ -7791,7 +7860,7 @@ async function startMcp(options) {
|
|
|
7791
7860
|
apiBaseUrl: repo.apiUrl,
|
|
7792
7861
|
getAuthToken: options.getAuthToken,
|
|
7793
7862
|
repoId: repo.repoId,
|
|
7794
|
-
targetPath:
|
|
7863
|
+
targetPath: join23(graphsDir, `${repo.repoId}.json`),
|
|
7795
7864
|
graphCache,
|
|
7796
7865
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
7797
7866
|
}));
|
|
@@ -7876,7 +7945,7 @@ async function startMcp(options) {
|
|
|
7876
7945
|
apiBaseUrl: repo.apiUrl,
|
|
7877
7946
|
getAuthToken: options.getAuthToken,
|
|
7878
7947
|
repoId: repo.repoId,
|
|
7879
|
-
targetPath:
|
|
7948
|
+
targetPath: join23(graphsDir, `${repo.repoId}.json`),
|
|
7880
7949
|
graphCache,
|
|
7881
7950
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
7882
7951
|
}));
|
|
@@ -7897,7 +7966,7 @@ async function startMcp(options) {
|
|
|
7897
7966
|
};
|
|
7898
7967
|
}
|
|
7899
7968
|
function defaultGraphsDir() {
|
|
7900
|
-
return
|
|
7969
|
+
return join23(getConfigDir(), "graphs");
|
|
7901
7970
|
}
|
|
7902
7971
|
function defaultMcpHome() {
|
|
7903
7972
|
return getConfigDir();
|
|
@@ -7950,16 +8019,16 @@ async function ensureServerConsent(opts) {
|
|
|
7950
8019
|
}
|
|
7951
8020
|
|
|
7952
8021
|
// ../listener/dist/mcp/auto-config/index.js
|
|
7953
|
-
import { homedir as
|
|
8022
|
+
import { homedir as homedir6 } from "os";
|
|
7954
8023
|
import { basename as basename3 } from "path";
|
|
7955
8024
|
|
|
7956
8025
|
// ../listener/dist/mcp/auto-config/writers/claude-code.js
|
|
7957
8026
|
import { promises as fs6 } from "fs";
|
|
7958
|
-
import { join as
|
|
8027
|
+
import { join as join24 } from "path";
|
|
7959
8028
|
|
|
7960
8029
|
// ../listener/dist/mcp/auto-config/markers.js
|
|
7961
8030
|
import { promises as fs5 } from "fs";
|
|
7962
|
-
import { dirname as
|
|
8031
|
+
import { dirname as dirname15 } from "path";
|
|
7963
8032
|
async function writeMergedConfig(params) {
|
|
7964
8033
|
const current = await readConfig(params.path);
|
|
7965
8034
|
const servers = { ...current.mcpServers ?? {} };
|
|
@@ -7969,7 +8038,7 @@ async function writeMergedConfig(params) {
|
|
|
7969
8038
|
const existing = safeExistingContent(params.path, current);
|
|
7970
8039
|
if (existing === canonical)
|
|
7971
8040
|
return "unchanged";
|
|
7972
|
-
await fs5.mkdir(
|
|
8041
|
+
await fs5.mkdir(dirname15(params.path), { recursive: true });
|
|
7973
8042
|
await fs5.writeFile(params.path, canonical, "utf-8");
|
|
7974
8043
|
return "written";
|
|
7975
8044
|
}
|
|
@@ -8035,10 +8104,10 @@ function safeExistingContent(path, current) {
|
|
|
8035
8104
|
var claudeCodeWriter = {
|
|
8036
8105
|
tool: "claude-code",
|
|
8037
8106
|
async detect(repoRoot, home) {
|
|
8038
|
-
return await fileExists2(
|
|
8107
|
+
return await fileExists2(join24(repoRoot, "CLAUDE.md")) || await hasClaudeBinary(home);
|
|
8039
8108
|
},
|
|
8040
8109
|
async write(ctx) {
|
|
8041
|
-
const path =
|
|
8110
|
+
const path = join24(ctx.repoRoot, ".mcp.json");
|
|
8042
8111
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8043
8112
|
const status2 = await writeMergedConfig({
|
|
8044
8113
|
path,
|
|
@@ -8048,7 +8117,7 @@ var claudeCodeWriter = {
|
|
|
8048
8117
|
return { status: status2, path };
|
|
8049
8118
|
},
|
|
8050
8119
|
async remove(ctx) {
|
|
8051
|
-
const path =
|
|
8120
|
+
const path = join24(ctx.repoRoot, ".mcp.json");
|
|
8052
8121
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8053
8122
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8054
8123
|
}
|
|
@@ -8062,20 +8131,20 @@ async function fileExists2(path) {
|
|
|
8062
8131
|
}
|
|
8063
8132
|
}
|
|
8064
8133
|
async function hasClaudeBinary(home) {
|
|
8065
|
-
return fileExists2(
|
|
8134
|
+
return fileExists2(join24(home, ".claude", "claude.json"));
|
|
8066
8135
|
}
|
|
8067
8136
|
|
|
8068
8137
|
// ../listener/dist/mcp/auto-config/writers/claude-code-hooks.js
|
|
8069
8138
|
import { promises as fs7 } from "fs";
|
|
8070
|
-
import { join as
|
|
8139
|
+
import { join as join25 } from "path";
|
|
8071
8140
|
var claudeCodeHooksWriter = {
|
|
8072
8141
|
tool: "claude-code-hooks",
|
|
8073
8142
|
async detect(repoRoot, home) {
|
|
8074
|
-
return await fileExists3(
|
|
8143
|
+
return await fileExists3(join25(repoRoot, "CLAUDE.md")) || await fileExists3(join25(home, ".claude.json"));
|
|
8075
8144
|
},
|
|
8076
8145
|
async write(ctx) {
|
|
8077
8146
|
const result = await writeClaudeHooksToRepo(ctx.repoRoot, ctx.contextFolder ?? "repowise-context", ctx.variant);
|
|
8078
|
-
return { status: result.status, path:
|
|
8147
|
+
return { status: result.status, path: join25(ctx.repoRoot, result.relPath) };
|
|
8079
8148
|
},
|
|
8080
8149
|
async remove(ctx) {
|
|
8081
8150
|
await removeClaudeHooksFromRepo(ctx.repoRoot);
|
|
@@ -8092,14 +8161,14 @@ async function fileExists3(path) {
|
|
|
8092
8161
|
|
|
8093
8162
|
// ../listener/dist/mcp/auto-config/writers/cline.js
|
|
8094
8163
|
import { promises as fs8 } from "fs";
|
|
8095
|
-
import { join as
|
|
8164
|
+
import { join as join26 } from "path";
|
|
8096
8165
|
var clineWriter = {
|
|
8097
8166
|
tool: "cline",
|
|
8098
8167
|
async detect(repoRoot, home) {
|
|
8099
|
-
return await fileExists4(
|
|
8168
|
+
return await fileExists4(join26(repoRoot, ".clinerules")) || await fileExists4(join26(home, ".cline"));
|
|
8100
8169
|
},
|
|
8101
8170
|
async write(ctx) {
|
|
8102
|
-
const path =
|
|
8171
|
+
const path = join26(ctx.home, ".cline", "mcp.json");
|
|
8103
8172
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8104
8173
|
const status2 = await writeMergedConfig({
|
|
8105
8174
|
path,
|
|
@@ -8109,7 +8178,7 @@ var clineWriter = {
|
|
|
8109
8178
|
return { status: status2, path };
|
|
8110
8179
|
},
|
|
8111
8180
|
async remove(ctx) {
|
|
8112
|
-
const path =
|
|
8181
|
+
const path = join26(ctx.home, ".cline", "mcp.json");
|
|
8113
8182
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8114
8183
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8115
8184
|
}
|
|
@@ -8125,13 +8194,13 @@ async function fileExists4(path) {
|
|
|
8125
8194
|
|
|
8126
8195
|
// ../listener/dist/mcp/auto-config/writers/cline-hooks.js
|
|
8127
8196
|
import { promises as fs9 } from "fs";
|
|
8128
|
-
import { join as
|
|
8197
|
+
import { join as join27 } from "path";
|
|
8129
8198
|
var SCRIPT_REL = ".clinerules/hooks/UserPromptSubmit";
|
|
8130
8199
|
var OWNERSHIP_MARKER = "managed by RepoWise";
|
|
8131
8200
|
var clineHooksWriter = {
|
|
8132
8201
|
tool: "cline-hooks",
|
|
8133
8202
|
async detect(repoRoot) {
|
|
8134
|
-
return fileExists5(
|
|
8203
|
+
return fileExists5(join27(repoRoot, ".clinerules"));
|
|
8135
8204
|
},
|
|
8136
8205
|
async write(ctx) {
|
|
8137
8206
|
if (await isGitTracked(ctx.repoRoot, SCRIPT_REL)) {
|
|
@@ -8141,7 +8210,7 @@ var clineHooksWriter = {
|
|
|
8141
8210
|
reason: `${SCRIPT_REL} is git-tracked; update it manually to opt in`
|
|
8142
8211
|
};
|
|
8143
8212
|
}
|
|
8144
|
-
const path =
|
|
8213
|
+
const path = join27(ctx.repoRoot, SCRIPT_REL);
|
|
8145
8214
|
const next = buildClineHookScript({
|
|
8146
8215
|
repoName: ctx.repoName,
|
|
8147
8216
|
contextFolder: ctx.contextFolder ?? "repowise-context",
|
|
@@ -8158,14 +8227,14 @@ var clineHooksWriter = {
|
|
|
8158
8227
|
await ensureExecutable(path);
|
|
8159
8228
|
return { status: "unchanged", path };
|
|
8160
8229
|
}
|
|
8161
|
-
await fs9.mkdir(
|
|
8230
|
+
await fs9.mkdir(join27(ctx.repoRoot, ".clinerules", "hooks"), { recursive: true });
|
|
8162
8231
|
await fs9.writeFile(path, next, { encoding: "utf-8", mode: 493 });
|
|
8163
8232
|
await ensureExecutable(path);
|
|
8164
8233
|
await applyGitignoreChanges(ctx.repoRoot, { add: [SCRIPT_REL] });
|
|
8165
8234
|
return { status: "written", path };
|
|
8166
8235
|
},
|
|
8167
8236
|
async remove(ctx) {
|
|
8168
|
-
const path =
|
|
8237
|
+
const path = join27(ctx.repoRoot, SCRIPT_REL);
|
|
8169
8238
|
const existing = await readOrNull(path);
|
|
8170
8239
|
if (existing !== null && existing.includes(OWNERSHIP_MARKER)) {
|
|
8171
8240
|
await fs9.unlink(path);
|
|
@@ -8200,14 +8269,14 @@ async function readOrNull(path) {
|
|
|
8200
8269
|
|
|
8201
8270
|
// ../listener/dist/mcp/auto-config/writers/codex.js
|
|
8202
8271
|
import { promises as fs10 } from "fs";
|
|
8203
|
-
import { join as
|
|
8272
|
+
import { join as join28 } from "path";
|
|
8204
8273
|
var codexWriter = {
|
|
8205
8274
|
tool: "codex",
|
|
8206
8275
|
async detect(_repoRoot, home) {
|
|
8207
|
-
return fileExists6(
|
|
8276
|
+
return fileExists6(join28(home, ".codex"));
|
|
8208
8277
|
},
|
|
8209
8278
|
async write(ctx) {
|
|
8210
|
-
const path =
|
|
8279
|
+
const path = join28(ctx.home, ".codex", "mcp.json");
|
|
8211
8280
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8212
8281
|
const status2 = await writeMergedConfig({
|
|
8213
8282
|
path,
|
|
@@ -8217,7 +8286,7 @@ var codexWriter = {
|
|
|
8217
8286
|
return { status: status2, path };
|
|
8218
8287
|
},
|
|
8219
8288
|
async remove(ctx) {
|
|
8220
|
-
const path =
|
|
8289
|
+
const path = join28(ctx.home, ".codex", "mcp.json");
|
|
8221
8290
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8222
8291
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8223
8292
|
}
|
|
@@ -8233,15 +8302,15 @@ async function fileExists6(path) {
|
|
|
8233
8302
|
|
|
8234
8303
|
// ../listener/dist/mcp/auto-config/writers/codex-hooks.js
|
|
8235
8304
|
import { promises as fs11 } from "fs";
|
|
8236
|
-
import { join as
|
|
8305
|
+
import { join as join29 } from "path";
|
|
8237
8306
|
var HOOKS_REL = ".codex/hooks.json";
|
|
8238
8307
|
var codexHooksWriter = {
|
|
8239
8308
|
tool: "codex-hooks",
|
|
8240
8309
|
async detect(repoRoot, home) {
|
|
8241
|
-
return await fileExists7(
|
|
8310
|
+
return await fileExists7(join29(home, ".codex")) || await fileExists7(join29(repoRoot, ".codex"));
|
|
8242
8311
|
},
|
|
8243
8312
|
async write(ctx) {
|
|
8244
|
-
const repoSignal = await fileExists7(
|
|
8313
|
+
const repoSignal = await fileExists7(join29(ctx.repoRoot, ".codex"));
|
|
8245
8314
|
const selected = ctx.selectedTools?.includes("codex") ?? false;
|
|
8246
8315
|
if (!repoSignal && !selected) {
|
|
8247
8316
|
return { status: "skipped", reason: "no repo-scoped Codex signal and not selected" };
|
|
@@ -8253,7 +8322,7 @@ var codexHooksWriter = {
|
|
|
8253
8322
|
reason: `${HOOKS_REL} is git-tracked; add the RepoWise UserPromptSubmit hook manually to opt in`
|
|
8254
8323
|
};
|
|
8255
8324
|
}
|
|
8256
|
-
const path =
|
|
8325
|
+
const path = join29(ctx.repoRoot, HOOKS_REL);
|
|
8257
8326
|
const existing = await readOrNull2(path);
|
|
8258
8327
|
const merged = mergeCodexHookSettings(existing, {
|
|
8259
8328
|
repoName: ctx.repoName,
|
|
@@ -8263,13 +8332,13 @@ var codexHooksWriter = {
|
|
|
8263
8332
|
if (merged === existing) {
|
|
8264
8333
|
return { status: "unchanged", path };
|
|
8265
8334
|
}
|
|
8266
|
-
await fs11.mkdir(
|
|
8335
|
+
await fs11.mkdir(join29(ctx.repoRoot, ".codex"), { recursive: true });
|
|
8267
8336
|
await fs11.writeFile(path, merged, "utf-8");
|
|
8268
8337
|
await applyGitignoreChanges(ctx.repoRoot, { add: [HOOKS_REL] });
|
|
8269
8338
|
return { status: "written", path };
|
|
8270
8339
|
},
|
|
8271
8340
|
async remove(ctx) {
|
|
8272
|
-
const path =
|
|
8341
|
+
const path = join29(ctx.repoRoot, HOOKS_REL);
|
|
8273
8342
|
const existing = await readOrNull2(path);
|
|
8274
8343
|
if (existing !== null) {
|
|
8275
8344
|
const next = removeCodexHookSettings(existing);
|
|
@@ -8300,14 +8369,14 @@ async function readOrNull2(path) {
|
|
|
8300
8369
|
|
|
8301
8370
|
// ../listener/dist/mcp/auto-config/writers/copilot.js
|
|
8302
8371
|
import { promises as fs12 } from "fs";
|
|
8303
|
-
import { join as
|
|
8372
|
+
import { join as join30 } from "path";
|
|
8304
8373
|
var copilotWriter = {
|
|
8305
8374
|
tool: "copilot",
|
|
8306
8375
|
async detect(repoRoot) {
|
|
8307
|
-
return fileExists8(
|
|
8376
|
+
return fileExists8(join30(repoRoot, ".vscode"));
|
|
8308
8377
|
},
|
|
8309
8378
|
async write(ctx) {
|
|
8310
|
-
const path =
|
|
8379
|
+
const path = join30(ctx.repoRoot, ".vscode", "mcp.json");
|
|
8311
8380
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8312
8381
|
const status2 = await writeMergedConfig({
|
|
8313
8382
|
path,
|
|
@@ -8317,7 +8386,7 @@ var copilotWriter = {
|
|
|
8317
8386
|
return { status: status2, path };
|
|
8318
8387
|
},
|
|
8319
8388
|
async remove(ctx) {
|
|
8320
|
-
const path =
|
|
8389
|
+
const path = join30(ctx.repoRoot, ".vscode", "mcp.json");
|
|
8321
8390
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8322
8391
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8323
8392
|
}
|
|
@@ -8333,15 +8402,15 @@ async function fileExists8(path) {
|
|
|
8333
8402
|
|
|
8334
8403
|
// ../listener/dist/mcp/auto-config/writers/copilot-hooks.js
|
|
8335
8404
|
import { promises as fs13 } from "fs";
|
|
8336
|
-
import { join as
|
|
8405
|
+
import { join as join31 } from "path";
|
|
8337
8406
|
var HOOKS_REL2 = ".github/hooks/repowise.json";
|
|
8338
8407
|
var copilotHooksWriter = {
|
|
8339
8408
|
tool: "copilot-hooks",
|
|
8340
8409
|
async detect(repoRoot) {
|
|
8341
|
-
return fileExists9(
|
|
8410
|
+
return fileExists9(join31(repoRoot, ".github", "copilot-instructions.md"));
|
|
8342
8411
|
},
|
|
8343
8412
|
async write(ctx) {
|
|
8344
|
-
const path =
|
|
8413
|
+
const path = join31(ctx.repoRoot, HOOKS_REL2);
|
|
8345
8414
|
const next = buildCopilotHooksFile({
|
|
8346
8415
|
repoName: ctx.repoName,
|
|
8347
8416
|
contextFolder: ctx.contextFolder ?? "repowise-context",
|
|
@@ -8361,14 +8430,14 @@ var copilotHooksWriter = {
|
|
|
8361
8430
|
if (existing === next) {
|
|
8362
8431
|
return { status: "unchanged", path };
|
|
8363
8432
|
}
|
|
8364
|
-
await fs13.mkdir(
|
|
8433
|
+
await fs13.mkdir(join31(ctx.repoRoot, ".github", "hooks"), { recursive: true });
|
|
8365
8434
|
await fs13.writeFile(path, next, "utf-8");
|
|
8366
8435
|
const userSelected = ctx.selectedTools?.includes("copilot") ?? false;
|
|
8367
8436
|
await applyGitignoreChanges(ctx.repoRoot, userSelected ? { remove: [HOOKS_REL2] } : { add: [HOOKS_REL2] });
|
|
8368
8437
|
return { status: "written", path };
|
|
8369
8438
|
},
|
|
8370
8439
|
async remove(ctx) {
|
|
8371
|
-
const path =
|
|
8440
|
+
const path = join31(ctx.repoRoot, HOOKS_REL2);
|
|
8372
8441
|
if (!await isGitTracked(ctx.repoRoot, HOOKS_REL2)) {
|
|
8373
8442
|
await fs13.unlink(path).catch(() => {
|
|
8374
8443
|
});
|
|
@@ -8394,14 +8463,14 @@ async function readOrNull3(path) {
|
|
|
8394
8463
|
|
|
8395
8464
|
// ../listener/dist/mcp/auto-config/writers/cursor.js
|
|
8396
8465
|
import { promises as fs14 } from "fs";
|
|
8397
|
-
import { join as
|
|
8466
|
+
import { join as join32 } from "path";
|
|
8398
8467
|
var cursorWriter = {
|
|
8399
8468
|
tool: "cursor",
|
|
8400
8469
|
async detect(repoRoot) {
|
|
8401
|
-
return await fileExists10(
|
|
8470
|
+
return await fileExists10(join32(repoRoot, ".cursor")) || await fileExists10(join32(repoRoot, ".cursorrules"));
|
|
8402
8471
|
},
|
|
8403
8472
|
async write(ctx) {
|
|
8404
|
-
const path =
|
|
8473
|
+
const path = join32(ctx.repoRoot, ".cursor", "mcp.json");
|
|
8405
8474
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8406
8475
|
const status2 = await writeMergedConfig({
|
|
8407
8476
|
path,
|
|
@@ -8411,7 +8480,7 @@ var cursorWriter = {
|
|
|
8411
8480
|
return { status: status2, path };
|
|
8412
8481
|
},
|
|
8413
8482
|
async remove(ctx) {
|
|
8414
|
-
const path =
|
|
8483
|
+
const path = join32(ctx.repoRoot, ".cursor", "mcp.json");
|
|
8415
8484
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8416
8485
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8417
8486
|
}
|
|
@@ -8427,14 +8496,14 @@ async function fileExists10(path) {
|
|
|
8427
8496
|
|
|
8428
8497
|
// ../listener/dist/mcp/auto-config/writers/gemini-cli.js
|
|
8429
8498
|
import { promises as fs15 } from "fs";
|
|
8430
|
-
import { join as
|
|
8499
|
+
import { join as join33 } from "path";
|
|
8431
8500
|
var geminiCliWriter = {
|
|
8432
8501
|
tool: "gemini-cli",
|
|
8433
8502
|
async detect(_repoRoot, home) {
|
|
8434
|
-
return fileExists11(
|
|
8503
|
+
return fileExists11(join33(home, ".gemini"));
|
|
8435
8504
|
},
|
|
8436
8505
|
async write(ctx) {
|
|
8437
|
-
const path =
|
|
8506
|
+
const path = join33(ctx.home, ".gemini", "settings.json");
|
|
8438
8507
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8439
8508
|
const status2 = await writeMergedConfig({
|
|
8440
8509
|
path,
|
|
@@ -8444,7 +8513,7 @@ var geminiCliWriter = {
|
|
|
8444
8513
|
return { status: status2, path };
|
|
8445
8514
|
},
|
|
8446
8515
|
async remove(ctx) {
|
|
8447
|
-
const path =
|
|
8516
|
+
const path = join33(ctx.home, ".gemini", "settings.json");
|
|
8448
8517
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8449
8518
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8450
8519
|
}
|
|
@@ -8460,15 +8529,15 @@ async function fileExists11(path) {
|
|
|
8460
8529
|
|
|
8461
8530
|
// ../listener/dist/mcp/auto-config/writers/gemini-hooks.js
|
|
8462
8531
|
import { promises as fs16 } from "fs";
|
|
8463
|
-
import { join as
|
|
8532
|
+
import { join as join34 } from "path";
|
|
8464
8533
|
var SETTINGS_REL = ".gemini/settings.json";
|
|
8465
8534
|
var geminiHooksWriter = {
|
|
8466
8535
|
tool: "gemini-hooks",
|
|
8467
8536
|
async detect(repoRoot, home) {
|
|
8468
|
-
return await fileExists12(
|
|
8537
|
+
return await fileExists12(join34(home, ".gemini")) || await fileExists12(join34(repoRoot, ".gemini"));
|
|
8469
8538
|
},
|
|
8470
8539
|
async write(ctx) {
|
|
8471
|
-
const repoSignal = await fileExists12(
|
|
8540
|
+
const repoSignal = await fileExists12(join34(ctx.repoRoot, ".gemini")) || await fileExists12(join34(ctx.repoRoot, "GEMINI.md"));
|
|
8472
8541
|
const selected = ctx.selectedTools?.includes("gemini") ?? false;
|
|
8473
8542
|
if (!repoSignal && !selected) {
|
|
8474
8543
|
return { status: "skipped", reason: "no repo-scoped Gemini signal and not selected" };
|
|
@@ -8480,7 +8549,7 @@ var geminiHooksWriter = {
|
|
|
8480
8549
|
reason: `${SETTINGS_REL} is git-tracked; add the RepoWise BeforeAgent hook manually to opt in`
|
|
8481
8550
|
};
|
|
8482
8551
|
}
|
|
8483
|
-
const path =
|
|
8552
|
+
const path = join34(ctx.repoRoot, SETTINGS_REL);
|
|
8484
8553
|
const existing = await readOrNull4(path);
|
|
8485
8554
|
const merged = mergeGeminiHookSettings(existing, {
|
|
8486
8555
|
repoName: ctx.repoName,
|
|
@@ -8490,13 +8559,13 @@ var geminiHooksWriter = {
|
|
|
8490
8559
|
if (merged === existing) {
|
|
8491
8560
|
return { status: "unchanged", path };
|
|
8492
8561
|
}
|
|
8493
|
-
await fs16.mkdir(
|
|
8562
|
+
await fs16.mkdir(join34(ctx.repoRoot, ".gemini"), { recursive: true });
|
|
8494
8563
|
await fs16.writeFile(path, merged, "utf-8");
|
|
8495
8564
|
await applyGitignoreChanges(ctx.repoRoot, { add: [SETTINGS_REL] });
|
|
8496
8565
|
return { status: "written", path };
|
|
8497
8566
|
},
|
|
8498
8567
|
async remove(ctx) {
|
|
8499
|
-
const path =
|
|
8568
|
+
const path = join34(ctx.repoRoot, SETTINGS_REL);
|
|
8500
8569
|
const existing = await readOrNull4(path);
|
|
8501
8570
|
if (existing !== null) {
|
|
8502
8571
|
const next = removeGeminiHookSettings(existing);
|
|
@@ -8527,14 +8596,14 @@ async function readOrNull4(path) {
|
|
|
8527
8596
|
|
|
8528
8597
|
// ../listener/dist/mcp/auto-config/writers/roo.js
|
|
8529
8598
|
import { promises as fs17 } from "fs";
|
|
8530
|
-
import { join as
|
|
8599
|
+
import { join as join35 } from "path";
|
|
8531
8600
|
var rooWriter = {
|
|
8532
8601
|
tool: "roo",
|
|
8533
8602
|
async detect(repoRoot, home) {
|
|
8534
|
-
return await fileExists13(
|
|
8603
|
+
return await fileExists13(join35(repoRoot, ".roo")) || await fileExists13(join35(home, ".roo"));
|
|
8535
8604
|
},
|
|
8536
8605
|
async write(ctx) {
|
|
8537
|
-
const repoConfig =
|
|
8606
|
+
const repoConfig = join35(ctx.repoRoot, ".roo", "mcp.json");
|
|
8538
8607
|
const before = await readOrNull5(repoConfig);
|
|
8539
8608
|
await this.remove(ctx);
|
|
8540
8609
|
const after = await readOrNull5(repoConfig);
|
|
@@ -8544,9 +8613,9 @@ var rooWriter = {
|
|
|
8544
8613
|
};
|
|
8545
8614
|
},
|
|
8546
8615
|
async remove(ctx) {
|
|
8547
|
-
const repoConfig =
|
|
8548
|
-
const homeConfig =
|
|
8549
|
-
const homeSettings =
|
|
8616
|
+
const repoConfig = join35(ctx.repoRoot, ".roo", "mcp.json");
|
|
8617
|
+
const homeConfig = join35(ctx.home, ".roo", "mcp.json");
|
|
8618
|
+
const homeSettings = join35(ctx.home, ".roo", "settings.json");
|
|
8550
8619
|
for (const path of [repoConfig, homeConfig, homeSettings]) {
|
|
8551
8620
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`).catch(() => {
|
|
8552
8621
|
});
|
|
@@ -8573,14 +8642,14 @@ async function readOrNull5(path) {
|
|
|
8573
8642
|
|
|
8574
8643
|
// ../listener/dist/mcp/auto-config/writers/windsurf.js
|
|
8575
8644
|
import { promises as fs18 } from "fs";
|
|
8576
|
-
import { join as
|
|
8645
|
+
import { join as join36 } from "path";
|
|
8577
8646
|
var windsurfWriter = {
|
|
8578
8647
|
tool: "windsurf",
|
|
8579
8648
|
async detect(_repoRoot, home) {
|
|
8580
|
-
return fileExists14(
|
|
8649
|
+
return fileExists14(join36(home, ".codeium", "windsurf"));
|
|
8581
8650
|
},
|
|
8582
8651
|
async write(ctx) {
|
|
8583
|
-
const path =
|
|
8652
|
+
const path = join36(ctx.home, ".codeium", "windsurf", "mcp_config.json");
|
|
8584
8653
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8585
8654
|
const status2 = await writeMergedConfig({
|
|
8586
8655
|
path,
|
|
@@ -8590,7 +8659,7 @@ var windsurfWriter = {
|
|
|
8590
8659
|
return { status: status2, path };
|
|
8591
8660
|
},
|
|
8592
8661
|
async remove(ctx) {
|
|
8593
|
-
const path =
|
|
8662
|
+
const path = join36(ctx.home, ".codeium", "windsurf", "mcp_config.json");
|
|
8594
8663
|
await removeFromConfig(path, `RepoWise MCP for ${ctx.repoName}`);
|
|
8595
8664
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8596
8665
|
}
|
|
@@ -8623,7 +8692,7 @@ var WRITERS = [
|
|
|
8623
8692
|
|
|
8624
8693
|
// ../listener/dist/mcp/auto-config/index.js
|
|
8625
8694
|
async function runAutoConfig(opts) {
|
|
8626
|
-
const home = opts.home ??
|
|
8695
|
+
const home = opts.home ?? homedir6();
|
|
8627
8696
|
const writers = opts.writers ?? WRITERS;
|
|
8628
8697
|
const results = [];
|
|
8629
8698
|
for (const writer of writers) {
|
|
@@ -8672,7 +8741,7 @@ init_installer();
|
|
|
8672
8741
|
init_registry();
|
|
8673
8742
|
init_lsp_tools();
|
|
8674
8743
|
import { promises as fs19 } from "fs";
|
|
8675
|
-
import { join as
|
|
8744
|
+
import { join as join37 } from "path";
|
|
8676
8745
|
async function collectRepresentativeFiles(repoRoot) {
|
|
8677
8746
|
const reps = /* @__PURE__ */ new Map();
|
|
8678
8747
|
let inspected = 0;
|
|
@@ -8713,7 +8782,7 @@ async function collectRepresentativeFiles(repoRoot) {
|
|
|
8713
8782
|
continue;
|
|
8714
8783
|
if (name === "node_modules" || name === "dist" || name === "build")
|
|
8715
8784
|
continue;
|
|
8716
|
-
const sub =
|
|
8785
|
+
const sub = join37(repoRoot, name);
|
|
8717
8786
|
try {
|
|
8718
8787
|
const stat8 = await fs19.stat(sub);
|
|
8719
8788
|
if (stat8.isDirectory())
|
|
@@ -8761,7 +8830,7 @@ init_config_dir();
|
|
|
8761
8830
|
import { promises as fs20 } from "fs";
|
|
8762
8831
|
import { spawn as spawn9, execFile as execFile5 } from "child_process";
|
|
8763
8832
|
import { createWriteStream as createWriteStream2 } from "fs";
|
|
8764
|
-
import { join as
|
|
8833
|
+
import { join as join38 } from "path";
|
|
8765
8834
|
import { promisify as promisify3 } from "util";
|
|
8766
8835
|
var execFileAsync3 = promisify3(execFile5);
|
|
8767
8836
|
async function isCommandOnPath2(cmd) {
|
|
@@ -8825,7 +8894,7 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
8825
8894
|
if (e.isDirectory()) {
|
|
8826
8895
|
if (skip.has(e.name) || e.name.startsWith("."))
|
|
8827
8896
|
continue;
|
|
8828
|
-
await rec(
|
|
8897
|
+
await rec(join38(dir, e.name));
|
|
8829
8898
|
continue;
|
|
8830
8899
|
}
|
|
8831
8900
|
const dot = e.name.lastIndexOf(".");
|
|
@@ -8834,7 +8903,7 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
8834
8903
|
const ext = e.name.slice(dot);
|
|
8835
8904
|
if (!C_EXTS.has(ext) && !CPP_EXTS.has(ext))
|
|
8836
8905
|
continue;
|
|
8837
|
-
sources.push({ path:
|
|
8906
|
+
sources.push({ path: join38(dir, e.name), ext });
|
|
8838
8907
|
}
|
|
8839
8908
|
}
|
|
8840
8909
|
await rec(repoRoot);
|
|
@@ -8850,9 +8919,9 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
8850
8919
|
command: `${driver} ${std} -I. -I./include -c "${src}"`
|
|
8851
8920
|
};
|
|
8852
8921
|
});
|
|
8853
|
-
const outDir =
|
|
8922
|
+
const outDir = join38(repoRoot, ".repowise");
|
|
8854
8923
|
await fs20.mkdir(outDir, { recursive: true });
|
|
8855
|
-
const outPath =
|
|
8924
|
+
const outPath = join38(outDir, "compile_commands.json");
|
|
8856
8925
|
await fs20.writeFile(outPath, JSON.stringify(entries, null, 2));
|
|
8857
8926
|
const capHit = sources.length >= MAX_STUB_SOURCES;
|
|
8858
8927
|
console.log(`[workspace-prep] ${repoId}: wrote ${entries.length.toString()}-entry compile_commands stub to .repowise/${capHit ? " (cap reached \u2014 additional sources truncated)" : ""}`);
|
|
@@ -8861,7 +8930,7 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
8861
8930
|
var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
8862
8931
|
async function fileExists15(repoRoot, name) {
|
|
8863
8932
|
try {
|
|
8864
|
-
await fs20.access(
|
|
8933
|
+
await fs20.access(join38(repoRoot, name));
|
|
8865
8934
|
return true;
|
|
8866
8935
|
} catch {
|
|
8867
8936
|
return false;
|
|
@@ -8872,7 +8941,7 @@ async function detectWorkspaceDeps(repoRoot) {
|
|
|
8872
8941
|
if (await fileExists15(repoRoot, "package.json")) {
|
|
8873
8942
|
let pkgRaw = "";
|
|
8874
8943
|
try {
|
|
8875
|
-
pkgRaw = await fs20.readFile(
|
|
8944
|
+
pkgRaw = await fs20.readFile(join38(repoRoot, "package.json"), "utf8");
|
|
8876
8945
|
} catch {
|
|
8877
8946
|
}
|
|
8878
8947
|
if (pkgRaw) {
|
|
@@ -8975,7 +9044,7 @@ async function runWorkspacePreps(opts) {
|
|
|
8975
9044
|
if (opts.missing.length === 0)
|
|
8976
9045
|
return [];
|
|
8977
9046
|
const safeRepoId = opts.repoId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8978
|
-
const logPath2 =
|
|
9047
|
+
const logPath2 = join38(getConfigDir(), `install-log.${safeRepoId}.txt`);
|
|
8979
9048
|
await fs20.mkdir(getConfigDir(), { recursive: true });
|
|
8980
9049
|
const stream = opts.logStream ?? createWriteStream2(logPath2, { flags: "a" });
|
|
8981
9050
|
stream.on("error", () => {
|
|
@@ -9126,7 +9195,7 @@ async function prepareWorkspaceDepsForRepos(repos) {
|
|
|
9126
9195
|
init_registry();
|
|
9127
9196
|
import { execFile as execFileCb, spawn as spawn10 } from "child_process";
|
|
9128
9197
|
import { access as access3, readdir as readdir4 } from "fs/promises";
|
|
9129
|
-
import { join as
|
|
9198
|
+
import { join as join39 } from "path";
|
|
9130
9199
|
import { promisify as promisify4 } from "util";
|
|
9131
9200
|
var execFile6 = promisify4(execFileCb);
|
|
9132
9201
|
var DEFAULT_BUILD_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
@@ -9179,7 +9248,7 @@ async function ensureIndexable(indexRoot, language, options = {}) {
|
|
|
9179
9248
|
}
|
|
9180
9249
|
}
|
|
9181
9250
|
try {
|
|
9182
|
-
await access3(
|
|
9251
|
+
await access3(join39(indexRoot, spec.indexStoreProbe));
|
|
9183
9252
|
return { ready: true, built: false };
|
|
9184
9253
|
} catch {
|
|
9185
9254
|
}
|
|
@@ -9219,7 +9288,9 @@ async function ensureIndexable(indexRoot, language, options = {}) {
|
|
|
9219
9288
|
init_src();
|
|
9220
9289
|
init_registry();
|
|
9221
9290
|
import { execFile as execFileCb2 } from "child_process";
|
|
9291
|
+
import { dirname as dirname16 } from "path";
|
|
9222
9292
|
import { promisify as promisify5 } from "util";
|
|
9293
|
+
init_daemon_path();
|
|
9223
9294
|
|
|
9224
9295
|
// ../listener/dist/typed-resolution/lsp-upgrade-strategy.js
|
|
9225
9296
|
var goStrategy = {
|
|
@@ -9701,7 +9772,13 @@ async function isCommandOnPath4(command) {
|
|
|
9701
9772
|
return false;
|
|
9702
9773
|
const probeCmd = process.platform === "win32" ? "where" : "which";
|
|
9703
9774
|
try {
|
|
9704
|
-
await execFile7(probeCmd, [command], {
|
|
9775
|
+
await execFile7(probeCmd, [command], {
|
|
9776
|
+
timeout: 5e3,
|
|
9777
|
+
env: {
|
|
9778
|
+
...process.env,
|
|
9779
|
+
PATH: buildLspSpawnPath(process.env.PATH, dirname16(process.execPath), managedBinDirs())
|
|
9780
|
+
}
|
|
9781
|
+
});
|
|
9705
9782
|
return true;
|
|
9706
9783
|
} catch {
|
|
9707
9784
|
return false;
|
|
@@ -9905,13 +9982,13 @@ init_config_dir();
|
|
|
9905
9982
|
import { execFile as execFileCb3 } from "child_process";
|
|
9906
9983
|
import { createHash as createHash5 } from "crypto";
|
|
9907
9984
|
import { mkdir as mkdir15, readdir as readdir5, rm, stat as stat6 } from "fs/promises";
|
|
9908
|
-
import { join as
|
|
9985
|
+
import { join as join40 } from "path";
|
|
9909
9986
|
import { promisify as promisify6 } from "util";
|
|
9910
9987
|
var execFile8 = promisify6(execFileCb3);
|
|
9911
9988
|
var GIT_OP_TIMEOUT_MS = 6e4;
|
|
9912
9989
|
var MAX_CONCURRENT_WORKTREES = 3;
|
|
9913
9990
|
function worktreeBaseDir() {
|
|
9914
|
-
return
|
|
9991
|
+
return join40(getConfigDir(), "lsp-worktrees");
|
|
9915
9992
|
}
|
|
9916
9993
|
async function reapOrphanWorktrees(maxAgeMs = 24 * 60 * 60 * 1e3, base = worktreeBaseDir()) {
|
|
9917
9994
|
let reaped = 0;
|
|
@@ -9923,7 +10000,7 @@ async function reapOrphanWorktrees(maxAgeMs = 24 * 60 * 60 * 1e3, base = worktre
|
|
|
9923
10000
|
}
|
|
9924
10001
|
const cutoff = Date.now() - maxAgeMs;
|
|
9925
10002
|
for (const entry of entries) {
|
|
9926
|
-
const dir =
|
|
10003
|
+
const dir = join40(base, entry);
|
|
9927
10004
|
try {
|
|
9928
10005
|
const info = await stat6(dir);
|
|
9929
10006
|
if (!info.isDirectory() || info.mtimeMs > cutoff)
|
|
@@ -9956,7 +10033,7 @@ async function prepareCommittedTree(repoRoot, commitSha, options = {}) {
|
|
|
9956
10033
|
}
|
|
9957
10034
|
const base = options.worktreeBase ?? worktreeBaseDir();
|
|
9958
10035
|
const dirName = createHash5("sha256").update(`${repoRoot}\0${commitSha}`).digest("hex").slice(0, 16) + "-" + commitSha.slice(0, 12);
|
|
9959
|
-
const worktreePath =
|
|
10036
|
+
const worktreePath = join40(base, dirName);
|
|
9960
10037
|
try {
|
|
9961
10038
|
await mkdir15(base, { recursive: true });
|
|
9962
10039
|
await git(["-C", repoRoot, "worktree", "prune"]).catch(() => void 0);
|
|
@@ -10292,7 +10369,7 @@ var CRASH_LOOP_WINDOW_MS = 3e4;
|
|
|
10292
10369
|
var CRASH_LOOP_THRESHOLD = 3;
|
|
10293
10370
|
async function readRawToolConfig() {
|
|
10294
10371
|
try {
|
|
10295
|
-
const configPath =
|
|
10372
|
+
const configPath = join41(getConfigDir(), "config.json");
|
|
10296
10373
|
const data = await readFile13(configPath, "utf-8");
|
|
10297
10374
|
const raw = JSON.parse(data);
|
|
10298
10375
|
return {
|
|
@@ -10350,7 +10427,7 @@ async function updateToolConfigsForRepo(localPath, config2, state, repoId) {
|
|
|
10350
10427
|
await updateToolConfig(localPath, "codex", repoName, contextFolder, contextFiles, variant);
|
|
10351
10428
|
}
|
|
10352
10429
|
if (!state.repos[repoId]) {
|
|
10353
|
-
state.repos[repoId] = { lastSyncTimestamp:
|
|
10430
|
+
state.repos[repoId] = { lastSyncTimestamp: (/* @__PURE__ */ new Date()).toISOString(), lastSyncCommitSha: null };
|
|
10354
10431
|
}
|
|
10355
10432
|
state.repos[repoId].lastToolConfigHash = hash;
|
|
10356
10433
|
console.log(`[ai-tools] Updated tool configs for ${repoId}`);
|
|
@@ -10367,11 +10444,11 @@ function resolveAuditRoots() {
|
|
|
10367
10444
|
return override.split(":").map((s) => s.trim()).filter(Boolean);
|
|
10368
10445
|
}
|
|
10369
10446
|
const out = /* @__PURE__ */ new Set();
|
|
10370
|
-
let dir =
|
|
10447
|
+
let dir = dirname17(process.execPath);
|
|
10371
10448
|
for (let i = 0; i < 8; i += 1) {
|
|
10372
|
-
out.add(
|
|
10373
|
-
out.add(
|
|
10374
|
-
const parent =
|
|
10449
|
+
out.add(join41(dir, "node_modules"));
|
|
10450
|
+
out.add(join41(dir, "lib", "node_modules"));
|
|
10451
|
+
const parent = dirname17(dir);
|
|
10375
10452
|
if (parent === dir)
|
|
10376
10453
|
break;
|
|
10377
10454
|
dir = parent;
|
|
@@ -10635,7 +10712,7 @@ async function checkStaleContext(repos, state, groups) {
|
|
|
10635
10712
|
if (group?.offline.isOffline)
|
|
10636
10713
|
continue;
|
|
10637
10714
|
const { statSync: statSync2, readdirSync: readdirSync2 } = await import("fs");
|
|
10638
|
-
const contextPath =
|
|
10715
|
+
const contextPath = join41(repo.localPath, "repowise-context");
|
|
10639
10716
|
let isMissingOrEmpty = false;
|
|
10640
10717
|
try {
|
|
10641
10718
|
const s = statSync2(contextPath);
|
|
@@ -10700,7 +10777,7 @@ async function reconcileAgentInstructions(repos) {
|
|
|
10700
10777
|
const { graphOnly } = await readRawToolConfig();
|
|
10701
10778
|
const variant = graphOnly ? "graph" : "full";
|
|
10702
10779
|
for (const repo of repos) {
|
|
10703
|
-
const path =
|
|
10780
|
+
const path = join41(repo.localPath, "repowise-context", "project-overview.md");
|
|
10704
10781
|
let content;
|
|
10705
10782
|
try {
|
|
10706
10783
|
content = await readFile13(path, "utf-8");
|
|
@@ -10784,7 +10861,7 @@ async function startListener() {
|
|
|
10784
10861
|
}
|
|
10785
10862
|
const configDir = getConfigDir();
|
|
10786
10863
|
await mkdir16(configDir, { recursive: true });
|
|
10787
|
-
const lockPath =
|
|
10864
|
+
const lockPath = join41(configDir, "listener.lock");
|
|
10788
10865
|
await writeFile15(lockPath, "", { flag: "a" });
|
|
10789
10866
|
let lockIsHeld = false;
|
|
10790
10867
|
try {
|
|
@@ -10827,7 +10904,7 @@ async function startListener() {
|
|
|
10827
10904
|
return;
|
|
10828
10905
|
}
|
|
10829
10906
|
if (config2.repos.length === 0 && !config2.autoDiscoverRepos) {
|
|
10830
|
-
console.error(`No repos configured. Add repos to ${
|
|
10907
|
+
console.error(`No repos configured. Add repos to ${join41(configDir, "config.json")}`);
|
|
10831
10908
|
await releaseLockAndExit();
|
|
10832
10909
|
process.exitCode = 1;
|
|
10833
10910
|
return;
|
|
@@ -10894,8 +10971,8 @@ async function startListener() {
|
|
|
10894
10971
|
const packageName = true ? "repowisestage" : "repowise";
|
|
10895
10972
|
let currentVersion = "";
|
|
10896
10973
|
try {
|
|
10897
|
-
const selfDir =
|
|
10898
|
-
const pkgJsonPath =
|
|
10974
|
+
const selfDir = dirname17(fileURLToPath3(import.meta.url));
|
|
10975
|
+
const pkgJsonPath = join41(selfDir, "..", "..", "package.json");
|
|
10899
10976
|
const pkgJson = JSON.parse(await readFile13(pkgJsonPath, "utf-8"));
|
|
10900
10977
|
currentVersion = pkgJson.version;
|
|
10901
10978
|
} catch (err) {
|
|
@@ -11137,7 +11214,8 @@ async function startListener() {
|
|
|
11137
11214
|
}
|
|
11138
11215
|
try {
|
|
11139
11216
|
const sinceTimestamp = group.repoIds.reduce((earliest, id) => {
|
|
11140
|
-
const
|
|
11217
|
+
const raw = state.repos[id]?.lastSyncTimestamp;
|
|
11218
|
+
const ts2 = raw && !Number.isNaN(Date.parse(raw)) ? raw : now;
|
|
11141
11219
|
return ts2 < earliest ? ts2 : earliest;
|
|
11142
11220
|
}, now);
|
|
11143
11221
|
const response = await group.pollClient.poll(group.repoIds, sinceTimestamp, {
|
|
@@ -11397,7 +11475,7 @@ async function startListener() {
|
|
|
11397
11475
|
} catch {
|
|
11398
11476
|
}
|
|
11399
11477
|
}
|
|
11400
|
-
const credentialsPath =
|
|
11478
|
+
const credentialsPath = join41(getConfigDir(), "credentials.json");
|
|
11401
11479
|
let credentialsChanged = false;
|
|
11402
11480
|
let watcher = null;
|
|
11403
11481
|
try {
|
|
@@ -11442,8 +11520,8 @@ if (isDirectRun) {
|
|
|
11442
11520
|
}
|
|
11443
11521
|
|
|
11444
11522
|
// src/lib/env.ts
|
|
11445
|
-
import { homedir as
|
|
11446
|
-
import { join as
|
|
11523
|
+
import { homedir as homedir7 } from "os";
|
|
11524
|
+
import { join as join42 } from "path";
|
|
11447
11525
|
var IS_STAGING2 = true ? true : false;
|
|
11448
11526
|
var PRODUCTION = {
|
|
11449
11527
|
apiUrl: "https://api.repowise.ai",
|
|
@@ -11463,7 +11541,7 @@ function getEnvConfig() {
|
|
|
11463
11541
|
return IS_STAGING2 ? STAGING : PRODUCTION;
|
|
11464
11542
|
}
|
|
11465
11543
|
function getConfigDir2() {
|
|
11466
|
-
return
|
|
11544
|
+
return join42(homedir7(), IS_STAGING2 ? ".repowise-staging" : ".repowise");
|
|
11467
11545
|
}
|
|
11468
11546
|
function getPackageName() {
|
|
11469
11547
|
return true ? "repowisestage" : "repowise";
|
|
@@ -11474,11 +11552,11 @@ import chalk from "chalk";
|
|
|
11474
11552
|
|
|
11475
11553
|
// src/lib/config.ts
|
|
11476
11554
|
import { readFile as readFile14, writeFile as writeFile16, mkdir as mkdir17, rename as rename4, unlink as unlink10 } from "fs/promises";
|
|
11477
|
-
import { join as
|
|
11555
|
+
import { join as join43 } from "path";
|
|
11478
11556
|
import lockfile5 from "proper-lockfile";
|
|
11479
11557
|
async function getConfig() {
|
|
11480
11558
|
try {
|
|
11481
|
-
const data = await readFile14(
|
|
11559
|
+
const data = await readFile14(join43(getConfigDir2(), "config.json"), "utf-8");
|
|
11482
11560
|
return JSON.parse(data);
|
|
11483
11561
|
} catch {
|
|
11484
11562
|
return {};
|
|
@@ -11486,7 +11564,7 @@ async function getConfig() {
|
|
|
11486
11564
|
}
|
|
11487
11565
|
async function saveConfig(config2) {
|
|
11488
11566
|
const dir = getConfigDir2();
|
|
11489
|
-
const path =
|
|
11567
|
+
const path = join43(dir, "config.json");
|
|
11490
11568
|
await mkdir17(dir, { recursive: true });
|
|
11491
11569
|
const tmpPath = path + ".tmp";
|
|
11492
11570
|
try {
|
|
@@ -11502,7 +11580,7 @@ async function saveConfig(config2) {
|
|
|
11502
11580
|
}
|
|
11503
11581
|
async function mergeAndSaveConfig(updates) {
|
|
11504
11582
|
const dir = getConfigDir2();
|
|
11505
|
-
const path =
|
|
11583
|
+
const path = join43(dir, "config.json");
|
|
11506
11584
|
await mkdir17(dir, { recursive: true });
|
|
11507
11585
|
try {
|
|
11508
11586
|
await writeFile16(path, "", { flag: "a" });
|
|
@@ -11573,7 +11651,7 @@ async function showWelcome(currentVersion) {
|
|
|
11573
11651
|
|
|
11574
11652
|
// src/commands/create.ts
|
|
11575
11653
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
11576
|
-
import { dirname as
|
|
11654
|
+
import { dirname as dirname19, join as join49 } from "path";
|
|
11577
11655
|
init_src();
|
|
11578
11656
|
import chalk8 from "chalk";
|
|
11579
11657
|
import ora from "ora";
|
|
@@ -11582,7 +11660,7 @@ import ora from "ora";
|
|
|
11582
11660
|
import { createHash as createHash6, randomBytes as randomBytes3 } from "crypto";
|
|
11583
11661
|
import { readFile as readFile15, writeFile as writeFile17, mkdir as mkdir18, chmod as chmod4, unlink as unlink11 } from "fs/promises";
|
|
11584
11662
|
import http from "http";
|
|
11585
|
-
import { join as
|
|
11663
|
+
import { join as join44 } from "path";
|
|
11586
11664
|
var CLI_CALLBACK_PORT = 19876;
|
|
11587
11665
|
var CALLBACK_TIMEOUT_MS = 12e4;
|
|
11588
11666
|
function getCognitoConfigForStorage() {
|
|
@@ -11748,7 +11826,7 @@ async function refreshTokens2(refreshToken) {
|
|
|
11748
11826
|
}
|
|
11749
11827
|
async function getStoredCredentials2() {
|
|
11750
11828
|
try {
|
|
11751
|
-
const credPath =
|
|
11829
|
+
const credPath = join44(getConfigDir2(), "credentials.json");
|
|
11752
11830
|
const data = await readFile15(credPath, "utf-8");
|
|
11753
11831
|
return JSON.parse(data);
|
|
11754
11832
|
} catch (err) {
|
|
@@ -11760,14 +11838,14 @@ async function getStoredCredentials2() {
|
|
|
11760
11838
|
}
|
|
11761
11839
|
async function storeCredentials2(credentials) {
|
|
11762
11840
|
const dir = getConfigDir2();
|
|
11763
|
-
const credPath =
|
|
11841
|
+
const credPath = join44(dir, "credentials.json");
|
|
11764
11842
|
await mkdir18(dir, { recursive: true, mode: 448 });
|
|
11765
11843
|
await writeFile17(credPath, JSON.stringify(credentials, null, 2));
|
|
11766
11844
|
await chmod4(credPath, 384);
|
|
11767
11845
|
}
|
|
11768
11846
|
async function clearCredentials() {
|
|
11769
11847
|
try {
|
|
11770
|
-
await unlink11(
|
|
11848
|
+
await unlink11(join44(getConfigDir2(), "credentials.json"));
|
|
11771
11849
|
} catch (err) {
|
|
11772
11850
|
if (err.code !== "ENOENT") throw err;
|
|
11773
11851
|
}
|
|
@@ -11975,9 +12053,9 @@ async function selectAiTools() {
|
|
|
11975
12053
|
|
|
11976
12054
|
// src/lib/gitignore.ts
|
|
11977
12055
|
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2 } from "fs";
|
|
11978
|
-
import { join as
|
|
12056
|
+
import { join as join45 } from "path";
|
|
11979
12057
|
function ensureGitignore(repoRoot, entry) {
|
|
11980
|
-
const gitignorePath =
|
|
12058
|
+
const gitignorePath = join45(repoRoot, ".gitignore");
|
|
11981
12059
|
if (existsSync2(gitignorePath)) {
|
|
11982
12060
|
const content = readFileSync2(gitignorePath, "utf-8");
|
|
11983
12061
|
const lines = content.split("\n").map((l) => l.trim());
|
|
@@ -11994,7 +12072,7 @@ function ensureGitignore(repoRoot, entry) {
|
|
|
11994
12072
|
// src/lib/graph-cache.ts
|
|
11995
12073
|
init_config_dir();
|
|
11996
12074
|
import { mkdirSync, writeFileSync as writeFileSync2, renameSync, unlinkSync } from "fs";
|
|
11997
|
-
import { dirname as
|
|
12075
|
+
import { dirname as dirname18, join as join46 } from "path";
|
|
11998
12076
|
var SAFE_REPO_ID = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
11999
12077
|
function assertSafeRepoId2(repoId) {
|
|
12000
12078
|
if (!repoId || typeof repoId !== "string" || !SAFE_REPO_ID.test(repoId) || repoId === "." || repoId === ".." || repoId.startsWith(".")) {
|
|
@@ -12003,7 +12081,7 @@ function assertSafeRepoId2(repoId) {
|
|
|
12003
12081
|
}
|
|
12004
12082
|
function graphCachePath(repoId) {
|
|
12005
12083
|
assertSafeRepoId2(repoId);
|
|
12006
|
-
return
|
|
12084
|
+
return join46(getConfigDir(), "graphs", `${repoId}.json`);
|
|
12007
12085
|
}
|
|
12008
12086
|
function isUsableGraph(parsed) {
|
|
12009
12087
|
if (typeof parsed !== "object" || parsed === null) return false;
|
|
@@ -12021,9 +12099,27 @@ function readErrorCode(body) {
|
|
|
12021
12099
|
return void 0;
|
|
12022
12100
|
}
|
|
12023
12101
|
}
|
|
12102
|
+
async function readBodyBounded(res, ctrl, bodyTimeoutMs) {
|
|
12103
|
+
const bodyPromise = res.text();
|
|
12104
|
+
void bodyPromise.catch(() => {
|
|
12105
|
+
});
|
|
12106
|
+
let timer;
|
|
12107
|
+
const timeout = new Promise((_, reject) => {
|
|
12108
|
+
timer = setTimeout(() => {
|
|
12109
|
+
ctrl.abort();
|
|
12110
|
+
reject(new Error("GRAPH_BODY_TIMEOUT"));
|
|
12111
|
+
}, bodyTimeoutMs);
|
|
12112
|
+
});
|
|
12113
|
+
try {
|
|
12114
|
+
return await Promise.race([bodyPromise, timeout]);
|
|
12115
|
+
} finally {
|
|
12116
|
+
if (timer) clearTimeout(timer);
|
|
12117
|
+
}
|
|
12118
|
+
}
|
|
12024
12119
|
async function ensureGraphDownloaded(opts) {
|
|
12025
12120
|
const fetchFn = opts.fetchFn ?? fetch;
|
|
12026
12121
|
const timeoutMs = opts.timeoutMs ?? 1e4;
|
|
12122
|
+
const bodyTimeoutMs = opts.bodyTimeoutMs ?? 12e4;
|
|
12027
12123
|
const maxRetries = opts.maxRetries ?? 3;
|
|
12028
12124
|
const sleep2 = opts.sleepFn ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
12029
12125
|
let targetPath;
|
|
@@ -12080,7 +12176,16 @@ async function ensureGraphDownloaded(opts) {
|
|
|
12080
12176
|
if (!res.ok) {
|
|
12081
12177
|
return { status: "error", message: `HTTP ${String(res.status)}` };
|
|
12082
12178
|
}
|
|
12083
|
-
|
|
12179
|
+
let body;
|
|
12180
|
+
try {
|
|
12181
|
+
body = await readBodyBounded(res, ctrl, bodyTimeoutMs);
|
|
12182
|
+
} catch (err) {
|
|
12183
|
+
if (attempt < maxRetries) {
|
|
12184
|
+
await sleep2(2e3 * attempt);
|
|
12185
|
+
continue;
|
|
12186
|
+
}
|
|
12187
|
+
return { status: "error", message: err instanceof Error ? err.message : String(err) };
|
|
12188
|
+
}
|
|
12084
12189
|
let parsed;
|
|
12085
12190
|
try {
|
|
12086
12191
|
parsed = JSON.parse(body);
|
|
@@ -12095,7 +12200,7 @@ async function ensureGraphDownloaded(opts) {
|
|
|
12095
12200
|
return { status: "not_found", message: "EMPTY_GRAPH" };
|
|
12096
12201
|
}
|
|
12097
12202
|
try {
|
|
12098
|
-
mkdirSync(
|
|
12203
|
+
mkdirSync(dirname18(targetPath), { recursive: true });
|
|
12099
12204
|
const tmp = `${targetPath}.${String(process.pid)}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
12100
12205
|
try {
|
|
12101
12206
|
writeFileSync2(tmp, body, { encoding: "utf-8", mode: 384 });
|
|
@@ -12246,7 +12351,7 @@ async function handleInterview(syncId, questionId, questionText, questionContext
|
|
|
12246
12351
|
const message = err instanceof Error ? err.message : String(err);
|
|
12247
12352
|
if (message.includes("not awaiting input") || message.includes("expired")) {
|
|
12248
12353
|
console.log(chalk3.dim(" Pipeline has already moved on \u2014 continuing."));
|
|
12249
|
-
return;
|
|
12354
|
+
return { finished: true };
|
|
12250
12355
|
}
|
|
12251
12356
|
try {
|
|
12252
12357
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
@@ -12256,7 +12361,7 @@ async function handleInterview(syncId, questionId, questionText, questionContext
|
|
|
12256
12361
|
});
|
|
12257
12362
|
} catch {
|
|
12258
12363
|
console.log(chalk3.yellow(" Could not submit answer \u2014 pipeline will continue."));
|
|
12259
|
-
return;
|
|
12364
|
+
return { finished: false };
|
|
12260
12365
|
}
|
|
12261
12366
|
}
|
|
12262
12367
|
if (action === "done") {
|
|
@@ -12267,6 +12372,7 @@ async function handleInterview(syncId, questionId, questionText, questionContext
|
|
|
12267
12372
|
console.log(chalk3.dim(" Answer recorded."));
|
|
12268
12373
|
}
|
|
12269
12374
|
console.log("");
|
|
12375
|
+
return { finished: action === "done" || questionCounter >= MAX_QUESTIONS };
|
|
12270
12376
|
}
|
|
12271
12377
|
|
|
12272
12378
|
// src/lib/progress-renderer.ts
|
|
@@ -12299,6 +12405,12 @@ var ProgressRenderer = class {
|
|
|
12299
12405
|
privacyShieldShown = false;
|
|
12300
12406
|
discoveryShown = false;
|
|
12301
12407
|
interviewCompleteShown = false;
|
|
12408
|
+
// FIX-10: the scan runs in PARALLEL with the interview, so scanProgress
|
|
12409
|
+
// arrives mid-interview. Hold scan rendering until the interview is
|
|
12410
|
+
// definitively over (setInterviewComplete) so the coffee/Code-Analysis/graph
|
|
12411
|
+
// block never interrupts the Q&A. Buffer the latest progress meanwhile.
|
|
12412
|
+
interviewComplete = false;
|
|
12413
|
+
pendingScanProgress = null;
|
|
12302
12414
|
scanHeaderShown = false;
|
|
12303
12415
|
scanSummaryShown = false;
|
|
12304
12416
|
graphSubtitleShown = false;
|
|
@@ -12600,6 +12712,21 @@ var ProgressRenderer = class {
|
|
|
12600
12712
|
}
|
|
12601
12713
|
return `${stepLabel}... ${chalk4.dim(`(${overallPct}%)`)}`;
|
|
12602
12714
|
}
|
|
12715
|
+
/**
|
|
12716
|
+
* FIX-10 — mark the interview definitively over. Unlocks scan-progress
|
|
12717
|
+
* rendering and flushes any progress buffered during the interview, so the
|
|
12718
|
+
* coffee → Code-Analysis → graph-ready block appears in order AFTER the last
|
|
12719
|
+
* question (renderScanProgress is idempotent via its *Shown latches).
|
|
12720
|
+
* Idempotent; safe to call from multiple completion paths.
|
|
12721
|
+
*/
|
|
12722
|
+
setInterviewComplete(spinner) {
|
|
12723
|
+
if (this.interviewComplete) return;
|
|
12724
|
+
this.interviewComplete = true;
|
|
12725
|
+
if (this.pendingScanProgress) {
|
|
12726
|
+
this.renderScanProgress(this.pendingScanProgress, spinner);
|
|
12727
|
+
this.pendingScanProgress = null;
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12603
12730
|
update(syncResult, spinner) {
|
|
12604
12731
|
if (syncResult.privacyShieldEnabled !== void 0) {
|
|
12605
12732
|
this.renderPrivacyShield(syncResult.privacyShieldEnabled, spinner);
|
|
@@ -12608,7 +12735,11 @@ var ProgressRenderer = class {
|
|
|
12608
12735
|
this.renderDiscovery(syncResult.discoveryResult, spinner);
|
|
12609
12736
|
}
|
|
12610
12737
|
if (syncResult.scanProgress) {
|
|
12611
|
-
this.
|
|
12738
|
+
if (this.interviewComplete) {
|
|
12739
|
+
this.renderScanProgress(syncResult.scanProgress, spinner);
|
|
12740
|
+
} else {
|
|
12741
|
+
this.pendingScanProgress = syncResult.scanProgress;
|
|
12742
|
+
}
|
|
12612
12743
|
}
|
|
12613
12744
|
if (syncResult.generationProgress?.fileStatuses && syncResult.generationProgress.fileStatuses.length > 0) {
|
|
12614
12745
|
this.renderFileStatuses(syncResult.generationProgress.fileStatuses, spinner);
|
|
@@ -12668,7 +12799,7 @@ import chalk6 from "chalk";
|
|
|
12668
12799
|
|
|
12669
12800
|
// src/lib/dep-installer.ts
|
|
12670
12801
|
import { promises as fs21 } from "fs";
|
|
12671
|
-
import { join as
|
|
12802
|
+
import { join as join47 } from "path";
|
|
12672
12803
|
var SUPPORTED_DEP_LANGUAGES = /* @__PURE__ */ new Set([
|
|
12673
12804
|
"typescript",
|
|
12674
12805
|
"javascript",
|
|
@@ -12685,7 +12816,7 @@ var exists = async (p) => {
|
|
|
12685
12816
|
}
|
|
12686
12817
|
};
|
|
12687
12818
|
async function fileExists16(repoRoot, name) {
|
|
12688
|
-
return exists(
|
|
12819
|
+
return exists(join47(repoRoot, name));
|
|
12689
12820
|
}
|
|
12690
12821
|
async function detectNodePackageManager(repoRoot) {
|
|
12691
12822
|
if (await fileExists16(repoRoot, "pnpm-lock.yaml")) {
|
|
@@ -12763,11 +12894,11 @@ async function detectMissingDeps(repoRoot, scopedLanguages) {
|
|
|
12763
12894
|
import { spawn as spawn11 } from "child_process";
|
|
12764
12895
|
import { createWriteStream as createWriteStream3 } from "fs";
|
|
12765
12896
|
import { promises as fs22 } from "fs";
|
|
12766
|
-
import { join as
|
|
12897
|
+
import { join as join48 } from "path";
|
|
12767
12898
|
var DEFAULT_INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
12768
12899
|
async function runMissingDepInstalls(opts) {
|
|
12769
12900
|
const safeRepoId = opts.repoId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
12770
|
-
const logPath2 =
|
|
12901
|
+
const logPath2 = join48(getConfigDir2(), `install-log.${safeRepoId}.txt`);
|
|
12771
12902
|
await fs22.mkdir(getConfigDir2(), { recursive: true });
|
|
12772
12903
|
const stream = opts.logStream ?? createWriteStream3(logPath2, { flags: "a" });
|
|
12773
12904
|
stream.on("error", () => {
|
|
@@ -12814,7 +12945,7 @@ async function runOne2(dep, repoRoot, stream, timeoutMs) {
|
|
|
12814
12945
|
}
|
|
12815
12946
|
async function runPipFlow(repoRoot, stream, timeoutMs) {
|
|
12816
12947
|
await runSimple(["python3", "-m", "venv", ".venv"], repoRoot, stream, timeoutMs);
|
|
12817
|
-
const venvPip = process.platform === "win32" ?
|
|
12948
|
+
const venvPip = process.platform === "win32" ? join48(".venv", "Scripts", "pip.exe") : join48(".venv", "bin", "pip");
|
|
12818
12949
|
await runSimple([venvPip, "install", "-r", "requirements.txt"], repoRoot, stream, timeoutMs);
|
|
12819
12950
|
}
|
|
12820
12951
|
function runSimple(cmd, repoRoot, stream, timeoutMs) {
|
|
@@ -12997,14 +13128,29 @@ async function create() {
|
|
|
12997
13128
|
const spinner = ora("Checking authentication...").start();
|
|
12998
13129
|
try {
|
|
12999
13130
|
let credentials = await getValidCredentials2();
|
|
13000
|
-
|
|
13001
|
-
|
|
13131
|
+
let needsLogin = !credentials;
|
|
13132
|
+
if (credentials) {
|
|
13133
|
+
try {
|
|
13134
|
+
await apiRequest("/v1/account/usage");
|
|
13135
|
+
} catch (err) {
|
|
13136
|
+
if (err instanceof Error && /Session expired|Not logged in/i.test(err.message)) {
|
|
13137
|
+
needsLogin = true;
|
|
13138
|
+
}
|
|
13139
|
+
}
|
|
13140
|
+
}
|
|
13141
|
+
if (needsLogin) {
|
|
13142
|
+
spinner.info(
|
|
13143
|
+
chalk8.yellow("Not logged in or session expired. Opening browser to authenticate...")
|
|
13144
|
+
);
|
|
13002
13145
|
credentials = await performLogin();
|
|
13003
13146
|
const { email } = decodeIdToken(credentials.idToken);
|
|
13004
13147
|
spinner.succeed(chalk8.green(`Authenticated as ${chalk8.bold(email)}`));
|
|
13005
13148
|
} else {
|
|
13006
13149
|
spinner.succeed("Authenticated");
|
|
13007
13150
|
}
|
|
13151
|
+
if (!credentials) {
|
|
13152
|
+
throw new Error("Authentication failed \u2014 run `repowise login` and retry.");
|
|
13153
|
+
}
|
|
13008
13154
|
let repoId;
|
|
13009
13155
|
let repoName;
|
|
13010
13156
|
let repoRoot;
|
|
@@ -13213,6 +13359,8 @@ async function create() {
|
|
|
13213
13359
|
const progressRenderer = new ProgressRenderer();
|
|
13214
13360
|
let depInstallShown = false;
|
|
13215
13361
|
let seenAwaitingInput = false;
|
|
13362
|
+
let interviewComplete = false;
|
|
13363
|
+
let interviewQuestionsAnswered = 0;
|
|
13216
13364
|
let lspWaitStartedAt = null;
|
|
13217
13365
|
let lspFellBackNoticeShown = false;
|
|
13218
13366
|
let depInstallPromise = null;
|
|
@@ -13253,6 +13401,8 @@ async function create() {
|
|
|
13253
13401
|
try {
|
|
13254
13402
|
while (true) {
|
|
13255
13403
|
if (++pollAttempts > MAX_POLL_ATTEMPTS) {
|
|
13404
|
+
progressRenderer.setInterviewComplete(spinner);
|
|
13405
|
+
progressRenderer.finalize();
|
|
13256
13406
|
spinner.fail(chalk8.red("Pipeline timed out. Check dashboard for status."));
|
|
13257
13407
|
process.exitCode = 1;
|
|
13258
13408
|
return;
|
|
@@ -13272,6 +13422,10 @@ async function create() {
|
|
|
13272
13422
|
if (sigintBusy) {
|
|
13273
13423
|
continue;
|
|
13274
13424
|
}
|
|
13425
|
+
if (!interviewComplete && graphOnly) {
|
|
13426
|
+
interviewComplete = true;
|
|
13427
|
+
progressRenderer.setInterviewComplete(spinner);
|
|
13428
|
+
}
|
|
13275
13429
|
progressRenderer.update(syncResult, spinner);
|
|
13276
13430
|
if (!graphOnly && syncResult.status === "in_progress") {
|
|
13277
13431
|
if (syncResult.lspWaitState === "awaiting" || syncResult.lspWaitState === "analyzing") {
|
|
@@ -13291,13 +13445,19 @@ async function create() {
|
|
|
13291
13445
|
}
|
|
13292
13446
|
if (syncResult.status === "awaiting_input" && syncResult.questionId && syncResult.questionText) {
|
|
13293
13447
|
spinner.stop();
|
|
13294
|
-
|
|
13448
|
+
const estimatedQ = syncResult.discoveryResult?.estimatedInterviewQuestions;
|
|
13449
|
+
const { finished } = await handleInterview(
|
|
13295
13450
|
syncId,
|
|
13296
13451
|
syncResult.questionId,
|
|
13297
13452
|
syncResult.questionText,
|
|
13298
13453
|
syncResult.questionContext ?? void 0,
|
|
13299
|
-
|
|
13454
|
+
estimatedQ
|
|
13300
13455
|
);
|
|
13456
|
+
interviewQuestionsAnswered++;
|
|
13457
|
+
if (!interviewComplete && (finished || estimatedQ !== void 0 && estimatedQ > 0 && interviewQuestionsAnswered >= estimatedQ)) {
|
|
13458
|
+
interviewComplete = true;
|
|
13459
|
+
progressRenderer.setInterviewComplete(spinner);
|
|
13460
|
+
}
|
|
13301
13461
|
spinner.start("Resuming pipeline...");
|
|
13302
13462
|
continue;
|
|
13303
13463
|
}
|
|
@@ -13317,6 +13477,7 @@ async function create() {
|
|
|
13317
13477
|
depInstallPromise = result.installPromise;
|
|
13318
13478
|
}
|
|
13319
13479
|
if (syncResult.status === "completed") {
|
|
13480
|
+
progressRenderer.setInterviewComplete(spinner);
|
|
13320
13481
|
progressRenderer.finalize();
|
|
13321
13482
|
const generatedFiles = syncResult.filesGenerated ?? [];
|
|
13322
13483
|
const fileCount = generatedFiles.length;
|
|
@@ -13341,6 +13502,7 @@ async function create() {
|
|
|
13341
13502
|
break;
|
|
13342
13503
|
}
|
|
13343
13504
|
if (syncResult.status === "failed") {
|
|
13505
|
+
progressRenderer.setInterviewComplete(spinner);
|
|
13344
13506
|
progressRenderer.finalize();
|
|
13345
13507
|
spinner.fail(chalk8.red(`Pipeline failed: ${syncResult.error ?? "Unknown error"}`));
|
|
13346
13508
|
process.exitCode = 1;
|
|
@@ -13356,7 +13518,7 @@ async function create() {
|
|
|
13356
13518
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
13357
13519
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
13358
13520
|
if (files.length > 0) {
|
|
13359
|
-
const contextDir =
|
|
13521
|
+
const contextDir = join49(repoRoot, DEFAULT_CONTEXT_FOLDER);
|
|
13360
13522
|
mkdirSync2(contextDir, { recursive: true });
|
|
13361
13523
|
let downloadedCount = 0;
|
|
13362
13524
|
let failedCount = 0;
|
|
@@ -13370,8 +13532,8 @@ async function create() {
|
|
|
13370
13532
|
const response = await fetch(presignedUrl);
|
|
13371
13533
|
if (response.ok) {
|
|
13372
13534
|
const content = await response.text();
|
|
13373
|
-
const filePath =
|
|
13374
|
-
mkdirSync2(
|
|
13535
|
+
const filePath = join49(contextDir, file.fileName);
|
|
13536
|
+
mkdirSync2(dirname19(filePath), { recursive: true });
|
|
13375
13537
|
writeFileSync3(filePath, content, "utf-8");
|
|
13376
13538
|
downloadedCount++;
|
|
13377
13539
|
} else {
|
|
@@ -13621,7 +13783,7 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
13621
13783
|
|
|
13622
13784
|
// src/commands/member.ts
|
|
13623
13785
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
13624
|
-
import { dirname as
|
|
13786
|
+
import { dirname as dirname20, join as join50, resolve, sep } from "path";
|
|
13625
13787
|
import chalk9 from "chalk";
|
|
13626
13788
|
import ora2 from "ora";
|
|
13627
13789
|
var DEFAULT_CONTEXT_FOLDER2 = "repowise-context";
|
|
@@ -13775,7 +13937,7 @@ async function member() {
|
|
|
13775
13937
|
spinner.succeed(`Found ${chalk9.bold(files.length)} context files on server`);
|
|
13776
13938
|
const { tools } = await selectAiTools();
|
|
13777
13939
|
spinner.start("Downloading context files...");
|
|
13778
|
-
const contextDir =
|
|
13940
|
+
const contextDir = join50(repoRoot, DEFAULT_CONTEXT_FOLDER2);
|
|
13779
13941
|
mkdirSync3(contextDir, { recursive: true });
|
|
13780
13942
|
let downloadedCount = 0;
|
|
13781
13943
|
let failedCount = 0;
|
|
@@ -13796,7 +13958,7 @@ async function member() {
|
|
|
13796
13958
|
const response = await fetch(presignedUrl);
|
|
13797
13959
|
if (response.ok) {
|
|
13798
13960
|
const content = await response.text();
|
|
13799
|
-
mkdirSync3(
|
|
13961
|
+
mkdirSync3(dirname20(safePath), { recursive: true });
|
|
13800
13962
|
writeFileSync4(safePath, content, "utf-8");
|
|
13801
13963
|
downloadedCount++;
|
|
13802
13964
|
} else {
|
|
@@ -13974,10 +14136,10 @@ import ora3 from "ora";
|
|
|
13974
14136
|
|
|
13975
14137
|
// src/lib/tenant-graph-purge.ts
|
|
13976
14138
|
import { promises as fs23 } from "fs";
|
|
13977
|
-
import { homedir as
|
|
13978
|
-
import { join as
|
|
13979
|
-
async function purgeForeignGraphs(validRepoIds, home =
|
|
13980
|
-
const graphsDir =
|
|
14139
|
+
import { homedir as homedir8 } from "os";
|
|
14140
|
+
import { join as join51 } from "path";
|
|
14141
|
+
async function purgeForeignGraphs(validRepoIds, home = homedir8()) {
|
|
14142
|
+
const graphsDir = join51(home, ".repowise", "graphs");
|
|
13981
14143
|
const result = { kept: [], removed: [] };
|
|
13982
14144
|
let entries;
|
|
13983
14145
|
try {
|
|
@@ -13995,7 +14157,7 @@ async function purgeForeignGraphs(validRepoIds, home = homedir7()) {
|
|
|
13995
14157
|
result.kept.push(entry);
|
|
13996
14158
|
continue;
|
|
13997
14159
|
}
|
|
13998
|
-
const path =
|
|
14160
|
+
const path = join51(graphsDir, entry);
|
|
13999
14161
|
try {
|
|
14000
14162
|
const stat8 = await fs23.lstat(path);
|
|
14001
14163
|
if (stat8.isSymbolicLink()) {
|
|
@@ -14088,11 +14250,11 @@ async function logout() {
|
|
|
14088
14250
|
|
|
14089
14251
|
// src/commands/status.ts
|
|
14090
14252
|
import { readFile as readFile16 } from "fs/promises";
|
|
14091
|
-
import { basename as basename4, join as
|
|
14253
|
+
import { basename as basename4, join as join52 } from "path";
|
|
14092
14254
|
async function status() {
|
|
14093
14255
|
const configDir = getConfigDir2();
|
|
14094
|
-
const STATE_PATH =
|
|
14095
|
-
const CONFIG_PATH =
|
|
14256
|
+
const STATE_PATH = join52(configDir, "listener-state.json");
|
|
14257
|
+
const CONFIG_PATH = join52(configDir, "config.json");
|
|
14096
14258
|
let state = null;
|
|
14097
14259
|
try {
|
|
14098
14260
|
const data = await readFile16(STATE_PATH, "utf-8");
|
|
@@ -14140,7 +14302,7 @@ async function status() {
|
|
|
14140
14302
|
|
|
14141
14303
|
// src/commands/sync.ts
|
|
14142
14304
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
14143
|
-
import { dirname as
|
|
14305
|
+
import { dirname as dirname21, join as join53 } from "path";
|
|
14144
14306
|
import chalk12 from "chalk";
|
|
14145
14307
|
import ora4 from "ora";
|
|
14146
14308
|
var POLL_INTERVAL_MS2 = 3e3;
|
|
@@ -14289,7 +14451,7 @@ async function sync() {
|
|
|
14289
14451
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
14290
14452
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
14291
14453
|
if (files.length > 0) {
|
|
14292
|
-
const contextDir =
|
|
14454
|
+
const contextDir = join53(repoRoot, DEFAULT_CONTEXT_FOLDER3);
|
|
14293
14455
|
mkdirSync4(contextDir, { recursive: true });
|
|
14294
14456
|
let downloadedCount = 0;
|
|
14295
14457
|
let failedCount = 0;
|
|
@@ -14303,8 +14465,8 @@ async function sync() {
|
|
|
14303
14465
|
const response = await fetch(presignedUrl);
|
|
14304
14466
|
if (response.ok) {
|
|
14305
14467
|
const content = await response.text();
|
|
14306
|
-
const filePath =
|
|
14307
|
-
mkdirSync4(
|
|
14468
|
+
const filePath = join53(contextDir, file.fileName);
|
|
14469
|
+
mkdirSync4(dirname21(filePath), { recursive: true });
|
|
14308
14470
|
writeFileSync5(filePath, content, "utf-8");
|
|
14309
14471
|
downloadedCount++;
|
|
14310
14472
|
} else {
|
|
@@ -14559,7 +14721,7 @@ async function config() {
|
|
|
14559
14721
|
// src/commands/mcp-log.ts
|
|
14560
14722
|
import { createDecipheriv as createDecipheriv2 } from "crypto";
|
|
14561
14723
|
import { mkdir as mkdir19, readFile as readFile17, stat as stat7, writeFile as writeFile18 } from "fs/promises";
|
|
14562
|
-
import { dirname as
|
|
14724
|
+
import { dirname as dirname22, join as join54 } from "path";
|
|
14563
14725
|
var FLAG_FILE = "mcp-log.flag";
|
|
14564
14726
|
var LOG_FILE = "mcp-log.jsonl.enc";
|
|
14565
14727
|
var KEY_FILE = "mcp-log.key";
|
|
@@ -14567,14 +14729,14 @@ var ENDPOINT_FILE = "listener.endpoint";
|
|
|
14567
14729
|
var IV_BYTES2 = 12;
|
|
14568
14730
|
var TAG_BYTES2 = 16;
|
|
14569
14731
|
function flagPath() {
|
|
14570
|
-
return
|
|
14732
|
+
return join54(getConfigDir2(), FLAG_FILE);
|
|
14571
14733
|
}
|
|
14572
14734
|
function logPath() {
|
|
14573
|
-
return
|
|
14735
|
+
return join54(getConfigDir2(), LOG_FILE);
|
|
14574
14736
|
}
|
|
14575
14737
|
async function writeFlag(flag) {
|
|
14576
14738
|
const path = flagPath();
|
|
14577
|
-
await mkdir19(
|
|
14739
|
+
await mkdir19(dirname22(path), { recursive: true });
|
|
14578
14740
|
await writeFile18(path, JSON.stringify(flag, null, 2), { encoding: "utf-8", mode: 384 });
|
|
14579
14741
|
}
|
|
14580
14742
|
async function mcpLogOn() {
|
|
@@ -14611,14 +14773,14 @@ async function trySendConsentToServer() {
|
|
|
14611
14773
|
let apiUrl = null;
|
|
14612
14774
|
let token = null;
|
|
14613
14775
|
try {
|
|
14614
|
-
const body = await readFile17(
|
|
14776
|
+
const body = await readFile17(join54(getConfigDir2(), "config.json"), "utf-8");
|
|
14615
14777
|
const parsed = JSON.parse(body);
|
|
14616
14778
|
apiUrl = parsed.repos?.find((r) => Boolean(r.apiUrl))?.apiUrl ?? parsed.defaultApiUrl ?? null;
|
|
14617
14779
|
} catch {
|
|
14618
14780
|
return false;
|
|
14619
14781
|
}
|
|
14620
14782
|
try {
|
|
14621
|
-
const body = await readFile17(
|
|
14783
|
+
const body = await readFile17(join54(getConfigDir2(), "credentials.json"), "utf-8");
|
|
14622
14784
|
const parsed = JSON.parse(body);
|
|
14623
14785
|
token = parsed.idToken ?? null;
|
|
14624
14786
|
} catch {
|
|
@@ -14688,7 +14850,7 @@ async function mcpLogStatus() {
|
|
|
14688
14850
|
process.stderr.write("Log size: no file yet\n");
|
|
14689
14851
|
}
|
|
14690
14852
|
try {
|
|
14691
|
-
const endpointBody = await readFile17(
|
|
14853
|
+
const endpointBody = await readFile17(join54(getConfigDir2(), ENDPOINT_FILE), "utf-8");
|
|
14692
14854
|
const match = /endpoint=([^\n]+)/.exec(endpointBody);
|
|
14693
14855
|
process.stderr.write(`MCP endpoint: ${match?.[1] ?? "(malformed endpoint file)"}
|
|
14694
14856
|
`);
|
|
@@ -14719,7 +14881,7 @@ async function mcpLogViewingFlags(flags = {}) {
|
|
|
14719
14881
|
const key = await readKey();
|
|
14720
14882
|
if (!key) {
|
|
14721
14883
|
process.stderr.write(
|
|
14722
|
-
`No encryption key at ${
|
|
14884
|
+
`No encryption key at ${join54(getConfigDir2(), KEY_FILE)} \u2014 listener may not have started yet.
|
|
14723
14885
|
`
|
|
14724
14886
|
);
|
|
14725
14887
|
return;
|
|
@@ -14795,7 +14957,7 @@ async function mcpLogViewingFlags(flags = {}) {
|
|
|
14795
14957
|
}
|
|
14796
14958
|
async function readKey() {
|
|
14797
14959
|
try {
|
|
14798
|
-
const body = await readFile17(
|
|
14960
|
+
const body = await readFile17(join54(getConfigDir2(), KEY_FILE), "utf-8");
|
|
14799
14961
|
const parsed = Buffer.from(body.trim(), "base64");
|
|
14800
14962
|
if (parsed.length !== 32) return null;
|
|
14801
14963
|
return parsed;
|
|
@@ -14839,7 +15001,7 @@ import chalk14 from "chalk";
|
|
|
14839
15001
|
|
|
14840
15002
|
// src/lib/graph-loader.ts
|
|
14841
15003
|
import { promises as fs24 } from "fs";
|
|
14842
|
-
import { join as
|
|
15004
|
+
import { join as join55, resolve as resolve2 } from "path";
|
|
14843
15005
|
import { gunzipSync } from "zlib";
|
|
14844
15006
|
var RELATIVE_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json";
|
|
14845
15007
|
var GZIPPED_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json.gz";
|
|
@@ -14856,8 +15018,8 @@ var GraphNotFoundError = class extends Error {
|
|
|
14856
15018
|
var cache = /* @__PURE__ */ new Map();
|
|
14857
15019
|
async function loadGraph(repoRoot = process.cwd()) {
|
|
14858
15020
|
const root = resolve2(repoRoot);
|
|
14859
|
-
const gzPath =
|
|
14860
|
-
const plainPath =
|
|
15021
|
+
const gzPath = join55(root, GZIPPED_GRAPH_PATH);
|
|
15022
|
+
const plainPath = join55(root, RELATIVE_GRAPH_PATH);
|
|
14861
15023
|
const cached = cache.get(root);
|
|
14862
15024
|
if (cached) {
|
|
14863
15025
|
return { graph: cached, path: plainPath, bytes: 0, parseMs: 0, fromCache: true };
|
|
@@ -15272,13 +15434,13 @@ function registerQueryCommand(program2) {
|
|
|
15272
15434
|
|
|
15273
15435
|
// src/commands/uninstall.ts
|
|
15274
15436
|
import { promises as fs28 } from "fs";
|
|
15275
|
-
import { homedir as
|
|
15276
|
-
import { join as
|
|
15437
|
+
import { homedir as homedir10 } from "os";
|
|
15438
|
+
import { join as join59 } from "path";
|
|
15277
15439
|
import chalk15 from "chalk";
|
|
15278
15440
|
|
|
15279
15441
|
// src/lib/cleanup/marker-blocks.ts
|
|
15280
15442
|
import { promises as fs25 } from "fs";
|
|
15281
|
-
import { join as
|
|
15443
|
+
import { join as join56 } from "path";
|
|
15282
15444
|
var MARKER_START = "<!-- repowise-start -->";
|
|
15283
15445
|
var MARKER_END = "<!-- repowise-end -->";
|
|
15284
15446
|
var CONTEXT_FILES = [
|
|
@@ -15318,7 +15480,7 @@ async function stripMarkerBlock(filePath) {
|
|
|
15318
15480
|
async function stripAllMarkerBlocks(repoRoot) {
|
|
15319
15481
|
const out = [];
|
|
15320
15482
|
for (const relative of CONTEXT_FILES) {
|
|
15321
|
-
const full =
|
|
15483
|
+
const full = join56(repoRoot, relative);
|
|
15322
15484
|
const result = await stripMarkerBlock(full).catch((err) => ({
|
|
15323
15485
|
path: full,
|
|
15324
15486
|
status: "untouched",
|
|
@@ -15331,18 +15493,18 @@ async function stripAllMarkerBlocks(repoRoot) {
|
|
|
15331
15493
|
|
|
15332
15494
|
// src/lib/cleanup/mcp-configs.ts
|
|
15333
15495
|
import { promises as fs26 } from "fs";
|
|
15334
|
-
import { join as
|
|
15496
|
+
import { join as join57 } from "path";
|
|
15335
15497
|
function mcpConfigPaths(repoRoot, home) {
|
|
15336
15498
|
return [
|
|
15337
|
-
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
|
|
15499
|
+
join57(repoRoot, ".mcp.json"),
|
|
15500
|
+
join57(repoRoot, ".cursor", "mcp.json"),
|
|
15501
|
+
join57(repoRoot, ".vscode", "mcp.json"),
|
|
15502
|
+
join57(repoRoot, ".roo", "mcp.json"),
|
|
15503
|
+
join57(home, ".cline", "mcp.json"),
|
|
15504
|
+
join57(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
15505
|
+
join57(home, ".gemini", "settings.json"),
|
|
15506
|
+
join57(home, ".codex", "mcp.json"),
|
|
15507
|
+
join57(home, ".roo", "mcp.json")
|
|
15346
15508
|
];
|
|
15347
15509
|
}
|
|
15348
15510
|
async function removeRepowiseFromConfig(path, serverName) {
|
|
@@ -15382,11 +15544,11 @@ async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
|
15382
15544
|
|
|
15383
15545
|
// src/lib/cleanup/local-state.ts
|
|
15384
15546
|
import { promises as fs27 } from "fs";
|
|
15385
|
-
import { homedir as
|
|
15386
|
-
import { join as
|
|
15547
|
+
import { homedir as homedir9 } from "os";
|
|
15548
|
+
import { join as join58, resolve as resolve3 } from "path";
|
|
15387
15549
|
async function clearLocalState(homeOverride) {
|
|
15388
|
-
const home = homeOverride ??
|
|
15389
|
-
const target = resolve3(
|
|
15550
|
+
const home = homeOverride ?? homedir9();
|
|
15551
|
+
const target = resolve3(join58(home, ".repowise"));
|
|
15390
15552
|
if (target === resolve3(home) || !target.startsWith(resolve3(home))) {
|
|
15391
15553
|
return { path: target, status: "error", error: "refused: not under home" };
|
|
15392
15554
|
}
|
|
@@ -15421,7 +15583,7 @@ async function stopAndUninstallService(uninstaller) {
|
|
|
15421
15583
|
// src/commands/uninstall.ts
|
|
15422
15584
|
async function uninstall2(opts = {}) {
|
|
15423
15585
|
const tier = opts.tier ?? "uninstall";
|
|
15424
|
-
const home = opts.home ??
|
|
15586
|
+
const home = opts.home ?? homedir10();
|
|
15425
15587
|
const repoRoot = opts.repoRoot ?? process.cwd();
|
|
15426
15588
|
const loadRepoIds = opts.loadRepoIds ?? defaultLoadRepoIds;
|
|
15427
15589
|
const report = { tier, removed: [], preserved: [], skipped: [] };
|
|
@@ -15430,7 +15592,7 @@ async function uninstall2(opts = {}) {
|
|
|
15430
15592
|
else if (svc.error) report.skipped.push({ path: "listener service", reason: svc.error });
|
|
15431
15593
|
if (tier === "stop") return report;
|
|
15432
15594
|
try {
|
|
15433
|
-
await fs28.unlink(
|
|
15595
|
+
await fs28.unlink(join59(home, ".repowise", "credentials.json"));
|
|
15434
15596
|
report.removed.push("credentials");
|
|
15435
15597
|
} catch (err) {
|
|
15436
15598
|
if (err.code !== "ENOENT") {
|
|
@@ -15469,7 +15631,7 @@ async function uninstall2(opts = {}) {
|
|
|
15469
15631
|
}
|
|
15470
15632
|
async function defaultLoadRepoIds(home) {
|
|
15471
15633
|
try {
|
|
15472
|
-
const raw = await fs28.readFile(
|
|
15634
|
+
const raw = await fs28.readFile(join59(home, ".repowise", "config.json"), "utf-8");
|
|
15473
15635
|
const parsed = JSON.parse(raw);
|
|
15474
15636
|
return (parsed.repos ?? []).map((r) => r.repoId);
|
|
15475
15637
|
} catch {
|
|
@@ -15518,10 +15680,10 @@ Done \u2014 ${report.removed.length} removed, ${report.skipped.length} skipped.
|
|
|
15518
15680
|
init_config_dir();
|
|
15519
15681
|
import { promises as fs29 } from "fs";
|
|
15520
15682
|
import { createInterface as createInterface2 } from "readline";
|
|
15521
|
-
import { join as
|
|
15683
|
+
import { join as join60 } from "path";
|
|
15522
15684
|
var DEFAULT_MAX = 200 * 1024;
|
|
15523
15685
|
async function mcpShim(opts) {
|
|
15524
|
-
const endpointPath = opts.endpointFile ??
|
|
15686
|
+
const endpointPath = opts.endpointFile ?? join60(getConfigDir(), "listener.endpoint");
|
|
15525
15687
|
const stdin = opts.stdin ?? process.stdin;
|
|
15526
15688
|
const stdout = opts.stdout ?? process.stdout;
|
|
15527
15689
|
const stderr = opts.stderr ?? process.stderr;
|
|
@@ -16269,8 +16431,8 @@ async function lspOn() {
|
|
|
16269
16431
|
|
|
16270
16432
|
// bin/repowise.ts
|
|
16271
16433
|
var __filename = fileURLToPath4(import.meta.url);
|
|
16272
|
-
var __dirname =
|
|
16273
|
-
var pkg = JSON.parse(readFileSync3(
|
|
16434
|
+
var __dirname = dirname23(__filename);
|
|
16435
|
+
var pkg = JSON.parse(readFileSync3(join61(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
16274
16436
|
var program = new Command();
|
|
16275
16437
|
program.name(getPackageName()).description("AI-optimized codebase context generator").version(pkg.version).hook("preAction", async () => {
|
|
16276
16438
|
await showWelcome(pkg.version);
|