Skip to content

Commit f0dd2bf

Browse files
committed
fix(llm): update default providers and fix proxy header forwarding
- Default LLM provider: MiniMax (M2.5 via Anthropic-compatible API) - Default image gen provider: Gemini (nano-banana-2 / gemini-3.1-flash-image-preview) - Route MiniMax through Anthropic chat format - Remove proxy header whitelist, forward all headers by default
1 parent a096031 commit f0dd2bf

5 files changed

Lines changed: 33 additions & 17 deletions

File tree

apps/webuiapps/src/components/ChatPanel/index.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,13 @@
190190
}
191191
}
192192

193+
.modelHint {
194+
display: block;
195+
font-size: 11px;
196+
color: rgba(250, 234, 95, 0.7);
197+
margin-top: 4px;
198+
}
199+
193200
.select {
194201
appearance: none;
195202
cursor: pointer;

apps/webuiapps/src/components/ChatPanel/index.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -508,22 +508,22 @@ const SettingsModal: React.FC<{
508508
onSave: (_config: LLMConfig, _igConfig: ImageGenConfig | null) => void;
509509
onClose: () => void;
510510
}> = ({ config, imageGenConfig, onSave, onClose }) => {
511-
const [provider, setProvider] = useState<LLMProvider>(config?.provider || 'openai');
511+
const [provider, setProvider] = useState<LLMProvider>(config?.provider || 'minimax');
512512
const [apiKey, setApiKey] = useState(config?.apiKey || '');
513-
const [baseUrl, setBaseUrl] = useState(config?.baseUrl || getDefaultConfig('openai').baseUrl);
514-
const [model, setModel] = useState(config?.model || getDefaultConfig('openai').model);
513+
const [baseUrl, setBaseUrl] = useState(config?.baseUrl || getDefaultConfig('minimax').baseUrl);
514+
const [model, setModel] = useState(config?.model || getDefaultConfig('minimax').model);
515515
const [customHeaders, setCustomHeaders] = useState(config?.customHeaders || '');
516516

517517
// Image generation settings
518518
const [igProvider, setIgProvider] = useState<ImageGenProvider>(
519-
imageGenConfig?.provider || 'openai',
519+
imageGenConfig?.provider || 'gemini',
520520
);
521521
const [igApiKey, setIgApiKey] = useState(imageGenConfig?.apiKey || '');
522522
const [igBaseUrl, setIgBaseUrl] = useState(
523-
imageGenConfig?.baseUrl || getDefaultImageGenConfig('openai').baseUrl,
523+
imageGenConfig?.baseUrl || getDefaultImageGenConfig('gemini').baseUrl,
524524
);
525525
const [igModel, setIgModel] = useState(
526-
imageGenConfig?.model || getDefaultImageGenConfig('openai').model,
526+
imageGenConfig?.model || getDefaultImageGenConfig('gemini').model,
527527
);
528528
const [igCustomHeaders, setIgCustomHeaders] = useState(imageGenConfig?.customHeaders || '');
529529

@@ -612,7 +612,7 @@ const SettingsModal: React.FC<{
612612
onChange={(e) => handleIgProviderChange(e.target.value as ImageGenProvider)}
613613
>
614614
<option value="openai">OpenAI (DALL-E)</option>
615-
<option value="gemini">Gemini</option>
615+
<option value="gemini">Gemini (nano-banana-2)</option>
616616
</select>
617617
</div>
618618

@@ -643,6 +643,9 @@ const SettingsModal: React.FC<{
643643
value={igModel}
644644
onChange={(e) => setIgModel(e.target.value)}
645645
/>
646+
{igProvider === 'gemini' && igModel === 'gemini-3.1-flash-image-preview' && (
647+
<span className={styles.modelHint}>nano-banana-2</span>
648+
)}
646649
</div>
647650

648651
<div className={styles.field}>

apps/webuiapps/src/lib/imageGenClient.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const DEFAULT_CONFIGS: Record<ImageGenProvider, Omit<ImageGenConfig, 'apiKey'>>
2929
gemini: {
3030
provider: 'gemini',
3131
baseUrl: 'https://generativelanguage.googleapis.com',
32-
model: 'gemini-2.0-flash-exp',
32+
model: 'gemini-3.1-flash-image-preview',
3333
},
3434
};
3535

@@ -126,7 +126,7 @@ async function generateImageGemini(
126126
prompt: string,
127127
config: ImageGenConfig,
128128
): Promise<ImageGenResult> {
129-
const targetUrl = `${config.baseUrl}/v1beta/models/${config.model}:generateContent?key=${config.apiKey}`;
129+
const targetUrl = `${config.baseUrl}/v1beta/models/${config.model}:generateContent`;
130130
const body = {
131131
contents: [{ parts: [{ text: prompt }] }],
132132
generationConfig: {
@@ -138,6 +138,7 @@ async function generateImageGemini(
138138
method: 'POST',
139139
headers: {
140140
'Content-Type': 'application/json',
141+
'x-goog-api-key': config.apiKey,
141142
'X-LLM-Target-URL': targetUrl,
142143
...parseCustomHeaders(config.customHeaders),
143144
},

apps/webuiapps/src/lib/llmClient.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ const DEFAULT_CONFIGS: Record<LLMProvider, Omit<LLMConfig, 'apiKey'>> = {
7575
baseUrl: 'https://api.anthropic.com',
7676
model: 'claude-sonnet-4-20250514',
7777
},
78-
minimax: { provider: 'minimax', baseUrl: 'https://api.minimax.chat', model: 'MiniMax-M1-80k' },
78+
minimax: {
79+
provider: 'minimax',
80+
baseUrl: 'https://api.minimax.io/anthropic',
81+
model: 'MiniMax-M2.5',
82+
},
7983
};
8084

8185
export function getDefaultConfig(provider: LLMProvider): Omit<LLMConfig, 'apiKey'> {
@@ -111,7 +115,7 @@ export async function chat(
111115
'messages:',
112116
messages.length,
113117
);
114-
if (config.provider === 'anthropic') {
118+
if (config.provider === 'anthropic' || config.provider === 'minimax') {
115119
return chatAnthropic(messages, tools, config);
116120
}
117121
return chatOpenAI(messages, tools, config);

apps/webuiapps/vite.config.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@ function llmProxyPlugin(): Plugin {
2424
req.on('end', async () => {
2525
try {
2626
const body = Buffer.concat(chunks).toString();
27-
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
28-
// Forward auth-related headers and custom headers
29-
const forwardKeys = ['authorization', 'x-api-key', 'anthropic-version'];
27+
const headers: Record<string, string> = {};
28+
// Forward all headers except host/connection/internal ones
29+
const skipKeys = new Set(['host', 'connection', 'content-length', 'x-llm-target-url']);
3030
for (const [key, val] of Object.entries(req.headers)) {
3131
if (typeof val !== 'string') continue;
32-
if (forwardKeys.includes(key)) {
33-
headers[key] = val;
34-
} else if (key.startsWith('x-custom-')) {
32+
if (skipKeys.has(key)) continue;
33+
if (key.startsWith('x-custom-')) {
3534
headers[key.replace('x-custom-', '')] = val;
35+
} else {
36+
headers[key] = val;
3637
}
3738
}
3839

0 commit comments

Comments
 (0)