Ctrl K
ComunidadGuías…

test/roleaudit.test.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { createServer } from "node:http";

/**
 * Whether every role is running the model it was configured to run.
 *
 * `resolveRole` has always recorded a substitution and nothing ever read it, so
 * a role quietly running a different model was invisible — section 9 traced a
 * thin outline to exactly that once. These pin the three answers the audit has
 * to give, including the one it must give when Ollama is not there at all: a
 * diagnostic that throws when the thing it is diagnosing is down is worse than
 * no diagnostic.
 */

const scratch = await mkdtemp(path.join(tmpdir(), "forge-roleaudit-"));
process.env.FORGE_CONFIG_DIR = path.join(scratch, "config");
await mkdir(process.env.FORGE_CONFIG_DIR, { recursive: true });

/** A stand-in Ollama that reports exactly these models installed. */
async function fakeOllama(names) {
  const server = createServer((req, res) => {
    if (req.url === "/api/tags") {
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ models: names.map((name) => ({ name })) }));
      return;
    }
    res.writeHead(404).end();
  });
  const port = await new Promise((r) => server.listen(0, "127.0.0.1", () => r(server.address().port)));
  return { server, url: `http://127.0.0.1:${port}` };
}

async function writeModelsYaml({ host, roles, fallbacks = [] }) {
  const lines = [`host: ${host}`, "roles:"];
  for (const [role, spec] of Object.entries(roles)) {
    lines.push(`  ${role}:`);
    lines.push(`    model: ${spec.model}`);
    if (spec.provider) lines.push(`    provider: ${spec.provider}`);
  }
  if (fallbacks.length) {
    lines.push("fallbacks:");
    for (const f of fallbacks) lines.push(`  - ${f}`);
  }
  lines.push("providers:");
  lines.push("  somecloud:");
  lines.push("    type: openai-compatible");
  lines.push("    baseURL: https://example.invalid/v1");
  await writeFile(path.join(process.env.FORGE_CONFIG_DIR, "models.yaml"), lines.join("\n") + "\n");
}

/** models.yaml is cached per process, so each case gets a fresh module. */
async function auditWith(config) {
  await writeModelsYaml(config);
  const mod = await import(`../src/ai/ollama.js?case=${Math.random()}`);
  return mod.roleAudit();
}

test.after(() => rm(scratch, { recursive: true, force: true }));

test("a role whose model is installed reports ok", async () => {
  const { server, url } = await fakeOllama(["author-model:1b", "utility-model:1b"]);
  try {
    const audit = await auditWith({
      host: url,
      roles: { author: { model: "author-model:1b" }, utility: { model: "utility-model:1b" } },
    });
    assert.equal(audit.reachable, true);
    assert.equal(audit.ok, true);
    assert.deepEqual(audit.roles.map((r) => r.status), ["ok", "ok"]);
  } finally {
    await new Promise((r) => server.close(r));
  }
});

test("a missing model that has a fallback is reported as a substitution, not as fine", async () => {
  const { server, url } = await fakeOllama(["the-fallback:1b"]);
  try {
    const audit = await auditWith({
      host: url,
      roles: { author: { model: "not-installed:70b" } },
      fallbacks: ["the-fallback:1b"],
    });
    assert.equal(audit.reachable, true);
    // The run would still work. That is exactly the problem: it works, and
    // the only symptom is output quietly worse than it should be.
    assert.equal(audit.ok, false);
    assert.deepEqual(audit.roles[0], {
      role: "author",
      configured: "not-installed:70b",
      resolved: "the-fallback:1b",
      status: "fallback",
    });
  } finally {
    await new Promise((r) => server.close(r));
  }
});

test("a missing model with no usable fallback is reported as missing", async () => {
  const { server, url } = await fakeOllama(["something-else:1b"]);
  try {
    const audit = await auditWith({
      host: url,
      roles: { author: { model: "not-installed:70b" } },
      fallbacks: ["also-not-installed:13b"],
    });
    assert.equal(audit.ok, false);
    assert.equal(audit.roles[0].status, "missing");
    assert.equal(audit.roles[0].resolved, null);
  } finally {
    await new Promise((r) => server.close(r));
  }
});

test("a role pointed at a cloud provider is not judged on what is installed locally", async () => {
  const { server, url } = await fakeOllama([]);
  try {
    const audit = await auditWith({
      host: url,
      roles: { author: { model: "gpt-whatever", provider: "somecloud" } },
    });
    // Its model lives on someone else's machine; "installed" means nothing.
    assert.equal(audit.roles[0].status, "provider");
    assert.equal(audit.ok, true);
  } finally {
    await new Promise((r) => server.close(r));
  }
});

test("hosted mode reports that local models are not what runs", async () => {
  // resolveRole does not look at installed models in hosted mode — every role
  // goes to the gateway or a BYOK provider. Reporting a local model as "ok"
  // there would make this audit the invisible substitution it exists to stop.
  const { setHostedForTest } = await import("../src/cloud.js");
  const { server, url } = await fakeOllama(["author-model:1b"]);
  setHostedForTest(true);
  try {
    const audit = await auditWith({ host: url, roles: { author: { model: "author-model:1b" } } });
    assert.equal(audit.reachable, false);
    assert.match(audit.reason, /hosted/i);
    assert.deepEqual(audit.roles, []);
  } finally {
    setHostedForTest(false);
    await new Promise((r) => server.close(r));
  }
});

test("an unreachable Ollama answers, it does not throw", async () => {
  // A diagnostic that fails when the thing it diagnoses is down is not a
  // diagnostic. Boot calls this, and boot must not depend on Ollama running.
  const audit = await auditWith({
    host: "http://127.0.0.1:1",
    roles: { author: { model: "anything:1b" } },
  });
  assert.equal(audit.reachable, false);
  assert.match(audit.reason, /unreachable/i);
  assert.deepEqual(audit.roles, []);
});