feat(tamagotchi): generate preview image when import live2d model (#555)
* fix(tamagotchi): set min width of settings page, use grid model selector view * fix(tamagotchi): sort model by import time * feat(tamagotchi): generate preview image when import live2d model * fix(tamagotchi): don't show onboarding page when window open unless `/` * fix: thanks to gemini
This commit is contained in:
@@ -22,6 +22,7 @@ pub fn new_settings_window<R: Runtime>(
|
||||
)
|
||||
.title("Settings")
|
||||
.inner_size(550.0, 900.0)
|
||||
.min_inner_size(550.0, 900.0)
|
||||
.shadow(true)
|
||||
.transparent(false)
|
||||
.accept_first_mouse(true);
|
||||
|
||||
@@ -11,7 +11,6 @@ import { computed, onMounted, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterView } from 'vue-router'
|
||||
|
||||
import { commands } from './bindings/tauri-plugins/window-router-link'
|
||||
import { useAppRuntime } from './composables/runtime'
|
||||
import { useTauriEvent } from './composables/tauri'
|
||||
import { useWindowMode } from './stores/window-controls'
|
||||
@@ -22,7 +21,6 @@ const displayModelsStore = useDisplayModelsStore()
|
||||
const settingsStore = useSettings()
|
||||
const { language, themeColorsHue, themeColorsHueDynamic, allowVisibleOnAllWorkspaces } = storeToRefs(settingsStore)
|
||||
const onboardingStore = useOnboardingStore()
|
||||
const { shouldShowSetup } = storeToRefs(onboardingStore)
|
||||
|
||||
const mcpStore = useMcpStore()
|
||||
const { listen } = useTauriEvent<AiriTamagotchiEvents>()
|
||||
@@ -48,12 +46,6 @@ watch(themeColorsHueDynamic, () => {
|
||||
document.documentElement.classList.toggle('dynamic-hue', themeColorsHueDynamic.value)
|
||||
}, { immediate: true })
|
||||
|
||||
watch(shouldShowSetup, () => {
|
||||
if (shouldShowSetup.value) {
|
||||
commands.go('/onboarding', 'onboarding')
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
listen('mcp_plugin_destroyed', () => {
|
||||
mcpStore.connected = false
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { AiriTamagotchiEvents, Point } from '../composables/tauri'
|
||||
import { WidgetStage } from '@proj-airi/stage-ui/components/scenes'
|
||||
import { useLive2d } from '@proj-airi/stage-ui/stores/live2d'
|
||||
import { useMcpStore } from '@proj-airi/stage-ui/stores/mcp'
|
||||
import { useOnboardingStore } from '@proj-airi/stage-ui/stores/onboarding'
|
||||
import { connectServer } from '@proj-airi/tauri-plugin-mcp'
|
||||
import { watchThrottled } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
@@ -12,6 +13,7 @@ import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import ResourceStatusIsland from '../components/Widgets/ResourceStatusIsland/index.vue'
|
||||
|
||||
import { commands as passThroughCommands } from '../bindings/tauri-plugins/window-pass-through-on-hover'
|
||||
import { commands } from '../bindings/tauri-plugins/window-router-link'
|
||||
import { useTauriCore, useTauriEvent, useTauriWindow } from '../composables/tauri'
|
||||
import { useTauriGlobalShortcuts } from '../composables/tauri-global-shortcuts'
|
||||
import { useRdevMouse } from '../composables/use-rdev-mouse'
|
||||
@@ -20,6 +22,9 @@ import { useWindowStore } from '../stores/window'
|
||||
import { useWindowControlStore } from '../stores/window-controls'
|
||||
import { WindowControlMode } from '../types/window-controls'
|
||||
|
||||
const onboardingStore = useOnboardingStore()
|
||||
const { shouldShowSetup } = storeToRefs(onboardingStore)
|
||||
|
||||
useTauriGlobalShortcuts()
|
||||
const windowControlStore = useWindowControlStore()
|
||||
const resourcesStore = useResourcesStore()
|
||||
@@ -44,6 +49,12 @@ const isPassingThrough = ref(false)
|
||||
const isOverUI = ref(false)
|
||||
const isFirstTime = ref(true)
|
||||
|
||||
watch(shouldShowSetup, () => {
|
||||
if (shouldShowSetup.value) {
|
||||
commands.go('/onboarding', 'onboarding')
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
watchThrottled([mouseX, mouseY], async ([x, y]) => {
|
||||
const canvas = widgetStageRef.value?.canvasElement()
|
||||
if (!canvas) {
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"@date-fns/utc": "^2.1.1",
|
||||
"@formkit/auto-animate": "^0.8.4",
|
||||
"@huggingface/transformers": "^3.7.2",
|
||||
"@lemonneko/crop-empty-pixels": "0.1.1",
|
||||
"@pixi/app": "^6.5.10",
|
||||
"@pixi/constants": "^6.5.10",
|
||||
"@pixi/core": "^6.5.10",
|
||||
|
||||
+19
-26
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import type { DisplayModel } from '../../../../stores/display-models'
|
||||
|
||||
import { BasicInputFile } from '@proj-airi/ui'
|
||||
import { useFileDialog } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { DropdownMenuContent, DropdownMenuItem, DropdownMenuPortal, DropdownMenuRoot, DropdownMenuTrigger, EditableArea, EditableEditTrigger, EditableInput, EditablePreview, EditableRoot, EditableSubmitTrigger } from 'reka-ui'
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import Button from '../../../Misc/Button.vue'
|
||||
|
||||
@@ -21,11 +21,9 @@ function handleRemoveModel(model: DisplayModel) {
|
||||
}
|
||||
|
||||
const highlightDisplayModelCard = ref<string | undefined>(selectedModel.value?.id)
|
||||
const live2dFiles = ref<File[]>([])
|
||||
const vrmFiles = ref<File[]>([])
|
||||
|
||||
function handleAddLive2DModel(file: File[]) {
|
||||
if (file.length === 0)
|
||||
function handleAddLive2DModel(file: FileList | null) {
|
||||
if (file === null || file.length === 0)
|
||||
return
|
||||
if (!file[0].name.endsWith('.zip'))
|
||||
return
|
||||
@@ -43,12 +41,8 @@ function handleMobilePick() {
|
||||
emits('close', undefined)
|
||||
}
|
||||
|
||||
watch(live2dFiles, (newFiles) => {
|
||||
handleAddLive2DModel(newFiles)
|
||||
}, { deep: true })
|
||||
|
||||
function handleAddVRMModel(file: File[]) {
|
||||
if (file.length === 0)
|
||||
function handleAddVRMModel(file: FileList | null) {
|
||||
if (file === null || file.length === 0)
|
||||
return
|
||||
if (!file[0].name.endsWith('.vrm'))
|
||||
return
|
||||
@@ -65,9 +59,11 @@ const mapFormatRenderer: Record<DisplayModelFormat, string> = {
|
||||
[DisplayModelFormat.PMD]: 'MMD',
|
||||
}
|
||||
|
||||
watch(vrmFiles, (newFiles) => {
|
||||
handleAddVRMModel(newFiles)
|
||||
}, { deep: true })
|
||||
const live2dDialog = useFileDialog({ accept: '.zip', multiple: false, reset: true })
|
||||
const vrmDialog = useFileDialog({ accept: '.vrm', multiple: false, reset: true })
|
||||
|
||||
live2dDialog.onChange(handleAddLive2DModel)
|
||||
vrmDialog.onChange(handleAddVRMModel)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -100,18 +96,15 @@ watch(vrmFiles, (newFiles) => {
|
||||
<DropdownMenuItem
|
||||
class="data-[disabled]:text-mauve8 relative flex cursor-pointer select-none items-center rounded-md px-3 py-2 text-base leading-none outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-primary-100/20 sm:text-sm data-[highlighted]:text-primary-200"
|
||||
transition="colors duration-200 ease-in-out"
|
||||
@click="live2dDialog.open()"
|
||||
>
|
||||
<BasicInputFile v-model="live2dFiles" accept=".zip">
|
||||
Live2D
|
||||
</BasicInputFile>
|
||||
Live2D
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
class="data-[disabled]:text-mauve8 relative flex cursor-pointer select-none items-center rounded-md px-3 py-2 text-base leading-none outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-primary-100/20 sm:text-sm data-[highlighted]:text-primary-200"
|
||||
transition="colors duration-200 ease-in-out"
|
||||
transition="colors duration-200 ease-in-out" @click="vrmDialog.open()"
|
||||
>
|
||||
<BasicInputFile v-model="vrmFiles" accept=".vrm">
|
||||
VRM
|
||||
</BasicInputFile>
|
||||
VRM
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenuPortal>
|
||||
@@ -121,8 +114,8 @@ watch(vrmFiles, (newFiles) => {
|
||||
<div v-if="displayModelsFromIndexedDBLoading">
|
||||
Loading display models...
|
||||
</div>
|
||||
<div class="flex-1 md:flex-none" h-full w-full>
|
||||
<div class="flex flex-1 flex-row gap-2 overflow-x-scroll md:grid lg:grid-cols-2 md:grid-cols-2 lg:max-h-80dvh md:overflow-y-scroll">
|
||||
<div class="flex-1 md:flex-none" h-full w-full overflow-x-hidden overflow-y-scroll>
|
||||
<div class="grid grid-cols-2 gap-2 lg:max-h-80dvh">
|
||||
<div
|
||||
v-for="(model) of displayModels"
|
||||
:key="model.id"
|
||||
@@ -165,11 +158,11 @@ watch(vrmFiles, (newFiles) => {
|
||||
</DropdownMenuRoot>
|
||||
</div>
|
||||
<div
|
||||
class="min-w-65 lg:min-h-60"
|
||||
class="min-w-60 lg:min-h-60"
|
||||
aspect="12/16"
|
||||
px-1 py-2
|
||||
>
|
||||
<img v-if="model.previewImage" :src="model.previewImage" h-full w-full rounded-lg object-cover :class="[highlightDisplayModelCard && highlightDisplayModelCard === model.id ? 'ring-3 ring-primary-400' : 'ring-0 ring-transparent']" transition="all duration-200 ease-in-out">
|
||||
<img v-if="model.previewImage" :src="model.previewImage" h-full w-full rounded-lg object-contain :class="[highlightDisplayModelCard && highlightDisplayModelCard === model.id ? 'ring-3 ring-primary-400' : 'ring-0 ring-transparent']" transition="all duration-200 ease-in-out">
|
||||
<div v-else bg="neutral-100 dark:neutral-900" relative h-full w-full flex flex-col items-center justify-center gap-2 overflow-hidden rounded-lg :class="[highlightDisplayModelCard && highlightDisplayModelCard === model.id ? 'ring-3 ring-primary-400' : 'ring-0 ring-transparent']" transition="all duration-200 ease-in-out">
|
||||
<div i-solar:question-square-bold-duotone text-4xl opacity-75 />
|
||||
<div translate-y="100%" absolute top-0 flex flex-col translate-x--7 rotate-45 scale-250 gap-0 opacity-5>
|
||||
|
||||
@@ -215,7 +215,7 @@ async function loadModel() {
|
||||
|
||||
hookedUpdate?.call(this, model, now)
|
||||
// Possibility 1: Only update eye focus when the model is idle
|
||||
// Possibility 2: For models having no motion groups, currentGroup will be undefined while groups can be { idle: ... }
|
||||
// Possibility 2: For models having no mo`ti`on groups, currentGroup will be undefined while groups can be { idle: ... }
|
||||
if (!motionManager.state.currentGroup || motionManager.state.currentGroup === motionManager.groups.idle) {
|
||||
idleEyeFocus.update(internalModel, now)
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import cropImg from '@lemonneko/crop-empty-pixels'
|
||||
import localforage from 'localforage'
|
||||
|
||||
import { Application } from '@pixi/app'
|
||||
import { extensions } from '@pixi/extensions'
|
||||
import { Ticker, TickerPlugin } from '@pixi/ticker'
|
||||
import { until } from '@vueuse/core'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { defineStore } from 'pinia'
|
||||
import { Live2DFactory, Live2DModel } from 'pixi-live2d-display/cubism4'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import '../utils/live2d-zip-loader'
|
||||
|
||||
export enum DisplayModelFormat {
|
||||
Live2dZip = 'live2d-zip',
|
||||
Live2dDirectory = 'live2d-directory',
|
||||
@@ -67,7 +74,7 @@ export const useDisplayModelsStore = defineStore('display-models', () => {
|
||||
console.error(err)
|
||||
}
|
||||
|
||||
displayModels.value = models
|
||||
displayModels.value = models.sort((a, b) => b.importedAt - a.importedAt)
|
||||
displayModelsFromIndexedDBLoading.value = false
|
||||
}
|
||||
|
||||
@@ -82,10 +89,84 @@ export const useDisplayModelsStore = defineStore('display-models', () => {
|
||||
return displayModelsPresets.find(model => model.id === id)
|
||||
}
|
||||
|
||||
async function loadLive2DModelPreview(file: File) {
|
||||
Live2DModel.registerTicker(Ticker)
|
||||
extensions.add(TickerPlugin)
|
||||
|
||||
const offscreenCanvas = document.createElement('canvas')
|
||||
offscreenCanvas.width = 720
|
||||
offscreenCanvas.height = 1280
|
||||
offscreenCanvas.style.position = 'absolute'
|
||||
offscreenCanvas.style.top = '0'
|
||||
offscreenCanvas.style.left = '0'
|
||||
offscreenCanvas.style.objectFit = 'cover'
|
||||
offscreenCanvas.style.display = 'block'
|
||||
offscreenCanvas.style.zIndex = '10000000000'
|
||||
offscreenCanvas.style.opacity = '0'
|
||||
document.body.appendChild(offscreenCanvas)
|
||||
|
||||
const app = new Application({
|
||||
view: offscreenCanvas,
|
||||
// Ensure the drawing buffer persists so toDataURL() can read pixels
|
||||
preserveDrawingBuffer: true,
|
||||
backgroundAlpha: 0,
|
||||
resizeTo: window,
|
||||
})
|
||||
|
||||
const modelInstance = new Live2DModel()
|
||||
const objUrl = URL.createObjectURL(file)
|
||||
const res = await fetch(objUrl)
|
||||
const blob = await res.blob()
|
||||
|
||||
try {
|
||||
await Live2DFactory.setupLive2DModel(modelInstance, [new File([blob], file.name)], { autoInteract: false })
|
||||
}
|
||||
catch (error) {
|
||||
app.destroy()
|
||||
document.body.removeChild(offscreenCanvas)
|
||||
URL.revokeObjectURL(objUrl)
|
||||
console.error(error)
|
||||
return
|
||||
}
|
||||
|
||||
app.stage.addChild(modelInstance)
|
||||
|
||||
// transforms
|
||||
modelInstance.x = 275
|
||||
modelInstance.y = 450
|
||||
modelInstance.width = offscreenCanvas.width
|
||||
modelInstance.height = offscreenCanvas.height
|
||||
modelInstance.scale.set(0.1, 0.1)
|
||||
modelInstance.anchor.set(0.5, 0.5)
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
// Force a render to ensure the latest frame is in the drawing buffer
|
||||
app.renderer.render(app.stage)
|
||||
|
||||
const croppedCanvas = cropImg(offscreenCanvas)
|
||||
const dataUrl = croppedCanvas.toDataURL()
|
||||
|
||||
app.destroy()
|
||||
document.body.removeChild(offscreenCanvas)
|
||||
URL.revokeObjectURL(objUrl)
|
||||
|
||||
// return dataUrl
|
||||
return dataUrl
|
||||
}
|
||||
|
||||
async function addDisplayModel(format: DisplayModelFormat, file: File) {
|
||||
await until(displayModelsFromIndexedDBLoading).toBe(false)
|
||||
const newDisplayModel: DisplayModelFile = { id: `display-model-${nanoid()}`, format, type: 'file', file, name: file.name, importedAt: Date.now() }
|
||||
displayModels.value.push(newDisplayModel)
|
||||
|
||||
if (format === DisplayModelFormat.Live2dZip) {
|
||||
const previewImage = await loadLive2DModelPreview(file)
|
||||
if (!previewImage)
|
||||
return
|
||||
|
||||
newDisplayModel.previewImage = previewImage
|
||||
}
|
||||
|
||||
displayModels.value.unshift(newDisplayModel)
|
||||
|
||||
localforage.setItem<DisplayModelFile>(newDisplayModel.id, newDisplayModel)
|
||||
.catch(err => console.error(err))
|
||||
|
||||
Generated
+26
-18
@@ -38,7 +38,7 @@ catalogs:
|
||||
version: 0.4.0-beta.2
|
||||
'@xsai/shared':
|
||||
specifier: ^0.4.0-beta.2
|
||||
version: 0.4.0-beta.2
|
||||
version: 0.4.0-beta.3
|
||||
'@xsai/shared-chat':
|
||||
specifier: ^0.4.0-beta.2
|
||||
version: 0.4.0-beta.2
|
||||
@@ -429,7 +429,7 @@ importers:
|
||||
version: 0.4.0-beta.2
|
||||
'@xsai/shared':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.2
|
||||
version: 0.4.0-beta.3
|
||||
'@xsai/shared-chat':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.2
|
||||
@@ -781,7 +781,7 @@ importers:
|
||||
version: 0.4.0-beta.2
|
||||
'@xsai/shared':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.2
|
||||
version: 0.4.0-beta.3
|
||||
'@xsai/shared-chat':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.2
|
||||
@@ -1251,6 +1251,9 @@ importers:
|
||||
'@huggingface/transformers':
|
||||
specifier: ^3.7.2
|
||||
version: 3.7.2
|
||||
'@lemonneko/crop-empty-pixels':
|
||||
specifier: 0.1.1
|
||||
version: 0.1.1
|
||||
'@pixi/app':
|
||||
specifier: ^6.5.10
|
||||
version: 6.5.10(@pixi/core@6.5.10(@pixi/constants@6.5.10)(@pixi/extensions@6.5.10)(@pixi/math@6.5.10)(@pixi/runner@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))(@pixi/ticker@6.5.10(@pixi/extensions@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10)))(@pixi/utils@6.5.10(@pixi/constants@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))))(@pixi/display@6.5.10(@pixi/constants@6.5.10)(@pixi/math@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))(@pixi/utils@6.5.10(@pixi/constants@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10))))(@pixi/math@6.5.10)(@pixi/utils@6.5.10(@pixi/constants@6.5.10)(@pixi/settings@6.5.10(@pixi/constants@6.5.10)))
|
||||
@@ -1382,7 +1385,7 @@ importers:
|
||||
version: 0.4.0-beta.2
|
||||
'@xsai/shared':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.2
|
||||
version: 0.4.0-beta.3
|
||||
'@xsai/shared-chat':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.2
|
||||
@@ -4275,6 +4278,9 @@ packages:
|
||||
'@kwsites/promise-deferred@1.1.1':
|
||||
resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==}
|
||||
|
||||
'@lemonneko/crop-empty-pixels@0.1.1':
|
||||
resolution: {integrity: sha512-4Mp6gBN3XbXw5OXyN0rF5bhWWISmrU4DRCGUWDnyWWFCERE2SZwvv2w4hoPhg804BcI0wXLPk5lHf/v15AFXSA==}
|
||||
|
||||
'@lezer/common@1.2.3':
|
||||
resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==}
|
||||
|
||||
@@ -7493,8 +7499,8 @@ packages:
|
||||
'@xsai/shared@0.3.5':
|
||||
resolution: {integrity: sha512-gxWH+9UjhXgqqKeU/o9UteC/ih1FzxEEsmPojImd/jvq4j/wtIg4aP3dCFnu+EhCT/MRQ38dkBSra99iY9cC3w==}
|
||||
|
||||
'@xsai/shared@0.4.0-beta.2':
|
||||
resolution: {integrity: sha512-nKdT+/gon1FxkEqv1iKfS2QRWnmYY/2o7Wl+Bcfot45qACE0sK9E4nw2BeLI/MeRYD6w7bTLP2J2U8373aHdYA==}
|
||||
'@xsai/shared@0.4.0-beta.3':
|
||||
resolution: {integrity: sha512-IOqe0CzSdRbaj5vgfL3pAjzOk/u2NCm0RrcsYgvvRc6VyTIPGsgAUuDpWXD+OfWEtCK4t24Q6qhjLkhgo2S9rA==}
|
||||
|
||||
'@xsai/stream-text@0.3.5':
|
||||
resolution: {integrity: sha512-XUyM3/jo9FulWoqmQU6vvHFOoRZzr3rcsTGm0MY8hUXg9HJl91N0voQGb6R5AMlo5XgoSbO3GMFzJ26AVxmRMg==}
|
||||
@@ -17425,6 +17431,8 @@ snapshots:
|
||||
|
||||
'@kwsites/promise-deferred@1.1.1': {}
|
||||
|
||||
'@lemonneko/crop-empty-pixels@0.1.1': {}
|
||||
|
||||
'@lezer/common@1.2.3': {}
|
||||
|
||||
'@lezer/highlight@1.2.1':
|
||||
@@ -21427,16 +21435,16 @@ snapshots:
|
||||
'@xsai-ext/providers-cloud@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai-ext/shared-providers': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai-ext/providers-local@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai-ext/shared-providers': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai-ext/shared-providers@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai-ext/shared-providers@0.3.5':
|
||||
dependencies:
|
||||
@@ -21444,7 +21452,7 @@ snapshots:
|
||||
|
||||
'@xsai-ext/shared-providers@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai-transformers/embed@0.0.7(web-worker@1.5.0)':
|
||||
dependencies:
|
||||
@@ -21471,11 +21479,11 @@ snapshots:
|
||||
|
||||
'@xsai/embed@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai/generate-speech@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai/generate-text@0.3.5':
|
||||
dependencies:
|
||||
@@ -21484,16 +21492,16 @@ snapshots:
|
||||
|
||||
'@xsai/generate-text@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
'@xsai/shared-chat': 0.4.0-beta.2
|
||||
|
||||
'@xsai/generate-transcription@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai/model@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai/shared-chat@0.3.5':
|
||||
dependencies:
|
||||
@@ -21501,13 +21509,13 @@ snapshots:
|
||||
|
||||
'@xsai/shared-chat@0.4.0-beta.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
|
||||
'@xsai/shared@0.2.2': {}
|
||||
|
||||
'@xsai/shared@0.3.5': {}
|
||||
|
||||
'@xsai/shared@0.4.0-beta.2': {}
|
||||
'@xsai/shared@0.4.0-beta.3': {}
|
||||
|
||||
'@xsai/stream-text@0.3.5':
|
||||
dependencies:
|
||||
@@ -21519,7 +21527,7 @@ snapshots:
|
||||
|
||||
'@xsai/tool@0.4.0-beta.2(zod-to-json-schema@3.24.6(zod@4.1.5))(zod@4.1.5)':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.4.0-beta.2
|
||||
'@xsai/shared': 0.4.0-beta.3
|
||||
'@xsai/shared-chat': 0.4.0-beta.2
|
||||
xsschema: 0.4.0-beta.2(@valibot/to-json-schema@1.0.0-rc.0(valibot@1.0.0-beta.9(typescript@5.9.2)))(zod-to-json-schema@3.24.6(zod@4.1.5))(zod@4.1.5)
|
||||
transitivePeerDependencies:
|
||||
|
||||
Reference in New Issue
Block a user