@vibgrate/cli 2026.718.2 → 2026.720.1
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 +2 -0
- package/dist/baseline-5QPV6API.js +6 -0
- package/dist/{baseline-DKPQWOQ6.js.map → baseline-5QPV6API.js.map} +1 -1
- package/dist/{chunk-RME7BFMU.js → chunk-AJDUMRVI.js} +3 -3
- package/dist/{chunk-RME7BFMU.js.map → chunk-AJDUMRVI.js.map} +1 -1
- package/dist/{chunk-H5M7CXE6.js → chunk-VQLOVQZP.js} +45 -20
- package/dist/chunk-VQLOVQZP.js.map +1 -0
- package/dist/{chunk-BFXDF6ZE.js → chunk-VYSTOEAK.js} +3 -3
- package/dist/{chunk-BFXDF6ZE.js.map → chunk-VYSTOEAK.js.map} +1 -1
- package/dist/cli.js +256 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +115 -45
- package/dist/index.js +2 -2
- package/package.json +3 -1
- package/dist/baseline-DKPQWOQ6.js +0 -6
- package/dist/chunk-H5M7CXE6.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, CliError, ExitCode, NPX_INVOCATION, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, recordCliCall, CLI_TOOL_ALIASES, countPending, resolveOne, indexFor, countTokens, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, serveStdio, ASSISTANTS, detectAssistants, usageError, loadGraph, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, readUsage, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, epistemicBreakdown, cacheDir, probeFreshness, discover, vibgrateDir, modelCacheInfo, clearModelCache, GraphSource, createServer, assistantById, serializeGraph, resolveLimits, loadCatalog, driftFor, addLibrary, parseDsn as parseDsn$1, publishPrivateLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, formatForExt, hostedBase, verifyDeterminism, renderHtml, isModelReady, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-
|
|
2
|
+
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, CliError, ExitCode, NPX_INVOCATION, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, recordCliCall, CLI_TOOL_ALIASES, countPending, resolveOne, indexFor, countTokens, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, serveStdio, ASSISTANTS, detectAssistants, usageError, loadGraph, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, readUsage, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, epistemicBreakdown, cacheDir, probeFreshness, discover, vibgrateDir, modelCacheInfo, clearModelCache, GraphSource, createServer, assistantById, serializeGraph, resolveLimits, loadCatalog, driftFor, addLibrary, parseDsn as parseDsn$1, publishPrivateLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, formatForExt, hostedBase, verifyDeterminism, renderHtml, isModelReady, SAVINGS_TOOLS, DEFAULT_RATE_LABEL, readStoredCredentials, projectCredentialsPath, DEFAULT_RATE_PER_M, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-VQLOVQZP.js';
|
|
3
3
|
import { resolvedGrammarFiles, grammarSetVersion, hashString, canonicalize, hashBytes } from './chunk-VFO5UDAT.js';
|
|
4
|
-
import { loadAdvancedScanHook, baselineCommand } from './chunk-
|
|
5
|
-
import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, brandProgressBar, resolveHead, workingTreeDirty } from './chunk-
|
|
4
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-VYSTOEAK.js';
|
|
5
|
+
import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, brandProgressBar, resolveHead, workingTreeDirty } from './chunk-AJDUMRVI.js';
|
|
6
6
|
import './chunk-RXP66R2E.js';
|
|
7
7
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
|
|
8
8
|
import * as fs8 from 'fs';
|
|
@@ -288,21 +288,23 @@ var ROBOT = [
|
|
|
288
288
|
" " + c.dim("\u2524") + teal("\u2502") + " " + c.dim("\u2581\u2581") + " " + teal("\u2502") + c.dim("\u251C"),
|
|
289
289
|
" " + teal("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F")
|
|
290
290
|
];
|
|
291
|
-
function logoLines(root) {
|
|
291
|
+
function logoLines(root, opts = {}) {
|
|
292
|
+
const product = opts.product ?? "Graph";
|
|
293
|
+
const tagline = opts.tagline ?? "Code Intelligence Engine";
|
|
292
294
|
return [
|
|
293
295
|
"",
|
|
294
296
|
` ${ROBOT[0]}`,
|
|
295
297
|
` ${ROBOT[1]}`,
|
|
296
298
|
` ${ROBOT[2]}`,
|
|
297
299
|
` ${ROBOT[3]}`,
|
|
298
|
-
` ${c.bold.white("Vibgrate")} ${teal(
|
|
300
|
+
` ${c.bold.white("Vibgrate")} ${teal(product)} ${c.dim(`\xB7 ${tagline} \xB7 v${VERSION}`)}`,
|
|
299
301
|
...root ? [` ${c.dim(root)}`] : [],
|
|
300
302
|
""
|
|
301
303
|
];
|
|
302
304
|
}
|
|
303
|
-
function printLogo(root) {
|
|
305
|
+
function printLogo(root, opts = {}) {
|
|
304
306
|
if (!process.stderr.isTTY) return;
|
|
305
|
-
process.stderr.write(`${logoLines(root).join("\n")}
|
|
307
|
+
process.stderr.write(`${logoLines(root, opts).join("\n")}
|
|
306
308
|
`);
|
|
307
309
|
}
|
|
308
310
|
|
|
@@ -1508,6 +1510,220 @@ function isLoopbackOrigin(origin) {
|
|
|
1508
1510
|
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
1509
1511
|
}
|
|
1510
1512
|
|
|
1513
|
+
// src/mcp/serve-stats.ts
|
|
1514
|
+
function zeroRow(key2) {
|
|
1515
|
+
return { key: key2, calls: 0, complete: 0, partial: 0, miss: 0, totalMs: 0, vgTokens: 0, baselineTokens: 0 };
|
|
1516
|
+
}
|
|
1517
|
+
var SessionStats = class {
|
|
1518
|
+
startedAt;
|
|
1519
|
+
revision = 0;
|
|
1520
|
+
lastCallAt = null;
|
|
1521
|
+
totals = zeroRow("total");
|
|
1522
|
+
byClient = /* @__PURE__ */ new Map();
|
|
1523
|
+
byTool = /* @__PURE__ */ new Map();
|
|
1524
|
+
constructor(now2 = Date.now()) {
|
|
1525
|
+
this.startedAt = now2;
|
|
1526
|
+
}
|
|
1527
|
+
record(sample, now2 = Date.now()) {
|
|
1528
|
+
this.revision++;
|
|
1529
|
+
this.lastCallAt = now2;
|
|
1530
|
+
for (const row of [this.totals, this.rowFor(this.byClient, sample.client), this.rowFor(this.byTool, sample.tool)]) {
|
|
1531
|
+
row.calls++;
|
|
1532
|
+
row[sample.outcome]++;
|
|
1533
|
+
row.totalMs += sample.ms;
|
|
1534
|
+
row.vgTokens += sample.vgTokens;
|
|
1535
|
+
row.baselineTokens += sample.baselineTokens;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
snapshot() {
|
|
1539
|
+
const sorted = (m) => [...m.values()].map((r) => ({ ...r })).sort((a, b) => b.calls - a.calls || a.key.localeCompare(b.key));
|
|
1540
|
+
return {
|
|
1541
|
+
startedAt: this.startedAt,
|
|
1542
|
+
revision: this.revision,
|
|
1543
|
+
lastCallAt: this.lastCallAt,
|
|
1544
|
+
totals: { ...this.totals },
|
|
1545
|
+
clients: sorted(this.byClient),
|
|
1546
|
+
tools: sorted(this.byTool)
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
rowFor(m, key2) {
|
|
1550
|
+
let row = m.get(key2);
|
|
1551
|
+
if (!row) {
|
|
1552
|
+
row = zeroRow(key2);
|
|
1553
|
+
m.set(key2, row);
|
|
1554
|
+
}
|
|
1555
|
+
return row;
|
|
1556
|
+
}
|
|
1557
|
+
};
|
|
1558
|
+
function fmtUptime(ms) {
|
|
1559
|
+
const s = Math.max(0, Math.floor(ms / 1e3));
|
|
1560
|
+
if (s < 60) return `${s}s`;
|
|
1561
|
+
const m = Math.floor(s / 60);
|
|
1562
|
+
if (m < 60) return `${m}m ${String(s % 60).padStart(2, "0")}s`;
|
|
1563
|
+
const h = Math.floor(m / 60);
|
|
1564
|
+
if (h < 24) return `${h}h ${String(m % 60).padStart(2, "0")}m`;
|
|
1565
|
+
const d = Math.floor(h / 24);
|
|
1566
|
+
return `${d}d ${String(h % 24).padStart(2, "0")}h`;
|
|
1567
|
+
}
|
|
1568
|
+
function fmtTokens(n) {
|
|
1569
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(2)}M`;
|
|
1570
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
1571
|
+
return String(n);
|
|
1572
|
+
}
|
|
1573
|
+
function fmtAvgMs(row) {
|
|
1574
|
+
if (row.calls === 0) return "\u2014";
|
|
1575
|
+
const avg = row.totalMs / row.calls;
|
|
1576
|
+
return avg >= 1e3 ? `${(avg / 1e3).toFixed(1)}s` : `${Math.round(avg)}ms`;
|
|
1577
|
+
}
|
|
1578
|
+
var teal2 = (s) => c.hex("#3FB0A4")(s);
|
|
1579
|
+
var mint2 = (s) => c.hex("#4FE3C1")(s);
|
|
1580
|
+
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1581
|
+
var MAX_TOOL_ROWS = 8;
|
|
1582
|
+
function serveStatusLines(snap, now2, tick = 0) {
|
|
1583
|
+
const spinner = mint2(SPINNER[tick % SPINNER.length]);
|
|
1584
|
+
const up = fmtUptime(now2 - snap.startedAt);
|
|
1585
|
+
const lines = [];
|
|
1586
|
+
if (snap.totals.calls === 0) {
|
|
1587
|
+
lines.push(
|
|
1588
|
+
` ${spinner} ${c.bold.white("vg serve")} ${c.dim("\xB7")} up ${teal2(up)} ${c.dim("\xB7 waiting for your assistant\u2019s first tool call\u2026")}`
|
|
1589
|
+
);
|
|
1590
|
+
return lines;
|
|
1591
|
+
}
|
|
1592
|
+
const t = snap.totals;
|
|
1593
|
+
const answered = Math.round((t.complete + t.partial) / t.calls * 100);
|
|
1594
|
+
const ago = snap.lastCallAt === null ? "" : c.dim(` \xB7 last call ${fmtUptime(now2 - snap.lastCallAt)} ago`);
|
|
1595
|
+
lines.push(
|
|
1596
|
+
` ${spinner} ${c.bold.white("vg serve")} ${c.dim("\xB7")} up ${teal2(up)} ${c.dim("\xB7")} ${c.bold.white(String(t.calls))} call${t.calls === 1 ? "" : "s"} ${c.dim("\xB7")} ${mint2(`${answered}%`)} answered${ago}`
|
|
1597
|
+
);
|
|
1598
|
+
lines.push(
|
|
1599
|
+
` ${c.dim("clients")} ` + snap.clients.map((cl) => `${c.white(cl.key)} ${teal2(String(cl.calls))}${c.dim(` (avg ${fmtAvgMs(cl)})`)}`).join(c.dim(" \xB7 "))
|
|
1600
|
+
);
|
|
1601
|
+
const shown = snap.tools.slice(0, MAX_TOOL_ROWS);
|
|
1602
|
+
const nameW = Math.max(...shown.map((r) => r.key.length));
|
|
1603
|
+
for (const row of shown) {
|
|
1604
|
+
let line = ` ${c.white(row.key.padEnd(nameW))} ${teal2(String(row.calls).padStart(4))} ${c.dim("\xB7")} ` + c.dim(`avg ${fmtAvgMs(row)}`);
|
|
1605
|
+
if (SAVINGS_TOOLS.has(row.key) && row.baselineTokens > 0) {
|
|
1606
|
+
line += c.dim(" \xB7 ctx ") + c.white(fmtTokens(row.vgTokens)) + c.dim(` vs \u2248${fmtTokens(row.baselineTokens)} grep/read`);
|
|
1607
|
+
}
|
|
1608
|
+
if (row.miss > 0) line += c.dim(" \xB7 ") + c.yellow(`${row.miss} miss`);
|
|
1609
|
+
lines.push(line);
|
|
1610
|
+
}
|
|
1611
|
+
if (snap.tools.length > shown.length) {
|
|
1612
|
+
lines.push(` ${c.dim(`\u2026 +${snap.tools.length - shown.length} more tools`)}`);
|
|
1613
|
+
}
|
|
1614
|
+
if (t.baselineTokens > 0) {
|
|
1615
|
+
const savedTokens = Math.max(0, t.baselineTokens - t.vgTokens);
|
|
1616
|
+
const savedUsd = savedTokens / 1e6 * DEFAULT_RATE_PER_M;
|
|
1617
|
+
const ratio = t.vgTokens > 0 ? (t.baselineTokens / t.vgTokens).toFixed(1) : "\u2014";
|
|
1618
|
+
lines.push(
|
|
1619
|
+
` ${c.dim("session")} ctx ${c.bold.white(fmtTokens(t.vgTokens))} ` + c.dim(`vs grep/read \u2248${fmtTokens(t.baselineTokens)} \u2192 `) + mint2(`${ratio}\xD7 fewer`)
|
|
1620
|
+
);
|
|
1621
|
+
lines.push(
|
|
1622
|
+
` ${c.dim("est. saved \u2248")} ${mint2(`${fmtTokens(savedTokens)} tokens ($${savedUsd.toFixed(2)})`)} ` + c.dim(`(${DEFAULT_RATE_LABEL}; estimate)`)
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
return lines;
|
|
1626
|
+
}
|
|
1627
|
+
function serveHeartbeatLine(snap, now2) {
|
|
1628
|
+
const up = fmtUptime(now2 - snap.startedAt);
|
|
1629
|
+
const t = snap.totals;
|
|
1630
|
+
if (t.calls === 0) return c.dim(`vg \xB7 serving for ${up} \u2014 no tool calls yet`);
|
|
1631
|
+
const clients = snap.clients.map((cl) => `${cl.key} ${cl.calls}`).join(", ");
|
|
1632
|
+
let line = `vg \xB7 serving for ${up} \u2014 ${t.calls} call${t.calls === 1 ? "" : "s"} (${clients})`;
|
|
1633
|
+
if (t.baselineTokens > 0) {
|
|
1634
|
+
const savedTokens = Math.max(0, t.baselineTokens - t.vgTokens);
|
|
1635
|
+
line += ` \xB7 ctx ${fmtTokens(t.vgTokens)} vs \u2248${fmtTokens(t.baselineTokens)} grep/read \xB7 est. saved \u2248 ${fmtTokens(savedTokens)} tokens`;
|
|
1636
|
+
}
|
|
1637
|
+
return c.dim(line);
|
|
1638
|
+
}
|
|
1639
|
+
var TTY_INTERVAL_MS = 1e3;
|
|
1640
|
+
var HEARTBEAT_INTERVAL_MS = 15 * 60 * 1e3;
|
|
1641
|
+
var ServeStatusDisplay = class {
|
|
1642
|
+
constructor(stats, stream = process.stderr) {
|
|
1643
|
+
this.stats = stats;
|
|
1644
|
+
this.stream = stream;
|
|
1645
|
+
this.isTTY = (stream.isTTY ?? false) && process.env.VIBGRATE_PROGRESS_MODE !== "plain";
|
|
1646
|
+
}
|
|
1647
|
+
stats;
|
|
1648
|
+
stream;
|
|
1649
|
+
timer = null;
|
|
1650
|
+
tick = 0;
|
|
1651
|
+
lastRowCount = 0;
|
|
1652
|
+
lastFrame = "";
|
|
1653
|
+
lastHeartbeatRevision = -1;
|
|
1654
|
+
cursorHidden = false;
|
|
1655
|
+
isTTY;
|
|
1656
|
+
start() {
|
|
1657
|
+
if (this.timer) return;
|
|
1658
|
+
if (this.isTTY) {
|
|
1659
|
+
this.hideCursor();
|
|
1660
|
+
process.on("exit", this.restoreCursor);
|
|
1661
|
+
process.once("SIGINT", () => {
|
|
1662
|
+
this.restoreCursor();
|
|
1663
|
+
process.exit(130);
|
|
1664
|
+
});
|
|
1665
|
+
process.once("SIGTERM", () => {
|
|
1666
|
+
this.restoreCursor();
|
|
1667
|
+
process.exit(143);
|
|
1668
|
+
});
|
|
1669
|
+
this.timer = setInterval(() => this.renderTTY(), TTY_INTERVAL_MS);
|
|
1670
|
+
this.renderTTY();
|
|
1671
|
+
} else {
|
|
1672
|
+
this.timer = setInterval(() => this.renderHeartbeat(), HEARTBEAT_INTERVAL_MS);
|
|
1673
|
+
}
|
|
1674
|
+
this.timer.unref?.();
|
|
1675
|
+
}
|
|
1676
|
+
stop() {
|
|
1677
|
+
if (this.timer) {
|
|
1678
|
+
clearInterval(this.timer);
|
|
1679
|
+
this.timer = null;
|
|
1680
|
+
}
|
|
1681
|
+
if (this.isTTY) {
|
|
1682
|
+
let buf = "";
|
|
1683
|
+
if (this.lastRowCount > 0) buf += `\x1B[${this.lastRowCount}A\x1B[J`;
|
|
1684
|
+
this.stream.write(buf);
|
|
1685
|
+
this.lastRowCount = 0;
|
|
1686
|
+
this.restoreCursor();
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
renderTTY() {
|
|
1690
|
+
this.tick++;
|
|
1691
|
+
const lines = serveStatusLines(this.stats.snapshot(), Date.now(), this.tick);
|
|
1692
|
+
const content = lines.join("\n") + "\n";
|
|
1693
|
+
if (content === this.lastFrame) return;
|
|
1694
|
+
this.lastFrame = content;
|
|
1695
|
+
let buf = "";
|
|
1696
|
+
if (this.lastRowCount > 0) buf += `\x1B[${this.lastRowCount}A\x1B[J`;
|
|
1697
|
+
buf += content;
|
|
1698
|
+
this.stream.write(buf);
|
|
1699
|
+
this.lastRowCount = this.countRows(lines);
|
|
1700
|
+
}
|
|
1701
|
+
renderHeartbeat() {
|
|
1702
|
+
const snap = this.stats.snapshot();
|
|
1703
|
+
if (snap.revision === this.lastHeartbeatRevision) return;
|
|
1704
|
+
this.lastHeartbeatRevision = snap.revision;
|
|
1705
|
+
this.stream.write(serveHeartbeatLine(snap, Date.now()) + "\n");
|
|
1706
|
+
}
|
|
1707
|
+
/** Terminal rows the frame occupies, accounting for line wrap. */
|
|
1708
|
+
countRows(lines) {
|
|
1709
|
+
const columns = Math.max(this.stream.columns ?? 80, 20);
|
|
1710
|
+
return lines.reduce((total, line) => {
|
|
1711
|
+
const visible = line.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
1712
|
+
return total + Math.max(1, Math.ceil(visible / columns));
|
|
1713
|
+
}, 0);
|
|
1714
|
+
}
|
|
1715
|
+
hideCursor() {
|
|
1716
|
+
if (this.cursorHidden) return;
|
|
1717
|
+
this.stream.write("\x1B[?25l");
|
|
1718
|
+
this.cursorHidden = true;
|
|
1719
|
+
}
|
|
1720
|
+
restoreCursor = () => {
|
|
1721
|
+
if (!this.cursorHidden) return;
|
|
1722
|
+
this.stream.write("\x1B[?25h");
|
|
1723
|
+
this.cursorHidden = false;
|
|
1724
|
+
};
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1511
1727
|
// src/commands/serve.ts
|
|
1512
1728
|
var SHARE_FLUSH_INTERVAL_MS = 5 * 60 * 1e3;
|
|
1513
1729
|
function registerServe(program) {
|
|
@@ -1519,6 +1735,11 @@ function registerServe(program) {
|
|
|
1519
1735
|
const local = global.local === true;
|
|
1520
1736
|
const optOut = telemetryOptOut();
|
|
1521
1737
|
const shareStats = opts.shareStats === true && !local && optOut === null;
|
|
1738
|
+
const quiet = global.quiet === true;
|
|
1739
|
+
const stats = quiet ? void 0 : new SessionStats();
|
|
1740
|
+
if (!quiet) {
|
|
1741
|
+
printLogo(root, { product: "AI Context", tagline: "Local-first MCP for your AI" });
|
|
1742
|
+
}
|
|
1522
1743
|
const serveOpts = {
|
|
1523
1744
|
// A *requested* --share-stats always implies local recording, even when
|
|
1524
1745
|
// the upload itself is suppressed (--local / env opt-out) — the local
|
|
@@ -1528,7 +1749,8 @@ function registerServe(program) {
|
|
|
1528
1749
|
shareStats,
|
|
1529
1750
|
local,
|
|
1530
1751
|
dedup: opts.dedup === true,
|
|
1531
|
-
refresh
|
|
1752
|
+
refresh,
|
|
1753
|
+
stats
|
|
1532
1754
|
};
|
|
1533
1755
|
await ensureServableGraph(root, graphPath, global, refresh);
|
|
1534
1756
|
if (opts.shareStats === true && local) {
|
|
@@ -1537,12 +1759,14 @@ function registerServe(program) {
|
|
|
1537
1759
|
info(c.dim(`vg \xB7 --share-stats disabled by ${optOut}: recording locally, not uploading.`));
|
|
1538
1760
|
}
|
|
1539
1761
|
if (shareStats) startSharing(root);
|
|
1762
|
+
const display = stats ? new ServeStatusDisplay(stats) : void 0;
|
|
1540
1763
|
const freshness = refresh ? "auto-refresh" : "as built";
|
|
1541
1764
|
if (opts.http) {
|
|
1542
|
-
await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness);
|
|
1765
|
+
await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness, () => display?.start());
|
|
1543
1766
|
} else {
|
|
1544
1767
|
info(c.dim(`vg \xB7 MCP server on stdio (read-only, ${freshness}). Connect your assistant to this process.`));
|
|
1545
1768
|
await serveStdio(graphPath, serveOpts);
|
|
1769
|
+
display?.start();
|
|
1546
1770
|
}
|
|
1547
1771
|
});
|
|
1548
1772
|
applyGlobalOptions(cmd);
|
|
@@ -1598,7 +1822,7 @@ function startSharing(root) {
|
|
|
1598
1822
|
});
|
|
1599
1823
|
process.once("beforeExit", finalFlush);
|
|
1600
1824
|
}
|
|
1601
|
-
async function serveHttp(graphPath, host, port, opts, freshness) {
|
|
1825
|
+
async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
|
|
1602
1826
|
const { createServer: createHttp } = await import('http');
|
|
1603
1827
|
const { StreamableHTTPServerTransport } = await import('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
1604
1828
|
const source = new GraphSource(graphPath, opts.refresh !== false);
|
|
@@ -1630,6 +1854,7 @@ async function serveHttp(graphPath, host, port, opts, freshness) {
|
|
|
1630
1854
|
});
|
|
1631
1855
|
await new Promise((resolve17) => httpServer.listen(port, host, resolve17));
|
|
1632
1856
|
info(c.dim(`vg \xB7 MCP server on http://${host}:${port}/mcp (read-only, local, ${freshness})`));
|
|
1857
|
+
onReady?.();
|
|
1633
1858
|
await new Promise(() => {
|
|
1634
1859
|
});
|
|
1635
1860
|
}
|
|
@@ -3558,17 +3783,18 @@ function printBreakdown(usage) {
|
|
|
3558
3783
|
info("");
|
|
3559
3784
|
info(c.bold(" by command") + c.dim(" (complete = full result \xB7 partial = capped/paginated \xB7 miss = no result)"));
|
|
3560
3785
|
const nameW = Math.max(7, ...usage.commands.map((cmd) => cmd.tool.length));
|
|
3561
|
-
const header = " " + "command".padEnd(nameW) + ["calls", "complete", "partial", "miss", "success%"].map((h) => h.padStart(9)).join("");
|
|
3786
|
+
const header = " " + "command".padEnd(nameW) + ["calls", "complete", "partial", "miss", "success%", "avg ms"].map((h) => h.padStart(9)).join("");
|
|
3562
3787
|
info(c.dim(header));
|
|
3563
3788
|
for (const cmd of usage.commands) {
|
|
3564
3789
|
info(
|
|
3565
|
-
" " + cmd.tool.padEnd(nameW) + String(cmd.calls).padStart(9) + String(cmd.complete).padStart(9) + String(cmd.partial).padStart(9) + String(cmd.miss).padStart(9) + `${cmd.successPct}%`.padStart(9)
|
|
3790
|
+
" " + cmd.tool.padEnd(nameW) + String(cmd.calls).padStart(9) + String(cmd.complete).padStart(9) + String(cmd.partial).padStart(9) + String(cmd.miss).padStart(9) + `${cmd.successPct}%`.padStart(9) + // Absent ≠ zero: calls recorded before timing existed show '—'.
|
|
3791
|
+
(cmd.avgMs === null ? "\u2014" : String(cmd.avgMs)).padStart(9)
|
|
3566
3792
|
);
|
|
3567
3793
|
}
|
|
3568
3794
|
const t = usage.totals;
|
|
3569
|
-
info(c.dim(" " + "\u2500".repeat(nameW +
|
|
3795
|
+
info(c.dim(" " + "\u2500".repeat(nameW + 54)));
|
|
3570
3796
|
info(
|
|
3571
|
-
" " + c.bold("total".padEnd(nameW)) + String(t.calls).padStart(9) + String(t.complete).padStart(9) + String(t.partial).padStart(9) + String(t.miss).padStart(9) + "".padStart(9)
|
|
3797
|
+
" " + c.bold("total".padEnd(nameW)) + String(t.calls).padStart(9) + String(t.complete).padStart(9) + String(t.partial).padStart(9) + String(t.miss).padStart(9) + "".padStart(9) + "".padStart(9)
|
|
3572
3798
|
);
|
|
3573
3799
|
info(c.dim(` avg success across commands: ${usage.avgSuccessPct}%`));
|
|
3574
3800
|
}
|
|
@@ -3994,7 +4220,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
3994
4220
|
console.log(chalk8.green("\u2714") + ` Created ${chalk8.bold("vibgrate.config.ts")}`);
|
|
3995
4221
|
}
|
|
3996
4222
|
if (opts.baseline) {
|
|
3997
|
-
const { runBaseline } = await import('./baseline-
|
|
4223
|
+
const { runBaseline } = await import('./baseline-5QPV6API.js');
|
|
3998
4224
|
await runBaseline(rootDir);
|
|
3999
4225
|
}
|
|
4000
4226
|
console.log("");
|
|
@@ -4299,22 +4525,22 @@ async function detectAiAssistant(rootDir) {
|
|
|
4299
4525
|
return null;
|
|
4300
4526
|
}
|
|
4301
4527
|
function printAiContextPrompt(detectedAssistant) {
|
|
4302
|
-
const
|
|
4303
|
-
const
|
|
4528
|
+
const teal3 = chalk8.hex("#3FB0A4");
|
|
4529
|
+
const mint3 = chalk8.hex("#4FE3C1");
|
|
4304
4530
|
const cli = resolveCliInvocation();
|
|
4305
4531
|
const installArgs = detectedAssistant ? `install ${detectedAssistant}` : "install --all";
|
|
4306
4532
|
const installCmd = `${cli} ${installArgs}`;
|
|
4307
4533
|
const detectedNote = detectedAssistant ? chalk8.dim(` (${detectedAssistant} config detected)`) : "";
|
|
4308
4534
|
console.log("");
|
|
4309
|
-
console.log(
|
|
4310
|
-
console.log(
|
|
4311
|
-
console.log(
|
|
4535
|
+
console.log(teal3(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
|
|
4536
|
+
console.log(teal3(" \u2502") + " " + mint3("\u25C6") + " " + chalk8.bold.white("Get AI-aware answers in your editor") + " " + teal3("\u2502"));
|
|
4537
|
+
console.log(teal3(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
|
|
4312
4538
|
console.log("");
|
|
4313
4539
|
console.log(" " + chalk8.bold.white(installCmd) + detectedNote);
|
|
4314
4540
|
console.log("");
|
|
4315
|
-
console.log(" " +
|
|
4316
|
-
console.log(" " +
|
|
4317
|
-
console.log(" " +
|
|
4541
|
+
console.log(" " + teal3("\xB7") + " " + chalk8.white("Code map in your assistant") + chalk8.dim(" \u2014 call trees, impact surfaces, import paths"));
|
|
4542
|
+
console.log(" " + teal3("\xB7") + " " + chalk8.white("Offline drift") + chalk8.dim(" \u2014 DriftScore and upgrade priorities, right inside your editor"));
|
|
4543
|
+
console.log(" " + teal3("\xB7") + " " + chalk8.white("Version-correct library docs") + chalk8.dim(" \u2014 pinned to your lockfile, no hallucinated APIs"));
|
|
4318
4544
|
console.log("");
|
|
4319
4545
|
}
|
|
4320
4546
|
|
|
@@ -5840,15 +6066,15 @@ Applied the ${chosen.label} plan:`));
|
|
|
5840
6066
|
}
|
|
5841
6067
|
function formatText(artifact) {
|
|
5842
6068
|
const lines = [];
|
|
5843
|
-
const
|
|
5844
|
-
const
|
|
6069
|
+
const teal3 = chalk8.hex("#3FB0A4");
|
|
6070
|
+
const mint3 = chalk8.hex("#4FE3C1");
|
|
5845
6071
|
lines.push("");
|
|
5846
|
-
lines.push(" " +
|
|
5847
|
-
lines.push(" " + chalk8.dim("\u2524") +
|
|
5848
|
-
lines.push(" " + chalk8.dim("\u2524") +
|
|
5849
|
-
lines.push(" " +
|
|
6072
|
+
lines.push(" " + teal3("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u256E") + mint3("\u279C"));
|
|
6073
|
+
lines.push(" " + chalk8.dim("\u2524") + teal3("\u2502") + " " + mint3("\u25FC") + " " + mint3("\u25FC") + " " + teal3("\u2502") + chalk8.dim("\u251C") + " " + chalk8.bold.white("vibgrate"));
|
|
6074
|
+
lines.push(" " + chalk8.dim("\u2524") + teal3("\u2502") + " " + chalk8.dim("\u2581\u2581") + " " + teal3("\u2502") + chalk8.dim("\u251C") + " " + chalk8.dim(`Code Intelligence Engine v${VERSION}`));
|
|
6075
|
+
lines.push(" " + teal3("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
|
|
5850
6076
|
lines.push("");
|
|
5851
|
-
lines.push(...titleBox("Vibgrate Drift Report",
|
|
6077
|
+
lines.push(...titleBox("Vibgrate Drift Report", teal3));
|
|
5852
6078
|
lines.push("");
|
|
5853
6079
|
for (const project of artifact.projects) {
|
|
5854
6080
|
lines.push(chalk8.bold(` \u2500\u2500 ${project.name} `) + chalk8.dim(`(${project.type}) ${project.path}`));
|