repowisestage 0.0.40 → 0.0.42
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 +1178 -549
- package/package.json +1 -1
package/dist/bin/repowise.js
CHANGED
|
@@ -456,404 +456,6 @@ var init_service_installer = __esm({
|
|
|
456
456
|
}
|
|
457
457
|
});
|
|
458
458
|
|
|
459
|
-
// ../../packages/shared/src/types/typed-resolution.ts
|
|
460
|
-
function typedResolutionKey(filePath, propertyName, line, column) {
|
|
461
|
-
return `${filePath}\0${propertyName}\0${line.toString()}\0${column.toString()}`;
|
|
462
|
-
}
|
|
463
|
-
var TYPED_RESOLUTION_SCHEMA_VERSION;
|
|
464
|
-
var init_typed_resolution = __esm({
|
|
465
|
-
"../../packages/shared/src/types/typed-resolution.ts"() {
|
|
466
|
-
"use strict";
|
|
467
|
-
TYPED_RESOLUTION_SCHEMA_VERSION = 1;
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
// ../../packages/shared/src/types/billing.ts
|
|
472
|
-
var init_billing = __esm({
|
|
473
|
-
"../../packages/shared/src/types/billing.ts"() {
|
|
474
|
-
"use strict";
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
// ../../packages/shared/src/constants/platforms.ts
|
|
479
|
-
var init_platforms = __esm({
|
|
480
|
-
"../../packages/shared/src/constants/platforms.ts"() {
|
|
481
|
-
"use strict";
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
// ../../packages/shared/src/constants/tiers.ts
|
|
486
|
-
var SUBSCRIPTION_TIERS, TIER_LIMITS;
|
|
487
|
-
var init_tiers = __esm({
|
|
488
|
-
"../../packages/shared/src/constants/tiers.ts"() {
|
|
489
|
-
"use strict";
|
|
490
|
-
SUBSCRIPTION_TIERS = {
|
|
491
|
-
STARTER: "starter",
|
|
492
|
-
PRO: "pro",
|
|
493
|
-
TEAM: "team"
|
|
494
|
-
};
|
|
495
|
-
TIER_LIMITS = {
|
|
496
|
-
[SUBSCRIPTION_TIERS.STARTER]: {
|
|
497
|
-
maxRepos: 1,
|
|
498
|
-
maxSeats: 1,
|
|
499
|
-
maxSyncsPerMonth: 10,
|
|
500
|
-
maxConcurrentSyncs: 1,
|
|
501
|
-
bedrockEndpoint: "public"
|
|
502
|
-
},
|
|
503
|
-
[SUBSCRIPTION_TIERS.PRO]: {
|
|
504
|
-
maxRepos: 2,
|
|
505
|
-
maxSeats: 1,
|
|
506
|
-
maxSyncsPerMonth: 30,
|
|
507
|
-
maxConcurrentSyncs: 2,
|
|
508
|
-
bedrockEndpoint: "public"
|
|
509
|
-
},
|
|
510
|
-
[SUBSCRIPTION_TIERS.TEAM]: {
|
|
511
|
-
maxRepos: 3,
|
|
512
|
-
maxSeats: 999999,
|
|
513
|
-
maxSyncsPerMonth: 30,
|
|
514
|
-
maxConcurrentSyncs: 10,
|
|
515
|
-
bedrockEndpoint: "public"
|
|
516
|
-
}
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
// ../../packages/shared/src/constants/roles.ts
|
|
522
|
-
function hasPermission(role, permission) {
|
|
523
|
-
return PERMISSIONS[role][permission];
|
|
524
|
-
}
|
|
525
|
-
function resolveRole(groups) {
|
|
526
|
-
for (const role of ROLE_PRIORITY) {
|
|
527
|
-
if (groups.includes(role)) return role;
|
|
528
|
-
}
|
|
529
|
-
return ROLES.MEMBER;
|
|
530
|
-
}
|
|
531
|
-
var ROLES, PERMISSIONS, ROLE_PRIORITY;
|
|
532
|
-
var init_roles = __esm({
|
|
533
|
-
"../../packages/shared/src/constants/roles.ts"() {
|
|
534
|
-
"use strict";
|
|
535
|
-
ROLES = {
|
|
536
|
-
OWNER: "owner",
|
|
537
|
-
ADMIN: "admin",
|
|
538
|
-
REPO_MANAGER: "repo_manager",
|
|
539
|
-
MEMBER: "member"
|
|
540
|
-
};
|
|
541
|
-
PERMISSIONS = {
|
|
542
|
-
[ROLES.OWNER]: {
|
|
543
|
-
connectRepos: true,
|
|
544
|
-
viewSync: true,
|
|
545
|
-
triggerRetry: true,
|
|
546
|
-
configWatcher: true,
|
|
547
|
-
inviteMembers: true,
|
|
548
|
-
manageBilling: true,
|
|
549
|
-
configAiTools: true,
|
|
550
|
-
manageTeam: true
|
|
551
|
-
},
|
|
552
|
-
[ROLES.ADMIN]: {
|
|
553
|
-
connectRepos: true,
|
|
554
|
-
viewSync: true,
|
|
555
|
-
triggerRetry: true,
|
|
556
|
-
configWatcher: true,
|
|
557
|
-
inviteMembers: true,
|
|
558
|
-
manageBilling: false,
|
|
559
|
-
configAiTools: true,
|
|
560
|
-
manageTeam: true
|
|
561
|
-
},
|
|
562
|
-
[ROLES.REPO_MANAGER]: {
|
|
563
|
-
connectRepos: true,
|
|
564
|
-
viewSync: true,
|
|
565
|
-
triggerRetry: true,
|
|
566
|
-
configWatcher: true,
|
|
567
|
-
inviteMembers: false,
|
|
568
|
-
manageBilling: false,
|
|
569
|
-
configAiTools: true,
|
|
570
|
-
manageTeam: false
|
|
571
|
-
},
|
|
572
|
-
[ROLES.MEMBER]: {
|
|
573
|
-
connectRepos: false,
|
|
574
|
-
viewSync: true,
|
|
575
|
-
triggerRetry: true,
|
|
576
|
-
configWatcher: false,
|
|
577
|
-
inviteMembers: false,
|
|
578
|
-
manageBilling: false,
|
|
579
|
-
configAiTools: true,
|
|
580
|
-
manageTeam: false
|
|
581
|
-
}
|
|
582
|
-
};
|
|
583
|
-
ROLE_PRIORITY = [
|
|
584
|
-
ROLES.OWNER,
|
|
585
|
-
ROLES.ADMIN,
|
|
586
|
-
ROLES.REPO_MANAGER,
|
|
587
|
-
ROLES.MEMBER
|
|
588
|
-
];
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
|
|
592
|
-
// ../../packages/shared/src/index.ts
|
|
593
|
-
var init_src = __esm({
|
|
594
|
-
"../../packages/shared/src/index.ts"() {
|
|
595
|
-
"use strict";
|
|
596
|
-
init_typed_resolution();
|
|
597
|
-
init_billing();
|
|
598
|
-
init_platforms();
|
|
599
|
-
init_tiers();
|
|
600
|
-
init_roles();
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
// ../listener/dist/typed-resolution/sidecar-cache.js
|
|
605
|
-
var sidecar_cache_exports = {};
|
|
606
|
-
__export(sidecar_cache_exports, {
|
|
607
|
-
loadMergedSidecar: () => loadMergedSidecar,
|
|
608
|
-
persistMergedSidecar: () => persistMergedSidecar,
|
|
609
|
-
sidecarCachePaths: () => sidecarCachePaths
|
|
610
|
-
});
|
|
611
|
-
import { mkdir as mkdir8, readFile as readFile7, readdir as readdir3, stat as stat2, unlink as unlink7, writeFile as writeFile8 } from "fs/promises";
|
|
612
|
-
import { dirname as dirname5, join as join14 } from "path";
|
|
613
|
-
function repoIdSafe(repoId) {
|
|
614
|
-
return /^[A-Za-z0-9_.-]{1,128}$/.test(repoId) && !repoId.startsWith(".");
|
|
615
|
-
}
|
|
616
|
-
function commitShaSafe(commitSha) {
|
|
617
|
-
return /^[a-f0-9]{7,64}$/.test(commitSha);
|
|
618
|
-
}
|
|
619
|
-
function sidecarCachePaths(repoId, commitSha) {
|
|
620
|
-
if (!repoIdSafe(repoId)) {
|
|
621
|
-
throw new Error(`unsafe repoId: ${repoId}`);
|
|
622
|
-
}
|
|
623
|
-
if (!commitShaSafe(commitSha)) {
|
|
624
|
-
throw new Error(`unsafe commitSha: ${commitSha}`);
|
|
625
|
-
}
|
|
626
|
-
const repoDir = join14(getConfigDir(), "typed-resolution", repoId);
|
|
627
|
-
const fullPath = join14(repoDir, `${commitSha}.jsonl`);
|
|
628
|
-
return { fullPath, repoDir };
|
|
629
|
-
}
|
|
630
|
-
async function persistMergedSidecar(repoId, commitSha, sidecar) {
|
|
631
|
-
const { fullPath, repoDir } = sidecarCachePaths(repoId, commitSha);
|
|
632
|
-
await mkdir8(repoDir, { recursive: true });
|
|
633
|
-
const tmpPath = `${fullPath}.tmp`;
|
|
634
|
-
await writeFile8(tmpPath, JSON.stringify(sidecar), "utf-8");
|
|
635
|
-
const { rename: rename5 } = await import("fs/promises");
|
|
636
|
-
await rename5(tmpPath, fullPath);
|
|
637
|
-
try {
|
|
638
|
-
await sweepSidecarDir(repoDir);
|
|
639
|
-
} catch {
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
async function sweepSidecarDir(repoDir) {
|
|
643
|
-
const entries = await readdir3(repoDir);
|
|
644
|
-
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
645
|
-
if (jsonlFiles.length <= SWEEP_KEEP_MIN)
|
|
646
|
-
return;
|
|
647
|
-
const withMtime = [];
|
|
648
|
-
for (const name of jsonlFiles) {
|
|
649
|
-
try {
|
|
650
|
-
const s = await stat2(join14(repoDir, name));
|
|
651
|
-
withMtime.push({ name, mtimeMs: s.mtimeMs });
|
|
652
|
-
} catch {
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
withMtime.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
656
|
-
const now = Date.now();
|
|
657
|
-
const candidates = withMtime.slice(SWEEP_KEEP_MIN);
|
|
658
|
-
for (const { name, mtimeMs } of candidates) {
|
|
659
|
-
if (now - mtimeMs >= SWEEP_MAX_AGE_MS) {
|
|
660
|
-
try {
|
|
661
|
-
await unlink7(join14(repoDir, name));
|
|
662
|
-
} catch {
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
function isValidSidecarEntry(e) {
|
|
668
|
-
if (!e || typeof e !== "object")
|
|
669
|
-
return false;
|
|
670
|
-
const r = e;
|
|
671
|
-
if (typeof r["filePath"] !== "string")
|
|
672
|
-
return false;
|
|
673
|
-
if (typeof r["propertyName"] !== "string")
|
|
674
|
-
return false;
|
|
675
|
-
if (typeof r["line"] !== "number" || !Number.isInteger(r["line"]))
|
|
676
|
-
return false;
|
|
677
|
-
if (typeof r["column"] !== "number" || !Number.isInteger(r["column"]))
|
|
678
|
-
return false;
|
|
679
|
-
if (typeof r["confidence"] !== "number")
|
|
680
|
-
return false;
|
|
681
|
-
return true;
|
|
682
|
-
}
|
|
683
|
-
async function loadMergedSidecar(repoId, commitSha) {
|
|
684
|
-
let body;
|
|
685
|
-
try {
|
|
686
|
-
const { fullPath } = sidecarCachePaths(repoId, commitSha);
|
|
687
|
-
body = await readFile7(fullPath, "utf-8");
|
|
688
|
-
} catch {
|
|
689
|
-
return null;
|
|
690
|
-
}
|
|
691
|
-
try {
|
|
692
|
-
const parsed = JSON.parse(body);
|
|
693
|
-
if (parsed.schemaVersion !== TYPED_RESOLUTION_SCHEMA_VERSION)
|
|
694
|
-
return null;
|
|
695
|
-
if (!Array.isArray(parsed.resolutions))
|
|
696
|
-
return null;
|
|
697
|
-
const all = parsed.resolutions;
|
|
698
|
-
const valid = all.filter(isValidSidecarEntry);
|
|
699
|
-
if (valid.length === 0 && all.length > 0)
|
|
700
|
-
return null;
|
|
701
|
-
if (valid.length < all.length * 0.5)
|
|
702
|
-
return null;
|
|
703
|
-
return { ...parsed, resolutions: valid };
|
|
704
|
-
} catch {
|
|
705
|
-
return null;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
var SWEEP_MAX_AGE_MS, SWEEP_KEEP_MIN;
|
|
709
|
-
var init_sidecar_cache = __esm({
|
|
710
|
-
"../listener/dist/typed-resolution/sidecar-cache.js"() {
|
|
711
|
-
"use strict";
|
|
712
|
-
init_config_dir();
|
|
713
|
-
init_src();
|
|
714
|
-
SWEEP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
715
|
-
SWEEP_KEEP_MIN = 5;
|
|
716
|
-
}
|
|
717
|
-
});
|
|
718
|
-
|
|
719
|
-
// ../listener/dist/typed-resolution/sidecar-client.js
|
|
720
|
-
var sidecar_client_exports = {};
|
|
721
|
-
__export(sidecar_client_exports, {
|
|
722
|
-
buildSidecar: () => buildSidecar,
|
|
723
|
-
buildSidecarIndex: () => buildSidecarIndex,
|
|
724
|
-
downloadMergedSidecar: () => downloadMergedSidecar,
|
|
725
|
-
overlayMergedSidecar: () => overlayMergedSidecar,
|
|
726
|
-
uploadSidecar: () => uploadSidecar
|
|
727
|
-
});
|
|
728
|
-
async function uploadSidecar(req, fetchImpl = fetch) {
|
|
729
|
-
const url = `${req.apiUrl.replace(/\/$/, "")}/v1/repos/${encodeURIComponent(req.repoId)}/typed-resolution`;
|
|
730
|
-
const body = JSON.stringify({ ...req.sidecar, commitSha: req.commitSha });
|
|
731
|
-
const byteLength = Buffer.byteLength(body, "utf8");
|
|
732
|
-
if (byteLength > UPLOAD_BODY_BYTE_LIMIT) {
|
|
733
|
-
const msg = `sidecar body too large to upload (${byteLength.toString()} bytes > ${UPLOAD_BODY_BYTE_LIMIT.toString()} byte cap); skipping`;
|
|
734
|
-
console.warn(`[typed-resolution] ${msg}`);
|
|
735
|
-
return {
|
|
736
|
-
uploaded: false,
|
|
737
|
-
resolutionCount: req.sidecar.resolutions.length,
|
|
738
|
-
uploadKey: "",
|
|
739
|
-
error: msg
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
const res = await fetchImpl(url, {
|
|
743
|
-
method: "POST",
|
|
744
|
-
headers: {
|
|
745
|
-
"content-type": "application/json",
|
|
746
|
-
authorization: `Bearer ${req.authToken}`
|
|
747
|
-
},
|
|
748
|
-
body
|
|
749
|
-
});
|
|
750
|
-
if (!res.ok) {
|
|
751
|
-
const text = await res.text().catch(() => "");
|
|
752
|
-
throw new Error(`upload failed: HTTP ${res.status.toString()} ${text}`);
|
|
753
|
-
}
|
|
754
|
-
const payload = await res.json();
|
|
755
|
-
if (!payload.data)
|
|
756
|
-
throw new Error("upload response missing `data`");
|
|
757
|
-
return payload.data;
|
|
758
|
-
}
|
|
759
|
-
async function downloadMergedSidecar(req, fetchImpl = fetch) {
|
|
760
|
-
const url = `${req.apiUrl.replace(/\/$/, "")}/v1/repos/${encodeURIComponent(req.repoId)}/typed-resolution/${encodeURIComponent(req.commitSha)}`;
|
|
761
|
-
const res = await fetchImpl(url, {
|
|
762
|
-
method: "GET",
|
|
763
|
-
headers: { authorization: `Bearer ${req.authToken}` }
|
|
764
|
-
});
|
|
765
|
-
if (res.status === 404)
|
|
766
|
-
return null;
|
|
767
|
-
if (!res.ok) {
|
|
768
|
-
throw new Error(`download failed: HTTP ${res.status.toString()}`);
|
|
769
|
-
}
|
|
770
|
-
const body = await res.json();
|
|
771
|
-
if (body.schemaVersion !== TYPED_RESOLUTION_SCHEMA_VERSION)
|
|
772
|
-
return null;
|
|
773
|
-
if (!Array.isArray(body.resolutions))
|
|
774
|
-
return null;
|
|
775
|
-
return body;
|
|
776
|
-
}
|
|
777
|
-
function buildSidecarIndex(sidecar) {
|
|
778
|
-
const map = /* @__PURE__ */ new Map();
|
|
779
|
-
if (!sidecar)
|
|
780
|
-
return map;
|
|
781
|
-
for (const r of sidecar.resolutions) {
|
|
782
|
-
map.set(typedResolutionKey(r.filePath, r.propertyName, r.line, r.column), r);
|
|
783
|
-
}
|
|
784
|
-
return map;
|
|
785
|
-
}
|
|
786
|
-
function overlayMergedSidecar(edges, sidecar) {
|
|
787
|
-
let edgesUpgraded = 0;
|
|
788
|
-
let edgesUnchanged = 0;
|
|
789
|
-
const index = buildSidecarIndex(sidecar);
|
|
790
|
-
for (const edge of edges) {
|
|
791
|
-
if (!edge.filePath || !edge.propertyName || !edge.location || edge.resolution === "typed") {
|
|
792
|
-
edgesUnchanged += 1;
|
|
793
|
-
continue;
|
|
794
|
-
}
|
|
795
|
-
const key = typedResolutionKey(edge.filePath, edge.propertyName, edge.location.line, edge.location.column);
|
|
796
|
-
const hit = index.get(key);
|
|
797
|
-
if (!hit || hit.targetSymbolId === null) {
|
|
798
|
-
edgesUnchanged += 1;
|
|
799
|
-
continue;
|
|
800
|
-
}
|
|
801
|
-
edge.to = hit.targetSymbolId;
|
|
802
|
-
edge.resolution = "typed";
|
|
803
|
-
edge.confidence = hit.confidence;
|
|
804
|
-
edgesUpgraded += 1;
|
|
805
|
-
}
|
|
806
|
-
return { edgesUpgraded, edgesUnchanged };
|
|
807
|
-
}
|
|
808
|
-
async function buildSidecar(req) {
|
|
809
|
-
const groupKeyFn = req.groupKey ?? (() => "default");
|
|
810
|
-
const groups = /* @__PURE__ */ new Map();
|
|
811
|
-
req.receivers.forEach((receiver, index) => {
|
|
812
|
-
const key = groupKeyFn(receiver) ?? "__default__";
|
|
813
|
-
let bucket = groups.get(key);
|
|
814
|
-
if (!bucket) {
|
|
815
|
-
bucket = [];
|
|
816
|
-
groups.set(key, bucket);
|
|
817
|
-
}
|
|
818
|
-
bucket.push({ index, receiver });
|
|
819
|
-
});
|
|
820
|
-
const resolutions = new Array(req.receivers.length);
|
|
821
|
-
await Promise.all(Array.from(groups.values()).map(async (bucket) => {
|
|
822
|
-
for (const { index, receiver } of bucket) {
|
|
823
|
-
let targetSymbolId;
|
|
824
|
-
try {
|
|
825
|
-
targetSymbolId = await req.resolve(receiver);
|
|
826
|
-
} catch (err) {
|
|
827
|
-
console.warn(`[typed-resolution] resolve failed for ${receiver.filePath}:${receiver.line.toString()}:${receiver.column.toString()} property=${receiver.propertyName} errMsg=${err instanceof Error ? err.message : String(err)}`);
|
|
828
|
-
targetSymbolId = null;
|
|
829
|
-
}
|
|
830
|
-
resolutions[index] = {
|
|
831
|
-
filePath: receiver.filePath,
|
|
832
|
-
propertyName: receiver.propertyName,
|
|
833
|
-
line: receiver.line,
|
|
834
|
-
column: receiver.column,
|
|
835
|
-
targetSymbolId,
|
|
836
|
-
confidence: 0.9
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
}));
|
|
840
|
-
return {
|
|
841
|
-
schemaVersion: TYPED_RESOLUTION_SCHEMA_VERSION,
|
|
842
|
-
producer: req.producer,
|
|
843
|
-
emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
844
|
-
languages: [...req.languages],
|
|
845
|
-
resolutions
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
var UPLOAD_BODY_BYTE_LIMIT;
|
|
849
|
-
var init_sidecar_client = __esm({
|
|
850
|
-
"../listener/dist/typed-resolution/sidecar-client.js"() {
|
|
851
|
-
"use strict";
|
|
852
|
-
init_src();
|
|
853
|
-
UPLOAD_BODY_BYTE_LIMIT = 8 * 1024 * 1024;
|
|
854
|
-
}
|
|
855
|
-
});
|
|
856
|
-
|
|
857
459
|
// ../listener/dist/lsp/registry.js
|
|
858
460
|
function detectLanguage(path) {
|
|
859
461
|
const dot = path.lastIndexOf(".");
|
|
@@ -895,7 +497,8 @@ var init_registry = __esm({
|
|
|
895
497
|
args: ["--stdio"],
|
|
896
498
|
extensions: [".ts", ".tsx", ".mts", ".cts"],
|
|
897
499
|
lspLanguageId: "typescript",
|
|
898
|
-
installHint: "npm i -g typescript typescript-language-server"
|
|
500
|
+
installHint: "npm i -g typescript typescript-language-server",
|
|
501
|
+
npmPackage: "typescript-language-server"
|
|
899
502
|
}
|
|
900
503
|
],
|
|
901
504
|
javascript: [
|
|
@@ -906,7 +509,8 @@ var init_registry = __esm({
|
|
|
906
509
|
args: ["--stdio"],
|
|
907
510
|
extensions: [".js", ".jsx", ".mjs", ".cjs"],
|
|
908
511
|
lspLanguageId: "javascript",
|
|
909
|
-
installHint: "npm i -g typescript typescript-language-server"
|
|
512
|
+
installHint: "npm i -g typescript typescript-language-server",
|
|
513
|
+
npmPackage: "typescript-language-server"
|
|
910
514
|
}
|
|
911
515
|
],
|
|
912
516
|
python: [
|
|
@@ -917,7 +521,8 @@ var init_registry = __esm({
|
|
|
917
521
|
args: ["--stdio"],
|
|
918
522
|
extensions: [".py", ".pyi"],
|
|
919
523
|
lspLanguageId: "python",
|
|
920
|
-
installHint: "npm i -g pyright"
|
|
524
|
+
installHint: "npm i -g pyright",
|
|
525
|
+
npmPackage: "pyright"
|
|
921
526
|
},
|
|
922
527
|
{
|
|
923
528
|
id: "pylsp",
|
|
@@ -1009,7 +614,8 @@ var init_registry = __esm({
|
|
|
1009
614
|
args: ["--stdio"],
|
|
1010
615
|
extensions: [".php"],
|
|
1011
616
|
lspLanguageId: "php",
|
|
1012
|
-
installHint: "npm i -g intelephense"
|
|
617
|
+
installHint: "npm i -g intelephense",
|
|
618
|
+
npmPackage: "intelephense"
|
|
1013
619
|
}
|
|
1014
620
|
],
|
|
1015
621
|
ruby: [
|
|
@@ -1095,7 +701,8 @@ var init_registry = __esm({
|
|
|
1095
701
|
args: ["--stdio"],
|
|
1096
702
|
extensions: [".vue"],
|
|
1097
703
|
lspLanguageId: "vue",
|
|
1098
|
-
installHint: "npm i -g @vue/language-server"
|
|
704
|
+
installHint: "npm i -g @vue/language-server",
|
|
705
|
+
npmPackage: "@vue/language-server"
|
|
1099
706
|
}
|
|
1100
707
|
],
|
|
1101
708
|
svelte: [
|
|
@@ -1106,13 +713,412 @@ var init_registry = __esm({
|
|
|
1106
713
|
args: ["--stdio"],
|
|
1107
714
|
extensions: [".svelte"],
|
|
1108
715
|
lspLanguageId: "svelte",
|
|
1109
|
-
installHint: "npm i -g svelte-language-server"
|
|
716
|
+
installHint: "npm i -g svelte-language-server",
|
|
717
|
+
npmPackage: "svelte-language-server"
|
|
1110
718
|
}
|
|
1111
719
|
]
|
|
1112
720
|
};
|
|
1113
721
|
}
|
|
1114
722
|
});
|
|
1115
723
|
|
|
724
|
+
// ../../packages/shared/src/types/typed-resolution.ts
|
|
725
|
+
function typedResolutionKey(filePath, propertyName, line, column) {
|
|
726
|
+
return `${filePath}\0${propertyName}\0${line.toString()}\0${column.toString()}`;
|
|
727
|
+
}
|
|
728
|
+
var TYPED_RESOLUTION_SCHEMA_VERSION;
|
|
729
|
+
var init_typed_resolution = __esm({
|
|
730
|
+
"../../packages/shared/src/types/typed-resolution.ts"() {
|
|
731
|
+
"use strict";
|
|
732
|
+
TYPED_RESOLUTION_SCHEMA_VERSION = 1;
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
// ../../packages/shared/src/types/billing.ts
|
|
737
|
+
var init_billing = __esm({
|
|
738
|
+
"../../packages/shared/src/types/billing.ts"() {
|
|
739
|
+
"use strict";
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
// ../../packages/shared/src/constants/platforms.ts
|
|
744
|
+
var init_platforms = __esm({
|
|
745
|
+
"../../packages/shared/src/constants/platforms.ts"() {
|
|
746
|
+
"use strict";
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
// ../../packages/shared/src/constants/tiers.ts
|
|
751
|
+
var SUBSCRIPTION_TIERS, TIER_LIMITS;
|
|
752
|
+
var init_tiers = __esm({
|
|
753
|
+
"../../packages/shared/src/constants/tiers.ts"() {
|
|
754
|
+
"use strict";
|
|
755
|
+
SUBSCRIPTION_TIERS = {
|
|
756
|
+
STARTER: "starter",
|
|
757
|
+
PRO: "pro",
|
|
758
|
+
TEAM: "team"
|
|
759
|
+
};
|
|
760
|
+
TIER_LIMITS = {
|
|
761
|
+
[SUBSCRIPTION_TIERS.STARTER]: {
|
|
762
|
+
maxRepos: 1,
|
|
763
|
+
maxSeats: 1,
|
|
764
|
+
maxSyncsPerMonth: 10,
|
|
765
|
+
maxConcurrentSyncs: 1,
|
|
766
|
+
bedrockEndpoint: "public"
|
|
767
|
+
},
|
|
768
|
+
[SUBSCRIPTION_TIERS.PRO]: {
|
|
769
|
+
maxRepos: 2,
|
|
770
|
+
maxSeats: 1,
|
|
771
|
+
maxSyncsPerMonth: 30,
|
|
772
|
+
maxConcurrentSyncs: 2,
|
|
773
|
+
bedrockEndpoint: "public"
|
|
774
|
+
},
|
|
775
|
+
[SUBSCRIPTION_TIERS.TEAM]: {
|
|
776
|
+
maxRepos: 3,
|
|
777
|
+
maxSeats: 999999,
|
|
778
|
+
maxSyncsPerMonth: 30,
|
|
779
|
+
maxConcurrentSyncs: 10,
|
|
780
|
+
bedrockEndpoint: "public"
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
// ../../packages/shared/src/constants/roles.ts
|
|
787
|
+
function hasPermission(role, permission) {
|
|
788
|
+
return PERMISSIONS[role][permission];
|
|
789
|
+
}
|
|
790
|
+
function resolveRole(groups) {
|
|
791
|
+
for (const role of ROLE_PRIORITY) {
|
|
792
|
+
if (groups.includes(role)) return role;
|
|
793
|
+
}
|
|
794
|
+
return ROLES.MEMBER;
|
|
795
|
+
}
|
|
796
|
+
var ROLES, PERMISSIONS, ROLE_PRIORITY;
|
|
797
|
+
var init_roles = __esm({
|
|
798
|
+
"../../packages/shared/src/constants/roles.ts"() {
|
|
799
|
+
"use strict";
|
|
800
|
+
ROLES = {
|
|
801
|
+
OWNER: "owner",
|
|
802
|
+
ADMIN: "admin",
|
|
803
|
+
REPO_MANAGER: "repo_manager",
|
|
804
|
+
MEMBER: "member"
|
|
805
|
+
};
|
|
806
|
+
PERMISSIONS = {
|
|
807
|
+
[ROLES.OWNER]: {
|
|
808
|
+
connectRepos: true,
|
|
809
|
+
viewSync: true,
|
|
810
|
+
triggerRetry: true,
|
|
811
|
+
configWatcher: true,
|
|
812
|
+
inviteMembers: true,
|
|
813
|
+
manageBilling: true,
|
|
814
|
+
configAiTools: true,
|
|
815
|
+
manageTeam: true
|
|
816
|
+
},
|
|
817
|
+
[ROLES.ADMIN]: {
|
|
818
|
+
connectRepos: true,
|
|
819
|
+
viewSync: true,
|
|
820
|
+
triggerRetry: true,
|
|
821
|
+
configWatcher: true,
|
|
822
|
+
inviteMembers: true,
|
|
823
|
+
manageBilling: false,
|
|
824
|
+
configAiTools: true,
|
|
825
|
+
manageTeam: true
|
|
826
|
+
},
|
|
827
|
+
[ROLES.REPO_MANAGER]: {
|
|
828
|
+
connectRepos: true,
|
|
829
|
+
viewSync: true,
|
|
830
|
+
triggerRetry: true,
|
|
831
|
+
configWatcher: true,
|
|
832
|
+
inviteMembers: false,
|
|
833
|
+
manageBilling: false,
|
|
834
|
+
configAiTools: true,
|
|
835
|
+
manageTeam: false
|
|
836
|
+
},
|
|
837
|
+
[ROLES.MEMBER]: {
|
|
838
|
+
connectRepos: false,
|
|
839
|
+
viewSync: true,
|
|
840
|
+
triggerRetry: true,
|
|
841
|
+
configWatcher: false,
|
|
842
|
+
inviteMembers: false,
|
|
843
|
+
manageBilling: false,
|
|
844
|
+
configAiTools: true,
|
|
845
|
+
manageTeam: false
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
ROLE_PRIORITY = [
|
|
849
|
+
ROLES.OWNER,
|
|
850
|
+
ROLES.ADMIN,
|
|
851
|
+
ROLES.REPO_MANAGER,
|
|
852
|
+
ROLES.MEMBER
|
|
853
|
+
];
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
// ../../packages/shared/src/index.ts
|
|
858
|
+
var init_src = __esm({
|
|
859
|
+
"../../packages/shared/src/index.ts"() {
|
|
860
|
+
"use strict";
|
|
861
|
+
init_typed_resolution();
|
|
862
|
+
init_billing();
|
|
863
|
+
init_platforms();
|
|
864
|
+
init_tiers();
|
|
865
|
+
init_roles();
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
// ../listener/dist/typed-resolution/sidecar-cache.js
|
|
870
|
+
var sidecar_cache_exports = {};
|
|
871
|
+
__export(sidecar_cache_exports, {
|
|
872
|
+
loadMergedSidecar: () => loadMergedSidecar,
|
|
873
|
+
persistMergedSidecar: () => persistMergedSidecar,
|
|
874
|
+
sidecarCachePaths: () => sidecarCachePaths
|
|
875
|
+
});
|
|
876
|
+
import { mkdir as mkdir8, readFile as readFile7, readdir as readdir3, stat as stat2, unlink as unlink7, writeFile as writeFile8 } from "fs/promises";
|
|
877
|
+
import { dirname as dirname6, join as join15 } from "path";
|
|
878
|
+
function repoIdSafe(repoId) {
|
|
879
|
+
return /^[A-Za-z0-9_.-]{1,128}$/.test(repoId) && !repoId.startsWith(".");
|
|
880
|
+
}
|
|
881
|
+
function commitShaSafe(commitSha) {
|
|
882
|
+
return /^[a-f0-9]{7,64}$/.test(commitSha);
|
|
883
|
+
}
|
|
884
|
+
function sidecarCachePaths(repoId, commitSha) {
|
|
885
|
+
if (!repoIdSafe(repoId)) {
|
|
886
|
+
throw new Error(`unsafe repoId: ${repoId}`);
|
|
887
|
+
}
|
|
888
|
+
if (!commitShaSafe(commitSha)) {
|
|
889
|
+
throw new Error(`unsafe commitSha: ${commitSha}`);
|
|
890
|
+
}
|
|
891
|
+
const repoDir = join15(getConfigDir(), "typed-resolution", repoId);
|
|
892
|
+
const fullPath = join15(repoDir, `${commitSha}.jsonl`);
|
|
893
|
+
return { fullPath, repoDir };
|
|
894
|
+
}
|
|
895
|
+
async function persistMergedSidecar(repoId, commitSha, sidecar) {
|
|
896
|
+
const { fullPath, repoDir } = sidecarCachePaths(repoId, commitSha);
|
|
897
|
+
await mkdir8(repoDir, { recursive: true });
|
|
898
|
+
const tmpPath = `${fullPath}.tmp`;
|
|
899
|
+
await writeFile8(tmpPath, JSON.stringify(sidecar), "utf-8");
|
|
900
|
+
const { rename: rename5 } = await import("fs/promises");
|
|
901
|
+
await rename5(tmpPath, fullPath);
|
|
902
|
+
try {
|
|
903
|
+
await sweepSidecarDir(repoDir);
|
|
904
|
+
} catch {
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
async function sweepSidecarDir(repoDir) {
|
|
908
|
+
const entries = await readdir3(repoDir);
|
|
909
|
+
const jsonlFiles = entries.filter((e) => e.endsWith(".jsonl"));
|
|
910
|
+
if (jsonlFiles.length <= SWEEP_KEEP_MIN)
|
|
911
|
+
return;
|
|
912
|
+
const withMtime = [];
|
|
913
|
+
for (const name of jsonlFiles) {
|
|
914
|
+
try {
|
|
915
|
+
const s = await stat2(join15(repoDir, name));
|
|
916
|
+
withMtime.push({ name, mtimeMs: s.mtimeMs });
|
|
917
|
+
} catch {
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
withMtime.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
921
|
+
const now = Date.now();
|
|
922
|
+
const candidates = withMtime.slice(SWEEP_KEEP_MIN);
|
|
923
|
+
for (const { name, mtimeMs } of candidates) {
|
|
924
|
+
if (now - mtimeMs >= SWEEP_MAX_AGE_MS) {
|
|
925
|
+
try {
|
|
926
|
+
await unlink7(join15(repoDir, name));
|
|
927
|
+
} catch {
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
function isValidSidecarEntry(e) {
|
|
933
|
+
if (!e || typeof e !== "object")
|
|
934
|
+
return false;
|
|
935
|
+
const r = e;
|
|
936
|
+
if (typeof r["filePath"] !== "string")
|
|
937
|
+
return false;
|
|
938
|
+
if (typeof r["propertyName"] !== "string")
|
|
939
|
+
return false;
|
|
940
|
+
if (typeof r["line"] !== "number" || !Number.isInteger(r["line"]))
|
|
941
|
+
return false;
|
|
942
|
+
if (typeof r["column"] !== "number" || !Number.isInteger(r["column"]))
|
|
943
|
+
return false;
|
|
944
|
+
if (typeof r["confidence"] !== "number")
|
|
945
|
+
return false;
|
|
946
|
+
return true;
|
|
947
|
+
}
|
|
948
|
+
async function loadMergedSidecar(repoId, commitSha) {
|
|
949
|
+
let body;
|
|
950
|
+
try {
|
|
951
|
+
const { fullPath } = sidecarCachePaths(repoId, commitSha);
|
|
952
|
+
body = await readFile7(fullPath, "utf-8");
|
|
953
|
+
} catch {
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
try {
|
|
957
|
+
const parsed = JSON.parse(body);
|
|
958
|
+
if (parsed.schemaVersion !== TYPED_RESOLUTION_SCHEMA_VERSION)
|
|
959
|
+
return null;
|
|
960
|
+
if (!Array.isArray(parsed.resolutions))
|
|
961
|
+
return null;
|
|
962
|
+
const all = parsed.resolutions;
|
|
963
|
+
const valid = all.filter(isValidSidecarEntry);
|
|
964
|
+
if (valid.length === 0 && all.length > 0)
|
|
965
|
+
return null;
|
|
966
|
+
if (valid.length < all.length * 0.5)
|
|
967
|
+
return null;
|
|
968
|
+
return { ...parsed, resolutions: valid };
|
|
969
|
+
} catch {
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
var SWEEP_MAX_AGE_MS, SWEEP_KEEP_MIN;
|
|
974
|
+
var init_sidecar_cache = __esm({
|
|
975
|
+
"../listener/dist/typed-resolution/sidecar-cache.js"() {
|
|
976
|
+
"use strict";
|
|
977
|
+
init_config_dir();
|
|
978
|
+
init_src();
|
|
979
|
+
SWEEP_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
980
|
+
SWEEP_KEEP_MIN = 5;
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
// ../listener/dist/typed-resolution/sidecar-client.js
|
|
985
|
+
var sidecar_client_exports = {};
|
|
986
|
+
__export(sidecar_client_exports, {
|
|
987
|
+
buildSidecar: () => buildSidecar,
|
|
988
|
+
buildSidecarIndex: () => buildSidecarIndex,
|
|
989
|
+
downloadMergedSidecar: () => downloadMergedSidecar,
|
|
990
|
+
overlayMergedSidecar: () => overlayMergedSidecar,
|
|
991
|
+
uploadSidecar: () => uploadSidecar
|
|
992
|
+
});
|
|
993
|
+
async function uploadSidecar(req, fetchImpl = fetch) {
|
|
994
|
+
const url = `${req.apiUrl.replace(/\/$/, "")}/v1/repos/${encodeURIComponent(req.repoId)}/typed-resolution`;
|
|
995
|
+
const body = JSON.stringify({ ...req.sidecar, commitSha: req.commitSha });
|
|
996
|
+
const byteLength = Buffer.byteLength(body, "utf8");
|
|
997
|
+
if (byteLength > UPLOAD_BODY_BYTE_LIMIT) {
|
|
998
|
+
const msg = `sidecar body too large to upload (${byteLength.toString()} bytes > ${UPLOAD_BODY_BYTE_LIMIT.toString()} byte cap); skipping`;
|
|
999
|
+
console.warn(`[typed-resolution] ${msg}`);
|
|
1000
|
+
return {
|
|
1001
|
+
uploaded: false,
|
|
1002
|
+
resolutionCount: req.sidecar.resolutions.length,
|
|
1003
|
+
uploadKey: "",
|
|
1004
|
+
error: msg
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
const res = await fetchImpl(url, {
|
|
1008
|
+
method: "POST",
|
|
1009
|
+
headers: {
|
|
1010
|
+
"content-type": "application/json",
|
|
1011
|
+
authorization: `Bearer ${req.authToken}`
|
|
1012
|
+
},
|
|
1013
|
+
body
|
|
1014
|
+
});
|
|
1015
|
+
if (!res.ok) {
|
|
1016
|
+
const text = await res.text().catch(() => "");
|
|
1017
|
+
throw new Error(`upload failed: HTTP ${res.status.toString()} ${text}`);
|
|
1018
|
+
}
|
|
1019
|
+
const payload = await res.json();
|
|
1020
|
+
if (!payload.data)
|
|
1021
|
+
throw new Error("upload response missing `data`");
|
|
1022
|
+
return payload.data;
|
|
1023
|
+
}
|
|
1024
|
+
async function downloadMergedSidecar(req, fetchImpl = fetch) {
|
|
1025
|
+
const url = `${req.apiUrl.replace(/\/$/, "")}/v1/repos/${encodeURIComponent(req.repoId)}/typed-resolution/${encodeURIComponent(req.commitSha)}`;
|
|
1026
|
+
const res = await fetchImpl(url, {
|
|
1027
|
+
method: "GET",
|
|
1028
|
+
headers: { authorization: `Bearer ${req.authToken}` }
|
|
1029
|
+
});
|
|
1030
|
+
if (res.status === 404)
|
|
1031
|
+
return null;
|
|
1032
|
+
if (!res.ok) {
|
|
1033
|
+
throw new Error(`download failed: HTTP ${res.status.toString()}`);
|
|
1034
|
+
}
|
|
1035
|
+
const body = await res.json();
|
|
1036
|
+
if (body.schemaVersion !== TYPED_RESOLUTION_SCHEMA_VERSION)
|
|
1037
|
+
return null;
|
|
1038
|
+
if (!Array.isArray(body.resolutions))
|
|
1039
|
+
return null;
|
|
1040
|
+
return body;
|
|
1041
|
+
}
|
|
1042
|
+
function buildSidecarIndex(sidecar) {
|
|
1043
|
+
const map = /* @__PURE__ */ new Map();
|
|
1044
|
+
if (!sidecar)
|
|
1045
|
+
return map;
|
|
1046
|
+
for (const r of sidecar.resolutions) {
|
|
1047
|
+
map.set(typedResolutionKey(r.filePath, r.propertyName, r.line, r.column), r);
|
|
1048
|
+
}
|
|
1049
|
+
return map;
|
|
1050
|
+
}
|
|
1051
|
+
function overlayMergedSidecar(edges, sidecar) {
|
|
1052
|
+
let edgesUpgraded = 0;
|
|
1053
|
+
let edgesUnchanged = 0;
|
|
1054
|
+
const index = buildSidecarIndex(sidecar);
|
|
1055
|
+
for (const edge of edges) {
|
|
1056
|
+
if (!edge.filePath || !edge.propertyName || !edge.location || edge.resolution === "typed") {
|
|
1057
|
+
edgesUnchanged += 1;
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
const key = typedResolutionKey(edge.filePath, edge.propertyName, edge.location.line, edge.location.column);
|
|
1061
|
+
const hit = index.get(key);
|
|
1062
|
+
if (!hit || hit.targetSymbolId === null) {
|
|
1063
|
+
edgesUnchanged += 1;
|
|
1064
|
+
continue;
|
|
1065
|
+
}
|
|
1066
|
+
edge.to = hit.targetSymbolId;
|
|
1067
|
+
edge.resolution = "typed";
|
|
1068
|
+
edge.confidence = hit.confidence;
|
|
1069
|
+
edgesUpgraded += 1;
|
|
1070
|
+
}
|
|
1071
|
+
return { edgesUpgraded, edgesUnchanged };
|
|
1072
|
+
}
|
|
1073
|
+
async function buildSidecar(req) {
|
|
1074
|
+
const groupKeyFn = req.groupKey ?? (() => "default");
|
|
1075
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1076
|
+
req.receivers.forEach((receiver, index) => {
|
|
1077
|
+
const key = groupKeyFn(receiver) ?? "__default__";
|
|
1078
|
+
let bucket = groups.get(key);
|
|
1079
|
+
if (!bucket) {
|
|
1080
|
+
bucket = [];
|
|
1081
|
+
groups.set(key, bucket);
|
|
1082
|
+
}
|
|
1083
|
+
bucket.push({ index, receiver });
|
|
1084
|
+
});
|
|
1085
|
+
const resolutions = new Array(req.receivers.length);
|
|
1086
|
+
await Promise.all(Array.from(groups.values()).map(async (bucket) => {
|
|
1087
|
+
for (const { index, receiver } of bucket) {
|
|
1088
|
+
let targetSymbolId;
|
|
1089
|
+
try {
|
|
1090
|
+
targetSymbolId = await req.resolve(receiver);
|
|
1091
|
+
} catch (err) {
|
|
1092
|
+
console.warn(`[typed-resolution] resolve failed for ${receiver.filePath}:${receiver.line.toString()}:${receiver.column.toString()} property=${receiver.propertyName} errMsg=${err instanceof Error ? err.message : String(err)}`);
|
|
1093
|
+
targetSymbolId = null;
|
|
1094
|
+
}
|
|
1095
|
+
resolutions[index] = {
|
|
1096
|
+
filePath: receiver.filePath,
|
|
1097
|
+
propertyName: receiver.propertyName,
|
|
1098
|
+
line: receiver.line,
|
|
1099
|
+
column: receiver.column,
|
|
1100
|
+
targetSymbolId,
|
|
1101
|
+
confidence: 0.9
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
}));
|
|
1105
|
+
return {
|
|
1106
|
+
schemaVersion: TYPED_RESOLUTION_SCHEMA_VERSION,
|
|
1107
|
+
producer: req.producer,
|
|
1108
|
+
emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1109
|
+
languages: [...req.languages],
|
|
1110
|
+
resolutions
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
var UPLOAD_BODY_BYTE_LIMIT;
|
|
1114
|
+
var init_sidecar_client = __esm({
|
|
1115
|
+
"../listener/dist/typed-resolution/sidecar-client.js"() {
|
|
1116
|
+
"use strict";
|
|
1117
|
+
init_src();
|
|
1118
|
+
UPLOAD_BODY_BYTE_LIMIT = 8 * 1024 * 1024;
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1116
1122
|
// ../listener/dist/lsp/lsp-tools.js
|
|
1117
1123
|
var lsp_tools_exports = {};
|
|
1118
1124
|
__export(lsp_tools_exports, {
|
|
@@ -1466,13 +1472,13 @@ var init_lsp_tools = __esm({
|
|
|
1466
1472
|
// bin/repowise.ts
|
|
1467
1473
|
import { readFileSync as readFileSync3 } from "fs";
|
|
1468
1474
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
1469
|
-
import { dirname as
|
|
1475
|
+
import { dirname as dirname18, join as join45 } from "path";
|
|
1470
1476
|
import { Command } from "commander";
|
|
1471
1477
|
|
|
1472
1478
|
// ../listener/dist/main.js
|
|
1473
1479
|
init_config_dir();
|
|
1474
|
-
import { readFile as readFile12, writeFile as writeFile14, mkdir as mkdir14 } from "fs/promises";
|
|
1475
|
-
import { join as
|
|
1480
|
+
import { readFile as readFile12, writeFile as writeFile14, mkdir as mkdir14, stat as fsStat } from "fs/promises";
|
|
1481
|
+
import { join as join27, dirname as dirname13 } from "path";
|
|
1476
1482
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1477
1483
|
import lockfile3 from "proper-lockfile";
|
|
1478
1484
|
|
|
@@ -2761,7 +2767,7 @@ async function stopListener() {
|
|
|
2761
2767
|
|
|
2762
2768
|
// ../listener/dist/mcp/bootstrap.js
|
|
2763
2769
|
init_config_dir();
|
|
2764
|
-
import { join as
|
|
2770
|
+
import { join as join18 } from "path";
|
|
2765
2771
|
|
|
2766
2772
|
// ../listener/dist/lsp/workspace-session.js
|
|
2767
2773
|
import { pathToFileURL } from "url";
|
|
@@ -3023,18 +3029,205 @@ var LspClient = class extends EventEmitter {
|
|
|
3023
3029
|
this.respondError(reqId, -32601, `method not found: ${method}`);
|
|
3024
3030
|
return;
|
|
3025
3031
|
}
|
|
3026
|
-
this.emit("request", method, msg["params"], reqId);
|
|
3032
|
+
this.emit("request", method, msg["params"], reqId);
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
failAllPending(err) {
|
|
3036
|
+
for (const pending of this.pending.values()) {
|
|
3037
|
+
if (pending.timer)
|
|
3038
|
+
clearTimeout(pending.timer);
|
|
3039
|
+
pending.reject(err);
|
|
3040
|
+
}
|
|
3041
|
+
this.pending.clear();
|
|
3042
|
+
}
|
|
3043
|
+
};
|
|
3044
|
+
|
|
3045
|
+
// ../listener/dist/lsp/installer.js
|
|
3046
|
+
init_config_dir();
|
|
3047
|
+
init_registry();
|
|
3048
|
+
import { promises as fs } from "fs";
|
|
3049
|
+
import { join as join14, dirname as dirname5 } from "path";
|
|
3050
|
+
import { spawn as spawn3 } from "child_process";
|
|
3051
|
+
function getLspInstallDir() {
|
|
3052
|
+
return join14(getConfigDir(), "lsp-servers");
|
|
3053
|
+
}
|
|
3054
|
+
function getLspBinDir() {
|
|
3055
|
+
return join14(getLspInstallDir(), "node_modules", ".bin");
|
|
3056
|
+
}
|
|
3057
|
+
async function ensureNpmLspInstalled(config2) {
|
|
3058
|
+
if (!config2.npmPackage)
|
|
3059
|
+
return { installed: false, skipped: "no-npm-package" };
|
|
3060
|
+
const installDir = getLspInstallDir();
|
|
3061
|
+
const binPath = join14(installDir, "node_modules", ".bin", config2.command);
|
|
3062
|
+
if (await pathExists(binPath)) {
|
|
3063
|
+
return { installed: false, skipped: "already-present" };
|
|
3064
|
+
}
|
|
3065
|
+
try {
|
|
3066
|
+
await fs.mkdir(installDir, { recursive: true });
|
|
3067
|
+
const pkgJsonPath = join14(installDir, "package.json");
|
|
3068
|
+
if (!await pathExists(pkgJsonPath)) {
|
|
3069
|
+
await fs.writeFile(pkgJsonPath, JSON.stringify({ name: "repowise-lsp-servers", private: true, version: "0.0.0" }, null, 2), "utf-8");
|
|
3070
|
+
}
|
|
3071
|
+
await runNpmInstall(installDir, config2.npmPackage);
|
|
3072
|
+
if (!await pathExists(binPath)) {
|
|
3073
|
+
return {
|
|
3074
|
+
installed: false,
|
|
3075
|
+
error: `npm install completed but ${config2.command} still not at ${binPath}`
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
return { installed: true };
|
|
3079
|
+
} catch (err) {
|
|
3080
|
+
return {
|
|
3081
|
+
installed: false,
|
|
3082
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3083
|
+
};
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
async function resolveNpmCommand() {
|
|
3087
|
+
const nodeDir = dirname5(process.execPath);
|
|
3088
|
+
for (const candidate of [join14(nodeDir, "npm"), join14(nodeDir, "npm.cmd")]) {
|
|
3089
|
+
try {
|
|
3090
|
+
await fs.access(candidate);
|
|
3091
|
+
return candidate;
|
|
3092
|
+
} catch {
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
for (const candidate of ["/opt/homebrew/bin/npm", "/usr/local/bin/npm", "/usr/bin/npm"]) {
|
|
3096
|
+
try {
|
|
3097
|
+
await fs.access(candidate);
|
|
3098
|
+
return candidate;
|
|
3099
|
+
} catch {
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
return "npm";
|
|
3103
|
+
}
|
|
3104
|
+
async function runNpmInstall(cwd, pkg2) {
|
|
3105
|
+
const npmCmd = await resolveNpmCommand();
|
|
3106
|
+
return new Promise((resolve4, reject) => {
|
|
3107
|
+
const child = spawn3(npmCmd, ["install", "--no-audit", "--no-fund", "--silent", pkg2], {
|
|
3108
|
+
cwd,
|
|
3109
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
3110
|
+
env: { ...process.env }
|
|
3111
|
+
});
|
|
3112
|
+
let stderr = "";
|
|
3113
|
+
child.stderr.on("data", (chunk) => {
|
|
3114
|
+
stderr += chunk.toString();
|
|
3115
|
+
});
|
|
3116
|
+
child.on("error", (err) => reject(err));
|
|
3117
|
+
child.on("close", (code) => {
|
|
3118
|
+
if (code === 0) {
|
|
3119
|
+
resolve4();
|
|
3120
|
+
} else {
|
|
3121
|
+
reject(new Error(`npm install ${pkg2} exited ${(code ?? -1).toString()}: ${sanitizeNpmStderr(stderr)}`));
|
|
3122
|
+
}
|
|
3123
|
+
});
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3126
|
+
function sanitizeNpmStderr(raw) {
|
|
3127
|
+
const truncated = raw.split("\n").slice(0, 3).join(" ").trim();
|
|
3128
|
+
return truncated.replace(/(https?:\/\/)[^@\s/]*@/g, (_match, scheme) => `${scheme}<redacted>@`);
|
|
3129
|
+
}
|
|
3130
|
+
async function pathExists(p) {
|
|
3131
|
+
try {
|
|
3132
|
+
await fs.access(p);
|
|
3133
|
+
return true;
|
|
3134
|
+
} catch {
|
|
3135
|
+
return false;
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
async function detectRepoLanguages(repoRoot) {
|
|
3139
|
+
const found = /* @__PURE__ */ new Set();
|
|
3140
|
+
let inspected = 0;
|
|
3141
|
+
const MAX_INSPECT = 200;
|
|
3142
|
+
async function inspect(dir) {
|
|
3143
|
+
if (inspected >= MAX_INSPECT)
|
|
3144
|
+
return;
|
|
3145
|
+
let entries;
|
|
3146
|
+
try {
|
|
3147
|
+
entries = await fs.readdir(dir);
|
|
3148
|
+
} catch {
|
|
3149
|
+
return;
|
|
3150
|
+
}
|
|
3151
|
+
for (const name of entries) {
|
|
3152
|
+
if (inspected >= MAX_INSPECT)
|
|
3153
|
+
return;
|
|
3154
|
+
if (name.startsWith("."))
|
|
3155
|
+
continue;
|
|
3156
|
+
if (name === "node_modules" || name === "dist" || name === "build")
|
|
3157
|
+
continue;
|
|
3158
|
+
const lang = detectLanguage(name);
|
|
3159
|
+
if (lang) {
|
|
3160
|
+
found.add(lang);
|
|
3161
|
+
inspected += 1;
|
|
3162
|
+
}
|
|
3027
3163
|
}
|
|
3028
3164
|
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3165
|
+
await inspect(repoRoot);
|
|
3166
|
+
let topEntries = [];
|
|
3167
|
+
try {
|
|
3168
|
+
topEntries = await fs.readdir(repoRoot);
|
|
3169
|
+
} catch {
|
|
3170
|
+
return found;
|
|
3171
|
+
}
|
|
3172
|
+
for (const name of topEntries) {
|
|
3173
|
+
if (name.startsWith("."))
|
|
3174
|
+
continue;
|
|
3175
|
+
if (name === "node_modules" || name === "dist" || name === "build")
|
|
3176
|
+
continue;
|
|
3177
|
+
const sub = join14(repoRoot, name);
|
|
3178
|
+
try {
|
|
3179
|
+
const stat7 = await fs.stat(sub);
|
|
3180
|
+
if (stat7.isDirectory())
|
|
3181
|
+
await inspect(sub);
|
|
3182
|
+
} catch {
|
|
3034
3183
|
}
|
|
3035
|
-
this.pending.clear();
|
|
3036
3184
|
}
|
|
3037
|
-
|
|
3185
|
+
return found;
|
|
3186
|
+
}
|
|
3187
|
+
async function prepareLspServersForRepos(repos) {
|
|
3188
|
+
const detected = /* @__PURE__ */ new Set();
|
|
3189
|
+
for (const r of repos) {
|
|
3190
|
+
if (!r.localPath)
|
|
3191
|
+
continue;
|
|
3192
|
+
try {
|
|
3193
|
+
const stat7 = await fs.stat(r.localPath);
|
|
3194
|
+
if (!stat7.isDirectory())
|
|
3195
|
+
continue;
|
|
3196
|
+
} catch {
|
|
3197
|
+
continue;
|
|
3198
|
+
}
|
|
3199
|
+
try {
|
|
3200
|
+
const langs = await detectRepoLanguages(r.localPath);
|
|
3201
|
+
for (const l of langs)
|
|
3202
|
+
detected.add(l);
|
|
3203
|
+
} catch {
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
const results = [];
|
|
3207
|
+
for (const language of detected) {
|
|
3208
|
+
const configs = LSP_REGISTRY[language];
|
|
3209
|
+
const npmConfig = configs.find((c) => c.npmPackage);
|
|
3210
|
+
if (!npmConfig) {
|
|
3211
|
+
results.push({
|
|
3212
|
+
language,
|
|
3213
|
+
installed: false,
|
|
3214
|
+
alreadyPresent: false,
|
|
3215
|
+
skippedNoNpmPackage: true,
|
|
3216
|
+
hint: configs[0]?.installHint
|
|
3217
|
+
});
|
|
3218
|
+
continue;
|
|
3219
|
+
}
|
|
3220
|
+
const outcome = await ensureNpmLspInstalled(npmConfig);
|
|
3221
|
+
results.push({
|
|
3222
|
+
language,
|
|
3223
|
+
installed: outcome.installed,
|
|
3224
|
+
alreadyPresent: outcome.skipped === "already-present",
|
|
3225
|
+
skippedNoNpmPackage: false,
|
|
3226
|
+
error: outcome.error
|
|
3227
|
+
});
|
|
3228
|
+
}
|
|
3229
|
+
return results;
|
|
3230
|
+
}
|
|
3038
3231
|
|
|
3039
3232
|
// ../listener/dist/lsp/workspace-session.js
|
|
3040
3233
|
function keyOf(args) {
|
|
@@ -3050,10 +3243,14 @@ var WorkspaceManager = class {
|
|
|
3050
3243
|
this.idleTimeoutMs = opts.idleTimeoutMs ?? 10 * 60 * 1e3;
|
|
3051
3244
|
this.maxSessions = opts.maxSessions ?? 32;
|
|
3052
3245
|
this.clientFactory = opts.clientFactory ?? ((config2, cwd) => {
|
|
3246
|
+
const env = { ...process.env };
|
|
3247
|
+
const lspBin = getLspBinDir();
|
|
3248
|
+
env.PATH = env.PATH ? `${env.PATH}:${lspBin}` : lspBin;
|
|
3053
3249
|
const client = new LspClient({
|
|
3054
3250
|
command: config2.command,
|
|
3055
3251
|
args: config2.args,
|
|
3056
|
-
cwd
|
|
3252
|
+
cwd,
|
|
3253
|
+
env
|
|
3057
3254
|
});
|
|
3058
3255
|
client.on("stderr", (line) => {
|
|
3059
3256
|
process.stderr.write(`[lsp:${config2.id}] ${line}`);
|
|
@@ -3381,7 +3578,7 @@ var PathEscapeError = class extends Error {
|
|
|
3381
3578
|
// ../listener/dist/mcp/graph-cache.js
|
|
3382
3579
|
init_config_dir();
|
|
3383
3580
|
import { readFile as readFile8, stat as stat3 } from "fs/promises";
|
|
3384
|
-
import { join as
|
|
3581
|
+
import { join as join16 } from "path";
|
|
3385
3582
|
var EVICT_DEBOUNCE_MS = 6e4;
|
|
3386
3583
|
function assertSafeRepoId(repoId) {
|
|
3387
3584
|
if (!repoId || typeof repoId !== "string") {
|
|
@@ -3396,7 +3593,7 @@ function assertSafeRepoId(repoId) {
|
|
|
3396
3593
|
}
|
|
3397
3594
|
function createGraphCache(options = {}) {
|
|
3398
3595
|
const evictMs = options.evictDebounceMs ?? EVICT_DEBOUNCE_MS;
|
|
3399
|
-
const resolvePath = options.resolveGraphPath ?? ((repoId) =>
|
|
3596
|
+
const resolvePath = options.resolveGraphPath ?? ((repoId) => join16(defaultRepoWiseHome(), "graphs", `${repoId}.json`));
|
|
3400
3597
|
const entries = /* @__PURE__ */ new Map();
|
|
3401
3598
|
const inFlight = /* @__PURE__ */ new Map();
|
|
3402
3599
|
async function loadFromDisk(repoId) {
|
|
@@ -3490,7 +3687,7 @@ function defaultRepoWiseHome() {
|
|
|
3490
3687
|
|
|
3491
3688
|
// ../listener/dist/mcp/graph-downloader.js
|
|
3492
3689
|
import { mkdir as mkdir9, rename as rename3, writeFile as writeFile9 } from "fs/promises";
|
|
3493
|
-
import { dirname as
|
|
3690
|
+
import { dirname as dirname7 } from "path";
|
|
3494
3691
|
function createGraphDownloader(options) {
|
|
3495
3692
|
const fetchFn = options.fetchImpl ?? fetch;
|
|
3496
3693
|
let lastSha = null;
|
|
@@ -3541,7 +3738,7 @@ function createGraphDownloader(options) {
|
|
|
3541
3738
|
message: `graph parse: ${err instanceof Error ? err.message : String(err)}`
|
|
3542
3739
|
};
|
|
3543
3740
|
}
|
|
3544
|
-
await mkdir9(
|
|
3741
|
+
await mkdir9(dirname7(options.targetPath), { recursive: true });
|
|
3545
3742
|
const tmpPath = `${options.targetPath}.${Date.now()}.tmp`;
|
|
3546
3743
|
await writeFile9(tmpPath, body, { encoding: "utf-8", mode: 384 });
|
|
3547
3744
|
await rename3(tmpPath, options.targetPath);
|
|
@@ -3567,7 +3764,7 @@ function createGraphDownloader(options) {
|
|
|
3567
3764
|
// ../listener/dist/mcp/log-encryption.js
|
|
3568
3765
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
3569
3766
|
import { mkdir as mkdir10, readFile as readFile9, stat as stat4, writeFile as writeFile10 } from "fs/promises";
|
|
3570
|
-
import { dirname as
|
|
3767
|
+
import { dirname as dirname8 } from "path";
|
|
3571
3768
|
var KEY_BYTES = 32;
|
|
3572
3769
|
var IV_BYTES = 12;
|
|
3573
3770
|
var TAG_BYTES = 16;
|
|
@@ -3614,7 +3811,7 @@ function createFileKeyStore(keyPath) {
|
|
|
3614
3811
|
return parsed;
|
|
3615
3812
|
}
|
|
3616
3813
|
const fresh = randomBytes(KEY_BYTES);
|
|
3617
|
-
await mkdir10(
|
|
3814
|
+
await mkdir10(dirname8(keyPath), { recursive: true });
|
|
3618
3815
|
const tmp = `${keyPath}.tmp`;
|
|
3619
3816
|
await writeFile10(tmp, fresh.toString("base64") + "\n", {
|
|
3620
3817
|
encoding: "utf-8",
|
|
@@ -3656,7 +3853,7 @@ function decryptLine(encoded, key) {
|
|
|
3656
3853
|
|
|
3657
3854
|
// ../listener/dist/mcp/mcp-logger.js
|
|
3658
3855
|
import { appendFile, mkdir as mkdir11, stat as stat5, unlink as unlink8, writeFile as writeFile11, readFile as readFile10 } from "fs/promises";
|
|
3659
|
-
import { dirname as
|
|
3856
|
+
import { dirname as dirname9 } from "path";
|
|
3660
3857
|
var DEFAULT_MAX_BYTES = 100 * 1024 * 1024;
|
|
3661
3858
|
function createMcpLogger(options) {
|
|
3662
3859
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
@@ -3679,7 +3876,7 @@ function createMcpLogger(options) {
|
|
|
3679
3876
|
await migrateLegacyPlaintext();
|
|
3680
3877
|
const key = await options.keyStore.getKey();
|
|
3681
3878
|
const encoded = encryptLine(JSON.stringify(entry), key) + "\n";
|
|
3682
|
-
await mkdir11(
|
|
3879
|
+
await mkdir11(dirname9(options.filePath), { recursive: true });
|
|
3683
3880
|
await appendFile(options.filePath, encoded, { encoding: "utf-8", mode: 384 });
|
|
3684
3881
|
try {
|
|
3685
3882
|
const s = await stat5(options.filePath);
|
|
@@ -3713,7 +3910,7 @@ async function rotate(path, size) {
|
|
|
3713
3910
|
// ../listener/dist/mcp/mcp-log-uploader.js
|
|
3714
3911
|
import { randomUUID } from "crypto";
|
|
3715
3912
|
import { readFile as readFile11, writeFile as writeFile12, mkdir as mkdir12 } from "fs/promises";
|
|
3716
|
-
import { dirname as
|
|
3913
|
+
import { dirname as dirname10 } from "path";
|
|
3717
3914
|
var DEFAULT_MAX_ENTRIES = 5e3;
|
|
3718
3915
|
var DEFAULT_MAX_BYTES2 = 1 * 1024 * 1024;
|
|
3719
3916
|
function createMcpLogUploader(options) {
|
|
@@ -3863,7 +4060,7 @@ async function readPendingBatch(watermarkPath) {
|
|
|
3863
4060
|
}
|
|
3864
4061
|
}
|
|
3865
4062
|
async function writePendingBatch(watermarkPath, batchId) {
|
|
3866
|
-
await mkdir12(
|
|
4063
|
+
await mkdir12(dirname10(watermarkPath), { recursive: true });
|
|
3867
4064
|
await writeFile12(pendingPath(watermarkPath), batchId, { encoding: "utf-8", mode: 384 });
|
|
3868
4065
|
}
|
|
3869
4066
|
async function clearPendingBatch(watermarkPath) {
|
|
@@ -3885,7 +4082,7 @@ async function readWatermark(path) {
|
|
|
3885
4082
|
}
|
|
3886
4083
|
}
|
|
3887
4084
|
async function writeWatermark(path, offset) {
|
|
3888
|
-
await mkdir12(
|
|
4085
|
+
await mkdir12(dirname10(path), { recursive: true });
|
|
3889
4086
|
const tmp = `${path}.tmp`;
|
|
3890
4087
|
await writeFile12(tmp, offset.toString() + "\n", { encoding: "utf-8", mode: 384 });
|
|
3891
4088
|
const { rename: rename5 } = await import("fs/promises");
|
|
@@ -3905,7 +4102,7 @@ async function isLocallyConsented(flagPath2) {
|
|
|
3905
4102
|
init_config_dir();
|
|
3906
4103
|
import { createServer } from "http";
|
|
3907
4104
|
import { mkdir as mkdir13, writeFile as writeFile13 } from "fs/promises";
|
|
3908
|
-
import { dirname as
|
|
4105
|
+
import { dirname as dirname11, join as join17 } from "path";
|
|
3909
4106
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
3910
4107
|
|
|
3911
4108
|
// ../listener/dist/mcp/sanitize.js
|
|
@@ -5244,7 +5441,7 @@ async function readJson(req) {
|
|
|
5244
5441
|
}
|
|
5245
5442
|
}
|
|
5246
5443
|
async function writeEndpointFile(path, endpoint, secret) {
|
|
5247
|
-
await mkdir13(
|
|
5444
|
+
await mkdir13(dirname11(path), { recursive: true });
|
|
5248
5445
|
await writeFile13(path, formatEndpointFile({ endpoint, secret }), {
|
|
5249
5446
|
encoding: "utf-8",
|
|
5250
5447
|
mode: 384
|
|
@@ -5258,7 +5455,7 @@ function extractBearer(header) {
|
|
|
5258
5455
|
return m ? m[1] : null;
|
|
5259
5456
|
}
|
|
5260
5457
|
function defaultEndpointFile() {
|
|
5261
|
-
return
|
|
5458
|
+
return join17(getConfigDir(), "listener.endpoint");
|
|
5262
5459
|
}
|
|
5263
5460
|
|
|
5264
5461
|
// ../listener/dist/mcp/bootstrap.js
|
|
@@ -5266,7 +5463,7 @@ async function startMcp(options) {
|
|
|
5266
5463
|
const disabled = process.env.REPOWISE_MCP_DISABLED === "true";
|
|
5267
5464
|
const graphsDir = options.graphsDir ?? defaultGraphsDir();
|
|
5268
5465
|
const graphCache = createGraphCache({
|
|
5269
|
-
resolveGraphPath: (repoId) =>
|
|
5466
|
+
resolveGraphPath: (repoId) => join18(graphsDir, `${repoId}.json`)
|
|
5270
5467
|
});
|
|
5271
5468
|
if (disabled) {
|
|
5272
5469
|
return {
|
|
@@ -5289,11 +5486,11 @@ async function startMcp(options) {
|
|
|
5289
5486
|
}
|
|
5290
5487
|
const firstRepoLocal = options.repos.find((r) => r.localPath)?.localPath;
|
|
5291
5488
|
const mcpHome = defaultMcpHome();
|
|
5292
|
-
const logFilePath =
|
|
5293
|
-
const keyStore = createFileKeyStore(
|
|
5489
|
+
const logFilePath = join18(mcpHome, "mcp-log.jsonl.enc");
|
|
5490
|
+
const keyStore = createFileKeyStore(join18(mcpHome, "mcp-log.key"));
|
|
5294
5491
|
const mcpLogger = createMcpLogger({ filePath: logFilePath, keyStore });
|
|
5295
|
-
const flagFilePath =
|
|
5296
|
-
const watermarkFilePath =
|
|
5492
|
+
const flagFilePath = join18(mcpHome, "mcp-log.flag");
|
|
5493
|
+
const watermarkFilePath = join18(mcpHome, "mcp-log.watermark");
|
|
5297
5494
|
let uploader = null;
|
|
5298
5495
|
let lastConsentState = false;
|
|
5299
5496
|
function ensureUploader() {
|
|
@@ -5337,7 +5534,7 @@ async function startMcp(options) {
|
|
|
5337
5534
|
apiBaseUrl: repo.apiUrl,
|
|
5338
5535
|
getAuthToken: options.getAuthToken,
|
|
5339
5536
|
repoId: repo.repoId,
|
|
5340
|
-
targetPath:
|
|
5537
|
+
targetPath: join18(graphsDir, `${repo.repoId}.json`),
|
|
5341
5538
|
graphCache,
|
|
5342
5539
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
5343
5540
|
}));
|
|
@@ -5413,7 +5610,7 @@ async function startMcp(options) {
|
|
|
5413
5610
|
apiBaseUrl: repo.apiUrl,
|
|
5414
5611
|
getAuthToken: options.getAuthToken,
|
|
5415
5612
|
repoId: repo.repoId,
|
|
5416
|
-
targetPath:
|
|
5613
|
+
targetPath: join18(graphsDir, `${repo.repoId}.json`),
|
|
5417
5614
|
graphCache,
|
|
5418
5615
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
5419
5616
|
}));
|
|
@@ -5434,12 +5631,389 @@ async function startMcp(options) {
|
|
|
5434
5631
|
};
|
|
5435
5632
|
}
|
|
5436
5633
|
function defaultGraphsDir() {
|
|
5437
|
-
return
|
|
5634
|
+
return join18(getConfigDir(), "graphs");
|
|
5438
5635
|
}
|
|
5439
5636
|
function defaultMcpHome() {
|
|
5440
5637
|
return getConfigDir();
|
|
5441
5638
|
}
|
|
5442
5639
|
|
|
5640
|
+
// ../listener/dist/mcp/auto-config/index.js
|
|
5641
|
+
import { homedir as homedir4 } from "os";
|
|
5642
|
+
|
|
5643
|
+
// ../listener/dist/mcp/auto-config/writers/claude-code.js
|
|
5644
|
+
import { promises as fs3 } from "fs";
|
|
5645
|
+
import { join as join19 } from "path";
|
|
5646
|
+
|
|
5647
|
+
// ../listener/dist/mcp/auto-config/markers.js
|
|
5648
|
+
import { promises as fs2 } from "fs";
|
|
5649
|
+
import { dirname as dirname12 } from "path";
|
|
5650
|
+
async function writeMergedConfig(params) {
|
|
5651
|
+
const current = await readConfig(params.path);
|
|
5652
|
+
const servers = { ...current.mcpServers ?? {} };
|
|
5653
|
+
servers[params.serverName] = params.spec;
|
|
5654
|
+
const next = { ...current, mcpServers: servers };
|
|
5655
|
+
const canonical = canonicalize(next);
|
|
5656
|
+
const existing = safeExistingContent(params.path, current);
|
|
5657
|
+
if (existing === canonical)
|
|
5658
|
+
return "unchanged";
|
|
5659
|
+
await fs2.mkdir(dirname12(params.path), { recursive: true });
|
|
5660
|
+
await fs2.writeFile(params.path, canonical, "utf-8");
|
|
5661
|
+
return "written";
|
|
5662
|
+
}
|
|
5663
|
+
async function removeFromConfig(path, serverName) {
|
|
5664
|
+
const current = await readConfig(path);
|
|
5665
|
+
if (!current.mcpServers || !(serverName in current.mcpServers))
|
|
5666
|
+
return;
|
|
5667
|
+
const servers = { ...current.mcpServers };
|
|
5668
|
+
delete servers[serverName];
|
|
5669
|
+
const next = { ...current, mcpServers: servers };
|
|
5670
|
+
if (Object.keys(servers).length === 0) {
|
|
5671
|
+
delete next.mcpServers;
|
|
5672
|
+
}
|
|
5673
|
+
await fs2.writeFile(path, canonicalize(next), "utf-8");
|
|
5674
|
+
}
|
|
5675
|
+
async function readConfig(path) {
|
|
5676
|
+
try {
|
|
5677
|
+
const raw = await fs2.readFile(path, "utf-8");
|
|
5678
|
+
return JSON.parse(raw);
|
|
5679
|
+
} catch (err) {
|
|
5680
|
+
if (err.code === "ENOENT")
|
|
5681
|
+
return {};
|
|
5682
|
+
throw err;
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
function canonicalize(config2) {
|
|
5686
|
+
const serversSorted = {};
|
|
5687
|
+
if (config2.mcpServers) {
|
|
5688
|
+
const keys = Object.keys(config2.mcpServers).sort();
|
|
5689
|
+
for (const k of keys)
|
|
5690
|
+
serversSorted[k] = normalizeSpec(config2.mcpServers[k]);
|
|
5691
|
+
}
|
|
5692
|
+
const top = {};
|
|
5693
|
+
const otherKeys = Object.keys(config2).filter((k) => k !== "mcpServers").sort();
|
|
5694
|
+
for (const k of otherKeys)
|
|
5695
|
+
top[k] = config2[k];
|
|
5696
|
+
if (Object.keys(serversSorted).length > 0)
|
|
5697
|
+
top.mcpServers = serversSorted;
|
|
5698
|
+
return JSON.stringify(top, null, 2) + "\n";
|
|
5699
|
+
}
|
|
5700
|
+
function normalizeSpec(spec) {
|
|
5701
|
+
const out = { command: spec.command };
|
|
5702
|
+
if (spec.args && spec.args.length > 0)
|
|
5703
|
+
out.args = [...spec.args];
|
|
5704
|
+
if (spec.env && Object.keys(spec.env).length > 0) {
|
|
5705
|
+
const sorted = {};
|
|
5706
|
+
for (const k of Object.keys(spec.env).sort())
|
|
5707
|
+
sorted[k] = spec.env[k];
|
|
5708
|
+
out.env = sorted;
|
|
5709
|
+
}
|
|
5710
|
+
return out;
|
|
5711
|
+
}
|
|
5712
|
+
function safeExistingContent(path, current) {
|
|
5713
|
+
try {
|
|
5714
|
+
return canonicalize(current);
|
|
5715
|
+
} catch {
|
|
5716
|
+
return null;
|
|
5717
|
+
}
|
|
5718
|
+
void path;
|
|
5719
|
+
}
|
|
5720
|
+
|
|
5721
|
+
// ../listener/dist/mcp/auto-config/writers/claude-code.js
|
|
5722
|
+
var claudeCodeWriter = {
|
|
5723
|
+
tool: "claude-code",
|
|
5724
|
+
async detect(repoRoot, home) {
|
|
5725
|
+
return await fileExists2(join19(repoRoot, "CLAUDE.md")) || await hasClaudeBinary(home);
|
|
5726
|
+
},
|
|
5727
|
+
async write(ctx) {
|
|
5728
|
+
const path = join19(ctx.repoRoot, ".mcp.json");
|
|
5729
|
+
const status2 = await writeMergedConfig({
|
|
5730
|
+
path,
|
|
5731
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5732
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5733
|
+
});
|
|
5734
|
+
return { status: status2, path };
|
|
5735
|
+
},
|
|
5736
|
+
async remove(ctx) {
|
|
5737
|
+
await removeFromConfig(join19(ctx.repoRoot, ".mcp.json"), `repowise-${ctx.repoId}`);
|
|
5738
|
+
}
|
|
5739
|
+
};
|
|
5740
|
+
async function fileExists2(path) {
|
|
5741
|
+
try {
|
|
5742
|
+
await fs3.access(path);
|
|
5743
|
+
return true;
|
|
5744
|
+
} catch {
|
|
5745
|
+
return false;
|
|
5746
|
+
}
|
|
5747
|
+
}
|
|
5748
|
+
async function hasClaudeBinary(home) {
|
|
5749
|
+
return fileExists2(join19(home, ".claude", "claude.json"));
|
|
5750
|
+
}
|
|
5751
|
+
|
|
5752
|
+
// ../listener/dist/mcp/auto-config/writers/cline.js
|
|
5753
|
+
import { promises as fs4 } from "fs";
|
|
5754
|
+
import { join as join20 } from "path";
|
|
5755
|
+
var clineWriter = {
|
|
5756
|
+
tool: "cline",
|
|
5757
|
+
async detect(repoRoot, home) {
|
|
5758
|
+
return await fileExists3(join20(repoRoot, ".clinerules")) || await fileExists3(join20(home, ".cline"));
|
|
5759
|
+
},
|
|
5760
|
+
async write(ctx) {
|
|
5761
|
+
const path = join20(ctx.home, ".cline", "mcp.json");
|
|
5762
|
+
const status2 = await writeMergedConfig({
|
|
5763
|
+
path,
|
|
5764
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5765
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5766
|
+
});
|
|
5767
|
+
return { status: status2, path };
|
|
5768
|
+
},
|
|
5769
|
+
async remove(ctx) {
|
|
5770
|
+
await removeFromConfig(join20(ctx.home, ".cline", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5771
|
+
}
|
|
5772
|
+
};
|
|
5773
|
+
async function fileExists3(path) {
|
|
5774
|
+
try {
|
|
5775
|
+
await fs4.access(path);
|
|
5776
|
+
return true;
|
|
5777
|
+
} catch {
|
|
5778
|
+
return false;
|
|
5779
|
+
}
|
|
5780
|
+
}
|
|
5781
|
+
|
|
5782
|
+
// ../listener/dist/mcp/auto-config/writers/codex.js
|
|
5783
|
+
import { promises as fs5 } from "fs";
|
|
5784
|
+
import { join as join21 } from "path";
|
|
5785
|
+
var codexWriter = {
|
|
5786
|
+
tool: "codex",
|
|
5787
|
+
async detect(_repoRoot, home) {
|
|
5788
|
+
return fileExists4(join21(home, ".codex"));
|
|
5789
|
+
},
|
|
5790
|
+
async write(ctx) {
|
|
5791
|
+
const path = join21(ctx.home, ".codex", "mcp.json");
|
|
5792
|
+
const status2 = await writeMergedConfig({
|
|
5793
|
+
path,
|
|
5794
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5795
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5796
|
+
});
|
|
5797
|
+
return { status: status2, path };
|
|
5798
|
+
},
|
|
5799
|
+
async remove(ctx) {
|
|
5800
|
+
await removeFromConfig(join21(ctx.home, ".codex", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5801
|
+
}
|
|
5802
|
+
};
|
|
5803
|
+
async function fileExists4(path) {
|
|
5804
|
+
try {
|
|
5805
|
+
await fs5.access(path);
|
|
5806
|
+
return true;
|
|
5807
|
+
} catch {
|
|
5808
|
+
return false;
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
|
|
5812
|
+
// ../listener/dist/mcp/auto-config/writers/copilot.js
|
|
5813
|
+
import { promises as fs6 } from "fs";
|
|
5814
|
+
import { join as join22 } from "path";
|
|
5815
|
+
var copilotWriter = {
|
|
5816
|
+
tool: "copilot",
|
|
5817
|
+
async detect(repoRoot) {
|
|
5818
|
+
return fileExists5(join22(repoRoot, ".vscode"));
|
|
5819
|
+
},
|
|
5820
|
+
async write(ctx) {
|
|
5821
|
+
const path = join22(ctx.repoRoot, ".vscode", "mcp.json");
|
|
5822
|
+
const status2 = await writeMergedConfig({
|
|
5823
|
+
path,
|
|
5824
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5825
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5826
|
+
});
|
|
5827
|
+
return { status: status2, path };
|
|
5828
|
+
},
|
|
5829
|
+
async remove(ctx) {
|
|
5830
|
+
await removeFromConfig(join22(ctx.repoRoot, ".vscode", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5831
|
+
}
|
|
5832
|
+
};
|
|
5833
|
+
async function fileExists5(path) {
|
|
5834
|
+
try {
|
|
5835
|
+
await fs6.access(path);
|
|
5836
|
+
return true;
|
|
5837
|
+
} catch {
|
|
5838
|
+
return false;
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5841
|
+
|
|
5842
|
+
// ../listener/dist/mcp/auto-config/writers/cursor.js
|
|
5843
|
+
import { promises as fs7 } from "fs";
|
|
5844
|
+
import { join as join23 } from "path";
|
|
5845
|
+
var cursorWriter = {
|
|
5846
|
+
tool: "cursor",
|
|
5847
|
+
async detect(repoRoot) {
|
|
5848
|
+
return await fileExists6(join23(repoRoot, ".cursor")) || await fileExists6(join23(repoRoot, ".cursorrules"));
|
|
5849
|
+
},
|
|
5850
|
+
async write(ctx) {
|
|
5851
|
+
const path = join23(ctx.repoRoot, ".cursor", "mcp.json");
|
|
5852
|
+
const status2 = await writeMergedConfig({
|
|
5853
|
+
path,
|
|
5854
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5855
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5856
|
+
});
|
|
5857
|
+
return { status: status2, path };
|
|
5858
|
+
},
|
|
5859
|
+
async remove(ctx) {
|
|
5860
|
+
await removeFromConfig(join23(ctx.repoRoot, ".cursor", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5861
|
+
}
|
|
5862
|
+
};
|
|
5863
|
+
async function fileExists6(path) {
|
|
5864
|
+
try {
|
|
5865
|
+
await fs7.access(path);
|
|
5866
|
+
return true;
|
|
5867
|
+
} catch {
|
|
5868
|
+
return false;
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
|
|
5872
|
+
// ../listener/dist/mcp/auto-config/writers/gemini-cli.js
|
|
5873
|
+
import { promises as fs8 } from "fs";
|
|
5874
|
+
import { join as join24 } from "path";
|
|
5875
|
+
var geminiCliWriter = {
|
|
5876
|
+
tool: "gemini-cli",
|
|
5877
|
+
async detect(_repoRoot, home) {
|
|
5878
|
+
return fileExists7(join24(home, ".gemini"));
|
|
5879
|
+
},
|
|
5880
|
+
async write(ctx) {
|
|
5881
|
+
const path = join24(ctx.home, ".gemini", "settings.json");
|
|
5882
|
+
const status2 = await writeMergedConfig({
|
|
5883
|
+
path,
|
|
5884
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5885
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5886
|
+
});
|
|
5887
|
+
return { status: status2, path };
|
|
5888
|
+
},
|
|
5889
|
+
async remove(ctx) {
|
|
5890
|
+
await removeFromConfig(join24(ctx.home, ".gemini", "settings.json"), `repowise-${ctx.repoId}`);
|
|
5891
|
+
}
|
|
5892
|
+
};
|
|
5893
|
+
async function fileExists7(path) {
|
|
5894
|
+
try {
|
|
5895
|
+
await fs8.access(path);
|
|
5896
|
+
return true;
|
|
5897
|
+
} catch {
|
|
5898
|
+
return false;
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5901
|
+
|
|
5902
|
+
// ../listener/dist/mcp/auto-config/writers/roo.js
|
|
5903
|
+
import { promises as fs9 } from "fs";
|
|
5904
|
+
import { join as join25 } from "path";
|
|
5905
|
+
var rooWriter = {
|
|
5906
|
+
tool: "roo",
|
|
5907
|
+
async detect(repoRoot, home) {
|
|
5908
|
+
return await fileExists8(join25(repoRoot, ".roo")) || await fileExists8(join25(home, ".roo"));
|
|
5909
|
+
},
|
|
5910
|
+
async write(ctx) {
|
|
5911
|
+
const repoConfig = join25(ctx.repoRoot, ".roo", "mcp.json");
|
|
5912
|
+
const useRepoScope = await fileExists8(join25(ctx.repoRoot, ".roo"));
|
|
5913
|
+
const path = useRepoScope ? repoConfig : join25(ctx.home, ".roo", "mcp.json");
|
|
5914
|
+
const status2 = await writeMergedConfig({
|
|
5915
|
+
path,
|
|
5916
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5917
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5918
|
+
});
|
|
5919
|
+
return { status: status2, path };
|
|
5920
|
+
},
|
|
5921
|
+
async remove(ctx) {
|
|
5922
|
+
await removeFromConfig(join25(ctx.repoRoot, ".roo", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5923
|
+
await removeFromConfig(join25(ctx.home, ".roo", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5924
|
+
}
|
|
5925
|
+
};
|
|
5926
|
+
async function fileExists8(path) {
|
|
5927
|
+
try {
|
|
5928
|
+
await fs9.access(path);
|
|
5929
|
+
return true;
|
|
5930
|
+
} catch {
|
|
5931
|
+
return false;
|
|
5932
|
+
}
|
|
5933
|
+
}
|
|
5934
|
+
|
|
5935
|
+
// ../listener/dist/mcp/auto-config/writers/windsurf.js
|
|
5936
|
+
import { promises as fs10 } from "fs";
|
|
5937
|
+
import { join as join26 } from "path";
|
|
5938
|
+
var windsurfWriter = {
|
|
5939
|
+
tool: "windsurf",
|
|
5940
|
+
async detect(_repoRoot, home) {
|
|
5941
|
+
return fileExists9(join26(home, ".codeium", "windsurf"));
|
|
5942
|
+
},
|
|
5943
|
+
async write(ctx) {
|
|
5944
|
+
const path = join26(ctx.home, ".codeium", "windsurf", "mcp_config.json");
|
|
5945
|
+
const status2 = await writeMergedConfig({
|
|
5946
|
+
path,
|
|
5947
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5948
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5949
|
+
});
|
|
5950
|
+
return { status: status2, path };
|
|
5951
|
+
},
|
|
5952
|
+
async remove(ctx) {
|
|
5953
|
+
await removeFromConfig(join26(ctx.home, ".codeium", "windsurf", "mcp_config.json"), `repowise-${ctx.repoId}`);
|
|
5954
|
+
}
|
|
5955
|
+
};
|
|
5956
|
+
async function fileExists9(path) {
|
|
5957
|
+
try {
|
|
5958
|
+
await fs10.access(path);
|
|
5959
|
+
return true;
|
|
5960
|
+
} catch {
|
|
5961
|
+
return false;
|
|
5962
|
+
}
|
|
5963
|
+
}
|
|
5964
|
+
|
|
5965
|
+
// ../listener/dist/mcp/auto-config/writers/index.js
|
|
5966
|
+
var WRITERS = [
|
|
5967
|
+
claudeCodeWriter,
|
|
5968
|
+
clineWriter,
|
|
5969
|
+
codexWriter,
|
|
5970
|
+
copilotWriter,
|
|
5971
|
+
cursorWriter,
|
|
5972
|
+
geminiCliWriter,
|
|
5973
|
+
rooWriter,
|
|
5974
|
+
windsurfWriter
|
|
5975
|
+
];
|
|
5976
|
+
|
|
5977
|
+
// ../listener/dist/mcp/auto-config/index.js
|
|
5978
|
+
async function runAutoConfig(opts) {
|
|
5979
|
+
const home = opts.home ?? homedir4();
|
|
5980
|
+
const writers = opts.writers ?? WRITERS;
|
|
5981
|
+
const results = [];
|
|
5982
|
+
for (const writer of writers) {
|
|
5983
|
+
let detected;
|
|
5984
|
+
try {
|
|
5985
|
+
detected = await writer.detect(opts.repoRoot, home);
|
|
5986
|
+
} catch (err) {
|
|
5987
|
+
results.push({
|
|
5988
|
+
tool: writer.tool,
|
|
5989
|
+
detected: false,
|
|
5990
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5991
|
+
});
|
|
5992
|
+
continue;
|
|
5993
|
+
}
|
|
5994
|
+
if (!detected) {
|
|
5995
|
+
results.push({ tool: writer.tool, detected: false });
|
|
5996
|
+
continue;
|
|
5997
|
+
}
|
|
5998
|
+
try {
|
|
5999
|
+
const outcome = await writer.write({
|
|
6000
|
+
repoRoot: opts.repoRoot,
|
|
6001
|
+
repoId: opts.repoId,
|
|
6002
|
+
shimCmd: opts.shimCmd,
|
|
6003
|
+
home
|
|
6004
|
+
});
|
|
6005
|
+
results.push({ tool: writer.tool, detected: true, outcome });
|
|
6006
|
+
} catch (err) {
|
|
6007
|
+
results.push({
|
|
6008
|
+
tool: writer.tool,
|
|
6009
|
+
detected: true,
|
|
6010
|
+
error: err instanceof Error ? err.message : String(err)
|
|
6011
|
+
});
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
return results;
|
|
6015
|
+
}
|
|
6016
|
+
|
|
5443
6017
|
// ../listener/dist/typed-resolution/resolver-loop.js
|
|
5444
6018
|
init_src();
|
|
5445
6019
|
init_registry();
|
|
@@ -5644,7 +6218,7 @@ var CRASH_LOOP_WINDOW_MS = 3e4;
|
|
|
5644
6218
|
var CRASH_LOOP_THRESHOLD = 3;
|
|
5645
6219
|
async function readRawToolConfig() {
|
|
5646
6220
|
try {
|
|
5647
|
-
const configPath =
|
|
6221
|
+
const configPath = join27(getConfigDir(), "config.json");
|
|
5648
6222
|
const data = await readFile12(configPath, "utf-8");
|
|
5649
6223
|
const raw = JSON.parse(data);
|
|
5650
6224
|
return {
|
|
@@ -5705,11 +6279,11 @@ function resolveAuditRoots() {
|
|
|
5705
6279
|
return override.split(":").map((s) => s.trim()).filter(Boolean);
|
|
5706
6280
|
}
|
|
5707
6281
|
const out = /* @__PURE__ */ new Set();
|
|
5708
|
-
let dir =
|
|
6282
|
+
let dir = dirname13(process.execPath);
|
|
5709
6283
|
for (let i = 0; i < 8; i += 1) {
|
|
5710
|
-
out.add(
|
|
5711
|
-
out.add(
|
|
5712
|
-
const parent =
|
|
6284
|
+
out.add(join27(dir, "node_modules"));
|
|
6285
|
+
out.add(join27(dir, "lib", "node_modules"));
|
|
6286
|
+
const parent = dirname13(dir);
|
|
5713
6287
|
if (parent === dir)
|
|
5714
6288
|
break;
|
|
5715
6289
|
dir = parent;
|
|
@@ -5928,7 +6502,7 @@ async function checkStaleContext(repos, state, groups) {
|
|
|
5928
6502
|
if (group?.offline.isOffline)
|
|
5929
6503
|
continue;
|
|
5930
6504
|
const { statSync: statSync2, readdirSync: readdirSync2 } = await import("fs");
|
|
5931
|
-
const contextPath =
|
|
6505
|
+
const contextPath = join27(repo.localPath, "repowise-context");
|
|
5932
6506
|
let isMissingOrEmpty = false;
|
|
5933
6507
|
try {
|
|
5934
6508
|
const s = statSync2(contextPath);
|
|
@@ -5957,9 +6531,36 @@ async function checkStaleContext(repos, state, groups) {
|
|
|
5957
6531
|
}
|
|
5958
6532
|
return dirty;
|
|
5959
6533
|
}
|
|
6534
|
+
async function reconcileMcpConfigs(repos, packageName) {
|
|
6535
|
+
const shimCmd = packageName;
|
|
6536
|
+
for (const repo of repos) {
|
|
6537
|
+
if (!repo.localPath)
|
|
6538
|
+
continue;
|
|
6539
|
+
try {
|
|
6540
|
+
const s = await fsStat(repo.localPath);
|
|
6541
|
+
if (!s.isDirectory())
|
|
6542
|
+
continue;
|
|
6543
|
+
} catch {
|
|
6544
|
+
continue;
|
|
6545
|
+
}
|
|
6546
|
+
try {
|
|
6547
|
+
const results = await runAutoConfig({
|
|
6548
|
+
repoRoot: repo.localPath,
|
|
6549
|
+
repoId: repo.repoId,
|
|
6550
|
+
shimCmd
|
|
6551
|
+
});
|
|
6552
|
+
const written = results.filter((r) => r.detected && r.outcome?.status === "written");
|
|
6553
|
+
if (written.length > 0) {
|
|
6554
|
+
console.log(`[mcp-config] Wrote ${written.length.toString()} config(s) for ${repo.repoId}: ${written.map((r) => `${r.tool}=${r.outcome.path}`).join(", ")}`);
|
|
6555
|
+
}
|
|
6556
|
+
} catch (err) {
|
|
6557
|
+
console.warn(`[mcp-config] Reconcile failed for ${repo.repoId}:`, err instanceof Error ? err.message : String(err));
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
}
|
|
5960
6561
|
async function reconcileAgentInstructions(repos) {
|
|
5961
6562
|
for (const repo of repos) {
|
|
5962
|
-
const path =
|
|
6563
|
+
const path = join27(repo.localPath, "repowise-context", "project-overview.md");
|
|
5963
6564
|
let content;
|
|
5964
6565
|
try {
|
|
5965
6566
|
content = await readFile12(path, "utf-8");
|
|
@@ -6021,7 +6622,7 @@ async function startListener() {
|
|
|
6021
6622
|
}
|
|
6022
6623
|
const configDir = getConfigDir();
|
|
6023
6624
|
await mkdir14(configDir, { recursive: true });
|
|
6024
|
-
const lockPath =
|
|
6625
|
+
const lockPath = join27(configDir, "listener.lock");
|
|
6025
6626
|
await writeFile14(lockPath, "", { flag: "a" });
|
|
6026
6627
|
let lockIsHeld = false;
|
|
6027
6628
|
try {
|
|
@@ -6064,7 +6665,7 @@ async function startListener() {
|
|
|
6064
6665
|
return;
|
|
6065
6666
|
}
|
|
6066
6667
|
if (config2.repos.length === 0 && !config2.autoDiscoverRepos) {
|
|
6067
|
-
console.error(`No repos configured. Add repos to ${
|
|
6668
|
+
console.error(`No repos configured. Add repos to ${join27(configDir, "config.json")}`);
|
|
6068
6669
|
await releaseLockAndExit();
|
|
6069
6670
|
process.exitCode = 1;
|
|
6070
6671
|
return;
|
|
@@ -6131,8 +6732,8 @@ async function startListener() {
|
|
|
6131
6732
|
const packageName = true ? "repowisestage" : "repowise";
|
|
6132
6733
|
let currentVersion = "";
|
|
6133
6734
|
try {
|
|
6134
|
-
const selfDir =
|
|
6135
|
-
const pkgJsonPath =
|
|
6735
|
+
const selfDir = dirname13(fileURLToPath3(import.meta.url));
|
|
6736
|
+
const pkgJsonPath = join27(selfDir, "..", "..", "package.json");
|
|
6136
6737
|
const pkgJson = JSON.parse(await readFile12(pkgJsonPath, "utf-8"));
|
|
6137
6738
|
currentVersion = pkgJson.version;
|
|
6138
6739
|
} catch (err) {
|
|
@@ -6185,6 +6786,29 @@ async function startListener() {
|
|
|
6185
6786
|
} catch (err) {
|
|
6186
6787
|
console.warn("[reconcile] Initial agent instructions reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6187
6788
|
}
|
|
6789
|
+
void (async () => {
|
|
6790
|
+
try {
|
|
6791
|
+
await reconcileMcpConfigs(config2.repos, packageName);
|
|
6792
|
+
} catch (err) {
|
|
6793
|
+
console.warn("[mcp-config] Initial MCP config reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6794
|
+
}
|
|
6795
|
+
})();
|
|
6796
|
+
void (async () => {
|
|
6797
|
+
try {
|
|
6798
|
+
const lspResults = await prepareLspServersForRepos(config2.repos);
|
|
6799
|
+
for (const r of lspResults) {
|
|
6800
|
+
if (r.installed) {
|
|
6801
|
+
console.log(`[lsp-install] Installed ${r.language} LSP server`);
|
|
6802
|
+
} else if (r.skippedNoNpmPackage && r.hint) {
|
|
6803
|
+
console.log(`[lsp-install] ${r.language} LSP not auto-installable. To enable: ${r.hint}`);
|
|
6804
|
+
} else if (r.error) {
|
|
6805
|
+
console.warn(`[lsp-install] ${r.language} install failed: ${r.error}`);
|
|
6806
|
+
}
|
|
6807
|
+
}
|
|
6808
|
+
} catch (err) {
|
|
6809
|
+
console.warn("[lsp-install] Pre-install scan failed:", err instanceof Error ? err.message : String(err));
|
|
6810
|
+
}
|
|
6811
|
+
})();
|
|
6188
6812
|
const typedResolutionHooks = mcpRuntime?.lspWorkspaces ? buildTypedResolutionHooks({
|
|
6189
6813
|
workspaces: mcpRuntime.lspWorkspaces,
|
|
6190
6814
|
graphCache: mcpRuntime.graphCache,
|
|
@@ -6385,6 +7009,11 @@ async function startListener() {
|
|
|
6385
7009
|
} catch (err) {
|
|
6386
7010
|
console.warn("[reconcile] Agent instructions reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6387
7011
|
}
|
|
7012
|
+
try {
|
|
7013
|
+
await reconcileMcpConfigs(config2.repos, packageName);
|
|
7014
|
+
} catch (err) {
|
|
7015
|
+
console.warn("[mcp-config] Reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
7016
|
+
}
|
|
6388
7017
|
}
|
|
6389
7018
|
if (latestCliVersion && currentVersion && !config2.noAutoUpdate && (state.crashCount ?? 0) < CRASH_LOOP_THRESHOLD) {
|
|
6390
7019
|
if (latestCliVersion !== state.lastUpdateTargetVersion) {
|
|
@@ -6448,12 +7077,12 @@ async function startListener() {
|
|
|
6448
7077
|
} catch {
|
|
6449
7078
|
}
|
|
6450
7079
|
}
|
|
6451
|
-
const credentialsPath =
|
|
7080
|
+
const credentialsPath = join27(getConfigDir(), "credentials.json");
|
|
6452
7081
|
let credentialsChanged = false;
|
|
6453
7082
|
let watcher = null;
|
|
6454
7083
|
try {
|
|
6455
|
-
const
|
|
6456
|
-
watcher =
|
|
7084
|
+
const fs18 = await import("fs");
|
|
7085
|
+
watcher = fs18.watch(credentialsPath, () => {
|
|
6457
7086
|
credentialsChanged = true;
|
|
6458
7087
|
});
|
|
6459
7088
|
} catch {
|
|
@@ -6493,8 +7122,8 @@ if (isDirectRun) {
|
|
|
6493
7122
|
}
|
|
6494
7123
|
|
|
6495
7124
|
// src/lib/env.ts
|
|
6496
|
-
import { homedir as
|
|
6497
|
-
import { join as
|
|
7125
|
+
import { homedir as homedir5 } from "os";
|
|
7126
|
+
import { join as join28 } from "path";
|
|
6498
7127
|
var IS_STAGING2 = true ? true : false;
|
|
6499
7128
|
var PRODUCTION = {
|
|
6500
7129
|
apiUrl: "https://api.repowise.ai",
|
|
@@ -6514,7 +7143,7 @@ function getEnvConfig() {
|
|
|
6514
7143
|
return IS_STAGING2 ? STAGING : PRODUCTION;
|
|
6515
7144
|
}
|
|
6516
7145
|
function getConfigDir2() {
|
|
6517
|
-
return
|
|
7146
|
+
return join28(homedir5(), IS_STAGING2 ? ".repowise-staging" : ".repowise");
|
|
6518
7147
|
}
|
|
6519
7148
|
function getPackageName() {
|
|
6520
7149
|
return true ? "repowisestage" : "repowise";
|
|
@@ -6525,11 +7154,11 @@ import chalk from "chalk";
|
|
|
6525
7154
|
|
|
6526
7155
|
// src/lib/config.ts
|
|
6527
7156
|
import { readFile as readFile13, writeFile as writeFile15, mkdir as mkdir15, rename as rename4, unlink as unlink9 } from "fs/promises";
|
|
6528
|
-
import { join as
|
|
7157
|
+
import { join as join29 } from "path";
|
|
6529
7158
|
import lockfile4 from "proper-lockfile";
|
|
6530
7159
|
async function getConfig() {
|
|
6531
7160
|
try {
|
|
6532
|
-
const data = await readFile13(
|
|
7161
|
+
const data = await readFile13(join29(getConfigDir2(), "config.json"), "utf-8");
|
|
6533
7162
|
return JSON.parse(data);
|
|
6534
7163
|
} catch {
|
|
6535
7164
|
return {};
|
|
@@ -6537,7 +7166,7 @@ async function getConfig() {
|
|
|
6537
7166
|
}
|
|
6538
7167
|
async function saveConfig(config2) {
|
|
6539
7168
|
const dir = getConfigDir2();
|
|
6540
|
-
const path =
|
|
7169
|
+
const path = join29(dir, "config.json");
|
|
6541
7170
|
await mkdir15(dir, { recursive: true });
|
|
6542
7171
|
const tmpPath = path + ".tmp";
|
|
6543
7172
|
try {
|
|
@@ -6553,7 +7182,7 @@ async function saveConfig(config2) {
|
|
|
6553
7182
|
}
|
|
6554
7183
|
async function mergeAndSaveConfig(updates) {
|
|
6555
7184
|
const dir = getConfigDir2();
|
|
6556
|
-
const path =
|
|
7185
|
+
const path = join29(dir, "config.json");
|
|
6557
7186
|
await mkdir15(dir, { recursive: true });
|
|
6558
7187
|
try {
|
|
6559
7188
|
await writeFile15(path, "", { flag: "a" });
|
|
@@ -6624,7 +7253,7 @@ async function showWelcome(currentVersion) {
|
|
|
6624
7253
|
|
|
6625
7254
|
// src/commands/create.ts
|
|
6626
7255
|
import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6627
|
-
import { dirname as
|
|
7256
|
+
import { dirname as dirname14, join as join33 } from "path";
|
|
6628
7257
|
init_src();
|
|
6629
7258
|
import chalk5 from "chalk";
|
|
6630
7259
|
import ora from "ora";
|
|
@@ -6633,7 +7262,7 @@ import ora from "ora";
|
|
|
6633
7262
|
import { createHash as createHash3, randomBytes as randomBytes3 } from "crypto";
|
|
6634
7263
|
import { readFile as readFile14, writeFile as writeFile16, mkdir as mkdir16, chmod as chmod4, unlink as unlink10 } from "fs/promises";
|
|
6635
7264
|
import http from "http";
|
|
6636
|
-
import { join as
|
|
7265
|
+
import { join as join30 } from "path";
|
|
6637
7266
|
var CLI_CALLBACK_PORT = 19876;
|
|
6638
7267
|
var CALLBACK_TIMEOUT_MS = 12e4;
|
|
6639
7268
|
function getCognitoConfigForStorage() {
|
|
@@ -6799,7 +7428,7 @@ async function refreshTokens2(refreshToken) {
|
|
|
6799
7428
|
}
|
|
6800
7429
|
async function getStoredCredentials2() {
|
|
6801
7430
|
try {
|
|
6802
|
-
const credPath =
|
|
7431
|
+
const credPath = join30(getConfigDir2(), "credentials.json");
|
|
6803
7432
|
const data = await readFile14(credPath, "utf-8");
|
|
6804
7433
|
return JSON.parse(data);
|
|
6805
7434
|
} catch (err) {
|
|
@@ -6811,14 +7440,14 @@ async function getStoredCredentials2() {
|
|
|
6811
7440
|
}
|
|
6812
7441
|
async function storeCredentials2(credentials) {
|
|
6813
7442
|
const dir = getConfigDir2();
|
|
6814
|
-
const credPath =
|
|
7443
|
+
const credPath = join30(dir, "credentials.json");
|
|
6815
7444
|
await mkdir16(dir, { recursive: true, mode: 448 });
|
|
6816
7445
|
await writeFile16(credPath, JSON.stringify(credentials, null, 2));
|
|
6817
7446
|
await chmod4(credPath, 384);
|
|
6818
7447
|
}
|
|
6819
7448
|
async function clearCredentials() {
|
|
6820
7449
|
try {
|
|
6821
|
-
await unlink10(
|
|
7450
|
+
await unlink10(join30(getConfigDir2(), "credentials.json"));
|
|
6822
7451
|
} catch (err) {
|
|
6823
7452
|
if (err.code !== "ENOENT") throw err;
|
|
6824
7453
|
}
|
|
@@ -7025,10 +7654,10 @@ async function selectAiTools() {
|
|
|
7025
7654
|
|
|
7026
7655
|
// src/lib/ai-tools.ts
|
|
7027
7656
|
import { readFile as readFile15, writeFile as writeFile17, mkdir as mkdir17 } from "fs/promises";
|
|
7028
|
-
import { join as
|
|
7657
|
+
import { join as join31 } from "path";
|
|
7029
7658
|
var REPOWISE_HOOK_MARKER = "repowise-context";
|
|
7030
7659
|
async function writeClaudeSubagentHook(repoRoot, contextFolder) {
|
|
7031
|
-
const settingsPath =
|
|
7660
|
+
const settingsPath = join31(repoRoot, ".claude", "settings.json");
|
|
7032
7661
|
let settings = {};
|
|
7033
7662
|
try {
|
|
7034
7663
|
const raw = await readFile15(settingsPath, "utf-8");
|
|
@@ -7063,15 +7692,15 @@ async function writeClaudeSubagentHook(repoRoot, contextFolder) {
|
|
|
7063
7692
|
}
|
|
7064
7693
|
hooks["SubagentStart"] = subagentStart;
|
|
7065
7694
|
settings["hooks"] = hooks;
|
|
7066
|
-
await mkdir17(
|
|
7695
|
+
await mkdir17(join31(repoRoot, ".claude"), { recursive: true });
|
|
7067
7696
|
await writeFile17(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
7068
7697
|
}
|
|
7069
7698
|
|
|
7070
7699
|
// src/lib/gitignore.ts
|
|
7071
7700
|
import { readFileSync as readFileSync2, writeFileSync, existsSync } from "fs";
|
|
7072
|
-
import { join as
|
|
7701
|
+
import { join as join32 } from "path";
|
|
7073
7702
|
function ensureGitignore(repoRoot, entry) {
|
|
7074
|
-
const gitignorePath =
|
|
7703
|
+
const gitignorePath = join32(repoRoot, ".gitignore");
|
|
7075
7704
|
if (existsSync(gitignorePath)) {
|
|
7076
7705
|
const content = readFileSync2(gitignorePath, "utf-8");
|
|
7077
7706
|
const lines = content.split("\n").map((l) => l.trim());
|
|
@@ -7861,7 +8490,7 @@ async function create() {
|
|
|
7861
8490
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
7862
8491
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
7863
8492
|
if (files.length > 0) {
|
|
7864
|
-
const contextDir =
|
|
8493
|
+
const contextDir = join33(repoRoot, DEFAULT_CONTEXT_FOLDER);
|
|
7865
8494
|
mkdirSync(contextDir, { recursive: true });
|
|
7866
8495
|
let downloadedCount = 0;
|
|
7867
8496
|
let failedCount = 0;
|
|
@@ -7875,8 +8504,8 @@ async function create() {
|
|
|
7875
8504
|
const response = await fetch(presignedUrl);
|
|
7876
8505
|
if (response.ok) {
|
|
7877
8506
|
const content = await response.text();
|
|
7878
|
-
const filePath =
|
|
7879
|
-
mkdirSync(
|
|
8507
|
+
const filePath = join33(contextDir, file.fileName);
|
|
8508
|
+
mkdirSync(dirname14(filePath), { recursive: true });
|
|
7880
8509
|
writeFileSync2(filePath, content, "utf-8");
|
|
7881
8510
|
downloadedCount++;
|
|
7882
8511
|
} else {
|
|
@@ -8017,7 +8646,7 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
8017
8646
|
|
|
8018
8647
|
// src/commands/member.ts
|
|
8019
8648
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
8020
|
-
import { dirname as
|
|
8649
|
+
import { dirname as dirname15, join as join34, resolve, sep } from "path";
|
|
8021
8650
|
import chalk6 from "chalk";
|
|
8022
8651
|
import ora2 from "ora";
|
|
8023
8652
|
var DEFAULT_CONTEXT_FOLDER2 = "repowise-context";
|
|
@@ -8141,7 +8770,7 @@ async function member() {
|
|
|
8141
8770
|
spinner.succeed(`Found ${chalk6.bold(files.length)} context files on server`);
|
|
8142
8771
|
const { tools } = await selectAiTools();
|
|
8143
8772
|
spinner.start("Downloading context files...");
|
|
8144
|
-
const contextDir =
|
|
8773
|
+
const contextDir = join34(repoRoot, DEFAULT_CONTEXT_FOLDER2);
|
|
8145
8774
|
mkdirSync2(contextDir, { recursive: true });
|
|
8146
8775
|
let downloadedCount = 0;
|
|
8147
8776
|
let failedCount = 0;
|
|
@@ -8162,7 +8791,7 @@ async function member() {
|
|
|
8162
8791
|
const response = await fetch(presignedUrl);
|
|
8163
8792
|
if (response.ok) {
|
|
8164
8793
|
const content = await response.text();
|
|
8165
|
-
mkdirSync2(
|
|
8794
|
+
mkdirSync2(dirname15(safePath), { recursive: true });
|
|
8166
8795
|
writeFileSync3(safePath, content, "utf-8");
|
|
8167
8796
|
downloadedCount++;
|
|
8168
8797
|
} else {
|
|
@@ -8286,15 +8915,15 @@ import chalk7 from "chalk";
|
|
|
8286
8915
|
import ora3 from "ora";
|
|
8287
8916
|
|
|
8288
8917
|
// src/lib/tenant-graph-purge.ts
|
|
8289
|
-
import { promises as
|
|
8290
|
-
import { homedir as
|
|
8291
|
-
import { join as
|
|
8292
|
-
async function purgeForeignGraphs(validRepoIds, home =
|
|
8293
|
-
const graphsDir =
|
|
8918
|
+
import { promises as fs11 } from "fs";
|
|
8919
|
+
import { homedir as homedir6 } from "os";
|
|
8920
|
+
import { join as join35 } from "path";
|
|
8921
|
+
async function purgeForeignGraphs(validRepoIds, home = homedir6()) {
|
|
8922
|
+
const graphsDir = join35(home, ".repowise", "graphs");
|
|
8294
8923
|
const result = { kept: [], removed: [] };
|
|
8295
8924
|
let entries;
|
|
8296
8925
|
try {
|
|
8297
|
-
entries = await
|
|
8926
|
+
entries = await fs11.readdir(graphsDir);
|
|
8298
8927
|
} catch (err) {
|
|
8299
8928
|
if (err.code === "ENOENT") return result;
|
|
8300
8929
|
throw err;
|
|
@@ -8308,15 +8937,15 @@ async function purgeForeignGraphs(validRepoIds, home = homedir5()) {
|
|
|
8308
8937
|
result.kept.push(entry);
|
|
8309
8938
|
continue;
|
|
8310
8939
|
}
|
|
8311
|
-
const path =
|
|
8940
|
+
const path = join35(graphsDir, entry);
|
|
8312
8941
|
try {
|
|
8313
|
-
const stat7 = await
|
|
8942
|
+
const stat7 = await fs11.lstat(path);
|
|
8314
8943
|
if (stat7.isSymbolicLink()) {
|
|
8315
|
-
await
|
|
8944
|
+
await fs11.unlink(path);
|
|
8316
8945
|
result.removed.push(entry);
|
|
8317
8946
|
continue;
|
|
8318
8947
|
}
|
|
8319
|
-
await
|
|
8948
|
+
await fs11.rm(path, { recursive: true, force: true });
|
|
8320
8949
|
result.removed.push(entry);
|
|
8321
8950
|
} catch {
|
|
8322
8951
|
}
|
|
@@ -8401,11 +9030,11 @@ async function logout() {
|
|
|
8401
9030
|
|
|
8402
9031
|
// src/commands/status.ts
|
|
8403
9032
|
import { readFile as readFile16 } from "fs/promises";
|
|
8404
|
-
import { basename as basename2, join as
|
|
9033
|
+
import { basename as basename2, join as join36 } from "path";
|
|
8405
9034
|
async function status() {
|
|
8406
9035
|
const configDir = getConfigDir2();
|
|
8407
|
-
const STATE_PATH =
|
|
8408
|
-
const CONFIG_PATH =
|
|
9036
|
+
const STATE_PATH = join36(configDir, "listener-state.json");
|
|
9037
|
+
const CONFIG_PATH = join36(configDir, "config.json");
|
|
8409
9038
|
let state = null;
|
|
8410
9039
|
try {
|
|
8411
9040
|
const data = await readFile16(STATE_PATH, "utf-8");
|
|
@@ -8453,7 +9082,7 @@ async function status() {
|
|
|
8453
9082
|
|
|
8454
9083
|
// src/commands/sync.ts
|
|
8455
9084
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
8456
|
-
import { dirname as
|
|
9085
|
+
import { dirname as dirname16, join as join37 } from "path";
|
|
8457
9086
|
import chalk9 from "chalk";
|
|
8458
9087
|
import ora4 from "ora";
|
|
8459
9088
|
var POLL_INTERVAL_MS2 = 3e3;
|
|
@@ -8602,7 +9231,7 @@ async function sync() {
|
|
|
8602
9231
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
8603
9232
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
8604
9233
|
if (files.length > 0) {
|
|
8605
|
-
const contextDir =
|
|
9234
|
+
const contextDir = join37(repoRoot, DEFAULT_CONTEXT_FOLDER3);
|
|
8606
9235
|
mkdirSync3(contextDir, { recursive: true });
|
|
8607
9236
|
let downloadedCount = 0;
|
|
8608
9237
|
let failedCount = 0;
|
|
@@ -8616,8 +9245,8 @@ async function sync() {
|
|
|
8616
9245
|
const response = await fetch(presignedUrl);
|
|
8617
9246
|
if (response.ok) {
|
|
8618
9247
|
const content = await response.text();
|
|
8619
|
-
const filePath =
|
|
8620
|
-
mkdirSync3(
|
|
9248
|
+
const filePath = join37(contextDir, file.fileName);
|
|
9249
|
+
mkdirSync3(dirname16(filePath), { recursive: true });
|
|
8621
9250
|
writeFileSync4(filePath, content, "utf-8");
|
|
8622
9251
|
downloadedCount++;
|
|
8623
9252
|
} else {
|
|
@@ -8869,7 +9498,7 @@ async function config() {
|
|
|
8869
9498
|
// src/commands/mcp-log.ts
|
|
8870
9499
|
import { createDecipheriv as createDecipheriv2 } from "crypto";
|
|
8871
9500
|
import { mkdir as mkdir18, readFile as readFile17, stat as stat6, writeFile as writeFile18 } from "fs/promises";
|
|
8872
|
-
import { dirname as
|
|
9501
|
+
import { dirname as dirname17, join as join38 } from "path";
|
|
8873
9502
|
var FLAG_FILE = "mcp-log.flag";
|
|
8874
9503
|
var LOG_FILE = "mcp-log.jsonl.enc";
|
|
8875
9504
|
var KEY_FILE = "mcp-log.key";
|
|
@@ -8877,10 +9506,10 @@ var ENDPOINT_FILE = "listener.endpoint";
|
|
|
8877
9506
|
var IV_BYTES2 = 12;
|
|
8878
9507
|
var TAG_BYTES2 = 16;
|
|
8879
9508
|
function flagPath() {
|
|
8880
|
-
return
|
|
9509
|
+
return join38(getConfigDir2(), FLAG_FILE);
|
|
8881
9510
|
}
|
|
8882
9511
|
function logPath() {
|
|
8883
|
-
return
|
|
9512
|
+
return join38(getConfigDir2(), LOG_FILE);
|
|
8884
9513
|
}
|
|
8885
9514
|
async function readFlag() {
|
|
8886
9515
|
try {
|
|
@@ -8896,7 +9525,7 @@ async function readFlag() {
|
|
|
8896
9525
|
}
|
|
8897
9526
|
async function writeFlag(flag) {
|
|
8898
9527
|
const path = flagPath();
|
|
8899
|
-
await mkdir18(
|
|
9528
|
+
await mkdir18(dirname17(path), { recursive: true });
|
|
8900
9529
|
await writeFile18(path, JSON.stringify(flag, null, 2), { encoding: "utf-8", mode: 384 });
|
|
8901
9530
|
}
|
|
8902
9531
|
async function showConsentPrompt() {
|
|
@@ -8967,14 +9596,14 @@ async function trySendConsentToServer() {
|
|
|
8967
9596
|
let apiUrl = null;
|
|
8968
9597
|
let token = null;
|
|
8969
9598
|
try {
|
|
8970
|
-
const body = await readFile17(
|
|
9599
|
+
const body = await readFile17(join38(getConfigDir2(), "config.json"), "utf-8");
|
|
8971
9600
|
const parsed = JSON.parse(body);
|
|
8972
9601
|
apiUrl = parsed.repos?.find((r) => Boolean(r.apiUrl))?.apiUrl ?? parsed.defaultApiUrl ?? null;
|
|
8973
9602
|
} catch {
|
|
8974
9603
|
return false;
|
|
8975
9604
|
}
|
|
8976
9605
|
try {
|
|
8977
|
-
const body = await readFile17(
|
|
9606
|
+
const body = await readFile17(join38(getConfigDir2(), "credentials.json"), "utf-8");
|
|
8978
9607
|
const parsed = JSON.parse(body);
|
|
8979
9608
|
token = parsed.idToken ?? null;
|
|
8980
9609
|
} catch {
|
|
@@ -9027,7 +9656,7 @@ async function mcpLogStatus() {
|
|
|
9027
9656
|
process.stderr.write("Log size: no file yet\n");
|
|
9028
9657
|
}
|
|
9029
9658
|
try {
|
|
9030
|
-
const endpointBody = await readFile17(
|
|
9659
|
+
const endpointBody = await readFile17(join38(getConfigDir2(), ENDPOINT_FILE), "utf-8");
|
|
9031
9660
|
const match = /endpoint=([^\n]+)/.exec(endpointBody);
|
|
9032
9661
|
process.stderr.write(`MCP endpoint: ${match?.[1] ?? "(malformed endpoint file)"}
|
|
9033
9662
|
`);
|
|
@@ -9054,7 +9683,7 @@ Run \`repowise mcp-log on\` to grant consent and view them.
|
|
|
9054
9683
|
const key = await readKey();
|
|
9055
9684
|
if (!key) {
|
|
9056
9685
|
process.stderr.write(
|
|
9057
|
-
`No encryption key at ${
|
|
9686
|
+
`No encryption key at ${join38(getConfigDir2(), KEY_FILE)} \u2014 listener may not have started yet.
|
|
9058
9687
|
`
|
|
9059
9688
|
);
|
|
9060
9689
|
return;
|
|
@@ -9130,7 +9759,7 @@ Run \`repowise mcp-log on\` to grant consent and view them.
|
|
|
9130
9759
|
}
|
|
9131
9760
|
async function readKey() {
|
|
9132
9761
|
try {
|
|
9133
|
-
const body = await readFile17(
|
|
9762
|
+
const body = await readFile17(join38(getConfigDir2(), KEY_FILE), "utf-8");
|
|
9134
9763
|
const parsed = Buffer.from(body.trim(), "base64");
|
|
9135
9764
|
if (parsed.length !== 32) return null;
|
|
9136
9765
|
return parsed;
|
|
@@ -9173,8 +9802,8 @@ async function mcpLog(subcommand, flags = {}) {
|
|
|
9173
9802
|
import chalk11 from "chalk";
|
|
9174
9803
|
|
|
9175
9804
|
// src/lib/graph-loader.ts
|
|
9176
|
-
import { promises as
|
|
9177
|
-
import { join as
|
|
9805
|
+
import { promises as fs12 } from "fs";
|
|
9806
|
+
import { join as join39, resolve as resolve2 } from "path";
|
|
9178
9807
|
import { gunzipSync } from "zlib";
|
|
9179
9808
|
var RELATIVE_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json";
|
|
9180
9809
|
var GZIPPED_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json.gz";
|
|
@@ -9191,8 +9820,8 @@ var GraphNotFoundError = class extends Error {
|
|
|
9191
9820
|
var cache = /* @__PURE__ */ new Map();
|
|
9192
9821
|
async function loadGraph(repoRoot = process.cwd()) {
|
|
9193
9822
|
const root = resolve2(repoRoot);
|
|
9194
|
-
const gzPath =
|
|
9195
|
-
const plainPath =
|
|
9823
|
+
const gzPath = join39(root, GZIPPED_GRAPH_PATH);
|
|
9824
|
+
const plainPath = join39(root, RELATIVE_GRAPH_PATH);
|
|
9196
9825
|
const cached = cache.get(root);
|
|
9197
9826
|
if (cached) {
|
|
9198
9827
|
return { graph: cached, path: plainPath, bytes: 0, parseMs: 0, fromCache: true };
|
|
@@ -9200,14 +9829,14 @@ async function loadGraph(repoRoot = process.cwd()) {
|
|
|
9200
9829
|
let graphPath = null;
|
|
9201
9830
|
let raw = null;
|
|
9202
9831
|
try {
|
|
9203
|
-
raw = await
|
|
9832
|
+
raw = await fs12.readFile(gzPath);
|
|
9204
9833
|
graphPath = gzPath;
|
|
9205
9834
|
} catch (err) {
|
|
9206
9835
|
if (err.code !== "ENOENT") throw err;
|
|
9207
9836
|
}
|
|
9208
9837
|
if (!raw) {
|
|
9209
9838
|
try {
|
|
9210
|
-
raw = await
|
|
9839
|
+
raw = await fs12.readFile(plainPath);
|
|
9211
9840
|
graphPath = plainPath;
|
|
9212
9841
|
} catch (err) {
|
|
9213
9842
|
if (err.code === "ENOENT") {
|
|
@@ -9606,14 +10235,14 @@ function registerQueryCommand(program2) {
|
|
|
9606
10235
|
}
|
|
9607
10236
|
|
|
9608
10237
|
// src/commands/uninstall.ts
|
|
9609
|
-
import { promises as
|
|
9610
|
-
import { homedir as
|
|
9611
|
-
import { join as
|
|
10238
|
+
import { promises as fs16 } from "fs";
|
|
10239
|
+
import { homedir as homedir8 } from "os";
|
|
10240
|
+
import { join as join43 } from "path";
|
|
9612
10241
|
import chalk12 from "chalk";
|
|
9613
10242
|
|
|
9614
10243
|
// src/lib/cleanup/marker-blocks.ts
|
|
9615
|
-
import { promises as
|
|
9616
|
-
import { join as
|
|
10244
|
+
import { promises as fs13 } from "fs";
|
|
10245
|
+
import { join as join40 } from "path";
|
|
9617
10246
|
var MARKER_START = "<!-- repowise-start -->";
|
|
9618
10247
|
var MARKER_END = "<!-- repowise-end -->";
|
|
9619
10248
|
var CONTEXT_FILES = [
|
|
@@ -9629,7 +10258,7 @@ var CONTEXT_FILES = [
|
|
|
9629
10258
|
async function stripMarkerBlock(filePath) {
|
|
9630
10259
|
let raw;
|
|
9631
10260
|
try {
|
|
9632
|
-
raw = await
|
|
10261
|
+
raw = await fs13.readFile(filePath, "utf-8");
|
|
9633
10262
|
} catch (err) {
|
|
9634
10263
|
if (err.code === "ENOENT")
|
|
9635
10264
|
return { path: filePath, status: "missing" };
|
|
@@ -9644,16 +10273,16 @@ async function stripMarkerBlock(filePath) {
|
|
|
9644
10273
|
const after = raw.slice(endIdx + MARKER_END.length).replace(/^\n+/, "");
|
|
9645
10274
|
const stripped = (before + (before && after ? "\n\n" : "") + after).trim();
|
|
9646
10275
|
if (stripped.length === 0) {
|
|
9647
|
-
await
|
|
10276
|
+
await fs13.unlink(filePath);
|
|
9648
10277
|
return { path: filePath, status: "deleted" };
|
|
9649
10278
|
}
|
|
9650
|
-
await
|
|
10279
|
+
await fs13.writeFile(filePath, stripped + "\n", "utf-8");
|
|
9651
10280
|
return { path: filePath, status: "stripped" };
|
|
9652
10281
|
}
|
|
9653
10282
|
async function stripAllMarkerBlocks(repoRoot) {
|
|
9654
10283
|
const out = [];
|
|
9655
10284
|
for (const relative of CONTEXT_FILES) {
|
|
9656
|
-
const full =
|
|
10285
|
+
const full = join40(repoRoot, relative);
|
|
9657
10286
|
const result = await stripMarkerBlock(full).catch((err) => ({
|
|
9658
10287
|
path: full,
|
|
9659
10288
|
status: "untouched",
|
|
@@ -9665,25 +10294,25 @@ async function stripAllMarkerBlocks(repoRoot) {
|
|
|
9665
10294
|
}
|
|
9666
10295
|
|
|
9667
10296
|
// src/lib/cleanup/mcp-configs.ts
|
|
9668
|
-
import { promises as
|
|
9669
|
-
import { join as
|
|
10297
|
+
import { promises as fs14 } from "fs";
|
|
10298
|
+
import { join as join41 } from "path";
|
|
9670
10299
|
function mcpConfigPaths(repoRoot, home) {
|
|
9671
10300
|
return [
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
10301
|
+
join41(repoRoot, ".mcp.json"),
|
|
10302
|
+
join41(repoRoot, ".cursor", "mcp.json"),
|
|
10303
|
+
join41(repoRoot, ".vscode", "mcp.json"),
|
|
10304
|
+
join41(repoRoot, ".roo", "mcp.json"),
|
|
10305
|
+
join41(home, ".cline", "mcp.json"),
|
|
10306
|
+
join41(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
10307
|
+
join41(home, ".gemini", "settings.json"),
|
|
10308
|
+
join41(home, ".codex", "mcp.json"),
|
|
10309
|
+
join41(home, ".roo", "mcp.json")
|
|
9681
10310
|
];
|
|
9682
10311
|
}
|
|
9683
10312
|
async function removeRepowiseFromConfig(path, serverName) {
|
|
9684
10313
|
let raw;
|
|
9685
10314
|
try {
|
|
9686
|
-
raw = await
|
|
10315
|
+
raw = await fs14.readFile(path, "utf-8");
|
|
9687
10316
|
} catch (err) {
|
|
9688
10317
|
if (err.code === "ENOENT") return { path, status: "not-found" };
|
|
9689
10318
|
return { path, status: "error", error: err.message };
|
|
@@ -9703,7 +10332,7 @@ async function removeRepowiseFromConfig(path, serverName) {
|
|
|
9703
10332
|
} else {
|
|
9704
10333
|
next.mcpServers = servers;
|
|
9705
10334
|
}
|
|
9706
|
-
await
|
|
10335
|
+
await fs14.writeFile(path, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
9707
10336
|
return { path, status: "removed" };
|
|
9708
10337
|
}
|
|
9709
10338
|
async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
@@ -9716,17 +10345,17 @@ async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
|
9716
10345
|
}
|
|
9717
10346
|
|
|
9718
10347
|
// src/lib/cleanup/local-state.ts
|
|
9719
|
-
import { promises as
|
|
9720
|
-
import { homedir as
|
|
9721
|
-
import { join as
|
|
10348
|
+
import { promises as fs15 } from "fs";
|
|
10349
|
+
import { homedir as homedir7 } from "os";
|
|
10350
|
+
import { join as join42, resolve as resolve3 } from "path";
|
|
9722
10351
|
async function clearLocalState(homeOverride) {
|
|
9723
|
-
const home = homeOverride ??
|
|
9724
|
-
const target = resolve3(
|
|
10352
|
+
const home = homeOverride ?? homedir7();
|
|
10353
|
+
const target = resolve3(join42(home, ".repowise"));
|
|
9725
10354
|
if (target === resolve3(home) || !target.startsWith(resolve3(home))) {
|
|
9726
10355
|
return { path: target, status: "error", error: "refused: not under home" };
|
|
9727
10356
|
}
|
|
9728
10357
|
try {
|
|
9729
|
-
await
|
|
10358
|
+
await fs15.rm(target, { recursive: true, force: false });
|
|
9730
10359
|
return { path: target, status: "removed" };
|
|
9731
10360
|
} catch (err) {
|
|
9732
10361
|
if (err.code === "ENOENT")
|
|
@@ -9756,7 +10385,7 @@ async function stopAndUninstallService(uninstaller) {
|
|
|
9756
10385
|
// src/commands/uninstall.ts
|
|
9757
10386
|
async function uninstall2(opts = {}) {
|
|
9758
10387
|
const tier = opts.tier ?? "uninstall";
|
|
9759
|
-
const home = opts.home ??
|
|
10388
|
+
const home = opts.home ?? homedir8();
|
|
9760
10389
|
const repoRoot = opts.repoRoot ?? process.cwd();
|
|
9761
10390
|
const loadRepoIds = opts.loadRepoIds ?? defaultLoadRepoIds;
|
|
9762
10391
|
const report = { tier, removed: [], preserved: [], skipped: [] };
|
|
@@ -9765,7 +10394,7 @@ async function uninstall2(opts = {}) {
|
|
|
9765
10394
|
else if (svc.error) report.skipped.push({ path: "listener service", reason: svc.error });
|
|
9766
10395
|
if (tier === "stop") return report;
|
|
9767
10396
|
try {
|
|
9768
|
-
await
|
|
10397
|
+
await fs16.unlink(join43(home, ".repowise", "credentials.json"));
|
|
9769
10398
|
report.removed.push("credentials");
|
|
9770
10399
|
} catch (err) {
|
|
9771
10400
|
if (err.code !== "ENOENT") {
|
|
@@ -9792,7 +10421,7 @@ async function uninstall2(opts = {}) {
|
|
|
9792
10421
|
const allPaths = mcpConfigPaths(repoRoot, home);
|
|
9793
10422
|
for (const p of allPaths) {
|
|
9794
10423
|
try {
|
|
9795
|
-
await
|
|
10424
|
+
await fs16.access(p);
|
|
9796
10425
|
} catch {
|
|
9797
10426
|
}
|
|
9798
10427
|
}
|
|
@@ -9804,7 +10433,7 @@ async function uninstall2(opts = {}) {
|
|
|
9804
10433
|
}
|
|
9805
10434
|
async function defaultLoadRepoIds(home) {
|
|
9806
10435
|
try {
|
|
9807
|
-
const raw = await
|
|
10436
|
+
const raw = await fs16.readFile(join43(home, ".repowise", "config.json"), "utf-8");
|
|
9808
10437
|
const parsed = JSON.parse(raw);
|
|
9809
10438
|
return (parsed.repos ?? []).map((r) => r.repoId);
|
|
9810
10439
|
} catch {
|
|
@@ -9850,13 +10479,13 @@ Done \u2014 ${report.removed.length} removed, ${report.skipped.length} skipped.
|
|
|
9850
10479
|
}
|
|
9851
10480
|
|
|
9852
10481
|
// src/commands/mcp-shim.ts
|
|
9853
|
-
import { promises as
|
|
10482
|
+
import { promises as fs17 } from "fs";
|
|
9854
10483
|
import { createInterface as createInterface2 } from "readline";
|
|
9855
|
-
import { homedir as
|
|
9856
|
-
import { join as
|
|
10484
|
+
import { homedir as homedir9 } from "os";
|
|
10485
|
+
import { join as join44 } from "path";
|
|
9857
10486
|
var DEFAULT_MAX = 200 * 1024;
|
|
9858
10487
|
async function mcpShim(opts) {
|
|
9859
|
-
const endpointPath = opts.endpointFile ??
|
|
10488
|
+
const endpointPath = opts.endpointFile ?? join44(homedir9(), ".repowise", "listener.endpoint");
|
|
9860
10489
|
const stdin = opts.stdin ?? process.stdin;
|
|
9861
10490
|
const stdout = opts.stdout ?? process.stdout;
|
|
9862
10491
|
const stderr = opts.stderr ?? process.stderr;
|
|
@@ -9927,7 +10556,7 @@ async function mcpShim(opts) {
|
|
|
9927
10556
|
}
|
|
9928
10557
|
async function readEndpoint(path) {
|
|
9929
10558
|
try {
|
|
9930
|
-
const raw = (await
|
|
10559
|
+
const raw = (await fs17.readFile(path, "utf-8")).trim();
|
|
9931
10560
|
if (!raw) return null;
|
|
9932
10561
|
if (raw.startsWith("http://") || raw.startsWith("https://")) {
|
|
9933
10562
|
return { endpoint: raw.split("\n")[0].trim(), secret: null };
|
|
@@ -10141,14 +10770,14 @@ function writeError(stream, id, code, message) {
|
|
|
10141
10770
|
|
|
10142
10771
|
// src/commands/lsp.ts
|
|
10143
10772
|
init_registry();
|
|
10144
|
-
import { spawn as
|
|
10773
|
+
import { spawn as spawn4 } from "child_process";
|
|
10145
10774
|
import chalk13 from "chalk";
|
|
10146
10775
|
async function isOnPath(command) {
|
|
10147
10776
|
if (/[^\w./+-]/.test(command)) return false;
|
|
10148
10777
|
const isWin = process.platform === "win32";
|
|
10149
10778
|
const probeCmd = isWin ? "where" : "which";
|
|
10150
10779
|
return new Promise((resolve4) => {
|
|
10151
|
-
const child =
|
|
10780
|
+
const child = spawn4(probeCmd, [command], { stdio: "ignore" });
|
|
10152
10781
|
child.on("close", (code) => {
|
|
10153
10782
|
resolve4(code === 0);
|
|
10154
10783
|
});
|
|
@@ -10209,8 +10838,8 @@ async function lspDoctor() {
|
|
|
10209
10838
|
|
|
10210
10839
|
// bin/repowise.ts
|
|
10211
10840
|
var __filename = fileURLToPath4(import.meta.url);
|
|
10212
|
-
var __dirname =
|
|
10213
|
-
var pkg = JSON.parse(readFileSync3(
|
|
10841
|
+
var __dirname = dirname18(__filename);
|
|
10842
|
+
var pkg = JSON.parse(readFileSync3(join45(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
10214
10843
|
var program = new Command();
|
|
10215
10844
|
program.name(getPackageName()).description("AI-optimized codebase context generator").version(pkg.version).hook("preAction", async () => {
|
|
10216
10845
|
await showWelcome(pkg.version);
|