diff --git a/frontend/src/lib/constants.ts b/frontend/src/lib/constants.ts
index 501aa92c..dbbf01e7 100644
--- a/frontend/src/lib/constants.ts
+++ b/frontend/src/lib/constants.ts
@@ -9,11 +9,11 @@ export const WS_RECONNECT_POLL_MS = 5_000;
export const SCROLL_NEAR_BOTTOM_PX = 150;
export const SCROLL_RESTORE_DELAY_MS = 100;
export const LAST_SESSION_KEY = 'mitzo-last-session';
-// Default model for new sessions. Opus 4.6 is used rather than 4.7 because
-// 4.7 is not yet available on every supported provider (e.g. Vertex AI at
-// time of writing) — picking a widely-available model keeps the out-of-box
-// experience functional. Users with access can still select Opus 4.7 from
-// the dropdown; the selection persists per-browser.
+// Default model for new sessions. Opus 4.6 is used rather than 4.8 because
+// 4.8 is not yet available on every supported provider — picking a widely-
+// available model keeps the out-of-box experience functional. Users with
+// access can still select Opus 4.8 from the dropdown; the selection persists
+// per-browser.
export const DEFAULT_MODEL = 'claude-opus-4-6';
// --- Tool grouping ---
diff --git a/frontend/src/pages/ChatView.tsx b/frontend/src/pages/ChatView.tsx
index 7907e004..6dfe3d15 100644
--- a/frontend/src/pages/ChatView.tsx
+++ b/frontend/src/pages/ChatView.tsx
@@ -223,10 +223,10 @@ export function ChatView() {
onChange={(e) => setModel(e.target.value)}
disabled={messages.running}
>
- Opus 4.7
- Opus 4.7 Max
+ Opus 4.8
+ Opus 4.8 Max
Opus 4.6
- Opus 4.5
+ Sonnet 5
Sonnet 4.6
Sonnet 4.5
Haiku 4.5
diff --git a/frontend/src/pages/DesktopChatView.tsx b/frontend/src/pages/DesktopChatView.tsx
index 1e85533b..cc0e65ce 100644
--- a/frontend/src/pages/DesktopChatView.tsx
+++ b/frontend/src/pages/DesktopChatView.tsx
@@ -198,10 +198,12 @@ export function DesktopChatView() {
onChange={(e) => setModel(e.target.value)}
disabled={messages.running}
>
- Opus 4.7
- Opus 4.7 Max
+ Opus 4.8
+ Opus 4.8 Max
Opus 4.6
+ Sonnet 5
Sonnet 4.6
+ Sonnet 4.5
Haiku 4.5
diff --git a/packages/client/__tests__/store.test.ts b/packages/client/__tests__/store.test.ts
index 2fba7283..fb7e8c5e 100644
--- a/packages/client/__tests__/store.test.ts
+++ b/packages/client/__tests__/store.test.ts
@@ -792,11 +792,11 @@ describe('interruptMessage', () => {
store.getState().sendMessage('first');
lastWs.simulateMessage({ type: 'session_id', sessionId: 'sess-int3' });
- store.getState().interruptMessage('urgent', { model: 'claude-opus-4-7' });
+ store.getState().interruptMessage('urgent', { model: 'claude-opus-4-8' });
const interrupts = lastWs.parsedSent().filter((m) => m.type === 'interrupt');
expect(interrupts).toHaveLength(1);
- expect(interrupts[0].model).toBe('claude-opus-4-7');
+ expect(interrupts[0].model).toBe('claude-opus-4-8');
});
it('does not include model field when both opts and config are null', () => {
diff --git a/server/__tests__/model-spec.test.ts b/server/__tests__/model-spec.test.ts
index 095ec4e5..76816c25 100644
--- a/server/__tests__/model-spec.test.ts
+++ b/server/__tests__/model-spec.test.ts
@@ -7,26 +7,26 @@ describe('parseModelSpec', () => {
});
it('parses a plain model ID', () => {
- expect(parseModelSpec('claude-opus-4-7')).toEqual({
- model: 'claude-opus-4-7',
+ expect(parseModelSpec('claude-opus-4-8')).toEqual({
+ model: 'claude-opus-4-8',
effort: undefined,
});
});
it('splits model and effort on colon', () => {
- expect(parseModelSpec('claude-opus-4-7:max')).toEqual({
- model: 'claude-opus-4-7',
+ expect(parseModelSpec('claude-opus-4-8:max')).toEqual({
+ model: 'claude-opus-4-8',
effort: 'max',
});
});
it('handles trailing colon as empty effort', () => {
- expect(parseModelSpec('claude-opus-4-7:')).toEqual({ model: 'claude-opus-4-7', effort: '' });
+ expect(parseModelSpec('claude-opus-4-8:')).toEqual({ model: 'claude-opus-4-8', effort: '' });
});
it('handles multiple colons — only splits on first', () => {
- expect(parseModelSpec('claude-opus-4-7:max:extra')).toEqual({
- model: 'claude-opus-4-7',
+ expect(parseModelSpec('claude-opus-4-8:max:extra')).toEqual({
+ model: 'claude-opus-4-8',
effort: 'max:extra',
});
});
@@ -38,7 +38,7 @@ describe('resolveThinking', () => {
});
it('returns adaptive for plain opus model', () => {
- expect(resolveThinking('claude-opus-4-7')).toEqual({ type: 'adaptive' });
+ expect(resolveThinking('claude-opus-4-8')).toEqual({ type: 'adaptive' });
});
it('returns adaptive for opus 4-6', () => {
@@ -46,19 +46,26 @@ describe('resolveThinking', () => {
});
it('returns 128k budget for opus :max', () => {
- expect(resolveThinking('claude-opus-4-7:max')).toEqual({
+ expect(resolveThinking('claude-opus-4-8:max')).toEqual({
type: 'enabled',
budgetTokens: 128_000,
});
});
- it('returns 10k budget for sonnet', () => {
+ it('returns 10k budget for sonnet 4-6', () => {
expect(resolveThinking('claude-sonnet-4-6')).toEqual({
type: 'enabled',
budgetTokens: 10_000,
});
});
+ it('returns 10k budget for sonnet 5', () => {
+ expect(resolveThinking('claude-sonnet-5')).toEqual({
+ type: 'enabled',
+ budgetTokens: 10_000,
+ });
+ });
+
it('returns undefined for haiku', () => {
expect(resolveThinking('claude-haiku-4-5')).toBeUndefined();
});
diff --git a/server/__tests__/ws-handler-v2.test.ts b/server/__tests__/ws-handler-v2.test.ts
index bad44d60..eb4f2031 100644
--- a/server/__tests__/ws-handler-v2.test.ts
+++ b/server/__tests__/ws-handler-v2.test.ts
@@ -2364,7 +2364,7 @@ describe('handleInterruptV2 forwarding', () => {
sessionId: 'sess-resume',
prompt: 'urgent',
clientMsgId: 'i-resume',
- model: 'claude-opus-4-7',
+ model: 'claude-opus-4-8',
},
ctx,
);
@@ -2373,7 +2373,7 @@ describe('handleInterruptV2 forwarding', () => {
transport,
'c2:sess-resume',
'urgent',
- expect.objectContaining({ resume: 'sess-resume', model: 'claude-opus-4-7' }),
+ expect.objectContaining({ resume: 'sess-resume', model: 'claude-opus-4-8' }),
);
});
@@ -2435,7 +2435,7 @@ describe('handleInterruptV2 forwarding', () => {
sessionId: 'sess-precedence',
prompt: 'override',
clientMsgId: 'i-precedence',
- model: 'claude-opus-4-7',
+ model: 'claude-opus-4-8',
},
ctx,
);
@@ -2444,7 +2444,7 @@ describe('handleInterruptV2 forwarding', () => {
transport,
'c4:sess-precedence',
'override',
- expect.objectContaining({ resume: 'sess-precedence', model: 'claude-opus-4-7' }),
+ expect.objectContaining({ resume: 'sess-precedence', model: 'claude-opus-4-8' }),
);
});
diff --git a/server/chat.ts b/server/chat.ts
index 6442db70..d915362d 100644
--- a/server/chat.ts
+++ b/server/chat.ts
@@ -366,16 +366,16 @@ export function getRepoConfig() {
}
export const AVAILABLE_MODELS = [
- { id: 'claude-opus-4-7', label: 'Opus 4.7', desc: 'Adaptive thinking' },
- { id: 'claude-opus-4-7:max', label: 'Opus 4.7 Max', desc: 'Max thinking (128k)' },
+ { id: 'claude-opus-4-8', label: 'Opus 4.8', desc: 'Latest Opus' },
+ { id: 'claude-opus-4-8:max', label: 'Opus 4.8 Max', desc: 'Max thinking (128k)' },
{ id: 'claude-opus-4-6', label: 'Opus 4.6', desc: 'Previous Opus' },
- { id: 'claude-opus-4-5', label: 'Opus 4.5', desc: 'Legacy Opus' },
+ { id: 'claude-sonnet-5', label: 'Sonnet 5', desc: 'Latest Sonnet' },
{ id: 'claude-sonnet-4-6', label: 'Sonnet 4.6', desc: 'Balanced' },
{ id: 'claude-sonnet-4-5', label: 'Sonnet 4.5', desc: 'Previous Sonnet' },
{ id: 'claude-haiku-4-5', label: 'Haiku 4.5', desc: 'Fastest' },
];
-/** Split "claude-opus-4-7:max" → { model: "claude-opus-4-7", effort: "max" } */
+/** Split "claude-opus-4-8:max" → { model: "claude-opus-4-8", effort: "max" } */
export function parseModelSpec(spec?: string): { model: string; effort: string | undefined } {
if (!spec) return { model: '', effort: undefined };
const idx = spec.indexOf(':');