@vibgrate/cli 2026.803.1 → 2026.803.4
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/agent-WYBWUBCC.js +26 -0
- package/dist/{agent-HNV2VUCO.js.map → agent-WYBWUBCC.js.map} +1 -1
- package/dist/baseline-3HECX4Q6.js +9 -0
- package/dist/{baseline-6WTULHM5.js.map → baseline-3HECX4Q6.js.map} +1 -1
- package/dist/{chunk-FKFRASAB.js → chunk-23UPIFRU.js} +8 -8
- package/dist/{chunk-FKFRASAB.js.map → chunk-23UPIFRU.js.map} +1 -1
- package/dist/chunk-2A7XCANX.js +375 -0
- package/dist/chunk-2A7XCANX.js.map +1 -0
- package/dist/{chunk-AJ2KE3NT.js → chunk-4LGDQBYK.js} +14 -102
- package/dist/chunk-4LGDQBYK.js.map +1 -0
- package/dist/{chunk-B2KLJPFY.js → chunk-4ZMJKR74.js} +451 -22
- package/dist/chunk-4ZMJKR74.js.map +1 -0
- package/dist/{chunk-DIU3MXB3.js → chunk-537JBQVB.js} +4 -4
- package/dist/{chunk-DIU3MXB3.js.map → chunk-537JBQVB.js.map} +1 -1
- package/dist/{chunk-4HFSUIIN.js → chunk-5TS7N7J2.js} +59 -9
- package/dist/chunk-5TS7N7J2.js.map +1 -0
- package/dist/{chunk-BWMMR5XA.js → chunk-5WMFX7TY.js} +4 -4
- package/dist/{chunk-BWMMR5XA.js.map → chunk-5WMFX7TY.js.map} +1 -1
- package/dist/{chunk-SNKTD23L.js → chunk-66B4ZQA3.js} +9 -8
- package/dist/chunk-66B4ZQA3.js.map +1 -0
- package/dist/{chunk-536J6HUR.js → chunk-7BU7CWXC.js} +39 -12
- package/dist/chunk-7BU7CWXC.js.map +1 -0
- package/dist/{chunk-N4IDP2M2.js → chunk-7TOIESUT.js} +5 -4
- package/dist/chunk-7TOIESUT.js.map +1 -0
- package/dist/{chunk-CE45STY5.js → chunk-BRUMBQV7.js} +4 -4
- package/dist/{chunk-CE45STY5.js.map → chunk-BRUMBQV7.js.map} +1 -1
- package/dist/{chunk-CC6F75GI.js → chunk-BUCNKYTW.js} +5 -5
- package/dist/{chunk-CC6F75GI.js.map → chunk-BUCNKYTW.js.map} +1 -1
- package/dist/{chunk-2TLQDF6C.js → chunk-FAA7RBIG.js} +9 -9
- package/dist/{chunk-2TLQDF6C.js.map → chunk-FAA7RBIG.js.map} +1 -1
- package/dist/chunk-FZ5Y4KEI.js +6 -0
- package/dist/{chunk-QT2PMGN3.js.map → chunk-FZ5Y4KEI.js.map} +1 -1
- package/dist/{chunk-S4NSF5AZ.js → chunk-HBQC4XQJ.js} +6 -6
- package/dist/{chunk-S4NSF5AZ.js.map → chunk-HBQC4XQJ.js.map} +1 -1
- package/dist/{chunk-O7MTBC52.js → chunk-HVHCXM2E.js} +9 -9
- package/dist/{chunk-O7MTBC52.js.map → chunk-HVHCXM2E.js.map} +1 -1
- package/dist/{chunk-NJFQCDGA.js → chunk-INIULQEP.js} +3 -3
- package/dist/{chunk-NJFQCDGA.js.map → chunk-INIULQEP.js.map} +1 -1
- package/dist/{chunk-Y7YKUZ3T.js → chunk-JZGVUH57.js} +30 -10
- package/dist/chunk-JZGVUH57.js.map +1 -0
- package/dist/{chunk-JUSXLCSE.js → chunk-KFK7KCAH.js} +3 -3
- package/dist/{chunk-JUSXLCSE.js.map → chunk-KFK7KCAH.js.map} +1 -1
- package/dist/{chunk-6I4TXAI6.js → chunk-OVDL76LB.js} +3 -3
- package/dist/{chunk-6I4TXAI6.js.map → chunk-OVDL76LB.js.map} +1 -1
- package/dist/{chunk-SJFBXCII.js → chunk-QUI3E3TQ.js} +54 -9
- package/dist/chunk-QUI3E3TQ.js.map +1 -0
- package/dist/chunk-RBMKBYGV.js +102 -0
- package/dist/chunk-RBMKBYGV.js.map +1 -0
- package/dist/{chunk-5VH3Y4QC.js → chunk-TVRM57CE.js} +78 -381
- package/dist/chunk-TVRM57CE.js.map +1 -0
- package/dist/{chunk-BBFQZ7CA.js → chunk-UWVFLVZX.js} +4 -4
- package/dist/{chunk-BBFQZ7CA.js.map → chunk-UWVFLVZX.js.map} +1 -1
- package/dist/{chunk-6JP7HGIF.js → chunk-Y4JO6LYP.js} +3 -3
- package/dist/{chunk-6JP7HGIF.js.map → chunk-Y4JO6LYP.js.map} +1 -1
- package/dist/cli.js +555 -351
- package/dist/cli.js.map +1 -1
- package/dist/embed-worker-main.d.ts +2 -0
- package/dist/embed-worker-main.js +64 -0
- package/dist/embed-worker-main.js.map +1 -0
- package/dist/ensure-map-DZ53QXRT.js +31 -0
- package/dist/{ensure-map-5YEI7R7V.js.map → ensure-map-DZ53QXRT.js.map} +1 -1
- package/dist/graph-backend-3A2M22QN.js +13 -0
- package/dist/{graph-backend-CPHLUKUC.js.map → graph-backend-3A2M22QN.js.map} +1 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.js +16 -14
- package/dist/index.js.map +1 -1
- package/dist/{interactive-TNRE4OEK.js → interactive-DB7IC3BL.js} +35 -29
- package/dist/interactive-DB7IC3BL.js.map +1 -0
- package/dist/load-6KVGUQMU.js +11 -0
- package/dist/{load-MWG6WZTK.js.map → load-6KVGUQMU.js.map} +1 -1
- package/dist/{run-outcome-375HMSQG.js → run-outcome-YOYRC32U.js} +7 -6
- package/dist/run-outcome-YOYRC32U.js.map +1 -0
- package/dist/runtime-session-XEP7IPGP.js +22 -0
- package/dist/{runtime-session-3MPWXNRL.js.map → runtime-session-XEP7IPGP.js.map} +1 -1
- package/dist/session-5WKEACIF.js +17 -0
- package/dist/{session-2NGJLI5Y.js.map → session-5WKEACIF.js.map} +1 -1
- package/dist/{stream-json-AUMU3NLV.js → stream-json-3OJCPBWY.js} +13 -11
- package/dist/stream-json-3OJCPBWY.js.map +1 -0
- package/dist/{vg-mcp-bridge-D463EHQI.js → vg-mcp-bridge-PM3C4FQL.js} +12 -10
- package/dist/vg-mcp-bridge-PM3C4FQL.js.map +1 -0
- package/dist/{vgd-Z23PXSP4.js → vgd-UTLMMPIZ.js} +12 -10
- package/dist/vgd-UTLMMPIZ.js.map +1 -0
- package/package.json +1 -1
- package/scripts/postinstall.mjs +22 -1
- package/dist/agent-HNV2VUCO.js +0 -24
- package/dist/baseline-6WTULHM5.js +0 -9
- package/dist/chunk-4HFSUIIN.js.map +0 -1
- package/dist/chunk-536J6HUR.js.map +0 -1
- package/dist/chunk-5VH3Y4QC.js.map +0 -1
- package/dist/chunk-AJ2KE3NT.js.map +0 -1
- package/dist/chunk-B2KLJPFY.js.map +0 -1
- package/dist/chunk-N4IDP2M2.js.map +0 -1
- package/dist/chunk-QT2PMGN3.js +0 -6
- package/dist/chunk-SJFBXCII.js.map +0 -1
- package/dist/chunk-SNKTD23L.js.map +0 -1
- package/dist/chunk-Y7YKUZ3T.js.map +0 -1
- package/dist/ensure-map-5YEI7R7V.js +0 -29
- package/dist/graph-backend-CPHLUKUC.js +0 -11
- package/dist/interactive-TNRE4OEK.js.map +0 -1
- package/dist/load-MWG6WZTK.js +0 -10
- package/dist/run-outcome-375HMSQG.js.map +0 -1
- package/dist/runtime-session-3MPWXNRL.js +0 -20
- package/dist/session-2NGJLI5Y.js +0 -15
- package/dist/stream-json-AUMU3NLV.js.map +0 -1
- package/dist/vg-mcp-bridge-D463EHQI.js.map +0 -1
- package/dist/vgd-Z23PXSP4.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,71 +1,73 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loadAdvancedScanHook, baselineCommand } from './chunk-
|
|
3
|
-
import { fetchCatalog, resolveProviders } from './chunk-
|
|
4
|
-
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-
|
|
5
|
-
import
|
|
2
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-Y4JO6LYP.js';
|
|
3
|
+
import { fetchCatalog, resolveProviders } from './chunk-5TS7N7J2.js';
|
|
4
|
+
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-4ZMJKR74.js';
|
|
5
|
+
import './chunk-IS7VTH2Q.js';
|
|
6
|
+
import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-UWVFLVZX.js';
|
|
7
|
+
import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-7BU7CWXC.js';
|
|
8
|
+
import './chunk-543E6WDJ.js';
|
|
6
9
|
import './chunk-7AVYKZEM.js';
|
|
7
10
|
import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
|
|
8
|
-
import { runCodeSession } from './chunk-
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
+
import { runCodeSession } from './chunk-BUCNKYTW.js';
|
|
12
|
+
import { summarizeDiffs, ScriptedProvider } from './chunk-QUI3E3TQ.js';
|
|
13
|
+
import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
|
|
14
|
+
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, runBuild } from './chunk-HVHCXM2E.js';
|
|
15
|
+
export { runBuild } from './chunk-HVHCXM2E.js';
|
|
11
16
|
import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
|
|
12
|
-
import './chunk-IS7VTH2Q.js';
|
|
13
17
|
import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
|
|
14
18
|
import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
|
|
15
19
|
import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
|
|
16
20
|
import './chunk-IZDH67DX.js';
|
|
21
|
+
import './chunk-KFK7KCAH.js';
|
|
22
|
+
import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
|
|
17
23
|
import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-JFE7XCAE.js';
|
|
18
24
|
import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-3LOWJSAF.js';
|
|
19
|
-
import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-536J6HUR.js';
|
|
20
|
-
import './chunk-543E6WDJ.js';
|
|
21
|
-
import { summarizeDiffs, ScriptedProvider } from './chunk-SJFBXCII.js';
|
|
22
|
-
import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
|
|
23
|
-
import './chunk-JUSXLCSE.js';
|
|
24
|
-
import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
|
|
25
25
|
import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
|
|
26
|
-
import { serveStdio, isRelevantChange, exportGraph, GraphSource, createServer, formatForExt } from './chunk-
|
|
27
|
-
import { refreshIfStale } from './chunk-
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
26
|
+
import { serveStdio, isRelevantChange, exportGraph, GraphSource, createServer, formatForExt } from './chunk-FAA7RBIG.js';
|
|
27
|
+
import { refreshIfStale } from './chunk-HBQC4XQJ.js';
|
|
28
|
+
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-JZGVUH57.js';
|
|
29
|
+
import { CliError, ExitCode, driftCount, ASSISTANTS, detectAssistants, isAssistantInstalled, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, isSkippedDirName, SKIP_FILES, SKIP_DIRS } from './chunk-23UPIFRU.js';
|
|
30
|
+
import { resolveDsn, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-66B4ZQA3.js';
|
|
31
|
+
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, perDependencyDrift } from './chunk-INIULQEP.js';
|
|
31
32
|
import { resolveIngestHost, dashHostForIngestHost, availableRegionIds, ingestHostForRegionId } from './chunk-HTLDXEHW.js';
|
|
33
|
+
import './chunk-VIWZ4QT7.js';
|
|
34
|
+
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-5WMFX7TY.js';
|
|
32
35
|
import { discoverModels } from './chunk-CQDUBAQY.js';
|
|
33
36
|
import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
|
|
37
|
+
import './chunk-5I4VSBWQ.js';
|
|
34
38
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-DT4KIVRI.js';
|
|
35
39
|
import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
|
|
36
|
-
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-Y7YKUZ3T.js';
|
|
37
|
-
import './chunk-VIWZ4QT7.js';
|
|
38
|
-
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-BWMMR5XA.js';
|
|
39
40
|
import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
|
|
40
41
|
import { resolveOne } from './chunk-J7LKEB2R.js';
|
|
41
|
-
import {
|
|
42
|
+
import { queryGraphSemantic, queryGraph, indexFor, impactOf } from './chunk-TVRM57CE.js';
|
|
42
43
|
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
|
|
43
44
|
import './chunk-RXP66R2E.js';
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
48
|
-
import './chunk-
|
|
45
|
+
import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, unavailableMessage, countPending, modelCacheInfo, clearModelCache, withTimeout } from './chunk-2A7XCANX.js';
|
|
46
|
+
import { loadGraph, loadGraphPreferIndex, SCHEMA_VERSION } from './chunk-537JBQVB.js';
|
|
47
|
+
import { resolveGraphPath, analyzeQuestion, loadTopicTags, renderReport, resetRelevanceProviderCache, loadRelevanceProvider, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, relevanceModuleDir, ensureVibgrateGitignore } from './chunk-7TOIESUT.js';
|
|
48
|
+
import { VERSION } from './chunk-FZ5Y4KEI.js';
|
|
49
|
+
import './chunk-4LGDQBYK.js';
|
|
50
|
+
import { cacheDir, serializeGraph, stableStringify, parseGraph } from './chunk-RBMKBYGV.js';
|
|
49
51
|
import './chunk-BWPBB45M.js';
|
|
50
52
|
import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
|
|
51
53
|
import './chunk-BPF3YX2U.js';
|
|
52
54
|
import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
|
|
53
|
-
import * as
|
|
54
|
-
import
|
|
55
|
-
import * as
|
|
56
|
-
import
|
|
55
|
+
import * as fs11 from 'fs';
|
|
56
|
+
import fs11__default, { realpathSync } from 'fs';
|
|
57
|
+
import * as path40 from 'path';
|
|
58
|
+
import path40__default from 'path';
|
|
57
59
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
58
60
|
import { Command, CommanderError, Option } from 'commander';
|
|
61
|
+
import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
|
|
62
|
+
import * as os from 'os';
|
|
59
63
|
import * as semver3 from 'semver';
|
|
60
64
|
import semver3__default from 'semver';
|
|
61
65
|
import * as readline from 'readline';
|
|
62
66
|
import * as zlib from 'zlib';
|
|
63
67
|
import * as crypto3 from 'crypto';
|
|
64
68
|
import { randomUUID, createHash } from 'crypto';
|
|
65
|
-
import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
|
|
66
69
|
import chalk7 from 'chalk';
|
|
67
|
-
import * as
|
|
68
|
-
import * as os from 'os';
|
|
70
|
+
import * as fs25 from 'fs/promises';
|
|
69
71
|
|
|
70
72
|
init_cli_invocation();
|
|
71
73
|
function registerStatus(program) {
|
|
@@ -75,10 +77,10 @@ function registerStatus(program) {
|
|
|
75
77
|
applyGlobalOptions(cmd);
|
|
76
78
|
}
|
|
77
79
|
async function runStatus(global) {
|
|
78
|
-
const root2 =
|
|
80
|
+
const root2 = path40.resolve(global.cwd ?? ".");
|
|
79
81
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
80
82
|
const graph = loadGraph(root2, graphPath);
|
|
81
|
-
const hasCache =
|
|
83
|
+
const hasCache = fs11.existsSync(path40.join(cacheDir(root2), "parse-cache.json"));
|
|
82
84
|
let stale = null;
|
|
83
85
|
let staleExact = false;
|
|
84
86
|
if (graph) {
|
|
@@ -98,8 +100,8 @@ async function runStatus(global) {
|
|
|
98
100
|
}
|
|
99
101
|
if (global.json) {
|
|
100
102
|
json({
|
|
101
|
-
root:
|
|
102
|
-
graphPath:
|
|
103
|
+
root: path40.relative(process.cwd(), root2) || ".",
|
|
104
|
+
graphPath: path40.relative(root2, graphPath),
|
|
103
105
|
built: graph !== null,
|
|
104
106
|
generatedAt: graph?.generatedAt ?? null,
|
|
105
107
|
counts: graph?.meta.counts ?? null,
|
|
@@ -114,11 +116,11 @@ async function runStatus(global) {
|
|
|
114
116
|
return;
|
|
115
117
|
}
|
|
116
118
|
if (!graph) {
|
|
117
|
-
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(
|
|
119
|
+
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path40.relative(root2, graphPath))}`);
|
|
118
120
|
info(` run ${c.bold("vg")} to build one`);
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
|
-
info(`${c.cyan("vg")} \xB7 ${
|
|
123
|
+
info(`${c.cyan("vg")} \xB7 ${path40.relative(root2, graphPath)}`);
|
|
122
124
|
info(` generated ${graph.generatedAt}`);
|
|
123
125
|
info(
|
|
124
126
|
` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
|
|
@@ -135,7 +137,7 @@ async function runStatus(global) {
|
|
|
135
137
|
if (vibgrateDir(root2)) ;
|
|
136
138
|
}
|
|
137
139
|
function rootOf(global) {
|
|
138
|
-
return
|
|
140
|
+
return path40.resolve(global.cwd ?? ".");
|
|
139
141
|
}
|
|
140
142
|
function requireGraph(global) {
|
|
141
143
|
const root2 = rootOf(global);
|
|
@@ -233,6 +235,107 @@ function registerAsk(program) {
|
|
|
233
235
|
});
|
|
234
236
|
applyGlobalOptions(cmd);
|
|
235
237
|
}
|
|
238
|
+
function crashedMessage(signal) {
|
|
239
|
+
return `semantic search is disabled: its native backend (onnxruntime-node, via fastembed) crashed with ${signal} \u2014 using fast lexical search instead. This is almost always an install-script block: npm skips onnxruntime-node's postinstall under allow-scripts/ignore-scripts, so the platform binaries were never downloaded. Reinstall allowing them \u2014 npm install -g --allow-scripts=@vibgrate/cli,onnxruntime-node,msgpackr-extract @vibgrate/cli \u2014 or run with --local to stay lexical quietly.`;
|
|
240
|
+
}
|
|
241
|
+
function defaultCacheDir() {
|
|
242
|
+
const base = process.env.XDG_CACHE_HOME || path40.join(os.homedir(), ".cache");
|
|
243
|
+
return path40.join(base, "vibgrate", "models");
|
|
244
|
+
}
|
|
245
|
+
function verdictPath(dir) {
|
|
246
|
+
return path40.join(dir, `embed-health-${process.platform}-${process.arch}.json`);
|
|
247
|
+
}
|
|
248
|
+
function readVerdict(dir) {
|
|
249
|
+
try {
|
|
250
|
+
const raw = JSON.parse(fs11.readFileSync(verdictPath(dir), "utf8"));
|
|
251
|
+
if (raw?.status !== "ok" && raw?.status !== "crashed") return null;
|
|
252
|
+
if (raw.version !== VERSION) return null;
|
|
253
|
+
return raw;
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
function writeVerdict(dir, verdict) {
|
|
259
|
+
try {
|
|
260
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
261
|
+
fs11.writeFileSync(verdictPath(dir), JSON.stringify(verdict, null, 2) + "\n", "utf8");
|
|
262
|
+
} catch {
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function defaultRunProbe(timeoutMs) {
|
|
266
|
+
const moduleUrl = new URL("./embeddings.js", import.meta.url).href;
|
|
267
|
+
const script = `
|
|
268
|
+
import(${JSON.stringify(moduleUrl)})
|
|
269
|
+
.then(async (m) => {
|
|
270
|
+
const e = await m.loadEmbedder({ noDownload: true });
|
|
271
|
+
if (!e) { process.stdout.write('{"ok":false}'); return; }
|
|
272
|
+
await e.embedQuery('probe');
|
|
273
|
+
process.stdout.write('{"ok":true}');
|
|
274
|
+
})
|
|
275
|
+
.catch(() => process.stdout.write('{"ok":false}'));
|
|
276
|
+
`;
|
|
277
|
+
return new Promise((resolve21) => {
|
|
278
|
+
const child = spawn(process.execPath, ["--input-type=module", "-e", script], {
|
|
279
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
280
|
+
// The probe must never inherit a debugger port or loader flags that would
|
|
281
|
+
// change what it proves about the addon.
|
|
282
|
+
env: { ...process.env, NODE_OPTIONS: "" }
|
|
283
|
+
});
|
|
284
|
+
let stdout = "";
|
|
285
|
+
let settled = false;
|
|
286
|
+
const done = (signal, status) => {
|
|
287
|
+
if (settled) return;
|
|
288
|
+
settled = true;
|
|
289
|
+
clearTimeout(timer);
|
|
290
|
+
resolve21({ signal, status, stdout });
|
|
291
|
+
};
|
|
292
|
+
const timer = setTimeout(() => {
|
|
293
|
+
child.kill("SIGTERM");
|
|
294
|
+
done("SIGTERM", null);
|
|
295
|
+
}, timeoutMs);
|
|
296
|
+
child.stdout?.on("data", (d) => {
|
|
297
|
+
stdout += d.toString("utf8");
|
|
298
|
+
});
|
|
299
|
+
child.on("error", () => done(null, null));
|
|
300
|
+
child.on("close", (code, signal) => done(signal ?? null, code ?? null));
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
async function embedderHealth(options = {}) {
|
|
304
|
+
const dir = options.cacheDir ?? defaultCacheDir();
|
|
305
|
+
if (!options.force) {
|
|
306
|
+
const stored = readVerdict(dir);
|
|
307
|
+
if (stored?.status === "ok") return { status: "ok" };
|
|
308
|
+
if (stored?.status === "crashed") {
|
|
309
|
+
const signal = stored.signal ?? "a fatal signal";
|
|
310
|
+
return { status: "crashed", signal, message: crashedMessage(signal) };
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const run = options.runProbe ?? defaultRunProbe;
|
|
314
|
+
let res;
|
|
315
|
+
try {
|
|
316
|
+
res = await run(options.timeoutMs ?? 3e4);
|
|
317
|
+
} catch {
|
|
318
|
+
return { status: "unknown" };
|
|
319
|
+
}
|
|
320
|
+
if (res.signal) {
|
|
321
|
+
if (res.signal === "SIGTERM") return { status: "unknown" };
|
|
322
|
+
writeVerdict(dir, { status: "crashed", signal: res.signal, at: (/* @__PURE__ */ new Date()).toISOString(), version: VERSION });
|
|
323
|
+
return { status: "crashed", signal: res.signal, message: crashedMessage(res.signal) };
|
|
324
|
+
}
|
|
325
|
+
if (res.stdout.includes('"ok":true')) {
|
|
326
|
+
writeVerdict(dir, { status: "ok", at: (/* @__PURE__ */ new Date()).toISOString(), version: VERSION });
|
|
327
|
+
return { status: "ok" };
|
|
328
|
+
}
|
|
329
|
+
return { status: "unknown" };
|
|
330
|
+
}
|
|
331
|
+
function clearEmbedderHealth(cacheDir2) {
|
|
332
|
+
try {
|
|
333
|
+
fs11.unlinkSync(verdictPath(cacheDir2 ?? defaultCacheDir()));
|
|
334
|
+
} catch {
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/commands/embed.ts
|
|
236
339
|
function mb(bytes) {
|
|
237
340
|
if (bytes <= 0) return "0 MB";
|
|
238
341
|
if (bytes < 1024 * 1024) return `${Math.max(1, Math.round(bytes / 1024))} KB`;
|
|
@@ -257,6 +360,12 @@ function registerEmbed(program) {
|
|
|
257
360
|
else if (speak) info(`${c.cyan("vg embed")} \xB7 semantic index already up to date`);
|
|
258
361
|
return;
|
|
259
362
|
}
|
|
363
|
+
const health = await embedderHealth();
|
|
364
|
+
if (health.status === "crashed") {
|
|
365
|
+
if (global.json) json({ embedded: 0, model: modelId, semantic: false, reason: "native-crash", signal: health.signal });
|
|
366
|
+
else if (speak) info(c.dim(`vg embed \xB7 ${health.message}`));
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
260
369
|
let reason;
|
|
261
370
|
const embedder = await loadEmbedder({
|
|
262
371
|
local: global.local,
|
|
@@ -298,6 +407,7 @@ function showWhere(root2, modelId, asJson) {
|
|
|
298
407
|
function doClear(asJson) {
|
|
299
408
|
const before = modelCacheInfo();
|
|
300
409
|
const freed = clearModelCache();
|
|
410
|
+
clearEmbedderHealth();
|
|
301
411
|
if (asJson) {
|
|
302
412
|
json({ removed: before.present, bytesFreed: freed, dir: before.dir });
|
|
303
413
|
return;
|
|
@@ -871,12 +981,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
|
|
|
871
981
|
var KEEPALIVE_MS = 1e4;
|
|
872
982
|
var STALE_MS = 6e4;
|
|
873
983
|
function liveStatsDir(root2) {
|
|
874
|
-
return
|
|
984
|
+
return path40.join(cacheDir(root2), "serve-live");
|
|
875
985
|
}
|
|
876
986
|
function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
|
|
877
987
|
let entries;
|
|
878
988
|
try {
|
|
879
|
-
entries =
|
|
989
|
+
entries = fs11.readdirSync(dir);
|
|
880
990
|
} catch {
|
|
881
991
|
return [];
|
|
882
992
|
}
|
|
@@ -885,7 +995,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
|
|
|
885
995
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
886
996
|
let parsed;
|
|
887
997
|
try {
|
|
888
|
-
parsed = JSON.parse(
|
|
998
|
+
parsed = JSON.parse(fs11.readFileSync(path40.join(dir, name), "utf8"));
|
|
889
999
|
} catch {
|
|
890
1000
|
continue;
|
|
891
1001
|
}
|
|
@@ -907,7 +1017,7 @@ var LiveStatsBus = class {
|
|
|
907
1017
|
this.dir = dir;
|
|
908
1018
|
this.stats = stats;
|
|
909
1019
|
this.pid = pid;
|
|
910
|
-
this.file =
|
|
1020
|
+
this.file = path40.join(dir, `serve-${this.pid}.json`);
|
|
911
1021
|
}
|
|
912
1022
|
dir;
|
|
913
1023
|
stats;
|
|
@@ -939,10 +1049,10 @@ var LiveStatsBus = class {
|
|
|
939
1049
|
this.lastWriteAt = now;
|
|
940
1050
|
const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
|
|
941
1051
|
try {
|
|
942
|
-
|
|
1052
|
+
fs11.mkdirSync(this.dir, { recursive: true });
|
|
943
1053
|
const tmp = `${this.file}.tmp`;
|
|
944
|
-
|
|
945
|
-
|
|
1054
|
+
fs11.writeFileSync(tmp, JSON.stringify(body));
|
|
1055
|
+
fs11.renameSync(tmp, this.file);
|
|
946
1056
|
} catch {
|
|
947
1057
|
}
|
|
948
1058
|
}
|
|
@@ -953,24 +1063,24 @@ var LiveStatsBus = class {
|
|
|
953
1063
|
siblings(now = Date.now()) {
|
|
954
1064
|
let entries;
|
|
955
1065
|
try {
|
|
956
|
-
entries =
|
|
1066
|
+
entries = fs11.readdirSync(this.dir);
|
|
957
1067
|
} catch {
|
|
958
1068
|
return [];
|
|
959
1069
|
}
|
|
960
1070
|
const out2 = [];
|
|
961
1071
|
for (const name of entries.sort()) {
|
|
962
1072
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
963
|
-
const file =
|
|
1073
|
+
const file = path40.join(this.dir, name);
|
|
964
1074
|
let parsed;
|
|
965
1075
|
try {
|
|
966
|
-
parsed = JSON.parse(
|
|
1076
|
+
parsed = JSON.parse(fs11.readFileSync(file, "utf8"));
|
|
967
1077
|
} catch {
|
|
968
1078
|
continue;
|
|
969
1079
|
}
|
|
970
1080
|
if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
|
|
971
1081
|
if (now - parsed.updatedAt > STALE_MS) {
|
|
972
1082
|
try {
|
|
973
|
-
|
|
1083
|
+
fs11.unlinkSync(file);
|
|
974
1084
|
} catch {
|
|
975
1085
|
}
|
|
976
1086
|
continue;
|
|
@@ -982,7 +1092,7 @@ var LiveStatsBus = class {
|
|
|
982
1092
|
}
|
|
983
1093
|
unlinkOwn = () => {
|
|
984
1094
|
try {
|
|
985
|
-
|
|
1095
|
+
fs11.unlinkSync(this.file);
|
|
986
1096
|
} catch {
|
|
987
1097
|
}
|
|
988
1098
|
};
|
|
@@ -1295,12 +1405,12 @@ var LedgerTail = class {
|
|
|
1295
1405
|
if (size === this.offset) return;
|
|
1296
1406
|
let chunk;
|
|
1297
1407
|
try {
|
|
1298
|
-
const fd =
|
|
1408
|
+
const fd = fs11.openSync(this.file, "r");
|
|
1299
1409
|
try {
|
|
1300
1410
|
chunk = Buffer.alloc(size - this.offset);
|
|
1301
|
-
|
|
1411
|
+
fs11.readSync(fd, chunk, 0, chunk.length, this.offset);
|
|
1302
1412
|
} finally {
|
|
1303
|
-
|
|
1413
|
+
fs11.closeSync(fd);
|
|
1304
1414
|
}
|
|
1305
1415
|
} catch {
|
|
1306
1416
|
return;
|
|
@@ -1313,7 +1423,7 @@ var LedgerTail = class {
|
|
|
1313
1423
|
}
|
|
1314
1424
|
sizeOf() {
|
|
1315
1425
|
try {
|
|
1316
|
-
return
|
|
1426
|
+
return fs11.statSync(this.file).size;
|
|
1317
1427
|
} catch {
|
|
1318
1428
|
return 0;
|
|
1319
1429
|
}
|
|
@@ -1706,19 +1816,19 @@ function endOfLine(text, line) {
|
|
|
1706
1816
|
}
|
|
1707
1817
|
var CACHE_VERSION = "vg-lsp-scan-cache/2";
|
|
1708
1818
|
function cachePath(root2) {
|
|
1709
|
-
return
|
|
1819
|
+
return path40.join(cacheDir(root2), "lsp-scan.json");
|
|
1710
1820
|
}
|
|
1711
1821
|
function manifestHash(root2) {
|
|
1712
1822
|
const files = [];
|
|
1713
1823
|
const walk2 = (dir) => {
|
|
1714
1824
|
let entries;
|
|
1715
1825
|
try {
|
|
1716
|
-
entries =
|
|
1826
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
1717
1827
|
} catch {
|
|
1718
1828
|
return;
|
|
1719
1829
|
}
|
|
1720
1830
|
for (const entry of entries) {
|
|
1721
|
-
const abs =
|
|
1831
|
+
const abs = path40.join(dir, entry.name);
|
|
1722
1832
|
if (entry.isDirectory()) {
|
|
1723
1833
|
if (isSkippedDirName(entry.name)) continue;
|
|
1724
1834
|
walk2(abs);
|
|
@@ -1728,8 +1838,8 @@ function manifestHash(root2) {
|
|
|
1728
1838
|
const base = entry.name.toLowerCase();
|
|
1729
1839
|
if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
|
|
1730
1840
|
try {
|
|
1731
|
-
const rel =
|
|
1732
|
-
files.push({ rel, hash: hashBytes(
|
|
1841
|
+
const rel = path40.relative(root2, abs).split(path40.sep).join("/");
|
|
1842
|
+
files.push({ rel, hash: hashBytes(fs11.readFileSync(abs)) });
|
|
1733
1843
|
} catch {
|
|
1734
1844
|
}
|
|
1735
1845
|
}
|
|
@@ -1739,16 +1849,16 @@ function manifestHash(root2) {
|
|
|
1739
1849
|
return hashString(canonicalize(files));
|
|
1740
1850
|
}
|
|
1741
1851
|
function isDependencyFile(root2, filePath) {
|
|
1742
|
-
const rel =
|
|
1743
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
1744
|
-
const parts = rel.split(
|
|
1852
|
+
const rel = path40.relative(path40.resolve(root2), path40.resolve(filePath));
|
|
1853
|
+
if (rel === "" || rel.startsWith("..") || path40.isAbsolute(rel)) return false;
|
|
1854
|
+
const parts = rel.split(path40.sep);
|
|
1745
1855
|
if (parts.slice(0, -1).some((dir) => isSkippedDirName(dir))) return false;
|
|
1746
1856
|
const base = parts[parts.length - 1].toLowerCase();
|
|
1747
1857
|
return isManifest(filePath) || SKIP_FILES.has(base);
|
|
1748
1858
|
}
|
|
1749
1859
|
function loadScanCache(root2, key2) {
|
|
1750
1860
|
try {
|
|
1751
|
-
const raw = JSON.parse(
|
|
1861
|
+
const raw = JSON.parse(fs11.readFileSync(cachePath(root2), "utf8"));
|
|
1752
1862
|
if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
|
|
1753
1863
|
return { manifestHash: raw.manifestHash, artifact: raw.artifact };
|
|
1754
1864
|
}
|
|
@@ -1758,8 +1868,8 @@ function loadScanCache(root2, key2) {
|
|
|
1758
1868
|
}
|
|
1759
1869
|
function writeScanCache(root2, key2, artifact) {
|
|
1760
1870
|
try {
|
|
1761
|
-
|
|
1762
|
-
|
|
1871
|
+
fs11.mkdirSync(cacheDir(root2), { recursive: true });
|
|
1872
|
+
fs11.writeFileSync(
|
|
1763
1873
|
cachePath(root2),
|
|
1764
1874
|
stableStringify(
|
|
1765
1875
|
{ version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
|
|
@@ -1772,7 +1882,7 @@ function writeScanCache(root2, key2, artifact) {
|
|
|
1772
1882
|
var MAX_ENTRIES = 1e3;
|
|
1773
1883
|
var KEEP_ENTRIES = 500;
|
|
1774
1884
|
function historyPath(root2) {
|
|
1775
|
-
return
|
|
1885
|
+
return path40.join(root2, ".vibgrate", "score-history.jsonl");
|
|
1776
1886
|
}
|
|
1777
1887
|
function parseLine(line) {
|
|
1778
1888
|
try {
|
|
@@ -1786,7 +1896,7 @@ function parseLine(line) {
|
|
|
1786
1896
|
}
|
|
1787
1897
|
function readHistory(root2) {
|
|
1788
1898
|
try {
|
|
1789
|
-
return
|
|
1899
|
+
return fs11.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
|
|
1790
1900
|
} catch {
|
|
1791
1901
|
return [];
|
|
1792
1902
|
}
|
|
@@ -1813,14 +1923,14 @@ function recordScore(root2, entry) {
|
|
|
1813
1923
|
}
|
|
1814
1924
|
}
|
|
1815
1925
|
const file = historyPath(root2);
|
|
1816
|
-
|
|
1926
|
+
fs11.mkdirSync(path40.dirname(file), { recursive: true });
|
|
1817
1927
|
ensureVibgrateGitignore(root2);
|
|
1818
|
-
|
|
1928
|
+
fs11.appendFileSync(file, `${JSON.stringify(entry)}
|
|
1819
1929
|
`);
|
|
1820
1930
|
const all = readHistory(root2);
|
|
1821
1931
|
if (all.length > MAX_ENTRIES) {
|
|
1822
1932
|
const kept = all.slice(-KEEP_ENTRIES);
|
|
1823
|
-
|
|
1933
|
+
fs11.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
1824
1934
|
}
|
|
1825
1935
|
} catch {
|
|
1826
1936
|
}
|
|
@@ -1832,6 +1942,10 @@ function deltaFrom(prev, current) {
|
|
|
1832
1942
|
}
|
|
1833
1943
|
|
|
1834
1944
|
// src/lsp/graph-query.ts
|
|
1945
|
+
function semanticBudgetMs() {
|
|
1946
|
+
const n = Number(process.env.VG_SEMANTIC_BUDGET_MS);
|
|
1947
|
+
return Number.isFinite(n) && n > 0 ? n : 2e4;
|
|
1948
|
+
}
|
|
1835
1949
|
async function runGraphQuery(graph, params, ctx) {
|
|
1836
1950
|
switch (params.mode) {
|
|
1837
1951
|
case "ask":
|
|
@@ -1856,26 +1970,58 @@ async function runAsk(graph, params, ctx) {
|
|
|
1856
1970
|
const question = (params.question ?? "").trim();
|
|
1857
1971
|
if (!question) return { ok: false, mode: "ask", error: "bad-request", message: "question is required" };
|
|
1858
1972
|
const budget = params.budget ?? 2e3;
|
|
1859
|
-
const
|
|
1860
|
-
|
|
1973
|
+
const semanticRequested = !!params.semantic && !ctx.offline && ctx.semantic !== false;
|
|
1974
|
+
const health = semanticRequested ? await embedderHealth() : { status: "unknown" };
|
|
1975
|
+
const wantSemantic = semanticRequested && health.status !== "crashed";
|
|
1976
|
+
const log = ctx.log ?? (() => {
|
|
1977
|
+
});
|
|
1978
|
+
let result = null;
|
|
1861
1979
|
let mode = "lexical";
|
|
1862
1980
|
let note;
|
|
1863
1981
|
if (wantSemantic) {
|
|
1982
|
+
const budgetMs = semanticBudgetMs();
|
|
1983
|
+
log(`ask: trying the semantic path (budget ${Math.round(budgetMs / 1e3)}s)`);
|
|
1864
1984
|
let reason;
|
|
1865
|
-
const
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1985
|
+
const started = Date.now();
|
|
1986
|
+
try {
|
|
1987
|
+
result = await withTimeout(
|
|
1988
|
+
(async () => {
|
|
1989
|
+
const embedder = await loadEmbedder({ onUnavailable: (r2) => reason = r2 });
|
|
1990
|
+
if (!embedder) return null;
|
|
1991
|
+
log(`ask: embedder "${embedder.id}" loaded in ${Date.now() - started}ms; embedding nodes\u2026`);
|
|
1992
|
+
const vectors = await getNodeEmbeddings(graph, embedder, ctx.root);
|
|
1993
|
+
log(`ask: ${vectors.size} node vectors ready in ${Date.now() - started}ms; ranking\u2026`);
|
|
1994
|
+
const r = await queryGraphSemantic(graph, question, { budget, embedder, nodeVectors: vectors });
|
|
1995
|
+
mode = `semantic (${embedder.id})`;
|
|
1996
|
+
return r;
|
|
1997
|
+
})(),
|
|
1998
|
+
budgetMs,
|
|
1999
|
+
"semantic search went over its time budget"
|
|
2000
|
+
);
|
|
2001
|
+
if (!result) {
|
|
2002
|
+
note = reason ? unavailableMessage(reason) : "semantic unavailable; used lexical";
|
|
2003
|
+
log(`ask: semantic unavailable (${reason ?? "no backend"}) \u2014 falling back to lexical`);
|
|
2004
|
+
}
|
|
2005
|
+
} catch (err) {
|
|
2006
|
+
mode = "lexical";
|
|
2007
|
+
result = null;
|
|
2008
|
+
note = "semantic search did not finish in time \u2014 answered with fast lexical search. It keeps warming in the background, so the next Ask should be semantic.";
|
|
2009
|
+
log(
|
|
2010
|
+
`ask: semantic path abandoned after ${Date.now() - started}ms (${err instanceof Error ? err.message : String(err)}) \u2014 falling back to lexical`
|
|
2011
|
+
);
|
|
1873
2012
|
}
|
|
1874
|
-
} else {
|
|
2013
|
+
} else if (health.status === "crashed") {
|
|
2014
|
+
note = health.message;
|
|
2015
|
+
log(`ask: semantic disabled \u2014 native backend crashed with ${health.signal}; answering lexically`);
|
|
2016
|
+
} else if (params.semantic && ctx.semantic === false) {
|
|
2017
|
+
note = "semantic search is turned off \u2014 used lexical";
|
|
2018
|
+
} else if (params.semantic && ctx.offline) {
|
|
2019
|
+
note = "semantic skipped \u2014 Vibgrate is running offline";
|
|
2020
|
+
}
|
|
2021
|
+
if (!result) {
|
|
1875
2022
|
result = queryGraph(graph, question, { budget });
|
|
1876
|
-
if (params.semantic && ctx.semantic === false) note = "semantic search is turned off \u2014 used lexical";
|
|
1877
|
-
else if (params.semantic && ctx.offline) note = "semantic skipped \u2014 Vibgrate is running offline";
|
|
1878
2023
|
}
|
|
2024
|
+
log(`ask: answered with ${mode} \u2014 ${result.matches.length} match(es)`);
|
|
1879
2025
|
return {
|
|
1880
2026
|
ok: true,
|
|
1881
2027
|
mode: "ask",
|
|
@@ -2640,14 +2786,26 @@ var VibgrateLanguageServer = class {
|
|
|
2640
2786
|
}
|
|
2641
2787
|
async onGraphQuery(params) {
|
|
2642
2788
|
const p = params;
|
|
2789
|
+
const trace = (message) => this.conn.notify("window/logMessage", { type: 3, message: `Vibgrate graph: ${message}` });
|
|
2643
2790
|
if (!this.opts.graph) {
|
|
2791
|
+
trace(`${p.mode} refused \u2014 the local Vibgrate Graph is turned off (--no-graph)`);
|
|
2644
2792
|
return { ok: false, mode: p.mode, error: "disabled", message: "the local Vibgrate Graph is turned off" };
|
|
2645
2793
|
}
|
|
2794
|
+
const started = Date.now();
|
|
2646
2795
|
const graph = await this.graphForQuery();
|
|
2647
2796
|
if (!graph) {
|
|
2797
|
+
trace(`${p.mode} has no code map yet \u2014 it is still building`);
|
|
2648
2798
|
return { ok: false, mode: p.mode, error: "not-found", message: "no code map yet \u2014 it is still building" };
|
|
2649
2799
|
}
|
|
2650
|
-
|
|
2800
|
+
trace(
|
|
2801
|
+
`${p.mode} over ${graph.nodes.length} nodes / ${graph.edges.length} edges (map ready in ${Date.now() - started}ms)`
|
|
2802
|
+
);
|
|
2803
|
+
return runGraphQuery(graph, p, {
|
|
2804
|
+
root: this.opts.root,
|
|
2805
|
+
offline: this.opts.offline,
|
|
2806
|
+
semantic: this.opts.semantic,
|
|
2807
|
+
log: trace
|
|
2808
|
+
});
|
|
2651
2809
|
}
|
|
2652
2810
|
/**
|
|
2653
2811
|
* `vibgrate/enrich` — lazy vulnerability enrichment for one expanded package,
|
|
@@ -2693,10 +2851,10 @@ var VibgrateLanguageServer = class {
|
|
|
2693
2851
|
const ecosystem = osvEcosystem(proj.type);
|
|
2694
2852
|
if (!ecosystem) continue;
|
|
2695
2853
|
const relManifest = manifestRelativePath(proj);
|
|
2696
|
-
const absManifest =
|
|
2854
|
+
const absManifest = path40.resolve(this.opts.root, relManifest);
|
|
2697
2855
|
let text = null;
|
|
2698
2856
|
try {
|
|
2699
|
-
if (
|
|
2857
|
+
if (fs11.existsSync(absManifest)) text = fs11.readFileSync(absManifest, "utf8");
|
|
2700
2858
|
} catch {
|
|
2701
2859
|
text = null;
|
|
2702
2860
|
}
|
|
@@ -2826,9 +2984,9 @@ function pruneArtifactProjects(a) {
|
|
|
2826
2984
|
return { ...a, projects, findings };
|
|
2827
2985
|
}
|
|
2828
2986
|
function projectByPath(a, projectPath) {
|
|
2829
|
-
const want =
|
|
2987
|
+
const want = path40.normalize(projectPath === "" ? "." : projectPath);
|
|
2830
2988
|
for (const proj of a.projects ?? []) {
|
|
2831
|
-
const got =
|
|
2989
|
+
const got = path40.normalize(proj.path === "" ? "." : proj.path);
|
|
2832
2990
|
if (got === want) return proj;
|
|
2833
2991
|
}
|
|
2834
2992
|
return void 0;
|
|
@@ -2865,12 +3023,12 @@ function buildProjectRefs(rootDir, projects) {
|
|
|
2865
3023
|
return refs.length > 0 ? refs : void 0;
|
|
2866
3024
|
}
|
|
2867
3025
|
function projectForFile(root2, a, filePath) {
|
|
2868
|
-
const dir =
|
|
3026
|
+
const dir = path40.dirname(path40.resolve(filePath));
|
|
2869
3027
|
let best;
|
|
2870
3028
|
let bestLen = -1;
|
|
2871
3029
|
for (const proj of a.projects ?? []) {
|
|
2872
|
-
const projDir =
|
|
2873
|
-
if ((dir === projDir || dir.startsWith(projDir +
|
|
3030
|
+
const projDir = path40.resolve(root2, proj.path);
|
|
3031
|
+
if ((dir === projDir || dir.startsWith(projDir + path40.sep)) && projDir.length > bestLen) {
|
|
2874
3032
|
best = proj;
|
|
2875
3033
|
bestLen = projDir.length;
|
|
2876
3034
|
}
|
|
@@ -2878,7 +3036,7 @@ function projectForFile(root2, a, filePath) {
|
|
|
2878
3036
|
return best;
|
|
2879
3037
|
}
|
|
2880
3038
|
function sameProject(location, projectPath) {
|
|
2881
|
-
return
|
|
3039
|
+
return path40.normalize(location) === path40.normalize(projectPath);
|
|
2882
3040
|
}
|
|
2883
3041
|
function hasReleaseDates(a) {
|
|
2884
3042
|
for (const proj of a.projects ?? []) {
|
|
@@ -2948,10 +3106,10 @@ function buildBreakdown(rootDir, projects) {
|
|
|
2948
3106
|
const relManifest = manifestRelativePath(p);
|
|
2949
3107
|
if (isPrunedWorkspacePath(p.path) || isPrunedWorkspacePath(relManifest)) continue;
|
|
2950
3108
|
const ecosystem = osvEcosystem(p.type);
|
|
2951
|
-
const absManifest =
|
|
3109
|
+
const absManifest = path40.resolve(rootDir, relManifest);
|
|
2952
3110
|
let text = null;
|
|
2953
3111
|
try {
|
|
2954
|
-
if (
|
|
3112
|
+
if (fs11.existsSync(absManifest)) text = fs11.readFileSync(absManifest, "utf8");
|
|
2955
3113
|
} catch {
|
|
2956
3114
|
text = null;
|
|
2957
3115
|
}
|
|
@@ -3016,34 +3174,34 @@ function buildBreakdown(rootDir, projects) {
|
|
|
3016
3174
|
}
|
|
3017
3175
|
function manifestRelativePath(proj) {
|
|
3018
3176
|
const base = proj.path === "." || proj.path === "" ? "" : proj.path;
|
|
3019
|
-
const
|
|
3177
|
+
const join30 = (name) => base ? path40.join(base, name) : name;
|
|
3020
3178
|
switch (proj.type) {
|
|
3021
3179
|
case "node":
|
|
3022
3180
|
case "typescript":
|
|
3023
|
-
return
|
|
3181
|
+
return join30("package.json");
|
|
3024
3182
|
case "python":
|
|
3025
|
-
return
|
|
3183
|
+
return join30("pyproject.toml");
|
|
3026
3184
|
case "go":
|
|
3027
|
-
return
|
|
3185
|
+
return join30("go.mod");
|
|
3028
3186
|
case "rust":
|
|
3029
|
-
return
|
|
3187
|
+
return join30("Cargo.toml");
|
|
3030
3188
|
case "ruby":
|
|
3031
|
-
return
|
|
3189
|
+
return join30("Gemfile");
|
|
3032
3190
|
case "php":
|
|
3033
|
-
return
|
|
3191
|
+
return join30("composer.json");
|
|
3034
3192
|
case "java":
|
|
3035
3193
|
case "kotlin":
|
|
3036
3194
|
case "scala":
|
|
3037
3195
|
case "groovy":
|
|
3038
|
-
return
|
|
3196
|
+
return join30("pom.xml");
|
|
3039
3197
|
case "dotnet":
|
|
3040
|
-
return
|
|
3198
|
+
return join30(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
|
|
3041
3199
|
case "dart":
|
|
3042
|
-
return
|
|
3200
|
+
return join30("pubspec.yaml");
|
|
3043
3201
|
case "elixir":
|
|
3044
|
-
return
|
|
3202
|
+
return join30("mix.exs");
|
|
3045
3203
|
default:
|
|
3046
|
-
return
|
|
3204
|
+
return join30("package.json");
|
|
3047
3205
|
}
|
|
3048
3206
|
}
|
|
3049
3207
|
function lockfileRelativePath(rootDir, proj) {
|
|
@@ -3074,9 +3232,9 @@ function lockfileRelativePath(rootDir, proj) {
|
|
|
3074
3232
|
const dirsToTry = base ? [base, ""] : [""];
|
|
3075
3233
|
for (const dir of dirsToTry) {
|
|
3076
3234
|
for (const name of candidateNames) {
|
|
3077
|
-
const rel = dir ?
|
|
3235
|
+
const rel = dir ? path40.join(dir, name) : name;
|
|
3078
3236
|
try {
|
|
3079
|
-
if (
|
|
3237
|
+
if (fs11.existsSync(path40.join(rootDir, rel))) return rel;
|
|
3080
3238
|
} catch {
|
|
3081
3239
|
}
|
|
3082
3240
|
}
|
|
@@ -3147,10 +3305,10 @@ function lookupImportFiles(map, pkg) {
|
|
|
3147
3305
|
}
|
|
3148
3306
|
function firstPackageMentionLine(root2, relFile, pkg) {
|
|
3149
3307
|
try {
|
|
3150
|
-
const abs =
|
|
3151
|
-
const stat2 =
|
|
3308
|
+
const abs = path40.resolve(root2, relFile);
|
|
3309
|
+
const stat2 = fs11.statSync(abs);
|
|
3152
3310
|
if (!stat2.isFile() || stat2.size > 256 * 1024) return null;
|
|
3153
|
-
const text =
|
|
3311
|
+
const text = fs11.readFileSync(abs, "utf8");
|
|
3154
3312
|
const tokens = [pkg];
|
|
3155
3313
|
if (pkg.startsWith("@")) {
|
|
3156
3314
|
const parts = pkg.split("/");
|
|
@@ -3302,7 +3460,7 @@ function hoverMarkdown(dep, contribution) {
|
|
|
3302
3460
|
return lines.join("\n");
|
|
3303
3461
|
}
|
|
3304
3462
|
function startLanguageServer(opts) {
|
|
3305
|
-
if (!
|
|
3463
|
+
if (!fs11.existsSync(opts.root)) {
|
|
3306
3464
|
process.stderr.write(`vg lsp: root does not exist: ${opts.root}
|
|
3307
3465
|
`);
|
|
3308
3466
|
process.exit(1);
|
|
@@ -3351,12 +3509,12 @@ function hookCommand(vgBin) {
|
|
|
3351
3509
|
return `${vgBin} hook pre-tool-use`;
|
|
3352
3510
|
}
|
|
3353
3511
|
function installClaudeHooks(root2, vgBin = "vg") {
|
|
3354
|
-
const file =
|
|
3355
|
-
const rel =
|
|
3512
|
+
const file = path40.join(root2, ".claude", "settings.json");
|
|
3513
|
+
const rel = path40.join(".claude", "settings.json");
|
|
3356
3514
|
let settings = {};
|
|
3357
|
-
if (
|
|
3515
|
+
if (fs11.existsSync(file)) {
|
|
3358
3516
|
try {
|
|
3359
|
-
const parsed = JSON.parse(
|
|
3517
|
+
const parsed = JSON.parse(fs11.readFileSync(file, "utf8"));
|
|
3360
3518
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3361
3519
|
return { file: rel, status: "skipped", note: "settings.json is not a JSON object \u2014 left untouched" };
|
|
3362
3520
|
}
|
|
@@ -3393,12 +3551,12 @@ function installClaudeHooks(root2, vgBin = "vg") {
|
|
|
3393
3551
|
return { file: rel, status: "written" };
|
|
3394
3552
|
}
|
|
3395
3553
|
function uninstallClaudeHooks(root2) {
|
|
3396
|
-
const file =
|
|
3397
|
-
const rel =
|
|
3398
|
-
if (!
|
|
3554
|
+
const file = path40.join(root2, ".claude", "settings.json");
|
|
3555
|
+
const rel = path40.join(".claude", "settings.json");
|
|
3556
|
+
if (!fs11.existsSync(file)) return { file: rel, status: "unchanged" };
|
|
3399
3557
|
let settings;
|
|
3400
3558
|
try {
|
|
3401
|
-
settings = JSON.parse(
|
|
3559
|
+
settings = JSON.parse(fs11.readFileSync(file, "utf8"));
|
|
3402
3560
|
} catch {
|
|
3403
3561
|
return { file: rel, status: "skipped", note: "settings.json is not parseable JSON \u2014 left untouched" };
|
|
3404
3562
|
}
|
|
@@ -3420,8 +3578,8 @@ function uninstallClaudeHooks(root2) {
|
|
|
3420
3578
|
return { file: rel, status: "written" };
|
|
3421
3579
|
}
|
|
3422
3580
|
function writeSettings(file, settings) {
|
|
3423
|
-
|
|
3424
|
-
|
|
3581
|
+
fs11.mkdirSync(path40.dirname(file), { recursive: true });
|
|
3582
|
+
fs11.writeFileSync(file, `${JSON.stringify(settings, null, 2)}
|
|
3425
3583
|
`);
|
|
3426
3584
|
}
|
|
3427
3585
|
|
|
@@ -3541,19 +3699,19 @@ function registryBase(opts) {
|
|
|
3541
3699
|
return (process.env.VIBGRATE_MODULE_REGISTRY || opts.registry || DEFAULT_REGISTRY).replace(/\/+$/, "");
|
|
3542
3700
|
}
|
|
3543
3701
|
function stateFile() {
|
|
3544
|
-
return
|
|
3702
|
+
return path40.join(path40.dirname(relevanceModuleDir()), "consent.json");
|
|
3545
3703
|
}
|
|
3546
3704
|
function readConsent() {
|
|
3547
3705
|
try {
|
|
3548
|
-
return JSON.parse(
|
|
3706
|
+
return JSON.parse(fs11.readFileSync(stateFile(), "utf8"));
|
|
3549
3707
|
} catch {
|
|
3550
3708
|
return {};
|
|
3551
3709
|
}
|
|
3552
3710
|
}
|
|
3553
3711
|
function writeConsent(state) {
|
|
3554
3712
|
try {
|
|
3555
|
-
|
|
3556
|
-
|
|
3713
|
+
fs11.mkdirSync(path40.dirname(stateFile()), { recursive: true });
|
|
3714
|
+
fs11.writeFileSync(stateFile(), JSON.stringify(state));
|
|
3557
3715
|
} catch {
|
|
3558
3716
|
}
|
|
3559
3717
|
}
|
|
@@ -3563,8 +3721,8 @@ function kernelDisabled() {
|
|
|
3563
3721
|
}
|
|
3564
3722
|
function moduleInstalled() {
|
|
3565
3723
|
try {
|
|
3566
|
-
const meta = JSON.parse(
|
|
3567
|
-
if (
|
|
3724
|
+
const meta = JSON.parse(fs11.readFileSync(path40.join(relevanceModuleDir(), ".module.json"), "utf8"));
|
|
3725
|
+
if (fs11.existsSync(path40.join(relevanceModuleDir(), "index.js"))) {
|
|
3568
3726
|
return { installed: true, version: meta.version };
|
|
3569
3727
|
}
|
|
3570
3728
|
} catch {
|
|
@@ -3613,7 +3771,7 @@ function untar(data) {
|
|
|
3613
3771
|
if (type !== "0" && type !== "\0") continue;
|
|
3614
3772
|
const name = pendingName ?? (prefix ? `${prefix}/${rawName}` : rawName);
|
|
3615
3773
|
pendingName = null;
|
|
3616
|
-
if (name.split("/").includes("..") ||
|
|
3774
|
+
if (name.split("/").includes("..") || path40.isAbsolute(name)) {
|
|
3617
3775
|
throw new Error(`unsafe path in tarball: ${name}`);
|
|
3618
3776
|
}
|
|
3619
3777
|
out2.push({ name, body: Buffer.from(body) });
|
|
@@ -3639,25 +3797,25 @@ async function installRelevanceModule(opts = {}) {
|
|
|
3639
3797
|
verifyIntegrity(gz, dist.integrity, dist.shasum);
|
|
3640
3798
|
const entries = untar(zlib.gunzipSync(gz));
|
|
3641
3799
|
const dir = relevanceModuleDir();
|
|
3642
|
-
|
|
3643
|
-
|
|
3800
|
+
fs11.rmSync(dir, { recursive: true, force: true });
|
|
3801
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
3644
3802
|
let wrote = 0;
|
|
3645
3803
|
for (const e of entries) {
|
|
3646
3804
|
let rel = null;
|
|
3647
3805
|
if (e.name.startsWith("package/dist/")) rel = e.name.slice("package/dist/".length);
|
|
3648
3806
|
else if (e.name === "package/LICENSE" || e.name === "package/README.md") rel = e.name.slice("package/".length);
|
|
3649
3807
|
if (!rel) continue;
|
|
3650
|
-
const target =
|
|
3651
|
-
if (!target.startsWith(dir +
|
|
3652
|
-
|
|
3653
|
-
|
|
3808
|
+
const target = path40.join(dir, rel);
|
|
3809
|
+
if (!target.startsWith(dir + path40.sep) && target !== dir) throw new Error(`unsafe extract path: ${rel}`);
|
|
3810
|
+
fs11.mkdirSync(path40.dirname(target), { recursive: true });
|
|
3811
|
+
fs11.writeFileSync(target, e.body);
|
|
3654
3812
|
wrote += 1;
|
|
3655
3813
|
}
|
|
3656
|
-
if (!wrote || !
|
|
3657
|
-
|
|
3814
|
+
if (!wrote || !fs11.existsSync(path40.join(dir, "index.js"))) {
|
|
3815
|
+
fs11.rmSync(dir, { recursive: true, force: true });
|
|
3658
3816
|
return { status: "unavailable", detail: "package layout not recognized (no dist/index.js)" };
|
|
3659
3817
|
}
|
|
3660
|
-
|
|
3818
|
+
fs11.writeFileSync(path40.join(dir, ".module.json"), JSON.stringify({ name: RELEVANCE_MODULE_NAME, version }));
|
|
3661
3819
|
resetRelevanceProviderCache();
|
|
3662
3820
|
return { status: "installed", version };
|
|
3663
3821
|
} catch (e) {
|
|
@@ -3665,7 +3823,7 @@ async function installRelevanceModule(opts = {}) {
|
|
|
3665
3823
|
}
|
|
3666
3824
|
}
|
|
3667
3825
|
function removeRelevanceModule() {
|
|
3668
|
-
|
|
3826
|
+
fs11.rmSync(relevanceModuleDir(), { recursive: true, force: true });
|
|
3669
3827
|
resetRelevanceProviderCache();
|
|
3670
3828
|
}
|
|
3671
3829
|
async function ensureRelevanceModule(io = {}) {
|
|
@@ -3774,7 +3932,7 @@ function hookContext(payloadText, root2, graphOverride) {
|
|
|
3774
3932
|
let graph;
|
|
3775
3933
|
try {
|
|
3776
3934
|
const preferred = loadGraphPreferIndex(root2, graphPath);
|
|
3777
|
-
graph = preferred ? preferred.graph : parseGraph(
|
|
3935
|
+
graph = preferred ? preferred.graph : parseGraph(fs11.readFileSync(graphPath, "utf8"));
|
|
3778
3936
|
} catch {
|
|
3779
3937
|
return null;
|
|
3780
3938
|
}
|
|
@@ -3796,7 +3954,7 @@ function registerHook(program) {
|
|
|
3796
3954
|
const global = readGlobal(this);
|
|
3797
3955
|
const root2 = rootOf(global);
|
|
3798
3956
|
try {
|
|
3799
|
-
const stdin =
|
|
3957
|
+
const stdin = fs11.readFileSync(0, "utf8");
|
|
3800
3958
|
const context = hookContext(stdin, root2, global.graph);
|
|
3801
3959
|
if (context) {
|
|
3802
3960
|
process.stdout.write(
|
|
@@ -3816,8 +3974,8 @@ function registerShare(program) {
|
|
|
3816
3974
|
const cmd = program.command("share").description("make the map committable + auto-updating for your team (git)").option("--undo", "reverse what `vg share` installed").option("--reports", "also commit graph.html / GRAPH_REPORT.md (default: gitignored)").action(function(opts) {
|
|
3817
3975
|
const global = readGlobal(this);
|
|
3818
3976
|
const root2 = rootOf(global);
|
|
3819
|
-
const gitDir =
|
|
3820
|
-
if (!
|
|
3977
|
+
const gitDir = path40.join(root2, ".git");
|
|
3978
|
+
if (!fs11.existsSync(gitDir)) {
|
|
3821
3979
|
throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
|
|
3822
3980
|
}
|
|
3823
3981
|
if (opts.undo) {
|
|
@@ -3838,23 +3996,23 @@ function registerShare(program) {
|
|
|
3838
3996
|
applyGlobalOptions(cmd);
|
|
3839
3997
|
}
|
|
3840
3998
|
function writeVibgrateGitignore(root2, reports) {
|
|
3841
|
-
const dir =
|
|
3842
|
-
|
|
3999
|
+
const dir = path40.join(root2, ".vibgrate");
|
|
4000
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
3843
4001
|
const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
|
|
3844
4002
|
if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
|
|
3845
|
-
|
|
4003
|
+
fs11.writeFileSync(path40.join(dir, ".gitignore"), `${lines.join("\n")}
|
|
3846
4004
|
`);
|
|
3847
4005
|
}
|
|
3848
4006
|
function writeGitAttributes(root2) {
|
|
3849
|
-
const file =
|
|
4007
|
+
const file = path40.join(root2, ".gitattributes");
|
|
3850
4008
|
const line = ".vibgrate/graph.json merge=vg";
|
|
3851
|
-
let content =
|
|
4009
|
+
let content = fs11.existsSync(file) ? fs11.readFileSync(file, "utf8") : "";
|
|
3852
4010
|
if (!content.split("\n").some((l) => l.trim() === line)) {
|
|
3853
4011
|
content = content.length ? `${content.replace(/\s*$/, "")}
|
|
3854
4012
|
${line}
|
|
3855
4013
|
` : `${line}
|
|
3856
4014
|
`;
|
|
3857
|
-
|
|
4015
|
+
fs11.writeFileSync(file, content);
|
|
3858
4016
|
}
|
|
3859
4017
|
}
|
|
3860
4018
|
function configureMergeDriver(root2) {
|
|
@@ -3863,8 +4021,8 @@ function configureMergeDriver(root2) {
|
|
|
3863
4021
|
}
|
|
3864
4022
|
function installPreCommitHook(root2) {
|
|
3865
4023
|
const hooksDir = hookDir(root2);
|
|
3866
|
-
|
|
3867
|
-
const file =
|
|
4024
|
+
fs11.mkdirSync(hooksDir, { recursive: true });
|
|
4025
|
+
const file = path40.join(hooksDir, "pre-commit");
|
|
3868
4026
|
const block = [
|
|
3869
4027
|
HOOK_BEGIN,
|
|
3870
4028
|
"if command -v vg >/dev/null 2>&1; then",
|
|
@@ -3873,7 +4031,7 @@ function installPreCommitHook(root2) {
|
|
|
3873
4031
|
"fi",
|
|
3874
4032
|
HOOK_END
|
|
3875
4033
|
].join("\n");
|
|
3876
|
-
let content =
|
|
4034
|
+
let content = fs11.existsSync(file) ? fs11.readFileSync(file, "utf8") : "#!/bin/sh\n";
|
|
3877
4035
|
const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
|
|
3878
4036
|
if (re.test(content)) content = content.replace(re, block);
|
|
3879
4037
|
else content = `${content.replace(/\s*$/, "")}
|
|
@@ -3882,21 +4040,21 @@ ${block}
|
|
|
3882
4040
|
`;
|
|
3883
4041
|
if (!content.startsWith("#!")) content = `#!/bin/sh
|
|
3884
4042
|
${content}`;
|
|
3885
|
-
|
|
3886
|
-
|
|
4043
|
+
fs11.writeFileSync(file, content);
|
|
4044
|
+
fs11.chmodSync(file, 493);
|
|
3887
4045
|
}
|
|
3888
4046
|
function undo(root2) {
|
|
3889
|
-
const hookFile =
|
|
3890
|
-
if (
|
|
4047
|
+
const hookFile = path40.join(hookDir(root2), "pre-commit");
|
|
4048
|
+
if (fs11.existsSync(hookFile)) {
|
|
3891
4049
|
const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
|
|
3892
|
-
const next2 =
|
|
3893
|
-
if (next2.trim() === "#!/bin/sh")
|
|
3894
|
-
else
|
|
4050
|
+
const next2 = fs11.readFileSync(hookFile, "utf8").replace(re, "\n");
|
|
4051
|
+
if (next2.trim() === "#!/bin/sh") fs11.rmSync(hookFile);
|
|
4052
|
+
else fs11.writeFileSync(hookFile, next2);
|
|
3895
4053
|
}
|
|
3896
|
-
const attr =
|
|
3897
|
-
if (
|
|
3898
|
-
const next2 =
|
|
3899
|
-
|
|
4054
|
+
const attr = path40.join(root2, ".gitattributes");
|
|
4055
|
+
if (fs11.existsSync(attr)) {
|
|
4056
|
+
const next2 = fs11.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
|
|
4057
|
+
fs11.writeFileSync(attr, next2);
|
|
3900
4058
|
}
|
|
3901
4059
|
try {
|
|
3902
4060
|
git(root2, ["config", "--remove-section", "merge.vg"]);
|
|
@@ -3906,10 +4064,10 @@ function undo(root2) {
|
|
|
3906
4064
|
function hookDir(root2) {
|
|
3907
4065
|
try {
|
|
3908
4066
|
const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
|
|
3909
|
-
if (configured) return
|
|
4067
|
+
if (configured) return path40.resolve(root2, configured);
|
|
3910
4068
|
} catch {
|
|
3911
4069
|
}
|
|
3912
|
-
return
|
|
4070
|
+
return path40.join(root2, ".git", "hooks");
|
|
3913
4071
|
}
|
|
3914
4072
|
function git(root2, args) {
|
|
3915
4073
|
return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
|
|
@@ -3923,9 +4081,9 @@ function registerWatch(program) {
|
|
|
3923
4081
|
const global = readGlobal(this);
|
|
3924
4082
|
const root2 = rootOf(global);
|
|
3925
4083
|
const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
|
|
3926
|
-
const watchRoots = (paths.length ? paths : ["."]).map((p) =>
|
|
4084
|
+
const watchRoots = (paths.length ? paths : ["."]).map((p) => path40.resolve(root2, p));
|
|
3927
4085
|
for (const w of watchRoots) {
|
|
3928
|
-
if (!
|
|
4086
|
+
if (!fs11.existsSync(w)) {
|
|
3929
4087
|
throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
|
|
3930
4088
|
}
|
|
3931
4089
|
}
|
|
@@ -3978,7 +4136,7 @@ function registerWatch(program) {
|
|
|
3978
4136
|
const watchers = [];
|
|
3979
4137
|
for (const w of watchRoots) {
|
|
3980
4138
|
try {
|
|
3981
|
-
const watcher =
|
|
4139
|
+
const watcher = fs11.watch(w, { recursive: true }, (_event, filename) => {
|
|
3982
4140
|
if (!filename) {
|
|
3983
4141
|
schedule("change");
|
|
3984
4142
|
return;
|
|
@@ -3991,7 +4149,7 @@ function registerWatch(program) {
|
|
|
3991
4149
|
throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
|
|
3992
4150
|
}
|
|
3993
4151
|
}
|
|
3994
|
-
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) =>
|
|
4152
|
+
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path40.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
|
|
3995
4153
|
await new Promise((resolve21) => {
|
|
3996
4154
|
const stop = () => {
|
|
3997
4155
|
for (const w of watchers) w.close();
|
|
@@ -4324,10 +4482,10 @@ function normalizeStandards(raw) {
|
|
|
4324
4482
|
}
|
|
4325
4483
|
function loadStandards(root2) {
|
|
4326
4484
|
for (const rel of STANDARDS_FILES) {
|
|
4327
|
-
const p =
|
|
4485
|
+
const p = path40__default.join(root2, rel);
|
|
4328
4486
|
let text;
|
|
4329
4487
|
try {
|
|
4330
|
-
text =
|
|
4488
|
+
text = fs11__default.readFileSync(p, "utf8");
|
|
4331
4489
|
} catch {
|
|
4332
4490
|
continue;
|
|
4333
4491
|
}
|
|
@@ -5045,8 +5203,8 @@ async function runHostBench(options = {}) {
|
|
|
5045
5203
|
}
|
|
5046
5204
|
async function runArmSimulate(input) {
|
|
5047
5205
|
const { arm, lib, modelPath, turns, trie, env, live } = input;
|
|
5048
|
-
const
|
|
5049
|
-
const session = await acquireHostSession(lib,
|
|
5206
|
+
const path42 = `${modelPath}#${arm.id}`;
|
|
5207
|
+
const session = await acquireHostSession(lib, path42);
|
|
5050
5208
|
const system = "You are a coding agent with a Task Capsule.";
|
|
5051
5209
|
const capsule = "function readConfig(): Config { return load(); }";
|
|
5052
5210
|
let last = null;
|
|
@@ -6258,7 +6416,7 @@ function registerModels(program) {
|
|
|
6258
6416
|
);
|
|
6259
6417
|
}
|
|
6260
6418
|
} else {
|
|
6261
|
-
if (!target.path || !
|
|
6419
|
+
if (!target.path || !fs11.existsSync(target.path)) {
|
|
6262
6420
|
throw new CliError(
|
|
6263
6421
|
`model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
|
|
6264
6422
|
ExitCode.NOT_FOUND
|
|
@@ -6272,7 +6430,7 @@ function registerModels(program) {
|
|
|
6272
6430
|
}
|
|
6273
6431
|
if (!global.json) info(c.dim(` $ rm ${target.path}`));
|
|
6274
6432
|
try {
|
|
6275
|
-
|
|
6433
|
+
fs11.unlinkSync(target.path);
|
|
6276
6434
|
} catch (e) {
|
|
6277
6435
|
const msg = e instanceof Error ? e.message : String(e);
|
|
6278
6436
|
throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
|
|
@@ -6410,9 +6568,9 @@ function registerModels(program) {
|
|
|
6410
6568
|
}
|
|
6411
6569
|
});
|
|
6412
6570
|
if (opts.out) {
|
|
6413
|
-
const outPath =
|
|
6414
|
-
|
|
6415
|
-
|
|
6571
|
+
const outPath = path40.resolve(opts.out);
|
|
6572
|
+
fs11.mkdirSync(path40.dirname(outPath), { recursive: true });
|
|
6573
|
+
fs11.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
|
|
6416
6574
|
`);
|
|
6417
6575
|
if (!global.json) info(c.dim(` wrote ${outPath}`));
|
|
6418
6576
|
}
|
|
@@ -6561,14 +6719,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
|
|
|
6561
6719
|
}
|
|
6562
6720
|
return exact[0];
|
|
6563
6721
|
}
|
|
6564
|
-
const base =
|
|
6722
|
+
const base = path40.basename(wantLc);
|
|
6565
6723
|
const soft = fleet.filter((m) => {
|
|
6566
6724
|
const n = m.name.toLowerCase();
|
|
6567
|
-
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) ||
|
|
6725
|
+
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path40.basename(n) === base;
|
|
6568
6726
|
});
|
|
6569
6727
|
if (soft.length === 1) return soft[0];
|
|
6570
6728
|
if (soft.length > 1) {
|
|
6571
|
-
const baseHits = soft.filter((m) =>
|
|
6729
|
+
const baseHits = soft.filter((m) => path40.basename(m.name).toLowerCase() === base);
|
|
6572
6730
|
const pool = baseHits.length ? baseHits : soft;
|
|
6573
6731
|
const order = ["ollama", "gguf", "lm-studio"];
|
|
6574
6732
|
for (const rt of order) {
|
|
@@ -6606,11 +6764,11 @@ function printBackends(backends) {
|
|
|
6606
6764
|
}
|
|
6607
6765
|
}
|
|
6608
6766
|
function codeConfigPath(root2) {
|
|
6609
|
-
return
|
|
6767
|
+
return path40.join(root2, ".vibgrate", "code.json");
|
|
6610
6768
|
}
|
|
6611
6769
|
function loadCodeConfig(root2) {
|
|
6612
6770
|
try {
|
|
6613
|
-
const raw = JSON.parse(
|
|
6771
|
+
const raw = JSON.parse(fs11.readFileSync(codeConfigPath(root2), "utf8"));
|
|
6614
6772
|
return sanitize(raw);
|
|
6615
6773
|
} catch {
|
|
6616
6774
|
return {};
|
|
@@ -6677,7 +6835,7 @@ function contextBudgetFor(config, modelContextWindow) {
|
|
|
6677
6835
|
var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
|
|
6678
6836
|
function readMcpServersFile(file) {
|
|
6679
6837
|
try {
|
|
6680
|
-
const raw = JSON.parse(
|
|
6838
|
+
const raw = JSON.parse(fs11.readFileSync(file, "utf8"));
|
|
6681
6839
|
const map = raw.mcpServers ?? raw.servers;
|
|
6682
6840
|
return map && typeof map === "object" ? parseMcpServers(map) : {};
|
|
6683
6841
|
} catch {
|
|
@@ -6688,7 +6846,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6688
6846
|
const servers = {};
|
|
6689
6847
|
const sources = [];
|
|
6690
6848
|
for (const rel of MCP_CONFIG_FILES) {
|
|
6691
|
-
const found = readMcpServersFile(
|
|
6849
|
+
const found = readMcpServersFile(path40.join(root2, rel));
|
|
6692
6850
|
const names = Object.keys(found);
|
|
6693
6851
|
if (names.length) {
|
|
6694
6852
|
sources.push(rel);
|
|
@@ -6720,7 +6878,7 @@ function registerCode(program) {
|
|
|
6720
6878
|
try {
|
|
6721
6879
|
const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
|
|
6722
6880
|
const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
|
|
6723
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
6881
|
+
const { loadGraph: loadGraph2 } = await import('./load-6KVGUQMU.js');
|
|
6724
6882
|
const state = readOrchestratorState2();
|
|
6725
6883
|
const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
|
|
6726
6884
|
const pin = mode ? activePin2(mode, state) : null;
|
|
@@ -6805,7 +6963,7 @@ function registerCode(program) {
|
|
|
6805
6963
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
6806
6964
|
throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
|
|
6807
6965
|
}
|
|
6808
|
-
const { runInteractive } = await import('./interactive-
|
|
6966
|
+
const { runInteractive } = await import('./interactive-DB7IC3BL.js');
|
|
6809
6967
|
await runInteractive(
|
|
6810
6968
|
rootOf(global),
|
|
6811
6969
|
global,
|
|
@@ -6835,7 +6993,7 @@ function registerCode(program) {
|
|
|
6835
6993
|
}
|
|
6836
6994
|
if (!instruction && !stdinFirstTurn) throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"`');
|
|
6837
6995
|
{
|
|
6838
|
-
const { ensureCodeMap } = await import('./ensure-map-
|
|
6996
|
+
const { ensureCodeMap } = await import('./ensure-map-DZ53QXRT.js');
|
|
6839
6997
|
const mapRoot = rootOf(global);
|
|
6840
6998
|
try {
|
|
6841
6999
|
await ensureCodeMap(mapRoot, global, {
|
|
@@ -6872,7 +7030,7 @@ function registerCode(program) {
|
|
|
6872
7030
|
let mockReply;
|
|
6873
7031
|
if (opts.mock) {
|
|
6874
7032
|
try {
|
|
6875
|
-
mockReply =
|
|
7033
|
+
mockReply = fs11.readFileSync(opts.mock, "utf8");
|
|
6876
7034
|
} catch {
|
|
6877
7035
|
throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
|
|
6878
7036
|
}
|
|
@@ -6920,20 +7078,20 @@ function registerCode(program) {
|
|
|
6920
7078
|
process.stdout.write(JSON.stringify(line) + "\n");
|
|
6921
7079
|
};
|
|
6922
7080
|
try {
|
|
6923
|
-
const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-
|
|
7081
|
+
const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-YOYRC32U.js');
|
|
6924
7082
|
const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
|
|
6925
|
-
const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-
|
|
6926
|
-
const { nodeCodeFs } = await import('./session-
|
|
7083
|
+
const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-3OJCPBWY.js');
|
|
7084
|
+
const { nodeCodeFs } = await import('./session-5WKEACIF.js');
|
|
6927
7085
|
const readline6 = await import('readline');
|
|
6928
7086
|
const child = await import('child_process');
|
|
6929
7087
|
const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
|
|
6930
7088
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
6931
7089
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
6932
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
6933
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
7090
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-XEP7IPGP.js');
|
|
7091
|
+
const { resolveGraphBackend } = await import('./graph-backend-3A2M22QN.js');
|
|
6934
7092
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
6935
7093
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
6936
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
7094
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-UTLMMPIZ.js');
|
|
6937
7095
|
const federation = loadOrDiscoverFederation(root2);
|
|
6938
7096
|
const modelProfile = mergeModelExecutionProfile(
|
|
6939
7097
|
resolveModelExecutionProfile({
|
|
@@ -6991,7 +7149,7 @@ ${res.stderr}` : ""),
|
|
|
6991
7149
|
exitCode: res.status ?? 1
|
|
6992
7150
|
};
|
|
6993
7151
|
};
|
|
6994
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
7152
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-PM3C4FQL.js');
|
|
6995
7153
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
6996
7154
|
getGraph: () => graph,
|
|
6997
7155
|
root: root2,
|
|
@@ -7012,10 +7170,10 @@ ${res.stderr}` : ""),
|
|
|
7012
7170
|
}
|
|
7013
7171
|
const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
|
|
7014
7172
|
const { createCheckpoint } = await import('./checkpoint-4WFZMKEO.js');
|
|
7015
|
-
const
|
|
7173
|
+
const os5 = await import('os');
|
|
7016
7174
|
const pathMod = await import('path');
|
|
7017
7175
|
const checkpointIndex = pathMod.join(
|
|
7018
|
-
|
|
7176
|
+
fs11.mkdtempSync(pathMod.join(os5.tmpdir(), "vg-code-cp-")),
|
|
7019
7177
|
"index"
|
|
7020
7178
|
);
|
|
7021
7179
|
const gitRunner = (gitArgs, gitEnv) => {
|
|
@@ -7081,8 +7239,8 @@ ${res.stderr}` : ""),
|
|
|
7081
7239
|
};
|
|
7082
7240
|
try {
|
|
7083
7241
|
if (opts.session) {
|
|
7084
|
-
const { runCodeStreamJsonSession } = await import('./stream-json-
|
|
7085
|
-
const { runAgent: runAgent2 } = await import('./agent-
|
|
7242
|
+
const { runCodeStreamJsonSession } = await import('./stream-json-3OJCPBWY.js');
|
|
7243
|
+
const { runAgent: runAgent2 } = await import('./agent-WYBWUBCC.js');
|
|
7086
7244
|
const {
|
|
7087
7245
|
condenseSession,
|
|
7088
7246
|
loadLatestSession,
|
|
@@ -7179,6 +7337,10 @@ ${res.stderr}` : ""),
|
|
|
7179
7337
|
...baseAgentOptions,
|
|
7180
7338
|
instruction: turnInstruction,
|
|
7181
7339
|
priorSummary,
|
|
7340
|
+
// Carry-over for capsule seed ranking: the previous
|
|
7341
|
+
// turn's instruction (the current turn is recorded only
|
|
7342
|
+
// in onTurnEnd, so .at(-1) is the prior ask).
|
|
7343
|
+
priorInstruction: record.tasks.at(-1)?.instruction,
|
|
7182
7344
|
signal,
|
|
7183
7345
|
auto: turnAuto,
|
|
7184
7346
|
plan,
|
|
@@ -7246,17 +7408,21 @@ ${res.stderr}` : ""),
|
|
|
7246
7408
|
if (!autonomous && !tty) {
|
|
7247
7409
|
throw usageError("the agent approves each edit/command \u2014 run in a terminal to approve interactively, or pass --auto to run autonomously (or --single for a one-shot diff).");
|
|
7248
7410
|
}
|
|
7249
|
-
const { agentTask } = await import('./interactive-
|
|
7250
|
-
const { nodeCodeFs } = await import('./session-
|
|
7411
|
+
const { agentTask } = await import('./interactive-DB7IC3BL.js');
|
|
7412
|
+
const { nodeCodeFs } = await import('./session-5WKEACIF.js');
|
|
7251
7413
|
const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
|
|
7252
7414
|
let priorSummary;
|
|
7415
|
+
let priorInstruction;
|
|
7253
7416
|
if (opts.continue) {
|
|
7254
7417
|
const { loadLatestSession, summarizeSession } = await import('./session-store-F7NX7SZN.js');
|
|
7255
7418
|
const prev = loadLatestSession(root2);
|
|
7256
|
-
if (prev)
|
|
7419
|
+
if (prev) {
|
|
7420
|
+
priorSummary = summarizeSession(prev);
|
|
7421
|
+
priorInstruction = prev.tasks.at(-1)?.instruction;
|
|
7422
|
+
}
|
|
7257
7423
|
}
|
|
7258
7424
|
const prompter = tty ? new TtyPrompter() : void 0;
|
|
7259
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
7425
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-PM3C4FQL.js');
|
|
7260
7426
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
7261
7427
|
getGraph: () => graph,
|
|
7262
7428
|
root: root2,
|
|
@@ -7280,11 +7446,11 @@ ${res.stderr}` : ""),
|
|
|
7280
7446
|
const { loadFederation } = await import('./federation-MDQPO3PW.js');
|
|
7281
7447
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
7282
7448
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
7283
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
7284
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
7449
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-XEP7IPGP.js');
|
|
7450
|
+
const { resolveGraphBackend } = await import('./graph-backend-3A2M22QN.js');
|
|
7285
7451
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7286
7452
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7287
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
7453
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-UTLMMPIZ.js');
|
|
7288
7454
|
const federation = loadFederation(root2);
|
|
7289
7455
|
const modelProfile = mergeModelExecutionProfile(
|
|
7290
7456
|
resolveModelExecutionProfile({
|
|
@@ -7334,6 +7500,7 @@ ${res.stderr}` : ""),
|
|
|
7334
7500
|
stream: opts.stream,
|
|
7335
7501
|
verify: verify3 ? { command: verify3.command, maxRounds: modelProfile.maxRepairRounds } : void 0,
|
|
7336
7502
|
priorSummary,
|
|
7503
|
+
priorInstruction,
|
|
7337
7504
|
externalTools: mcpTools,
|
|
7338
7505
|
prompter,
|
|
7339
7506
|
capsule,
|
|
@@ -7377,7 +7544,7 @@ ${res.stderr}` : ""),
|
|
|
7377
7544
|
attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
|
|
7378
7545
|
});
|
|
7379
7546
|
if (opts.out) {
|
|
7380
|
-
|
|
7547
|
+
fs11.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
|
|
7381
7548
|
}
|
|
7382
7549
|
if (global.json) {
|
|
7383
7550
|
json(result);
|
|
@@ -7590,7 +7757,7 @@ async function addCmd(root2, rest, opts, asJson) {
|
|
|
7590
7757
|
}
|
|
7591
7758
|
function readPackageVersion(root2) {
|
|
7592
7759
|
try {
|
|
7593
|
-
const pkg = JSON.parse(
|
|
7760
|
+
const pkg = JSON.parse(fs11__default.readFileSync(path40__default.join(root2, "package.json"), "utf8"));
|
|
7594
7761
|
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
7595
7762
|
} catch {
|
|
7596
7763
|
return void 0;
|
|
@@ -7598,7 +7765,7 @@ function readPackageVersion(root2) {
|
|
|
7598
7765
|
}
|
|
7599
7766
|
function readOptionalFile(p) {
|
|
7600
7767
|
try {
|
|
7601
|
-
const t =
|
|
7768
|
+
const t = fs11__default.readFileSync(p, "utf8");
|
|
7602
7769
|
return t.trim() ? t : void 0;
|
|
7603
7770
|
} catch {
|
|
7604
7771
|
return void 0;
|
|
@@ -7613,8 +7780,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
|
|
|
7613
7780
|
if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
|
|
7614
7781
|
const version = (opts.version || readPackageVersion(root2) || "").trim();
|
|
7615
7782
|
if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
|
|
7616
|
-
const readme = readOptionalFile(opts.readme ?
|
|
7617
|
-
const dts = opts.dts ? readOptionalFile(
|
|
7783
|
+
const readme = readOptionalFile(opts.readme ? path40__default.resolve(opts.readme) : path40__default.join(root2, "README.md"));
|
|
7784
|
+
const dts = opts.dts ? readOptionalFile(path40__default.resolve(opts.dts)) : void 0;
|
|
7618
7785
|
if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
|
|
7619
7786
|
const result = await publishPrivateLibrary(
|
|
7620
7787
|
{ name, version, readme, dts, language: opts.language },
|
|
@@ -7746,8 +7913,8 @@ function registerExport(program) {
|
|
|
7746
7913
|
out(content.trimEnd());
|
|
7747
7914
|
return;
|
|
7748
7915
|
}
|
|
7749
|
-
|
|
7750
|
-
|
|
7916
|
+
fs11.mkdirSync(path40.dirname(path40.resolve(file)), { recursive: true });
|
|
7917
|
+
fs11.writeFileSync(file, content);
|
|
7751
7918
|
info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
|
|
7752
7919
|
});
|
|
7753
7920
|
applyGlobalOptions(cmd);
|
|
@@ -7757,43 +7924,43 @@ function detectFormat(file) {
|
|
|
7757
7924
|
if (lower.endsWith(".cdx.json")) return "cyclonedx";
|
|
7758
7925
|
if (lower.endsWith(".spdx.json")) return "spdx";
|
|
7759
7926
|
if (file === "-") return "json";
|
|
7760
|
-
return formatForExt(
|
|
7927
|
+
return formatForExt(path40.extname(file));
|
|
7761
7928
|
}
|
|
7762
7929
|
function registerBundle(program) {
|
|
7763
7930
|
const cmd = program.command("bundle").description("build an air-gapped bundle (grammars + graph + library catalog)").option("--offline", "offline bundle (default; present for clarity)").option("-o, --out <dir>", "output directory", "vg-bundle").action(function(opts) {
|
|
7764
7931
|
const global = readGlobal(this);
|
|
7765
7932
|
const root2 = rootOf(global);
|
|
7766
|
-
const outDir =
|
|
7933
|
+
const outDir = path40.resolve(root2, opts.out ?? "vg-bundle");
|
|
7767
7934
|
let grammarFiles;
|
|
7768
7935
|
try {
|
|
7769
7936
|
grammarFiles = resolvedGrammarFiles();
|
|
7770
7937
|
} catch {
|
|
7771
7938
|
throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
|
|
7772
7939
|
}
|
|
7773
|
-
|
|
7940
|
+
fs11.mkdirSync(path40.join(outDir, "grammars"), { recursive: true });
|
|
7774
7941
|
let grammarCount = 0;
|
|
7775
7942
|
for (const { fileName, absPath } of grammarFiles) {
|
|
7776
|
-
|
|
7943
|
+
fs11.copyFileSync(absPath, path40.join(outDir, "grammars", fileName));
|
|
7777
7944
|
grammarCount++;
|
|
7778
7945
|
}
|
|
7779
7946
|
const included = [`grammars/ (${grammarCount} .wasm)`];
|
|
7780
7947
|
const graphSrc = resolveGraphPath(root2, global.graph);
|
|
7781
|
-
if (
|
|
7782
|
-
|
|
7948
|
+
if (fs11.existsSync(graphSrc)) {
|
|
7949
|
+
fs11.copyFileSync(graphSrc, path40.join(outDir, "graph.json"));
|
|
7783
7950
|
included.push("graph.json");
|
|
7784
7951
|
} else {
|
|
7785
7952
|
const graph = loadGraphFileWithSnapshot(graphSrc);
|
|
7786
7953
|
if (graph) {
|
|
7787
|
-
|
|
7954
|
+
fs11.writeFileSync(path40.join(outDir, "graph.json"), serializeGraph(graph));
|
|
7788
7955
|
included.push("graph.json");
|
|
7789
7956
|
}
|
|
7790
7957
|
}
|
|
7791
7958
|
const cat = catalogPath(root2);
|
|
7792
|
-
if (
|
|
7793
|
-
|
|
7959
|
+
if (fs11.existsSync(cat)) {
|
|
7960
|
+
fs11.copyFileSync(cat, path40.join(outDir, "vibgrate.lib.json"));
|
|
7794
7961
|
included.push("vibgrate.lib.json");
|
|
7795
|
-
if (
|
|
7796
|
-
|
|
7962
|
+
if (fs11.existsSync(libDir(root2))) {
|
|
7963
|
+
fs11.cpSync(libDir(root2), path40.join(outDir, "lib"), { recursive: true });
|
|
7797
7964
|
included.push("lib/");
|
|
7798
7965
|
}
|
|
7799
7966
|
}
|
|
@@ -7805,15 +7972,15 @@ function registerBundle(program) {
|
|
|
7805
7972
|
included,
|
|
7806
7973
|
usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
|
|
7807
7974
|
};
|
|
7808
|
-
|
|
7975
|
+
fs11.writeFileSync(path40.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
|
|
7809
7976
|
`);
|
|
7810
7977
|
if (global.json) {
|
|
7811
|
-
json({ out:
|
|
7978
|
+
json({ out: path40.relative(root2, outDir), ...manifest });
|
|
7812
7979
|
return;
|
|
7813
7980
|
}
|
|
7814
|
-
info(`${c.cyan("vg bundle")} \xB7 wrote ${
|
|
7981
|
+
info(`${c.cyan("vg bundle")} \xB7 wrote ${path40.relative(root2, outDir)}/`);
|
|
7815
7982
|
for (const i of included) info(` ${c.green("\u2714")} ${i}`);
|
|
7816
|
-
info(c.dim(` offline: vg build --grammars "${
|
|
7983
|
+
info(c.dim(` offline: vg build --grammars "${path40.relative(root2, outDir)}/grammars"`));
|
|
7817
7984
|
});
|
|
7818
7985
|
applyGlobalOptions(cmd);
|
|
7819
7986
|
}
|
|
@@ -7831,7 +7998,7 @@ async function runDoctor(global) {
|
|
|
7831
7998
|
const root2 = rootOf(global);
|
|
7832
7999
|
const local = global.local === true;
|
|
7833
8000
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
7834
|
-
const configFile = CONFIG_BASENAMES.find((f) =>
|
|
8001
|
+
const configFile = CONFIG_BASENAMES.find((f) => fs11.existsSync(path40.join(root2, f))) ?? null;
|
|
7835
8002
|
const graph = loadGraph(root2, graphPath);
|
|
7836
8003
|
let staleFiles = null;
|
|
7837
8004
|
if (graph) {
|
|
@@ -7857,14 +8024,14 @@ async function runDoctor(global) {
|
|
|
7857
8024
|
root: root2,
|
|
7858
8025
|
configFile,
|
|
7859
8026
|
map: {
|
|
7860
|
-
path:
|
|
8027
|
+
path: path40.relative(root2, graphPath),
|
|
7861
8028
|
built: graph !== null,
|
|
7862
8029
|
generatedAt: graph?.generatedAt ?? null,
|
|
7863
8030
|
staleFiles
|
|
7864
8031
|
},
|
|
7865
8032
|
libCatalog: {
|
|
7866
|
-
path:
|
|
7867
|
-
present:
|
|
8033
|
+
path: path40.relative(root2, catalogPath(root2)),
|
|
8034
|
+
present: fs11.existsSync(catalogPath(root2)),
|
|
7868
8035
|
libraries: libCount
|
|
7869
8036
|
},
|
|
7870
8037
|
credentials: creds,
|
|
@@ -7921,7 +8088,7 @@ async function runDoctor(global) {
|
|
|
7921
8088
|
);
|
|
7922
8089
|
info(
|
|
7923
8090
|
` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
|
|
7924
|
-
` \xB7 last ${
|
|
8091
|
+
` \xB7 last ${path40.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
|
|
7925
8092
|
) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
|
|
7926
8093
|
);
|
|
7927
8094
|
if (li.dynamicOnToken || li.dynamicCustomSampler) {
|
|
@@ -7986,12 +8153,24 @@ function registerDaemon(program) {
|
|
|
7986
8153
|
}
|
|
7987
8154
|
const res = await vgdRequest({ op: "status" }, { socketPath });
|
|
7988
8155
|
if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);
|
|
7989
|
-
|
|
8156
|
+
const semantic = await vgdRequest({ op: "embed-status" }, { socketPath }).catch(() => null);
|
|
8157
|
+
const semanticPayload = semantic && semantic.ok && "semantic" in semantic ? semantic.semantic : void 0;
|
|
8158
|
+
if (global.json) json({ running: true, ...res, semantic: semanticPayload });
|
|
7990
8159
|
else if ("pid" in res) {
|
|
7991
8160
|
const slots = typeof res.graphSlots === "number" ? ` \xB7 ${res.graphSlots} graph slot(s)` : "";
|
|
7992
8161
|
info(
|
|
7993
8162
|
`vgd \xB7 running pid ${res.pid} \xB7 ${res.workspaces} workspace(s)${slots} \xB7 ${res.uptimeMs}ms up \xB7 ${c.dim(res.socketPath)}`
|
|
7994
8163
|
);
|
|
8164
|
+
if (semanticPayload) {
|
|
8165
|
+
const ready = semanticPayload.slots.filter((sl) => sl.state === "ready");
|
|
8166
|
+
const vectors = ready.reduce((n, sl) => n + sl.vectors, 0);
|
|
8167
|
+
const detail = semanticPayload.worker === "unavailable" ? c.dim(semanticPayload.reason ?? "semantic off \u2014 lexical only") : `${ready.length}/${semanticPayload.slots.length} index(es) ready \xB7 ${vectors} vector(s)` + (semanticPayload.model ? ` \xB7 ${semanticPayload.model}` : "");
|
|
8168
|
+
info(` semantic \xB7 worker ${semanticPayload.worker} \xB7 ${detail}`);
|
|
8169
|
+
for (const sl of semanticPayload.slots) {
|
|
8170
|
+
if (sl.state === "ready") continue;
|
|
8171
|
+
info(c.dim(` ${sl.repositoryId}@${sl.gitRef} \xB7 ${sl.state}${sl.error ? ` \u2014 ${sl.error}` : ""}`));
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
7995
8174
|
}
|
|
7996
8175
|
});
|
|
7997
8176
|
applyGlobalOptions(status);
|
|
@@ -8003,7 +8182,13 @@ function registerDaemon(program) {
|
|
|
8003
8182
|
}
|
|
8004
8183
|
let requestShutdown = () => {
|
|
8005
8184
|
};
|
|
8006
|
-
const server = await startVgdServer({
|
|
8185
|
+
const server = await startVgdServer({
|
|
8186
|
+
socketPath,
|
|
8187
|
+
onShutdownRequest: () => requestShutdown(),
|
|
8188
|
+
// Show the daemon working: graph publishes, branch switches, new repos,
|
|
8189
|
+
// and every semantic index build. Silent under --quiet/--json.
|
|
8190
|
+
log: global.quiet || global.json ? void 0 : (message) => info(c.dim(`vgd \xB7 ${message}`))
|
|
8191
|
+
});
|
|
8007
8192
|
if (!global.quiet) {
|
|
8008
8193
|
info(`vgd \xB7 listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);
|
|
8009
8194
|
info(c.dim(" register a workspace: vg daemon register"));
|
|
@@ -8097,7 +8282,7 @@ function registerDaemon(program) {
|
|
|
8097
8282
|
const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
|
|
8098
8283
|
const global = readGlobal(this);
|
|
8099
8284
|
const socketPath = socketOf(this);
|
|
8100
|
-
const root2 =
|
|
8285
|
+
const root2 = path40.resolve(rootArg ?? rootOf(global));
|
|
8101
8286
|
if (!await vgdIsRunning({ socketPath })) {
|
|
8102
8287
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
8103
8288
|
}
|
|
@@ -8133,7 +8318,7 @@ function registerDaemon(program) {
|
|
|
8133
8318
|
const federation = cmd.command("federation").description("register a multi-root federation from .vibgrate/federation.json (or primary cwd)").argument("[root]", "primary repository root (default: cwd)").action(async function(rootArg) {
|
|
8134
8319
|
const global = readGlobal(this);
|
|
8135
8320
|
const socketPath = socketOf(this);
|
|
8136
|
-
const primary =
|
|
8321
|
+
const primary = path40.resolve(rootArg ?? rootOf(global));
|
|
8137
8322
|
if (!await vgdIsRunning({ socketPath })) {
|
|
8138
8323
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
8139
8324
|
}
|
|
@@ -8161,7 +8346,7 @@ function registerDaemon(program) {
|
|
|
8161
8346
|
const publish = cmd.command("publish").description("load the workspace code map into vgd ActiveGraph (from global/legacy store)").argument("[root]", "repository root (default: cwd)").option("--git-ref <ref>", "branch or SHA (default: detect HEAD)").action(async function(rootArg) {
|
|
8162
8347
|
const global = readGlobal(this);
|
|
8163
8348
|
const socketPath = socketOf(this);
|
|
8164
|
-
const root2 =
|
|
8349
|
+
const root2 = path40.resolve(rootArg ?? rootOf(global));
|
|
8165
8350
|
if (!await vgdIsRunning({ socketPath })) {
|
|
8166
8351
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
8167
8352
|
}
|
|
@@ -8175,7 +8360,7 @@ function registerDaemon(program) {
|
|
|
8175
8360
|
throw new CliError(loaded.error, ExitCode.NOT_FOUND);
|
|
8176
8361
|
}
|
|
8177
8362
|
if (!loaded.ok) {
|
|
8178
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
8363
|
+
const { loadGraph: loadGraph2 } = await import('./load-6KVGUQMU.js');
|
|
8179
8364
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
8180
8365
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
8181
8366
|
const graph = loadGraph2(root2, global.graph);
|
|
@@ -8291,7 +8476,7 @@ function socketOf(cmd) {
|
|
|
8291
8476
|
let c2 = cmd;
|
|
8292
8477
|
while (c2) {
|
|
8293
8478
|
const opts = c2.opts();
|
|
8294
|
-
if (opts.socket) return
|
|
8479
|
+
if (opts.socket) return path40.resolve(opts.socket);
|
|
8295
8480
|
c2 = c2.parent;
|
|
8296
8481
|
}
|
|
8297
8482
|
return vgdSocketPath();
|
|
@@ -8363,7 +8548,7 @@ async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
|
|
|
8363
8548
|
}
|
|
8364
8549
|
function readVgdPid() {
|
|
8365
8550
|
try {
|
|
8366
|
-
const raw =
|
|
8551
|
+
const raw = fs11.readFileSync(vgdPidPath(), "utf8").trim();
|
|
8367
8552
|
const pid = Number.parseInt(raw, 10);
|
|
8368
8553
|
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
8369
8554
|
} catch {
|
|
@@ -8448,7 +8633,7 @@ function registerPolicy(program) {
|
|
|
8448
8633
|
const global = readGlobal(this);
|
|
8449
8634
|
let raw;
|
|
8450
8635
|
try {
|
|
8451
|
-
raw =
|
|
8636
|
+
raw = fs11.readFileSync(file, "utf8");
|
|
8452
8637
|
} catch {
|
|
8453
8638
|
throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
|
|
8454
8639
|
}
|
|
@@ -8568,11 +8753,11 @@ function registerLlmHost(program) {
|
|
|
8568
8753
|
applyGlobalOptions(cmd);
|
|
8569
8754
|
}
|
|
8570
8755
|
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) => {
|
|
8571
|
-
const rootDir =
|
|
8572
|
-
const vibgrateDir2 =
|
|
8756
|
+
const rootDir = path40.resolve(targetPath);
|
|
8757
|
+
const vibgrateDir2 = path40.join(rootDir, ".vibgrate");
|
|
8573
8758
|
await ensureDir(vibgrateDir2);
|
|
8574
8759
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
|
|
8575
|
-
const configPath =
|
|
8760
|
+
const configPath = path40.join(rootDir, "vibgrate.config.ts");
|
|
8576
8761
|
if (await pathExists(configPath)) {
|
|
8577
8762
|
console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
|
|
8578
8763
|
} else {
|
|
@@ -8580,7 +8765,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
8580
8765
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
|
|
8581
8766
|
}
|
|
8582
8767
|
if (opts.baseline) {
|
|
8583
|
-
const { runBaseline } = await import('./baseline-
|
|
8768
|
+
const { runBaseline } = await import('./baseline-3HECX4Q6.js');
|
|
8584
8769
|
await runBaseline(rootDir);
|
|
8585
8770
|
}
|
|
8586
8771
|
console.log("");
|
|
@@ -8683,7 +8868,7 @@ function collectPackageImports(graph, ecosystem, pkg) {
|
|
|
8683
8868
|
};
|
|
8684
8869
|
}
|
|
8685
8870
|
async function firstReferenceLine(rootDir, relFile, identifier, readFile3) {
|
|
8686
|
-
const content = await readFile3(
|
|
8871
|
+
const content = await readFile3(path40.join(rootDir, relFile));
|
|
8687
8872
|
if (!content) return null;
|
|
8688
8873
|
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8689
8874
|
const re = new RegExp(`\\b${escaped}\\b`);
|
|
@@ -8721,9 +8906,9 @@ function sitesFromImportFiles(files, limit = 10) {
|
|
|
8721
8906
|
}
|
|
8722
8907
|
async function defaultReadFile(absPath) {
|
|
8723
8908
|
try {
|
|
8724
|
-
const stat2 = await
|
|
8909
|
+
const stat2 = await fs25.stat(absPath);
|
|
8725
8910
|
if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
|
|
8726
|
-
return await
|
|
8911
|
+
return await fs25.readFile(absPath, "utf8");
|
|
8727
8912
|
} catch {
|
|
8728
8913
|
return null;
|
|
8729
8914
|
}
|
|
@@ -8919,7 +9104,7 @@ var AI_ASSISTANT_DETECTORS = [
|
|
|
8919
9104
|
async function detectAiAssistant(rootDir) {
|
|
8920
9105
|
for (const detector of AI_ASSISTANT_DETECTORS) {
|
|
8921
9106
|
for (const file of detector.files) {
|
|
8922
|
-
if (await pathExists$1(
|
|
9107
|
+
if (await pathExists$1(path40.join(rootDir, file))) {
|
|
8923
9108
|
return detector.name;
|
|
8924
9109
|
}
|
|
8925
9110
|
}
|
|
@@ -9113,7 +9298,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
9113
9298
|
collectExcludes,
|
|
9114
9299
|
[]
|
|
9115
9300
|
).option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--full", "Comprehensive scan: turns on known-vulnerability detection (= --vulns) and, when a standards policy exists, a banned-dependency report \u2014 on top of drift scoring and the code map").option("--vulns", "Also scan installed dependencies for known vulnerabilities (OSV online, or advisories from --package-manifest when offline)").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--project-scan-timeout <seconds>", "Per-project scan timeout in seconds (default: 180)").option("--drift-budget <score>", "Fail if DriftScore is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").option("--repository-name <name>", "Override the repository name recorded for this scan (defaults to the directory or package.json name)").option("--force", "Always create a fresh scan ingest, even if the repository is unchanged since the last scan (skips the unchanged/reuse optimization). Used by scheduled and dashboard-triggered scans.").option("--no-graph", "Skip building the local code map (the AI/docs index) that scan produces after scoring drift").option("--quiet", "Suppress promotional output (the free-plan tracking panel and the AI Context install prompt); scan results are unaffected").action(async (targetPath, opts) => {
|
|
9116
|
-
const rootDir =
|
|
9301
|
+
const rootDir = path40.resolve(targetPath);
|
|
9117
9302
|
if (!await pathExists$1(rootDir)) {
|
|
9118
9303
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
9119
9304
|
process.exit(1);
|
|
@@ -9121,7 +9306,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
9121
9306
|
const hasDsn = !!resolveDsn(opts.dsn);
|
|
9122
9307
|
const willPush = !opts.offline && (opts.push || hasDsn);
|
|
9123
9308
|
const noLocalArtifacts = opts.localArtifacts === false;
|
|
9124
|
-
const isFirstRun = !await pathExists$1(
|
|
9309
|
+
const isFirstRun = !await pathExists$1(path40.join(rootDir, ".vibgrate", "scan_result.json"));
|
|
9125
9310
|
let pinnedRegion;
|
|
9126
9311
|
let planTier;
|
|
9127
9312
|
let upgradeUrl;
|
|
@@ -9380,7 +9565,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
|
9380
9565
|
function scanStaleness(rootDir, artifactPath) {
|
|
9381
9566
|
let ref;
|
|
9382
9567
|
try {
|
|
9383
|
-
ref =
|
|
9568
|
+
ref = fs11.statSync(artifactPath).mtimeMs;
|
|
9384
9569
|
} catch {
|
|
9385
9570
|
return { stale: false };
|
|
9386
9571
|
}
|
|
@@ -9392,7 +9577,7 @@ function scanStaleness(rootDir, artifactPath) {
|
|
|
9392
9577
|
if (depth > 8 || scanned > MAX_ENTRIES2) return;
|
|
9393
9578
|
let entries;
|
|
9394
9579
|
try {
|
|
9395
|
-
entries =
|
|
9580
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
9396
9581
|
} catch {
|
|
9397
9582
|
return;
|
|
9398
9583
|
}
|
|
@@ -9400,20 +9585,20 @@ function scanStaleness(rootDir, artifactPath) {
|
|
|
9400
9585
|
scanned++;
|
|
9401
9586
|
if (scanned > MAX_ENTRIES2) break;
|
|
9402
9587
|
if (e.isDirectory()) {
|
|
9403
|
-
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(
|
|
9588
|
+
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path40.join(dir, e.name), depth + 1);
|
|
9404
9589
|
continue;
|
|
9405
9590
|
}
|
|
9406
9591
|
if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
|
|
9407
|
-
const abs =
|
|
9592
|
+
const abs = path40.join(dir, e.name);
|
|
9408
9593
|
let mtimeMs;
|
|
9409
9594
|
try {
|
|
9410
|
-
mtimeMs =
|
|
9595
|
+
mtimeMs = fs11.statSync(abs).mtimeMs;
|
|
9411
9596
|
} catch {
|
|
9412
9597
|
continue;
|
|
9413
9598
|
}
|
|
9414
9599
|
if (mtimeMs > newest) {
|
|
9415
9600
|
newest = mtimeMs;
|
|
9416
|
-
newestChanged =
|
|
9601
|
+
newestChanged = path40.relative(rootDir, abs) || e.name;
|
|
9417
9602
|
}
|
|
9418
9603
|
}
|
|
9419
9604
|
};
|
|
@@ -9544,7 +9729,7 @@ function analyzeTree(root2, packages) {
|
|
|
9544
9729
|
if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
|
|
9545
9730
|
let entries;
|
|
9546
9731
|
try {
|
|
9547
|
-
entries =
|
|
9732
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
9548
9733
|
} catch {
|
|
9549
9734
|
return;
|
|
9550
9735
|
}
|
|
@@ -9553,17 +9738,17 @@ function analyzeTree(root2, packages) {
|
|
|
9553
9738
|
if (filesSeen >= MAX_FILES) return;
|
|
9554
9739
|
if (entry.isDirectory()) {
|
|
9555
9740
|
if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
9556
|
-
walk2(
|
|
9741
|
+
walk2(path40.join(dir, entry.name), depth + 1);
|
|
9557
9742
|
continue;
|
|
9558
9743
|
}
|
|
9559
|
-
const fileEco = EXT_ECOSYSTEM[
|
|
9744
|
+
const fileEco = EXT_ECOSYSTEM[path40.extname(entry.name)];
|
|
9560
9745
|
if (!fileEco || fileEco === "unknown") continue;
|
|
9561
9746
|
filesSeen++;
|
|
9562
|
-
const full =
|
|
9747
|
+
const full = path40.join(dir, entry.name);
|
|
9563
9748
|
let content;
|
|
9564
9749
|
try {
|
|
9565
|
-
if (
|
|
9566
|
-
content =
|
|
9750
|
+
if (fs11.statSync(full).size > MAX_FILE_BYTES2) continue;
|
|
9751
|
+
content = fs11.readFileSync(full, "utf8");
|
|
9567
9752
|
} catch {
|
|
9568
9753
|
continue;
|
|
9569
9754
|
}
|
|
@@ -9874,7 +10059,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
9874
10059
|
}
|
|
9875
10060
|
const outcomes = effective.map((t) => {
|
|
9876
10061
|
const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
|
|
9877
|
-
return { t, res: run(c2,
|
|
10062
|
+
return { t, res: run(c2, path40.join(rootDir, t.dir)) };
|
|
9878
10063
|
});
|
|
9879
10064
|
const failures = outcomes.filter((o) => !o.res.ok);
|
|
9880
10065
|
if (failures.length === 0) {
|
|
@@ -9903,8 +10088,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
9903
10088
|
return results;
|
|
9904
10089
|
}
|
|
9905
10090
|
var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
|
|
9906
|
-
var CACHE_DIR =
|
|
9907
|
-
var CACHE_FILE =
|
|
10091
|
+
var CACHE_DIR = path40.join(os.homedir(), ".vibgrate");
|
|
10092
|
+
var CACHE_FILE = path40.join(CACHE_DIR, "update-check.json");
|
|
9908
10093
|
async function fetchLatestVersion() {
|
|
9909
10094
|
try {
|
|
9910
10095
|
const controller = new AbortController();
|
|
@@ -9931,8 +10116,8 @@ async function fetchLatestVersion() {
|
|
|
9931
10116
|
}
|
|
9932
10117
|
async function writeCache(data) {
|
|
9933
10118
|
try {
|
|
9934
|
-
await
|
|
9935
|
-
await
|
|
10119
|
+
await fs25.mkdir(CACHE_DIR, { recursive: true });
|
|
10120
|
+
await fs25.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
|
|
9936
10121
|
} catch {
|
|
9937
10122
|
}
|
|
9938
10123
|
}
|
|
@@ -9943,7 +10128,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
|
|
|
9943
10128
|
if (!execPath) return null;
|
|
9944
10129
|
let resolved = execPath;
|
|
9945
10130
|
try {
|
|
9946
|
-
resolved =
|
|
10131
|
+
resolved = fs11.realpathSync(execPath);
|
|
9947
10132
|
} catch {
|
|
9948
10133
|
}
|
|
9949
10134
|
const p = resolved.replace(/\\/g, "/");
|
|
@@ -9973,14 +10158,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
|
|
|
9973
10158
|
pm: "yarn",
|
|
9974
10159
|
root: () => {
|
|
9975
10160
|
const dir = tryRun("yarn global dir");
|
|
9976
|
-
return dir ?
|
|
10161
|
+
return dir ? path40.join(dir, "node_modules") : null;
|
|
9977
10162
|
}
|
|
9978
10163
|
},
|
|
9979
|
-
{ pm: "bun", root: () =>
|
|
10164
|
+
{ pm: "bun", root: () => path40.join(os.homedir(), ".bun", "install", "global", "node_modules") }
|
|
9980
10165
|
];
|
|
9981
10166
|
for (const probe of probes) {
|
|
9982
10167
|
const root2 = probe.root();
|
|
9983
|
-
if (root2 && await pathExists(
|
|
10168
|
+
if (root2 && await pathExists(path40.join(root2, pkg))) return probe.pm;
|
|
9984
10169
|
}
|
|
9985
10170
|
return null;
|
|
9986
10171
|
}
|
|
@@ -9999,15 +10184,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
|
|
|
9999
10184
|
}
|
|
10000
10185
|
}
|
|
10001
10186
|
async function detectPackageManager(cwd) {
|
|
10002
|
-
if (await pathExists(
|
|
10003
|
-
if (await pathExists(
|
|
10004
|
-
if (await pathExists(
|
|
10187
|
+
if (await pathExists(path40.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
10188
|
+
if (await pathExists(path40.join(cwd, "bun.lockb"))) return "bun";
|
|
10189
|
+
if (await pathExists(path40.join(cwd, "yarn.lock"))) return "yarn";
|
|
10005
10190
|
return "npm";
|
|
10006
10191
|
}
|
|
10007
10192
|
async function detectWorkspaceRoot(cwd) {
|
|
10008
|
-
if (await pathExists(
|
|
10193
|
+
if (await pathExists(path40.join(cwd, "pnpm-workspace.yaml"))) return true;
|
|
10009
10194
|
try {
|
|
10010
|
-
const pkgPath =
|
|
10195
|
+
const pkgPath = path40.join(cwd, "package.json");
|
|
10011
10196
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
10012
10197
|
const pkg = JSON.parse(raw);
|
|
10013
10198
|
return pkg.workspaces != null;
|
|
@@ -10032,7 +10217,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
|
|
|
10032
10217
|
}
|
|
10033
10218
|
async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
|
|
10034
10219
|
try {
|
|
10035
|
-
const pkgPath =
|
|
10220
|
+
const pkgPath = path40.join(cwd, "package.json");
|
|
10036
10221
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
10037
10222
|
const parsed = JSON.parse(raw);
|
|
10038
10223
|
if (parsed.devDependencies?.[pkg]) return "dev";
|
|
@@ -10122,8 +10307,27 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
|
|
|
10122
10307
|
}
|
|
10123
10308
|
if (opts.reap !== false) reapAndReport(cwd, latest);
|
|
10124
10309
|
if (opts.reap !== false) await restartVgdAndReport();
|
|
10310
|
+
try {
|
|
10311
|
+
clearEmbedderHealth();
|
|
10312
|
+
} catch {
|
|
10313
|
+
}
|
|
10314
|
+
if (opts.reap !== false) await rewarmVgdAndReport(cwd);
|
|
10125
10315
|
}
|
|
10126
10316
|
);
|
|
10317
|
+
async function rewarmVgdAndReport(cwd) {
|
|
10318
|
+
try {
|
|
10319
|
+
const { vgdIsRunning: vgdIsRunning2, vgdRequest: vgdRequest2 } = await import('./vgd-UTLMMPIZ.js');
|
|
10320
|
+
if (!await vgdIsRunning2()) return;
|
|
10321
|
+
const loaded = await vgdRequest2({ op: "load-graph", root: cwd });
|
|
10322
|
+
if (!loaded.ok || !("repositoryId" in loaded)) return;
|
|
10323
|
+
console.log(chalk7.dim("Re-published the code map into the restarted daemon."));
|
|
10324
|
+
const indexed = await vgdRequest2({ op: "embed-index", repositoryId: loaded.repositoryId });
|
|
10325
|
+
if (indexed.ok && "vectors" in indexed && indexed.state === "ready") {
|
|
10326
|
+
console.log(chalk7.dim(`Semantic index warm again (${indexed.vectors} vectors).`));
|
|
10327
|
+
}
|
|
10328
|
+
} catch {
|
|
10329
|
+
}
|
|
10330
|
+
}
|
|
10127
10331
|
async function restartVgdAndReport() {
|
|
10128
10332
|
let result;
|
|
10129
10333
|
try {
|
|
@@ -10201,13 +10405,13 @@ function collectCandidates(artifact) {
|
|
|
10201
10405
|
return out2;
|
|
10202
10406
|
}
|
|
10203
10407
|
var defaultFixScanner = async (rootDir) => {
|
|
10204
|
-
const scratch =
|
|
10408
|
+
const scratch = path40.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
|
|
10205
10409
|
const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
|
|
10206
10410
|
const advanced = await loadAdvancedScanHook();
|
|
10207
10411
|
return runCoreScan(rootDir, scanOpts, advanced);
|
|
10208
10412
|
};
|
|
10209
10413
|
async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
|
|
10210
|
-
const artifactPath =
|
|
10414
|
+
const artifactPath = path40.isAbsolute(inFile) ? inFile : path40.join(rootDir, inFile);
|
|
10211
10415
|
if (await pathExists(artifactPath)) {
|
|
10212
10416
|
const staleness = scanStaleness(rootDir, artifactPath);
|
|
10213
10417
|
if (!staleness.stale) {
|
|
@@ -10234,7 +10438,7 @@ async function repositoryIdentity(rootDir, override) {
|
|
|
10234
10438
|
}
|
|
10235
10439
|
}
|
|
10236
10440
|
var fixCommand = new Command("fix").description("Get ranked, risk-tiered upgrade plans from the hosted planner and optionally apply them (prompts before changing files; --yes applies non-interactively, --dry-run previews, --no-apply only prints). Requires login/DSN.").argument("[path]", "Path to analyse", ".").option("--in <file>", "Scan artifact to read", ".vibgrate/scan_result.json").option("--format <format>", "Output format (text|json|md)", "text").option("--dsn <dsn>", 'DSN token (or use VIBGRATE_DSN env / "vg login")').option("--region <region>", "Override data residency region (us, eu)").option("--repository-name <name>", "Override the repository name recorded for this plan").option("--plan <tier>", "Apply a specific plan non-interactively (safe|balanced|aggressive)").option("--yes", "Apply the recommended plan without prompting").option("--dry-run", "Show what would change without applying").option("--no-apply", "Only print the plans; never modify the project").option("--fail-on-vulns <severity>", "Exit non-zero if the recommended plan leaves an advisory at/above this severity unresolved (low|moderate|high|critical)").action(async (targetPath, opts) => {
|
|
10237
|
-
const rootDir =
|
|
10441
|
+
const rootDir = path40.resolve(targetPath);
|
|
10238
10442
|
if (!await pathExists(rootDir)) {
|
|
10239
10443
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
10240
10444
|
process.exit(1);
|
|
@@ -10395,7 +10599,7 @@ function emit(report, format) {
|
|
|
10395
10599
|
}
|
|
10396
10600
|
}
|
|
10397
10601
|
function relProjectDir(rootDir, projectPath) {
|
|
10398
|
-
const rel =
|
|
10602
|
+
const rel = path40.isAbsolute(projectPath) ? path40.relative(rootDir, projectPath) : projectPath;
|
|
10399
10603
|
return rel === "" ? "." : rel;
|
|
10400
10604
|
}
|
|
10401
10605
|
async function buildTargetResolver(rootDir, artifact) {
|
|
@@ -11230,7 +11434,7 @@ function formatMarkdown(artifact) {
|
|
|
11230
11434
|
|
|
11231
11435
|
// src/reporting/commands/report.ts
|
|
11232
11436
|
var reportCommand = new Command("report").description("Generate a drift report from a scan artifact").option("--in <file>", "Input artifact file", ".vibgrate/scan_result.json").option("--format <format>", "Output format (md|text|json)", "text").action(async (opts) => {
|
|
11233
|
-
const artifactPath =
|
|
11437
|
+
const artifactPath = path40.resolve(opts.in);
|
|
11234
11438
|
if (!await pathExists(artifactPath)) {
|
|
11235
11439
|
console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
|
|
11236
11440
|
console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
|
|
@@ -11279,8 +11483,8 @@ function openUrl(url) {
|
|
|
11279
11483
|
// src/reporting/commands/login.ts
|
|
11280
11484
|
var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
11281
11485
|
function isInside(dir, file) {
|
|
11282
|
-
const rel =
|
|
11283
|
-
return !!rel && !rel.startsWith("..") && !
|
|
11486
|
+
const rel = path40.relative(dir, file);
|
|
11487
|
+
return !!rel && !rel.startsWith("..") && !path40.isAbsolute(rel);
|
|
11284
11488
|
}
|
|
11285
11489
|
var loginCommand = new Command("login").description("Authenticate the CLI with your Vibgrate workspace via the browser").option("--ingest <url>", "Ingest API URL (overrides --region)").option("--region <region>", `Data residency region (${availableRegionIds().join(", ")})`, "us").option("--no-browser", "Do not attempt to open a browser automatically").option(
|
|
11286
11490
|
"--local",
|
|
@@ -11535,7 +11739,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
11535
11739
|
try {
|
|
11536
11740
|
const statements = [];
|
|
11537
11741
|
if (opts.from) {
|
|
11538
|
-
const fromPath =
|
|
11742
|
+
const fromPath = path40.resolve(opts.from);
|
|
11539
11743
|
if (!await pathExists(fromPath)) {
|
|
11540
11744
|
process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
|
|
11541
11745
|
`));
|
|
@@ -11553,9 +11757,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
11553
11757
|
});
|
|
11554
11758
|
const json2 = JSON.stringify(doc, null, 2);
|
|
11555
11759
|
if (opts.out) {
|
|
11556
|
-
await writeTextFile(
|
|
11760
|
+
await writeTextFile(path40.resolve(opts.out), json2 + "\n");
|
|
11557
11761
|
process.stderr.write(
|
|
11558
|
-
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${
|
|
11762
|
+
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path40.resolve(opts.out)}
|
|
11559
11763
|
`
|
|
11560
11764
|
);
|
|
11561
11765
|
} else {
|
|
@@ -11738,7 +11942,7 @@ function formatDeltaText(base, current) {
|
|
|
11738
11942
|
return lines.join("\n");
|
|
11739
11943
|
}
|
|
11740
11944
|
async function readArtifactOrExit(filePath) {
|
|
11741
|
-
const absolutePath =
|
|
11945
|
+
const absolutePath = path40.resolve(filePath);
|
|
11742
11946
|
if (!await pathExists(absolutePath)) {
|
|
11743
11947
|
console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
|
|
11744
11948
|
process.exit(1);
|
|
@@ -11755,7 +11959,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
|
|
|
11755
11959
|
const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
|
|
11756
11960
|
const body = JSON.stringify(sbom, null, 2);
|
|
11757
11961
|
if (opts.out) {
|
|
11758
|
-
await writeTextFile(
|
|
11962
|
+
await writeTextFile(path40.resolve(opts.out), body);
|
|
11759
11963
|
console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
|
|
11760
11964
|
} else {
|
|
11761
11965
|
console.log(body);
|
|
@@ -11766,7 +11970,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
|
|
|
11766
11970
|
const current = await readArtifactOrExit(opts.to);
|
|
11767
11971
|
const report = formatDeltaText(base, current);
|
|
11768
11972
|
if (opts.out) {
|
|
11769
|
-
await writeTextFile(
|
|
11973
|
+
await writeTextFile(path40.resolve(opts.out), report);
|
|
11770
11974
|
console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
|
|
11771
11975
|
} else {
|
|
11772
11976
|
console.log(report);
|
|
@@ -11897,20 +12101,20 @@ function resolveRegime(id) {
|
|
|
11897
12101
|
return regime;
|
|
11898
12102
|
}
|
|
11899
12103
|
function evidenceDir(root2) {
|
|
11900
|
-
return
|
|
12104
|
+
return path40.join(root2, ".vibgrate", "evidence");
|
|
11901
12105
|
}
|
|
11902
12106
|
function orgPath(root2) {
|
|
11903
|
-
return
|
|
12107
|
+
return path40.join(evidenceDir(root2), "org.json");
|
|
11904
12108
|
}
|
|
11905
12109
|
function productsPath(root2) {
|
|
11906
|
-
return
|
|
12110
|
+
return path40.join(evidenceDir(root2), "products.json");
|
|
11907
12111
|
}
|
|
11908
12112
|
function releasesDir(root2) {
|
|
11909
|
-
return
|
|
12113
|
+
return path40.join(evidenceDir(root2), "releases");
|
|
11910
12114
|
}
|
|
11911
12115
|
function releasePath(root2, productId, version) {
|
|
11912
12116
|
const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
11913
|
-
return
|
|
12117
|
+
return path40.join(releasesDir(root2), `${safe}.json`);
|
|
11914
12118
|
}
|
|
11915
12119
|
var DEFAULT_ORG = {
|
|
11916
12120
|
responsiblePersons: [],
|
|
@@ -11941,7 +12145,7 @@ async function freezeRelease(root2, release) {
|
|
|
11941
12145
|
const p = releasePath(root2, release.productId, release.version);
|
|
11942
12146
|
if (await pathExists(p)) {
|
|
11943
12147
|
throw new CliError(
|
|
11944
|
-
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${
|
|
12148
|
+
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path40.relative(root2, p)} only if it was frozen in error`,
|
|
11945
12149
|
ExitCode.USAGE_ERROR
|
|
11946
12150
|
);
|
|
11947
12151
|
}
|
|
@@ -11955,7 +12159,7 @@ async function loadReleases(root2, productId) {
|
|
|
11955
12159
|
const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
|
|
11956
12160
|
const releases = [];
|
|
11957
12161
|
for (const f of files) {
|
|
11958
|
-
const rel = await readJsonFile(
|
|
12162
|
+
const rel = await readJsonFile(path40.join(dir, f));
|
|
11959
12163
|
if (!productId || rel.productId === productId) releases.push(rel);
|
|
11960
12164
|
}
|
|
11961
12165
|
return releases;
|
|
@@ -12650,19 +12854,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
|
|
|
12650
12854
|
var DEFAULT_KEY = "attest-key.pem";
|
|
12651
12855
|
function resolveSigningKey(root2, explicit) {
|
|
12652
12856
|
const chosen = process.env.VG_ATTEST_KEY;
|
|
12653
|
-
const keyPath = chosen ?
|
|
12857
|
+
const keyPath = chosen ? path40.resolve(chosen) : path40.join(root2, ".vibgrate", DEFAULT_KEY);
|
|
12654
12858
|
let minted = false;
|
|
12655
|
-
if (!
|
|
12859
|
+
if (!fs11.existsSync(keyPath)) {
|
|
12656
12860
|
if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
|
|
12657
12861
|
const kp = generateKeypair();
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12862
|
+
fs11.mkdirSync(path40.dirname(keyPath), { recursive: true });
|
|
12863
|
+
fs11.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
|
|
12864
|
+
fs11.writeFileSync(`${keyPath}.pub`, kp.publicPem);
|
|
12661
12865
|
minted = true;
|
|
12662
12866
|
}
|
|
12663
12867
|
let key2;
|
|
12664
12868
|
try {
|
|
12665
|
-
key2 = crypto3.createPrivateKey(
|
|
12869
|
+
key2 = crypto3.createPrivateKey(fs11.readFileSync(keyPath, "utf8"));
|
|
12666
12870
|
} catch {
|
|
12667
12871
|
throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
|
|
12668
12872
|
}
|
|
@@ -12673,16 +12877,16 @@ function resolveSigningKey(root2, explicit) {
|
|
|
12673
12877
|
}
|
|
12674
12878
|
function writeBundle(input) {
|
|
12675
12879
|
const dir = input.outDir;
|
|
12676
|
-
|
|
12677
|
-
const write = (rel, data) =>
|
|
12880
|
+
fs11.mkdirSync(path40.join(dir, "inputs", "releases"), { recursive: true });
|
|
12881
|
+
const write = (rel, data) => fs11.writeFileSync(path40.join(dir, rel), `${JSON.stringify(data, null, 2)}
|
|
12678
12882
|
`);
|
|
12679
12883
|
write("result.json", input.result);
|
|
12680
|
-
write(
|
|
12884
|
+
write(path40.join("inputs", "advisory.json"), input.advisory);
|
|
12681
12885
|
for (const rel of input.releases) {
|
|
12682
12886
|
const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
12683
|
-
write(
|
|
12887
|
+
write(path40.join("inputs", "releases", `${safe}.json`), rel);
|
|
12684
12888
|
}
|
|
12685
|
-
write(
|
|
12889
|
+
write(path40.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
|
|
12686
12890
|
write("provenance.json", {
|
|
12687
12891
|
method: "deterministic",
|
|
12688
12892
|
modelDrafted: [],
|
|
@@ -12698,13 +12902,13 @@ function writeBundle(input) {
|
|
|
12698
12902
|
disclaimer: input.regime.disclaimer
|
|
12699
12903
|
});
|
|
12700
12904
|
if (input.envelope) {
|
|
12701
|
-
|
|
12905
|
+
fs11.writeFileSync(path40.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
|
|
12702
12906
|
`);
|
|
12703
12907
|
}
|
|
12704
12908
|
if (input.timestampToken) {
|
|
12705
|
-
|
|
12909
|
+
fs11.writeFileSync(path40.join(dir, "timestamp.tsr"), input.timestampToken);
|
|
12706
12910
|
}
|
|
12707
|
-
|
|
12911
|
+
fs11.writeFileSync(path40.join(dir, "VERIFY.md"), verifyDoc(input));
|
|
12708
12912
|
return dir;
|
|
12709
12913
|
}
|
|
12710
12914
|
function verifyDoc(input) {
|
|
@@ -12765,13 +12969,13 @@ function undeterminedFields(result, regime) {
|
|
|
12765
12969
|
return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
|
|
12766
12970
|
}
|
|
12767
12971
|
async function recordDrill(root2, record) {
|
|
12768
|
-
const dir =
|
|
12769
|
-
const p =
|
|
12972
|
+
const dir = path40.join(evidenceDir(root2), "drills");
|
|
12973
|
+
const p = path40.join(dir, `${record.drillId}.json`);
|
|
12770
12974
|
await writeJsonFile(p, record);
|
|
12771
12975
|
return p;
|
|
12772
12976
|
}
|
|
12773
12977
|
async function hasRecentDrill(root2, asOf) {
|
|
12774
|
-
const dir =
|
|
12978
|
+
const dir = path40.join(evidenceDir(root2), "drills");
|
|
12775
12979
|
if (!await pathExists(dir)) return void 0;
|
|
12776
12980
|
const { readdir } = await import('fs/promises');
|
|
12777
12981
|
const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
|
|
@@ -12779,7 +12983,7 @@ async function hasRecentDrill(root2, asOf) {
|
|
|
12779
12983
|
if (files.length === 0) return void 0;
|
|
12780
12984
|
const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
|
|
12781
12985
|
for (const f of files) {
|
|
12782
|
-
const rec = await readJsonFile2(
|
|
12986
|
+
const rec = await readJsonFile2(path40.join(dir, f));
|
|
12783
12987
|
if (rec.ranAt >= cutoff) return true;
|
|
12784
12988
|
}
|
|
12785
12989
|
return false;
|
|
@@ -12859,7 +13063,7 @@ function formatRegimeList() {
|
|
|
12859
13063
|
|
|
12860
13064
|
// src/reporting/commands/evidence/index.ts
|
|
12861
13065
|
function root(opts) {
|
|
12862
|
-
return
|
|
13066
|
+
return path40.resolve(opts.cwd ?? process.cwd());
|
|
12863
13067
|
}
|
|
12864
13068
|
function slug(name) {
|
|
12865
13069
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
|
|
@@ -12947,7 +13151,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
12947
13151
|
const release = await buildRelease({
|
|
12948
13152
|
productId: product.id,
|
|
12949
13153
|
version,
|
|
12950
|
-
from:
|
|
13154
|
+
from: path40.resolve(rootDir, opts.from),
|
|
12951
13155
|
shipDate: opts.shipDate,
|
|
12952
13156
|
buildId: opts.buildId,
|
|
12953
13157
|
artefactDigest: opts.digest,
|
|
@@ -12955,7 +13159,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
12955
13159
|
frozenAt: nowIso()
|
|
12956
13160
|
});
|
|
12957
13161
|
const p = await freezeRelease(rootDir, release);
|
|
12958
|
-
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${
|
|
13162
|
+
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path40.relative(rootDir, p)}`);
|
|
12959
13163
|
});
|
|
12960
13164
|
async function runExposure(rootDir, vuln, opts) {
|
|
12961
13165
|
const org = await loadOrg(rootDir);
|
|
@@ -13007,7 +13211,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
13007
13211
|
console.log("\n" + buildPack(result, regime, org, stage));
|
|
13008
13212
|
}
|
|
13009
13213
|
if (opts.bundle) {
|
|
13010
|
-
const dir =
|
|
13214
|
+
const dir = path40.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
|
|
13011
13215
|
let envelope;
|
|
13012
13216
|
if (opts.sign !== false) {
|
|
13013
13217
|
const { key: key2, minted } = resolveSigningKey(rootDir);
|
|
@@ -13015,7 +13219,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
13015
13219
|
envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
|
|
13016
13220
|
}
|
|
13017
13221
|
writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
|
|
13018
|
-
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${
|
|
13222
|
+
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path40.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
|
|
13019
13223
|
}
|
|
13020
13224
|
process.exitCode = exposureExit(result.overallStatus);
|
|
13021
13225
|
});
|
|
@@ -13047,7 +13251,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
|
|
|
13047
13251
|
const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
|
|
13048
13252
|
const md = buildPack(result, regime, org, stage);
|
|
13049
13253
|
if (opts.out) {
|
|
13050
|
-
|
|
13254
|
+
fs11.writeFileSync(path40.resolve(rootDir, opts.out), md);
|
|
13051
13255
|
console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
|
|
13052
13256
|
} else {
|
|
13053
13257
|
console.log(md);
|
|
@@ -13089,20 +13293,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
|
|
|
13089
13293
|
}
|
|
13090
13294
|
});
|
|
13091
13295
|
var verifyCmd = new Command("verify").description("Verify an evidence bundle offline (no Vibgrate needed)").argument("<bundle>", "Path to an evidence bundle directory or evidence.intoto.jsonl").option("--pub <file>", "Public key PEM to pin the signer (establish trust)").action((bundlePath, opts) => {
|
|
13092
|
-
const abs =
|
|
13093
|
-
const envPath =
|
|
13094
|
-
if (!
|
|
13095
|
-
const envelope = JSON.parse(
|
|
13096
|
-
const resultPath =
|
|
13097
|
-
const result =
|
|
13098
|
-
const publicKeyPem = opts.pub ?
|
|
13296
|
+
const abs = path40.resolve(bundlePath);
|
|
13297
|
+
const envPath = fs11.statSync(abs).isDirectory() ? path40.join(abs, "evidence.intoto.jsonl") : abs;
|
|
13298
|
+
if (!fs11.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
|
|
13299
|
+
const envelope = JSON.parse(fs11.readFileSync(envPath, "utf8").trim().split("\n")[0]);
|
|
13300
|
+
const resultPath = path40.join(path40.dirname(envPath), "result.json");
|
|
13301
|
+
const result = fs11.existsSync(resultPath) ? JSON.parse(fs11.readFileSync(resultPath, "utf8")) : void 0;
|
|
13302
|
+
const publicKeyPem = opts.pub ? fs11.readFileSync(path40.resolve(opts.pub), "utf8") : void 0;
|
|
13099
13303
|
const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
|
|
13100
13304
|
const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
|
|
13101
13305
|
console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
|
|
13102
13306
|
if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
|
|
13103
|
-
const tsrPath =
|
|
13104
|
-
if (
|
|
13105
|
-
const t = verifyTimestamp(
|
|
13307
|
+
const tsrPath = path40.join(path40.dirname(envPath), "timestamp.tsr");
|
|
13308
|
+
if (fs11.existsSync(tsrPath) && result) {
|
|
13309
|
+
const t = verifyTimestamp(fs11.readFileSync(tsrPath), exposureSubjectDigest(result));
|
|
13106
13310
|
const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
|
|
13107
13311
|
console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
|
|
13108
13312
|
}
|
|
@@ -13169,12 +13373,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
|
|
|
13169
13373
|
const releases = [];
|
|
13170
13374
|
for (const list of releasesByProduct.values()) releases.push(...list);
|
|
13171
13375
|
const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
|
|
13172
|
-
const dir =
|
|
13173
|
-
await writeJsonFile(
|
|
13174
|
-
await writeJsonFile(
|
|
13175
|
-
for (const r of releases) await writeJsonFile(
|
|
13176
|
-
await writeJsonFile(
|
|
13177
|
-
console.error(chalk7.green("\u2714") + ` exported evidence state to ${
|
|
13376
|
+
const dir = path40.resolve(rootDir, opts.out);
|
|
13377
|
+
await writeJsonFile(path40.join(dir, "org.json"), org);
|
|
13378
|
+
await writeJsonFile(path40.join(dir, "products.json"), products);
|
|
13379
|
+
for (const r of releases) await writeJsonFile(path40.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
|
|
13380
|
+
await writeJsonFile(path40.join(dir, "readiness.json"), report);
|
|
13381
|
+
console.error(chalk7.green("\u2714") + ` exported evidence state to ${path40.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
|
|
13178
13382
|
});
|
|
13179
13383
|
var pushCmd = new Command("push").description("Push the product registry (and an optional exposure result) to Vibgrate Cloud").option(...cwdOption).option("--dsn <dsn>", "DSN token (or use VIBGRATE_DSN env / `vg login`)").option("--regime <id>", "Reporting regime").option("--result <file>", "An exposure result.json (or a bundle dir) to include").option("--signed", "Mark the included exposure result as signed").option("--strict", "Fail on push errors").action(async (opts) => {
|
|
13180
13384
|
const rootDir = root(opts);
|
|
@@ -13200,10 +13404,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
|
|
|
13200
13404
|
}));
|
|
13201
13405
|
let exposure;
|
|
13202
13406
|
if (opts.result) {
|
|
13203
|
-
const raw =
|
|
13204
|
-
const resultPath =
|
|
13205
|
-
if (!
|
|
13206
|
-
exposure = JSON.parse(
|
|
13407
|
+
const raw = path40.resolve(rootDir, opts.result);
|
|
13408
|
+
const resultPath = fs11.existsSync(raw) && fs11.statSync(raw).isDirectory() ? path40.join(raw, "result.json") : raw;
|
|
13409
|
+
if (!fs11.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
|
|
13410
|
+
exposure = JSON.parse(fs11.readFileSync(resultPath, "utf8"));
|
|
13207
13411
|
}
|
|
13208
13412
|
const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
|
|
13209
13413
|
const body = JSON.stringify(payload);
|
|
@@ -13397,7 +13601,7 @@ function dispatch(argv, cwd) {
|
|
|
13397
13601
|
}
|
|
13398
13602
|
const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
|
|
13399
13603
|
if (looksLikeQuestion) return ["ask", ...args];
|
|
13400
|
-
if (
|
|
13604
|
+
if (fs11.existsSync(path40.resolve(cwd, first))) {
|
|
13401
13605
|
return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
|
|
13402
13606
|
}
|
|
13403
13607
|
const moved = MOVED_COMMANDS[first];
|
|
@@ -13442,9 +13646,9 @@ async function main(argv = process.argv) {
|
|
|
13442
13646
|
}
|
|
13443
13647
|
function readCwd(raw) {
|
|
13444
13648
|
const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
|
|
13445
|
-
if (i >= 0 && raw[i + 1]) return
|
|
13649
|
+
if (i >= 0 && raw[i + 1]) return path40.resolve(raw[i + 1]);
|
|
13446
13650
|
const eq = raw.find((a) => a.startsWith("--cwd="));
|
|
13447
|
-
if (eq) return
|
|
13651
|
+
if (eq) return path40.resolve(eq.slice("--cwd=".length));
|
|
13448
13652
|
return process.cwd();
|
|
13449
13653
|
}
|
|
13450
13654
|
function handleError(err) {
|