-
-
Notifications
You must be signed in to change notification settings - Fork 985
feat: Support third-party API providers and project-level DEFAULT_BRANCH #626
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
base: develop
Are you sure you want to change the base?
feat: Support third-party API providers and project-level DEFAULT_BRANCH #626
Conversation
This commit adds two important features: 1. Third-party API Provider Support (auth.py): - Read env vars from active profile's settings.json (configDir/settings.json) - Support ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, and model overrides - Enable usage of Minimax, OpenRouter, and other Claude-compatible APIs - Maintain backward compatibility with existing OAuth flow 2. Project-level DEFAULT_BRANCH (worktree.py): - Read DEFAULT_BRANCH from project's .auto-claude/.env file - System environment variable still takes priority - Allows per-project branch configuration without modifying system env Priority order for DEFAULT_BRANCH: 1. System environment variable 2. Project's .auto-claude/.env file 3. Auto-detect main/master 4. Current branch (fallback) Priority order for auth token: 1. System env (CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_AUTH_TOKEN) 2. Profile settings.json env section 3. System credential store (Keychain/Credential Manager) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
|
Spark seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
📝 WalkthroughWalkthroughThis pull request introduces profile-aware environment configuration to the authentication system. New helper functions read the active UI profile's settings to source environment variables for authentication tokens and third-party provider configuration. Additionally, base-branch detection now checks project-level .env files before falling back to auto-detection. Changes
Sequence Diagram(s)sequenceDiagram
participant App as App
participant Auth as auth.py
participant UIConfig as UI Config Files
participant Profile as Active Profile
participant Env as System Environment
App->>Auth: get_auth_token()
Auth->>Auth: Locate UI config directory
Auth->>UIConfig: Load settings.json
UIConfig-->>Auth: Config data
Auth->>Profile: Extract active profile ID
Auth->>Profile: Load profile/settings.json
Profile-->>Auth: Profile env vars (ANTHROPIC_AUTH_TOKEN, etc.)
alt Profile value found
Auth-->>App: Return token from profile
else Profile value not found
Auth->>Env: Check system environment variables
Env-->>Auth: Env var value
Auth-->>App: Return token from system
end
rect rgb(240, 248, 255)
note over Auth,Profile: Profile-aware configuration<br/>New prioritization: profile → system env → credential store
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ 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 @aw338WoWmUI, 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 configuration flexibility of Auto Claude by introducing support for third-party API providers and enabling project-specific default branch settings. These changes allow users to seamlessly integrate with alternative Claude-compatible services and tailor branch configurations to individual project needs, improving adaptability and 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.
🎉 Thanks for your first PR!
A maintainer will review it soon. Please make sure:
- Your branch is synced with
develop - CI checks pass
- You've followed our contribution guide
Welcome to the Auto Claude community!
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 valuable flexibility by adding support for third-party API providers and project-level default branch configuration. The changes are well-implemented and align with the stated goals. My review includes suggestions to enhance robustness by improving exception handling, fixing a bug related to environment variable priority, and pointing out some minor inefficiencies for potential optimization. Overall, these are solid improvements to the project.
| for var in SDK_ENV_VARS: | ||
| value = os.environ.get(var) | ||
| if value: | ||
| env[var] = value |
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 overriding with system environment variables is incomplete. It only iterates over SDK_ENV_VARS, which no longer includes model-related variables like ANTHROPIC_MODEL. This means if a user sets ANTHROPIC_MODEL as a system environment variable, it will be ignored, which breaks the expected priority of system environment variables over profile settings. The loop should iterate over all possible SDK-related variables to ensure system environment variables always take precedence.
| for var in SDK_ENV_VARS: | |
| value = os.environ.get(var) | |
| if value: | |
| env[var] = value | |
| all_sdk_vars = set(SDK_ENV_VARS) | set(PROFILE_ENV_VARS) | |
| for var in all_sdk_vars: | |
| value = os.environ.get(var) | |
| if value: | |
| env[var] = value |
| except (json.JSONDecodeError, KeyError, Exception): | ||
| pass |
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.
Using a broad except Exception: pass can hide bugs and make debugging difficult. It's better to catch more specific exceptions or at least log any unexpected errors to help with troubleshooting when reading profile data.
| except (json.JSONDecodeError, KeyError, Exception): | |
| pass | |
| except (json.JSONDecodeError, KeyError, Exception) as e: | |
| # Consider logging this exception for easier debugging. | |
| # For example: logging.warning(f"Failed to get active profile: {e}") | |
| pass |
| except (json.JSONDecodeError, KeyError, Exception): | ||
| return {} |
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.
Silently catching all exceptions with except Exception can hide underlying issues with settings.json files, such as file permission errors or malformed content. It's recommended to log the exception to make debugging easier.
| except (json.JSONDecodeError, KeyError, Exception): | |
| return {} | |
| except (json.JSONDecodeError, KeyError, Exception) as e: | |
| # Consider logging this exception for easier debugging. | |
| # For example: logging.warning(f"Failed to get profile env vars: {e}") | |
| return {} |
| profile_env = _get_profile_env_vars() | ||
| if "ANTHROPIC_AUTH_TOKEN" in profile_env: | ||
| profile = _get_active_profile() |
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.
There's a small inefficiency here. The _get_profile_env_vars() function already calls _get_active_profile() internally. By calling _get_active_profile() again on line 281, you're doing redundant work (e.g., reading and parsing config files twice). This could be optimized by modifying _get_profile_env_vars to also return the profile it found, or by caching the result of _get_active_profile().
| profile = _get_active_profile() | ||
| if not profile: | ||
| return None | ||
|
|
||
| profile_env = _get_profile_env_vars() |
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.
Similar to another function in this file, there's a redundant call pattern. _get_active_profile() is called on line 395, and then _get_profile_env_vars() on line 399 calls it again internally. This results in reading and parsing configuration files twice. To improve efficiency, you could pass the profile object to a modified _get_profile_env_vars or have it return the profile along with the environment variables.
| except Exception: | ||
| pass |
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 except Exception: pass is too broad and will silently ignore all errors during .env file processing, such as permission errors or encoding issues. This can make it very difficult to diagnose problems. It's better to log the exception to provide visibility into potential issues.
| except Exception: | |
| pass | |
| except Exception as e: | |
| # Consider logging the exception for debugging purposes, e.g.: | |
| # import logging | |
| # logging.warning(f"Error loading .env file {env_path}: {e}") | |
| pass |
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.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/backend/core/worktree.py (2)
137-154: Fix stale comment numbering.The inline comments are out of sync with the updated docstring. After adding the project
.envcheck as step 2, these comments still reference the old numbering.🔎 Proposed fix
- # 2. Auto-detect main/master + # 3. Auto-detect main/master for branch in ["main", "master"]: result = subprocess.run( ["git", "rev-parse", "--verify", branch], cwd=self.project_dir, capture_output=True, text=True, encoding="utf-8", errors="replace", ) if result.returncode == 0: return branch - # 3. Fall back to current branch with warning + # 4. Fall back to current branch with warning current = self._get_current_branch()
152-155: Consider updating the tip to mention both configuration options.The tip only mentions
.envbut doesn't clarify which one. Since this PR adds project-level.auto-claude/.envsupport, the message could guide users to both options.🔎 Proposed improvement
print("Warning: Could not find 'main' or 'master' branch.") print(f"Warning: Using current branch '{current}' as base for worktree.") - print("Tip: Set DEFAULT_BRANCH=your-branch in .env to avoid this.") + print("Tip: Set DEFAULT_BRANCH in system env or .auto-claude/.env to specify the base branch.")apps/backend/core/auth.py (1)
271-295: Minor redundancy in profile fetching.
_get_profile_env_vars()(line 279) internally calls_get_active_profile(), then line 281 calls_get_active_profile()again. This results in reading and parsing the JSON file twice. Not critical since this isn't a hot path, but could be optimized.🔎 Proposed optimization
# Check profile settings - profile_env = _get_profile_env_vars() - if "ANTHROPIC_AUTH_TOKEN" in profile_env: - profile = _get_active_profile() - if profile: - return f"Profile: {profile.get('name', profile.get('id', 'unknown'))}" + profile = _get_active_profile() + if profile: + profile_env = _get_profile_env_vars() + if "ANTHROPIC_AUTH_TOKEN" in profile_env: + return f"Profile: {profile.get('name', profile.get('id', 'unknown'))}"Note: This still has redundancy since
_get_profile_env_vars()calls_get_active_profile()internally. A more thorough refactor would pass the profile as a parameter or cache the result.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
apps/backend/core/auth.pyapps/backend/core/worktree.py
🧰 Additional context used
📓 Path-based instructions (2)
apps/backend/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
apps/backend/**/*.py: Always use the Claude Agent SDK (claude-agent-sdkpackage) for all AI interactions, never use the Anthropic API directly
Use thecreate_client()function fromapps/backend/core/client.pyto instantiate Claude SDK clients, not directClaudeSDKClientinitialization
Files:
apps/backend/core/auth.pyapps/backend/core/worktree.py
⚙️ CodeRabbit configuration file
apps/backend/**/*.py: Focus on Python best practices, type hints, and async patterns.
Check for proper error handling and security considerations.
Verify compatibility with Python 3.12+.
Files:
apps/backend/core/auth.pyapps/backend/core/worktree.py
apps/backend/core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement dynamic command allowlisting based on detected project stack using
core/security.pyfor bash command validation
Files:
apps/backend/core/auth.pyapps/backend/core/worktree.py
🔇 Additional comments (7)
apps/backend/core/worktree.py (1)
26-60: LGTM! Clean .env parser implementation.The function handles common .env file patterns well: comments, empty lines, quoted values, and missing files. The broad exception handling is acceptable here since this is configuration loading where graceful degradation is preferred.
One minor note: the quote removal logic (line 53) won't handle escaped quotes within strings (e.g.,
KEY="value with \" inside"), but this is likely fine for typical .env usage.apps/backend/core/auth.py (6)
38-49: LGTM! Good security practice with allowlist.Using an explicit allowlist of environment variables that can be loaded from profile settings is the right approach. This prevents arbitrary environment variable injection from user-controlled config files.
52-64: LGTM! Correct platform-specific config path handling.The function properly follows platform conventions for application configuration directories.
67-100: Acceptable implementation with a note on fallback behavior.The fallback to the first profile (lines 93-95) when
activeProfileIddoesn't match any profile could lead to unexpected behavior if the active profile was deleted or renamed. Consider logging a debug message when this fallback occurs to aid troubleshooting.
103-147: LGTM! Secure env var loading with proper filtering.Good implementation:
- Allowlist filtering via
PROFILE_ENV_VARSprevents arbitrary env var injection- Handles type conversion for boolean and non-string values
- Graceful error handling for malformed config files
240-268: LGTM! Clean integration of profile-based auth token resolution.The priority order is well-documented and correctly implemented:
- System env vars (CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_AUTH_TOKEN)
- Profile settings.json
- System credential store
339-370: LGTM! Correct priority order for SDK environment variables.Profile settings are loaded first (lower priority), then system environment variables override them (higher priority). This allows system-level configuration to take precedence while enabling profile-based defaults for third-party providers.
| def get_active_profile_info() -> dict | None: | ||
| """ | ||
| Get information about the currently active profile. | ||
| Returns: | ||
| Dict with profile info (id, name, configDir, isThirdParty) or None | ||
| """ | ||
| profile = _get_active_profile() | ||
| if not profile: | ||
| return None | ||
|
|
||
| profile_env = _get_profile_env_vars() | ||
| is_third_party = bool(profile_env.get("ANTHROPIC_BASE_URL")) | ||
|
|
||
| return { | ||
| "id": profile.get("id"), | ||
| "name": profile.get("name"), | ||
| "configDir": profile.get("configDir"), | ||
| "isThirdParty": is_third_party, | ||
| "baseUrl": profile_env.get("ANTHROPIC_BASE_URL", "https://api.anthropic.com"), | ||
| } |
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.
🧹 Nitpick | 🔵 Trivial
LGTM with same redundancy note.
The function provides useful profile metadata. Same observation as before: _get_profile_env_vars() (line 399) will call _get_active_profile() internally, duplicating the work done on line 395.
Consider refactoring the internal functions to accept an optional pre-fetched profile to avoid repeated file I/O, but this is a nice-to-have optimization.
🤖 Prompt for AI Agents
In apps/backend/core/auth.py around lines 388 to 408, the call to
_get_profile_env_vars() duplicates work because that helper re-calls
_get_active_profile(); modify _get_profile_env_vars to accept an optional
profile argument (defaulting to None) and use the already-fetched profile when
provided, then change this function to pass the local profile into
_get_profile_env_vars(profile) to avoid redundant file I/O; update other callers
of _get_profile_env_vars as needed to preserve behavior (use existing call with
no arg or pass a pre-fetched profile) and add minimal docstring/comments noting
the new parameter.
Summary
This PR adds two important features for flexibility in Auto Claude configuration:
1. Third-party API Provider Support (auth.py)
settings.json(viaconfigDir/settings.json)ANTHROPIC_BASE_URL,ANTHROPIC_AUTH_TOKEN, and model overridesSupported profile env vars:
ANTHROPIC_BASE_URLANTHROPIC_AUTH_TOKENANTHROPIC_MODELANTHROPIC_SMALL_FAST_MODELANTHROPIC_DEFAULT_SONNET_MODELANTHROPIC_DEFAULT_OPUS_MODELANTHROPIC_DEFAULT_HAIKU_MODELAPI_TIMEOUT_MSCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC2. Project-level DEFAULT_BRANCH (worktree.py)
DEFAULT_BRANCHfrom project's.auto-claude/.envfilePriority order for DEFAULT_BRANCH:
.auto-claude/.envfilePriority order for auth token:
CLAUDE_CODE_OAUTH_TOKEN,ANTHROPIC_AUTH_TOKEN)settings.jsonenv sectionMotivation
developinstead ofmain), but setting system env affects all projectsTest Plan
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.