feat: add Gemini API as alternative AI provider
Adds support for Google's Gemini API as an alternative to Claude Agent SDK for observation extraction. Users can now choose between providers in the settings UI. Features: - New GeminiAgent class using Gemini REST API - Provider selection in Settings (Claude vs Gemini) - Gemini API key configuration (via UI or GEMINI_API_KEY env var) - Model selection: gemini-2.0-flash-exp, gemini-1.5-flash, gemini-1.5-pro - Graceful fallback to Claude SDK if Gemini selected but no API key - Seamless transition between providers without worker restart Settings: - CLAUDE_MEM_PROVIDER: 'claude' | 'gemini' - CLAUDE_MEM_GEMINI_API_KEY: API key for Gemini - CLAUDE_MEM_GEMINI_MODEL: Model selection 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -423,24 +423,65 @@ export function ContextSettingsModal({
|
||||
{/* Section 4: Advanced */}
|
||||
<CollapsibleSection
|
||||
title="Advanced"
|
||||
description="Model selection and integrations"
|
||||
description="AI provider and model selection"
|
||||
defaultOpen={false}
|
||||
>
|
||||
<FormField
|
||||
label="Model"
|
||||
tooltip="AI model used for generating observations"
|
||||
label="AI Provider"
|
||||
tooltip="Choose between Claude (via Agent SDK) or Gemini (via REST API)"
|
||||
>
|
||||
<select
|
||||
value={formState.CLAUDE_MEM_MODEL || 'haiku'}
|
||||
onChange={(e) => updateSetting('CLAUDE_MEM_MODEL', e.target.value)}
|
||||
value={formState.CLAUDE_MEM_PROVIDER || 'claude'}
|
||||
onChange={(e) => updateSetting('CLAUDE_MEM_PROVIDER', e.target.value)}
|
||||
>
|
||||
{/* Shorthand names forward to latest model version */}
|
||||
<option value="haiku">haiku (fastest)</option>
|
||||
<option value="sonnet">sonnet (balanced)</option>
|
||||
<option value="opus">opus (highest quality)</option>
|
||||
<option value="claude">Claude (uses your Claude account)</option>
|
||||
<option value="gemini">Gemini (uses API key)</option>
|
||||
</select>
|
||||
</FormField>
|
||||
|
||||
{formState.CLAUDE_MEM_PROVIDER === 'claude' ? (
|
||||
<FormField
|
||||
label="Claude Model"
|
||||
tooltip="Claude model used for generating observations"
|
||||
>
|
||||
<select
|
||||
value={formState.CLAUDE_MEM_MODEL || 'haiku'}
|
||||
onChange={(e) => updateSetting('CLAUDE_MEM_MODEL', e.target.value)}
|
||||
>
|
||||
<option value="haiku">haiku (fastest)</option>
|
||||
<option value="sonnet">sonnet (balanced)</option>
|
||||
<option value="opus">opus (highest quality)</option>
|
||||
</select>
|
||||
</FormField>
|
||||
) : (
|
||||
<>
|
||||
<FormField
|
||||
label="Gemini API Key"
|
||||
tooltip="Your Google AI Studio API key (or set GEMINI_API_KEY env var)"
|
||||
>
|
||||
<input
|
||||
type="password"
|
||||
value={formState.CLAUDE_MEM_GEMINI_API_KEY || ''}
|
||||
onChange={(e) => updateSetting('CLAUDE_MEM_GEMINI_API_KEY', e.target.value)}
|
||||
placeholder="Enter Gemini API key..."
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
label="Gemini Model"
|
||||
tooltip="Gemini model used for generating observations"
|
||||
>
|
||||
<select
|
||||
value={formState.CLAUDE_MEM_GEMINI_MODEL || 'gemini-2.0-flash-exp'}
|
||||
onChange={(e) => updateSetting('CLAUDE_MEM_GEMINI_MODEL', e.target.value)}
|
||||
>
|
||||
<option value="gemini-2.0-flash-exp">gemini-2.0-flash-exp (fastest)</option>
|
||||
<option value="gemini-1.5-flash">gemini-1.5-flash (balanced)</option>
|
||||
<option value="gemini-1.5-pro">gemini-1.5-pro (highest quality)</option>
|
||||
</select>
|
||||
</FormField>
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
label="Worker Port"
|
||||
tooltip="Port for the background worker service"
|
||||
|
||||
@@ -8,6 +8,11 @@ export const DEFAULT_SETTINGS = {
|
||||
CLAUDE_MEM_WORKER_PORT: '37777',
|
||||
CLAUDE_MEM_WORKER_HOST: '127.0.0.1',
|
||||
|
||||
// AI Provider Configuration
|
||||
CLAUDE_MEM_PROVIDER: 'claude',
|
||||
CLAUDE_MEM_GEMINI_API_KEY: '',
|
||||
CLAUDE_MEM_GEMINI_MODEL: 'gemini-2.0-flash-exp',
|
||||
|
||||
// Token Economics (all true for backwards compatibility)
|
||||
CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS: 'true',
|
||||
CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS: 'true',
|
||||
|
||||
@@ -20,6 +20,11 @@ export function useSettings() {
|
||||
CLAUDE_MEM_WORKER_PORT: data.CLAUDE_MEM_WORKER_PORT || DEFAULT_SETTINGS.CLAUDE_MEM_WORKER_PORT,
|
||||
CLAUDE_MEM_WORKER_HOST: data.CLAUDE_MEM_WORKER_HOST || DEFAULT_SETTINGS.CLAUDE_MEM_WORKER_HOST,
|
||||
|
||||
// AI Provider Configuration
|
||||
CLAUDE_MEM_PROVIDER: data.CLAUDE_MEM_PROVIDER || DEFAULT_SETTINGS.CLAUDE_MEM_PROVIDER,
|
||||
CLAUDE_MEM_GEMINI_API_KEY: data.CLAUDE_MEM_GEMINI_API_KEY || DEFAULT_SETTINGS.CLAUDE_MEM_GEMINI_API_KEY,
|
||||
CLAUDE_MEM_GEMINI_MODEL: data.CLAUDE_MEM_GEMINI_MODEL || DEFAULT_SETTINGS.CLAUDE_MEM_GEMINI_MODEL,
|
||||
|
||||
// Token Economics Display
|
||||
CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS: data.CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS || DEFAULT_SETTINGS.CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS,
|
||||
CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS: data.CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS || DEFAULT_SETTINGS.CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS,
|
||||
|
||||
@@ -60,6 +60,11 @@ export interface Settings {
|
||||
CLAUDE_MEM_WORKER_PORT: string;
|
||||
CLAUDE_MEM_WORKER_HOST: string;
|
||||
|
||||
// AI Provider Configuration
|
||||
CLAUDE_MEM_PROVIDER?: string; // 'claude' | 'gemini'
|
||||
CLAUDE_MEM_GEMINI_API_KEY?: string;
|
||||
CLAUDE_MEM_GEMINI_MODEL?: string; // 'gemini-2.0-flash-exp' | 'gemini-1.5-flash' | 'gemini-1.5-pro'
|
||||
|
||||
// Token Economics Display
|
||||
CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS?: string;
|
||||
CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS?: string;
|
||||
|
||||
Reference in New Issue
Block a user