mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 14:16:43 +00:00
fix(copilot): use gpt-4.1 as default model and 127.0.0.1 for local connections
Key changes: - Changed default model from claude-sonnet-4.5 to gpt-4.1 (free tier compatible) - Updated all Claude models to minPlan: 'pro' (requires paid Copilot subscription) - Replaced 'localhost' with '127.0.0.1' for more reliable local connections (bypasses DNS resolution and potential IPv6 issues) - Updated UI presets: replaced Claude Haiku with Raptor Mini in free tier - Fixed FREE_PRESETS to only include actually free models This fixes the "model_not_supported" error when using free tier GitHub Copilot subscription, which doesn't have access to Claude models.
This commit is contained in:
@@ -253,6 +253,7 @@ export interface SecretsConfig {
|
|||||||
/**
|
/**
|
||||||
* Default Copilot configuration.
|
* Default Copilot configuration.
|
||||||
* Strictly opt-in - disabled by default.
|
* Strictly opt-in - disabled by default.
|
||||||
|
* Uses gpt-4.1 as default model (free tier compatible).
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_COPILOT_CONFIG: CopilotConfig = {
|
export const DEFAULT_COPILOT_CONFIG: CopilotConfig = {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
@@ -261,7 +262,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-sonnet-4.5',
|
model: 'gpt-4.1', // Free tier compatible
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,12 +17,13 @@ const PID_FILE = path.join(getCopilotDir(), 'daemon.pid');
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if copilot-api daemon is running on the specified port.
|
* Check if copilot-api daemon is running on the specified port.
|
||||||
|
* Uses 127.0.0.1 instead of localhost for more reliable local connections.
|
||||||
*/
|
*/
|
||||||
export async function isDaemonRunning(port: number): Promise<boolean> {
|
export async function isDaemonRunning(port: number): Promise<boolean> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const req = http.request(
|
const req = http.request(
|
||||||
{
|
{
|
||||||
hostname: 'localhost',
|
hostname: '127.0.0.1',
|
||||||
port,
|
port,
|
||||||
path: '/usage',
|
path: '/usage',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|||||||
@@ -40,8 +40,10 @@ export function generateCopilotEnv(config: CopilotConfig): Record<string, string
|
|||||||
const sonnetModel = config.sonnet_model || config.model;
|
const sonnetModel = config.sonnet_model || config.model;
|
||||||
const haikuModel = config.haiku_model || config.model;
|
const haikuModel = config.haiku_model || config.model;
|
||||||
|
|
||||||
|
// Use 127.0.0.1 instead of localhost for more reliable local connections
|
||||||
|
// (bypasses DNS resolution and potential IPv6 issues)
|
||||||
return {
|
return {
|
||||||
ANTHROPIC_BASE_URL: `http://localhost:${config.port}`,
|
ANTHROPIC_BASE_URL: `http://127.0.0.1:${config.port}`,
|
||||||
ANTHROPIC_AUTH_TOKEN: 'dummy', // copilot-api handles auth internally
|
ANTHROPIC_AUTH_TOKEN: 'dummy', // copilot-api handles auth internally
|
||||||
ANTHROPIC_MODEL: config.model,
|
ANTHROPIC_MODEL: config.model,
|
||||||
// Model tier mapping - allows different models for opus/sonnet/haiku
|
// Model tier mapping - allows different models for opus/sonnet/haiku
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ import { CopilotModel } from './types';
|
|||||||
* Multipliers: 0 = free tier, 0.25-0.33 = cheap, 1 = standard, 3-10 = premium
|
* 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
|
// Anthropic Models - All require paid Copilot subscription
|
||||||
{
|
{
|
||||||
id: 'claude-sonnet-4.5',
|
id: 'claude-sonnet-4.5',
|
||||||
name: 'Claude Sonnet 4.5',
|
name: 'Claude Sonnet 4.5',
|
||||||
provider: 'anthropic',
|
provider: 'anthropic',
|
||||||
isDefault: true,
|
|
||||||
minPlan: 'pro',
|
minPlan: 'pro',
|
||||||
multiplier: 1,
|
multiplier: 1,
|
||||||
},
|
},
|
||||||
@@ -53,7 +52,7 @@ export const DEFAULT_COPILOT_MODELS: CopilotModel[] = [
|
|||||||
id: 'claude-haiku-4.5',
|
id: 'claude-haiku-4.5',
|
||||||
name: 'Claude Haiku 4.5',
|
name: 'Claude Haiku 4.5',
|
||||||
provider: 'anthropic',
|
provider: 'anthropic',
|
||||||
minPlan: 'free',
|
minPlan: 'pro', // Requires paid Copilot subscription
|
||||||
multiplier: 0.33,
|
multiplier: 0.33,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -93,7 +92,14 @@ export const DEFAULT_COPILOT_MODELS: CopilotModel[] = [
|
|||||||
},
|
},
|
||||||
{ id: 'gpt-5', name: 'GPT-5', provider: 'openai', minPlan: 'pro', multiplier: 1 },
|
{ 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-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 },
|
{
|
||||||
|
id: 'gpt-4.1',
|
||||||
|
name: 'GPT-4.1',
|
||||||
|
provider: 'openai',
|
||||||
|
isDefault: true,
|
||||||
|
minPlan: 'free',
|
||||||
|
multiplier: 0,
|
||||||
|
},
|
||||||
|
|
||||||
// Google Models
|
// Google Models
|
||||||
{
|
{
|
||||||
@@ -150,7 +156,8 @@ export async function fetchModelsFromDaemon(port: number): Promise<CopilotModel[
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const req = http.request(
|
const req = http.request(
|
||||||
{
|
{
|
||||||
hostname: 'localhost',
|
// Use 127.0.0.1 instead of localhost for more reliable local connections
|
||||||
|
hostname: '127.0.0.1',
|
||||||
port,
|
port,
|
||||||
path: '/v1/models',
|
path: '/v1/models',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@@ -171,7 +178,7 @@ export async function fetchModelsFromDaemon(port: number): Promise<CopilotModel[
|
|||||||
id: m.id,
|
id: m.id,
|
||||||
name: formatModelName(m.id),
|
name: formatModelName(m.id),
|
||||||
provider: detectProvider(m.id),
|
provider: detectProvider(m.id),
|
||||||
isDefault: m.id === 'claude-sonnet-4.5',
|
isDefault: m.id === 'gpt-4.1', // Free tier default
|
||||||
}));
|
}));
|
||||||
resolve(models.length > 0 ? models : DEFAULT_COPILOT_MODELS);
|
resolve(models.length > 0 ? models : DEFAULT_COPILOT_MODELS);
|
||||||
} else {
|
} else {
|
||||||
@@ -206,9 +213,10 @@ export async function getAvailableModels(port: number): Promise<CopilotModel[]>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default model.
|
* Get the default model.
|
||||||
|
* Uses gpt-4.1 as it's available on free tier.
|
||||||
*/
|
*/
|
||||||
export function getDefaultModel(): string {
|
export function getDefaultModel(): string {
|
||||||
return 'claude-sonnet-4.5';
|
return 'gpt-4.1';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1826,9 +1826,10 @@ apiRoutes.get('/copilot/settings/raw', (_req: Request, res: Response): void => {
|
|||||||
// If file doesn't exist, return default structure with all model mappings
|
// If file doesn't exist, return default structure with all model mappings
|
||||||
if (!fs.existsSync(settingsPath)) {
|
if (!fs.existsSync(settingsPath)) {
|
||||||
// Create settings structure matching CLIProxy pattern - always include all model mappings
|
// Create settings structure matching CLIProxy pattern - always include all model mappings
|
||||||
|
// Use 127.0.0.1 instead of localhost for more reliable local connections
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
env: {
|
env: {
|
||||||
ANTHROPIC_BASE_URL: `http://localhost:${copilotConfig.port}`,
|
ANTHROPIC_BASE_URL: `http://127.0.0.1:${copilotConfig.port}`,
|
||||||
ANTHROPIC_AUTH_TOKEN: 'copilot-managed',
|
ANTHROPIC_AUTH_TOKEN: 'copilot-managed',
|
||||||
ANTHROPIC_MODEL: defaultModel,
|
ANTHROPIC_MODEL: defaultModel,
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: copilotConfig.opus_model || defaultModel,
|
ANTHROPIC_DEFAULT_OPUS_MODEL: copilotConfig.opus_model || defaultModel,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const CodeEditor = lazy(() =>
|
|||||||
|
|
||||||
// Model presets for quick configuration
|
// Model presets for quick configuration
|
||||||
// Grouped by tier: Free (available to all) and Paid (requires Pro+)
|
// Grouped by tier: Free (available to all) and Paid (requires Pro+)
|
||||||
|
// Note: ALL Claude models require paid Copilot subscription
|
||||||
const FREE_PRESETS = [
|
const FREE_PRESETS = [
|
||||||
{
|
{
|
||||||
name: 'GPT-4.1 (Free)',
|
name: 'GPT-4.1 (Free)',
|
||||||
@@ -57,12 +58,12 @@ const FREE_PRESETS = [
|
|||||||
haiku: 'gpt-5-mini',
|
haiku: 'gpt-5-mini',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Claude Haiku 4.5 (Free)',
|
name: 'Raptor Mini (Free)',
|
||||||
description: 'Free tier - fast Anthropic model',
|
description: 'Free tier - fine-tuned for coding',
|
||||||
default: 'claude-haiku-4.5',
|
default: 'raptor-mini',
|
||||||
opus: 'claude-haiku-4.5',
|
opus: 'raptor-mini',
|
||||||
sonnet: 'claude-haiku-4.5',
|
sonnet: 'raptor-mini',
|
||||||
haiku: 'claude-haiku-4.5',
|
haiku: 'raptor-mini',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user