105 lines
4.4 KiB
JavaScript
105 lines
4.4 KiB
JavaScript
import test from 'brittle'
|
|
import { readFileSync } from 'node:fs'
|
|
import vm from 'node:vm'
|
|
|
|
const QVAC_SRC = readFileSync(new URL('../lib/agent-qvac.js', import.meta.url), 'utf8')
|
|
|
|
/** Eval concat-style preamble helpers into a sandbox (same shape as /bin/agent). */
|
|
function loadAgentQvacHelpers() {
|
|
const sandbox = { console }
|
|
vm.createContext(sandbox)
|
|
vm.runInContext(
|
|
QVAC_SRC +
|
|
'\n;this.__exports = { bareAgentFlattenToolsForQvac, bareAgentQvacGetProfile, bareAgentQvacProfileList, bareAgentResolveBackend, bareAgentQvacBridgeAvailable, bareAgentQvacResolveCtxSize, bareAgentQvacResolveDeviceOpts, bareAgentQvacModelCardCtxSize, BARE_AGENT_QVAC_CTX_QWEN3, BARE_AGENT_QVAC_CTX_LLAMA32_1B }',
|
|
sandbox
|
|
)
|
|
return sandbox.__exports
|
|
}
|
|
|
|
test('flatten OpenAI nested tools for QVAC', async (t) => {
|
|
const { bareAgentFlattenToolsForQvac } = loadAgentQvacHelpers()
|
|
const flat = bareAgentFlattenToolsForQvac([
|
|
{
|
|
type: 'function',
|
|
function: {
|
|
name: 'read_file',
|
|
description: 'Read a file',
|
|
parameters: { type: 'object', properties: { path: { type: 'string' } }, required: ['path'] }
|
|
}
|
|
}
|
|
])
|
|
t.is(flat.length, 1)
|
|
t.is(flat[0].name, 'read_file')
|
|
t.is(flat[0].type, 'function')
|
|
t.ok(flat[0].parameters && flat[0].parameters.properties)
|
|
t.is(flat[0].function, undefined)
|
|
})
|
|
|
|
test('qvac profiles include recommended + lite', async (t) => {
|
|
const { bareAgentQvacProfileList, bareAgentQvacGetProfile } = loadAgentQvacHelpers()
|
|
const list = bareAgentQvacProfileList()
|
|
t.ok(list.length >= 4)
|
|
t.is(bareAgentQvacGetProfile('recommended').chatModel, 'QWEN3_1_7B_INST_Q4')
|
|
t.is(bareAgentQvacGetProfile('recommended').ctxSize, 32768)
|
|
t.is(bareAgentQvacGetProfile('lite').id, 'lite')
|
|
t.is(bareAgentQvacGetProfile('lite').ctxSize, 32768)
|
|
t.is(bareAgentQvacGetProfile('tool-tiny').ctxSize, 131072)
|
|
t.is(bareAgentQvacGetProfile('strong').ctxSize, 32768)
|
|
t.is(bareAgentQvacGetProfile('nope').id, 'recommended')
|
|
})
|
|
|
|
test('model-card ctx sizes match upstream cards', async (t) => {
|
|
const { bareAgentQvacModelCardCtxSize } = loadAgentQvacHelpers()
|
|
t.is(bareAgentQvacModelCardCtxSize('QWEN3_600M_INST_Q4'), 32768)
|
|
t.is(bareAgentQvacModelCardCtxSize('QWEN3_1_7B_INST_Q4'), 32768)
|
|
t.is(bareAgentQvacModelCardCtxSize('QWEN3_4B_INST_Q4_K_M'), 32768)
|
|
t.is(bareAgentQvacModelCardCtxSize('LLAMA_TOOL_CALLING_1B_INST_Q4_K'), 131072)
|
|
})
|
|
|
|
test('resolve qvac ctx size from profile or config override', async (t) => {
|
|
const { bareAgentQvacGetProfile, bareAgentQvacResolveCtxSize } = loadAgentQvacHelpers()
|
|
const rec = bareAgentQvacGetProfile('recommended')
|
|
const lite = bareAgentQvacGetProfile('lite')
|
|
const tiny = bareAgentQvacGetProfile('tool-tiny')
|
|
t.is(bareAgentQvacResolveCtxSize({}, rec), 32768)
|
|
// Legacy undersized overrides are ignored (auto model-card).
|
|
t.is(bareAgentQvacResolveCtxSize({ qvac_ctx_size: 4096 }, rec), 32768)
|
|
t.is(bareAgentQvacResolveCtxSize({ qvac_ctx_size: 8192 }, lite), 32768)
|
|
t.is(bareAgentQvacResolveCtxSize({ qvac_ctx_size: 65536 }, rec), 65536)
|
|
t.is(bareAgentQvacResolveCtxSize({ qvac_ctx_size: 999999 }, rec), 131072)
|
|
t.is(bareAgentQvacResolveCtxSize({}, lite), 32768)
|
|
t.is(bareAgentQvacResolveCtxSize({}, tiny), 131072)
|
|
})
|
|
|
|
test('resolve qvac device opts', async (t) => {
|
|
const { bareAgentQvacResolveDeviceOpts } = loadAgentQvacHelpers()
|
|
const d = bareAgentQvacResolveDeviceOpts({})
|
|
t.is(d.mainGpu, 'auto')
|
|
t.absent(d.device)
|
|
t.is(bareAgentQvacResolveDeviceOpts({ qvac_device: 'cpu' }).device, 'cpu')
|
|
t.is(bareAgentQvacResolveDeviceOpts({ qvac_main_gpu: '1' }).mainGpu, 1)
|
|
t.is(bareAgentQvacResolveDeviceOpts({ qvac_gpu_layers: 0 }).gpuLayers, 0)
|
|
})
|
|
|
|
test('resolve backend defaults to qvac', async (t) => {
|
|
const { bareAgentResolveBackend } = loadAgentQvacHelpers()
|
|
t.is(bareAgentResolveBackend({}), 'qvac')
|
|
t.is(bareAgentResolveBackend({ backend: 'qvac' }), 'qvac')
|
|
t.is(bareAgentResolveBackend({ backend: 'rest' }), 'rest')
|
|
t.is(bareAgentResolveBackend({ provider: 'groq', rest_api_key: 'x' }), 'rest')
|
|
t.is(bareAgentResolveBackend({ provider: 'qvac' }), 'qvac')
|
|
})
|
|
|
|
test('qvac bridge available checks ctx hooks', async (t) => {
|
|
const { bareAgentQvacBridgeAvailable } = loadAgentQvacHelpers()
|
|
t.is(bareAgentQvacBridgeAvailable({}), false)
|
|
t.is(
|
|
bareAgentQvacBridgeAvailable({
|
|
bareOsQvacAvailable: () => true,
|
|
bareOsQvacComplete: async () => {}
|
|
}),
|
|
true
|
|
)
|
|
t.is(bareAgentQvacBridgeAvailable({ bareOsQvacAvailable: () => false }), false)
|
|
})
|