diff --git a/src/servers/api/pi/list-models.ts b/src/servers/api/pi/list-models.ts index b96fe45f..c5681c24 100644 --- a/src/servers/api/pi/list-models.ts +++ b/src/servers/api/pi/list-models.ts @@ -2,15 +2,11 @@ import type { ModelInfo } from './types'; import { PI_CONFIG_DIR } from '../../data-path'; import { logger } from './logger'; -const CLAUDE_CODE_MODEL: ModelInfo = { - id: 'claude-code', - name: 'claude-code', - provider: 'claude-code', - contextWindow: 200000, - maxTokens: 16000, - reasoning: true, - images: true, -}; +const CLAUDE_CODE_MODELS: ModelInfo[] = [ + { id: 'claude-code/opus', name: 'opus', provider: 'claude-code', contextWindow: 200000, maxTokens: 16000, reasoning: true, images: true }, + { id: 'claude-code/sonnet', name: 'sonnet', provider: 'claude-code', contextWindow: 200000, maxTokens: 16000, reasoning: true, images: true }, + { id: 'claude-code/haiku', name: 'haiku', provider: 'claude-code', contextWindow: 200000, maxTokens: 8192, reasoning: false, images: true }, +]; const CACHE_TTL_MS = 60_000; @@ -36,7 +32,7 @@ const parseSize = (s?: string): number => { export async function listPiModels(): Promise { if (cachedModels && Date.now() - cacheTimestamp < CACHE_TTL_MS) { - return [...cachedModels, CLAUDE_CODE_MODEL]; + return [...cachedModels, ...CLAUDE_CODE_MODELS]; } try { @@ -59,11 +55,11 @@ export async function listPiModels(): Promise { if (proc.exitCode !== 0) { const stderrText = proc.stderr.toString(); logger.error('pi --list-models failed', { exitCode: proc.exitCode, stderr: stderrText.trim(), piBin }); - return [CLAUDE_CODE_MODEL]; + return [...CLAUDE_CODE_MODELS]; } const lines = output.trim().split('\n'); - if (lines.length < 2) return [CLAUDE_CODE_MODEL]; + if (lines.length < 2) return [...CLAUDE_CODE_MODELS]; // Parse fixed-width table: provider, model, context, max-out, thinking, images const header = lines[0]!; @@ -114,9 +110,9 @@ export async function listPiModels(): Promise { logger.info('pi --list-models returned', { count: models.length }); cachedModels = models; cacheTimestamp = Date.now(); - return [...models, CLAUDE_CODE_MODEL]; + return [...models, ...CLAUDE_CODE_MODELS]; } catch (err) { logger.error('Failed to run pi --list-models', { error: String(err) }); - return [CLAUDE_CODE_MODEL]; + return [...CLAUDE_CODE_MODELS]; } } diff --git a/src/servers/api/pi/websocket.ts b/src/servers/api/pi/websocket.ts index b750dd18..60e6681a 100644 --- a/src/servers/api/pi/websocket.ts +++ b/src/servers/api/pi/websocket.ts @@ -275,7 +275,7 @@ async function handleChat( userDefault, }); - if (model === 'claude-code') { + if (model.startsWith('claude-code')) { return handleClaudeCodeChat(ws, sessionId, model, msg); } @@ -424,6 +424,7 @@ async function handleClaudeCodeChat( prompt: msg.prompt, sessionKey: sessionId, cwd, + model, onEvent, }); @@ -553,7 +554,7 @@ async function handleStop(ws: ServerWebSocket): Promise { if (session?.piProcess) { try { - if (session.model === 'claude-code') { + if (session.model.startsWith('claude-code')) { // Claude Code: kill the process directly session.piProcess.kill(); logger.info('Killed Claude Code process', { sessionId }); diff --git a/src/servers/channels/send-and-await.ts b/src/servers/channels/send-and-await.ts index c875ae1f..8005ef03 100644 --- a/src/servers/channels/send-and-await.ts +++ b/src/servers/channels/send-and-await.ts @@ -104,13 +104,14 @@ export async function sendAndAwait(params: SendAndAwaitParams): Promise void; }; @@ -293,6 +298,9 @@ export async function sendClaudeCodeStreaming(params: ClaudeCodeStreamingParams) '--include-partial-messages', ]; + const subModel = params.model?.split('/')[1]; + if (subModel) claudeArgs.push('--model', subModel); + const existingSession = claudeCodeSessions.get(sessionKey); if (existingSession) { claudeArgs.push('--resume', existingSession);