@vibgrate/cli 2026.717.1 → 2026.718.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/README.md +26 -0
- package/dist/baseline-DKPQWOQ6.js +6 -0
- package/dist/{baseline-YWGSHCKW.js.map → baseline-DKPQWOQ6.js.map} +1 -1
- package/dist/{chunk-WZNIDXZP.js → chunk-BFXDF6ZE.js} +3 -3
- package/dist/{chunk-WZNIDXZP.js.map → chunk-BFXDF6ZE.js.map} +1 -1
- package/dist/{chunk-L42NVMD6.js → chunk-H5M7CXE6.js} +35 -12
- package/dist/chunk-H5M7CXE6.js.map +1 -0
- package/dist/{chunk-M62BGJMK.js → chunk-RME7BFMU.js} +3 -3
- package/dist/{chunk-M62BGJMK.js.map → chunk-RME7BFMU.js.map} +1 -1
- package/dist/cli.js +192 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/baseline-YWGSHCKW.js +0 -6
- package/dist/chunk-L42NVMD6.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, CliError, ExitCode, NPX_INVOCATION, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, recordCliCall, CLI_TOOL_ALIASES, countPending, resolveOne, indexFor, countTokens, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, serveStdio, ASSISTANTS, detectAssistants, usageError, loadGraph, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, readUsage, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, epistemicBreakdown, cacheDir, probeFreshness, discover, vibgrateDir, modelCacheInfo, clearModelCache, GraphSource, createServer, assistantById, serializeGraph, resolveLimits, loadCatalog, driftFor, addLibrary, parseDsn as parseDsn$1, publishPrivateLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, formatForExt, verifyDeterminism, renderHtml, isModelReady, SKIP_DIRS, SKIP_FILES } from './chunk-
|
|
2
|
+
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, CliError, ExitCode, NPX_INVOCATION, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, recordCliCall, CLI_TOOL_ALIASES, countPending, resolveOne, indexFor, countTokens, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, serveStdio, ASSISTANTS, detectAssistants, usageError, loadGraph, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, readUsage, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, epistemicBreakdown, cacheDir, probeFreshness, discover, vibgrateDir, modelCacheInfo, clearModelCache, GraphSource, createServer, assistantById, serializeGraph, resolveLimits, loadCatalog, driftFor, addLibrary, parseDsn as parseDsn$1, publishPrivateLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, formatForExt, hostedBase, verifyDeterminism, renderHtml, isModelReady, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-H5M7CXE6.js';
|
|
3
3
|
import { resolvedGrammarFiles, grammarSetVersion, hashString, canonicalize, hashBytes } from './chunk-VFO5UDAT.js';
|
|
4
|
-
import { loadAdvancedScanHook, baselineCommand } from './chunk-
|
|
5
|
-
import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, brandProgressBar, resolveHead, workingTreeDirty } from './chunk-
|
|
4
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-BFXDF6ZE.js';
|
|
5
|
+
import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, brandProgressBar, resolveHead, workingTreeDirty } from './chunk-RME7BFMU.js';
|
|
6
6
|
import './chunk-RXP66R2E.js';
|
|
7
7
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
|
|
8
8
|
import * as fs8 from 'fs';
|
|
@@ -16,7 +16,7 @@ import * as crypto from 'crypto';
|
|
|
16
16
|
import { randomUUID } from 'crypto';
|
|
17
17
|
import chalk8 from 'chalk';
|
|
18
18
|
import * as os from 'os';
|
|
19
|
-
import * as
|
|
19
|
+
import * as fs15 from 'fs/promises';
|
|
20
20
|
import * as readline from 'readline';
|
|
21
21
|
import semver from 'semver';
|
|
22
22
|
|
|
@@ -1287,7 +1287,31 @@ var OFFSET_FILE = "stats-share.json";
|
|
|
1287
1287
|
var INSTALL_ID_DIR = path.join(os.homedir(), ".vibgrate");
|
|
1288
1288
|
var INSTALL_ID_FILE = path.join(INSTALL_ID_DIR, "install-id");
|
|
1289
1289
|
var SEND_TIMEOUT_MS = 4e3;
|
|
1290
|
-
function
|
|
1290
|
+
function telemetryOptOut(env = process.env) {
|
|
1291
|
+
const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
|
|
1292
|
+
if (dnt !== "" && dnt !== "0" && dnt !== "false") return "DO_NOT_TRACK";
|
|
1293
|
+
const vt = (env.VIBGRATE_TELEMETRY ?? "").trim().toLowerCase();
|
|
1294
|
+
if (vt === "0" || vt === "false" || vt === "off") return "VIBGRATE_TELEMETRY";
|
|
1295
|
+
return null;
|
|
1296
|
+
}
|
|
1297
|
+
var CI_ENV_VARS = [
|
|
1298
|
+
"CI",
|
|
1299
|
+
"GITHUB_ACTIONS",
|
|
1300
|
+
"GITLAB_CI",
|
|
1301
|
+
"CIRCLECI",
|
|
1302
|
+
"TRAVIS",
|
|
1303
|
+
"BUILDKITE",
|
|
1304
|
+
"JENKINS_URL",
|
|
1305
|
+
"TF_BUILD"
|
|
1306
|
+
];
|
|
1307
|
+
function isCI(env = process.env) {
|
|
1308
|
+
return CI_ENV_VARS.some((v) => {
|
|
1309
|
+
const val = (env[v] ?? "").trim().toLowerCase();
|
|
1310
|
+
return val !== "" && val !== "0" && val !== "false";
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
function installId(env = process.env) {
|
|
1314
|
+
if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
|
|
1291
1315
|
try {
|
|
1292
1316
|
const existing = fs8.readFileSync(INSTALL_ID_FILE, "utf8").trim();
|
|
1293
1317
|
if (isUuid(existing)) return existing;
|
|
@@ -1463,6 +1487,27 @@ var StatsSharer = class {
|
|
|
1463
1487
|
}
|
|
1464
1488
|
};
|
|
1465
1489
|
|
|
1490
|
+
// src/util/origin.ts
|
|
1491
|
+
function originAllowed(origin, allowlist) {
|
|
1492
|
+
if (origin === void 0 || origin === "") return true;
|
|
1493
|
+
const allowed = (allowlist ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
1494
|
+
if (allowed.includes("*")) return true;
|
|
1495
|
+
if (allowed.includes(origin)) return true;
|
|
1496
|
+
return isLoopbackOrigin(origin);
|
|
1497
|
+
}
|
|
1498
|
+
function isLoopbackOrigin(origin) {
|
|
1499
|
+
let url;
|
|
1500
|
+
try {
|
|
1501
|
+
url = new URL(origin);
|
|
1502
|
+
} catch {
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
1506
|
+
const host = url.hostname;
|
|
1507
|
+
if (host === "localhost" || host === "[::1]" || host === "::1") return true;
|
|
1508
|
+
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1466
1511
|
// src/commands/serve.ts
|
|
1467
1512
|
var SHARE_FLUSH_INTERVAL_MS = 5 * 60 * 1e3;
|
|
1468
1513
|
function registerServe(program) {
|
|
@@ -1472,9 +1517,14 @@ function registerServe(program) {
|
|
|
1472
1517
|
const graphPath = global.graph ?? defaultGraphPath(root);
|
|
1473
1518
|
const refresh = opts.refresh !== false && !global.graph;
|
|
1474
1519
|
const local = global.local === true;
|
|
1475
|
-
const
|
|
1520
|
+
const optOut = telemetryOptOut();
|
|
1521
|
+
const shareStats = opts.shareStats === true && !local && optOut === null;
|
|
1476
1522
|
const serveOpts = {
|
|
1477
|
-
|
|
1523
|
+
// A *requested* --share-stats always implies local recording, even when
|
|
1524
|
+
// the upload itself is suppressed (--local / env opt-out) — the local
|
|
1525
|
+
// ledger never leaves the machine, and the disclosure messages below
|
|
1526
|
+
// promise "recording locally".
|
|
1527
|
+
savings: opts.savings === true || opts.shareStats === true,
|
|
1478
1528
|
shareStats,
|
|
1479
1529
|
local,
|
|
1480
1530
|
dedup: opts.dedup === true,
|
|
@@ -1483,6 +1533,8 @@ function registerServe(program) {
|
|
|
1483
1533
|
await ensureServableGraph(root, graphPath, global, refresh);
|
|
1484
1534
|
if (opts.shareStats === true && local) {
|
|
1485
1535
|
info(c.dim("vg \xB7 --share-stats ignored under --local (air-gapped): recording locally, not uploading."));
|
|
1536
|
+
} else if (opts.shareStats === true && optOut !== null) {
|
|
1537
|
+
info(c.dim(`vg \xB7 --share-stats disabled by ${optOut}: recording locally, not uploading.`));
|
|
1486
1538
|
}
|
|
1487
1539
|
if (shareStats) startSharing(root);
|
|
1488
1540
|
const freshness = refresh ? "auto-refresh" : "as built";
|
|
@@ -1555,6 +1607,13 @@ async function serveHttp(graphPath, host, port, opts, freshness) {
|
|
|
1555
1607
|
res.writeHead(404).end("not found");
|
|
1556
1608
|
return;
|
|
1557
1609
|
}
|
|
1610
|
+
const origin = req.headers.origin;
|
|
1611
|
+
if (!originAllowed(origin, process.env.VIBGRATE_ALLOWED_ORIGINS)) {
|
|
1612
|
+
res.writeHead(403, { "Content-Type": "text/plain" }).end(
|
|
1613
|
+
"forbidden origin \u2014 vg serve only accepts browser requests from loopback origins. Set VIBGRATE_ALLOWED_ORIGINS to allow others."
|
|
1614
|
+
);
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1558
1617
|
try {
|
|
1559
1618
|
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
1560
1619
|
const server = createServer(source, opts);
|
|
@@ -3803,6 +3862,125 @@ function registerBundle(program) {
|
|
|
3803
3862
|
});
|
|
3804
3863
|
applyGlobalOptions(cmd);
|
|
3805
3864
|
}
|
|
3865
|
+
function registerDoctor(program) {
|
|
3866
|
+
const cmd = program.command("doctor").description("diagnose your setup: config, credentials, map freshness, hosted reachability, MCP launch").action(async function() {
|
|
3867
|
+
await runDoctor(readGlobal(this));
|
|
3868
|
+
});
|
|
3869
|
+
applyGlobalOptions(cmd);
|
|
3870
|
+
}
|
|
3871
|
+
var REACH_TIMEOUT_MS = 3e3;
|
|
3872
|
+
var CONFIG_BASENAMES = ["vibgrate.config.ts", "vibgrate.config.js", "vibgrate.config.json"];
|
|
3873
|
+
async function runDoctor(global) {
|
|
3874
|
+
const root = rootOf(global);
|
|
3875
|
+
const local = global.local === true;
|
|
3876
|
+
const graphPath = global.graph ?? defaultGraphPath(root);
|
|
3877
|
+
const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path.join(root, f))) ?? null;
|
|
3878
|
+
const graph = loadGraph(root, graphPath);
|
|
3879
|
+
let staleFiles = null;
|
|
3880
|
+
if (graph) {
|
|
3881
|
+
const probe = probeFreshness(root);
|
|
3882
|
+
if (probe) staleFiles = driftCount(probe.drift);
|
|
3883
|
+
}
|
|
3884
|
+
const catalog = loadCatalog(root);
|
|
3885
|
+
const libCount = Object.keys(catalog.libraries).length;
|
|
3886
|
+
const creds = diagnoseCredentials(root);
|
|
3887
|
+
const base = hostedBase();
|
|
3888
|
+
const reachable = local ? null : await probeReachable(base);
|
|
3889
|
+
const launch = detectServeLaunch();
|
|
3890
|
+
const optOut = telemetryOptOut();
|
|
3891
|
+
const d = {
|
|
3892
|
+
version: VERSION,
|
|
3893
|
+
node: process.version,
|
|
3894
|
+
platform: `${process.platform}/${process.arch}`,
|
|
3895
|
+
root,
|
|
3896
|
+
configFile,
|
|
3897
|
+
map: {
|
|
3898
|
+
path: path.relative(root, graphPath),
|
|
3899
|
+
built: graph !== null,
|
|
3900
|
+
generatedAt: graph?.generatedAt ?? null,
|
|
3901
|
+
staleFiles
|
|
3902
|
+
},
|
|
3903
|
+
libCatalog: {
|
|
3904
|
+
path: path.relative(root, catalogPath(root)),
|
|
3905
|
+
present: fs8.existsSync(catalogPath(root)),
|
|
3906
|
+
libraries: libCount
|
|
3907
|
+
},
|
|
3908
|
+
credentials: creds,
|
|
3909
|
+
hosted: { base, checked: !local, reachable },
|
|
3910
|
+
mcpLaunch: { command: launch.command, args: launch.args, note: launch.note ?? null },
|
|
3911
|
+
telemetry: { optOut, ci: isCI(), endpoint: statsEndpoint() }
|
|
3912
|
+
};
|
|
3913
|
+
if (global.json) {
|
|
3914
|
+
json(d);
|
|
3915
|
+
return;
|
|
3916
|
+
}
|
|
3917
|
+
info(`${c.cyan("vg")} doctor \xB7 v${d.version} \xB7 node ${d.node} \xB7 ${d.platform}`);
|
|
3918
|
+
info(` root ${d.root}`);
|
|
3919
|
+
info(` config ${d.configFile ? c.green(d.configFile) : c.dim("none (defaults) \u2014 `vg init` writes one")}`);
|
|
3920
|
+
if (!d.map.built) {
|
|
3921
|
+
info(` map ${c.yellow("none")} \u2014 run ${c.bold("vg")} to build ${c.dim(d.map.path)}`);
|
|
3922
|
+
} else {
|
|
3923
|
+
const fresh = d.map.staleFiles == null ? c.dim("freshness unknown (no snapshot)") : d.map.staleFiles === 0 ? c.green("up to date") : c.yellow(`${d.map.staleFiles} file(s) stale \u2014 auto-refreshes on next query`);
|
|
3924
|
+
info(` map ${c.green("built")} ${c.dim(d.map.generatedAt ?? "")} \xB7 ${fresh}`);
|
|
3925
|
+
}
|
|
3926
|
+
info(
|
|
3927
|
+
` lib ${d.libCatalog.present ? `${c.green(String(d.libCatalog.libraries))} librar${d.libCatalog.libraries === 1 ? "y" : "ies"} in ${d.libCatalog.path}` : c.dim("no catalog \u2014 `vg lib add <source>` starts one; `vg lib <name>` works without it")}`
|
|
3928
|
+
);
|
|
3929
|
+
if (d.credentials.source === "none") {
|
|
3930
|
+
info(` auth ${c.dim("anonymous \u2014 fine for everything local; `vg login` enables push/publish")}`);
|
|
3931
|
+
} else {
|
|
3932
|
+
info(
|
|
3933
|
+
` auth ${c.green(d.credentials.source)} ${c.dim(d.credentials.path ?? "")} \xB7 workspace ${d.credentials.workspaceId ?? "?"} \xB7 ${d.credentials.host ?? "?"}`
|
|
3934
|
+
);
|
|
3935
|
+
}
|
|
3936
|
+
if (!d.hosted.checked) {
|
|
3937
|
+
info(` hosted ${c.dim(`skipped under --local (${d.hosted.base})`)}`);
|
|
3938
|
+
} else {
|
|
3939
|
+
info(
|
|
3940
|
+
` hosted ${d.hosted.base} \xB7 ${d.hosted.reachable ? c.green("reachable") : c.yellow("unreachable \u2014 local answers still work")}`
|
|
3941
|
+
);
|
|
3942
|
+
}
|
|
3943
|
+
info(
|
|
3944
|
+
` mcp ${c.bold(`${d.mcpLaunch.command} ${d.mcpLaunch.args.join(" ")}`)}${d.mcpLaunch.note ? c.dim(` (${d.mcpLaunch.note})`) : ""}`
|
|
3945
|
+
);
|
|
3946
|
+
const tel = d.telemetry.optOut ? c.green(`opted out via ${d.telemetry.optOut}`) : "off by default \u2014 only `vg serve --share-stats` ever uploads";
|
|
3947
|
+
info(` telemetry ${tel}${d.telemetry.ci ? c.dim(" \xB7 CI detected") : ""}`);
|
|
3948
|
+
}
|
|
3949
|
+
function diagnoseCredentials(root) {
|
|
3950
|
+
const none = { source: "none", path: null, host: null, workspaceId: null };
|
|
3951
|
+
if (process.env.VIBGRATE_DSN) {
|
|
3952
|
+
const parsed2 = parseDsn$1(process.env.VIBGRATE_DSN);
|
|
3953
|
+
return { source: "env", path: null, host: parsed2?.host ?? null, workspaceId: parsed2?.workspaceId ?? null };
|
|
3954
|
+
}
|
|
3955
|
+
const stored = readStoredCredentials({ cwd: root });
|
|
3956
|
+
if (!stored) return none;
|
|
3957
|
+
const file = credentialsPath({ cwd: root });
|
|
3958
|
+
const source = process.env.VIBGRATE_CREDENTIALS ? "env" : file === projectCredentialsPath(root) ? "project" : "home";
|
|
3959
|
+
const parsed = parseDsn$1(stored.dsn);
|
|
3960
|
+
return {
|
|
3961
|
+
source,
|
|
3962
|
+
path: shortenHome(file),
|
|
3963
|
+
host: stored.ingestHost ?? parsed?.host ?? null,
|
|
3964
|
+
workspaceId: stored.workspaceId ?? parsed?.workspaceId ?? null
|
|
3965
|
+
};
|
|
3966
|
+
}
|
|
3967
|
+
function shortenHome(p) {
|
|
3968
|
+
const home = homeCredentialsPath().slice(0, -"/.vibgrate/credentials.json".length);
|
|
3969
|
+
return p.startsWith(home) ? `~${p.slice(home.length)}` : p;
|
|
3970
|
+
}
|
|
3971
|
+
async function probeReachable(base) {
|
|
3972
|
+
const controller = new AbortController();
|
|
3973
|
+
const timer = setTimeout(() => controller.abort(), REACH_TIMEOUT_MS);
|
|
3974
|
+
timer.unref?.();
|
|
3975
|
+
try {
|
|
3976
|
+
await fetch(base, { method: "HEAD", signal: controller.signal });
|
|
3977
|
+
return true;
|
|
3978
|
+
} catch {
|
|
3979
|
+
return false;
|
|
3980
|
+
} finally {
|
|
3981
|
+
clearTimeout(timer);
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3806
3984
|
var initCommand = new Command("init").description("Initialize vibgrate in a project").argument("[path]", "Path to initialize", ".").option("--baseline", "Create initial baseline after init").option("--yes", "Skip confirmation prompts").action(async (targetPath, opts) => {
|
|
3807
3985
|
const rootDir = path.resolve(targetPath);
|
|
3808
3986
|
const vibgrateDir2 = path.join(rootDir, ".vibgrate");
|
|
@@ -3816,7 +3994,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
3816
3994
|
console.log(chalk8.green("\u2714") + ` Created ${chalk8.bold("vibgrate.config.ts")}`);
|
|
3817
3995
|
}
|
|
3818
3996
|
if (opts.baseline) {
|
|
3819
|
-
const { runBaseline } = await import('./baseline-
|
|
3997
|
+
const { runBaseline } = await import('./baseline-DKPQWOQ6.js');
|
|
3820
3998
|
await runBaseline(rootDir);
|
|
3821
3999
|
}
|
|
3822
4000
|
console.log("");
|
|
@@ -3926,9 +4104,9 @@ async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3)
|
|
|
3926
4104
|
}
|
|
3927
4105
|
async function defaultReadFile(absPath) {
|
|
3928
4106
|
try {
|
|
3929
|
-
const stat2 = await
|
|
4107
|
+
const stat2 = await fs15.stat(absPath);
|
|
3930
4108
|
if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
|
|
3931
|
-
return await
|
|
4109
|
+
return await fs15.readFile(absPath, "utf8");
|
|
3932
4110
|
} catch {
|
|
3933
4111
|
return null;
|
|
3934
4112
|
}
|
|
@@ -5121,8 +5299,8 @@ async function fetchLatestVersion() {
|
|
|
5121
5299
|
}
|
|
5122
5300
|
async function writeCache(data) {
|
|
5123
5301
|
try {
|
|
5124
|
-
await
|
|
5125
|
-
await
|
|
5302
|
+
await fs15.mkdir(CACHE_DIR, { recursive: true });
|
|
5303
|
+
await fs15.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
|
|
5126
5304
|
} catch {
|
|
5127
5305
|
}
|
|
5128
5306
|
}
|
|
@@ -6949,6 +7127,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
6949
7127
|
"oddities",
|
|
6950
7128
|
"serve",
|
|
6951
7129
|
"lsp",
|
|
7130
|
+
"doctor",
|
|
6952
7131
|
"install",
|
|
6953
7132
|
"uninstall",
|
|
6954
7133
|
"share",
|
|
@@ -7004,6 +7183,7 @@ ${aliasNote}Docs: https://vibgrate.com/help`;
|
|
|
7004
7183
|
registerLib(program);
|
|
7005
7184
|
registerExport(program);
|
|
7006
7185
|
registerBundle(program);
|
|
7186
|
+
registerDoctor(program);
|
|
7007
7187
|
program.addCommand(initCommand);
|
|
7008
7188
|
program.addCommand(scanCommand);
|
|
7009
7189
|
program.addCommand(fixCommand);
|