llmrouter: Namen 42i/marvin-2609:*, Durchreiche unbekannter Namen an LiteLLM
Caddy zeigt llm.lan künftig auf den Router; alles Unbekannte (2608, role/*) geht unverändert mit dem Client-Key an LiteLLM :4000. Umstellung je Agent = Modellname, kein base_url-Wechsel (Andreas 2026-09-05). altnamen entfällt, bis LiteLLM abgeschaltet wird. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+6
-3
@@ -10,7 +10,7 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { dirname, resolve } from "path";
|
||||
|
||||
export type Upstream = { base: string; keyEnv?: string; maxParallel?: number };
|
||||
export type Upstream = { base: string; keyEnv?: string; maxParallel?: number; /** Client-Token unveraendert weitergeben (Durchreiche an LiteLLM) */ clientKey?: boolean };
|
||||
export type Alias =
|
||||
| { art: "alternative"; referenz: string }
|
||||
| { art: "schwelle"; index: number; minContext: number }
|
||||
@@ -23,7 +23,9 @@ export type Config = {
|
||||
lasttest: boolean;
|
||||
upstreams: Record<string, Upstream>;
|
||||
aliases: Record<string, Alias>;
|
||||
altnamen: Record<string, string>;
|
||||
altnamen?: Record<string, string>;
|
||||
/** Unbekannte Modellnamen unveraendert an diesen Upstream (Parallelbetrieb mit LiteLLM). */
|
||||
fallback?: { upstream: string };
|
||||
};
|
||||
|
||||
export const BASE = resolve(dirname(import.meta.path), "..");
|
||||
@@ -34,7 +36,8 @@ export function configLaden(): Config {
|
||||
for (const [name, a] of Object.entries(c.aliases)) {
|
||||
if (a.art === "fest" && c.upstreams[a.upstream] === undefined) throw new Error(`Alias ${name}: Upstream ${a.upstream} fehlt`);
|
||||
}
|
||||
for (const [alt, ziel] of Object.entries(c.altnamen)) {
|
||||
if (c.fallback !== undefined && c.upstreams[c.fallback.upstream] === undefined) throw new Error(`fallback: Upstream ${c.fallback.upstream} fehlt`);
|
||||
for (const [alt, ziel] of Object.entries(c.altnamen ?? {})) {
|
||||
if (c.aliases[ziel] === undefined) throw new Error(`Altname ${alt} zeigt auf unbekannten Alias ${ziel}`);
|
||||
}
|
||||
c.logDir = resolve(dirname(CONFIG_PATH), c.logDir);
|
||||
|
||||
+14
-4
@@ -53,9 +53,18 @@ async function belegen(name: string, u: Upstream): Promise<() => void> {
|
||||
// --- Aufloesung Alias -> Ziel ------------------------------------------------
|
||||
type Ziel = { alias: string; upstreamName: string; upstream: Upstream; model: string; effort: string | null; body?: Record<string, unknown>; alternative: boolean };
|
||||
function zielBestimmen(angefragt: string, keyName: string): Ziel | { fehler: string; status: number } {
|
||||
const alias = config.altnamen[angefragt] ?? angefragt;
|
||||
const alias = config.altnamen?.[angefragt] ?? angefragt;
|
||||
const def = config.aliases[alias];
|
||||
if (def === undefined) return { fehler: `Unbekanntes Modell ${angefragt}`, status: 404 };
|
||||
if (def === undefined) {
|
||||
// Durchreiche: unbekannter Name geht unveraendert an LiteLLM, mit dem
|
||||
// Client-Key -- dort gelten dessen ACLs. So wechselt ein Agent per
|
||||
// Modellname (2608 -> 2609), nicht per base_url.
|
||||
if (config.fallback !== undefined) {
|
||||
const name = config.fallback.upstream;
|
||||
return { alias: `(durchreiche)`, upstreamName: name, upstream: config.upstreams[name], model: angefragt, effort: null, alternative: false };
|
||||
}
|
||||
return { fehler: `Unbekanntes Modell ${angefragt}`, status: 404 };
|
||||
}
|
||||
const erlaubt = acl.get(keyName) ?? [];
|
||||
if (erlaubt.length > 0 && !erlaubt.includes(alias)) return { fehler: `${keyName} darf ${alias} nicht rufen`, status: 403 };
|
||||
if (def.art === "fest") {
|
||||
@@ -126,7 +135,7 @@ Bun.serve({
|
||||
if ("fehler" in z) return Response.json({ error: { message: z.fehler } }, { status: z.status });
|
||||
ziel = z;
|
||||
stream = orig.stream === true;
|
||||
upstreamBody = JSON.stringify(jsonBody(orig, ziel));
|
||||
upstreamBody = JSON.stringify(ziel.upstream.clientKey === true ? orig : jsonBody(orig, ziel));
|
||||
headers.set("content-type", "application/json");
|
||||
} else {
|
||||
const form = await req.formData();
|
||||
@@ -134,11 +143,12 @@ Bun.serve({
|
||||
const z = zielBestimmen(angefragt, keyName);
|
||||
if ("fehler" in z) return Response.json({ error: { message: z.fehler } }, { status: z.status });
|
||||
ziel = z;
|
||||
form.set("model", ziel.model);
|
||||
if (ziel.upstream.clientKey !== true) form.set("model", ziel.model);
|
||||
upstreamBody = form;
|
||||
}
|
||||
const k = upstreamKey(ziel.upstream);
|
||||
if (k !== undefined) headers.set("authorization", `Bearer ${k}`);
|
||||
if (ziel.upstream.clientKey === true) headers.set("authorization", `Bearer ${auth}`);
|
||||
if (ziel.upstreamName === "openrouter") { headers.set("http-referer", "https://llm.lan"); headers.set("x-title", `llmrouter/${keyName}`); }
|
||||
const accept = req.headers.get("accept"); if (accept) headers.set("accept", accept);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user