Add restriction on number of free uses before setting anthropic API key

This commit is contained in:
Brian Hackett
2025-01-22 08:18:35 -08:00
parent aef6fffc1f
commit 2916c0538d
5 changed files with 63 additions and 5 deletions

View File

@@ -27,6 +27,7 @@ import { getIFrameSimulationData, type SimulationData } from '~/lib/replay/Recor
import { getCurrentIFrame } from '../workbench/Preview';
import { getCurrentMouseData } from '../workbench/PointSelector';
import { assert } from '~/lib/replay/ReplayProtocolClient';
import { anthropicNumFreeUsesCookieName, anthropicApiKeyCookieName, MaxFreeUses } from '~/utils/freeUses';
const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
@@ -295,6 +296,17 @@ export const ChatImpl = memo(
return;
}
const anthropicApiKey = Cookies.get(anthropicApiKeyCookieName);
if (!anthropicApiKey) {
const numFreeUses = +(Cookies.get(anthropicNumFreeUsesCookieName) || 0);
if (numFreeUses >= MaxFreeUses) {
toast.error('All free uses consumed. Please set an Anthropic API key in the settings.');
return;
}
Cookies.set(anthropicNumFreeUsesCookieName, (numFreeUses + 1).toString());
}
setSimulationLoading(true);
/**
@@ -355,7 +367,7 @@ export const ChatImpl = memo(
image: imageData,
})),
] as any, // Type assertion to bypass compiler check
}, { body: { simulationEnhancedPrompt } });
}, { body: { simulationEnhancedPrompt, anthropicApiKey } });
if (fileModifications !== undefined) {
/**

View File

@@ -5,7 +5,7 @@ import { classNames } from '~/utils/classNames';
import { DialogTitle, dialogVariants, dialogBackdropVariants } from '~/components/ui/Dialog';
import { IconButton } from '~/components/ui/IconButton';
import styles from './Settings.module.scss';
import ProvidersTab from './providers/ProvidersTab';
import APIKeysTab from './providers/APIKeysTab';
import { useSettings } from '~/lib/hooks/useSettings';
import FeaturesTab from './features/FeaturesTab';
import DebugTab from './debug/DebugTab';
@@ -26,7 +26,7 @@ export const SettingsWindow = ({ open, onClose }: SettingsProps) => {
const tabs: { id: TabType; label: string; icon: string; component?: ReactElement }[] = [
{ id: 'data', label: 'Data', icon: 'i-ph:database', component: <DataTab /> },
{ id: 'providers', label: 'Providers', icon: 'i-ph:key', component: <ProvidersTab /> },
{ id: 'apiKeys', label: 'API Keys', icon: 'i-ph:key', component: <APIKeysTab /> },
{ id: 'connection', label: 'Connection', icon: 'i-ph:link', component: <ConnectionsTab /> },
{ id: 'features', label: 'Features', icon: 'i-ph:star', component: <FeaturesTab /> },
...(debug

View File

@@ -0,0 +1,42 @@
import { useState } from 'react';
import { toast } from 'react-toastify';
import Cookies from 'js-cookie';
import { anthropicNumFreeUsesCookieName, anthropicApiKeyCookieName, MaxFreeUses } from '~/utils/freeUses';
export default function ConnectionsTab() {
const [apiKey, setApiKey] = useState(Cookies.get(anthropicApiKeyCookieName) || '');
const numFreeUses = +(Cookies.get(anthropicNumFreeUsesCookieName) || 0);
const handleSaveAPIKey = async (key: string) => {
if (!key || !key.startsWith('sk-ant-')) {
toast.error('Please provide a valid Anthropic API key');
return;
}
Cookies.set('anthropicApiKey', key);
setApiKey(key);
};
return (
<div className="p-4 mb-4 border border-bolt-elements-borderColor rounded-lg bg-bolt-elements-background-depth-3">
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Anthropic API Key</h3>
<div className="flex mb-4">
<div className="flex-1 mr-2">
<input
type="text"
value={apiKey}
onChange={(e) => handleSaveAPIKey(e.target.value)}
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor disabled:opacity-50"
/>
</div>
</div>
{numFreeUses < MaxFreeUses && (
<div className="flex mb-4">
<div className="flex-1 mr-2">
{MaxFreeUses - numFreeUses} / {MaxFreeUses} free uses remaining
</div>
</div>
)}
</div>
);
}

View File

@@ -15,11 +15,12 @@ Focus specifically on fixing this bug. Do not guess about other problems.
`;
async function chatAction({ context, request }: ActionFunctionArgs) {
const { messages, files, promptId, simulationEnhancedPrompt } = await request.json<{
const { messages, files, promptId, simulationEnhancedPrompt, anthropicApiKey: clientAnthropicApiKey } = await request.json<{
messages: Messages;
files: any;
promptId?: string;
simulationEnhancedPrompt?: string;
anthropicApiKey?: string;
}>();
let finished: (v?: any) => void;
@@ -37,7 +38,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
promptId,
});
const anthropicApiKey = context.cloudflare.env.ANTHROPIC_API_KEY;
const anthropicApiKey = clientAnthropicApiKey ?? context.cloudflare.env.ANTHROPIC_API_KEY;
if (!anthropicApiKey) {
throw new Error("Anthropic API key is not set");
}

3
app/utils/freeUses.ts Normal file
View File

@@ -0,0 +1,3 @@
export const anthropicApiKeyCookieName = 'anthropicApiKey';
export const anthropicNumFreeUsesCookieName = 'anthropicNumFreeUses';
export const MaxFreeUses = 5;