@kamel-ahmed/proxy-claude 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/onboard.js +180 -69
package/package.json
CHANGED
package/src/cli/onboard.js
CHANGED
|
@@ -50,41 +50,36 @@ const ACCOUNTS_FILE = path.join(CONFIG_DIR, 'accounts.json');
|
|
|
50
50
|
const CLAUDE_CONFIG_DIR = path.join(PLATFORM.homeDir, '.claude');
|
|
51
51
|
const CLAUDE_SETTINGS_FILE = path.join(CLAUDE_CONFIG_DIR, 'settings.json');
|
|
52
52
|
|
|
53
|
-
//
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
53
|
+
// All available models in Antigravity (fetched dynamically, but this is a fallback)
|
|
54
|
+
const ALL_MODELS = [
|
|
55
|
+
// Claude models
|
|
56
|
+
{ id: 'claude-opus-4-5-thinking', family: 'claude', tier: 'opus', description: 'Claude Opus 4.5 with thinking' },
|
|
57
|
+
{ id: 'claude-sonnet-4-5-thinking', family: 'claude', tier: 'sonnet', description: 'Claude Sonnet 4.5 with thinking' },
|
|
58
|
+
{ id: 'claude-sonnet-4-5', family: 'claude', tier: 'sonnet', description: 'Claude Sonnet 4.5' },
|
|
59
|
+
// Gemini models
|
|
60
|
+
{ id: 'gemini-3-pro-high', family: 'gemini', tier: 'opus', description: 'Gemini 3 Pro High (best quality)' },
|
|
61
|
+
{ id: 'gemini-3-pro-low', family: 'gemini', tier: 'sonnet', description: 'Gemini 3 Pro Low' },
|
|
62
|
+
{ id: 'gemini-3-flash', family: 'gemini', tier: 'sonnet', description: 'Gemini 3 Flash (fast)' },
|
|
63
|
+
{ id: 'gemini-2.5-flash-lite', family: 'gemini', tier: 'haiku', description: 'Gemini 2.5 Flash Lite (fastest)' },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Model tier descriptions
|
|
67
|
+
const TIER_INFO = {
|
|
68
|
+
opus: {
|
|
69
|
+
name: 'Opus (Primary)',
|
|
70
|
+
description: 'Main model for complex tasks',
|
|
71
|
+
envKey: 'ANTHROPIC_DEFAULT_OPUS_MODEL',
|
|
65
72
|
},
|
|
66
|
-
|
|
67
|
-
name: '
|
|
68
|
-
description: '
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
73
|
+
sonnet: {
|
|
74
|
+
name: 'Sonnet (Default)',
|
|
75
|
+
description: 'Balanced model for most tasks',
|
|
76
|
+
envKey: 'ANTHROPIC_DEFAULT_SONNET_MODEL',
|
|
77
|
+
},
|
|
78
|
+
haiku: {
|
|
79
|
+
name: 'Haiku (Fast)',
|
|
80
|
+
description: 'Quick model for simple tasks & background',
|
|
81
|
+
envKey: 'ANTHROPIC_DEFAULT_HAIKU_MODEL',
|
|
76
82
|
},
|
|
77
|
-
balanced: {
|
|
78
|
-
name: 'Balanced (Claude + Gemini)',
|
|
79
|
-
description: 'Claude for main tasks, Gemini for background',
|
|
80
|
-
models: {
|
|
81
|
-
ANTHROPIC_MODEL: 'claude-sonnet-4-5-thinking',
|
|
82
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-opus-4-5-thinking',
|
|
83
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: 'claude-sonnet-4-5-thinking',
|
|
84
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL: 'gemini-2.5-flash-lite',
|
|
85
|
-
CLAUDE_CODE_SUBAGENT_MODEL: 'gemini-3-flash',
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
83
|
};
|
|
89
84
|
|
|
90
85
|
/**
|
|
@@ -215,6 +210,65 @@ function getExistingAccounts() {
|
|
|
215
210
|
return [];
|
|
216
211
|
}
|
|
217
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Fetch available models from the API using account token
|
|
215
|
+
*/
|
|
216
|
+
async function fetchAvailableModels(accounts) {
|
|
217
|
+
if (!accounts || accounts.length === 0) {
|
|
218
|
+
return ALL_MODELS;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
// Get token from first account
|
|
223
|
+
const account = accounts[0];
|
|
224
|
+
const token = account.accessToken;
|
|
225
|
+
|
|
226
|
+
if (!token) {
|
|
227
|
+
return ALL_MODELS;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Import the model API
|
|
231
|
+
const { fetchAvailableModels: fetchModels } = await import('../cloudcode/model-api.js');
|
|
232
|
+
const data = await fetchModels(token);
|
|
233
|
+
|
|
234
|
+
if (data && data.models) {
|
|
235
|
+
const models = [];
|
|
236
|
+
for (const [modelId, modelData] of Object.entries(data.models)) {
|
|
237
|
+
// Only include Claude and Gemini models
|
|
238
|
+
if (!modelId.includes('claude') && !modelId.includes('gemini')) continue;
|
|
239
|
+
|
|
240
|
+
// Determine family
|
|
241
|
+
const family = modelId.includes('claude') ? 'claude' : 'gemini';
|
|
242
|
+
|
|
243
|
+
// Determine tier based on model name
|
|
244
|
+
let tier = 'sonnet';
|
|
245
|
+
if (modelId.includes('opus') || modelId.includes('pro-high')) tier = 'opus';
|
|
246
|
+
else if (modelId.includes('haiku') || modelId.includes('flash-lite')) tier = 'haiku';
|
|
247
|
+
|
|
248
|
+
// Check if model has quota (remaining > 0)
|
|
249
|
+
const hasQuota = modelData.remainingFraction === undefined || modelData.remainingFraction > 0;
|
|
250
|
+
|
|
251
|
+
models.push({
|
|
252
|
+
id: modelId,
|
|
253
|
+
family,
|
|
254
|
+
tier,
|
|
255
|
+
description: modelData.displayName || modelId,
|
|
256
|
+
hasQuota,
|
|
257
|
+
remainingFraction: modelData.remainingFraction,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (models.length > 0) {
|
|
262
|
+
return models;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} catch (error) {
|
|
266
|
+
print(`Could not fetch models from API: ${error.message}`, 'warn');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return ALL_MODELS;
|
|
270
|
+
}
|
|
271
|
+
|
|
218
272
|
/**
|
|
219
273
|
* Add Google account via OAuth
|
|
220
274
|
*/
|
|
@@ -260,9 +314,69 @@ function saveClaudeSettings(settings) {
|
|
|
260
314
|
}
|
|
261
315
|
|
|
262
316
|
/**
|
|
263
|
-
*
|
|
317
|
+
* Select a model for a specific tier
|
|
318
|
+
*/
|
|
319
|
+
async function selectModelForTier(rl, tier, availableModels) {
|
|
320
|
+
const tierInfo = TIER_INFO[tier];
|
|
321
|
+
console.log('');
|
|
322
|
+
console.log(`${COLORS.bold}${tierInfo.name}${COLORS.reset} - ${COLORS.dim}${tierInfo.description}${COLORS.reset}`);
|
|
323
|
+
console.log('');
|
|
324
|
+
|
|
325
|
+
// Filter models that are suitable for this tier or higher
|
|
326
|
+
// opus can use any model, sonnet can use sonnet/haiku, haiku uses haiku
|
|
327
|
+
const tierPriority = { opus: 3, sonnet: 2, haiku: 1 };
|
|
328
|
+
const minTier = tierPriority[tier];
|
|
329
|
+
|
|
330
|
+
const suitableModels = availableModels.filter(m => {
|
|
331
|
+
const modelTier = tierPriority[m.tier] || 2;
|
|
332
|
+
return modelTier >= minTier - 1; // Allow one tier lower
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Sort: models with quota first, then by family (claude first), then by tier
|
|
336
|
+
suitableModels.sort((a, b) => {
|
|
337
|
+
// Quota status
|
|
338
|
+
if (a.hasQuota !== b.hasQuota) return a.hasQuota ? -1 : 1;
|
|
339
|
+
// Family (claude first for opus/sonnet, gemini first for haiku)
|
|
340
|
+
if (tier === 'haiku') {
|
|
341
|
+
if (a.family !== b.family) return a.family === 'gemini' ? -1 : 1;
|
|
342
|
+
} else {
|
|
343
|
+
if (a.family !== b.family) return a.family === 'claude' ? -1 : 1;
|
|
344
|
+
}
|
|
345
|
+
// Tier priority
|
|
346
|
+
return (tierPriority[b.tier] || 0) - (tierPriority[a.tier] || 0);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// Display models
|
|
350
|
+
console.log(`${COLORS.dim}Available models:${COLORS.reset}`);
|
|
351
|
+
suitableModels.forEach((model, index) => {
|
|
352
|
+
const quotaStatus = model.hasQuota === false
|
|
353
|
+
? `${COLORS.red}(no quota)${COLORS.reset}`
|
|
354
|
+
: model.remainingFraction !== undefined
|
|
355
|
+
? `${COLORS.green}(${Math.round(model.remainingFraction * 100)}% quota)${COLORS.reset}`
|
|
356
|
+
: '';
|
|
357
|
+
const familyBadge = model.family === 'claude'
|
|
358
|
+
? `${COLORS.magenta}[Claude]${COLORS.reset}`
|
|
359
|
+
: `${COLORS.blue}[Gemini]${COLORS.reset}`;
|
|
360
|
+
console.log(` ${COLORS.cyan}${index + 1}.${COLORS.reset} ${model.id} ${familyBadge} ${quotaStatus}`);
|
|
361
|
+
});
|
|
362
|
+
console.log('');
|
|
363
|
+
|
|
364
|
+
// Default to first model with quota
|
|
365
|
+
const defaultIndex = suitableModels.findIndex(m => m.hasQuota !== false) + 1 || 1;
|
|
366
|
+
|
|
367
|
+
const choice = await prompt(rl, `Select model for ${tier} (1-${suitableModels.length})`, String(defaultIndex));
|
|
368
|
+
const index = parseInt(choice, 10) - 1;
|
|
369
|
+
|
|
370
|
+
if (index >= 0 && index < suitableModels.length) {
|
|
371
|
+
return suitableModels[index].id;
|
|
372
|
+
}
|
|
373
|
+
return suitableModels[0]?.id || ALL_MODELS.find(m => m.tier === tier)?.id;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Configure Claude Code settings with selected models
|
|
264
378
|
*/
|
|
265
|
-
function
|
|
379
|
+
function configureClaudeSettingsWithModels(modelConfig, port = 8080) {
|
|
266
380
|
const existing = loadClaudeSettings();
|
|
267
381
|
|
|
268
382
|
const newSettings = {
|
|
@@ -271,7 +385,11 @@ function configureClaudeSettings(modelPreset, port = 8080) {
|
|
|
271
385
|
...(existing.env || {}),
|
|
272
386
|
ANTHROPIC_AUTH_TOKEN: 'proxy-claude',
|
|
273
387
|
ANTHROPIC_BASE_URL: `http://localhost:${port}`,
|
|
274
|
-
|
|
388
|
+
ANTHROPIC_MODEL: modelConfig.sonnet, // Default model is sonnet
|
|
389
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: modelConfig.opus,
|
|
390
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: modelConfig.sonnet,
|
|
391
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: modelConfig.haiku,
|
|
392
|
+
CLAUDE_CODE_SUBAGENT_MODEL: modelConfig.haiku, // Subagent uses haiku for efficiency
|
|
275
393
|
ENABLE_EXPERIMENTAL_MCP_CLI: 'true',
|
|
276
394
|
}
|
|
277
395
|
};
|
|
@@ -286,33 +404,9 @@ function configureClaudeSettings(modelPreset, port = 8080) {
|
|
|
286
404
|
}
|
|
287
405
|
|
|
288
406
|
/**
|
|
289
|
-
*
|
|
407
|
+
* Print summary with selected models
|
|
290
408
|
*/
|
|
291
|
-
|
|
292
|
-
console.log('');
|
|
293
|
-
console.log(`${COLORS.bold}Available model configurations:${COLORS.reset}`);
|
|
294
|
-
console.log('');
|
|
295
|
-
|
|
296
|
-
const presets = Object.entries(MODEL_PRESETS);
|
|
297
|
-
presets.forEach(([key, preset], index) => {
|
|
298
|
-
console.log(` ${COLORS.cyan}${index + 1}.${COLORS.reset} ${COLORS.bold}${preset.name}${COLORS.reset}`);
|
|
299
|
-
console.log(` ${COLORS.dim}${preset.description}${COLORS.reset}`);
|
|
300
|
-
});
|
|
301
|
-
console.log('');
|
|
302
|
-
|
|
303
|
-
const choice = await prompt(rl, 'Select configuration (1-3)', '1');
|
|
304
|
-
const index = parseInt(choice, 10) - 1;
|
|
305
|
-
|
|
306
|
-
if (index >= 0 && index < presets.length) {
|
|
307
|
-
return presets[index];
|
|
308
|
-
}
|
|
309
|
-
return presets[0]; // Default to first option
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Print summary
|
|
314
|
-
*/
|
|
315
|
-
function printSummary(accounts, modelPreset, port) {
|
|
409
|
+
function printSummary(accounts, modelConfig, port) {
|
|
316
410
|
console.log('');
|
|
317
411
|
console.log(`${COLORS.green}╔══════════════════════════════════════════════════════════╗${COLORS.reset}`);
|
|
318
412
|
console.log(`${COLORS.green}║${COLORS.reset} ${COLORS.bold}${COLORS.green}Setup Complete!${COLORS.reset} ${COLORS.green}║${COLORS.reset}`);
|
|
@@ -321,7 +415,9 @@ function printSummary(accounts, modelPreset, port) {
|
|
|
321
415
|
|
|
322
416
|
console.log(`${COLORS.bold}Configuration Summary:${COLORS.reset}`);
|
|
323
417
|
console.log(` ${COLORS.dim}•${COLORS.reset} Accounts: ${accounts.length} configured`);
|
|
324
|
-
console.log(` ${COLORS.dim}•${COLORS.reset}
|
|
418
|
+
console.log(` ${COLORS.dim}•${COLORS.reset} Opus model: ${COLORS.cyan}${modelConfig.opus}${COLORS.reset}`);
|
|
419
|
+
console.log(` ${COLORS.dim}•${COLORS.reset} Sonnet model: ${COLORS.cyan}${modelConfig.sonnet}${COLORS.reset}`);
|
|
420
|
+
console.log(` ${COLORS.dim}•${COLORS.reset} Haiku model: ${COLORS.cyan}${modelConfig.haiku}${COLORS.reset}`);
|
|
325
421
|
console.log(` ${COLORS.dim}•${COLORS.reset} Proxy port: ${port}`);
|
|
326
422
|
console.log(` ${COLORS.dim}•${COLORS.reset} Settings saved to: ${CLAUDE_SETTINGS_FILE}`);
|
|
327
423
|
console.log('');
|
|
@@ -422,11 +518,26 @@ export async function runOnboarding(options = {}) {
|
|
|
422
518
|
// Step 3: Model Configuration
|
|
423
519
|
printStep(++currentStep, totalSteps, 'Model Configuration');
|
|
424
520
|
|
|
425
|
-
print('
|
|
426
|
-
|
|
521
|
+
print('Fetching available models from your account...', 'step');
|
|
522
|
+
const availableModels = await fetchAvailableModels(accounts);
|
|
523
|
+
print(`Found ${availableModels.length} models available`, 'success');
|
|
524
|
+
|
|
525
|
+
console.log('');
|
|
526
|
+
print('Now select a model for each tier. Models with quota are shown first.', 'info');
|
|
527
|
+
print(`${COLORS.dim}Tip: Use Gemini for Haiku to save your Claude quota!${COLORS.reset}`, 'info');
|
|
528
|
+
|
|
529
|
+
// Select model for each tier
|
|
530
|
+
const modelConfig = {
|
|
531
|
+
opus: await selectModelForTier(rl, 'opus', availableModels),
|
|
532
|
+
sonnet: await selectModelForTier(rl, 'sonnet', availableModels),
|
|
533
|
+
haiku: await selectModelForTier(rl, 'haiku', availableModels),
|
|
534
|
+
};
|
|
427
535
|
|
|
428
|
-
|
|
429
|
-
print(
|
|
536
|
+
console.log('');
|
|
537
|
+
print('Model configuration:', 'success');
|
|
538
|
+
console.log(` ${COLORS.dim}Opus:${COLORS.reset} ${COLORS.cyan}${modelConfig.opus}${COLORS.reset}`);
|
|
539
|
+
console.log(` ${COLORS.dim}Sonnet:${COLORS.reset} ${COLORS.cyan}${modelConfig.sonnet}${COLORS.reset}`);
|
|
540
|
+
console.log(` ${COLORS.dim}Haiku:${COLORS.reset} ${COLORS.cyan}${modelConfig.haiku}${COLORS.reset}`);
|
|
430
541
|
|
|
431
542
|
// Step 4: Apply Configuration
|
|
432
543
|
printStep(++currentStep, totalSteps, 'Applying Configuration');
|
|
@@ -435,11 +546,11 @@ export async function runOnboarding(options = {}) {
|
|
|
435
546
|
|
|
436
547
|
// Configure Claude Code settings
|
|
437
548
|
print('Configuring Claude Code settings...', 'step');
|
|
438
|
-
|
|
549
|
+
configureClaudeSettingsWithModels(modelConfig, port);
|
|
439
550
|
print(`Settings saved to ${CLAUDE_SETTINGS_FILE}`, 'success');
|
|
440
551
|
|
|
441
552
|
// Print summary
|
|
442
|
-
printSummary(accounts,
|
|
553
|
+
printSummary(accounts, modelConfig, port);
|
|
443
554
|
|
|
444
555
|
rl.close();
|
|
445
556
|
return true;
|