@vibgrate/cli 2026.727.1 → 2026.727.2
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/DOCS.md +0 -17
- package/README.md +0 -1
- package/dist/baseline-TG4ATZGZ.js +8 -0
- package/dist/{baseline-K7YBFKZI.js.map → baseline-TG4ATZGZ.js.map} +1 -1
- package/dist/{chunk-JZYGEZTU.js → chunk-2MBL43EJ.js} +3 -3
- package/dist/{chunk-JZYGEZTU.js.map → chunk-2MBL43EJ.js.map} +1 -1
- package/dist/{chunk-HABUT7HW.js → chunk-2XQDMLKB.js} +240 -8
- package/dist/chunk-2XQDMLKB.js.map +1 -0
- package/dist/{chunk-VXGV6NTD.js → chunk-3V24O47U.js} +11 -9
- package/dist/chunk-3V24O47U.js.map +1 -0
- package/dist/{chunk-6IOQJGFT.js → chunk-6ABXHZRN.js} +34 -77
- package/dist/chunk-6ABXHZRN.js.map +1 -0
- package/dist/{chunk-4CQ3MGNN.js → chunk-6AYDFFP5.js} +3 -3
- package/dist/{chunk-4CQ3MGNN.js.map → chunk-6AYDFFP5.js.map} +1 -1
- package/dist/chunk-6UQMXIAG.js +122 -0
- package/dist/chunk-6UQMXIAG.js.map +1 -0
- package/dist/{chunk-KHJO4D5N.js → chunk-7N4Y3E47.js} +2 -2
- package/dist/{chunk-KHJO4D5N.js.map → chunk-7N4Y3E47.js.map} +1 -1
- package/dist/{chunk-OXQNQW5J.js → chunk-CY4WKXB2.js} +4 -4
- package/dist/{chunk-OXQNQW5J.js.map → chunk-CY4WKXB2.js.map} +1 -1
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/{chunk-HYZVHJ3Q.js → chunk-EX4PQT6W.js} +3 -3
- package/dist/{chunk-HYZVHJ3Q.js.map → chunk-EX4PQT6W.js.map} +1 -1
- package/dist/{chunk-3BVSDMHV.js → chunk-J4RFRKZH.js} +7 -7
- package/dist/{chunk-3BVSDMHV.js.map → chunk-J4RFRKZH.js.map} +1 -1
- package/dist/chunk-K3MZIVZW.js +88 -0
- package/dist/chunk-K3MZIVZW.js.map +1 -0
- package/dist/{chunk-65MEOA4E.js → chunk-KCKYKDMS.js} +9 -8
- package/dist/chunk-KCKYKDMS.js.map +1 -0
- package/dist/{chunk-S6CYDZEW.js → chunk-KNELIQJO.js} +364 -179
- package/dist/chunk-KNELIQJO.js.map +1 -0
- package/dist/{chunk-EDAAG7BL.js → chunk-KSBHGWRV.js} +4 -3
- package/dist/chunk-KSBHGWRV.js.map +1 -0
- package/dist/{chunk-C4CKTAZP.js → chunk-LKVMI67M.js} +4 -4
- package/dist/chunk-LKVMI67M.js.map +1 -0
- package/dist/{chunk-7JHPQ6WF.js → chunk-OFUC6RYN.js} +3 -3
- package/dist/{chunk-7JHPQ6WF.js.map → chunk-OFUC6RYN.js.map} +1 -1
- package/dist/{chunk-YDAT7LD2.js → chunk-RNP3SMTV.js} +17 -9
- package/dist/chunk-RNP3SMTV.js.map +1 -0
- package/dist/{chunk-SZLF66FJ.js → chunk-TCDAZZNP.js} +5 -5
- package/dist/{chunk-SZLF66FJ.js.map → chunk-TCDAZZNP.js.map} +1 -1
- package/dist/{chunk-WLETRGAC.js → chunk-WGUL45AV.js} +11 -11
- package/dist/{chunk-WLETRGAC.js.map → chunk-WGUL45AV.js.map} +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +97 -240
- package/dist/cli.js.map +1 -1
- package/dist/{execution-env-3BN7Z737.js → execution-env-ZU45JZ4G.js} +3 -2
- package/dist/{execution-env-3BN7Z737.js.map → execution-env-ZU45JZ4G.js.map} +1 -1
- package/dist/{federation-EPZDUWCK.js → federation-SZWZIFZ7.js} +3 -2
- package/dist/{federation-EPZDUWCK.js.map → federation-SZWZIFZ7.js.map} +1 -1
- package/dist/{fs-IPY4FJKH.js → fs-B5HZ2MIU.js} +3 -2
- package/dist/fs-B5HZ2MIU.js.map +1 -0
- package/dist/{fs-KCABDURV.js → fs-O5IQYXHO.js} +3 -2
- package/dist/fs-O5IQYXHO.js.map +1 -0
- package/dist/{git-ref-HPRLUFFW.js → git-ref-XDXB6JP5.js} +3 -2
- package/dist/{git-ref-HPRLUFFW.js.map → git-ref-XDXB6JP5.js.map} +1 -1
- package/dist/graph-backend-73URGTFY.js +11 -0
- package/dist/{graph-backend-ZMSYOZMW.js.map → graph-backend-73URGTFY.js.map} +1 -1
- package/dist/index.d.ts +44 -15
- package/dist/index.js +9 -8
- package/dist/index.js.map +1 -1
- package/dist/{interactive-ICL7D7LO.js → interactive-372NLI5C.js} +19 -18
- package/dist/interactive-372NLI5C.js.map +1 -0
- package/dist/{llm-host-2RAYQSDQ.js → llm-host-7GWDO6IX.js} +3 -2
- package/dist/{llm-host-2RAYQSDQ.js.map → llm-host-7GWDO6IX.js.map} +1 -1
- package/dist/load-I333TGNI.js +8 -0
- package/dist/{load-OHVKDX4R.js.map → load-I333TGNI.js.map} +1 -1
- package/dist/local-runtime-5O2NN3GA.js +5 -0
- package/dist/{local-runtime-OJFLX2HI.js.map → local-runtime-5O2NN3GA.js.map} +1 -1
- package/dist/mcp-tools-I7JK3S2M.js +4 -0
- package/dist/{mcp-tools-I6PME3AV.js.map → mcp-tools-I7JK3S2M.js.map} +1 -1
- package/dist/{model-execution-profile-MQ2QCP24.js → model-execution-profile-TFBKCNJG.js} +3 -2
- package/dist/{model-execution-profile-MQ2QCP24.js.map → model-execution-profile-TFBKCNJG.js.map} +1 -1
- package/dist/{model-orchestrator-FFTZI3U2.js → model-orchestrator-TVONAUPS.js} +5 -4
- package/dist/{model-orchestrator-FFTZI3U2.js.map → model-orchestrator-TVONAUPS.js.map} +1 -1
- package/dist/parse-worker.d.ts +1 -1
- package/dist/parse-worker.js +1 -0
- package/dist/parse-worker.js.map +1 -1
- package/dist/{paths-MCH75O3G.js → paths-2RAH3GME.js} +3 -2
- package/dist/{paths-MCH75O3G.js.map → paths-2RAH3GME.js.map} +1 -1
- package/dist/{resolve-gguf-4UPIGPEE.js → resolve-gguf-VPL4YQ6J.js} +3 -2
- package/dist/{resolve-gguf-4UPIGPEE.js.map → resolve-gguf-VPL4YQ6J.js.map} +1 -1
- package/dist/runtime-session-JRKCQUHY.js +18 -0
- package/dist/{runtime-session-IDU5BDUJ.js.map → runtime-session-JRKCQUHY.js.map} +1 -1
- package/dist/session-ITPYQ5XI.js +11 -0
- package/dist/{session-L2OSDRPI.js.map → session-ITPYQ5XI.js.map} +1 -1
- package/dist/session-store-WFBX7HXL.js +4 -0
- package/dist/{session-store-W5RZZHA3.js.map → session-store-WFBX7HXL.js.map} +1 -1
- package/dist/{stream-json-F74W5FCK.js → stream-json-SLMDKLXP.js} +10 -9
- package/dist/stream-json-SLMDKLXP.js.map +1 -0
- package/dist/{types-ZMg1mSuu.d.ts → types-7AHBUbFm.d.ts} +5 -1
- package/dist/ui-Q6DJ3GCU.js +5 -0
- package/dist/ui-Q6DJ3GCU.js.map +1 -0
- package/dist/{vgd-EGBQD7BW.js → vgd-7JV5KCNJ.js} +7 -6
- package/dist/vgd-7JV5KCNJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/baseline-K7YBFKZI.js +0 -7
- package/dist/chunk-5Q54GEHM.js +0 -29
- package/dist/chunk-5Q54GEHM.js.map +0 -1
- package/dist/chunk-65MEOA4E.js.map +0 -1
- package/dist/chunk-6IOQJGFT.js.map +0 -1
- package/dist/chunk-C4CKTAZP.js.map +0 -1
- package/dist/chunk-EDAAG7BL.js.map +0 -1
- package/dist/chunk-EDBV33B7.js +0 -57
- package/dist/chunk-EDBV33B7.js.map +0 -1
- package/dist/chunk-HABUT7HW.js.map +0 -1
- package/dist/chunk-S6CYDZEW.js.map +0 -1
- package/dist/chunk-VXGV6NTD.js.map +0 -1
- package/dist/chunk-YDAT7LD2.js.map +0 -1
- package/dist/fs-IPY4FJKH.js.map +0 -1
- package/dist/fs-KCABDURV.js.map +0 -1
- package/dist/graph-backend-ZMSYOZMW.js +0 -10
- package/dist/interactive-ICL7D7LO.js.map +0 -1
- package/dist/load-OHVKDX4R.js +0 -7
- package/dist/local-runtime-OJFLX2HI.js +0 -4
- package/dist/mcp-tools-I6PME3AV.js +0 -3
- package/dist/runtime-session-IDU5BDUJ.js +0 -17
- package/dist/session-L2OSDRPI.js +0 -10
- package/dist/session-store-W5RZZHA3.js +0 -3
- package/dist/stream-json-F74W5FCK.js.map +0 -1
- package/dist/ui-HOVOPWMX.js +0 -4
- package/dist/ui-HOVOPWMX.js.map +0 -1
- package/dist/vgd-EGBQD7BW.js.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-
|
|
2
|
-
import { resolveVersion, resolveLib, loadCatalog, driftFor, localPackageDocs, readDoc, inventory, localApiSurface, edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-
|
|
1
|
+
import { loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-WGUL45AV.js';
|
|
2
|
+
import { resolveVersion, resolveLib, loadCatalog, driftFor, localPackageDocs, readDoc, inventory, localApiSurface, edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-LKVMI67M.js';
|
|
3
3
|
import { resolveOne, findNodes } from './chunk-J7LKEB2R.js';
|
|
4
4
|
import { discoverModels } from './chunk-OOIG3RUM.js';
|
|
5
|
-
import { impactOf, indexFor, withTimeout, getNodeEmbeddings, queryGraphSemantic, queryGraph, loadEmbedder, isModelReady,
|
|
5
|
+
import { impactOf, indexFor, withTimeout, getNodeEmbeddings, queryGraphSemantic, queryGraph, loadEmbedder, isModelReady, acquireLock, releaseLock } from './chunk-6ABXHZRN.js';
|
|
6
6
|
import { langById, grammarSetVersion, langForExtension, setGrammarsOverride, parseSource } from './chunk-3Q7QBWFW.js';
|
|
7
7
|
import { redactSecrets } from './chunk-RXP66R2E.js';
|
|
8
|
-
import { loadGraph, ensureVibgrateGitignore, vibgrateDir, writeArtifacts } from './chunk-
|
|
9
|
-
import { serializeGraph, stableStringify } from './chunk-
|
|
8
|
+
import { writeGraphIndex, SCHEMA_VERSION, loadGraph, ensureVibgrateGitignore, vibgrateDir, writeArtifacts } from './chunk-2XQDMLKB.js';
|
|
9
|
+
import { cacheDir, loadCache, serializeGraph, stableStringify } from './chunk-K3MZIVZW.js';
|
|
10
10
|
import { shortId, canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
|
|
11
11
|
import { writeTextFile, pathExists, readJsonFile } from './chunk-CRAMOEBE.js';
|
|
12
|
-
import * as
|
|
12
|
+
import * as fs16 from 'fs';
|
|
13
13
|
import { spawnSync, execFileSync } from 'child_process';
|
|
14
|
-
import * as
|
|
14
|
+
import * as path18 from 'path';
|
|
15
15
|
import ignore from 'ignore';
|
|
16
16
|
import * as v8 from 'v8';
|
|
17
17
|
import Graph from 'graphology';
|
|
@@ -46,9 +46,9 @@ function whichOnPath(cmd) {
|
|
|
46
46
|
}
|
|
47
47
|
function isOwnBinary(binPath) {
|
|
48
48
|
try {
|
|
49
|
-
const real =
|
|
49
|
+
const real = fs16.realpathSync(binPath);
|
|
50
50
|
if (/[\\/]@vibgrate[\\/]cli[\\/]/.test(real)) return true;
|
|
51
|
-
const head =
|
|
51
|
+
const head = fs16.readFileSync(real, { encoding: "utf8" }).slice(0, 2048);
|
|
52
52
|
return head.includes("@vibgrate/cli") || head.includes("vibgrate");
|
|
53
53
|
} catch {
|
|
54
54
|
return false;
|
|
@@ -58,7 +58,7 @@ function isEphemeralNpxBinary(binPath) {
|
|
|
58
58
|
const NPX_SEGMENT = /[\\/]_npx[\\/]/;
|
|
59
59
|
if (NPX_SEGMENT.test(binPath)) return true;
|
|
60
60
|
try {
|
|
61
|
-
return NPX_SEGMENT.test(
|
|
61
|
+
return NPX_SEGMENT.test(fs16.realpathSync(binPath));
|
|
62
62
|
} catch {
|
|
63
63
|
return false;
|
|
64
64
|
}
|
|
@@ -235,19 +235,19 @@ var SKIP_FILES = /* @__PURE__ */ new Set([
|
|
|
235
235
|
"flake.lock"
|
|
236
236
|
]);
|
|
237
237
|
function toPosix(p) {
|
|
238
|
-
return p.split(
|
|
238
|
+
return p.split(path18.sep).join("/");
|
|
239
239
|
}
|
|
240
240
|
function buildRootIgnore(root, exclude) {
|
|
241
241
|
const ig = ignore();
|
|
242
|
-
const gitignorePath =
|
|
243
|
-
if (
|
|
244
|
-
ig.add(
|
|
242
|
+
const gitignorePath = path18.join(root, ".gitignore");
|
|
243
|
+
if (fs16.existsSync(gitignorePath)) {
|
|
244
|
+
ig.add(fs16.readFileSync(gitignorePath, "utf8"));
|
|
245
245
|
}
|
|
246
246
|
if (exclude.length) ig.add(exclude);
|
|
247
247
|
return ig;
|
|
248
248
|
}
|
|
249
249
|
function discover(options) {
|
|
250
|
-
const root =
|
|
250
|
+
const root = path18.resolve(options.root);
|
|
251
251
|
const onlyLangs = (options.only ?? []).filter(Boolean);
|
|
252
252
|
const allowLang = (lang) => onlyLangs.length === 0 || onlyLangs.includes(lang.id);
|
|
253
253
|
for (const id of onlyLangs) {
|
|
@@ -256,27 +256,27 @@ function discover(options) {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
const rootIg = buildRootIgnore(root, options.exclude ?? []);
|
|
259
|
-
const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) =>
|
|
259
|
+
const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path18.resolve(root, p)) : [root]).filter((p) => fs16.existsSync(p));
|
|
260
260
|
const found = /* @__PURE__ */ new Map();
|
|
261
261
|
const considerFile = (abs) => {
|
|
262
|
-
const rel2 = toPosix(
|
|
262
|
+
const rel2 = toPosix(path18.relative(root, abs));
|
|
263
263
|
if (rel2.startsWith("..")) return;
|
|
264
264
|
if (rel2 === "" || rootIg.ignores(rel2)) return;
|
|
265
|
-
if (SKIP_FILES.has(
|
|
266
|
-
const lang = langForExtension(
|
|
265
|
+
if (SKIP_FILES.has(path18.basename(abs).toLowerCase())) return;
|
|
266
|
+
const lang = langForExtension(path18.extname(abs));
|
|
267
267
|
if (!lang || !allowLang(lang)) return;
|
|
268
268
|
found.set(rel2, { rel: rel2, abs, lang });
|
|
269
269
|
};
|
|
270
270
|
const walk = (dir) => {
|
|
271
271
|
let entries;
|
|
272
272
|
try {
|
|
273
|
-
entries =
|
|
273
|
+
entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
274
274
|
} catch {
|
|
275
275
|
return;
|
|
276
276
|
}
|
|
277
277
|
for (const entry of entries) {
|
|
278
|
-
const abs =
|
|
279
|
-
const rel2 = toPosix(
|
|
278
|
+
const abs = path18.join(dir, entry.name);
|
|
279
|
+
const rel2 = toPosix(path18.relative(root, abs));
|
|
280
280
|
if (entry.isDirectory()) {
|
|
281
281
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
282
282
|
if (rel2 && rootIg.ignores(`${rel2}/`)) continue;
|
|
@@ -287,7 +287,7 @@ function discover(options) {
|
|
|
287
287
|
}
|
|
288
288
|
};
|
|
289
289
|
for (const scope of scopeAbs) {
|
|
290
|
-
const stat =
|
|
290
|
+
const stat = fs16.statSync(scope);
|
|
291
291
|
if (stat.isDirectory()) walk(scope);
|
|
292
292
|
else if (stat.isFile()) considerFile(scope);
|
|
293
293
|
}
|
|
@@ -540,25 +540,36 @@ function mulberry32(seed) {
|
|
|
540
540
|
var CLUSTER_SEED = 42;
|
|
541
541
|
|
|
542
542
|
// src/engine/analyze.ts
|
|
543
|
+
var TIER_LARGE_NODES = 5e3;
|
|
544
|
+
var TIER_XL_NODES = 5e4;
|
|
545
|
+
function pickAnalysisTier(nodeCount, forced) {
|
|
546
|
+
if (forced) return forced;
|
|
547
|
+
if (nodeCount > TIER_XL_NODES) return "xl";
|
|
548
|
+
if (nodeCount > TIER_LARGE_NODES) return "large";
|
|
549
|
+
return "full";
|
|
550
|
+
}
|
|
543
551
|
var DEP_EDGES = /* @__PURE__ */ new Set(["call", "import", "extends", "implements", "references"]);
|
|
544
552
|
var CLUSTER_EDGE_KINDS = /* @__PURE__ */ new Set([...DEP_EDGES, "contains"]);
|
|
545
553
|
var IMPORTANCE_WEIGHTS = { pagerank: 0.4, betweenness: 0.25, eigenvector: 0.2, degree: 0.15 };
|
|
546
554
|
var DEFAULT_BETWEENNESS_LIMIT = 5e3;
|
|
547
555
|
function analyze(nodes, edges, options = {}) {
|
|
548
|
-
const
|
|
556
|
+
const tier = pickAnalysisTier(nodes.length, options.tier);
|
|
557
|
+
const mode = options.cluster ?? (tier === "xl" ? "louvain" : "louvain");
|
|
549
558
|
const ids = [...nodes.map((n) => n.id)].sort((a, b) => a.localeCompare(b));
|
|
550
559
|
const dg = simpleGraph(ids, edges, DEP_EDGES, "directed");
|
|
551
560
|
const pr = safeMetric(() => pagerank(dg), ids);
|
|
552
|
-
const
|
|
553
|
-
const
|
|
561
|
+
const bwLimit = options.betweennessLimit ?? DEFAULT_BETWEENNESS_LIMIT;
|
|
562
|
+
const bw = tier === "full" && dg.order <= bwLimit ? safeMetric(() => betweenness(dg), ids) : zeros(ids);
|
|
563
|
+
const ev = tier === "full" || tier === "large" ? safeMetric(() => eigenvector(dg), ids) : zeros(ids);
|
|
554
564
|
const deg = degreeMap(dg, ids);
|
|
555
565
|
const prN = normalize(pr);
|
|
556
566
|
const bwN = normalize(bw);
|
|
557
567
|
const evN = normalize(ev);
|
|
558
568
|
const degN = normalize(deg);
|
|
569
|
+
const weights = tier === "xl" ? { pagerank: 0.7, betweenness: 0, eigenvector: 0, degree: 0.3 } : tier === "large" ? { pagerank: 0.5, betweenness: 0, eigenvector: 0.25, degree: 0.25 } : IMPORTANCE_WEIGHTS;
|
|
559
570
|
const importance = /* @__PURE__ */ new Map();
|
|
560
571
|
for (const id of ids) {
|
|
561
|
-
const score =
|
|
572
|
+
const score = weights.pagerank * (prN.get(id) ?? 0) + weights.betweenness * (bwN.get(id) ?? 0) + weights.eigenvector * (evN.get(id) ?? 0) + weights.degree * (degN.get(id) ?? 0);
|
|
562
573
|
importance.set(id, score);
|
|
563
574
|
}
|
|
564
575
|
const importanceN = normalize(importance);
|
|
@@ -567,7 +578,7 @@ function analyze(nodes, edges, options = {}) {
|
|
|
567
578
|
const variance = vals.reduce((a, b) => a + (b - mean) ** 2, 0) / (vals.length || 1);
|
|
568
579
|
const std = Math.sqrt(variance);
|
|
569
580
|
const hubThreshold = mean + 2 * std;
|
|
570
|
-
const { areaByNode, mode: actualMode } = cluster(ids, edges, mode);
|
|
581
|
+
const { areaByNode, mode: actualMode } = tier === "xl" ? clusterFileLevel(nodes, edges, mode) : cluster(ids, edges, mode);
|
|
571
582
|
const outNodes = nodes.map((n) => ({
|
|
572
583
|
...n,
|
|
573
584
|
centrality: {
|
|
@@ -582,7 +593,42 @@ function analyze(nodes, edges, options = {}) {
|
|
|
582
593
|
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
583
594
|
const areas = buildAreas(outNodes, edges, areaByNode);
|
|
584
595
|
const outEdges = scoreSurprise(edges, areaByNode);
|
|
585
|
-
return { nodes: outNodes, edges: outEdges, areas, cluster: actualMode };
|
|
596
|
+
return { nodes: outNodes, edges: outEdges, areas, cluster: actualMode, tier };
|
|
597
|
+
}
|
|
598
|
+
function clusterFileLevel(nodes, edges, mode) {
|
|
599
|
+
const fileNodes = nodes.filter((n) => n.kind === "file");
|
|
600
|
+
const fileIds = fileNodes.map((n) => n.id).sort((a, b) => a.localeCompare(b));
|
|
601
|
+
if (fileIds.length === 0) {
|
|
602
|
+
return { areaByNode: new Map(nodes.map((n) => [n.id, -1])), mode: "none" };
|
|
603
|
+
}
|
|
604
|
+
const fileIdByPath = new Map(fileNodes.map((n) => [n.file, n.id]));
|
|
605
|
+
const fileOf = /* @__PURE__ */ new Map();
|
|
606
|
+
for (const n of nodes) {
|
|
607
|
+
if (n.kind === "file") fileOf.set(n.id, n.id);
|
|
608
|
+
else if (n.file) {
|
|
609
|
+
const fid = fileIdByPath.get(n.file);
|
|
610
|
+
if (fid) fileOf.set(n.id, fid);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
const fileEdges = [];
|
|
614
|
+
const seen = /* @__PURE__ */ new Set();
|
|
615
|
+
for (const e of edges) {
|
|
616
|
+
if (!DEP_EDGES.has(e.kind)) continue;
|
|
617
|
+
const sf = fileOf.get(e.src);
|
|
618
|
+
const df = fileOf.get(e.dst);
|
|
619
|
+
if (!sf || !df || sf === df) continue;
|
|
620
|
+
const key = `${e.kind}|${sf}|${df}`;
|
|
621
|
+
if (seen.has(key)) continue;
|
|
622
|
+
seen.add(key);
|
|
623
|
+
fileEdges.push({ ...e, src: sf, dst: df, id: key });
|
|
624
|
+
}
|
|
625
|
+
const { areaByNode: fileAreas, mode: used } = cluster(fileIds, fileEdges, mode);
|
|
626
|
+
const areaByNode = /* @__PURE__ */ new Map();
|
|
627
|
+
for (const n of nodes) {
|
|
628
|
+
const fid = fileOf.get(n.id);
|
|
629
|
+
areaByNode.set(n.id, fid ? fileAreas.get(fid) ?? -1 : -1);
|
|
630
|
+
}
|
|
631
|
+
return { areaByNode, mode: used };
|
|
586
632
|
}
|
|
587
633
|
function simpleGraph(ids, edges, kinds, type) {
|
|
588
634
|
const g = new Graph({ type, multi: false, allowSelfLoops: false });
|
|
@@ -723,14 +769,14 @@ var DEFAULT_PATHS = [
|
|
|
723
769
|
];
|
|
724
770
|
function loadCoverage(root, explicit) {
|
|
725
771
|
const candidates = (explicit && explicit.length ? explicit : DEFAULT_PATHS).map(
|
|
726
|
-
(p) =>
|
|
772
|
+
(p) => path18.resolve(root, p)
|
|
727
773
|
);
|
|
728
|
-
const found = candidates.filter((p) =>
|
|
774
|
+
const found = candidates.filter((p) => fs16.existsSync(p));
|
|
729
775
|
if (found.length === 0) return null;
|
|
730
776
|
const map = /* @__PURE__ */ new Map();
|
|
731
777
|
for (const file of found) {
|
|
732
778
|
try {
|
|
733
|
-
const text =
|
|
779
|
+
const text = fs16.readFileSync(file, "utf8");
|
|
734
780
|
if (file.endsWith(".json")) mergeIstanbul(map, text, root);
|
|
735
781
|
else mergeLcov(map, text, root);
|
|
736
782
|
} catch {
|
|
@@ -739,8 +785,8 @@ function loadCoverage(root, explicit) {
|
|
|
739
785
|
return map.size ? map : null;
|
|
740
786
|
}
|
|
741
787
|
function rel(root, p) {
|
|
742
|
-
const abs =
|
|
743
|
-
return
|
|
788
|
+
const abs = path18.isAbsolute(p) ? p : path18.resolve(root, p);
|
|
789
|
+
return path18.relative(root, abs).split(path18.sep).join("/");
|
|
744
790
|
}
|
|
745
791
|
function bump(map, file, line, hits) {
|
|
746
792
|
let lh = map.get(file);
|
|
@@ -1027,9 +1073,6 @@ function matchConfidence(entry, nameParts, imports, callees) {
|
|
|
1027
1073
|
}
|
|
1028
1074
|
return conf;
|
|
1029
1075
|
}
|
|
1030
|
-
|
|
1031
|
-
// src/schema.ts
|
|
1032
|
-
var SCHEMA_VERSION = "vg-graph/1.0";
|
|
1033
1076
|
var DEFAULT_INLINE_THRESHOLD = 24;
|
|
1034
1077
|
async function parseFiles(files, options = {}) {
|
|
1035
1078
|
const threshold = options.inlineThreshold ?? DEFAULT_INLINE_THRESHOLD;
|
|
@@ -1050,7 +1093,7 @@ async function parseInline(files, options) {
|
|
|
1050
1093
|
onProgress?.(0, files.length);
|
|
1051
1094
|
for (const file of files) {
|
|
1052
1095
|
try {
|
|
1053
|
-
const source =
|
|
1096
|
+
const source = fs16.readFileSync(file.abs, "utf8");
|
|
1054
1097
|
out.push(await parseSource(file.rel, file.lang.id, source));
|
|
1055
1098
|
} catch (err) {
|
|
1056
1099
|
out.push(emptyParse(file, `parse failed: ${err.message}`));
|
|
@@ -1105,9 +1148,9 @@ function isWorkerOom(err) {
|
|
|
1105
1148
|
return e?.code === "ERR_WORKER_OUT_OF_MEMORY" || /out of memory/i.test(e?.message ?? "");
|
|
1106
1149
|
}
|
|
1107
1150
|
function resolveWorkerFile() {
|
|
1108
|
-
const here =
|
|
1109
|
-
const candidate =
|
|
1110
|
-
return
|
|
1151
|
+
const here = path18.dirname(fileURLToPath(import.meta.url));
|
|
1152
|
+
const candidate = path18.join(here, "parse-worker.js");
|
|
1153
|
+
return fs16.existsSync(candidate) ? candidate : null;
|
|
1111
1154
|
}
|
|
1112
1155
|
function chunk(items, buckets) {
|
|
1113
1156
|
const out = Array.from({ length: Math.min(buckets, items.length || 1) }, () => []);
|
|
@@ -1356,7 +1399,7 @@ function enclosing3(nodes, line) {
|
|
|
1356
1399
|
return best;
|
|
1357
1400
|
}
|
|
1358
1401
|
function normalize2(p) {
|
|
1359
|
-
return
|
|
1402
|
+
return path18.resolve(p).split(path18.sep).join("/");
|
|
1360
1403
|
}
|
|
1361
1404
|
|
|
1362
1405
|
// src/engine/epistemic.ts
|
|
@@ -1599,14 +1642,14 @@ var IMPORTANCE = {
|
|
|
1599
1642
|
"other-config": 0.08
|
|
1600
1643
|
};
|
|
1601
1644
|
function toPosix2(p) {
|
|
1602
|
-
return p.split(
|
|
1645
|
+
return p.split(path18.sep).join("/");
|
|
1603
1646
|
}
|
|
1604
1647
|
function buildRootIgnore2(root, exclude) {
|
|
1605
1648
|
const ig = ignore();
|
|
1606
|
-
const gitignorePath =
|
|
1607
|
-
if (
|
|
1649
|
+
const gitignorePath = path18.join(root, ".gitignore");
|
|
1650
|
+
if (fs16.existsSync(gitignorePath)) {
|
|
1608
1651
|
try {
|
|
1609
|
-
ig.add(
|
|
1652
|
+
ig.add(fs16.readFileSync(gitignorePath, "utf8"));
|
|
1610
1653
|
} catch {
|
|
1611
1654
|
}
|
|
1612
1655
|
}
|
|
@@ -1615,7 +1658,7 @@ function buildRootIgnore2(root, exclude) {
|
|
|
1615
1658
|
}
|
|
1616
1659
|
function classifyProjectContext(relOrName) {
|
|
1617
1660
|
const rel2 = relOrName.replace(/\\/g, "/");
|
|
1618
|
-
const base =
|
|
1661
|
+
const base = path18.basename(rel2);
|
|
1619
1662
|
const baseLower = base.toLowerCase();
|
|
1620
1663
|
if (/^\.env($|\.)/i.test(base) && !isEnvExampleName(baseLower)) return null;
|
|
1621
1664
|
if (SKIP_FILES.has(baseLower)) return null;
|
|
@@ -1628,7 +1671,7 @@ function classifyProjectContext(relOrName) {
|
|
|
1628
1671
|
for (const { re, category } of PATH_PATTERNS) {
|
|
1629
1672
|
if (re.test(rel2)) return category;
|
|
1630
1673
|
}
|
|
1631
|
-
const ext =
|
|
1674
|
+
const ext = path18.extname(baseLower);
|
|
1632
1675
|
if (DOC_EXTENSIONS.has(ext)) return ext === ".txt" ? "text" : "markdown";
|
|
1633
1676
|
if (API_EXTENSIONS.has(ext)) return "api-contract";
|
|
1634
1677
|
if ((ext === ".yaml" || ext === ".yml" || ext === ".json") && /openapi|swagger|asyncapi/i.test(base)) {
|
|
@@ -1646,24 +1689,24 @@ function isEnvExampleName(baseLower) {
|
|
|
1646
1689
|
return false;
|
|
1647
1690
|
}
|
|
1648
1691
|
function discoverDocs(options) {
|
|
1649
|
-
const root =
|
|
1692
|
+
const root = path18.resolve(options.root);
|
|
1650
1693
|
const maxFiles = options.maxFiles ?? DOC_MAX_FILES;
|
|
1651
1694
|
const rootIg = buildRootIgnore2(root, options.exclude ?? []);
|
|
1652
|
-
const scopeAbs = (options.paths?.length ? options.paths.map((p) =>
|
|
1653
|
-
(p) =>
|
|
1695
|
+
const scopeAbs = (options.paths?.length ? options.paths.map((p) => path18.resolve(root, p)) : [root]).filter(
|
|
1696
|
+
(p) => fs16.existsSync(p)
|
|
1654
1697
|
);
|
|
1655
1698
|
const found = /* @__PURE__ */ new Map();
|
|
1656
1699
|
const consider = (abs) => {
|
|
1657
1700
|
if (found.size >= maxFiles) return;
|
|
1658
|
-
const rel2 = toPosix2(
|
|
1701
|
+
const rel2 = toPosix2(path18.relative(root, abs));
|
|
1659
1702
|
if (!rel2 || rel2.startsWith("..")) return;
|
|
1660
1703
|
if (rootIg.ignores(rel2)) return;
|
|
1661
|
-
const base =
|
|
1704
|
+
const base = path18.basename(abs);
|
|
1662
1705
|
if (SKIP_FILES.has(base.toLowerCase())) return;
|
|
1663
1706
|
const category = classifyProjectContext(rel2);
|
|
1664
1707
|
if (!category) return;
|
|
1665
1708
|
try {
|
|
1666
|
-
const st =
|
|
1709
|
+
const st = fs16.statSync(abs);
|
|
1667
1710
|
if (!st.isFile() || st.size > DOC_FILE_MAX_BYTES) return;
|
|
1668
1711
|
if (st.size === 0) return;
|
|
1669
1712
|
} catch {
|
|
@@ -1675,14 +1718,14 @@ function discoverDocs(options) {
|
|
|
1675
1718
|
if (found.size >= maxFiles || depth > 12) return;
|
|
1676
1719
|
let entries;
|
|
1677
1720
|
try {
|
|
1678
|
-
entries =
|
|
1721
|
+
entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
1679
1722
|
} catch {
|
|
1680
1723
|
return;
|
|
1681
1724
|
}
|
|
1682
1725
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
1683
1726
|
if (found.size >= maxFiles) return;
|
|
1684
|
-
const abs =
|
|
1685
|
-
const rel2 = toPosix2(
|
|
1727
|
+
const abs = path18.join(dir, entry.name);
|
|
1728
|
+
const rel2 = toPosix2(path18.relative(root, abs));
|
|
1686
1729
|
if (entry.isDirectory()) {
|
|
1687
1730
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
1688
1731
|
if (rel2 && rootIg.ignores(`${rel2}/`) && !rel2.startsWith(".github")) continue;
|
|
@@ -1694,7 +1737,7 @@ function discoverDocs(options) {
|
|
|
1694
1737
|
};
|
|
1695
1738
|
for (const scope of scopeAbs) {
|
|
1696
1739
|
try {
|
|
1697
|
-
const st =
|
|
1740
|
+
const st = fs16.statSync(scope);
|
|
1698
1741
|
if (st.isDirectory()) walk(scope, 0);
|
|
1699
1742
|
else if (st.isFile()) consider(scope);
|
|
1700
1743
|
} catch {
|
|
@@ -1705,7 +1748,7 @@ function discoverDocs(options) {
|
|
|
1705
1748
|
function prepareDocBody(rel2, raw, category) {
|
|
1706
1749
|
const scrubbed = redactSecrets(raw);
|
|
1707
1750
|
if (scrubbed.length <= DOC_BODY_MAX_CHARS) return scrubbed;
|
|
1708
|
-
if (category === "manifest" &&
|
|
1751
|
+
if (category === "manifest" && path18.basename(rel2).toLowerCase() === "package.json") {
|
|
1709
1752
|
return summarizePackageJson(scrubbed);
|
|
1710
1753
|
}
|
|
1711
1754
|
if (category === "api-contract" && /\.(ya?ml|json)$/i.test(rel2)) {
|
|
@@ -1751,14 +1794,14 @@ function documentNodesFromDocs(docs) {
|
|
|
1751
1794
|
for (const d of docs) {
|
|
1752
1795
|
let raw = "";
|
|
1753
1796
|
try {
|
|
1754
|
-
raw =
|
|
1797
|
+
raw = fs16.readFileSync(d.abs, "utf8");
|
|
1755
1798
|
} catch {
|
|
1756
1799
|
continue;
|
|
1757
1800
|
}
|
|
1758
1801
|
const category = d.category ?? d.kind;
|
|
1759
1802
|
const scrubbed = prepareDocBody(d.rel, raw, category);
|
|
1760
1803
|
if (!scrubbed.trim()) continue;
|
|
1761
|
-
const name =
|
|
1804
|
+
const name = path18.basename(d.rel);
|
|
1762
1805
|
const qualifiedName = d.rel.replace(/\\/g, "/");
|
|
1763
1806
|
const id = nodeId({
|
|
1764
1807
|
kind: "document",
|
|
@@ -1787,17 +1830,89 @@ function documentNodesFromDocs(docs) {
|
|
|
1787
1830
|
}
|
|
1788
1831
|
return nodes.sort((a, b) => a.file.localeCompare(b.file) || a.id.localeCompare(b.id));
|
|
1789
1832
|
}
|
|
1833
|
+
function shardTsProjects(root, files) {
|
|
1834
|
+
if (files.length === 0) return [];
|
|
1835
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1836
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1837
|
+
for (const f of files) {
|
|
1838
|
+
const dir = path18.dirname(f.abs);
|
|
1839
|
+
const key = nearestProjectKey(root, dir, cache);
|
|
1840
|
+
const list = byKey.get(key);
|
|
1841
|
+
if (list) list.push(f);
|
|
1842
|
+
else byKey.set(key, [f]);
|
|
1843
|
+
}
|
|
1844
|
+
return [...byKey.entries()].sort((a, b) => a[0].localeCompare(b[0])).map(([key, shardFiles]) => ({
|
|
1845
|
+
key,
|
|
1846
|
+
files: [...shardFiles].sort((a, b) => a.rel.localeCompare(b.rel))
|
|
1847
|
+
}));
|
|
1848
|
+
}
|
|
1849
|
+
function nearestProjectKey(root, startDir, cache) {
|
|
1850
|
+
const hit = cache.get(startDir);
|
|
1851
|
+
if (hit !== void 0) return hit;
|
|
1852
|
+
let dir = startDir;
|
|
1853
|
+
const rootAbs = path18.resolve(root);
|
|
1854
|
+
while (true) {
|
|
1855
|
+
if (fs16.existsSync(path18.join(dir, "tsconfig.json")) || fs16.existsSync(path18.join(dir, "tsconfig.base.json")) || fs16.existsSync(path18.join(dir, "package.json"))) {
|
|
1856
|
+
const key = toPosix3(path18.relative(rootAbs, dir)) || ".";
|
|
1857
|
+
cache.set(startDir, key);
|
|
1858
|
+
return key;
|
|
1859
|
+
}
|
|
1860
|
+
if (dir === rootAbs || path18.dirname(dir) === dir) {
|
|
1861
|
+
cache.set(startDir, ".");
|
|
1862
|
+
return ".";
|
|
1863
|
+
}
|
|
1864
|
+
dir = path18.dirname(dir);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
function toPosix3(p) {
|
|
1868
|
+
return p.split(path18.sep).join("/");
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
// src/engine/timing.ts
|
|
1872
|
+
var StageTimer = class {
|
|
1873
|
+
marks = /* @__PURE__ */ new Map();
|
|
1874
|
+
durations = {};
|
|
1875
|
+
start(name) {
|
|
1876
|
+
this.marks.set(name, nowMs());
|
|
1877
|
+
}
|
|
1878
|
+
end(name) {
|
|
1879
|
+
const t0 = this.marks.get(name);
|
|
1880
|
+
if (t0 === void 0) return 0;
|
|
1881
|
+
const ms = Math.round((nowMs() - t0) * 1e3) / 1e3;
|
|
1882
|
+
this.durations[name] = ms;
|
|
1883
|
+
this.marks.delete(name);
|
|
1884
|
+
return ms;
|
|
1885
|
+
}
|
|
1886
|
+
/** Run `fn` under a named stage. */
|
|
1887
|
+
async measure(name, fn) {
|
|
1888
|
+
this.start(name);
|
|
1889
|
+
try {
|
|
1890
|
+
return await fn();
|
|
1891
|
+
} finally {
|
|
1892
|
+
this.end(name);
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
snapshot() {
|
|
1896
|
+
return { ...this.durations };
|
|
1897
|
+
}
|
|
1898
|
+
};
|
|
1899
|
+
function nowMs() {
|
|
1900
|
+
return Number(process.hrtime.bigint() / 1000n) / 1e3;
|
|
1901
|
+
}
|
|
1790
1902
|
|
|
1791
1903
|
// src/engine/build.ts
|
|
1792
1904
|
async function buildGraph(options) {
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1905
|
+
const timer = new StageTimer();
|
|
1906
|
+
timer.start("total");
|
|
1907
|
+
const root = path18.resolve(options.root);
|
|
1908
|
+
timer.start("discover");
|
|
1795
1909
|
const files = discover({
|
|
1796
1910
|
root,
|
|
1797
1911
|
only: options.only,
|
|
1798
1912
|
exclude: options.exclude,
|
|
1799
1913
|
paths: options.paths
|
|
1800
1914
|
});
|
|
1915
|
+
timer.end("discover");
|
|
1801
1916
|
const limits = resolveLimits(options.limits);
|
|
1802
1917
|
if (limits.maxFiles > 0 && files.length > limits.maxFiles) {
|
|
1803
1918
|
throw new ResourceLimitError(
|
|
@@ -1811,15 +1926,17 @@ async function buildGraph(options) {
|
|
|
1811
1926
|
grammars,
|
|
1812
1927
|
disabled: options.noCache
|
|
1813
1928
|
});
|
|
1929
|
+
timer.start("hash");
|
|
1814
1930
|
const hashes = /* @__PURE__ */ new Map();
|
|
1815
1931
|
const fileStats = [];
|
|
1816
1932
|
const toParse = [];
|
|
1817
1933
|
const reused = [];
|
|
1818
1934
|
const buildWarnings = [];
|
|
1935
|
+
let statHits = 0;
|
|
1819
1936
|
for (const file of files) {
|
|
1820
1937
|
let stat;
|
|
1821
1938
|
try {
|
|
1822
|
-
stat =
|
|
1939
|
+
stat = fs16.statSync(file.abs);
|
|
1823
1940
|
} catch {
|
|
1824
1941
|
continue;
|
|
1825
1942
|
}
|
|
@@ -1835,18 +1952,38 @@ async function buildGraph(options) {
|
|
|
1835
1952
|
);
|
|
1836
1953
|
continue;
|
|
1837
1954
|
}
|
|
1955
|
+
const byStat = options.noCache ? void 0 : cache.getByStat(file.rel, stat.mtimeMs, stat.size);
|
|
1956
|
+
if (byStat) {
|
|
1957
|
+
hashes.set(file.rel, byStat.hash);
|
|
1958
|
+
if (byStat.parse.hash !== byStat.hash) byStat.parse.hash = byStat.hash;
|
|
1959
|
+
fileStats.push({
|
|
1960
|
+
rel: file.rel,
|
|
1961
|
+
size: stat.size,
|
|
1962
|
+
mtimeMs: stat.mtimeMs,
|
|
1963
|
+
hash: byStat.hash
|
|
1964
|
+
});
|
|
1965
|
+
reused.push(byStat.parse);
|
|
1966
|
+
statHits++;
|
|
1967
|
+
continue;
|
|
1968
|
+
}
|
|
1838
1969
|
let hash = "";
|
|
1839
1970
|
try {
|
|
1840
|
-
hash = hashBytes(
|
|
1971
|
+
hash = hashBytes(fs16.readFileSync(file.abs));
|
|
1841
1972
|
} catch {
|
|
1842
1973
|
continue;
|
|
1843
1974
|
}
|
|
1844
1975
|
hashes.set(file.rel, hash);
|
|
1845
1976
|
fileStats.push({ rel: file.rel, size: stat.size, mtimeMs: stat.mtimeMs, hash });
|
|
1846
1977
|
const cached2 = cache.get(file.rel, hash);
|
|
1847
|
-
if (cached2)
|
|
1848
|
-
|
|
1978
|
+
if (cached2) {
|
|
1979
|
+
reused.push(cached2);
|
|
1980
|
+
cache.set(file.rel, cached2, { mtimeMs: stat.mtimeMs, size: stat.size });
|
|
1981
|
+
} else {
|
|
1982
|
+
toParse.push(file);
|
|
1983
|
+
}
|
|
1849
1984
|
}
|
|
1985
|
+
timer.end("hash");
|
|
1986
|
+
timer.start("parse");
|
|
1850
1987
|
const parsedNew = await parseFiles(toParse, {
|
|
1851
1988
|
jobs: options.jobs,
|
|
1852
1989
|
inline: options.inline,
|
|
@@ -1854,8 +1991,12 @@ async function buildGraph(options) {
|
|
|
1854
1991
|
grammarsDir: options.grammarsDir,
|
|
1855
1992
|
memoryBudgetMb: limits.memoryBudgetMb
|
|
1856
1993
|
});
|
|
1994
|
+
timer.end("parse");
|
|
1857
1995
|
checkMemoryBudget("parse", limits.memoryBudgetMb);
|
|
1858
|
-
for (const p of parsedNew)
|
|
1996
|
+
for (const p of parsedNew) {
|
|
1997
|
+
const st = fileStats.find((f) => f.rel === p.rel);
|
|
1998
|
+
cache.set(p.rel, p, st ? { mtimeMs: st.mtimeMs, size: st.size } : void 0);
|
|
1999
|
+
}
|
|
1859
2000
|
const currentRels = new Set(files.map((f) => f.rel));
|
|
1860
2001
|
cache.prune(currentRels);
|
|
1861
2002
|
cache.save();
|
|
@@ -1863,31 +2004,61 @@ async function buildGraph(options) {
|
|
|
1863
2004
|
(a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0
|
|
1864
2005
|
);
|
|
1865
2006
|
const warnings = [...buildWarnings, ...parses.flatMap((p) => p.warnings ?? [])];
|
|
2007
|
+
timer.start("resolve");
|
|
1866
2008
|
const moduleResolver = buildModuleResolver(root, new Set(parses.map((p) => p.rel)));
|
|
1867
2009
|
const resolved = resolve(parses, moduleResolver);
|
|
2010
|
+
timer.end("resolve");
|
|
1868
2011
|
checkMemoryBudget("resolve", limits.memoryBudgetMb);
|
|
1869
2012
|
const nodeFileById = new Map(resolved.nodes.map((n) => [n.id, n.file]));
|
|
1870
2013
|
let edges = resolved.edges;
|
|
1871
2014
|
const resolvers = [...resolved.stats.resolvers];
|
|
1872
2015
|
const preciseCoveredFiles = /* @__PURE__ */ new Set();
|
|
1873
2016
|
let tscStats;
|
|
1874
|
-
|
|
2017
|
+
const skipTsc = options.noTsc || options.fast;
|
|
2018
|
+
let tsFiles = skipTsc ? [] : files.filter((f) => (f.lang.id === "ts" || f.lang.id === "tsx" || f.lang.id === "js") && hashes.has(f.rel)).map((f) => ({ rel: f.rel, abs: f.abs }));
|
|
1875
2019
|
if (limits.tscMaxFiles > 0 && tsFiles.length > limits.tscMaxFiles) {
|
|
1876
2020
|
warnings.push(
|
|
1877
2021
|
`typescript resolver skipped \u2014 ${tsFiles.length.toLocaleString()} TS/JS files exceed the ${limits.tscMaxFiles.toLocaleString()}-file limit; calls use the heuristic resolver (set VG_TSC_MAX_FILES to raise it, 0 to disable)`
|
|
1878
2022
|
);
|
|
1879
2023
|
tsFiles = [];
|
|
1880
2024
|
}
|
|
2025
|
+
timer.start("tsc");
|
|
1881
2026
|
if (tsFiles.length) {
|
|
1882
|
-
const
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
2027
|
+
const shards = shardTsProjects(root, tsFiles);
|
|
2028
|
+
let filesCovered = 0;
|
|
2029
|
+
let calls = 0;
|
|
2030
|
+
let jsx = 0;
|
|
2031
|
+
let heritage = 0;
|
|
2032
|
+
let resolvedCount = 0;
|
|
2033
|
+
const coveredAll = /* @__PURE__ */ new Set();
|
|
2034
|
+
const preciseAll = [];
|
|
2035
|
+
for (const shard of shards) {
|
|
2036
|
+
const res = tsResolveEdges(root, shard.files, resolved.nodes);
|
|
2037
|
+
if (res.stats.files === 0) continue;
|
|
2038
|
+
filesCovered += res.stats.files;
|
|
2039
|
+
calls += res.stats.calls;
|
|
2040
|
+
jsx += res.stats.jsx;
|
|
2041
|
+
heritage += res.stats.heritage;
|
|
2042
|
+
resolvedCount += res.stats.resolved;
|
|
2043
|
+
for (const f of res.coveredFiles) coveredAll.add(f);
|
|
2044
|
+
preciseAll.push(...res.edges);
|
|
2045
|
+
}
|
|
2046
|
+
if (filesCovered > 0) {
|
|
2047
|
+
edges = mergePreciseEdges(edges, preciseAll, coveredAll, nodeFileById);
|
|
2048
|
+
for (const f of coveredAll) preciseCoveredFiles.add(f);
|
|
1886
2049
|
if (!resolvers.includes("tsc")) resolvers.unshift("tsc");
|
|
1887
|
-
tscStats =
|
|
2050
|
+
tscStats = {
|
|
2051
|
+
files: filesCovered,
|
|
2052
|
+
calls,
|
|
2053
|
+
jsx,
|
|
2054
|
+
heritage,
|
|
2055
|
+
resolved: resolvedCount,
|
|
2056
|
+
shards: shards.length
|
|
2057
|
+
};
|
|
1888
2058
|
}
|
|
1889
2059
|
checkMemoryBudget("typescript resolution", limits.memoryBudgetMb);
|
|
1890
2060
|
}
|
|
2061
|
+
timer.end("tsc");
|
|
1891
2062
|
const scip = options.noScip ? null : loadScipIndex(root, options.scip);
|
|
1892
2063
|
let scipStats;
|
|
1893
2064
|
if (scip) {
|
|
@@ -1908,8 +2079,8 @@ async function buildGraph(options) {
|
|
|
1908
2079
|
});
|
|
1909
2080
|
for (const d of docs) {
|
|
1910
2081
|
try {
|
|
1911
|
-
const st =
|
|
1912
|
-
const hash = hashBytes(
|
|
2082
|
+
const st = fs16.statSync(d.abs);
|
|
2083
|
+
const hash = hashBytes(fs16.readFileSync(d.abs));
|
|
1913
2084
|
hashes.set(d.rel, hash);
|
|
1914
2085
|
fileStats.push({ rel: d.rel, size: st.size, mtimeMs: st.mtimeMs, hash });
|
|
1915
2086
|
} catch {
|
|
@@ -1917,7 +2088,12 @@ async function buildGraph(options) {
|
|
|
1917
2088
|
}
|
|
1918
2089
|
const docNodes = documentNodesFromDocs(docs);
|
|
1919
2090
|
if (docNodes.length) nodes = [...nodes, ...docNodes];
|
|
1920
|
-
|
|
2091
|
+
timer.start("analyze");
|
|
2092
|
+
const analysis = analyze(nodes, linked.edges, {
|
|
2093
|
+
cluster: options.cluster,
|
|
2094
|
+
tier: options.analysisTier
|
|
2095
|
+
});
|
|
2096
|
+
timer.end("analyze");
|
|
1921
2097
|
checkMemoryBudget("analysis", limits.memoryBudgetMb);
|
|
1922
2098
|
const languages = [.../* @__PURE__ */ new Set([...parses.map((p) => p.lang), ...docNodes.map((n) => n.lang)])].sort();
|
|
1923
2099
|
const edgeKinds = [...new Set(analysis.edges.map((e) => e.kind))].sort();
|
|
@@ -1945,8 +2121,9 @@ async function buildGraph(options) {
|
|
|
1945
2121
|
toolchain
|
|
1946
2122
|
},
|
|
1947
2123
|
meta: {
|
|
1948
|
-
root:
|
|
2124
|
+
root: path18.basename(root) === "" ? "." : ".",
|
|
1949
2125
|
languages,
|
|
2126
|
+
analysisTier: analysis.tier,
|
|
1950
2127
|
counts: {
|
|
1951
2128
|
nodes: analysis.nodes.length,
|
|
1952
2129
|
edges: analysis.edges.length,
|
|
@@ -1972,16 +2149,27 @@ async function buildGraph(options) {
|
|
|
1972
2149
|
const grounding = groundGraph(analysis.nodes, analysis.edges, parses);
|
|
1973
2150
|
if (grounding.length) graph.grounding = grounding;
|
|
1974
2151
|
}
|
|
2152
|
+
let indexResult;
|
|
2153
|
+
if (!options.noIndex) {
|
|
2154
|
+
timer.start("index");
|
|
2155
|
+
const wr = writeGraphIndex(root, graph);
|
|
2156
|
+
indexResult = { ok: wr.ok, path: wr.ok ? wr.path : void 0, reason: wr.reason };
|
|
2157
|
+
timer.end("index");
|
|
2158
|
+
}
|
|
2159
|
+
timer.end("total");
|
|
2160
|
+
const stages = timer.snapshot();
|
|
1975
2161
|
return {
|
|
1976
2162
|
graph,
|
|
1977
|
-
timing: { totalMs:
|
|
2163
|
+
timing: { totalMs: stages.total ?? 0, stages },
|
|
1978
2164
|
reparsed: parsedNew.length,
|
|
1979
2165
|
reused: reused.length,
|
|
2166
|
+
statHits,
|
|
1980
2167
|
totalFiles: files.length,
|
|
1981
2168
|
fileStats,
|
|
1982
2169
|
resolveStats: resolved.stats,
|
|
1983
2170
|
tsc: tscStats,
|
|
1984
2171
|
scip: scipStats,
|
|
2172
|
+
index: indexResult,
|
|
1985
2173
|
warnings
|
|
1986
2174
|
};
|
|
1987
2175
|
}
|
|
@@ -1991,14 +2179,14 @@ function toRepoRel(p) {
|
|
|
1991
2179
|
function loadScipIndex(root, explicit) {
|
|
1992
2180
|
const candidates = [
|
|
1993
2181
|
explicit,
|
|
1994
|
-
|
|
1995
|
-
|
|
2182
|
+
path18.join(root, "index.scip"),
|
|
2183
|
+
path18.join(root, ".vibgrate", "index.scip")
|
|
1996
2184
|
].filter((p) => Boolean(p));
|
|
1997
2185
|
for (const file of candidates) {
|
|
1998
|
-
const abs =
|
|
1999
|
-
if (!
|
|
2186
|
+
const abs = path18.isAbsolute(file) ? file : path18.resolve(root, file);
|
|
2187
|
+
if (!fs16.existsSync(abs)) continue;
|
|
2000
2188
|
try {
|
|
2001
|
-
const index = decodeScipIndex(new Uint8Array(
|
|
2189
|
+
const index = decodeScipIndex(new Uint8Array(fs16.readFileSync(abs)));
|
|
2002
2190
|
if (index.documents.length) {
|
|
2003
2191
|
return { index, tool: index.toolVersion ? `${index.toolName} ${index.toolVersion}` : index.toolName };
|
|
2004
2192
|
}
|
|
@@ -2047,9 +2235,6 @@ function computeCorpusHash(parses, hashes) {
|
|
|
2047
2235
|
const list = [...byRel.entries()].sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
2048
2236
|
return hashString(canonicalize(list));
|
|
2049
2237
|
}
|
|
2050
|
-
function nowMs() {
|
|
2051
|
-
return Number(process.hrtime.bigint() / 1000n) / 1e3;
|
|
2052
|
-
}
|
|
2053
2238
|
|
|
2054
2239
|
// src/engine/verify.ts
|
|
2055
2240
|
var PINNED = "1970-01-01T00:00:00.000Z";
|
|
@@ -2116,21 +2301,21 @@ function usageError(message) {
|
|
|
2116
2301
|
}
|
|
2117
2302
|
var SNAPSHOT_VERSION = "vg-freshness/1";
|
|
2118
2303
|
function snapshotPath(root) {
|
|
2119
|
-
return
|
|
2304
|
+
return path18.join(cacheDir(root), "freshness.json");
|
|
2120
2305
|
}
|
|
2121
2306
|
function writeSnapshot(root, corpusHash, fileStats, scope = {}) {
|
|
2122
2307
|
const files = {};
|
|
2123
2308
|
for (const f of fileStats) files[f.rel] = { size: f.size, mtimeMs: f.mtimeMs, hash: f.hash };
|
|
2124
2309
|
const snapshot = { version: SNAPSHOT_VERSION, corpusHash, scope: pruneScope(scope), files };
|
|
2125
2310
|
try {
|
|
2126
|
-
|
|
2127
|
-
|
|
2311
|
+
fs16.mkdirSync(cacheDir(root), { recursive: true });
|
|
2312
|
+
fs16.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
|
|
2128
2313
|
} catch {
|
|
2129
2314
|
}
|
|
2130
2315
|
}
|
|
2131
2316
|
function loadSnapshot(root) {
|
|
2132
2317
|
try {
|
|
2133
|
-
const loaded = JSON.parse(
|
|
2318
|
+
const loaded = JSON.parse(fs16.readFileSync(snapshotPath(root), "utf8"));
|
|
2134
2319
|
if (loaded.version === SNAPSHOT_VERSION && loaded.files && typeof loaded.corpusHash === "string") {
|
|
2135
2320
|
return { ...loaded, scope: loaded.scope ?? {} };
|
|
2136
2321
|
}
|
|
@@ -2166,7 +2351,7 @@ function probeFreshness(root) {
|
|
|
2166
2351
|
}
|
|
2167
2352
|
let stat;
|
|
2168
2353
|
try {
|
|
2169
|
-
stat =
|
|
2354
|
+
stat = fs16.statSync(file.abs);
|
|
2170
2355
|
} catch {
|
|
2171
2356
|
drift.removed.push(file.rel);
|
|
2172
2357
|
continue;
|
|
@@ -2174,7 +2359,7 @@ function probeFreshness(root) {
|
|
|
2174
2359
|
if (stat.size === entry.size && stat.mtimeMs === entry.mtimeMs) continue;
|
|
2175
2360
|
let hash = "";
|
|
2176
2361
|
try {
|
|
2177
|
-
hash = hashBytes(
|
|
2362
|
+
hash = hashBytes(fs16.readFileSync(file.abs));
|
|
2178
2363
|
} catch {
|
|
2179
2364
|
drift.removed.push(file.rel);
|
|
2180
2365
|
continue;
|
|
@@ -2191,7 +2376,7 @@ function probeFreshness(root) {
|
|
|
2191
2376
|
}
|
|
2192
2377
|
if (absorbed && !hasDrift(drift)) {
|
|
2193
2378
|
try {
|
|
2194
|
-
|
|
2379
|
+
fs16.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
|
|
2195
2380
|
} catch {
|
|
2196
2381
|
}
|
|
2197
2382
|
}
|
|
@@ -2272,10 +2457,10 @@ function testsToRun(graph, rootId, depth = 4) {
|
|
|
2272
2457
|
};
|
|
2273
2458
|
}
|
|
2274
2459
|
function detectRunner(root, lang) {
|
|
2275
|
-
const pkgPath =
|
|
2276
|
-
if (
|
|
2460
|
+
const pkgPath = path18.join(root, "package.json");
|
|
2461
|
+
if (fs16.existsSync(pkgPath)) {
|
|
2277
2462
|
try {
|
|
2278
|
-
const pkg = JSON.parse(
|
|
2463
|
+
const pkg = JSON.parse(fs16.readFileSync(pkgPath, "utf8"));
|
|
2279
2464
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2280
2465
|
if (deps.vitest) return { name: "vitest", command: (f) => `npx vitest run ${f.join(" ")}`.trim() };
|
|
2281
2466
|
if (deps.jest) return { name: "jest", command: (f) => `npx jest ${f.join(" ")}`.trim() };
|
|
@@ -2283,10 +2468,10 @@ function detectRunner(root, lang) {
|
|
|
2283
2468
|
} catch {
|
|
2284
2469
|
}
|
|
2285
2470
|
}
|
|
2286
|
-
if (lang === "py" ||
|
|
2471
|
+
if (lang === "py" || fs16.existsSync(path18.join(root, "pyproject.toml")) || fs16.existsSync(path18.join(root, "pytest.ini"))) {
|
|
2287
2472
|
return { name: "pytest", command: (f) => `pytest ${f.join(" ")}`.trim() };
|
|
2288
2473
|
}
|
|
2289
|
-
if (lang === "go" ||
|
|
2474
|
+
if (lang === "go" || fs16.existsSync(path18.join(root, "go.mod"))) {
|
|
2290
2475
|
return { name: "go test", command: () => "go test ./..." };
|
|
2291
2476
|
}
|
|
2292
2477
|
if (lang === "cs" || hasFile(root, /\.csproj$/) || hasFile(root, /\.sln$/)) {
|
|
@@ -2297,16 +2482,16 @@ function detectRunner(root, lang) {
|
|
|
2297
2482
|
}
|
|
2298
2483
|
function hasFile(root, re) {
|
|
2299
2484
|
try {
|
|
2300
|
-
return
|
|
2485
|
+
return fs16.readdirSync(root).some((f) => re.test(f));
|
|
2301
2486
|
} catch {
|
|
2302
2487
|
return false;
|
|
2303
2488
|
}
|
|
2304
2489
|
}
|
|
2305
2490
|
function findGitRoot(startDir = process.cwd()) {
|
|
2306
|
-
let dir =
|
|
2491
|
+
let dir = path18.resolve(startDir);
|
|
2307
2492
|
for (; ; ) {
|
|
2308
|
-
if (
|
|
2309
|
-
const parent =
|
|
2493
|
+
if (fs16.existsSync(path18.join(dir, ".git"))) return dir;
|
|
2494
|
+
const parent = path18.dirname(dir);
|
|
2310
2495
|
if (parent === dir) return null;
|
|
2311
2496
|
dir = parent;
|
|
2312
2497
|
}
|
|
@@ -2317,19 +2502,19 @@ function normalizeEntry(line) {
|
|
|
2317
2502
|
function ensureGitignored(entry, startDir = process.cwd()) {
|
|
2318
2503
|
const root = findGitRoot(startDir);
|
|
2319
2504
|
if (!root) return { status: "not-a-repo", entry };
|
|
2320
|
-
const gitignorePath =
|
|
2505
|
+
const gitignorePath = path18.join(root, ".gitignore");
|
|
2321
2506
|
const target = normalizeEntry(entry);
|
|
2322
2507
|
let existing = "";
|
|
2323
2508
|
let fileExisted = true;
|
|
2324
2509
|
try {
|
|
2325
|
-
existing =
|
|
2510
|
+
existing = fs16.readFileSync(gitignorePath, "utf8");
|
|
2326
2511
|
} catch {
|
|
2327
2512
|
fileExisted = false;
|
|
2328
2513
|
}
|
|
2329
2514
|
const alreadyPresent = existing.split(/\r?\n/).some((line) => normalizeEntry(line) === target);
|
|
2330
2515
|
if (alreadyPresent) return { status: "present", entry, gitignorePath };
|
|
2331
2516
|
const needsLeadingNewline = existing.length > 0 && !existing.endsWith("\n");
|
|
2332
|
-
|
|
2517
|
+
fs16.appendFileSync(gitignorePath, `${needsLeadingNewline ? "\n" : ""}${entry}
|
|
2333
2518
|
`, "utf8");
|
|
2334
2519
|
return { status: fileExisted ? "added" : "created", entry, gitignorePath };
|
|
2335
2520
|
}
|
|
@@ -2483,14 +2668,14 @@ dsnCommand.command("create").description("Create a new DSN token").option("--ing
|
|
|
2483
2668
|
console.log(chalk.dim("The secret must be registered on your Vibgrate ingest API."));
|
|
2484
2669
|
}
|
|
2485
2670
|
if (opts.write) {
|
|
2486
|
-
const writePath =
|
|
2671
|
+
const writePath = path18.resolve(opts.write);
|
|
2487
2672
|
await writeTextFile(writePath, dsn + "\n");
|
|
2488
2673
|
console.log("");
|
|
2489
2674
|
console.log(chalk.green("\u2714") + ` DSN written to ${opts.write}`);
|
|
2490
|
-
const root = findGitRoot(
|
|
2491
|
-
const rel2 = root ?
|
|
2675
|
+
const root = findGitRoot(path18.dirname(writePath));
|
|
2676
|
+
const rel2 = root ? path18.relative(root, writePath).split(path18.sep).join("/") : "";
|
|
2492
2677
|
if (root && rel2 && !rel2.startsWith("..")) {
|
|
2493
|
-
const res = ensureGitignored(rel2,
|
|
2678
|
+
const res = ensureGitignored(rel2, path18.dirname(writePath));
|
|
2494
2679
|
if (res.status === "created") {
|
|
2495
2680
|
console.log(chalk.green("\u2714") + ` Created .gitignore and ignored ${rel2}`);
|
|
2496
2681
|
} else if (res.status === "added") {
|
|
@@ -2508,30 +2693,30 @@ dsnCommand.command("create").description("Create a new DSN token").option("--ing
|
|
|
2508
2693
|
var STORE_DIRNAME = ".vibgrate";
|
|
2509
2694
|
var STORE_FILENAME = "credentials.json";
|
|
2510
2695
|
function homeCredentialsPath() {
|
|
2511
|
-
return
|
|
2696
|
+
return path18.join(os.homedir(), STORE_DIRNAME, STORE_FILENAME);
|
|
2512
2697
|
}
|
|
2513
2698
|
function projectCredentialsPath(cwd = process.cwd()) {
|
|
2514
2699
|
const root = findGitRoot(cwd) ?? cwd;
|
|
2515
|
-
return
|
|
2700
|
+
return path18.join(root, STORE_DIRNAME, STORE_FILENAME);
|
|
2516
2701
|
}
|
|
2517
2702
|
function credentialsPath(opts = {}) {
|
|
2518
2703
|
const override = process.env.VIBGRATE_CREDENTIALS?.trim();
|
|
2519
|
-
if (override) return
|
|
2704
|
+
if (override) return path18.resolve(override);
|
|
2520
2705
|
const local = projectCredentialsPath(opts.cwd);
|
|
2521
2706
|
if (opts.local) return local;
|
|
2522
|
-
if (
|
|
2707
|
+
if (fs16.existsSync(local)) return local;
|
|
2523
2708
|
return homeCredentialsPath();
|
|
2524
2709
|
}
|
|
2525
2710
|
function gitignoreEntryForCredentials(repoRoot, credsFile = credentialsPath()) {
|
|
2526
|
-
const rel2 =
|
|
2527
|
-
if (rel2 && !rel2.startsWith("..") && !
|
|
2528
|
-
return rel2.split(
|
|
2711
|
+
const rel2 = path18.relative(repoRoot, credsFile);
|
|
2712
|
+
if (rel2 && !rel2.startsWith("..") && !path18.isAbsolute(rel2)) {
|
|
2713
|
+
return rel2.split(path18.sep).join("/");
|
|
2529
2714
|
}
|
|
2530
2715
|
return `${STORE_DIRNAME}/${STORE_FILENAME}`;
|
|
2531
2716
|
}
|
|
2532
2717
|
function readStoredCredentials(opts = {}) {
|
|
2533
2718
|
try {
|
|
2534
|
-
const raw =
|
|
2719
|
+
const raw = fs16.readFileSync(credentialsPath(opts), "utf8");
|
|
2535
2720
|
const parsed = JSON.parse(raw);
|
|
2536
2721
|
return parsed && typeof parsed.dsn === "string" && parsed.dsn ? parsed : null;
|
|
2537
2722
|
} catch {
|
|
@@ -2540,16 +2725,16 @@ function readStoredCredentials(opts = {}) {
|
|
|
2540
2725
|
}
|
|
2541
2726
|
function writeStoredCredentials(creds, opts = {}) {
|
|
2542
2727
|
const file = credentialsPath(opts);
|
|
2543
|
-
|
|
2544
|
-
|
|
2728
|
+
fs16.mkdirSync(path18.dirname(file), { recursive: true });
|
|
2729
|
+
fs16.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf8", mode: 384 });
|
|
2545
2730
|
try {
|
|
2546
|
-
|
|
2731
|
+
fs16.chmodSync(file, 384);
|
|
2547
2732
|
} catch {
|
|
2548
2733
|
}
|
|
2549
2734
|
}
|
|
2550
2735
|
function clearStoredCredentials(opts = {}) {
|
|
2551
2736
|
try {
|
|
2552
|
-
|
|
2737
|
+
fs16.rmSync(credentialsPath(opts));
|
|
2553
2738
|
return true;
|
|
2554
2739
|
} catch {
|
|
2555
2740
|
return false;
|
|
@@ -2920,7 +3105,7 @@ var pushCommand = new Command("push").description("Push scan results to Vibgrate
|
|
|
2920
3105
|
if (opts.strict) process.exit(1);
|
|
2921
3106
|
return;
|
|
2922
3107
|
}
|
|
2923
|
-
const filePath =
|
|
3108
|
+
const filePath = path18.resolve(opts.file);
|
|
2924
3109
|
if (!await pathExists(filePath)) {
|
|
2925
3110
|
console.error(chalk.red(`Scan artifact not found: ${filePath}`));
|
|
2926
3111
|
console.error(chalk.dim('Run "vibgrate scan" first.'));
|
|
@@ -3015,7 +3200,7 @@ function measure(root, files) {
|
|
|
3015
3200
|
for (const rel2 of files) {
|
|
3016
3201
|
let size;
|
|
3017
3202
|
try {
|
|
3018
|
-
size =
|
|
3203
|
+
size = fs16.statSync(path18.join(root, rel2)).size;
|
|
3019
3204
|
} catch {
|
|
3020
3205
|
continue;
|
|
3021
3206
|
}
|
|
@@ -3038,9 +3223,9 @@ function matchLines(text, needleLower) {
|
|
|
3038
3223
|
}
|
|
3039
3224
|
function readCandidate(abs, knownSize) {
|
|
3040
3225
|
try {
|
|
3041
|
-
const size = knownSize ??
|
|
3226
|
+
const size = knownSize ?? fs16.statSync(abs).size;
|
|
3042
3227
|
if (size > MAX_FILE_BYTES) return null;
|
|
3043
|
-
const text =
|
|
3228
|
+
const text = fs16.readFileSync(abs, "utf8");
|
|
3044
3229
|
return text.includes(NUL) ? null : text;
|
|
3045
3230
|
} catch {
|
|
3046
3231
|
return null;
|
|
@@ -3051,7 +3236,7 @@ function scanInline(root, files, needleLower, cap, stopAtCap, sizes) {
|
|
|
3051
3236
|
let total = 0;
|
|
3052
3237
|
let truncated = false;
|
|
3053
3238
|
for (const rel2 of files) {
|
|
3054
|
-
const text = readCandidate(
|
|
3239
|
+
const text = readCandidate(path18.join(root, rel2), sizes?.get(rel2));
|
|
3055
3240
|
if (text === null) continue;
|
|
3056
3241
|
for (const h of matchLines(text, needleLower)) {
|
|
3057
3242
|
total++;
|
|
@@ -3118,12 +3303,12 @@ var WORKER_SOURCE = [
|
|
|
3118
3303
|
"parentPort.postMessage({ hits, total, truncated });"
|
|
3119
3304
|
].join("\n");
|
|
3120
3305
|
function runWorker(root, files, needleLower) {
|
|
3121
|
-
return new Promise((
|
|
3306
|
+
return new Promise((resolve12, reject) => {
|
|
3122
3307
|
const w = new Worker(WORKER_SOURCE, { eval: true, workerData: { root, files, needleLower } });
|
|
3123
3308
|
let settled = false;
|
|
3124
3309
|
w.once("message", (m) => {
|
|
3125
3310
|
settled = true;
|
|
3126
|
-
|
|
3311
|
+
resolve12(m);
|
|
3127
3312
|
});
|
|
3128
3313
|
w.once("error", reject);
|
|
3129
3314
|
w.once("exit", (code) => {
|
|
@@ -3192,10 +3377,10 @@ var BINARY_EXTS = /* @__PURE__ */ new Set([
|
|
|
3192
3377
|
".pdf"
|
|
3193
3378
|
]);
|
|
3194
3379
|
function hasBinaryExt(rel2) {
|
|
3195
|
-
return BINARY_EXTS.has(
|
|
3380
|
+
return BINARY_EXTS.has(path18.extname(rel2).toLowerCase());
|
|
3196
3381
|
}
|
|
3197
|
-
function
|
|
3198
|
-
return
|
|
3382
|
+
function toPosix4(rel2) {
|
|
3383
|
+
return path18.sep === "\\" ? rel2.replaceAll("\\", "/") : rel2;
|
|
3199
3384
|
}
|
|
3200
3385
|
async function searchSymbols(graph, root, query, limit) {
|
|
3201
3386
|
let q = query.trim();
|
|
@@ -3334,13 +3519,13 @@ function walkCandidates(root) {
|
|
|
3334
3519
|
const dir = stack.pop();
|
|
3335
3520
|
let entries;
|
|
3336
3521
|
try {
|
|
3337
|
-
entries =
|
|
3522
|
+
entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
3338
3523
|
} catch {
|
|
3339
3524
|
continue;
|
|
3340
3525
|
}
|
|
3341
3526
|
for (const e of entries) {
|
|
3342
3527
|
if (e.name.startsWith(".") || IGNORE_DIRS.has(e.name)) continue;
|
|
3343
|
-
const abs =
|
|
3528
|
+
const abs = path18.join(dir, e.name);
|
|
3344
3529
|
if (e.isDirectory()) {
|
|
3345
3530
|
stack.push(abs);
|
|
3346
3531
|
continue;
|
|
@@ -3350,7 +3535,7 @@ function walkCandidates(root) {
|
|
|
3350
3535
|
truncated = true;
|
|
3351
3536
|
continue;
|
|
3352
3537
|
}
|
|
3353
|
-
files.push(
|
|
3538
|
+
files.push(toPosix4(path18.relative(root, abs)));
|
|
3354
3539
|
}
|
|
3355
3540
|
}
|
|
3356
3541
|
files.sort();
|
|
@@ -3381,11 +3566,11 @@ function ripgrepCandidates(root, needle) {
|
|
|
3381
3566
|
if (files.length > MAX_FILES_SCANNED) return { files: files.slice(0, MAX_FILES_SCANNED), truncated: true };
|
|
3382
3567
|
return { files, truncated: false };
|
|
3383
3568
|
}
|
|
3384
|
-
function parseRgFileList(stdout,
|
|
3569
|
+
function parseRgFileList(stdout, sep9 = path18.sep) {
|
|
3385
3570
|
const seen = /* @__PURE__ */ new Set();
|
|
3386
3571
|
for (const raw of stdout.split("\n")) {
|
|
3387
3572
|
if (!raw) continue;
|
|
3388
|
-
const posix =
|
|
3573
|
+
const posix = sep9 === "\\" ? raw.replaceAll("\\", "/") : raw;
|
|
3389
3574
|
const rel2 = posix.startsWith("./") ? posix.slice(2) : posix;
|
|
3390
3575
|
if (!rel2) continue;
|
|
3391
3576
|
const segs = rel2.split("/");
|
|
@@ -3397,8 +3582,8 @@ function parseRgFileList(stdout, sep8 = path17.sep) {
|
|
|
3397
3582
|
}
|
|
3398
3583
|
function readScanArtifact(root) {
|
|
3399
3584
|
try {
|
|
3400
|
-
const file =
|
|
3401
|
-
return JSON.parse(
|
|
3585
|
+
const file = path18.join(root, ".vibgrate", "scan_result.json");
|
|
3586
|
+
return JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
3402
3587
|
} catch {
|
|
3403
3588
|
return null;
|
|
3404
3589
|
}
|
|
@@ -3788,7 +3973,7 @@ var CACHE_VERSION = "vg-hosted-docs/1";
|
|
|
3788
3973
|
var HOSTED_DOCS_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
3789
3974
|
var MAX_ENTRIES = 64;
|
|
3790
3975
|
function cachePath(root) {
|
|
3791
|
-
return
|
|
3976
|
+
return path18.join(cacheDir(root), "hosted-docs.json");
|
|
3792
3977
|
}
|
|
3793
3978
|
function hostedDocsCacheKey(req, opts = {}) {
|
|
3794
3979
|
const material = JSON.stringify([
|
|
@@ -3804,7 +3989,7 @@ function hostedDocsCacheKey(req, opts = {}) {
|
|
|
3804
3989
|
}
|
|
3805
3990
|
function loadFile(root) {
|
|
3806
3991
|
try {
|
|
3807
|
-
const parsed = JSON.parse(
|
|
3992
|
+
const parsed = JSON.parse(fs16.readFileSync(cachePath(root), "utf8"));
|
|
3808
3993
|
if (parsed && parsed.version === CACHE_VERSION && parsed.entries && typeof parsed.entries === "object") return parsed;
|
|
3809
3994
|
} catch {
|
|
3810
3995
|
}
|
|
@@ -3818,8 +4003,8 @@ function saveFile(root, file) {
|
|
|
3818
4003
|
delete file.entries[k];
|
|
3819
4004
|
}
|
|
3820
4005
|
}
|
|
3821
|
-
|
|
3822
|
-
|
|
4006
|
+
fs16.mkdirSync(cacheDir(root), { recursive: true });
|
|
4007
|
+
fs16.writeFileSync(cachePath(root), JSON.stringify(file));
|
|
3823
4008
|
} catch {
|
|
3824
4009
|
}
|
|
3825
4010
|
}
|
|
@@ -4794,12 +4979,12 @@ function detectAssistants(root, opts = {}) {
|
|
|
4794
4979
|
const which = opts.which ?? whichOnPath;
|
|
4795
4980
|
const found = [];
|
|
4796
4981
|
for (const assistant of ASSISTANTS) {
|
|
4797
|
-
const repoHit = (assistant.markers ?? []).find((m) =>
|
|
4982
|
+
const repoHit = (assistant.markers ?? []).find((m) => fs16.existsSync(path18.join(root, m)));
|
|
4798
4983
|
if (repoHit) {
|
|
4799
4984
|
found.push({ assistant, via: "repo", marker: repoHit });
|
|
4800
4985
|
continue;
|
|
4801
4986
|
}
|
|
4802
|
-
const homeHit = (assistant.homeMarkers ?? []).find((m) =>
|
|
4987
|
+
const homeHit = (assistant.homeMarkers ?? []).find((m) => fs16.existsSync(path18.join(home, m)));
|
|
4803
4988
|
if (homeHit) {
|
|
4804
4989
|
found.push({ assistant, via: "home", marker: homeHit });
|
|
4805
4990
|
continue;
|
|
@@ -4831,19 +5016,19 @@ function installAssistant(a, opts) {
|
|
|
4831
5016
|
const skipped = [];
|
|
4832
5017
|
let note;
|
|
4833
5018
|
if (a.skill) {
|
|
4834
|
-
writeFileEnsured(
|
|
5019
|
+
writeFileEnsured(path18.join(opts.root, a.skill), skillMarkdown(a.id));
|
|
4835
5020
|
wrote.push(a.skill);
|
|
4836
5021
|
}
|
|
4837
5022
|
if (a.mcp) {
|
|
4838
5023
|
const launch = opts.launch ?? detectServeLaunch();
|
|
4839
|
-
upsertMcp(
|
|
5024
|
+
upsertMcp(path18.join(opts.root, a.mcp.file), a.mcp, launch);
|
|
4840
5025
|
wrote.push(a.mcp.file);
|
|
4841
5026
|
note = launch.note;
|
|
4842
5027
|
} else {
|
|
4843
5028
|
skipped.push("mcp (host-specific setup)");
|
|
4844
5029
|
}
|
|
4845
5030
|
if (a.nudge && opts.hook !== false) {
|
|
4846
|
-
writeNudge(
|
|
5031
|
+
writeNudge(path18.join(opts.root, a.nudge.file), a.nudge, opts.smallRepo, a.id);
|
|
4847
5032
|
wrote.push(a.nudge.file);
|
|
4848
5033
|
} else if (a.nudge) {
|
|
4849
5034
|
skipped.push("nudge (--no-hook)");
|
|
@@ -4853,41 +5038,41 @@ function installAssistant(a, opts) {
|
|
|
4853
5038
|
function uninstallAssistant(a, root, purge) {
|
|
4854
5039
|
const removed = [];
|
|
4855
5040
|
if (a.mcp) {
|
|
4856
|
-
const file =
|
|
5041
|
+
const file = path18.join(root, a.mcp.file);
|
|
4857
5042
|
if (removeMcp(file, a.mcp)) removed.push(a.mcp.file);
|
|
4858
5043
|
}
|
|
4859
5044
|
if (a.nudge) {
|
|
4860
|
-
const file =
|
|
5045
|
+
const file = path18.join(root, a.nudge.file);
|
|
4861
5046
|
if (a.nudge.kind === "block") {
|
|
4862
5047
|
if (removeBlock(file)) removed.push(a.nudge.file);
|
|
4863
|
-
} else if (
|
|
4864
|
-
|
|
5048
|
+
} else if (fs16.existsSync(file)) {
|
|
5049
|
+
fs16.rmSync(file);
|
|
4865
5050
|
removed.push(a.nudge.file);
|
|
4866
5051
|
}
|
|
4867
5052
|
}
|
|
4868
5053
|
if (purge && a.skill) {
|
|
4869
|
-
const file =
|
|
4870
|
-
if (
|
|
4871
|
-
|
|
5054
|
+
const file = path18.join(root, a.skill);
|
|
5055
|
+
if (fs16.existsSync(file)) {
|
|
5056
|
+
fs16.rmSync(file);
|
|
4872
5057
|
removed.push(a.skill);
|
|
4873
5058
|
}
|
|
4874
5059
|
}
|
|
4875
5060
|
return removed;
|
|
4876
5061
|
}
|
|
4877
5062
|
function writeFileEnsured(file, content) {
|
|
4878
|
-
|
|
4879
|
-
|
|
5063
|
+
fs16.mkdirSync(path18.dirname(file), { recursive: true });
|
|
5064
|
+
fs16.writeFileSync(file, content);
|
|
4880
5065
|
}
|
|
4881
5066
|
function writeNavigationConfig(root) {
|
|
4882
5067
|
ensureVibgrateGitignore(root);
|
|
4883
|
-
const rel2 =
|
|
5068
|
+
const rel2 = path18.join(".vibgrate", "mcp-navigation.json");
|
|
4884
5069
|
const doc = {
|
|
4885
5070
|
_readme: "Deferred-loading config for agents embedding `vg serve` via the Claude API (defer_loading + tool-search). The hot navigation core stays in context; the rest load on demand \u2014 ~350-450 schema tokens/step vs ~1,881 for the full set. Hosts without defer_loading ignore this and serve the whole (already optimized) tool set. See docs/graph/VG-NAVIGATION-PROFILE.md.",
|
|
4886
5071
|
hot_core: [...HOT_TOOLS],
|
|
4887
5072
|
deferred: deferredToolNames(),
|
|
4888
5073
|
toolset: navigationToolsetConfig()
|
|
4889
5074
|
};
|
|
4890
|
-
writeFileEnsured(
|
|
5075
|
+
writeFileEnsured(path18.join(root, rel2), `${JSON.stringify(doc, null, 2)}
|
|
4891
5076
|
`);
|
|
4892
5077
|
return rel2;
|
|
4893
5078
|
}
|
|
@@ -4902,7 +5087,7 @@ function upsertMcp(file, target, launch) {
|
|
|
4902
5087
|
`);
|
|
4903
5088
|
}
|
|
4904
5089
|
function removeMcp(file, target) {
|
|
4905
|
-
if (!
|
|
5090
|
+
if (!fs16.existsSync(file)) return false;
|
|
4906
5091
|
const config = readJson(file);
|
|
4907
5092
|
const bag = config[target.key];
|
|
4908
5093
|
if (!bag || !(bag.vg !== void 0)) return false;
|
|
@@ -4921,8 +5106,8 @@ function refreshInstalledInstructions(root, smallRepo) {
|
|
|
4921
5106
|
};
|
|
4922
5107
|
for (const a of ASSISTANTS) {
|
|
4923
5108
|
if (a.skill) {
|
|
4924
|
-
const file =
|
|
4925
|
-
if (
|
|
5109
|
+
const file = path18.join(root, a.skill);
|
|
5110
|
+
if (fs16.existsSync(file)) {
|
|
4926
5111
|
const text = readTextSafe(file);
|
|
4927
5112
|
const from = text === null ? null : staleVersion(text, "# vg \u2014 the code map");
|
|
4928
5113
|
if (from !== null) {
|
|
@@ -4932,8 +5117,8 @@ function refreshInstalledInstructions(root, smallRepo) {
|
|
|
4932
5117
|
}
|
|
4933
5118
|
}
|
|
4934
5119
|
if (a.nudge) {
|
|
4935
|
-
const file =
|
|
4936
|
-
if (!
|
|
5120
|
+
const file = path18.join(root, a.nudge.file);
|
|
5121
|
+
if (!fs16.existsSync(file)) continue;
|
|
4937
5122
|
const text = readTextSafe(file);
|
|
4938
5123
|
if (text === null) continue;
|
|
4939
5124
|
if (a.nudge.kind === "block") {
|
|
@@ -4957,7 +5142,7 @@ function refreshInstalledInstructions(root, smallRepo) {
|
|
|
4957
5142
|
}
|
|
4958
5143
|
function readTextSafe(file) {
|
|
4959
5144
|
try {
|
|
4960
|
-
return
|
|
5145
|
+
return fs16.readFileSync(file, "utf8");
|
|
4961
5146
|
} catch {
|
|
4962
5147
|
return null;
|
|
4963
5148
|
}
|
|
@@ -4976,8 +5161,8 @@ ${stripMarkers(nudgeMarkdown(smallRepo, client))}` : stripMarkers(nudgeMarkdown(
|
|
|
4976
5161
|
upsertBlock(file, nudgeMarkdown(smallRepo, client));
|
|
4977
5162
|
}
|
|
4978
5163
|
function upsertBlock(file, block) {
|
|
4979
|
-
|
|
4980
|
-
let existing =
|
|
5164
|
+
fs16.mkdirSync(path18.dirname(file), { recursive: true });
|
|
5165
|
+
let existing = fs16.existsSync(file) ? fs16.readFileSync(file, "utf8") : "";
|
|
4981
5166
|
const re = new RegExp(`${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}`);
|
|
4982
5167
|
if (re.test(existing)) existing = existing.replace(re, block);
|
|
4983
5168
|
else existing = existing.length ? `${existing.replace(/\s*$/, "")}
|
|
@@ -4985,20 +5170,20 @@ function upsertBlock(file, block) {
|
|
|
4985
5170
|
${block}
|
|
4986
5171
|
` : `${block}
|
|
4987
5172
|
`;
|
|
4988
|
-
|
|
5173
|
+
fs16.writeFileSync(file, existing);
|
|
4989
5174
|
}
|
|
4990
5175
|
function removeBlock(file) {
|
|
4991
|
-
if (!
|
|
4992
|
-
const existing =
|
|
5176
|
+
if (!fs16.existsSync(file)) return false;
|
|
5177
|
+
const existing = fs16.readFileSync(file, "utf8");
|
|
4993
5178
|
const re = new RegExp(`\\n*${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}\\n*`);
|
|
4994
5179
|
if (!re.test(existing)) return false;
|
|
4995
|
-
|
|
5180
|
+
fs16.writeFileSync(file, existing.replace(re, "\n"));
|
|
4996
5181
|
return true;
|
|
4997
5182
|
}
|
|
4998
5183
|
function readJson(file) {
|
|
4999
|
-
if (!
|
|
5184
|
+
if (!fs16.existsSync(file)) return {};
|
|
5000
5185
|
try {
|
|
5001
|
-
const parsed = JSON.parse(
|
|
5186
|
+
const parsed = JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
5002
5187
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5003
5188
|
return parsed;
|
|
5004
5189
|
}
|
|
@@ -5018,7 +5203,7 @@ function escapeRe(s) {
|
|
|
5018
5203
|
}
|
|
5019
5204
|
var REFRESH_LOCK_STALE_MS = 10 * 60 * 1e3;
|
|
5020
5205
|
function refreshLockPath(root) {
|
|
5021
|
-
return
|
|
5206
|
+
return path18.join(cacheDir(root), "refresh.lock");
|
|
5022
5207
|
}
|
|
5023
5208
|
async function refreshIfStale(root, opts = {}) {
|
|
5024
5209
|
const probe = probeFreshness(root);
|
|
@@ -5050,8 +5235,8 @@ async function refreshIfStale(root, opts = {}) {
|
|
|
5050
5235
|
writeArtifacts(result.graph, {
|
|
5051
5236
|
root,
|
|
5052
5237
|
graphPath: opts.graphPath,
|
|
5053
|
-
report:
|
|
5054
|
-
html:
|
|
5238
|
+
report: fs16.existsSync(path18.join(dir, "GRAPH_REPORT.md")),
|
|
5239
|
+
html: fs16.existsSync(path18.join(dir, "graph.html"))
|
|
5055
5240
|
});
|
|
5056
5241
|
}
|
|
5057
5242
|
writeSnapshot(root, result.graph.provenance.corpusHash, result.fileStats, scope);
|
|
@@ -5071,6 +5256,6 @@ async function refreshIfStale(root, opts = {}) {
|
|
|
5071
5256
|
}
|
|
5072
5257
|
}
|
|
5073
5258
|
|
|
5074
|
-
export { ASSISTANTS, CliError, ExitCode, FREE_PACK, NPX_INVOCATION, ResourceLimitError,
|
|
5075
|
-
//# sourceMappingURL=chunk-
|
|
5076
|
-
//# sourceMappingURL=chunk-
|
|
5259
|
+
export { ASSISTANTS, CliError, ExitCode, FREE_PACK, NPX_INVOCATION, ResourceLimitError, SKIP_DIRS, SKIP_FILES, SMALL_REPO_FILES, TOOLS, UsageError, analyze, applyCoverage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, clearStoredCredentials, countTokens, coveringTests, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, detectAssistants, detectRunner, detectServeLaunch, discover, driftCount, dsnCommand, ensureGitignored, epistemicBreakdown, fetchHostedDocsCached, findGitRoot, gitignoreEntryForCredentials, groundGraph, hasDrift, homeCredentialsPath, hostedBase, ingestHostForRegionId, installAssistant, loadCoverage, loadSnapshot, parseDsn, probeFreshness, projectCredentialsPath, publishPrivateLibrary, pushCommand, readScanArtifact, readStoredCredentials, refreshIfStale, refreshInstalledInstructions, renderToolResult, resolveCliInvocation, resolveDsn, resolveIngestHost, resolveLimits, scipEdges, searchSymbols, selectForBudget, shortestPath, symbolsFromApi, testsToRun, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, warmEmbedderInBackground, writeNavigationConfig, writeSnapshot, writeStoredCredentials };
|
|
5260
|
+
//# sourceMappingURL=chunk-KNELIQJO.js.map
|
|
5261
|
+
//# sourceMappingURL=chunk-KNELIQJO.js.map
|