This commit is contained in:
k
2026-09-21 13:36:25 +02:00
parent 59402b250c
commit c05aa7a211
18 changed files with 532 additions and 36 deletions
+6
View File
@@ -42,6 +42,12 @@ export const config = {
openaiApiKey: env("OPENAI_API_KEY", ""),
openaiEnabled: envBool("OPENAI_ENABLED", false),
glmApiKey: env("GLM_API_KEY", ""),
glmEnabled: envBool("GLM_ENABLED", false),
// Zhipu has two platforms: international (api.z.ai, default) and
// mainland China (open.bigmodel.cn) — override for the latter.
glmBaseUrl: env("GLM_BASE_URL", "https://api.z.ai/api/paas/v4"),
// Public docs wiki (served by the hosted git forge, e.g. Gitea wiki pages).
// The app redirects GET /wiki there (302) so the target stays configurable.
wikiUrl: env("WIKI_URL", "https://git.kisakay.com/k/chat/wiki"),
+1 -1
View File
@@ -4,7 +4,7 @@ import { driverLog, fmtBytes, fmtMs } from "./log.ts";
/**
* Base class for OpenAI-compatible HTTP API drivers
* (mistral / deepseek / openai / anthropic adapter).
* (mistral / glm / deepseek / openai / anthropic adapter).
* Only enabled when an API key is configured. Phase 1: disabled stubs.
*/
export abstract class ApiDriverBase implements LLMDriver {
+17
View File
@@ -52,3 +52,20 @@ export class OpenAIDriver extends ApiDriverBase {
});
}
}
/**
* GLM driver (Zhipu AI, OpenAI-compatible endpoint). Priority: after Mistral.
* Docs: https://docs.z.ai — international base is api.z.ai, mainland China
* uses https://open.bigmodel.cn/api/paas/v4 (via GLM_BASE_URL).
*/
export class GlmDriver extends ApiDriverBase {
readonly name = "glm";
constructor() {
super({
baseUrl: config.glmBaseUrl,
apiKey: config.glmApiKey,
enabled: config.glmEnabled,
defaultModels: ["glm-4.7", "glm-4.6", "glm-4.5-air", "glm-4.5-flash"],
});
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ export class OllamaDriver implements LLMDriver {
readonly name = "ollama";
readonly enabled: boolean;
constructor(private host: string = config.ollamaHost, enabled = config.ollamaEnabled) {
constructor(public readonly host: string = config.ollamaHost, enabled = config.ollamaEnabled) {
this.host = host.replace(/\/$/, "");
this.enabled = enabled;
}
+5 -4
View File
@@ -1,14 +1,14 @@
import { AnthropicDriver, DeepSeekDriver, MistralDriver, OpenAIDriver } from "./apis.ts";
import { AnthropicDriver, DeepSeekDriver, GlmDriver, MistralDriver, OpenAIDriver } from "./apis.ts";
import { OllamaDriver } from "./ollama.ts";
import { PuppeteerOpenAIDriver } from "./puppeteer.ts";
import type { DriverModel, LLMDriver } from "./types.ts";
/**
* Global driver priority (per spec):
* 1. ollama (local) -> 2. mistral -> 3. puppeteer-openai (stub)
* -> 4. deepseek -> 5. anthropic -> 6. openai
* 1. ollama (local) -> 2. mistral -> 3. glm -> 4. puppeteer-openai (stub)
* -> 5. deepseek -> 6. anthropic -> 7. openai
*/
const PRIORITY = ["ollama", "mistral", "puppeteer-openai", "deepseek", "anthropic", "openai"];
const PRIORITY = ["ollama", "mistral", "glm", "puppeteer-openai", "deepseek", "anthropic", "openai"];
export class DriverRegistry {
private drivers: Map<string, LLMDriver>;
@@ -17,6 +17,7 @@ export class DriverRegistry {
const all: LLMDriver[] = [
new OllamaDriver(),
new MistralDriver(),
new GlmDriver(),
new PuppeteerOpenAIDriver(),
new DeepSeekDriver(),
new AnthropicDriver(),
+1
View File
@@ -42,6 +42,7 @@ import {
updateUser,
} from "./db.ts";
import type { ChatMessage } from "./drivers/types.ts";
import type { OllamaDriver } from "./drivers/ollama.ts";
import { DriverRegistry } from "./drivers/registry.ts";
import { createHash, randomBytes } from "node:crypto";
import { statSync } from "node:fs";