refactor: use pinia store for captain config

This commit is contained in:
Shivam Mishra
2025-12-23 15:28:50 +05:30
parent fc8b2d6c72
commit def8a4bf99
5 changed files with 81 additions and 96 deletions
@@ -1,10 +1,12 @@
<script setup>
import { computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useAlert } from 'dashboard/composables';
import { useMapGetter, useStore } from 'dashboard/composables/store';
import { useStore } from 'dashboard/composables/store';
import { useCaptain } from 'dashboard/composables/useCaptain';
import { useConfig } from 'dashboard/composables/useConfig';
import { useCaptainConfigStore } from 'dashboard/store/captain/config';
import SettingsLayout from '../SettingsLayout.vue';
import BaseSettingsHeader from '../components/BaseSettingsHeader.vue';
@@ -18,8 +20,8 @@ const store = useStore();
const { captainEnabled } = useCaptain();
const { isEnterprise } = useConfig();
const uiFlags = useMapGetter('captainConfig/getUIFlags');
const features = useMapGetter('captainConfig/getFeatures');
const captainConfigStore = useCaptainConfigStore();
const { uiFlags, features } = storeToRefs(captainConfigStore);
const isLoading = computed(() => uiFlags.value.isFetching);
@@ -71,7 +73,7 @@ async function handleFeatureToggle({ feature, enabled }) {
} catch (error) {
useAlert(t('CAPTAIN_SETTINGS.API.ERROR'));
// Refetch to revert the toggle state
store.dispatch('captainConfig/fetch');
captainConfigStore.fetch();
}
}
@@ -84,12 +86,12 @@ async function handleModelChange({ feature, model }) {
} catch (error) {
useAlert(t('CAPTAIN_SETTINGS.API.ERROR'));
// Refetch to revert the model selection
store.dispatch('captainConfig/fetch');
captainConfigStore.fetch();
}
}
onMounted(() => {
store.dispatch('captainConfig/fetch');
captainConfigStore.fetch();
});
</script>
@@ -1,7 +1,8 @@
<script setup>
import { ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useFunctionGetter, useMapGetter } from 'dashboard/composables/store';
import { storeToRefs } from 'pinia';
import { useCaptainConfigStore } from 'dashboard/store/captain/config';
import Switch from 'dashboard/components-next/switch/Switch.vue';
import ModelDropdown from './ModelDropdown.vue';
@@ -15,11 +16,11 @@ const props = defineProps({
const emit = defineEmits(['change', 'modelChange']);
const { t } = useI18n();
const features = useMapGetter('captainConfig/getFeatures');
const captainConfigStore = useCaptainConfigStore();
const { features } = storeToRefs(captainConfigStore);
const availableModels = useFunctionGetter(
'captainConfig/getModelsForFeature',
props.featureKey
const availableModels = computed(() =>
captainConfigStore.getModelsForFeature(props.featureKey)
);
const isEnabled = ref(false);
@@ -1,7 +1,7 @@
<script setup>
import { ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useFunctionGetter } from 'dashboard/composables/store';
import { useCaptainConfigStore } from 'dashboard/store/captain/config';
import Icon from 'dashboard/components-next/icon/Icon.vue';
import DropdownBody from 'dashboard/components-next/dropdown-menu/base/DropdownBody.vue';
import DropdownItem from 'dashboard/components-next/dropdown-menu/base/DropdownItem.vue';
@@ -28,21 +28,19 @@ const iconForModel = model => {
};
const { t } = useI18n();
const captainConfigStore = useCaptainConfigStore();
const isOpen = ref(false);
const availableModels = useFunctionGetter(
'captainConfig/getModelsForFeature',
props.featureKey
const availableModels = computed(() =>
captainConfigStore.getModelsForFeature(props.featureKey)
);
const recommendedModelId = useFunctionGetter(
'captainConfig/getDefaultModelForFeature',
props.featureKey
const recommendedModelId = computed(() =>
captainConfigStore.getDefaultModelForFeature(props.featureKey)
);
const selectedModel = useFunctionGetter(
'captainConfig/getSelectedModelForFeature',
props.featureKey
const selectedModel = computed(() =>
captainConfigStore.getSelectedModelForFeature(props.featureKey)
);
const selectedModelId = ref(null);
@@ -1,78 +1,64 @@
import { defineStore } from 'pinia';
import CaptainConfigAPI from 'dashboard/api/captain/config';
const state = {
providers: {},
models: {},
features: {},
uiFlags: {
isFetching: false,
export const useCaptainConfigStore = defineStore('captainConfig', {
state: () => ({
providers: {},
models: {},
features: {},
uiFlags: {
isFetching: false,
},
}),
getters: {
getProviders: state => state.providers,
getModels: state => state.models,
getFeatures: state => state.features,
getUIFlags: state => state.uiFlags,
getModelsForFeature: state => featureKey => {
const feature = state.features[featureKey];
const models = feature?.models || [];
const providerOrder = { openai: 0, anthropic: 1, gemini: 2 };
return [...models].sort((a, b) => {
// Move coming_soon items to the end
if (a.coming_soon && !b.coming_soon) return 1;
if (!a.coming_soon && b.coming_soon) return -1;
// Sort by provider
const providerA = providerOrder[a.provider] ?? 999;
const providerB = providerOrder[b.provider] ?? 999;
if (providerA !== providerB) return providerA - providerB;
// Sort by credit_multiplier (highest first)
return (b.credit_multiplier || 0) - (a.credit_multiplier || 0);
});
},
getDefaultModelForFeature: state => featureKey => {
const feature = state.features[featureKey];
return feature?.default || null;
},
getSelectedModelForFeature: state => featureKey => {
const feature = state.features[featureKey];
return feature?.selected || feature?.default || null;
},
},
};
const getters = {
getProviders: $state => $state.providers,
getModels: $state => $state.models,
getFeatures: $state => $state.features,
getUIFlags: $state => $state.uiFlags,
getModelsForFeature: $state => featureKey => {
const feature = $state.features[featureKey];
const models = feature?.models || [];
const providerOrder = { openai: 0, anthropic: 1, gemini: 2 };
return [...models].sort((a, b) => {
// Move coming_soon items to the end
if (a.coming_soon && !b.coming_soon) return 1;
if (!a.coming_soon && b.coming_soon) return -1;
// Sort by provider
const providerA = providerOrder[a.provider] ?? 999;
const providerB = providerOrder[b.provider] ?? 999;
if (providerA !== providerB) return providerA - providerB;
// Sort by credit_multiplier (highest first)
return (b.credit_multiplier || 0) - (a.credit_multiplier || 0);
});
actions: {
async fetch() {
this.uiFlags.isFetching = true;
try {
const response = await CaptainConfigAPI.get();
this.providers = response.data.providers || {};
this.models = response.data.models || {};
this.features = response.data.features || {};
} catch (error) {
// Ignore error
} finally {
this.uiFlags.isFetching = false;
}
},
},
getDefaultModelForFeature: $state => featureKey => {
const feature = $state.features[featureKey];
return feature?.default || null;
},
getSelectedModelForFeature: $state => featureKey => {
const feature = $state.features[featureKey];
return feature?.selected || feature?.default || null;
},
};
const mutations = {
SET_UI_FLAG($state, data) {
$state.uiFlags = { ...$state.uiFlags, ...data };
},
SET_CONFIG($state, { providers, models, features }) {
$state.providers = providers || {};
$state.models = models || {};
$state.features = features || {};
},
};
const actions = {
async fetch({ commit }) {
commit('SET_UI_FLAG', { isFetching: true });
try {
const response = await CaptainConfigAPI.get();
commit('SET_CONFIG', response.data);
} catch (error) {
// Ignore error
} finally {
commit('SET_UI_FLAG', { isFetching: false });
}
},
};
export default {
namespaced: true,
state,
getters,
mutations,
actions,
};
});
-2
View File
@@ -58,7 +58,6 @@ import copilotMessages from './captain/copilotMessages';
import captainScenarios from './captain/scenarios';
import captainTools from './captain/tools';
import captainCustomTools from './captain/customTools';
import captainConfig from './captain/config';
const plugins = [];
@@ -122,7 +121,6 @@ export default createStore({
captainScenarios,
captainTools,
captainCustomTools,
captainConfig,
},
plugins,
});