-
Notifications
You must be signed in to change notification settings - Fork 491
feat: unified Claude API key and profile system with per-project overrides (z.AI, MiniMax, OpenRouter) #599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Introduce APP_HOST variable to allow custom hostname configuration for the web server. Default to localhost if VITE_HOSTNAME is not set. Update relevant URLs and CORS origins to use APP_HOST, enhancing flexibility for local development and deployment. This change improves the application's adaptability to different environments.
Updated the process termination logic in ClaudeUsageService to handle Windows environments correctly. The code now checks the operating system and calls the appropriate kill method, ensuring consistent behavior across platforms.
Refactored the process termination logic in both ClaudeUsageService and TerminalService to use a centralized method for killing PTY processes. This ensures consistent handling of process termination across Windows and Unix-like systems, improving reliability and maintainability of the code.
…ests Added a mock for the Unix platform in the SIGTERM test case to ensure proper behavior during testing on non-Windows systems. This change enhances the reliability of the tests by simulating the expected environment for process termination.
Add support for managing multiple Claude-compatible API endpoints (z.AI GLM, AWS Bedrock, etc.) through provider profiles in settings. Features: - New ClaudeApiProfile type with base URL, API key, model mappings - Pre-configured z.AI GLM template with correct model names - Profile selector in Settings > Claude > API Profiles - Clean switching between profiles and direct Anthropic API - Immediate persistence to prevent data loss on restart Profile support added to all execution paths: - Agent service (chat) - Ideation service - Auto-mode service (feature agents, enhancements) - Simple query service (title generation, descriptions, etc.) - Backlog planning, commit messages, spec generation - GitHub issue validation, suggestions Environment variables set when profile is active: - ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN/API_KEY - ANTHROPIC_DEFAULT_HAIKU/SONNET/OPUS_MODEL - API_TIMEOUT_MS, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
Resolved conflict in terminal-service.ts by accepting upstream Electron detection properties alongside local Windows termination fixes.
…upport The `./start-automaker.sh` script doesn't work when invoked from Windows CMD or PowerShell because: 1. The `./` prefix is Unix-style path notation 2. Windows shells don't execute .sh files directly This adds a Node.js launcher (`start-automaker.mjs`) that: - Detects the platform and finds bash (Git Bash, MSYS2, Cygwin, or WSL) - Converts Windows paths to Unix-style for bash compatibility - Passes all arguments through to the original bash script - Provides helpful error messages if bash isn't found The npm scripts now use `node start-automaker.mjs` which works on all platforms while preserving the full functionality of the bash TUI launcher.
- Remove duplicate killPtyProcess method in claude-usage-service.ts - Import and use spawnSync correctly instead of spawn.sync - Fix misleading comment about shell option and signal handling
- Add convertPathForBash() function that detects bash variant: - Cygwin: /cygdrive/c/path - WSL: /mnt/c/path - MSYS/Git Bash: /c/path - Update exit handler to properly handle signal termination (exit code 1 when killed by signal vs code from child) Addresses remaining CodeRabbit PR AutoMaker-Org#586 recommendations. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added handlers for theme submenu to manage mouse enter/leave events with a delay, preventing premature closure. - Implemented dynamic positioning for the submenu to avoid viewport overflow, ensuring better visibility. - Updated styles to accommodate new positioning logic and added scroll functionality for theme selection. These changes improve user experience by making the theme selection process more intuitive and visually accessible.
- Add detectBashVariant() that checks $OSTYPE for reliable WSL/MSYS/Cygwin detection instead of relying solely on executable path - Add input validation to convertPathForBash() to catch null/undefined args - Add validate_port() function in bash script to reject invalid port input (non-numeric, out of range) with clear error messages Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Collect web and server port inputs first, then validate both before assigning to global variables. This prevents WEB_PORT from being modified when SERVER_PORT validation subsequently fails. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…roject-theme-ui-overlap fix: enhance project context menu with theme submenu improvements
…r-compatibility fix: add cross-platform Node.js launcher for Windows CMD/PowerShell support
…ode-max-glm-api-keys
- Add ApiKeySource type ('inline' | 'env' | 'credentials') to ClaudeApiProfile
- Allow profiles to source API keys from credentials.json or environment variables
- Add provider templates: OpenRouter, MiniMax, MiniMax (China)
- Auto-migrate existing users with Anthropic key to "Direct Anthropic" profile
- Update all API call sites to pass credentials for key resolution
- Add API key source selector to profile creation UI
- Increment settings version to 5 for migration support
This allows users to:
- Share a single API key across multiple profile configurations
- Use environment variables for CI/CD deployments
- Easily switch between providers without re-entering keys
Allow users to override the global Claude API profile on a per-project basis. This enables experimentation with alternative providers (z.AI GLM, MiniMax, etc.) on specific projects while keeping others on Direct Anthropic. Changes: - Add activeClaudeApiProfileId to ProjectSettings type - Update getActiveClaudeApiProfile() to check project settings first - Pass projectPath to all server call sites (14 files) - Add Claude section to Project Settings UI with profile selector - Add setProjectClaudeApiProfile store action with server persistence - Update project settings loader to restore per-project profile - Document per-project override in UNIFIED_API_KEY_PROFILES.md Note: This only affects Claude model calls. When using Codex, OpenCode, or Cursor models, the Claude API profile setting has no effect.
Keep DATA_DIR export from feature branch and adopt improved CORS_ORIGINS handling from main that ensures localhost and 127.0.0.1 are always included for local development.
Updated enhance-prompt and generate-title endpoints to accept and use projectPath, ensuring per-project Claude API profile selection works correctly for these operations. Changes: - enhance.ts: Accept projectPath in request body, pass to getActiveClaudeApiProfile - generate-title.ts: Accept projectPath in request body, pass to getActiveClaudeApiProfile - http-api-client.ts: Update both API calls to accept projectPath - electron.ts: Update interface for both endpoints - enhance-with-ai.tsx: Get currentProject.path from store and pass it - use-board-actions.ts: Pass projectPath to generateTitle call All 16 call sites now pass project context to getActiveClaudeApiProfile().
Added claudeApiProfiles and activeClaudeApiProfileId to the buildSettingsUpdateFromStore() function so that Claude API profiles are properly persisted to the server settings file. Previously, profiles were only stored in Zustand state but not synced to the server, causing them to be lost on hot reload.
Two issues were preventing Claude API profiles from persisting: 1. Server: claudeApiProfiles was not protected against accidental empty array overwrites - added to ignoreEmptyArrayOverwrite list 2. UI: hydrateStoreFromSettings() was not loading claudeApiProfiles and activeClaudeApiProfileId from server settings into Zustand store Now profiles will properly survive browser refreshes and hot reloads.
When setting activeClaudeApiProfileId to undefined (meaning "use global"), the JavaScript spread operator was ignoring it, keeping the old value. Now explicitly delete the key when undefined is passed, so the project properly falls back to the global setting.
JavaScript/JSON doesn't serialize undefined values, so when the UI tried
to send {activeClaudeApiProfileId: undefined} to clear the project override,
the key was simply not included in the request.
Solution: Use "__USE_GLOBAL__" marker string when selecting "Use Global Setting".
The server detects this marker and deletes the key from project settings,
properly falling back to global configuration.
Prevent users from creating profiles with duplicate names (case-insensitive). Shows an error message under the name field and disables the save button when a duplicate is detected.
Added an info box below the Anthropic API Key field explaining: - How to use this key with Claude API Profiles (credentials source) - How to configure alternative providers (inline key source) This helps users understand the relationship between the API Keys section and the Claude API Profiles feature.
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughIntroduces per-project and global Claude API profile support with credentials management across the application. Adds new types, settings helpers, and provider updates to resolve and use active profiles. Extends UI with profile management components, includes auto-migration for existing API keys, and updates launcher infrastructure. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Client UI
participant Store as App Store
participant Server as Server Routes
participant Helper as Settings Helper
participant Provider as Claude Provider
participant Anthropic as Anthropic API
UI->>Store: Fetch active Claude profile
Store->>Store: Get currentProject & global settings
Note over Store: Determine active profile<br/>(project override or global)
UI->>Server: Execute query with projectPath
Server->>Helper: getActiveClaudeApiProfile(settingsService, projectPath)
Helper->>Helper: Check project-level override
alt Project override exists
Helper->>Helper: Use project activeClaudeApiProfileId
else Project override undefined
Helper->>Helper: Use global activeClaudeApiProfileId
end
Helper->>Helper: Resolve credentials based on apiKeySource
Helper-->>Server: Return {profile, credentials}
Server->>Provider: executeQuery(options, claudeApiProfile, credentials)
Provider->>Provider: buildEnv(profile, credentials)
alt apiKeySource = 'inline'
Provider->>Provider: Use profile.apiKey
else apiKeySource = 'env'
Provider->>Provider: Use process.env.ANTHROPIC_API_KEY
else apiKeySource = 'credentials'
Provider->>Provider: Use credentials.anthropic.apiKey
end
Provider->>Provider: Configure endpoint & models from profile
Provider->>Anthropic: Send request with configured env
Anthropic-->>Provider: Response
Provider-->>Server: Streamed/queried result
Server-->>UI: Response with generated content
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @stefandevo, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the flexibility and usability of Claude API configurations by introducing a unified profile system. Users can now define how their API keys are sourced (inline, environment variable, or global credentials) and apply these configurations globally or override them on a per-project basis. This change streamlines the management of various Claude-compatible endpoints, supports diverse use cases like experimentation and regional compliance, and includes a smooth migration path for existing users, all while improving the overall user experience. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a unified Claude API key and profile system, allowing users to configure Claude-compatible API endpoints with flexible API key sourcing strategies (inline, environment variable, or saved credentials). A new getActiveClaudeApiProfile helper function retrieves the active profile and credentials, which are then passed to various AI operations across the server, including agent chat, code analysis, and spec generation. A settings migration automatically creates a 'Direct Anthropic' profile for existing users with saved Anthropic API keys. The UI is updated with a new 'AI Providers → Claude' settings section to manage these API profiles, and a 'Project Settings → Claude' section to allow per-project overrides of the active Claude API profile. Additionally, the UI for theme selection in project menus has been refined with improved viewport-aware positioning and delayed hover handling for better user experience. Review comments highlighted the need to handle undefined API keys in the UI's maskApiKey function and to simplify the logic for falling back to global settings in getActiveClaudeApiProfile.
| function maskApiKey(key: string): string { | ||
| if (key.length <= 8) return '••••••••'; | ||
| return `${key.substring(0, 4)}••••${key.substring(key.length - 4)}`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The maskApiKey function expects a string argument, but it can be called with profile.apiKey which can be undefined when the apiKeySource is not 'inline'. This will cause a runtime error. Please update the function signature to handle string | undefined | null and return a default value for non-string inputs.
| function maskApiKey(key: string): string { | |
| if (key.length <= 8) return '••••••••'; | |
| return `${key.substring(0, 4)}••••${key.substring(key.length - 4)}`; | |
| } | |
| function maskApiKey(key: string | undefined | null): string { | |
| if (!key || key.length <= 8) return '••••••••'; | |
| return `${key.substring(0, 4)}••••${key.substring(key.length - 4)}`; | |
| } |
| if (activeProfileId === undefined && !isProjectOverride) { | ||
| activeProfileId = globalSettings.activeClaudeApiProfileId; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic for falling back to the global profile is correct, but it could be simplified for better readability. Using the isProjectOverride flag directly makes the intent clearer.
| if (activeProfileId === undefined && !isProjectOverride) { | |
| activeProfileId = globalSettings.activeClaudeApiProfileId; | |
| } | |
| if (!isProjectOverride) { | |
| activeProfileId = globalSettings.activeClaudeApiProfileId; | |
| } |
| </div> | ||
| <p className="text-xs text-muted-foreground truncate mt-1">{profile.baseUrl}</p> | ||
| <div className="flex flex-wrap items-center gap-x-4 gap-y-1 mt-2 text-xs text-muted-foreground"> | ||
| <span>Key: {maskApiKey(profile.apiKey)}</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UI currently tries to mask the API key regardless of its source. When the source is 'credentials' or 'env', profile.apiKey is undefined, and the UI shows a masked value which is misleading. It would be clearer to display the source of the key instead of always showing a masked value.
| <span>Key: {maskApiKey(profile.apiKey)}</span> | |
| <span>Key: {profile.apiKeySource === 'inline' ? maskApiKey(profile.apiKey) : profile.apiKeySource === 'credentials' ? 'From API Keys' : 'From Environment'}</span> |
Summary
This PR implements a unified Claude API key and profile system that allows flexible configuration of how API keys are resolved, plus per-project profile overrides.
Key Features
Flexible API Key Sourcing: Profiles can now source their API key from:
inline- Key stored directly in the profile (for alternative providers)credentials- Uses the Anthropic key from Settings → API Keysenv- UsesANTHROPIC_API_KEYenvironment variablePer-Project Profile Overrides: Each project can override the global Claude API profile, enabling:
New Provider Templates: Added templates for OpenRouter, z.AI GLM, MiniMax, and MiniMax (China)
UX Improvements:
Documentation
See docs/UNIFIED_API_KEY_PROFILES.md for complete implementation details including:
Changes
Types (
libs/types/src/settings.ts)ApiKeySourcetype ('inline' | 'env' | 'credentials')apiKeySourcefield toClaudeApiProfileactiveClaudeApiProfileIdtoProjectSettingsServer
getActiveClaudeApiProfile()to check project settings firstprojectPathparameter to all 16 Claude API call sitesclaudeApiProfilesfrom accidental empty array overwritesUI
ProjectClaudeSectioncomponent for per-project profile selectionclaudeApiProfilesandactiveClaudeApiProfileIdTesting
Summary by CodeRabbit
New Features
Improvements
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.