feat(stage): hide BYOK providers for Steam builds via VITE_DISABLE_CUSTOM_PROVIDERS (#1908)

This commit is contained in:
Lulu
2026-06-10 16:36:31 +08:00
committed by GitHub
parent 027ad7436f
commit aa5223ad73
6 changed files with 75 additions and 49 deletions
@@ -4,6 +4,7 @@ import type { AiriExtension } from '@proj-airi/stage-ui/stores/modules/airi-card
import kebabcase from '@stdlib/string-base-kebabcase'
import { isCustomProvidersDisabled } from '@proj-airi/stage-shared'
import { DEFAULT_ARTISTRY_WIDGET_INSTRUCTION } from '@proj-airi/stage-ui/constants/prompts/artistry-instruction'
import { useDisplayModelsStore } from '@proj-airi/stage-ui/stores/display-models'
import { useAiriCardStore } from '@proj-airi/stage-ui/stores/modules/airi-card'
@@ -155,9 +156,13 @@ const speechVoiceOptions = computed(() => {
const artistryProviderOptions = computed(() => {
return [
{ value: 'none', label: 'None (Disabled)' },
{ value: 'replicate', label: 'Replicate' },
{ value: 'comfyui', label: 'ComfyUI' },
{ value: 'nanobanana', label: 'Nano Banana' },
...(isCustomProvidersDisabled()
? []
: [
{ value: 'replicate', label: 'Replicate' },
{ value: 'nanobanana', label: 'Nano Banana' },
]),
]
})
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { isCustomProvidersDisabled } from '@proj-airi/stage-shared'
import { RadioCardSimple } from '@proj-airi/stage-ui/components'
import { useArtistryStore } from '@proj-airi/stage-ui/stores/modules/artistry'
import { storeToRefs } from 'pinia'
@@ -26,20 +27,24 @@ const availableProviders = computed(() => [
icon: 'i-solar:monitor-camera-bold-duotone',
configRoute: '/settings/providers/artistry/comfyui',
},
{
id: 'replicate',
name: t('settings.pages.modules.artistry.providers.replicate.name'),
description: t('settings.pages.modules.artistry.providers.replicate.description'),
icon: 'i-solar:cloud-upload-bold-duotone',
configRoute: '/settings/providers/artistry/replicate',
},
{
id: 'nanobanana',
name: t('settings.pages.modules.artistry.providers.nanobanana.name'),
description: t('settings.pages.modules.artistry.providers.nanobanana.description'),
icon: 'i-solar:gallery-round-bold-duotone',
configRoute: '/settings/providers/artistry/nanobanana',
},
...(isCustomProvidersDisabled()
? []
: [
{
id: 'replicate',
name: t('settings.pages.modules.artistry.providers.replicate.name'),
description: t('settings.pages.modules.artistry.providers.replicate.description'),
icon: 'i-solar:cloud-upload-bold-duotone',
configRoute: '/settings/providers/artistry/replicate',
},
{
id: 'nanobanana',
name: t('settings.pages.modules.artistry.providers.nanobanana.name'),
description: t('settings.pages.modules.artistry.providers.nanobanana.description'),
icon: 'i-solar:gallery-round-bold-duotone',
configRoute: '/settings/providers/artistry/nanobanana',
},
]),
])
</script>
@@ -2,6 +2,7 @@
import type { ProviderSourceDeployment, ProviderSourcePricing } from '@proj-airi/stage-ui/libs/providers/source-metadata'
import type { Ref } from 'vue'
import { isCustomProvidersDisabled } from '@proj-airi/stage-shared'
import { IconStatusItem, RippleGrid } from '@proj-airi/stage-ui/components'
import { useAnalytics } from '@proj-airi/stage-ui/composables'
import { useRippleGridState } from '@proj-airi/stage-ui/composables/use-ripple-grid-state'
@@ -69,36 +70,40 @@ const allArtistryProvidersMetadata = computed<ProviderSourceCard[]>(() => {
beginnerRecommended: true,
iconImage: undefined,
},
{
id: 'replicate',
category: 'artistry',
icon: 'i-lobe-icons:replicate',
iconColor: 'i-lobe-icons:replicate-color',
name: 'Replicate',
localizedName: 'Replicate',
description: t('settings.pages.providers.categories.artistry.items.replicate.description'),
localizedDescription: t('settings.pages.providers.categories.artistry.items.replicate.description'),
configured: !!artistryStore.replicateApiKey,
to: '/settings/providers/artistry/replicate',
pricing: 'paid',
deployment: 'cloud',
iconImage: undefined,
},
{
id: 'nanobanana',
category: 'artistry',
icon: 'i-solar:gallery-round-bold-duotone',
iconColor: 'text-amber-500',
name: 'Nano Banana',
localizedName: 'Nano Banana',
description: t('settings.pages.providers.categories.artistry.items.nanobanana.description'),
localizedDescription: t('settings.pages.providers.categories.artistry.items.nanobanana.description'),
configured: !!artistryStore.nanobananaApiKey,
to: '/settings/providers/artistry/nanobanana',
pricing: 'free',
deployment: 'cloud',
iconImage: undefined,
},
...(isCustomProvidersDisabled()
? []
: [
{
id: 'replicate',
category: 'artistry',
icon: 'i-lobe-icons:replicate',
iconColor: 'i-lobe-icons:replicate-color',
name: 'Replicate',
localizedName: 'Replicate',
description: t('settings.pages.providers.categories.artistry.items.replicate.description'),
localizedDescription: t('settings.pages.providers.categories.artistry.items.replicate.description'),
configured: !!artistryStore.replicateApiKey,
to: '/settings/providers/artistry/replicate',
pricing: 'paid',
deployment: 'cloud',
iconImage: undefined,
},
{
id: 'nanobanana',
category: 'artistry',
icon: 'i-solar:gallery-round-bold-duotone',
iconColor: 'text-amber-500',
name: 'Nano Banana',
localizedName: 'Nano Banana',
description: t('settings.pages.providers.categories.artistry.items.nanobanana.description'),
localizedDescription: t('settings.pages.providers.categories.artistry.items.nanobanana.description'),
configured: !!artistryStore.nanobananaApiKey,
to: '/settings/providers/artistry/nanobanana',
pricing: 'free',
deployment: 'cloud',
iconImage: undefined,
},
]),
]
})
+4
View File
@@ -12,3 +12,7 @@ export function isEnvTruthy(value: string | undefined | null): boolean {
export function isFluxPurchaseDisabled(): boolean {
return isEnvTruthy(import.meta.env.VITE_DISABLE_FLUX_PURCHASE)
}
export function isCustomProvidersDisabled(): boolean {
return isEnvTruthy(import.meta.env.VITE_DISABLE_CUSTOM_PROVIDERS)
}
+9 -3
View File
@@ -24,7 +24,7 @@ import type { ProviderOnboardingField } from '../libs/providers/types'
import type { AliyunRealtimeSpeechExtraOptions } from './providers/aliyun/stream-transcription'
import { errorMessageFrom } from '@moeru/std'
import { isStageTamagotchi, isUrl } from '@proj-airi/stage-shared'
import { isCustomProvidersDisabled, isStageTamagotchi, isUrl } from '@proj-airi/stage-shared'
import { getCachedWebGPUCapabilities, isWebGPUSupported } from '@proj-airi/stage-shared/webgpu'
import { computedAsync, useIntervalFn, useLocalStorage } from '@vueuse/core'
import {
@@ -283,6 +283,7 @@ export const useProvidersStore = defineStore('providers', () => {
descriptionKey: 'settings.pages.providers.provider.speech-noop.description',
description: 'No speech output.',
icon: 'i-solar:volume-cross-bold-duotone',
requiresCredentials: false,
defaultOptions: () => ({}),
createProvider: async () => ({
speech: () => ({
@@ -857,6 +858,7 @@ export const useProvidersStore = defineStore('providers', () => {
descriptionKey: 'settings.pages.providers.provider.browser-web-speech-api.description',
description: 'Browser-native speech recognition. No API keys.',
icon: 'i-solar:microphone-bold-duotone',
requiresCredentials: false,
defaultOptions: () => ({
language: 'en-US',
continuous: true,
@@ -2033,6 +2035,7 @@ export const useProvidersStore = defineStore('providers', () => {
descriptionKey: 'settings.pages.providers.provider.kokoro-local.description',
description: 'Local text-to-speech using Kokoro-82M.',
icon: 'i-lobe-icons:speaker',
requiresCredentials: false,
defaultOptions: () => {
const capabilities = getCachedWebGPUCapabilities()
@@ -2744,8 +2747,11 @@ export const useProvidersStore = defineStore('providers', () => {
if (overrides[provider.id] === false)
continue
const p = getProviderMetadata(provider.id)
const isAvailableBy = p.isAvailableBy || (() => true)
const metadata = getProviderMetadata(provider.id)
if (isCustomProvidersDisabled() && metadata.requiresCredentials !== false)
continue
const isAvailableBy = metadata.isAvailableBy || (() => true)
const isAvailable = await isAvailableBy()
if (isAvailable) {
+1
View File
@@ -2,6 +2,7 @@
interface ImportMetaEnv {
readonly VITE_DISABLE_FLUX_PURCHASE?: string
readonly VITE_DISABLE_CUSTOM_PROVIDERS?: string
readonly VITE_ENABLE_POSTHOG?: string
readonly VITE_POSTHOG_PROJECT_KEY_WEB?: string
readonly VITE_POSTHOG_PROJECT_KEY_DESKTOP?: string