Search: async answer/results
This commit is contained in:
@@ -17,7 +17,7 @@ import {
|
||||
listChats,
|
||||
listSearches,
|
||||
runCompletion,
|
||||
runSearch,
|
||||
runSearchStream,
|
||||
type ChatDetail,
|
||||
type ChatSummary,
|
||||
type CompletionRequestMessage,
|
||||
@@ -119,6 +119,8 @@ export default function App() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const transcriptEndRef = useRef<HTMLDivElement>(null);
|
||||
const contextMenuRef = useRef<HTMLDivElement>(null);
|
||||
const searchRunAbortRef = useRef<AbortController | null>(null);
|
||||
const searchRunCounterRef = useRef(0);
|
||||
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
|
||||
|
||||
const sidebarItems = useMemo(() => buildSidebarItems(chats, searches), [chats, searches]);
|
||||
@@ -241,6 +243,13 @@ export default function App() {
|
||||
transcriptEndRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
|
||||
}, [draftKind, selectedChat?.messages.length, isSending, selectedItem?.kind]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
searchRunAbortRef.current?.abort();
|
||||
searchRunAbortRef.current = null;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const messages = selectedChat?.messages ?? [];
|
||||
|
||||
const selectedChatSummary = useMemo(() => {
|
||||
@@ -411,6 +420,11 @@ export default function App() {
|
||||
};
|
||||
|
||||
const handleSendSearch = async (query: string) => {
|
||||
const runId = ++searchRunCounterRef.current;
|
||||
searchRunAbortRef.current?.abort();
|
||||
const abortController = new AbortController();
|
||||
searchRunAbortRef.current = abortController;
|
||||
|
||||
let searchId = draftKind === "search" ? null : selectedItem?.kind === "search" ? selectedItem.id : null;
|
||||
|
||||
if (!searchId) {
|
||||
@@ -460,15 +474,76 @@ export default function App() {
|
||||
};
|
||||
});
|
||||
|
||||
const search = await runSearch(searchId, {
|
||||
query,
|
||||
title: query.slice(0, 80),
|
||||
type: "auto",
|
||||
numResults: 10,
|
||||
});
|
||||
try {
|
||||
await runSearchStream(
|
||||
searchId,
|
||||
{
|
||||
query,
|
||||
title: query.slice(0, 80),
|
||||
type: "auto",
|
||||
numResults: 10,
|
||||
},
|
||||
{
|
||||
onSearchResults: (payload) => {
|
||||
if (runId !== searchRunCounterRef.current) return;
|
||||
setSelectedSearch((current) => {
|
||||
if (!current || current.id !== searchId) return current;
|
||||
return {
|
||||
...current,
|
||||
requestId: payload.requestId ?? current.requestId,
|
||||
error: null,
|
||||
results: payload.results,
|
||||
};
|
||||
});
|
||||
},
|
||||
onSearchError: (payload) => {
|
||||
if (runId !== searchRunCounterRef.current) return;
|
||||
setSelectedSearch((current) => {
|
||||
if (!current || current.id !== searchId) return current;
|
||||
return { ...current, error: payload.error };
|
||||
});
|
||||
},
|
||||
onAnswer: (payload) => {
|
||||
if (runId !== searchRunCounterRef.current) return;
|
||||
setSelectedSearch((current) => {
|
||||
if (!current || current.id !== searchId) return current;
|
||||
return {
|
||||
...current,
|
||||
answerText: payload.answerText,
|
||||
answerRequestId: payload.answerRequestId,
|
||||
answerCitations: payload.answerCitations,
|
||||
answerError: null,
|
||||
};
|
||||
});
|
||||
},
|
||||
onAnswerError: (payload) => {
|
||||
if (runId !== searchRunCounterRef.current) return;
|
||||
setSelectedSearch((current) => {
|
||||
if (!current || current.id !== searchId) return current;
|
||||
return { ...current, answerError: payload.error };
|
||||
});
|
||||
},
|
||||
onDone: (payload) => {
|
||||
if (runId !== searchRunCounterRef.current) return;
|
||||
setSelectedSearch(payload.search);
|
||||
setSelectedChat(null);
|
||||
},
|
||||
onError: (payload) => {
|
||||
if (runId !== searchRunCounterRef.current) return;
|
||||
setError(payload.message);
|
||||
},
|
||||
},
|
||||
{ signal: abortController.signal }
|
||||
);
|
||||
} catch (err) {
|
||||
if (abortController.signal.aborted) return;
|
||||
throw err;
|
||||
} finally {
|
||||
if (runId === searchRunCounterRef.current) {
|
||||
searchRunAbortRef.current = null;
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedSearch(search);
|
||||
setSelectedChat(null);
|
||||
await refreshCollections({ kind: "search", id: searchId });
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user