Search answers
This commit is contained in:
@@ -36,7 +36,7 @@ Default dev URL: `http://localhost:5173`
|
||||
- Left panel: mixed list of chat conversations and Exa searches.
|
||||
- Right panel:
|
||||
- Chat mode: transcript + provider/model controls.
|
||||
- Search mode: Google-style Exa results view.
|
||||
- Search mode: top AI answer block + Google-style Exa results view.
|
||||
- Composer adapts to the active item:
|
||||
- Chat sends `POST /v1/chat-completions`.
|
||||
- Search sends `POST /v1/searches/:searchId/run`.
|
||||
|
||||
@@ -431,6 +431,10 @@ export default function App() {
|
||||
requestId: null,
|
||||
latencyMs: null,
|
||||
error: null,
|
||||
answerText: null,
|
||||
answerRequestId: null,
|
||||
answerCitations: null,
|
||||
answerError: null,
|
||||
results: [],
|
||||
};
|
||||
}
|
||||
@@ -440,6 +444,10 @@ export default function App() {
|
||||
query,
|
||||
error: null,
|
||||
latencyMs: null,
|
||||
answerText: null,
|
||||
answerRequestId: null,
|
||||
answerCitations: null,
|
||||
answerError: null,
|
||||
results: [],
|
||||
};
|
||||
});
|
||||
@@ -718,6 +726,38 @@ export default function App() {
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{(isSearchRunning || !!selectedSearch?.answerText || !!selectedSearch?.answerError) && (
|
||||
<section className="mb-6 rounded-xl border border-slate-600/60 bg-[#121a2e] p-4">
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-sky-300/90">Answer</p>
|
||||
{isSearchRunning && !selectedSearch?.answerText ? (
|
||||
<p className="mt-2 text-sm text-muted-foreground">Generating answer...</p>
|
||||
) : null}
|
||||
{selectedSearch?.answerText ? (
|
||||
<p className="mt-2 whitespace-pre-wrap text-sm leading-6 text-slate-100">{selectedSearch.answerText}</p>
|
||||
) : null}
|
||||
{selectedSearch?.answerError ? <p className="mt-2 text-sm text-red-500">{selectedSearch.answerError}</p> : null}
|
||||
{!!selectedSearch?.answerCitations?.length && (
|
||||
<div className="mt-3 flex flex-wrap gap-2">
|
||||
{selectedSearch.answerCitations.slice(0, 6).map((citation, index) => {
|
||||
const href = citation.url || citation.id || "";
|
||||
if (!href) return null;
|
||||
return (
|
||||
<a
|
||||
key={`${href}-${index}`}
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="rounded-md border border-slate-500/60 px-2 py-1 text-xs text-sky-200 hover:bg-slate-700/40"
|
||||
>
|
||||
{citation.title?.trim() || formatHost(href)}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
{(isLoadingSelection || isSearchRunning) && !selectedSearch?.results.length ? (
|
||||
<p className="text-sm text-muted-foreground">{isSearchRunning ? "Searching Exa..." : "Loading search..."}</p>
|
||||
) : null}
|
||||
|
||||
@@ -54,6 +54,17 @@ export type SearchDetail = {
|
||||
requestId: string | null;
|
||||
latencyMs: number | null;
|
||||
error: string | null;
|
||||
answerText: string | null;
|
||||
answerRequestId: string | null;
|
||||
answerCitations: Array<{
|
||||
id?: string;
|
||||
url?: string;
|
||||
title?: string | null;
|
||||
publishedDate?: string | null;
|
||||
author?: string | null;
|
||||
text?: string | null;
|
||||
}> | null;
|
||||
answerError: string | null;
|
||||
results: SearchResultItem[];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user