peregrine/web/src/stores/appConfig.ts
pyr0ball 49e3265132 feat(web): merge Vue SPA from feature/vue-spa; add ClassicUIButton + useFeatureFlag
- Import web/ directory (Vue 3 + Vite + UnoCSS SPA) from feature/vue-spa branch
- Add web/src/components/ClassicUIButton.vue: switch-back to Streamlit via
  cookie (prgn_ui=streamlit) + ?prgn_switch=streamlit query param bridge
- Add web/src/composables/useFeatureFlag.ts: reads prgn_demo_tier cookie for
  demo toolbar visual consistency (not an authoritative gate, see issue #8)
- Update .gitignore: add .superpowers/, pytest-output.txt, docs/superpowers/
2026-03-22 18:46:11 -07:00

42 lines
1.4 KiB
TypeScript

import { ref } from 'vue'
import { defineStore } from 'pinia'
import { useApiFetch } from '../composables/useApi'
export type Tier = 'free' | 'paid' | 'premium' | 'ultra'
export type InferenceProfile = 'remote' | 'cpu' | 'single-gpu' | 'dual-gpu'
export const useAppConfigStore = defineStore('appConfig', () => {
const isCloud = ref(false)
const isDevMode = ref(false)
const tier = ref<Tier>('free')
const contractedClient = ref(false)
const inferenceProfile = ref<InferenceProfile>('cpu')
const loaded = ref(false)
const devTierOverride = ref(localStorage.getItem('dev_tier_override') ?? '')
async function load() {
const { data } = await useApiFetch<{
isCloud: boolean; isDevMode: boolean; tier: Tier
contractedClient: boolean; inferenceProfile: InferenceProfile
}>('/api/config/app')
if (!data) return
isCloud.value = data.isCloud
isDevMode.value = data.isDevMode
tier.value = data.tier
contractedClient.value = data.contractedClient
inferenceProfile.value = data.inferenceProfile
loaded.value = true
}
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 }
})