feat(stage-tamagotchi): add Apple Speech transcription (#2364)
This commit is contained in:
@@ -206,14 +206,11 @@ export default {
|
||||
// - Linux arm64 -> `latest-arm64-linux-arm64.yml`
|
||||
channel: 'latest-${arch}',
|
||||
},
|
||||
extendInfo: [
|
||||
{
|
||||
NSMicrophoneUsageDescription: 'AIRI requires microphone access for voice interaction',
|
||||
},
|
||||
{
|
||||
NSCameraUsageDescription: 'AIRI requires camera access for vision understanding',
|
||||
},
|
||||
],
|
||||
extendInfo: {
|
||||
NSMicrophoneUsageDescription: 'AIRI requires microphone access for voice interaction',
|
||||
NSSpeechRecognitionUsageDescription: 'AIRI uses Apple Speech to transcribe voice interactions on this device',
|
||||
NSCameraUsageDescription: 'AIRI requires camera access for vision understanding',
|
||||
},
|
||||
// For self-publishing, testing, and distribution after modified the code without access to
|
||||
// an Apple Developer account, comment and uncomment the following 4 lines.
|
||||
// Later on when you obtained one, you can set up the necessary certificates and provisioning
|
||||
|
||||
@@ -28,6 +28,7 @@ export default defineConfig({
|
||||
// them into ESM and causing issues in runtime.
|
||||
'electron-click-drag-plugin',
|
||||
'uiohook-napi',
|
||||
'@xsai-apple-speech/transcription-native',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -81,6 +81,9 @@
|
||||
"@vueuse/core": "catalog:",
|
||||
"@vueuse/motion": "catalog:",
|
||||
"@vueuse/shared": "catalog:",
|
||||
"@xsai-apple-speech/transcription": "catalog:",
|
||||
"@xsai-apple-speech/transcription-electron-plugin": "catalog:",
|
||||
"@xsai-apple-speech/transcription-native": "catalog:",
|
||||
"@xsai-ext/providers": "catalog:",
|
||||
"@xsai-transformers/embed": "catalog:",
|
||||
"@xsai-transformers/transcription": "catalog:",
|
||||
@@ -143,6 +146,10 @@
|
||||
"xsschema": "catalog:",
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@xsai-apple-speech/transcription-native-darwin-arm64": "catalog:",
|
||||
"@xsai-apple-speech/transcription-native-darwin-x64": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/preload": "catalog:",
|
||||
"@electron-toolkit/tsconfig": "catalog:",
|
||||
|
||||
@@ -28,6 +28,7 @@ import { createGlobalAppConfig } from './configs/global'
|
||||
import { emitAppBeforeQuit, emitAppReady, emitAppWindowAllClosed } from './libs/bootkit/lifecycle'
|
||||
import { setElectronMainDirname } from './libs/electron/location'
|
||||
import { createI18n } from './libs/i18n'
|
||||
import { setupAppleSpeechTranscriptionService } from './services/airi/apple-speech-transcription'
|
||||
import { setupServerChannel } from './services/airi/channel-server'
|
||||
import { setupGodotStageManager } from './services/airi/godot-stage'
|
||||
import { setupBuiltInServer } from './services/airi/http-server'
|
||||
@@ -165,6 +166,11 @@ app.whenReady().then(async () => {
|
||||
build: async () => setupGodotStageManager(),
|
||||
})
|
||||
|
||||
const appleSpeechTranscription = injeca.provide('modules:apple-speech-transcription', {
|
||||
dependsOn: { lifecycle },
|
||||
build: ({ dependsOn }) => setupAppleSpeechTranscriptionService(dependsOn),
|
||||
})
|
||||
|
||||
const mcpStdioManager = injeca.provide('modules:mcp-stdio-manager', {
|
||||
build: async () => setupMcpStdioManager(),
|
||||
})
|
||||
@@ -226,7 +232,7 @@ app.whenReady().then(async () => {
|
||||
})
|
||||
|
||||
const mainWindow = injeca.provide('windows:main', {
|
||||
dependsOn: { editorWindow, settingsWindow, chatWindow, widgetsManager, noticeWindow, beatSync, autoUpdater, serverChannel, godotStageManager, mcpStdioManager, i18n, onboardingWindowManager },
|
||||
dependsOn: { editorWindow, settingsWindow, chatWindow, widgetsManager, noticeWindow, beatSync, autoUpdater, serverChannel, godotStageManager, mcpStdioManager, i18n, onboardingWindowManager, appleSpeechTranscription },
|
||||
build: async ({ dependsOn }) => setupMainWindow({
|
||||
...dependsOn,
|
||||
onWindowCreated: (window) => {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Lifecycle } from 'injeca'
|
||||
|
||||
import { createContext } from '@moeru/eventa/adapters/electron/main'
|
||||
import { setupAppleSpeechTranscription } from '@xsai-apple-speech/transcription-electron-plugin/main'
|
||||
import { ipcMain } from 'electron'
|
||||
import { isMacOS } from 'std-env'
|
||||
|
||||
/**
|
||||
* Registers the app-wide Apple Speech transport and its native Provider.
|
||||
*
|
||||
* The Electron main process owns native work. Renderer Providers communicate
|
||||
* with it through the Eventa handlers registered by the xsAI plugin.
|
||||
* Non-macOS hosts return an inactive service without loading the native package.
|
||||
*
|
||||
* Call stack:
|
||||
*
|
||||
* setupAppleSpeechTranscriptionService
|
||||
* -> {@link createContext}
|
||||
* -> {@link setupAppleSpeechTranscription}
|
||||
* -> {@link createAppleSpeechProvider}
|
||||
*/
|
||||
export async function setupAppleSpeechTranscriptionService(options: { lifecycle: Lifecycle }) {
|
||||
if (!isMacOS)
|
||||
return { dispose: () => Promise.resolve() }
|
||||
|
||||
const { createAppleSpeechProvider } = await import('@xsai-apple-speech/transcription-native')
|
||||
const eventa = createContext(ipcMain)
|
||||
const setup = setupAppleSpeechTranscription({
|
||||
context: eventa.context,
|
||||
provider: createAppleSpeechProvider(),
|
||||
})
|
||||
let disposal: Promise<void> | undefined
|
||||
|
||||
const dispose = () => {
|
||||
disposal ??= (async () => {
|
||||
// Stop accepting native work before the transport cancels remaining invokes.
|
||||
await setup.dispose()
|
||||
eventa.dispose()
|
||||
})()
|
||||
return disposal
|
||||
}
|
||||
|
||||
options.lifecycle.appHooks.onStop(dispose)
|
||||
|
||||
return { dispose }
|
||||
}
|
||||
Reference in New Issue
Block a user