This commit is contained in:
MarkLo 2025-12-06 02:28:43 +08:00
parent a0e4365fc3
commit 43658df2a0
4 changed files with 82 additions and 6 deletions

View File

@ -113,15 +113,15 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
const quickThinkLlm = form.getValues("quick_think_llm");
const deepThinkLlm = form.getValues("deep_think_llm");
// Set base URLs based on selected models
form.setValue("quick_think_base_url", getBaseUrlForModel(quickThinkLlm));
form.setValue("deep_think_base_url", getBaseUrlForModel(deepThinkLlm));
form.setValue("embedding_base_url", "https://api.openai.com/v1");
// Set base URLs based on selected models (custom URL takes precedence)
form.setValue("quick_think_base_url", getBaseUrlForModel(quickThinkLlm, savedSettings.custom_base_url));
form.setValue("deep_think_base_url", getBaseUrlForModel(deepThinkLlm, savedSettings.custom_base_url));
form.setValue("embedding_base_url", savedSettings.custom_base_url || "https://api.openai.com/v1");
// Set API keys based on selected models
form.setValue("quick_think_api_key", getApiKeyForModel(quickThinkLlm, savedSettings));
form.setValue("deep_think_api_key", getApiKeyForModel(deepThinkLlm, savedSettings));
form.setValue("embedding_api_key", savedSettings.openai_api_key);
form.setValue("embedding_api_key", savedSettings.custom_api_key || savedSettings.openai_api_key);
form.setValue("alpha_vantage_api_key", savedSettings.alpha_vantage_api_key);
}, [form, form.watch("quick_think_llm"), form.watch("deep_think_llm")]);

View File

@ -47,6 +47,10 @@ const formSchema = z.object({
grok_api_key: z.string().optional().or(z.literal("")),
deepseek_api_key: z.string().optional().or(z.literal("")),
qwen_api_key: z.string().optional().or(z.literal("")),
// Custom endpoint
custom_base_url: z.string().optional().or(z.literal("")),
custom_api_key: z.string().optional().or(z.literal("")),
});
type FormValues = z.infer<typeof formSchema>;
@ -90,6 +94,7 @@ export function ApiSettingsDialog() {
return (
<Dialog open={open} onOpenChange={setOpen}>
{/* @ts-ignore - React 19 type compatibility issue with Radix UI */}
<DialogTrigger asChild>
<Button
variant="ghost"
@ -242,6 +247,57 @@ export function ApiSettingsDialog() {
/>
</div>
{/* Custom Endpoint Section */}
<div className="space-y-4 border-t pt-4">
<h3 className="text-lg font-semibold text-muted-foreground">
</h3>
{/* Custom Base URL */}
<FormField
control={form.control}
name="custom_base_url"
render={({ field }) => (
<FormItem>
<FormLabel> Base URL</FormLabel>
<FormControl>
<Input
type="text"
placeholder="https://your-custom-endpoint.com/v1"
{...field}
/>
</FormControl>
<FormDescription>
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* Custom API Key */}
<FormField
control={form.control}
name="custom_api_key"
render={({ field }) => (
<FormItem>
<FormLabel> API Key</FormLabel>
<FormControl>
<Input
type="password"
placeholder="輸入自訂端點的 API Key"
{...field}
/>
</FormControl>
<FormDescription>
Base URL 使 API Key
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</div>
{saveSuccess && (
<div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3 text-green-800 dark:text-green-300 text-sm">

View File

@ -6,8 +6,14 @@ import { ApiSettings } from "./storage";
/**
* Get the base URL for a given LLM model
* If custom_base_url is set, it takes precedence
*/
export function getBaseUrlForModel(model: string): string {
export function getBaseUrlForModel(model: string, customBaseUrl?: string): string {
// If custom base URL is provided, use it
if (customBaseUrl && customBaseUrl.trim() !== "") {
return customBaseUrl;
}
// OpenAI models
if (
model.startsWith("gpt-") ||
@ -48,11 +54,19 @@ export function getBaseUrlForModel(model: string): string {
/**
* Get the API key for a given LLM model from saved settings
* If custom_base_url is set and custom_api_key exists, use custom key
*/
export function getApiKeyForModel(
model: string,
settings: ApiSettings
): string {
// If custom base URL is configured and has a key, use the custom key
if (settings.custom_base_url && settings.custom_base_url.trim() !== "") {
if (settings.custom_api_key && settings.custom_api_key.trim() !== "") {
return settings.custom_api_key;
}
}
// OpenAI models
if (
model.startsWith("gpt-") ||

View File

@ -13,6 +13,10 @@ export interface ApiSettings {
grok_api_key: string;
deepseek_api_key: string;
qwen_api_key: string;
// Custom endpoint
custom_base_url: string;
custom_api_key: string;
}
const STORAGE_KEY = "tradingagents_api_settings";
@ -25,6 +29,8 @@ export const DEFAULT_API_SETTINGS: ApiSettings = {
grok_api_key: "",
deepseek_api_key: "",
qwen_api_key: "",
custom_base_url: "",
custom_api_key: "",
};
/**