Enhance chat UI and compatible anthropic thinking messages (#1018)

This commit is contained in:
JeffJiang
2026-03-08 20:19:31 +08:00
committed by GitHub
parent 3512279ce3
commit cf9af1fe75
9 changed files with 213 additions and 129 deletions
+58 -17
View File
@@ -40,39 +40,83 @@ export function useThreadStream({
onToolEnd,
}: ThreadStreamOptions) {
const { t } = useI18n();
const [_threadId, setThreadId] = useState<string | null>(threadId ?? null);
const threadIdRef = useRef<string | null>(threadId ?? null);
const startedRef = useRef(false);
const listeners = useRef({
onStart,
onFinish,
onToolEnd,
});
// Keep listeners ref updated with latest callbacks
useEffect(() => {
if (_threadId && _threadId !== threadId) {
setThreadId(threadId ?? null);
listeners.current = { onStart, onFinish, onToolEnd };
}, [onStart, onFinish, onToolEnd]);
useEffect(() => {
if (threadIdRef.current && threadIdRef.current !== threadId) {
threadIdRef.current = threadId ?? null;
startedRef.current = false; // Reset for new thread
}
}, [threadId, _threadId]);
}, [threadId]);
const _handleStart = useCallback((id: string) => {
if (!startedRef.current) {
listeners.current.onStart?.(id);
startedRef.current = true;
}
}, []);
const queryClient = useQueryClient();
const updateSubtask = useUpdateSubtask();
const thread = useStream<AgentThreadState>({
client: getAPIClient(isMock),
assistantId: "lead_agent",
threadId: _threadId,
threadId: threadIdRef.current,
reconnectOnMount: true,
fetchStateHistory: { limit: 1 },
onCreated(meta) {
setThreadId(meta.thread_id);
if (!startedRef.current) {
onStart?.(meta.thread_id);
startedRef.current = true;
}
threadIdRef.current = meta.thread_id;
_handleStart(meta.thread_id);
},
onLangChainEvent(event) {
if (event.event === "on_tool_end") {
onToolEnd?.({
listeners.current.onToolEnd?.({
name: event.name,
data: event.data,
});
}
},
onUpdateEvent(data) {
const updates: Array<Partial<AgentThreadState> | null> = Object.values(
data || {},
);
for (const update of updates) {
if (update && "title" in update && update.title) {
void queryClient.setQueriesData(
{
queryKey: ["threads", "search"],
exact: false,
},
(oldData: Array<AgentThread> | undefined) => {
return oldData?.map((t) => {
if (t.thread_id === threadIdRef.current) {
return {
...t,
values: {
...t.values,
title: update.title,
},
};
}
return t;
});
},
);
}
}
},
onCustomEvent(event: unknown) {
if (
typeof event === "object" &&
@@ -89,7 +133,7 @@ export function useThreadStream({
}
},
onFinish(state) {
onFinish?.(state.values);
listeners.current.onFinish?.(state.values);
void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
},
});
@@ -150,10 +194,7 @@ export function useThreadStream({
}
setOptimisticMessages(newOptimistic);
if (!startedRef.current) {
onStart?.(threadId);
startedRef.current = true;
}
_handleStart(threadId);
let uploadedFileInfo: UploadedFileInfo[] = [];
@@ -289,7 +330,7 @@ export function useThreadStream({
throw error;
}
},
[thread, t.uploads.uploadingFiles, onStart, context, queryClient],
[thread, _handleStart, t.uploads.uploadingFiles, context, queryClient],
);
// Merge thread with optimistic messages for display