diff --git a/pages/link/callback_openrouter.tsx b/pages/link/callback_openrouter.tsx
index b70868ea4..6479c20b0 100644
--- a/pages/link/callback_openrouter.tsx
+++ b/pages/link/callback_openrouter.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { Box, Typography } from '@mui/joy';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreActions } from '~/common/stores/llms/store-llms';
import { InlineError } from '~/common/components/InlineError';
import { apiQuery } from '~/common/util/trpc.client';
@@ -30,7 +30,7 @@ function CallbackOpenRouterPage(props: { openRouterCode: string | undefined }) {
return;
// 1. Save the key as the client key
- useModelsStore.getState().setOpenRoutersKey(openRouterKey);
+ llmsStoreActions().setOpenRouterKey(openRouterKey);
// 2. Navigate to the chat app
void navigateToIndex(true); //.then(openModelsSetup);
diff --git a/src/apps/beam/AppBeam.tsx b/src/apps/beam/AppBeam.tsx
index d5499720c..d579c0c94 100644
--- a/src/apps/beam/AppBeam.tsx
+++ b/src/apps/beam/AppBeam.tsx
@@ -10,8 +10,8 @@ import { createBeamVanillaStore } from '~/modules/beam/store-beam-vanilla';
import { OptimaToolbarIn } from '~/common/layout/optima/portals/OptimaPortalsIn';
import { createDConversation, DConversation } from '~/common/stores/chat/chat.conversation';
import { createDMessageTextContent, DMessage } from '~/common/stores/chat/chat.message';
+import { getChatLLMId } from '~/common/stores/llms/store-llms';
import { useIsMobile } from '~/common/components/useMatchMedia';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
function initTestConversation(): DConversation {
@@ -22,7 +22,7 @@ function initTestConversation(): DConversation {
}
function initTestBeamStore(messages: DMessage[], beamStore: BeamStoreApi = createBeamVanillaStore()): BeamStoreApi {
- beamStore.getState().open(messages, useModelsStore.getState().chatLLMId, (content) => alert(content));
+ beamStore.getState().open(messages, getChatLLMId(), (content) => alert(content));
return beamStore;
}
diff --git a/src/apps/chat/components/layout-bar/useLLMDropdown.tsx b/src/apps/chat/components/layout-bar/useLLMDropdown.tsx
index 56fd5e6dd..469277f1f 100644
--- a/src/apps/chat/components/layout-bar/useLLMDropdown.tsx
+++ b/src/apps/chat/components/layout-bar/useLLMDropdown.tsx
@@ -8,12 +8,12 @@ import SettingsIcon from '@mui/icons-material/Settings';
import { findModelVendor } from '~/modules/llms/vendors/vendors.registry';
import type { DLLM, DLLMId } from '~/common/stores/llms/llms.types';
- import type { DModelsServiceId } from '~/common/stores/llms/modelsservice.types';
+import type { DModelsServiceId } from '~/common/stores/llms/modelsservice.types';
import { DebouncedInputMemo } from '~/common/components/DebouncedInput';
import { DropdownItems, PageBarDropdownMemo } from '~/common/layout/optima/components/PageBarDropdown';
import { GoodTooltip } from '~/common/components/GoodTooltip';
import { KeyStroke } from '~/common/components/KeyStroke';
-import { findModelsServiceOrNull, useModelsStore } from '~/common/stores/llms/store-llms';
+import { findModelsServiceOrNull, llmsStoreActions, useModelsStore } from '~/common/stores/llms/store-llms';
import { optimaActions, optimaOpenModels } from '~/common/layout/optima/useOptima';
@@ -181,15 +181,14 @@ function LLMDropdown(props: {
export function useChatLLMDropdown() {
// external state
- const { llms, chatLLMId, setChatLLMId } = useModelsStore(useShallow(state => ({
+ const { llms, chatLLMId } = useModelsStore(useShallow(state => ({
llms: state.llms, // NOTE: we don't need a deep comparison as we reference the same array
chatLLMId: state.chatLLMId,
- setChatLLMId: state.setChatLLMId,
})));
const chatLLMDropdown = React.useMemo(() => {
- return ;
- }, [llms, chatLLMId, setChatLLMId]);
+ return ;
+ }, [llms, chatLLMId]);
return { chatLLMId, chatLLMDropdown };
}
diff --git a/src/common/chat-overlay/ConversationHandler.ts b/src/common/chat-overlay/ConversationHandler.ts
index 0f767df37..8871c0f0c 100644
--- a/src/common/chat-overlay/ConversationHandler.ts
+++ b/src/common/chat-overlay/ConversationHandler.ts
@@ -10,7 +10,7 @@ import type { DLLMId } from '~/common/stores/llms/llms.types';
import { ChatActions, getConversationSystemPurposeId, useChatStore } from '~/common/stores/chat/store-chats';
import { createDMessageEmpty, createDMessageFromFragments, createDMessagePlaceholderIncomplete, createDMessageTextContent, DMessage, DMessageId } from '~/common/stores/chat/chat.message';
import { createTextContentFragment, DMessageFragment, DMessageFragmentId } from '~/common/stores/chat/chat.fragments';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { getChatLLMId } from '~/common/stores/llms/store-llms';
import { createDEphemeral } from './store-ephemeralsoverlay-slice';
import { createPerChatVanillaStore } from './store-chat-overlay';
@@ -176,8 +176,8 @@ export class ConversationHandler {
terminateKeepingSettings();
};
- beamOpen(viewHistory, useModelsStore.getState().chatLLMId, onBeamSuccess);
- importMessages.length && beamImportRays(importMessages, useModelsStore.getState().chatLLMId);
+ beamOpen(viewHistory, getChatLLMId(), onBeamSuccess);
+ importMessages.length && beamImportRays(importMessages, getChatLLMId());
}
diff --git a/src/common/components/forms/useFormRadioLlmType.tsx b/src/common/components/forms/useFormRadioLlmType.tsx
index 54c5205c0..9117434f4 100644
--- a/src/common/components/forms/useFormRadioLlmType.tsx
+++ b/src/common/components/forms/useFormRadioLlmType.tsx
@@ -1,8 +1,7 @@
import * as React from 'react';
-import { useShallow } from 'zustand/react/shallow';
import type { DLLM } from '~/common/stores/llms/llms.types';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { useDefaultLLMs } from '~/common/stores/llms/llms.hooks';
import type { FormRadioOption } from './FormRadioControl';
import { useFormRadio } from './useFormRadio';
@@ -13,15 +12,7 @@ type LlmType = 'chat' | 'fast';
export function useFormRadioLlmType(label: string = 'Model', initialModelType: LlmType = 'fast'): [DLLM | null, React.JSX.Element | null] {
// external state
- const { chatLLM, fastLLM } = useModelsStore(useShallow(state => {
- const { chatLLMId, fastLLMId } = state;
- const chatLLM = chatLLMId ? state.llms.find(llm => llm.id === chatLLMId) ?? null : null;
- const fastLLM = fastLLMId ? state.llms.find(llm => llm.id === fastLLMId) ?? null : null;
- return {
- chatLLM,
- fastLLM,
- };
- }));
+ const { chatLLM, fastLLM } = useDefaultLLMs();
const hidden = !chatLLM || !fastLLM || chatLLM === fastLLM;
diff --git a/src/common/components/forms/useLLMSelect.tsx b/src/common/components/forms/useLLMSelect.tsx
index 579951cfd..38442e3d8 100644
--- a/src/common/components/forms/useLLMSelect.tsx
+++ b/src/common/components/forms/useLLMSelect.tsx
@@ -1,5 +1,4 @@
import * as React from 'react';
-import { useShallow } from 'zustand/react/shallow';
import type { SxProps } from '@mui/joy/styles/types';
import { FormControl, ListDivider, ListItemDecorator, Option, Select, SvgIconProps } from '@mui/joy';
@@ -8,18 +7,19 @@ import type { IModelVendor } from '~/modules/llms/vendors/IModelVendor';
import { findModelVendor } from '~/modules/llms/vendors/vendors.registry';
import type { DLLM, DLLMId } from '~/common/stores/llms/llms.types';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { getChatLLMId } from '~/common/stores/llms/store-llms';
+import { useNonHiddenLLMs } from '~/common/stores/llms/llms.hooks';
import { FormLabelStart } from './FormLabelStart';
/*export function useLLMSelectGlobalState(): [DLLMId | null, (llmId: DLLMId | null) => void] {
- return useModelsStore(useShallow(state => [state.chatLLMId, state.setChatLLMId]));
+ return ...(useShallow(state => [state.chatLLMId, state.setChatLLMId]));
}*/
export function useLLMSelectLocalState(initFromGlobal: boolean): [DLLMId | null, (llmId: DLLMId | null) => void] {
return React.useState(initFromGlobal ? () => {
- return useModelsStore.getState().chatLLMId;
+ return getChatLLMId();
} : null);
}
@@ -51,9 +51,7 @@ export function useLLMSelect(
): [DLLM | null, React.JSX.Element | null, React.FunctionComponent | undefined] {
// external state
- const _filteredLLMs = useModelsStore(useShallow(state =>
- state.llms.filter(llm => !llm.hidden || (chatLLMId && llm.id === chatLLMId)),
- ));
+ const _filteredLLMs = useNonHiddenLLMs();
// derived state
const noIcons = false; //smaller;
diff --git a/src/common/layout/optima/DesktopNav.tsx b/src/common/layout/optima/DesktopNav.tsx
index b638478fa..0e9a2018f 100644
--- a/src/common/layout/optima/DesktopNav.tsx
+++ b/src/common/layout/optima/DesktopNav.tsx
@@ -6,11 +6,10 @@ import { Divider, Dropdown, ListItemDecorator, Menu, MenuButton, MenuItem, Toolt
import MenuIcon from '@mui/icons-material/Menu';
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
-
import { AgiSquircleIcon } from '~/common/components/icons/AgiSquircleIcon';
import { checkDivider, checkVisibileIcon, NavItemApp, navItems } from '~/common/app.nav';
import { themeZIndexDesktopNav } from '~/common/app.theme';
+import { useHasLLMs } from '~/common/stores/llms/llms.hooks';
import { BringTheLove } from './components/BringTheLove';
import { DesktopNavGroupBox, DesktopNavIcon, navItemClasses } from './components/DesktopNavIcon';
@@ -38,7 +37,7 @@ export function DesktopNav(props: { component: React.ElementType, currentApp?: N
// external state
const isDrawerOpen = useOptimaDrawerOpen();
const { showModels, showPreferences } = useOptimaModelsModalsState();
- const noLLMs = useModelsStore(state => !state.llms.length);
+ const noLLMs = !useHasLLMs();
// show/hide the pane when clicking on the logo
diff --git a/src/common/logic/autoconf.ts b/src/common/logic/autoconf.ts
index b647de88a..21006366d 100644
--- a/src/common/logic/autoconf.ts
+++ b/src/common/logic/autoconf.ts
@@ -7,7 +7,7 @@ import { getBackendCapabilities } from '~/modules/backend/store-backend-capabili
import { llmsUpdateModelsForServiceOrThrow } from '~/modules/llms/llm.client';
import type { DModelsService } from '~/common/stores/llms/modelsservice.types';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreState } from '~/common/stores/llms/store-llms';
interface AutoConfStore {
@@ -56,14 +56,15 @@ const autoConfVanillaStore = createVanillaStore()(persist((_set,
.then(async () => {
// find the first service for this vendor
- const { sources: modelsServices, addService } = useModelsStore.getState();
+ const { sources: modelsServices, addService } = llmsStoreState();
let service: DModelsService;
const firstServiceForVendor = modelsServices.find(s => s.vId === vendor.id);
if (!firstServiceForVendor) {
// create and append the model service, assuming the backend configuration will be successful
service = createModelsServiceForVendor(vendor.id, modelsServices);
addService(service);
- service = useModelsStore.getState().sources.find(_s => _s.id === service.id)!;
+ // re-find it now what's added
+ service = llmsStoreState().sources.find(_s => _s.id === service.id)!;
} else
service = firstServiceForVendor;
diff --git a/src/common/stores/llms/llms.hooks.ts b/src/common/stores/llms/llms.hooks.ts
index d4cba7aa6..15127f946 100644
--- a/src/common/stores/llms/llms.hooks.ts
+++ b/src/common/stores/llms/llms.hooks.ts
@@ -1,4 +1,6 @@
-import type { DLLM } from './llms.types';
+import { useShallow } from 'zustand/react/shallow';
+
+import type { DLLM, DLLMId } from './llms.types';
import { useModelsStore } from './store-llms';
@@ -11,6 +13,48 @@ export function useChatLLM(): { chatLLM: DLLM | null } {
return { chatLLM };
}
+export function useLLM(llmId: DLLMId): DLLM | null {
+ return useModelsStore(state => state.llms.find(llm => llm.id === llmId) ?? null);
+}
+
+export function useDefaultLLMIDs(): { chatLLMId: DLLMId | null; fastLLMId: DLLMId | null; funcLLMId: DLLMId | null; } {
+ return useModelsStore(useShallow(state => ({
+ chatLLMId: state.chatLLMId,
+ fastLLMId: state.fastLLMId,
+ funcLLMId: state.funcLLMId,
+ })));
+}
+
+export function useDefaultLLMs(): { chatLLM: DLLM | null; fastLLM: DLLM | null; funcLLM: DLLM | null } {
+ return useModelsStore(useShallow(state => {
+ const { chatLLMId, fastLLMId, funcLLMId } = state;
+ const chatLLM = chatLLMId ? state.llms.find(llm => llm.id === chatLLMId) ?? null : null;
+ const fastLLM = fastLLMId ? state.llms.find(llm => llm.id === fastLLMId) ?? null : null;
+ const funcLLM = funcLLMId ? state.llms.find(llm => llm.id === funcLLMId) ?? null : null;
+ return { chatLLM, fastLLM, funcLLM };
+ }));
+}
+
+export function useFilteredLLMs(filterId: false | DLLMId): DLLM[] {
+ return useModelsStore(useShallow(
+ state => !filterId ? state.llms : state.llms.filter(llm => llm.sId === filterId),
+ ));
+}
+
+export function useNonHiddenLLMs(): DLLM[] {
+ return useModelsStore(useShallow(
+ ({ llms, chatLLMId }) => llms.filter(llm => !llm.hidden || (chatLLMId && llm.id === chatLLMId)),
+ ));
+}
+
+export function useLLMsCount(): number {
+ return useModelsStore(state => state.llms.length);
+}
+
+export function useHasLLMs(): boolean {
+ return useModelsStore(state => !!state.llms.length);
+}
+
export function useModelsServices() {
return useModelsStore(state => state.sources);
}
\ No newline at end of file
diff --git a/src/common/stores/llms/store-llms.ts b/src/common/stores/llms/store-llms.ts
index dd386feb5..938650614 100644
--- a/src/common/stores/llms/store-llms.ts
+++ b/src/common/stores/llms/store-llms.ts
@@ -43,7 +43,7 @@ interface LlmsActions {
setFuncLLMId: (id: DLLMId | null) => void;
// special
- setOpenRoutersKey: (key: string) => void;
+ setOpenRouterKey: (key: string) => void;
}
@@ -163,7 +163,7 @@ export const useModelsStore = create()(persist(
),
})),
- setOpenRoutersKey: (key: string) =>
+ setOpenRouterKey: (key: string) =>
set(state => {
const firstOpenRouterService = state.sources.find(s => s.vId === 'openrouter');
return !firstOpenRouterService ? state : {
@@ -270,6 +270,10 @@ export function getFastLLMId(): DLLMId | null {
return llmsStoreState().fastLLMId;
}
+export function getFuncLLMId(): DLLMId | null {
+ return llmsStoreState().funcLLMId;
+}
+
export function llmsStoreState(): LlmsState & LlmsActions {
return useModelsStore.getState();
}
@@ -321,7 +325,7 @@ export function getDiverseTopLlmIds(count: number, requireElo: boolean, fallback
}
export function getLLMsDebugInfo() {
- const { llms, sources, chatLLMId, fastLLMId, funcLLMId } = useModelsStore.getState();
+ const { llms, sources, chatLLMId, fastLLMId, funcLLMId } = llmsStoreState();
return { services: sources.length, llmsCount: llms.length, chatId: chatLLMId, fastId: fastLLMId, funcId: funcLLMId };
}
diff --git a/src/common/stores/metrics/store-metrics.ts b/src/common/stores/metrics/store-metrics.ts
index 69b2beb88..e99b7ed90 100644
--- a/src/common/stores/metrics/store-metrics.ts
+++ b/src/common/stores/metrics/store-metrics.ts
@@ -14,7 +14,7 @@
// interface MetricsActions {
// }
//
-// export const useModelsStore = create()(persist(
+// export const useMetricsStore = create()(persist(
// (set) => ({
//
// // initial state
diff --git a/src/modules/aifn/autosuggestions/autoSuggestions.ts b/src/modules/aifn/autosuggestions/autoSuggestions.ts
index 27e3a3484..2a85a777f 100644
--- a/src/modules/aifn/autosuggestions/autoSuggestions.ts
+++ b/src/modules/aifn/autosuggestions/autoSuggestions.ts
@@ -4,7 +4,7 @@ import { ConversationsManager } from '~/common/chat-overlay/ConversationsManager
import { DLLMId, LLM_IF_OAI_Fn } from '~/common/stores/llms/llms.types';
import { DMessage, messageFragmentsReduceText } from '~/common/stores/chat/chat.message';
import { createErrorContentFragment, createPlaceholderMetaFragment, createTextContentFragment } from '~/common/stores/chat/chat.fragments';
-import { findLLMOrThrow, useModelsStore } from '~/common/stores/llms/store-llms';
+import { findLLMOrThrow, getFuncLLMId } from '~/common/stores/llms/store-llms';
import { marshallWrapText } from '~/common/stores/chat/chat.tokens';
import { useChatStore } from '~/common/stores/chat/store-chats';
@@ -156,7 +156,7 @@ function validateFunctionLLMId(funcLLMId: DLLMId | null): DLLMId | null {
}
// if not provided, or provided but not a function llm, then use the default
- return useModelsStore.getState().funcLLMId;
+ return getFuncLLMId();
}
diff --git a/src/modules/aifn/summarize/ContentReducer.tsx b/src/modules/aifn/summarize/ContentReducer.tsx
index 943b6dfe8..60cebf09c 100644
--- a/src/modules/aifn/summarize/ContentReducer.tsx
+++ b/src/modules/aifn/summarize/ContentReducer.tsx
@@ -1,10 +1,8 @@
import * as React from 'react';
-import { useShallow } from 'zustand/react/shallow';
import { Alert, Box, Button, CircularProgress, Divider, FormControl, Option, Select, Slider, Stack, Textarea, Typography } from '@mui/joy';
import type { DLLM, DLLMId } from '~/common/stores/llms/llms.types';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
import { TokenBadgeMemo } from '../../../apps/chat/components/composer/tokens/TokenBadge';
@@ -12,6 +10,7 @@ import { FormLabelStart } from '~/common/components/forms/FormLabelStart';
import { GoodModal } from '~/common/components/GoodModal';
import { Section } from '~/common/components/Section';
import { lineHeightTextareaMd } from '~/common/app.theme';
+import { useDefaultLLMIDs, useNonHiddenLLMs } from '~/common/stores/llms/llms.hooks';
import { summerizeToFitContextBudget } from './summerize';
@@ -39,10 +38,8 @@ export function ContentReducer(props: {
}) {
// external state
- const { llms, fastLLMId } = useModelsStore(useShallow(state => ({
- llms: state.llms, // probably relying on the stability of this
- fastLLMId: state.fastLLMId,
- })));
+ const llms = useNonHiddenLLMs();
+ const { fastLLMId } = useDefaultLLMIDs();
// state
const [reducerModelId, setReducerModelId] = React.useState(fastLLMId);
diff --git a/src/modules/llms/llm.client.ts b/src/modules/llms/llm.client.ts
index 85ae3374c..0bda7eccf 100644
--- a/src/modules/llms/llm.client.ts
+++ b/src/modules/llms/llm.client.ts
@@ -6,7 +6,7 @@ import type { OpenAIWire_Tools } from '~/modules/aix/server/dispatch/wiretypes/o
import type { DModelsService, DModelsServiceId } from '~/common/stores/llms/modelsservice.types';
import { DLLM, DLLMId, LLM_IF_OAI_Chat, LLM_IF_OAI_Fn } from '~/common/stores/llms/llms.types';
-import { findLLMOrThrow, useModelsStore } from '~/common/stores/llms/store-llms';
+import { findLLMOrThrow, llmsStoreActions } from '~/common/stores/llms/store-llms';
import { isModelPriceFree } from '~/common/stores/llms/llms.pricing';
import type { ChatStreamingInputSchema } from './server/llm.server.streaming';
@@ -54,7 +54,7 @@ export async function llmsUpdateModelsForServiceOrThrow(serviceId: DModelsServic
const data = await vendor.rpcUpdateModelsOrThrow(transportAccess);
// update the global models store
- useModelsStore.getState().setLLMs(
+ llmsStoreActions().setLLMs(
data.models.map(model => _createDLLMFromModelDescription(model, service)),
service.id,
true,
diff --git a/src/modules/llms/models-modal/LLMOptionsModal.tsx b/src/modules/llms/models-modal/LLMOptionsModal.tsx
index 1077f9729..93c186f25 100644
--- a/src/modules/llms/models-modal/LLMOptionsModal.tsx
+++ b/src/modules/llms/models-modal/LLMOptionsModal.tsx
@@ -1,6 +1,5 @@
import * as React from 'react';
import TimeAgo from 'react-timeago';
-import { useShallow } from 'zustand/react/shallow';
import { Box, Button, ButtonGroup, Divider, FormControl, Input, Switch, Tooltip, Typography } from '@mui/joy';
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
@@ -11,14 +10,15 @@ import type { DChatGeneratePricing } from '~/common/stores/llms/llms.pricing';
import type { DLLMId } from '~/common/stores/llms/llms.types';
import { FormLabelStart } from '~/common/components/forms/FormLabelStart';
import { GoodModal } from '~/common/components/GoodModal';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreActions } from '~/common/stores/llms/store-llms';
+import { useDefaultLLMIDs, useLLM } from '~/common/stores/llms/llms.hooks';
import { findModelVendor } from '../vendors/vendors.registry';
function VendorLLMOptionsComponent(props: { llmId: DLLMId }) {
// get LLM (warning: this will refresh all children components on every change of any LLM field)
- const llm = useModelsStore(state => state.llms.find(llm => llm.id === props.llmId));
+ const llm = useLLM(props.llmId);
if (!llm)
return 'Options issue: LLM not found for id ' + props.llmId;
@@ -69,27 +69,16 @@ export function LLMOptionsModal(props: { id: DLLMId, onClose: () => void }) {
const [showDetails, setShowDetails] = React.useState(false);
// external state
- const {
- llm,
- removeLLM, updateLLM,
- isChatLLM, setChatLLMId,
- isFastLLM, setFastLLMId,
- isFuncLLM, setFuncLLMId,
- } = useModelsStore(useShallow(state => ({
- llm: state.llms.find(llm => llm.id === props.id),
- removeLLM: state.removeLLM,
- updateLLM: state.updateLLM,
- isChatLLM: state.chatLLMId === props.id,
- isFastLLM: state.fastLLMId === props.id,
- isFuncLLM: state.funcLLMId === props.id,
- setChatLLMId: state.setChatLLMId,
- setFastLLMId: state.setFastLLMId,
- setFuncLLMId: state.setFuncLLMId,
- })));
+ const llm = useLLM(props.id);
+ const { chatLLMId, fastLLMId, funcLLMId } = useDefaultLLMIDs();
+ const { removeLLM, updateLLM, setChatLLMId, setFastLLMId, setFuncLLMId } = llmsStoreActions();
if (!llm)
return <>Options issue: LLM not found for id {props.id}>;
+ const isChatLLM = chatLLMId === props.id;
+ const isFastLLM = fastLLMId === props.id;
+ const isFuncLLM = funcLLMId === props.id;
const handleLlmLabelSet = (event: React.ChangeEvent) => updateLLM(llm.id, { label: event.target.value || '' });
diff --git a/src/modules/llms/models-modal/ModelsList.tsx b/src/modules/llms/models-modal/ModelsList.tsx
index ebc9d1e9e..2d037d95d 100644
--- a/src/modules/llms/models-modal/ModelsList.tsx
+++ b/src/modules/llms/models-modal/ModelsList.tsx
@@ -1,5 +1,4 @@
import * as React from 'react';
-import { useShallow } from 'zustand/react/shallow';
import type { SxProps } from '@mui/joy/styles/types';
import { Box, Chip, IconButton, List, ListItem, ListItemButton, Typography } from '@mui/joy';
@@ -11,7 +10,8 @@ import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
import type { DLLM, DLLMId } from '~/common/stores/llms/llms.types';
import type { DModelsServiceId } from '~/common/stores/llms/modelsservice.types';
import { GoodTooltip } from '~/common/components/GoodTooltip';
-import { findModelsServiceOrNull, useModelsStore } from '~/common/stores/llms/store-llms';
+import { findModelsServiceOrNull, llmsStoreActions } from '~/common/stores/llms/store-llms';
+import { useDefaultLLMIDs, useFilteredLLMs } from '~/common/stores/llms/llms.hooks';
import { IModelVendor } from '../vendors/IModelVendor';
import { findModelVendor } from '../vendors/vendors.registry';
@@ -150,16 +150,9 @@ export function ModelsList(props: {
}) {
// external state
- const { chatLLMId, fastLLMId, funcLLMId, updateLLM } = useModelsStore(useShallow(state => ({
- chatLLMId: state.chatLLMId,
- fastLLMId: state.fastLLMId,
- funcLLMId: state.funcLLMId,
- updateLLM: state.updateLLM,
- })));
- const llms = useModelsStore(useShallow(state =>
- // note: we don't put this together with the former, to avoid going 1-level too deep in the shallow comparison
- state.llms.filter(llm => !props.filterServiceId || llm.sId === props.filterServiceId),
- ));
+ const { updateLLM } = llmsStoreActions();
+ const { chatLLMId, fastLLMId, funcLLMId } = useDefaultLLMIDs();
+ const llms = useFilteredLLMs(props.filterServiceId === null ? false : props.filterServiceId);
const { onOpenLLMOptions } = props;
diff --git a/src/modules/llms/models-modal/ModelsModal.tsx b/src/modules/llms/models-modal/ModelsModal.tsx
index 7fd5fb303..9fd6d033d 100644
--- a/src/modules/llms/models-modal/ModelsModal.tsx
+++ b/src/modules/llms/models-modal/ModelsModal.tsx
@@ -1,13 +1,13 @@
import * as React from 'react';
-import { useShallow } from 'zustand/react/shallow';
import { Box, Checkbox, Divider } from '@mui/joy';
import type { DModelsService, DModelsServiceId } from '~/common/stores/llms/modelsservice.types';
import { GoodModal } from '~/common/components/GoodModal';
-import { llmsStoreState, useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreState } from '~/common/stores/llms/store-llms';
import { optimaActions, optimaOpenModels, useOptimaModelsModalsState } from '~/common/layout/optima/useOptima';
import { runWhenIdle } from '~/common/util/pwaUtils';
+import { useLLMsCount, useModelsServices } from '~/common/stores/llms/llms.hooks';
import { LLMOptionsModal } from './LLMOptionsModal';
import { ModelsList } from './ModelsList';
@@ -32,10 +32,8 @@ export function ModelsModal(props: { suspendAutoModelsSetup?: boolean }) {
// external state
const { showModels, showModelOptions } = useOptimaModelsModalsState();
- const { modelsServices, llmCount } = useModelsStore(useShallow(state => ({
- modelsServices: state.sources,
- llmCount: state.llms.length,
- })));
+ const modelsServices = useModelsServices();
+ const llmCount = useLLMsCount();
// auto-select the first service - note: we could use a useEffect() here, but this is more efficient
// also note that state-persistence is unneeded
diff --git a/src/modules/llms/vendors/openai/OpenAILLMOptions.tsx b/src/modules/llms/vendors/openai/OpenAILLMOptions.tsx
index 1bd4c032d..45abb77ae 100644
--- a/src/modules/llms/vendors/openai/OpenAILLMOptions.tsx
+++ b/src/modules/llms/vendors/openai/OpenAILLMOptions.tsx
@@ -7,7 +7,7 @@ import type { DLLM } from '~/common/stores/llms/llms.types';
import { FormSliderControl } from '~/common/components/forms/FormSliderControl';
import { InlineError } from '~/common/components/InlineError';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreActions } from '~/common/stores/llms/store-llms';
import { DOpenAILLMOptions, FALLBACK_LLM_RESPONSE_TOKENS, FALLBACK_LLM_TEMPERATURE } from './openai.vendor';
@@ -27,7 +27,7 @@ export function OpenAILLMOptions(props: { llm: DLLM }) {
// derived state
const { id: llmId, maxOutputTokens, options } = props.llm;
const { llmResponseTokens, llmTemperature } = normalizeOpenAIOptions(options);
- const { updateLLMOptions } = useModelsStore.getState();
+ const { updateLLMOptions } = llmsStoreActions();
// state (here because the initial state depends on props)
const [overheat, setOverheat] = React.useState(llmTemperature > 1);
diff --git a/src/modules/llms/vendors/openrouter/OpenRouterServiceSetup.tsx b/src/modules/llms/vendors/openrouter/OpenRouterServiceSetup.tsx
index ad56a623a..d17b9dc3e 100644
--- a/src/modules/llms/vendors/openrouter/OpenRouterServiceSetup.tsx
+++ b/src/modules/llms/vendors/openrouter/OpenRouterServiceSetup.tsx
@@ -11,7 +11,7 @@ import { InlineError } from '~/common/components/InlineError';
import { Link } from '~/common/components/Link';
import { SetupFormRefetchButton } from '~/common/components/forms/SetupFormRefetchButton';
import { getCallbackUrl } from '~/common/app.routes';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreState } from '~/common/stores/llms/store-llms';
import { useLlmUpdateModels } from '../../llm.client.hooks';
import { useServiceSetup } from '../useServiceSetup';
@@ -48,7 +48,7 @@ export function OpenRouterServiceSetup(props: { serviceId: DModelsServiceId }) {
const handleRemoveNonFreeLLMs = () => {
// A bit of a hack
- const { llms, removeLLM } = useModelsStore.getState();
+ const { llms, removeLLM } = llmsStoreState();
llms
.filter(llm => llm.sId === props.serviceId)
.filter(llm => llm.pricing?.chat?._isFree === false)
@@ -57,7 +57,7 @@ export function OpenRouterServiceSetup(props: { serviceId: DModelsServiceId }) {
};
const handleSetVisibilityAll = React.useCallback((visible: boolean) => {
- const { llms, updateLLM } = useModelsStore.getState();
+ const { llms, updateLLM } = llmsStoreState();
llms
.filter(llm => llm.sId === props.serviceId)
.forEach(llm => updateLLM(llm.id, { hidden: !visible }));
diff --git a/src/modules/t2i/t2i.client.ts b/src/modules/t2i/t2i.client.ts
index 4f425ef57..f9f05665c 100644
--- a/src/modules/t2i/t2i.client.ts
+++ b/src/modules/t2i/t2i.client.ts
@@ -11,7 +11,7 @@ import type { DLLM } from '~/common/stores/llms/llms.types';
import type { DModelsService, DModelsServiceId } from '~/common/stores/llms/modelsservice.types';
import { createDMessageDataRefDBlob, createImageContentFragment, DMessageContentFragment } from '~/common/stores/chat/chat.fragments';
import { shallowEquals } from '~/common/util/hooks/useShallowObject';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
+import { llmsStoreState, useModelsStore } from '~/common/stores/llms/store-llms';
import type { T2iCreateImageOutput } from './t2i.server';
import { openAIGenerateImagesOrThrow } from './dalle/openaiGenerateImages';
@@ -81,7 +81,7 @@ export function getActiveTextToImageProviderOrThrow() {
throw new Error('No TextToImage Provider selected');
// [immediate] get all providers
- const { llms, sources: modelsServices } = useModelsStore.getState();
+ const { llms, sources: modelsServices } = llmsStoreState();
const openAIModelsServiceIDs = getLlmsModelServices(llms, modelsServices);
const providers = getTextToImageProviders(openAIModelsServiceIDs, !!useProdiaStore.getState().prodiaModelId);
diff --git a/src/modules/trade/trade.client.ts b/src/modules/trade/trade.client.ts
index fc147706f..c4f7f8713 100644
--- a/src/modules/trade/trade.client.ts
+++ b/src/modules/trade/trade.client.ts
@@ -6,12 +6,12 @@ import { Brand } from '~/common/app.config';
import { DataAtRestV1 } from '~/common/stores/chat/chats.converters';
import { capitalizeFirstLetter } from '~/common/util/textUtils';
import { conversationTitle, DConversation } from '~/common/stores/chat/chat.conversation';
+import { llmsStoreState } from '~/common/stores/llms/store-llms';
import { messageFragmentsReduceText } from '~/common/stores/chat/chat.message';
import { prettyBaseModel } from '~/common/util/modelUtils';
import { prettyTimestampForFilenames } from '~/common/util/timeUtils';
import { useChatStore } from '~/common/stores/chat/store-chats';
import { useFolderStore } from '~/common/state/store-folders';
-import { useModelsStore } from '~/common/stores/llms/store-llms';
import type { ImportedOutcome } from './ImportOutcomeModal';
@@ -124,7 +124,7 @@ export async function downloadAllJsonV1B() {
const { folders, enableFolders } = useFolderStore.getState();
const payload = DataAtRestV1.formatAllToJsonV1B(
useChatStore.getState().conversations,
- useModelsStore.getState().sources,
+ llmsStoreState().sources,
folders, enableFolders,
);
const json = JSON.stringify(payload);