mirror of
https://github.com/tiennm99/ccs.git
synced 2026-08-17 08:23:34 +00:00
feat(cliproxy): deprecate claude thinking models in agy provider
Deprecated 2 Claude thinking models: - gemini-claude-opus-4-5-thinking - gemini-claude-sonnet-4-5-thinking These models have compatibility issues with Antigravity. A new deprecation system was added with badges and warnings in the UI.
This commit is contained in:
@@ -23,6 +23,10 @@ export interface ModelEntry {
|
|||||||
broken?: boolean;
|
broken?: boolean;
|
||||||
/** Issue URL for broken models */
|
/** Issue URL for broken models */
|
||||||
issueUrl?: string;
|
issueUrl?: string;
|
||||||
|
/** Model is deprecated - show warning when selected */
|
||||||
|
deprecated?: boolean;
|
||||||
|
/** Deprecation reason/message */
|
||||||
|
deprecationReason?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,16 +50,6 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
|||||||
displayName: 'Antigravity',
|
displayName: 'Antigravity',
|
||||||
defaultModel: 'gemini-3-pro-preview',
|
defaultModel: 'gemini-3-pro-preview',
|
||||||
models: [
|
models: [
|
||||||
{
|
|
||||||
id: 'gemini-claude-opus-4-5-thinking',
|
|
||||||
name: 'Claude Opus 4.5 Thinking',
|
|
||||||
description: 'Most capable, extended thinking',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'gemini-claude-sonnet-4-5-thinking',
|
|
||||||
name: 'Claude Sonnet 4.5 Thinking',
|
|
||||||
description: 'Balanced with extended thinking',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'gemini-claude-sonnet-4-5',
|
id: 'gemini-claude-sonnet-4-5',
|
||||||
name: 'Claude Sonnet 4.5',
|
name: 'Claude Sonnet 4.5',
|
||||||
@@ -66,6 +60,22 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
|||||||
name: 'Gemini 3 Pro',
|
name: 'Gemini 3 Pro',
|
||||||
description: 'Google latest model via Antigravity',
|
description: 'Google latest model via Antigravity',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'gemini-claude-opus-4-5-thinking',
|
||||||
|
name: 'Claude Opus 4.5 Thinking',
|
||||||
|
description: 'Most capable, extended thinking',
|
||||||
|
deprecated: true,
|
||||||
|
deprecationReason:
|
||||||
|
'Thinking models are deprecated due to compatibility issues with Antigravity',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gemini-claude-sonnet-4-5-thinking',
|
||||||
|
name: 'Claude Sonnet 4.5 Thinking',
|
||||||
|
description: 'Balanced with extended thinking',
|
||||||
|
deprecated: true,
|
||||||
|
deprecationReason:
|
||||||
|
'Thinking models are deprecated due to compatibility issues with Antigravity',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
gemini: {
|
gemini: {
|
||||||
@@ -126,3 +136,22 @@ export function getModelIssueUrl(provider: CLIProxyProvider, modelId: string): s
|
|||||||
const model = findModel(provider, modelId);
|
const model = findModel(provider, modelId);
|
||||||
return model?.issueUrl;
|
return model?.issueUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if model is deprecated
|
||||||
|
*/
|
||||||
|
export function isModelDeprecated(provider: CLIProxyProvider, modelId: string): boolean {
|
||||||
|
const model = findModel(provider, modelId);
|
||||||
|
return model?.deprecated === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get deprecation reason for deprecated model
|
||||||
|
*/
|
||||||
|
export function getModelDeprecationReason(
|
||||||
|
provider: CLIProxyProvider,
|
||||||
|
modelId: string
|
||||||
|
): string | undefined {
|
||||||
|
const model = findModel(provider, modelId);
|
||||||
|
return model?.deprecationReason;
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ function formatModelOption(model: ModelEntry): string {
|
|||||||
// Tier badge: clarify that "paid" means paid Google account (not free tier)
|
// Tier badge: clarify that "paid" means paid Google account (not free tier)
|
||||||
const tierBadge = model.tier === 'paid' ? color(' [Paid Tier]', 'warning') : '';
|
const tierBadge = model.tier === 'paid' ? color(' [Paid Tier]', 'warning') : '';
|
||||||
const brokenBadge = model.broken ? color(' [BROKEN]', 'error') : '';
|
const brokenBadge = model.broken ? color(' [BROKEN]', 'error') : '';
|
||||||
return `${model.name}${tierBadge}${brokenBadge}`;
|
const deprecatedBadge = model.deprecated ? color(' [DEPRECATED]', 'warning') : '';
|
||||||
|
return `${model.name}${tierBadge}${brokenBadge}${deprecatedBadge}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,8 +79,9 @@ function formatModelDetailed(model: ModelEntry, isCurrent: boolean): string {
|
|||||||
const name = isCurrent ? bold(model.name) : model.name;
|
const name = isCurrent ? bold(model.name) : model.name;
|
||||||
const tierBadge = model.tier === 'paid' ? color(' [Paid Tier]', 'warning') : '';
|
const tierBadge = model.tier === 'paid' ? color(' [Paid Tier]', 'warning') : '';
|
||||||
const brokenBadge = model.broken ? color(' [BROKEN]', 'error') : '';
|
const brokenBadge = model.broken ? color(' [BROKEN]', 'error') : '';
|
||||||
|
const deprecatedBadge = model.deprecated ? color(' [DEPRECATED]', 'warning') : '';
|
||||||
const desc = model.description ? dim(` - ${model.description}`) : '';
|
const desc = model.description ? dim(` - ${model.description}`) : '';
|
||||||
return ` ${marker} ${name}${tierBadge}${brokenBadge}${desc}`;
|
return ` ${marker} ${name}${tierBadge}${brokenBadge}${deprecatedBadge}${desc}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -136,6 +138,7 @@ export async function configureProviderModel(
|
|||||||
console.error(
|
console.error(
|
||||||
dim(' Models marked [Paid Tier] require a paid Google account (not free tier).')
|
dim(' Models marked [Paid Tier] require a paid Google account (not free tier).')
|
||||||
);
|
);
|
||||||
|
console.error(dim(' Models marked [DEPRECATED] are not recommended for use.'));
|
||||||
console.error('');
|
console.error('');
|
||||||
|
|
||||||
// Interactive selection
|
// Interactive selection
|
||||||
@@ -211,6 +214,15 @@ export async function configureProviderModel(
|
|||||||
console.error(ok(`Model set to: ${bold(displayName)}`));
|
console.error(ok(`Model set to: ${bold(displayName)}`));
|
||||||
console.error(dim(` Config saved: ${settingsPath}`));
|
console.error(dim(` Config saved: ${settingsPath}`));
|
||||||
|
|
||||||
|
// Show deprecation warning if model is deprecated
|
||||||
|
if (selectedEntry?.deprecated) {
|
||||||
|
console.error('');
|
||||||
|
console.error(color('[!] DEPRECATION WARNING', 'warning'));
|
||||||
|
const reason = selectedEntry.deprecationReason || 'This model is deprecated';
|
||||||
|
console.error(dim(` ${reason}`));
|
||||||
|
console.error(dim(' Consider using a non-deprecated model for better compatibility.'));
|
||||||
|
}
|
||||||
|
|
||||||
// Show info for Claude models about thinking token limit
|
// Show info for Claude models about thinking token limit
|
||||||
if (isClaude) {
|
if (isClaude) {
|
||||||
console.error('');
|
console.error('');
|
||||||
@@ -261,6 +273,7 @@ export async function showCurrentConfig(provider: CLIProxyProvider): Promise<voi
|
|||||||
console.error('');
|
console.error('');
|
||||||
console.error(bold('Available models:'));
|
console.error(bold('Available models:'));
|
||||||
console.error(dim(' [Paid Tier] = Requires paid Google account (not free tier)'));
|
console.error(dim(' [Paid Tier] = Requires paid Google account (not free tier)'));
|
||||||
|
console.error(dim(' [DEPRECATED] = Not recommended for use'));
|
||||||
console.error('');
|
console.error('');
|
||||||
catalog.models.forEach((m) => {
|
catalog.models.forEach((m) => {
|
||||||
const isCurrent = m.id === currentModel;
|
const isCurrent = m.id === currentModel;
|
||||||
|
|||||||
@@ -214,4 +214,86 @@ describe('Model Catalog', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Deprecated models', () => {
|
||||||
|
it('Claude Opus 4.5 Thinking is marked as deprecated', () => {
|
||||||
|
const { MODEL_CATALOG } = modelCatalog;
|
||||||
|
const opus = MODEL_CATALOG.agy.models.find(
|
||||||
|
(m) => m.id === 'gemini-claude-opus-4-5-thinking'
|
||||||
|
);
|
||||||
|
assert(opus, 'Should include Claude Opus 4.5 Thinking');
|
||||||
|
assert.strictEqual(opus.deprecated, true, 'Should be marked as deprecated');
|
||||||
|
assert(opus.deprecationReason, 'Should have deprecation reason');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Claude Sonnet 4.5 Thinking is marked as deprecated', () => {
|
||||||
|
const { MODEL_CATALOG } = modelCatalog;
|
||||||
|
const sonnetThinking = MODEL_CATALOG.agy.models.find(
|
||||||
|
(m) => m.id === 'gemini-claude-sonnet-4-5-thinking'
|
||||||
|
);
|
||||||
|
assert(sonnetThinking, 'Should include Claude Sonnet 4.5 Thinking');
|
||||||
|
assert.strictEqual(sonnetThinking.deprecated, true, 'Should be marked as deprecated');
|
||||||
|
assert(sonnetThinking.deprecationReason, 'Should have deprecation reason');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('deprecated models are at the bottom of the list', () => {
|
||||||
|
const { MODEL_CATALOG } = modelCatalog;
|
||||||
|
const models = MODEL_CATALOG.agy.models;
|
||||||
|
|
||||||
|
// Find indices of deprecated models
|
||||||
|
const opusIdx = models.findIndex((m) => m.id === 'gemini-claude-opus-4-5-thinking');
|
||||||
|
const sonnetThinkingIdx = models.findIndex(
|
||||||
|
(m) => m.id === 'gemini-claude-sonnet-4-5-thinking'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find indices of non-deprecated models
|
||||||
|
const sonnetIdx = models.findIndex((m) => m.id === 'gemini-claude-sonnet-4-5');
|
||||||
|
const geminiIdx = models.findIndex((m) => m.id === 'gemini-3-pro-preview');
|
||||||
|
|
||||||
|
// Deprecated models should come after non-deprecated models
|
||||||
|
assert(opusIdx > sonnetIdx, 'Opus Thinking should be below non-deprecated Sonnet');
|
||||||
|
assert(opusIdx > geminiIdx, 'Opus Thinking should be below non-deprecated Gemini');
|
||||||
|
assert(
|
||||||
|
sonnetThinkingIdx > sonnetIdx,
|
||||||
|
'Sonnet Thinking should be below non-deprecated Sonnet'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
sonnetThinkingIdx > geminiIdx,
|
||||||
|
'Sonnet Thinking should be below non-deprecated Gemini'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isModelDeprecated', () => {
|
||||||
|
it('returns true for deprecated models', () => {
|
||||||
|
const { isModelDeprecated } = modelCatalog;
|
||||||
|
assert.strictEqual(isModelDeprecated('agy', 'gemini-claude-opus-4-5-thinking'), true);
|
||||||
|
assert.strictEqual(isModelDeprecated('agy', 'gemini-claude-sonnet-4-5-thinking'), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false for non-deprecated models', () => {
|
||||||
|
const { isModelDeprecated } = modelCatalog;
|
||||||
|
assert.strictEqual(isModelDeprecated('agy', 'gemini-claude-sonnet-4-5'), false);
|
||||||
|
assert.strictEqual(isModelDeprecated('agy', 'gemini-3-pro-preview'), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false for unknown models', () => {
|
||||||
|
const { isModelDeprecated } = modelCatalog;
|
||||||
|
assert.strictEqual(isModelDeprecated('agy', 'unknown-model'), false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getModelDeprecationReason', () => {
|
||||||
|
it('returns deprecation reason for deprecated models', () => {
|
||||||
|
const { getModelDeprecationReason } = modelCatalog;
|
||||||
|
const reason = getModelDeprecationReason('agy', 'gemini-claude-opus-4-5-thinking');
|
||||||
|
assert(reason, 'Should have deprecation reason');
|
||||||
|
assert(typeof reason === 'string', 'Reason should be a string');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns undefined for non-deprecated models', () => {
|
||||||
|
const { getModelDeprecationReason } = modelCatalog;
|
||||||
|
assert.strictEqual(getModelDeprecationReason('agy', 'gemini-claude-sonnet-4-5'), undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user