import assert from "node:assert/strict"; import { fileURLToPath } from "node:url"; import http from "node:http"; import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { stripTypeScriptTypes } from "node:module"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import test from "node:test"; import { pathToFileURL } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); // ─── Helpers ──────────────────────────────────────────────────────────────── /** Build a compiled .mjs module with a unique output dir. */ function buildCompiledModule() { const outputDir = mkdtempSync(join(tmpdir(), "llama-test-")); const modules = {}; for (const srcFile of ["config.ts", "discovery.ts", "model-utils.ts", "index.ts"]) { const source = readFileSync(join(__dirname, srcFile), "utf8"); const compiled = stripTypeScriptTypes(source, { mode: "transform" }); const baseName = srcFile.replace(/\.ts$/, ".js"); const destPath = join(outputDir, baseName); writeFileSync(destPath, compiled, "utf8"); modules[baseName.replace(/\.js$/, "")] = destPath; } return { outputDir, modules }; } /** Import the compiled index.js, forcing fresh load. */ async function importModule(outputDir) { return import(`${pathToFileURL(join(outputDir, "index.js")).href}?v=${Date.now()}-${Math.random()}`); } /** * Start an HTTP server on a random port that responds to /v1/models. * Returns { server, port, url }. */ function startMockServer(models, statusCode = 200) { return new Promise((resolve, reject) => { const server = http.createServer((req, res) => { if (req.url === "/v1/models" && req.method === "GET") { res.writeHead(statusCode, { "Content-Type": "application/json" }); res.end(JSON.stringify({ data: models })); } else { res.writeHead(404); res.end("not found"); } }); server.listen(0, "127.0.0.1", () => { const addr = server.address(); resolve({ server, port: addr.port, url: `http://127.0.0.1:${addr.port}/v1` }); }); server.on("error", reject); }); } async function stopMockServer(server) { return new Promise((resolve) => server.close(resolve)); } function createSSEChatResponse(events) { const encoder = new TextEncoder(); const payload = events.map((event) => `data: ${event}`).join("\n\n") + "\n\n"; return new Response( new ReadableStream({ start(controller) { controller.enqueue(encoder.encode(payload)); controller.close(); }, }), { status: 200, headers: { "Content-Type": "text/event-stream" }, }, ); } /** Clean the llama env vars so the compiled module picks up fresh values. */ function cleanLlamaEnv() { delete process.env.LLAMA_BASE_URL; delete process.env.LLAMA_MODEL_ID; delete process.env.LLAMA_CTX; delete process.env.LLAMA_MAX_OUT; // Point settings resolution at a nonexistent file so BASE_URL falls through // to the built-in default, independent of the developer's real settings.json. process.env.PI_SETTINGS_PATH = join(tmpdir(), "llama-test-no-such-settings.json"); } // ─── Mock PI ──────────────────────────────────────────────────────────────── function createMockPI() { const state = { providers: [], commands: new Map() }; const pi = { registerProvider(name, config) { state.providers.push({ name, config }); }, registerCommand(name, options) { state.commands.set(name, options); }, registerShortcut() {}, registerFlag() {}, getFlag() { return undefined; }, registerMessageRenderer() {}, on() {}, sendMessage() {}, sendUserMessage() {}, appendEntry() {}, setSessionName() {}, getSessionName() { return undefined; }, setLabel() {}, exec: async () => ({ stdout: "", stderr: "", code: 0 }), getActiveTools() { return []; }, getAllTools() { return []; }, setActiveTools() {}, refreshTools() {}, getCommands() { return []; }, setModel: async () => false, getThinkingLevel() { return "off"; }, setThinkingLevel() {}, unregisterProvider() {}, events: { on() {}, off() {} }, }; return { pi, state }; } function createMockCtx() { return { ui: { notify: (msg, type) => {}, setStatus: (key, text) => {}, }, hasUI: true, cwd: process.cwd(), sessionManager: {}, modelRegistry: {}, model: undefined, isIdle() { return true; }, signal: undefined, abort() {}, hasPendingMessages() { return false; }, shutdown() {}, getContextUsage() { return undefined; }, compact() {}, getSystemPrompt() { return ""; }, waitForIdle: async () => {}, newSession: async () => ({ cancelled: false }), fork: async () => ({ cancelled: false }), navigateTree: async () => ({ cancelled: false }), switchSession: async () => ({ cancelled: false }), reload: async () => {}, }; } // ─── isReasoningModel tests ──────────────────────────────────────────────── test("isReasoningModel: matches Qwen3.6", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("Qwen3.6-35B"), true); assert.equal(mod.isReasoningModel("Qwen3.6-35B-A3B"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: matches Qwen3-Coder", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("Qwen3-Coder-48B"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: matches Qwen3-VL", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("Qwen3-VL-32B"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: matches MiniMax", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("MiniMax-M1"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: matches gpt-oss", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("gpt-oss-20b"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: matches MiMo", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("MiMo-Large"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: matches Devstral", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("Devstral-72B"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: non-matches", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("gpt-4"), false); assert.equal(mod.isReasoningModel("claude-sonnet"), false); assert.equal(mod.isReasoningModel("llama-3.1"), false); assert.equal(mod.isReasoningModel(""), false); assert.equal(mod.isReasoningModel("unknown-model"), false); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("isReasoningModel: case insensitive", async () => { const { outputDir } = buildCompiledModule(); try { const mod = await importModule(outputDir); assert.equal(mod.isReasoningModel("qwen3.6-35b"), true); assert.equal(mod.isReasoningModel("QWEN3.6-35B"), true); assert.equal(mod.isReasoningModel("qwen3-coder"), true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); // ─── discoverModels tests ────────────────────────────────────────────────── test("discoverModels: returns models from server", async () => { const { outputDir } = buildCompiledModule(); const mockModels = [{ id: "model-a", name: "Model A", context_window: 32768, max_tokens: 8192 }]; const { server, url } = await startMockServer(mockModels); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const mod = await importModule(outputDir); const discovered = await mod.discoverModels(); assert.equal(discovered.length, 1); assert.equal(discovered[0].id, "model-a"); assert.equal(discovered[0].name, "Model A"); assert.equal(discovered[0].context_window, 32768); assert.equal(discovered[0].max_tokens, 8192); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("discoverModels: returns empty array when server has no models", async () => { const { outputDir } = buildCompiledModule(); const { server, url } = await startMockServer([]); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const mod = await importModule(outputDir); const discovered = await mod.discoverModels(); assert.equal(discovered.length, 0); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("discoverModels: throws on HTTP error", async () => { const { outputDir } = buildCompiledModule(); const { server, url } = await startMockServer([], 500); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const mod = await importModule(outputDir); try { await mod.discoverModels(); assert.fail("Should have thrown"); } catch (err) { assert.ok(err.message.includes("HTTP 500") || err.message.includes("500"), `Expected HTTP 500 error, got: ${err.message}`); } } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("discoverModels: handles missing data field in response", async () => { const { outputDir } = buildCompiledModule(); const { server, url } = await startMockServer([]); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const mod = await importModule(outputDir); const discovered = await mod.discoverModels(); assert.equal(discovered.length, 0); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("discoverModels: handles partial model data (missing name)", async () => { const { outputDir } = buildCompiledModule(); const { server, url } = await startMockServer([{ id: "bare-model" }]); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const mod = await importModule(outputDir); const discovered = await mod.discoverModels(); assert.equal(discovered.length, 1); assert.equal(discovered[0].id, "bare-model"); assert.equal(discovered[0].name, undefined); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); // ─── registerProviderWithModels tests ─────────────────────────────────────── test("registerProviderWithModels: registers provider with all model fields", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); const models = [ { id: "model-1", name: "Model 1", context_window: 65536, max_tokens: 16384 }, { id: "model-2", name: "Model 2" }, ]; mod.registerProviderWithModels(pi, models); assert.equal(state.providers.length, 1); const provider = state.providers[0]; assert.equal(provider.name, "local-llama"); assert.equal(provider.config.baseUrl, "http://192.168.2.35:8123/v1"); assert.equal(provider.config.apiKey, "sk-no-key"); assert.equal(provider.config.api, "local-llama"); assert.equal(provider.config.authHeader, true); assert.equal(provider.config.models.length, 2); assert.equal(provider.config.models[0].id, "model-1"); assert.equal(provider.config.models[0].name, "Model 1"); assert.equal(provider.config.models[0].contextWindow, 65536); assert.equal(provider.config.models[0].maxTokens, 16384); assert.equal(provider.config.models[0].cost.input, 0); assert.equal(provider.config.models[0].cost.output, 0); assert.equal(provider.config.models[1].contextWindow, 262144); assert.equal(provider.config.models[1].maxTokens, 65536); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("registerProviderWithModels: streamSimple emits assistant messages with piTokenStats", async () => { const { outputDir } = buildCompiledModule(); const originalFetch = globalThis.fetch; try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = "http://127.0.0.1:8123/v1"; const { pi, state } = createMockPI(); let requestedUrl = ""; globalThis.fetch = async (input) => { requestedUrl = String(input); return createSSEChatResponse([ JSON.stringify({ id: "chatcmpl-local-1", choices: [{ delta: { reasoning_content: "ponder" }, finish_reason: null }], }), JSON.stringify({ choices: [{ delta: { content: "Hello" }, finish_reason: null }], }), JSON.stringify({ usage: { prompt_tokens: 12, completion_tokens: 3, completion_tokens_details: { reasoning_tokens: 1 }, prompt_tokens_details: { cached_tokens: 4 }, }, choices: [{ delta: {}, finish_reason: "stop" }], }), "[DONE]", ]); }; const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "test-model", name: "Test Model" }]); const provider = state.providers[0]; const stream = provider.config.streamSimple( { ...provider.config.models[0], api: provider.config.api, provider: provider.name, }, { systemPrompt: "system", messages: [{ role: "user", content: "hello" }], }, { temperature: 0.1 }, ); assert.equal(typeof stream.result, "function"); assert.equal(typeof stream[Symbol.asyncIterator], "function"); const events = []; for await (const event of stream) { events.push(event); } const finalMessage = await stream.result(); assert.equal(events[0].type, "start"); assert.deepEqual( events.filter((event) => event.type === "thinking_delta").map((event) => event.delta), ["ponder"], ); assert.deepEqual( events.filter((event) => event.type === "text_delta").map((event) => event.delta), ["Hello"], ); assert.equal(events[events.length - 1].type, "done"); assert.equal(requestedUrl, "http://127.0.0.1:8123/v1/chat/completions"); assert.equal(finalMessage.role, "assistant"); assert.equal(finalMessage.api, "local-llama"); assert.equal(finalMessage.provider, "local-llama"); assert.equal(finalMessage.model, "test-model"); assert.equal(finalMessage.responseId, "chatcmpl-local-1"); assert.equal(finalMessage.usage.input, 12); assert.equal(finalMessage.usage.output, 3); assert.equal(finalMessage.usage.cacheRead, 4); assert.equal(finalMessage.usage.totalTokens, 15); assert.equal(finalMessage.content[0].type, "thinking"); assert.equal(finalMessage.content[0].thinking, "ponder"); assert.equal(finalMessage.content[1].type, "text"); assert.equal(finalMessage.content[1].text, "Hello"); assert.equal(finalMessage.piTokenStats.inputTokens, 12); assert.equal(finalMessage.piTokenStats.outputTokens, 3); assert.equal(finalMessage.piTokenStats.thinkingTokens, 1); assert.equal(typeof finalMessage.piTokenStats.requestStartMs, "number"); assert.equal(typeof finalMessage.piTokenStats.responseEndMs, "number"); } finally { globalThis.fetch = originalFetch; cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("registerProviderWithModels: streamSimple converts context tools to OpenAI payload", async () => { const { outputDir } = buildCompiledModule(); const originalFetch = globalThis.fetch; try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = "http://127.0.0.1:8123/v1"; const { pi, state } = createMockPI(); let requestedBody = null; globalThis.fetch = async (_input, init) => { requestedBody = JSON.parse(String(init?.body ?? "{}")); return createSSEChatResponse([ JSON.stringify({ usage: { prompt_tokens: 1, completion_tokens: 1, prompt_tokens_details: { cached_tokens: 0 }, }, choices: [{ delta: { content: "ok" }, finish_reason: "stop" }], }), "[DONE]", ]); }; const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "test-model", name: "Test Model" }]); const provider = state.providers[0]; const stream = provider.config.streamSimple( { ...provider.config.models[0], api: provider.config.api, provider: provider.name, }, { systemPrompt: "system", messages: [{ role: "user", content: "hello" }], tools: [ { name: "read", description: "Read a file", parameters: { type: "object", properties: { path: { type: "string" } }, }, }, ], }, { toolChoice: "auto" }, ); for await (const _event of stream) { // consume stream } assert.deepEqual(requestedBody.tools, [ { type: "function", function: { name: "read", description: "Read a file", parameters: { type: "object", properties: { path: { type: "string" } }, }, }, }, ]); assert.equal(requestedBody.tool_choice, "auto"); } finally { globalThis.fetch = originalFetch; cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("registerProviderWithModels: marks reasoning models correctly", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); const models = [ { id: "Qwen3.6-35B", name: "Qwen3.6" }, { id: "gpt-oss-20b", name: "GPT OSS" }, { id: "MiniMax-M1", name: "MiniMax" }, { id: "llama-3.1", name: "Llama" }, { id: "claude-sonnet", name: "Claude" }, ]; mod.registerProviderWithModels(pi, models); assert.equal(state.providers[0].config.models[0].reasoning, true); assert.equal(state.providers[0].config.models[1].reasoning, true); assert.equal(state.providers[0].config.models[2].reasoning, true); assert.equal(state.providers[0].config.models[3].reasoning, false); assert.equal(state.providers[0].config.models[4].reasoning, false); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("registerProviderWithModels: sets compat block", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "test", name: "Test" }]); const compat = state.providers[0].config.models[0].compat; assert.equal(compat.thinkingFormat, "qwen-chat-template"); assert.equal(compat.maxTokensField, "max_tokens"); assert.equal(compat.supportsDeveloperRole, false); assert.equal(compat.supportsReasoningEffort, false); assert.equal(compat.supportsUsageInStreaming, true); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("registerProviderWithModels: input is always [\"text\"]", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "test" }]); assert.deepEqual(state.providers[0].config.models[0].input, ["text"]); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("registerProviderWithModels: cost is zero for all fields", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "test" }]); const cost = state.providers[0].config.models[0].cost; assert.equal(cost.input, 0); assert.equal(cost.output, 0); assert.equal(cost.cacheRead, 0); assert.equal(cost.cacheWrite, 0); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); // ─── Slash command: /local-llama-refresh ──────────────────────────────────── test("/local-llama-refresh: succeeds with models", async () => { const { outputDir } = buildCompiledModule(); const mockModels = [{ id: "discovered-1", name: "D1" }]; const { server, url } = await startMockServer(mockModels); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const cmd = state.commands.get("local-llama-refresh"); assert.ok(cmd, "/local-llama-refresh should be registered"); assert.ok(cmd.description?.includes("discover"), "refresh command description mentions discover"); assert.ok(typeof cmd.handler === "function"); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("/local-llama-refresh: calls discover and re-registers on success", async () => { const { outputDir } = buildCompiledModule(); const mockModels = [{ id: "new-model-1", name: "New 1" }]; const { server, url } = await startMockServer(mockModels); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.ok(state.providers.length >= 1, "Should have at least 1 provider after load"); assert.equal(state.providers[0].config.models[0].id, "qwen-local", "First provider should be fallback"); const ctx = createMockCtx(); const cmd = state.commands.get("local-llama-refresh"); await cmd.handler("", ctx); const lastProvider = state.providers[state.providers.length - 1]; assert.equal(lastProvider.config.models[0].id, "new-model-1", "Last provider should have discovered model"); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("/local-llama-refresh: notifies on no models", async () => { const { outputDir } = buildCompiledModule(); const { server, url } = await startMockServer([]); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const ctx = createMockCtx(); const cmd = state.commands.get("local-llama-refresh"); await cmd.handler("", ctx); assert.ok(true, "refresh command handled empty models gracefully"); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("/local-llama-refresh: reports error when server unreachable", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = "http://127.0.0.1:1/v1"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const ctx = createMockCtx(); const cmd = state.commands.get("local-llama-refresh"); await cmd.handler("", ctx); assert.ok(true, "refresh command handled unreachable server gracefully"); } finally { cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); // ─── Slash command: /local-llama-status ───────────────────────────────────── test("/local-llama-status: shows models", async () => { const { outputDir } = buildCompiledModule(); const mockModels = [{ id: "status-model", name: "Status Model" }]; const { server, url } = await startMockServer(mockModels); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const cmd = state.commands.get("local-llama-status"); assert.ok(cmd, "/local-llama-status should be registered"); assert.ok(cmd.description?.includes("status"), "status command description mentions status"); assert.ok(typeof cmd.handler === "function"); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("/local-llama-status: handles no models", async () => { const { outputDir } = buildCompiledModule(); const { server, url } = await startMockServer([]); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = url; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const ctx = createMockCtx(); const cmd = state.commands.get("local-llama-status"); await cmd.handler("", ctx); assert.ok(true, "status command handled empty model list"); } finally { await stopMockServer(server); cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); test("/local-llama-status: handles server unreachable", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = "http://127.0.0.1:1/v1"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const ctx = createMockCtx(); const cmd = state.commands.get("local-llama-status"); await cmd.handler("", ctx); assert.ok(true, "status command handled unreachable server gracefully"); } finally { cleanLlamaEnv(); rmSync(outputDir, { recursive: true, force: true }); } }); // ─── Extension entry point tests ──────────────────────────────────────────── test("extension entry: registers fallback provider immediately", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.ok(state.providers.length > 0, "fallback provider should be registered"); const fallback = state.providers[0]; assert.equal(fallback.name, "local-llama"); assert.equal(fallback.config.models[0].id, "qwen-local"); assert.ok(fallback.config.models[0].name.includes("Qwen3.6"), "fallback model name includes Qwen3.6"); assert.equal(state.commands.size, 2, "should register 2 slash commands"); assert.ok(state.commands.has("local-llama-refresh")); assert.ok(state.commands.has("local-llama-status")); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: fallback model has correct defaults", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const model = state.providers[0].config.models[0]; assert.equal(model.contextWindow, 262144); assert.equal(model.maxTokens, 65536); assert.equal(model.reasoning, false); assert.equal(model.input.length, 1); assert.equal(model.input[0], "text"); assert.equal(model.cost.input, 0); assert.equal(model.cost.output, 0); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: registers slash commands", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); const refreshCmd = state.commands.get("local-llama-refresh"); const statusCmd = state.commands.get("local-llama-status"); assert.ok(refreshCmd.description?.includes("discover") || refreshCmd.description?.includes("Discover"), "refresh command description"); assert.ok(statusCmd.description?.includes("status") || statusCmd.description?.includes("Status"), "status command description"); assert.ok(typeof refreshCmd.handler === "function", "refresh has handler"); assert.ok(typeof statusCmd.handler === "function", "status has handler"); } finally { rmSync(outputDir, { recursive: true, force: true }); } }); test("config: reads baseUrl from localLlama settings when env unset", async () => { const { outputDir } = buildCompiledModule(); const settingsDir = mkdtempSync(join(tmpdir(), "llama-settings-")); const settingsPath = join(settingsDir, "settings.json"); writeFileSync( settingsPath, JSON.stringify({ localLlama: { baseUrl: "http://10.0.0.9:8123/v1" } }), "utf8", ); try { cleanLlamaEnv(); process.env.PI_SETTINGS_PATH = settingsPath; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "m" }]); assert.equal(state.providers[0].config.baseUrl, "http://10.0.0.9:8123/v1"); } finally { cleanLlamaEnv(); rmSync(settingsDir, { recursive: true, force: true }); rmSync(outputDir, { recursive: true, force: true }); } }); test("config: LLAMA_BASE_URL env overrides localLlama settings", async () => { const { outputDir } = buildCompiledModule(); const settingsDir = mkdtempSync(join(tmpdir(), "llama-settings-")); const settingsPath = join(settingsDir, "settings.json"); writeFileSync( settingsPath, JSON.stringify({ localLlama: { baseUrl: "http://10.0.0.9:8123/v1" } }), "utf8", ); try { cleanLlamaEnv(); process.env.PI_SETTINGS_PATH = settingsPath; process.env.LLAMA_BASE_URL = "http://env-host:9999/v1"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); mod.registerProviderWithModels(pi, [{ id: "m" }]); assert.equal(state.providers[0].config.baseUrl, "http://env-host:9999/v1"); } finally { cleanLlamaEnv(); rmSync(settingsDir, { recursive: true, force: true }); rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: uses env overrides for BASE_URL", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); process.env.LLAMA_BASE_URL = "http://custom-host:9999/v1"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.equal(state.providers[0].config.baseUrl, "http://custom-host:9999/v1"); } finally { delete process.env.LLAMA_BASE_URL; rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: uses env overrides for MODEL_ID and fallback name", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); process.env.LLAMA_MODEL_ID = "my-custom-model"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.equal(state.providers[0].config.models[0].id, "my-custom-model"); } finally { delete process.env.LLAMA_MODEL_ID; rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: uses env overrides for context window", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); process.env.LLAMA_CTX = "131072"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.equal(state.providers[0].config.models[0].contextWindow, 131072); } finally { delete process.env.LLAMA_CTX; rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: uses env overrides for max output tokens", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); process.env.LLAMA_MAX_OUT = "32768"; const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.equal(state.providers[0].config.models[0].maxTokens, 32768); } finally { delete process.env.LLAMA_MAX_OUT; rmSync(outputDir, { recursive: true, force: true }); } }); test("extension entry: reasoning model correctly detected from ID", async () => { const { outputDir } = buildCompiledModule(); try { cleanLlamaEnv(); const { pi, state } = createMockPI(); const mod = await importModule(outputDir); await mod.default(pi); assert.equal(state.providers[0].config.models[0].reasoning, false); mod.registerProviderWithModels(pi, [{ id: "Qwen3.6-35B" }]); assert.equal(state.providers[1].config.models[0].reasoning, true); } finally { rmSync(outputDir, { recursive: true, force: true }); } });