Merge pull request #329 from abi/add-anthropic-key
Add field for Anthropic API key in settings
This commit is contained in:
commit
22e45cc566
@ -120,6 +120,17 @@ async def stream_code(websocket: WebSocket):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Get the Anthropic API key from the request. Fall back to environment variable if not provided.
|
||||||
|
# If neither is provided, we throw an error later only if Claude is used.
|
||||||
|
anthropic_api_key = None
|
||||||
|
if "anthropicApiKey" in params and params["anthropicApiKey"]:
|
||||||
|
anthropic_api_key = params["anthropicApiKey"]
|
||||||
|
print("Using Anthropic API key from client-side settings dialog")
|
||||||
|
else:
|
||||||
|
anthropic_api_key = ANTHROPIC_API_KEY
|
||||||
|
if anthropic_api_key:
|
||||||
|
print("Using Anthropic API key from environment variable")
|
||||||
|
|
||||||
# Get the OpenAI Base URL from the request. Fall back to environment variable if not provided.
|
# Get the OpenAI Base URL from the request. Fall back to environment variable if not provided.
|
||||||
openai_base_url = None
|
openai_base_url = None
|
||||||
# Disable user-specified OpenAI Base URL in prod
|
# Disable user-specified OpenAI Base URL in prod
|
||||||
@ -219,31 +230,31 @@ async def stream_code(websocket: WebSocket):
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if validated_input_mode == "video":
|
if validated_input_mode == "video":
|
||||||
if not ANTHROPIC_API_KEY:
|
if not anthropic_api_key:
|
||||||
await throw_error(
|
await throw_error(
|
||||||
"Video only works with Anthropic models. No Anthropic API key found. Please add the environment variable ANTHROPIC_API_KEY to backend/.env"
|
"Video only works with Anthropic models. No Anthropic API key found. Please add the environment variable ANTHROPIC_API_KEY to backend/.env or in the settings dialog"
|
||||||
)
|
)
|
||||||
raise Exception("No Anthropic key")
|
raise Exception("No Anthropic key")
|
||||||
|
|
||||||
completion = await stream_claude_response_native(
|
completion = await stream_claude_response_native(
|
||||||
system_prompt=VIDEO_PROMPT,
|
system_prompt=VIDEO_PROMPT,
|
||||||
messages=prompt_messages, # type: ignore
|
messages=prompt_messages, # type: ignore
|
||||||
api_key=ANTHROPIC_API_KEY,
|
api_key=anthropic_api_key,
|
||||||
callback=lambda x: process_chunk(x),
|
callback=lambda x: process_chunk(x),
|
||||||
model=Llm.CLAUDE_3_OPUS,
|
model=Llm.CLAUDE_3_OPUS,
|
||||||
include_thinking=True,
|
include_thinking=True,
|
||||||
)
|
)
|
||||||
exact_llm_version = Llm.CLAUDE_3_OPUS
|
exact_llm_version = Llm.CLAUDE_3_OPUS
|
||||||
elif code_generation_model == Llm.CLAUDE_3_SONNET:
|
elif code_generation_model == Llm.CLAUDE_3_SONNET:
|
||||||
if not ANTHROPIC_API_KEY:
|
if not anthropic_api_key:
|
||||||
await throw_error(
|
await throw_error(
|
||||||
"No Anthropic API key found. Please add the environment variable ANTHROPIC_API_KEY to backend/.env"
|
"No Anthropic API key found. Please add the environment variable ANTHROPIC_API_KEY to backend/.env or in the settings dialog"
|
||||||
)
|
)
|
||||||
raise Exception("No Anthropic key")
|
raise Exception("No Anthropic key")
|
||||||
|
|
||||||
completion = await stream_claude_response(
|
completion = await stream_claude_response(
|
||||||
prompt_messages, # type: ignore
|
prompt_messages, # type: ignore
|
||||||
api_key=ANTHROPIC_API_KEY,
|
api_key=anthropic_api_key,
|
||||||
callback=lambda x: process_chunk(x),
|
callback=lambda x: process_chunk(x),
|
||||||
)
|
)
|
||||||
exact_llm_version = code_generation_model
|
exact_llm_version = code_generation_model
|
||||||
|
|||||||
@ -46,7 +46,8 @@
|
|||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"thememirror": "^2.0.1",
|
"thememirror": "^2.0.1",
|
||||||
"vite-plugin-checker": "^0.6.2",
|
"vite-plugin-checker": "^0.6.2",
|
||||||
"webm-duration-fix": "^1.0.4"
|
"webm-duration-fix": "^1.0.4",
|
||||||
|
"zustand": "^4.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
|
|||||||
@ -59,6 +59,7 @@ function App() {
|
|||||||
{
|
{
|
||||||
openAiApiKey: null,
|
openAiApiKey: null,
|
||||||
openAiBaseURL: null,
|
openAiBaseURL: null,
|
||||||
|
anthropicApiKey: null,
|
||||||
screenshotOneApiKey: null,
|
screenshotOneApiKey: null,
|
||||||
isImageGenerationEnabled: true,
|
isImageGenerationEnabled: true,
|
||||||
editorTheme: EditorTheme.COBALT,
|
editorTheme: EditorTheme.COBALT,
|
||||||
@ -378,7 +379,10 @@ function App() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="lg:fixed lg:inset-y-0 lg:z-40 lg:flex lg:w-96 lg:flex-col">
|
<div className="lg:fixed lg:inset-y-0 lg:z-40 lg:flex lg:w-96 lg:flex-col">
|
||||||
<div className="flex grow flex-col gap-y-2 overflow-y-auto border-r border-gray-200 bg-white px-6 dark:bg-zinc-950 dark:text-white">
|
<div
|
||||||
|
className="flex grow flex-col gap-y-2 overflow-y-auto border-r
|
||||||
|
border-gray-200 bg-white px-6 dark:bg-zinc-950 dark:text-white"
|
||||||
|
>
|
||||||
<div className="flex items-center justify-between mt-10 mb-2">
|
<div className="flex items-center justify-between mt-10 mb-2">
|
||||||
<h1 className="text-2xl ">Screenshot to Code</h1>
|
<h1 className="text-2xl ">Screenshot to Code</h1>
|
||||||
<SettingsDialog settings={settings} setSettings={setSettings} />
|
<SettingsDialog settings={settings} setSettings={setSettings} />
|
||||||
|
|||||||
@ -49,7 +49,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
|||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Label htmlFor="image-generation">
|
<Label htmlFor="image-generation">
|
||||||
<div>DALL-E Placeholder Image Generation</div>
|
<div>DALL-E Placeholder Image Generation</div>
|
||||||
<div className="font-light mt-2">
|
<div className="font-light mt-2 text-xs">
|
||||||
More fun with it but if you want to save money, turn it off.
|
More fun with it but if you want to save money, turn it off.
|
||||||
</div>
|
</div>
|
||||||
</Label>
|
</Label>
|
||||||
@ -64,29 +64,31 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col space-y-4">
|
<div className="flex flex-col space-y-6">
|
||||||
<Label htmlFor="openai-api-key">
|
<div>
|
||||||
<div>OpenAI API key</div>
|
<Label htmlFor="openai-api-key">
|
||||||
<div className="font-light mt-2 leading-relaxed">
|
<div>OpenAI API key</div>
|
||||||
Only stored in your browser. Never stored on servers. Overrides
|
<div className="font-light mt-1 mb-2 text-xs leading-relaxed">
|
||||||
your .env config.
|
Only stored in your browser. Never stored on servers. Overrides
|
||||||
</div>
|
your .env config.
|
||||||
</Label>
|
</div>
|
||||||
|
</Label>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
id="openai-api-key"
|
id="openai-api-key"
|
||||||
placeholder="OpenAI API key"
|
placeholder="OpenAI API key"
|
||||||
value={settings.openAiApiKey || ""}
|
value={settings.openAiApiKey || ""}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setSettings((s) => ({
|
setSettings((s) => ({
|
||||||
...s,
|
...s,
|
||||||
openAiApiKey: e.target.value,
|
openAiApiKey: e.target.value,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{!IS_RUNNING_ON_CLOUD && (
|
{!IS_RUNNING_ON_CLOUD && (
|
||||||
<>
|
<div>
|
||||||
<Label htmlFor="openai-api-key">
|
<Label htmlFor="openai-api-key">
|
||||||
<div>OpenAI Base URL (optional)</div>
|
<div>OpenAI Base URL (optional)</div>
|
||||||
<div className="font-light mt-2 leading-relaxed">
|
<div className="font-light mt-2 leading-relaxed">
|
||||||
@ -105,9 +107,31 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="anthropic-api-key">
|
||||||
|
<div>Anthropic API key</div>
|
||||||
|
<div className="font-light mt-1 text-xs leading-relaxed">
|
||||||
|
Only stored in your browser. Never stored on servers. Overrides
|
||||||
|
your .env config.
|
||||||
|
</div>
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id="anthropic-api-key"
|
||||||
|
placeholder="Anthropic API key"
|
||||||
|
value={settings.anthropicApiKey || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSettings((s) => ({
|
||||||
|
...s,
|
||||||
|
anthropicApiKey: e.target.value,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Accordion type="single" collapsible className="w-full">
|
<Accordion type="single" collapsible className="w-full">
|
||||||
<AccordionItem value="item-1">
|
<AccordionItem value="item-1">
|
||||||
<AccordionTrigger>Screenshot by URL Config</AccordionTrigger>
|
<AccordionTrigger>Screenshot by URL Config</AccordionTrigger>
|
||||||
|
|||||||
10
frontend/src/store/app-store.ts
Normal file
10
frontend/src/store/app-store.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
// Store for app-wide state
|
||||||
|
interface AppStore {
|
||||||
|
inputMode: "image" | "video";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useStore = create<AppStore>(() => ({
|
||||||
|
inputMode: "image",
|
||||||
|
}));
|
||||||
@ -16,6 +16,7 @@ export interface Settings {
|
|||||||
codeGenerationModel: CodeGenerationModel;
|
codeGenerationModel: CodeGenerationModel;
|
||||||
// Only relevant for hosted version
|
// Only relevant for hosted version
|
||||||
isTermOfServiceAccepted: boolean;
|
isTermOfServiceAccepted: boolean;
|
||||||
|
anthropicApiKey: string | null; // Added property for anthropic API key
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AppState {
|
export enum AppState {
|
||||||
|
|||||||
@ -5642,6 +5642,11 @@ use-sidecar@^1.1.2:
|
|||||||
detect-node-es "^1.1.0"
|
detect-node-es "^1.1.0"
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
use-sync-external-store@1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||||
|
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||||
|
|
||||||
util-deprecate@^1.0.2:
|
util-deprecate@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||||
@ -5937,3 +5942,10 @@ zod@3.22.4:
|
|||||||
version "3.22.4"
|
version "3.22.4"
|
||||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
|
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
|
||||||
integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
|
integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
|
||||||
|
|
||||||
|
zustand@^4.5.2:
|
||||||
|
version "4.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848"
|
||||||
|
integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==
|
||||||
|
dependencies:
|
||||||
|
use-sync-external-store "1.2.0"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user