added a configuration option for Claude through OpenRouter.
This commit is contained in:
@@ -15,6 +15,11 @@
|
|||||||
"api_key": "",
|
"api_key": "",
|
||||||
"model": "claude-sonnet-4-0"
|
"model": "claude-sonnet-4-0"
|
||||||
},
|
},
|
||||||
|
"claude_openrouter": {
|
||||||
|
"api_key": "",
|
||||||
|
"base_url": "https://openrouter.ai/api/v1/chat/completions",
|
||||||
|
"model": "anthropic/claude-sonnet-4"
|
||||||
|
},
|
||||||
"openai_compatible": {
|
"openai_compatible": {
|
||||||
"api_key": "",
|
"api_key": "",
|
||||||
"base_url": "",
|
"base_url": "",
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ const GeneralSettings: React.FC = () => {
|
|||||||
const [geminiModel, setGeminiModel] = useState<string>('');
|
const [geminiModel, setGeminiModel] = useState<string>('');
|
||||||
const [claudeKey, setClaudeKey] = useState<string>('');
|
const [claudeKey, setClaudeKey] = useState<string>('');
|
||||||
const [claudeModel, setClaudeModel] = useState<string>('');
|
const [claudeModel, setClaudeModel] = useState<string>('');
|
||||||
|
const [claudeOpenRouterKey, setClaudeOpenRouterKey] = useState<string>('');
|
||||||
|
const [claudeOpenRouterBaseUrl, setClaudeOpenRouterBaseUrl] = useState<string>('');
|
||||||
|
const [claudeOpenRouterModel, setClaudeOpenRouterModel] = useState<string>('');
|
||||||
const [openaiFlex, setOpenaiFlex] = useState<boolean>(false);
|
const [openaiFlex, setOpenaiFlex] = useState<boolean>(false);
|
||||||
const [compatibleKey, setCompatibleKey] = useState<string>('');
|
const [compatibleKey, setCompatibleKey] = useState<string>('');
|
||||||
const [compatibleBaseUrl, setCompatibleBaseUrl] = useState<string>('');
|
const [compatibleBaseUrl, setCompatibleBaseUrl] = useState<string>('');
|
||||||
@@ -46,6 +49,9 @@ const GeneralSettings: React.FC = () => {
|
|||||||
setGeminiModel((configManager.get('general.gemini.model') as string) || '');
|
setGeminiModel((configManager.get('general.gemini.model') as string) || '');
|
||||||
setClaudeKey((configManager.get('general.claude.api_key') as string) || '');
|
setClaudeKey((configManager.get('general.claude.api_key') as string) || '');
|
||||||
setClaudeModel((configManager.get('general.claude.model') as string) || '');
|
setClaudeModel((configManager.get('general.claude.model') as string) || '');
|
||||||
|
setClaudeOpenRouterKey((configManager.get('general.claude_openrouter.api_key') as string) || '');
|
||||||
|
setClaudeOpenRouterBaseUrl((configManager.get('general.claude_openrouter.base_url') as string) || '');
|
||||||
|
setClaudeOpenRouterModel((configManager.get('general.claude_openrouter.model') as string) || '');
|
||||||
setCompatibleKey((configManager.get('general.openai_compatible.api_key') as string) || '');
|
setCompatibleKey((configManager.get('general.openai_compatible.api_key') as string) || '');
|
||||||
setCompatibleBaseUrl((configManager.get('general.openai_compatible.base_url') as string) || '');
|
setCompatibleBaseUrl((configManager.get('general.openai_compatible.base_url') as string) || '');
|
||||||
setCompatibleModel((configManager.get('general.openai_compatible.model') as string) || '');
|
setCompatibleModel((configManager.get('general.openai_compatible.model') as string) || '');
|
||||||
@@ -121,6 +127,21 @@ const GeneralSettings: React.FC = () => {
|
|||||||
debouncedSave('general.claude.model', value);
|
debouncedSave('general.claude.model', value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClaudeOpenRouterKeyChange = (value: string) => {
|
||||||
|
setClaudeOpenRouterKey(value);
|
||||||
|
debouncedSave('general.claude_openrouter.api_key', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClaudeOpenRouterModelChange = (value: string) => {
|
||||||
|
setClaudeOpenRouterModel(value);
|
||||||
|
debouncedSave('general.claude_openrouter.model', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClaudeOpenRouterBaseUrlChange = (value: string) => {
|
||||||
|
setClaudeOpenRouterBaseUrl(value);
|
||||||
|
debouncedSave('general.claude_openrouter.base_url', value);
|
||||||
|
};
|
||||||
|
|
||||||
const handleCompatibleKeyChange = (value: string) => {
|
const handleCompatibleKeyChange = (value: string) => {
|
||||||
setCompatibleKey(value);
|
setCompatibleKey(value);
|
||||||
debouncedSave('general.openai_compatible.api_key', value);
|
debouncedSave('general.openai_compatible.api_key', value);
|
||||||
@@ -164,6 +185,7 @@ const GeneralSettings: React.FC = () => {
|
|||||||
<option value="openai">OpenAI</option>
|
<option value="openai">OpenAI</option>
|
||||||
{/* <option value="gemini">Gemini</option>
|
{/* <option value="gemini">Gemini</option>
|
||||||
<option value="claude">Claude</option> */}
|
<option value="claude">Claude</option> */}
|
||||||
|
<option value="claude_openrouter">Claude (via OpenRouter)</option>
|
||||||
<option value="openai_compatible">OpenAI Compatible (e.g. OpenRouter, Ollama)</option>
|
<option value="openai_compatible">OpenAI Compatible (e.g. OpenRouter, Ollama)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -284,6 +306,58 @@ const GeneralSettings: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
|
<div className="settings-group">
|
||||||
|
<h4>Anthropic Claude (via OpenRouter)</h4>
|
||||||
|
|
||||||
|
<div className="settings-item">
|
||||||
|
<label className="settings-label">
|
||||||
|
Key
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
className="settings-input"
|
||||||
|
placeholder="Enter your Claude API key"
|
||||||
|
value={claudeOpenRouterKey}
|
||||||
|
onChange={(e) => handleClaudeOpenRouterKeyChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
<div className="settings-help" style={{ fontSize: '12px', color: '#888', marginTop: '4px' }}>
|
||||||
|
{isLocalEnvironment
|
||||||
|
? 'Keys are persisted locally (the IndexedDB in your browser).'
|
||||||
|
: 'For security, keys are not persisted on non-local hosts and are kept in-memory for this session.'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="settings-item">
|
||||||
|
<label className="settings-label">
|
||||||
|
Base URL
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="settings-input"
|
||||||
|
placeholder="e.g. https://openrouter.ai/api/v1/chat/completions"
|
||||||
|
value={claudeOpenRouterBaseUrl}
|
||||||
|
onChange={(e) => handleClaudeOpenRouterBaseUrlChange(e.target.value)}
|
||||||
|
/>
|
||||||
|
<div className="settings-help" style={{ fontSize: '12px', color: '#888', marginTop: '4px' }}>
|
||||||
|
This is the base URL for the OpenRouter API. Please do not change this unless you know what you are doing.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="settings-item">
|
||||||
|
<label className="settings-label">
|
||||||
|
Model
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="settings-select"
|
||||||
|
value={claudeOpenRouterModel}
|
||||||
|
onChange={(e) => handleClaudeOpenRouterModelChange(e.target.value)}
|
||||||
|
>
|
||||||
|
<option value="anthropic/claude-sonnet-4">claude-sonnet-4</option>
|
||||||
|
<option value="anthropic/claude-opus-4.1">claude-opus-4.1</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="settings-group">
|
<div className="settings-group">
|
||||||
<h4>OpenAI Compatible Server</h4>
|
<h4>OpenAI Compatible Server</h4>
|
||||||
|
|
||||||
@@ -312,7 +386,7 @@ const GeneralSettings: React.FC = () => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="settings-input"
|
className="settings-input"
|
||||||
placeholder="e.g. https://api.openrouter.ai/v1"
|
placeholder="e.g. https://openrouter.ai/api/v1/chat/completions"
|
||||||
value={compatibleBaseUrl}
|
value={compatibleBaseUrl}
|
||||||
onChange={(e) => handleCompatibleBaseUrlChange(e.target.value)}
|
onChange={(e) => handleCompatibleBaseUrlChange(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { DB_CONSTANTS } from '../../constants/coreConstants';
|
|||||||
interface AppConfig {
|
interface AppConfig {
|
||||||
general: {
|
general: {
|
||||||
language: string;
|
language: string;
|
||||||
llm_provider: 'openai' | 'gemini' | 'claude' | 'openai_compatible';
|
llm_provider: 'openai' | 'gemini' | 'claude' | 'claude_openrouter' | 'openai_compatible';
|
||||||
openai: {
|
openai: {
|
||||||
api_key: string;
|
api_key: string;
|
||||||
flex: boolean;
|
flex: boolean;
|
||||||
@@ -21,6 +21,11 @@ interface AppConfig {
|
|||||||
api_key: string;
|
api_key: string;
|
||||||
model: string;
|
model: string;
|
||||||
};
|
};
|
||||||
|
claude_openrouter: {
|
||||||
|
api_key: string;
|
||||||
|
base_url: string;
|
||||||
|
model: string;
|
||||||
|
};
|
||||||
openai_compatible: {
|
openai_compatible: {
|
||||||
api_key: string;
|
api_key: string;
|
||||||
base_url: string;
|
base_url: string;
|
||||||
@@ -169,6 +174,11 @@ export class ConfigManager {
|
|||||||
api_key: '',
|
api_key: '',
|
||||||
model: 'claude-sonnet-4-0'
|
model: 'claude-sonnet-4-0'
|
||||||
},
|
},
|
||||||
|
claude_openrouter: {
|
||||||
|
api_key: '',
|
||||||
|
base_url: 'https://openrouter.ai/api/v1/chat/completions',
|
||||||
|
model: 'anthropic/claude-sonnet-4'
|
||||||
|
},
|
||||||
openai_compatible: {
|
openai_compatible: {
|
||||||
api_key: '',
|
api_key: '',
|
||||||
base_url: '',
|
base_url: '',
|
||||||
|
|||||||
Reference in New Issue
Block a user