mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 16:19:27 +00:00
feat(copilot): add complete model catalog with plan tiers
Add 19 GitHub Copilot supported models with metadata: - Anthropic: claude-sonnet-4.5, claude-sonnet-4, claude-opus-4.5, claude-opus-4.1, claude-haiku-4.5 - OpenAI: gpt-5.2, gpt-5.1-codex-max, gpt-5.1-codex, gpt-5.1-codex-mini, gpt-5.1, gpt-5-codex, gpt-5, gpt-5-mini, gpt-4.1 - Google: gemini-3-pro, gemini-3-flash, gemini-2.5-pro - xAI: grok-code-fast-1 - Fine-tuned: raptor-mini Each model includes: - minPlan: free, pro, pro+, business, enterprise - multiplier: 0 = free tier, 0.25-0.33 = cheap, 1 = standard, 3-10 = premium - preview: boolean for non-GA models Update default model to claude-sonnet-4.5 (standard multiplier).
This commit is contained in:
@@ -325,7 +325,7 @@ function generateYamlWithComments(config: UnifiedConfig): string {
|
|||||||
lines.push('# Setup: npx copilot-api auth (authenticate with GitHub)');
|
lines.push('# Setup: npx copilot-api auth (authenticate with GitHub)');
|
||||||
lines.push('# Usage: ccs copilot (switch to copilot profile)');
|
lines.push('# Usage: ccs copilot (switch to copilot profile)');
|
||||||
lines.push('#');
|
lines.push('#');
|
||||||
lines.push('# Models: claude-opus-4-5-20250514, claude-sonnet-4-20250514, gpt-4.1, o3');
|
lines.push('# Models: claude-sonnet-4.5, claude-opus-4.5, gpt-5.1, gemini-2.5-pro');
|
||||||
lines.push('# Account types: individual, business, enterprise');
|
lines.push('# Account types: individual, business, enterprise');
|
||||||
lines.push('# ----------------------------------------------------------------------------');
|
lines.push('# ----------------------------------------------------------------------------');
|
||||||
lines.push(
|
lines.push(
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export interface CopilotConfig {
|
|||||||
rate_limit: number | null;
|
rate_limit: number | null;
|
||||||
/** Wait instead of error when rate limit is hit (default: true) */
|
/** Wait instead of error when rate limit is hit (default: true) */
|
||||||
wait_on_limit: boolean;
|
wait_on_limit: boolean;
|
||||||
/** Default model ID (e.g., claude-opus-4-5-20250514) */
|
/** Default model ID (e.g., claude-sonnet-4.5) */
|
||||||
model: string;
|
model: string;
|
||||||
/** Model mapping for Claude tiers - maps opus/sonnet/haiku to specific models */
|
/** Model mapping for Claude tiers - maps opus/sonnet/haiku to specific models */
|
||||||
opus_model?: string;
|
opus_model?: string;
|
||||||
@@ -259,7 +259,7 @@ export const DEFAULT_COPILOT_CONFIG: CopilotConfig = {
|
|||||||
account_type: 'individual',
|
account_type: 'individual',
|
||||||
rate_limit: null,
|
rate_limit: null,
|
||||||
wait_on_limit: true,
|
wait_on_limit: true,
|
||||||
model: 'claude-opus-4-5-20250514',
|
model: 'claude-sonnet-4.5',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+146
-20
@@ -2,6 +2,8 @@
|
|||||||
* Copilot Model Catalog
|
* Copilot Model Catalog
|
||||||
*
|
*
|
||||||
* Manages available models from copilot-api.
|
* Manages available models from copilot-api.
|
||||||
|
* Based on GitHub Copilot supported models:
|
||||||
|
* https://docs.github.com/copilot/reference/ai-models/supported-models
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
@@ -10,19 +12,132 @@ import { CopilotModel } from './types';
|
|||||||
/**
|
/**
|
||||||
* Default models available through copilot-api.
|
* Default models available through copilot-api.
|
||||||
* Used as fallback when API is not reachable.
|
* Used as fallback when API is not reachable.
|
||||||
|
* Source: GitHub Copilot Supported Models (Dec 2025)
|
||||||
|
*
|
||||||
|
* Plan tiers: free, pro, pro+, business, enterprise
|
||||||
|
* Multipliers: 0 = free tier, 0.25-0.33 = cheap, 1 = standard, 3-10 = premium
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_COPILOT_MODELS: CopilotModel[] = [
|
export const DEFAULT_COPILOT_MODELS: CopilotModel[] = [
|
||||||
|
// Anthropic Models
|
||||||
{
|
{
|
||||||
id: 'claude-opus-4-5-20250514',
|
id: 'claude-sonnet-4.5',
|
||||||
name: 'Claude Opus 4.5',
|
name: 'Claude Sonnet 4.5',
|
||||||
provider: 'anthropic',
|
provider: 'anthropic',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'claude-sonnet-4',
|
||||||
|
name: 'Claude Sonnet 4',
|
||||||
|
provider: 'anthropic',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'claude-opus-4.5',
|
||||||
|
name: 'Claude Opus 4.5',
|
||||||
|
provider: 'anthropic',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 3,
|
||||||
|
preview: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'claude-opus-4.1',
|
||||||
|
name: 'Claude Opus 4.1',
|
||||||
|
provider: 'anthropic',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'claude-haiku-4.5',
|
||||||
|
name: 'Claude Haiku 4.5',
|
||||||
|
provider: 'anthropic',
|
||||||
|
minPlan: 'free',
|
||||||
|
multiplier: 0.33,
|
||||||
|
},
|
||||||
|
|
||||||
|
// OpenAI Models
|
||||||
|
{
|
||||||
|
id: 'gpt-5.2',
|
||||||
|
name: 'GPT-5.2',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
preview: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gpt-5.1-codex-max',
|
||||||
|
name: 'GPT-5.1 Codex Max',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
},
|
||||||
|
{ id: 'gpt-5.1-codex', name: 'GPT-5.1 Codex', provider: 'openai', minPlan: 'pro', multiplier: 1 },
|
||||||
|
{
|
||||||
|
id: 'gpt-5.1-codex-mini',
|
||||||
|
name: 'GPT-5.1 Codex Mini',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 0.33,
|
||||||
|
preview: true,
|
||||||
|
},
|
||||||
|
{ id: 'gpt-5.1', name: 'GPT-5.1', provider: 'openai', minPlan: 'pro', multiplier: 1 },
|
||||||
|
{
|
||||||
|
id: 'gpt-5-codex',
|
||||||
|
name: 'GPT-5 Codex',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
preview: true,
|
||||||
|
},
|
||||||
|
{ id: 'gpt-5', name: 'GPT-5', provider: 'openai', minPlan: 'pro', multiplier: 1 },
|
||||||
|
{ id: 'gpt-5-mini', name: 'GPT-5 Mini', provider: 'openai', minPlan: 'free', multiplier: 0 },
|
||||||
|
{ id: 'gpt-4.1', name: 'GPT-4.1', provider: 'openai', minPlan: 'free', multiplier: 0 },
|
||||||
|
|
||||||
|
// Google Models
|
||||||
|
{
|
||||||
|
id: 'gemini-3-pro',
|
||||||
|
name: 'Gemini 3 Pro',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
preview: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gemini-3-flash',
|
||||||
|
name: 'Gemini 3 Flash',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 0.33,
|
||||||
|
preview: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gemini-2.5-pro',
|
||||||
|
name: 'Gemini 2.5 Pro',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
// xAI Models
|
||||||
|
{
|
||||||
|
id: 'grok-code-fast-1',
|
||||||
|
name: 'Grok Code Fast 1',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'pro',
|
||||||
|
multiplier: 0.25,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Fine-tuned Models
|
||||||
|
{
|
||||||
|
id: 'raptor-mini',
|
||||||
|
name: 'Raptor Mini',
|
||||||
|
provider: 'openai',
|
||||||
|
minPlan: 'free',
|
||||||
|
multiplier: 0,
|
||||||
|
preview: true,
|
||||||
},
|
},
|
||||||
{ id: 'claude-sonnet-4-20250514', name: 'Claude Sonnet 4', provider: 'anthropic' },
|
|
||||||
{ id: 'gpt-4.1', name: 'GPT-4.1', provider: 'openai' },
|
|
||||||
{ id: 'gpt-4.1-mini', name: 'GPT-4.1 Mini', provider: 'openai' },
|
|
||||||
{ id: 'o3', name: 'O3', provider: 'openai' },
|
|
||||||
{ id: 'o4-mini', name: 'O4 Mini', provider: 'openai' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,8 +170,8 @@ export async function fetchModelsFromDaemon(port: number): Promise<CopilotModel[
|
|||||||
const models: CopilotModel[] = response.data.map((m) => ({
|
const models: CopilotModel[] = response.data.map((m) => ({
|
||||||
id: m.id,
|
id: m.id,
|
||||||
name: formatModelName(m.id),
|
name: formatModelName(m.id),
|
||||||
provider: m.id.includes('claude') ? 'anthropic' : 'openai',
|
provider: detectProvider(m.id),
|
||||||
isDefault: m.id === 'claude-opus-4-5-20250514',
|
isDefault: m.id === 'claude-sonnet-4.5',
|
||||||
}));
|
}));
|
||||||
resolve(models.length > 0 ? models : DEFAULT_COPILOT_MODELS);
|
resolve(models.length > 0 ? models : DEFAULT_COPILOT_MODELS);
|
||||||
} else {
|
} else {
|
||||||
@@ -93,22 +208,33 @@ export async function getAvailableModels(port: number): Promise<CopilotModel[]>
|
|||||||
* Get the default model.
|
* Get the default model.
|
||||||
*/
|
*/
|
||||||
export function getDefaultModel(): string {
|
export function getDefaultModel(): string {
|
||||||
return 'claude-opus-4-5-20250514';
|
return 'claude-sonnet-4.5';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect provider from model ID.
|
||||||
|
*/
|
||||||
|
function detectProvider(modelId: string): 'openai' | 'anthropic' {
|
||||||
|
if (modelId.includes('claude')) return 'anthropic';
|
||||||
|
return 'openai';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format model ID to human-readable name.
|
* Format model ID to human-readable name.
|
||||||
|
* Includes badges for preview and plan tier.
|
||||||
*/
|
*/
|
||||||
function formatModelName(modelId: string): string {
|
function formatModelName(modelId: string): string {
|
||||||
// Convert model IDs to readable names
|
// Find model in catalog for metadata
|
||||||
const nameMap: Record<string, string> = {
|
const model = DEFAULT_COPILOT_MODELS.find((m) => m.id === modelId);
|
||||||
'claude-opus-4-5-20250514': 'Claude Opus 4.5',
|
if (model) {
|
||||||
'claude-sonnet-4-20250514': 'Claude Sonnet 4',
|
let name = model.name;
|
||||||
'gpt-4.1': 'GPT-4.1',
|
if (model.preview) name += ' (Preview)';
|
||||||
'gpt-4.1-mini': 'GPT-4.1 Mini',
|
return name;
|
||||||
o3: 'O3',
|
}
|
||||||
'o4-mini': 'O4 Mini',
|
|
||||||
};
|
|
||||||
|
|
||||||
return nameMap[modelId] || modelId;
|
// Fallback: convert kebab-case to title case
|
||||||
|
return modelId
|
||||||
|
.split('-')
|
||||||
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||||
|
.join(' ');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ export interface CopilotStatus {
|
|||||||
daemon: CopilotDaemonStatus;
|
daemon: CopilotDaemonStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copilot plan tier for model availability.
|
||||||
|
* Based on GitHub Copilot plans.
|
||||||
|
*/
|
||||||
|
export type CopilotPlanTier = 'free' | 'pro' | 'pro+' | 'business' | 'enterprise';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copilot model information.
|
* Copilot model information.
|
||||||
*/
|
*/
|
||||||
@@ -45,6 +51,12 @@ export interface CopilotModel {
|
|||||||
provider: 'openai' | 'anthropic';
|
provider: 'openai' | 'anthropic';
|
||||||
/** Whether this is the default model */
|
/** Whether this is the default model */
|
||||||
isDefault?: boolean;
|
isDefault?: boolean;
|
||||||
|
/** Minimum plan tier required (free = available to all) */
|
||||||
|
minPlan?: CopilotPlanTier;
|
||||||
|
/** Premium request multiplier (0 = free, higher = more expensive) */
|
||||||
|
multiplier?: number;
|
||||||
|
/** Whether this model is in preview */
|
||||||
|
preview?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user