diff --git a/client/src/components/Admin/AddonManager.test.tsx b/client/src/components/Admin/AddonManager.test.tsx
index 6f13fcf7d..cfffacead 100644
--- a/client/src/components/Admin/AddonManager.test.tsx
+++ b/client/src/components/Admin/AddonManager.test.tsx
@@ -560,6 +560,34 @@ describe('AddonManager', () => {
});
});
+ it('FE-ADMIN-ADDON-029: switching to Anthropic clears a stale base URL before saving', async () => {
+ const user = userEvent.setup();
+ const bodies: unknown[] = [];
+ server.use(
+ addonsRoute([llmAddon({ provider: 'local', model: '', baseUrl: 'http://ollama.lan:11434/v1', apiKey: '', multimodal: false })]),
+ modelsRoute([]),
+ http.put('/api/admin/addons/llm_parsing', async ({ request }) => {
+ bodies.push(await request.json());
+ return HttpResponse.json({ success: true });
+ }),
+ );
+ render(<>>);
+
+ await screen.findByText('Installed on the server');
+
+ await user.click(screen.getByRole('button', { name: /Local · OpenAI-compatible/ }));
+ await user.click(screen.getByRole('button', { name: 'Anthropic' }));
+ await user.type(screen.getByPlaceholderText('claude-opus-4-8'), 'claude-haiku-4-5-20251001');
+ await user.type(screen.getByPlaceholderText('sk-…'), 'sk-ant-live');
+
+ await user.click(screen.getByRole('button', { name: 'Save' }));
+ await screen.findByText('Saved');
+ // The stale local base URL must not ride along to Anthropic — it would hijack the endpoint.
+ expect(bodies[0]).toEqual({
+ config: { provider: 'anthropic', model: 'claude-haiku-4-5-20251001', baseUrl: '', apiKey: 'sk-ant-live', multimodal: false },
+ });
+ });
+
it('FE-ADMIN-ADDON-027: an error frame in the pull stream aborts the pull and is reported', async () => {
const user = userEvent.setup();
server.use(
diff --git a/client/src/components/Admin/AddonManager.tsx b/client/src/components/Admin/AddonManager.tsx
index 1c658ee11..99b9c84d8 100644
--- a/client/src/components/Admin/AddonManager.tsx
+++ b/client/src/components/Admin/AddonManager.tsx
@@ -399,7 +399,7 @@ function LlmParsingConfig({ addon }: { addon: Addon }) {
setSaving(true)
try {
// Send the masked sentinel unchanged so the server keeps the stored key.
- await adminApi.updateAddon(addon.id, { config: { provider, model: model.trim(), baseUrl: baseUrl.trim(), apiKey, multimodal: cfg.multimodal === true } })
+ await adminApi.updateAddon(addon.id, { config: { provider, model: model.trim(), baseUrl: provider === 'anthropic' ? '' : baseUrl.trim(), apiKey, multimodal: cfg.multimodal === true } })
toast.success('Saved')
} catch {
toast.error('Failed to save')