@vibgrate/cli 2026.729.1 → 2026.729.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +5 -1
- package/dist/agent-Z4Z66IGM.js +22 -0
- package/dist/agent-Z4Z66IGM.js.map +1 -0
- package/dist/baseline-Q3QQF5QF.js +9 -0
- package/dist/{baseline-MROWBNK7.js.map → baseline-Q3QQF5QF.js.map} +1 -1
- package/dist/checkpoint-4WFZMKEO.js +56 -0
- package/dist/checkpoint-4WFZMKEO.js.map +1 -0
- package/dist/{chunk-YMHQZ24Q.js → chunk-3FQSBVQD.js} +6 -6
- package/dist/{chunk-YMHQZ24Q.js.map → chunk-3FQSBVQD.js.map} +1 -1
- package/dist/{chunk-2ZHWF7C6.js → chunk-42RDYQFF.js} +42 -67
- package/dist/chunk-42RDYQFF.js.map +1 -0
- package/dist/{chunk-OIWHR57Q.js → chunk-4BOWWYSE.js} +37 -19
- package/dist/chunk-4BOWWYSE.js.map +1 -0
- package/dist/chunk-543E6WDJ.js +61 -0
- package/dist/chunk-543E6WDJ.js.map +1 -0
- package/dist/{chunk-JIBOJTGS.js → chunk-5HYCB55P.js} +101 -101
- package/dist/chunk-5HYCB55P.js.map +1 -0
- package/dist/{chunk-EEVZVXT2.js → chunk-5MNX3OLS.js} +19 -11
- package/dist/chunk-5MNX3OLS.js.map +1 -0
- package/dist/{chunk-2JV3J5NF.js → chunk-EQ3IOFIG.js} +55 -9
- package/dist/chunk-EQ3IOFIG.js.map +1 -0
- package/dist/{chunk-SIPGDJT4.js → chunk-EVLS2M5G.js} +4 -4
- package/dist/{chunk-SIPGDJT4.js.map → chunk-EVLS2M5G.js.map} +1 -1
- package/dist/{chunk-TQFY6OSV.js → chunk-HWFVBYX4.js} +6 -6
- package/dist/{chunk-TQFY6OSV.js.map → chunk-HWFVBYX4.js.map} +1 -1
- package/dist/{chunk-YKVNMNEM.js → chunk-JXMZCTVZ.js} +3 -3
- package/dist/{chunk-YKVNMNEM.js.map → chunk-JXMZCTVZ.js.map} +1 -1
- package/dist/{chunk-3IJB5UJI.js → chunk-KBPNH67Q.js} +4 -4
- package/dist/{chunk-3IJB5UJI.js.map → chunk-KBPNH67Q.js.map} +1 -1
- package/dist/{chunk-RZEXHDCF.js → chunk-MYM5VIJ4.js} +14 -3
- package/dist/chunk-MYM5VIJ4.js.map +1 -0
- package/dist/chunk-N3HCPBFY.js +6 -0
- package/dist/{chunk-NQ4FSRXL.js.map → chunk-N3HCPBFY.js.map} +1 -1
- package/dist/{chunk-PMYWZRRS.js → chunk-RBIRXQR6.js} +21 -3
- package/dist/chunk-RBIRXQR6.js.map +1 -0
- package/dist/{chunk-TCJTQGAO.js → chunk-RGEVBSLK.js} +3 -3
- package/dist/{chunk-TCJTQGAO.js.map → chunk-RGEVBSLK.js.map} +1 -1
- package/dist/{chunk-QS5BTBRX.js → chunk-RIEUPFXO.js} +4 -4
- package/dist/{chunk-QS5BTBRX.js.map → chunk-RIEUPFXO.js.map} +1 -1
- package/dist/{chunk-PRGCCW7D.js → chunk-WBMMRERH.js} +3 -3
- package/dist/{chunk-PRGCCW7D.js.map → chunk-WBMMRERH.js.map} +1 -1
- package/dist/{chunk-6HX47EBL.js → chunk-X634FZVG.js} +3 -3
- package/dist/{chunk-6HX47EBL.js.map → chunk-X634FZVG.js.map} +1 -1
- package/dist/{chunk-CF2MLSOV.js → chunk-YMSXP6AO.js} +3 -3
- package/dist/{chunk-CF2MLSOV.js.map → chunk-YMSXP6AO.js.map} +1 -1
- package/dist/cli.js +738 -383
- package/dist/cli.js.map +1 -1
- package/dist/{graph-backend-GBL33GMW.js → graph-backend-G5Y6QQV4.js} +4 -4
- package/dist/{graph-backend-GBL33GMW.js.map → graph-backend-G5Y6QQV4.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -8
- package/dist/{interactive-R5VQGDWP.js → interactive-MJVMY5JP.js} +23 -22
- package/dist/interactive-MJVMY5JP.js.map +1 -0
- package/dist/{llm-host-5RE34322.js → llm-host-DZBD5D36.js} +5 -5
- package/dist/{llm-host-5RE34322.js.map → llm-host-DZBD5D36.js.map} +1 -1
- package/dist/load-4PARCNMD.js +9 -0
- package/dist/{load-WKIZF2AK.js.map → load-4PARCNMD.js.map} +1 -1
- package/dist/rules-ASYEUNB5.js +74 -0
- package/dist/rules-ASYEUNB5.js.map +1 -0
- package/dist/runtime-session-AILFASQV.js +19 -0
- package/dist/{runtime-session-5NRB6BTR.js.map → runtime-session-AILFASQV.js.map} +1 -1
- package/dist/{session-2JT4AUZT.js → session-3OBIQLE4.js} +5 -5
- package/dist/{session-2JT4AUZT.js.map → session-3OBIQLE4.js.map} +1 -1
- package/dist/{stream-json-Y45JBNYP.js → stream-json-MTPWWVRR.js} +81 -9
- package/dist/stream-json-MTPWWVRR.js.map +1 -0
- package/dist/{vg-mcp-bridge-YXQS6HTO.js → vg-mcp-bridge-BLHEIWMT.js} +6 -6
- package/dist/{vg-mcp-bridge-YXQS6HTO.js.map → vg-mcp-bridge-BLHEIWMT.js.map} +1 -1
- package/dist/{vgd-KC5RCOP6.js → vgd-S7D2SITC.js} +8 -8
- package/dist/vgd-S7D2SITC.js.map +1 -0
- package/package.json +1 -1
- package/dist/baseline-MROWBNK7.js +0 -9
- package/dist/chunk-2JV3J5NF.js.map +0 -1
- package/dist/chunk-2ZHWF7C6.js.map +0 -1
- package/dist/chunk-EEVZVXT2.js.map +0 -1
- package/dist/chunk-JIBOJTGS.js.map +0 -1
- package/dist/chunk-NQ4FSRXL.js +0 -6
- package/dist/chunk-OIWHR57Q.js.map +0 -1
- package/dist/chunk-PMYWZRRS.js.map +0 -1
- package/dist/chunk-RZEXHDCF.js.map +0 -1
- package/dist/interactive-R5VQGDWP.js.map +0 -1
- package/dist/load-WKIZF2AK.js +0 -9
- package/dist/runtime-session-5NRB6BTR.js +0 -19
- package/dist/stream-json-Y45JBNYP.js.map +0 -1
- package/dist/vgd-KC5RCOP6.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,63 +1,65 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-
|
|
3
|
-
export { runBuild } from './chunk-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { runCodeSession } from './chunk-
|
|
7
|
-
import { summarizeDiffs, ScriptedProvider } from './chunk-RZEXHDCF.js';
|
|
2
|
+
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-5MNX3OLS.js';
|
|
3
|
+
export { runBuild } from './chunk-5MNX3OLS.js';
|
|
4
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-YMSXP6AO.js';
|
|
5
|
+
import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
|
|
6
|
+
import { runCodeSession } from './chunk-WBMMRERH.js';
|
|
8
7
|
import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
|
|
9
|
-
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-
|
|
8
|
+
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-EQ3IOFIG.js';
|
|
10
9
|
import './chunk-5I4VSBWQ.js';
|
|
11
10
|
import './chunk-IS7VTH2Q.js';
|
|
12
11
|
import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
|
|
13
12
|
import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
|
|
14
13
|
import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
|
|
15
14
|
import './chunk-IZDH67DX.js';
|
|
16
|
-
import './chunk-
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import './chunk-7AVYKZEM.js';
|
|
22
|
-
import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
|
|
15
|
+
import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-EVLS2M5G.js';
|
|
16
|
+
import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-X634FZVG.js';
|
|
17
|
+
import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-42RDYQFF.js';
|
|
18
|
+
import './chunk-543E6WDJ.js';
|
|
19
|
+
import { summarizeDiffs, ScriptedProvider } from './chunk-MYM5VIJ4.js';
|
|
23
20
|
import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
21
|
+
import './chunk-RGEVBSLK.js';
|
|
22
|
+
import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
|
|
23
|
+
import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
|
|
24
|
+
import './chunk-7AVYKZEM.js';
|
|
25
|
+
import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-HWFVBYX4.js';
|
|
26
|
+
import { CliError, ExitCode, refreshIfStale, driftCount, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, SKIP_DIRS, SKIP_FILES } from './chunk-3FQSBVQD.js';
|
|
27
|
+
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-RIEUPFXO.js';
|
|
28
|
+
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-4BOWWYSE.js';
|
|
29
|
+
import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
|
|
27
30
|
import './chunk-IPICO2RV.js';
|
|
28
31
|
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-G4HTI4ZM.js';
|
|
29
|
-
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-OIWHR57Q.js';
|
|
30
32
|
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-US2DAKCM.js';
|
|
31
|
-
import {
|
|
33
|
+
import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
|
|
32
34
|
import { resolveOne } from './chunk-J7LKEB2R.js';
|
|
33
35
|
import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-EETK7S43.js';
|
|
34
36
|
import { discoverModels } from './chunk-CQDUBAQY.js';
|
|
35
|
-
import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
|
|
36
37
|
import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
|
|
37
38
|
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
|
|
38
39
|
import './chunk-RXP66R2E.js';
|
|
39
|
-
import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-
|
|
40
|
-
import { VERSION } from './chunk-
|
|
40
|
+
import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-JXMZCTVZ.js';
|
|
41
|
+
import { VERSION } from './chunk-N3HCPBFY.js';
|
|
41
42
|
import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
|
|
42
43
|
import './chunk-BWPBB45M.js';
|
|
43
44
|
import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
|
|
44
45
|
import './chunk-BPF3YX2U.js';
|
|
45
46
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
|
|
46
47
|
import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
|
|
47
|
-
import * as
|
|
48
|
-
import
|
|
49
|
-
import * as
|
|
50
|
-
import
|
|
48
|
+
import * as fs8 from 'fs';
|
|
49
|
+
import fs8__default, { realpathSync } from 'fs';
|
|
50
|
+
import * as path38 from 'path';
|
|
51
|
+
import path38__default from 'path';
|
|
51
52
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
52
53
|
import { Command, CommanderError, Option } from 'commander';
|
|
53
54
|
import * as os from 'os';
|
|
54
55
|
import * as crypto3 from 'crypto';
|
|
55
56
|
import { randomUUID } from 'crypto';
|
|
57
|
+
import * as semver3 from 'semver';
|
|
58
|
+
import semver3__default from 'semver';
|
|
56
59
|
import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
|
|
57
60
|
import * as readline from 'readline';
|
|
58
61
|
import chalk7 from 'chalk';
|
|
59
|
-
import * as
|
|
60
|
-
import semver2 from 'semver';
|
|
62
|
+
import * as fs22 from 'fs/promises';
|
|
61
63
|
|
|
62
64
|
init_cli_invocation();
|
|
63
65
|
function registerStatus(program) {
|
|
@@ -67,10 +69,10 @@ function registerStatus(program) {
|
|
|
67
69
|
applyGlobalOptions(cmd);
|
|
68
70
|
}
|
|
69
71
|
async function runStatus(global) {
|
|
70
|
-
const root2 =
|
|
72
|
+
const root2 = path38.resolve(global.cwd ?? ".");
|
|
71
73
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
72
74
|
const graph = loadGraph(root2, graphPath);
|
|
73
|
-
const hasCache =
|
|
75
|
+
const hasCache = fs8.existsSync(path38.join(cacheDir(root2), "parse-cache.json"));
|
|
74
76
|
let stale = null;
|
|
75
77
|
let staleExact = false;
|
|
76
78
|
if (graph) {
|
|
@@ -90,8 +92,8 @@ async function runStatus(global) {
|
|
|
90
92
|
}
|
|
91
93
|
if (global.json) {
|
|
92
94
|
json({
|
|
93
|
-
root:
|
|
94
|
-
graphPath:
|
|
95
|
+
root: path38.relative(process.cwd(), root2) || ".",
|
|
96
|
+
graphPath: path38.relative(root2, graphPath),
|
|
95
97
|
built: graph !== null,
|
|
96
98
|
generatedAt: graph?.generatedAt ?? null,
|
|
97
99
|
counts: graph?.meta.counts ?? null,
|
|
@@ -106,11 +108,11 @@ async function runStatus(global) {
|
|
|
106
108
|
return;
|
|
107
109
|
}
|
|
108
110
|
if (!graph) {
|
|
109
|
-
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(
|
|
111
|
+
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path38.relative(root2, graphPath))}`);
|
|
110
112
|
info(` run ${c.bold("vg")} to build one`);
|
|
111
113
|
return;
|
|
112
114
|
}
|
|
113
|
-
info(`${c.cyan("vg")} \xB7 ${
|
|
115
|
+
info(`${c.cyan("vg")} \xB7 ${path38.relative(root2, graphPath)}`);
|
|
114
116
|
info(` generated ${graph.generatedAt}`);
|
|
115
117
|
info(
|
|
116
118
|
` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
|
|
@@ -127,7 +129,7 @@ async function runStatus(global) {
|
|
|
127
129
|
if (vibgrateDir(root2)) ;
|
|
128
130
|
}
|
|
129
131
|
function rootOf(global) {
|
|
130
|
-
return
|
|
132
|
+
return path38.resolve(global.cwd ?? ".");
|
|
131
133
|
}
|
|
132
134
|
function requireGraph(global) {
|
|
133
135
|
const root2 = rootOf(global);
|
|
@@ -838,8 +840,8 @@ function pad2(s, n) {
|
|
|
838
840
|
}
|
|
839
841
|
var SCHEMA_VERSION2 = "1";
|
|
840
842
|
var OFFSET_FILE = "stats-share.json";
|
|
841
|
-
var INSTALL_ID_DIR =
|
|
842
|
-
var INSTALL_ID_FILE =
|
|
843
|
+
var INSTALL_ID_DIR = path38.join(os.homedir(), ".vibgrate");
|
|
844
|
+
var INSTALL_ID_FILE = path38.join(INSTALL_ID_DIR, "install-id");
|
|
843
845
|
var SEND_TIMEOUT_MS = 4e3;
|
|
844
846
|
function telemetryOptOut(env = process.env) {
|
|
845
847
|
const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
|
|
@@ -867,14 +869,14 @@ function isCI(env = process.env) {
|
|
|
867
869
|
function installId(env = process.env) {
|
|
868
870
|
if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
|
|
869
871
|
try {
|
|
870
|
-
const existing =
|
|
872
|
+
const existing = fs8.readFileSync(INSTALL_ID_FILE, "utf8").trim();
|
|
871
873
|
if (isUuid(existing)) return existing;
|
|
872
874
|
} catch {
|
|
873
875
|
}
|
|
874
876
|
const id = randomUuid();
|
|
875
877
|
try {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
+
fs8.mkdirSync(INSTALL_ID_DIR, { recursive: true });
|
|
879
|
+
fs8.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
|
|
878
880
|
} catch {
|
|
879
881
|
}
|
|
880
882
|
return id;
|
|
@@ -891,14 +893,14 @@ function statsEndpoint() {
|
|
|
891
893
|
return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
|
|
892
894
|
}
|
|
893
895
|
function offsetPath(root2) {
|
|
894
|
-
return
|
|
896
|
+
return path38.join(cacheDir(root2), OFFSET_FILE);
|
|
895
897
|
}
|
|
896
898
|
function ledgerFilePath(root2) {
|
|
897
|
-
return
|
|
899
|
+
return path38.join(cacheDir(root2), "savings.jsonl");
|
|
898
900
|
}
|
|
899
901
|
function readOffset(root2) {
|
|
900
902
|
try {
|
|
901
|
-
const raw = JSON.parse(
|
|
903
|
+
const raw = JSON.parse(fs8.readFileSync(offsetPath(root2), "utf8"));
|
|
902
904
|
return typeof raw.offset === "number" && raw.offset >= 0 ? raw.offset : 0;
|
|
903
905
|
} catch {
|
|
904
906
|
return 0;
|
|
@@ -906,8 +908,8 @@ function readOffset(root2) {
|
|
|
906
908
|
}
|
|
907
909
|
function writeOffset(root2, offset) {
|
|
908
910
|
try {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
+
fs8.mkdirSync(cacheDir(root2), { recursive: true });
|
|
912
|
+
fs8.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
|
|
911
913
|
} catch {
|
|
912
914
|
}
|
|
913
915
|
}
|
|
@@ -915,7 +917,7 @@ function buildBatch(root2, fromOffset, id = installId()) {
|
|
|
915
917
|
const file = ledgerFilePath(root2);
|
|
916
918
|
let size = 0;
|
|
917
919
|
try {
|
|
918
|
-
size =
|
|
920
|
+
size = fs8.statSync(file).size;
|
|
919
921
|
} catch {
|
|
920
922
|
return { batch: null, newOffset: 0 };
|
|
921
923
|
}
|
|
@@ -923,13 +925,13 @@ function buildBatch(root2, fromOffset, id = installId()) {
|
|
|
923
925
|
if (start >= size) return { batch: null, newOffset: size };
|
|
924
926
|
let text = "";
|
|
925
927
|
try {
|
|
926
|
-
const fd =
|
|
928
|
+
const fd = fs8.openSync(file, "r");
|
|
927
929
|
try {
|
|
928
930
|
const buf = Buffer.alloc(size - start);
|
|
929
|
-
|
|
931
|
+
fs8.readSync(fd, buf, 0, buf.length, start);
|
|
930
932
|
text = buf.toString("utf8");
|
|
931
933
|
} finally {
|
|
932
|
-
|
|
934
|
+
fs8.closeSync(fd);
|
|
933
935
|
}
|
|
934
936
|
} catch {
|
|
935
937
|
return { batch: null, newOffset: fromOffset };
|
|
@@ -1065,12 +1067,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
|
|
|
1065
1067
|
var KEEPALIVE_MS = 1e4;
|
|
1066
1068
|
var STALE_MS = 6e4;
|
|
1067
1069
|
function liveStatsDir(root2) {
|
|
1068
|
-
return
|
|
1070
|
+
return path38.join(cacheDir(root2), "serve-live");
|
|
1069
1071
|
}
|
|
1070
1072
|
function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
|
|
1071
1073
|
let entries;
|
|
1072
1074
|
try {
|
|
1073
|
-
entries =
|
|
1075
|
+
entries = fs8.readdirSync(dir);
|
|
1074
1076
|
} catch {
|
|
1075
1077
|
return [];
|
|
1076
1078
|
}
|
|
@@ -1079,7 +1081,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
|
|
|
1079
1081
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1080
1082
|
let parsed;
|
|
1081
1083
|
try {
|
|
1082
|
-
parsed = JSON.parse(
|
|
1084
|
+
parsed = JSON.parse(fs8.readFileSync(path38.join(dir, name), "utf8"));
|
|
1083
1085
|
} catch {
|
|
1084
1086
|
continue;
|
|
1085
1087
|
}
|
|
@@ -1101,7 +1103,7 @@ var LiveStatsBus = class {
|
|
|
1101
1103
|
this.dir = dir;
|
|
1102
1104
|
this.stats = stats;
|
|
1103
1105
|
this.pid = pid;
|
|
1104
|
-
this.file =
|
|
1106
|
+
this.file = path38.join(dir, `serve-${this.pid}.json`);
|
|
1105
1107
|
}
|
|
1106
1108
|
dir;
|
|
1107
1109
|
stats;
|
|
@@ -1133,10 +1135,10 @@ var LiveStatsBus = class {
|
|
|
1133
1135
|
this.lastWriteAt = now;
|
|
1134
1136
|
const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
|
|
1135
1137
|
try {
|
|
1136
|
-
|
|
1138
|
+
fs8.mkdirSync(this.dir, { recursive: true });
|
|
1137
1139
|
const tmp = `${this.file}.tmp`;
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
+
fs8.writeFileSync(tmp, JSON.stringify(body));
|
|
1141
|
+
fs8.renameSync(tmp, this.file);
|
|
1140
1142
|
} catch {
|
|
1141
1143
|
}
|
|
1142
1144
|
}
|
|
@@ -1147,24 +1149,24 @@ var LiveStatsBus = class {
|
|
|
1147
1149
|
siblings(now = Date.now()) {
|
|
1148
1150
|
let entries;
|
|
1149
1151
|
try {
|
|
1150
|
-
entries =
|
|
1152
|
+
entries = fs8.readdirSync(this.dir);
|
|
1151
1153
|
} catch {
|
|
1152
1154
|
return [];
|
|
1153
1155
|
}
|
|
1154
1156
|
const out2 = [];
|
|
1155
1157
|
for (const name of entries.sort()) {
|
|
1156
1158
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1157
|
-
const file =
|
|
1159
|
+
const file = path38.join(this.dir, name);
|
|
1158
1160
|
let parsed;
|
|
1159
1161
|
try {
|
|
1160
|
-
parsed = JSON.parse(
|
|
1162
|
+
parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
|
|
1161
1163
|
} catch {
|
|
1162
1164
|
continue;
|
|
1163
1165
|
}
|
|
1164
1166
|
if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
|
|
1165
1167
|
if (now - parsed.updatedAt > STALE_MS) {
|
|
1166
1168
|
try {
|
|
1167
|
-
|
|
1169
|
+
fs8.unlinkSync(file);
|
|
1168
1170
|
} catch {
|
|
1169
1171
|
}
|
|
1170
1172
|
continue;
|
|
@@ -1176,7 +1178,7 @@ var LiveStatsBus = class {
|
|
|
1176
1178
|
}
|
|
1177
1179
|
unlinkOwn = () => {
|
|
1178
1180
|
try {
|
|
1179
|
-
|
|
1181
|
+
fs8.unlinkSync(this.file);
|
|
1180
1182
|
} catch {
|
|
1181
1183
|
}
|
|
1182
1184
|
};
|
|
@@ -1489,12 +1491,12 @@ var LedgerTail = class {
|
|
|
1489
1491
|
if (size === this.offset) return;
|
|
1490
1492
|
let chunk;
|
|
1491
1493
|
try {
|
|
1492
|
-
const fd =
|
|
1494
|
+
const fd = fs8.openSync(this.file, "r");
|
|
1493
1495
|
try {
|
|
1494
1496
|
chunk = Buffer.alloc(size - this.offset);
|
|
1495
|
-
|
|
1497
|
+
fs8.readSync(fd, chunk, 0, chunk.length, this.offset);
|
|
1496
1498
|
} finally {
|
|
1497
|
-
|
|
1499
|
+
fs8.closeSync(fd);
|
|
1498
1500
|
}
|
|
1499
1501
|
} catch {
|
|
1500
1502
|
return;
|
|
@@ -1507,7 +1509,7 @@ var LedgerTail = class {
|
|
|
1507
1509
|
}
|
|
1508
1510
|
sizeOf() {
|
|
1509
1511
|
try {
|
|
1510
|
-
return
|
|
1512
|
+
return fs8.statSync(this.file).size;
|
|
1511
1513
|
} catch {
|
|
1512
1514
|
return 0;
|
|
1513
1515
|
}
|
|
@@ -1892,19 +1894,19 @@ function endOfLine(text, line) {
|
|
|
1892
1894
|
}
|
|
1893
1895
|
var CACHE_VERSION = "vg-lsp-scan-cache/2";
|
|
1894
1896
|
function cachePath(root2) {
|
|
1895
|
-
return
|
|
1897
|
+
return path38.join(cacheDir(root2), "lsp-scan.json");
|
|
1896
1898
|
}
|
|
1897
1899
|
function manifestHash(root2) {
|
|
1898
1900
|
const files = [];
|
|
1899
1901
|
const walk2 = (dir) => {
|
|
1900
1902
|
let entries;
|
|
1901
1903
|
try {
|
|
1902
|
-
entries =
|
|
1904
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
1903
1905
|
} catch {
|
|
1904
1906
|
return;
|
|
1905
1907
|
}
|
|
1906
1908
|
for (const entry of entries) {
|
|
1907
|
-
const abs =
|
|
1909
|
+
const abs = path38.join(dir, entry.name);
|
|
1908
1910
|
if (entry.isDirectory()) {
|
|
1909
1911
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
1910
1912
|
walk2(abs);
|
|
@@ -1914,8 +1916,8 @@ function manifestHash(root2) {
|
|
|
1914
1916
|
const base = entry.name.toLowerCase();
|
|
1915
1917
|
if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
|
|
1916
1918
|
try {
|
|
1917
|
-
const rel =
|
|
1918
|
-
files.push({ rel, hash: hashBytes(
|
|
1919
|
+
const rel = path38.relative(root2, abs).split(path38.sep).join("/");
|
|
1920
|
+
files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
|
|
1919
1921
|
} catch {
|
|
1920
1922
|
}
|
|
1921
1923
|
}
|
|
@@ -1925,16 +1927,16 @@ function manifestHash(root2) {
|
|
|
1925
1927
|
return hashString(canonicalize(files));
|
|
1926
1928
|
}
|
|
1927
1929
|
function isDependencyFile(root2, filePath) {
|
|
1928
|
-
const rel =
|
|
1929
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
1930
|
-
const parts = rel.split(
|
|
1930
|
+
const rel = path38.relative(path38.resolve(root2), path38.resolve(filePath));
|
|
1931
|
+
if (rel === "" || rel.startsWith("..") || path38.isAbsolute(rel)) return false;
|
|
1932
|
+
const parts = rel.split(path38.sep);
|
|
1931
1933
|
if (parts.slice(0, -1).some((dir) => SKIP_DIRS.has(dir))) return false;
|
|
1932
1934
|
const base = parts[parts.length - 1].toLowerCase();
|
|
1933
1935
|
return isManifest(filePath) || SKIP_FILES.has(base);
|
|
1934
1936
|
}
|
|
1935
1937
|
function loadScanCache(root2, key2) {
|
|
1936
1938
|
try {
|
|
1937
|
-
const raw = JSON.parse(
|
|
1939
|
+
const raw = JSON.parse(fs8.readFileSync(cachePath(root2), "utf8"));
|
|
1938
1940
|
if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
|
|
1939
1941
|
return { manifestHash: raw.manifestHash, artifact: raw.artifact };
|
|
1940
1942
|
}
|
|
@@ -1944,8 +1946,8 @@ function loadScanCache(root2, key2) {
|
|
|
1944
1946
|
}
|
|
1945
1947
|
function writeScanCache(root2, key2, artifact) {
|
|
1946
1948
|
try {
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
+
fs8.mkdirSync(cacheDir(root2), { recursive: true });
|
|
1950
|
+
fs8.writeFileSync(
|
|
1949
1951
|
cachePath(root2),
|
|
1950
1952
|
stableStringify(
|
|
1951
1953
|
{ version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
|
|
@@ -1955,6 +1957,66 @@ function writeScanCache(root2, key2, artifact) {
|
|
|
1955
1957
|
} catch {
|
|
1956
1958
|
}
|
|
1957
1959
|
}
|
|
1960
|
+
var MAX_ENTRIES = 1e3;
|
|
1961
|
+
var KEEP_ENTRIES = 500;
|
|
1962
|
+
function historyPath(root2) {
|
|
1963
|
+
return path38.join(root2, ".vibgrate", "score-history.jsonl");
|
|
1964
|
+
}
|
|
1965
|
+
function parseLine(line) {
|
|
1966
|
+
try {
|
|
1967
|
+
const e = JSON.parse(line);
|
|
1968
|
+
if (typeof e.ts === "string" && typeof e.score === "number" && typeof e.band === "string" && (e.mode === "verified" || e.mode === "estimated") && typeof e.methodology === "string") {
|
|
1969
|
+
return e;
|
|
1970
|
+
}
|
|
1971
|
+
} catch {
|
|
1972
|
+
}
|
|
1973
|
+
return null;
|
|
1974
|
+
}
|
|
1975
|
+
function readHistory(root2) {
|
|
1976
|
+
try {
|
|
1977
|
+
return fs8.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
|
|
1978
|
+
} catch {
|
|
1979
|
+
return [];
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
function lastEntry(root2) {
|
|
1983
|
+
const all = readHistory(root2);
|
|
1984
|
+
return all.length ? all[all.length - 1] : null;
|
|
1985
|
+
}
|
|
1986
|
+
function recentHistory(root2, days, now = Date.now()) {
|
|
1987
|
+
const cutoff = now - days * 24 * 60 * 60 * 1e3;
|
|
1988
|
+
return readHistory(root2).filter((e) => {
|
|
1989
|
+
const t = Date.parse(e.ts);
|
|
1990
|
+
return Number.isFinite(t) && t >= cutoff;
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
function recordScore(root2, entry) {
|
|
1994
|
+
try {
|
|
1995
|
+
const prev = lastEntry(root2);
|
|
1996
|
+
if (prev && prev.score === entry.score && prev.band === entry.band && prev.mode === entry.mode && prev.methodology === entry.methodology) {
|
|
1997
|
+
const prevT = Date.parse(prev.ts);
|
|
1998
|
+
const nextT = Date.parse(entry.ts);
|
|
1999
|
+
if (Number.isFinite(prevT) && Number.isFinite(nextT) && nextT - prevT < 24 * 60 * 60 * 1e3) {
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
const file = historyPath(root2);
|
|
2004
|
+
fs8.mkdirSync(path38.dirname(file), { recursive: true });
|
|
2005
|
+
fs8.appendFileSync(file, `${JSON.stringify(entry)}
|
|
2006
|
+
`);
|
|
2007
|
+
const all = readHistory(root2);
|
|
2008
|
+
if (all.length > MAX_ENTRIES) {
|
|
2009
|
+
const kept = all.slice(-KEEP_ENTRIES);
|
|
2010
|
+
fs8.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
2011
|
+
}
|
|
2012
|
+
} catch {
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
function deltaFrom(prev, current) {
|
|
2016
|
+
if (!prev) return void 0;
|
|
2017
|
+
if (prev.methodology !== current.methodology) return void 0;
|
|
2018
|
+
return current.score - prev.score;
|
|
2019
|
+
}
|
|
1958
2020
|
|
|
1959
2021
|
// src/lsp/graph-query.ts
|
|
1960
2022
|
async function runGraphQuery(graph, params, ctx) {
|
|
@@ -2466,6 +2528,11 @@ var VibgrateLanguageServer = class {
|
|
|
2466
2528
|
this.conn.onRequest("textDocument/codeLens", (_m, params) => this.onCodeLens(params));
|
|
2467
2529
|
this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
|
|
2468
2530
|
this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
|
|
2531
|
+
this.conn.onRequest("vibgrate/score/history", (_m, params) => {
|
|
2532
|
+
const p = params;
|
|
2533
|
+
const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
|
|
2534
|
+
return { days, entries: recentHistory(this.opts.root, days) };
|
|
2535
|
+
});
|
|
2469
2536
|
this.conn.onRequest("vibgrate/enrich", (_m, params) => this.onEnrich(params));
|
|
2470
2537
|
this.conn.onRequest("vibgrate/vulns", (_m, _params) => this.onVulns());
|
|
2471
2538
|
this.conn.onRequest("workspace/executeCommand", (_m, params) => {
|
|
@@ -2554,6 +2621,15 @@ var VibgrateLanguageServer = class {
|
|
|
2554
2621
|
(f) => f.ruleId === "vibgrate/unmaintained" || f.ruleId === "vibgrate/abandoned"
|
|
2555
2622
|
).length;
|
|
2556
2623
|
const band = a.drift.riskLevel ?? "low";
|
|
2624
|
+
const historyEntry = {
|
|
2625
|
+
ts: a.timestamp,
|
|
2626
|
+
score: a.drift.score,
|
|
2627
|
+
band,
|
|
2628
|
+
mode: a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated"),
|
|
2629
|
+
methodology: a.drift.methodologyVersion ?? "unknown"
|
|
2630
|
+
};
|
|
2631
|
+
const delta = deltaFrom(lastEntry(this.opts.root), historyEntry);
|
|
2632
|
+
recordScore(this.opts.root, historyEntry);
|
|
2557
2633
|
const payload = {
|
|
2558
2634
|
score: a.drift.score,
|
|
2559
2635
|
band,
|
|
@@ -2561,12 +2637,13 @@ var VibgrateLanguageServer = class {
|
|
|
2561
2637
|
// offline marker. An air-gapped scan against a dated snapshot is Verified.
|
|
2562
2638
|
// The score now carries the authoritative provenance (driftscore-3.0
|
|
2563
2639
|
// envelope); fall back to the artifact heuristic for pre-v3 engines.
|
|
2564
|
-
mode:
|
|
2565
|
-
methodology:
|
|
2640
|
+
mode: historyEntry.mode,
|
|
2641
|
+
methodology: historyEntry.methodology,
|
|
2566
2642
|
scale: "0 best, 100 worst",
|
|
2567
2643
|
counts: { behind, eol, unmaintained, total },
|
|
2568
2644
|
rootPath: a.rootPath,
|
|
2569
2645
|
scannedAt: a.timestamp,
|
|
2646
|
+
...delta !== void 0 ? { delta } : {},
|
|
2570
2647
|
...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {}
|
|
2571
2648
|
};
|
|
2572
2649
|
this.conn.notify("vibgrate/score", payload);
|
|
@@ -2756,10 +2833,10 @@ var VibgrateLanguageServer = class {
|
|
|
2756
2833
|
const ecosystem = osvEcosystem(proj.type);
|
|
2757
2834
|
if (!ecosystem) continue;
|
|
2758
2835
|
const relManifest = manifestRelativePath(proj);
|
|
2759
|
-
const absManifest =
|
|
2836
|
+
const absManifest = path38.resolve(this.opts.root, relManifest);
|
|
2760
2837
|
let text = null;
|
|
2761
2838
|
try {
|
|
2762
|
-
if (
|
|
2839
|
+
if (fs8.existsSync(absManifest)) text = fs8.readFileSync(absManifest, "utf8");
|
|
2763
2840
|
} catch {
|
|
2764
2841
|
text = null;
|
|
2765
2842
|
}
|
|
@@ -2805,12 +2882,12 @@ function uriToPath(uri) {
|
|
|
2805
2882
|
}
|
|
2806
2883
|
}
|
|
2807
2884
|
function projectForFile(root2, a, filePath) {
|
|
2808
|
-
const dir =
|
|
2885
|
+
const dir = path38.dirname(path38.resolve(filePath));
|
|
2809
2886
|
let best;
|
|
2810
2887
|
let bestLen = -1;
|
|
2811
2888
|
for (const proj of a.projects ?? []) {
|
|
2812
|
-
const projDir =
|
|
2813
|
-
if ((dir === projDir || dir.startsWith(projDir +
|
|
2889
|
+
const projDir = path38.resolve(root2, proj.path);
|
|
2890
|
+
if ((dir === projDir || dir.startsWith(projDir + path38.sep)) && projDir.length > bestLen) {
|
|
2814
2891
|
best = proj;
|
|
2815
2892
|
bestLen = projDir.length;
|
|
2816
2893
|
}
|
|
@@ -2818,7 +2895,7 @@ function projectForFile(root2, a, filePath) {
|
|
|
2818
2895
|
return best;
|
|
2819
2896
|
}
|
|
2820
2897
|
function sameProject(location, projectPath) {
|
|
2821
|
-
return
|
|
2898
|
+
return path38.normalize(location) === path38.normalize(projectPath);
|
|
2822
2899
|
}
|
|
2823
2900
|
function hasReleaseDates(a) {
|
|
2824
2901
|
for (const proj of a.projects ?? []) {
|
|
@@ -2891,34 +2968,34 @@ function buildBreakdown(drift, projects) {
|
|
|
2891
2968
|
}
|
|
2892
2969
|
function manifestRelativePath(proj) {
|
|
2893
2970
|
const base = proj.path === "." || proj.path === "" ? "" : proj.path;
|
|
2894
|
-
const
|
|
2971
|
+
const join28 = (name) => base ? path38.join(base, name) : name;
|
|
2895
2972
|
switch (proj.type) {
|
|
2896
2973
|
case "node":
|
|
2897
2974
|
case "typescript":
|
|
2898
|
-
return
|
|
2975
|
+
return join28("package.json");
|
|
2899
2976
|
case "python":
|
|
2900
|
-
return
|
|
2977
|
+
return join28("pyproject.toml");
|
|
2901
2978
|
case "go":
|
|
2902
|
-
return
|
|
2979
|
+
return join28("go.mod");
|
|
2903
2980
|
case "rust":
|
|
2904
|
-
return
|
|
2981
|
+
return join28("Cargo.toml");
|
|
2905
2982
|
case "ruby":
|
|
2906
|
-
return
|
|
2983
|
+
return join28("Gemfile");
|
|
2907
2984
|
case "php":
|
|
2908
|
-
return
|
|
2985
|
+
return join28("composer.json");
|
|
2909
2986
|
case "java":
|
|
2910
2987
|
case "kotlin":
|
|
2911
2988
|
case "scala":
|
|
2912
2989
|
case "groovy":
|
|
2913
|
-
return
|
|
2990
|
+
return join28("pom.xml");
|
|
2914
2991
|
case "dotnet":
|
|
2915
|
-
return
|
|
2992
|
+
return join28(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
|
|
2916
2993
|
case "dart":
|
|
2917
|
-
return
|
|
2994
|
+
return join28("pubspec.yaml");
|
|
2918
2995
|
case "elixir":
|
|
2919
|
-
return
|
|
2996
|
+
return join28("mix.exs");
|
|
2920
2997
|
default:
|
|
2921
|
-
return
|
|
2998
|
+
return join28("package.json");
|
|
2922
2999
|
}
|
|
2923
3000
|
}
|
|
2924
3001
|
function packageReachSet(graph) {
|
|
@@ -2978,9 +3055,19 @@ function osvEcosystem(type) {
|
|
|
2978
3055
|
return null;
|
|
2979
3056
|
}
|
|
2980
3057
|
}
|
|
3058
|
+
function inRangeStep(dep) {
|
|
3059
|
+
const target = dep.latestSatisfying;
|
|
3060
|
+
if (!target || !dep.resolvedVersion) return null;
|
|
3061
|
+
if (!semver3.valid(target) || !semver3.valid(dep.resolvedVersion)) return null;
|
|
3062
|
+
if (!semver3.gt(target, dep.resolvedVersion)) return null;
|
|
3063
|
+
const diff2 = semver3.diff(dep.resolvedVersion, target);
|
|
3064
|
+
return { version: target, size: diff2 === "patch" || diff2 === "prepatch" ? "patch" : "minor" };
|
|
3065
|
+
}
|
|
2981
3066
|
function inlineLabel(dep) {
|
|
2982
3067
|
const bits = [];
|
|
2983
3068
|
if (dep.drift === "major-behind") {
|
|
3069
|
+
const step2 = inRangeStep(dep);
|
|
3070
|
+
if (step2) bits.push(`${step2.size} behind`, step2.version);
|
|
2984
3071
|
const n = dep.majorsBehind ?? 1;
|
|
2985
3072
|
bits.push(`${n} major behind`);
|
|
2986
3073
|
} else if (dep.drift === "minor-behind") {
|
|
@@ -3025,6 +3112,10 @@ function hoverMarkdown(dep, contribution) {
|
|
|
3025
3112
|
lines.push(`| | |`);
|
|
3026
3113
|
lines.push(`|---|---|`);
|
|
3027
3114
|
lines.push(`| yours | \`${yours}\` |`);
|
|
3115
|
+
const step2 = inRangeStep(dep);
|
|
3116
|
+
if (step2 && step2.version !== dep.latestStable) {
|
|
3117
|
+
lines.push(`| latest in range | \`${step2.version}\` |`);
|
|
3118
|
+
}
|
|
3028
3119
|
lines.push(`| latest | \`${dep.latestStable}\` |`);
|
|
3029
3120
|
const journey = versionJourney(yours, dep.latestStable);
|
|
3030
3121
|
if (journey) lines.push(`| journey | ${journey} |`);
|
|
@@ -3064,7 +3155,7 @@ function hoverMarkdown(dep, contribution) {
|
|
|
3064
3155
|
return lines.join("\n");
|
|
3065
3156
|
}
|
|
3066
3157
|
function startLanguageServer(opts) {
|
|
3067
|
-
if (!
|
|
3158
|
+
if (!fs8.existsSync(opts.root)) {
|
|
3068
3159
|
process.stderr.write(`vg lsp: root does not exist: ${opts.root}
|
|
3069
3160
|
`);
|
|
3070
3161
|
process.exit(1);
|
|
@@ -3201,8 +3292,8 @@ function registerShare(program) {
|
|
|
3201
3292
|
const cmd = program.command("share").description("make the map committable + auto-updating for your team (git)").option("--undo", "reverse what `vg share` installed").option("--reports", "also commit graph.html / GRAPH_REPORT.md (default: gitignored)").action(function(opts) {
|
|
3202
3293
|
const global = readGlobal(this);
|
|
3203
3294
|
const root2 = rootOf(global);
|
|
3204
|
-
const gitDir =
|
|
3205
|
-
if (!
|
|
3295
|
+
const gitDir = path38.join(root2, ".git");
|
|
3296
|
+
if (!fs8.existsSync(gitDir)) {
|
|
3206
3297
|
throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
|
|
3207
3298
|
}
|
|
3208
3299
|
if (opts.undo) {
|
|
@@ -3223,23 +3314,23 @@ function registerShare(program) {
|
|
|
3223
3314
|
applyGlobalOptions(cmd);
|
|
3224
3315
|
}
|
|
3225
3316
|
function writeVibgrateGitignore(root2, reports) {
|
|
3226
|
-
const dir =
|
|
3227
|
-
|
|
3317
|
+
const dir = path38.join(root2, ".vibgrate");
|
|
3318
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
3228
3319
|
const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
|
|
3229
3320
|
if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
|
|
3230
|
-
|
|
3321
|
+
fs8.writeFileSync(path38.join(dir, ".gitignore"), `${lines.join("\n")}
|
|
3231
3322
|
`);
|
|
3232
3323
|
}
|
|
3233
3324
|
function writeGitAttributes(root2) {
|
|
3234
|
-
const file =
|
|
3325
|
+
const file = path38.join(root2, ".gitattributes");
|
|
3235
3326
|
const line = ".vibgrate/graph.json merge=vg";
|
|
3236
|
-
let content =
|
|
3327
|
+
let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
|
|
3237
3328
|
if (!content.split("\n").some((l) => l.trim() === line)) {
|
|
3238
3329
|
content = content.length ? `${content.replace(/\s*$/, "")}
|
|
3239
3330
|
${line}
|
|
3240
3331
|
` : `${line}
|
|
3241
3332
|
`;
|
|
3242
|
-
|
|
3333
|
+
fs8.writeFileSync(file, content);
|
|
3243
3334
|
}
|
|
3244
3335
|
}
|
|
3245
3336
|
function configureMergeDriver(root2) {
|
|
@@ -3248,8 +3339,8 @@ function configureMergeDriver(root2) {
|
|
|
3248
3339
|
}
|
|
3249
3340
|
function installPreCommitHook(root2) {
|
|
3250
3341
|
const hooksDir = hookDir(root2);
|
|
3251
|
-
|
|
3252
|
-
const file =
|
|
3342
|
+
fs8.mkdirSync(hooksDir, { recursive: true });
|
|
3343
|
+
const file = path38.join(hooksDir, "pre-commit");
|
|
3253
3344
|
const block = [
|
|
3254
3345
|
HOOK_BEGIN,
|
|
3255
3346
|
"if command -v vg >/dev/null 2>&1; then",
|
|
@@ -3258,7 +3349,7 @@ function installPreCommitHook(root2) {
|
|
|
3258
3349
|
"fi",
|
|
3259
3350
|
HOOK_END
|
|
3260
3351
|
].join("\n");
|
|
3261
|
-
let content =
|
|
3352
|
+
let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "#!/bin/sh\n";
|
|
3262
3353
|
const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
|
|
3263
3354
|
if (re.test(content)) content = content.replace(re, block);
|
|
3264
3355
|
else content = `${content.replace(/\s*$/, "")}
|
|
@@ -3267,21 +3358,21 @@ ${block}
|
|
|
3267
3358
|
`;
|
|
3268
3359
|
if (!content.startsWith("#!")) content = `#!/bin/sh
|
|
3269
3360
|
${content}`;
|
|
3270
|
-
|
|
3271
|
-
|
|
3361
|
+
fs8.writeFileSync(file, content);
|
|
3362
|
+
fs8.chmodSync(file, 493);
|
|
3272
3363
|
}
|
|
3273
3364
|
function undo(root2) {
|
|
3274
|
-
const hookFile =
|
|
3275
|
-
if (
|
|
3365
|
+
const hookFile = path38.join(hookDir(root2), "pre-commit");
|
|
3366
|
+
if (fs8.existsSync(hookFile)) {
|
|
3276
3367
|
const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
|
|
3277
|
-
const next2 =
|
|
3278
|
-
if (next2.trim() === "#!/bin/sh")
|
|
3279
|
-
else
|
|
3368
|
+
const next2 = fs8.readFileSync(hookFile, "utf8").replace(re, "\n");
|
|
3369
|
+
if (next2.trim() === "#!/bin/sh") fs8.rmSync(hookFile);
|
|
3370
|
+
else fs8.writeFileSync(hookFile, next2);
|
|
3280
3371
|
}
|
|
3281
|
-
const attr =
|
|
3282
|
-
if (
|
|
3283
|
-
const next2 =
|
|
3284
|
-
|
|
3372
|
+
const attr = path38.join(root2, ".gitattributes");
|
|
3373
|
+
if (fs8.existsSync(attr)) {
|
|
3374
|
+
const next2 = fs8.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
|
|
3375
|
+
fs8.writeFileSync(attr, next2);
|
|
3285
3376
|
}
|
|
3286
3377
|
try {
|
|
3287
3378
|
git(root2, ["config", "--remove-section", "merge.vg"]);
|
|
@@ -3291,10 +3382,10 @@ function undo(root2) {
|
|
|
3291
3382
|
function hookDir(root2) {
|
|
3292
3383
|
try {
|
|
3293
3384
|
const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
|
|
3294
|
-
if (configured) return
|
|
3385
|
+
if (configured) return path38.resolve(root2, configured);
|
|
3295
3386
|
} catch {
|
|
3296
3387
|
}
|
|
3297
|
-
return
|
|
3388
|
+
return path38.join(root2, ".git", "hooks");
|
|
3298
3389
|
}
|
|
3299
3390
|
function git(root2, args) {
|
|
3300
3391
|
return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
|
|
@@ -3322,9 +3413,9 @@ function registerWatch(program) {
|
|
|
3322
3413
|
const global = readGlobal(this);
|
|
3323
3414
|
const root2 = rootOf(global);
|
|
3324
3415
|
const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
|
|
3325
|
-
const watchRoots = (paths.length ? paths : ["."]).map((p) =>
|
|
3416
|
+
const watchRoots = (paths.length ? paths : ["."]).map((p) => path38.resolve(root2, p));
|
|
3326
3417
|
for (const w of watchRoots) {
|
|
3327
|
-
if (!
|
|
3418
|
+
if (!fs8.existsSync(w)) {
|
|
3328
3419
|
throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
|
|
3329
3420
|
}
|
|
3330
3421
|
}
|
|
@@ -3377,14 +3468,14 @@ function registerWatch(program) {
|
|
|
3377
3468
|
const watchers = [];
|
|
3378
3469
|
for (const w of watchRoots) {
|
|
3379
3470
|
try {
|
|
3380
|
-
const watcher =
|
|
3471
|
+
const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
|
|
3381
3472
|
if (!filename) {
|
|
3382
3473
|
schedule("change");
|
|
3383
3474
|
return;
|
|
3384
3475
|
}
|
|
3385
|
-
const parts = filename.split(
|
|
3476
|
+
const parts = filename.split(path38.sep);
|
|
3386
3477
|
if (parts.some((p) => SKIP_NAME.has(p))) return;
|
|
3387
|
-
if (filename.includes(`${
|
|
3478
|
+
if (filename.includes(`${path38.sep}.vibgrate${path38.sep}`) || filename.startsWith(".vibgrate")) {
|
|
3388
3479
|
return;
|
|
3389
3480
|
}
|
|
3390
3481
|
schedule(filename);
|
|
@@ -3394,7 +3485,7 @@ function registerWatch(program) {
|
|
|
3394
3485
|
throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
|
|
3395
3486
|
}
|
|
3396
3487
|
}
|
|
3397
|
-
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) =>
|
|
3488
|
+
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path38.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
|
|
3398
3489
|
await new Promise((resolve21) => {
|
|
3399
3490
|
const stop = () => {
|
|
3400
3491
|
for (const w of watchers) w.close();
|
|
@@ -3727,10 +3818,10 @@ function normalizeStandards(raw) {
|
|
|
3727
3818
|
}
|
|
3728
3819
|
function loadStandards(root2) {
|
|
3729
3820
|
for (const rel of STANDARDS_FILES) {
|
|
3730
|
-
const p =
|
|
3821
|
+
const p = path38__default.join(root2, rel);
|
|
3731
3822
|
let text;
|
|
3732
3823
|
try {
|
|
3733
|
-
text =
|
|
3824
|
+
text = fs8__default.readFileSync(p, "utf8");
|
|
3734
3825
|
} catch {
|
|
3735
3826
|
continue;
|
|
3736
3827
|
}
|
|
@@ -4448,8 +4539,8 @@ async function runHostBench(options = {}) {
|
|
|
4448
4539
|
}
|
|
4449
4540
|
async function runArmSimulate(input) {
|
|
4450
4541
|
const { arm, lib, modelPath, turns, trie, env, live } = input;
|
|
4451
|
-
const
|
|
4452
|
-
const session = await acquireHostSession(lib,
|
|
4542
|
+
const path40 = `${modelPath}#${arm.id}`;
|
|
4543
|
+
const session = await acquireHostSession(lib, path40);
|
|
4453
4544
|
const system = "You are a coding agent with a Task Capsule.";
|
|
4454
4545
|
const capsule = "function readConfig(): Config { return load(); }";
|
|
4455
4546
|
let last = null;
|
|
@@ -5661,7 +5752,7 @@ function registerModels(program) {
|
|
|
5661
5752
|
);
|
|
5662
5753
|
}
|
|
5663
5754
|
} else {
|
|
5664
|
-
if (!target.path || !
|
|
5755
|
+
if (!target.path || !fs8.existsSync(target.path)) {
|
|
5665
5756
|
throw new CliError(
|
|
5666
5757
|
`model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
|
|
5667
5758
|
ExitCode.NOT_FOUND
|
|
@@ -5675,7 +5766,7 @@ function registerModels(program) {
|
|
|
5675
5766
|
}
|
|
5676
5767
|
if (!global.json) info(c.dim(` $ rm ${target.path}`));
|
|
5677
5768
|
try {
|
|
5678
|
-
|
|
5769
|
+
fs8.unlinkSync(target.path);
|
|
5679
5770
|
} catch (e) {
|
|
5680
5771
|
const msg = e instanceof Error ? e.message : String(e);
|
|
5681
5772
|
throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
|
|
@@ -5813,9 +5904,9 @@ function registerModels(program) {
|
|
|
5813
5904
|
}
|
|
5814
5905
|
});
|
|
5815
5906
|
if (opts.out) {
|
|
5816
|
-
const outPath =
|
|
5817
|
-
|
|
5818
|
-
|
|
5907
|
+
const outPath = path38.resolve(opts.out);
|
|
5908
|
+
fs8.mkdirSync(path38.dirname(outPath), { recursive: true });
|
|
5909
|
+
fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
|
|
5819
5910
|
`);
|
|
5820
5911
|
if (!global.json) info(c.dim(` wrote ${outPath}`));
|
|
5821
5912
|
}
|
|
@@ -5964,14 +6055,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
|
|
|
5964
6055
|
}
|
|
5965
6056
|
return exact[0];
|
|
5966
6057
|
}
|
|
5967
|
-
const base =
|
|
6058
|
+
const base = path38.basename(wantLc);
|
|
5968
6059
|
const soft = fleet.filter((m) => {
|
|
5969
6060
|
const n = m.name.toLowerCase();
|
|
5970
|
-
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) ||
|
|
6061
|
+
return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path38.basename(n) === base;
|
|
5971
6062
|
});
|
|
5972
6063
|
if (soft.length === 1) return soft[0];
|
|
5973
6064
|
if (soft.length > 1) {
|
|
5974
|
-
const baseHits = soft.filter((m) =>
|
|
6065
|
+
const baseHits = soft.filter((m) => path38.basename(m.name).toLowerCase() === base);
|
|
5975
6066
|
const pool = baseHits.length ? baseHits : soft;
|
|
5976
6067
|
const order = ["ollama", "gguf", "lm-studio"];
|
|
5977
6068
|
for (const rt of order) {
|
|
@@ -6009,11 +6100,11 @@ function printBackends(backends) {
|
|
|
6009
6100
|
}
|
|
6010
6101
|
}
|
|
6011
6102
|
function codeConfigPath(root2) {
|
|
6012
|
-
return
|
|
6103
|
+
return path38.join(root2, ".vibgrate", "code.json");
|
|
6013
6104
|
}
|
|
6014
6105
|
function loadCodeConfig(root2) {
|
|
6015
6106
|
try {
|
|
6016
|
-
const raw = JSON.parse(
|
|
6107
|
+
const raw = JSON.parse(fs8.readFileSync(codeConfigPath(root2), "utf8"));
|
|
6017
6108
|
return sanitize(raw);
|
|
6018
6109
|
} catch {
|
|
6019
6110
|
return {};
|
|
@@ -6080,7 +6171,7 @@ function contextBudgetFor(config, modelContextWindow) {
|
|
|
6080
6171
|
var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
|
|
6081
6172
|
function readMcpServersFile(file) {
|
|
6082
6173
|
try {
|
|
6083
|
-
const raw = JSON.parse(
|
|
6174
|
+
const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
|
|
6084
6175
|
const map = raw.mcpServers ?? raw.servers;
|
|
6085
6176
|
return map && typeof map === "object" ? parseMcpServers(map) : {};
|
|
6086
6177
|
} catch {
|
|
@@ -6091,7 +6182,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6091
6182
|
const servers = {};
|
|
6092
6183
|
const sources = [];
|
|
6093
6184
|
for (const rel of MCP_CONFIG_FILES) {
|
|
6094
|
-
const found = readMcpServersFile(
|
|
6185
|
+
const found = readMcpServersFile(path38.join(root2, rel));
|
|
6095
6186
|
const names = Object.keys(found);
|
|
6096
6187
|
if (names.length) {
|
|
6097
6188
|
sources.push(rel);
|
|
@@ -6107,7 +6198,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
6107
6198
|
|
|
6108
6199
|
// src/commands/code.ts
|
|
6109
6200
|
function registerCode(program) {
|
|
6110
|
-
const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
|
|
6201
|
+
const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: vibgrate-relay (Vibgrate Relay), ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--session", "with --stream-json: stay open for further turns (warm graph and tools) instead of exiting after one").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
|
|
6111
6202
|
const global = readGlobal(this);
|
|
6112
6203
|
const instruction = (instructionParts ?? []).join(" ").trim();
|
|
6113
6204
|
const config = loadCodeConfig(rootOf(global));
|
|
@@ -6120,7 +6211,7 @@ function registerCode(program) {
|
|
|
6120
6211
|
try {
|
|
6121
6212
|
const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
|
|
6122
6213
|
const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
|
|
6123
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
6214
|
+
const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
|
|
6124
6215
|
const state = readOrchestratorState2();
|
|
6125
6216
|
const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
|
|
6126
6217
|
const pin = mode ? activePin2(mode, state) : null;
|
|
@@ -6204,7 +6295,7 @@ function registerCode(program) {
|
|
|
6204
6295
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
6205
6296
|
throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
|
|
6206
6297
|
}
|
|
6207
|
-
const { runInteractive } = await import('./interactive-
|
|
6298
|
+
const { runInteractive } = await import('./interactive-MJVMY5JP.js');
|
|
6208
6299
|
await runInteractive(
|
|
6209
6300
|
rootOf(global),
|
|
6210
6301
|
global,
|
|
@@ -6237,7 +6328,7 @@ function registerCode(program) {
|
|
|
6237
6328
|
let mockReply;
|
|
6238
6329
|
if (opts.mock) {
|
|
6239
6330
|
try {
|
|
6240
|
-
mockReply =
|
|
6331
|
+
mockReply = fs8.readFileSync(opts.mock, "utf8");
|
|
6241
6332
|
} catch {
|
|
6242
6333
|
throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
|
|
6243
6334
|
}
|
|
@@ -6286,18 +6377,18 @@ function registerCode(program) {
|
|
|
6286
6377
|
};
|
|
6287
6378
|
try {
|
|
6288
6379
|
const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
|
|
6289
|
-
const { runCodeStreamJson } = await import('./stream-json-
|
|
6290
|
-
const { nodeCodeFs } = await import('./session-
|
|
6380
|
+
const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-MTPWWVRR.js');
|
|
6381
|
+
const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
|
|
6291
6382
|
const readline5 = await import('readline');
|
|
6292
6383
|
const child = await import('child_process');
|
|
6293
6384
|
const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
|
|
6294
6385
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
6295
6386
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
6296
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
6297
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
6387
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
|
|
6388
|
+
const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
|
|
6298
6389
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
6299
6390
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
6300
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
6391
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
|
|
6301
6392
|
const federation = loadOrDiscoverFederation(root2);
|
|
6302
6393
|
const modelProfile = mergeModelExecutionProfile(
|
|
6303
6394
|
resolveModelExecutionProfile({
|
|
@@ -6343,7 +6434,7 @@ ${res.stderr}` : ""),
|
|
|
6343
6434
|
exitCode: res.status ?? 1
|
|
6344
6435
|
};
|
|
6345
6436
|
};
|
|
6346
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
6437
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
|
|
6347
6438
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
6348
6439
|
getGraph: () => graph,
|
|
6349
6440
|
root: root2,
|
|
@@ -6363,50 +6454,187 @@ ${res.stderr}` : ""),
|
|
|
6363
6454
|
};
|
|
6364
6455
|
}
|
|
6365
6456
|
const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
|
|
6457
|
+
const { createCheckpoint } = await import('./checkpoint-4WFZMKEO.js');
|
|
6458
|
+
const os5 = await import('os');
|
|
6459
|
+
const pathMod = await import('path');
|
|
6460
|
+
const checkpointIndex = pathMod.join(
|
|
6461
|
+
fs8.mkdtempSync(pathMod.join(os5.tmpdir(), "vg-code-cp-")),
|
|
6462
|
+
"index"
|
|
6463
|
+
);
|
|
6464
|
+
const gitRunner = (gitArgs, gitEnv) => {
|
|
6465
|
+
const res = child.spawnSync("git", gitArgs, {
|
|
6466
|
+
cwd: root2,
|
|
6467
|
+
encoding: "utf8",
|
|
6468
|
+
env: { ...process.env, ...gitEnv ?? {} },
|
|
6469
|
+
timeout: 3e4,
|
|
6470
|
+
maxBuffer: 32 * 1024 * 1024
|
|
6471
|
+
});
|
|
6472
|
+
return { stdout: res.stdout ?? "", exitCode: res.status ?? 1 };
|
|
6473
|
+
};
|
|
6474
|
+
const checkpointSessionId = `r${Date.now().toString(36)}`;
|
|
6475
|
+
let checkpointSeq = 0;
|
|
6476
|
+
const takeCheckpoint = (files) => createCheckpoint(gitRunner, {
|
|
6477
|
+
sessionId: checkpointSessionId,
|
|
6478
|
+
seq: ++checkpointSeq,
|
|
6479
|
+
files,
|
|
6480
|
+
indexFile: checkpointIndex
|
|
6481
|
+
});
|
|
6482
|
+
const { loadProjectRules, nodeRulesReader } = await import('./rules-ASYEUNB5.js');
|
|
6483
|
+
const projectRules = loadProjectRules(nodeRulesReader(root2));
|
|
6484
|
+
if (projectRules.sources.length && !global.quiet) {
|
|
6485
|
+
emitStream({
|
|
6486
|
+
event: "event",
|
|
6487
|
+
type: "notice",
|
|
6488
|
+
text: `project instructions: ${projectRules.sources.join(", ")}`
|
|
6489
|
+
});
|
|
6490
|
+
}
|
|
6491
|
+
const baseAgentOptions = {
|
|
6492
|
+
graph,
|
|
6493
|
+
root: root2,
|
|
6494
|
+
providers: route.providers,
|
|
6495
|
+
fsImpl: nodeCodeFs(root2),
|
|
6496
|
+
run,
|
|
6497
|
+
executionEnv,
|
|
6498
|
+
graphBackend,
|
|
6499
|
+
modelProfile,
|
|
6500
|
+
auto: !!auto,
|
|
6501
|
+
maxSteps,
|
|
6502
|
+
budget: modelProfile.capsuleBudgetTokens,
|
|
6503
|
+
contextBudget,
|
|
6504
|
+
denyCommands: config.denyCommands,
|
|
6505
|
+
testCommand: config.testCommand,
|
|
6506
|
+
stream: true,
|
|
6507
|
+
verify: verify3 ? { command: verify3.command, maxRounds: modelProfile.maxRepairRounds } : void 0,
|
|
6508
|
+
capsule,
|
|
6509
|
+
files: opts.file.length ? opts.file : void 0,
|
|
6510
|
+
worktreeOverlay: true,
|
|
6511
|
+
advancedMode: !capsule,
|
|
6512
|
+
externalTools,
|
|
6513
|
+
attribution: {
|
|
6514
|
+
client: "vg-code",
|
|
6515
|
+
provider: primarySlug,
|
|
6516
|
+
model: route.providers[0]?.model
|
|
6517
|
+
},
|
|
6518
|
+
now: () => Date.now(),
|
|
6519
|
+
projectRules: projectRules.rendered || void 0,
|
|
6520
|
+
checkpoint: takeCheckpoint
|
|
6521
|
+
};
|
|
6366
6522
|
try {
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
const msg = JSON.parse(raw);
|
|
6403
|
-
if (typeof msg.approveId === "number") session.submitDecision(msg.approveId, !!msg.approve);
|
|
6404
|
-
if (typeof msg.answerId === "number") session.submitAnswer(msg.answerId, String(msg.answer ?? ""));
|
|
6405
|
-
} catch {
|
|
6406
|
-
}
|
|
6523
|
+
if (opts.session) {
|
|
6524
|
+
const { runCodeStreamJsonSession } = await import('./stream-json-MTPWWVRR.js');
|
|
6525
|
+
const { runAgent: runAgent2 } = await import('./agent-Z4Z66IGM.js');
|
|
6526
|
+
const {
|
|
6527
|
+
loadLatestSession,
|
|
6528
|
+
newSession,
|
|
6529
|
+
recordTask,
|
|
6530
|
+
saveSession,
|
|
6531
|
+
summarizeSession
|
|
6532
|
+
} = await import('./session-store-O4XPXKOV.js');
|
|
6533
|
+
const resumedRecord = opts.continue ? loadLatestSession(root2) : void 0;
|
|
6534
|
+
let record = resumedRecord ?? newSession(
|
|
6535
|
+
`s${Date.now().toString(36)}`,
|
|
6536
|
+
primarySlug ?? route.providers[0]?.id ?? "unknown",
|
|
6537
|
+
route.providers[0]?.model ?? "unknown",
|
|
6538
|
+
Date.now()
|
|
6539
|
+
);
|
|
6540
|
+
const pendingTurns = [];
|
|
6541
|
+
let wakeTurn;
|
|
6542
|
+
let ended = false;
|
|
6543
|
+
const pushTurn = (instruction2) => {
|
|
6544
|
+
if (wakeTurn) {
|
|
6545
|
+
const wake = wakeTurn;
|
|
6546
|
+
wakeTurn = void 0;
|
|
6547
|
+
wake(instruction2);
|
|
6548
|
+
} else if (instruction2 !== null) {
|
|
6549
|
+
pendingTurns.push(instruction2);
|
|
6550
|
+
}
|
|
6551
|
+
};
|
|
6552
|
+
const nextTurn = () => {
|
|
6553
|
+
if (ended) return Promise.resolve(null);
|
|
6554
|
+
const queued = pendingTurns.shift();
|
|
6555
|
+
if (queued !== void 0) return Promise.resolve(queued);
|
|
6556
|
+
return new Promise((resolve21) => {
|
|
6557
|
+
wakeTurn = resolve21;
|
|
6407
6558
|
});
|
|
6408
|
-
}
|
|
6409
|
-
|
|
6559
|
+
};
|
|
6560
|
+
await runCodeStreamJsonSession({
|
|
6561
|
+
emit: emitStream,
|
|
6562
|
+
auto: !!auto,
|
|
6563
|
+
sessionId: record.id,
|
|
6564
|
+
resumed: !!resumedRecord,
|
|
6565
|
+
instruction,
|
|
6566
|
+
nextTurn,
|
|
6567
|
+
bindDecisions: (session) => {
|
|
6568
|
+
streamApprove = (action) => session.approve(action);
|
|
6569
|
+
const rl = readline5.createInterface({ input: process.stdin });
|
|
6570
|
+
rl.on("line", (raw) => {
|
|
6571
|
+
const msg = parseHostMessage(raw);
|
|
6572
|
+
if (!msg) return;
|
|
6573
|
+
if (msg.kind === "approve") session.submitDecision(msg.id, msg.approve);
|
|
6574
|
+
else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
|
|
6575
|
+
else if (msg.kind === "submit") pushTurn(msg.instruction);
|
|
6576
|
+
else if (msg.kind === "restore") {
|
|
6577
|
+
void import('./checkpoint-4WFZMKEO.js').then(({ restoreCheckpoint }) => {
|
|
6578
|
+
const outcome = restoreCheckpoint(gitRunner, {
|
|
6579
|
+
commit: msg.commit,
|
|
6580
|
+
files: msg.files
|
|
6581
|
+
});
|
|
6582
|
+
emitStream({ event: "checkpoint-restored", commit: msg.commit, ...outcome });
|
|
6583
|
+
});
|
|
6584
|
+
} else if (msg.kind === "cancel") session.cancelTurn();
|
|
6585
|
+
else if (msg.kind === "end") {
|
|
6586
|
+
ended = true;
|
|
6587
|
+
pushTurn(null);
|
|
6588
|
+
}
|
|
6589
|
+
});
|
|
6590
|
+
rl.on("close", () => {
|
|
6591
|
+
ended = true;
|
|
6592
|
+
session.cancelTurn();
|
|
6593
|
+
pushTurn(null);
|
|
6594
|
+
});
|
|
6595
|
+
},
|
|
6596
|
+
runTurn: ({ instruction: turnInstruction, priorSummary, signal, session }) => runAgent2({
|
|
6597
|
+
...baseAgentOptions,
|
|
6598
|
+
instruction: turnInstruction,
|
|
6599
|
+
priorSummary,
|
|
6600
|
+
signal,
|
|
6601
|
+
approve: session.approve,
|
|
6602
|
+
askUser: session.askUser,
|
|
6603
|
+
onEvent: session.onEvent
|
|
6604
|
+
}),
|
|
6605
|
+
onTurnEnd: (turn) => {
|
|
6606
|
+
record = recordTask(
|
|
6607
|
+
record,
|
|
6608
|
+
{
|
|
6609
|
+
instruction: turn.instruction,
|
|
6610
|
+
summary: turn.result?.finalText ?? "turn failed",
|
|
6611
|
+
changes: turn.result?.changes ?? [],
|
|
6612
|
+
stopped: turn.result?.stopped ?? "error"
|
|
6613
|
+
},
|
|
6614
|
+
Date.now()
|
|
6615
|
+
);
|
|
6616
|
+
saveSession(root2, record);
|
|
6617
|
+
return summarizeSession(record);
|
|
6618
|
+
}
|
|
6619
|
+
});
|
|
6620
|
+
} else {
|
|
6621
|
+
await runCodeStreamJson({
|
|
6622
|
+
...baseAgentOptions,
|
|
6623
|
+
instruction,
|
|
6624
|
+
emit: emitStream,
|
|
6625
|
+
bindDecisions: (session) => {
|
|
6626
|
+
streamApprove = (action) => session.approve(action);
|
|
6627
|
+
const rl = readline5.createInterface({ input: process.stdin });
|
|
6628
|
+
rl.on("line", (raw) => {
|
|
6629
|
+
const msg = parseHostMessage(raw);
|
|
6630
|
+
if (!msg) return;
|
|
6631
|
+
if (msg.kind === "approve") session.submitDecision(msg.id, msg.approve);
|
|
6632
|
+
else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
|
|
6633
|
+
else if (msg.kind === "cancel") session.cancelTurn();
|
|
6634
|
+
});
|
|
6635
|
+
}
|
|
6636
|
+
});
|
|
6637
|
+
}
|
|
6410
6638
|
} finally {
|
|
6411
6639
|
await disposeMcpStream?.();
|
|
6412
6640
|
await runtime.dispose();
|
|
@@ -6425,8 +6653,8 @@ ${res.stderr}` : ""),
|
|
|
6425
6653
|
if (!autonomous && !tty) {
|
|
6426
6654
|
throw usageError("the agent approves each edit/command \u2014 run in a terminal to approve interactively, or pass --auto to run autonomously (or --single for a one-shot diff).");
|
|
6427
6655
|
}
|
|
6428
|
-
const { agentTask } = await import('./interactive-
|
|
6429
|
-
const { nodeCodeFs } = await import('./session-
|
|
6656
|
+
const { agentTask } = await import('./interactive-MJVMY5JP.js');
|
|
6657
|
+
const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
|
|
6430
6658
|
const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
|
|
6431
6659
|
let priorSummary;
|
|
6432
6660
|
if (opts.continue) {
|
|
@@ -6435,7 +6663,7 @@ ${res.stderr}` : ""),
|
|
|
6435
6663
|
if (prev) priorSummary = summarizeSession(prev);
|
|
6436
6664
|
}
|
|
6437
6665
|
const prompter = tty ? new TtyPrompter() : void 0;
|
|
6438
|
-
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-
|
|
6666
|
+
const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
|
|
6439
6667
|
const vgBuiltin = createVgBuiltinMcpTools({
|
|
6440
6668
|
getGraph: () => graph,
|
|
6441
6669
|
root: root2,
|
|
@@ -6459,11 +6687,11 @@ ${res.stderr}` : ""),
|
|
|
6459
6687
|
const { loadFederation } = await import('./federation-MDQPO3PW.js');
|
|
6460
6688
|
const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
|
|
6461
6689
|
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
|
|
6462
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
6463
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
6690
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
|
|
6691
|
+
const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
|
|
6464
6692
|
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
6465
6693
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
6466
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
6694
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
|
|
6467
6695
|
const federation = loadFederation(root2);
|
|
6468
6696
|
const modelProfile = mergeModelExecutionProfile(
|
|
6469
6697
|
resolveModelExecutionProfile({
|
|
@@ -6555,7 +6783,7 @@ ${res.stderr}` : ""),
|
|
|
6555
6783
|
attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
|
|
6556
6784
|
});
|
|
6557
6785
|
if (opts.out) {
|
|
6558
|
-
|
|
6786
|
+
fs8.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
|
|
6559
6787
|
}
|
|
6560
6788
|
if (global.json) {
|
|
6561
6789
|
json(result);
|
|
@@ -6768,7 +6996,7 @@ async function addCmd(root2, rest, opts, asJson) {
|
|
|
6768
6996
|
}
|
|
6769
6997
|
function readPackageVersion(root2) {
|
|
6770
6998
|
try {
|
|
6771
|
-
const pkg = JSON.parse(
|
|
6999
|
+
const pkg = JSON.parse(fs8__default.readFileSync(path38__default.join(root2, "package.json"), "utf8"));
|
|
6772
7000
|
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
6773
7001
|
} catch {
|
|
6774
7002
|
return void 0;
|
|
@@ -6776,7 +7004,7 @@ function readPackageVersion(root2) {
|
|
|
6776
7004
|
}
|
|
6777
7005
|
function readOptionalFile(p) {
|
|
6778
7006
|
try {
|
|
6779
|
-
const t =
|
|
7007
|
+
const t = fs8__default.readFileSync(p, "utf8");
|
|
6780
7008
|
return t.trim() ? t : void 0;
|
|
6781
7009
|
} catch {
|
|
6782
7010
|
return void 0;
|
|
@@ -6791,8 +7019,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
|
|
|
6791
7019
|
if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
|
|
6792
7020
|
const version = (opts.version || readPackageVersion(root2) || "").trim();
|
|
6793
7021
|
if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
|
|
6794
|
-
const readme = readOptionalFile(opts.readme ?
|
|
6795
|
-
const dts = opts.dts ? readOptionalFile(
|
|
7022
|
+
const readme = readOptionalFile(opts.readme ? path38__default.resolve(opts.readme) : path38__default.join(root2, "README.md"));
|
|
7023
|
+
const dts = opts.dts ? readOptionalFile(path38__default.resolve(opts.dts)) : void 0;
|
|
6796
7024
|
if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
|
|
6797
7025
|
const result = await publishPrivateLibrary(
|
|
6798
7026
|
{ name, version, readme, dts, language: opts.language },
|
|
@@ -6924,8 +7152,8 @@ function registerExport(program) {
|
|
|
6924
7152
|
out(content.trimEnd());
|
|
6925
7153
|
return;
|
|
6926
7154
|
}
|
|
6927
|
-
|
|
6928
|
-
|
|
7155
|
+
fs8.mkdirSync(path38.dirname(path38.resolve(file)), { recursive: true });
|
|
7156
|
+
fs8.writeFileSync(file, content);
|
|
6929
7157
|
info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
|
|
6930
7158
|
});
|
|
6931
7159
|
applyGlobalOptions(cmd);
|
|
@@ -6935,43 +7163,43 @@ function detectFormat(file) {
|
|
|
6935
7163
|
if (lower.endsWith(".cdx.json")) return "cyclonedx";
|
|
6936
7164
|
if (lower.endsWith(".spdx.json")) return "spdx";
|
|
6937
7165
|
if (file === "-") return "json";
|
|
6938
|
-
return formatForExt(
|
|
7166
|
+
return formatForExt(path38.extname(file));
|
|
6939
7167
|
}
|
|
6940
7168
|
function registerBundle(program) {
|
|
6941
7169
|
const cmd = program.command("bundle").description("build an air-gapped bundle (grammars + graph + library catalog)").option("--offline", "offline bundle (default; present for clarity)").option("-o, --out <dir>", "output directory", "vg-bundle").action(function(opts) {
|
|
6942
7170
|
const global = readGlobal(this);
|
|
6943
7171
|
const root2 = rootOf(global);
|
|
6944
|
-
const outDir =
|
|
7172
|
+
const outDir = path38.resolve(root2, opts.out ?? "vg-bundle");
|
|
6945
7173
|
let grammarFiles;
|
|
6946
7174
|
try {
|
|
6947
7175
|
grammarFiles = resolvedGrammarFiles();
|
|
6948
7176
|
} catch {
|
|
6949
7177
|
throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
|
|
6950
7178
|
}
|
|
6951
|
-
|
|
7179
|
+
fs8.mkdirSync(path38.join(outDir, "grammars"), { recursive: true });
|
|
6952
7180
|
let grammarCount = 0;
|
|
6953
7181
|
for (const { fileName, absPath } of grammarFiles) {
|
|
6954
|
-
|
|
7182
|
+
fs8.copyFileSync(absPath, path38.join(outDir, "grammars", fileName));
|
|
6955
7183
|
grammarCount++;
|
|
6956
7184
|
}
|
|
6957
7185
|
const included = [`grammars/ (${grammarCount} .wasm)`];
|
|
6958
7186
|
const graphSrc = resolveGraphPath(root2, global.graph);
|
|
6959
|
-
if (
|
|
6960
|
-
|
|
7187
|
+
if (fs8.existsSync(graphSrc)) {
|
|
7188
|
+
fs8.copyFileSync(graphSrc, path38.join(outDir, "graph.json"));
|
|
6961
7189
|
included.push("graph.json");
|
|
6962
7190
|
} else {
|
|
6963
7191
|
const graph = loadGraphFileWithSnapshot(graphSrc);
|
|
6964
7192
|
if (graph) {
|
|
6965
|
-
|
|
7193
|
+
fs8.writeFileSync(path38.join(outDir, "graph.json"), serializeGraph(graph));
|
|
6966
7194
|
included.push("graph.json");
|
|
6967
7195
|
}
|
|
6968
7196
|
}
|
|
6969
7197
|
const cat = catalogPath(root2);
|
|
6970
|
-
if (
|
|
6971
|
-
|
|
7198
|
+
if (fs8.existsSync(cat)) {
|
|
7199
|
+
fs8.copyFileSync(cat, path38.join(outDir, "vibgrate.lib.json"));
|
|
6972
7200
|
included.push("vibgrate.lib.json");
|
|
6973
|
-
if (
|
|
6974
|
-
|
|
7201
|
+
if (fs8.existsSync(libDir(root2))) {
|
|
7202
|
+
fs8.cpSync(libDir(root2), path38.join(outDir, "lib"), { recursive: true });
|
|
6975
7203
|
included.push("lib/");
|
|
6976
7204
|
}
|
|
6977
7205
|
}
|
|
@@ -6983,15 +7211,15 @@ function registerBundle(program) {
|
|
|
6983
7211
|
included,
|
|
6984
7212
|
usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
|
|
6985
7213
|
};
|
|
6986
|
-
|
|
7214
|
+
fs8.writeFileSync(path38.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
|
|
6987
7215
|
`);
|
|
6988
7216
|
if (global.json) {
|
|
6989
|
-
json({ out:
|
|
7217
|
+
json({ out: path38.relative(root2, outDir), ...manifest });
|
|
6990
7218
|
return;
|
|
6991
7219
|
}
|
|
6992
|
-
info(`${c.cyan("vg bundle")} \xB7 wrote ${
|
|
7220
|
+
info(`${c.cyan("vg bundle")} \xB7 wrote ${path38.relative(root2, outDir)}/`);
|
|
6993
7221
|
for (const i of included) info(` ${c.green("\u2714")} ${i}`);
|
|
6994
|
-
info(c.dim(` offline: vg build --grammars "${
|
|
7222
|
+
info(c.dim(` offline: vg build --grammars "${path38.relative(root2, outDir)}/grammars"`));
|
|
6995
7223
|
});
|
|
6996
7224
|
applyGlobalOptions(cmd);
|
|
6997
7225
|
}
|
|
@@ -7009,7 +7237,7 @@ async function runDoctor(global) {
|
|
|
7009
7237
|
const root2 = rootOf(global);
|
|
7010
7238
|
const local = global.local === true;
|
|
7011
7239
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
7012
|
-
const configFile = CONFIG_BASENAMES.find((f) =>
|
|
7240
|
+
const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path38.join(root2, f))) ?? null;
|
|
7013
7241
|
const graph = loadGraph(root2, graphPath);
|
|
7014
7242
|
let staleFiles = null;
|
|
7015
7243
|
if (graph) {
|
|
@@ -7035,14 +7263,14 @@ async function runDoctor(global) {
|
|
|
7035
7263
|
root: root2,
|
|
7036
7264
|
configFile,
|
|
7037
7265
|
map: {
|
|
7038
|
-
path:
|
|
7266
|
+
path: path38.relative(root2, graphPath),
|
|
7039
7267
|
built: graph !== null,
|
|
7040
7268
|
generatedAt: graph?.generatedAt ?? null,
|
|
7041
7269
|
staleFiles
|
|
7042
7270
|
},
|
|
7043
7271
|
libCatalog: {
|
|
7044
|
-
path:
|
|
7045
|
-
present:
|
|
7272
|
+
path: path38.relative(root2, catalogPath(root2)),
|
|
7273
|
+
present: fs8.existsSync(catalogPath(root2)),
|
|
7046
7274
|
libraries: libCount
|
|
7047
7275
|
},
|
|
7048
7276
|
credentials: creds,
|
|
@@ -7099,7 +7327,7 @@ async function runDoctor(global) {
|
|
|
7099
7327
|
);
|
|
7100
7328
|
info(
|
|
7101
7329
|
` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
|
|
7102
|
-
` \xB7 last ${
|
|
7330
|
+
` \xB7 last ${path38.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
|
|
7103
7331
|
) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
|
|
7104
7332
|
);
|
|
7105
7333
|
if (li.dynamicOnToken || li.dynamicCustomSampler) {
|
|
@@ -7179,7 +7407,9 @@ function registerDaemon(program) {
|
|
|
7179
7407
|
if (await vgdIsRunning({ socketPath })) {
|
|
7180
7408
|
throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);
|
|
7181
7409
|
}
|
|
7182
|
-
|
|
7410
|
+
let requestShutdown = () => {
|
|
7411
|
+
};
|
|
7412
|
+
const server = await startVgdServer({ socketPath, onShutdownRequest: () => requestShutdown() });
|
|
7183
7413
|
if (!global.quiet) {
|
|
7184
7414
|
info(`vgd \xB7 listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);
|
|
7185
7415
|
info(c.dim(" register a workspace: vg daemon register"));
|
|
@@ -7190,6 +7420,7 @@ function registerDaemon(program) {
|
|
|
7190
7420
|
if (!global.quiet) info(c.dim("vgd \xB7 stopped"));
|
|
7191
7421
|
process.exit(0);
|
|
7192
7422
|
};
|
|
7423
|
+
requestShutdown = () => void shutdown();
|
|
7193
7424
|
process.on("SIGINT", () => void shutdown());
|
|
7194
7425
|
process.on("SIGTERM", () => void shutdown());
|
|
7195
7426
|
await new Promise(() => {
|
|
@@ -7209,33 +7440,70 @@ function registerDaemon(program) {
|
|
|
7209
7440
|
}
|
|
7210
7441
|
return;
|
|
7211
7442
|
}
|
|
7212
|
-
const child =
|
|
7213
|
-
child.unref();
|
|
7214
|
-
const deadline = Date.now() + 8e3;
|
|
7215
|
-
let ready = false;
|
|
7216
|
-
while (Date.now() < deadline) {
|
|
7217
|
-
await sleep(100);
|
|
7218
|
-
if (await vgdIsRunning({ socketPath })) {
|
|
7219
|
-
ready = true;
|
|
7220
|
-
break;
|
|
7221
|
-
}
|
|
7222
|
-
}
|
|
7223
|
-
if (!ready) {
|
|
7224
|
-
throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
|
|
7225
|
-
}
|
|
7443
|
+
const child = await startDetachedVgd(socketPath);
|
|
7226
7444
|
const res = await vgdRequest({ op: "status" }, { socketPath });
|
|
7227
7445
|
if (global.json) {
|
|
7228
7446
|
json({ running: true, ensured: true, ...res.ok ? res : { socketPath } });
|
|
7229
7447
|
} else if (!global.quiet) {
|
|
7230
|
-
const pid = res.ok && "pid" in res ? res.pid : child
|
|
7448
|
+
const pid = res.ok && "pid" in res ? res.pid : child;
|
|
7231
7449
|
info(`vgd \xB7 started in background pid ${pid} \xB7 ${c.dim(socketPath)}`);
|
|
7232
7450
|
}
|
|
7233
7451
|
});
|
|
7234
7452
|
applyGlobalOptions(ensure);
|
|
7453
|
+
const stop = cmd.command("stop").description("stop the running vgd (idempotent \u2014 succeeds if none is running)").action(async function() {
|
|
7454
|
+
const global = readGlobal(this);
|
|
7455
|
+
const socketPath = socketOf(this);
|
|
7456
|
+
const result = await stopVgd(socketPath);
|
|
7457
|
+
if (global.json) {
|
|
7458
|
+
json({ stopped: result === "stopped", result, socketPath });
|
|
7459
|
+
} else if (!global.quiet) {
|
|
7460
|
+
if (result === "stopped") info(`vgd \xB7 stopped ${c.dim(socketPath)}`);
|
|
7461
|
+
else if (result === "not-running") info(c.dim(`vgd \xB7 not running (${socketPath})`));
|
|
7462
|
+
}
|
|
7463
|
+
if (result === "refused") {
|
|
7464
|
+
throw new CliError(
|
|
7465
|
+
"this vgd is embedded in another process (e.g. vg code) \u2014 stop that process instead",
|
|
7466
|
+
ExitCode.ERROR
|
|
7467
|
+
);
|
|
7468
|
+
}
|
|
7469
|
+
if (result === "failed") {
|
|
7470
|
+
throw new CliError(
|
|
7471
|
+
`vgd did not stop within 5s (${socketPath}) \u2014 check \`vg daemon status\` and stop the process manually`,
|
|
7472
|
+
ExitCode.ERROR
|
|
7473
|
+
);
|
|
7474
|
+
}
|
|
7475
|
+
});
|
|
7476
|
+
applyGlobalOptions(stop);
|
|
7477
|
+
const restart = cmd.command("restart").description("restart vgd (stop if running, then start in the background)").action(async function() {
|
|
7478
|
+
const global = readGlobal(this);
|
|
7479
|
+
const socketPath = socketOf(this);
|
|
7480
|
+
const stopResult = await stopVgd(socketPath);
|
|
7481
|
+
if (stopResult === "refused") {
|
|
7482
|
+
throw new CliError(
|
|
7483
|
+
"this vgd is embedded in another process (e.g. vg code) \u2014 stop that process instead",
|
|
7484
|
+
ExitCode.ERROR
|
|
7485
|
+
);
|
|
7486
|
+
}
|
|
7487
|
+
if (stopResult === "failed") {
|
|
7488
|
+
throw new CliError(
|
|
7489
|
+
`vgd did not stop within 5s (${socketPath}) \u2014 check \`vg daemon status\` and stop the process manually`,
|
|
7490
|
+
ExitCode.ERROR
|
|
7491
|
+
);
|
|
7492
|
+
}
|
|
7493
|
+
await startDetachedVgd(socketPath);
|
|
7494
|
+
const res = await vgdRequest({ op: "status" }, { socketPath });
|
|
7495
|
+
if (global.json) {
|
|
7496
|
+
json({ running: true, restarted: true, ...res.ok ? res : { socketPath } });
|
|
7497
|
+
} else if (!global.quiet) {
|
|
7498
|
+
const pid = res.ok && "pid" in res ? res.pid : "?";
|
|
7499
|
+
info(`vgd \xB7 restarted pid ${pid} \xB7 ${c.dim(socketPath)}`);
|
|
7500
|
+
}
|
|
7501
|
+
});
|
|
7502
|
+
applyGlobalOptions(restart);
|
|
7235
7503
|
const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
|
|
7236
7504
|
const global = readGlobal(this);
|
|
7237
7505
|
const socketPath = socketOf(this);
|
|
7238
|
-
const root2 =
|
|
7506
|
+
const root2 = path38.resolve(rootArg ?? rootOf(global));
|
|
7239
7507
|
if (!await vgdIsRunning({ socketPath })) {
|
|
7240
7508
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
7241
7509
|
}
|
|
@@ -7271,7 +7539,7 @@ function registerDaemon(program) {
|
|
|
7271
7539
|
const federation = cmd.command("federation").description("register a multi-root federation from .vibgrate/federation.json (or primary cwd)").argument("[root]", "primary repository root (default: cwd)").action(async function(rootArg) {
|
|
7272
7540
|
const global = readGlobal(this);
|
|
7273
7541
|
const socketPath = socketOf(this);
|
|
7274
|
-
const primary =
|
|
7542
|
+
const primary = path38.resolve(rootArg ?? rootOf(global));
|
|
7275
7543
|
if (!await vgdIsRunning({ socketPath })) {
|
|
7276
7544
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
7277
7545
|
}
|
|
@@ -7299,32 +7567,42 @@ function registerDaemon(program) {
|
|
|
7299
7567
|
const publish = cmd.command("publish").description("load the workspace code map into vgd ActiveGraph (from global/legacy store)").argument("[root]", "repository root (default: cwd)").option("--git-ref <ref>", "branch or SHA (default: detect HEAD)").action(async function(rootArg) {
|
|
7300
7568
|
const global = readGlobal(this);
|
|
7301
7569
|
const socketPath = socketOf(this);
|
|
7302
|
-
const root2 =
|
|
7570
|
+
const root2 = path38.resolve(rootArg ?? rootOf(global));
|
|
7303
7571
|
if (!await vgdIsRunning({ socketPath })) {
|
|
7304
7572
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
7305
7573
|
}
|
|
7306
|
-
const { loadGraph: loadGraph2 } = await import('./load-WKIZF2AK.js');
|
|
7307
|
-
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7308
|
-
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7309
7574
|
const opts = this.opts();
|
|
7310
|
-
const
|
|
7311
|
-
|
|
7312
|
-
throw new CliError(
|
|
7313
|
-
`no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
|
|
7314
|
-
ExitCode.NOT_FOUND
|
|
7315
|
-
);
|
|
7316
|
-
}
|
|
7317
|
-
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
7318
|
-
if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
|
|
7319
|
-
const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
|
|
7320
|
-
const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
|
|
7321
|
-
const put = await vgdRequest(
|
|
7322
|
-
{ op: "put-graph", repositoryId, gitRef: git2, graph },
|
|
7575
|
+
const loaded = await vgdRequest(
|
|
7576
|
+
{ op: "load-graph", root: root2, gitRef: opts.gitRef?.trim() || void 0, graphPath: global.graph },
|
|
7323
7577
|
{ socketPath }
|
|
7324
7578
|
);
|
|
7325
|
-
|
|
7579
|
+
let put = loaded;
|
|
7580
|
+
if (!loaded.ok && loaded.code === "no_map") {
|
|
7581
|
+
throw new CliError(loaded.error, ExitCode.NOT_FOUND);
|
|
7582
|
+
}
|
|
7583
|
+
if (!loaded.ok) {
|
|
7584
|
+
const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
|
|
7585
|
+
const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
|
|
7586
|
+
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7587
|
+
const graph = loadGraph2(root2, global.graph);
|
|
7588
|
+
if (!graph) {
|
|
7589
|
+
throw new CliError(
|
|
7590
|
+
`no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
|
|
7591
|
+
ExitCode.NOT_FOUND
|
|
7592
|
+
);
|
|
7593
|
+
}
|
|
7594
|
+
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
7595
|
+
if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
|
|
7596
|
+
const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
|
|
7597
|
+
const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
|
|
7598
|
+
put = await vgdRequest(
|
|
7599
|
+
{ op: "put-graph", repositoryId, gitRef: git2, graph },
|
|
7600
|
+
{ socketPath }
|
|
7601
|
+
);
|
|
7602
|
+
if (!put.ok) throw new CliError(put.error, ExitCode.ERROR);
|
|
7603
|
+
}
|
|
7326
7604
|
if (global.json) json(put);
|
|
7327
|
-
else if ("stored" in put) {
|
|
7605
|
+
else if (put.ok && "stored" in put) {
|
|
7328
7606
|
info(`vgd \xB7 published graph \xB7 ${put.nodeCount} node(s) \xB7 ref ${put.gitRef}`);
|
|
7329
7607
|
info(c.dim(` repositoryId ${put.repositoryId}`));
|
|
7330
7608
|
}
|
|
@@ -7419,7 +7697,7 @@ function socketOf(cmd) {
|
|
|
7419
7697
|
let c2 = cmd;
|
|
7420
7698
|
while (c2) {
|
|
7421
7699
|
const opts = c2.opts();
|
|
7422
|
-
if (opts.socket) return
|
|
7700
|
+
if (opts.socket) return path38.resolve(opts.socket);
|
|
7423
7701
|
c2 = c2.parent;
|
|
7424
7702
|
}
|
|
7425
7703
|
return vgdSocketPath();
|
|
@@ -7442,6 +7720,62 @@ function spawnDetachedDaemonStart(socketPath) {
|
|
|
7442
7720
|
function sleep(ms) {
|
|
7443
7721
|
return new Promise((r) => setTimeout(r, ms));
|
|
7444
7722
|
}
|
|
7723
|
+
async function startDetachedVgd(socketPath) {
|
|
7724
|
+
const child = spawnDetachedDaemonStart(socketPath);
|
|
7725
|
+
child.unref();
|
|
7726
|
+
const deadline = Date.now() + 8e3;
|
|
7727
|
+
while (Date.now() < deadline) {
|
|
7728
|
+
await sleep(100);
|
|
7729
|
+
if (await vgdIsRunning({ socketPath })) return child.pid;
|
|
7730
|
+
}
|
|
7731
|
+
throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
|
|
7732
|
+
}
|
|
7733
|
+
async function stopVgd(socketPath) {
|
|
7734
|
+
if (!await vgdIsRunning({ socketPath })) return "not-running";
|
|
7735
|
+
let acknowledged = false;
|
|
7736
|
+
try {
|
|
7737
|
+
const res = await vgdRequest({ op: "shutdown" }, { socketPath });
|
|
7738
|
+
if (res.ok) acknowledged = true;
|
|
7739
|
+
else if (res.code === "shutdown_unsupported") return "refused";
|
|
7740
|
+
} catch {
|
|
7741
|
+
}
|
|
7742
|
+
if (!acknowledged) {
|
|
7743
|
+
const pid = readVgdPid();
|
|
7744
|
+
if (pid == null) return "failed";
|
|
7745
|
+
try {
|
|
7746
|
+
process.kill(pid, "SIGTERM");
|
|
7747
|
+
} catch {
|
|
7748
|
+
return "failed";
|
|
7749
|
+
}
|
|
7750
|
+
}
|
|
7751
|
+
const deadline = Date.now() + 5e3;
|
|
7752
|
+
while (Date.now() < deadline) {
|
|
7753
|
+
await sleep(100);
|
|
7754
|
+
if (!await vgdIsRunning({ socketPath })) return "stopped";
|
|
7755
|
+
}
|
|
7756
|
+
return "failed";
|
|
7757
|
+
}
|
|
7758
|
+
async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
|
|
7759
|
+
try {
|
|
7760
|
+
const stopResult = await stopVgd(socketPath);
|
|
7761
|
+
if (stopResult === "not-running") return "not-running";
|
|
7762
|
+
if (stopResult === "refused") return "refused";
|
|
7763
|
+
if (stopResult === "failed") return "failed";
|
|
7764
|
+
await startDetachedVgd(socketPath);
|
|
7765
|
+
return "restarted";
|
|
7766
|
+
} catch {
|
|
7767
|
+
return "failed";
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
function readVgdPid() {
|
|
7771
|
+
try {
|
|
7772
|
+
const raw = fs8.readFileSync(vgdPidPath(), "utf8").trim();
|
|
7773
|
+
const pid = Number.parseInt(raw, 10);
|
|
7774
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
7775
|
+
} catch {
|
|
7776
|
+
return null;
|
|
7777
|
+
}
|
|
7778
|
+
}
|
|
7445
7779
|
async function repositoryIdForCwd(socketPath, root2) {
|
|
7446
7780
|
const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
|
|
7447
7781
|
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
@@ -7520,7 +7854,7 @@ function registerPolicy(program) {
|
|
|
7520
7854
|
const global = readGlobal(this);
|
|
7521
7855
|
let raw;
|
|
7522
7856
|
try {
|
|
7523
|
-
raw =
|
|
7857
|
+
raw = fs8.readFileSync(file, "utf8");
|
|
7524
7858
|
} catch {
|
|
7525
7859
|
throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
|
|
7526
7860
|
}
|
|
@@ -7640,11 +7974,11 @@ function registerLlmHost(program) {
|
|
|
7640
7974
|
applyGlobalOptions(cmd);
|
|
7641
7975
|
}
|
|
7642
7976
|
var initCommand = new Command("init").description("Initialize vibgrate in a project").argument("[path]", "Path to initialize", ".").option("--baseline", "Create initial baseline after init").option("--yes", "Skip confirmation prompts").action(async (targetPath, opts) => {
|
|
7643
|
-
const rootDir =
|
|
7644
|
-
const vibgrateDir2 =
|
|
7977
|
+
const rootDir = path38.resolve(targetPath);
|
|
7978
|
+
const vibgrateDir2 = path38.join(rootDir, ".vibgrate");
|
|
7645
7979
|
await ensureDir(vibgrateDir2);
|
|
7646
7980
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
|
|
7647
|
-
const configPath =
|
|
7981
|
+
const configPath = path38.join(rootDir, "vibgrate.config.ts");
|
|
7648
7982
|
if (await pathExists(configPath)) {
|
|
7649
7983
|
console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
|
|
7650
7984
|
} else {
|
|
@@ -7652,7 +7986,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
7652
7986
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
|
|
7653
7987
|
}
|
|
7654
7988
|
if (opts.baseline) {
|
|
7655
|
-
const { runBaseline } = await import('./baseline-
|
|
7989
|
+
const { runBaseline } = await import('./baseline-Q3QQF5QF.js');
|
|
7656
7990
|
await runBaseline(rootDir);
|
|
7657
7991
|
}
|
|
7658
7992
|
console.log("");
|
|
@@ -7755,16 +8089,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
|
|
|
7755
8089
|
};
|
|
7756
8090
|
}
|
|
7757
8091
|
async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
|
|
7758
|
-
const content = await readFile3(
|
|
8092
|
+
const content = await readFile3(path38.join(rootDir, relFile));
|
|
7759
8093
|
if (!content) return false;
|
|
7760
8094
|
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7761
8095
|
return new RegExp(`\\b${escaped}\\b`).test(content);
|
|
7762
8096
|
}
|
|
7763
8097
|
async function defaultReadFile(absPath) {
|
|
7764
8098
|
try {
|
|
7765
|
-
const stat2 = await
|
|
8099
|
+
const stat2 = await fs22.stat(absPath);
|
|
7766
8100
|
if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
|
|
7767
|
-
return await
|
|
8101
|
+
return await fs22.readFile(absPath, "utf8");
|
|
7768
8102
|
} catch {
|
|
7769
8103
|
return null;
|
|
7770
8104
|
}
|
|
@@ -7950,7 +8284,7 @@ var AI_ASSISTANT_DETECTORS = [
|
|
|
7950
8284
|
async function detectAiAssistant(rootDir) {
|
|
7951
8285
|
for (const detector of AI_ASSISTANT_DETECTORS) {
|
|
7952
8286
|
for (const file of detector.files) {
|
|
7953
|
-
if (await pathExists$1(
|
|
8287
|
+
if (await pathExists$1(path38.join(rootDir, file))) {
|
|
7954
8288
|
return detector.name;
|
|
7955
8289
|
}
|
|
7956
8290
|
}
|
|
@@ -8144,7 +8478,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
8144
8478
|
collectExcludes,
|
|
8145
8479
|
[]
|
|
8146
8480
|
).option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--full", "Comprehensive scan: turns on known-vulnerability detection (= --vulns) and, when a standards policy exists, a banned-dependency report \u2014 on top of drift scoring and the code map").option("--vulns", "Also scan installed dependencies for known vulnerabilities (OSV online, or advisories from --package-manifest when offline)").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--project-scan-timeout <seconds>", "Per-project scan timeout in seconds (default: 180)").option("--drift-budget <score>", "Fail if DriftScore is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").option("--repository-name <name>", "Override the repository name recorded for this scan (defaults to the directory or package.json name)").option("--force", "Always create a fresh scan ingest, even if the repository is unchanged since the last scan (skips the unchanged/reuse optimization). Used by scheduled and dashboard-triggered scans.").option("--no-graph", "Skip building the local code map (the AI/docs index) that scan produces after scoring drift").option("--quiet", "Suppress promotional output (the free-plan tracking panel and the AI Context install prompt); scan results are unaffected").action(async (targetPath, opts) => {
|
|
8147
|
-
const rootDir =
|
|
8481
|
+
const rootDir = path38.resolve(targetPath);
|
|
8148
8482
|
if (!await pathExists$1(rootDir)) {
|
|
8149
8483
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
8150
8484
|
process.exit(1);
|
|
@@ -8152,7 +8486,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
8152
8486
|
const hasDsn = !!resolveDsn(opts.dsn);
|
|
8153
8487
|
const willPush = !opts.offline && (opts.push || hasDsn);
|
|
8154
8488
|
const noLocalArtifacts = opts.localArtifacts === false;
|
|
8155
|
-
const isFirstRun = !await pathExists$1(
|
|
8489
|
+
const isFirstRun = !await pathExists$1(path38.join(rootDir, ".vibgrate", "scan_result.json"));
|
|
8156
8490
|
let pinnedRegion;
|
|
8157
8491
|
let planTier;
|
|
8158
8492
|
let upgradeUrl;
|
|
@@ -8411,40 +8745,40 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
|
8411
8745
|
function scanStaleness(rootDir, artifactPath) {
|
|
8412
8746
|
let ref;
|
|
8413
8747
|
try {
|
|
8414
|
-
ref =
|
|
8748
|
+
ref = fs8.statSync(artifactPath).mtimeMs;
|
|
8415
8749
|
} catch {
|
|
8416
8750
|
return { stale: false };
|
|
8417
8751
|
}
|
|
8418
8752
|
let newest = -Infinity;
|
|
8419
8753
|
let newestChanged;
|
|
8420
|
-
const
|
|
8754
|
+
const MAX_ENTRIES2 = 2e4;
|
|
8421
8755
|
let scanned = 0;
|
|
8422
8756
|
const walk2 = (dir, depth) => {
|
|
8423
|
-
if (depth > 8 || scanned >
|
|
8757
|
+
if (depth > 8 || scanned > MAX_ENTRIES2) return;
|
|
8424
8758
|
let entries;
|
|
8425
8759
|
try {
|
|
8426
|
-
entries =
|
|
8760
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
8427
8761
|
} catch {
|
|
8428
8762
|
return;
|
|
8429
8763
|
}
|
|
8430
8764
|
for (const e of entries) {
|
|
8431
8765
|
scanned++;
|
|
8432
|
-
if (scanned >
|
|
8766
|
+
if (scanned > MAX_ENTRIES2) break;
|
|
8433
8767
|
if (e.isDirectory()) {
|
|
8434
|
-
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(
|
|
8768
|
+
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path38.join(dir, e.name), depth + 1);
|
|
8435
8769
|
continue;
|
|
8436
8770
|
}
|
|
8437
8771
|
if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
|
|
8438
|
-
const abs =
|
|
8772
|
+
const abs = path38.join(dir, e.name);
|
|
8439
8773
|
let mtimeMs;
|
|
8440
8774
|
try {
|
|
8441
|
-
mtimeMs =
|
|
8775
|
+
mtimeMs = fs8.statSync(abs).mtimeMs;
|
|
8442
8776
|
} catch {
|
|
8443
8777
|
continue;
|
|
8444
8778
|
}
|
|
8445
8779
|
if (mtimeMs > newest) {
|
|
8446
8780
|
newest = mtimeMs;
|
|
8447
|
-
newestChanged =
|
|
8781
|
+
newestChanged = path38.relative(rootDir, abs) || e.name;
|
|
8448
8782
|
}
|
|
8449
8783
|
}
|
|
8450
8784
|
};
|
|
@@ -8575,7 +8909,7 @@ function analyzeTree(root2, packages) {
|
|
|
8575
8909
|
if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
|
|
8576
8910
|
let entries;
|
|
8577
8911
|
try {
|
|
8578
|
-
entries =
|
|
8912
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
8579
8913
|
} catch {
|
|
8580
8914
|
return;
|
|
8581
8915
|
}
|
|
@@ -8584,17 +8918,17 @@ function analyzeTree(root2, packages) {
|
|
|
8584
8918
|
if (filesSeen >= MAX_FILES) return;
|
|
8585
8919
|
if (entry.isDirectory()) {
|
|
8586
8920
|
if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
8587
|
-
walk2(
|
|
8921
|
+
walk2(path38.join(dir, entry.name), depth + 1);
|
|
8588
8922
|
continue;
|
|
8589
8923
|
}
|
|
8590
|
-
const fileEco = EXT_ECOSYSTEM[
|
|
8924
|
+
const fileEco = EXT_ECOSYSTEM[path38.extname(entry.name)];
|
|
8591
8925
|
if (!fileEco || fileEco === "unknown") continue;
|
|
8592
8926
|
filesSeen++;
|
|
8593
|
-
const full =
|
|
8927
|
+
const full = path38.join(dir, entry.name);
|
|
8594
8928
|
let content;
|
|
8595
8929
|
try {
|
|
8596
|
-
if (
|
|
8597
|
-
content =
|
|
8930
|
+
if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
|
|
8931
|
+
content = fs8.readFileSync(full, "utf8");
|
|
8598
8932
|
} catch {
|
|
8599
8933
|
continue;
|
|
8600
8934
|
}
|
|
@@ -8905,7 +9239,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
8905
9239
|
}
|
|
8906
9240
|
const outcomes = effective.map((t) => {
|
|
8907
9241
|
const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
|
|
8908
|
-
return { t, res: run(c2,
|
|
9242
|
+
return { t, res: run(c2, path38.join(rootDir, t.dir)) };
|
|
8909
9243
|
});
|
|
8910
9244
|
const failures = outcomes.filter((o) => !o.res.ok);
|
|
8911
9245
|
if (failures.length === 0) {
|
|
@@ -8934,8 +9268,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
8934
9268
|
return results;
|
|
8935
9269
|
}
|
|
8936
9270
|
var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
|
|
8937
|
-
var CACHE_DIR =
|
|
8938
|
-
var CACHE_FILE =
|
|
9271
|
+
var CACHE_DIR = path38.join(os.homedir(), ".vibgrate");
|
|
9272
|
+
var CACHE_FILE = path38.join(CACHE_DIR, "update-check.json");
|
|
8939
9273
|
async function fetchLatestVersion() {
|
|
8940
9274
|
try {
|
|
8941
9275
|
const controller = new AbortController();
|
|
@@ -8953,7 +9287,7 @@ async function fetchLatestVersion() {
|
|
|
8953
9287
|
if (!response.ok) return null;
|
|
8954
9288
|
const data = await response.json();
|
|
8955
9289
|
const latest = data.version;
|
|
8956
|
-
if (!latest || !
|
|
9290
|
+
if (!latest || !semver3__default.valid(latest)) return null;
|
|
8957
9291
|
await writeCache({ latest, checkedAt: Date.now() });
|
|
8958
9292
|
return latest;
|
|
8959
9293
|
} catch {
|
|
@@ -8962,8 +9296,8 @@ async function fetchLatestVersion() {
|
|
|
8962
9296
|
}
|
|
8963
9297
|
async function writeCache(data) {
|
|
8964
9298
|
try {
|
|
8965
|
-
await
|
|
8966
|
-
await
|
|
9299
|
+
await fs22.mkdir(CACHE_DIR, { recursive: true });
|
|
9300
|
+
await fs22.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
|
|
8967
9301
|
} catch {
|
|
8968
9302
|
}
|
|
8969
9303
|
}
|
|
@@ -8974,7 +9308,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
|
|
|
8974
9308
|
if (!execPath) return null;
|
|
8975
9309
|
let resolved = execPath;
|
|
8976
9310
|
try {
|
|
8977
|
-
resolved =
|
|
9311
|
+
resolved = fs8.realpathSync(execPath);
|
|
8978
9312
|
} catch {
|
|
8979
9313
|
}
|
|
8980
9314
|
const p = resolved.replace(/\\/g, "/");
|
|
@@ -9004,14 +9338,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
|
|
|
9004
9338
|
pm: "yarn",
|
|
9005
9339
|
root: () => {
|
|
9006
9340
|
const dir = tryRun("yarn global dir");
|
|
9007
|
-
return dir ?
|
|
9341
|
+
return dir ? path38.join(dir, "node_modules") : null;
|
|
9008
9342
|
}
|
|
9009
9343
|
},
|
|
9010
|
-
{ pm: "bun", root: () =>
|
|
9344
|
+
{ pm: "bun", root: () => path38.join(os.homedir(), ".bun", "install", "global", "node_modules") }
|
|
9011
9345
|
];
|
|
9012
9346
|
for (const probe of probes) {
|
|
9013
9347
|
const root2 = probe.root();
|
|
9014
|
-
if (root2 && await pathExists(
|
|
9348
|
+
if (root2 && await pathExists(path38.join(root2, pkg))) return probe.pm;
|
|
9015
9349
|
}
|
|
9016
9350
|
return null;
|
|
9017
9351
|
}
|
|
@@ -9030,15 +9364,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
|
|
|
9030
9364
|
}
|
|
9031
9365
|
}
|
|
9032
9366
|
async function detectPackageManager(cwd) {
|
|
9033
|
-
if (await pathExists(
|
|
9034
|
-
if (await pathExists(
|
|
9035
|
-
if (await pathExists(
|
|
9367
|
+
if (await pathExists(path38.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
9368
|
+
if (await pathExists(path38.join(cwd, "bun.lockb"))) return "bun";
|
|
9369
|
+
if (await pathExists(path38.join(cwd, "yarn.lock"))) return "yarn";
|
|
9036
9370
|
return "npm";
|
|
9037
9371
|
}
|
|
9038
9372
|
async function detectWorkspaceRoot(cwd) {
|
|
9039
|
-
if (await pathExists(
|
|
9373
|
+
if (await pathExists(path38.join(cwd, "pnpm-workspace.yaml"))) return true;
|
|
9040
9374
|
try {
|
|
9041
|
-
const pkgPath =
|
|
9375
|
+
const pkgPath = path38.join(cwd, "package.json");
|
|
9042
9376
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
9043
9377
|
const pkg = JSON.parse(raw);
|
|
9044
9378
|
return pkg.workspaces != null;
|
|
@@ -9063,7 +9397,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
|
|
|
9063
9397
|
}
|
|
9064
9398
|
async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
|
|
9065
9399
|
try {
|
|
9066
|
-
const pkgPath =
|
|
9400
|
+
const pkgPath = path38.join(cwd, "package.json");
|
|
9067
9401
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
9068
9402
|
const parsed = JSON.parse(raw);
|
|
9069
9403
|
if (parsed.devDependencies?.[pkg]) return "dev";
|
|
@@ -9092,8 +9426,8 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
|
|
|
9092
9426
|
console.error(chalk7.red("Could not reach the npm registry. Check your network connection."));
|
|
9093
9427
|
process.exit(1);
|
|
9094
9428
|
}
|
|
9095
|
-
const
|
|
9096
|
-
if (!
|
|
9429
|
+
const semver4 = await import('semver');
|
|
9430
|
+
if (!semver4.gt(latest, VERSION)) {
|
|
9097
9431
|
console.log(chalk7.green("\u2714") + ` You are on the latest version (${VERSION}).`);
|
|
9098
9432
|
if (opts.reap !== false) reapAndReport(process.cwd(), VERSION);
|
|
9099
9433
|
return;
|
|
@@ -9152,8 +9486,29 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
|
|
|
9152
9486
|
process.exit(1);
|
|
9153
9487
|
}
|
|
9154
9488
|
if (opts.reap !== false) reapAndReport(cwd, latest);
|
|
9489
|
+
if (opts.reap !== false) await restartVgdAndReport();
|
|
9155
9490
|
}
|
|
9156
9491
|
);
|
|
9492
|
+
async function restartVgdAndReport() {
|
|
9493
|
+
let result;
|
|
9494
|
+
try {
|
|
9495
|
+
result = await restartVgdIfRunning();
|
|
9496
|
+
} catch {
|
|
9497
|
+
return;
|
|
9498
|
+
}
|
|
9499
|
+
if (result === "not-running") return;
|
|
9500
|
+
if (result === "restarted") {
|
|
9501
|
+
console.log(chalk7.dim("Restarted the vgd daemon on the new version."));
|
|
9502
|
+
} else if (result === "refused") {
|
|
9503
|
+
console.log(
|
|
9504
|
+
chalk7.dim("A vgd embedded in another process (e.g. vg code) is running \u2014 restart that session to pick up the update.")
|
|
9505
|
+
);
|
|
9506
|
+
} else {
|
|
9507
|
+
console.log(
|
|
9508
|
+
chalk7.dim('Could not restart the vgd daemon automatically \u2014 run "vg daemon restart" to pick up the update.')
|
|
9509
|
+
);
|
|
9510
|
+
}
|
|
9511
|
+
}
|
|
9157
9512
|
function reapAndReport(cwd, keepVersion) {
|
|
9158
9513
|
let reaped = [];
|
|
9159
9514
|
try {
|
|
@@ -9211,13 +9566,13 @@ function collectCandidates(artifact) {
|
|
|
9211
9566
|
return out2;
|
|
9212
9567
|
}
|
|
9213
9568
|
var defaultFixScanner = async (rootDir) => {
|
|
9214
|
-
const scratch =
|
|
9569
|
+
const scratch = path38.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
|
|
9215
9570
|
const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
|
|
9216
9571
|
const advanced = await loadAdvancedScanHook();
|
|
9217
9572
|
return runCoreScan(rootDir, scanOpts, advanced);
|
|
9218
9573
|
};
|
|
9219
9574
|
async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
|
|
9220
|
-
const artifactPath =
|
|
9575
|
+
const artifactPath = path38.isAbsolute(inFile) ? inFile : path38.join(rootDir, inFile);
|
|
9221
9576
|
if (await pathExists(artifactPath)) {
|
|
9222
9577
|
const staleness = scanStaleness(rootDir, artifactPath);
|
|
9223
9578
|
if (!staleness.stale) {
|
|
@@ -9244,7 +9599,7 @@ async function repositoryIdentity(rootDir, override) {
|
|
|
9244
9599
|
}
|
|
9245
9600
|
}
|
|
9246
9601
|
var fixCommand = new Command("fix").description("Get ranked, risk-tiered upgrade plans from the hosted planner and optionally apply them (prompts before changing files; --yes applies non-interactively, --dry-run previews, --no-apply only prints). Requires login/DSN.").argument("[path]", "Path to analyse", ".").option("--in <file>", "Scan artifact to read", ".vibgrate/scan_result.json").option("--format <format>", "Output format (text|json|md)", "text").option("--dsn <dsn>", 'DSN token (or use VIBGRATE_DSN env / "vg login")').option("--region <region>", "Override data residency region (us, eu)").option("--repository-name <name>", "Override the repository name recorded for this plan").option("--plan <tier>", "Apply a specific plan non-interactively (safe|balanced|aggressive)").option("--yes", "Apply the recommended plan without prompting").option("--dry-run", "Show what would change without applying").option("--no-apply", "Only print the plans; never modify the project").option("--fail-on-vulns <severity>", "Exit non-zero if the recommended plan leaves an advisory at/above this severity unresolved (low|moderate|high|critical)").action(async (targetPath, opts) => {
|
|
9247
|
-
const rootDir =
|
|
9602
|
+
const rootDir = path38.resolve(targetPath);
|
|
9248
9603
|
if (!await pathExists(rootDir)) {
|
|
9249
9604
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
9250
9605
|
process.exit(1);
|
|
@@ -9405,7 +9760,7 @@ function emit(report, format) {
|
|
|
9405
9760
|
}
|
|
9406
9761
|
}
|
|
9407
9762
|
function relProjectDir(rootDir, projectPath) {
|
|
9408
|
-
const rel =
|
|
9763
|
+
const rel = path38.isAbsolute(projectPath) ? path38.relative(rootDir, projectPath) : projectPath;
|
|
9409
9764
|
return rel === "" ? "." : rel;
|
|
9410
9765
|
}
|
|
9411
9766
|
async function buildTargetResolver(rootDir, artifact) {
|
|
@@ -10240,7 +10595,7 @@ function formatMarkdown(artifact) {
|
|
|
10240
10595
|
|
|
10241
10596
|
// src/reporting/commands/report.ts
|
|
10242
10597
|
var reportCommand = new Command("report").description("Generate a drift report from a scan artifact").option("--in <file>", "Input artifact file", ".vibgrate/scan_result.json").option("--format <format>", "Output format (md|text|json)", "text").action(async (opts) => {
|
|
10243
|
-
const artifactPath =
|
|
10598
|
+
const artifactPath = path38.resolve(opts.in);
|
|
10244
10599
|
if (!await pathExists(artifactPath)) {
|
|
10245
10600
|
console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
|
|
10246
10601
|
console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
|
|
@@ -10289,8 +10644,8 @@ function openUrl(url) {
|
|
|
10289
10644
|
// src/reporting/commands/login.ts
|
|
10290
10645
|
var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
10291
10646
|
function isInside(dir, file) {
|
|
10292
|
-
const rel =
|
|
10293
|
-
return !!rel && !rel.startsWith("..") && !
|
|
10647
|
+
const rel = path38.relative(dir, file);
|
|
10648
|
+
return !!rel && !rel.startsWith("..") && !path38.isAbsolute(rel);
|
|
10294
10649
|
}
|
|
10295
10650
|
var loginCommand = new Command("login").description("Authenticate the CLI with your Vibgrate workspace via the browser").option("--ingest <url>", "Ingest API URL (overrides --region)").option("--region <region>", `Data residency region (${availableRegionIds().join(", ")})`, "us").option("--no-browser", "Do not attempt to open a browser automatically").option(
|
|
10296
10651
|
"--local",
|
|
@@ -10545,7 +10900,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
10545
10900
|
try {
|
|
10546
10901
|
const statements = [];
|
|
10547
10902
|
if (opts.from) {
|
|
10548
|
-
const fromPath =
|
|
10903
|
+
const fromPath = path38.resolve(opts.from);
|
|
10549
10904
|
if (!await pathExists(fromPath)) {
|
|
10550
10905
|
process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
|
|
10551
10906
|
`));
|
|
@@ -10563,9 +10918,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
10563
10918
|
});
|
|
10564
10919
|
const json2 = JSON.stringify(doc, null, 2);
|
|
10565
10920
|
if (opts.out) {
|
|
10566
|
-
await writeTextFile(
|
|
10921
|
+
await writeTextFile(path38.resolve(opts.out), json2 + "\n");
|
|
10567
10922
|
process.stderr.write(
|
|
10568
|
-
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${
|
|
10923
|
+
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path38.resolve(opts.out)}
|
|
10569
10924
|
`
|
|
10570
10925
|
);
|
|
10571
10926
|
} else {
|
|
@@ -10748,7 +11103,7 @@ function formatDeltaText(base, current) {
|
|
|
10748
11103
|
return lines.join("\n");
|
|
10749
11104
|
}
|
|
10750
11105
|
async function readArtifactOrExit(filePath) {
|
|
10751
|
-
const absolutePath =
|
|
11106
|
+
const absolutePath = path38.resolve(filePath);
|
|
10752
11107
|
if (!await pathExists(absolutePath)) {
|
|
10753
11108
|
console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
|
|
10754
11109
|
process.exit(1);
|
|
@@ -10765,7 +11120,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
|
|
|
10765
11120
|
const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
|
|
10766
11121
|
const body = JSON.stringify(sbom, null, 2);
|
|
10767
11122
|
if (opts.out) {
|
|
10768
|
-
await writeTextFile(
|
|
11123
|
+
await writeTextFile(path38.resolve(opts.out), body);
|
|
10769
11124
|
console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
|
|
10770
11125
|
} else {
|
|
10771
11126
|
console.log(body);
|
|
@@ -10776,7 +11131,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
|
|
|
10776
11131
|
const current = await readArtifactOrExit(opts.to);
|
|
10777
11132
|
const report = formatDeltaText(base, current);
|
|
10778
11133
|
if (opts.out) {
|
|
10779
|
-
await writeTextFile(
|
|
11134
|
+
await writeTextFile(path38.resolve(opts.out), report);
|
|
10780
11135
|
console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
|
|
10781
11136
|
} else {
|
|
10782
11137
|
console.log(report);
|
|
@@ -10907,20 +11262,20 @@ function resolveRegime(id) {
|
|
|
10907
11262
|
return regime;
|
|
10908
11263
|
}
|
|
10909
11264
|
function evidenceDir(root2) {
|
|
10910
|
-
return
|
|
11265
|
+
return path38.join(root2, ".vibgrate", "evidence");
|
|
10911
11266
|
}
|
|
10912
11267
|
function orgPath(root2) {
|
|
10913
|
-
return
|
|
11268
|
+
return path38.join(evidenceDir(root2), "org.json");
|
|
10914
11269
|
}
|
|
10915
11270
|
function productsPath(root2) {
|
|
10916
|
-
return
|
|
11271
|
+
return path38.join(evidenceDir(root2), "products.json");
|
|
10917
11272
|
}
|
|
10918
11273
|
function releasesDir(root2) {
|
|
10919
|
-
return
|
|
11274
|
+
return path38.join(evidenceDir(root2), "releases");
|
|
10920
11275
|
}
|
|
10921
11276
|
function releasePath(root2, productId, version) {
|
|
10922
11277
|
const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
10923
|
-
return
|
|
11278
|
+
return path38.join(releasesDir(root2), `${safe}.json`);
|
|
10924
11279
|
}
|
|
10925
11280
|
var DEFAULT_ORG = {
|
|
10926
11281
|
responsiblePersons: [],
|
|
@@ -10951,7 +11306,7 @@ async function freezeRelease(root2, release) {
|
|
|
10951
11306
|
const p = releasePath(root2, release.productId, release.version);
|
|
10952
11307
|
if (await pathExists(p)) {
|
|
10953
11308
|
throw new CliError(
|
|
10954
|
-
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${
|
|
11309
|
+
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path38.relative(root2, p)} only if it was frozen in error`,
|
|
10955
11310
|
ExitCode.USAGE_ERROR
|
|
10956
11311
|
);
|
|
10957
11312
|
}
|
|
@@ -10965,15 +11320,15 @@ async function loadReleases(root2, productId) {
|
|
|
10965
11320
|
const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
|
|
10966
11321
|
const releases = [];
|
|
10967
11322
|
for (const f of files) {
|
|
10968
|
-
const rel = await readJsonFile(
|
|
11323
|
+
const rel = await readJsonFile(path38.join(dir, f));
|
|
10969
11324
|
if (!productId || rel.productId === productId) releases.push(rel);
|
|
10970
11325
|
}
|
|
10971
11326
|
return releases;
|
|
10972
11327
|
}
|
|
10973
11328
|
function coerce(version) {
|
|
10974
|
-
const parsed =
|
|
11329
|
+
const parsed = semver3__default.parse(version, { loose: true });
|
|
10975
11330
|
if (parsed) return parsed.version;
|
|
10976
|
-
const c2 =
|
|
11331
|
+
const c2 = semver3__default.coerce(version);
|
|
10977
11332
|
return c2 ? c2.version : null;
|
|
10978
11333
|
}
|
|
10979
11334
|
function versionAffected(version, range) {
|
|
@@ -10983,11 +11338,11 @@ function versionAffected(version, range) {
|
|
|
10983
11338
|
if (!range.introduced && !range.fixed && !range.versions) return false;
|
|
10984
11339
|
const introduced = range.introduced ? coerce(range.introduced) : "0.0.0";
|
|
10985
11340
|
if (!introduced) return false;
|
|
10986
|
-
if (
|
|
11341
|
+
if (semver3__default.lt(v, introduced)) return false;
|
|
10987
11342
|
if (range.fixed) {
|
|
10988
11343
|
const fixed = coerce(range.fixed);
|
|
10989
11344
|
if (!fixed) return false;
|
|
10990
|
-
if (
|
|
11345
|
+
if (semver3__default.gte(v, fixed)) return false;
|
|
10991
11346
|
}
|
|
10992
11347
|
return true;
|
|
10993
11348
|
}
|
|
@@ -11068,8 +11423,8 @@ function computeExposure(input) {
|
|
|
11068
11423
|
productName: product.name,
|
|
11069
11424
|
classification: product.classification,
|
|
11070
11425
|
status,
|
|
11071
|
-
affectedVersions: [...affectedVersions].sort(
|
|
11072
|
-
releases: affectedReleases.sort((a, b) =>
|
|
11426
|
+
affectedVersions: [...affectedVersions].sort(semver3__default.compareLoose),
|
|
11427
|
+
releases: affectedReleases.sort((a, b) => semver3__default.compareLoose(a.version, b.version)),
|
|
11073
11428
|
memberStates: product.memberStates,
|
|
11074
11429
|
supportStatus: support.status,
|
|
11075
11430
|
supportDetail: support.detail
|
|
@@ -11660,19 +12015,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
|
|
|
11660
12015
|
var DEFAULT_KEY = "attest-key.pem";
|
|
11661
12016
|
function resolveSigningKey(root2, explicit) {
|
|
11662
12017
|
const chosen = process.env.VG_ATTEST_KEY;
|
|
11663
|
-
const keyPath = chosen ?
|
|
12018
|
+
const keyPath = chosen ? path38.resolve(chosen) : path38.join(root2, ".vibgrate", DEFAULT_KEY);
|
|
11664
12019
|
let minted = false;
|
|
11665
|
-
if (!
|
|
12020
|
+
if (!fs8.existsSync(keyPath)) {
|
|
11666
12021
|
if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
|
|
11667
12022
|
const kp = generateKeypair();
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
12023
|
+
fs8.mkdirSync(path38.dirname(keyPath), { recursive: true });
|
|
12024
|
+
fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
|
|
12025
|
+
fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
|
|
11671
12026
|
minted = true;
|
|
11672
12027
|
}
|
|
11673
12028
|
let key2;
|
|
11674
12029
|
try {
|
|
11675
|
-
key2 = crypto3.createPrivateKey(
|
|
12030
|
+
key2 = crypto3.createPrivateKey(fs8.readFileSync(keyPath, "utf8"));
|
|
11676
12031
|
} catch {
|
|
11677
12032
|
throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
|
|
11678
12033
|
}
|
|
@@ -11683,16 +12038,16 @@ function resolveSigningKey(root2, explicit) {
|
|
|
11683
12038
|
}
|
|
11684
12039
|
function writeBundle(input) {
|
|
11685
12040
|
const dir = input.outDir;
|
|
11686
|
-
|
|
11687
|
-
const write = (rel, data) =>
|
|
12041
|
+
fs8.mkdirSync(path38.join(dir, "inputs", "releases"), { recursive: true });
|
|
12042
|
+
const write = (rel, data) => fs8.writeFileSync(path38.join(dir, rel), `${JSON.stringify(data, null, 2)}
|
|
11688
12043
|
`);
|
|
11689
12044
|
write("result.json", input.result);
|
|
11690
|
-
write(
|
|
12045
|
+
write(path38.join("inputs", "advisory.json"), input.advisory);
|
|
11691
12046
|
for (const rel of input.releases) {
|
|
11692
12047
|
const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
11693
|
-
write(
|
|
12048
|
+
write(path38.join("inputs", "releases", `${safe}.json`), rel);
|
|
11694
12049
|
}
|
|
11695
|
-
write(
|
|
12050
|
+
write(path38.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
|
|
11696
12051
|
write("provenance.json", {
|
|
11697
12052
|
method: "deterministic",
|
|
11698
12053
|
modelDrafted: [],
|
|
@@ -11708,13 +12063,13 @@ function writeBundle(input) {
|
|
|
11708
12063
|
disclaimer: input.regime.disclaimer
|
|
11709
12064
|
});
|
|
11710
12065
|
if (input.envelope) {
|
|
11711
|
-
|
|
12066
|
+
fs8.writeFileSync(path38.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
|
|
11712
12067
|
`);
|
|
11713
12068
|
}
|
|
11714
12069
|
if (input.timestampToken) {
|
|
11715
|
-
|
|
12070
|
+
fs8.writeFileSync(path38.join(dir, "timestamp.tsr"), input.timestampToken);
|
|
11716
12071
|
}
|
|
11717
|
-
|
|
12072
|
+
fs8.writeFileSync(path38.join(dir, "VERIFY.md"), verifyDoc(input));
|
|
11718
12073
|
return dir;
|
|
11719
12074
|
}
|
|
11720
12075
|
function verifyDoc(input) {
|
|
@@ -11775,13 +12130,13 @@ function undeterminedFields(result, regime) {
|
|
|
11775
12130
|
return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
|
|
11776
12131
|
}
|
|
11777
12132
|
async function recordDrill(root2, record) {
|
|
11778
|
-
const dir =
|
|
11779
|
-
const p =
|
|
12133
|
+
const dir = path38.join(evidenceDir(root2), "drills");
|
|
12134
|
+
const p = path38.join(dir, `${record.drillId}.json`);
|
|
11780
12135
|
await writeJsonFile(p, record);
|
|
11781
12136
|
return p;
|
|
11782
12137
|
}
|
|
11783
12138
|
async function hasRecentDrill(root2, asOf) {
|
|
11784
|
-
const dir =
|
|
12139
|
+
const dir = path38.join(evidenceDir(root2), "drills");
|
|
11785
12140
|
if (!await pathExists(dir)) return void 0;
|
|
11786
12141
|
const { readdir } = await import('fs/promises');
|
|
11787
12142
|
const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
|
|
@@ -11789,7 +12144,7 @@ async function hasRecentDrill(root2, asOf) {
|
|
|
11789
12144
|
if (files.length === 0) return void 0;
|
|
11790
12145
|
const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
|
|
11791
12146
|
for (const f of files) {
|
|
11792
|
-
const rec = await readJsonFile2(
|
|
12147
|
+
const rec = await readJsonFile2(path38.join(dir, f));
|
|
11793
12148
|
if (rec.ranAt >= cutoff) return true;
|
|
11794
12149
|
}
|
|
11795
12150
|
return false;
|
|
@@ -11869,7 +12224,7 @@ function formatRegimeList() {
|
|
|
11869
12224
|
|
|
11870
12225
|
// src/reporting/commands/evidence/index.ts
|
|
11871
12226
|
function root(opts) {
|
|
11872
|
-
return
|
|
12227
|
+
return path38.resolve(opts.cwd ?? process.cwd());
|
|
11873
12228
|
}
|
|
11874
12229
|
function slug(name) {
|
|
11875
12230
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
|
|
@@ -11957,7 +12312,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
11957
12312
|
const release = await buildRelease({
|
|
11958
12313
|
productId: product.id,
|
|
11959
12314
|
version,
|
|
11960
|
-
from:
|
|
12315
|
+
from: path38.resolve(rootDir, opts.from),
|
|
11961
12316
|
shipDate: opts.shipDate,
|
|
11962
12317
|
buildId: opts.buildId,
|
|
11963
12318
|
artefactDigest: opts.digest,
|
|
@@ -11965,7 +12320,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
11965
12320
|
frozenAt: nowIso()
|
|
11966
12321
|
});
|
|
11967
12322
|
const p = await freezeRelease(rootDir, release);
|
|
11968
|
-
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${
|
|
12323
|
+
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path38.relative(rootDir, p)}`);
|
|
11969
12324
|
});
|
|
11970
12325
|
async function runExposure(rootDir, vuln, opts) {
|
|
11971
12326
|
const org = await loadOrg(rootDir);
|
|
@@ -12017,7 +12372,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
12017
12372
|
console.log("\n" + buildPack(result, regime, org, stage));
|
|
12018
12373
|
}
|
|
12019
12374
|
if (opts.bundle) {
|
|
12020
|
-
const dir =
|
|
12375
|
+
const dir = path38.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
|
|
12021
12376
|
let envelope;
|
|
12022
12377
|
if (opts.sign !== false) {
|
|
12023
12378
|
const { key: key2, minted } = resolveSigningKey(rootDir);
|
|
@@ -12025,7 +12380,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
12025
12380
|
envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
|
|
12026
12381
|
}
|
|
12027
12382
|
writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
|
|
12028
|
-
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${
|
|
12383
|
+
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path38.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
|
|
12029
12384
|
}
|
|
12030
12385
|
process.exitCode = exposureExit(result.overallStatus);
|
|
12031
12386
|
});
|
|
@@ -12057,7 +12412,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
|
|
|
12057
12412
|
const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
|
|
12058
12413
|
const md = buildPack(result, regime, org, stage);
|
|
12059
12414
|
if (opts.out) {
|
|
12060
|
-
|
|
12415
|
+
fs8.writeFileSync(path38.resolve(rootDir, opts.out), md);
|
|
12061
12416
|
console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
|
|
12062
12417
|
} else {
|
|
12063
12418
|
console.log(md);
|
|
@@ -12099,20 +12454,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
|
|
|
12099
12454
|
}
|
|
12100
12455
|
});
|
|
12101
12456
|
var verifyCmd = new Command("verify").description("Verify an evidence bundle offline (no Vibgrate needed)").argument("<bundle>", "Path to an evidence bundle directory or evidence.intoto.jsonl").option("--pub <file>", "Public key PEM to pin the signer (establish trust)").action((bundlePath, opts) => {
|
|
12102
|
-
const abs =
|
|
12103
|
-
const envPath =
|
|
12104
|
-
if (!
|
|
12105
|
-
const envelope = JSON.parse(
|
|
12106
|
-
const resultPath =
|
|
12107
|
-
const result =
|
|
12108
|
-
const publicKeyPem = opts.pub ?
|
|
12457
|
+
const abs = path38.resolve(bundlePath);
|
|
12458
|
+
const envPath = fs8.statSync(abs).isDirectory() ? path38.join(abs, "evidence.intoto.jsonl") : abs;
|
|
12459
|
+
if (!fs8.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
|
|
12460
|
+
const envelope = JSON.parse(fs8.readFileSync(envPath, "utf8").trim().split("\n")[0]);
|
|
12461
|
+
const resultPath = path38.join(path38.dirname(envPath), "result.json");
|
|
12462
|
+
const result = fs8.existsSync(resultPath) ? JSON.parse(fs8.readFileSync(resultPath, "utf8")) : void 0;
|
|
12463
|
+
const publicKeyPem = opts.pub ? fs8.readFileSync(path38.resolve(opts.pub), "utf8") : void 0;
|
|
12109
12464
|
const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
|
|
12110
12465
|
const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
|
|
12111
12466
|
console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
|
|
12112
12467
|
if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
|
|
12113
|
-
const tsrPath =
|
|
12114
|
-
if (
|
|
12115
|
-
const t = verifyTimestamp(
|
|
12468
|
+
const tsrPath = path38.join(path38.dirname(envPath), "timestamp.tsr");
|
|
12469
|
+
if (fs8.existsSync(tsrPath) && result) {
|
|
12470
|
+
const t = verifyTimestamp(fs8.readFileSync(tsrPath), exposureSubjectDigest(result));
|
|
12116
12471
|
const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
|
|
12117
12472
|
console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
|
|
12118
12473
|
}
|
|
@@ -12179,12 +12534,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
|
|
|
12179
12534
|
const releases = [];
|
|
12180
12535
|
for (const list of releasesByProduct.values()) releases.push(...list);
|
|
12181
12536
|
const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
|
|
12182
|
-
const dir =
|
|
12183
|
-
await writeJsonFile(
|
|
12184
|
-
await writeJsonFile(
|
|
12185
|
-
for (const r of releases) await writeJsonFile(
|
|
12186
|
-
await writeJsonFile(
|
|
12187
|
-
console.error(chalk7.green("\u2714") + ` exported evidence state to ${
|
|
12537
|
+
const dir = path38.resolve(rootDir, opts.out);
|
|
12538
|
+
await writeJsonFile(path38.join(dir, "org.json"), org);
|
|
12539
|
+
await writeJsonFile(path38.join(dir, "products.json"), products);
|
|
12540
|
+
for (const r of releases) await writeJsonFile(path38.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
|
|
12541
|
+
await writeJsonFile(path38.join(dir, "readiness.json"), report);
|
|
12542
|
+
console.error(chalk7.green("\u2714") + ` exported evidence state to ${path38.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
|
|
12188
12543
|
});
|
|
12189
12544
|
var pushCmd = new Command("push").description("Push the product registry (and an optional exposure result) to Vibgrate Cloud").option(...cwdOption).option("--dsn <dsn>", "DSN token (or use VIBGRATE_DSN env / `vg login`)").option("--regime <id>", "Reporting regime").option("--result <file>", "An exposure result.json (or a bundle dir) to include").option("--signed", "Mark the included exposure result as signed").option("--strict", "Fail on push errors").action(async (opts) => {
|
|
12190
12545
|
const rootDir = root(opts);
|
|
@@ -12210,10 +12565,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
|
|
|
12210
12565
|
}));
|
|
12211
12566
|
let exposure;
|
|
12212
12567
|
if (opts.result) {
|
|
12213
|
-
const raw =
|
|
12214
|
-
const resultPath =
|
|
12215
|
-
if (!
|
|
12216
|
-
exposure = JSON.parse(
|
|
12568
|
+
const raw = path38.resolve(rootDir, opts.result);
|
|
12569
|
+
const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path38.join(raw, "result.json") : raw;
|
|
12570
|
+
if (!fs8.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
|
|
12571
|
+
exposure = JSON.parse(fs8.readFileSync(resultPath, "utf8"));
|
|
12217
12572
|
}
|
|
12218
12573
|
const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
|
|
12219
12574
|
const body = JSON.stringify(payload);
|
|
@@ -12403,7 +12758,7 @@ function dispatch(argv, cwd) {
|
|
|
12403
12758
|
}
|
|
12404
12759
|
const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
|
|
12405
12760
|
if (looksLikeQuestion) return ["ask", ...args];
|
|
12406
|
-
if (
|
|
12761
|
+
if (fs8.existsSync(path38.resolve(cwd, first))) {
|
|
12407
12762
|
return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
|
|
12408
12763
|
}
|
|
12409
12764
|
const moved = MOVED_COMMANDS[first];
|
|
@@ -12448,9 +12803,9 @@ async function main(argv = process.argv) {
|
|
|
12448
12803
|
}
|
|
12449
12804
|
function readCwd(raw) {
|
|
12450
12805
|
const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
|
|
12451
|
-
if (i >= 0 && raw[i + 1]) return
|
|
12806
|
+
if (i >= 0 && raw[i + 1]) return path38.resolve(raw[i + 1]);
|
|
12452
12807
|
const eq = raw.find((a) => a.startsWith("--cwd="));
|
|
12453
|
-
if (eq) return
|
|
12808
|
+
if (eq) return path38.resolve(eq.slice("--cwd=".length));
|
|
12454
12809
|
return process.cwd();
|
|
12455
12810
|
}
|
|
12456
12811
|
function handleError(err) {
|