diff --git a/frontend/src/components/workspace/command-palette.tsx b/frontend/src/components/workspace/command-palette.tsx
index a73f412b9..1d754f61d 100644
--- a/frontend/src/components/workspace/command-palette.tsx
+++ b/frontend/src/components/workspace/command-palette.tsx
@@ -6,7 +6,7 @@ import {
SettingsIcon,
} from "lucide-react";
import { useRouter } from "next/navigation";
-import { useCallback, useMemo, useState } from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
import {
CommandDialog,
@@ -35,6 +35,7 @@ export function CommandPalette() {
const [open, setOpen] = useState(false);
const [shortcutsOpen, setShortcutsOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
+ const [isMac, setIsMac] = useState(false);
const handleNewChat = useCallback(() => {
router.push("/workspace/chats/new");
@@ -63,8 +64,9 @@ export function CommandPalette() {
useGlobalShortcuts(shortcuts);
- const isMac =
- typeof navigator !== "undefined" && navigator.userAgent.includes("Mac");
+ useEffect(() => {
+ setIsMac(navigator.userAgent.includes("Mac"));
+ }, []);
const metaKey = isMac ? "โ" : "Ctrl+";
const shiftKey = isMac ? "โง" : "Shift+";
diff --git a/frontend/src/components/workspace/input-box.tsx b/frontend/src/components/workspace/input-box.tsx
index d1682bb73..19e93b3f3 100644
--- a/frontend/src/components/workspace/input-box.tsx
+++ b/frontend/src/components/workspace/input-box.tsx
@@ -109,6 +109,7 @@ export function InputBox({
threadId,
initialValue,
onContextChange,
+ onFollowupsVisibilityChange,
onSubmit,
onStop,
...props
@@ -136,6 +137,7 @@ export function InputBox({
reasoning_effort?: "minimal" | "low" | "medium" | "high";
},
) => void;
+ onFollowupsVisibilityChange?: (visible: boolean) => void;
onSubmit?: (message: PromptInputMessage) => void;
onStop?: () => void;
}) {
@@ -186,6 +188,8 @@ export function InputBox({
return models.find((m) => m.name === context.model_name) ?? models[0];
}, [context.model_name, models]);
+ const resolvedModelName = selectedModel?.name;
+
const supportThinking = useMemo(
() => selectedModel?.supports_thinking ?? false,
[selectedModel],
@@ -253,9 +257,33 @@ export function InputBox({
setFollowups([]);
setFollowupsHidden(false);
setFollowupsLoading(false);
+
+ // Guard against submitting before the initial model auto-selection
+ // effect has flushed thread settings to storage/state.
+ if (resolvedModelName && context.model_name !== resolvedModelName) {
+ onContextChange?.({
+ ...context,
+ model_name: resolvedModelName,
+ mode: getResolvedMode(
+ context.mode,
+ selectedModel?.supports_thinking ?? false,
+ ),
+ });
+ setTimeout(() => onSubmit?.(message), 0);
+ return;
+ }
+
onSubmit?.(message);
},
- [onSubmit, onStop, status],
+ [
+ context,
+ onContextChange,
+ onSubmit,
+ onStop,
+ resolvedModelName,
+ selectedModel?.supports_thinking,
+ status,
+ ],
);
const requestFormSubmit = useCallback(() => {
@@ -309,6 +337,26 @@ export function InputBox({
setTimeout(() => requestFormSubmit(), 0);
}, [pendingSuggestion, requestFormSubmit, textInput]);
+ const showFollowups =
+ !disabled &&
+ !isNewThread &&
+ !followupsHidden &&
+ (followupsLoading || followups.length > 0);
+
+ const followupsVisibilityChangeRef = useRef(onFollowupsVisibilityChange);
+
+ useEffect(() => {
+ followupsVisibilityChangeRef.current = onFollowupsVisibilityChange;
+ }, [onFollowupsVisibilityChange]);
+
+ useEffect(() => {
+ followupsVisibilityChangeRef.current?.(showFollowups);
+ }, [showFollowups]);
+
+ useEffect(() => {
+ return () => followupsVisibilityChangeRef.current?.(false);
+ }, []);
+
useEffect(() => {
const streaming = status === "streaming";
const wasStreaming = wasStreamingRef.current;
@@ -769,40 +817,37 @@ export function InputBox({
)}
- {!disabled &&
- !isNewThread &&
- !followupsHidden &&
- (followupsLoading || followups.length > 0) && (
-
-
- {followupsLoading ? (
-
- {t.inputBox.followupLoading}
-
- ) : (
-
- {followups.map((s) => (
- handleFollowupClick(s)}
- />
- ))}
-
-
- )}
-
+ {showFollowups && (
+
+
+ {followupsLoading ? (
+
+ {t.inputBox.followupLoading}
+
+ ) : (
+
+ {followups.map((s) => (
+ handleFollowupClick(s)}
+ />
+ ))}
+
+
+ )}
- )}
+
+ )}