From 9244d58325d86016a1db3ba91a9080399a672f72 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 19 Jun 2026 22:37:18 +0000 Subject: [PATCH] cerebellum: env-driven plug-and-play model selection PickLLM reads OPENHERMES_URL/OPENHERMES_MODEL from the environment and mounts OpenHermesClient when a URL is set, else StubLLM -- the bus wiring is identical either way. EnvLookup helper parses Env.vars. Verified both paths compile + run. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_015hmgREHNsxYCuim33yUF2c --- src/ichor/cerebellum.pony | 31 +++++++++++++++++++++++++++++++ src/ichor/main.pony | 6 ++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/ichor/cerebellum.pony b/src/ichor/cerebellum.pony index 860110a..9a25cdb 100644 --- a/src/ichor/cerebellum.pony +++ b/src/ichor/cerebellum.pony @@ -50,6 +50,37 @@ actor OpenHermesClient is LLM // than perform an untested network call. respond("[openhermes " + _cfg.model + " @ " + _cfg.url + "] " + prompt) +// --- config plumbing ------------------------------------------------------ +primitive EnvLookup + """Find KEY in an Env.vars array ("KEY=value" entries); None if absent.""" + fun apply(vars: Array[String] val, key: String): (String | None) => + for v in vars.values() do + let parts: Array[String] val = v.split_by("=", 2) + try + if parts(0)? == key then + return parts(1)? + end + end + end + None + +primitive PickLLM + """Plug-and-play model selection: OPENHERMES_URL picks the real client.""" + fun apply(out: OutStream, vars: Array[String] val): LLM => + match EnvLookup(vars, "OPENHERMES_URL") + | let url: String => + let model = + match EnvLookup(vars, "OPENHERMES_MODEL") + | let m: String => m + else "openhermes" + end + out.print("[cerebellum] model: OpenHermes " + model + " @ " + url) + OpenHermesClient(OpenHermesConfig(url, model)) + else + out.print("[cerebellum] model: StubLLM (set OPENHERMES_URL for a real model)") + StubLLM + end + // --- the harness ---------------------------------------------------------- actor CerebellumHarness is OrganReceiver let _out: OutStream diff --git a/src/ichor/main.pony b/src/ichor/main.pony index 0546b7b..3497ec5 100644 --- a/src/ichor/main.pony +++ b/src/ichor/main.pony @@ -26,8 +26,10 @@ actor Main "reshuffle: cross-only")) // --- cerebellum harness plugged into the bus (C1 / OpenHermes) --- - // Swap StubLLM for a real OpenHermes client and nothing else changes. - let cerebellum = CerebellumHarness(env.out, broker, StubLLM, 2) + // Plug-and-play: PickLLM chooses the model from the environment + // (OPENHERMES_URL/MODEL -> real client, else StubLLM); nothing else changes. + let cerebellum = + CerebellumHarness(env.out, broker, PickLLM(env.out, env.vars), 2) broker.register(Cerebellum, cerebellum) // A user turn enters the bus addressed to the cerebellum; it sequences the