repowisestage 0.0.40 → 0.0.41
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 +1154 -544
- 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 dirname5, 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 dirname17, 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 dirname12 } 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";
|
|
@@ -3016,25 +3022,193 @@ var LspClient = class extends EventEmitter {
|
|
|
3016
3022
|
this.emit("notification", msg["method"], msg["params"]);
|
|
3017
3023
|
return;
|
|
3018
3024
|
}
|
|
3019
|
-
if (msg["method"] !== void 0 && msg["id"] !== void 0) {
|
|
3020
|
-
const method = msg["method"];
|
|
3021
|
-
const reqId = msg["id"];
|
|
3022
|
-
if (this.listenerCount("request") === 0) {
|
|
3023
|
-
this.respondError(reqId, -32601, `method not found: ${method}`);
|
|
3025
|
+
if (msg["method"] !== void 0 && msg["id"] !== void 0) {
|
|
3026
|
+
const method = msg["method"];
|
|
3027
|
+
const reqId = msg["id"];
|
|
3028
|
+
if (this.listenerCount("request") === 0) {
|
|
3029
|
+
this.respondError(reqId, -32601, `method not found: ${method}`);
|
|
3030
|
+
return;
|
|
3031
|
+
}
|
|
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 } 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
|
+
function runNpmInstall(cwd, pkg2) {
|
|
3087
|
+
return new Promise((resolve4, reject) => {
|
|
3088
|
+
const child = spawn3("npm", ["install", "--no-audit", "--no-fund", "--silent", pkg2], {
|
|
3089
|
+
cwd,
|
|
3090
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
3091
|
+
env: { ...process.env }
|
|
3092
|
+
});
|
|
3093
|
+
let stderr = "";
|
|
3094
|
+
child.stderr.on("data", (chunk) => {
|
|
3095
|
+
stderr += chunk.toString();
|
|
3096
|
+
});
|
|
3097
|
+
child.on("error", (err) => reject(err));
|
|
3098
|
+
child.on("close", (code) => {
|
|
3099
|
+
if (code === 0) {
|
|
3100
|
+
resolve4();
|
|
3101
|
+
} else {
|
|
3102
|
+
reject(new Error(`npm install ${pkg2} exited ${(code ?? -1).toString()}: ${sanitizeNpmStderr(stderr)}`));
|
|
3103
|
+
}
|
|
3104
|
+
});
|
|
3105
|
+
});
|
|
3106
|
+
}
|
|
3107
|
+
function sanitizeNpmStderr(raw) {
|
|
3108
|
+
const truncated = raw.split("\n").slice(0, 3).join(" ").trim();
|
|
3109
|
+
return truncated.replace(/(https?:\/\/)[^@\s/]*@/g, (_match, scheme) => `${scheme}<redacted>@`);
|
|
3110
|
+
}
|
|
3111
|
+
async function pathExists(p) {
|
|
3112
|
+
try {
|
|
3113
|
+
await fs.access(p);
|
|
3114
|
+
return true;
|
|
3115
|
+
} catch {
|
|
3116
|
+
return false;
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
async function detectRepoLanguages(repoRoot) {
|
|
3120
|
+
const found = /* @__PURE__ */ new Set();
|
|
3121
|
+
let inspected = 0;
|
|
3122
|
+
const MAX_INSPECT = 200;
|
|
3123
|
+
async function inspect(dir) {
|
|
3124
|
+
if (inspected >= MAX_INSPECT)
|
|
3125
|
+
return;
|
|
3126
|
+
let entries;
|
|
3127
|
+
try {
|
|
3128
|
+
entries = await fs.readdir(dir);
|
|
3129
|
+
} catch {
|
|
3130
|
+
return;
|
|
3131
|
+
}
|
|
3132
|
+
for (const name of entries) {
|
|
3133
|
+
if (inspected >= MAX_INSPECT)
|
|
3024
3134
|
return;
|
|
3135
|
+
if (name.startsWith("."))
|
|
3136
|
+
continue;
|
|
3137
|
+
if (name === "node_modules" || name === "dist" || name === "build")
|
|
3138
|
+
continue;
|
|
3139
|
+
const lang = detectLanguage(name);
|
|
3140
|
+
if (lang) {
|
|
3141
|
+
found.add(lang);
|
|
3142
|
+
inspected += 1;
|
|
3025
3143
|
}
|
|
3026
|
-
this.emit("request", method, msg["params"], reqId);
|
|
3027
3144
|
}
|
|
3028
3145
|
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3146
|
+
await inspect(repoRoot);
|
|
3147
|
+
let topEntries = [];
|
|
3148
|
+
try {
|
|
3149
|
+
topEntries = await fs.readdir(repoRoot);
|
|
3150
|
+
} catch {
|
|
3151
|
+
return found;
|
|
3152
|
+
}
|
|
3153
|
+
for (const name of topEntries) {
|
|
3154
|
+
if (name.startsWith("."))
|
|
3155
|
+
continue;
|
|
3156
|
+
if (name === "node_modules" || name === "dist" || name === "build")
|
|
3157
|
+
continue;
|
|
3158
|
+
const sub = join14(repoRoot, name);
|
|
3159
|
+
try {
|
|
3160
|
+
const stat7 = await fs.stat(sub);
|
|
3161
|
+
if (stat7.isDirectory())
|
|
3162
|
+
await inspect(sub);
|
|
3163
|
+
} catch {
|
|
3034
3164
|
}
|
|
3035
|
-
this.pending.clear();
|
|
3036
3165
|
}
|
|
3037
|
-
|
|
3166
|
+
return found;
|
|
3167
|
+
}
|
|
3168
|
+
async function prepareLspServersForRepos(repos) {
|
|
3169
|
+
const detected = /* @__PURE__ */ new Set();
|
|
3170
|
+
for (const r of repos) {
|
|
3171
|
+
if (!r.localPath)
|
|
3172
|
+
continue;
|
|
3173
|
+
try {
|
|
3174
|
+
const stat7 = await fs.stat(r.localPath);
|
|
3175
|
+
if (!stat7.isDirectory())
|
|
3176
|
+
continue;
|
|
3177
|
+
} catch {
|
|
3178
|
+
continue;
|
|
3179
|
+
}
|
|
3180
|
+
try {
|
|
3181
|
+
const langs = await detectRepoLanguages(r.localPath);
|
|
3182
|
+
for (const l of langs)
|
|
3183
|
+
detected.add(l);
|
|
3184
|
+
} catch {
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
const results = [];
|
|
3188
|
+
for (const language of detected) {
|
|
3189
|
+
const configs = LSP_REGISTRY[language];
|
|
3190
|
+
const npmConfig = configs.find((c) => c.npmPackage);
|
|
3191
|
+
if (!npmConfig) {
|
|
3192
|
+
results.push({
|
|
3193
|
+
language,
|
|
3194
|
+
installed: false,
|
|
3195
|
+
alreadyPresent: false,
|
|
3196
|
+
skippedNoNpmPackage: true,
|
|
3197
|
+
hint: configs[0]?.installHint
|
|
3198
|
+
});
|
|
3199
|
+
continue;
|
|
3200
|
+
}
|
|
3201
|
+
const outcome = await ensureNpmLspInstalled(npmConfig);
|
|
3202
|
+
results.push({
|
|
3203
|
+
language,
|
|
3204
|
+
installed: outcome.installed,
|
|
3205
|
+
alreadyPresent: outcome.skipped === "already-present",
|
|
3206
|
+
skippedNoNpmPackage: false,
|
|
3207
|
+
error: outcome.error
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
3210
|
+
return results;
|
|
3211
|
+
}
|
|
3038
3212
|
|
|
3039
3213
|
// ../listener/dist/lsp/workspace-session.js
|
|
3040
3214
|
function keyOf(args) {
|
|
@@ -3050,10 +3224,14 @@ var WorkspaceManager = class {
|
|
|
3050
3224
|
this.idleTimeoutMs = opts.idleTimeoutMs ?? 10 * 60 * 1e3;
|
|
3051
3225
|
this.maxSessions = opts.maxSessions ?? 32;
|
|
3052
3226
|
this.clientFactory = opts.clientFactory ?? ((config2, cwd) => {
|
|
3227
|
+
const env = { ...process.env };
|
|
3228
|
+
const lspBin = getLspBinDir();
|
|
3229
|
+
env.PATH = env.PATH ? `${env.PATH}:${lspBin}` : lspBin;
|
|
3053
3230
|
const client = new LspClient({
|
|
3054
3231
|
command: config2.command,
|
|
3055
3232
|
args: config2.args,
|
|
3056
|
-
cwd
|
|
3233
|
+
cwd,
|
|
3234
|
+
env
|
|
3057
3235
|
});
|
|
3058
3236
|
client.on("stderr", (line) => {
|
|
3059
3237
|
process.stderr.write(`[lsp:${config2.id}] ${line}`);
|
|
@@ -3381,7 +3559,7 @@ var PathEscapeError = class extends Error {
|
|
|
3381
3559
|
// ../listener/dist/mcp/graph-cache.js
|
|
3382
3560
|
init_config_dir();
|
|
3383
3561
|
import { readFile as readFile8, stat as stat3 } from "fs/promises";
|
|
3384
|
-
import { join as
|
|
3562
|
+
import { join as join16 } from "path";
|
|
3385
3563
|
var EVICT_DEBOUNCE_MS = 6e4;
|
|
3386
3564
|
function assertSafeRepoId(repoId) {
|
|
3387
3565
|
if (!repoId || typeof repoId !== "string") {
|
|
@@ -3396,7 +3574,7 @@ function assertSafeRepoId(repoId) {
|
|
|
3396
3574
|
}
|
|
3397
3575
|
function createGraphCache(options = {}) {
|
|
3398
3576
|
const evictMs = options.evictDebounceMs ?? EVICT_DEBOUNCE_MS;
|
|
3399
|
-
const resolvePath = options.resolveGraphPath ?? ((repoId) =>
|
|
3577
|
+
const resolvePath = options.resolveGraphPath ?? ((repoId) => join16(defaultRepoWiseHome(), "graphs", `${repoId}.json`));
|
|
3400
3578
|
const entries = /* @__PURE__ */ new Map();
|
|
3401
3579
|
const inFlight = /* @__PURE__ */ new Map();
|
|
3402
3580
|
async function loadFromDisk(repoId) {
|
|
@@ -3905,7 +4083,7 @@ async function isLocallyConsented(flagPath2) {
|
|
|
3905
4083
|
init_config_dir();
|
|
3906
4084
|
import { createServer } from "http";
|
|
3907
4085
|
import { mkdir as mkdir13, writeFile as writeFile13 } from "fs/promises";
|
|
3908
|
-
import { dirname as dirname10, join as
|
|
4086
|
+
import { dirname as dirname10, join as join17 } from "path";
|
|
3909
4087
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
3910
4088
|
|
|
3911
4089
|
// ../listener/dist/mcp/sanitize.js
|
|
@@ -5258,7 +5436,7 @@ function extractBearer(header) {
|
|
|
5258
5436
|
return m ? m[1] : null;
|
|
5259
5437
|
}
|
|
5260
5438
|
function defaultEndpointFile() {
|
|
5261
|
-
return
|
|
5439
|
+
return join17(getConfigDir(), "listener.endpoint");
|
|
5262
5440
|
}
|
|
5263
5441
|
|
|
5264
5442
|
// ../listener/dist/mcp/bootstrap.js
|
|
@@ -5266,7 +5444,7 @@ async function startMcp(options) {
|
|
|
5266
5444
|
const disabled = process.env.REPOWISE_MCP_DISABLED === "true";
|
|
5267
5445
|
const graphsDir = options.graphsDir ?? defaultGraphsDir();
|
|
5268
5446
|
const graphCache = createGraphCache({
|
|
5269
|
-
resolveGraphPath: (repoId) =>
|
|
5447
|
+
resolveGraphPath: (repoId) => join18(graphsDir, `${repoId}.json`)
|
|
5270
5448
|
});
|
|
5271
5449
|
if (disabled) {
|
|
5272
5450
|
return {
|
|
@@ -5289,11 +5467,11 @@ async function startMcp(options) {
|
|
|
5289
5467
|
}
|
|
5290
5468
|
const firstRepoLocal = options.repos.find((r) => r.localPath)?.localPath;
|
|
5291
5469
|
const mcpHome = defaultMcpHome();
|
|
5292
|
-
const logFilePath =
|
|
5293
|
-
const keyStore = createFileKeyStore(
|
|
5470
|
+
const logFilePath = join18(mcpHome, "mcp-log.jsonl.enc");
|
|
5471
|
+
const keyStore = createFileKeyStore(join18(mcpHome, "mcp-log.key"));
|
|
5294
5472
|
const mcpLogger = createMcpLogger({ filePath: logFilePath, keyStore });
|
|
5295
|
-
const flagFilePath =
|
|
5296
|
-
const watermarkFilePath =
|
|
5473
|
+
const flagFilePath = join18(mcpHome, "mcp-log.flag");
|
|
5474
|
+
const watermarkFilePath = join18(mcpHome, "mcp-log.watermark");
|
|
5297
5475
|
let uploader = null;
|
|
5298
5476
|
let lastConsentState = false;
|
|
5299
5477
|
function ensureUploader() {
|
|
@@ -5337,7 +5515,7 @@ async function startMcp(options) {
|
|
|
5337
5515
|
apiBaseUrl: repo.apiUrl,
|
|
5338
5516
|
getAuthToken: options.getAuthToken,
|
|
5339
5517
|
repoId: repo.repoId,
|
|
5340
|
-
targetPath:
|
|
5518
|
+
targetPath: join18(graphsDir, `${repo.repoId}.json`),
|
|
5341
5519
|
graphCache,
|
|
5342
5520
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
5343
5521
|
}));
|
|
@@ -5413,7 +5591,7 @@ async function startMcp(options) {
|
|
|
5413
5591
|
apiBaseUrl: repo.apiUrl,
|
|
5414
5592
|
getAuthToken: options.getAuthToken,
|
|
5415
5593
|
repoId: repo.repoId,
|
|
5416
|
-
targetPath:
|
|
5594
|
+
targetPath: join18(graphsDir, `${repo.repoId}.json`),
|
|
5417
5595
|
graphCache,
|
|
5418
5596
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
5419
5597
|
}));
|
|
@@ -5434,12 +5612,389 @@ async function startMcp(options) {
|
|
|
5434
5612
|
};
|
|
5435
5613
|
}
|
|
5436
5614
|
function defaultGraphsDir() {
|
|
5437
|
-
return
|
|
5615
|
+
return join18(getConfigDir(), "graphs");
|
|
5438
5616
|
}
|
|
5439
5617
|
function defaultMcpHome() {
|
|
5440
5618
|
return getConfigDir();
|
|
5441
5619
|
}
|
|
5442
5620
|
|
|
5621
|
+
// ../listener/dist/mcp/auto-config/index.js
|
|
5622
|
+
import { homedir as homedir4 } from "os";
|
|
5623
|
+
|
|
5624
|
+
// ../listener/dist/mcp/auto-config/writers/claude-code.js
|
|
5625
|
+
import { promises as fs3 } from "fs";
|
|
5626
|
+
import { join as join19 } from "path";
|
|
5627
|
+
|
|
5628
|
+
// ../listener/dist/mcp/auto-config/markers.js
|
|
5629
|
+
import { promises as fs2 } from "fs";
|
|
5630
|
+
import { dirname as dirname11 } from "path";
|
|
5631
|
+
async function writeMergedConfig(params) {
|
|
5632
|
+
const current = await readConfig(params.path);
|
|
5633
|
+
const servers = { ...current.mcpServers ?? {} };
|
|
5634
|
+
servers[params.serverName] = params.spec;
|
|
5635
|
+
const next = { ...current, mcpServers: servers };
|
|
5636
|
+
const canonical = canonicalize(next);
|
|
5637
|
+
const existing = safeExistingContent(params.path, current);
|
|
5638
|
+
if (existing === canonical)
|
|
5639
|
+
return "unchanged";
|
|
5640
|
+
await fs2.mkdir(dirname11(params.path), { recursive: true });
|
|
5641
|
+
await fs2.writeFile(params.path, canonical, "utf-8");
|
|
5642
|
+
return "written";
|
|
5643
|
+
}
|
|
5644
|
+
async function removeFromConfig(path, serverName) {
|
|
5645
|
+
const current = await readConfig(path);
|
|
5646
|
+
if (!current.mcpServers || !(serverName in current.mcpServers))
|
|
5647
|
+
return;
|
|
5648
|
+
const servers = { ...current.mcpServers };
|
|
5649
|
+
delete servers[serverName];
|
|
5650
|
+
const next = { ...current, mcpServers: servers };
|
|
5651
|
+
if (Object.keys(servers).length === 0) {
|
|
5652
|
+
delete next.mcpServers;
|
|
5653
|
+
}
|
|
5654
|
+
await fs2.writeFile(path, canonicalize(next), "utf-8");
|
|
5655
|
+
}
|
|
5656
|
+
async function readConfig(path) {
|
|
5657
|
+
try {
|
|
5658
|
+
const raw = await fs2.readFile(path, "utf-8");
|
|
5659
|
+
return JSON.parse(raw);
|
|
5660
|
+
} catch (err) {
|
|
5661
|
+
if (err.code === "ENOENT")
|
|
5662
|
+
return {};
|
|
5663
|
+
throw err;
|
|
5664
|
+
}
|
|
5665
|
+
}
|
|
5666
|
+
function canonicalize(config2) {
|
|
5667
|
+
const serversSorted = {};
|
|
5668
|
+
if (config2.mcpServers) {
|
|
5669
|
+
const keys = Object.keys(config2.mcpServers).sort();
|
|
5670
|
+
for (const k of keys)
|
|
5671
|
+
serversSorted[k] = normalizeSpec(config2.mcpServers[k]);
|
|
5672
|
+
}
|
|
5673
|
+
const top = {};
|
|
5674
|
+
const otherKeys = Object.keys(config2).filter((k) => k !== "mcpServers").sort();
|
|
5675
|
+
for (const k of otherKeys)
|
|
5676
|
+
top[k] = config2[k];
|
|
5677
|
+
if (Object.keys(serversSorted).length > 0)
|
|
5678
|
+
top.mcpServers = serversSorted;
|
|
5679
|
+
return JSON.stringify(top, null, 2) + "\n";
|
|
5680
|
+
}
|
|
5681
|
+
function normalizeSpec(spec) {
|
|
5682
|
+
const out = { command: spec.command };
|
|
5683
|
+
if (spec.args && spec.args.length > 0)
|
|
5684
|
+
out.args = [...spec.args];
|
|
5685
|
+
if (spec.env && Object.keys(spec.env).length > 0) {
|
|
5686
|
+
const sorted = {};
|
|
5687
|
+
for (const k of Object.keys(spec.env).sort())
|
|
5688
|
+
sorted[k] = spec.env[k];
|
|
5689
|
+
out.env = sorted;
|
|
5690
|
+
}
|
|
5691
|
+
return out;
|
|
5692
|
+
}
|
|
5693
|
+
function safeExistingContent(path, current) {
|
|
5694
|
+
try {
|
|
5695
|
+
return canonicalize(current);
|
|
5696
|
+
} catch {
|
|
5697
|
+
return null;
|
|
5698
|
+
}
|
|
5699
|
+
void path;
|
|
5700
|
+
}
|
|
5701
|
+
|
|
5702
|
+
// ../listener/dist/mcp/auto-config/writers/claude-code.js
|
|
5703
|
+
var claudeCodeWriter = {
|
|
5704
|
+
tool: "claude-code",
|
|
5705
|
+
async detect(repoRoot, home) {
|
|
5706
|
+
return await fileExists2(join19(repoRoot, "CLAUDE.md")) || await hasClaudeBinary(home);
|
|
5707
|
+
},
|
|
5708
|
+
async write(ctx) {
|
|
5709
|
+
const path = join19(ctx.repoRoot, ".mcp.json");
|
|
5710
|
+
const status2 = await writeMergedConfig({
|
|
5711
|
+
path,
|
|
5712
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5713
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5714
|
+
});
|
|
5715
|
+
return { status: status2, path };
|
|
5716
|
+
},
|
|
5717
|
+
async remove(ctx) {
|
|
5718
|
+
await removeFromConfig(join19(ctx.repoRoot, ".mcp.json"), `repowise-${ctx.repoId}`);
|
|
5719
|
+
}
|
|
5720
|
+
};
|
|
5721
|
+
async function fileExists2(path) {
|
|
5722
|
+
try {
|
|
5723
|
+
await fs3.access(path);
|
|
5724
|
+
return true;
|
|
5725
|
+
} catch {
|
|
5726
|
+
return false;
|
|
5727
|
+
}
|
|
5728
|
+
}
|
|
5729
|
+
async function hasClaudeBinary(home) {
|
|
5730
|
+
return fileExists2(join19(home, ".claude", "claude.json"));
|
|
5731
|
+
}
|
|
5732
|
+
|
|
5733
|
+
// ../listener/dist/mcp/auto-config/writers/cline.js
|
|
5734
|
+
import { promises as fs4 } from "fs";
|
|
5735
|
+
import { join as join20 } from "path";
|
|
5736
|
+
var clineWriter = {
|
|
5737
|
+
tool: "cline",
|
|
5738
|
+
async detect(repoRoot, home) {
|
|
5739
|
+
return await fileExists3(join20(repoRoot, ".clinerules")) || await fileExists3(join20(home, ".cline"));
|
|
5740
|
+
},
|
|
5741
|
+
async write(ctx) {
|
|
5742
|
+
const path = join20(ctx.home, ".cline", "mcp.json");
|
|
5743
|
+
const status2 = await writeMergedConfig({
|
|
5744
|
+
path,
|
|
5745
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5746
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5747
|
+
});
|
|
5748
|
+
return { status: status2, path };
|
|
5749
|
+
},
|
|
5750
|
+
async remove(ctx) {
|
|
5751
|
+
await removeFromConfig(join20(ctx.home, ".cline", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5752
|
+
}
|
|
5753
|
+
};
|
|
5754
|
+
async function fileExists3(path) {
|
|
5755
|
+
try {
|
|
5756
|
+
await fs4.access(path);
|
|
5757
|
+
return true;
|
|
5758
|
+
} catch {
|
|
5759
|
+
return false;
|
|
5760
|
+
}
|
|
5761
|
+
}
|
|
5762
|
+
|
|
5763
|
+
// ../listener/dist/mcp/auto-config/writers/codex.js
|
|
5764
|
+
import { promises as fs5 } from "fs";
|
|
5765
|
+
import { join as join21 } from "path";
|
|
5766
|
+
var codexWriter = {
|
|
5767
|
+
tool: "codex",
|
|
5768
|
+
async detect(_repoRoot, home) {
|
|
5769
|
+
return fileExists4(join21(home, ".codex"));
|
|
5770
|
+
},
|
|
5771
|
+
async write(ctx) {
|
|
5772
|
+
const path = join21(ctx.home, ".codex", "mcp.json");
|
|
5773
|
+
const status2 = await writeMergedConfig({
|
|
5774
|
+
path,
|
|
5775
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5776
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5777
|
+
});
|
|
5778
|
+
return { status: status2, path };
|
|
5779
|
+
},
|
|
5780
|
+
async remove(ctx) {
|
|
5781
|
+
await removeFromConfig(join21(ctx.home, ".codex", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5782
|
+
}
|
|
5783
|
+
};
|
|
5784
|
+
async function fileExists4(path) {
|
|
5785
|
+
try {
|
|
5786
|
+
await fs5.access(path);
|
|
5787
|
+
return true;
|
|
5788
|
+
} catch {
|
|
5789
|
+
return false;
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
|
|
5793
|
+
// ../listener/dist/mcp/auto-config/writers/copilot.js
|
|
5794
|
+
import { promises as fs6 } from "fs";
|
|
5795
|
+
import { join as join22 } from "path";
|
|
5796
|
+
var copilotWriter = {
|
|
5797
|
+
tool: "copilot",
|
|
5798
|
+
async detect(repoRoot) {
|
|
5799
|
+
return fileExists5(join22(repoRoot, ".vscode"));
|
|
5800
|
+
},
|
|
5801
|
+
async write(ctx) {
|
|
5802
|
+
const path = join22(ctx.repoRoot, ".vscode", "mcp.json");
|
|
5803
|
+
const status2 = await writeMergedConfig({
|
|
5804
|
+
path,
|
|
5805
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5806
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5807
|
+
});
|
|
5808
|
+
return { status: status2, path };
|
|
5809
|
+
},
|
|
5810
|
+
async remove(ctx) {
|
|
5811
|
+
await removeFromConfig(join22(ctx.repoRoot, ".vscode", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5812
|
+
}
|
|
5813
|
+
};
|
|
5814
|
+
async function fileExists5(path) {
|
|
5815
|
+
try {
|
|
5816
|
+
await fs6.access(path);
|
|
5817
|
+
return true;
|
|
5818
|
+
} catch {
|
|
5819
|
+
return false;
|
|
5820
|
+
}
|
|
5821
|
+
}
|
|
5822
|
+
|
|
5823
|
+
// ../listener/dist/mcp/auto-config/writers/cursor.js
|
|
5824
|
+
import { promises as fs7 } from "fs";
|
|
5825
|
+
import { join as join23 } from "path";
|
|
5826
|
+
var cursorWriter = {
|
|
5827
|
+
tool: "cursor",
|
|
5828
|
+
async detect(repoRoot) {
|
|
5829
|
+
return await fileExists6(join23(repoRoot, ".cursor")) || await fileExists6(join23(repoRoot, ".cursorrules"));
|
|
5830
|
+
},
|
|
5831
|
+
async write(ctx) {
|
|
5832
|
+
const path = join23(ctx.repoRoot, ".cursor", "mcp.json");
|
|
5833
|
+
const status2 = await writeMergedConfig({
|
|
5834
|
+
path,
|
|
5835
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5836
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5837
|
+
});
|
|
5838
|
+
return { status: status2, path };
|
|
5839
|
+
},
|
|
5840
|
+
async remove(ctx) {
|
|
5841
|
+
await removeFromConfig(join23(ctx.repoRoot, ".cursor", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5842
|
+
}
|
|
5843
|
+
};
|
|
5844
|
+
async function fileExists6(path) {
|
|
5845
|
+
try {
|
|
5846
|
+
await fs7.access(path);
|
|
5847
|
+
return true;
|
|
5848
|
+
} catch {
|
|
5849
|
+
return false;
|
|
5850
|
+
}
|
|
5851
|
+
}
|
|
5852
|
+
|
|
5853
|
+
// ../listener/dist/mcp/auto-config/writers/gemini-cli.js
|
|
5854
|
+
import { promises as fs8 } from "fs";
|
|
5855
|
+
import { join as join24 } from "path";
|
|
5856
|
+
var geminiCliWriter = {
|
|
5857
|
+
tool: "gemini-cli",
|
|
5858
|
+
async detect(_repoRoot, home) {
|
|
5859
|
+
return fileExists7(join24(home, ".gemini"));
|
|
5860
|
+
},
|
|
5861
|
+
async write(ctx) {
|
|
5862
|
+
const path = join24(ctx.home, ".gemini", "settings.json");
|
|
5863
|
+
const status2 = await writeMergedConfig({
|
|
5864
|
+
path,
|
|
5865
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5866
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5867
|
+
});
|
|
5868
|
+
return { status: status2, path };
|
|
5869
|
+
},
|
|
5870
|
+
async remove(ctx) {
|
|
5871
|
+
await removeFromConfig(join24(ctx.home, ".gemini", "settings.json"), `repowise-${ctx.repoId}`);
|
|
5872
|
+
}
|
|
5873
|
+
};
|
|
5874
|
+
async function fileExists7(path) {
|
|
5875
|
+
try {
|
|
5876
|
+
await fs8.access(path);
|
|
5877
|
+
return true;
|
|
5878
|
+
} catch {
|
|
5879
|
+
return false;
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
|
|
5883
|
+
// ../listener/dist/mcp/auto-config/writers/roo.js
|
|
5884
|
+
import { promises as fs9 } from "fs";
|
|
5885
|
+
import { join as join25 } from "path";
|
|
5886
|
+
var rooWriter = {
|
|
5887
|
+
tool: "roo",
|
|
5888
|
+
async detect(repoRoot, home) {
|
|
5889
|
+
return await fileExists8(join25(repoRoot, ".roo")) || await fileExists8(join25(home, ".roo"));
|
|
5890
|
+
},
|
|
5891
|
+
async write(ctx) {
|
|
5892
|
+
const repoConfig = join25(ctx.repoRoot, ".roo", "mcp.json");
|
|
5893
|
+
const useRepoScope = await fileExists8(join25(ctx.repoRoot, ".roo"));
|
|
5894
|
+
const path = useRepoScope ? repoConfig : join25(ctx.home, ".roo", "mcp.json");
|
|
5895
|
+
const status2 = await writeMergedConfig({
|
|
5896
|
+
path,
|
|
5897
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5898
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5899
|
+
});
|
|
5900
|
+
return { status: status2, path };
|
|
5901
|
+
},
|
|
5902
|
+
async remove(ctx) {
|
|
5903
|
+
await removeFromConfig(join25(ctx.repoRoot, ".roo", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5904
|
+
await removeFromConfig(join25(ctx.home, ".roo", "mcp.json"), `repowise-${ctx.repoId}`);
|
|
5905
|
+
}
|
|
5906
|
+
};
|
|
5907
|
+
async function fileExists8(path) {
|
|
5908
|
+
try {
|
|
5909
|
+
await fs9.access(path);
|
|
5910
|
+
return true;
|
|
5911
|
+
} catch {
|
|
5912
|
+
return false;
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
|
|
5916
|
+
// ../listener/dist/mcp/auto-config/writers/windsurf.js
|
|
5917
|
+
import { promises as fs10 } from "fs";
|
|
5918
|
+
import { join as join26 } from "path";
|
|
5919
|
+
var windsurfWriter = {
|
|
5920
|
+
tool: "windsurf",
|
|
5921
|
+
async detect(_repoRoot, home) {
|
|
5922
|
+
return fileExists9(join26(home, ".codeium", "windsurf"));
|
|
5923
|
+
},
|
|
5924
|
+
async write(ctx) {
|
|
5925
|
+
const path = join26(ctx.home, ".codeium", "windsurf", "mcp_config.json");
|
|
5926
|
+
const status2 = await writeMergedConfig({
|
|
5927
|
+
path,
|
|
5928
|
+
serverName: `repowise-${ctx.repoId}`,
|
|
5929
|
+
spec: { command: ctx.shimCmd, args: ["--repo-id", ctx.repoId] }
|
|
5930
|
+
});
|
|
5931
|
+
return { status: status2, path };
|
|
5932
|
+
},
|
|
5933
|
+
async remove(ctx) {
|
|
5934
|
+
await removeFromConfig(join26(ctx.home, ".codeium", "windsurf", "mcp_config.json"), `repowise-${ctx.repoId}`);
|
|
5935
|
+
}
|
|
5936
|
+
};
|
|
5937
|
+
async function fileExists9(path) {
|
|
5938
|
+
try {
|
|
5939
|
+
await fs10.access(path);
|
|
5940
|
+
return true;
|
|
5941
|
+
} catch {
|
|
5942
|
+
return false;
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5945
|
+
|
|
5946
|
+
// ../listener/dist/mcp/auto-config/writers/index.js
|
|
5947
|
+
var WRITERS = [
|
|
5948
|
+
claudeCodeWriter,
|
|
5949
|
+
clineWriter,
|
|
5950
|
+
codexWriter,
|
|
5951
|
+
copilotWriter,
|
|
5952
|
+
cursorWriter,
|
|
5953
|
+
geminiCliWriter,
|
|
5954
|
+
rooWriter,
|
|
5955
|
+
windsurfWriter
|
|
5956
|
+
];
|
|
5957
|
+
|
|
5958
|
+
// ../listener/dist/mcp/auto-config/index.js
|
|
5959
|
+
async function runAutoConfig(opts) {
|
|
5960
|
+
const home = opts.home ?? homedir4();
|
|
5961
|
+
const writers = opts.writers ?? WRITERS;
|
|
5962
|
+
const results = [];
|
|
5963
|
+
for (const writer of writers) {
|
|
5964
|
+
let detected;
|
|
5965
|
+
try {
|
|
5966
|
+
detected = await writer.detect(opts.repoRoot, home);
|
|
5967
|
+
} catch (err) {
|
|
5968
|
+
results.push({
|
|
5969
|
+
tool: writer.tool,
|
|
5970
|
+
detected: false,
|
|
5971
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5972
|
+
});
|
|
5973
|
+
continue;
|
|
5974
|
+
}
|
|
5975
|
+
if (!detected) {
|
|
5976
|
+
results.push({ tool: writer.tool, detected: false });
|
|
5977
|
+
continue;
|
|
5978
|
+
}
|
|
5979
|
+
try {
|
|
5980
|
+
const outcome = await writer.write({
|
|
5981
|
+
repoRoot: opts.repoRoot,
|
|
5982
|
+
repoId: opts.repoId,
|
|
5983
|
+
shimCmd: opts.shimCmd,
|
|
5984
|
+
home
|
|
5985
|
+
});
|
|
5986
|
+
results.push({ tool: writer.tool, detected: true, outcome });
|
|
5987
|
+
} catch (err) {
|
|
5988
|
+
results.push({
|
|
5989
|
+
tool: writer.tool,
|
|
5990
|
+
detected: true,
|
|
5991
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5992
|
+
});
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
return results;
|
|
5996
|
+
}
|
|
5997
|
+
|
|
5443
5998
|
// ../listener/dist/typed-resolution/resolver-loop.js
|
|
5444
5999
|
init_src();
|
|
5445
6000
|
init_registry();
|
|
@@ -5644,7 +6199,7 @@ var CRASH_LOOP_WINDOW_MS = 3e4;
|
|
|
5644
6199
|
var CRASH_LOOP_THRESHOLD = 3;
|
|
5645
6200
|
async function readRawToolConfig() {
|
|
5646
6201
|
try {
|
|
5647
|
-
const configPath =
|
|
6202
|
+
const configPath = join27(getConfigDir(), "config.json");
|
|
5648
6203
|
const data = await readFile12(configPath, "utf-8");
|
|
5649
6204
|
const raw = JSON.parse(data);
|
|
5650
6205
|
return {
|
|
@@ -5705,11 +6260,11 @@ function resolveAuditRoots() {
|
|
|
5705
6260
|
return override.split(":").map((s) => s.trim()).filter(Boolean);
|
|
5706
6261
|
}
|
|
5707
6262
|
const out = /* @__PURE__ */ new Set();
|
|
5708
|
-
let dir =
|
|
6263
|
+
let dir = dirname12(process.execPath);
|
|
5709
6264
|
for (let i = 0; i < 8; i += 1) {
|
|
5710
|
-
out.add(
|
|
5711
|
-
out.add(
|
|
5712
|
-
const parent =
|
|
6265
|
+
out.add(join27(dir, "node_modules"));
|
|
6266
|
+
out.add(join27(dir, "lib", "node_modules"));
|
|
6267
|
+
const parent = dirname12(dir);
|
|
5713
6268
|
if (parent === dir)
|
|
5714
6269
|
break;
|
|
5715
6270
|
dir = parent;
|
|
@@ -5928,7 +6483,7 @@ async function checkStaleContext(repos, state, groups) {
|
|
|
5928
6483
|
if (group?.offline.isOffline)
|
|
5929
6484
|
continue;
|
|
5930
6485
|
const { statSync: statSync2, readdirSync: readdirSync2 } = await import("fs");
|
|
5931
|
-
const contextPath =
|
|
6486
|
+
const contextPath = join27(repo.localPath, "repowise-context");
|
|
5932
6487
|
let isMissingOrEmpty = false;
|
|
5933
6488
|
try {
|
|
5934
6489
|
const s = statSync2(contextPath);
|
|
@@ -5957,9 +6512,36 @@ async function checkStaleContext(repos, state, groups) {
|
|
|
5957
6512
|
}
|
|
5958
6513
|
return dirty;
|
|
5959
6514
|
}
|
|
6515
|
+
async function reconcileMcpConfigs(repos, packageName) {
|
|
6516
|
+
const shimCmd = packageName;
|
|
6517
|
+
for (const repo of repos) {
|
|
6518
|
+
if (!repo.localPath)
|
|
6519
|
+
continue;
|
|
6520
|
+
try {
|
|
6521
|
+
const s = await fsStat(repo.localPath);
|
|
6522
|
+
if (!s.isDirectory())
|
|
6523
|
+
continue;
|
|
6524
|
+
} catch {
|
|
6525
|
+
continue;
|
|
6526
|
+
}
|
|
6527
|
+
try {
|
|
6528
|
+
const results = await runAutoConfig({
|
|
6529
|
+
repoRoot: repo.localPath,
|
|
6530
|
+
repoId: repo.repoId,
|
|
6531
|
+
shimCmd
|
|
6532
|
+
});
|
|
6533
|
+
const written = results.filter((r) => r.detected && r.outcome?.status === "written");
|
|
6534
|
+
if (written.length > 0) {
|
|
6535
|
+
console.log(`[mcp-config] Wrote ${written.length.toString()} config(s) for ${repo.repoId}: ${written.map((r) => `${r.tool}=${r.outcome.path}`).join(", ")}`);
|
|
6536
|
+
}
|
|
6537
|
+
} catch (err) {
|
|
6538
|
+
console.warn(`[mcp-config] Reconcile failed for ${repo.repoId}:`, err instanceof Error ? err.message : String(err));
|
|
6539
|
+
}
|
|
6540
|
+
}
|
|
6541
|
+
}
|
|
5960
6542
|
async function reconcileAgentInstructions(repos) {
|
|
5961
6543
|
for (const repo of repos) {
|
|
5962
|
-
const path =
|
|
6544
|
+
const path = join27(repo.localPath, "repowise-context", "project-overview.md");
|
|
5963
6545
|
let content;
|
|
5964
6546
|
try {
|
|
5965
6547
|
content = await readFile12(path, "utf-8");
|
|
@@ -6021,7 +6603,7 @@ async function startListener() {
|
|
|
6021
6603
|
}
|
|
6022
6604
|
const configDir = getConfigDir();
|
|
6023
6605
|
await mkdir14(configDir, { recursive: true });
|
|
6024
|
-
const lockPath =
|
|
6606
|
+
const lockPath = join27(configDir, "listener.lock");
|
|
6025
6607
|
await writeFile14(lockPath, "", { flag: "a" });
|
|
6026
6608
|
let lockIsHeld = false;
|
|
6027
6609
|
try {
|
|
@@ -6064,7 +6646,7 @@ async function startListener() {
|
|
|
6064
6646
|
return;
|
|
6065
6647
|
}
|
|
6066
6648
|
if (config2.repos.length === 0 && !config2.autoDiscoverRepos) {
|
|
6067
|
-
console.error(`No repos configured. Add repos to ${
|
|
6649
|
+
console.error(`No repos configured. Add repos to ${join27(configDir, "config.json")}`);
|
|
6068
6650
|
await releaseLockAndExit();
|
|
6069
6651
|
process.exitCode = 1;
|
|
6070
6652
|
return;
|
|
@@ -6131,8 +6713,8 @@ async function startListener() {
|
|
|
6131
6713
|
const packageName = true ? "repowisestage" : "repowise";
|
|
6132
6714
|
let currentVersion = "";
|
|
6133
6715
|
try {
|
|
6134
|
-
const selfDir =
|
|
6135
|
-
const pkgJsonPath =
|
|
6716
|
+
const selfDir = dirname12(fileURLToPath3(import.meta.url));
|
|
6717
|
+
const pkgJsonPath = join27(selfDir, "..", "..", "package.json");
|
|
6136
6718
|
const pkgJson = JSON.parse(await readFile12(pkgJsonPath, "utf-8"));
|
|
6137
6719
|
currentVersion = pkgJson.version;
|
|
6138
6720
|
} catch (err) {
|
|
@@ -6185,6 +6767,29 @@ async function startListener() {
|
|
|
6185
6767
|
} catch (err) {
|
|
6186
6768
|
console.warn("[reconcile] Initial agent instructions reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6187
6769
|
}
|
|
6770
|
+
void (async () => {
|
|
6771
|
+
try {
|
|
6772
|
+
await reconcileMcpConfigs(config2.repos, packageName);
|
|
6773
|
+
} catch (err) {
|
|
6774
|
+
console.warn("[mcp-config] Initial MCP config reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6775
|
+
}
|
|
6776
|
+
})();
|
|
6777
|
+
void (async () => {
|
|
6778
|
+
try {
|
|
6779
|
+
const lspResults = await prepareLspServersForRepos(config2.repos);
|
|
6780
|
+
for (const r of lspResults) {
|
|
6781
|
+
if (r.installed) {
|
|
6782
|
+
console.log(`[lsp-install] Installed ${r.language} LSP server`);
|
|
6783
|
+
} else if (r.skippedNoNpmPackage && r.hint) {
|
|
6784
|
+
console.log(`[lsp-install] ${r.language} LSP not auto-installable. To enable: ${r.hint}`);
|
|
6785
|
+
} else if (r.error) {
|
|
6786
|
+
console.warn(`[lsp-install] ${r.language} install failed: ${r.error}`);
|
|
6787
|
+
}
|
|
6788
|
+
}
|
|
6789
|
+
} catch (err) {
|
|
6790
|
+
console.warn("[lsp-install] Pre-install scan failed:", err instanceof Error ? err.message : String(err));
|
|
6791
|
+
}
|
|
6792
|
+
})();
|
|
6188
6793
|
const typedResolutionHooks = mcpRuntime?.lspWorkspaces ? buildTypedResolutionHooks({
|
|
6189
6794
|
workspaces: mcpRuntime.lspWorkspaces,
|
|
6190
6795
|
graphCache: mcpRuntime.graphCache,
|
|
@@ -6385,6 +6990,11 @@ async function startListener() {
|
|
|
6385
6990
|
} catch (err) {
|
|
6386
6991
|
console.warn("[reconcile] Agent instructions reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6387
6992
|
}
|
|
6993
|
+
try {
|
|
6994
|
+
await reconcileMcpConfigs(config2.repos, packageName);
|
|
6995
|
+
} catch (err) {
|
|
6996
|
+
console.warn("[mcp-config] Reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
6997
|
+
}
|
|
6388
6998
|
}
|
|
6389
6999
|
if (latestCliVersion && currentVersion && !config2.noAutoUpdate && (state.crashCount ?? 0) < CRASH_LOOP_THRESHOLD) {
|
|
6390
7000
|
if (latestCliVersion !== state.lastUpdateTargetVersion) {
|
|
@@ -6448,12 +7058,12 @@ async function startListener() {
|
|
|
6448
7058
|
} catch {
|
|
6449
7059
|
}
|
|
6450
7060
|
}
|
|
6451
|
-
const credentialsPath =
|
|
7061
|
+
const credentialsPath = join27(getConfigDir(), "credentials.json");
|
|
6452
7062
|
let credentialsChanged = false;
|
|
6453
7063
|
let watcher = null;
|
|
6454
7064
|
try {
|
|
6455
|
-
const
|
|
6456
|
-
watcher =
|
|
7065
|
+
const fs18 = await import("fs");
|
|
7066
|
+
watcher = fs18.watch(credentialsPath, () => {
|
|
6457
7067
|
credentialsChanged = true;
|
|
6458
7068
|
});
|
|
6459
7069
|
} catch {
|
|
@@ -6493,8 +7103,8 @@ if (isDirectRun) {
|
|
|
6493
7103
|
}
|
|
6494
7104
|
|
|
6495
7105
|
// src/lib/env.ts
|
|
6496
|
-
import { homedir as
|
|
6497
|
-
import { join as
|
|
7106
|
+
import { homedir as homedir5 } from "os";
|
|
7107
|
+
import { join as join28 } from "path";
|
|
6498
7108
|
var IS_STAGING2 = true ? true : false;
|
|
6499
7109
|
var PRODUCTION = {
|
|
6500
7110
|
apiUrl: "https://api.repowise.ai",
|
|
@@ -6514,7 +7124,7 @@ function getEnvConfig() {
|
|
|
6514
7124
|
return IS_STAGING2 ? STAGING : PRODUCTION;
|
|
6515
7125
|
}
|
|
6516
7126
|
function getConfigDir2() {
|
|
6517
|
-
return
|
|
7127
|
+
return join28(homedir5(), IS_STAGING2 ? ".repowise-staging" : ".repowise");
|
|
6518
7128
|
}
|
|
6519
7129
|
function getPackageName() {
|
|
6520
7130
|
return true ? "repowisestage" : "repowise";
|
|
@@ -6525,11 +7135,11 @@ import chalk from "chalk";
|
|
|
6525
7135
|
|
|
6526
7136
|
// src/lib/config.ts
|
|
6527
7137
|
import { readFile as readFile13, writeFile as writeFile15, mkdir as mkdir15, rename as rename4, unlink as unlink9 } from "fs/promises";
|
|
6528
|
-
import { join as
|
|
7138
|
+
import { join as join29 } from "path";
|
|
6529
7139
|
import lockfile4 from "proper-lockfile";
|
|
6530
7140
|
async function getConfig() {
|
|
6531
7141
|
try {
|
|
6532
|
-
const data = await readFile13(
|
|
7142
|
+
const data = await readFile13(join29(getConfigDir2(), "config.json"), "utf-8");
|
|
6533
7143
|
return JSON.parse(data);
|
|
6534
7144
|
} catch {
|
|
6535
7145
|
return {};
|
|
@@ -6537,7 +7147,7 @@ async function getConfig() {
|
|
|
6537
7147
|
}
|
|
6538
7148
|
async function saveConfig(config2) {
|
|
6539
7149
|
const dir = getConfigDir2();
|
|
6540
|
-
const path =
|
|
7150
|
+
const path = join29(dir, "config.json");
|
|
6541
7151
|
await mkdir15(dir, { recursive: true });
|
|
6542
7152
|
const tmpPath = path + ".tmp";
|
|
6543
7153
|
try {
|
|
@@ -6553,7 +7163,7 @@ async function saveConfig(config2) {
|
|
|
6553
7163
|
}
|
|
6554
7164
|
async function mergeAndSaveConfig(updates) {
|
|
6555
7165
|
const dir = getConfigDir2();
|
|
6556
|
-
const path =
|
|
7166
|
+
const path = join29(dir, "config.json");
|
|
6557
7167
|
await mkdir15(dir, { recursive: true });
|
|
6558
7168
|
try {
|
|
6559
7169
|
await writeFile15(path, "", { flag: "a" });
|
|
@@ -6624,7 +7234,7 @@ async function showWelcome(currentVersion) {
|
|
|
6624
7234
|
|
|
6625
7235
|
// src/commands/create.ts
|
|
6626
7236
|
import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6627
|
-
import { dirname as
|
|
7237
|
+
import { dirname as dirname13, join as join33 } from "path";
|
|
6628
7238
|
init_src();
|
|
6629
7239
|
import chalk5 from "chalk";
|
|
6630
7240
|
import ora from "ora";
|
|
@@ -6633,7 +7243,7 @@ import ora from "ora";
|
|
|
6633
7243
|
import { createHash as createHash3, randomBytes as randomBytes3 } from "crypto";
|
|
6634
7244
|
import { readFile as readFile14, writeFile as writeFile16, mkdir as mkdir16, chmod as chmod4, unlink as unlink10 } from "fs/promises";
|
|
6635
7245
|
import http from "http";
|
|
6636
|
-
import { join as
|
|
7246
|
+
import { join as join30 } from "path";
|
|
6637
7247
|
var CLI_CALLBACK_PORT = 19876;
|
|
6638
7248
|
var CALLBACK_TIMEOUT_MS = 12e4;
|
|
6639
7249
|
function getCognitoConfigForStorage() {
|
|
@@ -6799,7 +7409,7 @@ async function refreshTokens2(refreshToken) {
|
|
|
6799
7409
|
}
|
|
6800
7410
|
async function getStoredCredentials2() {
|
|
6801
7411
|
try {
|
|
6802
|
-
const credPath =
|
|
7412
|
+
const credPath = join30(getConfigDir2(), "credentials.json");
|
|
6803
7413
|
const data = await readFile14(credPath, "utf-8");
|
|
6804
7414
|
return JSON.parse(data);
|
|
6805
7415
|
} catch (err) {
|
|
@@ -6811,14 +7421,14 @@ async function getStoredCredentials2() {
|
|
|
6811
7421
|
}
|
|
6812
7422
|
async function storeCredentials2(credentials) {
|
|
6813
7423
|
const dir = getConfigDir2();
|
|
6814
|
-
const credPath =
|
|
7424
|
+
const credPath = join30(dir, "credentials.json");
|
|
6815
7425
|
await mkdir16(dir, { recursive: true, mode: 448 });
|
|
6816
7426
|
await writeFile16(credPath, JSON.stringify(credentials, null, 2));
|
|
6817
7427
|
await chmod4(credPath, 384);
|
|
6818
7428
|
}
|
|
6819
7429
|
async function clearCredentials() {
|
|
6820
7430
|
try {
|
|
6821
|
-
await unlink10(
|
|
7431
|
+
await unlink10(join30(getConfigDir2(), "credentials.json"));
|
|
6822
7432
|
} catch (err) {
|
|
6823
7433
|
if (err.code !== "ENOENT") throw err;
|
|
6824
7434
|
}
|
|
@@ -7025,10 +7635,10 @@ async function selectAiTools() {
|
|
|
7025
7635
|
|
|
7026
7636
|
// src/lib/ai-tools.ts
|
|
7027
7637
|
import { readFile as readFile15, writeFile as writeFile17, mkdir as mkdir17 } from "fs/promises";
|
|
7028
|
-
import { join as
|
|
7638
|
+
import { join as join31 } from "path";
|
|
7029
7639
|
var REPOWISE_HOOK_MARKER = "repowise-context";
|
|
7030
7640
|
async function writeClaudeSubagentHook(repoRoot, contextFolder) {
|
|
7031
|
-
const settingsPath =
|
|
7641
|
+
const settingsPath = join31(repoRoot, ".claude", "settings.json");
|
|
7032
7642
|
let settings = {};
|
|
7033
7643
|
try {
|
|
7034
7644
|
const raw = await readFile15(settingsPath, "utf-8");
|
|
@@ -7063,15 +7673,15 @@ async function writeClaudeSubagentHook(repoRoot, contextFolder) {
|
|
|
7063
7673
|
}
|
|
7064
7674
|
hooks["SubagentStart"] = subagentStart;
|
|
7065
7675
|
settings["hooks"] = hooks;
|
|
7066
|
-
await mkdir17(
|
|
7676
|
+
await mkdir17(join31(repoRoot, ".claude"), { recursive: true });
|
|
7067
7677
|
await writeFile17(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
7068
7678
|
}
|
|
7069
7679
|
|
|
7070
7680
|
// src/lib/gitignore.ts
|
|
7071
7681
|
import { readFileSync as readFileSync2, writeFileSync, existsSync } from "fs";
|
|
7072
|
-
import { join as
|
|
7682
|
+
import { join as join32 } from "path";
|
|
7073
7683
|
function ensureGitignore(repoRoot, entry) {
|
|
7074
|
-
const gitignorePath =
|
|
7684
|
+
const gitignorePath = join32(repoRoot, ".gitignore");
|
|
7075
7685
|
if (existsSync(gitignorePath)) {
|
|
7076
7686
|
const content = readFileSync2(gitignorePath, "utf-8");
|
|
7077
7687
|
const lines = content.split("\n").map((l) => l.trim());
|
|
@@ -7861,7 +8471,7 @@ async function create() {
|
|
|
7861
8471
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
7862
8472
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
7863
8473
|
if (files.length > 0) {
|
|
7864
|
-
const contextDir =
|
|
8474
|
+
const contextDir = join33(repoRoot, DEFAULT_CONTEXT_FOLDER);
|
|
7865
8475
|
mkdirSync(contextDir, { recursive: true });
|
|
7866
8476
|
let downloadedCount = 0;
|
|
7867
8477
|
let failedCount = 0;
|
|
@@ -7875,8 +8485,8 @@ async function create() {
|
|
|
7875
8485
|
const response = await fetch(presignedUrl);
|
|
7876
8486
|
if (response.ok) {
|
|
7877
8487
|
const content = await response.text();
|
|
7878
|
-
const filePath =
|
|
7879
|
-
mkdirSync(
|
|
8488
|
+
const filePath = join33(contextDir, file.fileName);
|
|
8489
|
+
mkdirSync(dirname13(filePath), { recursive: true });
|
|
7880
8490
|
writeFileSync2(filePath, content, "utf-8");
|
|
7881
8491
|
downloadedCount++;
|
|
7882
8492
|
} else {
|
|
@@ -8017,7 +8627,7 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
8017
8627
|
|
|
8018
8628
|
// src/commands/member.ts
|
|
8019
8629
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
8020
|
-
import { dirname as
|
|
8630
|
+
import { dirname as dirname14, join as join34, resolve, sep } from "path";
|
|
8021
8631
|
import chalk6 from "chalk";
|
|
8022
8632
|
import ora2 from "ora";
|
|
8023
8633
|
var DEFAULT_CONTEXT_FOLDER2 = "repowise-context";
|
|
@@ -8141,7 +8751,7 @@ async function member() {
|
|
|
8141
8751
|
spinner.succeed(`Found ${chalk6.bold(files.length)} context files on server`);
|
|
8142
8752
|
const { tools } = await selectAiTools();
|
|
8143
8753
|
spinner.start("Downloading context files...");
|
|
8144
|
-
const contextDir =
|
|
8754
|
+
const contextDir = join34(repoRoot, DEFAULT_CONTEXT_FOLDER2);
|
|
8145
8755
|
mkdirSync2(contextDir, { recursive: true });
|
|
8146
8756
|
let downloadedCount = 0;
|
|
8147
8757
|
let failedCount = 0;
|
|
@@ -8162,7 +8772,7 @@ async function member() {
|
|
|
8162
8772
|
const response = await fetch(presignedUrl);
|
|
8163
8773
|
if (response.ok) {
|
|
8164
8774
|
const content = await response.text();
|
|
8165
|
-
mkdirSync2(
|
|
8775
|
+
mkdirSync2(dirname14(safePath), { recursive: true });
|
|
8166
8776
|
writeFileSync3(safePath, content, "utf-8");
|
|
8167
8777
|
downloadedCount++;
|
|
8168
8778
|
} else {
|
|
@@ -8286,15 +8896,15 @@ import chalk7 from "chalk";
|
|
|
8286
8896
|
import ora3 from "ora";
|
|
8287
8897
|
|
|
8288
8898
|
// 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 =
|
|
8899
|
+
import { promises as fs11 } from "fs";
|
|
8900
|
+
import { homedir as homedir6 } from "os";
|
|
8901
|
+
import { join as join35 } from "path";
|
|
8902
|
+
async function purgeForeignGraphs(validRepoIds, home = homedir6()) {
|
|
8903
|
+
const graphsDir = join35(home, ".repowise", "graphs");
|
|
8294
8904
|
const result = { kept: [], removed: [] };
|
|
8295
8905
|
let entries;
|
|
8296
8906
|
try {
|
|
8297
|
-
entries = await
|
|
8907
|
+
entries = await fs11.readdir(graphsDir);
|
|
8298
8908
|
} catch (err) {
|
|
8299
8909
|
if (err.code === "ENOENT") return result;
|
|
8300
8910
|
throw err;
|
|
@@ -8308,15 +8918,15 @@ async function purgeForeignGraphs(validRepoIds, home = homedir5()) {
|
|
|
8308
8918
|
result.kept.push(entry);
|
|
8309
8919
|
continue;
|
|
8310
8920
|
}
|
|
8311
|
-
const path =
|
|
8921
|
+
const path = join35(graphsDir, entry);
|
|
8312
8922
|
try {
|
|
8313
|
-
const stat7 = await
|
|
8923
|
+
const stat7 = await fs11.lstat(path);
|
|
8314
8924
|
if (stat7.isSymbolicLink()) {
|
|
8315
|
-
await
|
|
8925
|
+
await fs11.unlink(path);
|
|
8316
8926
|
result.removed.push(entry);
|
|
8317
8927
|
continue;
|
|
8318
8928
|
}
|
|
8319
|
-
await
|
|
8929
|
+
await fs11.rm(path, { recursive: true, force: true });
|
|
8320
8930
|
result.removed.push(entry);
|
|
8321
8931
|
} catch {
|
|
8322
8932
|
}
|
|
@@ -8401,11 +9011,11 @@ async function logout() {
|
|
|
8401
9011
|
|
|
8402
9012
|
// src/commands/status.ts
|
|
8403
9013
|
import { readFile as readFile16 } from "fs/promises";
|
|
8404
|
-
import { basename as basename2, join as
|
|
9014
|
+
import { basename as basename2, join as join36 } from "path";
|
|
8405
9015
|
async function status() {
|
|
8406
9016
|
const configDir = getConfigDir2();
|
|
8407
|
-
const STATE_PATH =
|
|
8408
|
-
const CONFIG_PATH =
|
|
9017
|
+
const STATE_PATH = join36(configDir, "listener-state.json");
|
|
9018
|
+
const CONFIG_PATH = join36(configDir, "config.json");
|
|
8409
9019
|
let state = null;
|
|
8410
9020
|
try {
|
|
8411
9021
|
const data = await readFile16(STATE_PATH, "utf-8");
|
|
@@ -8453,7 +9063,7 @@ async function status() {
|
|
|
8453
9063
|
|
|
8454
9064
|
// src/commands/sync.ts
|
|
8455
9065
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
8456
|
-
import { dirname as
|
|
9066
|
+
import { dirname as dirname15, join as join37 } from "path";
|
|
8457
9067
|
import chalk9 from "chalk";
|
|
8458
9068
|
import ora4 from "ora";
|
|
8459
9069
|
var POLL_INTERVAL_MS2 = 3e3;
|
|
@@ -8602,7 +9212,7 @@ async function sync() {
|
|
|
8602
9212
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
8603
9213
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
8604
9214
|
if (files.length > 0) {
|
|
8605
|
-
const contextDir =
|
|
9215
|
+
const contextDir = join37(repoRoot, DEFAULT_CONTEXT_FOLDER3);
|
|
8606
9216
|
mkdirSync3(contextDir, { recursive: true });
|
|
8607
9217
|
let downloadedCount = 0;
|
|
8608
9218
|
let failedCount = 0;
|
|
@@ -8616,8 +9226,8 @@ async function sync() {
|
|
|
8616
9226
|
const response = await fetch(presignedUrl);
|
|
8617
9227
|
if (response.ok) {
|
|
8618
9228
|
const content = await response.text();
|
|
8619
|
-
const filePath =
|
|
8620
|
-
mkdirSync3(
|
|
9229
|
+
const filePath = join37(contextDir, file.fileName);
|
|
9230
|
+
mkdirSync3(dirname15(filePath), { recursive: true });
|
|
8621
9231
|
writeFileSync4(filePath, content, "utf-8");
|
|
8622
9232
|
downloadedCount++;
|
|
8623
9233
|
} else {
|
|
@@ -8869,7 +9479,7 @@ async function config() {
|
|
|
8869
9479
|
// src/commands/mcp-log.ts
|
|
8870
9480
|
import { createDecipheriv as createDecipheriv2 } from "crypto";
|
|
8871
9481
|
import { mkdir as mkdir18, readFile as readFile17, stat as stat6, writeFile as writeFile18 } from "fs/promises";
|
|
8872
|
-
import { dirname as
|
|
9482
|
+
import { dirname as dirname16, join as join38 } from "path";
|
|
8873
9483
|
var FLAG_FILE = "mcp-log.flag";
|
|
8874
9484
|
var LOG_FILE = "mcp-log.jsonl.enc";
|
|
8875
9485
|
var KEY_FILE = "mcp-log.key";
|
|
@@ -8877,10 +9487,10 @@ var ENDPOINT_FILE = "listener.endpoint";
|
|
|
8877
9487
|
var IV_BYTES2 = 12;
|
|
8878
9488
|
var TAG_BYTES2 = 16;
|
|
8879
9489
|
function flagPath() {
|
|
8880
|
-
return
|
|
9490
|
+
return join38(getConfigDir2(), FLAG_FILE);
|
|
8881
9491
|
}
|
|
8882
9492
|
function logPath() {
|
|
8883
|
-
return
|
|
9493
|
+
return join38(getConfigDir2(), LOG_FILE);
|
|
8884
9494
|
}
|
|
8885
9495
|
async function readFlag() {
|
|
8886
9496
|
try {
|
|
@@ -8896,7 +9506,7 @@ async function readFlag() {
|
|
|
8896
9506
|
}
|
|
8897
9507
|
async function writeFlag(flag) {
|
|
8898
9508
|
const path = flagPath();
|
|
8899
|
-
await mkdir18(
|
|
9509
|
+
await mkdir18(dirname16(path), { recursive: true });
|
|
8900
9510
|
await writeFile18(path, JSON.stringify(flag, null, 2), { encoding: "utf-8", mode: 384 });
|
|
8901
9511
|
}
|
|
8902
9512
|
async function showConsentPrompt() {
|
|
@@ -8967,14 +9577,14 @@ async function trySendConsentToServer() {
|
|
|
8967
9577
|
let apiUrl = null;
|
|
8968
9578
|
let token = null;
|
|
8969
9579
|
try {
|
|
8970
|
-
const body = await readFile17(
|
|
9580
|
+
const body = await readFile17(join38(getConfigDir2(), "config.json"), "utf-8");
|
|
8971
9581
|
const parsed = JSON.parse(body);
|
|
8972
9582
|
apiUrl = parsed.repos?.find((r) => Boolean(r.apiUrl))?.apiUrl ?? parsed.defaultApiUrl ?? null;
|
|
8973
9583
|
} catch {
|
|
8974
9584
|
return false;
|
|
8975
9585
|
}
|
|
8976
9586
|
try {
|
|
8977
|
-
const body = await readFile17(
|
|
9587
|
+
const body = await readFile17(join38(getConfigDir2(), "credentials.json"), "utf-8");
|
|
8978
9588
|
const parsed = JSON.parse(body);
|
|
8979
9589
|
token = parsed.idToken ?? null;
|
|
8980
9590
|
} catch {
|
|
@@ -9027,7 +9637,7 @@ async function mcpLogStatus() {
|
|
|
9027
9637
|
process.stderr.write("Log size: no file yet\n");
|
|
9028
9638
|
}
|
|
9029
9639
|
try {
|
|
9030
|
-
const endpointBody = await readFile17(
|
|
9640
|
+
const endpointBody = await readFile17(join38(getConfigDir2(), ENDPOINT_FILE), "utf-8");
|
|
9031
9641
|
const match = /endpoint=([^\n]+)/.exec(endpointBody);
|
|
9032
9642
|
process.stderr.write(`MCP endpoint: ${match?.[1] ?? "(malformed endpoint file)"}
|
|
9033
9643
|
`);
|
|
@@ -9054,7 +9664,7 @@ Run \`repowise mcp-log on\` to grant consent and view them.
|
|
|
9054
9664
|
const key = await readKey();
|
|
9055
9665
|
if (!key) {
|
|
9056
9666
|
process.stderr.write(
|
|
9057
|
-
`No encryption key at ${
|
|
9667
|
+
`No encryption key at ${join38(getConfigDir2(), KEY_FILE)} \u2014 listener may not have started yet.
|
|
9058
9668
|
`
|
|
9059
9669
|
);
|
|
9060
9670
|
return;
|
|
@@ -9130,7 +9740,7 @@ Run \`repowise mcp-log on\` to grant consent and view them.
|
|
|
9130
9740
|
}
|
|
9131
9741
|
async function readKey() {
|
|
9132
9742
|
try {
|
|
9133
|
-
const body = await readFile17(
|
|
9743
|
+
const body = await readFile17(join38(getConfigDir2(), KEY_FILE), "utf-8");
|
|
9134
9744
|
const parsed = Buffer.from(body.trim(), "base64");
|
|
9135
9745
|
if (parsed.length !== 32) return null;
|
|
9136
9746
|
return parsed;
|
|
@@ -9173,8 +9783,8 @@ async function mcpLog(subcommand, flags = {}) {
|
|
|
9173
9783
|
import chalk11 from "chalk";
|
|
9174
9784
|
|
|
9175
9785
|
// src/lib/graph-loader.ts
|
|
9176
|
-
import { promises as
|
|
9177
|
-
import { join as
|
|
9786
|
+
import { promises as fs12 } from "fs";
|
|
9787
|
+
import { join as join39, resolve as resolve2 } from "path";
|
|
9178
9788
|
import { gunzipSync } from "zlib";
|
|
9179
9789
|
var RELATIVE_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json";
|
|
9180
9790
|
var GZIPPED_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json.gz";
|
|
@@ -9191,8 +9801,8 @@ var GraphNotFoundError = class extends Error {
|
|
|
9191
9801
|
var cache = /* @__PURE__ */ new Map();
|
|
9192
9802
|
async function loadGraph(repoRoot = process.cwd()) {
|
|
9193
9803
|
const root = resolve2(repoRoot);
|
|
9194
|
-
const gzPath =
|
|
9195
|
-
const plainPath =
|
|
9804
|
+
const gzPath = join39(root, GZIPPED_GRAPH_PATH);
|
|
9805
|
+
const plainPath = join39(root, RELATIVE_GRAPH_PATH);
|
|
9196
9806
|
const cached = cache.get(root);
|
|
9197
9807
|
if (cached) {
|
|
9198
9808
|
return { graph: cached, path: plainPath, bytes: 0, parseMs: 0, fromCache: true };
|
|
@@ -9200,14 +9810,14 @@ async function loadGraph(repoRoot = process.cwd()) {
|
|
|
9200
9810
|
let graphPath = null;
|
|
9201
9811
|
let raw = null;
|
|
9202
9812
|
try {
|
|
9203
|
-
raw = await
|
|
9813
|
+
raw = await fs12.readFile(gzPath);
|
|
9204
9814
|
graphPath = gzPath;
|
|
9205
9815
|
} catch (err) {
|
|
9206
9816
|
if (err.code !== "ENOENT") throw err;
|
|
9207
9817
|
}
|
|
9208
9818
|
if (!raw) {
|
|
9209
9819
|
try {
|
|
9210
|
-
raw = await
|
|
9820
|
+
raw = await fs12.readFile(plainPath);
|
|
9211
9821
|
graphPath = plainPath;
|
|
9212
9822
|
} catch (err) {
|
|
9213
9823
|
if (err.code === "ENOENT") {
|
|
@@ -9606,14 +10216,14 @@ function registerQueryCommand(program2) {
|
|
|
9606
10216
|
}
|
|
9607
10217
|
|
|
9608
10218
|
// src/commands/uninstall.ts
|
|
9609
|
-
import { promises as
|
|
9610
|
-
import { homedir as
|
|
9611
|
-
import { join as
|
|
10219
|
+
import { promises as fs16 } from "fs";
|
|
10220
|
+
import { homedir as homedir8 } from "os";
|
|
10221
|
+
import { join as join43 } from "path";
|
|
9612
10222
|
import chalk12 from "chalk";
|
|
9613
10223
|
|
|
9614
10224
|
// src/lib/cleanup/marker-blocks.ts
|
|
9615
|
-
import { promises as
|
|
9616
|
-
import { join as
|
|
10225
|
+
import { promises as fs13 } from "fs";
|
|
10226
|
+
import { join as join40 } from "path";
|
|
9617
10227
|
var MARKER_START = "<!-- repowise-start -->";
|
|
9618
10228
|
var MARKER_END = "<!-- repowise-end -->";
|
|
9619
10229
|
var CONTEXT_FILES = [
|
|
@@ -9629,7 +10239,7 @@ var CONTEXT_FILES = [
|
|
|
9629
10239
|
async function stripMarkerBlock(filePath) {
|
|
9630
10240
|
let raw;
|
|
9631
10241
|
try {
|
|
9632
|
-
raw = await
|
|
10242
|
+
raw = await fs13.readFile(filePath, "utf-8");
|
|
9633
10243
|
} catch (err) {
|
|
9634
10244
|
if (err.code === "ENOENT")
|
|
9635
10245
|
return { path: filePath, status: "missing" };
|
|
@@ -9644,16 +10254,16 @@ async function stripMarkerBlock(filePath) {
|
|
|
9644
10254
|
const after = raw.slice(endIdx + MARKER_END.length).replace(/^\n+/, "");
|
|
9645
10255
|
const stripped = (before + (before && after ? "\n\n" : "") + after).trim();
|
|
9646
10256
|
if (stripped.length === 0) {
|
|
9647
|
-
await
|
|
10257
|
+
await fs13.unlink(filePath);
|
|
9648
10258
|
return { path: filePath, status: "deleted" };
|
|
9649
10259
|
}
|
|
9650
|
-
await
|
|
10260
|
+
await fs13.writeFile(filePath, stripped + "\n", "utf-8");
|
|
9651
10261
|
return { path: filePath, status: "stripped" };
|
|
9652
10262
|
}
|
|
9653
10263
|
async function stripAllMarkerBlocks(repoRoot) {
|
|
9654
10264
|
const out = [];
|
|
9655
10265
|
for (const relative of CONTEXT_FILES) {
|
|
9656
|
-
const full =
|
|
10266
|
+
const full = join40(repoRoot, relative);
|
|
9657
10267
|
const result = await stripMarkerBlock(full).catch((err) => ({
|
|
9658
10268
|
path: full,
|
|
9659
10269
|
status: "untouched",
|
|
@@ -9665,25 +10275,25 @@ async function stripAllMarkerBlocks(repoRoot) {
|
|
|
9665
10275
|
}
|
|
9666
10276
|
|
|
9667
10277
|
// src/lib/cleanup/mcp-configs.ts
|
|
9668
|
-
import { promises as
|
|
9669
|
-
import { join as
|
|
10278
|
+
import { promises as fs14 } from "fs";
|
|
10279
|
+
import { join as join41 } from "path";
|
|
9670
10280
|
function mcpConfigPaths(repoRoot, home) {
|
|
9671
10281
|
return [
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
10282
|
+
join41(repoRoot, ".mcp.json"),
|
|
10283
|
+
join41(repoRoot, ".cursor", "mcp.json"),
|
|
10284
|
+
join41(repoRoot, ".vscode", "mcp.json"),
|
|
10285
|
+
join41(repoRoot, ".roo", "mcp.json"),
|
|
10286
|
+
join41(home, ".cline", "mcp.json"),
|
|
10287
|
+
join41(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
10288
|
+
join41(home, ".gemini", "settings.json"),
|
|
10289
|
+
join41(home, ".codex", "mcp.json"),
|
|
10290
|
+
join41(home, ".roo", "mcp.json")
|
|
9681
10291
|
];
|
|
9682
10292
|
}
|
|
9683
10293
|
async function removeRepowiseFromConfig(path, serverName) {
|
|
9684
10294
|
let raw;
|
|
9685
10295
|
try {
|
|
9686
|
-
raw = await
|
|
10296
|
+
raw = await fs14.readFile(path, "utf-8");
|
|
9687
10297
|
} catch (err) {
|
|
9688
10298
|
if (err.code === "ENOENT") return { path, status: "not-found" };
|
|
9689
10299
|
return { path, status: "error", error: err.message };
|
|
@@ -9703,7 +10313,7 @@ async function removeRepowiseFromConfig(path, serverName) {
|
|
|
9703
10313
|
} else {
|
|
9704
10314
|
next.mcpServers = servers;
|
|
9705
10315
|
}
|
|
9706
|
-
await
|
|
10316
|
+
await fs14.writeFile(path, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
9707
10317
|
return { path, status: "removed" };
|
|
9708
10318
|
}
|
|
9709
10319
|
async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
@@ -9716,17 +10326,17 @@ async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
|
9716
10326
|
}
|
|
9717
10327
|
|
|
9718
10328
|
// src/lib/cleanup/local-state.ts
|
|
9719
|
-
import { promises as
|
|
9720
|
-
import { homedir as
|
|
9721
|
-
import { join as
|
|
10329
|
+
import { promises as fs15 } from "fs";
|
|
10330
|
+
import { homedir as homedir7 } from "os";
|
|
10331
|
+
import { join as join42, resolve as resolve3 } from "path";
|
|
9722
10332
|
async function clearLocalState(homeOverride) {
|
|
9723
|
-
const home = homeOverride ??
|
|
9724
|
-
const target = resolve3(
|
|
10333
|
+
const home = homeOverride ?? homedir7();
|
|
10334
|
+
const target = resolve3(join42(home, ".repowise"));
|
|
9725
10335
|
if (target === resolve3(home) || !target.startsWith(resolve3(home))) {
|
|
9726
10336
|
return { path: target, status: "error", error: "refused: not under home" };
|
|
9727
10337
|
}
|
|
9728
10338
|
try {
|
|
9729
|
-
await
|
|
10339
|
+
await fs15.rm(target, { recursive: true, force: false });
|
|
9730
10340
|
return { path: target, status: "removed" };
|
|
9731
10341
|
} catch (err) {
|
|
9732
10342
|
if (err.code === "ENOENT")
|
|
@@ -9756,7 +10366,7 @@ async function stopAndUninstallService(uninstaller) {
|
|
|
9756
10366
|
// src/commands/uninstall.ts
|
|
9757
10367
|
async function uninstall2(opts = {}) {
|
|
9758
10368
|
const tier = opts.tier ?? "uninstall";
|
|
9759
|
-
const home = opts.home ??
|
|
10369
|
+
const home = opts.home ?? homedir8();
|
|
9760
10370
|
const repoRoot = opts.repoRoot ?? process.cwd();
|
|
9761
10371
|
const loadRepoIds = opts.loadRepoIds ?? defaultLoadRepoIds;
|
|
9762
10372
|
const report = { tier, removed: [], preserved: [], skipped: [] };
|
|
@@ -9765,7 +10375,7 @@ async function uninstall2(opts = {}) {
|
|
|
9765
10375
|
else if (svc.error) report.skipped.push({ path: "listener service", reason: svc.error });
|
|
9766
10376
|
if (tier === "stop") return report;
|
|
9767
10377
|
try {
|
|
9768
|
-
await
|
|
10378
|
+
await fs16.unlink(join43(home, ".repowise", "credentials.json"));
|
|
9769
10379
|
report.removed.push("credentials");
|
|
9770
10380
|
} catch (err) {
|
|
9771
10381
|
if (err.code !== "ENOENT") {
|
|
@@ -9792,7 +10402,7 @@ async function uninstall2(opts = {}) {
|
|
|
9792
10402
|
const allPaths = mcpConfigPaths(repoRoot, home);
|
|
9793
10403
|
for (const p of allPaths) {
|
|
9794
10404
|
try {
|
|
9795
|
-
await
|
|
10405
|
+
await fs16.access(p);
|
|
9796
10406
|
} catch {
|
|
9797
10407
|
}
|
|
9798
10408
|
}
|
|
@@ -9804,7 +10414,7 @@ async function uninstall2(opts = {}) {
|
|
|
9804
10414
|
}
|
|
9805
10415
|
async function defaultLoadRepoIds(home) {
|
|
9806
10416
|
try {
|
|
9807
|
-
const raw = await
|
|
10417
|
+
const raw = await fs16.readFile(join43(home, ".repowise", "config.json"), "utf-8");
|
|
9808
10418
|
const parsed = JSON.parse(raw);
|
|
9809
10419
|
return (parsed.repos ?? []).map((r) => r.repoId);
|
|
9810
10420
|
} catch {
|
|
@@ -9850,13 +10460,13 @@ Done \u2014 ${report.removed.length} removed, ${report.skipped.length} skipped.
|
|
|
9850
10460
|
}
|
|
9851
10461
|
|
|
9852
10462
|
// src/commands/mcp-shim.ts
|
|
9853
|
-
import { promises as
|
|
10463
|
+
import { promises as fs17 } from "fs";
|
|
9854
10464
|
import { createInterface as createInterface2 } from "readline";
|
|
9855
|
-
import { homedir as
|
|
9856
|
-
import { join as
|
|
10465
|
+
import { homedir as homedir9 } from "os";
|
|
10466
|
+
import { join as join44 } from "path";
|
|
9857
10467
|
var DEFAULT_MAX = 200 * 1024;
|
|
9858
10468
|
async function mcpShim(opts) {
|
|
9859
|
-
const endpointPath = opts.endpointFile ??
|
|
10469
|
+
const endpointPath = opts.endpointFile ?? join44(homedir9(), ".repowise", "listener.endpoint");
|
|
9860
10470
|
const stdin = opts.stdin ?? process.stdin;
|
|
9861
10471
|
const stdout = opts.stdout ?? process.stdout;
|
|
9862
10472
|
const stderr = opts.stderr ?? process.stderr;
|
|
@@ -9927,7 +10537,7 @@ async function mcpShim(opts) {
|
|
|
9927
10537
|
}
|
|
9928
10538
|
async function readEndpoint(path) {
|
|
9929
10539
|
try {
|
|
9930
|
-
const raw = (await
|
|
10540
|
+
const raw = (await fs17.readFile(path, "utf-8")).trim();
|
|
9931
10541
|
if (!raw) return null;
|
|
9932
10542
|
if (raw.startsWith("http://") || raw.startsWith("https://")) {
|
|
9933
10543
|
return { endpoint: raw.split("\n")[0].trim(), secret: null };
|
|
@@ -10141,14 +10751,14 @@ function writeError(stream, id, code, message) {
|
|
|
10141
10751
|
|
|
10142
10752
|
// src/commands/lsp.ts
|
|
10143
10753
|
init_registry();
|
|
10144
|
-
import { spawn as
|
|
10754
|
+
import { spawn as spawn4 } from "child_process";
|
|
10145
10755
|
import chalk13 from "chalk";
|
|
10146
10756
|
async function isOnPath(command) {
|
|
10147
10757
|
if (/[^\w./+-]/.test(command)) return false;
|
|
10148
10758
|
const isWin = process.platform === "win32";
|
|
10149
10759
|
const probeCmd = isWin ? "where" : "which";
|
|
10150
10760
|
return new Promise((resolve4) => {
|
|
10151
|
-
const child =
|
|
10761
|
+
const child = spawn4(probeCmd, [command], { stdio: "ignore" });
|
|
10152
10762
|
child.on("close", (code) => {
|
|
10153
10763
|
resolve4(code === 0);
|
|
10154
10764
|
});
|
|
@@ -10209,8 +10819,8 @@ async function lspDoctor() {
|
|
|
10209
10819
|
|
|
10210
10820
|
// bin/repowise.ts
|
|
10211
10821
|
var __filename = fileURLToPath4(import.meta.url);
|
|
10212
|
-
var __dirname =
|
|
10213
|
-
var pkg = JSON.parse(readFileSync3(
|
|
10822
|
+
var __dirname = dirname17(__filename);
|
|
10823
|
+
var pkg = JSON.parse(readFileSync3(join45(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
10214
10824
|
var program = new Command();
|
|
10215
10825
|
program.name(getPackageName()).description("AI-optimized codebase context generator").version(pkg.version).hook("preAction", async () => {
|
|
10216
10826
|
await showWelcome(pkg.version);
|