Fix bug 1: Only fetch Anthropic models when API key exists
getAnthropicModels() was called unconditionally on mount, causing a console error when no API key was set. Now chains the call after getAnthropicApiKeyExists() confirms a key is present. Includes regression test added before the fix per bug workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
name: Anthropic models fetched without API key
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bug 1: Anthropic Models Fetched Without API Key
|
||||||
|
|
||||||
|
## Symptom
|
||||||
|
|
||||||
|
Browser console shows `Error: Anthropic API key not found. Please set your API key.` on every page load, even when the user has no Anthropic API key and is using `claude-code-pty`.
|
||||||
|
|
||||||
|
## Root Cause
|
||||||
|
|
||||||
|
`Chat.tsx` unconditionally calls `api.getAnthropicModels()` on mount. The server endpoint requires an API key to call the Anthropic models list API. When no key is set, the request fails with an error logged to the console.
|
||||||
|
|
||||||
|
## Reproduction Steps
|
||||||
|
|
||||||
|
1. Start the server without setting an Anthropic API key
|
||||||
|
2. Open the web UI
|
||||||
|
3. Open browser developer console
|
||||||
|
4. Observe the error on page load
|
||||||
|
|
||||||
|
## Proposed Fix
|
||||||
|
|
||||||
|
Only call `getAnthropicModels()` after `getAnthropicApiKeyExists()` confirms a key is set. Chain the calls so the models fetch is conditional.
|
||||||
@@ -592,4 +592,17 @@ describe("Chat review panel", () => {
|
|||||||
|
|
||||||
expect(await screen.findByText("Cannot read stories")).toBeInTheDocument();
|
expect(await screen.findByText("Cannot read stories")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not fetch Anthropic models when no API key exists", async () => {
|
||||||
|
mockedApi.getAnthropicApiKeyExists.mockResolvedValue(false);
|
||||||
|
mockedApi.getAnthropicModels.mockClear();
|
||||||
|
|
||||||
|
render(<Chat projectPath="/tmp/project" onCloseProject={vi.fn()} />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(mockedApi.getAnthropicApiKeyExists).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockedApi.getAnthropicModels).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -174,15 +174,8 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
|||||||
.getAnthropicApiKeyExists()
|
.getAnthropicApiKeyExists()
|
||||||
.then((exists) => {
|
.then((exists) => {
|
||||||
setHasAnthropicKey(exists);
|
setHasAnthropicKey(exists);
|
||||||
})
|
if (!exists) return;
|
||||||
.catch((err) => {
|
return api.getAnthropicModels().then((models) => {
|
||||||
console.error(err);
|
|
||||||
setHasAnthropicKey(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
api
|
|
||||||
.getAnthropicModels()
|
|
||||||
.then((models) => {
|
|
||||||
if (models.length > 0) {
|
if (models.length > 0) {
|
||||||
const sortedModels = models.sort((a, b) =>
|
const sortedModels = models.sort((a, b) =>
|
||||||
a.toLowerCase().localeCompare(b.toLowerCase()),
|
a.toLowerCase().localeCompare(b.toLowerCase()),
|
||||||
@@ -191,9 +184,11 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
|||||||
} else {
|
} else {
|
||||||
setClaudeModels([]);
|
setClaudeModels([]);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
setHasAnthropicKey(false);
|
||||||
setClaudeModels([]);
|
setClaudeModels([]);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
Reference in New Issue
Block a user