@vibgrate/cli 2026.729.2 → 2026.729.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +5 -1
- package/dist/agent-Z4Z66IGM.js +22 -0
- package/dist/agent-Z4Z66IGM.js.map +1 -0
- package/dist/baseline-Q3QQF5QF.js +9 -0
- package/dist/{baseline-UOTGTJYT.js.map → baseline-Q3QQF5QF.js.map} +1 -1
- package/dist/checkpoint-4WFZMKEO.js +56 -0
- package/dist/checkpoint-4WFZMKEO.js.map +1 -0
- package/dist/{chunk-CYC3ZI32.js → chunk-3FQSBVQD.js} +6 -6
- package/dist/{chunk-CYC3ZI32.js.map → chunk-3FQSBVQD.js.map} +1 -1
- package/dist/{chunk-2ZHWF7C6.js → chunk-42RDYQFF.js} +42 -67
- package/dist/chunk-42RDYQFF.js.map +1 -0
- package/dist/{chunk-HDQG3QYV.js → chunk-4BOWWYSE.js} +32 -17
- package/dist/chunk-4BOWWYSE.js.map +1 -0
- package/dist/chunk-543E6WDJ.js +61 -0
- package/dist/chunk-543E6WDJ.js.map +1 -0
- package/dist/{chunk-JIBOJTGS.js → chunk-5HYCB55P.js} +101 -101
- package/dist/chunk-5HYCB55P.js.map +1 -0
- package/dist/{chunk-QDZ47G45.js → chunk-5MNX3OLS.js} +19 -11
- package/dist/chunk-5MNX3OLS.js.map +1 -0
- package/dist/{chunk-74ZMAOVF.js → chunk-EQ3IOFIG.js} +55 -9
- package/dist/chunk-EQ3IOFIG.js.map +1 -0
- package/dist/{chunk-SIPGDJT4.js → chunk-EVLS2M5G.js} +4 -4
- package/dist/{chunk-SIPGDJT4.js.map → chunk-EVLS2M5G.js.map} +1 -1
- package/dist/{chunk-PXXVLX7K.js → chunk-HWFVBYX4.js} +6 -6
- package/dist/{chunk-PXXVLX7K.js.map → chunk-HWFVBYX4.js.map} +1 -1
- package/dist/{chunk-P3QIO4ZU.js → chunk-JXMZCTVZ.js} +3 -3
- package/dist/{chunk-P3QIO4ZU.js.map → chunk-JXMZCTVZ.js.map} +1 -1
- package/dist/{chunk-VZRQUI54.js → chunk-KBPNH67Q.js} +4 -4
- package/dist/{chunk-VZRQUI54.js.map → chunk-KBPNH67Q.js.map} +1 -1
- package/dist/{chunk-RZEXHDCF.js → chunk-MYM5VIJ4.js} +14 -3
- package/dist/chunk-MYM5VIJ4.js.map +1 -0
- package/dist/chunk-N3HCPBFY.js +6 -0
- package/dist/{chunk-WQE4OIZS.js.map → chunk-N3HCPBFY.js.map} +1 -1
- package/dist/{chunk-PMYWZRRS.js → chunk-RBIRXQR6.js} +21 -3
- package/dist/chunk-RBIRXQR6.js.map +1 -0
- package/dist/{chunk-TCJTQGAO.js → chunk-RGEVBSLK.js} +3 -3
- package/dist/{chunk-TCJTQGAO.js.map → chunk-RGEVBSLK.js.map} +1 -1
- package/dist/{chunk-67YG3R5F.js → chunk-RIEUPFXO.js} +4 -4
- package/dist/{chunk-67YG3R5F.js.map → chunk-RIEUPFXO.js.map} +1 -1
- package/dist/{chunk-PRGCCW7D.js → chunk-WBMMRERH.js} +3 -3
- package/dist/{chunk-PRGCCW7D.js.map → chunk-WBMMRERH.js.map} +1 -1
- package/dist/{chunk-6HX47EBL.js → chunk-X634FZVG.js} +3 -3
- package/dist/{chunk-6HX47EBL.js.map → chunk-X634FZVG.js.map} +1 -1
- package/dist/{chunk-F6ZPUKED.js → chunk-YMSXP6AO.js} +3 -3
- package/dist/{chunk-F6ZPUKED.js.map → chunk-YMSXP6AO.js.map} +1 -1
- package/dist/cli.js +713 -373
- package/dist/cli.js.map +1 -1
- package/dist/{graph-backend-GBL33GMW.js → graph-backend-G5Y6QQV4.js} +4 -4
- package/dist/{graph-backend-GBL33GMW.js.map → graph-backend-G5Y6QQV4.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -8
- package/dist/{interactive-HLGJJFLI.js → interactive-MJVMY5JP.js} +23 -22
- package/dist/interactive-MJVMY5JP.js.map +1 -0
- package/dist/{llm-host-5RE34322.js → llm-host-DZBD5D36.js} +5 -5
- package/dist/{llm-host-5RE34322.js.map → llm-host-DZBD5D36.js.map} +1 -1
- package/dist/load-4PARCNMD.js +9 -0
- package/dist/{load-4MLIHGXF.js.map → load-4PARCNMD.js.map} +1 -1
- package/dist/rules-ASYEUNB5.js +74 -0
- package/dist/rules-ASYEUNB5.js.map +1 -0
- package/dist/runtime-session-AILFASQV.js +19 -0
- package/dist/{runtime-session-5M6QZZOS.js.map → runtime-session-AILFASQV.js.map} +1 -1
- package/dist/{session-2JT4AUZT.js → session-3OBIQLE4.js} +5 -5
- package/dist/{session-2JT4AUZT.js.map → session-3OBIQLE4.js.map} +1 -1
- package/dist/{stream-json-Y45JBNYP.js → stream-json-MTPWWVRR.js} +81 -9
- package/dist/stream-json-MTPWWVRR.js.map +1 -0
- package/dist/{vg-mcp-bridge-ZCKBYQ2D.js → vg-mcp-bridge-BLHEIWMT.js} +6 -6
- package/dist/{vg-mcp-bridge-ZCKBYQ2D.js.map → vg-mcp-bridge-BLHEIWMT.js.map} +1 -1
- package/dist/{vgd-TGGEAGQZ.js → vgd-S7D2SITC.js} +8 -8
- package/dist/vgd-S7D2SITC.js.map +1 -0
- package/package.json +1 -1
- package/dist/baseline-UOTGTJYT.js +0 -9
- package/dist/chunk-2ZHWF7C6.js.map +0 -1
- package/dist/chunk-74ZMAOVF.js.map +0 -1
- package/dist/chunk-HDQG3QYV.js.map +0 -1
- package/dist/chunk-JIBOJTGS.js.map +0 -1
- package/dist/chunk-PMYWZRRS.js.map +0 -1
- package/dist/chunk-QDZ47G45.js.map +0 -1
- package/dist/chunk-RZEXHDCF.js.map +0 -1
- package/dist/chunk-WQE4OIZS.js +0 -6
- package/dist/interactive-HLGJJFLI.js.map +0 -1
- package/dist/load-4MLIHGXF.js +0 -9
- package/dist/runtime-session-5M6QZZOS.js +0 -19
- package/dist/stream-json-Y45JBNYP.js.map +0 -1
- package/dist/vgd-TGGEAGQZ.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-
|
|
3
|
-
export { runBuild } from './chunk-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { runCodeSession } from './chunk-
|
|
7
|
-
import { summarizeDiffs, ScriptedProvider } from './chunk-RZEXHDCF.js';
|
|
2
|
+
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-5MNX3OLS.js';
|
|
3
|
+
export { runBuild } from './chunk-5MNX3OLS.js';
|
|
4
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-YMSXP6AO.js';
|
|
5
|
+
import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
|
|
6
|
+
import { runCodeSession } from './chunk-WBMMRERH.js';
|
|
8
7
|
import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
|
|
9
|
-
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-
|
|
8
|
+
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-EQ3IOFIG.js';
|
|
10
9
|
import './chunk-5I4VSBWQ.js';
|
|
11
10
|
import './chunk-IS7VTH2Q.js';
|
|
12
11
|
import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
|
|
13
12
|
import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
|
|
14
13
|
import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
|
|
15
14
|
import './chunk-IZDH67DX.js';
|
|
16
|
-
import './chunk-
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import './chunk-7AVYKZEM.js';
|
|
22
|
-
import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
|
|
15
|
+
import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-EVLS2M5G.js';
|
|
16
|
+
import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-X634FZVG.js';
|
|
17
|
+
import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-42RDYQFF.js';
|
|
18
|
+
import './chunk-543E6WDJ.js';
|
|
19
|
+
import { summarizeDiffs, ScriptedProvider } from './chunk-MYM5VIJ4.js';
|
|
23
20
|
import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
21
|
+
import './chunk-RGEVBSLK.js';
|
|
22
|
+
import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
|
|
23
|
+
import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
|
|
24
|
+
import './chunk-7AVYKZEM.js';
|
|
25
|
+
import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-HWFVBYX4.js';
|
|
26
|
+
import { CliError, ExitCode, refreshIfStale, driftCount, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, SKIP_DIRS, SKIP_FILES } from './chunk-3FQSBVQD.js';
|
|
27
|
+
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-RIEUPFXO.js';
|
|
28
|
+
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 } from './chunk-4BOWWYSE.js';
|
|
29
|
+
import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
|
|
27
30
|
import './chunk-IPICO2RV.js';
|
|
28
31
|
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-G4HTI4ZM.js';
|
|
29
|
-
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 } from './chunk-HDQG3QYV.js';
|
|
30
32
|
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-US2DAKCM.js';
|
|
31
|
-
import {
|
|
33
|
+
import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
|
|
32
34
|
import { resolveOne } from './chunk-J7LKEB2R.js';
|
|
33
35
|
import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-EETK7S43.js';
|
|
34
36
|
import { discoverModels } from './chunk-CQDUBAQY.js';
|
|
35
|
-
import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
|
|
36
37
|
import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
|
|
37
38
|
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
|
|
38
39
|
import './chunk-RXP66R2E.js';
|
|
39
|
-
import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-
|
|
40
|
-
import { VERSION } from './chunk-
|
|
40
|
+
import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-JXMZCTVZ.js';
|
|
41
|
+
import { VERSION } from './chunk-N3HCPBFY.js';
|
|
41
42
|
import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
|
|
42
43
|
import './chunk-BWPBB45M.js';
|
|
43
44
|
import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
|
|
44
45
|
import './chunk-BPF3YX2U.js';
|
|
45
46
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
|
|
46
47
|
import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
|
|
47
|
-
import * as
|
|
48
|
-
import
|
|
49
|
-
import * as
|
|
50
|
-
import
|
|
48
|
+
import * as fs8 from 'fs';
|
|
49
|
+
import fs8__default, { realpathSync } from 'fs';
|
|
50
|
+
import * as path38 from 'path';
|
|
51
|
+
import path38__default from 'path';
|
|
51
52
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
52
53
|
import { Command, CommanderError, Option } from 'commander';
|
|
53
54
|
import * as os from 'os';
|
|
@@ -58,7 +59,7 @@ import semver3__default from 'semver';
|
|
|
58
59
|
import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
|
|
59
60
|
import * as readline from 'readline';
|
|
60
61
|
import chalk7 from 'chalk';
|
|
61
|
-
import * as
|
|
62
|
+
import * as fs22 from 'fs/promises';
|
|
62
63
|
|
|
63
64
|
init_cli_invocation();
|
|
64
65
|
function registerStatus(program) {
|
|
@@ -68,10 +69,10 @@ function registerStatus(program) {
|
|
|
68
69
|
applyGlobalOptions(cmd);
|
|
69
70
|
}
|
|
70
71
|
async function runStatus(global) {
|
|
71
|
-
const root2 =
|
|
72
|
+
const root2 = path38.resolve(global.cwd ?? ".");
|
|
72
73
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
73
74
|
const graph = loadGraph(root2, graphPath);
|
|
74
|
-
const hasCache =
|
|
75
|
+
const hasCache = fs8.existsSync(path38.join(cacheDir(root2), "parse-cache.json"));
|
|
75
76
|
let stale = null;
|
|
76
77
|
let staleExact = false;
|
|
77
78
|
if (graph) {
|
|
@@ -91,8 +92,8 @@ async function runStatus(global) {
|
|
|
91
92
|
}
|
|
92
93
|
if (global.json) {
|
|
93
94
|
json({
|
|
94
|
-
root:
|
|
95
|
-
graphPath:
|
|
95
|
+
root: path38.relative(process.cwd(), root2) || ".",
|
|
96
|
+
graphPath: path38.relative(root2, graphPath),
|
|
96
97
|
built: graph !== null,
|
|
97
98
|
generatedAt: graph?.generatedAt ?? null,
|
|
98
99
|
counts: graph?.meta.counts ?? null,
|
|
@@ -107,11 +108,11 @@ async function runStatus(global) {
|
|
|
107
108
|
return;
|
|
108
109
|
}
|
|
109
110
|
if (!graph) {
|
|
110
|
-
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(
|
|
111
|
+
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path38.relative(root2, graphPath))}`);
|
|
111
112
|
info(` run ${c.bold("vg")} to build one`);
|
|
112
113
|
return;
|
|
113
114
|
}
|
|
114
|
-
info(`${c.cyan("vg")} \xB7 ${
|
|
115
|
+
info(`${c.cyan("vg")} \xB7 ${path38.relative(root2, graphPath)}`);
|
|
115
116
|
info(` generated ${graph.generatedAt}`);
|
|
116
117
|
info(
|
|
117
118
|
` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
|
|
@@ -128,7 +129,7 @@ async function runStatus(global) {
|
|
|
128
129
|
if (vibgrateDir(root2)) ;
|
|
129
130
|
}
|
|
130
131
|
function rootOf(global) {
|
|
131
|
-
return
|
|
132
|
+
return path38.resolve(global.cwd ?? ".");
|
|
132
133
|
}
|
|
133
134
|
function requireGraph(global) {
|
|
134
135
|
const root2 = rootOf(global);
|
|
@@ -839,8 +840,8 @@ function pad2(s, n) {
|
|
|
839
840
|
}
|
|
840
841
|
var SCHEMA_VERSION2 = "1";
|
|
841
842
|
var OFFSET_FILE = "stats-share.json";
|
|
842
|
-
var INSTALL_ID_DIR =
|
|
843
|
-
var INSTALL_ID_FILE =
|
|
843
|
+
var INSTALL_ID_DIR = path38.join(os.homedir(), ".vibgrate");
|
|
844
|
+
var INSTALL_ID_FILE = path38.join(INSTALL_ID_DIR, "install-id");
|
|
844
845
|
var SEND_TIMEOUT_MS = 4e3;
|
|
845
846
|
function telemetryOptOut(env = process.env) {
|
|
846
847
|
const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
|
|
@@ -868,14 +869,14 @@ function isCI(env = process.env) {
|
|
|
868
869
|
function installId(env = process.env) {
|
|
869
870
|
if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
|
|
870
871
|
try {
|
|
871
|
-
const existing =
|
|
872
|
+
const existing = fs8.readFileSync(INSTALL_ID_FILE, "utf8").trim();
|
|
872
873
|
if (isUuid(existing)) return existing;
|
|
873
874
|
} catch {
|
|
874
875
|
}
|
|
875
876
|
const id = randomUuid();
|
|
876
877
|
try {
|
|
877
|
-
|
|
878
|
-
|
|
878
|
+
fs8.mkdirSync(INSTALL_ID_DIR, { recursive: true });
|
|
879
|
+
fs8.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
|
|
879
880
|
} catch {
|
|
880
881
|
}
|
|
881
882
|
return id;
|
|
@@ -892,14 +893,14 @@ function statsEndpoint() {
|
|
|
892
893
|
return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
|
|
893
894
|
}
|
|
894
895
|
function offsetPath(root2) {
|
|
895
|
-
return
|
|
896
|
+
return path38.join(cacheDir(root2), OFFSET_FILE);
|
|
896
897
|
}
|
|
897
898
|
function ledgerFilePath(root2) {
|
|
898
|
-
return
|
|
899
|
+
return path38.join(cacheDir(root2), "savings.jsonl");
|
|
899
900
|
}
|
|
900
901
|
function readOffset(root2) {
|
|
901
902
|
try {
|
|
902
|
-
const raw = JSON.parse(
|
|
903
|
+
const raw = JSON.parse(fs8.readFileSync(offsetPath(root2), "utf8"));
|
|
903
904
|
return typeof raw.offset === "number" && raw.offset >= 0 ? raw.offset : 0;
|
|
904
905
|
} catch {
|
|
905
906
|
return 0;
|
|
@@ -907,8 +908,8 @@ function readOffset(root2) {
|
|
|
907
908
|
}
|
|
908
909
|
function writeOffset(root2, offset) {
|
|
909
910
|
try {
|
|
910
|
-
|
|
911
|
-
|
|
911
|
+
fs8.mkdirSync(cacheDir(root2), { recursive: true });
|
|
912
|
+
fs8.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
|
|
912
913
|
} catch {
|
|
913
914
|
}
|
|
914
915
|
}
|
|
@@ -916,7 +917,7 @@ function buildBatch(root2, fromOffset, id = installId()) {
|
|
|
916
917
|
const file = ledgerFilePath(root2);
|
|
917
918
|
let size = 0;
|
|
918
919
|
try {
|
|
919
|
-
size =
|
|
920
|
+
size = fs8.statSync(file).size;
|
|
920
921
|
} catch {
|
|
921
922
|
return { batch: null, newOffset: 0 };
|
|
922
923
|
}
|
|
@@ -924,13 +925,13 @@ function buildBatch(root2, fromOffset, id = installId()) {
|
|
|
924
925
|
if (start >= size) return { batch: null, newOffset: size };
|
|
925
926
|
let text = "";
|
|
926
927
|
try {
|
|
927
|
-
const fd =
|
|
928
|
+
const fd = fs8.openSync(file, "r");
|
|
928
929
|
try {
|
|
929
930
|
const buf = Buffer.alloc(size - start);
|
|
930
|
-
|
|
931
|
+
fs8.readSync(fd, buf, 0, buf.length, start);
|
|
931
932
|
text = buf.toString("utf8");
|
|
932
933
|
} finally {
|
|
933
|
-
|
|
934
|
+
fs8.closeSync(fd);
|
|
934
935
|
}
|
|
935
936
|
} catch {
|
|
936
937
|
return { batch: null, newOffset: fromOffset };
|
|
@@ -1066,12 +1067,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
|
|
|
1066
1067
|
var KEEPALIVE_MS = 1e4;
|
|
1067
1068
|
var STALE_MS = 6e4;
|
|
1068
1069
|
function liveStatsDir(root2) {
|
|
1069
|
-
return
|
|
1070
|
+
return path38.join(cacheDir(root2), "serve-live");
|
|
1070
1071
|
}
|
|
1071
1072
|
function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
|
|
1072
1073
|
let entries;
|
|
1073
1074
|
try {
|
|
1074
|
-
entries =
|
|
1075
|
+
entries = fs8.readdirSync(dir);
|
|
1075
1076
|
} catch {
|
|
1076
1077
|
return [];
|
|
1077
1078
|
}
|
|
@@ -1080,7 +1081,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
|
|
|
1080
1081
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1081
1082
|
let parsed;
|
|
1082
1083
|
try {
|
|
1083
|
-
parsed = JSON.parse(
|
|
1084
|
+
parsed = JSON.parse(fs8.readFileSync(path38.join(dir, name), "utf8"));
|
|
1084
1085
|
} catch {
|
|
1085
1086
|
continue;
|
|
1086
1087
|
}
|
|
@@ -1102,7 +1103,7 @@ var LiveStatsBus = class {
|
|
|
1102
1103
|
this.dir = dir;
|
|
1103
1104
|
this.stats = stats;
|
|
1104
1105
|
this.pid = pid;
|
|
1105
|
-
this.file =
|
|
1106
|
+
this.file = path38.join(dir, `serve-${this.pid}.json`);
|
|
1106
1107
|
}
|
|
1107
1108
|
dir;
|
|
1108
1109
|
stats;
|
|
@@ -1134,10 +1135,10 @@ var LiveStatsBus = class {
|
|
|
1134
1135
|
this.lastWriteAt = now;
|
|
1135
1136
|
const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
|
|
1136
1137
|
try {
|
|
1137
|
-
|
|
1138
|
+
fs8.mkdirSync(this.dir, { recursive: true });
|
|
1138
1139
|
const tmp = `${this.file}.tmp`;
|
|
1139
|
-
|
|
1140
|
-
|
|
1140
|
+
fs8.writeFileSync(tmp, JSON.stringify(body));
|
|
1141
|
+
fs8.renameSync(tmp, this.file);
|
|
1141
1142
|
} catch {
|
|
1142
1143
|
}
|
|
1143
1144
|
}
|
|
@@ -1148,24 +1149,24 @@ var LiveStatsBus = class {
|
|
|
1148
1149
|
siblings(now = Date.now()) {
|
|
1149
1150
|
let entries;
|
|
1150
1151
|
try {
|
|
1151
|
-
entries =
|
|
1152
|
+
entries = fs8.readdirSync(this.dir);
|
|
1152
1153
|
} catch {
|
|
1153
1154
|
return [];
|
|
1154
1155
|
}
|
|
1155
1156
|
const out2 = [];
|
|
1156
1157
|
for (const name of entries.sort()) {
|
|
1157
1158
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1158
|
-
const file =
|
|
1159
|
+
const file = path38.join(this.dir, name);
|
|
1159
1160
|
let parsed;
|
|
1160
1161
|
try {
|
|
1161
|
-
parsed = JSON.parse(
|
|
1162
|
+
parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
|
|
1162
1163
|
} catch {
|
|
1163
1164
|
continue;
|
|
1164
1165
|
}
|
|
1165
1166
|
if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
|
|
1166
1167
|
if (now - parsed.updatedAt > STALE_MS) {
|
|
1167
1168
|
try {
|
|
1168
|
-
|
|
1169
|
+
fs8.unlinkSync(file);
|
|
1169
1170
|
} catch {
|
|
1170
1171
|
}
|
|
1171
1172
|
continue;
|
|
@@ -1177,7 +1178,7 @@ var LiveStatsBus = class {
|
|
|
1177
1178
|
}
|
|
1178
1179
|
unlinkOwn = () => {
|
|
1179
1180
|
try {
|
|
1180
|
-
|
|
1181
|
+
fs8.unlinkSync(this.file);
|
|
1181
1182
|
} catch {
|
|
1182
1183
|
}
|
|
1183
1184
|
};
|
|
@@ -1490,12 +1491,12 @@ var LedgerTail = class {
|
|
|
1490
1491
|
if (size === this.offset) return;
|
|
1491
1492
|
let chunk;
|
|
1492
1493
|
try {
|
|
1493
|
-
const fd =
|
|
1494
|
+
const fd = fs8.openSync(this.file, "r");
|
|
1494
1495
|
try {
|
|
1495
1496
|
chunk = Buffer.alloc(size - this.offset);
|
|
1496
|
-
|
|
1497
|
+
fs8.readSync(fd, chunk, 0, chunk.length, this.offset);
|
|
1497
1498
|
} finally {
|
|
1498
|
-
|
|
1499
|
+
fs8.closeSync(fd);
|
|
1499
1500
|
}
|
|
1500
1501
|
} catch {
|
|
1501
1502
|
return;
|
|
@@ -1508,7 +1509,7 @@ var LedgerTail = class {
|
|
|
1508
1509
|
}
|
|
1509
1510
|
sizeOf() {
|
|
1510
1511
|
try {
|
|
1511
|
-
return
|
|
1512
|
+
return fs8.statSync(this.file).size;
|
|
1512
1513
|
} catch {
|
|
1513
1514
|
return 0;
|
|
1514
1515
|
}
|
|
@@ -1893,19 +1894,19 @@ function endOfLine(text, line) {
|
|
|
1893
1894
|
}
|
|
1894
1895
|
var CACHE_VERSION = "vg-lsp-scan-cache/2";
|
|
1895
1896
|
function cachePath(root2) {
|
|
1896
|
-
return
|
|
1897
|
+
return path38.join(cacheDir(root2), "lsp-scan.json");
|
|
1897
1898
|
}
|
|
1898
1899
|
function manifestHash(root2) {
|
|
1899
1900
|
const files = [];
|
|
1900
1901
|
const walk2 = (dir) => {
|
|
1901
1902
|
let entries;
|
|
1902
1903
|
try {
|
|
1903
|
-
entries =
|
|
1904
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
1904
1905
|
} catch {
|
|
1905
1906
|
return;
|
|
1906
1907
|
}
|
|
1907
1908
|
for (const entry of entries) {
|
|
1908
|
-
const abs =
|
|
1909
|
+
const abs = path38.join(dir, entry.name);
|
|
1909
1910
|
if (entry.isDirectory()) {
|
|
1910
1911
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
1911
1912
|
walk2(abs);
|
|
@@ -1915,8 +1916,8 @@ function manifestHash(root2) {
|
|
|
1915
1916
|
const base = entry.name.toLowerCase();
|
|
1916
1917
|
if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
|
|
1917
1918
|
try {
|
|
1918
|
-
const rel =
|
|
1919
|
-
files.push({ rel, hash: hashBytes(
|
|
1919
|
+
const rel = path38.relative(root2, abs).split(path38.sep).join("/");
|
|
1920
|
+
files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
|
|
1920
1921
|
} catch {
|
|
1921
1922
|
}
|
|
1922
1923
|
}
|
|
@@ -1926,16 +1927,16 @@ function manifestHash(root2) {
|
|
|
1926
1927
|
return hashString(canonicalize(files));
|
|
1927
1928
|
}
|
|
1928
1929
|
function isDependencyFile(root2, filePath) {
|
|
1929
|
-
const rel =
|
|
1930
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
1931
|
-
const parts = rel.split(
|
|
1930
|
+
const rel = path38.relative(path38.resolve(root2), path38.resolve(filePath));
|
|
1931
|
+
if (rel === "" || rel.startsWith("..") || path38.isAbsolute(rel)) return false;
|
|
1932
|
+
const parts = rel.split(path38.sep);
|
|
1932
1933
|
if (parts.slice(0, -1).some((dir) => SKIP_DIRS.has(dir))) return false;
|
|
1933
1934
|
const base = parts[parts.length - 1].toLowerCase();
|
|
1934
1935
|
return isManifest(filePath) || SKIP_FILES.has(base);
|
|
1935
1936
|
}
|
|
1936
1937
|
function loadScanCache(root2, key2) {
|
|
1937
1938
|
try {
|
|
1938
|
-
const raw = JSON.parse(
|
|
1939
|
+
const raw = JSON.parse(fs8.readFileSync(cachePath(root2), "utf8"));
|
|
1939
1940
|
if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
|
|
1940
1941
|
return { manifestHash: raw.manifestHash, artifact: raw.artifact };
|
|
1941
1942
|
}
|
|
@@ -1945,8 +1946,8 @@ function loadScanCache(root2, key2) {
|
|
|
1945
1946
|
}
|
|
1946
1947
|
function writeScanCache(root2, key2, artifact) {
|
|
1947
1948
|
try {
|
|
1948
|
-
|
|
1949
|
-
|
|
1949
|
+
fs8.mkdirSync(cacheDir(root2), { recursive: true });
|
|
1950
|
+
fs8.writeFileSync(
|
|
1950
1951
|
cachePath(root2),
|
|
1951
1952
|
stableStringify(
|
|
1952
1953
|
{ version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
|
|
@@ -1956,6 +1957,66 @@ function writeScanCache(root2, key2, artifact) {
|
|
|
1956
1957
|
} catch {
|
|
1957
1958
|
}
|
|
1958
1959
|
}
|
|
1960
|
+
var MAX_ENTRIES = 1e3;
|
|
1961
|
+
var KEEP_ENTRIES = 500;
|
|
1962
|
+
function historyPath(root2) {
|
|
1963
|
+
return path38.join(root2, ".vibgrate", "score-history.jsonl");
|
|
1964
|
+
}
|
|
1965
|
+
function parseLine(line) {
|
|
1966
|
+
try {
|
|
1967
|
+
const e = JSON.parse(line);
|
|
1968
|
+
if (typeof e.ts === "string" && typeof e.score === "number" && typeof e.band === "string" && (e.mode === "verified" || e.mode === "estimated") && typeof e.methodology === "string") {
|
|
1969
|
+
return e;
|
|
1970
|
+
}
|
|
1971
|
+
} catch {
|
|
1972
|
+
}
|
|
1973
|
+
return null;
|
|
1974
|
+
}
|
|
1975
|
+
function readHistory(root2) {
|
|
1976
|
+
try {
|
|
1977
|
+
return fs8.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
|
|
1978
|
+
} catch {
|
|
1979
|
+
return [];
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
function lastEntry(root2) {
|
|
1983
|
+
const all = readHistory(root2);
|
|
1984
|
+
return all.length ? all[all.length - 1] : null;
|
|
1985
|
+
}
|
|
1986
|
+
function recentHistory(root2, days, now = Date.now()) {
|
|
1987
|
+
const cutoff = now - days * 24 * 60 * 60 * 1e3;
|
|
1988
|
+
return readHistory(root2).filter((e) => {
|
|
1989
|
+
const t = Date.parse(e.ts);
|
|
1990
|
+
return Number.isFinite(t) && t >= cutoff;
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
function recordScore(root2, entry) {
|
|
1994
|
+
try {
|
|
1995
|
+
const prev = lastEntry(root2);
|
|
1996
|
+
if (prev && prev.score === entry.score && prev.band === entry.band && prev.mode === entry.mode && prev.methodology === entry.methodology) {
|
|
1997
|
+
const prevT = Date.parse(prev.ts);
|
|
1998
|
+
const nextT = Date.parse(entry.ts);
|
|
1999
|
+
if (Number.isFinite(prevT) && Number.isFinite(nextT) && nextT - prevT < 24 * 60 * 60 * 1e3) {
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
const file = historyPath(root2);
|
|
2004
|
+
fs8.mkdirSync(path38.dirname(file), { recursive: true });
|
|
2005
|
+
fs8.appendFileSync(file, `${JSON.stringify(entry)}
|
|
2006
|
+
`);
|
|
2007
|
+
const all = readHistory(root2);
|
|
2008
|
+
if (all.length > MAX_ENTRIES) {
|
|
2009
|
+
const kept = all.slice(-KEEP_ENTRIES);
|
|
2010
|
+
fs8.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
2011
|
+
}
|
|
2012
|
+
} catch {
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
function deltaFrom(prev, current) {
|
|
2016
|
+
if (!prev) return void 0;
|
|
2017
|
+
if (prev.methodology !== current.methodology) return void 0;
|
|
2018
|
+
return current.score - prev.score;
|
|
2019
|
+
}
|
|
1959
2020
|
|
|
1960
2021
|
// src/lsp/graph-query.ts
|
|
1961
2022
|
async function runGraphQuery(graph, params, ctx) {
|
|
@@ -2467,6 +2528,11 @@ var VibgrateLanguageServer = class {
|
|
|
2467
2528
|
this.conn.onRequest("textDocument/codeLens", (_m, params) => this.onCodeLens(params));
|
|
2468
2529
|
this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
|
|
2469
2530
|
this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
|
|
2531
|
+
this.conn.onRequest("vibgrate/score/history", (_m, params) => {
|
|
2532
|
+
const p = params;
|
|
2533
|
+
const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
|
|
2534
|
+
return { days, entries: recentHistory(this.opts.root, days) };
|
|
2535
|
+
});
|
|
2470
2536
|
this.conn.onRequest("vibgrate/enrich", (_m, params) => this.onEnrich(params));
|
|
2471
2537
|
this.conn.onRequest("vibgrate/vulns", (_m, _params) => this.onVulns());
|
|
2472
2538
|
this.conn.onRequest("workspace/executeCommand", (_m, params) => {
|
|
@@ -2555,6 +2621,15 @@ var VibgrateLanguageServer = class {
|
|
|
2555
2621
|
(f) => f.ruleId === "vibgrate/unmaintained" || f.ruleId === "vibgrate/abandoned"
|
|
2556
2622
|
).length;
|
|
2557
2623
|
const band = a.drift.riskLevel ?? "low";
|
|
2624
|
+
const historyEntry = {
|
|
2625
|
+
ts: a.timestamp,
|
|
2626
|
+
score: a.drift.score,
|
|
2627
|
+
band,
|
|
2628
|
+
mode: a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated"),
|
|
2629
|
+
methodology: a.drift.methodologyVersion ?? "unknown"
|
|
2630
|
+
};
|
|
2631
|
+
const delta = deltaFrom(lastEntry(this.opts.root), historyEntry);
|
|
2632
|
+
recordScore(this.opts.root, historyEntry);
|
|
2558
2633
|
const payload = {
|
|
2559
2634
|
score: a.drift.score,
|
|
2560
2635
|
band,
|
|
@@ -2562,12 +2637,13 @@ var VibgrateLanguageServer = class {
|
|
|
2562
2637
|
// offline marker. An air-gapped scan against a dated snapshot is Verified.
|
|
2563
2638
|
// The score now carries the authoritative provenance (driftscore-3.0
|
|
2564
2639
|
// envelope); fall back to the artifact heuristic for pre-v3 engines.
|
|
2565
|
-
mode:
|
|
2566
|
-
methodology:
|
|
2640
|
+
mode: historyEntry.mode,
|
|
2641
|
+
methodology: historyEntry.methodology,
|
|
2567
2642
|
scale: "0 best, 100 worst",
|
|
2568
2643
|
counts: { behind, eol, unmaintained, total },
|
|
2569
2644
|
rootPath: a.rootPath,
|
|
2570
2645
|
scannedAt: a.timestamp,
|
|
2646
|
+
...delta !== void 0 ? { delta } : {},
|
|
2571
2647
|
...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {}
|
|
2572
2648
|
};
|
|
2573
2649
|
this.conn.notify("vibgrate/score", payload);
|
|
@@ -2757,10 +2833,10 @@ var VibgrateLanguageServer = class {
|
|
|
2757
2833
|
const ecosystem = osvEcosystem(proj.type);
|
|
2758
2834
|
if (!ecosystem) continue;
|
|
2759
2835
|
const relManifest = manifestRelativePath(proj);
|
|
2760
|
-
const absManifest =
|
|
2836
|
+
const absManifest = path38.resolve(this.opts.root, relManifest);
|
|
2761
2837
|
let text = null;
|
|
2762
2838
|
try {
|
|
2763
|
-
if (
|
|
2839
|
+
if (fs8.existsSync(absManifest)) text = fs8.readFileSync(absManifest, "utf8");
|
|
2764
2840
|
} catch {
|
|
2765
2841
|
text = null;
|
|
2766
2842
|
}
|
|
@@ -2806,12 +2882,12 @@ function uriToPath(uri) {
|
|
|
2806
2882
|
}
|
|
2807
2883
|
}
|
|
2808
2884
|
function projectForFile(root2, a, filePath) {
|
|
2809
|
-
const dir =
|
|
2885
|
+
const dir = path38.dirname(path38.resolve(filePath));
|
|
2810
2886
|
let best;
|
|
2811
2887
|
let bestLen = -1;
|
|
2812
2888
|
for (const proj of a.projects ?? []) {
|
|
2813
|
-
const projDir =
|
|
2814
|
-
if ((dir === projDir || dir.startsWith(projDir +
|
|
2889
|
+
const projDir = path38.resolve(root2, proj.path);
|
|
2890
|
+
if ((dir === projDir || dir.startsWith(projDir + path38.sep)) && projDir.length > bestLen) {
|
|
2815
2891
|
best = proj;
|
|
2816
2892
|
bestLen = projDir.length;
|
|
2817
2893
|
}
|
|
@@ -2819,7 +2895,7 @@ function projectForFile(root2, a, filePath) {
|
|
|
2819
2895
|
return best;
|
|
2820
2896
|
}
|
|
2821
2897
|
function sameProject(location, projectPath) {
|
|
2822
|
-
return
|
|
2898
|
+
return path38.normalize(location) === path38.normalize(projectPath);
|
|
2823
2899
|
}
|
|
2824
2900
|
function hasReleaseDates(a) {
|
|
2825
2901
|
for (const proj of a.projects ?? []) {
|
|
@@ -2892,34 +2968,34 @@ function buildBreakdown(drift, projects) {
|
|
|
2892
2968
|
}
|
|
2893
2969
|
function manifestRelativePath(proj) {
|
|
2894
2970
|
const base = proj.path === "." || proj.path === "" ? "" : proj.path;
|
|
2895
|
-
const
|
|
2971
|
+
const join28 = (name) => base ? path38.join(base, name) : name;
|
|
2896
2972
|
switch (proj.type) {
|
|
2897
2973
|
case "node":
|
|
2898
2974
|
case "typescript":
|
|
2899
|
-
return
|
|
2975
|
+
return join28("package.json");
|
|
2900
2976
|
case "python":
|
|
2901
|
-
return
|
|
2977
|
+
return join28("pyproject.toml");
|
|
2902
2978
|
case "go":
|
|
2903
|
-
return
|
|
2979
|
+
return join28("go.mod");
|
|
2904
2980
|
case "rust":
|
|
2905
|
-
return
|
|
2981
|
+
return join28("Cargo.toml");
|
|
2906
2982
|
case "ruby":
|
|
2907
|
-
return
|
|
2983
|
+
return join28("Gemfile");
|
|
2908
2984
|
case "php":
|
|
2909
|
-
return
|
|
2985
|
+
return join28("composer.json");
|
|
2910
2986
|
case "java":
|
|
2911
2987
|
case "kotlin":
|
|
2912
2988
|
case "scala":
|
|
2913
2989
|
case "groovy":
|
|
2914
|
-
return
|
|
2990
|
+
return join28("pom.xml");
|
|
2915
2991
|
case "dotnet":
|
|
2916
|
-
return
|
|
2992
|
+
return join28(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
|
|
2917
2993
|
case "dart":
|
|
2918
|
-
return
|
|
2994
|
+
return join28("pubspec.yaml");
|
|
2919
2995
|
case "elixir":
|
|
2920
|
-
return
|
|
2996
|
+
return join28("mix.exs");
|
|
2921
2997
|
default:
|
|
2922
|
-
return
|
|
2998
|
+
return join28("package.json");
|
|
2923
2999
|
}
|
|
2924
3000
|
}
|
|
2925
3001
|
function packageReachSet(graph) {
|
|
@@ -3079,7 +3155,7 @@ function hoverMarkdown(dep, contribution) {
|
|
|
3079
3155
|
return lines.join("\n");
|
|
3080
3156
|
}
|
|
3081
3157
|
function startLanguageServer(opts) {
|
|
3082
|
-
if (!
|
|
3158
|
+
if (!fs8.existsSync(opts.root)) {
|
|
3083
3159
|
process.stderr.write(`vg lsp: root does not exist: ${opts.root}
|
|
3084
3160
|
`);
|
|
3085
3161
|
process.exit(1);
|
|
@@ -3216,8 +3292,8 @@ function registerShare(program) {
|
|
|
3216
3292
|
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) {
|
|
3217
3293
|
const global = readGlobal(this);
|
|
3218
3294
|
const root2 = rootOf(global);
|
|
3219
|
-
const gitDir =
|
|
3220
|
-
if (!
|
|
3295
|
+
const gitDir = path38.join(root2, ".git");
|
|
3296
|
+
if (!fs8.existsSync(gitDir)) {
|
|
3221
3297
|
throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
|
|
3222
3298
|
}
|
|
3223
3299
|
if (opts.undo) {
|
|
@@ -3238,23 +3314,23 @@ function registerShare(program) {
|
|
|
3238
3314
|
applyGlobalOptions(cmd);
|
|
3239
3315
|
}
|
|
3240
3316
|
function writeVibgrateGitignore(root2, reports) {
|
|
3241
|
-
const dir =
|
|
3242
|
-
|
|
3317
|
+
const dir = path38.join(root2, ".vibgrate");
|
|
3318
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
3243
3319
|
const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
|
|
3244
3320
|
if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
|
|
3245
|
-
|
|
3321
|
+
fs8.writeFileSync(path38.join(dir, ".gitignore"), `${lines.join("\n")}
|
|
3246
3322
|
`);
|
|
3247
3323
|
}
|
|
3248
3324
|
function writeGitAttributes(root2) {
|
|
3249
|
-
const file =
|
|
3325
|
+
const file = path38.join(root2, ".gitattributes");
|
|
3250
3326
|
const line = ".vibgrate/graph.json merge=vg";
|
|
3251
|
-
let content =
|
|
3327
|
+
let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
|
|
3252
3328
|
if (!content.split("\n").some((l) => l.trim() === line)) {
|
|
3253
3329
|
content = content.length ? `${content.replace(/\s*$/, "")}
|
|
3254
3330
|
${line}
|
|
3255
3331
|
` : `${line}
|
|
3256
3332
|
`;
|
|
3257
|
-
|
|
3333
|
+
fs8.writeFileSync(file, content);
|
|
3258
3334
|
}
|
|
3259
3335
|
}
|
|
3260
3336
|
function configureMergeDriver(root2) {
|
|
@@ -3263,8 +3339,8 @@ function configureMergeDriver(root2) {
|
|
|
3263
3339
|
}
|
|
3264
3340
|
function installPreCommitHook(root2) {
|
|
3265
3341
|
const hooksDir = hookDir(root2);
|
|
3266
|
-
|
|
3267
|
-
const file =
|
|
3342
|
+
fs8.mkdirSync(hooksDir, { recursive: true });
|
|
3343
|
+
const file = path38.join(hooksDir, "pre-commit");
|
|
3268
3344
|
const block = [
|
|
3269
3345
|
HOOK_BEGIN,
|
|
3270
3346
|
"if command -v vg >/dev/null 2>&1; then",
|
|
@@ -3273,7 +3349,7 @@ function installPreCommitHook(root2) {
|
|
|
3273
3349
|
"fi",
|
|
3274
3350
|
HOOK_END
|
|
3275
3351
|
].join("\n");
|
|
3276
|
-
let content =
|
|
3352
|
+
let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "#!/bin/sh\n";
|
|
3277
3353
|
const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
|
|
3278
3354
|
if (re.test(content)) content = content.replace(re, block);
|
|
3279
3355
|
else content = `${content.replace(/\s*$/, "")}
|
|
@@ -3282,21 +3358,21 @@ ${block}
|
|
|
3282
3358
|
`;
|
|
3283
3359
|
if (!content.startsWith("#!")) content = `#!/bin/sh
|
|
3284
3360
|
${content}`;
|
|
3285
|
-
|
|
3286
|
-
|
|
3361
|
+
fs8.writeFileSync(file, content);
|
|
3362
|
+
fs8.chmodSync(file, 493);
|
|
3287
3363
|
}
|
|
3288
3364
|
function undo(root2) {
|
|
3289
|
-
const hookFile =
|
|
3290
|
-
if (
|
|
3365
|
+
const hookFile = path38.join(hookDir(root2), "pre-commit");
|
|
3366
|
+
if (fs8.existsSync(hookFile)) {
|
|
3291
3367
|
const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
|
|
3292
|
-
const next2 =
|
|
3293
|
-
if (next2.trim() === "#!/bin/sh")
|
|
3294
|
-
else
|
|
3368
|
+
const next2 = fs8.readFileSync(hookFile, "utf8").replace(re, "\n");
|
|
3369
|
+
if (next2.trim() === "#!/bin/sh") fs8.rmSync(hookFile);
|
|
3370
|
+
else fs8.writeFileSync(hookFile, next2);
|
|
3295
3371
|
}
|
|
3296
|
-
const attr =
|
|
3297
|
-
if (
|
|
3298
|
-
const next2 =
|
|
3299
|
-
|
|
3372
|
+
const attr = path38.join(root2, ".gitattributes");
|
|
3373
|
+
if (fs8.existsSync(attr)) {
|
|
3374
|
+
const next2 = fs8.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
|
|
3375
|
+
fs8.writeFileSync(attr, next2);
|
|
3300
3376
|
}
|
|
3301
3377
|
try {
|
|
3302
3378
|
git(root2, ["config", "--remove-section", "merge.vg"]);
|
|
@@ -3306,10 +3382,10 @@ function undo(root2) {
|
|
|
3306
3382
|
function hookDir(root2) {
|
|
3307
3383
|
try {
|
|
3308
3384
|
const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
|
|
3309
|
-
if (configured) return
|
|
3385
|
+
if (configured) return path38.resolve(root2, configured);
|
|
3310
3386
|
} catch {
|
|
3311
3387
|
}
|
|
3312
|
-
return
|
|
3388
|
+
return path38.join(root2, ".git", "hooks");
|
|
3313
3389
|
}
|
|
3314
3390
|
function git(root2, args) {
|
|
3315
3391
|
return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
|
|
@@ -3337,9 +3413,9 @@ function registerWatch(program) {
|
|
|
3337
3413
|
const global = readGlobal(this);
|
|
3338
3414
|
const root2 = rootOf(global);
|
|
3339
3415
|
const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
|
|
3340
|
-
const watchRoots = (paths.length ? paths : ["."]).map((p) =>
|
|
3416
|
+
const watchRoots = (paths.length ? paths : ["."]).map((p) => path38.resolve(root2, p));
|
|
3341
3417
|
for (const w of watchRoots) {
|
|
3342
|
-
if (!
|
|
3418
|
+
if (!fs8.existsSync(w)) {
|
|
3343
3419
|
throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
|
|
3344
3420
|
}
|
|
3345
3421
|
}
|
|
@@ -3392,14 +3468,14 @@ function registerWatch(program) {
|
|
|
3392
3468
|
const watchers = [];
|
|
3393
3469
|
for (const w of watchRoots) {
|
|
3394
3470
|
try {
|
|
3395
|
-
const watcher =
|
|
3471
|
+
const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
|
|
3396
3472
|
if (!filename) {
|
|
3397
3473
|
schedule("change");
|
|
3398
3474
|
return;
|
|
3399
3475
|
}
|
|
3400
|
-
const parts = filename.split(
|
|
3476
|
+
const parts = filename.split(path38.sep);
|
|
3401
3477
|
if (parts.some((p) => SKIP_NAME.has(p))) return;
|
|
3402
|
-
if (filename.includes(`${
|
|
3478
|
+
if (filename.includes(`${path38.sep}.vibgrate${path38.sep}`) || filename.startsWith(".vibgrate")) {
|
|
3403
3479
|
return;
|
|
3404
3480
|
}
|
|
3405
3481
|
schedule(filename);
|
|
@@ -3409,7 +3485,7 @@ function registerWatch(program) {
|
|
|
3409
3485
|
throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
|
|
3410
3486
|
}
|
|
3411
3487
|
}
|
|
3412
|
-
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) =>
|
|
3488
|
+
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path38.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
|
|
3413
3489
|
await new Promise((resolve21) => {
|
|
3414
3490
|
const stop = () => {
|
|
3415
3491
|
for (const w of watchers) w.close();
|
|
@@ -3742,10 +3818,10 @@ function normalizeStandards(raw) {
|
|
|
3742
3818
|
}
|
|
3743
3819
|
function loadStandards(root2) {
|
|
3744
3820
|
for (const rel of STANDARDS_FILES) {
|
|
3745
|
-
const p =
|
|
3821
|
+
const p = path38__default.join(root2, rel);
|
|
3746
3822
|
let text;
|
|
3747
3823
|
try {
|
|
3748
|
-
text =
|
|
3824
|
+
text = fs8__default.readFileSync(p, "utf8");
|
|
3749
3825
|
} catch {
|
|
3750
3826
|
continue;
|
|
3751
3827
|
}
|
|
@@ -4463,8 +4539,8 @@ async function runHostBench(options = {}) {
|
|
|
4463
4539
|
}
|
|
4464
4540
|
async function runArmSimulate(input) {
|
|
4465
4541
|
const { arm, lib, modelPath, turns, trie, env, live } = input;
|
|
4466
|
-
const
|
|
4467
|
-
const session = await acquireHostSession(lib,
|
|
4542
|
+
const path40 = `${modelPath}#${arm.id}`;
|
|
4543
|
+
const session = await acquireHostSession(lib, path40);
|
|
4468
4544
|
const system = "You are a coding agent with a Task Capsule.";
|
|
4469
4545
|
const capsule = "function readConfig(): Config { return load(); }";
|
|
4470
4546
|
let last = null;
|
|
@@ -5676,7 +5752,7 @@ function registerModels(program) {
|
|
|
5676
5752
|
);
|
|
5677
5753
|
}
|
|
5678
5754
|
} else {
|
|
5679
|
-
if (!target.path || !
|
|
5755
|
+
if (!target.path || !fs8.existsSync(target.path)) {
|
|
5680
5756
|
throw new CliError(
|
|
5681
5757
|
`model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
|
|
5682
5758
|
ExitCode.NOT_FOUND
|
|
@@ -5690,7 +5766,7 @@ function registerModels(program) {
|
|
|
5690
5766
|
}
|
|
5691
5767
|
if (!global.json) info(c.dim(` $ rm ${target.path}`));
|
|
5692
5768
|
try {
|
|
5693
|
-
|
|
5769
|
+
fs8.unlinkSync(target.path);
|
|
5694
5770
|
} catch (e) {
|
|
5695
5771
|
const msg = e instanceof Error ? e.message : String(e);
|
|
5696
5772
|
throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
|
|
@@ -5828,9 +5904,9 @@ function registerModels(program) {
|
|
|
5828
5904
|
}
|
|
5829
5905
|
});
|
|
5830
5906
|
if (opts.out) {
|
|
5831
|
-
const outPath =
|
|
5832
|
-
|
|
5833
|
-
|
|
5907
|
+
const outPath = path38.resolve(opts.out);
|
|
5908
|
+
fs8.mkdirSync(path38.dirname(outPath), { recursive: true });
|
|
5909
|
+
fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
|
|
5834
5910
|
`);
|
|
5835
5911
|
if (!global.json) info(c.dim(` wrote ${outPath}`));
|
|
5836
5912
|
}
|
|
@@ -5979,14 +6055,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
|
|
|
5979
6055
|
}
|
|
5980
6056
|
return exact[0];
|
|
5981
6057
|
}
|
|
5982
|
-
const base =
|
|
6058
|
+
const base = path38.basename(wantLc);
|
|
5983
6059
|
const soft = fleet.filter((m) => {
|
|
5984
6060
|
const n = m.name.toLowerCase();
|
|
5985
|
-
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) ||
|
|
6061
|
+
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path38.basename(n) === base;
|
|
5986
6062
|
});
|
|
5987
6063
|
if (soft.length === 1) return soft[0];
|
|
5988
6064
|
if (soft.length > 1) {
|
|
5989
|
-
const baseHits = soft.filter((m) =>
|
|
6065
|
+
const baseHits = soft.filter((m) => path38.basename(m.name).toLowerCase() === base);
|
|
5990
6066
|
const pool = baseHits.length ? baseHits : soft;
|
|
5991
6067
|
const order = ["ollama", "gguf", "lm-studio"];
|
|
5992
6068
|
for (const rt of order) {
|
|
@@ -6024,11 +6100,11 @@ function printBackends(backends) {
|
|
|
6024
6100
|
}
|
|
6025
6101
|
}
|
|
6026
6102
|
function codeConfigPath(root2) {
|
|
6027
|
-
return
|
|
6103
|
+
return path38.join(root2, ".vibgrate", "code.json");
|
|
6028
6104
|
}
|
|
6029
6105
|
function loadCodeConfig(root2) {
|
|
6030
6106
|
try {
|
|
6031
|
-
const raw = JSON.parse(
|
|
6107
|
+
const raw = JSON.parse(fs8.readFileSync(codeConfigPath(root2), "utf8"));
|
|
6032
6108
|
return sanitize(raw);
|
|
6033
6109
|
} catch {
|
|
6034
6110
|
return {};
|
|
@@ -6095,7 +6171,7 @@ function contextBudgetFor(config, modelContextWindow) {
|
|
|
6095
6171
|
var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
|
|
6096
6172
|
function readMcpServersFile(file) {
|
|
6097
6173
|
try {
|
|
6098
|
-
const raw = JSON.parse(
|
|
6174
|
+
const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
|
|
6099
6175
|
const map = raw.mcpServers ?? raw.servers;
|
|
6100
6176
|
return map && typeof map === "object" ? parseMcpServers(map) : {};
|
|
6101
6177
|
} catch {
|
|
@@ -6106,7 +6182,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6106
6182
|
const servers = {};
|
|
6107
6183
|
const sources = [];
|
|
6108
6184
|
for (const rel of MCP_CONFIG_FILES) {
|
|
6109
|
-
const found = readMcpServersFile(
|
|
6185
|
+
const found = readMcpServersFile(path38.join(root2, rel));
|
|
6110
6186
|
const names = Object.keys(found);
|
|
6111
6187
|
if (names.length) {
|
|
6112
6188
|
sources.push(rel);
|
|
@@ -6122,7 +6198,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6122
6198
|
|
|
6123
6199
|
// src/commands/code.ts
|
|
6124
6200
|
function registerCode(program) {
|
|
6125
|
-
const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
|
|
6201
|
+
const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: vibgrate-relay (Vibgrate Relay), ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--session", "with --stream-json: stay open for further turns (warm graph and tools) instead of exiting after one").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
|
|
6126
6202
|
const global = readGlobal(this);
|
|
6127
6203
|
const instruction = (instructionParts ?? []).join(" ").trim();
|
|
6128
6204
|
const config = loadCodeConfig(rootOf(global));
|
|
@@ -6135,7 +6211,7 @@ function registerCode(program) {
|
|
|
6135
6211
|
try {
|
|
6136
6212
|
const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
|
|
6137
6213
|
const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
|
|
6138
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
6214
|
+
const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
|
|
6139
6215
|
const state = readOrchestratorState2();
|
|
6140
6216
|
const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
|
|
6141
6217
|
const pin = mode ? activePin2(mode, state) : null;
|
|
@@ -6219,7 +6295,7 @@ function registerCode(program) {
|
|
|
6219
6295
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
6220
6296
|
throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
|
|
6221
6297
|
}
|
|
6222
|
-
const { runInteractive } = await import('./interactive-
|
|
6298
|
+
const { runInteractive } = await import('./interactive-MJVMY5JP.js');
|
|
6223
6299
|
await runInteractive(
|
|
6224
6300
|
rootOf(global),
|
|
6225
6301
|
global,
|
|
@@ -6252,7 +6328,7 @@ function registerCode(program) {
|
|
|
6252
6328
|
let mockReply;
|
|
6253
6329
|
if (opts.mock) {
|
|
6254
6330
|
try {
|
|
6255
|
-
mockReply =
|
|
6331
|
+
mockReply = fs8.readFileSync(opts.mock, "utf8");
|
|
6256
6332
|
} catch {
|
|
6257
6333
|
throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
|
|
6258
6334
|
}
|
|
@@ -6301,18 +6377,18 @@ function registerCode(program) {
|
|
|
6301
6377
|
};
|
|
6302
6378
|
try {
|
|
6303
6379
|
const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
|
|
6304
|
-
const { runCodeStreamJson } = await import('./stream-json-
|
|
6305
|
-
const { nodeCodeFs } = await import('./session-
|
|
6380
|
+
const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-MTPWWVRR.js');
|
|
6381
|
+
const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
|
|
6306
6382
|
const readline5 = await import('readline');
|
|
6307
6383
|
const child = await import('child_process');
|
|
6308
6384
|
const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
|
|
6309
6385
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
6310
6386
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
6311
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
6312
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
6387
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
|
|
6388
|
+
const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
|
|
6313
6389
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
6314
6390
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
6315
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
6391
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
|
|
6316
6392
|
const federation = loadOrDiscoverFederation(root2);
|
|
6317
6393
|
const modelProfile = mergeModelExecutionProfile(
|
|
6318
6394
|
resolveModelExecutionProfile({
|
|
@@ -6358,7 +6434,7 @@ ${res.stderr}` : ""),
|
|
|
6358
6434
|
exitCode: res.status ?? 1
|
|
6359
6435
|
};
|
|
6360
6436
|
};
|
|
6361
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
6437
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
|
|
6362
6438
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
6363
6439
|
getGraph: () => graph,
|
|
6364
6440
|
root: root2,
|
|
@@ -6378,50 +6454,187 @@ ${res.stderr}` : ""),
|
|
|
6378
6454
|
};
|
|
6379
6455
|
}
|
|
6380
6456
|
const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
|
|
6457
|
+
const { createCheckpoint } = await import('./checkpoint-4WFZMKEO.js');
|
|
6458
|
+
const os5 = await import('os');
|
|
6459
|
+
const pathMod = await import('path');
|
|
6460
|
+
const checkpointIndex = pathMod.join(
|
|
6461
|
+
fs8.mkdtempSync(pathMod.join(os5.tmpdir(), "vg-code-cp-")),
|
|
6462
|
+
"index"
|
|
6463
|
+
);
|
|
6464
|
+
const gitRunner = (gitArgs, gitEnv) => {
|
|
6465
|
+
const res = child.spawnSync("git", gitArgs, {
|
|
6466
|
+
cwd: root2,
|
|
6467
|
+
encoding: "utf8",
|
|
6468
|
+
env: { ...process.env, ...gitEnv ?? {} },
|
|
6469
|
+
timeout: 3e4,
|
|
6470
|
+
maxBuffer: 32 * 1024 * 1024
|
|
6471
|
+
});
|
|
6472
|
+
return { stdout: res.stdout ?? "", exitCode: res.status ?? 1 };
|
|
6473
|
+
};
|
|
6474
|
+
const checkpointSessionId = `r${Date.now().toString(36)}`;
|
|
6475
|
+
let checkpointSeq = 0;
|
|
6476
|
+
const takeCheckpoint = (files) => createCheckpoint(gitRunner, {
|
|
6477
|
+
sessionId: checkpointSessionId,
|
|
6478
|
+
seq: ++checkpointSeq,
|
|
6479
|
+
files,
|
|
6480
|
+
indexFile: checkpointIndex
|
|
6481
|
+
});
|
|
6482
|
+
const { loadProjectRules, nodeRulesReader } = await import('./rules-ASYEUNB5.js');
|
|
6483
|
+
const projectRules = loadProjectRules(nodeRulesReader(root2));
|
|
6484
|
+
if (projectRules.sources.length && !global.quiet) {
|
|
6485
|
+
emitStream({
|
|
6486
|
+
event: "event",
|
|
6487
|
+
type: "notice",
|
|
6488
|
+
text: `project instructions: ${projectRules.sources.join(", ")}`
|
|
6489
|
+
});
|
|
6490
|
+
}
|
|
6491
|
+
const baseAgentOptions = {
|
|
6492
|
+
graph,
|
|
6493
|
+
root: root2,
|
|
6494
|
+
providers: route.providers,
|
|
6495
|
+
fsImpl: nodeCodeFs(root2),
|
|
6496
|
+
run,
|
|
6497
|
+
executionEnv,
|
|
6498
|
+
graphBackend,
|
|
6499
|
+
modelProfile,
|
|
6500
|
+
auto: !!auto,
|
|
6501
|
+
maxSteps,
|
|
6502
|
+
budget: modelProfile.capsuleBudgetTokens,
|
|
6503
|
+
contextBudget,
|
|
6504
|
+
denyCommands: config.denyCommands,
|
|
6505
|
+
testCommand: config.testCommand,
|
|
6506
|
+
stream: true,
|
|
6507
|
+
verify: verify3 ? { command: verify3.command, maxRounds: modelProfile.maxRepairRounds } : void 0,
|
|
6508
|
+
capsule,
|
|
6509
|
+
files: opts.file.length ? opts.file : void 0,
|
|
6510
|
+
worktreeOverlay: true,
|
|
6511
|
+
advancedMode: !capsule,
|
|
6512
|
+
externalTools,
|
|
6513
|
+
attribution: {
|
|
6514
|
+
client: "vg-code",
|
|
6515
|
+
provider: primarySlug,
|
|
6516
|
+
model: route.providers[0]?.model
|
|
6517
|
+
},
|
|
6518
|
+
now: () => Date.now(),
|
|
6519
|
+
projectRules: projectRules.rendered || void 0,
|
|
6520
|
+
checkpoint: takeCheckpoint
|
|
6521
|
+
};
|
|
6381
6522
|
try {
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
const msg = JSON.parse(raw);
|
|
6418
|
-
if (typeof msg.approveId === "number") session.submitDecision(msg.approveId, !!msg.approve);
|
|
6419
|
-
if (typeof msg.answerId === "number") session.submitAnswer(msg.answerId, String(msg.answer ?? ""));
|
|
6420
|
-
} catch {
|
|
6421
|
-
}
|
|
6523
|
+
if (opts.session) {
|
|
6524
|
+
const { runCodeStreamJsonSession } = await import('./stream-json-MTPWWVRR.js');
|
|
6525
|
+
const { runAgent: runAgent2 } = await import('./agent-Z4Z66IGM.js');
|
|
6526
|
+
const {
|
|
6527
|
+
loadLatestSession,
|
|
6528
|
+
newSession,
|
|
6529
|
+
recordTask,
|
|
6530
|
+
saveSession,
|
|
6531
|
+
summarizeSession
|
|
6532
|
+
} = await import('./session-store-O4XPXKOV.js');
|
|
6533
|
+
const resumedRecord = opts.continue ? loadLatestSession(root2) : void 0;
|
|
6534
|
+
let record = resumedRecord ?? newSession(
|
|
6535
|
+
`s${Date.now().toString(36)}`,
|
|
6536
|
+
primarySlug ?? route.providers[0]?.id ?? "unknown",
|
|
6537
|
+
route.providers[0]?.model ?? "unknown",
|
|
6538
|
+
Date.now()
|
|
6539
|
+
);
|
|
6540
|
+
const pendingTurns = [];
|
|
6541
|
+
let wakeTurn;
|
|
6542
|
+
let ended = false;
|
|
6543
|
+
const pushTurn = (instruction2) => {
|
|
6544
|
+
if (wakeTurn) {
|
|
6545
|
+
const wake = wakeTurn;
|
|
6546
|
+
wakeTurn = void 0;
|
|
6547
|
+
wake(instruction2);
|
|
6548
|
+
} else if (instruction2 !== null) {
|
|
6549
|
+
pendingTurns.push(instruction2);
|
|
6550
|
+
}
|
|
6551
|
+
};
|
|
6552
|
+
const nextTurn = () => {
|
|
6553
|
+
if (ended) return Promise.resolve(null);
|
|
6554
|
+
const queued = pendingTurns.shift();
|
|
6555
|
+
if (queued !== void 0) return Promise.resolve(queued);
|
|
6556
|
+
return new Promise((resolve21) => {
|
|
6557
|
+
wakeTurn = resolve21;
|
|
6422
6558
|
});
|
|
6423
|
-
}
|
|
6424
|
-
|
|
6559
|
+
};
|
|
6560
|
+
await runCodeStreamJsonSession({
|
|
6561
|
+
emit: emitStream,
|
|
6562
|
+
auto: !!auto,
|
|
6563
|
+
sessionId: record.id,
|
|
6564
|
+
resumed: !!resumedRecord,
|
|
6565
|
+
instruction,
|
|
6566
|
+
nextTurn,
|
|
6567
|
+
bindDecisions: (session) => {
|
|
6568
|
+
streamApprove = (action) => session.approve(action);
|
|
6569
|
+
const rl = readline5.createInterface({ input: process.stdin });
|
|
6570
|
+
rl.on("line", (raw) => {
|
|
6571
|
+
const msg = parseHostMessage(raw);
|
|
6572
|
+
if (!msg) return;
|
|
6573
|
+
if (msg.kind === "approve") session.submitDecision(msg.id, msg.approve);
|
|
6574
|
+
else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
|
|
6575
|
+
else if (msg.kind === "submit") pushTurn(msg.instruction);
|
|
6576
|
+
else if (msg.kind === "restore") {
|
|
6577
|
+
void import('./checkpoint-4WFZMKEO.js').then(({ restoreCheckpoint }) => {
|
|
6578
|
+
const outcome = restoreCheckpoint(gitRunner, {
|
|
6579
|
+
commit: msg.commit,
|
|
6580
|
+
files: msg.files
|
|
6581
|
+
});
|
|
6582
|
+
emitStream({ event: "checkpoint-restored", commit: msg.commit, ...outcome });
|
|
6583
|
+
});
|
|
6584
|
+
} else if (msg.kind === "cancel") session.cancelTurn();
|
|
6585
|
+
else if (msg.kind === "end") {
|
|
6586
|
+
ended = true;
|
|
6587
|
+
pushTurn(null);
|
|
6588
|
+
}
|
|
6589
|
+
});
|
|
6590
|
+
rl.on("close", () => {
|
|
6591
|
+
ended = true;
|
|
6592
|
+
session.cancelTurn();
|
|
6593
|
+
pushTurn(null);
|
|
6594
|
+
});
|
|
6595
|
+
},
|
|
6596
|
+
runTurn: ({ instruction: turnInstruction, priorSummary, signal, session }) => runAgent2({
|
|
6597
|
+
...baseAgentOptions,
|
|
6598
|
+
instruction: turnInstruction,
|
|
6599
|
+
priorSummary,
|
|
6600
|
+
signal,
|
|
6601
|
+
approve: session.approve,
|
|
6602
|
+
askUser: session.askUser,
|
|
6603
|
+
onEvent: session.onEvent
|
|
6604
|
+
}),
|
|
6605
|
+
onTurnEnd: (turn) => {
|
|
6606
|
+
record = recordTask(
|
|
6607
|
+
record,
|
|
6608
|
+
{
|
|
6609
|
+
instruction: turn.instruction,
|
|
6610
|
+
summary: turn.result?.finalText ?? "turn failed",
|
|
6611
|
+
changes: turn.result?.changes ?? [],
|
|
6612
|
+
stopped: turn.result?.stopped ?? "error"
|
|
6613
|
+
},
|
|
6614
|
+
Date.now()
|
|
6615
|
+
);
|
|
6616
|
+
saveSession(root2, record);
|
|
6617
|
+
return summarizeSession(record);
|
|
6618
|
+
}
|
|
6619
|
+
});
|
|
6620
|
+
} else {
|
|
6621
|
+
await runCodeStreamJson({
|
|
6622
|
+
...baseAgentOptions,
|
|
6623
|
+
instruction,
|
|
6624
|
+
emit: emitStream,
|
|
6625
|
+
bindDecisions: (session) => {
|
|
6626
|
+
streamApprove = (action) => session.approve(action);
|
|
6627
|
+
const rl = readline5.createInterface({ input: process.stdin });
|
|
6628
|
+
rl.on("line", (raw) => {
|
|
6629
|
+
const msg = parseHostMessage(raw);
|
|
6630
|
+
if (!msg) return;
|
|
6631
|
+
if (msg.kind === "approve") session.submitDecision(msg.id, msg.approve);
|
|
6632
|
+
else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
|
|
6633
|
+
else if (msg.kind === "cancel") session.cancelTurn();
|
|
6634
|
+
});
|
|
6635
|
+
}
|
|
6636
|
+
});
|
|
6637
|
+
}
|
|
6425
6638
|
} finally {
|
|
6426
6639
|
await disposeMcpStream?.();
|
|
6427
6640
|
await runtime.dispose();
|
|
@@ -6440,8 +6653,8 @@ ${res.stderr}` : ""),
|
|
|
6440
6653
|
if (!autonomous && !tty) {
|
|
6441
6654
|
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).");
|
|
6442
6655
|
}
|
|
6443
|
-
const { agentTask } = await import('./interactive-
|
|
6444
|
-
const { nodeCodeFs } = await import('./session-
|
|
6656
|
+
const { agentTask } = await import('./interactive-MJVMY5JP.js');
|
|
6657
|
+
const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
|
|
6445
6658
|
const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
|
|
6446
6659
|
let priorSummary;
|
|
6447
6660
|
if (opts.continue) {
|
|
@@ -6450,7 +6663,7 @@ ${res.stderr}` : ""),
|
|
|
6450
6663
|
if (prev) priorSummary = summarizeSession(prev);
|
|
6451
6664
|
}
|
|
6452
6665
|
const prompter = tty ? new TtyPrompter() : void 0;
|
|
6453
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
6666
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
|
|
6454
6667
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
6455
6668
|
getGraph: () => graph,
|
|
6456
6669
|
root: root2,
|
|
@@ -6474,11 +6687,11 @@ ${res.stderr}` : ""),
|
|
|
6474
6687
|
const { loadFederation } = await import('./federation-MDQPO3PW.js');
|
|
6475
6688
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
6476
6689
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
6477
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
6478
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
6690
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
|
|
6691
|
+
const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
|
|
6479
6692
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
6480
6693
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
6481
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
6694
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
|
|
6482
6695
|
const federation = loadFederation(root2);
|
|
6483
6696
|
const modelProfile = mergeModelExecutionProfile(
|
|
6484
6697
|
resolveModelExecutionProfile({
|
|
@@ -6570,7 +6783,7 @@ ${res.stderr}` : ""),
|
|
|
6570
6783
|
attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
|
|
6571
6784
|
});
|
|
6572
6785
|
if (opts.out) {
|
|
6573
|
-
|
|
6786
|
+
fs8.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
|
|
6574
6787
|
}
|
|
6575
6788
|
if (global.json) {
|
|
6576
6789
|
json(result);
|
|
@@ -6783,7 +6996,7 @@ async function addCmd(root2, rest, opts, asJson) {
|
|
|
6783
6996
|
}
|
|
6784
6997
|
function readPackageVersion(root2) {
|
|
6785
6998
|
try {
|
|
6786
|
-
const pkg = JSON.parse(
|
|
6999
|
+
const pkg = JSON.parse(fs8__default.readFileSync(path38__default.join(root2, "package.json"), "utf8"));
|
|
6787
7000
|
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
6788
7001
|
} catch {
|
|
6789
7002
|
return void 0;
|
|
@@ -6791,7 +7004,7 @@ function readPackageVersion(root2) {
|
|
|
6791
7004
|
}
|
|
6792
7005
|
function readOptionalFile(p) {
|
|
6793
7006
|
try {
|
|
6794
|
-
const t =
|
|
7007
|
+
const t = fs8__default.readFileSync(p, "utf8");
|
|
6795
7008
|
return t.trim() ? t : void 0;
|
|
6796
7009
|
} catch {
|
|
6797
7010
|
return void 0;
|
|
@@ -6806,8 +7019,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
|
|
|
6806
7019
|
if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
|
|
6807
7020
|
const version = (opts.version || readPackageVersion(root2) || "").trim();
|
|
6808
7021
|
if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
|
|
6809
|
-
const readme = readOptionalFile(opts.readme ?
|
|
6810
|
-
const dts = opts.dts ? readOptionalFile(
|
|
7022
|
+
const readme = readOptionalFile(opts.readme ? path38__default.resolve(opts.readme) : path38__default.join(root2, "README.md"));
|
|
7023
|
+
const dts = opts.dts ? readOptionalFile(path38__default.resolve(opts.dts)) : void 0;
|
|
6811
7024
|
if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
|
|
6812
7025
|
const result = await publishPrivateLibrary(
|
|
6813
7026
|
{ name, version, readme, dts, language: opts.language },
|
|
@@ -6939,8 +7152,8 @@ function registerExport(program) {
|
|
|
6939
7152
|
out(content.trimEnd());
|
|
6940
7153
|
return;
|
|
6941
7154
|
}
|
|
6942
|
-
|
|
6943
|
-
|
|
7155
|
+
fs8.mkdirSync(path38.dirname(path38.resolve(file)), { recursive: true });
|
|
7156
|
+
fs8.writeFileSync(file, content);
|
|
6944
7157
|
info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
|
|
6945
7158
|
});
|
|
6946
7159
|
applyGlobalOptions(cmd);
|
|
@@ -6950,43 +7163,43 @@ function detectFormat(file) {
|
|
|
6950
7163
|
if (lower.endsWith(".cdx.json")) return "cyclonedx";
|
|
6951
7164
|
if (lower.endsWith(".spdx.json")) return "spdx";
|
|
6952
7165
|
if (file === "-") return "json";
|
|
6953
|
-
return formatForExt(
|
|
7166
|
+
return formatForExt(path38.extname(file));
|
|
6954
7167
|
}
|
|
6955
7168
|
function registerBundle(program) {
|
|
6956
7169
|
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) {
|
|
6957
7170
|
const global = readGlobal(this);
|
|
6958
7171
|
const root2 = rootOf(global);
|
|
6959
|
-
const outDir =
|
|
7172
|
+
const outDir = path38.resolve(root2, opts.out ?? "vg-bundle");
|
|
6960
7173
|
let grammarFiles;
|
|
6961
7174
|
try {
|
|
6962
7175
|
grammarFiles = resolvedGrammarFiles();
|
|
6963
7176
|
} catch {
|
|
6964
7177
|
throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
|
|
6965
7178
|
}
|
|
6966
|
-
|
|
7179
|
+
fs8.mkdirSync(path38.join(outDir, "grammars"), { recursive: true });
|
|
6967
7180
|
let grammarCount = 0;
|
|
6968
7181
|
for (const { fileName, absPath } of grammarFiles) {
|
|
6969
|
-
|
|
7182
|
+
fs8.copyFileSync(absPath, path38.join(outDir, "grammars", fileName));
|
|
6970
7183
|
grammarCount++;
|
|
6971
7184
|
}
|
|
6972
7185
|
const included = [`grammars/ (${grammarCount} .wasm)`];
|
|
6973
7186
|
const graphSrc = resolveGraphPath(root2, global.graph);
|
|
6974
|
-
if (
|
|
6975
|
-
|
|
7187
|
+
if (fs8.existsSync(graphSrc)) {
|
|
7188
|
+
fs8.copyFileSync(graphSrc, path38.join(outDir, "graph.json"));
|
|
6976
7189
|
included.push("graph.json");
|
|
6977
7190
|
} else {
|
|
6978
7191
|
const graph = loadGraphFileWithSnapshot(graphSrc);
|
|
6979
7192
|
if (graph) {
|
|
6980
|
-
|
|
7193
|
+
fs8.writeFileSync(path38.join(outDir, "graph.json"), serializeGraph(graph));
|
|
6981
7194
|
included.push("graph.json");
|
|
6982
7195
|
}
|
|
6983
7196
|
}
|
|
6984
7197
|
const cat = catalogPath(root2);
|
|
6985
|
-
if (
|
|
6986
|
-
|
|
7198
|
+
if (fs8.existsSync(cat)) {
|
|
7199
|
+
fs8.copyFileSync(cat, path38.join(outDir, "vibgrate.lib.json"));
|
|
6987
7200
|
included.push("vibgrate.lib.json");
|
|
6988
|
-
if (
|
|
6989
|
-
|
|
7201
|
+
if (fs8.existsSync(libDir(root2))) {
|
|
7202
|
+
fs8.cpSync(libDir(root2), path38.join(outDir, "lib"), { recursive: true });
|
|
6990
7203
|
included.push("lib/");
|
|
6991
7204
|
}
|
|
6992
7205
|
}
|
|
@@ -6998,15 +7211,15 @@ function registerBundle(program) {
|
|
|
6998
7211
|
included,
|
|
6999
7212
|
usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
|
|
7000
7213
|
};
|
|
7001
|
-
|
|
7214
|
+
fs8.writeFileSync(path38.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
|
|
7002
7215
|
`);
|
|
7003
7216
|
if (global.json) {
|
|
7004
|
-
json({ out:
|
|
7217
|
+
json({ out: path38.relative(root2, outDir), ...manifest });
|
|
7005
7218
|
return;
|
|
7006
7219
|
}
|
|
7007
|
-
info(`${c.cyan("vg bundle")} \xB7 wrote ${
|
|
7220
|
+
info(`${c.cyan("vg bundle")} \xB7 wrote ${path38.relative(root2, outDir)}/`);
|
|
7008
7221
|
for (const i of included) info(` ${c.green("\u2714")} ${i}`);
|
|
7009
|
-
info(c.dim(` offline: vg build --grammars "${
|
|
7222
|
+
info(c.dim(` offline: vg build --grammars "${path38.relative(root2, outDir)}/grammars"`));
|
|
7010
7223
|
});
|
|
7011
7224
|
applyGlobalOptions(cmd);
|
|
7012
7225
|
}
|
|
@@ -7024,7 +7237,7 @@ async function runDoctor(global) {
|
|
|
7024
7237
|
const root2 = rootOf(global);
|
|
7025
7238
|
const local = global.local === true;
|
|
7026
7239
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
7027
|
-
const configFile = CONFIG_BASENAMES.find((f) =>
|
|
7240
|
+
const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path38.join(root2, f))) ?? null;
|
|
7028
7241
|
const graph = loadGraph(root2, graphPath);
|
|
7029
7242
|
let staleFiles = null;
|
|
7030
7243
|
if (graph) {
|
|
@@ -7050,14 +7263,14 @@ async function runDoctor(global) {
|
|
|
7050
7263
|
root: root2,
|
|
7051
7264
|
configFile,
|
|
7052
7265
|
map: {
|
|
7053
|
-
path:
|
|
7266
|
+
path: path38.relative(root2, graphPath),
|
|
7054
7267
|
built: graph !== null,
|
|
7055
7268
|
generatedAt: graph?.generatedAt ?? null,
|
|
7056
7269
|
staleFiles
|
|
7057
7270
|
},
|
|
7058
7271
|
libCatalog: {
|
|
7059
|
-
path:
|
|
7060
|
-
present:
|
|
7272
|
+
path: path38.relative(root2, catalogPath(root2)),
|
|
7273
|
+
present: fs8.existsSync(catalogPath(root2)),
|
|
7061
7274
|
libraries: libCount
|
|
7062
7275
|
},
|
|
7063
7276
|
credentials: creds,
|
|
@@ -7114,7 +7327,7 @@ async function runDoctor(global) {
|
|
|
7114
7327
|
);
|
|
7115
7328
|
info(
|
|
7116
7329
|
` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
|
|
7117
|
-
` \xB7 last ${
|
|
7330
|
+
` \xB7 last ${path38.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
|
|
7118
7331
|
) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
|
|
7119
7332
|
);
|
|
7120
7333
|
if (li.dynamicOnToken || li.dynamicCustomSampler) {
|
|
@@ -7194,7 +7407,9 @@ function registerDaemon(program) {
|
|
|
7194
7407
|
if (await vgdIsRunning({ socketPath })) {
|
|
7195
7408
|
throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);
|
|
7196
7409
|
}
|
|
7197
|
-
|
|
7410
|
+
let requestShutdown = () => {
|
|
7411
|
+
};
|
|
7412
|
+
const server = await startVgdServer({ socketPath, onShutdownRequest: () => requestShutdown() });
|
|
7198
7413
|
if (!global.quiet) {
|
|
7199
7414
|
info(`vgd \xB7 listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);
|
|
7200
7415
|
info(c.dim(" register a workspace: vg daemon register"));
|
|
@@ -7205,6 +7420,7 @@ function registerDaemon(program) {
|
|
|
7205
7420
|
if (!global.quiet) info(c.dim("vgd \xB7 stopped"));
|
|
7206
7421
|
process.exit(0);
|
|
7207
7422
|
};
|
|
7423
|
+
requestShutdown = () => void shutdown();
|
|
7208
7424
|
process.on("SIGINT", () => void shutdown());
|
|
7209
7425
|
process.on("SIGTERM", () => void shutdown());
|
|
7210
7426
|
await new Promise(() => {
|
|
@@ -7224,33 +7440,70 @@ function registerDaemon(program) {
|
|
|
7224
7440
|
}
|
|
7225
7441
|
return;
|
|
7226
7442
|
}
|
|
7227
|
-
const child =
|
|
7228
|
-
child.unref();
|
|
7229
|
-
const deadline = Date.now() + 8e3;
|
|
7230
|
-
let ready = false;
|
|
7231
|
-
while (Date.now() < deadline) {
|
|
7232
|
-
await sleep(100);
|
|
7233
|
-
if (await vgdIsRunning({ socketPath })) {
|
|
7234
|
-
ready = true;
|
|
7235
|
-
break;
|
|
7236
|
-
}
|
|
7237
|
-
}
|
|
7238
|
-
if (!ready) {
|
|
7239
|
-
throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
|
|
7240
|
-
}
|
|
7443
|
+
const child = await startDetachedVgd(socketPath);
|
|
7241
7444
|
const res = await vgdRequest({ op: "status" }, { socketPath });
|
|
7242
7445
|
if (global.json) {
|
|
7243
7446
|
json({ running: true, ensured: true, ...res.ok ? res : { socketPath } });
|
|
7244
7447
|
} else if (!global.quiet) {
|
|
7245
|
-
const pid = res.ok && "pid" in res ? res.pid : child
|
|
7448
|
+
const pid = res.ok && "pid" in res ? res.pid : child;
|
|
7246
7449
|
info(`vgd \xB7 started in background pid ${pid} \xB7 ${c.dim(socketPath)}`);
|
|
7247
7450
|
}
|
|
7248
7451
|
});
|
|
7249
7452
|
applyGlobalOptions(ensure);
|
|
7453
|
+
const stop = cmd.command("stop").description("stop the running vgd (idempotent \u2014 succeeds if none is running)").action(async function() {
|
|
7454
|
+
const global = readGlobal(this);
|
|
7455
|
+
const socketPath = socketOf(this);
|
|
7456
|
+
const result = await stopVgd(socketPath);
|
|
7457
|
+
if (global.json) {
|
|
7458
|
+
json({ stopped: result === "stopped", result, socketPath });
|
|
7459
|
+
} else if (!global.quiet) {
|
|
7460
|
+
if (result === "stopped") info(`vgd \xB7 stopped ${c.dim(socketPath)}`);
|
|
7461
|
+
else if (result === "not-running") info(c.dim(`vgd \xB7 not running (${socketPath})`));
|
|
7462
|
+
}
|
|
7463
|
+
if (result === "refused") {
|
|
7464
|
+
throw new CliError(
|
|
7465
|
+
"this vgd is embedded in another process (e.g. vg code) \u2014 stop that process instead",
|
|
7466
|
+
ExitCode.ERROR
|
|
7467
|
+
);
|
|
7468
|
+
}
|
|
7469
|
+
if (result === "failed") {
|
|
7470
|
+
throw new CliError(
|
|
7471
|
+
`vgd did not stop within 5s (${socketPath}) \u2014 check \`vg daemon status\` and stop the process manually`,
|
|
7472
|
+
ExitCode.ERROR
|
|
7473
|
+
);
|
|
7474
|
+
}
|
|
7475
|
+
});
|
|
7476
|
+
applyGlobalOptions(stop);
|
|
7477
|
+
const restart = cmd.command("restart").description("restart vgd (stop if running, then start in the background)").action(async function() {
|
|
7478
|
+
const global = readGlobal(this);
|
|
7479
|
+
const socketPath = socketOf(this);
|
|
7480
|
+
const stopResult = await stopVgd(socketPath);
|
|
7481
|
+
if (stopResult === "refused") {
|
|
7482
|
+
throw new CliError(
|
|
7483
|
+
"this vgd is embedded in another process (e.g. vg code) \u2014 stop that process instead",
|
|
7484
|
+
ExitCode.ERROR
|
|
7485
|
+
);
|
|
7486
|
+
}
|
|
7487
|
+
if (stopResult === "failed") {
|
|
7488
|
+
throw new CliError(
|
|
7489
|
+
`vgd did not stop within 5s (${socketPath}) \u2014 check \`vg daemon status\` and stop the process manually`,
|
|
7490
|
+
ExitCode.ERROR
|
|
7491
|
+
);
|
|
7492
|
+
}
|
|
7493
|
+
await startDetachedVgd(socketPath);
|
|
7494
|
+
const res = await vgdRequest({ op: "status" }, { socketPath });
|
|
7495
|
+
if (global.json) {
|
|
7496
|
+
json({ running: true, restarted: true, ...res.ok ? res : { socketPath } });
|
|
7497
|
+
} else if (!global.quiet) {
|
|
7498
|
+
const pid = res.ok && "pid" in res ? res.pid : "?";
|
|
7499
|
+
info(`vgd \xB7 restarted pid ${pid} \xB7 ${c.dim(socketPath)}`);
|
|
7500
|
+
}
|
|
7501
|
+
});
|
|
7502
|
+
applyGlobalOptions(restart);
|
|
7250
7503
|
const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
|
|
7251
7504
|
const global = readGlobal(this);
|
|
7252
7505
|
const socketPath = socketOf(this);
|
|
7253
|
-
const root2 =
|
|
7506
|
+
const root2 = path38.resolve(rootArg ?? rootOf(global));
|
|
7254
7507
|
if (!await vgdIsRunning({ socketPath })) {
|
|
7255
7508
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
7256
7509
|
}
|
|
@@ -7286,7 +7539,7 @@ function registerDaemon(program) {
|
|
|
7286
7539
|
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) {
|
|
7287
7540
|
const global = readGlobal(this);
|
|
7288
7541
|
const socketPath = socketOf(this);
|
|
7289
|
-
const primary =
|
|
7542
|
+
const primary = path38.resolve(rootArg ?? rootOf(global));
|
|
7290
7543
|
if (!await vgdIsRunning({ socketPath })) {
|
|
7291
7544
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
7292
7545
|
}
|
|
@@ -7314,32 +7567,42 @@ function registerDaemon(program) {
|
|
|
7314
7567
|
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) {
|
|
7315
7568
|
const global = readGlobal(this);
|
|
7316
7569
|
const socketPath = socketOf(this);
|
|
7317
|
-
const root2 =
|
|
7570
|
+
const root2 = path38.resolve(rootArg ?? rootOf(global));
|
|
7318
7571
|
if (!await vgdIsRunning({ socketPath })) {
|
|
7319
7572
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
7320
7573
|
}
|
|
7321
|
-
const { loadGraph: loadGraph2 } = await import('./load-4MLIHGXF.js');
|
|
7322
|
-
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7323
|
-
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7324
7574
|
const opts = this.opts();
|
|
7325
|
-
const
|
|
7326
|
-
|
|
7327
|
-
throw new CliError(
|
|
7328
|
-
`no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
|
|
7329
|
-
ExitCode.NOT_FOUND
|
|
7330
|
-
);
|
|
7331
|
-
}
|
|
7332
|
-
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
7333
|
-
if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
|
|
7334
|
-
const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
|
|
7335
|
-
const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
|
|
7336
|
-
const put = await vgdRequest(
|
|
7337
|
-
{ op: "put-graph", repositoryId, gitRef: git2, graph },
|
|
7575
|
+
const loaded = await vgdRequest(
|
|
7576
|
+
{ op: "load-graph", root: root2, gitRef: opts.gitRef?.trim() || void 0, graphPath: global.graph },
|
|
7338
7577
|
{ socketPath }
|
|
7339
7578
|
);
|
|
7340
|
-
|
|
7579
|
+
let put = loaded;
|
|
7580
|
+
if (!loaded.ok && loaded.code === "no_map") {
|
|
7581
|
+
throw new CliError(loaded.error, ExitCode.NOT_FOUND);
|
|
7582
|
+
}
|
|
7583
|
+
if (!loaded.ok) {
|
|
7584
|
+
const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
|
|
7585
|
+
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7586
|
+
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7587
|
+
const graph = loadGraph2(root2, global.graph);
|
|
7588
|
+
if (!graph) {
|
|
7589
|
+
throw new CliError(
|
|
7590
|
+
`no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
|
|
7591
|
+
ExitCode.NOT_FOUND
|
|
7592
|
+
);
|
|
7593
|
+
}
|
|
7594
|
+
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
7595
|
+
if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
|
|
7596
|
+
const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
|
|
7597
|
+
const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
|
|
7598
|
+
put = await vgdRequest(
|
|
7599
|
+
{ op: "put-graph", repositoryId, gitRef: git2, graph },
|
|
7600
|
+
{ socketPath }
|
|
7601
|
+
);
|
|
7602
|
+
if (!put.ok) throw new CliError(put.error, ExitCode.ERROR);
|
|
7603
|
+
}
|
|
7341
7604
|
if (global.json) json(put);
|
|
7342
|
-
else if ("stored" in put) {
|
|
7605
|
+
else if (put.ok && "stored" in put) {
|
|
7343
7606
|
info(`vgd \xB7 published graph \xB7 ${put.nodeCount} node(s) \xB7 ref ${put.gitRef}`);
|
|
7344
7607
|
info(c.dim(` repositoryId ${put.repositoryId}`));
|
|
7345
7608
|
}
|
|
@@ -7434,7 +7697,7 @@ function socketOf(cmd) {
|
|
|
7434
7697
|
let c2 = cmd;
|
|
7435
7698
|
while (c2) {
|
|
7436
7699
|
const opts = c2.opts();
|
|
7437
|
-
if (opts.socket) return
|
|
7700
|
+
if (opts.socket) return path38.resolve(opts.socket);
|
|
7438
7701
|
c2 = c2.parent;
|
|
7439
7702
|
}
|
|
7440
7703
|
return vgdSocketPath();
|
|
@@ -7457,6 +7720,62 @@ function spawnDetachedDaemonStart(socketPath) {
|
|
|
7457
7720
|
function sleep(ms) {
|
|
7458
7721
|
return new Promise((r) => setTimeout(r, ms));
|
|
7459
7722
|
}
|
|
7723
|
+
async function startDetachedVgd(socketPath) {
|
|
7724
|
+
const child = spawnDetachedDaemonStart(socketPath);
|
|
7725
|
+
child.unref();
|
|
7726
|
+
const deadline = Date.now() + 8e3;
|
|
7727
|
+
while (Date.now() < deadline) {
|
|
7728
|
+
await sleep(100);
|
|
7729
|
+
if (await vgdIsRunning({ socketPath })) return child.pid;
|
|
7730
|
+
}
|
|
7731
|
+
throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
|
|
7732
|
+
}
|
|
7733
|
+
async function stopVgd(socketPath) {
|
|
7734
|
+
if (!await vgdIsRunning({ socketPath })) return "not-running";
|
|
7735
|
+
let acknowledged = false;
|
|
7736
|
+
try {
|
|
7737
|
+
const res = await vgdRequest({ op: "shutdown" }, { socketPath });
|
|
7738
|
+
if (res.ok) acknowledged = true;
|
|
7739
|
+
else if (res.code === "shutdown_unsupported") return "refused";
|
|
7740
|
+
} catch {
|
|
7741
|
+
}
|
|
7742
|
+
if (!acknowledged) {
|
|
7743
|
+
const pid = readVgdPid();
|
|
7744
|
+
if (pid == null) return "failed";
|
|
7745
|
+
try {
|
|
7746
|
+
process.kill(pid, "SIGTERM");
|
|
7747
|
+
} catch {
|
|
7748
|
+
return "failed";
|
|
7749
|
+
}
|
|
7750
|
+
}
|
|
7751
|
+
const deadline = Date.now() + 5e3;
|
|
7752
|
+
while (Date.now() < deadline) {
|
|
7753
|
+
await sleep(100);
|
|
7754
|
+
if (!await vgdIsRunning({ socketPath })) return "stopped";
|
|
7755
|
+
}
|
|
7756
|
+
return "failed";
|
|
7757
|
+
}
|
|
7758
|
+
async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
|
|
7759
|
+
try {
|
|
7760
|
+
const stopResult = await stopVgd(socketPath);
|
|
7761
|
+
if (stopResult === "not-running") return "not-running";
|
|
7762
|
+
if (stopResult === "refused") return "refused";
|
|
7763
|
+
if (stopResult === "failed") return "failed";
|
|
7764
|
+
await startDetachedVgd(socketPath);
|
|
7765
|
+
return "restarted";
|
|
7766
|
+
} catch {
|
|
7767
|
+
return "failed";
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
function readVgdPid() {
|
|
7771
|
+
try {
|
|
7772
|
+
const raw = fs8.readFileSync(vgdPidPath(), "utf8").trim();
|
|
7773
|
+
const pid = Number.parseInt(raw, 10);
|
|
7774
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
7775
|
+
} catch {
|
|
7776
|
+
return null;
|
|
7777
|
+
}
|
|
7778
|
+
}
|
|
7460
7779
|
async function repositoryIdForCwd(socketPath, root2) {
|
|
7461
7780
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7462
7781
|
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
@@ -7535,7 +7854,7 @@ function registerPolicy(program) {
|
|
|
7535
7854
|
const global = readGlobal(this);
|
|
7536
7855
|
let raw;
|
|
7537
7856
|
try {
|
|
7538
|
-
raw =
|
|
7857
|
+
raw = fs8.readFileSync(file, "utf8");
|
|
7539
7858
|
} catch {
|
|
7540
7859
|
throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
|
|
7541
7860
|
}
|
|
@@ -7655,11 +7974,11 @@ function registerLlmHost(program) {
|
|
|
7655
7974
|
applyGlobalOptions(cmd);
|
|
7656
7975
|
}
|
|
7657
7976
|
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) => {
|
|
7658
|
-
const rootDir =
|
|
7659
|
-
const vibgrateDir2 =
|
|
7977
|
+
const rootDir = path38.resolve(targetPath);
|
|
7978
|
+
const vibgrateDir2 = path38.join(rootDir, ".vibgrate");
|
|
7660
7979
|
await ensureDir(vibgrateDir2);
|
|
7661
7980
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
|
|
7662
|
-
const configPath =
|
|
7981
|
+
const configPath = path38.join(rootDir, "vibgrate.config.ts");
|
|
7663
7982
|
if (await pathExists(configPath)) {
|
|
7664
7983
|
console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
|
|
7665
7984
|
} else {
|
|
@@ -7667,7 +7986,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
7667
7986
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
|
|
7668
7987
|
}
|
|
7669
7988
|
if (opts.baseline) {
|
|
7670
|
-
const { runBaseline } = await import('./baseline-
|
|
7989
|
+
const { runBaseline } = await import('./baseline-Q3QQF5QF.js');
|
|
7671
7990
|
await runBaseline(rootDir);
|
|
7672
7991
|
}
|
|
7673
7992
|
console.log("");
|
|
@@ -7770,16 +8089,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
|
|
|
7770
8089
|
};
|
|
7771
8090
|
}
|
|
7772
8091
|
async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
|
|
7773
|
-
const content = await readFile3(
|
|
8092
|
+
const content = await readFile3(path38.join(rootDir, relFile));
|
|
7774
8093
|
if (!content) return false;
|
|
7775
8094
|
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7776
8095
|
return new RegExp(`\\b${escaped}\\b`).test(content);
|
|
7777
8096
|
}
|
|
7778
8097
|
async function defaultReadFile(absPath) {
|
|
7779
8098
|
try {
|
|
7780
|
-
const stat2 = await
|
|
8099
|
+
const stat2 = await fs22.stat(absPath);
|
|
7781
8100
|
if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
|
|
7782
|
-
return await
|
|
8101
|
+
return await fs22.readFile(absPath, "utf8");
|
|
7783
8102
|
} catch {
|
|
7784
8103
|
return null;
|
|
7785
8104
|
}
|
|
@@ -7965,7 +8284,7 @@ var AI_ASSISTANT_DETECTORS = [
|
|
|
7965
8284
|
async function detectAiAssistant(rootDir) {
|
|
7966
8285
|
for (const detector of AI_ASSISTANT_DETECTORS) {
|
|
7967
8286
|
for (const file of detector.files) {
|
|
7968
|
-
if (await pathExists$1(
|
|
8287
|
+
if (await pathExists$1(path38.join(rootDir, file))) {
|
|
7969
8288
|
return detector.name;
|
|
7970
8289
|
}
|
|
7971
8290
|
}
|
|
@@ -8159,7 +8478,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
8159
8478
|
collectExcludes,
|
|
8160
8479
|
[]
|
|
8161
8480
|
).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) => {
|
|
8162
|
-
const rootDir =
|
|
8481
|
+
const rootDir = path38.resolve(targetPath);
|
|
8163
8482
|
if (!await pathExists$1(rootDir)) {
|
|
8164
8483
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
8165
8484
|
process.exit(1);
|
|
@@ -8167,7 +8486,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
8167
8486
|
const hasDsn = !!resolveDsn(opts.dsn);
|
|
8168
8487
|
const willPush = !opts.offline && (opts.push || hasDsn);
|
|
8169
8488
|
const noLocalArtifacts = opts.localArtifacts === false;
|
|
8170
|
-
const isFirstRun = !await pathExists$1(
|
|
8489
|
+
const isFirstRun = !await pathExists$1(path38.join(rootDir, ".vibgrate", "scan_result.json"));
|
|
8171
8490
|
let pinnedRegion;
|
|
8172
8491
|
let planTier;
|
|
8173
8492
|
let upgradeUrl;
|
|
@@ -8426,40 +8745,40 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
|
8426
8745
|
function scanStaleness(rootDir, artifactPath) {
|
|
8427
8746
|
let ref;
|
|
8428
8747
|
try {
|
|
8429
|
-
ref =
|
|
8748
|
+
ref = fs8.statSync(artifactPath).mtimeMs;
|
|
8430
8749
|
} catch {
|
|
8431
8750
|
return { stale: false };
|
|
8432
8751
|
}
|
|
8433
8752
|
let newest = -Infinity;
|
|
8434
8753
|
let newestChanged;
|
|
8435
|
-
const
|
|
8754
|
+
const MAX_ENTRIES2 = 2e4;
|
|
8436
8755
|
let scanned = 0;
|
|
8437
8756
|
const walk2 = (dir, depth) => {
|
|
8438
|
-
if (depth > 8 || scanned >
|
|
8757
|
+
if (depth > 8 || scanned > MAX_ENTRIES2) return;
|
|
8439
8758
|
let entries;
|
|
8440
8759
|
try {
|
|
8441
|
-
entries =
|
|
8760
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
8442
8761
|
} catch {
|
|
8443
8762
|
return;
|
|
8444
8763
|
}
|
|
8445
8764
|
for (const e of entries) {
|
|
8446
8765
|
scanned++;
|
|
8447
|
-
if (scanned >
|
|
8766
|
+
if (scanned > MAX_ENTRIES2) break;
|
|
8448
8767
|
if (e.isDirectory()) {
|
|
8449
|
-
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(
|
|
8768
|
+
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path38.join(dir, e.name), depth + 1);
|
|
8450
8769
|
continue;
|
|
8451
8770
|
}
|
|
8452
8771
|
if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
|
|
8453
|
-
const abs =
|
|
8772
|
+
const abs = path38.join(dir, e.name);
|
|
8454
8773
|
let mtimeMs;
|
|
8455
8774
|
try {
|
|
8456
|
-
mtimeMs =
|
|
8775
|
+
mtimeMs = fs8.statSync(abs).mtimeMs;
|
|
8457
8776
|
} catch {
|
|
8458
8777
|
continue;
|
|
8459
8778
|
}
|
|
8460
8779
|
if (mtimeMs > newest) {
|
|
8461
8780
|
newest = mtimeMs;
|
|
8462
|
-
newestChanged =
|
|
8781
|
+
newestChanged = path38.relative(rootDir, abs) || e.name;
|
|
8463
8782
|
}
|
|
8464
8783
|
}
|
|
8465
8784
|
};
|
|
@@ -8590,7 +8909,7 @@ function analyzeTree(root2, packages) {
|
|
|
8590
8909
|
if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
|
|
8591
8910
|
let entries;
|
|
8592
8911
|
try {
|
|
8593
|
-
entries =
|
|
8912
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
8594
8913
|
} catch {
|
|
8595
8914
|
return;
|
|
8596
8915
|
}
|
|
@@ -8599,17 +8918,17 @@ function analyzeTree(root2, packages) {
|
|
|
8599
8918
|
if (filesSeen >= MAX_FILES) return;
|
|
8600
8919
|
if (entry.isDirectory()) {
|
|
8601
8920
|
if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
8602
|
-
walk2(
|
|
8921
|
+
walk2(path38.join(dir, entry.name), depth + 1);
|
|
8603
8922
|
continue;
|
|
8604
8923
|
}
|
|
8605
|
-
const fileEco = EXT_ECOSYSTEM[
|
|
8924
|
+
const fileEco = EXT_ECOSYSTEM[path38.extname(entry.name)];
|
|
8606
8925
|
if (!fileEco || fileEco === "unknown") continue;
|
|
8607
8926
|
filesSeen++;
|
|
8608
|
-
const full =
|
|
8927
|
+
const full = path38.join(dir, entry.name);
|
|
8609
8928
|
let content;
|
|
8610
8929
|
try {
|
|
8611
|
-
if (
|
|
8612
|
-
content =
|
|
8930
|
+
if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
|
|
8931
|
+
content = fs8.readFileSync(full, "utf8");
|
|
8613
8932
|
} catch {
|
|
8614
8933
|
continue;
|
|
8615
8934
|
}
|
|
@@ -8920,7 +9239,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
8920
9239
|
}
|
|
8921
9240
|
const outcomes = effective.map((t) => {
|
|
8922
9241
|
const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
|
|
8923
|
-
return { t, res: run(c2,
|
|
9242
|
+
return { t, res: run(c2, path38.join(rootDir, t.dir)) };
|
|
8924
9243
|
});
|
|
8925
9244
|
const failures = outcomes.filter((o) => !o.res.ok);
|
|
8926
9245
|
if (failures.length === 0) {
|
|
@@ -8949,8 +9268,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
8949
9268
|
return results;
|
|
8950
9269
|
}
|
|
8951
9270
|
var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
|
|
8952
|
-
var CACHE_DIR =
|
|
8953
|
-
var CACHE_FILE =
|
|
9271
|
+
var CACHE_DIR = path38.join(os.homedir(), ".vibgrate");
|
|
9272
|
+
var CACHE_FILE = path38.join(CACHE_DIR, "update-check.json");
|
|
8954
9273
|
async function fetchLatestVersion() {
|
|
8955
9274
|
try {
|
|
8956
9275
|
const controller = new AbortController();
|
|
@@ -8977,8 +9296,8 @@ async function fetchLatestVersion() {
|
|
|
8977
9296
|
}
|
|
8978
9297
|
async function writeCache(data) {
|
|
8979
9298
|
try {
|
|
8980
|
-
await
|
|
8981
|
-
await
|
|
9299
|
+
await fs22.mkdir(CACHE_DIR, { recursive: true });
|
|
9300
|
+
await fs22.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
|
|
8982
9301
|
} catch {
|
|
8983
9302
|
}
|
|
8984
9303
|
}
|
|
@@ -8989,7 +9308,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
|
|
|
8989
9308
|
if (!execPath) return null;
|
|
8990
9309
|
let resolved = execPath;
|
|
8991
9310
|
try {
|
|
8992
|
-
resolved =
|
|
9311
|
+
resolved = fs8.realpathSync(execPath);
|
|
8993
9312
|
} catch {
|
|
8994
9313
|
}
|
|
8995
9314
|
const p = resolved.replace(/\\/g, "/");
|
|
@@ -9019,14 +9338,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
|
|
|
9019
9338
|
pm: "yarn",
|
|
9020
9339
|
root: () => {
|
|
9021
9340
|
const dir = tryRun("yarn global dir");
|
|
9022
|
-
return dir ?
|
|
9341
|
+
return dir ? path38.join(dir, "node_modules") : null;
|
|
9023
9342
|
}
|
|
9024
9343
|
},
|
|
9025
|
-
{ pm: "bun", root: () =>
|
|
9344
|
+
{ pm: "bun", root: () => path38.join(os.homedir(), ".bun", "install", "global", "node_modules") }
|
|
9026
9345
|
];
|
|
9027
9346
|
for (const probe of probes) {
|
|
9028
9347
|
const root2 = probe.root();
|
|
9029
|
-
if (root2 && await pathExists(
|
|
9348
|
+
if (root2 && await pathExists(path38.join(root2, pkg))) return probe.pm;
|
|
9030
9349
|
}
|
|
9031
9350
|
return null;
|
|
9032
9351
|
}
|
|
@@ -9045,15 +9364,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
|
|
|
9045
9364
|
}
|
|
9046
9365
|
}
|
|
9047
9366
|
async function detectPackageManager(cwd) {
|
|
9048
|
-
if (await pathExists(
|
|
9049
|
-
if (await pathExists(
|
|
9050
|
-
if (await pathExists(
|
|
9367
|
+
if (await pathExists(path38.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
9368
|
+
if (await pathExists(path38.join(cwd, "bun.lockb"))) return "bun";
|
|
9369
|
+
if (await pathExists(path38.join(cwd, "yarn.lock"))) return "yarn";
|
|
9051
9370
|
return "npm";
|
|
9052
9371
|
}
|
|
9053
9372
|
async function detectWorkspaceRoot(cwd) {
|
|
9054
|
-
if (await pathExists(
|
|
9373
|
+
if (await pathExists(path38.join(cwd, "pnpm-workspace.yaml"))) return true;
|
|
9055
9374
|
try {
|
|
9056
|
-
const pkgPath =
|
|
9375
|
+
const pkgPath = path38.join(cwd, "package.json");
|
|
9057
9376
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
9058
9377
|
const pkg = JSON.parse(raw);
|
|
9059
9378
|
return pkg.workspaces != null;
|
|
@@ -9078,7 +9397,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
|
|
|
9078
9397
|
}
|
|
9079
9398
|
async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
|
|
9080
9399
|
try {
|
|
9081
|
-
const pkgPath =
|
|
9400
|
+
const pkgPath = path38.join(cwd, "package.json");
|
|
9082
9401
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
9083
9402
|
const parsed = JSON.parse(raw);
|
|
9084
9403
|
if (parsed.devDependencies?.[pkg]) return "dev";
|
|
@@ -9167,8 +9486,29 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
|
|
|
9167
9486
|
process.exit(1);
|
|
9168
9487
|
}
|
|
9169
9488
|
if (opts.reap !== false) reapAndReport(cwd, latest);
|
|
9489
|
+
if (opts.reap !== false) await restartVgdAndReport();
|
|
9170
9490
|
}
|
|
9171
9491
|
);
|
|
9492
|
+
async function restartVgdAndReport() {
|
|
9493
|
+
let result;
|
|
9494
|
+
try {
|
|
9495
|
+
result = await restartVgdIfRunning();
|
|
9496
|
+
} catch {
|
|
9497
|
+
return;
|
|
9498
|
+
}
|
|
9499
|
+
if (result === "not-running") return;
|
|
9500
|
+
if (result === "restarted") {
|
|
9501
|
+
console.log(chalk7.dim("Restarted the vgd daemon on the new version."));
|
|
9502
|
+
} else if (result === "refused") {
|
|
9503
|
+
console.log(
|
|
9504
|
+
chalk7.dim("A vgd embedded in another process (e.g. vg code) is running \u2014 restart that session to pick up the update.")
|
|
9505
|
+
);
|
|
9506
|
+
} else {
|
|
9507
|
+
console.log(
|
|
9508
|
+
chalk7.dim('Could not restart the vgd daemon automatically \u2014 run "vg daemon restart" to pick up the update.')
|
|
9509
|
+
);
|
|
9510
|
+
}
|
|
9511
|
+
}
|
|
9172
9512
|
function reapAndReport(cwd, keepVersion) {
|
|
9173
9513
|
let reaped = [];
|
|
9174
9514
|
try {
|
|
@@ -9226,13 +9566,13 @@ function collectCandidates(artifact) {
|
|
|
9226
9566
|
return out2;
|
|
9227
9567
|
}
|
|
9228
9568
|
var defaultFixScanner = async (rootDir) => {
|
|
9229
|
-
const scratch =
|
|
9569
|
+
const scratch = path38.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
|
|
9230
9570
|
const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
|
|
9231
9571
|
const advanced = await loadAdvancedScanHook();
|
|
9232
9572
|
return runCoreScan(rootDir, scanOpts, advanced);
|
|
9233
9573
|
};
|
|
9234
9574
|
async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
|
|
9235
|
-
const artifactPath =
|
|
9575
|
+
const artifactPath = path38.isAbsolute(inFile) ? inFile : path38.join(rootDir, inFile);
|
|
9236
9576
|
if (await pathExists(artifactPath)) {
|
|
9237
9577
|
const staleness = scanStaleness(rootDir, artifactPath);
|
|
9238
9578
|
if (!staleness.stale) {
|
|
@@ -9259,7 +9599,7 @@ async function repositoryIdentity(rootDir, override) {
|
|
|
9259
9599
|
}
|
|
9260
9600
|
}
|
|
9261
9601
|
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) => {
|
|
9262
|
-
const rootDir =
|
|
9602
|
+
const rootDir = path38.resolve(targetPath);
|
|
9263
9603
|
if (!await pathExists(rootDir)) {
|
|
9264
9604
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
9265
9605
|
process.exit(1);
|
|
@@ -9420,7 +9760,7 @@ function emit(report, format) {
|
|
|
9420
9760
|
}
|
|
9421
9761
|
}
|
|
9422
9762
|
function relProjectDir(rootDir, projectPath) {
|
|
9423
|
-
const rel =
|
|
9763
|
+
const rel = path38.isAbsolute(projectPath) ? path38.relative(rootDir, projectPath) : projectPath;
|
|
9424
9764
|
return rel === "" ? "." : rel;
|
|
9425
9765
|
}
|
|
9426
9766
|
async function buildTargetResolver(rootDir, artifact) {
|
|
@@ -10255,7 +10595,7 @@ function formatMarkdown(artifact) {
|
|
|
10255
10595
|
|
|
10256
10596
|
// src/reporting/commands/report.ts
|
|
10257
10597
|
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) => {
|
|
10258
|
-
const artifactPath =
|
|
10598
|
+
const artifactPath = path38.resolve(opts.in);
|
|
10259
10599
|
if (!await pathExists(artifactPath)) {
|
|
10260
10600
|
console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
|
|
10261
10601
|
console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
|
|
@@ -10304,8 +10644,8 @@ function openUrl(url) {
|
|
|
10304
10644
|
// src/reporting/commands/login.ts
|
|
10305
10645
|
var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
10306
10646
|
function isInside(dir, file) {
|
|
10307
|
-
const rel =
|
|
10308
|
-
return !!rel && !rel.startsWith("..") && !
|
|
10647
|
+
const rel = path38.relative(dir, file);
|
|
10648
|
+
return !!rel && !rel.startsWith("..") && !path38.isAbsolute(rel);
|
|
10309
10649
|
}
|
|
10310
10650
|
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(
|
|
10311
10651
|
"--local",
|
|
@@ -10560,7 +10900,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
10560
10900
|
try {
|
|
10561
10901
|
const statements = [];
|
|
10562
10902
|
if (opts.from) {
|
|
10563
|
-
const fromPath =
|
|
10903
|
+
const fromPath = path38.resolve(opts.from);
|
|
10564
10904
|
if (!await pathExists(fromPath)) {
|
|
10565
10905
|
process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
|
|
10566
10906
|
`));
|
|
@@ -10578,9 +10918,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
10578
10918
|
});
|
|
10579
10919
|
const json2 = JSON.stringify(doc, null, 2);
|
|
10580
10920
|
if (opts.out) {
|
|
10581
|
-
await writeTextFile(
|
|
10921
|
+
await writeTextFile(path38.resolve(opts.out), json2 + "\n");
|
|
10582
10922
|
process.stderr.write(
|
|
10583
|
-
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${
|
|
10923
|
+
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path38.resolve(opts.out)}
|
|
10584
10924
|
`
|
|
10585
10925
|
);
|
|
10586
10926
|
} else {
|
|
@@ -10763,7 +11103,7 @@ function formatDeltaText(base, current) {
|
|
|
10763
11103
|
return lines.join("\n");
|
|
10764
11104
|
}
|
|
10765
11105
|
async function readArtifactOrExit(filePath) {
|
|
10766
|
-
const absolutePath =
|
|
11106
|
+
const absolutePath = path38.resolve(filePath);
|
|
10767
11107
|
if (!await pathExists(absolutePath)) {
|
|
10768
11108
|
console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
|
|
10769
11109
|
process.exit(1);
|
|
@@ -10780,7 +11120,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
|
|
|
10780
11120
|
const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
|
|
10781
11121
|
const body = JSON.stringify(sbom, null, 2);
|
|
10782
11122
|
if (opts.out) {
|
|
10783
|
-
await writeTextFile(
|
|
11123
|
+
await writeTextFile(path38.resolve(opts.out), body);
|
|
10784
11124
|
console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
|
|
10785
11125
|
} else {
|
|
10786
11126
|
console.log(body);
|
|
@@ -10791,7 +11131,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
|
|
|
10791
11131
|
const current = await readArtifactOrExit(opts.to);
|
|
10792
11132
|
const report = formatDeltaText(base, current);
|
|
10793
11133
|
if (opts.out) {
|
|
10794
|
-
await writeTextFile(
|
|
11134
|
+
await writeTextFile(path38.resolve(opts.out), report);
|
|
10795
11135
|
console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
|
|
10796
11136
|
} else {
|
|
10797
11137
|
console.log(report);
|
|
@@ -10922,20 +11262,20 @@ function resolveRegime(id) {
|
|
|
10922
11262
|
return regime;
|
|
10923
11263
|
}
|
|
10924
11264
|
function evidenceDir(root2) {
|
|
10925
|
-
return
|
|
11265
|
+
return path38.join(root2, ".vibgrate", "evidence");
|
|
10926
11266
|
}
|
|
10927
11267
|
function orgPath(root2) {
|
|
10928
|
-
return
|
|
11268
|
+
return path38.join(evidenceDir(root2), "org.json");
|
|
10929
11269
|
}
|
|
10930
11270
|
function productsPath(root2) {
|
|
10931
|
-
return
|
|
11271
|
+
return path38.join(evidenceDir(root2), "products.json");
|
|
10932
11272
|
}
|
|
10933
11273
|
function releasesDir(root2) {
|
|
10934
|
-
return
|
|
11274
|
+
return path38.join(evidenceDir(root2), "releases");
|
|
10935
11275
|
}
|
|
10936
11276
|
function releasePath(root2, productId, version) {
|
|
10937
11277
|
const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
10938
|
-
return
|
|
11278
|
+
return path38.join(releasesDir(root2), `${safe}.json`);
|
|
10939
11279
|
}
|
|
10940
11280
|
var DEFAULT_ORG = {
|
|
10941
11281
|
responsiblePersons: [],
|
|
@@ -10966,7 +11306,7 @@ async function freezeRelease(root2, release) {
|
|
|
10966
11306
|
const p = releasePath(root2, release.productId, release.version);
|
|
10967
11307
|
if (await pathExists(p)) {
|
|
10968
11308
|
throw new CliError(
|
|
10969
|
-
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${
|
|
11309
|
+
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path38.relative(root2, p)} only if it was frozen in error`,
|
|
10970
11310
|
ExitCode.USAGE_ERROR
|
|
10971
11311
|
);
|
|
10972
11312
|
}
|
|
@@ -10980,7 +11320,7 @@ async function loadReleases(root2, productId) {
|
|
|
10980
11320
|
const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
|
|
10981
11321
|
const releases = [];
|
|
10982
11322
|
for (const f of files) {
|
|
10983
|
-
const rel = await readJsonFile(
|
|
11323
|
+
const rel = await readJsonFile(path38.join(dir, f));
|
|
10984
11324
|
if (!productId || rel.productId === productId) releases.push(rel);
|
|
10985
11325
|
}
|
|
10986
11326
|
return releases;
|
|
@@ -11675,19 +12015,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
|
|
|
11675
12015
|
var DEFAULT_KEY = "attest-key.pem";
|
|
11676
12016
|
function resolveSigningKey(root2, explicit) {
|
|
11677
12017
|
const chosen = process.env.VG_ATTEST_KEY;
|
|
11678
|
-
const keyPath = chosen ?
|
|
12018
|
+
const keyPath = chosen ? path38.resolve(chosen) : path38.join(root2, ".vibgrate", DEFAULT_KEY);
|
|
11679
12019
|
let minted = false;
|
|
11680
|
-
if (!
|
|
12020
|
+
if (!fs8.existsSync(keyPath)) {
|
|
11681
12021
|
if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
|
|
11682
12022
|
const kp = generateKeypair();
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
12023
|
+
fs8.mkdirSync(path38.dirname(keyPath), { recursive: true });
|
|
12024
|
+
fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
|
|
12025
|
+
fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
|
|
11686
12026
|
minted = true;
|
|
11687
12027
|
}
|
|
11688
12028
|
let key2;
|
|
11689
12029
|
try {
|
|
11690
|
-
key2 = crypto3.createPrivateKey(
|
|
12030
|
+
key2 = crypto3.createPrivateKey(fs8.readFileSync(keyPath, "utf8"));
|
|
11691
12031
|
} catch {
|
|
11692
12032
|
throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
|
|
11693
12033
|
}
|
|
@@ -11698,16 +12038,16 @@ function resolveSigningKey(root2, explicit) {
|
|
|
11698
12038
|
}
|
|
11699
12039
|
function writeBundle(input) {
|
|
11700
12040
|
const dir = input.outDir;
|
|
11701
|
-
|
|
11702
|
-
const write = (rel, data) =>
|
|
12041
|
+
fs8.mkdirSync(path38.join(dir, "inputs", "releases"), { recursive: true });
|
|
12042
|
+
const write = (rel, data) => fs8.writeFileSync(path38.join(dir, rel), `${JSON.stringify(data, null, 2)}
|
|
11703
12043
|
`);
|
|
11704
12044
|
write("result.json", input.result);
|
|
11705
|
-
write(
|
|
12045
|
+
write(path38.join("inputs", "advisory.json"), input.advisory);
|
|
11706
12046
|
for (const rel of input.releases) {
|
|
11707
12047
|
const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
11708
|
-
write(
|
|
12048
|
+
write(path38.join("inputs", "releases", `${safe}.json`), rel);
|
|
11709
12049
|
}
|
|
11710
|
-
write(
|
|
12050
|
+
write(path38.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
|
|
11711
12051
|
write("provenance.json", {
|
|
11712
12052
|
method: "deterministic",
|
|
11713
12053
|
modelDrafted: [],
|
|
@@ -11723,13 +12063,13 @@ function writeBundle(input) {
|
|
|
11723
12063
|
disclaimer: input.regime.disclaimer
|
|
11724
12064
|
});
|
|
11725
12065
|
if (input.envelope) {
|
|
11726
|
-
|
|
12066
|
+
fs8.writeFileSync(path38.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
|
|
11727
12067
|
`);
|
|
11728
12068
|
}
|
|
11729
12069
|
if (input.timestampToken) {
|
|
11730
|
-
|
|
12070
|
+
fs8.writeFileSync(path38.join(dir, "timestamp.tsr"), input.timestampToken);
|
|
11731
12071
|
}
|
|
11732
|
-
|
|
12072
|
+
fs8.writeFileSync(path38.join(dir, "VERIFY.md"), verifyDoc(input));
|
|
11733
12073
|
return dir;
|
|
11734
12074
|
}
|
|
11735
12075
|
function verifyDoc(input) {
|
|
@@ -11790,13 +12130,13 @@ function undeterminedFields(result, regime) {
|
|
|
11790
12130
|
return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
|
|
11791
12131
|
}
|
|
11792
12132
|
async function recordDrill(root2, record) {
|
|
11793
|
-
const dir =
|
|
11794
|
-
const p =
|
|
12133
|
+
const dir = path38.join(evidenceDir(root2), "drills");
|
|
12134
|
+
const p = path38.join(dir, `${record.drillId}.json`);
|
|
11795
12135
|
await writeJsonFile(p, record);
|
|
11796
12136
|
return p;
|
|
11797
12137
|
}
|
|
11798
12138
|
async function hasRecentDrill(root2, asOf) {
|
|
11799
|
-
const dir =
|
|
12139
|
+
const dir = path38.join(evidenceDir(root2), "drills");
|
|
11800
12140
|
if (!await pathExists(dir)) return void 0;
|
|
11801
12141
|
const { readdir } = await import('fs/promises');
|
|
11802
12142
|
const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
|
|
@@ -11804,7 +12144,7 @@ async function hasRecentDrill(root2, asOf) {
|
|
|
11804
12144
|
if (files.length === 0) return void 0;
|
|
11805
12145
|
const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
|
|
11806
12146
|
for (const f of files) {
|
|
11807
|
-
const rec = await readJsonFile2(
|
|
12147
|
+
const rec = await readJsonFile2(path38.join(dir, f));
|
|
11808
12148
|
if (rec.ranAt >= cutoff) return true;
|
|
11809
12149
|
}
|
|
11810
12150
|
return false;
|
|
@@ -11884,7 +12224,7 @@ function formatRegimeList() {
|
|
|
11884
12224
|
|
|
11885
12225
|
// src/reporting/commands/evidence/index.ts
|
|
11886
12226
|
function root(opts) {
|
|
11887
|
-
return
|
|
12227
|
+
return path38.resolve(opts.cwd ?? process.cwd());
|
|
11888
12228
|
}
|
|
11889
12229
|
function slug(name) {
|
|
11890
12230
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
|
|
@@ -11972,7 +12312,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
11972
12312
|
const release = await buildRelease({
|
|
11973
12313
|
productId: product.id,
|
|
11974
12314
|
version,
|
|
11975
|
-
from:
|
|
12315
|
+
from: path38.resolve(rootDir, opts.from),
|
|
11976
12316
|
shipDate: opts.shipDate,
|
|
11977
12317
|
buildId: opts.buildId,
|
|
11978
12318
|
artefactDigest: opts.digest,
|
|
@@ -11980,7 +12320,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
11980
12320
|
frozenAt: nowIso()
|
|
11981
12321
|
});
|
|
11982
12322
|
const p = await freezeRelease(rootDir, release);
|
|
11983
|
-
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${
|
|
12323
|
+
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path38.relative(rootDir, p)}`);
|
|
11984
12324
|
});
|
|
11985
12325
|
async function runExposure(rootDir, vuln, opts) {
|
|
11986
12326
|
const org = await loadOrg(rootDir);
|
|
@@ -12032,7 +12372,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
12032
12372
|
console.log("\n" + buildPack(result, regime, org, stage));
|
|
12033
12373
|
}
|
|
12034
12374
|
if (opts.bundle) {
|
|
12035
|
-
const dir =
|
|
12375
|
+
const dir = path38.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
|
|
12036
12376
|
let envelope;
|
|
12037
12377
|
if (opts.sign !== false) {
|
|
12038
12378
|
const { key: key2, minted } = resolveSigningKey(rootDir);
|
|
@@ -12040,7 +12380,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
12040
12380
|
envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
|
|
12041
12381
|
}
|
|
12042
12382
|
writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
|
|
12043
|
-
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${
|
|
12383
|
+
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path38.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
|
|
12044
12384
|
}
|
|
12045
12385
|
process.exitCode = exposureExit(result.overallStatus);
|
|
12046
12386
|
});
|
|
@@ -12072,7 +12412,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
|
|
|
12072
12412
|
const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
|
|
12073
12413
|
const md = buildPack(result, regime, org, stage);
|
|
12074
12414
|
if (opts.out) {
|
|
12075
|
-
|
|
12415
|
+
fs8.writeFileSync(path38.resolve(rootDir, opts.out), md);
|
|
12076
12416
|
console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
|
|
12077
12417
|
} else {
|
|
12078
12418
|
console.log(md);
|
|
@@ -12114,20 +12454,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
|
|
|
12114
12454
|
}
|
|
12115
12455
|
});
|
|
12116
12456
|
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) => {
|
|
12117
|
-
const abs =
|
|
12118
|
-
const envPath =
|
|
12119
|
-
if (!
|
|
12120
|
-
const envelope = JSON.parse(
|
|
12121
|
-
const resultPath =
|
|
12122
|
-
const result =
|
|
12123
|
-
const publicKeyPem = opts.pub ?
|
|
12457
|
+
const abs = path38.resolve(bundlePath);
|
|
12458
|
+
const envPath = fs8.statSync(abs).isDirectory() ? path38.join(abs, "evidence.intoto.jsonl") : abs;
|
|
12459
|
+
if (!fs8.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
|
|
12460
|
+
const envelope = JSON.parse(fs8.readFileSync(envPath, "utf8").trim().split("\n")[0]);
|
|
12461
|
+
const resultPath = path38.join(path38.dirname(envPath), "result.json");
|
|
12462
|
+
const result = fs8.existsSync(resultPath) ? JSON.parse(fs8.readFileSync(resultPath, "utf8")) : void 0;
|
|
12463
|
+
const publicKeyPem = opts.pub ? fs8.readFileSync(path38.resolve(opts.pub), "utf8") : void 0;
|
|
12124
12464
|
const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
|
|
12125
12465
|
const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
|
|
12126
12466
|
console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
|
|
12127
12467
|
if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
|
|
12128
|
-
const tsrPath =
|
|
12129
|
-
if (
|
|
12130
|
-
const t = verifyTimestamp(
|
|
12468
|
+
const tsrPath = path38.join(path38.dirname(envPath), "timestamp.tsr");
|
|
12469
|
+
if (fs8.existsSync(tsrPath) && result) {
|
|
12470
|
+
const t = verifyTimestamp(fs8.readFileSync(tsrPath), exposureSubjectDigest(result));
|
|
12131
12471
|
const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
|
|
12132
12472
|
console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
|
|
12133
12473
|
}
|
|
@@ -12194,12 +12534,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
|
|
|
12194
12534
|
const releases = [];
|
|
12195
12535
|
for (const list of releasesByProduct.values()) releases.push(...list);
|
|
12196
12536
|
const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
|
|
12197
|
-
const dir =
|
|
12198
|
-
await writeJsonFile(
|
|
12199
|
-
await writeJsonFile(
|
|
12200
|
-
for (const r of releases) await writeJsonFile(
|
|
12201
|
-
await writeJsonFile(
|
|
12202
|
-
console.error(chalk7.green("\u2714") + ` exported evidence state to ${
|
|
12537
|
+
const dir = path38.resolve(rootDir, opts.out);
|
|
12538
|
+
await writeJsonFile(path38.join(dir, "org.json"), org);
|
|
12539
|
+
await writeJsonFile(path38.join(dir, "products.json"), products);
|
|
12540
|
+
for (const r of releases) await writeJsonFile(path38.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
|
|
12541
|
+
await writeJsonFile(path38.join(dir, "readiness.json"), report);
|
|
12542
|
+
console.error(chalk7.green("\u2714") + ` exported evidence state to ${path38.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
|
|
12203
12543
|
});
|
|
12204
12544
|
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) => {
|
|
12205
12545
|
const rootDir = root(opts);
|
|
@@ -12225,10 +12565,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
|
|
|
12225
12565
|
}));
|
|
12226
12566
|
let exposure;
|
|
12227
12567
|
if (opts.result) {
|
|
12228
|
-
const raw =
|
|
12229
|
-
const resultPath =
|
|
12230
|
-
if (!
|
|
12231
|
-
exposure = JSON.parse(
|
|
12568
|
+
const raw = path38.resolve(rootDir, opts.result);
|
|
12569
|
+
const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path38.join(raw, "result.json") : raw;
|
|
12570
|
+
if (!fs8.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
|
|
12571
|
+
exposure = JSON.parse(fs8.readFileSync(resultPath, "utf8"));
|
|
12232
12572
|
}
|
|
12233
12573
|
const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
|
|
12234
12574
|
const body = JSON.stringify(payload);
|
|
@@ -12418,7 +12758,7 @@ function dispatch(argv, cwd) {
|
|
|
12418
12758
|
}
|
|
12419
12759
|
const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
|
|
12420
12760
|
if (looksLikeQuestion) return ["ask", ...args];
|
|
12421
|
-
if (
|
|
12761
|
+
if (fs8.existsSync(path38.resolve(cwd, first))) {
|
|
12422
12762
|
return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
|
|
12423
12763
|
}
|
|
12424
12764
|
const moved = MOVED_COMMANDS[first];
|
|
@@ -12463,9 +12803,9 @@ async function main(argv = process.argv) {
|
|
|
12463
12803
|
}
|
|
12464
12804
|
function readCwd(raw) {
|
|
12465
12805
|
const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
|
|
12466
|
-
if (i >= 0 && raw[i + 1]) return
|
|
12806
|
+
if (i >= 0 && raw[i + 1]) return path38.resolve(raw[i + 1]);
|
|
12467
12807
|
const eq = raw.find((a) => a.startsWith("--cwd="));
|
|
12468
|
-
if (eq) return
|
|
12808
|
+
if (eq) return path38.resolve(eq.slice("--cwd=".length));
|
|
12469
12809
|
return process.cwd();
|
|
12470
12810
|
}
|
|
12471
12811
|
function handleError(err) {
|