chat: remember last model
This commit is contained in:
@@ -37,6 +37,10 @@ type SidebarItem = SidebarSelection & {
|
||||
title: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
initiatedProvider: Provider | null;
|
||||
initiatedModel: string | null;
|
||||
lastUsedProvider: Provider | null;
|
||||
lastUsedModel: string | null;
|
||||
};
|
||||
type ContextMenuState = {
|
||||
item: SidebarSelection;
|
||||
@@ -89,11 +93,26 @@ function loadStoredModelPreferences() {
|
||||
}
|
||||
|
||||
function pickProviderModel(options: string[], preferred: string | null, fallback: string | null = null) {
|
||||
if (preferred && options.includes(preferred)) return preferred;
|
||||
if (fallback && options.includes(fallback)) return fallback;
|
||||
if (preferred && options.includes(preferred)) return preferred;
|
||||
return options[0] ?? "";
|
||||
}
|
||||
|
||||
function getProviderLabel(provider: Provider | null | undefined) {
|
||||
if (provider === "openai") return "OpenAI";
|
||||
if (provider === "anthropic") return "Anthropic";
|
||||
if (provider === "xai") return "xAI";
|
||||
return "";
|
||||
}
|
||||
|
||||
function getChatModelSelection(chat: Pick<ChatSummary, "lastUsedProvider" | "lastUsedModel"> | Pick<ChatDetail, "lastUsedProvider" | "lastUsedModel"> | null) {
|
||||
if (!chat?.lastUsedProvider || !chat.lastUsedModel?.trim()) return null;
|
||||
return {
|
||||
provider: chat.lastUsedProvider,
|
||||
model: chat.lastUsedModel.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
type ModelComboboxProps = {
|
||||
options: string[];
|
||||
value: string;
|
||||
@@ -212,6 +231,10 @@ function buildSidebarItems(chats: ChatSummary[], searches: SearchSummary[]): Sid
|
||||
title: getChatTitle(chat),
|
||||
updatedAt: chat.updatedAt,
|
||||
createdAt: chat.createdAt,
|
||||
initiatedProvider: chat.initiatedProvider,
|
||||
initiatedModel: chat.initiatedModel,
|
||||
lastUsedProvider: chat.lastUsedProvider,
|
||||
lastUsedModel: chat.lastUsedModel,
|
||||
})),
|
||||
...searches.map((search) => ({
|
||||
kind: "search" as const,
|
||||
@@ -219,6 +242,10 @@ function buildSidebarItems(chats: ChatSummary[], searches: SearchSummary[]): Sid
|
||||
title: getSearchTitle(search),
|
||||
updatedAt: search.updatedAt,
|
||||
createdAt: search.createdAt,
|
||||
initiatedProvider: null,
|
||||
initiatedModel: null,
|
||||
lastUsedProvider: null,
|
||||
lastUsedModel: null,
|
||||
})),
|
||||
];
|
||||
|
||||
@@ -473,6 +500,16 @@ export default function App() {
|
||||
return searches.find((search) => search.id === selectedItem.id) ?? null;
|
||||
}, [searches, selectedItem]);
|
||||
|
||||
useEffect(() => {
|
||||
if (draftKind || selectedItem?.kind !== "chat") return;
|
||||
const detailSelection = selectedChat?.id === selectedItem.id ? getChatModelSelection(selectedChat) : null;
|
||||
const summarySelection = getChatModelSelection(selectedChatSummary);
|
||||
const nextSelection = detailSelection ?? summarySelection;
|
||||
if (!nextSelection) return;
|
||||
setProvider(nextSelection.provider);
|
||||
setModel(nextSelection.model);
|
||||
}, [draftKind, selectedChat, selectedChatSummary, selectedItem]);
|
||||
|
||||
const selectedTitle = useMemo(() => {
|
||||
if (draftKind === "chat") return "New chat";
|
||||
if (draftKind === "search") return "New search";
|
||||
@@ -611,6 +648,10 @@ export default function App() {
|
||||
title: chat.title,
|
||||
createdAt: chat.createdAt,
|
||||
updatedAt: chat.updatedAt,
|
||||
initiatedProvider: chat.initiatedProvider,
|
||||
initiatedModel: chat.initiatedModel,
|
||||
lastUsedProvider: chat.lastUsedProvider,
|
||||
lastUsedModel: chat.lastUsedModel,
|
||||
messages: [],
|
||||
});
|
||||
setSelectedSearch(null);
|
||||
@@ -937,6 +978,9 @@ export default function App() {
|
||||
) : null}
|
||||
{sidebarItems.map((item) => {
|
||||
const active = selectedItem?.kind === item.kind && selectedItem.id === item.id;
|
||||
const initiatedLabel = item.kind === "chat" && item.initiatedModel
|
||||
? `${getProviderLabel(item.initiatedProvider)}${item.initiatedProvider ? " · " : ""}${item.initiatedModel}`
|
||||
: null;
|
||||
return (
|
||||
<button
|
||||
key={`${item.kind}-${item.id}`}
|
||||
@@ -956,7 +1000,12 @@ export default function App() {
|
||||
{item.kind === "chat" ? <MessageSquare className="h-3.5 w-3.5" /> : <Search className="h-3.5 w-3.5" />}
|
||||
<p className="truncate text-sm font-medium">{item.title}</p>
|
||||
</div>
|
||||
<p className={cn("mt-1 text-xs", active ? "text-violet-100/90" : "text-violet-300/60")}>{formatDate(item.updatedAt)}</p>
|
||||
<div className="mt-1 flex items-center gap-2 text-xs">
|
||||
<p className={cn("shrink-0", active ? "text-violet-100/90" : "text-violet-300/60")}>{formatDate(item.updatedAt)}</p>
|
||||
{initiatedLabel ? (
|
||||
<p className={cn("ml-auto truncate text-right", active ? "text-violet-200/65" : "text-violet-300/45")}>{initiatedLabel}</p>
|
||||
) : null}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -3,6 +3,10 @@ export type ChatSummary = {
|
||||
title: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
initiatedProvider: Provider | null;
|
||||
initiatedModel: string | null;
|
||||
lastUsedProvider: Provider | null;
|
||||
lastUsedModel: string | null;
|
||||
};
|
||||
|
||||
export type SearchSummary = {
|
||||
@@ -26,6 +30,10 @@ export type ChatDetail = {
|
||||
title: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
initiatedProvider: Provider | null;
|
||||
initiatedModel: string | null;
|
||||
lastUsedProvider: Provider | null;
|
||||
lastUsedModel: string | null;
|
||||
messages: Message[];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user