File size: 10,598 Bytes
1dbc34b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# 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

```typescript
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

```typescript
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:

```typescript
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`:

```typescript
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:

```typescript
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:

```typescript
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`:

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

### Storage

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

```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`:

```typescript
// 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

```bash
# 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