mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-17 04:17:11 +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;
|
||||
/** Issue URL for broken models */
|
||||
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',
|
||||
defaultModel: 'gemini-3-pro-preview',
|
||||
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',
|
||||
name: 'Claude Sonnet 4.5',
|
||||
@@ -66,6 +60,22 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
|
||||
name: 'Gemini 3 Pro',
|
||||
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: {
|
||||
@@ -126,3 +136,22 @@ export function getModelIssueUrl(provider: CLIProxyProvider, modelId: string): s
|
||||
const model = findModel(provider, modelId);
|
||||
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)
|
||||
const tierBadge = model.tier === 'paid' ? color(' [Paid Tier]', 'warning') : '';
|
||||
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 tierBadge = model.tier === 'paid' ? color(' [Paid Tier]', 'warning') : '';
|
||||
const brokenBadge = model.broken ? color(' [BROKEN]', 'error') : '';
|
||||
const deprecatedBadge = model.deprecated ? color(' [DEPRECATED]', 'warning') : '';
|
||||
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(
|
||||
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('');
|
||||
|
||||
// Interactive selection
|
||||
@@ -211,6 +214,15 @@ export async function configureProviderModel(
|
||||
console.error(ok(`Model set to: ${bold(displayName)}`));
|
||||
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
|
||||
if (isClaude) {
|
||||
console.error('');
|
||||
@@ -261,6 +273,7 @@ export async function showCurrentConfig(provider: CLIProxyProvider): Promise<voi
|
||||
console.error('');
|
||||
console.error(bold('Available models:'));
|
||||
console.error(dim(' [Paid Tier] = Requires paid Google account (not free tier)'));
|
||||
console.error(dim(' [DEPRECATED] = Not recommended for use'));
|
||||
console.error('');
|
||||
catalog.models.forEach((m) => {
|
||||
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