Skip to content

Commit 05c1724

Browse files
fix: centralize stale model IDs into single CLAUDE_MODELS constant
Hardcoded model IDs (claude-sonnet-4-20250514, claude-opus-4-20250514) were scattered across 7+ files as fallbacks. These were stale after the CLI update to v2.1.73 which resolves aliases to the new model IDs (claude-sonnet-4-6, claude-opus-4-6). - Add src/lib/model-ids.ts with CLAUDE_MODELS + DEFAULT_MODEL_ID (client-safe, no fs/db imports — avoids Next.js bundling errors) - provider-resolver.ts: import + re-export from model-ids.ts, replace hardcoded envModels and toAiSdkConfig fallback - model-context.ts: derive context window map from CLAUDE_MODELS (import from model-ids.ts to stay client-safe) - skills/search/route.ts: derive MODEL_MAP from CLAUDE_MODELS - checkin-processor.ts, onboarding-processor.ts, media/jobs/plan/route.ts: use DEFAULT_MODEL_ID for last-resort fallback One place to update when new models release. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e694d75 commit 05c1724

7 files changed

Lines changed: 45 additions & 24 deletions

File tree

src/app/api/media/jobs/plan/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NextRequest } from 'next/server';
22
import { streamTextFromProvider } from '@/lib/text-generator';
3-
import { resolveProvider } from '@/lib/provider-resolver';
3+
import { resolveProvider, DEFAULT_MODEL_ID } from '@/lib/provider-resolver';
44
import fs from 'fs';
55
import type { PlanMediaJobRequest } from '@/types';
66

@@ -62,7 +62,7 @@ export async function POST(request: NextRequest) {
6262
});
6363
// Preserve 'env' semantics (see onboarding route for rationale)
6464
const providerId = resolved.provider?.id || 'env';
65-
const modelId = resolved.upstreamModel || resolved.model || session?.model || 'claude-sonnet-4-20250514';
65+
const modelId = resolved.upstreamModel || resolved.model || session?.model || DEFAULT_MODEL_ID;
6666

6767
// Read document content
6868
let docContent = body.docContent || '';

src/app/api/skills/search/route.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NextResponse } from 'next/server';
22
import { getActiveProvider, getSetting } from '@/lib/db';
3+
import { CLAUDE_MODELS } from '@/lib/provider-resolver';
34

