fix: read env vars directly from localStorage to avoid React closure issue
The previous approach using useEnvVars() hook had a closure problem: - envVars started as [] on first render - buildEnvObject captured this empty array - Even with function body, the transport memoized the old buildEnvObject Solution: Read directly from localStorage inside the body function - Bypasses React state entirely - Gets fresh values on each request - No closure issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
c6b4456baf
commit
d0110f990d
1 changed files with 32 additions and 19 deletions
|
|
@ -4,38 +4,51 @@ import { useChat as useAISDKChat } from '@ai-sdk/react';
|
|||
import { DefaultChatTransport } from 'ai';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useState } from 'react';
|
||||
import { useEnvVars } from '~/components/sidebar/SettingsSidebar';
|
||||
|
||||
/**
|
||||
* Custom chat hook that wraps the official @ai-sdk/react useChat
|
||||
* Handles SSE streaming with tool calls and UI message protocol
|
||||
* Includes conversation ID tracking for dynamic tool loading
|
||||
*/
|
||||
const ENV_STORAGE_KEY = 'tpmjs-playground-env-vars';
|
||||
|
||||
export function useChat(): ReturnType<typeof useAISDKChat> & { conversationId: string } {
|
||||
// Generate stable conversation ID for session
|
||||
const [conversationId] = useState(() => nanoid());
|
||||
|
||||
// Get environment variables from settings sidebar
|
||||
const envVars = useEnvVars();
|
||||
|
||||
// Convert env vars to object format (called fresh on each request)
|
||||
const buildEnvObject = () =>
|
||||
envVars.reduce(
|
||||
(acc, { key, value }) => {
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
const chat = useAISDKChat({
|
||||
transport: new DefaultChatTransport({
|
||||
api: '/api/chat',
|
||||
// Use function body so it's evaluated on each request (not just once on mount)
|
||||
body: () => ({
|
||||
conversationId, // Pass conversation ID to API
|
||||
env: buildEnvObject(), // Pass LATEST environment variables to API
|
||||
}),
|
||||
// Use function body that reads FRESH from localStorage on each request
|
||||
// This avoids React closure issues where envVars would be stale
|
||||
body: () => {
|
||||
// Read env vars directly from localStorage (not from React state)
|
||||
let envVars: Array<{ key: string; value: string }> = [];
|
||||
try {
|
||||
const stored = localStorage.getItem(ENV_STORAGE_KEY);
|
||||
if (stored) {
|
||||
envVars = JSON.parse(stored);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to read env vars from localStorage:', error);
|
||||
}
|
||||
|
||||
// Convert to object format
|
||||
const env = envVars.reduce(
|
||||
(acc, { key, value }) => {
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
console.log('🔑 [useChat] Reading env vars from localStorage:', Object.keys(env));
|
||||
|
||||
return {
|
||||
conversationId,
|
||||
env,
|
||||
};
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue