import test from 'brittle' import path from 'path' import { bareOsQvacSkipFromEnv, bareOsQvacFlattenTools, bareOsQvacEmitAgentEvent, bareOsQvacResolveDeviceConfig, bareOsQvacBuildModelConfig, bareOsQvacPickVulkanPin, createBareOsQvacBridge } from './lib/bare-os-qvac-host.mjs' test('BARE_OS_SKIP_QVAC disables bridge', async (t) => { t.ok(bareOsQvacSkipFromEnv({ BARE_OS_SKIP_QVAC: '1' })) t.ok(bareOsQvacSkipFromEnv({ BARE_OS_SKIP_QVAC: 'true' })) t.absent(bareOsQvacSkipFromEnv({})) const bridge = createBareOsQvacBridge({ env: { BARE_OS_SKIP_QVAC: '1' } }) t.absent(bridge.available()) t.is(bridge.status().status, 'unavailable') t.ok(bridge.status().cacheDir) t.is(bridge.status().hdmsPath, '/mnt/models') await t.exception(() => bridge.loadModel({ modelSrc: 'QWEN3_1_7B_INST_Q4' })) }) test('resolve device config defaults to auto GPU', async (t) => { const d = bareOsQvacResolveDeviceConfig({}, {}) t.is(d.device, 'gpu') t.is(d.mainGpu, 'auto') t.absent(d.gpuLayers) t.absent(d.noCpuFallback) const cpu = bareOsQvacResolveDeviceConfig({}, { BARE_OS_QVAC_DEVICE: 'cpu' }) t.is(cpu.device, 'cpu') const idx = bareOsQvacResolveDeviceConfig({ mainGpu: '1' }, {}) t.is(idx.mainGpu, 1) const cfg = bareOsQvacBuildModelConfig({ tools: true, ctxSize: 4096, device: 'gpu', mainGpu: 'dedicated' }) t.is(cfg.device, 'gpu') t.is(cfg['main-gpu'], 'dedicated') t.is(cfg.ctx_size, 4096) t.absent(cfg.no_mmap) const cpuCfg = bareOsQvacBuildModelConfig({ tools: false, ctxSize: 2048, device: 'cpu', mainGpu: 'dedicated' }) t.is(cpuCfg.device, 'cpu') t.is(cpuCfg.gpu_layers, 0) t.absent(cpuCfg['main-gpu']) t.absent(cpuCfg.no_mmap) }) test('pick vulkan pin prefers highest-VRAM vulkaninfo device', async (t) => { // Caller passes rank-sorted list (highest VRAM first). const pin = bareOsQvacPickVulkanPin([ { index: 1, name: 'NVIDIA', memoryBytes: 4 * 1024 * 1024 * 1024, deviceType: 'DISCRETE', source: 'vulkaninfo' }, { index: 0, name: 'Intel', memoryBytes: 512 * 1024 * 1024, deviceType: 'INTEGRATED', source: 'vulkaninfo' } ]) t.is(pin.index, 1) const nvidiaOnly = bareOsQvacPickVulkanPin([ { index: 0, name: 'NVIDIA GeForce RTX 3050 Ti', memoryBytes: 4 * 1024 * 1024 * 1024, deviceType: 'DISCRETE', source: 'nvidia-smi' } ]) t.is(nvidiaOnly.index, 1) }) test('flatten tools nested → flat', async (t) => { const flat = bareOsQvacFlattenTools([ { type: 'function', function: { name: 'run_command', description: 'Run shell', parameters: { type: 'object', properties: { cmd: { type: 'string' } } } } }, { type: 'function', name: 'already_flat', parameters: { type: 'object', properties: {} } } ]) t.is(flat.length, 2) t.is(flat[0].name, 'run_command') t.is(flat[1].name, 'already_flat') }) test('emit agent events from QVAC stream shapes', async (t) => { /** @type {Record[]} */ const out = [] const state = { toolIndex: 0 } bareOsQvacEmitAgentEvent({ type: 'contentDelta', text: 'hi' }, (e) => out.push(e), state) bareOsQvacEmitAgentEvent({ type: 'thinkingDelta', text: 'think' }, (e) => out.push(e), state) bareOsQvacEmitAgentEvent( { type: 'toolCall', call: { name: 'read_file', arguments: { path: '/x' }, id: 'c1' } }, (e) => out.push(e), state ) t.is(out[0].type, 'delta_content') t.is(out[0].content, 'hi') t.is(out[1].type, 'delta_reasoning') t.is(out[2].type, 'delta_tool_calls') t.is(/** @type {any} */ (out[2]).tool_calls[0].function.name, 'read_file') t.ok(String(/** @type {any} */ (out[2]).tool_calls[0].function.arguments).includes('/x')) }) test('backendsDir resolves to real prebuilds (not app.bundle)', async (t) => { const { bareOsQvacNativeHostId, bareOsQvacResolveBackendsDir } = await import('./lib/bare-os-qvac-sdk-bind.mjs') const host = bareOsQvacNativeHostId() t.ok(/^(darwin|linux|win32)-/.test(host)) const dir = bareOsQvacResolveBackendsDir() // On this CI/dev host the package prebuilds exist on disk. if (dir) { t.absent(/app\.bundle/i.test(dir)) t.ok( dir.endsWith('prebuilds') || dir.includes(path.join('qvac', 'backends')) ) } else { t.pass('no backends for this host (ok)') } })