45
interface SkillInfo {
56
name: string;
@@ -12,12 +13,10 @@ interface SearchRequest {
1213
model?: string;
1314
}
1415

15-
// Model alias -> full model ID
16-
const MODEL_MAP: Record<string, string> = {
17-
sonnet: 'claude-sonnet-4-20250514',
18-
opus: 'claude-opus-4-20250514',
19-
haiku: 'claude-haiku-4-20250414',
20-
};
16+
// Model alias -> full model ID (derived from central CLAUDE_MODELS)
17+
const MODEL_MAP: Record<string, string> = Object.fromEntries(
18+
Object.entries(CLAUDE_MODELS).map(([alias, m]) => [alias, m.id])
19+
);
2120

2221
interface ApiConfig {
2322
supported: boolean;

src/lib/checkin-processor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import fs from 'fs';
77
import path from 'path';
88
import { getSetting, getSession } from '@/lib/db';
9-
import { resolveProvider } from '@/lib/provider-resolver';
9+
import { resolveProvider, DEFAULT_MODEL_ID } from '@/lib/provider-resolver';
1010
import { loadState, saveState, writeDailyMemory } from '@/lib/assistant-workspace';
1111
import { getLocalDateString } from '@/lib/utils';
1212
import { generateTextFromProvider } from '@/lib/text-generator';
@@ -70,7 +70,7 @@ export async function processCheckin(
7070
sessionModel: session?.model || undefined,
7171
});
7272
const providerId = resolved.provider?.id || 'env';
73-
const model = resolved.upstreamModel || resolved.model || getSetting('default_model') || 'claude-sonnet-4-20250514';
73+
const model = resolved.upstreamModel || resolved.model || getSetting('default_model') || DEFAULT_MODEL_ID;
7474

7575
const dailyMemoryPrompt = `You maintain daily memory entries for an AI assistant. Given the user's daily check-in answers, generate a daily memory entry for ${today}.
7676

src/lib/model-context.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { CLAUDE_MODELS } from './model-ids';
2+
13
export const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
2-
'sonnet': 200000,
3-
'opus': 200000,
4-
'haiku': 200000,
5-
'claude-sonnet-4-20250514': 200000,
6-
'claude-opus-4-20250514': 200000,
7-
'claude-haiku-4-5-20251001': 200000,
4+
// Short aliases
5+
...Object.fromEntries(Object.entries(CLAUDE_MODELS).map(([alias, m]) => [alias, m.contextWindow])),
6+
// Full model IDs
7+
...Object.fromEntries(Object.values(CLAUDE_MODELS).map(m => [m.id, m.contextWindow])),
88
};
99

1010
export function getContextWindow(model: string): number | null {

src/lib/model-ids.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Canonical Claude model definitions — single source of truth.
3+
*
4+
* This file has ZERO server-side imports (no fs, no db) so it can be
5+
* safely imported from both server code and client-side React hooks.
6+
*
7+
* Update these when Anthropic releases new model generations.
8+
*/
9+
10+
export const CLAUDE_MODELS = {
11+
sonnet: { id: 'claude-sonnet-4-6', displayName: 'Sonnet 4.6', contextWindow: 200000 },
12+
opus: { id: 'claude-opus-4-6', displayName: 'Opus 4.6', contextWindow: 200000 },
13+
haiku: { id: 'claude-haiku-4-5-20251001', displayName: 'Haiku 4.5', contextWindow: 200000 },
14+
} as const;
15+
16+
/** Default model ID used as a last-resort fallback */
17+
export const DEFAULT_MODEL_ID = CLAUDE_MODELS.sonnet.id;

src/lib/onboarding-processor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import fs from 'fs';
77
import path from 'path';
88
import { getSetting, getSession } from '@/lib/db';
9-
import { resolveProvider } from '@/lib/provider-resolver';
9+
import { resolveProvider, DEFAULT_MODEL_ID } from '@/lib/provider-resolver';
1010
import { loadState, saveState, ensureDailyDir, generateRootDocs } from '@/lib/assistant-workspace';
1111
import { getLocalDateString } from '@/lib/utils';
1212
import { generateTextFromProvider } from '@/lib/text-generator';
@@ -74,7 +74,7 @@ export async function processOnboarding(
7474
sessionModel: session?.model || undefined,
7575
});
7676
const providerId = resolved.provider?.id || 'env';
77-
const model = resolved.upstreamModel || resolved.model || getSetting('default_model') || 'claude-sonnet-4-20250514';
77+
const model = resolved.upstreamModel || resolved.model || getSetting('default_model') || DEFAULT_MODEL_ID;
7878

7979
const soulPrompt = `Based on the following user onboarding answers, generate a concise "soul.md" file that defines an AI assistant's personality, communication style, and behavioral rules. Write in second person ("You are..."). Keep it under 2000 characters. Use markdown headers and bullet points.\n\n${qaText}`;
8080

src/lib/provider-resolver.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ import {
2525
getModelsForProvider,
2626
} from './db';
2727

28+
// Canonical model definitions live in model-ids.ts (client-safe, no fs/db imports).
29+
// Import for local use and re-export for external consumers.
30+
import { CLAUDE_MODELS, DEFAULT_MODEL_ID } from './model-ids';
31+
export { CLAUDE_MODELS, DEFAULT_MODEL_ID };
32+
2833
// ── Resolution result ───────────────────────────────────────────
2934

3035
export interface ResolvedProvider {
@@ -285,7 +290,7 @@ export function toAiSdkConfig(
285290
const catalogEntry = resolved.availableModels.find(m => m.modelId === modelOverride);
286291
modelId = catalogEntry?.upstreamModelId || modelOverride;
287292
} else {
288-
modelId = resolved.upstreamModel || resolved.model || 'claude-sonnet-4-20250514';
293+
modelId = resolved.upstreamModel || resolved.model || DEFAULT_MODEL_ID;
289294
}
290295
const provider = resolved.provider;
291296
const protocol = resolved.protocol;
@@ -461,11 +466,11 @@ function buildResolution(
461466

462467
// Env mode uses short aliases (sonnet/opus/haiku) in the UI.
463468
// Map them to full Anthropic model IDs so toAiSdkConfig can resolve correctly.
464-
const envModels: CatalogModel[] = [
465-
{ modelId: 'sonnet', upstreamModelId: 'claude-sonnet-4-20250514', displayName: 'Sonnet 4.6' },
466-
{ modelId: 'opus', upstreamModelId: 'claude-opus-4-20250514', displayName: 'Opus 4.6' },
467-
{ modelId: 'haiku', upstreamModelId: 'claude-haiku-4-5-20251001', displayName: 'Haiku 4.5' },
468-
];
469+
const envModels: CatalogModel[] = Object.entries(CLAUDE_MODELS).map(([alias, m]) => ({
470+
modelId: alias,
471+
upstreamModelId: m.id,
472+
displayName: m.displayName,
473+
}));
469474

470475
// Resolve upstream model from the alias table
471476
const catalogEntry = model ? envModels.find(m => m.modelId === model) : undefined;

0 commit comments

Comments
 (0)