llmrouter: leichtgewichtiger Gateway-Ersatz mit Alternativ-Auflösung
OpenAI-kompatibler Reverse-Proxy in Bun: Client-Key -> ACL, Alias -> Modell (alternative: günstigstes Modell derselben Klasse über llmlite/openrouter-auswahl inkl. Effort-Achse; fest: lokale Upstreams, TTS/STT, Embeddings), Usage/Kosten aus der OpenRouter-Antwort (auch im Stream), JSONL + SQLite-Log, Tagesstatistik je Key. Altnamen der LiteLLM-Zeit werden übersetzt. Kein 3456/stdcmpt, kein role/*, kein -auto (Andreas 2026-09-05). Lokal verifiziert: Chat, Stream, ACL, Altname, Kosten im Log. Parallelbetrieb auf :4001 geplant. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* keys.ts — Client-Token verwalten. Die Datei (KEYS_FILE) liegt nur auf dem
|
||||
* Host, nie im Repo. `add <name>` erzeugt ein Token und gibt es EINMAL aus;
|
||||
* `add <name> --token <t>` uebernimmt ein bestehendes (Migration von LiteLLM,
|
||||
* damit kein Container angefasst werden muss). `list` zeigt Namen.
|
||||
*/
|
||||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { randomBytes } from "crypto";
|
||||
|
||||
const pfad = process.env.KEYS_FILE;
|
||||
if (pfad === undefined) { console.error("KEYS_FILE nicht gesetzt"); process.exit(1); }
|
||||
let daten: Record<string, string> = {};
|
||||
try { daten = JSON.parse(readFileSync(pfad, "utf8")); } catch { /* neu */ }
|
||||
|
||||
const [befehl, name] = process.argv.slice(2);
|
||||
if (befehl === "list") {
|
||||
for (const n of [...new Set(Object.values(daten))].sort()) console.log(n);
|
||||
} else if (befehl === "add" && name) {
|
||||
const i = process.argv.indexOf("--token");
|
||||
const token = i > 0 ? process.argv[i + 1] : `sk-42i-${randomBytes(24).toString("base64url")}`;
|
||||
daten[token] = name;
|
||||
writeFileSync(pfad, JSON.stringify(daten, null, 1), { mode: 0o600 });
|
||||
console.log(i > 0 ? `uebernommen fuer ${name}` : token);
|
||||
} else if (befehl === "remove" && name) {
|
||||
for (const [t, n] of Object.entries(daten)) if (n === name) delete daten[t];
|
||||
writeFileSync(pfad, JSON.stringify(daten, null, 1), { mode: 0o600 });
|
||||
} else {
|
||||
console.log("keys.ts list | add <name> [--token <t>] | remove <name>");
|
||||
}
|
||||
Reference in New Issue
Block a user