fix(stage-pages,stage-shared,stage-ui): rollback 3f82942 falsy fix

This commit is contained in:
Neko Ayaka
2026-04-22 14:14:02 +08:00
parent 32d2ebfe73
commit c7cf0c6a47
6 changed files with 11 additions and 69 deletions
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { SpeechProvider } from '@xsai-ext/providers/utils'
import { getCachedWebGPUCapabilities, hasNavigatorWebGPU } from '@proj-airi/stage-shared/webgpu'
import { getCachedWebGPUCapabilities } from '@proj-airi/stage-shared/webgpu'
import {
SpeechPlayground,
SpeechProviderSettings,
@@ -104,7 +104,7 @@ onMounted(async () => {
// NOTICE: Uses synchronous check for initial render. The cached result from
// detectWebGPU() is populated by the providers store during initialization.
const capabilities = getCachedWebGPUCapabilities()
hasWebGPU.value = capabilities?.supported ?? hasNavigatorWebGPU()
hasWebGPU.value = capabilities?.supported ?? (typeof navigator !== 'undefined' && !!navigator.gpu)
fp16Supported.value = capabilities?.fp16Supported ?? false
try {
@@ -7,14 +7,6 @@
import { check as gpuuCheck, isWebGPUSupported as gpuuIsSupported } from 'gpuu/webgpu'
interface NavigatorWebGPU {
requestAdapter: () => Promise<unknown>
}
interface NavigatorWithOptionalWebGPU extends Navigator {
gpu?: NavigatorWebGPU
}
export interface WebGPUCapabilities {
/** Whether WebGPU is available in this environment */
supported: boolean
@@ -29,50 +21,6 @@ export interface WebGPUCapabilities {
let cachedResult: WebGPUCapabilities | null = null
let pendingDetection: Promise<WebGPUCapabilities> | null = null
/**
* Returns the WebGPU navigator entry point when the current runtime exposes it.
*
* Use when:
* - browser or worker code needs guarded access to WebGPU
* - a caller only needs the `navigator.gpu` entry point, not a full capability probe
*
* Expects:
* - browser-like runtimes where `navigator` may be unavailable during SSR or tests
*
* Returns:
* - the WebGPU navigator entry point when available, otherwise `null`
*/
export function getNavigatorWebGPU(): NavigatorWebGPU | null {
// NOTICE:
// TypeScript's default DOM libs in this repo do not declare `Navigator.gpu`.
// Direct `navigator.gpu` access fails in consumers like `@proj-airi/ui-server-auth`
// and in `@proj-airi/stage-ui` worker compilation even though the runtime guard is valid.
// We centralize the structural cast here until the repo opts into WebGPU ambient types.
// Removal condition: remove this helper once the workspace TypeScript config includes
// WebGPU navigator typings everywhere that imports these modules.
if (typeof navigator === 'undefined' || !('gpu' in navigator))
return null
return (navigator as NavigatorWithOptionalWebGPU).gpu ?? null
}
/**
* Returns whether the current runtime exposes a WebGPU entry point on `navigator`.
*
* Use when:
* - synchronous code only needs a fast boolean feature probe
* - cached capability detection has not completed yet
*
* Expects:
* - browser-like runtimes where `navigator` may be unavailable
*
* Returns:
* - `true` when `navigator.gpu` is available, otherwise `false`
*/
export function hasNavigatorWebGPU(): boolean {
return getNavigatorWebGPU() != null
}
/**
* Detect WebGPU capabilities. The result is cached as a singleton
* after the first successful call -- safe to call repeatedly.
@@ -1,8 +1,6 @@
export {
detectWebGPU,
getCachedWebGPUCapabilities,
getNavigatorWebGPU,
hasNavigatorWebGPU,
isWebGPUSupported,
resetWebGPUCache,
} from './detect'
+2 -4
View File
@@ -31,7 +31,6 @@ import {
TextStreamer,
WhisperForConditionalGeneration,
} from '@huggingface/transformers'
import { getNavigatorWebGPU } from '@proj-airi/stage-shared/webgpu'
import { MODEL_IDS, MODEL_NAMES } from '../inference/constants'
import { classifyError, isRecoverable } from '../inference/protocol'
@@ -76,10 +75,9 @@ const MODEL_ID = MODEL_IDS.WHISPER
*/
async function detectWebGPUInWorker(): Promise<boolean> {
try {
const webgpu = getNavigatorWebGPU()
if (!webgpu)
if (typeof navigator === 'undefined' || !navigator.gpu)
return false
const adapter = await webgpu.requestAdapter()
const adapter = await navigator.gpu.requestAdapter()
return adapter != null
}
catch {
+5 -5
View File
@@ -21,7 +21,7 @@ import type {
import type { AliyunRealtimeSpeechExtraOptions } from './providers/aliyun/stream-transcription'
import { isStageTamagotchi, isUrl } from '@proj-airi/stage-shared'
import { getCachedWebGPUCapabilities, hasNavigatorWebGPU, isWebGPUSupported } from '@proj-airi/stage-shared/webgpu'
import { getCachedWebGPUCapabilities, isWebGPUSupported } from '@proj-airi/stage-shared/webgpu'
import { computedAsync, useIntervalFn, useLocalStorage } from '@vueuse/core'
import {
createOpenAI,
@@ -1715,7 +1715,7 @@ export const useProvidersStore = defineStore('providers', () => {
defaultOptions: () => {
const capabilities = getCachedWebGPUCapabilities()
const hasWebGPU = capabilities?.supported ?? hasNavigatorWebGPU()
const hasWebGPU = capabilities?.supported ?? (typeof navigator !== 'undefined' && !!navigator.gpu)
const fp16Supported = capabilities?.fp16Supported ?? false
const model = getDefaultKokoroModel(hasWebGPU, fp16Supported)
return {
@@ -1772,7 +1772,7 @@ export const useProvidersStore = defineStore('providers', () => {
capabilities: {
listModels: async (_config: Record<string, unknown>) => {
const caps = getCachedWebGPUCapabilities()
const hasWebGPU = caps?.supported ?? hasNavigatorWebGPU()
const hasWebGPU = caps?.supported ?? (typeof navigator !== 'undefined' && !!navigator.gpu)
const fp16Supported = caps?.fp16Supported ?? false
return kokoroModelsToModelInfo(hasWebGPU, t, fp16Supported)
},
@@ -1791,7 +1791,7 @@ export const useProvidersStore = defineStore('providers', () => {
// Validate platform requirements
if (modelDef.platform === 'webgpu') {
const hasWebGPU = getCachedWebGPUCapabilities()?.supported ?? hasNavigatorWebGPU()
const hasWebGPU = getCachedWebGPUCapabilities()?.supported ?? (typeof navigator !== 'undefined' && !!navigator.gpu)
if (!hasWebGPU) {
throw new Error('WebGPU is required for this model but is not available in your browser')
}
@@ -1835,7 +1835,7 @@ export const useProvidersStore = defineStore('providers', () => {
const modelDef = KOKORO_MODELS.find(m => m.id === modelId)
if (modelDef) {
if (modelDef.platform === 'webgpu') {
const hasWebGPU = getCachedWebGPUCapabilities()?.supported ?? hasNavigatorWebGPU()
const hasWebGPU = getCachedWebGPUCapabilities()?.supported ?? (typeof navigator !== 'undefined' && !!navigator.gpu)
if (!hasWebGPU) {
throw new Error('WebGPU is required for this model but is not available in your browser')
}
@@ -18,7 +18,6 @@ import type {
} from '../../libs/inference/protocol'
import { AutoModel, AutoProcessor, env, RawImage } from '@huggingface/transformers'
import { getNavigatorWebGPU } from '@proj-airi/stage-shared/webgpu'
import { MODEL_IDS, MODEL_NAMES } from '../../libs/inference/constants'
import { classifyError, isRecoverable } from '../../libs/inference/protocol'
@@ -81,10 +80,9 @@ function sendError(requestId: string, error: unknown, phase?: 'load' | 'inferenc
*/
async function detectWebGPUInWorker(): Promise<boolean> {
try {
const webgpu = getNavigatorWebGPU()
if (!webgpu)
if (typeof navigator === 'undefined' || !navigator.gpu)
return false
const adapter = await webgpu.requestAdapter()
const adapter = await navigator.gpu.requestAdapter()
return adapter != null
}
catch {