Beds read the catalogue: a shared loader, eight beds converted, the rest declared
catalogueModule() in the harness reads a module's manifest from the catalogue and rewrites only what the lab must: the build section goes, each artifact becomes the image the machine holds, images are pinned, and a bed may declare a host-port remap or a lab-local address. confluence, gitlab, openai-consumer, audit-logger, ollama, local-model-consumer, model-usage, mosquitto, anthropic-manager and anthropic-consumer now install the catalogue's manifest. A unit test refuses any inline copy naming a catalogue module unless the bed is declared with its reason; the declared list is the debt (novox/hq 04-ISSUES/073).
This commit is contained in:
@@ -26,7 +26,7 @@ import { loadScenario } from "../../src/declaration/parse.ts";
|
||||
import { raise } from "../../src/lifecycle/raise.ts";
|
||||
import { destroy, exec } from "../../src/lifecycle/operate.ts";
|
||||
import { hostBinaryPath, HOST_PATH } from "../../src/lifecycle/place.ts";
|
||||
import { labIsUsable, destroyAll, foundationBundle, onTheMachine } from "./harness.ts";
|
||||
import { labIsUsable, destroyAll, foundationBundle, onTheMachine, catalogueModule, catalogueIsPresent } from "./harness.ts";
|
||||
import type { HeldImage } from "../../src/pinning.ts";
|
||||
|
||||
const capability = await labIsUsable();
|
||||
@@ -39,7 +39,7 @@ const skip = !capability.usable
|
||||
? "MESH_LAB_HOST_BINARY is not set to a built mesh-host"
|
||||
: !bundle || !existsSync(bundle)
|
||||
? "MESH_LAB_BUNDLE is not set to a foundation bundle (mesh-host examples/)"
|
||||
: false;
|
||||
: catalogueIsPresent();
|
||||
|
||||
const SCENARIO = "local-model-bed";
|
||||
const MACHINE = "anchor";
|
||||
@@ -153,47 +153,13 @@ after(async () => {
|
||||
test("a node hosting a model answers model-access, and the consumer is handed its endpoint", {
|
||||
skip, timeout: 1_500_000,
|
||||
}, async () => {
|
||||
const ollamaImage = pinned("ollama/ollama");
|
||||
|
||||
// The provider: ollama runs the model server and `provides: ["model-access"]` at node scope, serving
|
||||
// its port and model. It mints nothing — provides/serves are declaration the mesh reads, so there is
|
||||
// no runtime container, only the server.
|
||||
const ollamaManifest = JSON.stringify({
|
||||
module: "ollama",
|
||||
version: "1",
|
||||
capabilities: ["container-runtime"],
|
||||
provides: [{ name: "model-access", scope: "node" }],
|
||||
listens: [{ port: 11434, protocol: "tcp", from: "machine", why: "local consumers reaching the model server" }],
|
||||
serves: { "model-access": { port: 11434, model: "llama3.2" } },
|
||||
resources: [
|
||||
{ id: "state", type: "directory", path: "/services/ollama", mode: "0700" },
|
||||
{
|
||||
id: "server", type: "container", name: "ollama",
|
||||
image: ollamaImage, network: "host", env: { OLLAMA_HOST: "0.0.0.0:11434" },
|
||||
volumes: ["/services/ollama:/root/.ollama"],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// The consumer: it requires model-access and is answered by the local node. No secret (the local
|
||||
// server is keyless), only the bound endpoint facts, templated into an openai.env the mesh writes.
|
||||
const consumerManifest = JSON.stringify({
|
||||
module: "local-model-consumer",
|
||||
version: "1",
|
||||
slug: "local",
|
||||
requires: ["model-access"],
|
||||
binds: { "model-access": "/var/lib/local-model-consumer/model.json" },
|
||||
resources: [
|
||||
{ id: "state", type: "directory", path: "/var/lib/local-model-consumer", mode: "0700" },
|
||||
{ id: "config", type: "directory", path: "/var/lib/local-model-consumer/config", mode: "0700" },
|
||||
{
|
||||
id: "openai-env", type: "file", path: "/var/lib/local-model-consumer/config/openai.env", mode: "0600",
|
||||
content:
|
||||
"OPENAI_BASE_URL=http://${bound:model-access:at}:${bound:model-access:port}/v1\n" +
|
||||
"OPENAI_MODEL=${bound:model-access:model}\nOPENAI_API_KEY=local\n",
|
||||
},
|
||||
],
|
||||
});
|
||||
// Both manifests are the catalogue's own (novox/hq 04-ISSUES/073). The provider: ollama runs the
|
||||
// model server and `provides: ["model-access"]` at node scope, serving its port and model. It mints
|
||||
// nothing — provides/serves are declaration the mesh reads, so there is no runtime container, only
|
||||
// the server. The consumer requires model-access and is answered by the local node: no secret (the
|
||||
// local server is keyless), only the bound endpoint facts, templated into an openai.env the mesh writes.
|
||||
const ollamaManifest = catalogueModule("ollama", held);
|
||||
const consumerManifest = catalogueModule("local-model-consumer", held);
|
||||
|
||||
await addAssign("ollama", ollamaManifest);
|
||||
await addAssign("local-model-consumer", consumerManifest);
|
||||
|
||||
Reference in New Issue
Block a user