From 32a83d6ff4b10215b0217be4210f17b04bf36d04 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sat, 21 Mar 2026 02:23:10 -0700 Subject: [PATCH] fix(settings): async guard awaits config load, reactive devTierOverride, validate APP_TIER --- dev-api.py | 4 +++- web/src/router/index.ts | 5 +++-- web/src/stores/appConfig.ts | 13 ++++++++++++- web/src/views/settings/SettingsView.test.ts | 9 +++++++++ web/src/views/settings/SettingsView.vue | 2 +- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/dev-api.py b/dev-api.py index 77d0aca..60f98e3 100644 --- a/dev-api.py +++ b/dev-api.py @@ -875,10 +875,12 @@ def get_app_config(): import os profile = os.environ.get("INFERENCE_PROFILE", "cpu") valid_profiles = {"remote", "cpu", "single-gpu", "dual-gpu"} + valid_tiers = {"free", "paid", "premium", "ultra"} + raw_tier = os.environ.get("APP_TIER", "free") return { "isCloud": os.environ.get("CLOUD_MODE", "").lower() in ("1", "true"), "isDevMode": os.environ.get("DEV_MODE", "").lower() in ("1", "true"), - "tier": os.environ.get("APP_TIER", "free"), + "tier": raw_tier if raw_tier in valid_tiers else "free", "contractedClient": os.environ.get("CONTRACTED_CLIENT", "").lower() in ("1", "true"), "inferenceProfile": profile if profile in valid_profiles else "cpu", } diff --git a/web/src/router/index.ts b/web/src/router/index.ts index 46a3b27..585c22c 100644 --- a/web/src/router/index.ts +++ b/web/src/router/index.ts @@ -35,11 +35,12 @@ export const router = createRouter({ ], }) -router.beforeEach((to, _from, next) => { +router.beforeEach(async (to, _from, next) => { if (!to.path.startsWith('/settings/')) return next() const config = useAppConfigStore() + if (!config.loaded) await config.load() const tab = to.path.replace('/settings/', '') - const devOverride = localStorage.getItem('dev_tier_override') + const devOverride = config.devTierOverride const gpuProfiles = ['single-gpu', 'dual-gpu'] if (tab === 'system' && config.isCloud) return next('/settings/my-profile') diff --git a/web/src/stores/appConfig.ts b/web/src/stores/appConfig.ts index 9042f84..6519134 100644 --- a/web/src/stores/appConfig.ts +++ b/web/src/stores/appConfig.ts @@ -12,6 +12,7 @@ export const useAppConfigStore = defineStore('appConfig', () => { const contractedClient = ref(false) const inferenceProfile = ref('cpu') const loaded = ref(false) + const devTierOverride = ref(localStorage.getItem('dev_tier_override') ?? '') async function load() { const { data } = await useApiFetch<{ @@ -27,5 +28,15 @@ export const useAppConfigStore = defineStore('appConfig', () => { loaded.value = true } - return { isCloud, isDevMode, tier, contractedClient, inferenceProfile, loaded, load } + function setDevTierOverride(value: string | null) { + if (value) { + localStorage.setItem('dev_tier_override', value) + devTierOverride.value = value + } else { + localStorage.removeItem('dev_tier_override') + devTierOverride.value = '' + } + } + + return { isCloud, isDevMode, tier, contractedClient, inferenceProfile, loaded, load, devTierOverride, setDevTierOverride } }) diff --git a/web/src/views/settings/SettingsView.test.ts b/web/src/views/settings/SettingsView.test.ts index 7507b90..2317007 100644 --- a/web/src/views/settings/SettingsView.test.ts +++ b/web/src/views/settings/SettingsView.test.ts @@ -33,4 +33,13 @@ describe('SettingsView sidebar', () => { const wrapper = mount(SettingsView, { global: { plugins: [makeRouter()] } }) expect(wrapper.find('[data-testid="nav-developer"]').exists()).toBe(false) }) + + it('shows Developer when devTierOverride is set in store', () => { + const store = useAppConfigStore() + store.isDevMode = false + store.setDevTierOverride('premium') + const wrapper = mount(SettingsView, { global: { plugins: [makeRouter()] } }) + expect(wrapper.find('[data-testid="nav-developer"]').exists()).toBe(true) + store.setDevTierOverride(null) // cleanup + }) }) diff --git a/web/src/views/settings/SettingsView.vue b/web/src/views/settings/SettingsView.vue index 5603347..25cbf9d 100644 --- a/web/src/views/settings/SettingsView.vue +++ b/web/src/views/settings/SettingsView.vue @@ -38,7 +38,7 @@ import { computed } from 'vue' import { useAppConfigStore } from '../../stores/appConfig' const config = useAppConfigStore() -const devOverride = computed(() => !!localStorage.getItem('dev_tier_override')) +const devOverride = computed(() => !!config.devTierOverride) const gpuProfiles = ['single-gpu', 'dual-gpu'] const showSystem = computed(() => !config.isCloud)