hyp / docs /UNIFIED_API_KEY_PROFILES.md
Leon4gr45's picture
Upload folder using huggingface_hub
1dbc34b verified

Claude Compatible Providers System

This document describes the implementation of Claude Compatible Providers, allowing users to configure alternative API endpoints that expose Claude-compatible models to the application.

Overview

Claude Compatible Providers allow Automaker to work with third-party API endpoints that implement Claude's API protocol. This enables:

  • Cost savings: Use providers like z.AI GLM or MiniMax at lower costs
  • Alternative models: Access models like GLM-4.7 or MiniMax M2.1 through familiar interfaces
  • Flexibility: Configure per-phase model selection to optimize for speed vs quality
  • Project overrides: Use different providers for different projects

Architecture

Type Definitions

ClaudeCompatibleProvider

export interface ClaudeCompatibleProvider {
  id: string; // Unique identifier (UUID)
  name: string; // Display name (e.g., "z.AI GLM")
  baseUrl: string; // API endpoint URL
  providerType?: string; // Provider type for icon/grouping (e.g., 'glm', 'minimax', 'openrouter')
  apiKeySource?: ApiKeySource; // 'inline' | 'env' | 'credentials'
  apiKey?: string; // API key (when apiKeySource = 'inline')
  useAuthToken?: boolean; // Use ANTHROPIC_AUTH_TOKEN header
  timeoutMs?: number; // Request timeout in milliseconds
  disableNonessentialTraffic?: boolean; // Minimize non-essential API calls
  enabled?: boolean; // Whether provider is active (default: true)
  models?: ProviderModel[]; // Models exposed by this provider
}

ProviderModel

export interface ProviderModel {
  id: string; // Model ID sent to API (e.g., "GLM-4.7")
  displayName: string; // Display name in UI (e.g., "GLM 4.7")
  mapsToClaudeModel?: ClaudeModelAlias; // Which Claude tier this replaces ('haiku' | 'sonnet' | 'opus')
  capabilities?: {
    supportsVision?: boolean; // Whether model supports image inputs
    supportsThinking?: boolean; // Whether model supports extended thinking
    maxThinkingLevel?: ThinkingLevel; // Maximum thinking level if supported
  };
}

PhaseModelEntry

Phase model configuration now supports provider models:

export interface PhaseModelEntry {
  providerId?: string; // Provider ID (undefined = native Claude)
  model: string; // Model ID or alias
  thinkingLevel?: ThinkingLevel; // 'none' | 'low' | 'medium' | 'high'
}

Provider Templates

Available provider templates in CLAUDE_PROVIDER_TEMPLATES:

Template Provider Type Base URL Description
Direct Anthropic anthropic https://api.anthropic.com Standard Anthropic API
OpenRouter openrouter https://openrouter.ai/api Access Claude and 300+ models
z.AI GLM glm https://api.z.ai/api/anthropic GLM models at lower cost
MiniMax minimax https://api.minimax.io/anthropic MiniMax M2.1 model
MiniMax (China) minimax https://api.minimaxi.com/anthropic MiniMax for China region

Model Mappings

Each provider model specifies which Claude model tier it maps to via mapsToClaudeModel:

z.AI GLM:

  • GLM-4.5-Air β†’ haiku
  • GLM-4.7 β†’ sonnet, opus

MiniMax:

  • MiniMax-M2.1 β†’ haiku, sonnet, opus

OpenRouter:

  • anthropic/claude-3.5-haiku β†’ haiku
  • anthropic/claude-3.5-sonnet β†’ sonnet
  • anthropic/claude-3-opus β†’ opus

Server-Side Implementation

API Key Resolution

The buildEnv() function in claude-provider.ts resolves API keys based on apiKeySource:

function buildEnv(
  providerConfig?: ClaudeCompatibleProvider,
  credentials?: Credentials
): Record<string, string | undefined> {
  if (providerConfig) {
    let apiKey: string | undefined;
    const source = providerConfig.apiKeySource ?? 'inline';

    switch (source) {
      case 'inline':
        apiKey = providerConfig.apiKey;
        break;
      case 'env':
        apiKey = process.env.ANTHROPIC_API_KEY;
        break;
      case 'credentials':
        apiKey = credentials?.apiKeys?.anthropic;
        break;
    }
    // ... build environment with resolved key
  }
}

Provider Lookup

The getProviderByModelId() helper resolves provider configuration from model IDs:

export async function getProviderByModelId(
  modelId: string,
  settingsService: SettingsService,
  logPrefix?: string
): Promise<{
  provider?: ClaudeCompatibleProvider;
  resolvedModel?: string;
  credentials?: Credentials;
}>;

This is used by all routes that call the Claude SDK to:

  1. Check if the model ID belongs to a provider
  2. Get the provider configuration (baseUrl, auth, etc.)
  3. Resolve the mapsToClaudeModel for the SDK

