Wire token-budget packing into the overview/rerank fallback path
This commit is contained in:
@@ -40,20 +40,36 @@ export function Composer({
|
||||
}
|
||||
}, [initialValue]);
|
||||
|
||||
// Fetch suggestions from API route when query length > 1
|
||||
// Fetch suggestions from API route when query length > 1.
|
||||
//
|
||||
// `term` is the LAST WORD being typed, not the whole textarea — a natural
|
||||
// sentence like "cho tôi thuốc parace" has no drug alias containing that
|
||||
// full phrase, so matching against it always returns empty (found live
|
||||
// 2026-08-10: this silently killed every suggestion once a user typed a
|
||||
// sentence instead of a bare drug name, which is the more common case).
|
||||
useEffect(() => {
|
||||
const term = value.trim();
|
||||
const words = value.trim().split(/\s+/);
|
||||
const term = words[words.length - 1] ?? "";
|
||||
if (term.length < 2) {
|
||||
setSuggestions([]);
|
||||
setShowSuggestions(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Race guard: a slower request for an earlier keystroke must not
|
||||
// overwrite a faster one for a later keystroke — found live 2026-08-10
|
||||
// typing fast could show a stale, unrelated suggestion list because the
|
||||
// fetch callback set state unconditionally regardless of whether `term`
|
||||
// (and therefore `value`) had already changed by the time it resolved.
|
||||
let cancelled = false;
|
||||
|
||||
const timer = setTimeout(async () => {
|
||||
try {
|
||||
const res = await fetch(`/api/suggest?q=${encodeURIComponent(term)}`);
|
||||
if (cancelled) return;
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
if (cancelled) return;
|
||||
if (data?.suggestions && Array.isArray(data.suggestions) && data.suggestions.length > 0) {
|
||||
setSuggestions(data.suggestions);
|
||||
setShowSuggestions(true);
|
||||
@@ -64,15 +80,21 @@ export function Composer({
|
||||
const filtered = SAMPLE_SUGGESTIONS.filter((s) =>
|
||||
s.toLowerCase().includes(term.toLowerCase())
|
||||
);
|
||||
if (cancelled) return;
|
||||
setSuggestions(filtered);
|
||||
setShowSuggestions(filtered.length > 0);
|
||||
} catch {
|
||||
setSuggestions([]);
|
||||
setShowSuggestions(false);
|
||||
if (!cancelled) {
|
||||
setSuggestions([]);
|
||||
setShowSuggestions(false);
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [value]);
|
||||
|
||||
// Close suggestions on outside click
|
||||
|
||||
Reference in New Issue
Block a user