32f5f857d2
The hosted-API BYOK fallback was hard-wired to api.anthropic.com. Issue #16 asks for Azure (Microsoft OpenAI hosting Anthropic-style models) but the same plumbing unlocks every common BYOK target — OpenRouter, LiteLLM, DeepSeek, Groq, Together, Mistral, plus Google Gemini direct. Provider model: - New `provider: 'anthropic' | 'openai' | 'azure' | 'google'` discriminator on AppConfig (defaults to 'anthropic' so existing localStorage configs migrate seamlessly). - src/providers/model.ts routes to one of four streaming clients: anthropic.ts (existing SDK path), openai.ts (new SSE pump shared with azure.ts), azure.ts (deployment URL + api-key header), google.ts (Generative Language streamGenerateContent). - src/providers/presets.ts ships per-provider defaults (baseUrl, model suggestions, api-key placeholder, Azure api-version flag) so the UI can stay declarative. UI: - SettingsDialog now shows a provider picker on the Hosted-API tab and surfaces an Azure-only api-version field. Provider switches preserve any non-empty user values. - EntryView / AvatarMenu env meta line shows the active provider label. - en + zh-CN locales updated; README + README.zh-CN document every provider, with explicit guidance to reach AWS Bedrock / GCP Vertex Anthropic models via a server-side LiteLLM proxy (signing belongs on the server, not the browser). Why an OpenAI-compatible adapter rather than a native Bedrock/Vertex client: AWS SigV4 and GCP service-account JWTs aren't safe to do from a browser holding long-lived BYOK credentials. LiteLLM (or any Anthropic/OpenAI-compatible proxy) sidesteps that and is the same path lobe-chat uses for Bedrock/Vertex.
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
/**
|
|
* BYOK model router. Picks a streaming client based on cfg.provider so
|
|
* the rest of the app can stay provider-agnostic. Adding a fifth provider
|
|
* later means: add an entry to ModelProvider, add a presets row, add a
|
|
* `stream<X>` function, and one more `case` here.
|
|
*/
|
|
import type { AppConfig, ChatMessage } from '../types';
|
|
import type { StreamHandlers } from './anthropic';
|
|
import { streamMessage as streamAnthropic } from './anthropic';
|
|
import { streamAzure } from './azure';
|
|
import { streamGoogle } from './google';
|
|
import { streamOpenAI } from './openai';
|
|
|
|
export async function streamModel(
|
|
cfg: AppConfig,
|
|
system: string,
|
|
history: ChatMessage[],
|
|
signal: AbortSignal,
|
|
handlers: StreamHandlers,
|
|
): Promise<void> {
|
|
switch (cfg.provider) {
|
|
case 'openai':
|
|
return streamOpenAI(cfg, system, history, signal, handlers);
|
|
case 'azure':
|
|
return streamAzure(cfg, system, history, signal, handlers);
|
|
case 'google':
|
|
return streamGoogle(cfg, system, history, signal, handlers);
|
|
case 'anthropic':
|
|
default:
|
|
return streamAnthropic(cfg, system, history, signal, handlers);
|
|
}
|
|
}
|