fix: single gpt-5.4 model selector + SSE buffer edge case fix
- Replace Flash/Pro dual model buttons with single "gpt-5.4" label - Backend still receives "flash" as model param (matches schema validation) - Remove unused selectedModel/onSelectedModelChange props from GeminiInput - Fix SSE stream parsing: process remaining buffer data when stream ends without trailing newline (potential cause of "no return" issue) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
71efdff800
commit
c2e14c48a0
@@ -72,7 +72,7 @@ export function GeminiChat() {
|
||||
const [extensions, setExtensions] = useState<Extension[]>(INITIAL_EXTENSIONS);
|
||||
const [ticketSummary, setTicketSummary] = useState<TicketSummaryData | null>(null);
|
||||
const [activeTools, setActiveTools] = useState<Set<string>>(new Set());
|
||||
const [selectedModel, setSelectedModel] = useState<"flash" | "pro">("pro");
|
||||
const [selectedModel, setSelectedModel] = useState<"flash" | "pro">("flash");
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const abortRef = useRef<AbortController | null>(null);
|
||||
|
||||
@@ -381,8 +381,6 @@ export function GeminiChat() {
|
||||
isLoading={isLoading}
|
||||
activeTools={activeTools}
|
||||
onActiveToolsChange={setActiveTools}
|
||||
selectedModel={selectedModel}
|
||||
onSelectedModelChange={setSelectedModel}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -27,8 +27,6 @@ interface GeminiInputProps {
|
||||
isLoading?: boolean;
|
||||
activeTools: Set<string>;
|
||||
onActiveToolsChange: (tools: Set<string>) => void;
|
||||
selectedModel: "flash" | "pro";
|
||||
onSelectedModelChange: (model: "flash" | "pro") => void;
|
||||
}
|
||||
|
||||
const TOOLS: Tool[] = [
|
||||
@@ -45,8 +43,6 @@ export function GeminiInput({
|
||||
isLoading,
|
||||
activeTools,
|
||||
onActiveToolsChange,
|
||||
selectedModel,
|
||||
onSelectedModelChange,
|
||||
}: GeminiInputProps) {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
@@ -204,32 +200,13 @@ export function GeminiInput({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom row: Model selector */}
|
||||
{/* Bottom row: Model indicator */}
|
||||
<div className="flex items-center justify-end px-4 pb-3 pt-0 gap-2">
|
||||
<button
|
||||
onClick={() => onSelectedModelChange("flash")}
|
||||
className={cn(
|
||||
"px-3 py-1.5 rounded-full text-xs font-medium transition-all duration-150 cursor-pointer",
|
||||
selectedModel === "flash"
|
||||
? "bg-[var(--gem-blue)] text-white"
|
||||
: "bg-[var(--gem-surface-2)] text-[var(--gem-text-muted)] hover:bg-[var(--gem-surface-3)] hover:text-[var(--gem-text)]"
|
||||
)}
|
||||
aria-pressed={selectedModel === "flash"}
|
||||
<span
|
||||
className="px-3 py-1.5 rounded-full text-xs font-medium bg-[var(--gem-blue)] text-white"
|
||||
>
|
||||
Flash
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onSelectedModelChange("pro")}
|
||||
className={cn(
|
||||
"px-3 py-1.5 rounded-full text-xs font-medium transition-all duration-150 cursor-pointer",
|
||||
selectedModel === "pro"
|
||||
? "bg-[var(--gem-purple)] text-white"
|
||||
: "bg-[var(--gem-surface-2)] text-[var(--gem-text-muted)] hover:bg-[var(--gem-surface-3)] hover:text-[var(--gem-text)]"
|
||||
)}
|
||||
aria-pressed={selectedModel === "pro"}
|
||||
>
|
||||
Pro
|
||||
</button>
|
||||
gpt-5.4
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Tools panel (collapsible, below input) */}
|
||||
|
||||
+18
-1
@@ -114,7 +114,24 @@ export function streamChat(
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
if (done) {
|
||||
// Process any remaining data in buffer (last line may lack trailing newline)
|
||||
if (buffer.trim()) {
|
||||
const trimmed = buffer.trim();
|
||||
if (trimmed.startsWith("data: ")) {
|
||||
const json = trimmed.slice(6);
|
||||
if (json) {
|
||||
try {
|
||||
const event: ChatStreamEvent = JSON.parse(json);
|
||||
onEvent(event);
|
||||
} catch {
|
||||
// skip malformed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
|
||||
Reference in New Issue
Block a user