"use strict"; const test = require("node:test"); const assert = require("node:assert/strict"); const childProcess = require("node:child_process"); const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { HoloLakeAiGateway, HoloLakeKnowledgeProvider, } = require("./hololake-capabilities"); function createBareKnowledgeRepository() { const root = fs.mkdtempSync(path.join(os.tmpdir(), "hololake-knowledge-")); const work = path.join(root, "work"); const bare = path.join(root, "knowledge.git"); fs.mkdirSync(work); childProcess.execFileSync("git", ["init", "-b", "main"], { cwd: work }); childProcess.execFileSync("git", ["config", "user.email", "test@example.invalid"], { cwd: work }); childProcess.execFileSync("git", ["config", "user.name", "HoloLake Test"], { cwd: work }); fs.writeFileSync(path.join(work, "INDEX.md"), "# HoloLake\n"); childProcess.execFileSync("git", ["add", "INDEX.md"], { cwd: work }); childProcess.execFileSync("git", ["commit", "-m", "knowledge baseline"], { cwd: work }); childProcess.execFileSync("git", ["clone", "--bare", work, bare]); return { root, bare }; } test("knowledge provider exposes only the fixed main commit and archive", () => { const repository = createBareKnowledgeRepository(); const provider = new HoloLakeKnowledgeProvider({ repositoryId: "bingshuo/hololake-knowledge-base", repositoryPath: repository.bare, maxArchiveBytes: 2 * 1024 * 1024, }); const manifest = provider.manifest(); assert.equal( manifest.repository, "bingshuo/hololake-knowledge-base", ); assert.match(manifest.commit, /^[0-9a-f]{40}$/); assert.equal(manifest.ref, "refs/heads/main"); const archive = provider.archive(manifest.commit); assert.equal(archive.commit, manifest.commit); assert.equal(archive.content_type, "application/zip"); assert.equal(archive.body.subarray(0, 2).toString("ascii"), "PK"); assert.equal(archive.sha256.length, 64); assert.throws( () => provider.archive("0000000000000000000000000000000000000000"), /knowledge_commit_not_current/, ); }); test("AI gateway accepts only registered provider models and never leaks the key", async () => { const requests = []; const gateway = new HoloLakeAiGateway({ providers: { default: { baseUrl: "https://models.example.invalid/v1", apiKey: "server-secret-key", models: ["gpt-test"], }, }, fetchImpl: async (url, options) => { requests.push({ url, options }); return new Response(JSON.stringify({ id: "response-1", choices: [{ message: { role: "assistant", content: "ok" } }], usage: { total_tokens: 3 }, }), { status: 200, headers: { "content-type": "application/json" }, }); }, }); const result = await gateway.execute({ provider: "default", model: "gpt-test", messages: [{ role: "user", content: "hello" }], max_tokens: 32, }); assert.equal(result.ok, true); assert.equal(result.response.choices[0].message.content, "ok"); assert.equal(result.receipt.provider, "default"); assert.equal(requests.length, 1); assert.equal( requests[0].options.headers.authorization, "Bearer server-secret-key", ); assert.doesNotMatch(JSON.stringify(result), /server-secret-key/); const catalog = gateway.catalog(); assert.deepEqual(catalog.providers[0].models, ["gpt-test"]); assert.doesNotMatch(JSON.stringify(catalog), /server-secret-key|models\\.example/); await assert.rejects( () => gateway.execute({ provider: "default", model: "not-registered", messages: [{ role: "user", content: "hello" }], }), /ai_model_not_registered/, ); await assert.rejects( () => gateway.execute({ provider: "https://attacker.invalid/v1", model: "gpt-test", messages: [{ role: "user", content: "hello" }], }), /ai_provider_not_registered/, ); assert.equal(requests.length, 1); }); test("AI gateway bounds message shape, count, text, and requested output", async () => { const gateway = new HoloLakeAiGateway({ providers: { default: { baseUrl: "https://models.example.invalid/v1", apiKey: "server-secret-key", models: ["gpt-test"], }, }, fetchImpl: async () => new Response("{}", { status: 200 }), maxMessages: 2, maxInputCharacters: 10, maxOutputTokens: 64, }); await assert.rejects( () => gateway.execute({ provider: "default", model: "gpt-test", messages: [{ role: "user", content: "12345678901" }], }), /ai_input_too_large/, ); await assert.rejects( () => gateway.execute({ provider: "default", model: "gpt-test", messages: [{ role: "tool", content: "hello" }], }), /ai_message_invalid/, ); await assert.rejects( () => gateway.execute({ provider: "default", model: "gpt-test", messages: [{ role: "user", content: "hello" }], max_tokens: 65, }), /ai_output_limit_exceeded/, ); });