fix: dynamic col names + no-duplicate assistant/result event handling

This commit is contained in:
Zac Gaetano 2026-04-05 12:09:39 -04:00
parent 048072b4f3
commit 1de99654fc

View file

@ -41,6 +41,7 @@ const App = () => {
const [wsConnected, setWsConnected] = useState(false); const [wsConnected, setWsConnected] = useState(false);
const [wsError, setWsError] = useState(null); const [wsError, setWsError] = useState(null);
const pendingAssistantRef = useRef(''); const pendingAssistantRef = useRef('');
const messageFinalizedRef = useRef(false); // true when assistant event already finalized the bubble
const reconnectTimerRef = useRef(null); const reconnectTimerRef = useRef(null);
// Tasks state // Tasks state
@ -201,25 +202,32 @@ const App = () => {
} }
if (text) { if (text) {
pendingAssistantRef.current = text; pendingAssistantRef.current = text;
messageFinalizedRef.current = true; // already final, don't re-render on result
upsertStreamingMessage(text, false); upsertStreamingMessage(text, false);
} }
} else {
// Deltas already built the text mark as final so result doesn't duplicate
messageFinalizedRef.current = true;
} }
// If deltas already built the text, skip no duplicate
} }
if (type === 'result') { if (type === 'result') {
const sub = data.subtype; const sub = data.subtype;
if (sub === 'success' || sub === 'error_max_turns') { if (sub === 'success' || sub === 'error_max_turns') {
if (pendingAssistantRef.current) { // Only call upsertStreamingMessage if the message is still streaming (from deltas)
// If messageFinalizedRef is true, the bubble is already rendered as final
if (pendingAssistantRef.current && !messageFinalizedRef.current) {
upsertStreamingMessage(pendingAssistantRef.current, false); upsertStreamingMessage(pendingAssistantRef.current, false);
pendingAssistantRef.current = '';
} }
pendingAssistantRef.current = '';
messageFinalizedRef.current = false;
if (data.session_id) setClaudeSessionId(data.session_id); if (data.session_id) setClaudeSessionId(data.session_id);
setChatWaiting(false); setChatWaiting(false);
fetchChatSessions(); fetchChatSessions();
} }
if (sub === 'error' || sub === 'error_during_execution') { if (sub === 'error' || sub === 'error_during_execution') {
pendingAssistantRef.current = ''; pendingAssistantRef.current = '';
messageFinalizedRef.current = false;
setChatWaiting(false); setChatWaiting(false);
appendErrorMsg(data.error || 'Claude returned an error'); appendErrorMsg(data.error || 'Claude returned an error');
} }
@ -271,6 +279,7 @@ const App = () => {
setChatInput(''); setChatInput('');
setChatWaiting(true); setChatWaiting(true);
pendingAssistantRef.current = ''; pendingAssistantRef.current = '';
messageFinalizedRef.current = false;
if (!wsRef.current || wsRef.current.readyState !== 1) { if (!wsRef.current || wsRef.current.readyState !== 1) {
appendErrorMsg('Not connected — reconnecting...'); appendErrorMsg('Not connected — reconnecting...');