feat: unified Claude API key and profile system with z.AI, MiniMax, OpenRouter support (#600)

* feat: add Claude API provider profiles for alternative endpoints

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
This commit is contained in:
Stefan de Vogelaere
2026-01-19 20:36:58 +01:00
committed by GitHub
parent 63b8eb0991
commit d97c4b7b57
45 changed files with 2661 additions and 146 deletions

View File

@@ -23,6 +23,7 @@ export function useProjectSettingsLoader() {
const setAutoDismissInitScriptIndicator = useAppStore(
(state) => state.setAutoDismissInitScriptIndicator
);
const setCurrentProject = useAppStore((state) => state.setCurrentProject);
const loadingRef = useRef<string | null>(null);
const currentProjectRef = useRef<string | null>(null);
@@ -107,6 +108,28 @@ export function useProjectSettingsLoader() {
result.settings.autoDismissInitScriptIndicator
);
}
// Apply activeClaudeApiProfileId if present
// This is stored directly on the project, so we need to update the currentProject
// Type assertion needed because API returns Record<string, unknown>
const settingsWithProfile = result.settings as Record<string, unknown>;
const activeClaudeApiProfileId = settingsWithProfile.activeClaudeApiProfileId as
| string
| null
| undefined;
if (activeClaudeApiProfileId !== undefined) {
const updatedProject = useAppStore.getState().currentProject;
if (
updatedProject &&
updatedProject.path === requestedProjectPath &&
updatedProject.activeClaudeApiProfileId !== activeClaudeApiProfileId
) {
setCurrentProject({
...updatedProject,
activeClaudeApiProfileId,
});
}
}
}
} catch (error) {
console.error('Failed to load project settings:', error);