feat(providers): support OpenAI-compatible / Azure / Google Gemini endpoints (closes #16)
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.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useT } from '../i18n';
|
||||
import { providerLabel } from '../providers/presets';
|
||||
import type {
|
||||
AgentInfo,
|
||||
AppConfig,
|
||||
@@ -82,16 +83,17 @@ export function EntryView({
|
||||
|
||||
const envMetaLine = useMemo(() => {
|
||||
if (config.mode === 'api') {
|
||||
const provider = providerLabel(config.provider);
|
||||
try {
|
||||
return `${config.model} · ${new URL(config.baseUrl).host}`;
|
||||
return `${provider} · ${config.model} · ${new URL(config.baseUrl).host}`;
|
||||
} catch {
|
||||
return config.model;
|
||||
return `${provider} · ${config.model}`;
|
||||
}
|
||||
}
|
||||
return currentAgent
|
||||
? `${currentAgent.name}${currentAgent.version ? ` · ${currentAgent.version}` : ''}`
|
||||
: t('settings.noAgentSelected');
|
||||
}, [config.mode, config.model, config.baseUrl, currentAgent, t]);
|
||||
}, [config.mode, config.model, config.baseUrl, config.provider, currentAgent, t]);
|
||||
|
||||
// 'Use this prompt' on an example card is a fast path — skip the form and
|
||||
// create the project immediately with sane defaults derived from the skill,
|
||||
|
||||
Reference in New Issue
Block a user