@vibgrate/cli 2026.813.1 → 2026.814.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +258 -22
- package/NOTICE +7 -0
- package/README.md +273 -11
- package/dist/agent-5ANHRYEI.js +26 -0
- package/dist/{agent-N3CP3SPI.js.map → agent-5ANHRYEI.js.map} +1 -1
- package/dist/approvals-T2KXPJLV.js +9 -0
- package/dist/approvals-T2KXPJLV.js.map +1 -0
- package/dist/baseline-WVD6P5IO.js +9 -0
- package/dist/{baseline-ZMRZRGFI.js.map → baseline-WVD6P5IO.js.map} +1 -1
- package/dist/{checkpoint-4WFZMKEO.js → checkpoint-UYMYMMQO.js} +6 -3
- package/dist/checkpoint-UYMYMMQO.js.map +1 -0
- package/dist/chunk-2H2U3DC7.js +6 -0
- package/dist/{chunk-RT7P5AYU.js.map → chunk-2H2U3DC7.js.map} +1 -1
- package/dist/chunk-2U37PFB2.js +64 -0
- package/dist/chunk-2U37PFB2.js.map +1 -0
- package/dist/{chunk-GOPANQZT.js → chunk-54RGT2T5.js} +3 -3
- package/dist/{chunk-GOPANQZT.js.map → chunk-54RGT2T5.js.map} +1 -1
- package/dist/{chunk-OYHAF2J2.js → chunk-5GLQNMTI.js} +5 -5
- package/dist/{chunk-OYHAF2J2.js.map → chunk-5GLQNMTI.js.map} +1 -1
- package/dist/{chunk-EWZKOU66.js → chunk-75LJM5XD.js} +30 -66
- package/dist/chunk-75LJM5XD.js.map +1 -0
- package/dist/{chunk-KF2QT6RY.js → chunk-7NMXE6KG.js} +4 -4
- package/dist/{chunk-KF2QT6RY.js.map → chunk-7NMXE6KG.js.map} +1 -1
- package/dist/{chunk-UZP623Y4.js → chunk-7QDHQLUS.js} +4 -4
- package/dist/{chunk-UZP623Y4.js.map → chunk-7QDHQLUS.js.map} +1 -1
- package/dist/chunk-AJS4EL2C.js +266 -0
- package/dist/chunk-AJS4EL2C.js.map +1 -0
- package/dist/{chunk-Z3MUWXP3.js → chunk-BH54SLGZ.js} +4 -4
- package/dist/{chunk-Z3MUWXP3.js.map → chunk-BH54SLGZ.js.map} +1 -1
- package/dist/{chunk-CJNWHXQD.js → chunk-DSUGC7F5.js} +4 -4
- package/dist/{chunk-CJNWHXQD.js.map → chunk-DSUGC7F5.js.map} +1 -1
- package/dist/{chunk-FBVKQXBH.js → chunk-FOW5IF73.js} +3 -3
- package/dist/{chunk-FBVKQXBH.js.map → chunk-FOW5IF73.js.map} +1 -1
- package/dist/{chunk-6GQLEDVK.js → chunk-IHLLWBZU.js} +6 -5
- package/dist/chunk-IHLLWBZU.js.map +1 -0
- package/dist/{chunk-RHKJPTON.js → chunk-IHXNOY3R.js} +208 -56
- package/dist/chunk-IHXNOY3R.js.map +1 -0
- package/dist/{chunk-5JJBGBP2.js → chunk-JCN6MSXQ.js} +7 -7
- package/dist/{chunk-5JJBGBP2.js.map → chunk-JCN6MSXQ.js.map} +1 -1
- package/dist/{chunk-YJU7S7N6.js → chunk-KGPX4EUN.js} +4 -4
- package/dist/{chunk-YJU7S7N6.js.map → chunk-KGPX4EUN.js.map} +1 -1
- package/dist/{chunk-ADP6ITGF.js → chunk-N3XFY3PX.js} +68 -11
- package/dist/chunk-N3XFY3PX.js.map +1 -0
- package/dist/{chunk-JYM4QT6F.js → chunk-NKFXXP6W.js} +5 -5
- package/dist/{chunk-JYM4QT6F.js.map → chunk-NKFXXP6W.js.map} +1 -1
- package/dist/{chunk-5ROZODMW.js → chunk-TFAXW7VM.js} +2 -2
- package/dist/chunk-TFAXW7VM.js.map +1 -0
- package/dist/{chunk-6423BHLN.js → chunk-TNROG5CO.js} +19 -9
- package/dist/chunk-TNROG5CO.js.map +1 -0
- package/dist/chunk-TVDYEHIM.js +174 -0
- package/dist/chunk-TVDYEHIM.js.map +1 -0
- package/dist/{chunk-7ZHSSGUF.js → chunk-WQLZSVNF.js} +4 -3
- package/dist/chunk-WQLZSVNF.js.map +1 -0
- package/dist/{chunk-3WUTQYRY.js → chunk-WWGLVF7D.js} +9 -8
- package/dist/chunk-WWGLVF7D.js.map +1 -0
- package/dist/{chunk-KBP7GJV6.js → chunk-X76VPOYH.js} +19 -9
- package/dist/chunk-X76VPOYH.js.map +1 -0
- package/dist/{chunk-IJQOZ6ZD.js → chunk-YNV5M3JW.js} +8 -8
- package/dist/chunk-YNV5M3JW.js.map +1 -0
- package/dist/{chunk-Z3AYOZ3C.js → chunk-YQNTIBKS.js} +6 -6
- package/dist/{chunk-Z3AYOZ3C.js.map → chunk-YQNTIBKS.js.map} +1 -1
- package/dist/cli.js +1130 -489
- package/dist/cli.js.map +1 -1
- package/dist/embed-worker-main.js +4 -3
- package/dist/embed-worker-main.js.map +1 -1
- package/dist/{ensure-map-PHAJACFF.js → ensure-map-HQ7A5NDL.js} +15 -14
- package/dist/{ensure-map-PHAJACFF.js.map → ensure-map-HQ7A5NDL.js.map} +1 -1
- package/dist/fastembed-S6YEJYQV.js +292 -0
- package/dist/fastembed-S6YEJYQV.js.map +1 -0
- package/dist/graph-backend-W2TNTMY7.js +14 -0
- package/dist/{graph-backend-4B3MTVIW.js.map → graph-backend-W2TNTMY7.js.map} +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +14 -13
- package/dist/index.js.map +1 -1
- package/dist/{interactive-WUXMXFNM.js → interactive-EW2VJ3BZ.js} +32 -30
- package/dist/interactive-EW2VJ3BZ.js.map +1 -0
- package/dist/load-64RK5O6C.js +10 -0
- package/dist/{load-EUZSV73H.js.map → load-64RK5O6C.js.map} +1 -1
- package/dist/{run-outcome-O5PR7ZCK.js → run-outcome-6QNQIHPV.js} +6 -5
- package/dist/run-outcome-6QNQIHPV.js.map +1 -0
- package/dist/runtime-session-RJHH3KMF.js +21 -0
- package/dist/{runtime-session-PPQDTFIK.js.map → runtime-session-RJHH3KMF.js.map} +1 -1
- package/dist/session-4BGYASOH.js +16 -0
- package/dist/{session-WS7SOVJE.js.map → session-4BGYASOH.js.map} +1 -1
- package/dist/session-store-AQUORKWB.js +4 -0
- package/dist/{session-store-KGONLWHN.js.map → session-store-AQUORKWB.js.map} +1 -1
- package/dist/{stream-json-7MK3QQYG.js → stream-json-GY5N7WZT.js} +76 -24
- package/dist/stream-json-GY5N7WZT.js.map +1 -0
- package/dist/version-DPAMQW6M.js +4 -0
- package/dist/version-DPAMQW6M.js.map +1 -0
- package/dist/{vg-mcp-bridge-DQLCHBI6.js → vg-mcp-bridge-IGHJKKSL.js} +11 -10
- package/dist/vg-mcp-bridge-IGHJKKSL.js.map +1 -0
- package/dist/{vgd-Y25XSQGZ.js → vgd-ORPA5C2K.js} +12 -11
- package/dist/vgd-ORPA5C2K.js.map +1 -0
- package/dist/worktree-session-D575IQWM.js +82 -0
- package/dist/worktree-session-D575IQWM.js.map +1 -0
- package/package.json +4 -2
- package/dist/agent-N3CP3SPI.js +0 -24
- package/dist/baseline-ZMRZRGFI.js +0 -9
- package/dist/checkpoint-4WFZMKEO.js.map +0 -1
- package/dist/chunk-3WUTQYRY.js.map +0 -1
- package/dist/chunk-5ROZODMW.js.map +0 -1
- package/dist/chunk-6423BHLN.js.map +0 -1
- package/dist/chunk-6GQLEDVK.js.map +0 -1
- package/dist/chunk-7ZHSSGUF.js.map +0 -1
- package/dist/chunk-ADP6ITGF.js.map +0 -1
- package/dist/chunk-EWZKOU66.js.map +0 -1
- package/dist/chunk-IJQOZ6ZD.js.map +0 -1
- package/dist/chunk-KBP7GJV6.js.map +0 -1
- package/dist/chunk-RHKJPTON.js.map +0 -1
- package/dist/chunk-RT7P5AYU.js +0 -6
- package/dist/chunk-Z7FM3ETS.js +0 -126
- package/dist/chunk-Z7FM3ETS.js.map +0 -1
- package/dist/graph-backend-4B3MTVIW.js +0 -13
- package/dist/interactive-WUXMXFNM.js.map +0 -1
- package/dist/load-EUZSV73H.js +0 -9
- package/dist/run-outcome-O5PR7ZCK.js.map +0 -1
- package/dist/runtime-session-PPQDTFIK.js +0 -20
- package/dist/session-WS7SOVJE.js +0 -15
- package/dist/session-store-KGONLWHN.js +0 -4
- package/dist/stream-json-7MK3QQYG.js.map +0 -1
- package/dist/vg-mcp-bridge-DQLCHBI6.js.map +0 -1
- package/dist/vgd-Y25XSQGZ.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,59 +1,61 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { fetchCatalog, resolveProviders } from './chunk-5GLQNMTI.js';
|
|
3
|
+
import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-7NMXE6KG.js';
|
|
4
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-TFAXW7VM.js';
|
|
5
|
+
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, runBuild } from './chunk-JCN6MSXQ.js';
|
|
6
|
+
export { runBuild } from './chunk-JCN6MSXQ.js';
|
|
7
|
+
import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
|
|
8
|
+
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-NKFXXP6W.js';
|
|
5
9
|
import './chunk-IS7VTH2Q.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
10
|
+
import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-JFE7XCAE.js';
|
|
11
|
+
import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-3LOWJSAF.js';
|
|
12
|
+
import { runCodeSession } from './chunk-YQNTIBKS.js';
|
|
13
|
+
import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-IHXNOY3R.js';
|
|
9
14
|
import './chunk-543E6WDJ.js';
|
|
10
|
-
import
|
|
15
|
+
import './chunk-TVDYEHIM.js';
|
|
16
|
+
import './chunk-54RGT2T5.js';
|
|
17
|
+
import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
|
|
18
|
+
import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
|
|
19
|
+
import { parseReasoningEffort, summarizeDiffs, ScriptedProvider } from './chunk-N3XFY3PX.js';
|
|
11
20
|
import './chunk-7AVYKZEM.js';
|
|
12
21
|
import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
|
|
13
22
|
import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
|
|
14
|
-
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, runBuild } from './chunk-5JJBGBP2.js';
|
|
15
|
-
export { runBuild } from './chunk-5JJBGBP2.js';
|
|
16
|
-
import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
|
|
17
23
|
import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
|
|
18
24
|
import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
|
|
19
25
|
import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
|
|
20
26
|
import './chunk-IZDH67DX.js';
|
|
21
|
-
import './chunk-
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
|
|
26
|
-
import { serveStdio, isRelevantChange, exportGraph, GraphSource, createServer, formatForExt, RefreshScheduler } from './chunk-IJQOZ6ZD.js';
|
|
27
|
-
import { refreshIfStale } from './chunk-6GQLEDVK.js';
|
|
28
|
-
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-CJNWHXQD.js';
|
|
29
|
-
import { CliError, ExitCode, driftCount, ASSISTANTS, detectAssistants, isAssistantInstalled, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, isSkippedDirName, SKIP_FILES, SKIP_DIRS } from './chunk-6423BHLN.js';
|
|
30
|
-
import { resolveDsn, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-3WUTQYRY.js';
|
|
31
|
-
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, perDependencyDrift } from './chunk-N6ZMZ5AI.js';
|
|
27
|
+
import { serveStdio, isRelevantChange, exportGraph, GraphSource, createServer, formatForExt, RefreshScheduler } from './chunk-YNV5M3JW.js';
|
|
28
|
+
import { refreshIfStale } from './chunk-IHLLWBZU.js';
|
|
29
|
+
import { CliError, ExitCode, driftCount, ASSISTANTS, detectAssistants, isAssistantInstalled, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, engineUnavailable, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, isSkippedDirName, SKIP_FILES, SKIP_DIRS } from './chunk-TNROG5CO.js';
|
|
30
|
+
import { resolveDsn, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-WWGLVF7D.js';
|
|
32
31
|
import { resolveIngestHost, dashHostForIngestHost, availableRegionIds, ingestHostForRegionId } from './chunk-HTLDXEHW.js';
|
|
32
|
+
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, perDependencyDrift } from './chunk-N6ZMZ5AI.js';
|
|
33
33
|
import './chunk-VIWZ4QT7.js';
|
|
34
|
-
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-
|
|
34
|
+
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-7QDHQLUS.js';
|
|
35
|
+
import { resolveOne } from './chunk-J7LKEB2R.js';
|
|
36
|
+
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-DSUGC7F5.js';
|
|
37
|
+
import { queryGraphSemantic, queryGraph, indexFor, impactOf } from './chunk-KGPX4EUN.js';
|
|
35
38
|
import { discoverModels } from './chunk-CQDUBAQY.js';
|
|
36
39
|
import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
|
|
40
|
+
import { loadGraph, loadGraphPreferIndex, SCHEMA_VERSION } from './chunk-WQLZSVNF.js';
|
|
37
41
|
import './chunk-5I4VSBWQ.js';
|
|
38
42
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-DT4KIVRI.js';
|
|
39
43
|
import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
|
|
40
44
|
import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
|
|
41
|
-
import { resolveOne } from './chunk-J7LKEB2R.js';
|
|
42
|
-
import { queryGraphSemantic, queryGraph, indexFor, impactOf } from './chunk-YJU7S7N6.js';
|
|
43
45
|
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
|
|
44
46
|
import './chunk-RXP66R2E.js';
|
|
45
|
-
import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, unavailableMessage, countPending, modelCacheInfo, embeddingsPath, clearModelCache, withTimeout } from './chunk-
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
48
|
-
import { VERSION } from './chunk-
|
|
47
|
+
import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, unavailableMessage, countPending, modelCacheInfo, embeddingsPath, clearModelCache, withTimeout } from './chunk-X76VPOYH.js';
|
|
48
|
+
import { cacheDir } from './chunk-2U37PFB2.js';
|
|
49
|
+
import { resetRelevanceProviderCache, loadRelevanceProvider, relevanceModuleDir, resolveGraphPath, analyzeQuestion, loadTopicTags, renderReport, loadGraphFileWithSnapshot, serializeGraph, stableStringify, writeArtifacts, vibgrateDir, mapFileExists, parseGraph, ensureVibgrateGitignore } from './chunk-75LJM5XD.js';
|
|
50
|
+
import { VERSION } from './chunk-2H2U3DC7.js';
|
|
49
51
|
import './chunk-BWPBB45M.js';
|
|
50
52
|
import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
|
|
51
53
|
import './chunk-BPF3YX2U.js';
|
|
52
54
|
import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
|
|
53
|
-
import * as
|
|
54
|
-
import
|
|
55
|
-
import * as
|
|
56
|
-
import
|
|
55
|
+
import * as fs12 from 'fs';
|
|
56
|
+
import fs12__default, { realpathSync } from 'fs';
|
|
57
|
+
import * as path43 from 'path';
|
|
58
|
+
import path43__default from 'path';
|
|
57
59
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
58
60
|
import { Command, CommanderError, Option } from 'commander';
|
|
59
61
|
import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
|
|
@@ -65,7 +67,7 @@ import * as zlib from 'zlib';
|
|
|
65
67
|
import * as crypto3 from 'crypto';
|
|
66
68
|
import { randomUUID, createHash } from 'crypto';
|
|
67
69
|
import chalk7 from 'chalk';
|
|
68
|
-
import * as
|
|
70
|
+
import * as fs27 from 'fs/promises';
|
|
69
71
|
|
|
70
72
|
init_cli_invocation();
|
|
71
73
|
function registerStatus(program) {
|
|
@@ -75,10 +77,10 @@ function registerStatus(program) {
|
|
|
75
77
|
applyGlobalOptions(cmd);
|
|
76
78
|
}
|
|
77
79
|
async function runStatus(global) {
|
|
78
|
-
const root2 =
|
|
80
|
+
const root2 = path43.resolve(global.cwd ?? ".");
|
|
79
81
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
80
82
|
const graph = loadGraph(root2, graphPath);
|
|
81
|
-
const hasCache =
|
|
83
|
+
const hasCache = fs12.existsSync(path43.join(cacheDir(root2), "parse-cache.json"));
|
|
82
84
|
let stale = null;
|
|
83
85
|
let staleExact = false;
|
|
84
86
|
if (graph) {
|
|
@@ -98,8 +100,8 @@ async function runStatus(global) {
|
|
|
98
100
|
}
|
|
99
101
|
if (global.json) {
|
|
100
102
|
json({
|
|
101
|
-
root:
|
|
102
|
-
graphPath:
|
|
103
|
+
root: path43.relative(process.cwd(), root2) || ".",
|
|
104
|
+
graphPath: path43.relative(root2, graphPath),
|
|
103
105
|
built: graph !== null,
|
|
104
106
|
generatedAt: graph?.generatedAt ?? null,
|
|
105
107
|
counts: graph?.meta.counts ?? null,
|
|
@@ -114,11 +116,11 @@ async function runStatus(global) {
|
|
|
114
116
|
return;
|
|
115
117
|
}
|
|
116
118
|
if (!graph) {
|
|
117
|
-
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(
|
|
119
|
+
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path43.relative(root2, graphPath))}`);
|
|
118
120
|
info(` run ${c.bold("vg")} to build one`);
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
|
-
info(`${c.cyan("vg")} \xB7 ${
|
|
123
|
+
info(`${c.cyan("vg")} \xB7 ${path43.relative(root2, graphPath)}`);
|
|
122
124
|
info(` generated ${graph.generatedAt}`);
|
|
123
125
|
info(
|
|
124
126
|
` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
|
|
@@ -135,7 +137,7 @@ async function runStatus(global) {
|
|
|
135
137
|
if (vibgrateDir(root2)) ;
|
|
136
138
|
}
|
|
137
139
|
function rootOf(global) {
|
|
138
|
-
return
|
|
140
|
+
return path43.resolve(global.cwd ?? ".");
|
|
139
141
|
}
|
|
140
142
|
function requireGraph(global) {
|
|
141
143
|
const root2 = rootOf(global);
|
|
@@ -242,18 +244,19 @@ function registerAsk(program) {
|
|
|
242
244
|
applyGlobalOptions(cmd);
|
|
243
245
|
}
|
|
244
246
|
function crashedMessage(signal) {
|
|
245
|
-
|
|
247
|
+
const envPrefix = process.platform === "linux" ? "ONNXRUNTIME_NODE_INSTALL=skip " : "";
|
|
248
|
+
return `semantic search is disabled: its native backend (onnxruntime-node, via the vendored fastembed path) crashed with ${signal} \u2014 using fast lexical search instead. This usually means the installed native binaries are broken (an interrupted install, or a platform without prebuilt CPU binaries). Reinstall to repair \u2014 ${envPrefix}npm install -g --allow-scripts=@vibgrate/cli,onnxruntime-node,msgpackr-extract @vibgrate/cli \u2014 or run with --local to stay lexical quietly.`;
|
|
246
249
|
}
|
|
247
250
|
function defaultCacheDir() {
|
|
248
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
249
|
-
return
|
|
251
|
+
const base = process.env.XDG_CACHE_HOME || path43.join(os.homedir(), ".cache");
|
|
252
|
+
return path43.join(base, "vibgrate", "models");
|
|
250
253
|
}
|
|
251
254
|
function verdictPath(dir) {
|
|
252
|
-
return
|
|
255
|
+
return path43.join(dir, `embed-health-${process.platform}-${process.arch}.json`);
|
|
253
256
|
}
|
|
254
257
|
function readVerdict(dir) {
|
|
255
258
|
try {
|
|
256
|
-
const raw = JSON.parse(
|
|
259
|
+
const raw = JSON.parse(fs12.readFileSync(verdictPath(dir), "utf8"));
|
|
257
260
|
if (raw?.status !== "ok" && raw?.status !== "crashed") return null;
|
|
258
261
|
if (raw.version !== VERSION) return null;
|
|
259
262
|
return raw;
|
|
@@ -263,18 +266,18 @@ function readVerdict(dir) {
|
|
|
263
266
|
}
|
|
264
267
|
function writeVerdict(dir, verdict) {
|
|
265
268
|
try {
|
|
266
|
-
|
|
267
|
-
|
|
269
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
270
|
+
fs12.writeFileSync(verdictPath(dir), JSON.stringify(verdict, null, 2) + "\n", "utf8");
|
|
268
271
|
} catch {
|
|
269
272
|
}
|
|
270
273
|
}
|
|
271
274
|
function probeModuleUrl(from = import.meta.url) {
|
|
272
|
-
const dir =
|
|
275
|
+
const dir = path43.dirname(fileURLToPath(from));
|
|
273
276
|
for (const name of ["embeddings.js", "index.js"]) {
|
|
274
|
-
const candidate =
|
|
275
|
-
if (
|
|
277
|
+
const candidate = path43.join(dir, name);
|
|
278
|
+
if (fs12.existsSync(candidate)) return pathToFileURL(candidate).href;
|
|
276
279
|
}
|
|
277
|
-
return pathToFileURL(
|
|
280
|
+
return pathToFileURL(path43.join(dir, "index.js")).href;
|
|
278
281
|
}
|
|
279
282
|
function defaultRunProbe(timeoutMs) {
|
|
280
283
|
const moduleUrl = probeModuleUrl();
|
|
@@ -293,7 +296,7 @@ function defaultRunProbe(timeoutMs) {
|
|
|
293
296
|
})
|
|
294
297
|
.catch(() => process.stdout.write('{"ok":false}'));
|
|
295
298
|
`;
|
|
296
|
-
return new Promise((
|
|
299
|
+
return new Promise((resolve23) => {
|
|
297
300
|
const child = spawn(process.execPath, ["--input-type=module", "-e", script], {
|
|
298
301
|
stdio: ["ignore", "pipe", "ignore"],
|
|
299
302
|
// The probe must never inherit a debugger port or loader flags that would
|
|
@@ -306,7 +309,7 @@ function defaultRunProbe(timeoutMs) {
|
|
|
306
309
|
if (settled) return;
|
|
307
310
|
settled = true;
|
|
308
311
|
clearTimeout(timer);
|
|
309
|
-
|
|
312
|
+
resolve23({ signal, status, stdout });
|
|
310
313
|
};
|
|
311
314
|
const timer = setTimeout(() => {
|
|
312
315
|
child.kill("SIGTERM");
|
|
@@ -349,7 +352,7 @@ async function embedderHealth(options = {}) {
|
|
|
349
352
|
}
|
|
350
353
|
function clearEmbedderHealth(cacheDir2) {
|
|
351
354
|
try {
|
|
352
|
-
|
|
355
|
+
fs12.unlinkSync(verdictPath(cacheDir2 ?? defaultCacheDir()));
|
|
353
356
|
} catch {
|
|
354
357
|
}
|
|
355
358
|
}
|
|
@@ -1019,12 +1022,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
|
|
|
1019
1022
|
var KEEPALIVE_MS = 1e4;
|
|
1020
1023
|
var STALE_MS = 6e4;
|
|
1021
1024
|
function liveStatsDir(root2) {
|
|
1022
|
-
return
|
|
1025
|
+
return path43.join(cacheDir(root2), "serve-live");
|
|
1023
1026
|
}
|
|
1024
1027
|
function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
|
|
1025
1028
|
let entries;
|
|
1026
1029
|
try {
|
|
1027
|
-
entries =
|
|
1030
|
+
entries = fs12.readdirSync(dir);
|
|
1028
1031
|
} catch {
|
|
1029
1032
|
return [];
|
|
1030
1033
|
}
|
|
@@ -1033,7 +1036,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
|
|
|
1033
1036
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1034
1037
|
let parsed;
|
|
1035
1038
|
try {
|
|
1036
|
-
parsed = JSON.parse(
|
|
1039
|
+
parsed = JSON.parse(fs12.readFileSync(path43.join(dir, name), "utf8"));
|
|
1037
1040
|
} catch {
|
|
1038
1041
|
continue;
|
|
1039
1042
|
}
|
|
@@ -1055,7 +1058,7 @@ var LiveStatsBus = class {
|
|
|
1055
1058
|
this.dir = dir;
|
|
1056
1059
|
this.stats = stats;
|
|
1057
1060
|
this.pid = pid;
|
|
1058
|
-
this.file =
|
|
1061
|
+
this.file = path43.join(dir, `serve-${this.pid}.json`);
|
|
1059
1062
|
}
|
|
1060
1063
|
dir;
|
|
1061
1064
|
stats;
|
|
@@ -1087,10 +1090,10 @@ var LiveStatsBus = class {
|
|
|
1087
1090
|
this.lastWriteAt = now;
|
|
1088
1091
|
const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
|
|
1089
1092
|
try {
|
|
1090
|
-
|
|
1093
|
+
fs12.mkdirSync(this.dir, { recursive: true });
|
|
1091
1094
|
const tmp = `${this.file}.tmp`;
|
|
1092
|
-
|
|
1093
|
-
|
|
1095
|
+
fs12.writeFileSync(tmp, JSON.stringify(body));
|
|
1096
|
+
fs12.renameSync(tmp, this.file);
|
|
1094
1097
|
} catch {
|
|
1095
1098
|
}
|
|
1096
1099
|
}
|
|
@@ -1101,24 +1104,24 @@ var LiveStatsBus = class {
|
|
|
1101
1104
|
siblings(now = Date.now()) {
|
|
1102
1105
|
let entries;
|
|
1103
1106
|
try {
|
|
1104
|
-
entries =
|
|
1107
|
+
entries = fs12.readdirSync(this.dir);
|
|
1105
1108
|
} catch {
|
|
1106
1109
|
return [];
|
|
1107
1110
|
}
|
|
1108
1111
|
const out2 = [];
|
|
1109
1112
|
for (const name of entries.sort()) {
|
|
1110
1113
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1111
|
-
const file =
|
|
1114
|
+
const file = path43.join(this.dir, name);
|
|
1112
1115
|
let parsed;
|
|
1113
1116
|
try {
|
|
1114
|
-
parsed = JSON.parse(
|
|
1117
|
+
parsed = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
1115
1118
|
} catch {
|
|
1116
1119
|
continue;
|
|
1117
1120
|
}
|
|
1118
1121
|
if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
|
|
1119
1122
|
if (now - parsed.updatedAt > STALE_MS) {
|
|
1120
1123
|
try {
|
|
1121
|
-
|
|
1124
|
+
fs12.unlinkSync(file);
|
|
1122
1125
|
} catch {
|
|
1123
1126
|
}
|
|
1124
1127
|
continue;
|
|
@@ -1130,7 +1133,7 @@ var LiveStatsBus = class {
|
|
|
1130
1133
|
}
|
|
1131
1134
|
unlinkOwn = () => {
|
|
1132
1135
|
try {
|
|
1133
|
-
|
|
1136
|
+
fs12.unlinkSync(this.file);
|
|
1134
1137
|
} catch {
|
|
1135
1138
|
}
|
|
1136
1139
|
};
|
|
@@ -1443,12 +1446,12 @@ var LedgerTail = class {
|
|
|
1443
1446
|
if (size === this.offset) return;
|
|
1444
1447
|
let chunk;
|
|
1445
1448
|
try {
|
|
1446
|
-
const fd =
|
|
1449
|
+
const fd = fs12.openSync(this.file, "r");
|
|
1447
1450
|
try {
|
|
1448
1451
|
chunk = Buffer.alloc(size - this.offset);
|
|
1449
|
-
|
|
1452
|
+
fs12.readSync(fd, chunk, 0, chunk.length, this.offset);
|
|
1450
1453
|
} finally {
|
|
1451
|
-
|
|
1454
|
+
fs12.closeSync(fd);
|
|
1452
1455
|
}
|
|
1453
1456
|
} catch {
|
|
1454
1457
|
return;
|
|
@@ -1461,7 +1464,7 @@ var LedgerTail = class {
|
|
|
1461
1464
|
}
|
|
1462
1465
|
sizeOf() {
|
|
1463
1466
|
try {
|
|
1464
|
-
return
|
|
1467
|
+
return fs12.statSync(this.file).size;
|
|
1465
1468
|
} catch {
|
|
1466
1469
|
return 0;
|
|
1467
1470
|
}
|
|
@@ -1640,7 +1643,7 @@ async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
|
|
|
1640
1643
|
info(c.red(`vg serve: request error: ${err.message}`));
|
|
1641
1644
|
}
|
|
1642
1645
|
});
|
|
1643
|
-
await new Promise((
|
|
1646
|
+
await new Promise((resolve23) => httpServer.listen(port, host, resolve23));
|
|
1644
1647
|
info(c.dim(`vg \xB7 MCP server on http://${host}:${port}/mcp (read-only, local, ${freshness})`));
|
|
1645
1648
|
onReady?.();
|
|
1646
1649
|
await new Promise(() => {
|
|
@@ -1854,19 +1857,19 @@ function endOfLine(text, line) {
|
|
|
1854
1857
|
}
|
|
1855
1858
|
var CACHE_VERSION = "vg-lsp-scan-cache/2";
|
|
1856
1859
|
function cachePath(root2) {
|
|
1857
|
-
return
|
|
1860
|
+
return path43.join(cacheDir(root2), "lsp-scan.json");
|
|
1858
1861
|
}
|
|
1859
1862
|
function manifestHash(root2) {
|
|
1860
1863
|
const files = [];
|
|
1861
1864
|
const walk2 = (dir) => {
|
|
1862
1865
|
let entries;
|
|
1863
1866
|
try {
|
|
1864
|
-
entries =
|
|
1867
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
1865
1868
|
} catch {
|
|
1866
1869
|
return;
|
|
1867
1870
|
}
|
|
1868
1871
|
for (const entry of entries) {
|
|
1869
|
-
const abs =
|
|
1872
|
+
const abs = path43.join(dir, entry.name);
|
|
1870
1873
|
if (entry.isDirectory()) {
|
|
1871
1874
|
if (isSkippedDirName(entry.name)) continue;
|
|
1872
1875
|
walk2(abs);
|
|
@@ -1876,8 +1879,8 @@ function manifestHash(root2) {
|
|
|
1876
1879
|
const base = entry.name.toLowerCase();
|
|
1877
1880
|
if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
|
|
1878
1881
|
try {
|
|
1879
|
-
const rel =
|
|
1880
|
-
files.push({ rel, hash: hashBytes(
|
|
1882
|
+
const rel = path43.relative(root2, abs).split(path43.sep).join("/");
|
|
1883
|
+
files.push({ rel, hash: hashBytes(fs12.readFileSync(abs)) });
|
|
1881
1884
|
} catch {
|
|
1882
1885
|
}
|
|
1883
1886
|
}
|
|
@@ -1887,16 +1890,16 @@ function manifestHash(root2) {
|
|
|
1887
1890
|
return hashString(canonicalize(files));
|
|
1888
1891
|
}
|
|
1889
1892
|
function isDependencyFile(root2, filePath) {
|
|
1890
|
-
const rel =
|
|
1891
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
1892
|
-
const parts = rel.split(
|
|
1893
|
+
const rel = path43.relative(path43.resolve(root2), path43.resolve(filePath));
|
|
1894
|
+
if (rel === "" || rel.startsWith("..") || path43.isAbsolute(rel)) return false;
|
|
1895
|
+
const parts = rel.split(path43.sep);
|
|
1893
1896
|
if (parts.slice(0, -1).some((dir) => isSkippedDirName(dir))) return false;
|
|
1894
1897
|
const base = parts[parts.length - 1].toLowerCase();
|
|
1895
1898
|
return isManifest(filePath) || SKIP_FILES.has(base);
|
|
1896
1899
|
}
|
|
1897
1900
|
function loadScanCache(root2, key2) {
|
|
1898
1901
|
try {
|
|
1899
|
-
const raw = JSON.parse(
|
|
1902
|
+
const raw = JSON.parse(fs12.readFileSync(cachePath(root2), "utf8"));
|
|
1900
1903
|
if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
|
|
1901
1904
|
return { manifestHash: raw.manifestHash, artifact: raw.artifact };
|
|
1902
1905
|
}
|
|
@@ -1906,8 +1909,8 @@ function loadScanCache(root2, key2) {
|
|
|
1906
1909
|
}
|
|
1907
1910
|
function writeScanCache(root2, key2, artifact) {
|
|
1908
1911
|
try {
|
|
1909
|
-
|
|
1910
|
-
|
|
1912
|
+
fs12.mkdirSync(cacheDir(root2), { recursive: true });
|
|
1913
|
+
fs12.writeFileSync(
|
|
1911
1914
|
cachePath(root2),
|
|
1912
1915
|
stableStringify(
|
|
1913
1916
|
{ version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
|
|
@@ -1920,7 +1923,7 @@ function writeScanCache(root2, key2, artifact) {
|
|
|
1920
1923
|
var MAX_ENTRIES = 1e3;
|
|
1921
1924
|
var KEEP_ENTRIES = 500;
|
|
1922
1925
|
function historyPath(root2) {
|
|
1923
|
-
return
|
|
1926
|
+
return path43.join(root2, ".vibgrate", "score-history.jsonl");
|
|
1924
1927
|
}
|
|
1925
1928
|
function parseLine(line) {
|
|
1926
1929
|
try {
|
|
@@ -1934,7 +1937,7 @@ function parseLine(line) {
|
|
|
1934
1937
|
}
|
|
1935
1938
|
function readHistory(root2) {
|
|
1936
1939
|
try {
|
|
1937
|
-
return
|
|
1940
|
+
return fs12.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
|
|
1938
1941
|
} catch {
|
|
1939
1942
|
return [];
|
|
1940
1943
|
}
|
|
@@ -1961,14 +1964,14 @@ function recordScore(root2, entry) {
|
|
|
1961
1964
|
}
|
|
1962
1965
|
}
|
|
1963
1966
|
const file = historyPath(root2);
|
|
1964
|
-
|
|
1967
|
+
fs12.mkdirSync(path43.dirname(file), { recursive: true });
|
|
1965
1968
|
ensureVibgrateGitignore(root2);
|
|
1966
|
-
|
|
1969
|
+
fs12.appendFileSync(file, `${JSON.stringify(entry)}
|
|
1967
1970
|
`);
|
|
1968
1971
|
const all = readHistory(root2);
|
|
1969
1972
|
if (all.length > MAX_ENTRIES) {
|
|
1970
1973
|
const kept = all.slice(-KEEP_ENTRIES);
|
|
1971
|
-
|
|
1974
|
+
fs12.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
1972
1975
|
}
|
|
1973
1976
|
} catch {
|
|
1974
1977
|
}
|
|
@@ -2311,8 +2314,8 @@ async function enrichVulns(ecosystem, name, version, opts = { offline: false })
|
|
|
2311
2314
|
if (!ecosystem || !version) return { vulns: [], cveCount: 0, source: "error" };
|
|
2312
2315
|
if (opts.offline) return { vulns: [], cveCount: 0, source: "offline" };
|
|
2313
2316
|
const k = key(ecosystem, name, version);
|
|
2314
|
-
const
|
|
2315
|
-
if (
|
|
2317
|
+
const cached2 = cache.get(k);
|
|
2318
|
+
if (cached2) return { ...cached2, source: "cache" };
|
|
2316
2319
|
try {
|
|
2317
2320
|
const controller = new AbortController();
|
|
2318
2321
|
const timer = setTimeout(() => controller.abort(), 8e3);
|
|
@@ -2624,10 +2627,10 @@ var VibgrateLanguageServer = class {
|
|
|
2624
2627
|
this.forceNextScan = false;
|
|
2625
2628
|
try {
|
|
2626
2629
|
const cacheKey = { manifestHash: manifestHash(this.opts.root), toolVersion: VERSION, offline: this.opts.offline };
|
|
2627
|
-
const
|
|
2630
|
+
const cached2 = force ? null : loadScanCache(this.opts.root, cacheKey);
|
|
2628
2631
|
let fromCache = false;
|
|
2629
|
-
if (
|
|
2630
|
-
this.artifact = pruneArtifactProjects(
|
|
2632
|
+
if (cached2) {
|
|
2633
|
+
this.artifact = pruneArtifactProjects(cached2.artifact);
|
|
2631
2634
|
fromCache = true;
|
|
2632
2635
|
} else {
|
|
2633
2636
|
const scanOpts = {
|
|
@@ -2940,10 +2943,10 @@ var VibgrateLanguageServer = class {
|
|
|
2940
2943
|
const ecosystem = osvEcosystem(proj.type);
|
|
2941
2944
|
if (!ecosystem) continue;
|
|
2942
2945
|
const relManifest = manifestRelativePath(proj);
|
|
2943
|
-
const absManifest =
|
|
2946
|
+
const absManifest = path43.resolve(this.opts.root, relManifest);
|
|
2944
2947
|
let text = null;
|
|
2945
2948
|
try {
|
|
2946
|
-
if (
|
|
2949
|
+
if (fs12.existsSync(absManifest)) text = fs12.readFileSync(absManifest, "utf8");
|
|
2947
2950
|
} catch {
|
|
2948
2951
|
text = null;
|
|
2949
2952
|
}
|
|
@@ -3092,7 +3095,7 @@ function pruneArtifactProjects(a) {
|
|
|
3092
3095
|
return { ...a, projects, findings };
|
|
3093
3096
|
}
|
|
3094
3097
|
function projectByPath(a, projectPath) {
|
|
3095
|
-
const norm = (p) =>
|
|
3098
|
+
const norm = (p) => path43.normalize((p === "" ? "." : p).replace(/\\/g, "/"));
|
|
3096
3099
|
const want = norm(projectPath);
|
|
3097
3100
|
for (const proj of a.projects ?? []) {
|
|
3098
3101
|
if (norm(proj.path) === want) return proj;
|
|
@@ -3131,12 +3134,12 @@ function buildProjectRefs(rootDir, projects) {
|
|
|
3131
3134
|
return refs.length > 0 ? refs : void 0;
|
|
3132
3135
|
}
|
|
3133
3136
|
function projectForFile(root2, a, filePath) {
|
|
3134
|
-
const dir =
|
|
3137
|
+
const dir = path43.dirname(path43.resolve(filePath));
|
|
3135
3138
|
let best;
|
|
3136
3139
|
let bestLen = -1;
|
|
3137
3140
|
for (const proj of a.projects ?? []) {
|
|
3138
|
-
const projDir =
|
|
3139
|
-
if ((dir === projDir || dir.startsWith(projDir +
|
|
3141
|
+
const projDir = path43.resolve(root2, proj.path);
|
|
3142
|
+
if ((dir === projDir || dir.startsWith(projDir + path43.sep)) && projDir.length > bestLen) {
|
|
3140
3143
|
best = proj;
|
|
3141
3144
|
bestLen = projDir.length;
|
|
3142
3145
|
}
|
|
@@ -3144,7 +3147,7 @@ function projectForFile(root2, a, filePath) {
|
|
|
3144
3147
|
return best;
|
|
3145
3148
|
}
|
|
3146
3149
|
function sameProject(location, projectPath) {
|
|
3147
|
-
return
|
|
3150
|
+
return path43.normalize(location) === path43.normalize(projectPath);
|
|
3148
3151
|
}
|
|
3149
3152
|
function hasReleaseDates(a) {
|
|
3150
3153
|
for (const proj of a.projects ?? []) {
|
|
@@ -3214,10 +3217,10 @@ function buildBreakdown(rootDir, projects) {
|
|
|
3214
3217
|
const relManifest = manifestRelativePath(p);
|
|
3215
3218
|
if (isPrunedWorkspacePath(p.path) || isPrunedWorkspacePath(relManifest)) continue;
|
|
3216
3219
|
const ecosystem = osvEcosystem(p.type);
|
|
3217
|
-
const absManifest =
|
|
3220
|
+
const absManifest = path43.resolve(rootDir, relManifest);
|
|
3218
3221
|
let text = null;
|
|
3219
3222
|
try {
|
|
3220
|
-
if (
|
|
3223
|
+
if (fs12.existsSync(absManifest)) text = fs12.readFileSync(absManifest, "utf8");
|
|
3221
3224
|
} catch {
|
|
3222
3225
|
text = null;
|
|
3223
3226
|
}
|
|
@@ -3282,34 +3285,34 @@ function buildBreakdown(rootDir, projects) {
|
|
|
3282
3285
|
}
|
|
3283
3286
|
function manifestRelativePath(proj) {
|
|
3284
3287
|
const base = proj.path === "." || proj.path === "" ? "" : proj.path;
|
|
3285
|
-
const
|
|
3288
|
+
const join33 = (name) => base ? path43.join(base, name) : name;
|
|
3286
3289
|
switch (proj.type) {
|
|
3287
3290
|
case "node":
|
|
3288
3291
|
case "typescript":
|
|
3289
|
-
return
|
|
3292
|
+
return join33("package.json");
|
|
3290
3293
|
case "python":
|
|
3291
|
-
return
|
|
3294
|
+
return join33("pyproject.toml");
|
|
3292
3295
|
case "go":
|
|
3293
|
-
return
|
|
3296
|
+
return join33("go.mod");
|
|
3294
3297
|
case "rust":
|
|
3295
|
-
return
|
|
3298
|
+
return join33("Cargo.toml");
|
|
3296
3299
|
case "ruby":
|
|
3297
|
-
return
|
|
3300
|
+
return join33("Gemfile");
|
|
3298
3301
|
case "php":
|
|
3299
|
-
return
|
|
3302
|
+
return join33("composer.json");
|
|
3300
3303
|
case "java":
|
|
3301
3304
|
case "kotlin":
|
|
3302
3305
|
case "scala":
|
|
3303
3306
|
case "groovy":
|
|
3304
|
-
return
|
|
3307
|
+
return join33("pom.xml");
|
|
3305
3308
|
case "dotnet":
|
|
3306
|
-
return
|
|
3309
|
+
return join33(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
|
|
3307
3310
|
case "dart":
|
|
3308
|
-
return
|
|
3311
|
+
return join33("pubspec.yaml");
|
|
3309
3312
|
case "elixir":
|
|
3310
|
-
return
|
|
3313
|
+
return join33("mix.exs");
|
|
3311
3314
|
default:
|
|
3312
|
-
return
|
|
3315
|
+
return join33("package.json");
|
|
3313
3316
|
}
|
|
3314
3317
|
}
|
|
3315
3318
|
function lockfileRelativePath(rootDir, proj) {
|
|
@@ -3340,9 +3343,9 @@ function lockfileRelativePath(rootDir, proj) {
|
|
|
3340
3343
|
const dirsToTry = base ? [base, ""] : [""];
|
|
3341
3344
|
for (const dir of dirsToTry) {
|
|
3342
3345
|
for (const name of candidateNames) {
|
|
3343
|
-
const rel = dir ?
|
|
3346
|
+
const rel = dir ? path43.join(dir, name) : name;
|
|
3344
3347
|
try {
|
|
3345
|
-
if (
|
|
3348
|
+
if (fs12.existsSync(path43.join(rootDir, rel))) return rel;
|
|
3346
3349
|
} catch {
|
|
3347
3350
|
}
|
|
3348
3351
|
}
|
|
@@ -3413,10 +3416,10 @@ function lookupImportFiles(map, pkg) {
|
|
|
3413
3416
|
}
|
|
3414
3417
|
function firstPackageMentionLine(root2, relFile, pkg) {
|
|
3415
3418
|
try {
|
|
3416
|
-
const abs =
|
|
3417
|
-
const stat2 =
|
|
3419
|
+
const abs = path43.resolve(root2, relFile);
|
|
3420
|
+
const stat2 = fs12.statSync(abs);
|
|
3418
3421
|
if (!stat2.isFile() || stat2.size > 256 * 1024) return null;
|
|
3419
|
-
const text =
|
|
3422
|
+
const text = fs12.readFileSync(abs, "utf8");
|
|
3420
3423
|
const tokens = [pkg];
|
|
3421
3424
|
if (pkg.startsWith("@")) {
|
|
3422
3425
|
const parts = pkg.split("/");
|
|
@@ -3568,7 +3571,7 @@ function hoverMarkdown(dep, contribution) {
|
|
|
3568
3571
|
return lines.join("\n");
|
|
3569
3572
|
}
|
|
3570
3573
|
function startLanguageServer(opts) {
|
|
3571
|
-
if (!
|
|
3574
|
+
if (!fs12.existsSync(opts.root)) {
|
|
3572
3575
|
process.stderr.write(`vg lsp: root does not exist: ${opts.root}
|
|
3573
3576
|
`);
|
|
3574
3577
|
process.exit(1);
|
|
@@ -3617,12 +3620,12 @@ function hookCommand(vgBin) {
|
|
|
3617
3620
|
return `${vgBin} hook pre-tool-use`;
|
|
3618
3621
|
}
|
|
3619
3622
|
function installClaudeHooks(root2, vgBin = "vg") {
|
|
3620
|
-
const file =
|
|
3621
|
-
const rel =
|
|
3623
|
+
const file = path43.join(root2, ".claude", "settings.json");
|
|
3624
|
+
const rel = path43.join(".claude", "settings.json");
|
|
3622
3625
|
let settings = {};
|
|
3623
|
-
if (
|
|
3626
|
+
if (fs12.existsSync(file)) {
|
|
3624
3627
|
try {
|
|
3625
|
-
const parsed = JSON.parse(
|
|
3628
|
+
const parsed = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
3626
3629
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3627
3630
|
return { file: rel, status: "skipped", note: "settings.json is not a JSON object \u2014 left untouched" };
|
|
3628
3631
|
}
|
|
@@ -3659,12 +3662,12 @@ function installClaudeHooks(root2, vgBin = "vg") {
|
|
|
3659
3662
|
return { file: rel, status: "written" };
|
|
3660
3663
|
}
|
|
3661
3664
|
function uninstallClaudeHooks(root2) {
|
|
3662
|
-
const file =
|
|
3663
|
-
const rel =
|
|
3664
|
-
if (!
|
|
3665
|
+
const file = path43.join(root2, ".claude", "settings.json");
|
|
3666
|
+
const rel = path43.join(".claude", "settings.json");
|
|
3667
|
+
if (!fs12.existsSync(file)) return { file: rel, status: "unchanged" };
|
|
3665
3668
|
let settings;
|
|
3666
3669
|
try {
|
|
3667
|
-
settings = JSON.parse(
|
|
3670
|
+
settings = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
3668
3671
|
} catch {
|
|
3669
3672
|
return { file: rel, status: "skipped", note: "settings.json is not parseable JSON \u2014 left untouched" };
|
|
3670
3673
|
}
|
|
@@ -3686,8 +3689,8 @@ function uninstallClaudeHooks(root2) {
|
|
|
3686
3689
|
return { file: rel, status: "written" };
|
|
3687
3690
|
}
|
|
3688
3691
|
function writeSettings(file, settings) {
|
|
3689
|
-
|
|
3690
|
-
|
|
3692
|
+
fs12.mkdirSync(path43.dirname(file), { recursive: true });
|
|
3693
|
+
fs12.writeFileSync(file, `${JSON.stringify(settings, null, 2)}
|
|
3691
3694
|
`);
|
|
3692
3695
|
}
|
|
3693
3696
|
|
|
@@ -3801,25 +3804,28 @@ function resolve5(id) {
|
|
|
3801
3804
|
}
|
|
3802
3805
|
return a;
|
|
3803
3806
|
}
|
|
3804
|
-
var RELEVANCE_MODULE_NAME = "@vibgrate/relevance";
|
|
3805
3807
|
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
3806
3808
|
function registryBase(opts) {
|
|
3807
3809
|
return (process.env.VIBGRATE_MODULE_REGISTRY || opts.registry || DEFAULT_REGISTRY).replace(/\/+$/, "");
|
|
3808
3810
|
}
|
|
3811
|
+
function modulesBaseDir() {
|
|
3812
|
+
const base = process.env.XDG_CACHE_HOME || path43.join(os.homedir(), ".cache");
|
|
3813
|
+
return path43.join(base, "vibgrate", "modules");
|
|
3814
|
+
}
|
|
3809
3815
|
function stateFile() {
|
|
3810
|
-
return
|
|
3816
|
+
return path43.join(modulesBaseDir(), "consent.json");
|
|
3811
3817
|
}
|
|
3812
3818
|
function readConsent() {
|
|
3813
3819
|
try {
|
|
3814
|
-
return JSON.parse(
|
|
3820
|
+
return JSON.parse(fs12.readFileSync(stateFile(), "utf8"));
|
|
3815
3821
|
} catch {
|
|
3816
3822
|
return {};
|
|
3817
3823
|
}
|
|
3818
3824
|
}
|
|
3819
3825
|
function writeConsent(state) {
|
|
3820
3826
|
try {
|
|
3821
|
-
|
|
3822
|
-
|
|
3827
|
+
fs12.mkdirSync(path43.dirname(stateFile()), { recursive: true });
|
|
3828
|
+
fs12.writeFileSync(stateFile(), JSON.stringify(state));
|
|
3823
3829
|
} catch {
|
|
3824
3830
|
}
|
|
3825
3831
|
}
|
|
@@ -3827,17 +3833,16 @@ function kernelDisabled() {
|
|
|
3827
3833
|
const v = process.env.VIBGRATE_NO_KERNEL;
|
|
3828
3834
|
return v === "1" || v === "true";
|
|
3829
3835
|
}
|
|
3830
|
-
function
|
|
3836
|
+
function moduleInstalledAt(dir) {
|
|
3831
3837
|
try {
|
|
3832
|
-
const meta = JSON.parse(
|
|
3833
|
-
if (
|
|
3838
|
+
const meta = JSON.parse(fs12.readFileSync(path43.join(dir, ".module.json"), "utf8"));
|
|
3839
|
+
if (fs12.existsSync(path43.join(dir, "index.js"))) {
|
|
3834
3840
|
return { installed: true, version: meta.version };
|
|
3835
3841
|
}
|
|
3836
3842
|
} catch {
|
|
3837
3843
|
}
|
|
3838
3844
|
return { installed: false };
|
|
3839
3845
|
}
|
|
3840
|
-
var DISCLOSURE = "vg can install the optional Vibgrate relevance module (proprietary license, runs fully locally, improves how questions find the code they mean). Disable any time with VIBGRATE_NO_KERNEL=1.";
|
|
3841
3846
|
function verifyIntegrity(buf, integrity, shasum) {
|
|
3842
3847
|
if (integrity) {
|
|
3843
3848
|
const [algo, expected] = integrity.split("-", 2);
|
|
@@ -3879,21 +3884,21 @@ function untar(data) {
|
|
|
3879
3884
|
if (type !== "0" && type !== "\0") continue;
|
|
3880
3885
|
const name = pendingName ?? (prefix ? `${prefix}/${rawName}` : rawName);
|
|
3881
3886
|
pendingName = null;
|
|
3882
|
-
if (name.split("/").includes("..") ||
|
|
3887
|
+
if (name.split("/").includes("..") || path43.isAbsolute(name)) {
|
|
3883
3888
|
throw new Error(`unsafe path in tarball: ${name}`);
|
|
3884
3889
|
}
|
|
3885
3890
|
out2.push({ name, body: Buffer.from(body) });
|
|
3886
3891
|
}
|
|
3887
3892
|
return out2;
|
|
3888
3893
|
}
|
|
3889
|
-
async function
|
|
3894
|
+
async function installModule(mod, opts = {}) {
|
|
3890
3895
|
if (kernelDisabled()) return { status: "disabled", detail: "VIBGRATE_NO_KERNEL is set" };
|
|
3891
|
-
const existing =
|
|
3896
|
+
const existing = moduleInstalledAt(mod.dir());
|
|
3892
3897
|
if (existing.installed && !opts.force) return { status: "already-installed", version: existing.version };
|
|
3893
3898
|
const doFetch = opts.fetchImpl ?? fetch;
|
|
3894
3899
|
const base = registryBase(opts);
|
|
3895
3900
|
try {
|
|
3896
|
-
const metaRes = await doFetch(`${base}/${
|
|
3901
|
+
const metaRes = await doFetch(`${base}/${mod.npmName.replace("/", "%2f")}`);
|
|
3897
3902
|
if (!metaRes.ok) return { status: "unavailable", detail: `registry ${metaRes.status}` };
|
|
3898
3903
|
const meta = await metaRes.json();
|
|
3899
3904
|
const version = meta["dist-tags"]?.latest;
|
|
@@ -3904,35 +3909,54 @@ async function installRelevanceModule(opts = {}) {
|
|
|
3904
3909
|
const gz = Buffer.from(await tarRes.arrayBuffer());
|
|
3905
3910
|
verifyIntegrity(gz, dist.integrity, dist.shasum);
|
|
3906
3911
|
const entries = untar(zlib.gunzipSync(gz));
|
|
3907
|
-
const dir =
|
|
3908
|
-
|
|
3909
|
-
|
|
3912
|
+
const dir = mod.dir();
|
|
3913
|
+
fs12.rmSync(dir, { recursive: true, force: true });
|
|
3914
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
3910
3915
|
let wrote = 0;
|
|
3911
3916
|
for (const e of entries) {
|
|
3912
3917
|
let rel = null;
|
|
3913
3918
|
if (e.name.startsWith("package/dist/")) rel = e.name.slice("package/dist/".length);
|
|
3914
3919
|
else if (e.name === "package/LICENSE" || e.name === "package/README.md") rel = e.name.slice("package/".length);
|
|
3915
3920
|
if (!rel) continue;
|
|
3916
|
-
const target =
|
|
3917
|
-
if (!target.startsWith(dir +
|
|
3918
|
-
|
|
3919
|
-
|
|
3921
|
+
const target = path43.join(dir, rel);
|
|
3922
|
+
if (!target.startsWith(dir + path43.sep) && target !== dir) throw new Error(`unsafe extract path: ${rel}`);
|
|
3923
|
+
fs12.mkdirSync(path43.dirname(target), { recursive: true });
|
|
3924
|
+
fs12.writeFileSync(target, e.body);
|
|
3920
3925
|
wrote += 1;
|
|
3921
3926
|
}
|
|
3922
|
-
if (!wrote || !
|
|
3923
|
-
|
|
3927
|
+
if (!wrote || !fs12.existsSync(path43.join(dir, "index.js"))) {
|
|
3928
|
+
fs12.rmSync(dir, { recursive: true, force: true });
|
|
3924
3929
|
return { status: "unavailable", detail: "package layout not recognized (no dist/index.js)" };
|
|
3925
3930
|
}
|
|
3926
|
-
|
|
3927
|
-
|
|
3931
|
+
fs12.writeFileSync(path43.join(dir, ".module.json"), JSON.stringify({ name: mod.npmName, version }));
|
|
3932
|
+
mod.onChanged?.();
|
|
3928
3933
|
return { status: "installed", version };
|
|
3929
3934
|
} catch (e) {
|
|
3930
3935
|
return { status: "unavailable", detail: String(e.message ?? e).slice(0, 200) };
|
|
3931
3936
|
}
|
|
3932
3937
|
}
|
|
3938
|
+
function removeModule(mod) {
|
|
3939
|
+
fs12.rmSync(mod.dir(), { recursive: true, force: true });
|
|
3940
|
+
mod.onChanged?.();
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
// src/install/relevance-module.ts
|
|
3944
|
+
var RELEVANCE_MODULE_NAME = "@vibgrate/relevance";
|
|
3945
|
+
var RELEVANCE_MODULE = {
|
|
3946
|
+
id: "relevance",
|
|
3947
|
+
npmName: RELEVANCE_MODULE_NAME,
|
|
3948
|
+
dir: relevanceModuleDir,
|
|
3949
|
+
onChanged: resetRelevanceProviderCache
|
|
3950
|
+
};
|
|
3951
|
+
function moduleInstalled() {
|
|
3952
|
+
return moduleInstalledAt(relevanceModuleDir());
|
|
3953
|
+
}
|
|
3954
|
+
var DISCLOSURE = "vg can install the optional Vibgrate relevance module (proprietary license, runs fully locally, improves how questions find the code they mean). Disable any time with VIBGRATE_NO_KERNEL=1.";
|
|
3955
|
+
async function installRelevanceModule(opts = {}) {
|
|
3956
|
+
return installModule(RELEVANCE_MODULE, opts);
|
|
3957
|
+
}
|
|
3933
3958
|
function removeRelevanceModule() {
|
|
3934
|
-
|
|
3935
|
-
resetRelevanceProviderCache();
|
|
3959
|
+
removeModule(RELEVANCE_MODULE);
|
|
3936
3960
|
}
|
|
3937
3961
|
async function ensureRelevanceModule(io = {}) {
|
|
3938
3962
|
try {
|
|
@@ -3945,78 +3969,178 @@ async function ensureRelevanceModule(io = {}) {
|
|
|
3945
3969
|
return { status: "unavailable", detail: "auto-install failed" };
|
|
3946
3970
|
}
|
|
3947
3971
|
}
|
|
3972
|
+
function disabled() {
|
|
3973
|
+
const v = process.env.VIBGRATE_NO_KERNEL;
|
|
3974
|
+
return v === "1" || v === "true";
|
|
3975
|
+
}
|
|
3976
|
+
function hcsModuleDir() {
|
|
3977
|
+
return path43.join(modulesBaseDir(), "hcs");
|
|
3978
|
+
}
|
|
3979
|
+
function candidatePaths() {
|
|
3980
|
+
const custom = process.env.VIBGRATE_HCS_PATH;
|
|
3981
|
+
if (custom) {
|
|
3982
|
+
const p = path43.resolve(custom);
|
|
3983
|
+
try {
|
|
3984
|
+
if (fs12.statSync(p).isDirectory()) return [path43.join(p, "index.js")];
|
|
3985
|
+
} catch {
|
|
3986
|
+
}
|
|
3987
|
+
return [p];
|
|
3988
|
+
}
|
|
3989
|
+
return [path43.join(hcsModuleDir(), "index.js")];
|
|
3990
|
+
}
|
|
3991
|
+
var cached;
|
|
3992
|
+
function resetHcsEngineCache() {
|
|
3993
|
+
cached = void 0;
|
|
3994
|
+
}
|
|
3995
|
+
async function loadHcsEngine() {
|
|
3996
|
+
if (cached !== void 0) return cached;
|
|
3997
|
+
cached = null;
|
|
3998
|
+
if (disabled()) return cached;
|
|
3999
|
+
for (const p of candidatePaths()) {
|
|
4000
|
+
if (!fs12.existsSync(p)) continue;
|
|
4001
|
+
try {
|
|
4002
|
+
const mod = await import(pathToFileURL(p).href);
|
|
4003
|
+
const engine = await mod.createHcsEngine?.();
|
|
4004
|
+
if (engine && typeof engine.version === "function" && typeof engine.renderDigest === "function" && typeof engine.buildMap === "function" && typeof engine.evaluateGate === "function") {
|
|
4005
|
+
cached = engine;
|
|
4006
|
+
return cached;
|
|
4007
|
+
}
|
|
4008
|
+
} catch {
|
|
4009
|
+
}
|
|
4010
|
+
}
|
|
4011
|
+
return cached;
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
// src/install/hcs-module.ts
|
|
4015
|
+
var HCS_MODULE_NAME = "@vibgrate/hcs-engine";
|
|
4016
|
+
var HCS_MODULE = {
|
|
4017
|
+
id: "hcs",
|
|
4018
|
+
npmName: HCS_MODULE_NAME,
|
|
4019
|
+
dir: hcsModuleDir,
|
|
4020
|
+
onChanged: resetHcsEngineCache
|
|
4021
|
+
};
|
|
4022
|
+
var HCS_DISCLOSURE = "vg can install the optional Vibgrate HCS engine module (proprietary license, runs fully locally in a WASM sandbox \u2014 no network, no process spawns). Disable any time with VIBGRATE_NO_KERNEL=1.";
|
|
4023
|
+
function hcsModuleInstalled() {
|
|
4024
|
+
return moduleInstalledAt(hcsModuleDir());
|
|
4025
|
+
}
|
|
4026
|
+
async function installHcsModule(opts = {}) {
|
|
4027
|
+
return installModule(HCS_MODULE, opts);
|
|
4028
|
+
}
|
|
4029
|
+
function removeHcsModule() {
|
|
4030
|
+
removeModule(HCS_MODULE);
|
|
4031
|
+
}
|
|
4032
|
+
async function ensureHcsModule(io = {}) {
|
|
4033
|
+
try {
|
|
4034
|
+
if (kernelDisabled()) return { status: "disabled" };
|
|
4035
|
+
const existing = hcsModuleInstalled();
|
|
4036
|
+
if (existing.installed) return { status: "already-installed", version: existing.version };
|
|
4037
|
+
if (readConsent().hcs === "denied") return { status: "declined" };
|
|
4038
|
+
return await installHcsModule({ fetchImpl: io.fetchImpl });
|
|
4039
|
+
} catch {
|
|
4040
|
+
return { status: "unavailable", detail: "auto-install failed" };
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
3948
4043
|
|
|
3949
4044
|
// src/commands/module.ts
|
|
4045
|
+
var MODULES = {
|
|
4046
|
+
relevance: {
|
|
4047
|
+
npmName: RELEVANCE_MODULE_NAME,
|
|
4048
|
+
disclosure: DISCLOSURE,
|
|
4049
|
+
install: installRelevanceModule,
|
|
4050
|
+
remove: removeRelevanceModule,
|
|
4051
|
+
installed: moduleInstalled,
|
|
4052
|
+
resetLoader: resetRelevanceProviderCache,
|
|
4053
|
+
loadedVersion: async () => {
|
|
4054
|
+
const provider = await loadRelevanceProvider();
|
|
4055
|
+
return provider ? provider.version() : null;
|
|
4056
|
+
}
|
|
4057
|
+
},
|
|
4058
|
+
hcs: {
|
|
4059
|
+
npmName: HCS_MODULE_NAME,
|
|
4060
|
+
disclosure: HCS_DISCLOSURE,
|
|
4061
|
+
install: installHcsModule,
|
|
4062
|
+
remove: removeHcsModule,
|
|
4063
|
+
installed: hcsModuleInstalled,
|
|
4064
|
+
resetLoader: resetHcsEngineCache,
|
|
4065
|
+
loadedVersion: async () => {
|
|
4066
|
+
const engine = await loadHcsEngine();
|
|
4067
|
+
return engine ? engine.version() : null;
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
};
|
|
4071
|
+
var SUPPORTED = Object.keys(MODULES).join(", ");
|
|
3950
4072
|
function registerModule(program) {
|
|
3951
|
-
const cmd = program.command("module").description(
|
|
3952
|
-
cmd.command("install").description("install an optional module (fetches from the registry, integrity-checked)").argument("<name>",
|
|
4073
|
+
const cmd = program.command("module").description(`manage optional local modules (${SUPPORTED})`);
|
|
4074
|
+
cmd.command("install").description("install an optional module (fetches from the registry, integrity-checked)").argument("<name>", `module name (supported: ${SUPPORTED})`).option("--yes", "skip the confirmation prompt").option("--force", "reinstall even when already present").action(async function(name, opts) {
|
|
3953
4075
|
const global = readGlobal(this);
|
|
3954
|
-
|
|
4076
|
+
const mod = requireModule(name);
|
|
3955
4077
|
if (kernelDisabled()) {
|
|
3956
|
-
throw new CliError(
|
|
4078
|
+
throw new CliError(`VIBGRATE_NO_KERNEL is set \u2014 unset it to install the ${name} module`, ExitCode.USAGE_ERROR);
|
|
3957
4079
|
}
|
|
3958
4080
|
if (!opts.yes && process.stdin.isTTY && process.stdout.isTTY) {
|
|
3959
|
-
const ok = await confirm(`${
|
|
4081
|
+
const ok = await confirm(`${mod.disclosure}
|
|
3960
4082
|
Install now? [Y/n] `);
|
|
3961
4083
|
if (!ok) {
|
|
3962
|
-
writeConsent({ ...readConsent(),
|
|
4084
|
+
writeConsent({ ...readConsent(), [name]: "denied" });
|
|
3963
4085
|
info("not installed");
|
|
3964
4086
|
return;
|
|
3965
4087
|
}
|
|
3966
4088
|
}
|
|
3967
|
-
writeConsent({ ...readConsent(),
|
|
3968
|
-
const result = await
|
|
4089
|
+
writeConsent({ ...readConsent(), [name]: "granted" });
|
|
4090
|
+
const result = await mod.install({ force: opts.force });
|
|
3969
4091
|
if (global.json) {
|
|
3970
4092
|
json(result);
|
|
3971
4093
|
if (result.status === "unavailable") process.exitCode = ExitCode.ERROR;
|
|
3972
4094
|
return;
|
|
3973
4095
|
}
|
|
3974
|
-
if (result.status === "installed") out(`installed ${
|
|
4096
|
+
if (result.status === "installed") out(`installed ${mod.npmName}@${result.version}`);
|
|
3975
4097
|
else if (result.status === "already-installed") out(`already installed (${result.version ?? "unknown"}) \u2014 use --force to reinstall`);
|
|
3976
4098
|
else throw new CliError(`install failed: ${result.detail ?? result.status} \u2014 check network access to the registry, or retry later`, ExitCode.ERROR);
|
|
3977
4099
|
});
|
|
3978
|
-
cmd.command("remove").description("remove an installed module").argument("<name>",
|
|
3979
|
-
|
|
3980
|
-
removeRelevanceModule();
|
|
4100
|
+
cmd.command("remove").description("remove an installed module").argument("<name>", `module name (supported: ${SUPPORTED})`).action(async function(name) {
|
|
4101
|
+
requireModule(name).remove();
|
|
3981
4102
|
out("removed");
|
|
3982
4103
|
});
|
|
3983
4104
|
cmd.command("status").description("show installed modules and whether they load").action(async function() {
|
|
3984
4105
|
const global = readGlobal(this);
|
|
3985
|
-
const
|
|
3986
|
-
|
|
3987
|
-
const
|
|
3988
|
-
|
|
3989
|
-
|
|
4106
|
+
const consent = readConsent();
|
|
4107
|
+
const status = {};
|
|
4108
|
+
for (const [name, mod] of Object.entries(MODULES)) {
|
|
4109
|
+
const installed = mod.installed();
|
|
4110
|
+
mod.resetLoader();
|
|
4111
|
+
const loadedVersion = installed.installed ? await mod.loadedVersion() : null;
|
|
4112
|
+
status[name] = {
|
|
3990
4113
|
installed: installed.installed,
|
|
3991
4114
|
version: installed.version ?? null,
|
|
3992
|
-
loadable:
|
|
3993
|
-
providerVersion:
|
|
4115
|
+
loadable: loadedVersion !== null,
|
|
4116
|
+
providerVersion: loadedVersion,
|
|
3994
4117
|
disabled: kernelDisabled(),
|
|
3995
|
-
consent:
|
|
3996
|
-
}
|
|
3997
|
-
}
|
|
4118
|
+
consent: consent[name] ?? "unset"
|
|
4119
|
+
};
|
|
4120
|
+
}
|
|
3998
4121
|
if (global.json) {
|
|
3999
4122
|
json(status);
|
|
4000
4123
|
return;
|
|
4001
4124
|
}
|
|
4002
|
-
const
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4125
|
+
for (const [name, s] of Object.entries(status)) {
|
|
4126
|
+
out(`${name}: ${s.installed ? `installed ${s.version}` : "not installed"}${s.disabled ? " (disabled via VIBGRATE_NO_KERNEL)" : ""}`);
|
|
4127
|
+
if (s.installed) out(` loads: ${s.loadable ? `yes (${s.providerVersion})` : "no"}`);
|
|
4128
|
+
info(c.dim(` consent: ${s.consent}`));
|
|
4129
|
+
}
|
|
4006
4130
|
});
|
|
4007
4131
|
applyGlobalOptions(cmd);
|
|
4008
4132
|
}
|
|
4009
|
-
function
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4133
|
+
function requireModule(name) {
|
|
4134
|
+
const mod = MODULES[name];
|
|
4135
|
+
if (!mod) throw usageError(`unknown module '${name}' \u2014 supported modules: ${SUPPORTED}`);
|
|
4136
|
+
return mod;
|
|
4013
4137
|
}
|
|
4014
4138
|
function confirm(question) {
|
|
4015
|
-
return new Promise((
|
|
4139
|
+
return new Promise((resolve23) => {
|
|
4016
4140
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
4017
4141
|
rl.question(question, (answer) => {
|
|
4018
4142
|
rl.close();
|
|
4019
|
-
|
|
4143
|
+
resolve23(answer.trim() === "" || /^y(es)?$/i.test(answer.trim()));
|
|
4020
4144
|
});
|
|
4021
4145
|
});
|
|
4022
4146
|
}
|
|
@@ -4040,7 +4164,7 @@ function hookContext(payloadText, root2, graphOverride) {
|
|
|
4040
4164
|
let graph;
|
|
4041
4165
|
try {
|
|
4042
4166
|
const preferred = loadGraphPreferIndex(root2, graphPath);
|
|
4043
|
-
graph = preferred ? preferred.graph : parseGraph(
|
|
4167
|
+
graph = preferred ? preferred.graph : parseGraph(fs12.readFileSync(graphPath, "utf8"));
|
|
4044
4168
|
} catch {
|
|
4045
4169
|
return null;
|
|
4046
4170
|
}
|
|
@@ -4062,7 +4186,7 @@ function registerHook(program) {
|
|
|
4062
4186
|
const global = readGlobal(this);
|
|
4063
4187
|
const root2 = rootOf(global);
|
|
4064
4188
|
try {
|
|
4065
|
-
const stdin =
|
|
4189
|
+
const stdin = fs12.readFileSync(0, "utf8");
|
|
4066
4190
|
const context = hookContext(stdin, root2, global.graph);
|
|
4067
4191
|
if (context) {
|
|
4068
4192
|
process.stdout.write(
|
|
@@ -4082,8 +4206,8 @@ function registerShare(program) {
|
|
|
4082
4206
|
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) {
|
|
4083
4207
|
const global = readGlobal(this);
|
|
4084
4208
|
const root2 = rootOf(global);
|
|
4085
|
-
const gitDir =
|
|
4086
|
-
if (!
|
|
4209
|
+
const gitDir = path43.join(root2, ".git");
|
|
4210
|
+
if (!fs12.existsSync(gitDir)) {
|
|
4087
4211
|
throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
|
|
4088
4212
|
}
|
|
4089
4213
|
if (opts.undo) {
|
|
@@ -4104,23 +4228,23 @@ function registerShare(program) {
|
|
|
4104
4228
|
applyGlobalOptions(cmd);
|
|
4105
4229
|
}
|
|
4106
4230
|
function writeVibgrateGitignore(root2, reports) {
|
|
4107
|
-
const dir =
|
|
4108
|
-
|
|
4231
|
+
const dir = path43.join(root2, ".vibgrate");
|
|
4232
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
4109
4233
|
const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
|
|
4110
4234
|
if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
|
|
4111
|
-
|
|
4235
|
+
fs12.writeFileSync(path43.join(dir, ".gitignore"), `${lines.join("\n")}
|
|
4112
4236
|
`);
|
|
4113
4237
|
}
|
|
4114
4238
|
function writeGitAttributes(root2) {
|
|
4115
|
-
const file =
|
|
4239
|
+
const file = path43.join(root2, ".gitattributes");
|
|
4116
4240
|
const line = ".vibgrate/graph.json merge=vg";
|
|
4117
|
-
let content =
|
|
4241
|
+
let content = fs12.existsSync(file) ? fs12.readFileSync(file, "utf8") : "";
|
|
4118
4242
|
if (!content.split("\n").some((l) => l.trim() === line)) {
|
|
4119
4243
|
content = content.length ? `${content.replace(/\s*$/, "")}
|
|
4120
4244
|
${line}
|
|
4121
4245
|
` : `${line}
|
|
4122
4246
|
`;
|
|
4123
|
-
|
|
4247
|
+
fs12.writeFileSync(file, content);
|
|
4124
4248
|
}
|
|
4125
4249
|
}
|
|
4126
4250
|
function configureMergeDriver(root2) {
|
|
@@ -4129,8 +4253,8 @@ function configureMergeDriver(root2) {
|
|
|
4129
4253
|
}
|
|
4130
4254
|
function installPreCommitHook(root2) {
|
|
4131
4255
|
const hooksDir = hookDir(root2);
|
|
4132
|
-
|
|
4133
|
-
const file =
|
|
4256
|
+
fs12.mkdirSync(hooksDir, { recursive: true });
|
|
4257
|
+
const file = path43.join(hooksDir, "pre-commit");
|
|
4134
4258
|
const block = [
|
|
4135
4259
|
HOOK_BEGIN,
|
|
4136
4260
|
"if command -v vg >/dev/null 2>&1; then",
|
|
@@ -4139,7 +4263,7 @@ function installPreCommitHook(root2) {
|
|
|
4139
4263
|
"fi",
|
|
4140
4264
|
HOOK_END
|
|
4141
4265
|
].join("\n");
|
|
4142
|
-
let content =
|
|
4266
|
+
let content = fs12.existsSync(file) ? fs12.readFileSync(file, "utf8") : "#!/bin/sh\n";
|
|
4143
4267
|
const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
|
|
4144
4268
|
if (re.test(content)) content = content.replace(re, block);
|
|
4145
4269
|
else content = `${content.replace(/\s*$/, "")}
|
|
@@ -4148,21 +4272,21 @@ ${block}
|
|
|
4148
4272
|
`;
|
|
4149
4273
|
if (!content.startsWith("#!")) content = `#!/bin/sh
|
|
4150
4274
|
${content}`;
|
|
4151
|
-
|
|
4152
|
-
|
|
4275
|
+
fs12.writeFileSync(file, content);
|
|
4276
|
+
fs12.chmodSync(file, 493);
|
|
4153
4277
|
}
|
|
4154
4278
|
function undo(root2) {
|
|
4155
|
-
const hookFile =
|
|
4156
|
-
if (
|
|
4279
|
+
const hookFile = path43.join(hookDir(root2), "pre-commit");
|
|
4280
|
+
if (fs12.existsSync(hookFile)) {
|
|
4157
4281
|
const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
|
|
4158
|
-
const next2 =
|
|
4159
|
-
if (next2.trim() === "#!/bin/sh")
|
|
4160
|
-
else
|
|
4282
|
+
const next2 = fs12.readFileSync(hookFile, "utf8").replace(re, "\n");
|
|
4283
|
+
if (next2.trim() === "#!/bin/sh") fs12.rmSync(hookFile);
|
|
4284
|
+
else fs12.writeFileSync(hookFile, next2);
|
|
4161
4285
|
}
|
|
4162
|
-
const attr =
|
|
4163
|
-
if (
|
|
4164
|
-
const next2 =
|
|
4165
|
-
|
|
4286
|
+
const attr = path43.join(root2, ".gitattributes");
|
|
4287
|
+
if (fs12.existsSync(attr)) {
|
|
4288
|
+
const next2 = fs12.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
|
|
4289
|
+
fs12.writeFileSync(attr, next2);
|
|
4166
4290
|
}
|
|
4167
4291
|
try {
|
|
4168
4292
|
git(root2, ["config", "--remove-section", "merge.vg"]);
|
|
@@ -4172,10 +4296,10 @@ function undo(root2) {
|
|
|
4172
4296
|
function hookDir(root2) {
|
|
4173
4297
|
try {
|
|
4174
4298
|
const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
|
|
4175
|
-
if (configured) return
|
|
4299
|
+
if (configured) return path43.resolve(root2, configured);
|
|
4176
4300
|
} catch {
|
|
4177
4301
|
}
|
|
4178
|
-
return
|
|
4302
|
+
return path43.join(root2, ".git", "hooks");
|
|
4179
4303
|
}
|
|
4180
4304
|
function git(root2, args) {
|
|
4181
4305
|
return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
|
|
@@ -4189,9 +4313,9 @@ function registerWatch(program) {
|
|
|
4189
4313
|
const global = readGlobal(this);
|
|
4190
4314
|
const root2 = rootOf(global);
|
|
4191
4315
|
const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
|
|
4192
|
-
const watchRoots = (paths.length ? paths : ["."]).map((p) =>
|
|
4316
|
+
const watchRoots = (paths.length ? paths : ["."]).map((p) => path43.resolve(root2, p));
|
|
4193
4317
|
for (const w of watchRoots) {
|
|
4194
|
-
if (!
|
|
4318
|
+
if (!fs12.existsSync(w)) {
|
|
4195
4319
|
throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
|
|
4196
4320
|
}
|
|
4197
4321
|
}
|
|
@@ -4244,7 +4368,7 @@ function registerWatch(program) {
|
|
|
4244
4368
|
const watchers = [];
|
|
4245
4369
|
for (const w of watchRoots) {
|
|
4246
4370
|
try {
|
|
4247
|
-
const watcher =
|
|
4371
|
+
const watcher = fs12.watch(w, { recursive: true }, (_event, filename) => {
|
|
4248
4372
|
if (!filename) {
|
|
4249
4373
|
schedule("change");
|
|
4250
4374
|
return;
|
|
@@ -4257,12 +4381,12 @@ function registerWatch(program) {
|
|
|
4257
4381
|
throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
|
|
4258
4382
|
}
|
|
4259
4383
|
}
|
|
4260
|
-
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) =>
|
|
4261
|
-
await new Promise((
|
|
4384
|
+
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path43.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
|
|
4385
|
+
await new Promise((resolve23) => {
|
|
4262
4386
|
const stop = () => {
|
|
4263
4387
|
for (const w of watchers) w.close();
|
|
4264
4388
|
if (timer) clearTimeout(timer);
|
|
4265
|
-
|
|
4389
|
+
resolve23();
|
|
4266
4390
|
};
|
|
4267
4391
|
process.once("SIGINT", stop);
|
|
4268
4392
|
process.once("SIGTERM", stop);
|
|
@@ -4590,10 +4714,10 @@ function normalizeStandards(raw) {
|
|
|
4590
4714
|
}
|
|
4591
4715
|
function loadStandards(root2) {
|
|
4592
4716
|
for (const rel of STANDARDS_FILES) {
|
|
4593
|
-
const p =
|
|
4717
|
+
const p = path43__default.join(root2, rel);
|
|
4594
4718
|
let text;
|
|
4595
4719
|
try {
|
|
4596
|
-
text =
|
|
4720
|
+
text = fs12__default.readFileSync(p, "utf8");
|
|
4597
4721
|
} catch {
|
|
4598
4722
|
continue;
|
|
4599
4723
|
}
|
|
@@ -5311,8 +5435,8 @@ async function runHostBench(options = {}) {
|
|
|
5311
5435
|
}
|
|
5312
5436
|
async function runArmSimulate(input) {
|
|
5313
5437
|
const { arm, lib, modelPath, turns, trie, env, live } = input;
|
|
5314
|
-
const
|
|
5315
|
-
const session = await acquireHostSession(lib,
|
|
5438
|
+
const path45 = `${modelPath}#${arm.id}`;
|
|
5439
|
+
const session = await acquireHostSession(lib, path45);
|
|
5316
5440
|
const system = "You are a coding agent with a Task Capsule.";
|
|
5317
5441
|
const capsule = "function readConfig(): Config { return load(); }";
|
|
5318
5442
|
let last = null;
|
|
@@ -6089,14 +6213,14 @@ function buildLocalInferenceStatus(opts) {
|
|
|
6089
6213
|
const dynamicCustomSampler = /^(1|true|yes)$/i.test(String(env.VG_LLM_CUSTOM_SAMPLER ?? ""));
|
|
6090
6214
|
const preferOllama = /^(1|true|yes)$/i.test(String(env.VG_PREFER_OLLAMA ?? ""));
|
|
6091
6215
|
const weightCatalog = catalogIntegrityReport();
|
|
6092
|
-
const
|
|
6216
|
+
const cached2 = listCachedWeights(env);
|
|
6093
6217
|
const sessions = listHostSessions();
|
|
6094
6218
|
const recommendedMode = recommendMode(opts.system, opts.repo);
|
|
6095
6219
|
const hints = [];
|
|
6096
6220
|
if (!weightCatalog.complete) {
|
|
6097
6221
|
hints.push(`weight catalog unpinned: ${weightCatalog.unpinned.join(", ")}`);
|
|
6098
6222
|
}
|
|
6099
|
-
if (
|
|
6223
|
+
if (cached2.length === 0) {
|
|
6100
6224
|
hints.push("no first-party GGUF in weight store \u2014 `vg models install` for embedded path");
|
|
6101
6225
|
}
|
|
6102
6226
|
if (preferOllama) {
|
|
@@ -6121,8 +6245,8 @@ function buildLocalInferenceStatus(opts) {
|
|
|
6121
6245
|
weightCatalog,
|
|
6122
6246
|
weightStore: {
|
|
6123
6247
|
dir: weightStoreDir(env),
|
|
6124
|
-
cachedGgufs:
|
|
6125
|
-
names:
|
|
6248
|
+
cachedGgufs: cached2.length,
|
|
6249
|
+
names: cached2.map((w) => w.name).slice(0, 12)
|
|
6126
6250
|
},
|
|
6127
6251
|
hostPool: {
|
|
6128
6252
|
size: hostSessionPoolSize(),
|
|
@@ -6255,7 +6379,7 @@ function registerModels(program) {
|
|
|
6255
6379
|
);
|
|
6256
6380
|
});
|
|
6257
6381
|
applyGlobalOptions(modeCmd);
|
|
6258
|
-
const
|
|
6382
|
+
const resolve23 = cmd.command("resolve").description("resolve a Code Mode to pack + underlying model + fit (no download)").argument("[mode]", "spark | flow | forge (default: auto-fit or configured default)").action(function(modeArg) {
|
|
6259
6383
|
const global = readGlobal(this);
|
|
6260
6384
|
const root2 = rootOf(global);
|
|
6261
6385
|
const sys = gatherSystemMemory();
|
|
@@ -6287,7 +6411,7 @@ function registerModels(program) {
|
|
|
6287
6411
|
info(c.yellow(" will not fit \u2014 choose a lower mode or free memory before loading"));
|
|
6288
6412
|
}
|
|
6289
6413
|
});
|
|
6290
|
-
applyGlobalOptions(
|
|
6414
|
+
applyGlobalOptions(resolve23);
|
|
6291
6415
|
const installCmd = cmd.command("install").description("resolve the best Code Mode for this machine and install the pack").argument("[mode]", "spark | flow | forge (default: auto-fit)").option("--dry-run", "print the install plan only \u2014 do not download").option("--yes", "skip prompts (install already runs by default)").action(async function(modeArg, opts) {
|
|
6292
6416
|
const global = readGlobal(this);
|
|
6293
6417
|
const root2 = rootOf(global);
|
|
@@ -6524,7 +6648,7 @@ function registerModels(program) {
|
|
|
6524
6648
|
);
|
|
6525
6649
|
}
|
|
6526
6650
|
} else {
|
|
6527
|
-
if (!target.path || !
|
|
6651
|
+
if (!target.path || !fs12.existsSync(target.path)) {
|
|
6528
6652
|
throw new CliError(
|
|
6529
6653
|
`model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
|
|
6530
6654
|
ExitCode.NOT_FOUND
|
|
@@ -6538,7 +6662,7 @@ function registerModels(program) {
|
|
|
6538
6662
|
}
|
|
6539
6663
|
if (!global.json) info(c.dim(` $ rm ${target.path}`));
|
|
6540
6664
|
try {
|
|
6541
|
-
|
|
6665
|
+
fs12.unlinkSync(target.path);
|
|
6542
6666
|
} catch (e) {
|
|
6543
6667
|
const msg = e instanceof Error ? e.message : String(e);
|
|
6544
6668
|
throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
|
|
@@ -6676,9 +6800,9 @@ function registerModels(program) {
|
|
|
6676
6800
|
}
|
|
6677
6801
|
});
|
|
6678
6802
|
if (opts.out) {
|
|
6679
|
-
const outPath =
|
|
6680
|
-
|
|
6681
|
-
|
|
6803
|
+
const outPath = path43.resolve(opts.out);
|
|
6804
|
+
fs12.mkdirSync(path43.dirname(outPath), { recursive: true });
|
|
6805
|
+
fs12.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
|
|
6682
6806
|
`);
|
|
6683
6807
|
if (!global.json) info(c.dim(` wrote ${outPath}`));
|
|
6684
6808
|
}
|
|
@@ -6792,11 +6916,11 @@ function fitColor(label) {
|
|
|
6792
6916
|
return label;
|
|
6793
6917
|
}
|
|
6794
6918
|
function confirmYesNo(question) {
|
|
6795
|
-
return new Promise((
|
|
6919
|
+
return new Promise((resolve23) => {
|
|
6796
6920
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
6797
6921
|
rl.question(`${question} [y/N] `, (answer) => {
|
|
6798
6922
|
rl.close();
|
|
6799
|
-
|
|
6923
|
+
resolve23(/^y(es)?$/i.test(answer.trim()));
|
|
6800
6924
|
});
|
|
6801
6925
|
});
|
|
6802
6926
|
}
|
|
@@ -6827,14 +6951,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
|
|
|
6827
6951
|
}
|
|
6828
6952
|
return exact[0];
|
|
6829
6953
|
}
|
|
6830
|
-
const base =
|
|
6954
|
+
const base = path43.basename(wantLc);
|
|
6831
6955
|
const soft = fleet.filter((m) => {
|
|
6832
6956
|
const n = m.name.toLowerCase();
|
|
6833
|
-
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) ||
|
|
6957
|
+
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path43.basename(n) === base;
|
|
6834
6958
|
});
|
|
6835
6959
|
if (soft.length === 1) return soft[0];
|
|
6836
6960
|
if (soft.length > 1) {
|
|
6837
|
-
const baseHits = soft.filter((m) =>
|
|
6961
|
+
const baseHits = soft.filter((m) => path43.basename(m.name).toLowerCase() === base);
|
|
6838
6962
|
const pool = baseHits.length ? baseHits : soft;
|
|
6839
6963
|
const order = ["ollama", "gguf", "lm-studio"];
|
|
6840
6964
|
for (const rt of order) {
|
|
@@ -6872,11 +6996,11 @@ function printBackends(backends) {
|
|
|
6872
6996
|
}
|
|
6873
6997
|
}
|
|
6874
6998
|
function codeConfigPath(root2) {
|
|
6875
|
-
return
|
|
6999
|
+
return path43.join(root2, ".vibgrate", "code.json");
|
|
6876
7000
|
}
|
|
6877
7001
|
function loadCodeConfig(root2) {
|
|
6878
7002
|
try {
|
|
6879
|
-
const raw = JSON.parse(
|
|
7003
|
+
const raw = JSON.parse(fs12.readFileSync(codeConfigPath(root2), "utf8"));
|
|
6880
7004
|
return sanitize(raw);
|
|
6881
7005
|
} catch {
|
|
6882
7006
|
return {};
|
|
@@ -6943,7 +7067,7 @@ function contextBudgetFor(config, modelContextWindow) {
|
|
|
6943
7067
|
var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
|
|
6944
7068
|
function readMcpServersFile(file) {
|
|
6945
7069
|
try {
|
|
6946
|
-
const raw = JSON.parse(
|
|
7070
|
+
const raw = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
6947
7071
|
const map = raw.mcpServers ?? raw.servers;
|
|
6948
7072
|
return map && typeof map === "object" ? parseMcpServers(map) : {};
|
|
6949
7073
|
} catch {
|
|
@@ -6954,7 +7078,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6954
7078
|
const servers = {};
|
|
6955
7079
|
const sources = [];
|
|
6956
7080
|
for (const rel of MCP_CONFIG_FILES) {
|
|
6957
|
-
const found = readMcpServersFile(
|
|
7081
|
+
const found = readMcpServersFile(path43.join(root2, rel));
|
|
6958
7082
|
const names = Object.keys(found);
|
|
6959
7083
|
if (names.length) {
|
|
6960
7084
|
sources.push(rel);
|
|
@@ -6970,9 +7094,160 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6970
7094
|
|
|
6971
7095
|
// src/commands/code.ts
|
|
6972
7096
|
function registerCode(program) {
|
|
6973
|
-
const cmd = program.command("code").description("
|
|
7097
|
+
const cmd = program.command("code").description("graph-grounded coding agent (guided mode with no instruction; every edit and command is approved)").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", "one-shot path (--single/--mock) only: 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 [id]", "resume a session: the most recent one, or the given session id (recap + restore /undo)").option("--restore-checkpoint <commit>", "one-shot: restore the given --file paths from a checkpoint commit, then exit (for host UIs after the original session ended)").option("--reasoning-effort <level>", "how hard a reasoning-capable model should think: low | medium | high (ignored by models without the knob)").option("--worktree [id]", "run the session in an isolated git worktree under .vibgrate/worktrees (bare: create a new one; with id: reuse it)").option("--worktree-diff <id>", "one-shot: print the worktree's delta against its base as a patch, then exit").option("--worktree-apply <id>", "one-shot: apply the worktree's delta onto the main tree (git apply --3way), then exit").option("--worktree-remove <id>", "one-shot: remove the worktree checkout, then exit").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) {
|
|
6974
7098
|
const global = readGlobal(this);
|
|
6975
|
-
|
|
7099
|
+
let instruction = (instructionParts ?? []).join(" ").trim();
|
|
7100
|
+
if (typeof opts.continue === "string") {
|
|
7101
|
+
const { looksLikeSessionId } = await import('./session-store-AQUORKWB.js');
|
|
7102
|
+
if (!looksLikeSessionId(opts.continue)) {
|
|
7103
|
+
instruction = [opts.continue, instruction].filter(Boolean).join(" ");
|
|
7104
|
+
opts.continue = true;
|
|
7105
|
+
}
|
|
7106
|
+
}
|
|
7107
|
+
if (opts.restoreCheckpoint) {
|
|
7108
|
+
const { restoreCheckpoint, isValidCheckpointCommit } = await import('./checkpoint-UYMYMMQO.js');
|
|
7109
|
+
if (!isValidCheckpointCommit(opts.restoreCheckpoint)) {
|
|
7110
|
+
throw usageError("--restore-checkpoint expects a checkpoint commit id (hex SHA)");
|
|
7111
|
+
}
|
|
7112
|
+
const files = (opts.file ?? []).filter(Boolean);
|
|
7113
|
+
if (!files.length) {
|
|
7114
|
+
throw usageError("--restore-checkpoint needs the files to restore, e.g. -f src/a.ts -f src/b.ts");
|
|
7115
|
+
}
|
|
7116
|
+
const root3 = rootOf(global);
|
|
7117
|
+
const child = await import('child_process');
|
|
7118
|
+
const gitRunner = (gitArgs, gitEnv) => {
|
|
7119
|
+
const res = child.spawnSync("git", gitArgs, {
|
|
7120
|
+
cwd: root3,
|
|
7121
|
+
encoding: "utf8",
|
|
7122
|
+
env: { ...process.env, ...gitEnv ?? {} },
|
|
7123
|
+
timeout: 3e4,
|
|
7124
|
+
maxBuffer: 32 * 1024 * 1024
|
|
7125
|
+
});
|
|
7126
|
+
return { stdout: res.stdout ?? "", exitCode: res.status ?? 1 };
|
|
7127
|
+
};
|
|
7128
|
+
const outcome = restoreCheckpoint(gitRunner, { commit: opts.restoreCheckpoint, files });
|
|
7129
|
+
if (opts.streamJson) {
|
|
7130
|
+
process.stdout.write(
|
|
7131
|
+
JSON.stringify({ event: "checkpoint-restored", commit: opts.restoreCheckpoint, ...outcome }) + "\n"
|
|
7132
|
+
);
|
|
7133
|
+
} else if (global.json) {
|
|
7134
|
+
json({ commit: opts.restoreCheckpoint, ...outcome });
|
|
7135
|
+
} else {
|
|
7136
|
+
out(
|
|
7137
|
+
`restored ${outcome.restored.length}, removed ${outcome.removed.length}, failed ${outcome.failed.length}`
|
|
7138
|
+
);
|
|
7139
|
+
}
|
|
7140
|
+
if (outcome.failed.length) process.exitCode = 1;
|
|
7141
|
+
return;
|
|
7142
|
+
}
|
|
7143
|
+
if (opts.worktreeDiff || opts.worktreeApply || opts.worktreeRemove) {
|
|
7144
|
+
const wt = await import('./worktree-session-D575IQWM.js');
|
|
7145
|
+
const child = await import('child_process');
|
|
7146
|
+
const os7 = await import('os');
|
|
7147
|
+
const pathMod = await import('path');
|
|
7148
|
+
const root3 = rootOf(global);
|
|
7149
|
+
const gitRunner = (gitArgs, gitEnv) => {
|
|
7150
|
+
const res = child.spawnSync("git", gitArgs, {
|
|
7151
|
+
cwd: root3,
|
|
7152
|
+
encoding: "utf8",
|
|
7153
|
+
env: { ...process.env, ...gitEnv ?? {} },
|
|
7154
|
+
timeout: 6e4,
|
|
7155
|
+
maxBuffer: 64 * 1024 * 1024
|
|
7156
|
+
});
|
|
7157
|
+
return { stdout: (res.stdout ?? "") + (res.stderr ?? ""), exitCode: res.status ?? 1 };
|
|
7158
|
+
};
|
|
7159
|
+
const emitLine = (line) => {
|
|
7160
|
+
if (opts.streamJson) process.stdout.write(JSON.stringify(line) + "\n");
|
|
7161
|
+
else if (global.json) json(line);
|
|
7162
|
+
};
|
|
7163
|
+
const findWt = (id) => wt.listSessionWorktrees(gitRunner, root3).find((w) => w.id === id);
|
|
7164
|
+
if (opts.worktreeDiff) {
|
|
7165
|
+
const target = findWt(opts.worktreeDiff);
|
|
7166
|
+
if (!target) throw new CliError(`no worktree ${opts.worktreeDiff} under .vibgrate/worktrees`, ExitCode.NOT_FOUND);
|
|
7167
|
+
const diff2 = wt.worktreeDiffToBase(gitRunner, target.path, target.base);
|
|
7168
|
+
if ("error" in diff2) throw new CliError(diff2.error, ExitCode.ERROR);
|
|
7169
|
+
const MAX_PATCH = 2 * 1024 * 1024;
|
|
7170
|
+
const truncated = diff2.patch.length > MAX_PATCH;
|
|
7171
|
+
emitLine({
|
|
7172
|
+
event: "worktree-diff",
|
|
7173
|
+
id: target.id,
|
|
7174
|
+
base: target.base,
|
|
7175
|
+
files: diff2.files,
|
|
7176
|
+
patch: truncated ? diff2.patch.slice(0, MAX_PATCH) : diff2.patch,
|
|
7177
|
+
truncated
|
|
7178
|
+
});
|
|
7179
|
+
if (!opts.streamJson && !global.json) {
|
|
7180
|
+
out(diff2.patch || `worktree ${target.id}: no changes vs base`);
|
|
7181
|
+
}
|
|
7182
|
+
return;
|
|
7183
|
+
}
|
|
7184
|
+
if (opts.worktreeApply) {
|
|
7185
|
+
const target = findWt(opts.worktreeApply);
|
|
7186
|
+
if (!target) throw new CliError(`no worktree ${opts.worktreeApply} under .vibgrate/worktrees`, ExitCode.NOT_FOUND);
|
|
7187
|
+
const diff2 = wt.worktreeDiffToBase(gitRunner, target.path, target.base);
|
|
7188
|
+
if ("error" in diff2) throw new CliError(diff2.error, ExitCode.ERROR);
|
|
7189
|
+
if (!diff2.files.length) {
|
|
7190
|
+
emitLine({ event: "worktree-applied", id: target.id, applied: true, files: [] });
|
|
7191
|
+
if (!opts.streamJson && !global.json) out(`worktree ${target.id}: nothing to apply`);
|
|
7192
|
+
return;
|
|
7193
|
+
}
|
|
7194
|
+
const patchFile = pathMod.join(
|
|
7195
|
+
fs12.mkdtempSync(pathMod.join(os7.tmpdir(), "vg-wt-")),
|
|
7196
|
+
"delta.patch"
|
|
7197
|
+
);
|
|
7198
|
+
fs12.writeFileSync(patchFile, diff2.patch);
|
|
7199
|
+
const outcome = wt.applyWorktreePatch(gitRunner, root3, patchFile, diff2.files);
|
|
7200
|
+
emitLine({ event: "worktree-applied", id: target.id, ...outcome });
|
|
7201
|
+
if (!opts.streamJson && !global.json) {
|
|
7202
|
+
out(
|
|
7203
|
+
outcome.applied ? `applied ${outcome.files.length} file(s) from worktree ${target.id}` : `apply failed: ${outcome.error}`
|
|
7204
|
+
);
|
|
7205
|
+
}
|
|
7206
|
+
if (!outcome.applied) process.exitCode = 1;
|
|
7207
|
+
return;
|
|
7208
|
+
}
|
|
7209
|
+
if (opts.worktreeRemove) {
|
|
7210
|
+
const outcome = wt.removeSessionWorktree(gitRunner, root3, opts.worktreeRemove);
|
|
7211
|
+
emitLine({ event: "worktree-removed", id: opts.worktreeRemove, ...outcome });
|
|
7212
|
+
if (!opts.streamJson && !global.json) {
|
|
7213
|
+
out(outcome.removed ? `removed worktree ${opts.worktreeRemove}` : `remove failed: ${outcome.error}`);
|
|
7214
|
+
}
|
|
7215
|
+
if (!outcome.removed) process.exitCode = 1;
|
|
7216
|
+
return;
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
7219
|
+
const mainRoot = rootOf(global);
|
|
7220
|
+
let activeWorktree;
|
|
7221
|
+
if (opts.worktree) {
|
|
7222
|
+
const wt = await import('./worktree-session-D575IQWM.js');
|
|
7223
|
+
const child = await import('child_process');
|
|
7224
|
+
const gitRunner = (gitArgs, gitEnv) => {
|
|
7225
|
+
const res = child.spawnSync("git", gitArgs, {
|
|
7226
|
+
cwd: mainRoot,
|
|
7227
|
+
encoding: "utf8",
|
|
7228
|
+
env: { ...process.env, ...gitEnv ?? {} },
|
|
7229
|
+
timeout: 6e4,
|
|
7230
|
+
maxBuffer: 64 * 1024 * 1024
|
|
7231
|
+
});
|
|
7232
|
+
return { stdout: (res.stdout ?? "") + (res.stderr ?? ""), exitCode: res.status ?? 1 };
|
|
7233
|
+
};
|
|
7234
|
+
if (typeof opts.worktree === "string") {
|
|
7235
|
+
const existing = wt.listSessionWorktrees(gitRunner, mainRoot).find((w) => w.id === opts.worktree);
|
|
7236
|
+
if (!existing) {
|
|
7237
|
+
throw new CliError(`no worktree ${opts.worktree} under .vibgrate/worktrees \u2014 start one with --worktree`, ExitCode.NOT_FOUND);
|
|
7238
|
+
}
|
|
7239
|
+
activeWorktree = existing;
|
|
7240
|
+
} else {
|
|
7241
|
+
const created = wt.createSessionWorktree(
|
|
7242
|
+
gitRunner,
|
|
7243
|
+
mainRoot,
|
|
7244
|
+
`wt${Date.now().toString(36)}`
|
|
7245
|
+
);
|
|
7246
|
+
if ("error" in created) throw new CliError(created.error, ExitCode.ERROR);
|
|
7247
|
+
activeWorktree = created;
|
|
7248
|
+
}
|
|
7249
|
+
global.cwd = activeWorktree.path;
|
|
7250
|
+
}
|
|
6976
7251
|
if (!global.local) {
|
|
6977
7252
|
await ensureRelevanceModule();
|
|
6978
7253
|
}
|
|
@@ -6986,7 +7261,7 @@ function registerCode(program) {
|
|
|
6986
7261
|
try {
|
|
6987
7262
|
const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
|
|
6988
7263
|
const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
|
|
6989
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
7264
|
+
const { loadGraph: loadGraph2 } = await import('./load-64RK5O6C.js');
|
|
6990
7265
|
const state = readOrchestratorState2();
|
|
6991
7266
|
const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
|
|
6992
7267
|
const pin = mode ? activePin2(mode, state) : null;
|
|
@@ -7071,7 +7346,7 @@ function registerCode(program) {
|
|
|
7071
7346
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
7072
7347
|
throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
|
|
7073
7348
|
}
|
|
7074
|
-
const { runInteractive } = await import('./interactive-
|
|
7349
|
+
const { runInteractive } = await import('./interactive-EW2VJ3BZ.js');
|
|
7075
7350
|
await runInteractive(
|
|
7076
7351
|
rootOf(global),
|
|
7077
7352
|
global,
|
|
@@ -7101,7 +7376,7 @@ function registerCode(program) {
|
|
|
7101
7376
|
}
|
|
7102
7377
|
if (!instruction && !stdinFirstTurn) throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"`');
|
|
7103
7378
|
{
|
|
7104
|
-
const { ensureCodeMap } = await import('./ensure-map-
|
|
7379
|
+
const { ensureCodeMap } = await import('./ensure-map-HQ7A5NDL.js');
|
|
7105
7380
|
const mapRoot = rootOf(global);
|
|
7106
7381
|
try {
|
|
7107
7382
|
await ensureCodeMap(mapRoot, global, {
|
|
@@ -7138,7 +7413,7 @@ function registerCode(program) {
|
|
|
7138
7413
|
let mockReply;
|
|
7139
7414
|
if (opts.mock) {
|
|
7140
7415
|
try {
|
|
7141
|
-
mockReply =
|
|
7416
|
+
mockReply = fs12.readFileSync(opts.mock, "utf8");
|
|
7142
7417
|
} catch {
|
|
7143
7418
|
throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
|
|
7144
7419
|
}
|
|
@@ -7186,20 +7461,20 @@ function registerCode(program) {
|
|
|
7186
7461
|
process.stdout.write(JSON.stringify(line) + "\n");
|
|
7187
7462
|
};
|
|
7188
7463
|
try {
|
|
7189
|
-
const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-
|
|
7464
|
+
const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-6QNQIHPV.js');
|
|
7190
7465
|
const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
|
|
7191
|
-
const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-
|
|
7192
|
-
const { nodeCodeFs } = await import('./session-
|
|
7466
|
+
const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-GY5N7WZT.js');
|
|
7467
|
+
const { nodeCodeFs } = await import('./session-4BGYASOH.js');
|
|
7193
7468
|
const readline6 = await import('readline');
|
|
7194
7469
|
const child = await import('child_process');
|
|
7195
7470
|
const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
|
|
7196
7471
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
7197
7472
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
7198
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
7199
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
7473
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-RJHH3KMF.js');
|
|
7474
|
+
const { resolveGraphBackend } = await import('./graph-backend-W2TNTMY7.js');
|
|
7200
7475
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7201
7476
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7202
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
7477
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-ORPA5C2K.js');
|
|
7203
7478
|
const federation = loadOrDiscoverFederation(root2);
|
|
7204
7479
|
const modelProfile = mergeModelExecutionProfile(
|
|
7205
7480
|
resolveModelExecutionProfile({
|
|
@@ -7257,7 +7532,7 @@ ${res.stderr}` : ""),
|
|
|
7257
7532
|
exitCode: res.status ?? 1
|
|
7258
7533
|
};
|
|
7259
7534
|
};
|
|
7260
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
7535
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-IGHJKKSL.js');
|
|
7261
7536
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
7262
7537
|
getGraph: () => graph,
|
|
7263
7538
|
root: root2,
|
|
@@ -7277,11 +7552,11 @@ ${res.stderr}` : ""),
|
|
|
7277
7552
|
};
|
|
7278
7553
|
}
|
|
7279
7554
|
const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
|
|
7280
|
-
const { createCheckpoint } = await import('./checkpoint-
|
|
7281
|
-
const
|
|
7555
|
+
const { createCheckpoint } = await import('./checkpoint-UYMYMMQO.js');
|
|
7556
|
+
const os7 = await import('os');
|
|
7282
7557
|
const pathMod = await import('path');
|
|
7283
7558
|
const checkpointIndex = pathMod.join(
|
|
7284
|
-
|
|
7559
|
+
fs12.mkdtempSync(pathMod.join(os7.tmpdir(), "vg-code-cp-")),
|
|
7285
7560
|
"index"
|
|
7286
7561
|
);
|
|
7287
7562
|
const gitRunner = (gitArgs, gitEnv) => {
|
|
@@ -7302,6 +7577,7 @@ ${res.stderr}` : ""),
|
|
|
7302
7577
|
files,
|
|
7303
7578
|
indexFile: checkpointIndex
|
|
7304
7579
|
});
|
|
7580
|
+
const { loadApprovalRules, addApprovalRule, ruleForAction, ruleLabel } = await import('./approvals-T2KXPJLV.js');
|
|
7305
7581
|
const { loadProjectRules, nodeRulesReader } = await import('./rules-ASYEUNB5.js');
|
|
7306
7582
|
const projectRules = loadProjectRules(nodeRulesReader(root2));
|
|
7307
7583
|
if (projectRules.sources.length && !global.quiet) {
|
|
@@ -7325,6 +7601,9 @@ ${res.stderr}` : ""),
|
|
|
7325
7601
|
graphBackend,
|
|
7326
7602
|
modelProfile,
|
|
7327
7603
|
auto: !!auto,
|
|
7604
|
+
// v5: spawn-time reasoning budget. Session mode lets a per-turn
|
|
7605
|
+
// value override it; one-shot runs use this.
|
|
7606
|
+
reasoningEffort: parseReasoningEffort(opts.reasoningEffort),
|
|
7328
7607
|
maxSteps,
|
|
7329
7608
|
budget: modelProfile.capsuleBudgetTokens,
|
|
7330
7609
|
contextBudget,
|
|
@@ -7347,27 +7626,43 @@ ${res.stderr}` : ""),
|
|
|
7347
7626
|
},
|
|
7348
7627
|
now: () => Date.now(),
|
|
7349
7628
|
projectRules: projectRules.rendered || void 0,
|
|
7350
|
-
checkpoint: takeCheckpoint
|
|
7629
|
+
checkpoint: takeCheckpoint,
|
|
7630
|
+
// Standing allow-always rules, re-read per approval so an
|
|
7631
|
+
// "Always allow" or a revocation applies to the very next action.
|
|
7632
|
+
// Always the MAIN root: consent is per-developer, and a worktree
|
|
7633
|
+
// checkout has no code-approvals.json (it is gitignored).
|
|
7634
|
+
approvalRules: () => loadApprovalRules(mainRoot)
|
|
7351
7635
|
};
|
|
7352
7636
|
try {
|
|
7353
7637
|
if (opts.session) {
|
|
7354
|
-
const { runCodeStreamJsonSession } = await import('./stream-json-
|
|
7355
|
-
const { runAgent: runAgent2 } = await import('./agent-
|
|
7638
|
+
const { runCodeStreamJsonSession, STREAM_JSON_PROTOCOL_VERSION } = await import('./stream-json-GY5N7WZT.js');
|
|
7639
|
+
const { runAgent: runAgent2 } = await import('./agent-5ANHRYEI.js');
|
|
7356
7640
|
const {
|
|
7357
7641
|
condenseSession,
|
|
7358
7642
|
loadLatestSession,
|
|
7643
|
+
loadSession,
|
|
7359
7644
|
newSession,
|
|
7360
7645
|
recordTask,
|
|
7361
7646
|
saveSession,
|
|
7647
|
+
sessionsDir,
|
|
7362
7648
|
summarizeSession
|
|
7363
|
-
} = await import('./session-store-
|
|
7364
|
-
const
|
|
7649
|
+
} = await import('./session-store-AQUORKWB.js');
|
|
7650
|
+
const { VERSION: VERSION2 } = await import('./version-DPAMQW6M.js');
|
|
7651
|
+
const resumedRecord = typeof opts.continue === "string" ? loadSession(mainRoot, opts.continue) : opts.continue ? loadLatestSession(mainRoot) : void 0;
|
|
7652
|
+
if (typeof opts.continue === "string" && !resumedRecord) {
|
|
7653
|
+
emitStream({
|
|
7654
|
+
event: "event",
|
|
7655
|
+
type: "notice",
|
|
7656
|
+
text: `Could not load session ${opts.continue} \u2014 starting a fresh conversation.`
|
|
7657
|
+
});
|
|
7658
|
+
}
|
|
7365
7659
|
let record = resumedRecord ?? newSession(
|
|
7366
7660
|
`s${Date.now().toString(36)}`,
|
|
7367
7661
|
primarySlug ?? route.providers[0]?.id ?? "unknown",
|
|
7368
7662
|
route.providers[0]?.model ?? "unknown",
|
|
7369
7663
|
Date.now()
|
|
7370
7664
|
);
|
|
7665
|
+
if (activeWorktree) record = { ...record, worktree: activeWorktree };
|
|
7371
7666
|
const pendingTurns = [];
|
|
7372
7667
|
let wakeTurn;
|
|
7373
7668
|
let ended = false;
|
|
@@ -7384,32 +7679,54 @@ ${res.stderr}` : ""),
|
|
|
7384
7679
|
if (ended) return Promise.resolve(null);
|
|
7385
7680
|
const queued = pendingTurns.shift();
|
|
7386
7681
|
if (queued !== void 0) return Promise.resolve(queued);
|
|
7387
|
-
return new Promise((
|
|
7388
|
-
wakeTurn =
|
|
7682
|
+
return new Promise((resolve23) => {
|
|
7683
|
+
wakeTurn = resolve23;
|
|
7389
7684
|
});
|
|
7390
7685
|
};
|
|
7391
7686
|
let turnIndex = 0;
|
|
7687
|
+
let lastTurnAttachments;
|
|
7392
7688
|
await runCodeStreamJsonSession({
|
|
7393
7689
|
emit: emitAndRecord,
|
|
7394
7690
|
auto: !!auto,
|
|
7395
7691
|
sessionId: record.id,
|
|
7396
7692
|
resumed: !!resumedRecord,
|
|
7693
|
+
// Environment facts for the host: where sessions live (the
|
|
7694
|
+
// single source of truth for history UIs, fixing multi-root
|
|
7695
|
+
// ambiguity) and the versions in play for its first-use report.
|
|
7696
|
+
sessionInfo: {
|
|
7697
|
+
sessionDir: sessionsDir(mainRoot),
|
|
7698
|
+
engineVersion: VERSION2,
|
|
7699
|
+
protocolVersion: STREAM_JSON_PROTOCOL_VERSION,
|
|
7700
|
+
provider: primarySlug,
|
|
7701
|
+
model: route.providers[0]?.model,
|
|
7702
|
+
...activeWorktree ? { worktree: { path: activeWorktree.path, base: activeWorktree.base } } : {}
|
|
7703
|
+
},
|
|
7397
7704
|
instruction,
|
|
7398
7705
|
nextTurn,
|
|
7399
7706
|
bindDecisions: (session) => {
|
|
7400
7707
|
streamApprove = (action) => session.approve(action);
|
|
7708
|
+
session.onAlwaysRule = (action) => {
|
|
7709
|
+
const rule = ruleForAction(action);
|
|
7710
|
+
if (!rule) return;
|
|
7711
|
+
const saved = addApprovalRule(mainRoot, rule);
|
|
7712
|
+
emitStream({
|
|
7713
|
+
event: "event",
|
|
7714
|
+
type: "notice",
|
|
7715
|
+
text: saved ? `Always-allow rule saved: ${ruleLabel(rule)} (manage in .vibgrate/code-approvals.json)` : "Could not save the always-allow rule (is .vibgrate writable?) \u2014 approved this once."
|
|
7716
|
+
});
|
|
7717
|
+
};
|
|
7401
7718
|
const rl = readline6.createInterface({ input: process.stdin });
|
|
7402
7719
|
rl.on("line", (raw) => {
|
|
7403
7720
|
const msg = parseHostMessage(raw);
|
|
7404
7721
|
if (!msg) return;
|
|
7405
7722
|
if (msg.kind === "approve") {
|
|
7406
|
-
session.submitDecision(msg.id, msg.approve);
|
|
7723
|
+
session.submitDecision(msg.id, msg.approve, msg.always);
|
|
7407
7724
|
runOutcome.noteDecision(msg.id, msg.approve);
|
|
7408
7725
|
} else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
|
|
7409
7726
|
else if (msg.kind === "submit")
|
|
7410
7727
|
pushTurn({ instruction: msg.instruction, agentMode: msg.agentMode, images: msg.images });
|
|
7411
7728
|
else if (msg.kind === "restore") {
|
|
7412
|
-
void import('./checkpoint-
|
|
7729
|
+
void import('./checkpoint-UYMYMMQO.js').then(({ restoreCheckpoint }) => {
|
|
7413
7730
|
const outcome = restoreCheckpoint(gitRunner, {
|
|
7414
7731
|
commit: msg.commit,
|
|
7415
7732
|
files: msg.files
|
|
@@ -7418,12 +7735,22 @@ ${res.stderr}` : ""),
|
|
|
7418
7735
|
});
|
|
7419
7736
|
} else if (msg.kind === "compact") {
|
|
7420
7737
|
record = condenseSession(record, Date.now());
|
|
7421
|
-
saveSession(
|
|
7738
|
+
saveSession(mainRoot, record);
|
|
7422
7739
|
emitStream({
|
|
7423
7740
|
event: "event",
|
|
7424
7741
|
type: "notice",
|
|
7425
7742
|
text: "Conversation compacted \u2014 earlier turns condensed into a checkpoint."
|
|
7426
7743
|
});
|
|
7744
|
+
} else if (msg.kind === "inject") {
|
|
7745
|
+
session.inject(msg.text);
|
|
7746
|
+
} else if (msg.kind === "rename") {
|
|
7747
|
+
const t = msg.title.slice(0, 120);
|
|
7748
|
+
if (t) record = { ...record, title: t };
|
|
7749
|
+
else {
|
|
7750
|
+
record = { ...record };
|
|
7751
|
+
delete record.title;
|
|
7752
|
+
}
|
|
7753
|
+
saveSession(mainRoot, record);
|
|
7427
7754
|
} else if (msg.kind === "cancel") {
|
|
7428
7755
|
session.cancelTurn();
|
|
7429
7756
|
runOutcome.cancelPending();
|
|
@@ -7439,7 +7766,8 @@ ${res.stderr}` : ""),
|
|
|
7439
7766
|
pushTurn(null);
|
|
7440
7767
|
});
|
|
7441
7768
|
},
|
|
7442
|
-
runTurn: ({ instruction: turnInstruction, signal, session, agentMode, auto: turnAuto, images }) => {
|
|
7769
|
+
runTurn: ({ instruction: turnInstruction, signal, session, agentMode, auto: turnAuto, images, reasoningEffort: turnEffort, attachments: turnAttachments }) => {
|
|
7770
|
+
lastTurnAttachments = turnAttachments;
|
|
7443
7771
|
const priorSummary = summarizeSession(record) || void 0;
|
|
7444
7772
|
turnIndex++;
|
|
7445
7773
|
runOutcome.beginRun(turnRunId(record.id, turnIndex), turnInstruction);
|
|
@@ -7448,6 +7776,8 @@ ${res.stderr}` : ""),
|
|
|
7448
7776
|
return runAgent2({
|
|
7449
7777
|
...baseAgentOptions,
|
|
7450
7778
|
instruction: turnInstruction,
|
|
7779
|
+
// v4 steer: the loop drains injected content at each step.
|
|
7780
|
+
takeInjected: () => session.drainInjected(),
|
|
7451
7781
|
priorSummary,
|
|
7452
7782
|
// Carry-over for capsule seed ranking: the previous
|
|
7453
7783
|
// turn's instruction (the current turn is recorded only
|
|
@@ -7457,6 +7787,9 @@ ${res.stderr}` : ""),
|
|
|
7457
7787
|
auto: turnAuto,
|
|
7458
7788
|
plan,
|
|
7459
7789
|
images,
|
|
7790
|
+
// v5: per-turn reasoning budget beats the spawn-time flag,
|
|
7791
|
+
// so a host's effort picker takes effect without a respawn.
|
|
7792
|
+
reasoningEffort: turnEffort ?? baseAgentOptions.reasoningEffort,
|
|
7460
7793
|
approve: session.approve,
|
|
7461
7794
|
askUser: session.askUser,
|
|
7462
7795
|
onEvent: session.onEvent
|
|
@@ -7469,11 +7802,13 @@ ${res.stderr}` : ""),
|
|
|
7469
7802
|
instruction: turn.instruction,
|
|
7470
7803
|
summary: turn.result?.finalText ?? "turn failed",
|
|
7471
7804
|
changes: turn.result?.changes ?? [],
|
|
7472
|
-
stopped: turn.result?.stopped ?? "error"
|
|
7805
|
+
stopped: turn.result?.stopped ?? "error",
|
|
7806
|
+
// Metadata only — recordTask never stores the bytes.
|
|
7807
|
+
attachments: lastTurnAttachments
|
|
7473
7808
|
},
|
|
7474
7809
|
Date.now()
|
|
7475
7810
|
);
|
|
7476
|
-
saveSession(
|
|
7811
|
+
saveSession(mainRoot, record);
|
|
7477
7812
|
return summarizeSession(record);
|
|
7478
7813
|
}
|
|
7479
7814
|
});
|
|
@@ -7485,12 +7820,16 @@ ${res.stderr}` : ""),
|
|
|
7485
7820
|
emit: emitAndRecord,
|
|
7486
7821
|
bindDecisions: (session) => {
|
|
7487
7822
|
streamApprove = (action) => session.approve(action);
|
|
7823
|
+
session.onAlwaysRule = (action) => {
|
|
7824
|
+
const rule = ruleForAction(action);
|
|
7825
|
+
if (rule) addApprovalRule(mainRoot, rule);
|
|
7826
|
+
};
|
|
7488
7827
|
const rl = readline6.createInterface({ input: process.stdin });
|
|
7489
7828
|
rl.on("line", (raw) => {
|
|
7490
7829
|
const msg = parseHostMessage(raw);
|
|
7491
7830
|
if (!msg) return;
|
|
7492
7831
|
if (msg.kind === "approve") {
|
|
7493
|
-
session.submitDecision(msg.id, msg.approve);
|
|
7832
|
+
session.submitDecision(msg.id, msg.approve, msg.always);
|
|
7494
7833
|
runOutcome.noteDecision(msg.id, msg.approve);
|
|
7495
7834
|
} else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
|
|
7496
7835
|
else if (msg.kind === "cancel") {
|
|
@@ -7520,21 +7859,23 @@ ${res.stderr}` : ""),
|
|
|
7520
7859
|
if (!autonomous && !tty) {
|
|
7521
7860
|
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).");
|
|
7522
7861
|
}
|
|
7523
|
-
const { agentTask } = await import('./interactive-
|
|
7524
|
-
const { nodeCodeFs } = await import('./session-
|
|
7862
|
+
const { agentTask } = await import('./interactive-EW2VJ3BZ.js');
|
|
7863
|
+
const { nodeCodeFs } = await import('./session-4BGYASOH.js');
|
|
7525
7864
|
const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
|
|
7526
7865
|
let priorSummary;
|
|
7527
7866
|
let priorInstruction;
|
|
7528
7867
|
if (opts.continue) {
|
|
7529
|
-
const { loadLatestSession, summarizeSession } = await import('./session-store-
|
|
7530
|
-
const prev = loadLatestSession(
|
|
7868
|
+
const { loadLatestSession, loadSession, summarizeSession } = await import('./session-store-AQUORKWB.js');
|
|
7869
|
+
const prev = typeof opts.continue === "string" ? loadSession(mainRoot, opts.continue) : loadLatestSession(mainRoot);
|
|
7531
7870
|
if (prev) {
|
|
7532
7871
|
priorSummary = summarizeSession(prev);
|
|
7533
7872
|
priorInstruction = prev.tasks.at(-1)?.instruction;
|
|
7873
|
+
} else if (typeof opts.continue === "string") {
|
|
7874
|
+
info(`could not load session ${opts.continue} \u2014 continuing without its recap`);
|
|
7534
7875
|
}
|
|
7535
7876
|
}
|
|
7536
7877
|
const prompter = tty ? new TtyPrompter() : void 0;
|
|
7537
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
7878
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-IGHJKKSL.js');
|
|
7538
7879
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
7539
7880
|
getGraph: () => graph,
|
|
7540
7881
|
root: root2,
|
|
@@ -7558,11 +7899,11 @@ ${res.stderr}` : ""),
|
|
|
7558
7899
|
const { loadFederation } = await import('./federation-MDQPO3PW.js');
|
|
7559
7900
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
7560
7901
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
7561
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
7562
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
7902
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-RJHH3KMF.js');
|
|
7903
|
+
const { resolveGraphBackend } = await import('./graph-backend-W2TNTMY7.js');
|
|
7563
7904
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7564
7905
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7565
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
7906
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-ORPA5C2K.js');
|
|
7566
7907
|
const federation = loadFederation(root2);
|
|
7567
7908
|
const modelProfile = mergeModelExecutionProfile(
|
|
7568
7909
|
resolveModelExecutionProfile({
|
|
@@ -7656,7 +7997,7 @@ ${res.stderr}` : ""),
|
|
|
7656
7997
|
attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
|
|
7657
7998
|
});
|
|
7658
7999
|
if (opts.out) {
|
|
7659
|
-
|
|
8000
|
+
fs12.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
|
|
7660
8001
|
}
|
|
7661
8002
|
if (global.json) {
|
|
7662
8003
|
json(result);
|
|
@@ -7708,11 +8049,11 @@ function resolveSecurityTierFlag(flag, fromConfig, auto) {
|
|
|
7708
8049
|
return auto ? "L1" : "L0";
|
|
7709
8050
|
}
|
|
7710
8051
|
function confirm2(question) {
|
|
7711
|
-
return new Promise((
|
|
8052
|
+
return new Promise((resolve23) => {
|
|
7712
8053
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
7713
8054
|
rl.question(`${question} [y/N] `, (answer) => {
|
|
7714
8055
|
rl.close();
|
|
7715
|
-
|
|
8056
|
+
resolve23(/^y(es)?$/i.test(answer.trim()));
|
|
7716
8057
|
});
|
|
7717
8058
|
});
|
|
7718
8059
|
}
|
|
@@ -7869,7 +8210,7 @@ async function addCmd(root2, rest, opts, asJson) {
|
|
|
7869
8210
|
}
|
|
7870
8211
|
function readPackageVersion(root2) {
|
|
7871
8212
|
try {
|
|
7872
|
-
const pkg = JSON.parse(
|
|
8213
|
+
const pkg = JSON.parse(fs12__default.readFileSync(path43__default.join(root2, "package.json"), "utf8"));
|
|
7873
8214
|
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
7874
8215
|
} catch {
|
|
7875
8216
|
return void 0;
|
|
@@ -7877,7 +8218,7 @@ function readPackageVersion(root2) {
|
|
|
7877
8218
|
}
|
|
7878
8219
|
function readOptionalFile(p) {
|
|
7879
8220
|
try {
|
|
7880
|
-
const t =
|
|
8221
|
+
const t = fs12__default.readFileSync(p, "utf8");
|
|
7881
8222
|
return t.trim() ? t : void 0;
|
|
7882
8223
|
} catch {
|
|
7883
8224
|
return void 0;
|
|
@@ -7892,8 +8233,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
|
|
|
7892
8233
|
if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
|
|
7893
8234
|
const version = (opts.version || readPackageVersion(root2) || "").trim();
|
|
7894
8235
|
if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
|
|
7895
|
-
const readme = readOptionalFile(opts.readme ?
|
|
7896
|
-
const dts = opts.dts ? readOptionalFile(
|
|
8236
|
+
const readme = readOptionalFile(opts.readme ? path43__default.resolve(opts.readme) : path43__default.join(root2, "README.md"));
|
|
8237
|
+
const dts = opts.dts ? readOptionalFile(path43__default.resolve(opts.dts)) : void 0;
|
|
7897
8238
|
if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
|
|
7898
8239
|
const result = await publishPrivateLibrary(
|
|
7899
8240
|
{ name, version, readme, dts, language: opts.language },
|
|
@@ -8025,8 +8366,8 @@ function registerExport(program) {
|
|
|
8025
8366
|
out(content.trimEnd());
|
|
8026
8367
|
return;
|
|
8027
8368
|
}
|
|
8028
|
-
|
|
8029
|
-
|
|
8369
|
+
fs12.mkdirSync(path43.dirname(path43.resolve(file)), { recursive: true });
|
|
8370
|
+
fs12.writeFileSync(file, content);
|
|
8030
8371
|
info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
|
|
8031
8372
|
});
|
|
8032
8373
|
applyGlobalOptions(cmd);
|
|
@@ -8036,43 +8377,43 @@ function detectFormat(file) {
|
|
|
8036
8377
|
if (lower.endsWith(".cdx.json")) return "cyclonedx";
|
|
8037
8378
|
if (lower.endsWith(".spdx.json")) return "spdx";
|
|
8038
8379
|
if (file === "-") return "json";
|
|
8039
|
-
return formatForExt(
|
|
8380
|
+
return formatForExt(path43.extname(file));
|
|
8040
8381
|
}
|
|
8041
8382
|
function registerBundle(program) {
|
|
8042
8383
|
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) {
|
|
8043
8384
|
const global = readGlobal(this);
|
|
8044
8385
|
const root2 = rootOf(global);
|
|
8045
|
-
const outDir =
|
|
8386
|
+
const outDir = path43.resolve(root2, opts.out ?? "vg-bundle");
|
|
8046
8387
|
let grammarFiles;
|
|
8047
8388
|
try {
|
|
8048
8389
|
grammarFiles = resolvedGrammarFiles();
|
|
8049
8390
|
} catch {
|
|
8050
8391
|
throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
|
|
8051
8392
|
}
|
|
8052
|
-
|
|
8393
|
+
fs12.mkdirSync(path43.join(outDir, "grammars"), { recursive: true });
|
|
8053
8394
|
let grammarCount = 0;
|
|
8054
8395
|
for (const { fileName, absPath } of grammarFiles) {
|
|
8055
|
-
|
|
8396
|
+
fs12.copyFileSync(absPath, path43.join(outDir, "grammars", fileName));
|
|
8056
8397
|
grammarCount++;
|
|
8057
8398
|
}
|
|
8058
8399
|
const included = [`grammars/ (${grammarCount} .wasm)`];
|
|
8059
8400
|
const graphSrc = resolveGraphPath(root2, global.graph);
|
|
8060
|
-
if (
|
|
8061
|
-
|
|
8401
|
+
if (fs12.existsSync(graphSrc)) {
|
|
8402
|
+
fs12.copyFileSync(graphSrc, path43.join(outDir, "graph.json"));
|
|
8062
8403
|
included.push("graph.json");
|
|
8063
8404
|
} else {
|
|
8064
8405
|
const graph = loadGraphFileWithSnapshot(graphSrc);
|
|
8065
8406
|
if (graph) {
|
|
8066
|
-
|
|
8407
|
+
fs12.writeFileSync(path43.join(outDir, "graph.json"), serializeGraph(graph));
|
|
8067
8408
|
included.push("graph.json");
|
|
8068
8409
|
}
|
|
8069
8410
|
}
|
|
8070
8411
|
const cat = catalogPath(root2);
|
|
8071
|
-
if (
|
|
8072
|
-
|
|
8412
|
+
if (fs12.existsSync(cat)) {
|
|
8413
|
+
fs12.copyFileSync(cat, path43.join(outDir, "vibgrate.lib.json"));
|
|
8073
8414
|
included.push("vibgrate.lib.json");
|
|
8074
|
-
if (
|
|
8075
|
-
|
|
8415
|
+
if (fs12.existsSync(libDir(root2))) {
|
|
8416
|
+
fs12.cpSync(libDir(root2), path43.join(outDir, "lib"), { recursive: true });
|
|
8076
8417
|
included.push("lib/");
|
|
8077
8418
|
}
|
|
8078
8419
|
}
|
|
@@ -8084,15 +8425,15 @@ function registerBundle(program) {
|
|
|
8084
8425
|
included,
|
|
8085
8426
|
usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
|
|
8086
8427
|
};
|
|
8087
|
-
|
|
8428
|
+
fs12.writeFileSync(path43.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
|
|
8088
8429
|
`);
|
|
8089
8430
|
if (global.json) {
|
|
8090
|
-
json({ out:
|
|
8431
|
+
json({ out: path43.relative(root2, outDir), ...manifest });
|
|
8091
8432
|
return;
|
|
8092
8433
|
}
|
|
8093
|
-
info(`${c.cyan("vg bundle")} \xB7 wrote ${
|
|
8434
|
+
info(`${c.cyan("vg bundle")} \xB7 wrote ${path43.relative(root2, outDir)}/`);
|
|
8094
8435
|
for (const i of included) info(` ${c.green("\u2714")} ${i}`);
|
|
8095
|
-
info(c.dim(` offline: vg build --grammars "${
|
|
8436
|
+
info(c.dim(` offline: vg build --grammars "${path43.relative(root2, outDir)}/grammars"`));
|
|
8096
8437
|
});
|
|
8097
8438
|
applyGlobalOptions(cmd);
|
|
8098
8439
|
}
|
|
@@ -8110,7 +8451,7 @@ async function runDoctor(global) {
|
|
|
8110
8451
|
const root2 = rootOf(global);
|
|
8111
8452
|
const local = global.local === true;
|
|
8112
8453
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
8113
|
-
const configFile = CONFIG_BASENAMES.find((f) =>
|
|
8454
|
+
const configFile = CONFIG_BASENAMES.find((f) => fs12.existsSync(path43.join(root2, f))) ?? null;
|
|
8114
8455
|
const graph = loadGraph(root2, graphPath);
|
|
8115
8456
|
let staleFiles = null;
|
|
8116
8457
|
if (graph) {
|
|
@@ -8136,14 +8477,14 @@ async function runDoctor(global) {
|
|
|
8136
8477
|
root: root2,
|
|
8137
8478
|
configFile,
|
|
8138
8479
|
map: {
|
|
8139
|
-
path:
|
|
8480
|
+
path: path43.relative(root2, graphPath),
|
|
8140
8481
|
built: graph !== null,
|
|
8141
8482
|
generatedAt: graph?.generatedAt ?? null,
|
|
8142
8483
|
staleFiles
|
|
8143
8484
|
},
|
|
8144
8485
|
libCatalog: {
|
|
8145
|
-
path:
|
|
8146
|
-
present:
|
|
8486
|
+
path: path43.relative(root2, catalogPath(root2)),
|
|
8487
|
+
present: fs12.existsSync(catalogPath(root2)),
|
|
8147
8488
|
libraries: libCount
|
|
8148
8489
|
},
|
|
8149
8490
|
credentials: creds,
|
|
@@ -8200,7 +8541,7 @@ async function runDoctor(global) {
|
|
|
8200
8541
|
);
|
|
8201
8542
|
info(
|
|
8202
8543
|
` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
|
|
8203
|
-
` \xB7 last ${
|
|
8544
|
+
` \xB7 last ${path43.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
|
|
8204
8545
|
) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
|
|
8205
8546
|
);
|
|
8206
8547
|
if (li.dynamicOnToken || li.dynamicCustomSampler) {
|
|
@@ -8400,7 +8741,7 @@ function registerDaemon(program) {
|
|
|
8400
8741
|
const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
|
|
8401
8742
|
const global = readGlobal(this);
|
|
8402
8743
|
const socketPath = socketOf(this);
|
|
8403
|
-
const root2 =
|
|
8744
|
+
const root2 = path43.resolve(rootArg ?? rootOf(global));
|
|
8404
8745
|
if (!await vgdIsRunning({ socketPath })) {
|
|
8405
8746
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
8406
8747
|
}
|
|
@@ -8436,7 +8777,7 @@ function registerDaemon(program) {
|
|
|
8436
8777
|
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) {
|
|
8437
8778
|
const global = readGlobal(this);
|
|
8438
8779
|
const socketPath = socketOf(this);
|
|
8439
|
-
const primary =
|
|
8780
|
+
const primary = path43.resolve(rootArg ?? rootOf(global));
|
|
8440
8781
|
if (!await vgdIsRunning({ socketPath })) {
|
|
8441
8782
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
8442
8783
|
}
|
|
@@ -8464,7 +8805,7 @@ function registerDaemon(program) {
|
|
|
8464
8805
|
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) {
|
|
8465
8806
|
const global = readGlobal(this);
|
|
8466
8807
|
const socketPath = socketOf(this);
|
|
8467
|
-
const root2 =
|
|
8808
|
+
const root2 = path43.resolve(rootArg ?? rootOf(global));
|
|
8468
8809
|
if (!await vgdIsRunning({ socketPath })) {
|
|
8469
8810
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
8470
8811
|
}
|
|
@@ -8478,7 +8819,7 @@ function registerDaemon(program) {
|
|
|
8478
8819
|
throw new CliError(loaded.error, ExitCode.NOT_FOUND);
|
|
8479
8820
|
}
|
|
8480
8821
|
if (!loaded.ok) {
|
|
8481
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
8822
|
+
const { loadGraph: loadGraph2 } = await import('./load-64RK5O6C.js');
|
|
8482
8823
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
8483
8824
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
8484
8825
|
const graph = loadGraph2(root2, global.graph);
|
|
@@ -8594,7 +8935,7 @@ function socketOf(cmd) {
|
|
|
8594
8935
|
let c2 = cmd;
|
|
8595
8936
|
while (c2) {
|
|
8596
8937
|
const opts = c2.opts();
|
|
8597
|
-
if (opts.socket) return
|
|
8938
|
+
if (opts.socket) return path43.resolve(opts.socket);
|
|
8598
8939
|
c2 = c2.parent;
|
|
8599
8940
|
}
|
|
8600
8941
|
return vgdSocketPath();
|
|
@@ -8674,7 +9015,7 @@ async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
|
|
|
8674
9015
|
}
|
|
8675
9016
|
function readVgdPid() {
|
|
8676
9017
|
try {
|
|
8677
|
-
const raw =
|
|
9018
|
+
const raw = fs12.readFileSync(vgdPidPath(), "utf8").trim();
|
|
8678
9019
|
const pid = Number.parseInt(raw, 10);
|
|
8679
9020
|
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
8680
9021
|
} catch {
|
|
@@ -8759,7 +9100,7 @@ function registerPolicy(program) {
|
|
|
8759
9100
|
const global = readGlobal(this);
|
|
8760
9101
|
let raw;
|
|
8761
9102
|
try {
|
|
8762
|
-
raw =
|
|
9103
|
+
raw = fs12.readFileSync(file, "utf8");
|
|
8763
9104
|
} catch {
|
|
8764
9105
|
throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
|
|
8765
9106
|
}
|
|
@@ -8878,12 +9219,299 @@ function registerLlmHost(program) {
|
|
|
8878
9219
|
});
|
|
8879
9220
|
applyGlobalOptions(cmd);
|
|
8880
9221
|
}
|
|
9222
|
+
var DIGEST_FORMATS = ["md", "json", "html"];
|
|
9223
|
+
var DIGEST_LEVELS = ["concise", "full"];
|
|
9224
|
+
var MAP_FORMATS = ["json", "md", "mermaid"];
|
|
9225
|
+
var MAP_PROFILES = ["integration", "migration", "governance"];
|
|
9226
|
+
var GATE_FORMATS = ["text", "json", "sarif"];
|
|
9227
|
+
var LANGUAGE_EXTENSIONS = {
|
|
9228
|
+
rust: [".rs"],
|
|
9229
|
+
ruby: [".rb", ".rake", ".gemspec"],
|
|
9230
|
+
php: [".php"],
|
|
9231
|
+
dart: [".dart"],
|
|
9232
|
+
swift: [".swift"],
|
|
9233
|
+
scala: [".scala", ".sc"],
|
|
9234
|
+
cplusplus: [".cpp", ".cc", ".cxx", ".hpp", ".hh", ".hxx", ".h", ".ixx"],
|
|
9235
|
+
cobol: [".cbl", ".cob", ".cpy", ".cob85", ".cobol"],
|
|
9236
|
+
vb6: [".vbp", ".bas", ".cls", ".frm", ".ctl", ".dsr"]
|
|
9237
|
+
};
|
|
9238
|
+
var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
9239
|
+
"node_modules",
|
|
9240
|
+
".git",
|
|
9241
|
+
".vibgrate",
|
|
9242
|
+
".hg",
|
|
9243
|
+
".svn",
|
|
9244
|
+
"dist",
|
|
9245
|
+
"build",
|
|
9246
|
+
"out",
|
|
9247
|
+
"bin",
|
|
9248
|
+
"obj",
|
|
9249
|
+
"target",
|
|
9250
|
+
"vendor",
|
|
9251
|
+
"coverage",
|
|
9252
|
+
"__pycache__",
|
|
9253
|
+
"DerivedData",
|
|
9254
|
+
"Pods"
|
|
9255
|
+
]);
|
|
9256
|
+
var TEST_PATTERNS = [/[/\\]tests?[/\\]/i, /[/\\]__tests__[/\\]/i, /[/\\]spec[/\\]/i, /\.spec\./i, /\.test\./i];
|
|
9257
|
+
var MAX_EXTRACT_FILE_BYTES = 2 * 1024 * 1024;
|
|
9258
|
+
async function requireEngine() {
|
|
9259
|
+
if (kernelDisabled()) {
|
|
9260
|
+
throw engineUnavailable(
|
|
9261
|
+
"vg hcs needs the HCS engine module, but VIBGRATE_NO_KERNEL is set \u2014 unset it and retry"
|
|
9262
|
+
);
|
|
9263
|
+
}
|
|
9264
|
+
let engine = await loadHcsEngine();
|
|
9265
|
+
if (engine) return engine;
|
|
9266
|
+
const result = await ensureHcsModule();
|
|
9267
|
+
if (result.status === "installed") {
|
|
9268
|
+
info(c.dim(`installed ${HCS_MODULE_NAME}@${result.version} (proprietary license, runs fully locally)`));
|
|
9269
|
+
resetHcsEngineCache();
|
|
9270
|
+
engine = await loadHcsEngine();
|
|
9271
|
+
if (engine) return engine;
|
|
9272
|
+
}
|
|
9273
|
+
if (result.status === "declined") {
|
|
9274
|
+
throw engineUnavailable(
|
|
9275
|
+
"the HCS engine module was previously declined \u2014 run `vg module install hcs` to install it"
|
|
9276
|
+
);
|
|
9277
|
+
}
|
|
9278
|
+
throw engineUnavailable(
|
|
9279
|
+
`the HCS engine module is not installed and could not be fetched${result.detail ? ` (${result.detail})` : ""} \u2014 run \`vg module install hcs\` on a machine with registry access, or point VIBGRATE_HCS_PATH at an installed engine. This exit (6, ENGINE_UNAVAILABLE) is distinct from a gate failure (2) by design.`
|
|
9280
|
+
);
|
|
9281
|
+
}
|
|
9282
|
+
async function readStdin() {
|
|
9283
|
+
const chunks = [];
|
|
9284
|
+
for await (const chunk of process.stdin) {
|
|
9285
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
9286
|
+
}
|
|
9287
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
9288
|
+
}
|
|
9289
|
+
function readFileOrThrow(file, label) {
|
|
9290
|
+
const p = path43.resolve(file);
|
|
9291
|
+
if (!fs12.existsSync(p)) throw usageError(`${label} file not found: ${p}`);
|
|
9292
|
+
return fs12.readFileSync(p, "utf-8");
|
|
9293
|
+
}
|
|
9294
|
+
async function readInput(file, label) {
|
|
9295
|
+
return file ? readFileOrThrow(file, label) : readStdin();
|
|
9296
|
+
}
|
|
9297
|
+
function writeOutput(outFile, content) {
|
|
9298
|
+
if (!outFile) {
|
|
9299
|
+
process.stdout.write(content.endsWith("\n") ? content : content + "\n");
|
|
9300
|
+
return;
|
|
9301
|
+
}
|
|
9302
|
+
const outPath = path43.resolve(outFile);
|
|
9303
|
+
const dir = path43.dirname(outPath);
|
|
9304
|
+
if (!fs12.existsSync(dir)) throw usageError(`output directory does not exist: ${dir}`);
|
|
9305
|
+
fs12.writeFileSync(outPath, content.endsWith("\n") ? content : content + "\n", "utf-8");
|
|
9306
|
+
info(c.dim(`wrote ${outPath}`));
|
|
9307
|
+
}
|
|
9308
|
+
function requireChoice(value, valid2, flag) {
|
|
9309
|
+
if (!valid2.includes(value)) throw usageError(`${flag} must be one of: ${valid2.join(", ")}`);
|
|
9310
|
+
}
|
|
9311
|
+
function engineCall(what, fn) {
|
|
9312
|
+
try {
|
|
9313
|
+
return fn();
|
|
9314
|
+
} catch (err) {
|
|
9315
|
+
throw new CliError(`${what} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
function registerHcs(program) {
|
|
9319
|
+
const cmd = program.command("hcs").description("Holistic Code Specification \u2014 extract and analyze deterministic code facts");
|
|
9320
|
+
cmd.command("extract").description("extract HCS facts from source into an NDJSON stream").argument("[dir]", "directory to extract from", ".").option("--language <lang>", "only extract this language (default: all the engine supports)").option("--include-tests", "include test files (excluded by default)").option("-o, --out <file>", "write NDJSON to file (default: stdout)").option(
|
|
9321
|
+
"--previous <file>",
|
|
9322
|
+
"previous extract output to update incrementally (default: the --out file, so repeated `-o` runs are incremental; a missing file means a full extraction)"
|
|
9323
|
+
).option("--full", "ignore the previous stream and re-extract every file from scratch").action(async function(dir, opts) {
|
|
9324
|
+
const engine = await requireEngine();
|
|
9325
|
+
if (!engine.extractFacts || !engine.supportedLanguages) {
|
|
9326
|
+
throw engineUnavailable(
|
|
9327
|
+
"the installed HCS engine does not include extraction \u2014 update it with `vg module install hcs --force`"
|
|
9328
|
+
);
|
|
9329
|
+
}
|
|
9330
|
+
const canIncremental = Boolean(engine.planExtract && engine.mergeExtract);
|
|
9331
|
+
if (opts.previous && !canIncremental) {
|
|
9332
|
+
throw engineUnavailable(
|
|
9333
|
+
"the installed HCS engine does not include incremental extraction \u2014 update it with `vg module install hcs --force`"
|
|
9334
|
+
);
|
|
9335
|
+
}
|
|
9336
|
+
const statePath = opts.previous ?? opts.out;
|
|
9337
|
+
const useIncremental = canIncremental && statePath !== void 0;
|
|
9338
|
+
const root2 = path43.resolve(dir);
|
|
9339
|
+
if (!fs12.existsSync(root2) || !fs12.statSync(root2).isDirectory()) {
|
|
9340
|
+
throw usageError(`not a directory: ${root2}`);
|
|
9341
|
+
}
|
|
9342
|
+
const supported = new Set(
|
|
9343
|
+
engine.supportedLanguages().split(",").map((l) => l.trim()).filter(Boolean)
|
|
9344
|
+
);
|
|
9345
|
+
if (opts.language && !supported.has(opts.language)) {
|
|
9346
|
+
throw usageError(`--language must be one of: ${[...supported].sort().join(", ")}`);
|
|
9347
|
+
}
|
|
9348
|
+
const wanted = opts.language ? /* @__PURE__ */ new Set([opts.language]) : supported;
|
|
9349
|
+
const extToLang = /* @__PURE__ */ new Map();
|
|
9350
|
+
for (const [lang, exts] of Object.entries(LANGUAGE_EXTENSIONS)) {
|
|
9351
|
+
if (wanted.has(lang)) for (const ext of exts) extToLang.set(ext, lang);
|
|
9352
|
+
}
|
|
9353
|
+
const byLanguage = /* @__PURE__ */ new Map();
|
|
9354
|
+
const walk2 = (abs, rel) => {
|
|
9355
|
+
let entries;
|
|
9356
|
+
try {
|
|
9357
|
+
entries = fs12.readdirSync(abs, { withFileTypes: true });
|
|
9358
|
+
} catch {
|
|
9359
|
+
return;
|
|
9360
|
+
}
|
|
9361
|
+
for (const entry of entries.sort((a, b) => a.name < b.name ? -1 : 1)) {
|
|
9362
|
+
if (entry.name.startsWith(".")) continue;
|
|
9363
|
+
const absChild = path43.join(abs, entry.name);
|
|
9364
|
+
const relChild = rel ? `${rel}/${entry.name}` : entry.name;
|
|
9365
|
+
if (entry.isDirectory()) {
|
|
9366
|
+
if (!SKIP_DIRS2.has(entry.name)) walk2(absChild, relChild);
|
|
9367
|
+
continue;
|
|
9368
|
+
}
|
|
9369
|
+
if (!entry.isFile()) continue;
|
|
9370
|
+
if (!opts.includeTests && TEST_PATTERNS.some((p) => p.test(relChild))) continue;
|
|
9371
|
+
const lang = extToLang.get(path43.extname(entry.name).toLowerCase());
|
|
9372
|
+
if (!lang) continue;
|
|
9373
|
+
try {
|
|
9374
|
+
if (fs12.statSync(absChild).size > MAX_EXTRACT_FILE_BYTES) continue;
|
|
9375
|
+
const content = fs12.readFileSync(absChild, "utf-8");
|
|
9376
|
+
let bucket = byLanguage.get(lang);
|
|
9377
|
+
if (!bucket) byLanguage.set(lang, bucket = []);
|
|
9378
|
+
bucket.push({ path: relChild, content });
|
|
9379
|
+
} catch {
|
|
9380
|
+
}
|
|
9381
|
+
}
|
|
9382
|
+
};
|
|
9383
|
+
walk2(root2, "");
|
|
9384
|
+
if (byLanguage.size === 0 && !useIncremental) {
|
|
9385
|
+
info(`no extractable sources found under ${root2} (languages: ${[...wanted].sort().join(", ")})`);
|
|
9386
|
+
writeOutput(opts.out, "");
|
|
9387
|
+
return;
|
|
9388
|
+
}
|
|
9389
|
+
const extractLanguage = (language, only) => {
|
|
9390
|
+
let files = byLanguage.get(language);
|
|
9391
|
+
if (only) files = files.filter((f) => only.has(f.path));
|
|
9392
|
+
if (files.length === 0) return "";
|
|
9393
|
+
info(c.dim(`extracting ${language} (${files.length} files)`));
|
|
9394
|
+
return engineCall(
|
|
9395
|
+
`${language} extraction`,
|
|
9396
|
+
() => engine.extractFacts(JSON.stringify({ language, files, emittedAt: "" }))
|
|
9397
|
+
).trim();
|
|
9398
|
+
};
|
|
9399
|
+
const languages = [...byLanguage.keys()].sort();
|
|
9400
|
+
if (!useIncremental) {
|
|
9401
|
+
const parts2 = languages.map((l) => extractLanguage(l)).filter(Boolean);
|
|
9402
|
+
writeOutput(opts.out, parts2.join("\n"));
|
|
9403
|
+
return;
|
|
9404
|
+
}
|
|
9405
|
+
const previousPath = path43.resolve(statePath);
|
|
9406
|
+
const previousNdjson = !opts.full && fs12.existsSync(previousPath) ? fs12.readFileSync(previousPath, "utf-8") : "";
|
|
9407
|
+
if (opts.full) info(c.dim("running a full re-extraction (--full)"));
|
|
9408
|
+
else if (!previousNdjson) info(c.dim(`previous stream not found at ${previousPath} \u2014 running a full extraction`));
|
|
9409
|
+
const currentFilesJson = JSON.stringify(
|
|
9410
|
+
languages.flatMap((l) => byLanguage.get(l).map((f) => ({ path: f.path, content: f.content })))
|
|
9411
|
+
);
|
|
9412
|
+
const plan = JSON.parse(
|
|
9413
|
+
engineCall("incremental planning", () => engine.planExtract(previousNdjson, currentFilesJson))
|
|
9414
|
+
);
|
|
9415
|
+
const toExtract = /* @__PURE__ */ new Set([...plan.added, ...plan.changed]);
|
|
9416
|
+
info(
|
|
9417
|
+
c.dim(
|
|
9418
|
+
`incremental plan (${plan.mode}): ${plan.added.length} added, ${plan.changed.length} changed, ${plan.removed.length} removed, ${plan.unchanged} unchanged`
|
|
9419
|
+
)
|
|
9420
|
+
);
|
|
9421
|
+
const parts = languages.map((l) => extractLanguage(l, toExtract)).filter(Boolean);
|
|
9422
|
+
const merged = JSON.parse(
|
|
9423
|
+
engineCall(
|
|
9424
|
+
"incremental merge",
|
|
9425
|
+
() => engine.mergeExtract(previousNdjson, parts.join("\n"), currentFilesJson)
|
|
9426
|
+
)
|
|
9427
|
+
);
|
|
9428
|
+
info(
|
|
9429
|
+
c.dim(
|
|
9430
|
+
`merged: ${merged.stats.reusedFacts} facts reused, ${merged.stats.freshFacts} fresh, ${merged.stats.droppedFacts} dropped`
|
|
9431
|
+
)
|
|
9432
|
+
);
|
|
9433
|
+
writeOutput(opts.out, merged.ndjson);
|
|
9434
|
+
});
|
|
9435
|
+
cmd.command("digest").description("render an HCS NDJSON fact stream (from `vg hcs extract`) as Markdown, JSON, or HTML").option("--in <file>", "NDJSON file to read (default: stdin)").option("-o, --out <file>", "write output to file (default: stdout)").option("--format <format>", `output format: ${DIGEST_FORMATS.join(" | ")}`, "md").option("--level <level>", `detail level: ${DIGEST_LEVELS.join(" | ")}`, "concise").option("--title <title>", "override the document title").action(async function(opts) {
|
|
9436
|
+
requireChoice(opts.format, DIGEST_FORMATS, "--format");
|
|
9437
|
+
requireChoice(opts.level, DIGEST_LEVELS, "--level");
|
|
9438
|
+
const engine = await requireEngine();
|
|
9439
|
+
const ndjson = await readInput(opts.in, "input");
|
|
9440
|
+
const options = { format: opts.format, level: opts.level };
|
|
9441
|
+
if (opts.title) options.title = opts.title;
|
|
9442
|
+
writeOutput(opts.out, engineCall("digest rendering", () => engine.renderDigest(ndjson, JSON.stringify(options))));
|
|
9443
|
+
});
|
|
9444
|
+
cmd.command("map").description("build the System Map from an HCS NDJSON fact stream").option("--facts <file>", "NDJSON facts file to read (default: stdin)").option("-o, --out <file>", "write output to file (default: stdout)").option("--format <format>", `output format: ${MAP_FORMATS.join(" | ")}`, "json").option("--profile <profile>", `consumer projection: ${MAP_PROFILES.join(" | ")}`).action(async function(opts) {
|
|
9445
|
+
requireChoice(opts.format, MAP_FORMATS, "--format");
|
|
9446
|
+
if (opts.profile) requireChoice(opts.profile, MAP_PROFILES, "--profile");
|
|
9447
|
+
const generatedAt = readGlobal(this).generatedAt;
|
|
9448
|
+
const engine = await requireEngine();
|
|
9449
|
+
const ndjson = await readInput(opts.facts, "facts");
|
|
9450
|
+
const options = { format: opts.format };
|
|
9451
|
+
if (opts.profile) options.profile = opts.profile;
|
|
9452
|
+
if (generatedAt) options.generatedAt = generatedAt;
|
|
9453
|
+
writeOutput(opts.out, engineCall("map build", () => engine.buildMap(ndjson, JSON.stringify(options))));
|
|
9454
|
+
});
|
|
9455
|
+
cmd.command("gate").description("governance gate \u2014 diff two HCS fact streams and fail (exit 2) on material structural regressions").requiredOption("--baseline <file>", 'baseline NDJSON facts (the "before" stream)').option("--facts <file>", 'current NDJSON facts (the "after" stream; default: stdin)').option("--policy <file>", "gate policy JSON \u2014 thresholds and disabled rules").option("-o, --out <file>", "write the result to file (default: stdout)").option("--format <format>", `output format: ${GATE_FORMATS.join(" | ")}`, "text").action(async function(opts) {
|
|
9456
|
+
requireChoice(opts.format, GATE_FORMATS, "--format");
|
|
9457
|
+
const engine = await requireEngine();
|
|
9458
|
+
const before = readFileOrThrow(opts.baseline, "baseline");
|
|
9459
|
+
const after = await readInput(opts.facts, "facts");
|
|
9460
|
+
let policy;
|
|
9461
|
+
if (opts.policy) {
|
|
9462
|
+
try {
|
|
9463
|
+
policy = JSON.parse(readFileOrThrow(opts.policy, "policy"));
|
|
9464
|
+
} catch (err) {
|
|
9465
|
+
if (err instanceof CliError) throw err;
|
|
9466
|
+
throw usageError(`invalid policy JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
9467
|
+
}
|
|
9468
|
+
}
|
|
9469
|
+
const jsonOut = engineCall(
|
|
9470
|
+
"gate evaluation",
|
|
9471
|
+
() => engine.evaluateGate(before, after, JSON.stringify({ format: "json", policy }))
|
|
9472
|
+
);
|
|
9473
|
+
const pass = JSON.parse(jsonOut).pass;
|
|
9474
|
+
const output = opts.format === "json" ? jsonOut : engineCall("gate evaluation", () => engine.evaluateGate(before, after, JSON.stringify({ format: opts.format, policy })));
|
|
9475
|
+
writeOutput(opts.out, output);
|
|
9476
|
+
if (!pass) {
|
|
9477
|
+
info(c.red("gate FAILED \u2014 material structural regression against the baseline"));
|
|
9478
|
+
process.exitCode = ExitCode.GATE_FAILED;
|
|
9479
|
+
} else {
|
|
9480
|
+
info(c.green("gate passed"));
|
|
9481
|
+
}
|
|
9482
|
+
});
|
|
9483
|
+
cmd.command("validate").description("validate an HCS NDJSON model against the spec (exits with the Appendix-I conformance code)").argument("<file>", "NDJSON model file (e.g. `vg hcs extract` output)").action(async function(file) {
|
|
9484
|
+
const opts = { json: readGlobal(this).json };
|
|
9485
|
+
const engine = await requireEngine();
|
|
9486
|
+
if (!engine.validateLines) {
|
|
9487
|
+
throw engineUnavailable(
|
|
9488
|
+
"the installed HCS engine does not include the validator \u2014 update it with `vg module install hcs --force`"
|
|
9489
|
+
);
|
|
9490
|
+
}
|
|
9491
|
+
const content = readFileOrThrow(file, "model");
|
|
9492
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
9493
|
+
const report = JSON.parse(engineCall("validation", () => engine.validateLines(JSON.stringify(lines))));
|
|
9494
|
+
if (opts.json) {
|
|
9495
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
9496
|
+
} else if (report.ok) {
|
|
9497
|
+
info(c.green("\u2714 conformant \u2014 model satisfies the HCS spec"));
|
|
9498
|
+
} else {
|
|
9499
|
+
info(c.red(`\u2718 ${report.errors.length} validation error(s) (exit ${report.exitCode}):`));
|
|
9500
|
+
for (const e of report.errors.slice(0, 50)) {
|
|
9501
|
+
info(c.dim(` [${e.code}] ${e.factId || "(model)"}: ${e.message}`));
|
|
9502
|
+
}
|
|
9503
|
+
if (report.errors.length > 50) info(c.dim(` \u2026 and ${report.errors.length - 50} more`));
|
|
9504
|
+
}
|
|
9505
|
+
process.exitCode = report.exitCode;
|
|
9506
|
+
});
|
|
9507
|
+
applyGlobalOptions(cmd);
|
|
9508
|
+
}
|
|
8881
9509
|
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) => {
|
|
8882
|
-
const rootDir =
|
|
8883
|
-
const vibgrateDir2 =
|
|
9510
|
+
const rootDir = path43.resolve(targetPath);
|
|
9511
|
+
const vibgrateDir2 = path43.join(rootDir, ".vibgrate");
|
|
8884
9512
|
await ensureDir(vibgrateDir2);
|
|
8885
9513
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
|
|
8886
|
-
const configPath =
|
|
9514
|
+
const configPath = path43.join(rootDir, "vibgrate.config.ts");
|
|
8887
9515
|
if (await pathExists(configPath)) {
|
|
8888
9516
|
console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
|
|
8889
9517
|
} else {
|
|
@@ -8891,7 +9519,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
8891
9519
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
|
|
8892
9520
|
}
|
|
8893
9521
|
if (opts.baseline) {
|
|
8894
|
-
const { runBaseline } = await import('./baseline-
|
|
9522
|
+
const { runBaseline } = await import('./baseline-WVD6P5IO.js');
|
|
8895
9523
|
await runBaseline(rootDir);
|
|
8896
9524
|
}
|
|
8897
9525
|
console.log("");
|
|
@@ -8994,7 +9622,7 @@ function collectPackageImports(graph, ecosystem, pkg) {
|
|
|
8994
9622
|
};
|
|
8995
9623
|
}
|
|
8996
9624
|
async function firstReferenceLine(rootDir, relFile, identifier, readFile3) {
|
|
8997
|
-
const content = await readFile3(
|
|
9625
|
+
const content = await readFile3(path43.join(rootDir, relFile));
|
|
8998
9626
|
if (!content) return null;
|
|
8999
9627
|
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9000
9628
|
const re = new RegExp(`\\b${escaped}\\b`);
|
|
@@ -9032,9 +9660,9 @@ function sitesFromImportFiles(files, limit = 10) {
|
|
|
9032
9660
|
}
|
|
9033
9661
|
async function defaultReadFile(absPath) {
|
|
9034
9662
|
try {
|
|
9035
|
-
const stat2 = await
|
|
9663
|
+
const stat2 = await fs27.stat(absPath);
|
|
9036
9664
|
if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
|
|
9037
|
-
return await
|
|
9665
|
+
return await fs27.readFile(absPath, "utf8");
|
|
9038
9666
|
} catch {
|
|
9039
9667
|
return null;
|
|
9040
9668
|
}
|
|
@@ -9230,7 +9858,7 @@ var AI_ASSISTANT_DETECTORS = [
|
|
|
9230
9858
|
async function detectAiAssistant(rootDir) {
|
|
9231
9859
|
for (const detector of AI_ASSISTANT_DETECTORS) {
|
|
9232
9860
|
for (const file of detector.files) {
|
|
9233
|
-
if (await pathExists$1(
|
|
9861
|
+
if (await pathExists$1(path43.join(rootDir, file))) {
|
|
9234
9862
|
return detector.name;
|
|
9235
9863
|
}
|
|
9236
9864
|
}
|
|
@@ -9424,18 +10052,31 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
9424
10052
|
collectExcludes,
|
|
9425
10053
|
[]
|
|
9426
10054
|
).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) => {
|
|
9427
|
-
const rootDir =
|
|
10055
|
+
const rootDir = path43.resolve(targetPath);
|
|
9428
10056
|
if (!await pathExists$1(rootDir)) {
|
|
9429
10057
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
9430
10058
|
process.exit(1);
|
|
9431
10059
|
}
|
|
9432
10060
|
const hasDsn = !!resolveDsn(opts.dsn);
|
|
9433
|
-
|
|
10061
|
+
let willPush = !opts.offline && (opts.push || hasDsn);
|
|
9434
10062
|
const noLocalArtifacts = opts.localArtifacts === false;
|
|
9435
|
-
const isFirstRun = !await pathExists$1(
|
|
10063
|
+
const isFirstRun = !await pathExists$1(path43.join(rootDir, ".vibgrate", "scan_result.json"));
|
|
9436
10064
|
let pinnedRegion;
|
|
9437
10065
|
let planTier;
|
|
9438
10066
|
let upgradeUrl;
|
|
10067
|
+
let pushBlockedReason;
|
|
10068
|
+
const blockPush = (reason, detailLines) => {
|
|
10069
|
+
if (opts.strict) {
|
|
10070
|
+
console.error(chalk7.red(reason));
|
|
10071
|
+
for (const line of detailLines) console.error(chalk7.dim(line));
|
|
10072
|
+
process.exit(1);
|
|
10073
|
+
}
|
|
10074
|
+
console.error(chalk7.yellow(`\u26A0 ${reason}`));
|
|
10075
|
+
for (const line of detailLines) console.error(chalk7.dim(` ${line}`));
|
|
10076
|
+
console.error(chalk7.dim(" Scanning locally \u2014 results will not be uploaded to Vibgrate Cloud."));
|
|
10077
|
+
pushBlockedReason = reason;
|
|
10078
|
+
willPush = false;
|
|
10079
|
+
};
|
|
9439
10080
|
if (willPush && hasDsn) {
|
|
9440
10081
|
const dsn = resolveDsn(opts.dsn);
|
|
9441
10082
|
const parsed = parseDsn(dsn);
|
|
@@ -9458,59 +10099,45 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
9458
10099
|
planTier = preflight.plan?.tier;
|
|
9459
10100
|
upgradeUrl = preflight.upgradeUrl ?? `https://${dashHostForIngestHost(preflight.ingestHost ?? ingestHost)}/${parsed.workspaceId}`;
|
|
9460
10101
|
if (preflight.vm && !preflight.vm.allowed) {
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
)
|
|
9466
|
-
);
|
|
9467
|
-
process.exit(1);
|
|
9468
|
-
}
|
|
9469
|
-
if (preflight.repositories && !preflight.repositories.allowed) {
|
|
9470
|
-
console.error(
|
|
9471
|
-
chalk7.red(
|
|
9472
|
-
preflight.error ?? `Repository limit reached for the ${preflight.plan.label} plan \u2014 cannot scan a new repository.`
|
|
9473
|
-
)
|
|
9474
|
-
);
|
|
10102
|
+
blockPush(preflight.error ?? "VM meter usage exhausted", [
|
|
10103
|
+
`VM minutes: ${preflight.vm.used}/${preflight.vm.limit} (${preflight.plan.label} plan) \u2014 enable overages or upgrade your plan.`
|
|
10104
|
+
]);
|
|
10105
|
+
} else if (preflight.repositories && !preflight.repositories.allowed) {
|
|
9475
10106
|
const max = preflight.repositories.max < 0 ? "unlimited" : String(preflight.repositories.max);
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
)
|
|
9480
|
-
);
|
|
10107
|
+
const detail = [
|
|
10108
|
+
`Repositories: ${preflight.repositories.total}/${max} (${preflight.plan.label} plan) \u2014 archive a repository or upgrade your plan.`
|
|
10109
|
+
];
|
|
9481
10110
|
if (preflight.upgradeUrl) {
|
|
9482
|
-
|
|
10111
|
+
detail.push(`Upgrade: ${preflight.upgradeUrl}`);
|
|
9483
10112
|
}
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
console.error(chalk7.red(preflight.error ?? "Scan ingestion not allowed for this workspace."));
|
|
9488
|
-
console.error(
|
|
9489
|
-
chalk7.dim(
|
|
9490
|
-
`Credits: ${preflight.scans.used}/${preflight.scans.limit} (${preflight.plan.label} plan)`
|
|
9491
|
-
)
|
|
10113
|
+
blockPush(
|
|
10114
|
+
preflight.error ?? `Repository limit reached for the ${preflight.plan.label} plan \u2014 cannot upload a new repository.`,
|
|
10115
|
+
detail
|
|
9492
10116
|
);
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
`Plan: ${preflight.plan.label} \u2014 scan credits ${preflight.scans.used}/${preflight.scans.limit} this month`
|
|
9499
|
-
)
|
|
9500
|
-
);
|
|
9501
|
-
if (preflight.repository?.unchanged && !opts.force) {
|
|
10117
|
+
} else if (preflight.status === "error" || !preflight.scans.allowed) {
|
|
10118
|
+
blockPush(preflight.error ?? "Scan ingestion not allowed for this workspace.", [
|
|
10119
|
+
`Credits: ${preflight.scans.used}/${preflight.scans.limit} (${preflight.plan.label} plan)`
|
|
10120
|
+
]);
|
|
10121
|
+
} else {
|
|
9502
10122
|
console.log(
|
|
9503
|
-
chalk7.
|
|
10123
|
+
chalk7.dim(
|
|
10124
|
+
`Plan: ${preflight.plan.label} \u2014 scan credits ${preflight.scans.used}/${preflight.scans.limit} this month`
|
|
10125
|
+
)
|
|
9504
10126
|
);
|
|
9505
|
-
if (preflight.repository.
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
10127
|
+
if (preflight.repository?.unchanged && !opts.force) {
|
|
10128
|
+
console.log(
|
|
10129
|
+
chalk7.green("\u2714") + ` Repository unchanged at ${preflight.repository.lastVcsSha?.slice(0, 7) ?? "same revision"} \u2014 skipping scan.`
|
|
10130
|
+
);
|
|
10131
|
+
if (preflight.repository.lastIngestId) {
|
|
10132
|
+
emitIngestIdLine(preflight.repository.lastIngestId, { unchanged: true });
|
|
10133
|
+
const dashUrl = `https://${dashHostForIngestHost(ingestHost)}/${parsed.workspaceId}/scan/${preflight.repository.lastIngestId}`;
|
|
10134
|
+
console.log(chalk7.dim(` Latest report: ${dashUrl}`));
|
|
10135
|
+
} else if (opts.strict) {
|
|
10136
|
+
console.error(chalk7.red("Repository unchanged but no previous ingest id available."));
|
|
10137
|
+
process.exit(1);
|
|
10138
|
+
}
|
|
10139
|
+
return;
|
|
9512
10140
|
}
|
|
9513
|
-
return;
|
|
9514
10141
|
}
|
|
9515
10142
|
} catch (e) {
|
|
9516
10143
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -9626,6 +10253,12 @@ Failing fitness function: drift worsened by ${worseningPercent.toFixed(2)}% (thr
|
|
|
9626
10253
|
}
|
|
9627
10254
|
if (willPush) {
|
|
9628
10255
|
await autoPush(artifact, rootDir, scanOpts);
|
|
10256
|
+
} else if (pushBlockedReason) {
|
|
10257
|
+
console.error("");
|
|
10258
|
+
console.error(chalk7.yellow(`\u26A0 Results were not uploaded: ${pushBlockedReason}`));
|
|
10259
|
+
if (upgradeUrl) {
|
|
10260
|
+
console.error(chalk7.dim(` Upgrade: ${upgradeUrl}`));
|
|
10261
|
+
}
|
|
9629
10262
|
}
|
|
9630
10263
|
const showAiPrompt = scanOpts.format === "text" && !opts.quiet && !hasDsn && !opts.offline && !noLocalArtifacts && !opts.maxPrivacy && isFirstRun;
|
|
9631
10264
|
if (showAiPrompt) {
|
|
@@ -9675,7 +10308,7 @@ var WATCHED_FILES = /* @__PURE__ */ new Set([
|
|
|
9675
10308
|
"packages.lock.json"
|
|
9676
10309
|
]);
|
|
9677
10310
|
var WATCHED_EXT = /\.(cs|fs)proj$/i;
|
|
9678
|
-
var
|
|
10311
|
+
var SKIP_DIRS3 = /* @__PURE__ */ new Set([
|
|
9679
10312
|
"node_modules",
|
|
9680
10313
|
".git",
|
|
9681
10314
|
"dist",
|
|
@@ -9696,7 +10329,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
|
9696
10329
|
function scanStaleness(rootDir, artifactPath) {
|
|
9697
10330
|
let ref;
|
|
9698
10331
|
try {
|
|
9699
|
-
ref =
|
|
10332
|
+
ref = fs12.statSync(artifactPath).mtimeMs;
|
|
9700
10333
|
} catch {
|
|
9701
10334
|
return { stale: false };
|
|
9702
10335
|
}
|
|
@@ -9708,7 +10341,7 @@ function scanStaleness(rootDir, artifactPath) {
|
|
|
9708
10341
|
if (depth > 8 || scanned > MAX_ENTRIES2) return;
|
|
9709
10342
|
let entries;
|
|
9710
10343
|
try {
|
|
9711
|
-
entries =
|
|
10344
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
9712
10345
|
} catch {
|
|
9713
10346
|
return;
|
|
9714
10347
|
}
|
|
@@ -9716,20 +10349,20 @@ function scanStaleness(rootDir, artifactPath) {
|
|
|
9716
10349
|
scanned++;
|
|
9717
10350
|
if (scanned > MAX_ENTRIES2) break;
|
|
9718
10351
|
if (e.isDirectory()) {
|
|
9719
|
-
if (!
|
|
10352
|
+
if (!SKIP_DIRS3.has(e.name) && !e.name.startsWith(".")) walk2(path43.join(dir, e.name), depth + 1);
|
|
9720
10353
|
continue;
|
|
9721
10354
|
}
|
|
9722
10355
|
if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
|
|
9723
|
-
const abs =
|
|
10356
|
+
const abs = path43.join(dir, e.name);
|
|
9724
10357
|
let mtimeMs;
|
|
9725
10358
|
try {
|
|
9726
|
-
mtimeMs =
|
|
10359
|
+
mtimeMs = fs12.statSync(abs).mtimeMs;
|
|
9727
10360
|
} catch {
|
|
9728
10361
|
continue;
|
|
9729
10362
|
}
|
|
9730
10363
|
if (mtimeMs > newest) {
|
|
9731
10364
|
newest = mtimeMs;
|
|
9732
|
-
newestChanged =
|
|
10365
|
+
newestChanged = path43.relative(rootDir, abs) || e.name;
|
|
9733
10366
|
}
|
|
9734
10367
|
}
|
|
9735
10368
|
};
|
|
@@ -9793,7 +10426,7 @@ function extractContracts(content, pkg, ecosystem) {
|
|
|
9793
10426
|
}
|
|
9794
10427
|
|
|
9795
10428
|
// src/reporting/planning/usage.ts
|
|
9796
|
-
var
|
|
10429
|
+
var SKIP_DIRS4 = /* @__PURE__ */ new Set([
|
|
9797
10430
|
"node_modules",
|
|
9798
10431
|
".git",
|
|
9799
10432
|
"dist",
|
|
@@ -9860,7 +10493,7 @@ function analyzeTree(root2, packages) {
|
|
|
9860
10493
|
if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
|
|
9861
10494
|
let entries;
|
|
9862
10495
|
try {
|
|
9863
|
-
entries =
|
|
10496
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
9864
10497
|
} catch {
|
|
9865
10498
|
return;
|
|
9866
10499
|
}
|
|
@@ -9868,18 +10501,18 @@ function analyzeTree(root2, packages) {
|
|
|
9868
10501
|
for (const entry of entries) {
|
|
9869
10502
|
if (filesSeen >= MAX_FILES) return;
|
|
9870
10503
|
if (entry.isDirectory()) {
|
|
9871
|
-
if (
|
|
9872
|
-
walk2(
|
|
10504
|
+
if (SKIP_DIRS4.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
10505
|
+
walk2(path43.join(dir, entry.name), depth + 1);
|
|
9873
10506
|
continue;
|
|
9874
10507
|
}
|
|
9875
|
-
const fileEco = EXT_ECOSYSTEM[
|
|
10508
|
+
const fileEco = EXT_ECOSYSTEM[path43.extname(entry.name)];
|
|
9876
10509
|
if (!fileEco || fileEco === "unknown") continue;
|
|
9877
10510
|
filesSeen++;
|
|
9878
|
-
const full =
|
|
10511
|
+
const full = path43.join(dir, entry.name);
|
|
9879
10512
|
let content;
|
|
9880
10513
|
try {
|
|
9881
|
-
if (
|
|
9882
|
-
content =
|
|
10514
|
+
if (fs12.statSync(full).size > MAX_FILE_BYTES2) continue;
|
|
10515
|
+
content = fs12.readFileSync(full, "utf8");
|
|
9883
10516
|
} catch {
|
|
9884
10517
|
continue;
|
|
9885
10518
|
}
|
|
@@ -10190,7 +10823,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
10190
10823
|
}
|
|
10191
10824
|
const outcomes = effective.map((t) => {
|
|
10192
10825
|
const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
|
|
10193
|
-
return { t, res: run(c2,
|
|
10826
|
+
return { t, res: run(c2, path43.join(rootDir, t.dir)) };
|
|
10194
10827
|
});
|
|
10195
10828
|
const failures = outcomes.filter((o) => !o.res.ok);
|
|
10196
10829
|
if (failures.length === 0) {
|
|
@@ -10219,8 +10852,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
10219
10852
|
return results;
|
|
10220
10853
|
}
|
|
10221
10854
|
var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
|
|
10222
|
-
var CACHE_DIR =
|
|
10223
|
-
var CACHE_FILE =
|
|
10855
|
+
var CACHE_DIR = path43.join(os.homedir(), ".vibgrate");
|
|
10856
|
+
var CACHE_FILE = path43.join(CACHE_DIR, "update-check.json");
|
|
10224
10857
|
async function fetchLatestVersion() {
|
|
10225
10858
|
try {
|
|
10226
10859
|
const controller = new AbortController();
|
|
@@ -10247,8 +10880,8 @@ async function fetchLatestVersion() {
|
|
|
10247
10880
|
}
|
|
10248
10881
|
async function writeCache(data) {
|
|
10249
10882
|
try {
|
|
10250
|
-
await
|
|
10251
|
-
await
|
|
10883
|
+
await fs27.mkdir(CACHE_DIR, { recursive: true });
|
|
10884
|
+
await fs27.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
|
|
10252
10885
|
} catch {
|
|
10253
10886
|
}
|
|
10254
10887
|
}
|
|
@@ -10283,10 +10916,10 @@ function buildDeferredUpdateScript(opts) {
|
|
|
10283
10916
|
}
|
|
10284
10917
|
function scheduleDeferredUpdate(command, pid = process.pid, dir = os.tmpdir()) {
|
|
10285
10918
|
const stamp = `${pid}-${process.hrtime.bigint().toString(36)}`;
|
|
10286
|
-
const scriptPath =
|
|
10287
|
-
const logPath =
|
|
10919
|
+
const scriptPath = path43.join(dir, `vg-update-${stamp}.cmd`);
|
|
10920
|
+
const logPath = path43.join(dir, `vg-update-${stamp}.log`);
|
|
10288
10921
|
try {
|
|
10289
|
-
|
|
10922
|
+
fs12.writeFileSync(scriptPath, buildDeferredUpdateScript({ pid, command, logPath }), "utf8");
|
|
10290
10923
|
const child = spawn(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", scriptPath], {
|
|
10291
10924
|
detached: true,
|
|
10292
10925
|
stdio: "ignore",
|
|
@@ -10305,11 +10938,12 @@ var SCRIPT_PACKAGES = [PACKAGE_NAME, "onnxruntime-node", "msgpackr-extract"];
|
|
|
10305
10938
|
function allowScriptsFlag(pm) {
|
|
10306
10939
|
return pm === "npm" ? ` --allow-scripts=${SCRIPT_PACKAGES.join(",")}` : "";
|
|
10307
10940
|
}
|
|
10941
|
+
var ORT_INSTALL_SKIP_ENV = { ONNXRUNTIME_NODE_INSTALL: "skip" };
|
|
10308
10942
|
function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd()) {
|
|
10309
10943
|
if (!execPath) return null;
|
|
10310
10944
|
let resolved = execPath;
|
|
10311
10945
|
try {
|
|
10312
|
-
resolved =
|
|
10946
|
+
resolved = fs12.realpathSync(execPath);
|
|
10313
10947
|
} catch {
|
|
10314
10948
|
}
|
|
10315
10949
|
const p = resolved.replace(/\\/g, "/");
|
|
@@ -10339,14 +10973,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
|
|
|
10339
10973
|
pm: "yarn",
|
|
10340
10974
|
root: () => {
|
|
10341
10975
|
const dir = tryRun("yarn global dir");
|
|
10342
|
-
return dir ?
|
|
10976
|
+
return dir ? path43.join(dir, "node_modules") : null;
|
|
10343
10977
|
}
|
|
10344
10978
|
},
|
|
10345
|
-
{ pm: "bun", root: () =>
|
|
10979
|
+
{ pm: "bun", root: () => path43.join(os.homedir(), ".bun", "install", "global", "node_modules") }
|
|
10346
10980
|
];
|
|
10347
10981
|
for (const probe of probes) {
|
|
10348
10982
|
const root2 = probe.root();
|
|
10349
|
-
if (root2 && await pathExists(
|
|
10983
|
+
if (root2 && await pathExists(path43.join(root2, pkg))) return probe.pm;
|
|
10350
10984
|
}
|
|
10351
10985
|
return null;
|
|
10352
10986
|
}
|
|
@@ -10361,19 +10995,19 @@ function getGlobalUpdateCommand(pm, pkg, version) {
|
|
|
10361
10995
|
return `bun add -g ${spec}`;
|
|
10362
10996
|
case "npm":
|
|
10363
10997
|
default:
|
|
10364
|
-
return `npm install -g${allowScriptsFlag("npm")} ${spec}`;
|
|
10998
|
+
return `npm install -g --no-fund${allowScriptsFlag("npm")} ${spec}`;
|
|
10365
10999
|
}
|
|
10366
11000
|
}
|
|
10367
11001
|
async function detectPackageManager(cwd) {
|
|
10368
|
-
if (await pathExists(
|
|
10369
|
-
if (await pathExists(
|
|
10370
|
-
if (await pathExists(
|
|
11002
|
+
if (await pathExists(path43.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
11003
|
+
if (await pathExists(path43.join(cwd, "bun.lockb"))) return "bun";
|
|
11004
|
+
if (await pathExists(path43.join(cwd, "yarn.lock"))) return "yarn";
|
|
10371
11005
|
return "npm";
|
|
10372
11006
|
}
|
|
10373
11007
|
async function detectWorkspaceRoot(cwd) {
|
|
10374
|
-
if (await pathExists(
|
|
11008
|
+
if (await pathExists(path43.join(cwd, "pnpm-workspace.yaml"))) return true;
|
|
10375
11009
|
try {
|
|
10376
|
-
const pkgPath =
|
|
11010
|
+
const pkgPath = path43.join(cwd, "package.json");
|
|
10377
11011
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
10378
11012
|
const pkg = JSON.parse(raw);
|
|
10379
11013
|
return pkg.workspaces != null;
|
|
@@ -10394,13 +11028,13 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
|
|
|
10394
11028
|
case "npm":
|
|
10395
11029
|
default: {
|
|
10396
11030
|
const allow = allowScriptsFlag("npm");
|
|
10397
|
-
return isDev ? `npm install${allow} --save-dev ${spec}` : `npm install${allow} ${spec}`;
|
|
11031
|
+
return isDev ? `npm install --no-fund${allow} --save-dev ${spec}` : `npm install --no-fund${allow} ${spec}`;
|
|
10398
11032
|
}
|
|
10399
11033
|
}
|
|
10400
11034
|
}
|
|
10401
11035
|
async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
|
|
10402
11036
|
try {
|
|
10403
|
-
const pkgPath =
|
|
11037
|
+
const pkgPath = path43.join(cwd, "package.json");
|
|
10404
11038
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
10405
11039
|
const parsed = JSON.parse(raw);
|
|
10406
11040
|
if (parsed.devDependencies?.[pkg]) return "dev";
|
|
@@ -10415,19 +11049,24 @@ async function confirmWorkspaceRoot(pm) {
|
|
|
10415
11049
|
async function confirm3(question) {
|
|
10416
11050
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) return false;
|
|
10417
11051
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
10418
|
-
return new Promise((
|
|
11052
|
+
return new Promise((resolve23) => {
|
|
10419
11053
|
rl.question(chalk7.yellow(question), (ans) => {
|
|
10420
11054
|
rl.close();
|
|
10421
11055
|
const t = ans.trim().toLowerCase();
|
|
10422
|
-
|
|
11056
|
+
resolve23(t === "y" || t === "yes");
|
|
10423
11057
|
});
|
|
10424
11058
|
});
|
|
10425
11059
|
}
|
|
10426
11060
|
var CAPTURED_OUTPUT_LIMIT = 64e3;
|
|
10427
11061
|
async function runInstall(cmd, cwd) {
|
|
10428
11062
|
const { spawn: spawn5 } = await import('child_process');
|
|
10429
|
-
return new Promise((
|
|
10430
|
-
const child = spawn5(cmd, {
|
|
11063
|
+
return new Promise((resolve23) => {
|
|
11064
|
+
const child = spawn5(cmd, {
|
|
11065
|
+
cwd,
|
|
11066
|
+
shell: true,
|
|
11067
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
11068
|
+
env: { ...process.env, ...ORT_INSTALL_SKIP_ENV }
|
|
11069
|
+
});
|
|
10431
11070
|
let output = "";
|
|
10432
11071
|
const tee = (src, dest) => {
|
|
10433
11072
|
if (!src) return;
|
|
@@ -10440,15 +11079,15 @@ async function runInstall(cmd, cwd) {
|
|
|
10440
11079
|
};
|
|
10441
11080
|
tee(child.stdout, process.stdout);
|
|
10442
11081
|
tee(child.stderr, process.stderr);
|
|
10443
|
-
child.on("error", (err) =>
|
|
11082
|
+
child.on("error", (err) => resolve23({ ok: false, output: `${output}
|
|
10444
11083
|
${String(err)}` }));
|
|
10445
|
-
child.on("close", (code) =>
|
|
11084
|
+
child.on("close", (code) => resolve23({ ok: code === 0, output }));
|
|
10446
11085
|
});
|
|
10447
11086
|
}
|
|
10448
11087
|
async function releaseWindowsFileLocks(cwd, keepVersion) {
|
|
10449
11088
|
reapAndReport(cwd, keepVersion);
|
|
10450
11089
|
try {
|
|
10451
|
-
const { vgdSocketPath: vgdSocketPath2 } = await import('./vgd-
|
|
11090
|
+
const { vgdSocketPath: vgdSocketPath2 } = await import('./vgd-ORPA5C2K.js');
|
|
10452
11091
|
const result = await stopVgd(vgdSocketPath2());
|
|
10453
11092
|
if (result === "stopped") {
|
|
10454
11093
|
console.log(chalk7.dim("Stopped the vgd daemon so its files can be replaced \u2014 it restarts on the next command."));
|
|
@@ -10573,7 +11212,7 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
|
|
|
10573
11212
|
);
|
|
10574
11213
|
async function rewarmVgdAndReport(cwd) {
|
|
10575
11214
|
try {
|
|
10576
|
-
const { vgdIsRunning: vgdIsRunning2, vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
11215
|
+
const { vgdIsRunning: vgdIsRunning2, vgdRequest: vgdRequest2 } = await import('./vgd-ORPA5C2K.js');
|
|
10577
11216
|
if (!await vgdIsRunning2()) return;
|
|
10578
11217
|
const loaded = await vgdRequest2({ op: "load-graph", root: cwd });
|
|
10579
11218
|
if (!loaded.ok || !("repositoryId" in loaded)) return;
|
|
@@ -10662,13 +11301,13 @@ function collectCandidates(artifact) {
|
|
|
10662
11301
|
return out2;
|
|
10663
11302
|
}
|
|
10664
11303
|
var defaultFixScanner = async (rootDir) => {
|
|
10665
|
-
const scratch =
|
|
11304
|
+
const scratch = path43.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
|
|
10666
11305
|
const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
|
|
10667
11306
|
const advanced = await loadAdvancedScanHook();
|
|
10668
11307
|
return runCoreScan(rootDir, scanOpts, advanced);
|
|
10669
11308
|
};
|
|
10670
11309
|
async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
|
|
10671
|
-
const artifactPath =
|
|
11310
|
+
const artifactPath = path43.isAbsolute(inFile) ? inFile : path43.join(rootDir, inFile);
|
|
10672
11311
|
if (await pathExists(artifactPath)) {
|
|
10673
11312
|
const staleness = scanStaleness(rootDir, artifactPath);
|
|
10674
11313
|
if (!staleness.stale) {
|
|
@@ -10695,7 +11334,7 @@ async function repositoryIdentity(rootDir, override) {
|
|
|
10695
11334
|
}
|
|
10696
11335
|
}
|
|
10697
11336
|
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", "Preview the recommended plan (or --plan <tier>) without applying; never prompts").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) => {
|
|
10698
|
-
const rootDir =
|
|
11337
|
+
const rootDir = path43.resolve(targetPath);
|
|
10699
11338
|
if (!await pathExists(rootDir)) {
|
|
10700
11339
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
10701
11340
|
process.exit(1);
|
|
@@ -10856,7 +11495,7 @@ function emit(report, format) {
|
|
|
10856
11495
|
}
|
|
10857
11496
|
}
|
|
10858
11497
|
function relProjectDir(rootDir, projectPath) {
|
|
10859
|
-
const rel =
|
|
11498
|
+
const rel = path43.isAbsolute(projectPath) ? path43.relative(rootDir, projectPath) : projectPath;
|
|
10860
11499
|
return rel === "" ? "." : rel;
|
|
10861
11500
|
}
|
|
10862
11501
|
async function buildTargetResolver(rootDir, artifact) {
|
|
@@ -10897,14 +11536,14 @@ function promptPlanSelection(response) {
|
|
|
10897
11536
|
const defaultIdx = plans.findIndex((p) => p.tier === response.recommended);
|
|
10898
11537
|
const def = defaultIdx >= 0 ? defaultIdx + 1 : 1;
|
|
10899
11538
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
10900
|
-
return new Promise((
|
|
11539
|
+
return new Promise((resolve23) => {
|
|
10901
11540
|
rl.question(`Plan [1-${plans.length}, default ${def}, q to cancel]: `, (ans) => {
|
|
10902
11541
|
rl.close();
|
|
10903
11542
|
const t = ans.trim().toLowerCase();
|
|
10904
|
-
if (t === "q" || t === "quit") return
|
|
11543
|
+
if (t === "q" || t === "quit") return resolve23(null);
|
|
10905
11544
|
const n = t === "" ? def : Number.parseInt(t, 10);
|
|
10906
|
-
if (!Number.isInteger(n) || n < 1 || n > plans.length) return
|
|
10907
|
-
|
|
11545
|
+
if (!Number.isInteger(n) || n < 1 || n > plans.length) return resolve23(null);
|
|
11546
|
+
resolve23(plans[n - 1].tier);
|
|
10908
11547
|
});
|
|
10909
11548
|
});
|
|
10910
11549
|
}
|
|
@@ -11699,7 +12338,7 @@ function formatMarkdown(artifact) {
|
|
|
11699
12338
|
|
|
11700
12339
|
// src/reporting/commands/report.ts
|
|
11701
12340
|
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) => {
|
|
11702
|
-
const artifactPath =
|
|
12341
|
+
const artifactPath = path43.resolve(opts.in);
|
|
11703
12342
|
if (!await pathExists(artifactPath)) {
|
|
11704
12343
|
console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
|
|
11705
12344
|
console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
|
|
@@ -11746,10 +12385,10 @@ function openUrl(url) {
|
|
|
11746
12385
|
}
|
|
11747
12386
|
|
|
11748
12387
|
// src/reporting/commands/login.ts
|
|
11749
|
-
var delay = (ms) => new Promise((
|
|
12388
|
+
var delay = (ms) => new Promise((resolve23) => setTimeout(resolve23, ms));
|
|
11750
12389
|
function isInside(dir, file) {
|
|
11751
|
-
const rel =
|
|
11752
|
-
return !!rel && !rel.startsWith("..") && !
|
|
12390
|
+
const rel = path43.relative(dir, file);
|
|
12391
|
+
return !!rel && !rel.startsWith("..") && !path43.isAbsolute(rel);
|
|
11753
12392
|
}
|
|
11754
12393
|
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(
|
|
11755
12394
|
"--local",
|
|
@@ -12004,7 +12643,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
12004
12643
|
try {
|
|
12005
12644
|
const statements = [];
|
|
12006
12645
|
if (opts.from) {
|
|
12007
|
-
const fromPath =
|
|
12646
|
+
const fromPath = path43.resolve(opts.from);
|
|
12008
12647
|
if (!await pathExists(fromPath)) {
|
|
12009
12648
|
process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
|
|
12010
12649
|
`));
|
|
@@ -12022,9 +12661,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
12022
12661
|
});
|
|
12023
12662
|
const json2 = JSON.stringify(doc, null, 2);
|
|
12024
12663
|
if (opts.out) {
|
|
12025
|
-
await writeTextFile(
|
|
12664
|
+
await writeTextFile(path43.resolve(opts.out), json2 + "\n");
|
|
12026
12665
|
process.stderr.write(
|
|
12027
|
-
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${
|
|
12666
|
+
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path43.resolve(opts.out)}
|
|
12028
12667
|
`
|
|
12029
12668
|
);
|
|
12030
12669
|
} else {
|
|
@@ -12207,7 +12846,7 @@ function formatDeltaText(base, current) {
|
|
|
12207
12846
|
return lines.join("\n");
|
|
12208
12847
|
}
|
|
12209
12848
|
async function readArtifactOrExit(filePath) {
|
|
12210
|
-
const absolutePath =
|
|
12849
|
+
const absolutePath = path43.resolve(filePath);
|
|
12211
12850
|
if (!await pathExists(absolutePath)) {
|
|
12212
12851
|
console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
|
|
12213
12852
|
process.exit(1);
|
|
@@ -12224,7 +12863,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
|
|
|
12224
12863
|
const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
|
|
12225
12864
|
const body = JSON.stringify(sbom, null, 2);
|
|
12226
12865
|
if (opts.out) {
|
|
12227
|
-
await writeTextFile(
|
|
12866
|
+
await writeTextFile(path43.resolve(opts.out), body);
|
|
12228
12867
|
console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
|
|
12229
12868
|
} else {
|
|
12230
12869
|
console.log(body);
|
|
@@ -12235,7 +12874,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
|
|
|
12235
12874
|
const current = await readArtifactOrExit(opts.to);
|
|
12236
12875
|
const report = formatDeltaText(base, current);
|
|
12237
12876
|
if (opts.out) {
|
|
12238
|
-
await writeTextFile(
|
|
12877
|
+
await writeTextFile(path43.resolve(opts.out), report);
|
|
12239
12878
|
console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
|
|
12240
12879
|
} else {
|
|
12241
12880
|
console.log(report);
|
|
@@ -12366,20 +13005,20 @@ function resolveRegime(id) {
|
|
|
12366
13005
|
return regime;
|
|
12367
13006
|
}
|
|
12368
13007
|
function evidenceDir(root2) {
|
|
12369
|
-
return
|
|
13008
|
+
return path43.join(root2, ".vibgrate", "evidence");
|
|
12370
13009
|
}
|
|
12371
13010
|
function orgPath(root2) {
|
|
12372
|
-
return
|
|
13011
|
+
return path43.join(evidenceDir(root2), "org.json");
|
|
12373
13012
|
}
|
|
12374
13013
|
function productsPath(root2) {
|
|
12375
|
-
return
|
|
13014
|
+
return path43.join(evidenceDir(root2), "products.json");
|
|
12376
13015
|
}
|
|
12377
13016
|
function releasesDir(root2) {
|
|
12378
|
-
return
|
|
13017
|
+
return path43.join(evidenceDir(root2), "releases");
|
|
12379
13018
|
}
|
|
12380
13019
|
function releasePath(root2, productId, version) {
|
|
12381
13020
|
const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
12382
|
-
return
|
|
13021
|
+
return path43.join(releasesDir(root2), `${safe}.json`);
|
|
12383
13022
|
}
|
|
12384
13023
|
var DEFAULT_ORG = {
|
|
12385
13024
|
responsiblePersons: [],
|
|
@@ -12410,7 +13049,7 @@ async function freezeRelease(root2, release) {
|
|
|
12410
13049
|
const p = releasePath(root2, release.productId, release.version);
|
|
12411
13050
|
if (await pathExists(p)) {
|
|
12412
13051
|
throw new CliError(
|
|
12413
|
-
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${
|
|
13052
|
+
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path43.relative(root2, p)} only if it was frozen in error`,
|
|
12414
13053
|
ExitCode.USAGE_ERROR
|
|
12415
13054
|
);
|
|
12416
13055
|
}
|
|
@@ -12424,7 +13063,7 @@ async function loadReleases(root2, productId) {
|
|
|
12424
13063
|
const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
|
|
12425
13064
|
const releases = [];
|
|
12426
13065
|
for (const f of files) {
|
|
12427
|
-
const rel = await readJsonFile(
|
|
13066
|
+
const rel = await readJsonFile(path43.join(dir, f));
|
|
12428
13067
|
if (!productId || rel.productId === productId) releases.push(rel);
|
|
12429
13068
|
}
|
|
12430
13069
|
return releases;
|
|
@@ -13119,19 +13758,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
|
|
|
13119
13758
|
var DEFAULT_KEY = "attest-key.pem";
|
|
13120
13759
|
function resolveSigningKey(root2, explicit) {
|
|
13121
13760
|
const chosen = process.env.VG_ATTEST_KEY;
|
|
13122
|
-
const keyPath = chosen ?
|
|
13761
|
+
const keyPath = chosen ? path43.resolve(chosen) : path43.join(root2, ".vibgrate", DEFAULT_KEY);
|
|
13123
13762
|
let minted = false;
|
|
13124
|
-
if (!
|
|
13763
|
+
if (!fs12.existsSync(keyPath)) {
|
|
13125
13764
|
if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
|
|
13126
13765
|
const kp = generateKeypair();
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13766
|
+
fs12.mkdirSync(path43.dirname(keyPath), { recursive: true });
|
|
13767
|
+
fs12.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
|
|
13768
|
+
fs12.writeFileSync(`${keyPath}.pub`, kp.publicPem);
|
|
13130
13769
|
minted = true;
|
|
13131
13770
|
}
|
|
13132
13771
|
let key2;
|
|
13133
13772
|
try {
|
|
13134
|
-
key2 = crypto3.createPrivateKey(
|
|
13773
|
+
key2 = crypto3.createPrivateKey(fs12.readFileSync(keyPath, "utf8"));
|
|
13135
13774
|
} catch {
|
|
13136
13775
|
throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
|
|
13137
13776
|
}
|
|
@@ -13142,16 +13781,16 @@ function resolveSigningKey(root2, explicit) {
|
|
|
13142
13781
|
}
|
|
13143
13782
|
function writeBundle(input) {
|
|
13144
13783
|
const dir = input.outDir;
|
|
13145
|
-
|
|
13146
|
-
const write = (rel, data) =>
|
|
13784
|
+
fs12.mkdirSync(path43.join(dir, "inputs", "releases"), { recursive: true });
|
|
13785
|
+
const write = (rel, data) => fs12.writeFileSync(path43.join(dir, rel), `${JSON.stringify(data, null, 2)}
|
|
13147
13786
|
`);
|
|
13148
13787
|
write("result.json", input.result);
|
|
13149
|
-
write(
|
|
13788
|
+
write(path43.join("inputs", "advisory.json"), input.advisory);
|
|
13150
13789
|
for (const rel of input.releases) {
|
|
13151
13790
|
const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
13152
|
-
write(
|
|
13791
|
+
write(path43.join("inputs", "releases", `${safe}.json`), rel);
|
|
13153
13792
|
}
|
|
13154
|
-
write(
|
|
13793
|
+
write(path43.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
|
|
13155
13794
|
write("provenance.json", {
|
|
13156
13795
|
method: "deterministic",
|
|
13157
13796
|
modelDrafted: [],
|
|
@@ -13167,13 +13806,13 @@ function writeBundle(input) {
|
|
|
13167
13806
|
disclaimer: input.regime.disclaimer
|
|
13168
13807
|
});
|
|
13169
13808
|
if (input.envelope) {
|
|
13170
|
-
|
|
13809
|
+
fs12.writeFileSync(path43.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
|
|
13171
13810
|
`);
|
|
13172
13811
|
}
|
|
13173
13812
|
if (input.timestampToken) {
|
|
13174
|
-
|
|
13813
|
+
fs12.writeFileSync(path43.join(dir, "timestamp.tsr"), input.timestampToken);
|
|
13175
13814
|
}
|
|
13176
|
-
|
|
13815
|
+
fs12.writeFileSync(path43.join(dir, "VERIFY.md"), verifyDoc(input));
|
|
13177
13816
|
return dir;
|
|
13178
13817
|
}
|
|
13179
13818
|
function verifyDoc(input) {
|
|
@@ -13234,13 +13873,13 @@ function undeterminedFields(result, regime) {
|
|
|
13234
13873
|
return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
|
|
13235
13874
|
}
|
|
13236
13875
|
async function recordDrill(root2, record) {
|
|
13237
|
-
const dir =
|
|
13238
|
-
const p =
|
|
13876
|
+
const dir = path43.join(evidenceDir(root2), "drills");
|
|
13877
|
+
const p = path43.join(dir, `${record.drillId}.json`);
|
|
13239
13878
|
await writeJsonFile(p, record);
|
|
13240
13879
|
return p;
|
|
13241
13880
|
}
|
|
13242
13881
|
async function hasRecentDrill(root2, asOf) {
|
|
13243
|
-
const dir =
|
|
13882
|
+
const dir = path43.join(evidenceDir(root2), "drills");
|
|
13244
13883
|
if (!await pathExists(dir)) return void 0;
|
|
13245
13884
|
const { readdir } = await import('fs/promises');
|
|
13246
13885
|
const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
|
|
@@ -13248,7 +13887,7 @@ async function hasRecentDrill(root2, asOf) {
|
|
|
13248
13887
|
if (files.length === 0) return void 0;
|
|
13249
13888
|
const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
|
|
13250
13889
|
for (const f of files) {
|
|
13251
|
-
const rec = await readJsonFile2(
|
|
13890
|
+
const rec = await readJsonFile2(path43.join(dir, f));
|
|
13252
13891
|
if (rec.ranAt >= cutoff) return true;
|
|
13253
13892
|
}
|
|
13254
13893
|
return false;
|
|
@@ -13328,7 +13967,7 @@ function formatRegimeList() {
|
|
|
13328
13967
|
|
|
13329
13968
|
// src/reporting/commands/evidence/index.ts
|
|
13330
13969
|
function root(opts) {
|
|
13331
|
-
return
|
|
13970
|
+
return path43.resolve(opts.cwd ?? process.cwd());
|
|
13332
13971
|
}
|
|
13333
13972
|
function slug(name) {
|
|
13334
13973
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
|
|
@@ -13416,7 +14055,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
13416
14055
|
const release = await buildRelease({
|
|
13417
14056
|
productId: product.id,
|
|
13418
14057
|
version,
|
|
13419
|
-
from:
|
|
14058
|
+
from: path43.resolve(rootDir, opts.from),
|
|
13420
14059
|
shipDate: opts.shipDate,
|
|
13421
14060
|
buildId: opts.buildId,
|
|
13422
14061
|
artefactDigest: opts.digest,
|
|
@@ -13424,7 +14063,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
13424
14063
|
frozenAt: nowIso()
|
|
13425
14064
|
});
|
|
13426
14065
|
const p = await freezeRelease(rootDir, release);
|
|
13427
|
-
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${
|
|
14066
|
+
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path43.relative(rootDir, p)}`);
|
|
13428
14067
|
});
|
|
13429
14068
|
async function runExposure(rootDir, vuln, opts) {
|
|
13430
14069
|
const org = await loadOrg(rootDir);
|
|
@@ -13476,7 +14115,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
13476
14115
|
console.log("\n" + buildPack(result, regime, org, stage));
|
|
13477
14116
|
}
|
|
13478
14117
|
if (opts.bundle) {
|
|
13479
|
-
const dir =
|
|
14118
|
+
const dir = path43.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
|
|
13480
14119
|
let envelope;
|
|
13481
14120
|
if (opts.sign !== false) {
|
|
13482
14121
|
const { key: key2, minted } = resolveSigningKey(rootDir);
|
|
@@ -13484,7 +14123,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
13484
14123
|
envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
|
|
13485
14124
|
}
|
|
13486
14125
|
writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
|
|
13487
|
-
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${
|
|
14126
|
+
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path43.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
|
|
13488
14127
|
}
|
|
13489
14128
|
process.exitCode = exposureExit(result.overallStatus);
|
|
13490
14129
|
});
|
|
@@ -13516,7 +14155,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
|
|
|
13516
14155
|
const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
|
|
13517
14156
|
const md = buildPack(result, regime, org, stage);
|
|
13518
14157
|
if (opts.out) {
|
|
13519
|
-
|
|
14158
|
+
fs12.writeFileSync(path43.resolve(rootDir, opts.out), md);
|
|
13520
14159
|
console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
|
|
13521
14160
|
} else {
|
|
13522
14161
|
console.log(md);
|
|
@@ -13558,20 +14197,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
|
|
|
13558
14197
|
}
|
|
13559
14198
|
});
|
|
13560
14199
|
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) => {
|
|
13561
|
-
const abs =
|
|
13562
|
-
const envPath =
|
|
13563
|
-
if (!
|
|
13564
|
-
const envelope = JSON.parse(
|
|
13565
|
-
const resultPath =
|
|
13566
|
-
const result =
|
|
13567
|
-
const publicKeyPem = opts.pub ?
|
|
14200
|
+
const abs = path43.resolve(bundlePath);
|
|
14201
|
+
const envPath = fs12.statSync(abs).isDirectory() ? path43.join(abs, "evidence.intoto.jsonl") : abs;
|
|
14202
|
+
if (!fs12.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
|
|
14203
|
+
const envelope = JSON.parse(fs12.readFileSync(envPath, "utf8").trim().split("\n")[0]);
|
|
14204
|
+
const resultPath = path43.join(path43.dirname(envPath), "result.json");
|
|
14205
|
+
const result = fs12.existsSync(resultPath) ? JSON.parse(fs12.readFileSync(resultPath, "utf8")) : void 0;
|
|
14206
|
+
const publicKeyPem = opts.pub ? fs12.readFileSync(path43.resolve(opts.pub), "utf8") : void 0;
|
|
13568
14207
|
const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
|
|
13569
14208
|
const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
|
|
13570
14209
|
console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
|
|
13571
14210
|
if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
|
|
13572
|
-
const tsrPath =
|
|
13573
|
-
if (
|
|
13574
|
-
const t = verifyTimestamp(
|
|
14211
|
+
const tsrPath = path43.join(path43.dirname(envPath), "timestamp.tsr");
|
|
14212
|
+
if (fs12.existsSync(tsrPath) && result) {
|
|
14213
|
+
const t = verifyTimestamp(fs12.readFileSync(tsrPath), exposureSubjectDigest(result));
|
|
13575
14214
|
const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
|
|
13576
14215
|
console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
|
|
13577
14216
|
}
|
|
@@ -13638,12 +14277,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
|
|
|
13638
14277
|
const releases = [];
|
|
13639
14278
|
for (const list of releasesByProduct.values()) releases.push(...list);
|
|
13640
14279
|
const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
|
|
13641
|
-
const dir =
|
|
13642
|
-
await writeJsonFile(
|
|
13643
|
-
await writeJsonFile(
|
|
13644
|
-
for (const r of releases) await writeJsonFile(
|
|
13645
|
-
await writeJsonFile(
|
|
13646
|
-
console.error(chalk7.green("\u2714") + ` exported evidence state to ${
|
|
14280
|
+
const dir = path43.resolve(rootDir, opts.out);
|
|
14281
|
+
await writeJsonFile(path43.join(dir, "org.json"), org);
|
|
14282
|
+
await writeJsonFile(path43.join(dir, "products.json"), products);
|
|
14283
|
+
for (const r of releases) await writeJsonFile(path43.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
|
|
14284
|
+
await writeJsonFile(path43.join(dir, "readiness.json"), report);
|
|
14285
|
+
console.error(chalk7.green("\u2714") + ` exported evidence state to ${path43.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
|
|
13647
14286
|
});
|
|
13648
14287
|
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) => {
|
|
13649
14288
|
const rootDir = root(opts);
|
|
@@ -13669,10 +14308,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
|
|
|
13669
14308
|
}));
|
|
13670
14309
|
let exposure;
|
|
13671
14310
|
if (opts.result) {
|
|
13672
|
-
const raw =
|
|
13673
|
-
const resultPath =
|
|
13674
|
-
if (!
|
|
13675
|
-
exposure = JSON.parse(
|
|
14311
|
+
const raw = path43.resolve(rootDir, opts.result);
|
|
14312
|
+
const resultPath = fs12.existsSync(raw) && fs12.statSync(raw).isDirectory() ? path43.join(raw, "result.json") : raw;
|
|
14313
|
+
if (!fs12.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
|
|
14314
|
+
exposure = JSON.parse(fs12.readFileSync(resultPath, "utf8"));
|
|
13676
14315
|
}
|
|
13677
14316
|
const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
|
|
13678
14317
|
const body = JSON.stringify(payload);
|
|
@@ -13734,6 +14373,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
13734
14373
|
"daemon",
|
|
13735
14374
|
"policy",
|
|
13736
14375
|
"llm-host",
|
|
14376
|
+
"hcs",
|
|
13737
14377
|
"install",
|
|
13738
14378
|
"uninstall",
|
|
13739
14379
|
"share",
|
|
@@ -13798,6 +14438,7 @@ ${aliasNote}Docs: https://vibgrate.com/help`;
|
|
|
13798
14438
|
registerDaemon(program);
|
|
13799
14439
|
registerPolicy(program);
|
|
13800
14440
|
registerLlmHost(program);
|
|
14441
|
+
registerHcs(program);
|
|
13801
14442
|
program.addCommand(initCommand);
|
|
13802
14443
|
program.addCommand(scanCommand);
|
|
13803
14444
|
program.addCommand(fixCommand);
|
|
@@ -13866,7 +14507,7 @@ function dispatch(argv, cwd) {
|
|
|
13866
14507
|
}
|
|
13867
14508
|
const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
|
|
13868
14509
|
if (looksLikeQuestion) return ["ask", ...args];
|
|
13869
|
-
if (
|
|
14510
|
+
if (fs12.existsSync(path43.resolve(cwd, first))) {
|
|
13870
14511
|
return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
|
|
13871
14512
|
}
|
|
13872
14513
|
const moved = MOVED_COMMANDS[first];
|
|
@@ -13911,9 +14552,9 @@ async function main(argv = process.argv) {
|
|
|
13911
14552
|
}
|
|
13912
14553
|
function readCwd(raw) {
|
|
13913
14554
|
const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
|
|
13914
|
-
if (i >= 0 && raw[i + 1]) return
|
|
14555
|
+
if (i >= 0 && raw[i + 1]) return path43.resolve(raw[i + 1]);
|
|
13915
14556
|
const eq = raw.find((a) => a.startsWith("--cwd="));
|
|
13916
|
-
if (eq) return
|
|
14557
|
+
if (eq) return path43.resolve(eq.slice("--cwd=".length));
|
|
13917
14558
|
return process.cwd();
|
|
13918
14559
|
}
|
|
13919
14560
|
function handleError(err) {
|