First Try: QVAC (QuantumVerse Automatic Computer)
CI / test (push) Successful in 1m8s
Release rolling / release (push) Successful in 8m25s

This commit is contained in:
Raven Scott
2026-07-30 13:42:14 -04:00
parent f52168feb9
commit 32928f19bd
27 changed files with 2893 additions and 2 deletions
+139
View File
@@ -0,0 +1,139 @@
/**
* Lightweight local RAG for QVAC — no native embeddings required.
* Keyword retrieval over guide snippets + live chart catalog.
*/
/** Built-in operator knowledge (subset of user-guide). */
const GUIDE_DOCS = [
{
id: 'guide:connect',
title: 'Connect',
text: 'Connect to a PearData agent with public key or pd1 invite. Viewer vs operator vs admin roles. Saved bookmarks restore agents. Active peer is used by all tools.',
},
{
id: 'guide:charts',
title: 'Charts',
text: 'Metrics wall with sections TOC, play pause, time presets 1m 5m 15m 1h 6h, pin board, correlate brush, related metrics, chart types line area stacked bar pie, dimension legend.',
},
{
id: 'guide:alerts',
title: 'Alerts',
text: 'Anomaly list with severity warning critical, Show jumps to chart, Correlate opens metric correlations around event time, silence TTL re-enables.',
},
{
id: 'guide:processes',
title: 'Processes',
text: 'Live process table from /proc when PEARDATA_PROCESSES=1, sort by cpu rss, tree view, CSV export, open top process charts.',
},
{
id: 'guide:logs',
title: 'Logs',
text: 'System logs journal default, anomalies source, audit admin, follow stream, search unit priority.',
},
{
id: 'guide:retention',
title: 'Data retention',
text: 'Settings Data Manager hot tier0 warm tier1 HyperDB prune age disk budget. Longer chart windows may be sparse until samples accumulate.',
},
{
id: 'guide:qvac',
title: 'QVAC',
text: 'Local AI copilot on desktop. Tools call agent RPC never invent metrics. Profiles lite recommended strong. Install @qvac/sdk for full LLM else tools-only fallback.',
},
{
id: 'guide:fleet',
title: 'Fleet',
text: 'Multi-host roster set active reconnect forget. Parent collector aggregates child getHealth. getFleetHealth RPC.',
},
{
id: 'guide:kpis',
title: 'Core KPIs',
text: 'system.cpu user system idle iowait, system.ram used, system.load load1, system.net received sent, system.io reads writes, mem.available.',
},
]
/**
* @param {string} text
* @returns {string[]}
*/
function tokens(text) {
return String(text || '')
.toLowerCase()
.split(/[^a-z0-9._-]+/)
.filter((t) => t.length > 1)
}
/**
* Build docs from chart catalog map.
* @param {Record<string, object>} catalog
* @param {number} [cap]
*/
export function catalogDocs(catalog, cap = 400) {
/** @type {Array<{ id: string, title: string, text: string }>} */
const docs = []
for (const [id, meta] of Object.entries(catalog || {})) {
if (docs.length >= cap) break
const dims = Array.isArray(meta.dimensions)
? meta.dimensions
.map((d) => (typeof d === 'string' ? d : d?.id || d?.name || ''))
.filter(Boolean)
.join(' ')
: ''
docs.push({
id: `chart:${id}`,
title: meta.title || id,
text: [id, meta.title, meta.context, meta.family, meta.plugin, meta.units, dims]
.filter(Boolean)
.join(' '),
})
}
return docs
}
/**
* @param {string} query
* @param {Array<{ id: string, title: string, text: string }>} docs
* @param {number} [topK]
*/
export function retrieve(query, docs, topK = 6) {
const qToks = tokens(query)
if (!qToks.length || !docs?.length) return []
/** @type {Array<{ id: string, title: string, text: string, score: number }>} */
const scored = []
for (const d of docs) {
const hay = tokens(`${d.title} ${d.text}`)
const set = new Set(hay)
let score = 0
for (const t of qToks) {
if (set.has(t)) score += 2
else if (hay.some((h) => h.includes(t) || t.includes(h))) score += 1
}
if (d.id.startsWith('chart:') && qToks.some((t) => d.id.includes(t))) score += 3
if (score > 0) scored.push({ ...d, score })
}
scored.sort((a, b) => b.score - a.score || a.id.localeCompare(b.id))
return scored.slice(0, topK)
}
/**
* @param {{
* query: string,
* catalog?: Record<string, object>,
* topK?: number,
* includeGuide?: boolean,
* }} opts
*/
export function buildRagContext(opts) {
const docs = []
if (opts.includeGuide !== false) docs.push(...GUIDE_DOCS)
if (opts.catalog) docs.push(...catalogDocs(opts.catalog))
const hits = retrieve(opts.query, docs, opts.topK ?? 6)
if (!hits.length) return ''
const lines = hits.map((h) => {
const snippet = h.text.length > 180 ? h.text.slice(0, 177) + '…' : h.text
return `- [${h.id}] ${h.title}: ${snippet}`
})
return `Relevant local knowledge (do not invent beyond tools + this context):\n${lines.join('\n')}`
}
export { GUIDE_DOCS }