mirror of
https://github.com/alsk1992/CloddsBot.git
synced 2026-10-02 02:54:40 +08:00
fix: replace retired Anthropic model defaults
This commit is contained in:
+2
-1
@@ -342,7 +342,7 @@ const STREAM_RESPONSE_PLATFORMS = new Set([
|
||||
'teams',
|
||||
'webchat',
|
||||
]);
|
||||
const MEMORY_EXTRACT_MODEL = process.env.CLODDS_MEMORY_EXTRACT_MODEL || process.env.CLODDS_SUMMARY_MODEL || 'claude-3-5-haiku-20241022';
|
||||
const MEMORY_EXTRACT_MODEL = process.env.CLODDS_MEMORY_EXTRACT_MODEL || process.env.CLODDS_SUMMARY_MODEL || 'claude-haiku-4-5-20251001';
|
||||
const KALSHI_API_BASE = 'https://api.elections.kalshi.com/trade-api/v2';
|
||||
const DRIFT_GATEWAY_URL = process.env.DRIFT_GATEWAY_URL || 'http://localhost:8080';
|
||||
|
||||
@@ -17642,6 +17642,7 @@ export async function createAgentManager(
|
||||
const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
|
||||
'claude-opus-4-6': 200000,
|
||||
'claude-opus-4-5-20250514': 200000,
|
||||
'claude-sonnet-4-6': 200000,
|
||||
'claude-sonnet-4-5-20250929': 200000,
|
||||
'claude-sonnet-4-20250514': 200000,
|
||||
'claude-haiku-4-5-20251001': 200000,
|
||||
|
||||
@@ -150,6 +150,10 @@ export interface RunRegistryEntry {
|
||||
// =============================================================================
|
||||
|
||||
const MODEL_COSTS: Record<string, { input: number; output: number }> = {
|
||||
'claude-opus-4-6': { input: 5, output: 25 },
|
||||
'claude-sonnet-4-6': { input: 3, output: 15 },
|
||||
'claude-sonnet-4-5-20250929': { input: 3, output: 15 },
|
||||
'claude-haiku-4-5-20251001': { input: 1, output: 5 },
|
||||
'claude-3-opus-20240229': { input: 15, output: 75 },
|
||||
'claude-3-5-sonnet-20241022': { input: 3, output: 15 },
|
||||
'claude-3-5-haiku-20241022': { input: 0.25, output: 1.25 },
|
||||
@@ -553,7 +557,7 @@ export function createSubagentManager(): SubagentManager {
|
||||
anthropicClient = new Anthropic({ apiKey });
|
||||
}
|
||||
|
||||
const model = state.config.model || 'claude-3-5-sonnet-20241022';
|
||||
const model = state.config.model || 'claude-sonnet-4-6';
|
||||
const maxTurns = state.config.maxTurns || 10;
|
||||
const timeout = state.config.timeout || 300000; // 5 min default
|
||||
|
||||
|
||||
@@ -135,10 +135,7 @@ export function createModelCommands(program: Command): void {
|
||||
{ id: 'claude-opus-4-6', provider: 'anthropic', context: '200K' },
|
||||
{ id: 'claude-sonnet-4-5-20250929', provider: 'anthropic', context: '200K' },
|
||||
{ id: 'claude-haiku-4-5-20251001', provider: 'anthropic', context: '200K' },
|
||||
// Anthropic (Legacy)
|
||||
{ id: 'claude-3-5-sonnet-20241022', provider: 'anthropic', context: '200K' },
|
||||
{ id: 'claude-3-opus-20240229', provider: 'anthropic', context: '200K' },
|
||||
{ id: 'claude-3-5-haiku-20241022', provider: 'anthropic', context: '200K' },
|
||||
{ id: 'claude-sonnet-4-6', provider: 'anthropic', context: '200K' },
|
||||
// OpenAI
|
||||
{ id: 'gpt-4o', provider: 'openai', context: '128K' },
|
||||
{ id: 'gpt-4-turbo', provider: 'openai', context: '128K' },
|
||||
@@ -175,7 +172,7 @@ export function createModelCommands(program: Command): void {
|
||||
writeFileSync(configPath, JSON.stringify(data, null, 2));
|
||||
console.log(`Default model set to: ${model}`);
|
||||
} else {
|
||||
console.log(`Default model: ${data.defaultModel || 'claude-3-5-sonnet-20241022'}`);
|
||||
console.log(`Default model: ${data.defaultModel || 'claude-sonnet-4-6'}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2034,7 +2031,7 @@ export function createInitCommand(program: Command): void {
|
||||
const defaultConfig = {
|
||||
name: 'clodds-project',
|
||||
version: '0.1.0',
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
model: 'claude-sonnet-4-6',
|
||||
features: {
|
||||
memory: true,
|
||||
tools: true,
|
||||
@@ -2201,7 +2198,7 @@ export function createCredsCommands(program: Command): void {
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'claude-3-haiku-20240307',
|
||||
model: 'claude-haiku-4-5-20251001',
|
||||
max_tokens: 1,
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
@@ -3434,7 +3431,7 @@ export function createDoctorCommand(program: Command): void {
|
||||
const r = await fetch('https://api.anthropic.com/v1/messages', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'x-api-key': anthropicKey, 'anthropic-version': '2023-06-01' },
|
||||
body: JSON.stringify({ model: 'claude-3-haiku-20240307', max_tokens: 1, messages: [{ role: 'user', content: 'hi' }] }),
|
||||
body: JSON.stringify({ model: 'claude-haiku-4-5-20251001', max_tokens: 1, messages: [{ role: 'user', content: 'hi' }] }),
|
||||
});
|
||||
if (r.ok || r.status === 429) {
|
||||
results.push({ name: 'Anthropic', status: 'pass', message: r.ok ? 'Key valid' : 'Key valid (rate limited)' });
|
||||
|
||||
@@ -38,7 +38,7 @@ async function validateAnthropicKey(key: string): Promise<{ valid: boolean; erro
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'claude-3-haiku-20240307',
|
||||
model: 'claude-haiku-4-5-20251001',
|
||||
max_tokens: 1,
|
||||
messages: [{ role: 'user', content: 'Hi' }],
|
||||
}),
|
||||
|
||||
+1
-1
@@ -268,7 +268,7 @@ const checks: Record<string, Check> = {
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'claude-3-haiku-20240307',
|
||||
model: 'claude-haiku-4-5-20251001',
|
||||
max_tokens: 1,
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
|
||||
@@ -298,7 +298,7 @@ ${doc.content}
|
||||
Respond with ONLY the edited document content, no explanations. Preserve the original format.`;
|
||||
|
||||
const response = await provider.complete({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
model: 'claude-sonnet-4-6',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
maxTokens: 8192,
|
||||
});
|
||||
@@ -353,7 +353,7 @@ ${textAfter ? `Text after cursor:\n${textAfter}` : ''}
|
||||
Provide only the completion text, no explanations. Write 1-3 sentences that naturally continue from where the cursor is.`;
|
||||
|
||||
const response = await provider.complete({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
model: 'claude-sonnet-4-6',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
maxTokens: 500,
|
||||
});
|
||||
@@ -379,7 +379,7 @@ Provide only the completion text, no explanations. Write 1-3 sentences that natu
|
||||
${doc.content}`;
|
||||
|
||||
const response = await provider.complete({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
model: 'claude-sonnet-4-6',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
maxTokens: 200,
|
||||
});
|
||||
@@ -404,7 +404,7 @@ ${doc.content}
|
||||
Output only the rewritten document content.`;
|
||||
|
||||
const response = await provider.complete({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
model: 'claude-sonnet-4-6',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
maxTokens: 8192,
|
||||
});
|
||||
@@ -448,7 +448,7 @@ ${doc.content}
|
||||
Output the expanded document.`;
|
||||
|
||||
const response = await provider.complete({
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
model: 'claude-sonnet-4-6',
|
||||
messages: [{ role: 'user', content: prompt }],
|
||||
maxTokens: 8192,
|
||||
});
|
||||
|
||||
@@ -269,7 +269,7 @@ builtInExecutors.set('llm', {
|
||||
async execute(task, context) {
|
||||
const prompt = task.input?.prompt as string;
|
||||
const systemPrompt = task.input?.system as string;
|
||||
const model = (task.input?.model as string) || 'claude-3-5-sonnet-20241022';
|
||||
const model = (task.input?.model as string) || 'claude-sonnet-4-6';
|
||||
|
||||
const messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }> = [];
|
||||
if (systemPrompt) {
|
||||
@@ -441,7 +441,7 @@ export class TaskRunner {
|
||||
* Plan tasks from a high-level goal
|
||||
*/
|
||||
async planTasks(goal: string, context?: string): Promise<TaskDefinition[]> {
|
||||
const planningModel = this.config.planningModel || 'claude-3-5-sonnet-20241022';
|
||||
const planningModel = this.config.planningModel || 'claude-sonnet-4-6';
|
||||
|
||||
const systemPrompt = `You are a task planner. Given a high-level goal, break it down into concrete, executable tasks.
|
||||
|
||||
|
||||
+1
-1
@@ -822,7 +822,7 @@ export function createVisionService(): VisionService {
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'claude-sonnet-4-20250514',
|
||||
model: 'claude-sonnet-4-6',
|
||||
max_tokens: 1024,
|
||||
messages: [{
|
||||
role: 'user',
|
||||
|
||||
@@ -12,7 +12,7 @@ interface ClaudeSummarizerOptions {
|
||||
model?: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SUMMARY_MODEL = process.env.CLODDS_SUMMARY_MODEL || 'claude-3-5-haiku-20241022';
|
||||
const DEFAULT_SUMMARY_MODEL = process.env.CLODDS_SUMMARY_MODEL || 'claude-haiku-4-5-20251001';
|
||||
|
||||
export function createClaudeSummarizer(options: ClaudeSummarizerOptions = {}): SummarizerFn | undefined {
|
||||
const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;
|
||||
|
||||
@@ -22,6 +22,7 @@ const MODEL_META: Record<string, ModelMeta> = {
|
||||
// Latest models
|
||||
'claude-opus-4-6': { costScore: 1, speedScore: 3, qualityScore: 10 },
|
||||
'claude-opus-4-5-20250514': { costScore: 2, speedScore: 4, qualityScore: 10 },
|
||||
'claude-sonnet-4-6': { costScore: 5, speedScore: 7, qualityScore: 9 },
|
||||
'claude-sonnet-4-5-20250929': { costScore: 5, speedScore: 7, qualityScore: 9 },
|
||||
'claude-sonnet-4-20250514': { costScore: 6, speedScore: 7, qualityScore: 8 },
|
||||
'claude-haiku-4-5-20251001': { costScore: 9, speedScore: 10, qualityScore: 7 },
|
||||
|
||||
@@ -115,6 +115,38 @@ export function createModelRegistry(providers: Map<string, Provider>): ModelRegi
|
||||
|
||||
// Known model metadata
|
||||
const KNOWN_MODELS: Record<string, Partial<DiscoveredModel>> = {
|
||||
'claude-opus-4-6': {
|
||||
name: 'Claude Opus 4.6',
|
||||
contextWindow: 200000,
|
||||
maxOutput: 128000,
|
||||
inputCostPer1k: 0.005,
|
||||
outputCostPer1k: 0.025,
|
||||
capabilities: ['vision', 'tools', 'streaming'],
|
||||
},
|
||||
'claude-sonnet-4-6': {
|
||||
name: 'Claude Sonnet 4.6',
|
||||
contextWindow: 200000,
|
||||
maxOutput: 64000,
|
||||
inputCostPer1k: 0.003,
|
||||
outputCostPer1k: 0.015,
|
||||
capabilities: ['vision', 'tools', 'streaming'],
|
||||
},
|
||||
'claude-sonnet-4-5-20250929': {
|
||||
name: 'Claude Sonnet 4.5',
|
||||
contextWindow: 200000,
|
||||
maxOutput: 8192,
|
||||
inputCostPer1k: 0.003,
|
||||
outputCostPer1k: 0.015,
|
||||
capabilities: ['vision', 'tools', 'streaming'],
|
||||
},
|
||||
'claude-haiku-4-5-20251001': {
|
||||
name: 'Claude Haiku 4.5',
|
||||
contextWindow: 200000,
|
||||
maxOutput: 8192,
|
||||
inputCostPer1k: 0.001,
|
||||
outputCostPer1k: 0.005,
|
||||
capabilities: ['vision', 'tools', 'streaming'],
|
||||
},
|
||||
'claude-3-5-sonnet-20241022': {
|
||||
name: 'Claude 3.5 Sonnet',
|
||||
contextWindow: 200000,
|
||||
|
||||
+10
-6
@@ -265,7 +265,7 @@ export class AnthropicProvider implements Provider {
|
||||
constructor(config: ProviderConfig) {
|
||||
this.config = {
|
||||
baseUrl: 'https://api.anthropic.com',
|
||||
defaultModel: 'claude-3-5-sonnet-20241022',
|
||||
defaultModel: 'claude-sonnet-4-6',
|
||||
timeout: 120000,
|
||||
maxRetries: 3,
|
||||
...config,
|
||||
@@ -403,10 +403,10 @@ export class AnthropicProvider implements Provider {
|
||||
|
||||
async listModels(): Promise<string[]> {
|
||||
return [
|
||||
'claude-3-5-sonnet-20241022',
|
||||
'claude-3-opus-20240229',
|
||||
'claude-3-sonnet-20240229',
|
||||
'claude-3-haiku-20240307',
|
||||
'claude-opus-4-6',
|
||||
'claude-sonnet-4-6',
|
||||
'claude-sonnet-4-5-20250929',
|
||||
'claude-haiku-4-5-20251001',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ export class AnthropicProvider implements Provider {
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'claude-3-haiku-20240307',
|
||||
model: 'claude-haiku-4-5-20251001',
|
||||
max_tokens: 1,
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
@@ -1044,6 +1044,10 @@ export interface CostConfig {
|
||||
}
|
||||
|
||||
const MODEL_COSTS: Record<string, CostConfig> = {
|
||||
'claude-opus-4-6': { inputCostPer1k: 0.005, outputCostPer1k: 0.025 },
|
||||
'claude-sonnet-4-6': { inputCostPer1k: 0.003, outputCostPer1k: 0.015 },
|
||||
'claude-sonnet-4-5-20250929': { inputCostPer1k: 0.003, outputCostPer1k: 0.015 },
|
||||
'claude-haiku-4-5-20251001': { inputCostPer1k: 0.001, outputCostPer1k: 0.005 },
|
||||
'claude-3-5-sonnet-20241022': { inputCostPer1k: 0.003, outputCostPer1k: 0.015 },
|
||||
'claude-3-opus-20240229': { inputCostPer1k: 0.015, outputCostPer1k: 0.075 },
|
||||
'claude-3-sonnet-20240229': { inputCostPer1k: 0.003, outputCostPer1k: 0.015 },
|
||||
|
||||
@@ -175,7 +175,7 @@ async function execute(args: string): Promise<string> {
|
||||
|
||||
case 'estimate': {
|
||||
// Estimate cost for a hypothetical request
|
||||
const model = parts[1] || 'claude-sonnet-4-20250514';
|
||||
const model = parts[1] || 'claude-sonnet-4-6';
|
||||
const inputTokens = parseInt(parts[2] || '1000', 10);
|
||||
const outputTokens = parseInt(parts[3] || '500', 10);
|
||||
const cost = service.estimateCost(model, inputTokens, outputTokens);
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export interface ImageTool {
|
||||
}
|
||||
|
||||
const DEFAULT_PROMPT = 'Describe this image in detail. Include any text visible in the image.';
|
||||
const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
|
||||
const DEFAULT_MODEL = 'claude-sonnet-4-6';
|
||||
const DEFAULT_MAX_TOKENS = 1024;
|
||||
const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000;
|
||||
const DEFAULT_RATE_LIMIT_WINDOW_MS = 60_000;
|
||||
|
||||
+4
-1
@@ -15,8 +15,11 @@ import { generateId } from '../utils/id';
|
||||
|
||||
/** Model pricing (per 1M tokens) */
|
||||
const MODEL_PRICING: Record<string, { input: number; output: number }> = {
|
||||
'claude-opus-4-6': { input: 5.0, output: 25.0 },
|
||||
'claude-sonnet-4-6': { input: 3.0, output: 15.0 },
|
||||
'claude-sonnet-4-5-20250929': { input: 3.0, output: 15.0 },
|
||||
'claude-haiku-4-5-20251001': { input: 1.0, output: 5.0 },
|
||||
'claude-opus-4-5-20250514': { input: 15.0, output: 75.0 },
|
||||
'claude-sonnet-4-20250514': { input: 3.0, output: 15.0 },
|
||||
'claude-haiku-3-5-20250514': { input: 0.25, output: 1.25 },
|
||||
// Fallback for unknown models
|
||||
default: { input: 3.0, output: 15.0 },
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { AnthropicProvider } from '../../src/providers/index';
|
||||
|
||||
const RETIRED_MODELS = [
|
||||
'claude-3-haiku-20240307',
|
||||
'claude-3-5-haiku-20241022',
|
||||
'claude-3-5-sonnet-20241022',
|
||||
'claude-sonnet-4-20250514',
|
||||
];
|
||||
|
||||
test('runtime model defaults do not use retired Anthropic IDs', () => {
|
||||
const runtimeFiles = [
|
||||
'src/cli/commands/index.ts',
|
||||
'src/cli/commands/onboard.ts',
|
||||
'src/doctor/index.ts',
|
||||
'src/extensions/open-prose/index.ts',
|
||||
'src/extensions/task-runner/index.ts',
|
||||
'src/memory/summarizer.ts',
|
||||
'src/media/index.ts',
|
||||
'src/skills/bundled/usage/index.ts',
|
||||
'src/tools/image.ts',
|
||||
'src/usage/index.ts',
|
||||
];
|
||||
|
||||
for (const relativePath of runtimeFiles) {
|
||||
const source = readFileSync(join(process.cwd(), relativePath), 'utf8');
|
||||
for (const retiredModel of RETIRED_MODELS) {
|
||||
assert.equal(
|
||||
source.includes(retiredModel),
|
||||
false,
|
||||
`${relativePath} still references retired model ${retiredModel}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('Anthropic provider uses active defaults for completion and health checks', async () => {
|
||||
const requests: Array<{ url: string; body: Record<string, unknown> }> = [];
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = (async (input, init) => {
|
||||
requests.push({
|
||||
url: String(input),
|
||||
body: JSON.parse(String(init?.body)) as Record<string, unknown>,
|
||||
});
|
||||
return new Response(JSON.stringify({
|
||||
content: [{ text: 'ok' }],
|
||||
model: 'claude-sonnet-4-6',
|
||||
usage: { input_tokens: 1, output_tokens: 1 },
|
||||
stop_reason: 'end_turn',
|
||||
}), { status: 200, headers: { 'content-type': 'application/json' } });
|
||||
}) as typeof fetch;
|
||||
|
||||
try {
|
||||
const provider = new AnthropicProvider({ apiKey: 'test-key' });
|
||||
await provider.complete([{ role: 'user', content: 'hello' }]);
|
||||
await provider.isAvailable();
|
||||
|
||||
assert.equal(requests[0].body.model, 'claude-sonnet-4-6');
|
||||
assert.equal(requests[1].body.model, 'claude-haiku-4-5-20251001');
|
||||
assert.deepEqual(await provider.listModels(), [
|
||||
'claude-opus-4-6',
|
||||
'claude-sonnet-4-6',
|
||||
'claude-sonnet-4-5-20250929',
|
||||
'claude-haiku-4-5-20251001',
|
||||
]);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user