[hAIk]: fix: create modelsSlice and register it in store to resolve ModelModeSelector TypeError on dashboard agent launch. Reuses SUBSCRIPTIONS_STATUS thunk instead of duplicating the fetch.

This commit is contained in:
haikdc
2026-04-18 08:28:54 -07:00
parent dde5c6de5c
commit 5439420fa9
5 changed files with 59 additions and 9 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ import { ThemeProvider as MuiThemeProvider, CssBaseline } from '@mui/material';
import { store } from '../shared/state/store';
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
import { GET_SETTINGS } from '@/shared/backend-bridge/apps/settings';
// import { fetchModels } from '@/shared/state/modelsSlice';
import { SUBSCRIPTIONS_STATUS } from '@/shared/backend-bridge/apps/subscriptions';
import {
setAppVersion,
setUpdateAvailable,
@@ -40,7 +40,7 @@ const SettingsLoader: React.FC<{ children: React.ReactNode }> = ({ children }) =
const loaded = useAppSelector((s) => s.settings.loaded);
useEffect(() => {
dispatch(GET_SETTINGS());
// dispatch(fetchModels());
dispatch(SUBSCRIPTIONS_STATUS());
}, [dispatch]);
useEffect(() => {
if (loaded) setThemeMode(theme as 'light' | 'dark');
@@ -52,10 +52,10 @@ interface Props {
}
const ModelModeSelector: React.FC<Props> = ({
mode, onModeChange, model, onModelChange, provider, onProviderChange,
mode, onModeChange, model, onModelChange, onProviderChange,
contextEstimate, ownerId, sessionId,
autoRunMode, hasContent, isRunning, disabled, onSend, onStop,
browseAndAttachFiles, queueLength = 0,
browseAndAttachFiles,
}) => {
const c = useClaudeTokens();
const dispatch = useAppDispatch();
@@ -2,7 +2,7 @@ import { useState, useEffect, useMemo, useCallback } from 'react';
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
import { UPDATE_SETTINGS, AppSettings } from '@/shared/backend-bridge/apps/settings';
import { closeSettingsModal } from '@/shared/state/settingsSlice';
// import { fetchModels } from '@/shared/state/modelsSlice';
import { SUBSCRIPTIONS_STATUS } from '@/shared/backend-bridge/apps/subscriptions';
import { setChecking, setUpdateError } from '@/shared/state/updateSlice';
import { LIST_MODES } from '@/shared/state/modesSlice';
import { useClaudeTokens, useThemeMode } from '@/shared/styles/ThemeContext';
@@ -35,7 +35,7 @@ export function useSettings() {
const handleSave = async () => {
await dispatch(UPDATE_SETTINGS(form));
if (form.theme !== settings.theme) setThemeMode(form.theme);
// dispatch(fetchModels());
dispatch(SUBSCRIPTIONS_STATUS());
setSaved(true);
};
const handleRequestClose = useCallback(() => {
@@ -50,7 +50,7 @@ export function useSettings() {
const handleSaveAndClose = useCallback(async () => {
await dispatch(UPDATE_SETTINGS(form));
if (form.theme !== settings.theme) setThemeMode(form.theme);
// dispatch(fetchModels());
dispatch(SUBSCRIPTIONS_STATUS());
setSaved(true);
setConfirmDiscard(false);
dispatch(closeSettingsModal());
+50
View File
@@ -0,0 +1,50 @@
import { createSlice } from '@reduxjs/toolkit';
import { SUBSCRIPTIONS_STATUS } from '@/shared/backend-bridge/apps/subscriptions';
interface ModelEntry {
value: string;
label: string;
context_window: number;
provider: string;
}
interface ModelsState {
byProvider: Record<string, ModelEntry[]>;
loading: boolean;
loaded: boolean;
}
const initialState: ModelsState = { byProvider: {}, loading: false, loaded: false };
function groupByProvider(raw: any[]): Record<string, ModelEntry[]> {
const grouped: Record<string, ModelEntry[]> = {};
for (const m of raw) {
const entry: ModelEntry = {
value: m.value ?? m.id ?? '',
label: m.label ?? m.value ?? '',
context_window: m.context_window ?? 200_000,
provider: m.provider ?? 'Unknown',
};
const key = entry.provider.charAt(0).toUpperCase() + entry.provider.slice(1);
(grouped[key] ??= []).push(entry);
}
return grouped;
}
const modelsSlice = createSlice({
name: 'models',
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(SUBSCRIPTIONS_STATUS.pending, (state) => { state.loading = true; })
.addCase(SUBSCRIPTIONS_STATUS.fulfilled, (state, action) => {
state.loading = false;
state.loaded = true;
state.byProvider = groupByProvider((action.payload as any).models ?? []);
})
.addCase(SUBSCRIPTIONS_STATUS.rejected, (state) => { state.loading = false; state.loaded = true; });
},
});
export default modelsSlice.reducer;
+2 -2
View File
@@ -11,7 +11,7 @@ import dashboardLayoutReducer from './dashboardLayoutSlice';
import dashboardsReducer from './dashboardsSlice';
import appsReducer from './appsSlice';
import updateReducer from './updateSlice';
// import modelsReducer from './modelsSlice';
import modelsReducer from './modelsSlice';
export const store = configureStore({
reducer: {
@@ -27,7 +27,7 @@ export const store = configureStore({
dashboards: dashboardsReducer,
apps: appsReducer,
update: updateReducer,
// models: modelsReducer,
models: modelsReducer,
},
});