From e13baaab28c522a2f1974b025ba4b6803538b9bf Mon Sep 17 00:00:00 2001 From: Elton Turing Date: Sat, 5 Sep 2026 08:12:31 +0200 Subject: [PATCH] llmrouter vor LiteLLM: Caddy llm.lan -> :4010, /models mischt LiteLLM-Liste dazu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seit 2026-09-05 06:11 läuft llm.lan über den Router; 2608-Namen und role/* gehen per Durchreiche an LiteLLM (:4000). Caddyfile-Falle: Datei-Bind-Mount, mv tauscht den Inode -> podman restart llmlite-caddy statt caddy reload. Co-Authored-By: Claude Fable 5.1 --- src/server.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/server.ts b/src/server.ts index 8021709..77871ef 100644 --- a/src/server.ts +++ b/src/server.ts @@ -116,7 +116,17 @@ Bun.serve({ if (pfad === "/models") { const erlaubt = acl.get(keyName) ?? []; const namen = Object.keys(config.aliases).filter((a) => erlaubt.length === 0 || erlaubt.includes(a)); - return Response.json({ object: "list", data: namen.map((id) => ({ id, object: "model", owned_by: "42i" })) }); + const data = namen.map((id) => ({ id, object: "model", owned_by: "42i" })); + // Im Parallelbetrieb auch die LiteLLM-Liste des Clients zeigen, sonst + // verlieren Clients, die Modelle per /models entdecken, die 2608-Namen. + if (config.fallback !== undefined) { + try { + const u = config.upstreams[config.fallback.upstream]; + const r = await fetch(`${u.base}/models`, { headers: { authorization: `Bearer ${auth}` }, signal: AbortSignal.timeout(10_000) }); + if (r.ok) for (const m of ((await r.json()) as { data?: { id: string }[] }).data ?? []) if (!namen.includes(m.id)) data.push({ id: m.id, object: "model", owned_by: config.fallback.upstream }); + } catch { /* LiteLLM nicht da: nur eigene Liste */ } + } + return Response.json({ object: "list", data }); } if (req.method !== "POST" || !(JSON_PFADE.has(pfad) || FORM_PFADE.has(pfad))) return Response.json({ error: { message: `Pfad ${pfad} wird nicht bedient` } }, { status: 404 });