fix: 切换聊天后模型选择不保持

两个问题:
1. 用户选择模型只写 localStorage,不写 DB。切换聊天回来后从 DB
   读到空值,模型回退到默认值
2. ChatView 的 useState 只用初始值,后续 modelName prop 异步更新
   不会同步到 currentModel state

修复:
- handleProviderModelChange 选择模型时立即 PATCH 到 DB
- PATCH /api/chat/sessions/:id 新增 model + provider_id 字段支持
- ChatView 添加 useEffect 同步 modelName/providerId prop 变化

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-03-01 22:55:36 +08:00
1 parent 7e45448860
commit d9c4ad2c95
2 files changed
+22 -2

No files matched your search

+7 -1
View File
@@ -1,5 +1,5 @@
import { NextRequest } from 'next/server';
import { deleteSession, getSession, updateSessionWorkingDirectory, updateSessionTitle, updateSessionMode, clearSessionMessages } from '@/lib/db';
import { deleteSession, getSession, updateSessionWorkingDirectory, updateSessionTitle, updateSessionMode, updateSessionModel, updateSessionProviderId, clearSessionMessages } from '@/lib/db';
export async function GET(
_request: NextRequest,
@@ -40,6 +40,12 @@ export async function PATCH(
if (body.mode) {
updateSessionMode(id, body.mode);
}
if (body.model !== undefined) {
updateSessionModel(id, body.model);
}
if (body.provider_id !== undefined) {
updateSessionProviderId(id, body.provider_id);
}
if (body.clear_messages) {
clearSessionMessages(id);
}
+15 -1
View File
@@ -35,6 +35,14 @@ export function ChatView({ sessionId, initialMessages = [], initialHasMore = fal
const [currentModel, setCurrentModel] = useState(modelName || (typeof window !== 'undefined' ? localStorage.getItem('codepilot:last-model') : null) || 'sonnet');
const [currentProviderId, setCurrentProviderId] = useState(providerId || (typeof window !== 'undefined' ? localStorage.getItem('codepilot:last-provider-id') : null) || '');
// Sync model/provider when session data loads (props update after async fetch)
useEffect(() => {
if (modelName) setCurrentModel(modelName);
}, [modelName]);
useEffect(() => {
if (providerId) setCurrentProviderId(providerId);
}, [providerId]);
// Stream snapshot from the manager — drives all streaming UI
const [streamSnapshot, setStreamSnapshot] = useState<SessionStreamSnapshot | null>(
() => getSnapshot(sessionId)
@@ -79,7 +87,13 @@ export function ChatView({ sessionId, initialMessages = [], initialHasMore = fal
const handleProviderModelChange = useCallback((newProviderId: string, model: string) => {
setCurrentProviderId(newProviderId);
setCurrentModel(model);
}, []);
// Persist immediately so switching chats preserves the selection
fetch(`/api/chat/sessions/${sessionId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model, provider_id: newProviderId }),
}).catch(() => {});
}, [sessionId]);
// Subscribe to stream-session-manager for this session.
// On unmount we only unsubscribe — we do NOT abort the stream.