Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions src/components/app-builder/AppBuilderChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ export function AppBuilderChat({ onNewProject, organizationId }: AppBuilderChatP
const [messageUuid, setMessageUuid] = useState(() => crypto.randomUUID());
const [selectedModel, setSelectedModel] = useState<string>(projectModel ?? '');
const [hasImages, setHasImages] = useState(false);
// Track the initial projectModel to detect when a new project loads
const initialProjectModelRef = useRef(projectModel);
const [visibleSessionCount, setVisibleSessionCount] = useState(DEFAULT_VISIBLE_SESSIONS);
const trpc = useTRPC();

Expand Down Expand Up @@ -280,33 +282,33 @@ export function AppBuilderChat({ onNewProject, organizationId }: AppBuilderChatP
// Warning state: user uploaded images but model doesn't support them
const hasImageWarning = hasImages && !modelSupportsImages;

// Sync selectedModel with projectModel when it changes (e.g., when loading a project)
// This takes priority over default selection - always apply projectModel when it arrives
// Sync selectedModel when a different project loads (projectModel changes from initial)
useEffect(() => {
if (projectModel) {
if (projectModel && projectModel !== initialProjectModelRef.current) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Model sync only triggers when the model ID string changes

If you navigate to a different project that happens to use the same projectModel value as the previous project, this effect will not run, so selectedModel can incorrectly carry over a prior user selection. Consider keying this sync off a project identity (e.g., project id / manager) rather than projectModel value, or resetting selectedModel when the manager/project changes.

initialProjectModelRef.current = projectModel;
setSelectedModel(projectModel);
}
}, [projectModel]);

// Set fallback model when available and not yet selected (and no projectModel)
// Set fallback model when models load and no valid selection exists
useEffect(() => {
if (modelOptions.length === 0) {
if (selectedModel) {
setSelectedModel('');
}
return;
}

// If no model selected yet and no projectModel provided, select the default or first available
if (!selectedModel && !projectModel) {
const defaultModel = defaultsData?.defaultModel;
const isDefaultAllowed = defaultModel && modelOptions.some(m => m.id === defaultModel);
const newModel = isDefaultAllowed ? defaultModel : modelOptions[0]?.id;
if (newModel) {
setSelectedModel(newModel);
}
// If current selection is valid, keep it
if (selectedModel && modelOptions.some(m => m.id === selectedModel)) {
return;
}

// Pick a default model
const defaultModel = defaultsData?.defaultModel;
const isDefaultAllowed = defaultModel && modelOptions.some(m => m.id === defaultModel);
const newModel = isDefaultAllowed ? defaultModel : modelOptions[0]?.id;
if (newModel) {
setSelectedModel(newModel);
}
}, [defaultsData?.defaultModel, modelOptions, selectedModel, projectModel]);
}, [defaultsData?.defaultModel, modelOptions, selectedModel]);

// Filter messages to show only important ones for cleaner UX
const filteredMessages = useMemo(() => filterAppBuilderMessages(messages), [messages]);
Expand Down