feat:(stage-ui) Modify settings card (#1027)
This commit is contained in:
@@ -1 +0,0 @@
|
||||
sha256-69tCpJaxRUnyR9CrHlmWJWEWLDpYzyzska7ui9++QoY=
|
||||
|
||||
@@ -91,6 +91,8 @@ pages:
|
||||
card_not_found: Card not found
|
||||
character: Character
|
||||
close: Close
|
||||
chat:
|
||||
provider: Chat / Provider
|
||||
consciousness:
|
||||
model: Consciousness / Model
|
||||
created_by: created by
|
||||
@@ -119,6 +121,9 @@ pages:
|
||||
scenario: You recently woke up and forgot everything about your previous life.
|
||||
systemprompt: You will receive messages, answer to them like a real human.
|
||||
posthistoryinstructions: Remember to imitate an human.
|
||||
modules_info: Configure modules for this character card. If not set, default module configuration will be used.
|
||||
use_default: Use default
|
||||
use_default_not_configured: Use default (not configured)
|
||||
fields_info:
|
||||
subtitle: >-
|
||||
You can put here some details about the character you are creating,
|
||||
@@ -139,6 +144,8 @@ pages:
|
||||
version: >-
|
||||
Card version, you should increase this if you are making changes from
|
||||
a previous card.
|
||||
consciousness_model: Select the consciousness model (AI model) for this character.
|
||||
speech_model: Select the speech synthesis model and voice for this character.
|
||||
errors:
|
||||
name: Name should be valid or non-empty.
|
||||
version: 'Error: Invalid version number !'
|
||||
@@ -148,6 +155,7 @@ pages:
|
||||
systemprompt: 'Error: Please, provide a system prompt.'
|
||||
posthistoryinstructions: 'Error: Post history prompt is required.'
|
||||
modules: Modules
|
||||
|
||||
name_asc: Name (A-Z)
|
||||
name_desc: Name (Z-A)
|
||||
no_cards: No cards yet. Click the button above to upload one!
|
||||
@@ -159,6 +167,7 @@ pages:
|
||||
search: Search cards...
|
||||
sort_by: Sort by
|
||||
speech:
|
||||
provider: Speech / Provider
|
||||
model: Speech / Model
|
||||
voice: Speech / Voice
|
||||
systemprompt: System Prompt
|
||||
@@ -305,7 +314,7 @@ pages:
|
||||
search_results: Found {count} of {total} models
|
||||
show_less: Show less
|
||||
show_more: Show more
|
||||
subtitle: Select a model from the provider
|
||||
subtitle: Select a default model from the provider
|
||||
title: Model
|
||||
title: Consciousness
|
||||
description: Thinking, vision, speech synthesis, gaming, etc.
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: Encontrados {count} de {total} modelos
|
||||
show_less: Mostrar menos
|
||||
show_more: Mostrar más
|
||||
subtitle: Selecciona un modelo del proveedor
|
||||
subtitle: Seleccionar un modelo predeterminado del proveedor
|
||||
title: Modelo
|
||||
title: Consciencia
|
||||
description: Pensamiento, visión, síntesis de voz, juegos, etc.
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: '{count} modèles trouvés sur {total}'
|
||||
show_less: Afficher moins
|
||||
show_more: Afficher plus
|
||||
subtitle: Sélectionnez un modèle du fournisseur
|
||||
subtitle: Sélectionner un modèle par défaut du fournisseur
|
||||
title: Modèle
|
||||
title: Conscience
|
||||
description: Synthèse, vision, parole, jeux, etc.
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: 結果{total}個中{count}個のモデルが見つかりました
|
||||
show_less: 表示を減らす
|
||||
show_more: もっと表示
|
||||
subtitle: プロバイダーからモデルを選択
|
||||
subtitle: プロバイダーからデフォルトモデルを選択
|
||||
title: モデル
|
||||
title: 意識
|
||||
description: 思考、視覚、音声合成、ゲームなど。
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: Found {count} of {total} models
|
||||
show_less: Show less
|
||||
show_more: Show more
|
||||
subtitle: Select a model from the provider
|
||||
subtitle: 제공업체에서 기본 모델 선택
|
||||
title: Model
|
||||
title: Consciousness
|
||||
description: Thinking, vision, speech synthesis, gaming, etc.
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: Найдено {count} из {total} моделей
|
||||
show_less: Показать меньше
|
||||
show_more: Показать больше
|
||||
subtitle: Выберите модель у провайдера
|
||||
subtitle: Выберите модель по умолчанию у провайдера
|
||||
title: Модель
|
||||
title: Сознание
|
||||
description: Мыслительный процесс, зрение, синтез речи, игры и т. д.
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: Tìm thấy {count}/{total} mô hình
|
||||
show_less: Ẩn bớt
|
||||
show_more: Hiện thêm
|
||||
subtitle: Chọn mô hình từ nhà cung cấp
|
||||
subtitle: Chọn mô hình mặc định từ nhà cung cấp
|
||||
title: Mô hình
|
||||
title: Ý thức
|
||||
description: Tư duy, thị giác, tổng hợp giọng nói, chơi game, v.v.
|
||||
|
||||
@@ -88,6 +88,8 @@ pages:
|
||||
card_not_found: 未找到角色卡
|
||||
character: 角色设定
|
||||
close: 关闭
|
||||
chat:
|
||||
provider: 聊天 / 提供商
|
||||
consciousness:
|
||||
model: 意识 / 模型
|
||||
created_by: 创建者
|
||||
@@ -116,6 +118,9 @@ pages:
|
||||
scenario: 你最近醒来,忘记了之前的所有生活。
|
||||
systemprompt: 你将收到消息,请像真实人类一样回复。
|
||||
posthistoryinstructions: 记得模仿人类的行为。
|
||||
modules_info: 配置此角色卡使用的模块。如果不设置,将使用默认模块配置。
|
||||
use_default: 使用默认
|
||||
use_default_not_configured: 使用默认 (当前未配置)
|
||||
fields_info:
|
||||
subtitle: >-
|
||||
您可以在这里填写有关您正在创建的角色的一些详细信息,解释他的背景和情境,以及应该如何回应您的互动。
|
||||
@@ -127,11 +132,13 @@ pages:
|
||||
在这里描述您的角色的个性。例如:害羞?好奇?其他?
|
||||
scenario: 周围环境是怎样的?当前的情境是什么?
|
||||
greetings_field: 问候语
|
||||
greetings: 您的角色应该如何说“你好”?
|
||||
greetings: 您的角色应该如何说"你好"?
|
||||
systemprompt: 在这里向 AI LLM 解释当被提示时应该如何回应。
|
||||
posthistoryinstructions: 在消息历史之后,放入 AI LLM 应该阅读的内容。
|
||||
version: >-
|
||||
卡片版本,如果您从之前的卡片做了更改,应当增加此版本号。
|
||||
consciousness_model: 选择此角色使用的意识模型(AI 模型)。
|
||||
speech_model: 选择此角色使用的语音合成模型和声线。
|
||||
errors:
|
||||
name: 错误:你必须提供一个有效的名称!
|
||||
version: '错误:版本号无效!'
|
||||
@@ -152,6 +159,7 @@ pages:
|
||||
search: 搜索角色卡...
|
||||
sort_by: 排序方式
|
||||
speech:
|
||||
provider: 声音 / 提供商
|
||||
model: 声音 / 模型
|
||||
voice: 声音 / 声线
|
||||
systemprompt: 系统提示词
|
||||
@@ -294,7 +302,7 @@ pages:
|
||||
search_results: 找到 {count} / {total} 个模型
|
||||
show_less: 显示更多
|
||||
show_more: 收起
|
||||
subtitle: 选择一个模型
|
||||
subtitle: 选择一个默认模型
|
||||
title: 模型
|
||||
title: 意识
|
||||
description: 思维,视觉,言语综合,游戏等
|
||||
|
||||
@@ -294,7 +294,7 @@ pages:
|
||||
search_results: 找到 {count} / {total} 個模型
|
||||
show_less: 顯示更少
|
||||
show_more: 顯示更多
|
||||
subtitle: 選擇一個模型
|
||||
subtitle: 選擇一個預設模型
|
||||
title: 模型
|
||||
title: 意識
|
||||
description: 思維、視覺、語音綜合、遊戲等
|
||||
|
||||
+248
-8
@@ -1,10 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import type { Card } from '@proj-airi/ccc'
|
||||
import type { AiriExtension } from '@proj-airi/stage-ui/stores/modules/airi-card'
|
||||
|
||||
import kebabcase from '@stdlib/string-base-kebabcase'
|
||||
|
||||
import { useAiriCardStore } from '@proj-airi/stage-ui/stores/modules/airi-card'
|
||||
import { useConsciousnessStore } from '@proj-airi/stage-ui/stores/modules/consciousness'
|
||||
import { useSpeechStore } from '@proj-airi/stage-ui/stores/modules/speech'
|
||||
import { useProvidersStore } from '@proj-airi/stage-ui/stores/providers'
|
||||
import { Button, FieldInput, FieldValues } from '@proj-airi/ui'
|
||||
import { Select } from '@proj-airi/ui/components/form'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import {
|
||||
DialogContent,
|
||||
DialogOverlay,
|
||||
@@ -29,10 +35,125 @@ const modelValue = defineModel<boolean>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const cardStore = useAiriCardStore()
|
||||
const consciousnessStore = useConsciousnessStore()
|
||||
const speechStore = useSpeechStore()
|
||||
const providersStore = useProvidersStore()
|
||||
|
||||
const { activeProvider: consciousnessProvider, activeModel: defaultConsciousnessModel } = storeToRefs(consciousnessStore)
|
||||
const { activeSpeechProvider: speechProvider, activeSpeechModel: defaultSpeechModel, activeSpeechVoiceId: defaultSpeechVoiceId } = storeToRefs(speechStore)
|
||||
|
||||
// Determine if we're in edit mode
|
||||
const isEditMode = computed(() => !!props.cardId)
|
||||
|
||||
// Modules configuration
|
||||
const selectedConsciousnessProvider = ref<string>('')
|
||||
const selectedConsciousnessModel = ref<string>('')
|
||||
const selectedSpeechProvider = ref<string>('')
|
||||
const selectedSpeechModel = ref<string>('')
|
||||
const selectedSpeechVoiceId = ref<string>('')
|
||||
|
||||
// Computed: available consciousness provider options
|
||||
const consciousnessProviderOptions = computed(() => {
|
||||
return providersStore.configuredChatProvidersMetadata.map(provider => ({
|
||||
value: provider.id,
|
||||
label: provider.localizedName || provider.name,
|
||||
}))
|
||||
})
|
||||
|
||||
// Computed: available consciousness models options
|
||||
const consciousnessModelOptions = computed(() => {
|
||||
const provider = selectedConsciousnessProvider.value || consciousnessProvider.value
|
||||
if (!provider)
|
||||
return []
|
||||
const models = providersStore.getModelsForProvider(provider)
|
||||
return models.map(model => ({
|
||||
value: model.id,
|
||||
label: model.name || model.id,
|
||||
}))
|
||||
})
|
||||
|
||||
// Computed: available speech provider options
|
||||
const speechProviderOptions = computed(() => {
|
||||
return providersStore.configuredSpeechProvidersMetadata.map(provider => ({
|
||||
value: provider.id,
|
||||
label: provider.localizedName || provider.name,
|
||||
}))
|
||||
})
|
||||
|
||||
// Computed: available speech models options
|
||||
const speechModelOptions = computed(() => {
|
||||
const provider = selectedSpeechProvider.value || speechProvider.value
|
||||
if (!provider)
|
||||
return []
|
||||
const models = providersStore.getModelsForProvider(provider)
|
||||
return models.map(model => ({
|
||||
value: model.id,
|
||||
label: model.name || model.id,
|
||||
}))
|
||||
})
|
||||
|
||||
// Computed: available speech voices options
|
||||
const speechVoiceOptions = computed(() => {
|
||||
const provider = selectedSpeechProvider.value || speechProvider.value
|
||||
if (!provider)
|
||||
return []
|
||||
const voices = speechStore.getVoicesForProvider(provider)
|
||||
return voices.map(voice => ({
|
||||
value: voice.id,
|
||||
label: voice.name || voice.id,
|
||||
}))
|
||||
})
|
||||
|
||||
// Load models for current providers on init
|
||||
watch(() => [consciousnessProvider.value, speechProvider.value], async ([consProvider, spProvider]) => {
|
||||
if (consProvider) {
|
||||
await consciousnessStore.loadModelsForProvider(consProvider)
|
||||
}
|
||||
if (spProvider) {
|
||||
await speechStore.loadVoicesForProvider(spProvider)
|
||||
const metadata = providersStore.getProviderMetadata(spProvider)
|
||||
if (metadata?.capabilities.listModels) {
|
||||
await providersStore.fetchModelsForProvider(spProvider)
|
||||
}
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
// Watch consciousness provider changes and reload models
|
||||
watch(selectedConsciousnessProvider, async (newProvider, oldProvider) => {
|
||||
if (oldProvider !== undefined && newProvider !== oldProvider && newProvider) {
|
||||
await consciousnessStore.loadModelsForProvider(newProvider)
|
||||
// Reset model selection to default or empty
|
||||
selectedConsciousnessModel.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
// Watch speech provider changes and reload models/voices
|
||||
watch(selectedSpeechProvider, async (newProvider, oldProvider) => {
|
||||
if (oldProvider !== undefined && newProvider !== oldProvider && newProvider) {
|
||||
await speechStore.loadVoicesForProvider(newProvider)
|
||||
const metadata = providersStore.getProviderMetadata(newProvider)
|
||||
if (metadata?.capabilities.listModels) {
|
||||
await providersStore.fetchModelsForProvider(newProvider)
|
||||
}
|
||||
// Reset model and voice selection
|
||||
selectedSpeechModel.value = ''
|
||||
selectedSpeechVoiceId.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
// Reset voice when speech model changes (different models may have different voices)
|
||||
watch(selectedSpeechModel, async (newModel, oldModel) => {
|
||||
// Only reset if model actually changed and we're not initializing
|
||||
const provider = selectedSpeechProvider.value || speechProvider.value
|
||||
if (oldModel !== undefined && newModel !== oldModel && provider) {
|
||||
// Reload voices for the current provider
|
||||
await speechStore.loadVoicesForProvider(provider)
|
||||
|
||||
// Reset voice selection to default
|
||||
selectedSpeechVoiceId.value = defaultSpeechVoiceId.value || ''
|
||||
}
|
||||
})
|
||||
|
||||
// Tab type definition
|
||||
interface Tab {
|
||||
id: string
|
||||
@@ -47,6 +168,7 @@ const activeTabId = ref('')
|
||||
const tabs: Tab[] = [
|
||||
{ id: 'identity', label: t('settings.pages.card.creation.identity'), icon: 'i-solar:emoji-funny-square-bold-duotone' },
|
||||
{ id: 'behavior', label: t('settings.pages.card.creation.behavior'), icon: 'i-solar:chat-round-line-bold-duotone' },
|
||||
{ id: 'modules', label: t('settings.pages.card.modules'), icon: 'i-solar:widget-4-bold-duotone' },
|
||||
{ id: 'settings', label: t('settings.pages.card.creation.settings'), icon: 'i-solar:settings-bold-duotone' },
|
||||
]
|
||||
|
||||
@@ -116,13 +238,35 @@ function saveCard(card: Card): boolean {
|
||||
}
|
||||
showError.value = false
|
||||
|
||||
// Build card with modules extension
|
||||
const cardWithModules = {
|
||||
...rawCard,
|
||||
extensions: {
|
||||
...rawCard.extensions,
|
||||
airi: {
|
||||
modules: {
|
||||
consciousness: {
|
||||
provider: selectedConsciousnessProvider.value || consciousnessProvider.value,
|
||||
model: selectedConsciousnessModel.value || defaultConsciousnessModel.value,
|
||||
},
|
||||
speech: {
|
||||
provider: selectedSpeechProvider.value || speechProvider.value,
|
||||
model: selectedSpeechModel.value || defaultSpeechModel.value,
|
||||
voice_id: selectedSpeechVoiceId.value || defaultSpeechVoiceId.value,
|
||||
},
|
||||
},
|
||||
agents: {},
|
||||
} as AiriExtension,
|
||||
},
|
||||
}
|
||||
|
||||
if (isEditMode.value && props.cardId) {
|
||||
// Edit mode: update existing card
|
||||
cardStore.updateCard(props.cardId, rawCard)
|
||||
cardStore.updateCard(props.cardId, cardWithModules)
|
||||
}
|
||||
else {
|
||||
// Create mode: add new card
|
||||
cardStore.addCard(rawCard)
|
||||
cardStore.addCard(cardWithModules)
|
||||
}
|
||||
|
||||
modelValue.value = false // Close this
|
||||
@@ -133,14 +277,22 @@ function saveCard(card: Card): boolean {
|
||||
|
||||
// Initialize card data - load from existing card if in edit mode
|
||||
function initializeCard(): Card {
|
||||
if (isEditMode.value && props.cardId) {
|
||||
const existingCard = cardStore.getCard(props.cardId)
|
||||
if (existingCard) {
|
||||
return { ...toRaw(existingCard) }
|
||||
}
|
||||
// Extract existing card data if in edit mode
|
||||
const existingCard = (isEditMode.value && props.cardId) ? cardStore.getCard(props.cardId) : undefined
|
||||
const airiExt = existingCard?.extensions?.airi as AiriExtension | undefined
|
||||
|
||||
// Initialize module selections with fallback logic (handles all cases: create, edit with/without extension)
|
||||
selectedConsciousnessProvider.value = airiExt?.modules?.consciousness?.provider || consciousnessProvider.value
|
||||
selectedConsciousnessModel.value = airiExt?.modules?.consciousness?.model || defaultConsciousnessModel.value
|
||||
selectedSpeechProvider.value = airiExt?.modules?.speech?.provider || speechProvider.value
|
||||
selectedSpeechModel.value = airiExt?.modules?.speech?.model || defaultSpeechModel.value
|
||||
selectedSpeechVoiceId.value = airiExt?.modules?.speech?.voice_id || defaultSpeechVoiceId.value
|
||||
|
||||
// Return existing card data or defaults
|
||||
if (existingCard) {
|
||||
return { ...toRaw(existingCard) }
|
||||
}
|
||||
|
||||
// Default values for create mode
|
||||
return {
|
||||
name: t('settings.pages.card.creation.defaults.name'),
|
||||
nickname: undefined,
|
||||
@@ -202,6 +354,13 @@ const cardGreetings = computed({
|
||||
const cardVersion = makeComputed('version')
|
||||
const cardSystemPrompt = makeComputed('systemPrompt')
|
||||
const cardPostHistoryInstructions = makeComputed('postHistoryInstructions')
|
||||
|
||||
// Helper function to generate placeholder text for default values
|
||||
function getDefaultPlaceholder(defaultValue: string | undefined): string {
|
||||
return defaultValue
|
||||
? `${t('settings.pages.card.creation.use_default')} (${defaultValue})`
|
||||
: t('settings.pages.card.creation.use_default_not_configured')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -267,6 +426,87 @@ const cardPostHistoryInstructions = makeComputed('postHistoryInstructions')
|
||||
<FieldValues v-model="cardGreetings" :label="t('settings.pages.card.creation.greetings')" :description="t('settings.pages.card.creation.fields_info.greetings')" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modules -->
|
||||
<div v-else-if="activeTab === 'modules'" class="tab-content ml-auto mr-auto w-95%">
|
||||
<p class="mb-3">
|
||||
{{ t('settings.pages.card.creation.modules_info') }}
|
||||
</p>
|
||||
|
||||
<div :class="['grid', 'grid-cols-1', 'sm:grid-cols-2', 'gap-4', 'ml-auto', 'mr-auto', 'w-90%']">
|
||||
<!-- Consciousness Provider -->
|
||||
<div :class="['flex', 'flex-col', 'gap-2']">
|
||||
<label :class="['flex', 'flex-row', 'items-center', 'gap-2', 'text-sm', 'text-neutral-500', 'dark:text-neutral-400']">
|
||||
<div i-lucide:brain />
|
||||
{{ t('settings.pages.card.chat.provider') }}
|
||||
</label>
|
||||
<Select
|
||||
v-model="selectedConsciousnessProvider"
|
||||
:options="consciousnessProviderOptions"
|
||||
:placeholder="getDefaultPlaceholder(consciousnessProvider)"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Consciousness Model -->
|
||||
<div :class="['flex', 'flex-col', 'gap-2']">
|
||||
<label :class="['flex', 'flex-row', 'items-center', 'gap-2', 'text-sm', 'text-neutral-500', 'dark:text-neutral-400']">
|
||||
<div i-lucide:ghost />
|
||||
{{ t('settings.pages.card.consciousness.model') }}
|
||||
</label>
|
||||
<Select
|
||||
v-model="selectedConsciousnessModel"
|
||||
:options="consciousnessModelOptions"
|
||||
:placeholder="getDefaultPlaceholder(defaultConsciousnessModel)"
|
||||
:disabled="!selectedConsciousnessProvider && !consciousnessProvider"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Speech Provider -->
|
||||
<div :class="['flex', 'flex-col', 'gap-2']">
|
||||
<label :class="['flex', 'flex-row', 'items-center', 'gap-2', 'text-sm', 'text-neutral-500', 'dark:text-neutral-400']">
|
||||
<div i-lucide:radio />
|
||||
{{ t('settings.pages.card.speech.provider') }}
|
||||
</label>
|
||||
<Select
|
||||
v-model="selectedSpeechProvider"
|
||||
:options="speechProviderOptions"
|
||||
:placeholder="getDefaultPlaceholder(speechProvider)"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Speech Model -->
|
||||
<div :class="['flex', 'flex-col', 'gap-2']">
|
||||
<label :class="['flex', 'flex-row', 'items-center', 'gap-2', 'text-sm', 'text-neutral-500', 'dark:text-neutral-400']">
|
||||
<div i-lucide:mic />
|
||||
{{ t('settings.pages.card.speech.model') }}
|
||||
</label>
|
||||
<Select
|
||||
v-model="selectedSpeechModel"
|
||||
:options="speechModelOptions"
|
||||
:placeholder="getDefaultPlaceholder(defaultSpeechModel)"
|
||||
:disabled="!selectedSpeechProvider && !speechProvider"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Speech Voice -->
|
||||
<div :class="['flex', 'flex-col', 'gap-2']">
|
||||
<label :class="['flex', 'flex-row', 'items-center', 'gap-2', 'text-sm', 'text-neutral-500', 'dark:text-neutral-400']">
|
||||
<div i-lucide:music />
|
||||
{{ t('settings.pages.card.speech.voice') }}
|
||||
</label>
|
||||
<Select
|
||||
v-model="selectedSpeechVoiceId"
|
||||
:options="speechVoiceOptions"
|
||||
:placeholder="getDefaultPlaceholder(defaultSpeechVoiceId)"
|
||||
:disabled="!selectedSpeechProvider && !speechProvider"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Settings -->
|
||||
<div v-else-if="activeTab === 'settings'" class="tab-content ml-auto mr-auto w-95%">
|
||||
<div class="input-list ml-auto mr-auto w-90% flex flex-row flex-wrap justify-center gap-8">
|
||||
|
||||
@@ -4,6 +4,8 @@ import type { AiriCard } from '@proj-airi/stage-ui/stores/modules/airi-card'
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
import { useAiriCardStore } from '@proj-airi/stage-ui/stores/modules/airi-card'
|
||||
import { useConsciousnessStore } from '@proj-airi/stage-ui/stores/modules/consciousness'
|
||||
import { useSpeechStore } from '@proj-airi/stage-ui/stores/modules/speech'
|
||||
import { Button } from '@proj-airi/ui'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import {
|
||||
@@ -30,8 +32,12 @@ const emit = defineEmits<{
|
||||
|
||||
const { t } = useI18n()
|
||||
const cardStore = useAiriCardStore()
|
||||
const consciousnessStore = useConsciousnessStore()
|
||||
const speechStore = useSpeechStore()
|
||||
const { removeCard } = cardStore
|
||||
const { activeCardId } = storeToRefs(cardStore)
|
||||
const { activeProvider: consciousnessProvider, activeModel: defaultConsciousnessModel } = storeToRefs(consciousnessStore)
|
||||
const { activeSpeechProvider: speechProvider, activeSpeechModel: defaultSpeechModel, activeSpeechVoiceId: defaultVoiceId } = storeToRefs(speechStore)
|
||||
|
||||
// Get selected card data
|
||||
const selectedCard = computed<AiriCard | undefined>(() => {
|
||||
@@ -44,7 +50,9 @@ const selectedCard = computed<AiriCard | undefined>(() => {
|
||||
const moduleSettings = computed(() => {
|
||||
if (!selectedCard.value || !selectedCard.value.extensions?.airi?.modules) {
|
||||
return {
|
||||
consciousnessProvider: '',
|
||||
consciousness: '',
|
||||
speechProvider: '',
|
||||
speech: '',
|
||||
voice: '',
|
||||
}
|
||||
@@ -52,7 +60,9 @@ const moduleSettings = computed(() => {
|
||||
|
||||
const airiExt = selectedCard.value.extensions.airi.modules
|
||||
return {
|
||||
consciousnessProvider: airiExt.consciousness?.provider || '',
|
||||
consciousness: airiExt.consciousness?.model || '',
|
||||
speechProvider: airiExt.speech?.provider || '',
|
||||
speech: airiExt.speech?.model || '',
|
||||
voice: airiExt.speech?.voice_id || '',
|
||||
}
|
||||
@@ -163,6 +173,18 @@ const activeTab = computed({
|
||||
activeTabId.value = value
|
||||
},
|
||||
})
|
||||
|
||||
// Helper function to generate placeholder text for default values
|
||||
function getDefaultPlaceholder(defaultValue: string | undefined): string {
|
||||
return defaultValue
|
||||
? `${t('settings.pages.card.creation.use_default')} (${defaultValue})`
|
||||
: t('settings.pages.card.creation.use_default_not_configured')
|
||||
}
|
||||
|
||||
// Helper function to get display value for module settings
|
||||
function getModuleDisplayValue(value: string | undefined, defaultValue: string | undefined): string {
|
||||
return value || getDefaultPlaceholder(defaultValue)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -275,7 +297,24 @@ const activeTab = computed({
|
||||
|
||||
<!-- Modules -->
|
||||
<div v-if="activeTab === 'modules'">
|
||||
<div grid="~ cols-1 sm:cols-3" gap-4>
|
||||
<div grid="~ cols-1 sm:cols-2" gap-4>
|
||||
<div
|
||||
flex="~ col"
|
||||
bg="white/60 dark:black/30"
|
||||
gap-1 rounded-lg p-3
|
||||
border="~ neutral-200/50 dark:neutral-700/30"
|
||||
transition="all duration-200"
|
||||
hover="bg-white/80 dark:bg-black/40"
|
||||
>
|
||||
<span flex="~ row" items-center gap-2 text-sm text-neutral-500 dark:text-neutral-400>
|
||||
<div i-lucide:brain />
|
||||
{{ t('settings.pages.card.chat.provider') }}
|
||||
</span>
|
||||
<div truncate font-medium>
|
||||
{{ getModuleDisplayValue(moduleSettings.consciousnessProvider, consciousnessProvider) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
flex="~ col"
|
||||
bg="white/60 dark:black/30"
|
||||
@@ -289,7 +328,24 @@ const activeTab = computed({
|
||||
{{ t('settings.pages.card.consciousness.model') }}
|
||||
</span>
|
||||
<div truncate font-medium>
|
||||
{{ moduleSettings.consciousness ?? 'default' }}
|
||||
{{ getModuleDisplayValue(moduleSettings.consciousness, defaultConsciousnessModel) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
flex="~ col"
|
||||
bg="white/60 dark:black/30"
|
||||
gap-1 rounded-lg p-3
|
||||
border="~ neutral-200/50 dark:neutral-700/30"
|
||||
transition="all duration-200"
|
||||
hover="bg-white/80 dark:bg-black/40"
|
||||
>
|
||||
<span flex="~ row" items-center gap-2 text-sm text-neutral-500 dark:text-neutral-400>
|
||||
<div i-lucide:radio />
|
||||
{{ t('settings.pages.card.speech.provider') }}
|
||||
</span>
|
||||
<div truncate font-medium>
|
||||
{{ getModuleDisplayValue(moduleSettings.speechProvider, speechProvider) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -306,7 +362,7 @@ const activeTab = computed({
|
||||
{{ t('settings.pages.card.speech.model') }}
|
||||
</span>
|
||||
<div truncate font-medium>
|
||||
{{ moduleSettings.speech ?? 'default' }}
|
||||
{{ getModuleDisplayValue(moduleSettings.speech, defaultSpeechModel) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -323,7 +379,7 @@ const activeTab = computed({
|
||||
{{ t('settings.pages.card.speech.voice') }}
|
||||
</span>
|
||||
<div truncate font-medium>
|
||||
{{ moduleSettings.voice ?? 'default' }}
|
||||
{{ getModuleDisplayValue(moduleSettings.voice, defaultVoiceId) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,9 +25,15 @@ const {
|
||||
const { t } = useI18n()
|
||||
const { trackProviderClick } = useAnalytics()
|
||||
|
||||
watch(activeProvider, async (provider) => {
|
||||
watch(activeProvider, async (provider, oldProvider) => {
|
||||
if (!provider)
|
||||
return
|
||||
|
||||
// Reset model when switching providers (but not on initial load)
|
||||
if (oldProvider !== undefined && oldProvider !== provider) {
|
||||
activeModel.value = ''
|
||||
}
|
||||
|
||||
await consciousnessStore.loadModelsForProvider(provider)
|
||||
}, { immediate: true })
|
||||
|
||||
|
||||
@@ -90,9 +90,17 @@ onMounted(async () => {
|
||||
syncOpenAICompatibleSettings()
|
||||
})
|
||||
|
||||
watch(activeSpeechProvider, async (newProvider) => {
|
||||
watch(activeSpeechProvider, async (newProvider, oldProvider) => {
|
||||
await providersStore.loadModelsForConfiguredProviders()
|
||||
await speechStore.loadVoicesForProvider(newProvider)
|
||||
|
||||
// Reset model and voice when switching providers (but not on initial load)
|
||||
if (oldProvider !== undefined && oldProvider !== newProvider) {
|
||||
activeSpeechModel.value = ''
|
||||
activeSpeechVoiceId.value = ''
|
||||
activeSpeechVoice.value = undefined
|
||||
}
|
||||
|
||||
syncOpenAICompatibleSettings()
|
||||
})
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { InvocableEventContext } from '@moeru/eventa'
|
||||
import type { AnalyserBeatEvent, AnalyserWorkletParameters } from '@nekopaw/tempora'
|
||||
|
||||
import type { BeatSyncDetectorState } from './types'
|
||||
@@ -28,9 +29,9 @@ function getBroadcastChannel() {
|
||||
return _broadcastChannel
|
||||
}
|
||||
|
||||
export function createContext() {
|
||||
export function createContext(): InvocableEventContext<any, { raw?: any }> {
|
||||
if (isElectronWindow(window)) {
|
||||
return createBroadcastChannelContext(getBroadcastChannel()).context
|
||||
return createBroadcastChannelContext(getBroadcastChannel()).context as InvocableEventContext<any, { raw?: any }>
|
||||
}
|
||||
else {
|
||||
return createWebContext()
|
||||
|
||||
@@ -59,9 +59,11 @@ describe('store character', () => {
|
||||
agents: {},
|
||||
modules: {
|
||||
consciousness: {
|
||||
provider: 'mock-provider',
|
||||
model: 'mock-model',
|
||||
},
|
||||
speech: {
|
||||
provider: 'mock-speech-provider',
|
||||
model: 'mock-speech-model',
|
||||
voice_id: 'alloy',
|
||||
},
|
||||
|
||||
@@ -126,9 +126,11 @@ describe('store character-orchestrator', () => {
|
||||
agents: {},
|
||||
modules: {
|
||||
consciousness: {
|
||||
provider: 'mock-provider',
|
||||
model: 'mock-model',
|
||||
},
|
||||
speech: {
|
||||
provider: 'mock-speech-provider',
|
||||
model: 'mock-speech-model',
|
||||
voice_id: 'alloy',
|
||||
},
|
||||
|
||||
@@ -14,10 +14,12 @@ import { useSpeechStore } from './speech'
|
||||
export interface AiriExtension {
|
||||
modules: {
|
||||
consciousness: {
|
||||
provider: string // Example: "openai"
|
||||
model: string // Example: "gpt-4o"
|
||||
}
|
||||
|
||||
speech: {
|
||||
provider: string // Example: "elevenlabs"
|
||||
model: string // Example: "eleven_multilingual_v2"
|
||||
voice_id: string // Example: "alloy"
|
||||
|
||||
@@ -66,10 +68,12 @@ export const useAiriCardStore = defineStore('airi-card', () => {
|
||||
const speechStore = useSpeechStore()
|
||||
|
||||
const {
|
||||
activeProvider: activeConsciousnessProvider,
|
||||
activeModel: activeConsciousnessModel,
|
||||
} = storeToRefs(consciousnessStore)
|
||||
|
||||
const {
|
||||
activeSpeechProvider,
|
||||
activeSpeechVoiceId,
|
||||
activeSpeechModel,
|
||||
} = storeToRefs(speechStore)
|
||||
@@ -111,9 +115,11 @@ export const useAiriCardStore = defineStore('airi-card', () => {
|
||||
// Create default modules config
|
||||
const defaultModules = {
|
||||
consciousness: {
|
||||
provider: activeConsciousnessProvider.value,
|
||||
model: activeConsciousnessModel.value,
|
||||
},
|
||||
speech: {
|
||||
provider: activeSpeechProvider.value,
|
||||
model: activeSpeechModel.value,
|
||||
voice_id: activeSpeechVoiceId.value,
|
||||
},
|
||||
@@ -131,9 +137,11 @@ export const useAiriCardStore = defineStore('airi-card', () => {
|
||||
return {
|
||||
modules: {
|
||||
consciousness: {
|
||||
provider: existingExtension.modules?.consciousness?.provider ?? defaultModules.consciousness.provider,
|
||||
model: existingExtension.modules?.consciousness?.model ?? defaultModules.consciousness.model,
|
||||
},
|
||||
speech: {
|
||||
provider: existingExtension.modules?.speech?.provider ?? defaultModules.speech.provider,
|
||||
model: existingExtension.modules?.speech?.model ?? defaultModules.speech.model,
|
||||
voice_id: existingExtension.modules?.speech?.voice_id ?? defaultModules.speech.voice_id,
|
||||
pitch: existingExtension.modules?.speech?.pitch,
|
||||
@@ -221,7 +229,10 @@ export const useAiriCardStore = defineStore('airi-card', () => {
|
||||
if (!extension)
|
||||
return
|
||||
|
||||
activeConsciousnessProvider.value = extension?.modules?.consciousness?.provider
|
||||
activeConsciousnessModel.value = extension?.modules?.consciousness?.model
|
||||
|
||||
activeSpeechProvider.value = extension?.modules?.speech?.provider
|
||||
activeSpeechModel.value = extension?.modules?.speech?.model
|
||||
activeSpeechVoiceId.value = extension?.modules?.speech?.voice_id
|
||||
})
|
||||
@@ -245,9 +256,11 @@ export const useAiriCardStore = defineStore('airi-card', () => {
|
||||
currentModels: computed(() => {
|
||||
return {
|
||||
consciousness: {
|
||||
provider: activeConsciousnessProvider.value,
|
||||
model: activeConsciousnessModel.value,
|
||||
},
|
||||
speech: {
|
||||
provider: activeSpeechProvider.value,
|
||||
model: activeSpeechModel.value,
|
||||
voice_id: activeSpeechVoiceId.value,
|
||||
},
|
||||
|
||||
@@ -18,7 +18,7 @@ export const useSpeechStore = defineStore('speech', () => {
|
||||
|
||||
// State
|
||||
const activeSpeechProvider = useLocalStorageManualReset<string>('settings/speech/active-provider', '')
|
||||
const activeSpeechModel = useLocalStorageManualReset<string>('settings/speech/active-model', 'eleven_multilingual_v2')
|
||||
const activeSpeechModel = useLocalStorageManualReset<string>('settings/speech/active-model', '')
|
||||
const activeSpeechVoiceId = useLocalStorageManualReset<string>('settings/speech/voice', '')
|
||||
const activeSpeechVoice = refManualReset<VoiceInfo | undefined>(undefined)
|
||||
|
||||
|
||||
Generated
+16
-37
@@ -495,7 +495,7 @@ importers:
|
||||
version: 3.8.1
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@moeru/std':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.0-beta.14
|
||||
@@ -886,7 +886,7 @@ importers:
|
||||
version: 3.8.1
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@moeru/std':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.0-beta.14
|
||||
@@ -1277,7 +1277,7 @@ importers:
|
||||
version: 3.8.1
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@moeru/std':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.0-beta.14
|
||||
@@ -1962,7 +1962,7 @@ importers:
|
||||
dependencies:
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@moeru/std':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.0-beta.14
|
||||
@@ -1974,7 +1974,7 @@ importers:
|
||||
dependencies:
|
||||
'@moeru/eventa':
|
||||
specifier: 'catalog:'
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@xsai/shared-chat':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-beta.13
|
||||
@@ -1983,7 +1983,7 @@ importers:
|
||||
dependencies:
|
||||
'@moeru/eventa':
|
||||
specifier: 'catalog:'
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@proj-airi/server-shared':
|
||||
specifier: workspace:*
|
||||
version: link:../server-shared
|
||||
@@ -2038,7 +2038,7 @@ importers:
|
||||
dependencies:
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@moeru/std':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.0-beta.14
|
||||
@@ -2141,7 +2141,7 @@ importers:
|
||||
dependencies:
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@moeru/std':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.0-beta.14
|
||||
@@ -2269,7 +2269,7 @@ importers:
|
||||
version: 3.0.2(electron@40.0.0)
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@nekopaw/tempora':
|
||||
specifier: 'catalog:'
|
||||
version: 0.4.0-alpha.1
|
||||
@@ -2293,7 +2293,7 @@ importers:
|
||||
version: 3.8.1
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@proj-airi/audio':
|
||||
specifier: workspace:^
|
||||
version: link:../audio
|
||||
@@ -3018,7 +3018,7 @@ importers:
|
||||
version: 1.2.4
|
||||
'@moeru/eventa':
|
||||
specifier: ^1.0.0-alpha.11
|
||||
version: 1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
version: 1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))
|
||||
'@proj-airi/server-sdk':
|
||||
specifier: workspace:^
|
||||
version: link:../../packages/server-sdk
|
||||
@@ -3033,7 +3033,7 @@ importers:
|
||||
version: 14.1.0(vue@3.5.26(typescript@5.9.3))
|
||||
'@wxt-dev/module-vue':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3(vite@8.0.0-beta.9(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.55.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
|
||||
version: 1.0.3(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.55.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
|
||||
nanoid:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
@@ -6008,20 +6008,6 @@ packages:
|
||||
web-worker:
|
||||
optional: true
|
||||
|
||||
'@moeru/eventa@1.0.0-alpha.11':
|
||||
resolution: {integrity: sha512-5i2LYA19E9siAdqhobVm386dqkV4EZw0+uGDEwLiGqfopE/3yX1zdgOkdvEoT+YJf0SIUqDwuMZoYXkvfWV/kA==}
|
||||
peerDependencies:
|
||||
electron: '>=30'
|
||||
h3: 2.0.0-beta.1
|
||||
web-worker: ^1.5.0
|
||||
peerDependenciesMeta:
|
||||
electron:
|
||||
optional: true
|
||||
h3:
|
||||
optional: true
|
||||
web-worker:
|
||||
optional: true
|
||||
|
||||
'@moeru/eventa@1.0.0-alpha.14':
|
||||
resolution: {integrity: sha512-VMz75aYTJO85yXj0jj/M8ImakOYr6OUZnV/I5gmseVrMFcqBc8UC6Pk2LTwoMQw/EWaU59557a1lpnUqeyTMQw==}
|
||||
peerDependencies:
|
||||
@@ -19704,14 +19690,6 @@ snapshots:
|
||||
electron: 40.0.0
|
||||
h3: 2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1))
|
||||
|
||||
'@moeru/eventa@1.0.0-alpha.11(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))':
|
||||
dependencies:
|
||||
nanoid: 5.1.6
|
||||
picomatch: 4.0.3
|
||||
optionalDependencies:
|
||||
electron: 40.0.0
|
||||
h3: 2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1))
|
||||
|
||||
'@moeru/eventa@1.0.0-alpha.14(electron@39.2.7)':
|
||||
dependencies:
|
||||
nanoid: 5.1.6
|
||||
@@ -19719,12 +19697,13 @@ snapshots:
|
||||
optionalDependencies:
|
||||
electron: 39.2.7
|
||||
|
||||
'@moeru/eventa@1.0.0-alpha.14(electron@40.0.0)':
|
||||
'@moeru/eventa@1.0.0-alpha.14(electron@40.0.0)(h3@2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1)))':
|
||||
dependencies:
|
||||
nanoid: 5.1.6
|
||||
picomatch: 4.0.3
|
||||
optionalDependencies:
|
||||
electron: 40.0.0
|
||||
h3: 2.0.1-rc.5(crossws@0.4.3(srvx@0.10.1))
|
||||
|
||||
'@moeru/std@0.1.0-beta.1': {}
|
||||
|
||||
@@ -23303,9 +23282,9 @@ snapshots:
|
||||
'@types/filesystem': 0.0.36
|
||||
'@types/har-format': 1.2.16
|
||||
|
||||
'@wxt-dev/module-vue@1.0.3(vite@8.0.0-beta.9(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.55.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
'@wxt-dev/module-vue@1.0.3(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))(wxt@0.20.13(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.55.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
dependencies:
|
||||
'@vitejs/plugin-vue': 6.0.3(vite@8.0.0-beta.9(@types/node@24.10.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))
|
||||
'@vitejs/plugin-vue': 6.0.3(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.26(typescript@5.9.3))
|
||||
wxt: 0.20.13(@types/node@24.10.9)(jiti@2.6.1)(less@4.5.1)(lightningcss@1.30.2)(rollup@4.55.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)
|
||||
transitivePeerDependencies:
|
||||
- vite
|
||||
|
||||
Reference in New Issue
Block a user