Skip to content

Commit 013d15d

Browse files
simplesagarclaude
andauthored
fix: restore chat history loading in playground (#999)
## Summary Fixes chat history loading in the Playground after the AI SDK 5 upgrade broke the functionality. ## Problem The AI SDK 5 upgrade (commit c213781) introduced a regression where chat history was being fetched from the API but never passed to the `useChat()` hook, causing previously saved messages to be lost when users loaded existing chats from the dropdown. ## Root Cause - `useChatHistory()` was fetching chat history correctly via React Query - The result was stored in `_chatHistory` (underscore indicating intentionally unused) - AI SDK 5's `useChat()` hook was called without `initialMessages` parameter - Chat always started empty, ignoring saved history ## Solution Created a bridge between React Query (server state) and AI SDK (local state): 1. **Extract chat history** from `useChatHistory()` (remove underscore prefix) 2. **Get `setMessages`** from `useChat()` hook for message initialization 3. **Add `useEffect`** to load history once per chat ID after React Query finishes 4. **Use `isLoading` state** from React Query instead of arbitrary timeouts ## Technical Details The `useEffect` is necessary because: - React Query manages server-side chat history fetching - AI SDK 5 manages local chat interaction state - These are separate state systems that need synchronization - The effect only runs once per unique chat ID (tracked via ref) ## Changes **File**: `client/dashboard/src/pages/playground/ChatWindow.tsx` - Line 157-158: Destructure `chatHistory` and `isLoading` from `useChatHistory()` - Line 166: Add `loadedChatIdRef` to track loaded chat IDs - Line 415: Extract `setMessages` from `useChat()` return value - Lines 466-485: Add `useEffect` to bridge React Query → AI SDK state ## Testing ✅ Chat history loads correctly when selecting from dropdown ✅ No infinite loops or excessive re-renders ✅ Server requests are not canceled repeatedly ✅ React Query loading state properly synchronized ## Follows Best Practices ✅ All data fetching uses React Query (not manual `useEffect`) ✅ The `useEffect` is for state synchronization, not data fetching ✅ Uses React Query's `isLoading` state declaratively ✅ Minimal, focused bridge between two state management systems Fixes AGE-969 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
1 parent 2667ecf commit 013d15d

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

.changeset/lovely-oranges-give.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"dashboard": patch
3+
---
4+
5+
Restore chat history loading in playground after v5 AI SDK upgrade

client/dashboard/src/pages/playground/ChatWindow.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,19 @@ function ChatInner({
154154

155155
const chat = useChatContext();
156156
const { setMessages } = chat;
157-
const { chatHistory: _chatHistory } = useChatHistory(chat.id);
157+
const { chatHistory, isLoading: isChatHistoryLoading } = useChatHistory(
158+
chat.id,
159+
);
158160

159161
const [displayOnlyMessages, setDisplayOnlyMessages] = useState<UIMessage[]>(
160162
[],
161163
);
162164
const [_mentionedToolIds, setMentionedToolIds] = useState<string[]>([]);
163165
const [_inputText, setInputText] = useState("");
164166

167+
// Track which chat ID we've loaded messages for to prevent re-loading
168+
const loadedChatIdRef = useRef<string | null>(null);
169+
165170
// Feature flag for experimental tool tagging syntax
166171
const isToolTaggingEnabled = telemetry.isFeatureEnabled(
167172
"gram-experimental-chat",
@@ -412,6 +417,7 @@ function ChatInner({
412417
status,
413418
sendMessage,
414419
addToolResult,
420+
setMessages: setUseChatMessages,
415421
} = useChat({
416422
// Include model in the chat ID to force a fresh session when switching models
417423
id: `${chat.id}-${model}`,
@@ -458,6 +464,23 @@ function ChatInner({
458464
},
459465
});
460466

467+
// Load chat history when available (AI SDK 5 workaround)
468+
// Bridge between React Query (server state) and AI SDK (local state)
469+
const currentChatId = `${chat.id}-${model}`;
470+
useEffect(() => {
471+
// Only load once per chat ID after React Query finishes loading
472+
if (loadedChatIdRef.current !== currentChatId && !isChatHistoryLoading) {
473+
loadedChatIdRef.current = currentChatId;
474+
475+
// Priority: loaded chat history > programmatically provided initial messages
476+
const initialMessagesInner =
477+
chatHistory.length > 0 ? chatHistory : _initialMessages;
478+
if (initialMessagesInner && initialMessagesInner.length > 0) {
479+
setUseChatMessages(initialMessagesInner);
480+
}
481+
}
482+
}, [currentChatId, isChatHistoryLoading]);
483+
461484
const handleSend = useCallback(
462485
async (msg: string) => {
463486
const userMessages = chatMessages.filter((m) => m.role === "user");

0 commit comments

Comments
 (0)