mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
Merge pull request #6 from AutoMaker-Org/feature/auth-setup-settings-menu
Added Authentication Status Settings to API Keys Tab in Settings
This commit is contained in:
5
.automaker/.gitignore
vendored
5
.automaker/.gitignore
vendored
@@ -6,3 +6,8 @@ agents-context/
|
||||
|
||||
# Attached images - uploaded by users as feature context
|
||||
images/
|
||||
|
||||
# Launch script - local development script
|
||||
launch.sh
|
||||
|
||||
.cursor
|
||||
@@ -1,453 +0,0 @@
|
||||
---
|
||||
name: Codex CLI OpenAI Model Support
|
||||
overview: Extend the model support system to integrate OpenAI Codex CLI, enabling users to use OpenAI models (GPT-4o, o3, etc.) alongside existing Claude models. This includes CLI detection, model provider abstraction, execution wrapper, and UI updates.
|
||||
todos:
|
||||
- id: model-provider-abstraction
|
||||
content: Create model provider abstraction layer with base interface and Claude/Codex implementations
|
||||
status: pending
|
||||
- id: codex-cli-detector
|
||||
content: Implement Codex CLI detector service to check installation status and version
|
||||
status: pending
|
||||
- id: codex-executor
|
||||
content: Create Codex CLI execution wrapper that spawns subprocess and parses JSON output
|
||||
status: pending
|
||||
- id: codex-config-manager
|
||||
content: Implement Codex TOML configuration manager for model provider setup
|
||||
status: pending
|
||||
- id: model-registry
|
||||
content: Create centralized model registry with provider mappings and metadata
|
||||
status: pending
|
||||
- id: update-feature-executor
|
||||
content: Refactor feature-executor.js to use model provider abstraction instead of direct SDK calls
|
||||
status: pending
|
||||
- id: update-agent-service
|
||||
content: Update agent-service.js to support configurable model selection via provider abstraction
|
||||
status: pending
|
||||
- id: message-converter
|
||||
content: Create message format converter to translate Codex JSONL output to Claude SDK format
|
||||
status: pending
|
||||
- id: update-ui-types
|
||||
content: Extend TypeScript types in app-store.ts to include OpenAI models and provider metadata
|
||||
status: pending
|
||||
- id: update-board-view
|
||||
content: Expand model selection dropdown in board-view.tsx to include OpenAI models with provider grouping
|
||||
status: pending
|
||||
- id: update-settings-view
|
||||
content: Add OpenAI API key input, Codex CLI status check, and test connection button to settings-view.tsx
|
||||
status: pending
|
||||
- id: openai-test-api
|
||||
content: Create OpenAI API test endpoint at app/src/app/api/openai/test/route.ts
|
||||
status: pending
|
||||
- id: ipc-handlers
|
||||
content: Add IPC handlers in main.js for model management (checkCodexCli, getAvailableModels, testOpenAI)
|
||||
status: pending
|
||||
- id: preload-api
|
||||
content: Update preload.js and electron.d.ts to expose new IPC methods to renderer process
|
||||
status: pending
|
||||
- id: env-manager
|
||||
content: Create environment variable manager for centralized API key and config handling
|
||||
status: pending
|
||||
- id: error-handling
|
||||
content: Implement provider fallback logic and user-friendly error messages for missing CLI/API keys
|
||||
status: pending
|
||||
---
|
||||
|
||||
# Codex CLI OpenAI Model Support Implementation Plan
|
||||
|
||||
## Overview
|
||||
|
||||
Extend Automaker's model support to integrate OpenAI Codex CLI, allowing users to use the latest GPT-5.1 Codex models (`gpt-5.1-codex-max`, `gpt-5.1-codex`, `gpt-5.1-codex-mini`, `gpt-5.1`) alongside existing Claude models. Codex CLI defaults to `gpt-5.1-codex-max` and uses ChatGPT Enterprise authentication (no API key required). The implementation will follow the existing Claude CLI pattern but add abstraction for multiple model providers.
|
||||
|
||||
## Current Architecture Analysis
|
||||
|
||||
### Model Usage Points
|
||||
|
||||
1. **Feature Executor** (`app/electron/services/feature-executor.js`):
|
||||
|
||||
- Uses `MODEL_MAP` with hardcoded Claude models (haiku, sonnet, opus)
|
||||
- Calls `@anthropic-ai/claude-agent-sdk` `query()` function
|
||||
- Model selection via `getModelString(feature)` method
|
||||
|
||||
2. **Agent Service** (`app/electron/agent-service.js`):
|
||||
|
||||
- Hardcoded model: `"claude-opus-4-5-20251101"`
|
||||
- Uses Claude Agent SDK directly
|
||||
|
||||
3. **API Route** (`app/src/app/api/chat/route.ts`):
|
||||
|
||||
- Hardcoded model: `"claude-opus-4-5-20251101"`
|
||||
- Uses Claude Agent SDK
|
||||
|
||||
4. **Project Analyzer** (`app/electron/services/project-analyzer.js`):
|
||||
|
||||
- Hardcoded model: `"claude-sonnet-4-20250514"`
|
||||
|
||||
5. **UI Components**:
|
||||
|
||||
- `board-view.tsx`: Model dropdown (haiku/sonnet/opus)
|
||||
- `app-store.ts`: `AgentModel` type limited to Claude models
|
||||
|
||||
### Authentication
|
||||
|
||||
- Claude: Uses `CLAUDE_CODE_OAUTH_TOKEN` environment variable
|
||||
- Codex: Uses `OPENAI_API_KEY` environment variable (per Codex docs)
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Phase 1: Model Provider Abstraction Layer
|
||||
|
||||
#### 1.1 Create Model Provider Interface
|
||||
|
||||
**File**: `app/electron/services/model-provider.js`
|
||||
|
||||
- Abstract base class/interface for model providers
|
||||
- Methods: `executeQuery()`, `detectInstallation()`, `getAvailableModels()`, `validateConfig()`
|
||||
- Implementations:
|
||||
- `ClaudeProvider` (wraps existing SDK usage)
|
||||
- `CodexProvider` (new, wraps Codex CLI execution)
|
||||
|
||||
#### 1.2 Create Codex CLI Detector
|
||||
|
||||
**File**: `app/electron/services/codex-cli-detector.js`
|
||||
|
||||
- Similar to `claude-cli-detector.js`
|
||||
- Check for `codex` command in PATH
|
||||
- Check for npm global installation: `npm list -g @openai/codex`
|
||||
- Check for Homebrew installation on macOS
|
||||
- Return: `{ installed: boolean, path: string, version: string, method: 'cli'|'npm'|'brew'|'none' }`
|
||||
|
||||
#### 1.3 Create Codex Provider Implementation
|
||||
|
||||
**File**: `app/electron/services/codex-provider.js`
|
||||
|
||||
- Extends model provider interface
|
||||
- Executes Codex CLI via `child_process.spawn()` or `execSync()`
|
||||
- Handles JSON output parsing (`codex exec --json`)
|
||||
- Manages TOML configuration file creation/updates
|
||||
- Supports latest GPT-5.1 Codex models:
|
||||
- `gpt-5.1-codex-max` (default, latest flagship for deep and fast reasoning)
|
||||
- `gpt-5.1-codex` (optimized for codex)
|
||||
- `gpt-5.1-codex-mini` (cheaper, faster, less capable)
|
||||
- `gpt-5.1` (broad world knowledge with strong general reasoning)
|
||||
- Uses ChatGPT Enterprise authentication (no API key required for these models)
|
||||
- Note: Legacy models (GPT-4o, o3, o1, etc.) are not supported - Codex CLI focuses on GPT-5.1 Codex family only
|
||||
|
||||
### Phase 2: Model Configuration System
|
||||
|
||||
#### 2.1 Extended Model Registry
|
||||
|
||||
**File**: `app/electron/services/model-registry.js`
|
||||
|
||||
- Centralized model configuration
|
||||
- Model definitions with provider mapping:
|
||||
```javascript
|
||||
{
|
||||
id: "claude-opus",
|
||||
name: "Claude Opus 4.5",
|
||||
provider: "claude",
|
||||
modelString: "claude-opus-4-5-20251101",
|
||||
...
|
||||
},
|
||||
{
|
||||
id: "gpt-4o",
|
||||
name: "GPT-4o",
|
||||
provider: "codex",
|
||||
modelString: "gpt-4o",
|
||||
requiresApiKey: "OPENAI_API_KEY",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
- Model categories: `claude`, `openai`, `azure`, `custom`
|
||||
|
||||
#### 2.2 Codex Configuration Manager
|
||||
|
||||
**File**: `app/electron/services/codex-config-manager.js`
|
||||
|
||||
- Manages Codex TOML config file (typically `~/.config/codex/config.toml` or project-specific)
|
||||
- Creates/updates model provider configurations:
|
||||
```toml
|
||||
[model_providers.openai-chat-completions]
|
||||
name = "OpenAI using Chat Completions"
|
||||
base_url = "https://api.openai.com/v1"
|
||||
env_key = "OPENAI_API_KEY"
|
||||
wire_api = "chat"
|
||||
|
||||
[profiles.gpt4o]
|
||||
model = "gpt-4o"
|
||||
model_provider = "openai-chat-completions"
|
||||
```
|
||||
|
||||
- Profile management for different use cases
|
||||
- Validates configuration before execution
|
||||
|
||||
### Phase 3: Execution Integration
|
||||
|
||||
#### 3.1 Update Feature Executor
|
||||
|
||||
**File**: `app/electron/services/feature-executor.js`
|
||||
|
||||
- Replace direct SDK calls with model provider abstraction
|
||||
- Update `getModelString()` to return model ID instead of string
|
||||
- Add `getModelProvider(modelId)` method
|
||||
- Modify `implementFeature()` to:
|
||||
- Get provider for selected model
|
||||
- Use provider's `executeQuery()` method
|
||||
- Handle different response formats (SDK vs CLI JSON)
|
||||
|
||||
#### 3.2 Update Agent Service
|
||||
|
||||
**File**: `app/electron/agent-service.js`
|
||||
|
||||
- Replace hardcoded model with configurable model selection
|
||||
- Use model provider abstraction
|
||||
- Support model selection per session
|
||||
|
||||
#### 3.3 Update Project Analyzer
|
||||
|
||||
**File**: `app/electron/services/project-analyzer.js`
|
||||
|
||||
- Use model provider abstraction
|
||||
- Make model configurable (currently hardcoded to sonnet)
|
||||
|
||||
#### 3.4 Update API Route
|
||||
|
||||
**File**: `app/src/app/api/chat/route.ts`
|
||||
|
||||
- Support model selection from request
|
||||
- Use model provider abstraction (if running in Electron context)
|
||||
- Fallback to Claude SDK for web-only usage
|
||||
|
||||
### Phase 4: Codex CLI Execution Wrapper
|
||||
|
||||
#### 4.1 Codex Executor
|
||||
|
||||
**File**: `app/electron/services/codex-executor.js`
|
||||
|
||||
- Wraps `codex exec` command execution
|
||||
- Handles subprocess spawning with proper environment variables
|
||||
- Parses JSON output (JSONL format from `--json` flag)
|
||||
- Converts Codex output format to match Claude SDK message format
|
||||
- Handles streaming responses
|
||||
- Error handling and timeout management
|
||||
|
||||
#### 4.2 Message Format Conversion
|
||||
|
||||
**File**: `app/electron/services/message-converter.js`
|
||||
|
||||
- Converts Codex JSONL output to Claude SDK message format
|
||||
- Maps Codex events:
|
||||
- `thread.started` → session initialization
|
||||
- `item.completed` (reasoning) → thinking output
|
||||
- `item.completed` (command_execution) → tool use
|
||||
- `item.completed` (agent_message) → assistant message
|
||||
- Maintains compatibility with existing UI components
|
||||
|
||||
### Phase 5: UI Updates
|
||||
|
||||
#### 5.1 Update Type Definitions
|
||||
|
||||
**File**: `app/src/store/app-store.ts`
|
||||
|
||||
- Extend `AgentModel` type to include OpenAI models:
|
||||
```typescript
|
||||
export type AgentModel =
|
||||
| "opus" | "sonnet" | "haiku" // Claude
|
||||
| "gpt-4o" | "gpt-4o-mini" | "gpt-3.5-turbo" | "o3" | "o1"; // OpenAI
|
||||
```
|
||||
|
||||
- Add `modelProvider` field to `Feature` interface
|
||||
- Add provider metadata to model selection
|
||||
|
||||
#### 5.2 Update Board View
|
||||
|
||||
**File**: `app/src/components/views/board-view.tsx`
|
||||
|
||||
- Expand model dropdown to include OpenAI models
|
||||
- Group models by provider (Claude / OpenAI)
|
||||
- Show provider badges/icons
|
||||
- Display model availability based on CLI detection
|
||||
- Add tooltips showing model capabilities
|
||||
|
||||
#### 5.3 Update Settings View
|
||||
|
||||
**File**: `app/src/components/views/settings-view.tsx`
|
||||
|
||||
- Add OpenAI API key input field (similar to Anthropic key)
|
||||
- Add Codex CLI status check (similar to Claude CLI check)
|
||||
- Show installation instructions if Codex CLI not detected
|
||||
- Add test connection button for OpenAI API
|
||||
- Display detected Codex CLI version/path
|
||||
|
||||
#### 5.4 Create API Test Route
|
||||
|
||||
**File**: `app/src/app/api/openai/test/route.ts`
|
||||
|
||||
- Similar to `app/src/app/api/claude/test/route.ts`
|
||||
- Test OpenAI API connection
|
||||
- Validate API key format
|
||||
- Return connection status
|
||||
|
||||
### Phase 6: Configuration & Environment
|
||||
|
||||
#### 6.1 Environment Variable Management
|
||||
|
||||
**File**: `app/electron/services/env-manager.js`
|
||||
|
||||
- Centralized environment variable handling
|
||||
- Loads from `.env` file and system environment
|
||||
- Validates required variables per provider
|
||||
- Provides fallback mechanisms
|
||||
|
||||
#### 6.2 IPC Handlers for Model Management
|
||||
|
||||
**File**: `app/electron/main.js`
|
||||
|
||||
- Add IPC handlers:
|
||||
- `model:checkCodexCli` - Check Codex CLI installation
|
||||
- `model:getAvailableModels` - List available models per provider
|
||||
- `model:testOpenAI` - Test OpenAI API connection
|
||||
- `model:updateCodexConfig` - Update Codex TOML config
|
||||
|
||||
#### 6.3 Preload API Updates
|
||||
|
||||
**File**: `app/electron/preload.js`
|
||||
|
||||
- Expose new IPC methods to renderer
|
||||
- Add TypeScript definitions in `app/src/types/electron.d.ts`
|
||||
|
||||
### Phase 7: Error Handling & Fallbacks
|
||||
|
||||
#### 7.1 Provider Fallback Logic
|
||||
|
||||
- If Codex CLI not available, fallback to Claude
|
||||
- If OpenAI API key missing, show clear error messages
|
||||
- Graceful degradation when provider unavailable
|
||||
|
||||
#### 7.2 Error Messages
|
||||
|
||||
- User-friendly error messages for missing CLI
|
||||
- Installation instructions per platform
|
||||
- API key validation errors
|
||||
- Model availability warnings
|
||||
|
||||
## File Structure Summary
|
||||
|
||||
### New Files
|
||||
|
||||
```
|
||||
app/electron/services/
|
||||
├── model-provider.js # Abstract provider interface
|
||||
├── claude-provider.js # Claude SDK wrapper
|
||||
├── codex-provider.js # Codex CLI wrapper
|
||||
├── codex-cli-detector.js # Codex CLI detection
|
||||
├── codex-executor.js # Codex CLI execution wrapper
|
||||
├── codex-config-manager.js # TOML config management
|
||||
├── model-registry.js # Centralized model definitions
|
||||
├── message-converter.js # Format conversion utilities
|
||||
└── env-manager.js # Environment variable management
|
||||
|
||||
app/src/app/api/openai/
|
||||
└── test/route.ts # OpenAI API test endpoint
|
||||
```
|
||||
|
||||
### Modified Files
|
||||
|
||||
```
|
||||
app/electron/services/
|
||||
├── feature-executor.js # Use model provider abstraction
|
||||
├── agent-service.js # Support multiple providers
|
||||
└── project-analyzer.js # Configurable model selection
|
||||
|
||||
app/electron/
|
||||
├── main.js # Add IPC handlers
|
||||
└── preload.js # Expose new APIs
|
||||
|
||||
app/src/
|
||||
├── store/app-store.ts # Extended model types
|
||||
├── components/views/
|
||||
│ ├── board-view.tsx # Expanded model selection UI
|
||||
│ └── settings-view.tsx # OpenAI API key & Codex CLI status
|
||||
└── types/electron.d.ts # Updated IPC type definitions
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Codex CLI Execution Pattern
|
||||
|
||||
```javascript
|
||||
// Example execution flow
|
||||
const codexExecutor = require('./codex-executor');
|
||||
const result = await codexExecutor.execute({
|
||||
prompt: "Implement feature X",
|
||||
model: "gpt-4o",
|
||||
cwd: projectPath,
|
||||
systemPrompt: "...",
|
||||
maxTurns: 20,
|
||||
allowedTools: ["Read", "Write", "Edit", "Bash"],
|
||||
env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY }
|
||||
});
|
||||
```
|
||||
|
||||
### Model Provider Interface
|
||||
|
||||
```javascript
|
||||
class ModelProvider {
|
||||
async executeQuery(options) {
|
||||
// Returns async generator of messages
|
||||
}
|
||||
|
||||
async detectInstallation() {
|
||||
// Returns installation status
|
||||
}
|
||||
|
||||
getAvailableModels() {
|
||||
// Returns list of supported models
|
||||
}
|
||||
|
||||
validateConfig() {
|
||||
// Validates provider configuration
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration File Location
|
||||
|
||||
- User config: `~/.config/codex/config.toml` (or platform equivalent)
|
||||
- Project config: `.codex/config.toml` (optional, project-specific)
|
||||
- Fallback: In-memory config passed via CLI args
|
||||
|
||||
## Testing Considerations
|
||||
|
||||
1. **CLI Detection**: Test on macOS, Linux, Windows
|
||||
2. **Model Execution**: Test with different OpenAI models
|
||||
3. **Error Handling**: Test missing CLI, invalid API keys, network errors
|
||||
4. **Format Conversion**: Verify message format compatibility
|
||||
5. **Concurrent Execution**: Test multiple features with different providers
|
||||
6. **Fallback Logic**: Test provider fallback scenarios
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
1. Update README with Codex CLI installation instructions:
|
||||
|
||||
- `npm install -g @openai/codex@latest` or `brew install codex`
|
||||
- ChatGPT Enterprise authentication (no API key needed)
|
||||
- API-based authentication for older models
|
||||
|
||||
2. Add model selection guide:
|
||||
|
||||
- GPT-5.1 Codex Max (default, best for coding)
|
||||
- o3/o4-mini with reasoning efforts
|
||||
- GPT-5.1/GPT-5 with verbosity control
|
||||
|
||||
3. Document reasoning effort and verbosity settings
|
||||
4. Add troubleshooting section for common issues
|
||||
5. Document model list discovery via MCP interface
|
||||
|
||||
## Migration Path
|
||||
|
||||
1. Implement provider abstraction alongside existing code
|
||||
2. Add Codex support without breaking existing Claude functionality
|
||||
3. Gradually migrate services to use abstraction layer
|
||||
4. Maintain backward compatibility during transition
|
||||
5. Remove hardcoded models after full migration
|
||||
34
app/package-lock.json
generated
34
app/package-lock.json
generated
@@ -24,6 +24,7 @@
|
||||
"@tanstack/react-query": "^5.90.12",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^17.2.3",
|
||||
"lucide-react": "^0.556.0",
|
||||
"next": "16.0.7",
|
||||
"react": "19.2.0",
|
||||
@@ -4687,6 +4688,19 @@
|
||||
"electron-builder-squirrel-windows": "26.0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
@@ -6308,10 +6322,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"dev": true,
|
||||
"version": "17.2.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
||||
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -6336,6 +6349,19 @@
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-expand/node_modules/dotenv": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"@tanstack/react-query": "^5.90.12",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^17.2.3",
|
||||
"lucide-react": "^0.556.0",
|
||||
"next": "16.0.7",
|
||||
"react": "19.2.0",
|
||||
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
TestTube,
|
||||
Settings2,
|
||||
RefreshCw,
|
||||
RotateCcw,
|
||||
Info,
|
||||
} from "lucide-react";
|
||||
import { getElectronAPI } from "@/lib/electron";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
@@ -52,6 +52,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { useSetupStore } from "@/store/setup-store";
|
||||
|
||||
// Navigation items for the side panel
|
||||
const NAV_ITEMS = [
|
||||
@@ -143,10 +144,15 @@ export function SettingsView() {
|
||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||
const [isCheckingClaudeCli, setIsCheckingClaudeCli] = useState(false);
|
||||
const [isCheckingCodexCli, setIsCheckingCodexCli] = useState(false);
|
||||
const [editingShortcut, setEditingShortcut] = useState<string | null>(null);
|
||||
const [shortcutValue, setShortcutValue] = useState("");
|
||||
const [shortcutError, setShortcutError] = useState<string | null>(null);
|
||||
const [apiKeyStatus, setApiKeyStatus] = useState<{
|
||||
hasAnthropicKey: boolean;
|
||||
hasOpenAIKey: boolean;
|
||||
hasGoogleKey: boolean;
|
||||
} | null>(null);
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Get authentication status from setup store
|
||||
const { claudeAuthStatus, codexAuthStatus } = useSetupStore();
|
||||
|
||||
useEffect(() => {
|
||||
setAnthropicKey(apiKeys.anthropic);
|
||||
@@ -173,6 +179,21 @@ export function SettingsView() {
|
||||
console.error("Failed to check Codex CLI status:", error);
|
||||
}
|
||||
}
|
||||
// Check API key status from environment
|
||||
if (api?.setup?.getApiKeys) {
|
||||
try {
|
||||
const status = await api.setup.getApiKeys();
|
||||
if (status.success) {
|
||||
setApiKeyStatus({
|
||||
hasAnthropicKey: status.hasAnthropicKey,
|
||||
hasOpenAIKey: status.hasOpenAIKey,
|
||||
hasGoogleKey: status.hasGoogleKey,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to check API key status:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
checkCliStatus();
|
||||
}, []);
|
||||
@@ -747,6 +768,176 @@ export function SettingsView() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Authentication Status Display */}
|
||||
<div className="space-y-4 pt-4 border-t border-border">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Info className="w-4 h-4 text-brand-500" />
|
||||
<Label className="text-foreground font-semibold">
|
||||
Current Authentication Configuration
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{/* Claude Authentication Status */}
|
||||
<div className="p-3 rounded-lg bg-card border border-border">
|
||||
<div className="flex items-center gap-2 mb-1.5">
|
||||
<Terminal className="w-4 h-4 text-brand-500" />
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
Claude (Anthropic)
|
||||
</span>
|
||||
</div>
|
||||
<div className="space-y-1.5 text-xs min-h-[3rem]">
|
||||
{claudeAuthStatus?.authenticated ? (
|
||||
<>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-3 h-3 text-green-500 shrink-0" />
|
||||
<span className="text-muted-foreground">
|
||||
Method:{" "}
|
||||
<span className="font-mono text-foreground">
|
||||
{claudeAuthStatus.method === "oauth"
|
||||
? "OAuth Token"
|
||||
: claudeAuthStatus.method === "api_key"
|
||||
? "API Key"
|
||||
: "Unknown"}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
{claudeAuthStatus.oauthTokenValid && (
|
||||
<div className="flex items-center gap-2 text-green-400">
|
||||
<CheckCircle2 className="w-3 h-3 shrink-0" />
|
||||
<span>OAuth token configured</span>
|
||||
</div>
|
||||
)}
|
||||
{claudeAuthStatus.apiKeyValid && (
|
||||
<div className="flex items-center gap-2 text-green-400">
|
||||
<CheckCircle2 className="w-3 h-3 shrink-0" />
|
||||
<span>API key configured</span>
|
||||
</div>
|
||||
)}
|
||||
{apiKeyStatus?.hasAnthropicKey && (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Environment variable detected</span>
|
||||
</div>
|
||||
)}
|
||||
{apiKeys.anthropic && (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Manual API key in settings</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : apiKeyStatus?.hasAnthropicKey ? (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Using environment variable (ANTHROPIC_API_KEY)</span>
|
||||
</div>
|
||||
) : apiKeys.anthropic ? (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Using manual API key from settings</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-1.5 text-muted-foreground py-0.5">
|
||||
<AlertCircle className="w-2.5 h-2.5 shrink-0" />
|
||||
<span className="text-xs">Not Setup</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Codex/OpenAI Authentication Status */}
|
||||
<div className="p-3 rounded-lg bg-card border border-border">
|
||||
<div className="flex items-center gap-2 mb-1.5">
|
||||
<Atom className="w-4 h-4 text-green-500" />
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
Codex (OpenAI)
|
||||
</span>
|
||||
</div>
|
||||
<div className="space-y-1.5 text-xs min-h-[3rem]">
|
||||
{codexAuthStatus?.authenticated ? (
|
||||
<>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle2 className="w-3 h-3 text-green-500 shrink-0" />
|
||||
<span className="text-muted-foreground">
|
||||
Method:{" "}
|
||||
<span className="font-mono text-foreground">
|
||||
{codexAuthStatus.method === "api_key"
|
||||
? "API Key (Auth File)"
|
||||
: codexAuthStatus.method === "env"
|
||||
? "API Key (Environment)"
|
||||
: "Unknown"}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
{codexAuthStatus.apiKeyValid && (
|
||||
<div className="flex items-center gap-2 text-green-400">
|
||||
<CheckCircle2 className="w-3 h-3 shrink-0" />
|
||||
<span>API key configured</span>
|
||||
</div>
|
||||
)}
|
||||
{apiKeyStatus?.hasOpenAIKey && (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Environment variable detected</span>
|
||||
</div>
|
||||
)}
|
||||
{apiKeys.openai && (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Manual API key in settings</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : apiKeyStatus?.hasOpenAIKey ? (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Using environment variable (OPENAI_API_KEY)</span>
|
||||
</div>
|
||||
) : apiKeys.openai ? (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Using manual API key from settings</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-1.5 text-muted-foreground py-0.5">
|
||||
<AlertCircle className="w-2.5 h-2.5 shrink-0" />
|
||||
<span className="text-xs">Not Setup</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Google/Gemini Authentication Status */}
|
||||
<div className="p-3 rounded-lg bg-card border border-border">
|
||||
<div className="flex items-center gap-2 mb-1.5">
|
||||
<Sparkles className="w-4 h-4 text-purple-500" />
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
Gemini (Google)
|
||||
</span>
|
||||
</div>
|
||||
<div className="space-y-1.5 text-xs min-h-[3rem]">
|
||||
{apiKeyStatus?.hasGoogleKey ? (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Using environment variable (GOOGLE_API_KEY)</span>
|
||||
</div>
|
||||
) : apiKeys.google ? (
|
||||
<div className="flex items-center gap-2 text-blue-400">
|
||||
<Info className="w-3 h-3 shrink-0" />
|
||||
<span>Using manual API key from settings</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-1.5 text-muted-foreground py-0.5">
|
||||
<AlertCircle className="w-2.5 h-2.5 shrink-0" />
|
||||
<span className="text-xs">Not Setup</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Security Notice */}
|
||||
<div className="flex items-start gap-3 p-4 rounded-lg bg-yellow-500/10 border border-yellow-500/20">
|
||||
<AlertCircle className="w-5 h-5 text-yellow-500 mt-0.5 shrink-0" />
|
||||
|
||||
Reference in New Issue
Block a user