This commit is contained in:
2026-08-18 18:11:28 -04:00
parent 0e9a650fa2
commit bbaf47028f
259 changed files with 0 additions and 0 deletions
@@ -0,0 +1,376 @@
/**
* QVAC helpers for /bin/agent (no SDK import — host bridge via ctx.bareOsQvac*).
*/
/** @typedef {'lite'|'recommended'|'strong'|'tool-tiny'} BareAgentQvacProfileId */
/**
* Native context windows from upstream model cards (not conservative laptop defaults).
* Qwen3 dense (0.6B/1.7B/4B): https://huggingface.co/Qwen/Qwen3-0.6B — 32,768
* Llama 3.2 1B (tool-calling finetune base): Meta Llama 3.2 — 128,000
* Absolute ceiling for overrides / host clamp.
*/
const BARE_AGENT_QVAC_CTX_QWEN3 = 32768
const BARE_AGENT_QVAC_CTX_LLAMA32_1B = 131072
const BARE_AGENT_QVAC_CTX_ABSOLUTE_MAX = 131072
/**
* @typedef {{
* id: BareAgentQvacProfileId,
* label: string,
* description: string,
* chatModel: string,
* tools: boolean,
* minRamGb: number,
* minDiskGb: number,
* approxDownloadGb: number,
* ctxSize: number
* }} BareAgentQvacProfile
*/
/** @type {Record<BareAgentQvacProfileId, BareAgentQvacProfile>} */
const BARE_AGENT_QVAC_PROFILES = {
lite: {
id: 'lite',
label: 'Lite',
description:
'Smallest download (Qwen3-0.6B). Model-card context 32k; tools enabled.',
chatModel: 'QWEN3_600M_INST_Q4',
tools: true,
minRamGb: 4,
minDiskGb: 2,
approxDownloadGb: 0.5,
ctxSize: BARE_AGENT_QVAC_CTX_QWEN3
},
recommended: {
id: 'recommended',
label: 'Recommended',
description:
'Best balance for Bare OS agent tool calling (Qwen3-1.7B, model-card context 32k).',
chatModel: 'QWEN3_1_7B_INST_Q4',
tools: true,
minRamGb: 8,
minDiskGb: 5,
approxDownloadGb: 2.5,
ctxSize: BARE_AGENT_QVAC_CTX_QWEN3
},
strong: {
id: 'strong',
label: 'Strong',
description:
'Better reasoning (Qwen3-4B). Model-card context 32k (131k with YaRN not enabled).',
chatModel: 'QWEN3_4B_INST_Q4_K_M',
tools: true,
minRamGb: 16,
minDiskGb: 8,
approxDownloadGb: 3.5,
ctxSize: BARE_AGENT_QVAC_CTX_QWEN3
},
'tool-tiny': {
id: 'tool-tiny',
label: 'Tool-tiny',
description:
'Llama 3.2 1B tool-calling fallback (model-card context 128k).',
chatModel: 'LLAMA_TOOL_CALLING_1B_INST_Q4_K',
tools: true,
minRamGb: 6,
minDiskGb: 3,
approxDownloadGb: 1,
ctxSize: BARE_AGENT_QVAC_CTX_LLAMA32_1B
}
}
/**
* Model-card / train context for a QVAC registry id (fallback 32k).
* @param {string} [modelId]
* @returns {number}
*/
function bareAgentQvacModelCardCtxSize(modelId) {
const id = String(modelId || '')
.trim()
.toUpperCase()
if (!id) return BARE_AGENT_QVAC_CTX_QWEN3
if (id.includes('LLAMA') || id.includes('LLAMA_TOOL')) {
return BARE_AGENT_QVAC_CTX_LLAMA32_1B
}
if (id.includes('QWEN3')) return BARE_AGENT_QVAC_CTX_QWEN3
return BARE_AGENT_QVAC_CTX_QWEN3
}
/** @returns {BareAgentQvacProfile[]} */
function bareAgentQvacProfileList() {
return Object.values(BARE_AGENT_QVAC_PROFILES)
}
/**
* @param {string} [id]
* @returns {BareAgentQvacProfile}
*/
function bareAgentQvacGetProfile(id) {
const key = String(id || '').trim().toLowerCase()
return BARE_AGENT_QVAC_PROFILES[key] || BARE_AGENT_QVAC_PROFILES.recommended
}
/**
* Flatten OpenAI nested tool defs → QVAC flat shape.
* @param {unknown[]} tools
* @returns {unknown[]}
*/
function bareAgentFlattenToolsForQvac(tools) {
if (!Array.isArray(tools)) return []
/** @type {unknown[]} */
const out = []
for (const t of tools) {
if (!t || typeof t !== 'object') continue
const o = /** @type {Record<string, unknown>} */ (t)
if (o.function && typeof o.function === 'object') {
const fn = /** @type {Record<string, unknown>} */ (o.function)
out.push({
type: 'function',
name: typeof fn.name === 'string' ? fn.name : '',
description: typeof fn.description === 'string' ? fn.description : '',
parameters:
fn.parameters && typeof fn.parameters === 'object'
? fn.parameters
: { type: 'object', properties: {} }
})
continue
}
if (typeof o.name === 'string') {
out.push({
type: 'function',
name: o.name,
description: typeof o.description === 'string' ? o.description : '',
parameters:
o.parameters && typeof o.parameters === 'object'
? o.parameters
: { type: 'object', properties: {} }
})
}
}
return out.filter((x) => x && typeof x === 'object' && /** @type {any} */ (x).name)
}
/**
* @param {Record<string, unknown>} ctx
* @returns {boolean}
*/
function bareAgentQvacBridgeAvailable(ctx) {
if (!ctx || typeof ctx !== 'object') return false
if (typeof ctx.bareOsQvacAvailable === 'function') {
try {
return Boolean(ctx.bareOsQvacAvailable())
} catch {
return false
}
}
return typeof ctx.bareOsQvacComplete === 'function'
}
/**
* Normalize backend from config (qvac | rest).
* @param {Record<string, unknown>} config
* @returns {'qvac'|'rest'}
*/
function bareAgentResolveBackend(config) {
const b = String(config?.backend || '').trim().toLowerCase()
if (b === 'rest' || b === 'openai' || b === 'http') return 'rest'
if (b === 'qvac') return 'qvac'
const p = String(config?.provider || '').trim().toLowerCase()
if (p === 'qvac') return 'qvac'
if (p === 'groq' || p === 'xai' || p === 'openai' || p === 'custom') return 'rest'
// Default: qvac when key unset; rest when key present (legacy configs)
if (config?.rest_api_key && String(config.rest_api_key).trim()) return 'rest'
return 'qvac'
}
/** @type {readonly string[]} */
var BARE_AGENT_QVAC_ONLY_KEYS = Object.freeze([
'qvac_model',
'qvac_profile',
'qvac_ctx_size',
'qvac_device',
'qvac_main_gpu',
'qvac_gpu_layers'
])
/** @type {readonly string[]} */
var BARE_AGENT_REST_ONLY_KEYS = Object.freeze(['rest_base_url', 'rest_api_key'])
/**
* @typedef {{
* id: string,
* label: string,
* rest_base_url: string,
* default_model: string,
* models: string[]
* }} BareAgentRestProvider
*/
/** @type {Record<string, BareAgentRestProvider>} */
const BARE_AGENT_REST_PROVIDERS = {
groq: {
id: 'groq',
label: 'Groq',
rest_base_url: 'https://api.groq.com/openai/v1',
default_model: 'llama-3.3-70b-versatile',
models: [
'llama-3.3-70b-versatile',
'llama-3.1-8b-instant',
'openai/gpt-oss-120b',
'openai/gpt-oss-20b',
'qwen/qwen3-32b',
'moonshotai/kimi-k2-instruct'
]
},
xai: {
id: 'xai',
label: 'xAI (Grok)',
rest_base_url: 'https://api.x.ai/v1',
default_model: 'grok-4',
models: ['grok-4', 'grok-3', 'grok-3-mini', 'grok-3-fast', 'grok-2-1212']
},
openai: {
id: 'openai',
label: 'OpenAI',
rest_base_url: 'https://api.openai.com/v1',
default_model: 'gpt-4.1',
models: ['gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano', 'gpt-4o', 'o4-mini']
},
custom: {
id: 'custom',
label: 'Custom OpenAI-compatible',
rest_base_url: '',
default_model: '',
models: []
}
}
/** @returns {BareAgentRestProvider[]} */
function bareAgentRestProviderList() {
return [BARE_AGENT_REST_PROVIDERS.groq, BARE_AGENT_REST_PROVIDERS.xai, BARE_AGENT_REST_PROVIDERS.openai, BARE_AGENT_REST_PROVIDERS.custom]
}
/**
* @param {string} [id]
* @returns {BareAgentRestProvider}
*/
function bareAgentRestGetProvider(id) {
const key = String(id || '').trim().toLowerCase()
if (key === 'http' || key === 'rest') return BARE_AGENT_REST_PROVIDERS.custom
return BARE_AGENT_REST_PROVIDERS[key] || BARE_AGENT_REST_PROVIDERS.groq
}
/**
* @param {string} [model]
*/
function bareAgentIsQvacModelId(model) {
const m = String(model || '').trim()
if (!m) return false
return (
/^QWEN/i.test(m) ||
/^LLAMA_TOOL/i.test(m) ||
/QWEN3/i.test(m) ||
/LLAMA_TOOL_CALLING/i.test(m)
)
}
/**
* Drop keys that belong to the other backend so config.json matches the choice.
* @param {Record<string, unknown>} config
* @returns {Record<string, unknown>}
*/
function bareAgentSanitizeConfigForBackend(config) {
const out = { ...(config && typeof config === 'object' ? config : {}) }
const backend = bareAgentResolveBackend(out)
out.backend = backend
if (backend === 'rest') {
for (let i = 0; i < BARE_AGENT_QVAC_ONLY_KEYS.length; i++) {
delete out[BARE_AGENT_QVAC_ONLY_KEYS[i]]
}
const prov = String(out.provider || '')
.trim()
.toLowerCase()
if (!prov || prov === 'qvac') out.provider = 'groq'
if (bareAgentIsQvacModelId(String(out.model || ''))) {
const spec = bareAgentRestGetProvider(String(out.provider || 'groq'))
if (spec.default_model) out.model = spec.default_model
}
} else {
for (let i = 0; i < BARE_AGENT_REST_ONLY_KEYS.length; i++) {
delete out[BARE_AGENT_REST_ONLY_KEYS[i]]
}
out.provider = 'qvac'
}
return out
}
/**
* @param {string} [secret]
*/
function bareAgentMaskSecretPreview(secret) {
const t = String(secret || '')
if (!t.trim()) return '(not set)'
if (t.length <= 8) return '********'
return t.slice(0, 3) + '…' + t.slice(-4)
}
/**
* Resolve context window for QVAC load from the model card / profile.
* Legacy undersized `qvac_ctx_size` values (e.g. 4096/8192) are ignored so
* setup stays automatic; only overrides ≥ the profile default apply.
* Host may still cap via `BARE_OS_QVAC_MAX_CTX`.
* @param {Record<string, unknown>} config
* @param {BareAgentQvacProfile} profile
*/
function bareAgentQvacResolveCtxSize(config, profile) {
const modelId = String(
(config && (config.qvac_model || config.model)) ||
(profile && profile.chatModel) ||
''
)
const cardCtx = bareAgentQvacModelCardCtxSize(modelId)
const profileCtx = Math.max(
2048,
Number(profile && profile.ctxSize) || cardCtx
)
let ctx = Math.min(
BARE_AGENT_QVAC_CTX_ABSOLUTE_MAX,
Math.max(profileCtx, cardCtx)
)
const raw = Number(config && config.qvac_ctx_size)
if (Number.isFinite(raw) && raw >= profileCtx) {
ctx = Math.min(BARE_AGENT_QVAC_CTX_ABSOLUTE_MAX, Math.floor(raw))
}
// Full Bare OS tool list ≈ 4.5k tokens; leave room for system + reply.
// Tools are always on for agent sessions — keep enough ctx for schemas.
if (ctx < 8192) ctx = 8192
return ctx
}
/**
* Device / main-gpu / layers for QVAC load (config + profile defaults).
* @param {Record<string, unknown>} config
* @returns {{ device?: string, mainGpu?: string | number, gpuLayers?: number }}
*/
function bareAgentQvacResolveDeviceOpts(config) {
/** @type {{ device?: string, mainGpu?: string | number, gpuLayers?: number }} */
const out = {}
const device = String(config && config.qvac_device ? config.qvac_device : '')
.trim()
.toLowerCase()
if (device === 'cpu' || device === 'gpu') out.device = device
const mainRaw = config && config.qvac_main_gpu
if (mainRaw !== undefined && mainRaw !== null && String(mainRaw).trim() !== '') {
const s = String(mainRaw).trim().toLowerCase()
if (s === 'auto' || s === 'dedicated' || s === 'integrated') out.mainGpu = s
else if (/^\d+$/.test(s)) out.mainGpu = Number.parseInt(s, 10)
} else {
out.mainGpu = 'auto'
}
const layers = Number(config && config.qvac_gpu_layers)
if (Number.isFinite(layers) && layers >= 0) out.gpuLayers = Math.floor(layers)
return out
}