Phase Model Resolution

The getPhaseModelWithOverrides() helper gets effective phase model config:

export async function getPhaseModelWithOverrides(
  phaseKey: PhaseModelKey,
  settingsService: SettingsService,
  projectPath?: string,
  logPrefix?: string
): Promise<{
  model: string;
  thinkingLevel?: ThinkingLevel;
  providerId?: string;
  providerConfig?: ClaudeCompatibleProvider;
  credentials?: Credentials;
}>;

This handles:

  1. Project-level overrides (if projectPath provided)
  2. Global phase model settings
  3. Default fallback models

UI Implementation

Model Selection Dropdowns

Phase model selectors (PhaseModelSelector) display:

  1. Claude Models - Native Claude models (Haiku, Sonnet, Opus)
  2. Provider Sections - Each enabled provider as a separate group:
    • Section header: {provider.name} (via Claude)
    • Models with their mapped Claude tiers: "Maps to Haiku, Sonnet, Opus"
    • Thinking level submenu for models that support it

Provider Icons

Icons are determined by providerType:

  • glm β†’ Z logo
  • minimax β†’ MiniMax logo
  • openrouter β†’ OpenRouter logo
  • Generic β†’ OpenRouter as fallback

Bulk Replace

The "Bulk Replace" feature allows switching all phase models to a provider at once:

  1. Select a provider from the dropdown
  2. Preview shows which models will be assigned:
    • haiku phases β†’ provider's haiku-mapped model
    • sonnet phases β†’ provider's sonnet-mapped model
    • opus phases β†’ provider's opus-mapped model
  3. Apply replaces all phase model configurations

The Bulk Replace button only appears when at least one provider is enabled.

Project-Level Overrides

Projects can override global phase model settings via phaseModelOverrides:

interface Project {
  // ...
  phaseModelOverrides?: PhaseModelConfig; // Per-phase overrides
}

Storage

Project overrides are stored in .automaker/settings.json:

{
  "phaseModelOverrides": {
    "enhancementModel": {
      "providerId": "provider-uuid",
      "model": "GLM-4.5-Air",
      "thinkingLevel": "none"
    }
  }
}

Resolution Priority

  1. Project override for specific phase (if set)
  2. Global phase model setting
  3. Default model for phase

Migration

v5 β†’ v6 Migration

The system migrated from claudeApiProfiles to claudeCompatibleProviders:

// Old: modelMappings object
{
  modelMappings: {
    haiku: 'GLM-4.5-Air',
    sonnet: 'GLM-4.7',
    opus: 'GLM-4.7'
  }
}

// New: models array with mapsToClaudeModel
{
  models: [
    { id: 'GLM-4.5-Air', displayName: 'GLM 4.5 Air', mapsToClaudeModel: 'haiku' },
    { id: 'GLM-4.7', displayName: 'GLM 4.7', mapsToClaudeModel: 'sonnet' },
    { id: 'GLM-4.7', displayName: 'GLM 4.7', mapsToClaudeModel: 'opus' },
  ]
}

The migration is automatic and preserves existing provider configurations.

Files Changed

Types

File Changes
libs/types/src/settings.ts ClaudeCompatibleProvider, ProviderModel, PhaseModelEntry types
libs/types/src/provider.ts ExecuteOptions.claudeCompatibleProvider field
libs/types/src/index.ts Exports for new types

Server

File Changes
apps/server/src/providers/claude-provider.ts Provider config handling, buildEnv updates
apps/server/src/lib/settings-helpers.ts getProviderByModelId(), getPhaseModelWithOverrides()
apps/server/src/services/settings-service.ts v5β†’v6 migration
apps/server/src/routes/**/*.ts Provider lookup for all SDK calls

UI

File Changes
apps/ui/src/.../phase-model-selector.tsx Provider model rendering, thinking levels
apps/ui/src/.../bulk-replace-dialog.tsx Bulk replace feature
apps/ui/src/.../api-profiles-section.tsx Provider management UI
apps/ui/src/components/ui/provider-icon.tsx Provider-specific icons
apps/ui/src/hooks/use-project-settings-loader.ts Load phaseModelOverrides

Testing

# Build and run
npm run build:packages
npm run dev:web

# Run server tests
npm run test:server

Test Cases

  1. Provider setup: Add z.AI GLM provider with inline API key
  2. Model selection: Select GLM-4.7 for a phase, verify it appears in dropdown
  3. Thinking levels: Select thinking level for provider model
  4. Bulk replace: Switch all phases to a provider at once
  5. Project override: Set per-project model override, verify it persists
  6. Provider deletion: Delete all providers, verify empty state persists

Future Enhancements

Potential improvements:

  1. Provider validation: Test API connection before saving
  2. Usage tracking: Show which phases use which provider
  3. Cost estimation: Display estimated costs per provider
  4. Model capabilities: Auto-detect supported features from provider