@elizaos/app-core 2.0.0-beta.3 → 2.0.3-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-bridge.d.ts +27 -0
- package/agent-bridge.d.ts.map +1 -0
- package/agent-bridge.js +26 -0
- package/api/__tests__/sandbox-test-helpers.js +1 -1
- package/api/auth/audit.d.ts +1 -1
- package/api/auth/audit.js +1 -1
- package/api/auth/auth-context.d.ts +1 -1
- package/api/auth/auth-context.js +1 -1
- package/api/auth/bootstrap-token.d.ts +1 -1
- package/api/auth/bootstrap-token.js +2 -2
- package/api/auth/index.d.ts +9 -10
- package/api/auth/index.d.ts.map +1 -1
- package/api/auth/index.js +9 -10
- package/api/auth/passwords.js +2 -2
- package/api/auth/sensitive-rate-limit.d.ts +1 -4
- package/api/auth/sensitive-rate-limit.d.ts.map +1 -1
- package/api/auth/sensitive-rate-limit.js +6 -6
- package/api/auth/sessions.d.ts +1 -1
- package/api/auth/sessions.js +2 -2
- package/api/auth-bootstrap-routes.d.ts +7 -14
- package/api/auth-bootstrap-routes.d.ts.map +1 -1
- package/api/auth-bootstrap-routes.js +14 -27
- package/api/auth-pairing-routes.d.ts +17 -0
- package/api/auth-pairing-routes.d.ts.map +1 -0
- package/api/auth-pairing-routes.js +299 -0
- package/api/auth-session-routes.d.ts +2 -2
- package/api/auth-session-routes.d.ts.map +1 -1
- package/api/auth-session-routes.js +36 -15
- package/api/auth.d.ts +13 -20
- package/api/auth.d.ts.map +1 -1
- package/api/auth.js +32 -27
- package/api/automations-compat-routes.d.ts +1 -1
- package/api/automations-compat-routes.d.ts.map +1 -1
- package/api/automations-compat-routes.js +5 -5
- package/api/background-tasks-routes.d.ts +4 -0
- package/api/background-tasks-routes.d.ts.map +1 -0
- package/api/background-tasks-routes.js +63 -0
- package/api/catalog-routes.d.ts +1 -1
- package/api/catalog-routes.js +3 -3
- package/api/cloud-pair-route.d.ts +26 -0
- package/api/cloud-pair-route.d.ts.map +1 -0
- package/api/cloud-pair-route.js +222 -0
- package/api/cloud-voice-routes.d.ts +52 -0
- package/api/cloud-voice-routes.d.ts.map +1 -0
- package/api/cloud-voice-routes.js +50 -0
- package/api/compat-route-shared.d.ts +14 -7
- package/api/compat-route-shared.d.ts.map +1 -1
- package/api/compat-route-shared.js +27 -188
- package/api/credential-resolver.d.ts +2 -2
- package/api/credential-resolver.d.ts.map +1 -1
- package/api/credential-resolver.js +8 -2
- package/api/database-rows-compat-routes.d.ts +1 -1
- package/api/database-rows-compat-routes.d.ts.map +1 -1
- package/api/database-rows-compat-routes.js +69 -31
- package/api/dev-boot-history.d.ts +26 -0
- package/api/dev-boot-history.d.ts.map +1 -0
- package/api/dev-boot-history.js +69 -0
- package/api/dev-compat-routes.d.ts +6 -1
- package/api/dev-compat-routes.d.ts.map +1 -1
- package/api/dev-compat-routes.js +127 -4
- package/api/dev-console-log.d.ts +2 -2
- package/api/dev-console-log.d.ts.map +1 -1
- package/api/dev-console-log.js +8 -5
- package/api/dev-route-catalog.d.ts +58 -0
- package/api/dev-route-catalog.d.ts.map +1 -0
- package/api/dev-route-catalog.js +477 -0
- package/api/dev-stack.d.ts.map +1 -1
- package/api/dev-stack.js +6 -9
- package/api/drop-status-compat-route.d.ts +3 -0
- package/api/drop-status-compat-route.d.ts.map +1 -0
- package/api/drop-status-compat-route.js +12 -0
- package/api/first-run-routes.d.ts +4 -0
- package/api/first-run-routes.d.ts.map +1 -0
- package/api/first-run-routes.js +208 -0
- package/api/first-run-tts-route.d.ts +19 -0
- package/api/first-run-tts-route.d.ts.map +1 -0
- package/api/first-run-tts-route.js +59 -0
- package/api/internal-routes.d.ts +23 -0
- package/api/internal-routes.d.ts.map +1 -0
- package/api/internal-routes.js +203 -0
- package/api/ios-local-agent-transport.d.ts +36 -0
- package/api/ios-local-agent-transport.d.ts.map +1 -0
- package/api/ios-local-agent-transport.js +566 -0
- package/api/onboarding-voice-lines.d.ts +23 -0
- package/api/onboarding-voice-lines.d.ts.map +1 -0
- package/api/onboarding-voice-lines.js +8 -0
- package/api/perf-instrument.d.ts +43 -0
- package/api/perf-instrument.d.ts.map +1 -0
- package/api/perf-instrument.js +113 -0
- package/api/response.d.ts.map +1 -1
- package/api/response.js +14 -14
- package/api/runtime-mode-routes.d.ts +1 -1
- package/api/runtime-mode-routes.d.ts.map +1 -1
- package/api/runtime-mode-routes.js +2 -2
- package/api/secrets-inventory-routes.js +2 -2
- package/api/secrets-manager-routes.d.ts +1 -1
- package/api/secrets-manager-routes.d.ts.map +1 -1
- package/api/secrets-manager-routes.js +9 -10
- package/api/sensitive-request-routes.d.ts +2 -2
- package/api/sensitive-request-routes.js +5 -5
- package/api/server-config-filter.d.ts.map +1 -1
- package/api/server-config-filter.js +0 -1
- package/api/server-cors.d.ts.map +1 -1
- package/api/server-cors.js +13 -2
- package/api/server-first-run-helpers.d.ts +26 -0
- package/api/server-first-run-helpers.d.ts.map +1 -0
- package/api/server-first-run-helpers.js +268 -0
- package/api/server-security.js +1 -1
- package/api/server-startup.d.ts.map +1 -1
- package/api/server-startup.js +3 -4
- package/api/server-wallet-trade.js +1 -1
- package/api/server.d.ts +11 -11
- package/api/server.d.ts.map +1 -1
- package/api/server.js +227 -139
- package/api/setup-contract.d.ts +63 -0
- package/api/setup-contract.d.ts.map +1 -0
- package/api/setup-contract.js +39 -0
- package/api/training-benchmarks.d.ts +97 -0
- package/api/training-benchmarks.d.ts.map +1 -0
- package/api/training-benchmarks.js +329 -0
- package/api/workbench-compat-routes.d.ts +1 -1
- package/api/workbench-compat-routes.js +2 -2
- package/benchmark/cerebras-autowire.d.ts +28 -0
- package/benchmark/cerebras-autowire.d.ts.map +1 -0
- package/benchmark/cerebras-autowire.js +62 -0
- package/benchmark/lifeops-bench-handler.d.ts +36 -0
- package/benchmark/lifeops-bench-handler.d.ts.map +1 -1
- package/benchmark/lifeops-bench-handler.js +63 -1
- package/benchmark/lifeops-fake-backend.d.ts +39 -0
- package/benchmark/lifeops-fake-backend.d.ts.map +1 -1
- package/benchmark/lifeops-fake-backend.js +993 -21
- package/benchmark/mock-plugin.d.ts.map +1 -1
- package/benchmark/mock-plugin.js +0 -24
- package/benchmark/plugin.d.ts +2 -1
- package/benchmark/plugin.d.ts.map +1 -1
- package/benchmark/plugin.js +989 -68
- package/benchmark/replay-capture.d.ts +2 -2
- package/benchmark/replay-capture.d.ts.map +1 -1
- package/benchmark/replay-capture.js +3 -3
- package/benchmark/server-utils.d.ts +164 -11
- package/benchmark/server-utils.d.ts.map +1 -1
- package/benchmark/server-utils.js +625 -62
- package/benchmark/server.d.ts.map +1 -1
- package/benchmark/server.js +1962 -118
- package/boot-profile.d.ts +3 -0
- package/boot-profile.d.ts.map +1 -0
- package/boot-profile.js +30 -0
- package/browser.d.ts +23 -1
- package/browser.d.ts.map +1 -1
- package/browser.js +20 -1
- package/cli/argv.js +1 -1
- package/cli/banner.js +1 -1
- package/cli/command-format.js +2 -2
- package/cli/doctor/checks.d.ts.map +1 -1
- package/cli/doctor/checks.js +6 -6
- package/cli/plugins-cli.d.ts.map +1 -1
- package/cli/plugins-cli.js +82 -32
- package/cli/profile.d.ts.map +1 -1
- package/cli/profile.js +5 -4
- package/cli/program/build-program.js +4 -4
- package/cli/program/command-registry.d.ts.map +1 -1
- package/cli/program/command-registry.js +13 -11
- package/cli/program/help.js +5 -5
- package/cli/program/preaction.js +5 -5
- package/cli/program/register.auth.d.ts +27 -1
- package/cli/program/register.auth.d.ts.map +1 -1
- package/cli/program/register.auth.js +193 -12
- package/cli/program/register.capability-router.d.ts +29 -0
- package/cli/program/register.capability-router.d.ts.map +1 -0
- package/cli/program/register.capability-router.js +568 -0
- package/cli/program/register.config.js +1 -1
- package/cli/program/register.configure.d.ts.map +1 -1
- package/cli/program/register.configure.js +1 -1
- package/cli/program/register.dashboard.d.ts.map +1 -1
- package/cli/program/register.dashboard.js +17 -8
- package/cli/program/register.db.d.ts.map +1 -1
- package/cli/program/register.db.js +3 -4
- package/cli/program/register.doctor.js +7 -7
- package/cli/program/register.setup.d.ts.map +1 -1
- package/cli/program/register.setup.js +14 -10
- package/cli/program/register.start.d.ts.map +1 -1
- package/cli/program/register.start.js +5 -3
- package/cli/program/register.subclis.js +3 -3
- package/cli/program/register.update.d.ts +6 -0
- package/cli/program/register.update.d.ts.map +1 -1
- package/cli/program/register.update.js +58 -6
- package/cli/program.d.ts +1 -1
- package/cli/program.js +1 -1
- package/cli/run-main.js +4 -4
- package/config/app-config.d.ts +2 -0
- package/config/app-config.d.ts.map +1 -0
- package/config/app-config.js +1 -0
- package/connectors/capacitor-jsc.d.ts.map +1 -1
- package/connectors/capacitor-jsc.js +16 -10
- package/connectors/capacitor-quickjs.d.ts.map +1 -1
- package/connectors/capacitor-quickjs.js +18 -13
- package/connectors/capacitor-sqlite.d.ts.map +1 -1
- package/connectors/capacitor-sqlite.js +27 -12
- package/dispatch/approval-queue.d.ts +37 -0
- package/dispatch/approval-queue.d.ts.map +1 -0
- package/dispatch/approval-queue.js +25 -0
- package/dispatch/channel-registry.d.ts +30 -0
- package/dispatch/channel-registry.d.ts.map +1 -0
- package/dispatch/channel-registry.js +22 -0
- package/dispatch/connector-registry.d.ts +39 -0
- package/dispatch/connector-registry.d.ts.map +1 -0
- package/dispatch/connector-registry.js +24 -0
- package/dispatch/index.d.ts +14 -0
- package/dispatch/index.d.ts.map +1 -0
- package/dispatch/index.js +13 -0
- package/dispatch/send-policy.d.ts +36 -0
- package/dispatch/send-policy.d.ts.map +1 -0
- package/dispatch/send-policy.js +16 -0
- package/entry.js +28 -11
- package/first-run/first-run-config.d.ts +55 -0
- package/first-run/first-run-config.d.ts.map +1 -0
- package/first-run/first-run-config.js +178 -0
- package/first-run/runtime-target.d.ts +4 -0
- package/first-run/runtime-target.d.ts.map +1 -0
- package/first-run/runtime-target.js +13 -0
- package/index.d.ts +46 -34
- package/index.d.ts.map +1 -1
- package/index.js +53 -33
- package/package.json +166 -51
- package/packaging/PUBLISHING_GUIDE.md +20 -20
- package/packaging/debian/apt-repo-config/README.md +18 -0
- package/packaging/debian/apt-repo-config/conf/distributions +11 -0
- package/packaging/flatpak/README.md +26 -16
- package/packaging/flatpak/ai.elizaos.App.metainfo.xml +17 -12
- package/packaging/flatpak/ai.elizaos.App.store.yml +5 -5
- package/packaging/flatpak/ai.elizaos.App.yml +10 -24
- package/packaging/flatpak/elizaos-app-wrapper.store.sh +2 -2
- package/packaging/flatpak/generate-sources.sh +74 -0
- package/packaging/flatpak/node-sources.json +7930 -0
- package/packaging/inno/build-inno.ps1 +34 -9
- package/packaging/msix/AppxManifest.store.xml +1 -1
- package/packaging/msix/README.md +39 -19
- package/packaging/msix/build-msix.ps1 +44 -14
- package/packaging/snap/snapcraft.yaml +22 -21
- package/packaging/test-packaging.sh +2 -2
- package/permissions/types.d.ts +1 -1
- package/permissions/types.js +1 -1
- package/platform/elizaos-agent-browser-stub.d.ts +143 -0
- package/platform/elizaos-agent-browser-stub.d.ts.map +1 -0
- package/platform/elizaos-agent-browser-stub.js +157 -0
- package/platform/elizaos-plugin-elizacloud-browser-stub.d.ts +34 -0
- package/platform/elizaos-plugin-elizacloud-browser-stub.d.ts.map +1 -0
- package/platform/elizaos-plugin-elizacloud-browser-stub.js +51 -0
- package/platform/empty-node-module.d.ts +148 -0
- package/platform/empty-node-module.d.ts.map +1 -1
- package/platform/empty-node-module.js +140 -3
- package/platform/ios-runtime-backends.d.ts +83 -0
- package/platform/ios-runtime-backends.d.ts.map +1 -0
- package/platform/ios-runtime-backends.js +133 -0
- package/platform/ios-runtime-bridge.d.ts +15 -0
- package/platform/ios-runtime-bridge.d.ts.map +1 -0
- package/platform/ios-runtime-bridge.js +526 -0
- package/platform/native-library-policy.d.ts +23 -0
- package/platform/native-library-policy.d.ts.map +1 -0
- package/platform/native-library-policy.js +112 -0
- package/platform/native-plugin-entrypoints.d.ts +19 -0
- package/platform/native-plugin-entrypoints.d.ts.map +1 -0
- package/platform/native-plugin-entrypoints.js +29 -0
- package/platforms/android/README.md +68 -10
- package/platforms/android/app/build.gradle +291 -3
- package/platforms/android/app/capacitor.build.gradle +18 -1
- package/platforms/android/app/proguard-rules.pro +17 -2
- package/platforms/android/app/src/androidTest/java/ai/elizaos/app/ElizaOsInstrumentedTest.java +1 -1
- package/platforms/android/app/src/main/AndroidManifest.xml +335 -18
- package/platforms/android/app/src/main/assets/runners/eliza-tasks.js +177 -0
- package/platforms/android/app/src/main/elizavoice-jni/CMakeLists.txt +100 -0
- package/platforms/android/app/src/main/elizavoice-jni/elizavoice-jni.cpp +1629 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/AgentPlugin.java +111 -171
- package/platforms/android/app/src/main/java/ai/elizaos/app/AndroidVirtualizationBridge.java +284 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/BatteryOptimizationPlugin.java +95 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAccessibilityService.java +55 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAgentService.java +1283 -141
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAndroidSystemBridge.java +83 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAssistActivity.java +50 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBionicInferenceServer.java +740 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBootReceiver.java +90 -8
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBrowserActivity.java +2 -2
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaCalendarActivity.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaCameraActivity.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaClockActivity.java +2 -2
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaContactsActivity.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaDialActivity.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaInCallService.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaMmsReceiver.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaNativeBridge.java +22 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaNotificationListenerService.java +45 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaQuickActionsWidgetProvider.java +68 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaShareActivity.java +132 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaSmsComposeActivity.java +1 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaSmsGatewayService.java +268 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaSmsReceiver.java +12 -1
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaTasksWorker.java +194 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceCaptureService.java +198 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceNative.java +255 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoicePlugin.java +505 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceTileService.java +39 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaWorkScheduler.java +60 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/GatewayConnectionService.java +53 -19
- package/platforms/android/app/src/main/java/ai/elizaos/app/MainActivity.java +160 -33
- package/platforms/android/app/src/main/java/ai/elizaos/app/ResourceProbePlugin.java +169 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/VoiceCapturePlugin.java +119 -0
- package/platforms/android/app/src/main/res/drawable/eliza_widget_background.xml +10 -0
- package/platforms/android/app/src/main/res/drawable/eliza_widget_button_background.xml +13 -0
- package/platforms/android/app/src/main/res/drawable/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
- package/platforms/android/app/src/main/res/layout/eliza_quick_actions_widget.xml +86 -0
- package/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +2 -1
- package/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +2 -1
- package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png +0 -0
- package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/platforms/android/app/src/main/res/values/android_app_actions.xml +48 -0
- package/platforms/android/app/src/main/res/values/colors.xml +12 -0
- package/platforms/android/app/src/main/res/values/ic_launcher_background.xml +2 -2
- package/platforms/android/app/src/main/res/values/strings.xml +2 -2
- package/platforms/android/app/src/main/res/values/styles.xml +28 -1
- package/platforms/android/app/src/main/res/xml/eliza_accessibility_service.xml +9 -0
- package/platforms/android/app/src/main/res/xml/eliza_quick_actions_widget.xml +13 -0
- package/platforms/android/app/src/main/res/xml/shortcuts.xml +121 -0
- package/platforms/android/build.gradle +2 -2
- package/platforms/android/capacitor-cordova-android-plugins/build.gradle +9 -3
- package/platforms/android/capacitor-cordova-android-plugins/cordova.variables.gradle +6 -2
- package/platforms/android/capacitor-cordova-android-plugins/src/main/AndroidManifest.xml +7 -2
- package/platforms/android/capacitor-cordova-android-plugins/src/main/java/.gitkeep +0 -1
- package/platforms/android/capacitor.settings.gradle +66 -16
- package/platforms/android/gradle.properties +1 -0
- package/platforms/android/update-manifest/generate-manifest.mjs +97 -0
- package/platforms/android/update-manifest/schema.json +26 -0
- package/platforms/apple-store-entitlements.reviewed.json +155 -0
- package/platforms/electrobun/.generated/brand-config.json +3 -2
- package/platforms/electrobun/LICENSE +21 -0
- package/platforms/electrobun/README.md +15 -1
- package/platforms/electrobun/assets/appIcon.icns +0 -0
- package/platforms/electrobun/assets/appIcon.ico +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_128x128.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_128x128@2x.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_16x16.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_16x16@2x.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_256x256.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_256x256@2x.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_32x32.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_32x32@2x.png +0 -0
- package/platforms/electrobun/assets/appIcon.iconset/icon_512x512.png +0 -0
- package/platforms/electrobun/assets/brand-config.json +6 -6
- package/platforms/electrobun/biome.json +9 -9
- package/platforms/electrobun/docs/capability-collapse-matrix.json +318 -0
- package/platforms/electrobun/docs/capability-collapse-matrix.md +129 -0
- package/platforms/electrobun/docs/capability-routing.md +86 -0
- package/platforms/electrobun/docs/database-boot-policy.md +90 -0
- package/platforms/electrobun/docs/riscv64-port.md +175 -0
- package/platforms/electrobun/docs/startup-first-run-cleanup.md +18 -0
- package/platforms/electrobun/docs/trace-first-annotations.md +52 -0
- package/platforms/electrobun/docs/ui-boundary-audit.json +580 -0
- package/platforms/electrobun/docs/ui-boundary-audit.md +257 -0
- package/platforms/electrobun/electrobun.config.ts +591 -364
- package/platforms/electrobun/entitlements/JUSTIFICATIONS.md +141 -0
- package/platforms/electrobun/entitlements/README.md +34 -6
- package/platforms/electrobun/entitlements/mas-bun.entitlements +15 -0
- package/platforms/electrobun/entitlements/mas.entitlements +6 -4
- package/platforms/electrobun/native/macos/window-effects.mm +1526 -0
- package/platforms/electrobun/package.json +21 -13
- package/platforms/electrobun/remotes/fs/README.md +70 -0
- package/platforms/electrobun/remotes/fs/electrobun.config.ts +38 -0
- package/platforms/electrobun/remotes/fs/package.json +12 -0
- package/platforms/electrobun/remotes/fs/plugin.json +25 -0
- package/platforms/electrobun/remotes/fs/src/bun/errors.ts +57 -0
- package/platforms/electrobun/remotes/fs/src/bun/file-limits.ts +50 -0
- package/platforms/electrobun/remotes/fs/src/bun/fs-service.ts +389 -0
- package/platforms/electrobun/remotes/fs/src/bun/path-guard.ts +270 -0
- package/platforms/electrobun/remotes/fs/src/bun/protocol.ts +149 -0
- package/platforms/electrobun/remotes/fs/src/bun/worker.ts +174 -0
- package/platforms/electrobun/remotes/fs/src/dev/phase5-smoke.ts +171 -0
- package/platforms/electrobun/remotes/fs/src/web/index.html +8 -0
- package/platforms/electrobun/remotes/git/README.md +75 -0
- package/platforms/electrobun/remotes/git/electrobun.config.ts +44 -0
- package/platforms/electrobun/remotes/git/package.json +12 -0
- package/platforms/electrobun/remotes/git/plugin.json +31 -0
- package/platforms/electrobun/remotes/git/src/bun/errors.ts +69 -0
- package/platforms/electrobun/remotes/git/src/bun/git-command.ts +156 -0
- package/platforms/electrobun/remotes/git/src/bun/git-service.ts +446 -0
- package/platforms/electrobun/remotes/git/src/bun/operation-history.ts +124 -0
- package/platforms/electrobun/remotes/git/src/bun/protocol.ts +252 -0
- package/platforms/electrobun/remotes/git/src/bun/worker.ts +316 -0
- package/platforms/electrobun/remotes/git/src/dev/phase7-smoke.ts +141 -0
- package/platforms/electrobun/remotes/git/src/web/index.html +8 -0
- package/platforms/electrobun/remotes/local-model/README.md +138 -0
- package/platforms/electrobun/remotes/local-model/electrobun.config.ts +46 -0
- package/platforms/electrobun/remotes/local-model/package.json +12 -0
- package/platforms/electrobun/remotes/local-model/plugin.json +33 -0
- package/platforms/electrobun/remotes/local-model/src/bun/download-state.ts +115 -0
- package/platforms/electrobun/remotes/local-model/src/bun/eliza1-catalog.ts +405 -0
- package/platforms/electrobun/remotes/local-model/src/bun/errors.ts +74 -0
- package/platforms/electrobun/remotes/local-model/src/bun/hf-eliza1-client.ts +169 -0
- package/platforms/electrobun/remotes/local-model/src/bun/local-inference-api-client.ts +245 -0
- package/platforms/electrobun/remotes/local-model/src/bun/model-service.ts +490 -0
- package/platforms/electrobun/remotes/local-model/src/bun/protocol.ts +301 -0
- package/platforms/electrobun/remotes/local-model/src/bun/worker.ts +248 -0
- package/platforms/electrobun/remotes/local-model/src/dev/phase8-smoke.ts +116 -0
- package/platforms/electrobun/remotes/local-model/src/web/index.html +13 -0
- package/platforms/electrobun/remotes/pty/README.md +65 -0
- package/platforms/electrobun/remotes/pty/electrobun.config.ts +47 -0
- package/platforms/electrobun/remotes/pty/package.json +12 -0
- package/platforms/electrobun/remotes/pty/plugin.json +34 -0
- package/platforms/electrobun/remotes/pty/src/bun/errors.ts +57 -0
- package/platforms/electrobun/remotes/pty/src/bun/output-buffer.ts +127 -0
- package/platforms/electrobun/remotes/pty/src/bun/protocol.ts +192 -0
- package/platforms/electrobun/remotes/pty/src/bun/pty-service.ts +562 -0
- package/platforms/electrobun/remotes/pty/src/bun/worker.ts +218 -0
- package/platforms/electrobun/remotes/pty/src/dev/phase6-smoke.ts +127 -0
- package/platforms/electrobun/remotes/pty/src/web/index.html +8 -0
- package/platforms/electrobun/remotes/runtime/README.md +370 -0
- package/platforms/electrobun/remotes/runtime/electrobun.config.ts +48 -0
- package/platforms/electrobun/remotes/runtime/package.json +14 -0
- package/platforms/electrobun/remotes/runtime/plugin.json +30 -0
- package/platforms/electrobun/remotes/runtime/src/bun/api-client.ts +620 -0
- package/platforms/electrobun/remotes/runtime/src/bun/errors.ts +45 -0
- package/platforms/electrobun/remotes/runtime/src/bun/log-buffer.ts +33 -0
- package/platforms/electrobun/remotes/runtime/src/bun/protocol.ts +366 -0
- package/platforms/electrobun/remotes/runtime/src/bun/route-discovery.ts +419 -0
- package/platforms/electrobun/remotes/runtime/src/bun/runtime-manager.ts +423 -0
- package/platforms/electrobun/remotes/runtime/src/bun/sse-parser.ts +99 -0
- package/platforms/electrobun/remotes/runtime/src/bun/stream-manager.ts +887 -0
- package/platforms/electrobun/remotes/runtime/src/bun/worker.ts +1231 -0
- package/platforms/electrobun/remotes/runtime/src/dev/phase1-smoke.ts +34 -0
- package/platforms/electrobun/remotes/runtime/src/dev/phase2-smoke.ts +91 -0
- package/platforms/electrobun/remotes/runtime/src/dev/phase3-smoke.ts +137 -0
- package/platforms/electrobun/remotes/runtime/src/web/index.css +187 -0
- package/platforms/electrobun/remotes/runtime/src/web/index.html +76 -0
- package/platforms/electrobun/remotes/runtime/src/web/index.ts +192 -0
- package/platforms/electrobun/remotes/surface/README.md +201 -0
- package/platforms/electrobun/remotes/surface/electrobun.config.ts +38 -0
- package/platforms/electrobun/remotes/surface/package.json +12 -0
- package/platforms/electrobun/remotes/surface/plugin.json +28 -0
- package/platforms/electrobun/remotes/surface/src/bun/worker.ts +132 -0
- package/platforms/electrobun/remotes/surface/src/dev/phase4-smoke.ts +566 -0
- package/platforms/electrobun/remotes/surface/src/protocol/event-types.ts +84 -0
- package/platforms/electrobun/remotes/surface/src/protocol/runtime-client.ts +673 -0
- package/platforms/electrobun/remotes/surface/src/web/app.ts +595 -0
- package/platforms/electrobun/remotes/surface/src/web/index.css +460 -0
- package/platforms/electrobun/remotes/surface/src/web/index.html +466 -0
- package/platforms/electrobun/remotes/surface/src/web/index.ts +5 -0
- package/platforms/electrobun/remotes/surface/src/web/render.ts +455 -0
- package/platforms/electrobun/remotes/surface/src/web/state.ts +427 -0
- package/platforms/electrobun/scripts/build-macos-effects.sh +4 -0
- package/platforms/electrobun/scripts/ensure-build-folder.ts +28 -0
- package/platforms/electrobun/scripts/local-adhoc-sign-macos.ts +159 -159
- package/platforms/electrobun/scripts/postwrap-diagnostics.ts +424 -339
- package/platforms/electrobun/scripts/postwrap-sign-runtime-macos.ts +302 -271
- package/platforms/electrobun/scripts/smoke-test-windows.ps1 +17 -16
- package/platforms/electrobun/scripts/smoke-test.sh +5 -7
- package/platforms/electrobun/scripts/sync-web-assets.mjs +13 -13
- package/platforms/electrobun/scripts/verify-rpc-handlers.ts +109 -110
- package/platforms/electrobun/scripts/verify-windows-installer-proof.ps1 +3 -8
- package/platforms/electrobun/src/__stubs__/bun-ffi.ts +31 -31
- package/platforms/electrobun/src/__stubs__/electrobun-bun.ts +1 -1
- package/platforms/electrobun/src/agent-ready-state.ts +8 -8
- package/platforms/electrobun/src/agent-reset-from-main.test.ts +162 -0
- package/platforms/electrobun/src/agent-reset-from-main.ts +62 -62
- package/platforms/electrobun/src/agent-status-rpc.test.ts +95 -0
- package/platforms/electrobun/src/agent-status-rpc.ts +156 -0
- package/platforms/electrobun/src/api-base.test.ts +247 -0
- package/platforms/electrobun/src/api-base.ts +202 -93
- package/platforms/electrobun/src/application-menu-action-registry.ts +9 -9
- package/platforms/electrobun/src/application-menu.ts +341 -348
- package/platforms/electrobun/src/background-notice.ts +36 -36
- package/platforms/electrobun/src/boot-progress.test.ts +188 -0
- package/platforms/electrobun/src/boot-progress.ts +111 -0
- package/platforms/electrobun/src/brand-config.test.ts +39 -0
- package/platforms/electrobun/src/brand-config.ts +141 -129
- package/platforms/electrobun/src/bridge/browser-tabs-renderer-registry.ts +28 -28
- package/platforms/electrobun/src/bridge/electrobun-boot-config.ts +42 -0
- package/platforms/electrobun/src/bridge/electrobun-crypto-ready.ts +120 -0
- package/platforms/electrobun/src/bridge/electrobun-direct-rpc.ts +342 -357
- package/platforms/electrobun/src/bridge/electrobun-stub.ts +13 -13
- package/platforms/electrobun/src/browser-workspace-bridge-server.ts +285 -243
- package/platforms/electrobun/src/cloud-auth-window.ts +136 -136
- package/platforms/electrobun/src/cloud-disconnect-from-main.ts +90 -90
- package/platforms/electrobun/src/config-and-auth-rpc.test.ts +256 -0
- package/platforms/electrobun/src/config-and-auth-rpc.ts +302 -0
- package/platforms/electrobun/src/conversations-and-character-rpc.test.ts +185 -0
- package/platforms/electrobun/src/conversations-and-character-rpc.ts +131 -0
- package/platforms/electrobun/src/dashboard-rpc.test.ts +200 -0
- package/platforms/electrobun/src/dashboard-rpc.ts +344 -0
- package/platforms/electrobun/src/database/database-lock.ts +141 -0
- package/platforms/electrobun/src/database/database-mode.ts +149 -0
- package/platforms/electrobun/src/database/database-recovery.ts +72 -0
- package/platforms/electrobun/src/database/database-snapshot.ts +190 -0
- package/platforms/electrobun/src/database/database.test.ts +196 -0
- package/platforms/electrobun/src/database/index.ts +5 -0
- package/platforms/electrobun/src/database/pglite-paths.ts +100 -0
- package/platforms/electrobun/src/desktop-deep-link-events.test.ts +30 -0
- package/platforms/electrobun/src/desktop-deep-link-events.ts +17 -0
- package/platforms/electrobun/src/desktop-http-request.test.ts +102 -73
- package/platforms/electrobun/src/desktop-http-request.ts +97 -85
- package/platforms/electrobun/src/desktop-pill-config.test.ts +27 -0
- package/platforms/electrobun/src/desktop-pill-config.ts +40 -0
- package/platforms/electrobun/src/desktop-test-bridge-server.ts +232 -204
- package/platforms/electrobun/src/desktop-tray-config.test.ts +87 -0
- package/platforms/electrobun/src/desktop-tray-config.ts +84 -0
- package/platforms/electrobun/src/devtools-layout.ts +41 -41
- package/platforms/electrobun/src/diagnostic-format.test.ts +71 -0
- package/platforms/electrobun/src/diagnostic-format.ts +75 -36
- package/platforms/electrobun/src/dynamic-view-rpc-schema.test.ts +37 -0
- package/platforms/electrobun/src/dynamic-views/README.md +44 -0
- package/platforms/electrobun/src/dynamic-views/demo/agent-run-trace.html +135 -0
- package/platforms/electrobun/src/dynamic-views/errors.ts +29 -0
- package/platforms/electrobun/src/dynamic-views/host.test.ts +353 -0
- package/platforms/electrobun/src/dynamic-views/host.ts +332 -0
- package/platforms/electrobun/src/dynamic-views/index.ts +57 -0
- package/platforms/electrobun/src/dynamic-views/kiosk-canvas.ts +89 -0
- package/platforms/electrobun/src/dynamic-views/registry.test.ts +139 -0
- package/platforms/electrobun/src/dynamic-views/registry.ts +196 -0
- package/platforms/electrobun/src/dynamic-views/session-manager.test.ts +355 -0
- package/platforms/electrobun/src/dynamic-views/session-manager.ts +348 -0
- package/platforms/electrobun/src/dynamic-views/types.ts +105 -0
- package/platforms/electrobun/src/electrobun-boot-config.test.ts +50 -0
- package/platforms/electrobun/src/electrobun-config.test.ts +62 -0
- package/platforms/electrobun/src/electrobun-crypto-ready.test.ts +65 -0
- package/platforms/electrobun/src/electrobun-window-options.ts +25 -0
- package/platforms/electrobun/src/extension-rpc.test.ts +88 -0
- package/platforms/electrobun/src/extension-rpc.ts +102 -0
- package/platforms/electrobun/src/fatal-shutdown.test.ts +12 -16
- package/platforms/electrobun/src/fatal-shutdown.ts +1 -1
- package/platforms/electrobun/src/first-party-remotes.test.ts +169 -0
- package/platforms/electrobun/src/first-party-remotes.ts +297 -0
- package/platforms/electrobun/src/first-run-rpc.test.ts +192 -0
- package/platforms/electrobun/src/first-run-rpc.ts +146 -0
- package/platforms/electrobun/src/floating-chat-window.ts +181 -181
- package/platforms/electrobun/src/inbox-rpc.test.ts +123 -0
- package/platforms/electrobun/src/inbox-rpc.ts +158 -0
- package/platforms/electrobun/src/index.ts +2608 -2098
- package/platforms/electrobun/src/kiosk-mode.ts +50 -0
- package/platforms/electrobun/src/launch/index.ts +4 -0
- package/platforms/electrobun/src/launch/launch-dynamic-view.ts +37 -0
- package/platforms/electrobun/src/launch/launch-orchestrator.test.ts +224 -0
- package/platforms/electrobun/src/launch/launch-orchestrator.ts +456 -0
- package/platforms/electrobun/src/launch/launch-store.test.ts +97 -0
- package/platforms/electrobun/src/launch/launch-store.ts +134 -0
- package/platforms/electrobun/src/launch/types.ts +103 -0
- package/platforms/electrobun/src/launch/views/launch-diagnostics.html +205 -0
- package/platforms/electrobun/src/lifecycle/agent-ready-publish.test.ts +50 -0
- package/platforms/electrobun/src/lifecycle/agent-ready-publish.ts +27 -0
- package/platforms/electrobun/src/lifecycle/api-base-owner.test.ts +83 -0
- package/platforms/electrobun/src/lifecycle/api-base-owner.ts +63 -31
- package/platforms/electrobun/src/lifecycle/desktop-session-prime.ts +44 -44
- package/platforms/electrobun/src/logger.ts +14 -14
- package/platforms/electrobun/src/main-window-runtime.ts +83 -83
- package/platforms/electrobun/src/main-window-session.test.ts +109 -0
- package/platforms/electrobun/src/main-window-session.ts +87 -51
- package/platforms/electrobun/src/menu-reset-from-main.ts +158 -158
- package/platforms/electrobun/src/native/agent-env.test.ts +52 -0
- package/platforms/electrobun/src/native/agent-runtime-layout.test.ts +42 -0
- package/platforms/electrobun/src/native/agent-state-dir.test.ts +91 -0
- package/platforms/electrobun/src/native/agent.ts +2133 -1682
- package/platforms/electrobun/src/native/auth-bridge.test.ts +67 -0
- package/platforms/electrobun/src/native/auth-bridge.ts +464 -360
- package/platforms/electrobun/src/native/browser-workspace.ts +723 -471
- package/platforms/electrobun/src/native/camera.ts +50 -50
- package/platforms/electrobun/src/native/canvas.ts +444 -445
- package/platforms/electrobun/src/native/credentials.ts +678 -616
- package/platforms/electrobun/src/native/desktop-window.test.ts +416 -0
- package/platforms/electrobun/src/native/desktop.ts +2200 -2156
- package/platforms/electrobun/src/native/editor-bridge.ts +201 -201
- package/platforms/electrobun/src/native/file-watcher.ts +154 -154
- package/platforms/electrobun/src/native/gateway.ts +179 -180
- package/platforms/electrobun/src/native/gpu-window.ts +256 -256
- package/platforms/electrobun/src/native/index.ts +82 -74
- package/platforms/electrobun/src/native/location.test.ts +44 -0
- package/platforms/electrobun/src/native/location.ts +90 -80
- package/platforms/electrobun/src/native/loopback-port.ts +60 -60
- package/platforms/electrobun/src/native/mac-window-effects.ts +166 -104
- package/platforms/electrobun/src/native/music-player.ts +38 -38
- package/platforms/electrobun/src/native/permissions-shared.ts +249 -150
- package/platforms/electrobun/src/native/permissions.ts +301 -208
- package/platforms/electrobun/src/native/power-state.ts +129 -129
- package/platforms/electrobun/src/native/remote-plugin-host.test.ts +1394 -0
- package/platforms/electrobun/src/native/remote-plugin-host.ts +1541 -0
- package/platforms/electrobun/src/native/screencapture.ts +667 -573
- package/platforms/electrobun/src/native/steward.ts +207 -204
- package/platforms/electrobun/src/native/swabble.ts +68 -324
- package/platforms/electrobun/src/native/talkmode.ts +253 -422
- package/platforms/electrobun/src/native/webgpu-browser-support.test.ts +18 -0
- package/platforms/electrobun/src/native/webgpu-browser-support.ts +165 -147
- package/platforms/electrobun/src/native-onboarding.ts +270 -0
- package/platforms/electrobun/src/onboarding-overlay-window.ts +141 -0
- package/platforms/electrobun/src/persisted-deployment.ts +91 -0
- package/platforms/electrobun/src/pill-window.test.ts +91 -0
- package/platforms/electrobun/src/pill-window.ts +99 -0
- package/platforms/electrobun/src/preload-validation.ts +44 -44
- package/platforms/electrobun/src/preload.js +1 -1
- package/platforms/electrobun/src/print-electrobun-dev-settings-banner.ts +120 -120
- package/platforms/electrobun/src/renderer-api-proxy.test.ts +73 -0
- package/platforms/electrobun/src/renderer-api-proxy.ts +86 -0
- package/platforms/electrobun/src/renderer-static.test.ts +53 -0
- package/platforms/electrobun/src/renderer-static.ts +144 -57
- package/platforms/electrobun/src/rpc-handler-slices.ts +121 -0
- package/platforms/electrobun/src/rpc-handlers.test.ts +267 -0
- package/platforms/electrobun/src/rpc-handlers.ts +1306 -913
- package/platforms/electrobun/src/rpc-parse-utils.ts +57 -0
- package/platforms/electrobun/src/rpc-port-resolver.test.ts +45 -0
- package/platforms/electrobun/src/rpc-port-resolver.ts +31 -0
- package/platforms/electrobun/src/rpc-schema.ts +2556 -1619
- package/platforms/electrobun/src/runtime-layout.ts +105 -105
- package/platforms/electrobun/src/runtime-permissions.ts +95 -95
- package/platforms/electrobun/src/runtime-rpc.test.ts +126 -0
- package/platforms/electrobun/src/runtime-rpc.ts +237 -0
- package/platforms/electrobun/src/screenshot-dev-server.ts +87 -87
- package/platforms/electrobun/src/settings-mutations-rpc.test.ts +193 -0
- package/platforms/electrobun/src/settings-mutations-rpc.ts +220 -0
- package/platforms/electrobun/src/startup-trace.ts +274 -270
- package/platforms/electrobun/src/subscription-rpc.test.ts +89 -0
- package/platforms/electrobun/src/subscription-rpc.ts +192 -0
- package/platforms/electrobun/src/surface-windows.test.ts +355 -0
- package/platforms/electrobun/src/surface-windows.ts +410 -410
- package/platforms/electrobun/src/trace/README.md +73 -0
- package/platforms/electrobun/src/trace/errors.ts +21 -0
- package/platforms/electrobun/src/trace/index.ts +40 -0
- package/platforms/electrobun/src/trace/trace-dynamic-view.ts +40 -0
- package/platforms/electrobun/src/trace/trace-host-requests.ts +473 -0
- package/platforms/electrobun/src/trace/trace-service.test.ts +186 -0
- package/platforms/electrobun/src/trace/trace-service.ts +324 -0
- package/platforms/electrobun/src/trace/trace-store.test.ts +141 -0
- package/platforms/electrobun/src/trace/trace-store.ts +551 -0
- package/platforms/electrobun/src/trace/types.ts +250 -0
- package/platforms/electrobun/src/trace/views/agent-run-trace.html +311 -0
- package/platforms/electrobun/src/types/web-speech.d.ts +28 -28
- package/platforms/electrobun/src/types.ts +5 -5
- package/platforms/electrobun/src/update-availability.test.ts +72 -0
- package/platforms/electrobun/src/update-availability.ts +90 -0
- package/platforms/electrobun/src/update-rpc.test.ts +83 -0
- package/platforms/electrobun/src/update-rpc.ts +123 -0
- package/platforms/electrobun/src/voice/README.md +184 -0
- package/platforms/electrobun/src/voice/errors.ts +42 -0
- package/platforms/electrobun/src/voice/index.ts +78 -0
- package/platforms/electrobun/src/voice/types.ts +316 -0
- package/platforms/electrobun/src/voice/voice-host-requests.ts +259 -0
- package/platforms/electrobun/src/voice/voice-latency-budget.test.ts +66 -0
- package/platforms/electrobun/src/voice/voice-latency-budget.ts +243 -0
- package/platforms/electrobun/src/voice/voice-live-validation.test.ts +357 -0
- package/platforms/electrobun/src/voice/voice-live-validation.ts +838 -0
- package/platforms/electrobun/src/voice/voice-pipeline.ts +250 -0
- package/platforms/electrobun/src/voice/voice-playback-adapter.ts +31 -0
- package/platforms/electrobun/src/voice/voice-runtime-adapter.test.ts +213 -0
- package/platforms/electrobun/src/voice/voice-runtime-adapter.ts +687 -0
- package/platforms/electrobun/src/voice/voice-service.test.ts +587 -0
- package/platforms/electrobun/src/voice/voice-service.ts +1067 -0
- package/platforms/electrobun/src/voice/voice-stream-coordinator.test.ts +115 -0
- package/platforms/electrobun/src/voice/voice-stream-coordinator.ts +270 -0
- package/platforms/electrobun/src/voice/voice-trace.ts +97 -0
- package/platforms/electrobun/src/voice/voice-tts-chunker.test.ts +91 -0
- package/platforms/electrobun/src/voice/voice-tts-chunker.ts +194 -0
- package/platforms/electrobun/src/windows-cef-profile.ts +88 -88
- package/platforms/electrobun/tsconfig.json +88 -12
- package/platforms/electrobun/update-channels.json +22 -0
- package/platforms/electrobun/vitest.electrobun.config.ts +72 -42
- package/platforms/ios/App/App/App.entitlements +4 -0
- package/platforms/ios/App/App/AppDelegate.swift +80 -18
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ios-marketing-1024.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-20x20@1x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-20x20@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-29x29@1x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-29x29@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-40x40@1x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-40x40@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-76x76@1x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-76x76@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-83_5x83_5@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-20x20@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-20x20@3x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-29x29@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-29x29@3x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-40x40@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-40x40@3x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-60x60@2x.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-60x60@3x.png +0 -0
- package/platforms/ios/App/App/Base.lproj/LaunchScreen.storyboard +4 -9
- package/platforms/ios/App/App/ComputerUseBridge.swift +589 -0
- package/platforms/ios/App/App/DeviceActivityMonitorExtension/DeviceActivityMonitorExtension.entitlements +12 -0
- package/platforms/ios/App/App/DeviceActivityMonitorExtension/DeviceActivityMonitorExtension.swift +34 -0
- package/platforms/ios/App/App/DeviceActivityMonitorExtension/Info.plist +29 -0
- package/platforms/ios/App/App/DeviceActivityReportExtension/DeviceActivityReportExtension.entitlements +12 -0
- package/platforms/ios/App/App/DeviceActivityReportExtension/DeviceActivityReportExtension.swift +53 -0
- package/platforms/ios/App/App/DeviceActivityReportExtension/Info.plist +27 -0
- package/platforms/ios/App/App/ElizaAppIntents.swift +183 -0
- package/platforms/ios/App/App/ElizaIntentPlugin.swift +342 -5
- package/platforms/ios/App/App/Info.plist +17 -1
- package/platforms/ios/App/App/runners/eliza-tasks.js +177 -0
- package/platforms/ios/App/App.xcodeproj/project.pbxproj +262 -6
- package/platforms/ios/App/BroadcastExtension/SampleHandler.swift +100 -0
- package/platforms/ios/App/Podfile +5 -0
- package/platforms/ios/App/Podfile.lock +83 -59
- package/register-runtime-hooks.js +11 -5
- package/registry/index.d.ts +1 -5
- package/registry/index.d.ts.map +1 -1
- package/registry/index.js +10 -68
- package/runtime/android-avf-microdroid-bridge.d.ts +29 -0
- package/runtime/android-avf-microdroid-bridge.d.ts.map +1 -0
- package/runtime/android-avf-microdroid-bridge.js +149 -0
- package/runtime/api-dev-settings-banner.d.ts.map +1 -1
- package/runtime/api-dev-settings-banner.js +5 -13
- package/runtime/app-core-runtime-hooks.d.ts +21 -0
- package/runtime/app-core-runtime-hooks.d.ts.map +1 -0
- package/runtime/app-core-runtime-hooks.js +10 -0
- package/runtime/autonomy-policy.d.ts +2 -0
- package/runtime/autonomy-policy.d.ts.map +1 -0
- package/runtime/autonomy-policy.js +4 -0
- package/runtime/bundled-fused-lib.d.ts +36 -0
- package/runtime/bundled-fused-lib.d.ts.map +1 -0
- package/runtime/bundled-fused-lib.js +77 -0
- package/runtime/channel-plugin-map.d.ts +1 -5
- package/runtime/channel-plugin-map.d.ts.map +1 -1
- package/runtime/channel-plugin-map.js +11 -31
- package/runtime/desktop/AppWindowRenderer.d.ts +17 -0
- package/runtime/desktop/AppWindowRenderer.d.ts.map +1 -0
- package/runtime/desktop/AppWindowRenderer.js +360 -0
- package/runtime/desktop/DesktopSurfaceNavigationRuntime.d.ts +2 -0
- package/runtime/desktop/DesktopSurfaceNavigationRuntime.d.ts.map +1 -0
- package/runtime/desktop/DesktopSurfaceNavigationRuntime.js +41 -0
- package/runtime/desktop/DesktopTrayRuntime.d.ts +2 -0
- package/runtime/desktop/DesktopTrayRuntime.d.ts.map +1 -0
- package/runtime/desktop/DesktopTrayRuntime.js +174 -0
- package/runtime/desktop/DetachedShellRoot.d.ts +10 -0
- package/runtime/desktop/DetachedShellRoot.d.ts.map +1 -0
- package/runtime/desktop/DetachedShellRoot.js +111 -0
- package/runtime/desktop/index.d.ts +6 -0
- package/runtime/desktop/index.d.ts.map +1 -0
- package/runtime/desktop/index.js +5 -0
- package/runtime/desktop/tray-menu.d.ts +20 -0
- package/runtime/desktop/tray-menu.d.ts.map +1 -0
- package/runtime/desktop/tray-menu.js +143 -0
- package/runtime/dev-server.d.ts +1 -1
- package/runtime/dev-server.d.ts.map +1 -1
- package/runtime/dev-server.js +104 -19
- package/runtime/eliza.d.ts +75 -1
- package/runtime/eliza.d.ts.map +1 -1
- package/runtime/eliza.js +606 -122
- package/runtime/ensure-text-to-speech-handler.d.ts.map +1 -1
- package/runtime/ensure-text-to-speech-handler.js +10 -3
- package/runtime/mobile-safe-runtime.d.ts +181 -2
- package/runtime/mobile-safe-runtime.d.ts.map +1 -1
- package/runtime/mobile-safe-runtime.js +1019 -12
- package/runtime/mode/remote-forwarder.d.ts.map +1 -1
- package/runtime/mode/remote-forwarder.js +2 -2
- package/runtime/mode/route-mode-guard.d.ts +2 -3
- package/runtime/mode/route-mode-guard.d.ts.map +1 -1
- package/runtime/mode/route-mode-guard.js +4 -5
- package/runtime/mode/route-mode-matrix.d.ts +1 -1
- package/runtime/mode/route-mode-matrix.d.ts.map +1 -1
- package/runtime/mode/route-mode-matrix.js +14 -1
- package/runtime/mode/runtime-mode.d.ts +1 -1
- package/runtime/mode/runtime-mode.js +1 -1
- package/runtime/runtime-bootstrap-policy.d.ts.map +1 -1
- package/runtime/runtime-bootstrap-policy.js +14 -2
- package/runtime/telegram-standalone-handler.d.ts.map +1 -1
- package/runtime/telegram-standalone-handler.js +10 -9
- package/runtime/tts-cache-wiring.d.ts +29 -0
- package/runtime/tts-cache-wiring.d.ts.map +1 -0
- package/runtime/tts-cache-wiring.js +114 -0
- package/runtime/voice-warmup.d.ts +66 -0
- package/runtime/voice-warmup.d.ts.map +1 -0
- package/runtime/voice-warmup.js +101 -0
- package/scripts/android-sms-gateway-template.test.mjs +1014 -0
- package/scripts/aosp/README.md +29 -16
- package/scripts/aosp/compile-libllama-zig-pin.test.mjs +147 -0
- package/scripts/aosp/compile-libllama.mjs +1750 -267
- package/scripts/aosp/compile-libllama.test.mjs +133 -0
- package/scripts/aosp/compile-shim.mjs +68 -19
- package/scripts/aosp/deploy-pixel.mjs +405 -0
- package/scripts/aosp/lib/load-variant-config.mjs +3 -3
- package/scripts/aosp/llama-cpp-patches/README.md +8 -8
- package/scripts/aosp/llama-cpp-patches/apply-patches.mjs +23 -6
- package/scripts/aosp/llama-cpp-patches/polarquant/README.md +37 -0
- package/scripts/aosp/llama-cpp-patches/qjl/README.md +37 -0
- package/scripts/aosp/seccomp-shim/sigsys-handler-arm64.c +169 -0
- package/scripts/aosp/seccomp-shim/sigsys-handler-riscv64.c +217 -0
- package/scripts/aosp/smoke-cuttlefish.mjs +34 -4
- package/scripts/aosp/stage-default-models.mjs +59 -35
- package/scripts/aosp/stage-default-models.test.mjs +23 -0
- package/scripts/aosp/variant-config-schema.ts +2 -2
- package/scripts/assert-required-bundled-packages.test.ts +555 -0
- package/scripts/audit-apple-store-sandbox.mjs +146 -0
- package/scripts/audit-live-test-surface.mjs +5 -2
- package/scripts/build-capacitor-app.mjs +21 -0
- package/scripts/build-flatpak.mjs +5 -5
- package/scripts/build-helpers/arm64-simd.mjs +72 -0
- package/scripts/build-helpers/omnivoice-merged.mjs +87 -0
- package/scripts/build-helpers/verify-fused-symbols.mjs +600 -0
- package/scripts/build-helpers/verify-fused-symbols.test.mjs +0 -0
- package/scripts/build-image.sh +1 -1
- package/scripts/build-llama-cpp-mtp.mjs +488 -0
- package/scripts/build-native-plugins.mjs +230 -18
- package/scripts/build-patched-electrobun-cli.mjs +68 -10
- package/scripts/build-win.mjs +1 -1
- package/scripts/bun-riscv64/Dockerfile +418 -0
- package/scripts/bun-riscv64/README.md +316 -0
- package/scripts/bun-riscv64/build.sh +469 -0
- package/scripts/bun-riscv64/bun-patches/0001-config-add-riscv64-arch.patch +74 -0
- package/scripts/bun-riscv64/bun-patches/0002-flags-add-riscv64-march-mabi.patch +16 -0
- package/scripts/bun-riscv64/bun-patches/0003-zig-add-riscv64-target-triple-and-cpu.patch +26 -0
- package/scripts/bun-riscv64/bun-patches/0004-webkit-force-local-mode-on-riscv64.patch +33 -0
- package/scripts/bun-riscv64/bun-patches/0005-tinycc-disable-on-riscv64.patch +16 -0
- package/scripts/bun-riscv64/bun-patches/0006-build-add-riscv64-cli-validation.patch +15 -0
- package/scripts/bun-riscv64/bun-patches/0007-deps-per-dep-riscv64-checks.patch +24 -0
- package/scripts/bun-riscv64/bun-patches/0008-source-stabilize-riscv64-musl-build.patch +226 -0
- package/scripts/bun-riscv64/bun-patches/0009-disable-wasm-streaming-hooks-for-c-loop.patch +162 -0
- package/scripts/bun-riscv64/bun-patches/0010-disable-inspector-profiler-for-riscv64-c-loop.patch +80 -0
- package/scripts/bun-riscv64/bun-patches/0011-process-arch-add-riscv64.patch +23 -0
- package/scripts/bun-riscv64/bun-patches/0012-cpu-features-add-riscv64-fallback.patch +13 -0
- package/scripts/bun-riscv64/bun-patches/0013-disable-console-inspector-hooks-for-riscv64-c-loop.patch +43 -0
- package/scripts/bun-riscv64/bun-patches/0014-disable-custom-inspector-dispatchers-on-riscv64.patch +127 -0
- package/scripts/bun-riscv64/bun-patches/0015-disable-jsc-profiler-builtins-on-riscv64.patch +75 -0
- package/scripts/bun-riscv64/bun-patches/0016-node-vm-disable-jit-cached-data-on-riscv64-c-loop.patch +96 -0
- package/scripts/bun-riscv64/bun-patches/0017-disable-performance-domjit-signature-on-riscv64-c-loop.patch +34 -0
- package/scripts/bun-riscv64/bun-patches/0018-fix-serialized-script-identifier-big-endian-path.patch +19 -0
- package/scripts/bun-riscv64/bun-patches/0019-add-wtf-timer-fire-bridge-for-c-loop.patch +24 -0
- package/scripts/bun-riscv64/bun-patches/0020-run-riscv64-smoke-test-under-qemu.patch +13 -0
- package/scripts/bun-riscv64/bun-patches/0021-fix-riscv64-linux-open-flags.patch +25 -0
- package/scripts/bun-riscv64/bun-patches/0022-zlib-riscv64-generic-kernels.patch +25 -0
- package/scripts/bun-riscv64/bun-patches/README.md +127 -0
- package/scripts/bun-riscv64/bun-version.json +202 -0
- package/scripts/bun-riscv64/run-build.sh +162 -0
- package/scripts/bun-riscv64/rust-core/0001-riscv64-rust-core-port.patch +868 -0
- package/scripts/bun-riscv64/rust-core/0002-second-wave-riscv64-source-gaps.patch +130 -0
- package/scripts/bun-riscv64/rust-core/0003-third-wave-riscv64-crash-handler-gaps.patch +78 -0
- package/scripts/bun-riscv64/rust-core/0004-rust-target-cpu-riscv64.patch +39 -0
- package/scripts/bun-riscv64/rust-core/0005-fifth-wave-riscv64-source-gaps.patch +96 -0
- package/scripts/bun-riscv64/rust-core/0006-cpp-wasm-and-inspector-guards-riscv64.patch +91 -0
- package/scripts/bun-riscv64/rust-core/0007-bun-alloc-max-align-t-riscv64.patch +36 -0
- package/scripts/bun-riscv64/rust-core/0008-workspace-lints-warn-not-deny-riscv64.patch +75 -0
- package/scripts/bun-riscv64/rust-core/0009-zigglobalobject-wasm-streaming-guards-riscv64.patch +109 -0
- package/scripts/bun-riscv64/rust-core/0010-tcc-externs-stub-on-riscv64.patch +62 -0
- package/scripts/bun-riscv64/rust-core/0011-clippy-ptr-cast-lints-warn-riscv64.patch +61 -0
- package/scripts/bun-riscv64/rust-core/README.md +80 -0
- package/scripts/bun-riscv64/rust-core/webkit-patches/0003-disable-dfg-ftl-on-riscv64.patch +60 -0
- package/scripts/bun-riscv64/rust-core/webkit-patches/0004-riscv64-do-not-force-wasm-in-c-loop.patch +31 -0
- package/scripts/bun-riscv64/rust-core/webkit-patches/0005-domjit-effect-allow-no-dfg-c-loop.patch +40 -0
- package/scripts/bun-riscv64/rust-core/webkit-patches/0006-disable-usewasm-when-webassembly-compiled-out.patch +33 -0
- package/scripts/bun-riscv64/rust-core/webkit-patches/0007-restore-dropped-includes-and-llint-fwd-decl.patch +31 -0
- package/scripts/bun-riscv64/validate.sh +264 -0
- package/scripts/bun-riscv64/webkit-patches/0001-cherry-pick-llint-riscv64.recipe +155 -0
- package/scripts/bun-riscv64/webkit-patches/0002-cherry-pick-baseline-jit-riscv64.recipe +40 -0
- package/scripts/bun-riscv64/webkit-patches/0003-disable-dfg-ftl-on-riscv64.patch +60 -0
- package/scripts/bun-riscv64/webkit-patches/0004-riscv64-do-not-force-wasm-in-c-loop.patch +31 -0
- package/scripts/bun-riscv64/webkit-patches/0005-domjit-effect-allow-no-dfg-c-loop.patch +40 -0
- package/scripts/bun-riscv64/webkit-patches/0006-disable-usewasm-when-webassembly-compiled-out.patch +33 -0
- package/scripts/bun-riscv64/webkit-patches/0007-restore-dropped-includes-and-llint-fwd-decl.patch +72 -0
- package/scripts/bun-riscv64/webkit-patches/README.md +146 -0
- package/scripts/check-homepage-public-readiness.mjs +353 -0
- package/scripts/check-homepage-release-data.mjs +110 -0
- package/scripts/check-i18n.mjs +1 -1
- package/scripts/check-real-local-chat.ts +147 -0
- package/scripts/check-real-local-provisioning.ts +104 -0
- package/scripts/check-real-local-reset.ts +249 -0
- package/scripts/check-sms-gateway-completion-audit.mjs +428 -0
- package/scripts/check-sms-gateway-readiness.mjs +266 -0
- package/scripts/clean-repo.mjs +5 -5
- package/scripts/codesign-mas.mjs +222 -16
- package/scripts/collect-docker-runtime-deps.mjs +229 -0
- package/scripts/continue-sms-gateway-work.mjs +121 -0
- package/scripts/copy-runtime-node-modules.ts +1050 -195
- package/scripts/deploy-cloud-api-production-gateway.mjs +52 -0
- package/scripts/desktop-build.mjs +965 -98
- package/scripts/dev-platform.mjs +346 -102
- package/scripts/dev-startup-smoke.mjs +248 -0
- package/scripts/dev-ui.mjs +418 -176
- package/scripts/disable-local-eliza-workspace.mjs +35 -0
- package/scripts/docker-ci-smoke.sh +465 -96
- package/scripts/docker-entrypoint.sh +62 -1
- package/scripts/docker-entrypoint.test.ts +283 -0
- package/scripts/ensure-avatars.mjs +2 -2
- package/scripts/ensure-electrobun-core.mjs +1 -1
- package/scripts/ensure-generated-core-proto-js.mjs +1 -1
- package/scripts/ensure-type-package-aliases.mjs +62 -5
- package/scripts/ensure-vision-deps.mjs +20 -1
- package/scripts/entry.ts +1 -1
- package/scripts/ffi-stub/Makefile +64 -0
- package/scripts/ffi-stub/README.md +391 -0
- package/scripts/ffi-stub/asr-ffi-smoke.ts +139 -0
- package/scripts/ffi-stub/ffi-stub.c +539 -0
- package/scripts/ffi-stub/ffi.h +538 -0
- package/scripts/ffi-stub/libelizainference_stub.so +0 -0
- package/scripts/ffi-stub/tts-stream-ffi-smoke.ts +349 -0
- package/scripts/generate-first-run-voicelines.mjs +194 -0
- package/scripts/generate-plugin-index.js +4 -3
- package/scripts/generate-static-asset-manifest.mjs +1 -1
- package/scripts/i18n-dynamic-keys.json +5 -5
- package/scripts/init-submodules.mjs +2 -2
- package/scripts/install-android-sms-gateway.md +177 -0
- package/scripts/install-android-sms-gateway.mjs +1088 -0
- package/scripts/ios-xcframework/README.md +74 -72
- package/scripts/ios-xcframework/build-xcframework.mjs +204 -43
- package/scripts/ios-xcframework/run-physical-device-smoke.mjs +1943 -0
- package/scripts/ios-xcframework/runtime-symbol-shim.c +450 -0
- package/scripts/kernel-patches/cpu-polar-kernels.mjs +441 -0
- package/scripts/kernel-patches/cpu-simd-kernels.mjs +253 -0
- package/scripts/kernel-patches/cpu-thread-parallelism.mjs +368 -0
- package/scripts/kernel-patches/cuda-kernels.mjs +117 -0
- package/scripts/kernel-patches/metal-kernels.mjs +1698 -109
- package/scripts/kernel-patches/server-omnivoice-route.mjs +718 -0
- package/scripts/kernel-patches/server-structured-output.mjs +279 -0
- package/scripts/kernel-patches/vulkan-dispatch-log.mjs +166 -0
- package/scripts/kernel-patches/vulkan-dispatch-log.test.mjs +50 -0
- package/scripts/kernel-patches/vulkan-dispatch-patches/01-vulkan-shaders-gen.patch +30 -16
- package/scripts/kernel-patches/vulkan-dispatch-patches/02-ggml-vulkan-pipelines.patch +75 -30
- package/scripts/kernel-patches/vulkan-kernels.mjs +800 -49
- package/scripts/lib/agent-source-watcher.mjs +173 -0
- package/scripts/lib/agent-source-watcher.test.mjs +184 -0
- package/scripts/lib/api-supervisor.mjs +78 -9
- package/scripts/lib/api-supervisor.test.mjs +121 -0
- package/scripts/lib/app-dir.mjs +2 -16
- package/scripts/lib/apple-entitlement-audit.mjs +655 -0
- package/scripts/lib/apple-entitlement-audit.test.mjs +144 -0
- package/scripts/lib/artifact-staleness.d.mts +33 -0
- package/scripts/lib/artifact-staleness.mjs +122 -0
- package/scripts/lib/artifact-staleness.test.mts +98 -0
- package/scripts/lib/bun-version-guard.mjs +13 -13
- package/scripts/lib/capacitor-plugin-build-needed.mjs +4 -3
- package/scripts/lib/capacitor-plugin-names.mjs +30 -14
- package/scripts/lib/desktop-preflight.mjs +9 -5
- package/scripts/lib/desktop-startup-embedding-warmup-policy.mjs +51 -0
- package/scripts/lib/desktop-startup-embedding-warmup-policy.test.mjs +55 -0
- package/scripts/lib/duet-bridge.d.mts +63 -0
- package/scripts/lib/duet-bridge.mjs +193 -0
- package/scripts/lib/ios-plist-url-scheme.mjs +80 -0
- package/scripts/lib/mobile-build-decisions.mjs +97 -0
- package/scripts/lib/node-path-env.mjs +4 -2
- package/scripts/lib/orchestrator-desktop-dev-banner.mjs +12 -3
- package/scripts/lib/patch-bun-exports.mjs +90 -27
- package/scripts/lib/patch-bun-exports.test.mjs +79 -0
- package/scripts/lib/renderer-build-action.mjs +35 -0
- package/scripts/lib/renderer-build-action.test.mjs +70 -0
- package/scripts/lib/renderer-build-manifest.d.mts +65 -0
- package/scripts/lib/renderer-build-manifest.mjs +257 -0
- package/scripts/lib/renderer-build-manifest.test.mts +277 -0
- package/scripts/lib/stage-android-agent.mjs +757 -99
- package/scripts/lib/sync-eliza-env-aliases.mjs +3 -25
- package/scripts/lib/ui-smoke-stub-decision.mjs +33 -0
- package/scripts/lib/ui-smoke-stub-decision.test.mjs +46 -0
- package/scripts/lib/verify-ondevice-artifact.d.mts +16 -0
- package/scripts/lib/verify-ondevice-artifact.mjs +61 -0
- package/scripts/lib/verify-ondevice-artifact.test.mts +98 -0
- package/scripts/lib/vite-renderer-dist-stale.mjs +5 -0
- package/scripts/lib/voice-latency-report.mjs +154 -0
- package/scripts/lib/websocket-pending-queue.ts +92 -0
- package/scripts/lifeops-prompt-benchmark.ts +21 -12
- package/scripts/link-docker-local-app-packages.mjs +109 -36
- package/scripts/local-stt-bench.ts +192 -0
- package/scripts/maintain-cloud-api-production-gateway.mjs +54 -0
- package/scripts/mas-smoke.mjs +459 -0
- package/scripts/mas-smoke.test.mjs +220 -0
- package/scripts/mobile-auth-simulator-smoke.mjs +0 -1
- package/scripts/normalize-eliza-capture.ts +97 -0
- package/scripts/omnivoice-fuse/prepare.mjs +2543 -23
- package/scripts/pack-upstreams.mjs +65 -5
- package/scripts/package-electrobun-linux.mjs +303 -0
- package/scripts/patch-deps.mjs +5 -3
- package/scripts/patches/llama-asr-word-timestamps.patch +218 -0
- package/scripts/playwright-ui-live-stack.ts +588 -157
- package/scripts/playwright-ui-smoke-api-stub.mjs +3495 -111
- package/scripts/pre-review-local.mjs +2 -2
- package/scripts/prepare-ios-cocoapods.sh +41 -3
- package/scripts/release-check.ts +180 -84
- package/scripts/relink-workspace-packages-to-dist.mjs +21 -4
- package/scripts/rt.mjs +16 -1
- package/scripts/run-biome-check.mjs +1 -1
- package/scripts/run-coding-agent-e2e.mjs +3 -3
- package/scripts/run-eliza-app-core-script.mjs +34 -0
- package/scripts/run-local-plugin-live-smoke.mjs +66 -2
- package/scripts/run-mobile-build-android-app-actions.test.mjs +426 -0
- package/scripts/run-mobile-build-brand-separation.test.mts +33 -0
- package/scripts/run-mobile-build-ios-engine-gate.test.mjs +85 -0
- package/scripts/run-mobile-build-mtp-staleness.test.mts +198 -0
- package/scripts/run-mobile-build.mjs +5082 -610
- package/scripts/run-node-runtime.mjs +184 -7
- package/scripts/run-node-runtime.test.mjs +167 -0
- package/scripts/run-node-tsx.mjs +80 -33
- package/scripts/run-node.mjs +41 -1
- package/scripts/run-production-build.mjs +34 -27
- package/scripts/run-release-check.mjs +19 -0
- package/scripts/run-release-contract-suite.mjs +107 -14
- package/scripts/run-ui-smoke-playwright-suite.mjs +0 -2
- package/scripts/runtime-package-manifest.ts +21 -3
- package/scripts/serve-real-local-agent.ts +72 -0
- package/scripts/setup-upstreams.mjs +42 -1
- package/scripts/sms-gateway-status.mjs +194 -0
- package/scripts/stage-android-agent.test.mjs +97 -0
- package/scripts/stage-desktop-fused-lib.mjs +453 -0
- package/scripts/stage-elizavoice-lib.mjs +363 -0
- package/scripts/startup-integration-script-drift.test.ts +82 -4
- package/scripts/streaming-pipeline-bench.ts +543 -0
- package/scripts/sync-homepage-porkbun-dns.mjs +262 -0
- package/scripts/test-sms-gateway-software.mjs +100 -0
- package/scripts/type-audit.mjs +1 -1
- package/scripts/validate-bluebubbles-outbound.mjs +293 -0
- package/scripts/validate-cdn-assets.mjs +15 -7
- package/scripts/validate-regression-matrix.mjs +109 -8
- package/scripts/verify-android-sms-gateway-e2e.mjs +362 -0
- package/scripts/verify-bluebubbles-gateway-e2e.mjs +191 -0
- package/scripts/verify-bluebubbles-inbound-readiness.mjs +88 -0
- package/scripts/verify-cloud-api-production-deploy.mjs +87 -0
- package/scripts/verify-cloud-sms-onboarding-flow.mjs +336 -0
- package/scripts/verify-ondevice-artifact.mjs +111 -0
- package/scripts/voice/freeze-voice.mjs +521 -0
- package/scripts/voice-attribution-smoke.ts +644 -0
- package/scripts/voice-create-profile.mjs +379 -0
- package/scripts/voice-duet.mjs +1355 -0
- package/scripts/voice-e2e-hardware.ts +877 -0
- package/scripts/voice-interactive.mjs +1721 -0
- package/scripts/voice-latency-report.mjs +96 -0
- package/scripts/voice-latency-report.test.ts +176 -0
- package/scripts/voice-preset/build-default-voice-preset.mjs +249 -0
- package/scripts/voice-preset/build-onboarding-voice.mjs +281 -0
- package/scripts/watch-sms-gateway-readiness.mjs +303 -0
- package/scripts/write-homepage-release-data.mjs +458 -26
- package/security/agent-vault-id.d.ts +2 -2
- package/security/agent-vault-id.js +1 -1
- package/security/hydrate-wallet-keys-from-platform-store.d.ts.map +1 -1
- package/security/hydrate-wallet-keys-from-platform-store.js +23 -14
- package/security/platform-secure-store-node.d.ts +3 -3
- package/security/platform-secure-store-node.js +3 -3
- package/security/wallet-os-store-actions.d.ts +0 -9
- package/security/wallet-os-store-actions.d.ts.map +1 -1
- package/security/wallet-os-store-actions.js +3 -10
- package/services/account-pool.d.ts +23 -14
- package/services/account-pool.d.ts.map +1 -1
- package/services/account-pool.js +86 -24
- package/services/account-usage.d.ts.map +1 -1
- package/services/account-usage.js +2 -5
- package/services/ambient-audio/consent.d.ts +9 -0
- package/services/ambient-audio/consent.d.ts.map +1 -0
- package/services/ambient-audio/consent.js +28 -0
- package/services/ambient-audio/index.d.ts +7 -0
- package/services/ambient-audio/index.d.ts.map +1 -0
- package/services/ambient-audio/index.js +4 -0
- package/services/ambient-audio/replay-buffer.d.ts +14 -0
- package/services/ambient-audio/replay-buffer.d.ts.map +1 -0
- package/services/ambient-audio/replay-buffer.js +66 -0
- package/services/ambient-audio/response-gate.d.ts +3 -0
- package/services/ambient-audio/response-gate.d.ts.map +1 -0
- package/services/ambient-audio/response-gate.js +33 -0
- package/services/ambient-audio/service.d.ts +22 -0
- package/services/ambient-audio/service.d.ts.map +1 -0
- package/services/ambient-audio/service.js +47 -0
- package/services/ambient-audio/types.d.ts +42 -0
- package/services/ambient-audio/types.d.ts.map +1 -0
- package/services/app-updates/update-policy.d.ts +64 -0
- package/services/app-updates/update-policy.d.ts.map +1 -0
- package/services/app-updates/update-policy.js +228 -0
- package/services/auth-store.d.ts +37 -1
- package/services/auth-store.d.ts.map +1 -1
- package/services/auth-store.js +59 -26
- package/services/cloud-jwks-store.d.ts +3 -3
- package/services/cloud-jwks-store.d.ts.map +1 -1
- package/services/cloud-jwks-store.js +5 -8
- package/services/coding-account-bridge.d.ts +71 -0
- package/services/coding-account-bridge.d.ts.map +1 -0
- package/services/coding-account-bridge.js +267 -0
- package/services/connector-target-catalog.d.ts +11 -4
- package/services/connector-target-catalog.d.ts.map +1 -1
- package/services/connector-target-catalog.js +7 -4
- package/services/credential-tunnel-service.d.ts +66 -0
- package/services/credential-tunnel-service.d.ts.map +1 -0
- package/services/credential-tunnel-service.js +227 -0
- package/services/github-credentials.d.ts +1 -1
- package/services/github-credentials.js +1 -1
- package/services/inference-abort.d.ts +47 -0
- package/services/inference-abort.d.ts.map +1 -0
- package/services/inference-abort.js +76 -0
- package/services/persistence.d.ts +2 -3
- package/services/persistence.d.ts.map +1 -1
- package/services/persistence.js +2 -3
- package/services/phrase-chunked-tts.d.ts +136 -0
- package/services/phrase-chunked-tts.d.ts.map +1 -0
- package/services/phrase-chunked-tts.js +208 -0
- package/services/sandbox-registry.d.ts +78 -0
- package/services/sandbox-registry.d.ts.map +1 -0
- package/services/sandbox-registry.js +323 -0
- package/services/secrets-manager-installer.d.ts +8 -1
- package/services/secrets-manager-installer.d.ts.map +1 -1
- package/services/secrets-manager-installer.js +27 -2
- package/services/sensitive-requests/cloud-link-adapter.d.ts +15 -0
- package/services/sensitive-requests/cloud-link-adapter.d.ts.map +1 -0
- package/services/sensitive-requests/cloud-link-adapter.js +73 -0
- package/services/sensitive-requests/index.d.ts +27 -0
- package/services/sensitive-requests/index.d.ts.map +1 -0
- package/services/sensitive-requests/index.js +51 -0
- package/services/sensitive-requests/instruct-dm-only-adapter.d.ts +14 -0
- package/services/sensitive-requests/instruct-dm-only-adapter.d.ts.map +1 -0
- package/services/sensitive-requests/instruct-dm-only-adapter.js +22 -0
- package/services/sensitive-requests/owner-app-inline-adapter.d.ts +3 -0
- package/services/sensitive-requests/owner-app-inline-adapter.d.ts.map +1 -0
- package/services/sensitive-requests/owner-app-inline-adapter.js +146 -0
- package/services/sensitive-requests/owner-app-oauth-adapter.d.ts +3 -0
- package/services/sensitive-requests/owner-app-oauth-adapter.d.ts.map +1 -0
- package/services/sensitive-requests/owner-app-oauth-adapter.js +156 -0
- package/services/sensitive-requests/public-link-adapter.d.ts +14 -0
- package/services/sensitive-requests/public-link-adapter.d.ts.map +1 -0
- package/services/sensitive-requests/public-link-adapter.js +86 -0
- package/services/sensitive-requests/tunnel-link-adapter.d.ts +17 -0
- package/services/sensitive-requests/tunnel-link-adapter.d.ts.map +1 -0
- package/services/sensitive-requests/tunnel-link-adapter.js +38 -0
- package/services/steward-credentials.d.ts +1 -1
- package/services/steward-credentials.d.ts.map +1 -1
- package/services/steward-credentials.js +10 -6
- package/services/steward-sidecar/health-check.d.ts.map +1 -1
- package/services/steward-sidecar/health-check.js +4 -3
- package/services/steward-sidecar/process-management.d.ts +1 -1
- package/services/steward-sidecar/process-management.d.ts.map +1 -1
- package/services/steward-sidecar/process-management.js +9 -3
- package/services/steward-sidecar/types.d.ts +1 -1
- package/services/steward-sidecar/types.d.ts.map +1 -1
- package/services/steward-sidecar/wallet-setup.d.ts +1 -1
- package/services/steward-sidecar/wallet-setup.d.ts.map +1 -1
- package/services/steward-sidecar/wallet-setup.js +8 -7
- package/services/steward-sidecar.d.ts +5 -5
- package/services/steward-sidecar.d.ts.map +1 -1
- package/services/steward-sidecar.js +27 -19
- package/services/task-host-capabilities.d.ts +60 -0
- package/services/task-host-capabilities.d.ts.map +1 -0
- package/services/task-host-capabilities.js +122 -0
- package/services/tool-call-cache/index.d.ts +2 -2
- package/services/tool-call-cache/index.d.ts.map +1 -1
- package/services/tool-call-cache/index.js +1 -1
- package/services/trigger-event-bridge.js +1 -1
- package/services/tunnel-to-mobile/index.d.ts +2 -0
- package/services/tunnel-to-mobile/index.d.ts.map +1 -0
- package/services/tunnel-to-mobile/index.js +1 -0
- package/services/tunnel-to-mobile/tunnel-to-mobile-client.d.ts +105 -0
- package/services/tunnel-to-mobile/tunnel-to-mobile-client.d.ts.map +1 -0
- package/services/tunnel-to-mobile/tunnel-to-mobile-client.js +190 -0
- package/services/vault-bootstrap.d.ts.map +1 -1
- package/services/vault-bootstrap.js +52 -21
- package/services/vault-mirror.d.ts +1 -1
- package/services/vault-mirror.d.ts.map +1 -1
- package/services/vault-mirror.js +29 -6
- package/services/voice-profiles/diarization-pipeline.d.ts +6 -0
- package/services/voice-profiles/diarization-pipeline.d.ts.map +1 -0
- package/services/voice-profiles/diarization-pipeline.js +20 -0
- package/services/voice-profiles/index.d.ts +12 -0
- package/services/voice-profiles/index.d.ts.map +1 -0
- package/services/voice-profiles/index.js +5 -0
- package/services/voice-profiles/nickname-evaluator.d.ts +14 -0
- package/services/voice-profiles/nickname-evaluator.d.ts.map +1 -0
- package/services/voice-profiles/nickname-evaluator.js +46 -0
- package/services/voice-profiles/owner-confidence.d.ts +10 -0
- package/services/voice-profiles/owner-confidence.d.ts.map +1 -0
- package/services/voice-profiles/owner-confidence.js +38 -0
- package/services/voice-profiles/private-challenge.d.ts +20 -0
- package/services/voice-profiles/private-challenge.d.ts.map +1 -0
- package/services/voice-profiles/private-challenge.js +44 -0
- package/services/voice-profiles/store.d.ts +21 -0
- package/services/voice-profiles/store.d.ts.map +1 -0
- package/services/voice-profiles/store.js +50 -0
- package/services/voice-profiles/types.d.ts +38 -0
- package/services/voice-profiles/types.d.ts.map +1 -0
- package/services/voice-profiles/types.js +1 -0
- package/styles/electrobun-mac-window-drag.css +4 -4
- package/test/helpers/__tests__/live-agent-test.smoke.test.ts +43 -70
- package/test/helpers/browser-mocks.ts +2 -2
- package/test/helpers/conditional-tests.ts +2 -2
- package/test/helpers/live-agent-test.ts +537 -551
- package/test/helpers/live-provider.test.ts +95 -5
- package/test/helpers/live-provider.ts +234 -56
- package/test/helpers/live-runtime-server.ts +4 -4
- package/test/helpers/pglite-runtime.ts +1 -1
- package/test/helpers/real-runtime.ts +72 -20
- package/test/helpers/trajectory-harness.ts +11 -7
- package/test/scripts/start-eliza-live.ts +9 -0
- package/test/scripts/test-parallel.mjs +1 -1
- package/test/scripts/test-root-unit.mjs +6 -7
- package/test/scripts/websocket-pending-queue.test.ts +119 -0
- package/test-support/test-helpers.d.ts +0 -33
- package/test-support/test-helpers.d.ts.map +1 -1
- package/test-support/test-helpers.js +81 -189
- package/ui-compat.d.ts +14 -2
- package/ui-compat.d.ts.map +1 -1
- package/ui-compat.js +23 -3
- package/api/auth-pairing-compat-routes.d.ts +0 -17
- package/api/auth-pairing-compat-routes.d.ts.map +0 -1
- package/api/auth-pairing-compat-routes.js +0 -301
- package/api/local-inference-compat-routes.d.ts +0 -16
- package/api/local-inference-compat-routes.d.ts.map +0 -1
- package/api/local-inference-compat-routes.js +0 -617
- package/api/onboarding-compat-routes.d.ts +0 -4
- package/api/onboarding-compat-routes.d.ts.map +0 -1
- package/api/onboarding-compat-routes.js +0 -207
- package/api/plugins-compat-routes.d.ts +0 -103
- package/api/plugins-compat-routes.d.ts.map +0 -1
- package/api/plugins-compat-routes.js +0 -1181
- package/api/server-onboarding-compat.d.ts +0 -31
- package/api/server-onboarding-compat.d.ts.map +0 -1
- package/api/server-onboarding-compat.js +0 -283
- package/benchmark/cua-routes.d.ts +0 -10
- package/benchmark/cua-routes.d.ts.map +0 -1
- package/benchmark/cua-routes.js +0 -179
- package/benchmark/mock-plugin-base.d.ts +0 -9
- package/benchmark/mock-plugin-base.d.ts.map +0 -1
- package/benchmark/mock-plugin-base.js +0 -325
- package/cli/parse-duration.d.ts +0 -5
- package/cli/parse-duration.d.ts.map +0 -1
- package/cli/parse-duration.js +0 -27
- package/patches/llama-cpp-capacitor@0.1.5.patch +0 -2387
- package/platform/agent-browser-stub.d.ts +0 -27
- package/platform/agent-browser-stub.d.ts.map +0 -1
- package/platform/agent-browser-stub.js +0 -16
- package/platforms/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +0 -26
- package/platforms/android/app/src/main/res/drawable/ic_launcher_background.xml +0 -170
- package/platforms/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -34
- package/platforms/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +0 -18
- package/platforms/electrobun/assets/appIcon.iconset/icon_512x512@2x.png +0 -0
- package/platforms/electrobun/assets/appIcon.png +0 -0
- package/platforms/electrobun/scripts/build-whisper-universal.sh +0 -137
- package/platforms/electrobun/scripts/build-whisper.sh +0 -95
- package/platforms/electrobun/scripts/ensure-whisper-model.sh +0 -93
- package/platforms/electrobun/src/libMacWindowEffects.dylib +0 -0
- package/platforms/electrobun/src/native/whisper.ts +0 -280
- package/platforms/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png +0 -0
- package/platforms/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png +0 -0
- package/registry/generate-apps.d.ts +0 -2
- package/registry/generate-apps.d.ts.map +0 -1
- package/registry/generate-apps.js +0 -338
- package/registry/generate.d.ts +0 -2
- package/registry/generate.d.ts.map +0 -1
- package/registry/generate.js +0 -506
- package/registry/loader.d.ts +0 -27
- package/registry/loader.d.ts.map +0 -1
- package/registry/loader.js +0 -111
- package/registry/schema.d.ts +0 -989
- package/registry/schema.d.ts.map +0 -1
- package/registry/schema.js +0 -264
- package/runtime/embedding-manager-support.d.ts +0 -77
- package/runtime/embedding-manager-support.d.ts.map +0 -1
- package/runtime/embedding-manager-support.js +0 -309
- package/runtime/embedding-presets.d.ts +0 -5
- package/runtime/embedding-presets.d.ts.map +0 -1
- package/runtime/embedding-presets.js +0 -47
- package/runtime/embedding-warmup-policy.d.ts +0 -13
- package/runtime/embedding-warmup-policy.d.ts.map +0 -1
- package/runtime/embedding-warmup-policy.js +0 -33
- package/runtime/ensure-local-inference-handler.d.ts +0 -25
- package/runtime/ensure-local-inference-handler.d.ts.map +0 -1
- package/runtime/ensure-local-inference-handler.js +0 -389
- package/runtime/mobile-local-inference-gate.d.ts +0 -21
- package/runtime/mobile-local-inference-gate.d.ts.map +0 -1
- package/runtime/mobile-local-inference-gate.js +0 -24
- package/scripts/aosp/avd-test.mjs +0 -403
- package/scripts/aosp/boot-validate.mjs +0 -536
- package/scripts/aosp/build-aosp.mjs +0 -448
- package/scripts/aosp/build-bootanimation.mjs +0 -178
- package/scripts/aosp/capture-screens.mjs +0 -325
- package/scripts/aosp/e2e-validate.mjs +0 -225
- package/scripts/aosp/lint-init-rc.mjs +0 -258
- package/scripts/aosp/llama-shim/eliza_llama_shim.c +0 -276
- package/scripts/aosp/sim.mjs +0 -277
- package/scripts/aosp/sync-to-aosp.mjs +0 -134
- package/scripts/aosp/validate.mjs +0 -1273
- package/scripts/build-llama-cpp-dflash.mjs +0 -1866
- package/scripts/generate-onboarding-voicelines.mjs +0 -194
- package/scripts/generated/static-asset-manifest.json +0 -4
- package/scripts/normalize-parallax-capture.ts +0 -97
- package/scripts/omnivoice-fuse/Makefile +0 -44
- package/scripts/omnivoice-fuse/README.md +0 -266
- package/scripts/omnivoice-fuse/cmake-graft.mjs +0 -180
- package/scripts/omnivoice-fuse/ffi-stub.c +0 -222
- package/scripts/omnivoice-fuse/ffi.h +0 -158
- package/scripts/omnivoice-fuse/libelizainference_stub.dylib +0 -0
- package/scripts/omnivoice-fuse/verify-symbols.mjs +0 -138
- package/security/cloud-secret-store.d.ts +0 -34
- package/security/cloud-secret-store.d.ts.map +0 -1
- package/security/cloud-secret-store.js +0 -65
- package/security/export-guard.d.ts +0 -34
- package/security/export-guard.d.ts.map +0 -1
- package/security/export-guard.js +0 -127
- package/services/local-inference/__stress__/cache-stress-helpers.d.ts +0 -76
- package/services/local-inference/__stress__/cache-stress-helpers.d.ts.map +0 -1
- package/services/local-inference/__stress__/cache-stress-helpers.js +0 -238
- package/services/local-inference/active-model.d.ts +0 -180
- package/services/local-inference/active-model.d.ts.map +0 -1
- package/services/local-inference/active-model.js +0 -362
- package/services/local-inference/assignments.d.ts +0 -58
- package/services/local-inference/assignments.d.ts.map +0 -1
- package/services/local-inference/assignments.js +0 -179
- package/services/local-inference/backend.d.ts +0 -200
- package/services/local-inference/backend.d.ts.map +0 -1
- package/services/local-inference/backend.js +0 -242
- package/services/local-inference/bundled-models.d.ts +0 -34
- package/services/local-inference/bundled-models.d.ts.map +0 -1
- package/services/local-inference/bundled-models.js +0 -104
- package/services/local-inference/cache-bridge.d.ts +0 -184
- package/services/local-inference/cache-bridge.d.ts.map +0 -1
- package/services/local-inference/cache-bridge.js +0 -333
- package/services/local-inference/catalog.d.ts +0 -57
- package/services/local-inference/catalog.d.ts.map +0 -1
- package/services/local-inference/catalog.js +0 -262
- package/services/local-inference/conversation-registry.d.ts +0 -122
- package/services/local-inference/conversation-registry.d.ts.map +0 -1
- package/services/local-inference/conversation-registry.js +0 -182
- package/services/local-inference/device-bridge.d.ts +0 -139
- package/services/local-inference/device-bridge.d.ts.map +0 -1
- package/services/local-inference/device-bridge.js +0 -774
- package/services/local-inference/dflash-doctor.d.ts +0 -27
- package/services/local-inference/dflash-doctor.d.ts.map +0 -1
- package/services/local-inference/dflash-doctor.js +0 -149
- package/services/local-inference/dflash-server.d.ts +0 -248
- package/services/local-inference/dflash-server.d.ts.map +0 -1
- package/services/local-inference/dflash-server.js +0 -1076
- package/services/local-inference/downloader.d.ts +0 -48
- package/services/local-inference/downloader.d.ts.map +0 -1
- package/services/local-inference/downloader.js +0 -688
- package/services/local-inference/engine.d.ts +0 -282
- package/services/local-inference/engine.d.ts.map +0 -1
- package/services/local-inference/engine.js +0 -743
- package/services/local-inference/external-scanner.d.ts +0 -17
- package/services/local-inference/external-scanner.d.ts.map +0 -1
- package/services/local-inference/external-scanner.js +0 -261
- package/services/local-inference/handler-registry.d.ts +0 -72
- package/services/local-inference/handler-registry.d.ts.map +0 -1
- package/services/local-inference/handler-registry.js +0 -159
- package/services/local-inference/hardware.d.ts +0 -26
- package/services/local-inference/hardware.d.ts.map +0 -1
- package/services/local-inference/hardware.js +0 -139
- package/services/local-inference/hf-search.d.ts +0 -19
- package/services/local-inference/hf-search.d.ts.map +0 -1
- package/services/local-inference/hf-search.js +0 -169
- package/services/local-inference/index.d.ts +0 -10
- package/services/local-inference/index.d.ts.map +0 -1
- package/services/local-inference/index.js +0 -7
- package/services/local-inference/llama-server-metrics.d.ts +0 -108
- package/services/local-inference/llama-server-metrics.d.ts.map +0 -1
- package/services/local-inference/llama-server-metrics.js +0 -175
- package/services/local-inference/manifest/index.d.ts +0 -4
- package/services/local-inference/manifest/index.d.ts.map +0 -1
- package/services/local-inference/manifest/index.js +0 -5
- package/services/local-inference/manifest/schema.d.ts +0 -419
- package/services/local-inference/manifest/schema.d.ts.map +0 -1
- package/services/local-inference/manifest/schema.js +0 -227
- package/services/local-inference/manifest/types.d.ts +0 -23
- package/services/local-inference/manifest/types.d.ts.map +0 -1
- package/services/local-inference/manifest/types.js +0 -5
- package/services/local-inference/manifest/validator.d.ts +0 -43
- package/services/local-inference/manifest/validator.d.ts.map +0 -1
- package/services/local-inference/manifest/validator.js +0 -187
- package/services/local-inference/paths.d.ts +0 -8
- package/services/local-inference/paths.d.ts.map +0 -1
- package/services/local-inference/paths.js +0 -7
- package/services/local-inference/providers.d.ts +0 -61
- package/services/local-inference/providers.d.ts.map +0 -1
- package/services/local-inference/providers.js +0 -334
- package/services/local-inference/ram-budget.d.ts +0 -57
- package/services/local-inference/ram-budget.d.ts.map +0 -1
- package/services/local-inference/ram-budget.js +0 -107
- package/services/local-inference/readiness.d.ts +0 -9
- package/services/local-inference/readiness.d.ts.map +0 -1
- package/services/local-inference/readiness.js +0 -153
- package/services/local-inference/recommendation.d.ts +0 -62
- package/services/local-inference/recommendation.d.ts.map +0 -1
- package/services/local-inference/recommendation.js +0 -309
- package/services/local-inference/registry.d.ts +0 -35
- package/services/local-inference/registry.d.ts.map +0 -1
- package/services/local-inference/registry.js +0 -117
- package/services/local-inference/router-handler.d.ts +0 -51
- package/services/local-inference/router-handler.d.ts.map +0 -1
- package/services/local-inference/router-handler.js +0 -165
- package/services/local-inference/routing-policy.d.ts +0 -55
- package/services/local-inference/routing-policy.d.ts.map +0 -1
- package/services/local-inference/routing-policy.js +0 -195
- package/services/local-inference/routing-preferences.d.ts +0 -8
- package/services/local-inference/routing-preferences.d.ts.map +0 -1
- package/services/local-inference/routing-preferences.js +0 -7
- package/services/local-inference/service.d.ts +0 -88
- package/services/local-inference/service.d.ts.map +0 -1
- package/services/local-inference/service.js +0 -210
- package/services/local-inference/session-pool.d.ts +0 -72
- package/services/local-inference/session-pool.d.ts.map +0 -1
- package/services/local-inference/session-pool.js +0 -125
- package/services/local-inference/types.d.ts +0 -309
- package/services/local-inference/types.d.ts.map +0 -1
- package/services/local-inference/types.js +0 -23
- package/services/local-inference/verify.d.ts +0 -8
- package/services/local-inference/verify.d.ts.map +0 -1
- package/services/local-inference/verify.js +0 -7
- package/services/local-inference/voice/barge-in.d.ts +0 -15
- package/services/local-inference/voice/barge-in.d.ts.map +0 -1
- package/services/local-inference/voice/barge-in.js +0 -20
- package/services/local-inference/voice/engine-bridge.d.ts +0 -256
- package/services/local-inference/voice/engine-bridge.d.ts.map +0 -1
- package/services/local-inference/voice/engine-bridge.js +0 -398
- package/services/local-inference/voice/ffi-bindings.d.ts +0 -114
- package/services/local-inference/voice/ffi-bindings.d.ts.map +0 -1
- package/services/local-inference/voice/ffi-bindings.js +0 -281
- package/services/local-inference/voice/index.d.ts +0 -51
- package/services/local-inference/voice/index.d.ts.map +0 -1
- package/services/local-inference/voice/index.js +0 -50
- package/services/local-inference/voice/lifecycle.d.ts +0 -135
- package/services/local-inference/voice/lifecycle.d.ts.map +0 -1
- package/services/local-inference/voice/lifecycle.js +0 -189
- package/services/local-inference/voice/phoneme-tokenizer.d.ts +0 -58
- package/services/local-inference/voice/phoneme-tokenizer.d.ts.map +0 -1
- package/services/local-inference/voice/phoneme-tokenizer.js +0 -53
- package/services/local-inference/voice/phrase-cache.d.ts +0 -24
- package/services/local-inference/voice/phrase-cache.d.ts.map +0 -1
- package/services/local-inference/voice/phrase-cache.js +0 -32
- package/services/local-inference/voice/phrase-chunker.d.ts +0 -20
- package/services/local-inference/voice/phrase-chunker.d.ts.map +0 -1
- package/services/local-inference/voice/phrase-chunker.js +0 -85
- package/services/local-inference/voice/ring-buffer.d.ts +0 -40
- package/services/local-inference/voice/ring-buffer.d.ts.map +0 -1
- package/services/local-inference/voice/ring-buffer.js +0 -85
- package/services/local-inference/voice/rollback-queue.d.ts +0 -24
- package/services/local-inference/voice/rollback-queue.d.ts.map +0 -1
- package/services/local-inference/voice/rollback-queue.js +0 -49
- package/services/local-inference/voice/scheduler.d.ts +0 -47
- package/services/local-inference/voice/scheduler.d.ts.map +0 -1
- package/services/local-inference/voice/scheduler.js +0 -123
- package/services/local-inference/voice/shared-resources.d.ts +0 -119
- package/services/local-inference/voice/shared-resources.d.ts.map +0 -1
- package/services/local-inference/voice/shared-resources.js +0 -83
- package/services/local-inference/voice/speaker-preset-cache.d.ts +0 -28
- package/services/local-inference/voice/speaker-preset-cache.d.ts.map +0 -1
- package/services/local-inference/voice/speaker-preset-cache.js +0 -44
- package/services/local-inference/voice/types.d.ts +0 -80
- package/services/local-inference/voice/types.d.ts.map +0 -1
- package/services/local-inference/voice/voice-preset-format.d.ts +0 -56
- package/services/local-inference/voice/voice-preset-format.d.ts.map +0 -1
- package/services/local-inference/voice/voice-preset-format.js +0 -184
- package/services/plugin-installer.d.ts +0 -22
- package/services/plugin-installer.d.ts.map +0 -1
- package/services/plugin-installer.js +0 -41
- package/test/helpers/i18n.ts +0 -5
- package/test/helpers/loopback.ts +0 -33
- package/test/helpers/react-test.ts +0 -40
- package/test/helpers/skip-without.ts +0 -53
- package/test/scripts/task-agent-live-smoke.ts +0 -1335
- /package/services/{local-inference/voice → ambient-audio}/types.js +0 -0
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* and copy `src/` + `tools/` + selected `examples/` data into the
|
|
4
4
|
* llama.cpp tree under `<llamaCppRoot>/omnivoice/`.
|
|
5
5
|
*
|
|
6
|
-
* Caller (build-llama-cpp-
|
|
6
|
+
* Caller (build-llama-cpp-mtp.mjs):
|
|
7
7
|
* import { prepareOmnivoiceFusion } from
|
|
8
8
|
* "./omnivoice-fuse/prepare.mjs";
|
|
9
9
|
* const { commit, ggmlSubmoduleCommit, sourceCount } =
|
|
10
10
|
* prepareOmnivoiceFusion({
|
|
11
|
-
* cacheRoot: "...", // ~/.cache/eliza-
|
|
12
|
-
* llamaCppRoot: "...", // path to
|
|
11
|
+
* cacheRoot: "...", // ~/.cache/eliza-mtp
|
|
12
|
+
* llamaCppRoot: "...", // path to elizaOS/llama.cpp checkout
|
|
13
13
|
* omnivoiceRef: "38f824023d…",
|
|
14
14
|
* });
|
|
15
15
|
*
|
|
@@ -22,24 +22,38 @@ import fs from "node:fs";
|
|
|
22
22
|
import path from "node:path";
|
|
23
23
|
|
|
24
24
|
const OMNIVOICE_REPO =
|
|
25
|
-
process.env.
|
|
26
|
-
"https://github.com/
|
|
25
|
+
process.env.ELIZA_OMNIVOICE_REMOTE ||
|
|
26
|
+
"https://github.com/elizaOS/omnivoice.cpp.git";
|
|
27
27
|
|
|
28
28
|
// Master HEAD as of 2026-05-10. Bump per the runbook in README.md.
|
|
29
29
|
export const OMNIVOICE_REF =
|
|
30
|
-
process.env.
|
|
30
|
+
process.env.ELIZA_OMNIVOICE_REF || "38f824023d12b21a7c324651b18bd90f16d8bb86";
|
|
31
31
|
|
|
32
32
|
// The ServeurpersoCom ggml submodule pin we explicitly DO NOT include
|
|
33
33
|
// in the fused build. Recorded so verify-symbols.mjs can assert that no
|
|
34
34
|
// `omnivoice/ggml` directory is left dangling under the llama.cpp tree.
|
|
35
35
|
export const OMNIVOICE_GGML_REF =
|
|
36
|
-
process.env.
|
|
36
|
+
process.env.ELIZA_OMNIVOICE_GGML_REF ||
|
|
37
37
|
"0e3980ef205ea3639650f59e54cfeecd7d947700";
|
|
38
38
|
|
|
39
39
|
// Subdirectory inside the llama.cpp checkout where omnivoice sources
|
|
40
40
|
// land. Stable so the CMake graft and the symbol verifier agree.
|
|
41
41
|
export const OMNIVOICE_GRAFT_SUBDIR = "omnivoice";
|
|
42
42
|
|
|
43
|
+
const REQUIRED_PUBLIC_OMNIVOICE_SYMBOLS = Object.freeze([
|
|
44
|
+
"ov_version",
|
|
45
|
+
"ov_last_error",
|
|
46
|
+
"ov_audio_free",
|
|
47
|
+
"ov_init_default_params",
|
|
48
|
+
"ov_tts_default_params",
|
|
49
|
+
"ov_init",
|
|
50
|
+
"ov_free",
|
|
51
|
+
"ov_log_set",
|
|
52
|
+
"ov_synthesize",
|
|
53
|
+
"ov_encode_reference",
|
|
54
|
+
"ov_duration_sec_to_tokens",
|
|
55
|
+
]);
|
|
56
|
+
|
|
43
57
|
function run(cmd, args, opts = {}) {
|
|
44
58
|
const result = spawnSync(cmd, args, {
|
|
45
59
|
stdio: opts.capture ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
@@ -52,23 +66,2142 @@ function run(cmd, args, opts = {}) {
|
|
|
52
66
|
? `\nstdout:\n${result.stdout || ""}\nstderr:\n${result.stderr || ""}`
|
|
53
67
|
: "";
|
|
54
68
|
throw new Error(
|
|
55
|
-
`[omnivoice-fuse] ${cmd} ${args.join(" ")} failed with ${result.status}${detail}`,
|
|
69
|
+
`[omnivoice-fuse] ${cmd} ${args.join(" ")} failed with ${result.status}${detail}`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return result.stdout?.trim() ?? "";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function copyDirRecursive(src, dst) {
|
|
76
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
77
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
78
|
+
const from = path.join(src, entry.name);
|
|
79
|
+
const to = path.join(dst, entry.name);
|
|
80
|
+
if (entry.isDirectory()) {
|
|
81
|
+
copyDirRecursive(from, to);
|
|
82
|
+
} else if (entry.isFile() || entry.isSymbolicLink()) {
|
|
83
|
+
fs.copyFileSync(from, to);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function replaceBetween(source, startMarker, endMarker, replacement) {
|
|
89
|
+
const start = source.indexOf(startMarker);
|
|
90
|
+
if (start < 0) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`[omnivoice-fuse] compatibility patch anchor not found: ${startMarker}`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const end = source.indexOf(endMarker, start);
|
|
96
|
+
if (end < 0) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`[omnivoice-fuse] compatibility patch end anchor not found: ${endMarker}`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return source.slice(0, start) + replacement + source.slice(end);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function writeElizaFfiAdapter({ graftRoot, commit }) {
|
|
105
|
+
const ffiHeaderSrc = new URL("./ffi.h", import.meta.url).pathname;
|
|
106
|
+
const ffiHeaderDst = path.join(graftRoot, "src", "ffi.h");
|
|
107
|
+
fs.copyFileSync(ffiHeaderSrc, ffiHeaderDst);
|
|
108
|
+
fs.writeFileSync(
|
|
109
|
+
path.join(graftRoot, "src", "eliza-inference-ffi.cpp"),
|
|
110
|
+
`// Generated by omnivoice-fuse/prepare.mjs.
|
|
111
|
+
// C ABI bridge between libelizainference and omnivoice.cpp.
|
|
112
|
+
|
|
113
|
+
#include "ffi.h"
|
|
114
|
+
#include "omnivoice.h"
|
|
115
|
+
#include "llama.h"
|
|
116
|
+
#include "mtmd.h"
|
|
117
|
+
#include "mtmd-helper.h"
|
|
118
|
+
|
|
119
|
+
#include <algorithm>
|
|
120
|
+
#include <atomic>
|
|
121
|
+
#include <cerrno>
|
|
122
|
+
#include <cctype>
|
|
123
|
+
#include <cmath>
|
|
124
|
+
#include <cstddef>
|
|
125
|
+
#include <cstdint>
|
|
126
|
+
#include <cstdio>
|
|
127
|
+
#include <cstdlib>
|
|
128
|
+
#include <cstring>
|
|
129
|
+
#include <filesystem>
|
|
130
|
+
#include <fstream>
|
|
131
|
+
#include <memory>
|
|
132
|
+
#include <mutex>
|
|
133
|
+
#include <new>
|
|
134
|
+
#include <string>
|
|
135
|
+
#include <thread>
|
|
136
|
+
#include <unordered_map>
|
|
137
|
+
#include <vector>
|
|
138
|
+
|
|
139
|
+
/* OmniVoice voice-preset payload parsed from
|
|
140
|
+
* <bundle_dir>/cache/voice-preset-<id>.bin (ELZ2 v2 binary format). v1
|
|
141
|
+
* presets (Kokoro-style: embedding + phrase-cache seed only) parse with
|
|
142
|
+
* empty ref_audio_tokens / ref_text / instruct fields so the C side
|
|
143
|
+
* falls back to OmniVoice's auto-voice path on those entries.
|
|
144
|
+
*
|
|
145
|
+
* The format is described in TypeScript at
|
|
146
|
+
* plugins/plugin-local-inference/src/services/voice/voice-preset-format.ts.
|
|
147
|
+
* This C-side parser is a slim, read-only mirror of that contract — it
|
|
148
|
+
* understands both v1 and v2, returns false on any structural error,
|
|
149
|
+
* and never copies large buffers (ref_audio_tokens is a 24 KB span at
|
|
150
|
+
* most for a 30 s reference). */
|
|
151
|
+
struct EliVoicePreset {
|
|
152
|
+
std::string voice_id;
|
|
153
|
+
std::string instruct;
|
|
154
|
+
std::string ref_text;
|
|
155
|
+
std::vector<int32_t> ref_audio_tokens;
|
|
156
|
+
int K = 0;
|
|
157
|
+
int ref_T = 0;
|
|
158
|
+
int version = 0;
|
|
159
|
+
bool empty_payload = true;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
struct EliInferenceContext {
|
|
163
|
+
std::string bundle_dir;
|
|
164
|
+
std::string tts_model_path;
|
|
165
|
+
std::string codec_model_path;
|
|
166
|
+
std::string asr_model_path;
|
|
167
|
+
std::string asr_mmproj_path;
|
|
168
|
+
ov_context * ov = nullptr;
|
|
169
|
+
llama_model * asr_model = nullptr;
|
|
170
|
+
llama_context * asr_lctx = nullptr;
|
|
171
|
+
mtmd_context * asr_mtmd = nullptr;
|
|
172
|
+
llama_sampler * asr_sampler = nullptr;
|
|
173
|
+
int asr_sample_rate = 0;
|
|
174
|
+
int asr_n_batch = 512;
|
|
175
|
+
std::atomic<bool> tts_cancel{false};
|
|
176
|
+
std::mutex tts_mutex;
|
|
177
|
+
std::mutex asr_mutex;
|
|
178
|
+
/* Streaming-LLM text model, loaded lazily on the first
|
|
179
|
+
* eliza_inference_llm_stream_open and shared across sessions. */
|
|
180
|
+
std::string llm_model_path;
|
|
181
|
+
llama_model * llm_model = nullptr;
|
|
182
|
+
std::mutex llm_mutex;
|
|
183
|
+
/* Parsed voice presets, keyed by voice id. Populated lazily on the
|
|
184
|
+
* first TTS call that mentions the id. The mutex protects the map
|
|
185
|
+
* itself; presets are immutable once inserted. */
|
|
186
|
+
std::mutex preset_mutex;
|
|
187
|
+
std::unordered_map<std::string, EliVoicePreset> presets;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/* ELZ2 magic 'ELZ1' (the ascii bytes 'E','L','Z','1' little-endian).
|
|
191
|
+
* The magic stays 'ELZ1' across format versions — only the version
|
|
192
|
+
* word at offset 4 changes between v1 and v2. */
|
|
193
|
+
static constexpr uint32_t ELIZA_VOICE_PRESET_MAGIC = 0x315A4C45u;
|
|
194
|
+
|
|
195
|
+
static inline uint32_t eliza_le_u32(const uint8_t * p) {
|
|
196
|
+
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) |
|
|
197
|
+
((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
static inline int32_t eliza_le_i32(const uint8_t * p) {
|
|
201
|
+
return (int32_t) eliza_le_u32(p);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* Validated voice-id allowlist: a single path-safe segment (mirrors the
|
|
205
|
+
* TypeScript voicePresetPath check). Refuses anything containing '/'
|
|
206
|
+
* '..' or characters outside [A-Za-z0-9._-]. */
|
|
207
|
+
static bool eliza_is_safe_voice_id(const std::string & id) {
|
|
208
|
+
if (id.empty()) return false;
|
|
209
|
+
if (id.find("..") != std::string::npos) return false;
|
|
210
|
+
for (char c : id) {
|
|
211
|
+
const bool ok =
|
|
212
|
+
(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
|
213
|
+
(c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-';
|
|
214
|
+
if (!ok) return false;
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Read a whole file into memory. Returns true on success. */
|
|
220
|
+
static bool eliza_read_file_bytes(const std::filesystem::path & path,
|
|
221
|
+
std::vector<uint8_t> & out) {
|
|
222
|
+
std::ifstream f(path, std::ios::binary);
|
|
223
|
+
if (!f.good()) return false;
|
|
224
|
+
f.seekg(0, std::ios::end);
|
|
225
|
+
std::streamsize sz = f.tellg();
|
|
226
|
+
if (sz < 0) return false;
|
|
227
|
+
out.resize((size_t) sz);
|
|
228
|
+
if (sz == 0) return true;
|
|
229
|
+
f.seekg(0, std::ios::beg);
|
|
230
|
+
f.read(reinterpret_cast<char *>(out.data()), sz);
|
|
231
|
+
return f.good() || f.eof();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Parse an ELZ2 voice-preset blob (also accepts v1 — v2-only fields
|
|
235
|
+
* stay empty). Returns false on any structural error. */
|
|
236
|
+
static bool eliza_parse_voice_preset(const std::vector<uint8_t> & bytes,
|
|
237
|
+
EliVoicePreset & out,
|
|
238
|
+
std::string & err) {
|
|
239
|
+
if (bytes.size() < 24) {
|
|
240
|
+
err = "voice preset truncated: header < 24 bytes";
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
const uint8_t * p = bytes.data();
|
|
244
|
+
const size_t len = bytes.size();
|
|
245
|
+
const uint32_t magic = eliza_le_u32(p);
|
|
246
|
+
if (magic != ELIZA_VOICE_PRESET_MAGIC) {
|
|
247
|
+
err = "voice preset bad magic";
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
const uint32_t version = eliza_le_u32(p + 4);
|
|
251
|
+
if (version != 1u && version != 2u) {
|
|
252
|
+
err = "voice preset unsupported version";
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
out.version = (int) version;
|
|
256
|
+
|
|
257
|
+
/* v1 has a 24-byte header (embedding section + phrase section). v2
|
|
258
|
+
* has a 64-byte header that ADDS ref_audio_tokens / ref_text /
|
|
259
|
+
* instruct / metadata section descriptors. We only care about the
|
|
260
|
+
* v2 sections — the embedding + phrase seed are handled in JS. */
|
|
261
|
+
if (version == 1u) {
|
|
262
|
+
/* v1: nothing the C side needs (embedding is fp32 for Kokoro
|
|
263
|
+
* etc., not OmniVoice). Mark empty and return OK. */
|
|
264
|
+
out.empty_payload = true;
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
if (len < 64) {
|
|
268
|
+
err = "voice preset v2 truncated header";
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
auto section_at = [&](size_t hdr_off, uint32_t & off, uint32_t & sz) {
|
|
272
|
+
off = eliza_le_u32(p + hdr_off);
|
|
273
|
+
sz = eliza_le_u32(p + hdr_off + 4);
|
|
274
|
+
};
|
|
275
|
+
uint32_t ref_tok_off = 0, ref_tok_sz = 0;
|
|
276
|
+
uint32_t ref_txt_off = 0, ref_txt_sz = 0;
|
|
277
|
+
uint32_t instr_off = 0, instr_sz = 0;
|
|
278
|
+
section_at(24, ref_tok_off, ref_tok_sz);
|
|
279
|
+
section_at(32, ref_txt_off, ref_txt_sz);
|
|
280
|
+
section_at(40, instr_off, instr_sz);
|
|
281
|
+
/* metadata at +48/+52 — we don't consume it on the C side. */
|
|
282
|
+
|
|
283
|
+
auto bounds_ok = [&](uint32_t off, uint32_t sz) {
|
|
284
|
+
if (sz == 0) return true;
|
|
285
|
+
if (off < 64) return false;
|
|
286
|
+
const size_t end = (size_t) off + (size_t) sz;
|
|
287
|
+
return end <= len;
|
|
288
|
+
};
|
|
289
|
+
if (!bounds_ok(ref_tok_off, ref_tok_sz) ||
|
|
290
|
+
!bounds_ok(ref_txt_off, ref_txt_sz) ||
|
|
291
|
+
!bounds_ok(instr_off, instr_sz)) {
|
|
292
|
+
err = "voice preset section out of bounds";
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (ref_tok_sz > 0) {
|
|
297
|
+
if (ref_tok_sz < 8) {
|
|
298
|
+
err = "voice preset ref_audio_tokens truncated";
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
const uint8_t * rt = p + ref_tok_off;
|
|
302
|
+
const uint32_t K = eliza_le_u32(rt);
|
|
303
|
+
const uint32_t refT = eliza_le_u32(rt + 4);
|
|
304
|
+
const size_t payload = ref_tok_sz - 8;
|
|
305
|
+
if (payload != (size_t) K * (size_t) refT * 4u) {
|
|
306
|
+
err = "voice preset ref_audio_tokens shape mismatch";
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
out.K = (int) K;
|
|
310
|
+
out.ref_T = (int) refT;
|
|
311
|
+
out.ref_audio_tokens.resize((size_t) K * (size_t) refT);
|
|
312
|
+
for (size_t i = 0; i < out.ref_audio_tokens.size(); ++i) {
|
|
313
|
+
out.ref_audio_tokens[i] = eliza_le_i32(rt + 8 + i * 4u);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (ref_txt_sz > 0) {
|
|
317
|
+
out.ref_text.assign(reinterpret_cast<const char *>(p + ref_txt_off),
|
|
318
|
+
(size_t) ref_txt_sz);
|
|
319
|
+
}
|
|
320
|
+
if (instr_sz > 0) {
|
|
321
|
+
out.instruct.assign(reinterpret_cast<const char *>(p + instr_off),
|
|
322
|
+
(size_t) instr_sz);
|
|
323
|
+
}
|
|
324
|
+
out.empty_payload =
|
|
325
|
+
out.instruct.empty() && out.ref_text.empty() && out.ref_audio_tokens.empty();
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* Resolve a preset id to a parsed preset. Returns nullptr if the id is
|
|
330
|
+
* unsafe, the file is missing, or parsing fails — in those cases the
|
|
331
|
+
* caller falls back to OmniVoice auto-voice (params.instruct = "")
|
|
332
|
+
* after logging via out_error.
|
|
333
|
+
*
|
|
334
|
+
* On a cache hit the cached preset is returned without re-reading the
|
|
335
|
+
* file. The preset table is keyed by voice id and lives on the
|
|
336
|
+
* EliInferenceContext, so two different contexts (different bundles)
|
|
337
|
+
* load independent presets.
|
|
338
|
+
*
|
|
339
|
+
* Caller must hold ctx->preset_mutex (or otherwise serialize). */
|
|
340
|
+
static const EliVoicePreset * eliza_load_voice_preset_locked(
|
|
341
|
+
EliInferenceContext * ctx,
|
|
342
|
+
const std::string & voice_id,
|
|
343
|
+
std::string & err) {
|
|
344
|
+
auto it = ctx->presets.find(voice_id);
|
|
345
|
+
if (it != ctx->presets.end()) return &it->second;
|
|
346
|
+
|
|
347
|
+
if (!eliza_is_safe_voice_id(voice_id)) {
|
|
348
|
+
err = "voice preset id is not a safe single segment: " + voice_id;
|
|
349
|
+
return nullptr;
|
|
350
|
+
}
|
|
351
|
+
std::filesystem::path file =
|
|
352
|
+
std::filesystem::path(ctx->bundle_dir) / "cache" /
|
|
353
|
+
("voice-preset-" + voice_id + ".bin");
|
|
354
|
+
std::error_code ec;
|
|
355
|
+
if (!std::filesystem::is_regular_file(file, ec)) {
|
|
356
|
+
err = "voice preset file not found: " + file.string();
|
|
357
|
+
return nullptr;
|
|
358
|
+
}
|
|
359
|
+
std::vector<uint8_t> bytes;
|
|
360
|
+
if (!eliza_read_file_bytes(file, bytes)) {
|
|
361
|
+
err = "voice preset file unreadable: " + file.string();
|
|
362
|
+
return nullptr;
|
|
363
|
+
}
|
|
364
|
+
EliVoicePreset preset;
|
|
365
|
+
preset.voice_id = voice_id;
|
|
366
|
+
if (!eliza_parse_voice_preset(bytes, preset, err)) {
|
|
367
|
+
return nullptr;
|
|
368
|
+
}
|
|
369
|
+
auto ins = ctx->presets.emplace(voice_id, std::move(preset));
|
|
370
|
+
return &ins.first->second;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/* Apply a resolved preset to an ov_tts_params struct. Sets instruct,
|
|
374
|
+
* ref_audio_tokens, ref_T, ref_text from the preset. Leaves
|
|
375
|
+
* ref_audio_24k / ref_n_samples alone — they are only used by the
|
|
376
|
+
* encode entrypoint, not synthesis. */
|
|
377
|
+
static void eliza_apply_preset_to_params(const EliVoicePreset & preset,
|
|
378
|
+
ov_tts_params * params) {
|
|
379
|
+
if (!preset.instruct.empty()) {
|
|
380
|
+
params->instruct = preset.instruct.c_str();
|
|
381
|
+
}
|
|
382
|
+
if (!preset.ref_audio_tokens.empty() && preset.K > 0 && preset.ref_T > 0) {
|
|
383
|
+
params->ref_audio_tokens = preset.ref_audio_tokens.data();
|
|
384
|
+
params->ref_T = preset.ref_T;
|
|
385
|
+
}
|
|
386
|
+
if (!preset.ref_text.empty()) {
|
|
387
|
+
params->ref_text = preset.ref_text.c_str();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
#define ELIZA_STRINGIFY_IMPL(x) #x
|
|
392
|
+
#define ELIZA_STRINGIFY(x) ELIZA_STRINGIFY_IMPL(x)
|
|
393
|
+
|
|
394
|
+
static char * eliza_strdup(const std::string & s) {
|
|
395
|
+
char * out = (char *) std::malloc(s.size() + 1);
|
|
396
|
+
if (!out) return nullptr;
|
|
397
|
+
std::memcpy(out, s.c_str(), s.size() + 1);
|
|
398
|
+
return out;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static void eliza_set_error(char ** out_error, const std::string & msg) {
|
|
402
|
+
if (!out_error) return;
|
|
403
|
+
*out_error = eliza_strdup(msg);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
static bool eliza_is_region(const char * region_name) {
|
|
407
|
+
return region_name &&
|
|
408
|
+
(std::strcmp(region_name, "tts") == 0 ||
|
|
409
|
+
std::strcmp(region_name, "asr") == 0 ||
|
|
410
|
+
std::strcmp(region_name, "text") == 0 ||
|
|
411
|
+
std::strcmp(region_name, "mtp") == 0 ||
|
|
412
|
+
std::strcmp(region_name, "vad") == 0);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
static std::vector<std::string> eliza_find_ggufs(const std::filesystem::path & dir) {
|
|
416
|
+
std::vector<std::string> out;
|
|
417
|
+
std::error_code ec;
|
|
418
|
+
if (!std::filesystem::exists(dir, ec) || !std::filesystem::is_directory(dir, ec)) return out;
|
|
419
|
+
for (const auto & entry : std::filesystem::recursive_directory_iterator(dir, ec)) {
|
|
420
|
+
if (ec) break;
|
|
421
|
+
if (!entry.is_regular_file(ec)) continue;
|
|
422
|
+
const auto path = entry.path();
|
|
423
|
+
if (path.extension() == ".gguf") out.push_back(path.string());
|
|
424
|
+
}
|
|
425
|
+
std::sort(out.begin(), out.end());
|
|
426
|
+
return out;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
static std::string eliza_lower_ascii(std::string value) {
|
|
430
|
+
std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) {
|
|
431
|
+
return (char) std::tolower(c);
|
|
432
|
+
});
|
|
433
|
+
return value;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
static bool eliza_pick_voice_files(
|
|
437
|
+
const std::filesystem::path & bundle_dir,
|
|
438
|
+
std::string & tts_model,
|
|
439
|
+
std::string & codec_model) {
|
|
440
|
+
std::vector<std::string> tts = eliza_find_ggufs(bundle_dir / "tts");
|
|
441
|
+
std::vector<std::string> codec = eliza_find_ggufs(bundle_dir / "codec");
|
|
442
|
+
if (tts.empty()) tts = eliza_find_ggufs(bundle_dir / "voice");
|
|
443
|
+
if (tts.empty()) return false;
|
|
444
|
+
|
|
445
|
+
std::vector<std::string> tts_candidates;
|
|
446
|
+
std::vector<std::string> codec_candidates = codec;
|
|
447
|
+
for (const std::string & path : tts) {
|
|
448
|
+
const std::string lower = eliza_lower_ascii(std::filesystem::path(path).filename().string());
|
|
449
|
+
const bool is_omnivoice = lower.find("omnivoice") != std::string::npos;
|
|
450
|
+
const bool is_codec = lower.find("tokenizer") != std::string::npos || lower.find("codec") != std::string::npos;
|
|
451
|
+
const bool is_other_voice = lower.find("kokoro") != std::string::npos;
|
|
452
|
+
if (is_omnivoice && !is_codec && !is_other_voice) {
|
|
453
|
+
tts_candidates.push_back(path);
|
|
454
|
+
}
|
|
455
|
+
if (is_omnivoice && is_codec) {
|
|
456
|
+
codec_candidates.push_back(path);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (tts_candidates.empty() || codec_candidates.empty()) {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
tts_model = tts_candidates[0];
|
|
465
|
+
codec_model = codec_candidates[0];
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
static bool eliza_pick_asr_files(
|
|
470
|
+
const std::filesystem::path & bundle_dir,
|
|
471
|
+
std::string & asr_model,
|
|
472
|
+
std::string & asr_mmproj) {
|
|
473
|
+
const auto asr_dir = bundle_dir / "asr";
|
|
474
|
+
std::error_code ec;
|
|
475
|
+
const auto canonical_model = asr_dir / "eliza-1-asr.gguf";
|
|
476
|
+
const auto canonical_mmproj = asr_dir / "eliza-1-asr-mmproj.gguf";
|
|
477
|
+
if (std::filesystem::is_regular_file(canonical_model, ec) &&
|
|
478
|
+
std::filesystem::is_regular_file(canonical_mmproj, ec)) {
|
|
479
|
+
asr_model = canonical_model.string();
|
|
480
|
+
asr_mmproj = canonical_mmproj.string();
|
|
481
|
+
return true;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
std::vector<std::string> asr = eliza_find_ggufs(asr_dir);
|
|
485
|
+
std::vector<std::string> model_candidates;
|
|
486
|
+
std::vector<std::string> mmproj_candidates;
|
|
487
|
+
for (const auto & candidate : asr) {
|
|
488
|
+
const std::string filename = eliza_lower_ascii(std::filesystem::path(candidate).filename().string());
|
|
489
|
+
if (filename.find("mmproj") != std::string::npos) {
|
|
490
|
+
mmproj_candidates.push_back(candidate);
|
|
491
|
+
} else if (filename.find("tokenizer") == std::string::npos &&
|
|
492
|
+
filename.find("support") == std::string::npos &&
|
|
493
|
+
filename.find("vocab") == std::string::npos) {
|
|
494
|
+
model_candidates.push_back(candidate);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (asr_model.empty() && model_candidates.size() == 1) {
|
|
498
|
+
asr_model = model_candidates[0];
|
|
499
|
+
}
|
|
500
|
+
if (asr_mmproj.empty() && mmproj_candidates.size() == 1) {
|
|
501
|
+
asr_mmproj = mmproj_candidates[0];
|
|
502
|
+
}
|
|
503
|
+
return !asr_model.empty() && !asr_mmproj.empty();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
static std::once_flag eliza_llama_backend_once;
|
|
507
|
+
|
|
508
|
+
static int eliza_thread_count(bool batch) {
|
|
509
|
+
unsigned int hw = std::thread::hardware_concurrency();
|
|
510
|
+
if (hw == 0) hw = 4;
|
|
511
|
+
const unsigned int cap = batch ? 8 : 4;
|
|
512
|
+
return (int) std::max(1u, std::min(hw, cap));
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
static void eliza_apply_tts_env_overrides(ov_tts_params * params) {
|
|
516
|
+
if (!params) return;
|
|
517
|
+
if (const char * env = std::getenv("ELIZA_TTS_MASKGIT_STEPS")) {
|
|
518
|
+
int n = std::atoi(env);
|
|
519
|
+
if (n >= 1 && n <= 64) {
|
|
520
|
+
params->mg_num_step = n;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (const char * env = std::getenv("ELIZA_TTS_CHUNK_DURATION_SEC")) {
|
|
524
|
+
char * end = nullptr;
|
|
525
|
+
float v = std::strtof(env, &end);
|
|
526
|
+
if (end != env && v > 0.0f && v <= 120.0f) {
|
|
527
|
+
params->chunk_duration_sec = v;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (const char * env = std::getenv("ELIZA_TTS_CHUNK_THRESHOLD_SEC")) {
|
|
531
|
+
char * end = nullptr;
|
|
532
|
+
float v = std::strtof(env, &end);
|
|
533
|
+
if (end != env && v > 0.0f && v <= 120.0f) {
|
|
534
|
+
params->chunk_threshold_sec = v;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/* ASR thread budget. The voice-realtime caps in eliza_thread_count() exist
|
|
540
|
+
* so TTS + the MTP drafter keep cores free during a streaming turn; the
|
|
541
|
+
* ASR Whisper-style audio encoder (the mmproj prefill via
|
|
542
|
+
* mtmd_helper_eval_chunks) and the short greedy text decode are *not*
|
|
543
|
+
* barge-in-sensitive — they run once per utterance, before TTS competes —
|
|
544
|
+
* so they can use more cores. Scale the encoder up to half the box (it is
|
|
545
|
+
* the dominant cost on a ~30 s window) and keep the decode moderate. The
|
|
546
|
+
* ELIZA_ASR_THREADS env var overrides both when set. */
|
|
547
|
+
static int eliza_asr_thread_count(bool encoder) {
|
|
548
|
+
if (const char * env = std::getenv("ELIZA_ASR_THREADS")) {
|
|
549
|
+
int n = std::atoi(env);
|
|
550
|
+
if (n > 0) return n;
|
|
551
|
+
}
|
|
552
|
+
unsigned int hw = std::thread::hardware_concurrency();
|
|
553
|
+
if (hw == 0) hw = 4;
|
|
554
|
+
const unsigned int cap = encoder ? std::max(8u, hw / 2u) : std::max(4u, hw / 4u);
|
|
555
|
+
return (int) std::max(1u, std::min(hw, cap));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
static std::vector<float> eliza_resample_linear(
|
|
559
|
+
const float * pcm,
|
|
560
|
+
size_t n_samples,
|
|
561
|
+
int source_rate,
|
|
562
|
+
int target_rate) {
|
|
563
|
+
if (source_rate == target_rate || n_samples <= 1) {
|
|
564
|
+
return std::vector<float>(pcm, pcm + n_samples);
|
|
565
|
+
}
|
|
566
|
+
const double scale = (double) target_rate / (double) source_rate;
|
|
567
|
+
const size_t out_samples = std::max<size_t>(1, (size_t) std::llround((double) n_samples * scale));
|
|
568
|
+
std::vector<float> out(out_samples);
|
|
569
|
+
for (size_t i = 0; i < out_samples; ++i) {
|
|
570
|
+
const double src = (double) i * (double) source_rate / (double) target_rate;
|
|
571
|
+
const size_t lo = std::min((size_t) std::floor(src), n_samples - 1);
|
|
572
|
+
const size_t hi = std::min(lo + 1, n_samples - 1);
|
|
573
|
+
const float t = (float) (src - (double) lo);
|
|
574
|
+
out[i] = pcm[lo] * (1.0f - t) + pcm[hi] * t;
|
|
575
|
+
}
|
|
576
|
+
return out;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
static std::string eliza_llama_token_piece(const llama_vocab * vocab, llama_token token) {
|
|
580
|
+
char small[256];
|
|
581
|
+
int32_t n = llama_token_to_piece(vocab, token, small, (int32_t) sizeof(small), 0, false);
|
|
582
|
+
if (n > 0) return std::string(small, (size_t) n);
|
|
583
|
+
if (n == 0) return "";
|
|
584
|
+
std::string buf((size_t) -n, '\\0');
|
|
585
|
+
n = llama_token_to_piece(vocab, token, buf.data(), (int32_t) buf.size(), 0, false);
|
|
586
|
+
if (n > 0) return std::string(buf.data(), (size_t) n);
|
|
587
|
+
return "";
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
static std::string eliza_trim_ascii(std::string value);
|
|
591
|
+
|
|
592
|
+
static std::string eliza_asr_force_language() {
|
|
593
|
+
const char * env = std::getenv("ELIZA_ASR_FORCE_LANGUAGE");
|
|
594
|
+
if (!env) return "English";
|
|
595
|
+
std::string value = eliza_trim_ascii(env);
|
|
596
|
+
std::string lower = value;
|
|
597
|
+
std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c) {
|
|
598
|
+
return (char) std::tolower(c);
|
|
599
|
+
});
|
|
600
|
+
if (lower.empty() || lower == "0" || lower == "false" || lower == "none" || lower == "auto") {
|
|
601
|
+
return "";
|
|
602
|
+
}
|
|
603
|
+
return value;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
static std::string eliza_format_asr_prompt(llama_model * model) {
|
|
607
|
+
(void) model;
|
|
608
|
+
// Match llama-mtmd-cli's Qwen3-ASR path: one user turn with audio first,
|
|
609
|
+
// a plain transcription instruction, then the assistant generation prompt.
|
|
610
|
+
// Forcing "language X<asr_text>" before decode makes the 0.6B ASR emit EOG
|
|
611
|
+
// too early on short mobile-loopback clips.
|
|
612
|
+
std::string prompt = std::string("<|im_start|>user\\n") +
|
|
613
|
+
mtmd_default_marker() +
|
|
614
|
+
"Transcribe audio to text";
|
|
615
|
+
std::string language = eliza_asr_force_language();
|
|
616
|
+
if (!language.empty()) {
|
|
617
|
+
prompt += " in " + language;
|
|
618
|
+
}
|
|
619
|
+
prompt += "<|im_end|>\\n<|im_start|>assistant\\n";
|
|
620
|
+
return prompt;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
static std::string eliza_trim_ascii(std::string value) {
|
|
624
|
+
auto is_space = [](unsigned char c) {
|
|
625
|
+
return c == ' ' || c == '\\n' || c == '\\r' || c == '\\t';
|
|
626
|
+
};
|
|
627
|
+
while (!value.empty() && is_space((unsigned char) value.front())) {
|
|
628
|
+
value.erase(value.begin());
|
|
629
|
+
}
|
|
630
|
+
while (!value.empty() && is_space((unsigned char) value.back())) {
|
|
631
|
+
value.pop_back();
|
|
632
|
+
}
|
|
633
|
+
return value;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
static std::string eliza_clean_asr_transcript(std::string transcript) {
|
|
637
|
+
const std::string asr_marker = "<asr_text>";
|
|
638
|
+
size_t marker = transcript.find(asr_marker);
|
|
639
|
+
if (marker != std::string::npos) {
|
|
640
|
+
transcript = transcript.substr(marker + asr_marker.size());
|
|
641
|
+
}
|
|
642
|
+
const char * sentinels[] = {
|
|
643
|
+
"<|im_start|>",
|
|
644
|
+
"<|im_end|>",
|
|
645
|
+
"<|endoftext|>",
|
|
646
|
+
"<|audio_start|>",
|
|
647
|
+
"<|audio_end|>",
|
|
648
|
+
"<|vision_start|>",
|
|
649
|
+
"<|vision_end|>",
|
|
650
|
+
"</s>",
|
|
651
|
+
};
|
|
652
|
+
for (const char * sentinel : sentinels) {
|
|
653
|
+
size_t pos = transcript.find(sentinel);
|
|
654
|
+
if (pos != std::string::npos) {
|
|
655
|
+
transcript = transcript.substr(0, pos);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
transcript = eliza_trim_ascii(transcript);
|
|
659
|
+
for (const char * sentinel : sentinels) {
|
|
660
|
+
std::string full(sentinel);
|
|
661
|
+
if (full.rfind(transcript, 0) == 0) {
|
|
662
|
+
return "";
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return transcript;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
static bool eliza_asr_has_text_payload(const std::string & transcript) {
|
|
669
|
+
for (unsigned char c : transcript) {
|
|
670
|
+
if (std::isalnum(c)) return true;
|
|
671
|
+
}
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
static int eliza_map_ov_status(ov_status rc) {
|
|
676
|
+
if (rc == OV_STATUS_OK) return ELIZA_OK;
|
|
677
|
+
if (rc == OV_STATUS_OOM) return ELIZA_ERR_OOM;
|
|
678
|
+
if (rc == OV_STATUS_CANCELLED) return ELIZA_ERR_CANCELLED;
|
|
679
|
+
if (rc == OV_STATUS_INVALID_PARAMS || rc == OV_STATUS_INSTRUCT_INVALID) return ELIZA_ERR_INVALID_ARG;
|
|
680
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
static bool eliza_tts_cancel_requested(void * user_data) {
|
|
684
|
+
EliInferenceContext * ctx = (EliInferenceContext *) user_data;
|
|
685
|
+
return ctx && ctx->tts_cancel.load(std::memory_order_acquire);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
struct ElizaScopedTtsForward {
|
|
689
|
+
EliInferenceContext * ctx;
|
|
690
|
+
|
|
691
|
+
explicit ElizaScopedTtsForward(EliInferenceContext * c) : ctx(c) {
|
|
692
|
+
if (ctx) ctx->tts_cancel.store(false, std::memory_order_release);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
~ElizaScopedTtsForward() {
|
|
696
|
+
if (ctx) ctx->tts_cancel.store(false, std::memory_order_release);
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
struct ElizaTtsStreamState {
|
|
701
|
+
EliInferenceContext * ctx;
|
|
702
|
+
eliza_tts_chunk_cb on_chunk;
|
|
703
|
+
void * user_data;
|
|
704
|
+
bool callback_cancelled;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
static bool eliza_tts_stream_chunk(const float * samples, int n_samples, void * user_data) {
|
|
708
|
+
ElizaTtsStreamState * state = (ElizaTtsStreamState *) user_data;
|
|
709
|
+
if (!state || !state->on_chunk) return false;
|
|
710
|
+
if (state->ctx && state->ctx->tts_cancel.load(std::memory_order_acquire)) return false;
|
|
711
|
+
const int rc = state->on_chunk(samples, n_samples < 0 ? 0 : (size_t) n_samples, 0, state->user_data);
|
|
712
|
+
if (rc != 0) {
|
|
713
|
+
state->callback_cancelled = true;
|
|
714
|
+
if (state->ctx) state->ctx->tts_cancel.store(true, std::memory_order_release);
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
return !(state->ctx && state->ctx->tts_cancel.load(std::memory_order_acquire));
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
static void eliza_free_asr(EliInferenceContext * ctx) {
|
|
721
|
+
if (!ctx) return;
|
|
722
|
+
if (ctx->asr_sampler) {
|
|
723
|
+
llama_sampler_free(ctx->asr_sampler);
|
|
724
|
+
ctx->asr_sampler = nullptr;
|
|
725
|
+
}
|
|
726
|
+
if (ctx->asr_mtmd) {
|
|
727
|
+
mtmd_free(ctx->asr_mtmd);
|
|
728
|
+
ctx->asr_mtmd = nullptr;
|
|
729
|
+
}
|
|
730
|
+
if (ctx->asr_lctx) {
|
|
731
|
+
llama_free(ctx->asr_lctx);
|
|
732
|
+
ctx->asr_lctx = nullptr;
|
|
733
|
+
}
|
|
734
|
+
if (ctx->asr_model) {
|
|
735
|
+
llama_model_free(ctx->asr_model);
|
|
736
|
+
ctx->asr_model = nullptr;
|
|
737
|
+
}
|
|
738
|
+
ctx->asr_sample_rate = 0;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
static int eliza_load_tts(EliInferenceContext * ctx, char ** out_error) {
|
|
742
|
+
if (!ctx) {
|
|
743
|
+
eliza_set_error(out_error, "[libelizainference] load_tts: ctx is NULL");
|
|
744
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
745
|
+
}
|
|
746
|
+
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
747
|
+
if (ctx->ov) return ELIZA_OK;
|
|
748
|
+
if (ctx->tts_model_path.empty()) {
|
|
749
|
+
if (!eliza_pick_voice_files(std::filesystem::path(ctx->bundle_dir), ctx->tts_model_path, ctx->codec_model_path)) {
|
|
750
|
+
eliza_set_error(out_error, std::string("[libelizainference] no TTS GGUF found under ") + (std::filesystem::path(ctx->bundle_dir) / "tts").string());
|
|
751
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
ov_init_params params;
|
|
756
|
+
ov_init_default_params(¶ms);
|
|
757
|
+
params.model_path = ctx->tts_model_path.c_str();
|
|
758
|
+
params.codec_path = ctx->codec_model_path.c_str();
|
|
759
|
+
params.use_fa = true;
|
|
760
|
+
ctx->ov = ov_init(¶ms);
|
|
761
|
+
if (!ctx->ov) {
|
|
762
|
+
std::string msg = "[libelizainference] ov_init failed: ";
|
|
763
|
+
msg += ov_last_error();
|
|
764
|
+
msg += " tts_model=";
|
|
765
|
+
msg += ctx->tts_model_path;
|
|
766
|
+
msg += " codec_model=";
|
|
767
|
+
msg += ctx->codec_model_path;
|
|
768
|
+
eliza_set_error(out_error, msg);
|
|
769
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
770
|
+
}
|
|
771
|
+
return ELIZA_OK;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
static int eliza_load_asr(EliInferenceContext * ctx, char ** out_error) {
|
|
775
|
+
if (!ctx) {
|
|
776
|
+
eliza_set_error(out_error, "[libelizainference] load_asr: ctx is NULL");
|
|
777
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
778
|
+
}
|
|
779
|
+
std::lock_guard<std::mutex> lock(ctx->asr_mutex);
|
|
780
|
+
if (ctx->asr_model && ctx->asr_lctx && ctx->asr_mtmd && ctx->asr_sampler) {
|
|
781
|
+
return ELIZA_OK;
|
|
782
|
+
}
|
|
783
|
+
if (ctx->asr_model_path.empty() || ctx->asr_mmproj_path.empty()) {
|
|
784
|
+
if (!eliza_pick_asr_files(std::filesystem::path(ctx->bundle_dir), ctx->asr_model_path, ctx->asr_mmproj_path)) {
|
|
785
|
+
eliza_set_error(out_error, std::string("[libelizainference] ASR requires both a text GGUF and mmproj GGUF under ") + (std::filesystem::path(ctx->bundle_dir) / "asr").string());
|
|
786
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
std::call_once(eliza_llama_backend_once, []() {
|
|
791
|
+
llama_backend_init();
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
llama_model_params mparams = llama_model_default_params();
|
|
795
|
+
mparams.n_gpu_layers = 99;
|
|
796
|
+
mparams.use_mmap = true;
|
|
797
|
+
ctx->asr_model = llama_model_load_from_file(ctx->asr_model_path.c_str(), mparams);
|
|
798
|
+
if (!ctx->asr_model) {
|
|
799
|
+
eliza_free_asr(ctx);
|
|
800
|
+
eliza_set_error(out_error, std::string("[libelizainference] failed to load ASR model: ") + ctx->asr_model_path);
|
|
801
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
llama_context_params cparams = llama_context_default_params();
|
|
805
|
+
cparams.n_ctx = 8192;
|
|
806
|
+
cparams.n_batch = (uint32_t) ctx->asr_n_batch;
|
|
807
|
+
cparams.n_ubatch = (uint32_t) ctx->asr_n_batch;
|
|
808
|
+
cparams.n_threads = eliza_asr_thread_count(false);
|
|
809
|
+
cparams.n_threads_batch = eliza_asr_thread_count(true);
|
|
810
|
+
cparams.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_AUTO;
|
|
811
|
+
ctx->asr_lctx = llama_init_from_model(ctx->asr_model, cparams);
|
|
812
|
+
if (!ctx->asr_lctx) {
|
|
813
|
+
eliza_free_asr(ctx);
|
|
814
|
+
eliza_set_error(out_error, "[libelizainference] failed to initialize ASR llama context");
|
|
815
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
mtmd_context_params aparams = mtmd_context_params_default();
|
|
819
|
+
aparams.use_gpu = true;
|
|
820
|
+
aparams.print_timings = false;
|
|
821
|
+
aparams.n_threads = eliza_asr_thread_count(true);
|
|
822
|
+
aparams.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_AUTO;
|
|
823
|
+
aparams.warmup = true;
|
|
824
|
+
ctx->asr_mtmd = mtmd_init_from_file(ctx->asr_mmproj_path.c_str(), ctx->asr_model, aparams);
|
|
825
|
+
if (!ctx->asr_mtmd) {
|
|
826
|
+
eliza_free_asr(ctx);
|
|
827
|
+
eliza_set_error(out_error, std::string("[libelizainference] failed to load ASR mmproj: ") + ctx->asr_mmproj_path);
|
|
828
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
829
|
+
}
|
|
830
|
+
if (!mtmd_support_audio(ctx->asr_mtmd)) {
|
|
831
|
+
eliza_free_asr(ctx);
|
|
832
|
+
eliza_set_error(out_error, "[libelizainference] ASR mmproj does not report audio support");
|
|
833
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
834
|
+
}
|
|
835
|
+
ctx->asr_sample_rate = mtmd_get_audio_sample_rate(ctx->asr_mtmd);
|
|
836
|
+
if (ctx->asr_sample_rate <= 0) {
|
|
837
|
+
eliza_free_asr(ctx);
|
|
838
|
+
eliza_set_error(out_error, "[libelizainference] ASR mmproj returned an invalid audio sample rate");
|
|
839
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
llama_sampler_chain_params sparams = llama_sampler_chain_default_params();
|
|
843
|
+
ctx->asr_sampler = llama_sampler_chain_init(sparams);
|
|
844
|
+
if (!ctx->asr_sampler) {
|
|
845
|
+
eliza_free_asr(ctx);
|
|
846
|
+
eliza_set_error(out_error, "[libelizainference] failed to initialize ASR sampler");
|
|
847
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
848
|
+
}
|
|
849
|
+
llama_sampler_chain_add(ctx->asr_sampler, llama_sampler_init_greedy());
|
|
850
|
+
return ELIZA_OK;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/* ---- Streaming LLM (text generation) ------------------------------- *
|
|
854
|
+
* Deprecated-graft mirror of the in-tree
|
|
855
|
+
* tools/omnivoice/src/eliza-inference-ffi.cpp implementation. See the ABI
|
|
856
|
+
* in tools/omnivoice/include/eliza-inference-ffi.h. */
|
|
857
|
+
|
|
858
|
+
static int eliza_llm_int_env_or_default(const char * name, int fallback) {
|
|
859
|
+
if (const char * env = std::getenv(name)) {
|
|
860
|
+
int n = std::atoi(env);
|
|
861
|
+
if (n > 0) return n;
|
|
862
|
+
}
|
|
863
|
+
return fallback;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
static bool eliza_llm_bool_env_or_default(const char * name, bool fallback) {
|
|
867
|
+
if (const char * env = std::getenv(name)) {
|
|
868
|
+
std::string value = env;
|
|
869
|
+
std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) {
|
|
870
|
+
return (char) std::tolower(c);
|
|
871
|
+
});
|
|
872
|
+
if (value == "1" || value == "true" || value == "yes" || value == "on") return true;
|
|
873
|
+
if (value == "0" || value == "false" || value == "no" || value == "off") return false;
|
|
874
|
+
}
|
|
875
|
+
return fallback;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
struct EliLlmStream {
|
|
879
|
+
EliInferenceContext * ctx = nullptr;
|
|
880
|
+
llama_context * lctx = nullptr;
|
|
881
|
+
llama_sampler * sampler = nullptr;
|
|
882
|
+
int n_past = 0;
|
|
883
|
+
int generated = 0;
|
|
884
|
+
int max_tokens = 0;
|
|
885
|
+
bool eos = false;
|
|
886
|
+
std::atomic<bool> cancel{false};
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
static bool eliza_pick_text_file(
|
|
890
|
+
const std::filesystem::path & bundle_dir,
|
|
891
|
+
std::string & text_model) {
|
|
892
|
+
std::vector<std::string> candidates = eliza_find_ggufs(bundle_dir / "text");
|
|
893
|
+
std::vector<std::string> picked;
|
|
894
|
+
for (const std::string & path : candidates) {
|
|
895
|
+
const std::string lower =
|
|
896
|
+
eliza_lower_ascii(std::filesystem::path(path).filename().string());
|
|
897
|
+
if (lower.find("mmproj") != std::string::npos) continue;
|
|
898
|
+
if (lower.find("tokenizer") != std::string::npos) continue;
|
|
899
|
+
if (lower.find("codec") != std::string::npos) continue;
|
|
900
|
+
picked.push_back(path);
|
|
901
|
+
}
|
|
902
|
+
if (picked.empty()) return false;
|
|
903
|
+
text_model = picked[0];
|
|
904
|
+
return true;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
static int eliza_load_llm_model_locked(
|
|
908
|
+
EliInferenceContext * ctx,
|
|
909
|
+
char ** out_error) {
|
|
910
|
+
if (ctx->llm_model) return ELIZA_OK;
|
|
911
|
+
if (ctx->llm_model_path.empty()) {
|
|
912
|
+
if (!eliza_pick_text_file(std::filesystem::path(ctx->bundle_dir),
|
|
913
|
+
ctx->llm_model_path)) {
|
|
914
|
+
eliza_set_error(out_error,
|
|
915
|
+
std::string("[libelizainference] no text GGUF found under ") +
|
|
916
|
+
(std::filesystem::path(ctx->bundle_dir) / "text").string());
|
|
917
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
std::call_once(eliza_llama_backend_once, []() { llama_backend_init(); });
|
|
921
|
+
llama_model_params mparams = llama_model_default_params();
|
|
922
|
+
mparams.n_gpu_layers = eliza_llm_bool_env_or_default("ELIZA_LLM_USE_GPU", true) ? 99 : 0;
|
|
923
|
+
mparams.use_mmap = true;
|
|
924
|
+
ctx->llm_model = llama_model_load_from_file(ctx->llm_model_path.c_str(), mparams);
|
|
925
|
+
if (!ctx->llm_model) {
|
|
926
|
+
eliza_set_error(out_error,
|
|
927
|
+
std::string("[libelizainference] failed to load text model: ") +
|
|
928
|
+
ctx->llm_model_path);
|
|
929
|
+
return ELIZA_ERR_BUNDLE_INVALID;
|
|
930
|
+
}
|
|
931
|
+
return ELIZA_OK;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
static llama_sampler * eliza_build_llm_sampler_chain(
|
|
935
|
+
const llama_model * model,
|
|
936
|
+
const eliza_llm_stream_config_t * cfg,
|
|
937
|
+
char ** out_error) {
|
|
938
|
+
const llama_vocab * vocab = llama_model_get_vocab(model);
|
|
939
|
+
llama_sampler_chain_params sparams = llama_sampler_chain_default_params();
|
|
940
|
+
llama_sampler * chain = llama_sampler_chain_init(sparams);
|
|
941
|
+
if (!chain) {
|
|
942
|
+
eliza_set_error(out_error,
|
|
943
|
+
"[libelizainference] llm_stream: failed to init sampler chain");
|
|
944
|
+
return nullptr;
|
|
945
|
+
}
|
|
946
|
+
if (cfg->gbnf_grammar && cfg->gbnf_grammar[0] != '\\0') {
|
|
947
|
+
llama_sampler * grammar = llama_sampler_init_grammar(vocab, cfg->gbnf_grammar, "root");
|
|
948
|
+
if (!grammar) {
|
|
949
|
+
llama_sampler_free(chain);
|
|
950
|
+
eliza_set_error(out_error,
|
|
951
|
+
"[libelizainference] llm_stream: GBNF grammar failed to parse");
|
|
952
|
+
return nullptr;
|
|
953
|
+
}
|
|
954
|
+
llama_sampler_chain_add(chain, grammar);
|
|
955
|
+
}
|
|
956
|
+
if (cfg->repeat_penalty != 0.0f && cfg->repeat_penalty != 1.0f) {
|
|
957
|
+
llama_sampler_chain_add(chain,
|
|
958
|
+
llama_sampler_init_penalties(64, cfg->repeat_penalty, 0.0f, 0.0f));
|
|
959
|
+
}
|
|
960
|
+
const bool greedy = cfg->temperature <= 0.0f;
|
|
961
|
+
if (!greedy) {
|
|
962
|
+
if (cfg->top_k > 0) {
|
|
963
|
+
llama_sampler_chain_add(chain, llama_sampler_init_top_k(cfg->top_k));
|
|
964
|
+
}
|
|
965
|
+
if (cfg->top_p > 0.0f && cfg->top_p < 1.0f) {
|
|
966
|
+
llama_sampler_chain_add(chain, llama_sampler_init_top_p(cfg->top_p, 1));
|
|
967
|
+
}
|
|
968
|
+
llama_sampler_chain_add(chain, llama_sampler_init_temp(cfg->temperature));
|
|
969
|
+
llama_sampler_chain_add(chain, llama_sampler_init_dist(LLAMA_DEFAULT_SEED));
|
|
970
|
+
} else {
|
|
971
|
+
llama_sampler_chain_add(chain, llama_sampler_init_greedy());
|
|
972
|
+
}
|
|
973
|
+
return chain;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
extern "C" {
|
|
977
|
+
|
|
978
|
+
const char * eliza_inference_abi_version(void) {
|
|
979
|
+
// Keep this tied to ffi.h so ABI bumps cannot drift between the
|
|
980
|
+
// generated adapter and the TypeScript loader.
|
|
981
|
+
// Keep in lockstep with ELIZA_INFERENCE_ABI_VERSION in
|
|
982
|
+
// packages/app-core/src/services/local-inference/voice/ffi-bindings.ts.
|
|
983
|
+
return ELIZA_STRINGIFY(ELIZA_INFERENCE_ABI_VERSION);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
EliInferenceContext * eliza_inference_create(
|
|
987
|
+
const char * bundle_dir,
|
|
988
|
+
char ** out_error) {
|
|
989
|
+
if (!bundle_dir || bundle_dir[0] == '\\0') {
|
|
990
|
+
eliza_set_error(out_error, "[libelizainference] bundle_dir is required");
|
|
991
|
+
return nullptr;
|
|
992
|
+
}
|
|
993
|
+
std::filesystem::path root(bundle_dir);
|
|
994
|
+
std::error_code ec;
|
|
995
|
+
if (!std::filesystem::exists(root, ec) || !std::filesystem::is_directory(root, ec)) {
|
|
996
|
+
eliza_set_error(out_error, std::string("[libelizainference] bundle_dir does not exist: ") + bundle_dir);
|
|
997
|
+
return nullptr;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
EliInferenceContext * ctx = new (std::nothrow) EliInferenceContext();
|
|
1001
|
+
if (!ctx) {
|
|
1002
|
+
eliza_set_error(out_error, "[libelizainference] out of memory allocating context");
|
|
1003
|
+
return nullptr;
|
|
1004
|
+
}
|
|
1005
|
+
ctx->bundle_dir = root.string();
|
|
1006
|
+
|
|
1007
|
+
// Metadata-only: heavy voice weights are intentionally loaded by
|
|
1008
|
+
// eliza_inference_mmap_acquire("tts") so voice-off does not keep
|
|
1009
|
+
// OmniVoice resident.
|
|
1010
|
+
return ctx;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
void eliza_inference_destroy(EliInferenceContext * ctx) {
|
|
1014
|
+
if (!ctx) return;
|
|
1015
|
+
{
|
|
1016
|
+
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
1017
|
+
ov_free(ctx->ov);
|
|
1018
|
+
ctx->ov = nullptr;
|
|
1019
|
+
}
|
|
1020
|
+
{
|
|
1021
|
+
std::lock_guard<std::mutex> lock(ctx->asr_mutex);
|
|
1022
|
+
eliza_free_asr(ctx);
|
|
1023
|
+
}
|
|
1024
|
+
{
|
|
1025
|
+
std::lock_guard<std::mutex> lock(ctx->llm_mutex);
|
|
1026
|
+
if (ctx->llm_model) {
|
|
1027
|
+
llama_model_free(ctx->llm_model);
|
|
1028
|
+
ctx->llm_model = nullptr;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
delete ctx;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
int eliza_inference_mmap_acquire(
|
|
1035
|
+
EliInferenceContext * ctx,
|
|
1036
|
+
const char * region_name,
|
|
1037
|
+
char ** out_error) {
|
|
1038
|
+
if (!ctx) {
|
|
1039
|
+
eliza_set_error(out_error, "[libelizainference] mmap_acquire: ctx is NULL");
|
|
1040
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1041
|
+
}
|
|
1042
|
+
if (!eliza_is_region(region_name)) {
|
|
1043
|
+
eliza_set_error(out_error, "[libelizainference] mmap_acquire: invalid region");
|
|
1044
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1045
|
+
}
|
|
1046
|
+
if (std::strcmp(region_name, "tts") == 0) {
|
|
1047
|
+
return eliza_load_tts(ctx, out_error);
|
|
1048
|
+
}
|
|
1049
|
+
if (std::strcmp(region_name, "asr") == 0) {
|
|
1050
|
+
return eliza_load_asr(ctx, out_error);
|
|
1051
|
+
}
|
|
1052
|
+
return ELIZA_OK;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
int eliza_inference_mmap_evict(
|
|
1056
|
+
EliInferenceContext * ctx,
|
|
1057
|
+
const char * region_name,
|
|
1058
|
+
char ** out_error) {
|
|
1059
|
+
if (!ctx) {
|
|
1060
|
+
eliza_set_error(out_error, "[libelizainference] mmap_evict: ctx is NULL");
|
|
1061
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1062
|
+
}
|
|
1063
|
+
if (!eliza_is_region(region_name)) {
|
|
1064
|
+
eliza_set_error(out_error, "[libelizainference] mmap_evict: invalid region");
|
|
1065
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1066
|
+
}
|
|
1067
|
+
if (std::strcmp(region_name, "tts") == 0) {
|
|
1068
|
+
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
1069
|
+
if (ctx->ov) {
|
|
1070
|
+
ov_free(ctx->ov);
|
|
1071
|
+
ctx->ov = nullptr;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
if (std::strcmp(region_name, "asr") == 0) {
|
|
1075
|
+
std::lock_guard<std::mutex> lock(ctx->asr_mutex);
|
|
1076
|
+
eliza_free_asr(ctx);
|
|
1077
|
+
}
|
|
1078
|
+
return ELIZA_OK;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
int eliza_inference_tts_synthesize(
|
|
1082
|
+
EliInferenceContext * ctx,
|
|
1083
|
+
const char * text,
|
|
1084
|
+
size_t text_len,
|
|
1085
|
+
const char * speaker_preset_id,
|
|
1086
|
+
float * out_pcm,
|
|
1087
|
+
size_t max_samples,
|
|
1088
|
+
char ** out_error) {
|
|
1089
|
+
if (!ctx || !out_pcm || max_samples == 0) {
|
|
1090
|
+
eliza_set_error(out_error, "[libelizainference] tts_synthesize: invalid arguments");
|
|
1091
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1092
|
+
}
|
|
1093
|
+
if (!text || text_len == 0) {
|
|
1094
|
+
eliza_set_error(out_error, "[libelizainference] tts_synthesize: text is required");
|
|
1095
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
1099
|
+
if (!ctx->ov) {
|
|
1100
|
+
eliza_set_error(out_error, "[libelizainference] tts_synthesize: TTS region is not acquired; call mmap_acquire(\\"tts\\") after arming voice");
|
|
1101
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1102
|
+
}
|
|
1103
|
+
ElizaScopedTtsForward forward(ctx);
|
|
1104
|
+
|
|
1105
|
+
std::string text_owned(text, text_len);
|
|
1106
|
+
ov_tts_params params;
|
|
1107
|
+
ov_tts_default_params(¶ms);
|
|
1108
|
+
eliza_apply_tts_env_overrides(¶ms);
|
|
1109
|
+
params.text = text_owned.c_str();
|
|
1110
|
+
/* Default to OmniVoice's auto-voice path. The preset (if any)
|
|
1111
|
+
* overwrites params.instruct / ref_audio_tokens / ref_text via
|
|
1112
|
+
* eliza_apply_preset_to_params below. */
|
|
1113
|
+
params.instruct = "";
|
|
1114
|
+
if (speaker_preset_id && speaker_preset_id[0] != '\\0') {
|
|
1115
|
+
std::string preset_err;
|
|
1116
|
+
const EliVoicePreset * preset = nullptr;
|
|
1117
|
+
{
|
|
1118
|
+
std::lock_guard<std::mutex> preset_lock(ctx->preset_mutex);
|
|
1119
|
+
preset = eliza_load_voice_preset_locked(ctx, speaker_preset_id, preset_err);
|
|
1120
|
+
}
|
|
1121
|
+
if (preset && !preset->empty_payload) {
|
|
1122
|
+
eliza_apply_preset_to_params(*preset, ¶ms);
|
|
1123
|
+
}
|
|
1124
|
+
/* A missing or v1-only preset is not fatal — auto-voice mode
|
|
1125
|
+
* still produces audio. The preset_err is only surfaced via
|
|
1126
|
+
* out_error when synthesis itself fails. */
|
|
1127
|
+
}
|
|
1128
|
+
params.cancel = eliza_tts_cancel_requested;
|
|
1129
|
+
params.cancel_user_data = ctx;
|
|
1130
|
+
|
|
1131
|
+
ov_audio audio = {};
|
|
1132
|
+
ov_status rc = ov_synthesize(ctx->ov, ¶ms, &audio);
|
|
1133
|
+
if (rc != OV_STATUS_OK) {
|
|
1134
|
+
std::string msg = "[libelizainference] ov_synthesize failed: ";
|
|
1135
|
+
msg += ov_last_error();
|
|
1136
|
+
ov_audio_free(&audio);
|
|
1137
|
+
eliza_set_error(out_error, msg);
|
|
1138
|
+
return eliza_map_ov_status(rc);
|
|
1139
|
+
}
|
|
1140
|
+
if (audio.n_samples < 0 || (size_t) audio.n_samples > max_samples) {
|
|
1141
|
+
std::string msg = "[libelizainference] output buffer too small; required samples=" +
|
|
1142
|
+
std::to_string(audio.n_samples);
|
|
1143
|
+
ov_audio_free(&audio);
|
|
1144
|
+
eliza_set_error(out_error, msg);
|
|
1145
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1146
|
+
}
|
|
1147
|
+
std::memcpy(out_pcm, audio.samples, (size_t) audio.n_samples * sizeof(float));
|
|
1148
|
+
int written = audio.n_samples;
|
|
1149
|
+
ov_audio_free(&audio);
|
|
1150
|
+
return written;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
int eliza_inference_asr_transcribe(
|
|
1154
|
+
EliInferenceContext * ctx,
|
|
1155
|
+
const float * pcm,
|
|
1156
|
+
size_t n_samples,
|
|
1157
|
+
int sample_rate_hz,
|
|
1158
|
+
char * out_text,
|
|
1159
|
+
size_t max_text_bytes,
|
|
1160
|
+
char ** out_error) {
|
|
1161
|
+
if (!ctx || !pcm || !out_text || max_text_bytes == 0 || sample_rate_hz <= 0) {
|
|
1162
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: invalid arguments");
|
|
1163
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1164
|
+
}
|
|
1165
|
+
if (n_samples == 0) {
|
|
1166
|
+
out_text[0] = '\\0';
|
|
1167
|
+
return 0;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
std::lock_guard<std::mutex> lock(ctx->asr_mutex);
|
|
1171
|
+
if (!ctx->asr_model || !ctx->asr_lctx || !ctx->asr_mtmd || !ctx->asr_sampler) {
|
|
1172
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: ASR region is not acquired; call mmap_acquire(\\"asr\\") after arming voice input");
|
|
1173
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
std::vector<float> audio = eliza_resample_linear(pcm, n_samples, sample_rate_hz, ctx->asr_sample_rate);
|
|
1177
|
+
std::unique_ptr<mtmd_bitmap, decltype(&mtmd_bitmap_free)> bitmap(
|
|
1178
|
+
mtmd_bitmap_init_from_audio(audio.size(), audio.data()),
|
|
1179
|
+
mtmd_bitmap_free);
|
|
1180
|
+
if (!bitmap) {
|
|
1181
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: failed to create audio bitmap");
|
|
1182
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
std::string prompt = eliza_format_asr_prompt(ctx->asr_model);
|
|
1186
|
+
mtmd_input_text text = { prompt.c_str(), true, true };
|
|
1187
|
+
const mtmd_bitmap * bitmaps[] = { bitmap.get() };
|
|
1188
|
+
std::unique_ptr<mtmd_input_chunks, decltype(&mtmd_input_chunks_free)> chunks(
|
|
1189
|
+
mtmd_input_chunks_init(),
|
|
1190
|
+
mtmd_input_chunks_free);
|
|
1191
|
+
if (!chunks) {
|
|
1192
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: failed to allocate input chunks");
|
|
1193
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1194
|
+
}
|
|
1195
|
+
int32_t tok_rc = mtmd_tokenize(ctx->asr_mtmd, chunks.get(), &text, bitmaps, 1);
|
|
1196
|
+
if (tok_rc != 0) {
|
|
1197
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: mtmd_tokenize failed rc=" + std::to_string(tok_rc));
|
|
1198
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
llama_memory_clear(llama_get_memory(ctx->asr_lctx), true);
|
|
1202
|
+
llama_sampler_reset(ctx->asr_sampler);
|
|
1203
|
+
|
|
1204
|
+
llama_pos n_past = 0;
|
|
1205
|
+
int32_t eval_rc = mtmd_helper_eval_chunks(
|
|
1206
|
+
ctx->asr_mtmd,
|
|
1207
|
+
ctx->asr_lctx,
|
|
1208
|
+
chunks.get(),
|
|
1209
|
+
n_past,
|
|
1210
|
+
0,
|
|
1211
|
+
ctx->asr_n_batch,
|
|
1212
|
+
true,
|
|
1213
|
+
&n_past);
|
|
1214
|
+
if (eval_rc != 0) {
|
|
1215
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: mtmd_helper_eval_chunks failed rc=" + std::to_string(eval_rc));
|
|
1216
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
const llama_vocab * vocab = llama_model_get_vocab(ctx->asr_model);
|
|
1220
|
+
std::string transcript;
|
|
1221
|
+
transcript.reserve(std::min<size_t>(max_text_bytes, 256));
|
|
1222
|
+
const int max_decode_tokens = std::min<int>(
|
|
1223
|
+
4096,
|
|
1224
|
+
std::max<int>(
|
|
1225
|
+
192,
|
|
1226
|
+
64 + (int) (((audio.size() + (size_t) ctx->asr_sample_rate - 1) /
|
|
1227
|
+
(size_t) ctx->asr_sample_rate) * 32)));
|
|
1228
|
+
bool completed = false;
|
|
1229
|
+
for (int i = 0; i < max_decode_tokens; ++i) {
|
|
1230
|
+
llama_token token = llama_sampler_sample(ctx->asr_sampler, ctx->asr_lctx, -1);
|
|
1231
|
+
if (llama_vocab_is_eog(vocab, token)) {
|
|
1232
|
+
completed = true;
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
std::string piece = eliza_llama_token_piece(vocab, token);
|
|
1236
|
+
if (!piece.empty()) {
|
|
1237
|
+
if (transcript.size() + piece.size() + 1 > max_text_bytes) {
|
|
1238
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: output buffer too small");
|
|
1239
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1240
|
+
}
|
|
1241
|
+
transcript += piece;
|
|
1242
|
+
std::string cleaned_partial = eliza_clean_asr_transcript(transcript);
|
|
1243
|
+
if (eliza_asr_has_text_payload(cleaned_partial)) {
|
|
1244
|
+
if (piece.find('\\n') != std::string::npos ||
|
|
1245
|
+
transcript.find("<|im_end|>") != std::string::npos ||
|
|
1246
|
+
transcript.find("<|endoftext|>") != std::string::npos ||
|
|
1247
|
+
transcript.find("</s>") != std::string::npos) {
|
|
1248
|
+
completed = true;
|
|
1249
|
+
break;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
llama_sampler_accept(ctx->asr_sampler, token);
|
|
1254
|
+
llama_batch batch = llama_batch_get_one(&token, 1);
|
|
1255
|
+
int32_t decode_rc = llama_decode(ctx->asr_lctx, batch);
|
|
1256
|
+
if (decode_rc != 0) {
|
|
1257
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: llama_decode failed rc=" + std::to_string(decode_rc));
|
|
1258
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
if (!completed) {
|
|
1262
|
+
eliza_set_error(out_error,
|
|
1263
|
+
"[libelizainference] asr_transcribe: decode reached token cap before EOG; "
|
|
1264
|
+
"refusing to return a possibly truncated transcript");
|
|
1265
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1266
|
+
} else {
|
|
1267
|
+
transcript = eliza_clean_asr_transcript(transcript);
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
if (transcript.size() + 1 > max_text_bytes) {
|
|
1271
|
+
eliza_set_error(out_error, "[libelizainference] asr_transcribe: output buffer too small after transcript normalization");
|
|
1272
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1273
|
+
}
|
|
1274
|
+
std::memcpy(out_text, transcript.data(), transcript.size());
|
|
1275
|
+
out_text[transcript.size()] = '\\0';
|
|
1276
|
+
return (int) transcript.size();
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
/* ---- Streaming ASR (ABI v2) ---------------------------------------- *
|
|
1280
|
+
*
|
|
1281
|
+
* The fused build ships the v1 batch \`eliza_inference_asr_transcribe\`
|
|
1282
|
+
* decoder above; the windowed streaming-session decoder is not yet wired
|
|
1283
|
+
* (W7). Per packages/inference/AGENTS.md §3 we do NOT fake it — the
|
|
1284
|
+
* capability probe returns 0 so EngineVoiceBridge / StreamingTranscriber
|
|
1285
|
+
* pick the fused batch ASR adapter instead of opening a session that would
|
|
1286
|
+
* only return the unsupported-operation error code.
|
|
1287
|
+
* These symbols exist so the ABI surface is complete and the loader's
|
|
1288
|
+
* version check (ffi-bindings.ts expects v3) succeeds.
|
|
1289
|
+
*/
|
|
1290
|
+
|
|
1291
|
+
int eliza_inference_asr_stream_supported(void) {
|
|
1292
|
+
return 0;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
EliAsrStream * eliza_inference_asr_stream_open(
|
|
1296
|
+
EliInferenceContext * ctx,
|
|
1297
|
+
int sample_rate_hz,
|
|
1298
|
+
char ** out_error) {
|
|
1299
|
+
(void) ctx;
|
|
1300
|
+
(void) sample_rate_hz;
|
|
1301
|
+
eliza_set_error(out_error,
|
|
1302
|
+
"[libelizainference] streaming ASR session API is unsupported in this build "
|
|
1303
|
+
"(eliza_inference_asr_stream_supported() == 0); use the batch transcribe path");
|
|
1304
|
+
return nullptr;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
int eliza_inference_asr_stream_feed(
|
|
1308
|
+
EliAsrStream * stream,
|
|
1309
|
+
const float * pcm,
|
|
1310
|
+
size_t n_samples,
|
|
1311
|
+
char ** out_error) {
|
|
1312
|
+
(void) stream;
|
|
1313
|
+
(void) pcm;
|
|
1314
|
+
(void) n_samples;
|
|
1315
|
+
eliza_set_error(out_error, "[libelizainference] streaming ASR is unsupported in this build");
|
|
1316
|
+
return ELIZA_ERR_NOT_IMPLEMENTED;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
int eliza_inference_asr_stream_partial(
|
|
1320
|
+
EliAsrStream * stream,
|
|
1321
|
+
char * out_text,
|
|
1322
|
+
size_t max_text_bytes,
|
|
1323
|
+
int * out_tokens,
|
|
1324
|
+
size_t * io_n_tokens,
|
|
1325
|
+
char ** out_error) {
|
|
1326
|
+
(void) stream;
|
|
1327
|
+
(void) out_text;
|
|
1328
|
+
(void) max_text_bytes;
|
|
1329
|
+
(void) out_tokens;
|
|
1330
|
+
if (io_n_tokens) *io_n_tokens = 0;
|
|
1331
|
+
eliza_set_error(out_error, "[libelizainference] streaming ASR is unsupported in this build");
|
|
1332
|
+
return ELIZA_ERR_NOT_IMPLEMENTED;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
int eliza_inference_asr_stream_finish(
|
|
1336
|
+
EliAsrStream * stream,
|
|
1337
|
+
char * out_text,
|
|
1338
|
+
size_t max_text_bytes,
|
|
1339
|
+
int * out_tokens,
|
|
1340
|
+
size_t * io_n_tokens,
|
|
1341
|
+
char ** out_error) {
|
|
1342
|
+
(void) stream;
|
|
1343
|
+
(void) out_text;
|
|
1344
|
+
(void) max_text_bytes;
|
|
1345
|
+
(void) out_tokens;
|
|
1346
|
+
if (io_n_tokens) *io_n_tokens = 0;
|
|
1347
|
+
eliza_set_error(out_error, "[libelizainference] streaming ASR is unsupported in this build");
|
|
1348
|
+
return ELIZA_ERR_NOT_IMPLEMENTED;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
void eliza_inference_asr_stream_close(EliAsrStream * stream) {
|
|
1352
|
+
(void) stream;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/* ---- Streaming TTS + MTP verifier callback (ABI v2) ------------- *
|
|
1356
|
+
*
|
|
1357
|
+
* TTS streaming is backed by OmniVoice's real \`ov_tts_params.on_chunk\`
|
|
1358
|
+
* path and cooperative cancel hook. The native MTP verifier-event
|
|
1359
|
+
* callback is still not wired in this generated adapter, so the JS
|
|
1360
|
+
* scheduler continues to synthesize verifier events from llama-server SSE
|
|
1361
|
+
* deltas until that text-generation path moves in-process.
|
|
1362
|
+
*/
|
|
1363
|
+
|
|
1364
|
+
int eliza_inference_tts_stream_supported(void) {
|
|
1365
|
+
return OV_ABI_VERSION >= 2 ? 1 : 0;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
int eliza_inference_tts_synthesize_stream(
|
|
1369
|
+
EliInferenceContext * ctx,
|
|
1370
|
+
const char * text,
|
|
1371
|
+
size_t text_len,
|
|
1372
|
+
const char * speaker_preset_id,
|
|
1373
|
+
eliza_tts_chunk_cb on_chunk,
|
|
1374
|
+
void * user_data,
|
|
1375
|
+
char ** out_error) {
|
|
1376
|
+
if (!ctx || !on_chunk) {
|
|
1377
|
+
eliza_set_error(out_error, "[libelizainference] tts_synthesize_stream: invalid arguments");
|
|
1378
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1379
|
+
}
|
|
1380
|
+
if (!text || text_len == 0) {
|
|
1381
|
+
eliza_set_error(out_error, "[libelizainference] tts_synthesize_stream: text is required");
|
|
1382
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
1386
|
+
if (!ctx->ov) {
|
|
1387
|
+
eliza_set_error(out_error, "[libelizainference] tts_synthesize_stream: TTS region is not acquired; call mmap_acquire(\\"tts\\") after arming voice");
|
|
1388
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1389
|
+
}
|
|
1390
|
+
ElizaScopedTtsForward forward(ctx);
|
|
1391
|
+
|
|
1392
|
+
std::string text_owned(text, text_len);
|
|
1393
|
+
ov_tts_params params;
|
|
1394
|
+
ov_tts_default_params(¶ms);
|
|
1395
|
+
eliza_apply_tts_env_overrides(¶ms);
|
|
1396
|
+
params.text = text_owned.c_str();
|
|
1397
|
+
/* Default to OmniVoice's auto-voice path. The preset (if any)
|
|
1398
|
+
* overwrites params.instruct / ref_audio_tokens / ref_text via
|
|
1399
|
+
* eliza_apply_preset_to_params below. */
|
|
1400
|
+
params.instruct = "";
|
|
1401
|
+
if (speaker_preset_id && speaker_preset_id[0] != '\\0') {
|
|
1402
|
+
std::string preset_err;
|
|
1403
|
+
const EliVoicePreset * preset = nullptr;
|
|
1404
|
+
{
|
|
1405
|
+
std::lock_guard<std::mutex> preset_lock(ctx->preset_mutex);
|
|
1406
|
+
preset = eliza_load_voice_preset_locked(ctx, speaker_preset_id, preset_err);
|
|
1407
|
+
}
|
|
1408
|
+
if (preset && !preset->empty_payload) {
|
|
1409
|
+
eliza_apply_preset_to_params(*preset, ¶ms);
|
|
1410
|
+
}
|
|
1411
|
+
/* A missing or v1-only preset is not fatal — auto-voice mode
|
|
1412
|
+
* still produces audio. The preset_err is only surfaced via
|
|
1413
|
+
* out_error when synthesis itself fails. */
|
|
1414
|
+
}
|
|
1415
|
+
params.cancel = eliza_tts_cancel_requested;
|
|
1416
|
+
params.cancel_user_data = ctx;
|
|
1417
|
+
|
|
1418
|
+
ElizaTtsStreamState state = {
|
|
1419
|
+
ctx,
|
|
1420
|
+
on_chunk,
|
|
1421
|
+
user_data,
|
|
1422
|
+
false,
|
|
1423
|
+
};
|
|
1424
|
+
params.on_chunk = eliza_tts_stream_chunk;
|
|
1425
|
+
params.on_chunk_user_data = &state;
|
|
1426
|
+
|
|
1427
|
+
ov_status rc = ov_synthesize(ctx->ov, ¶ms, nullptr);
|
|
1428
|
+
const bool cancelled =
|
|
1429
|
+
rc == OV_STATUS_CANCELLED ||
|
|
1430
|
+
state.callback_cancelled ||
|
|
1431
|
+
ctx->tts_cancel.load(std::memory_order_acquire);
|
|
1432
|
+
(void) on_chunk(nullptr, 0, 1, user_data);
|
|
1433
|
+
if (cancelled) {
|
|
1434
|
+
return ELIZA_ERR_CANCELLED;
|
|
1435
|
+
}
|
|
1436
|
+
if (rc != OV_STATUS_OK) {
|
|
1437
|
+
std::string msg = "[libelizainference] ov_synthesize(stream) failed: ";
|
|
1438
|
+
msg += ov_last_error();
|
|
1439
|
+
eliza_set_error(out_error, msg);
|
|
1440
|
+
return eliza_map_ov_status(rc);
|
|
1441
|
+
}
|
|
1442
|
+
return ELIZA_OK;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
int eliza_inference_cancel_tts(
|
|
1446
|
+
EliInferenceContext * ctx,
|
|
1447
|
+
char ** out_error) {
|
|
1448
|
+
(void) out_error;
|
|
1449
|
+
if (ctx) {
|
|
1450
|
+
ctx->tts_cancel.store(true, std::memory_order_release);
|
|
1451
|
+
}
|
|
1452
|
+
// Cancelling nothing is not an error.
|
|
1453
|
+
return ELIZA_OK;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
int eliza_inference_set_verifier_callback(
|
|
1457
|
+
EliInferenceContext * ctx,
|
|
1458
|
+
eliza_verifier_cb cb,
|
|
1459
|
+
void * user_data,
|
|
1460
|
+
char ** out_error) {
|
|
1461
|
+
(void) ctx;
|
|
1462
|
+
(void) cb;
|
|
1463
|
+
(void) user_data;
|
|
1464
|
+
eliza_set_error(out_error,
|
|
1465
|
+
"[libelizainference] native MTP verifier callback is unsupported in this build; "
|
|
1466
|
+
"the JS scheduler synthesizes verifier events from llama-server streaming deltas");
|
|
1467
|
+
return ELIZA_ERR_NOT_IMPLEMENTED;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
/* ---- OmniVoice reference encode (ABI v4) -------------------------- *
|
|
1471
|
+
*
|
|
1472
|
+
* Thin wrapper around ov_encode_reference. The TTS region must have
|
|
1473
|
+
* been acquired (\`mmap_acquire("tts")\`) before the call. The library
|
|
1474
|
+
* malloc-allocates the token buffer; callers release it via
|
|
1475
|
+
* eliza_inference_free_tokens.
|
|
1476
|
+
*/
|
|
1477
|
+
int eliza_inference_encode_reference(
|
|
1478
|
+
EliInferenceContext * ctx,
|
|
1479
|
+
const float * pcm,
|
|
1480
|
+
size_t n_samples,
|
|
1481
|
+
int sample_rate_hz,
|
|
1482
|
+
int * out_K,
|
|
1483
|
+
int * out_ref_T,
|
|
1484
|
+
int ** out_tokens,
|
|
1485
|
+
char ** out_error) {
|
|
1486
|
+
if (!ctx || !pcm || !out_K || !out_ref_T || !out_tokens) {
|
|
1487
|
+
eliza_set_error(out_error, "[libelizainference] encode_reference: invalid arguments");
|
|
1488
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1489
|
+
}
|
|
1490
|
+
if (n_samples == 0) {
|
|
1491
|
+
eliza_set_error(out_error, "[libelizainference] encode_reference: n_samples must be > 0");
|
|
1492
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1493
|
+
}
|
|
1494
|
+
if (sample_rate_hz != 24000) {
|
|
1495
|
+
eliza_set_error(out_error,
|
|
1496
|
+
"[libelizainference] encode_reference: sample_rate_hz must be 24000 (got " +
|
|
1497
|
+
std::to_string(sample_rate_hz) + "); caller is responsible for upstream resample");
|
|
1498
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
1502
|
+
if (!ctx->ov) {
|
|
1503
|
+
eliza_set_error(out_error,
|
|
1504
|
+
"[libelizainference] encode_reference: TTS region is not acquired; "
|
|
1505
|
+
"call mmap_acquire(\\"tts\\") after arming voice");
|
|
1506
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
int32_t * tokens = nullptr;
|
|
1510
|
+
int K = 0;
|
|
1511
|
+
int ref_T = 0;
|
|
1512
|
+
ov_status rc = ov_encode_reference(ctx->ov, pcm, (int) n_samples,
|
|
1513
|
+
&tokens, &K, &ref_T);
|
|
1514
|
+
if (rc != OV_STATUS_OK) {
|
|
1515
|
+
std::string msg = "[libelizainference] ov_encode_reference failed: ";
|
|
1516
|
+
msg += ov_last_error();
|
|
1517
|
+
eliza_set_error(out_error, msg);
|
|
1518
|
+
if (tokens) std::free(tokens);
|
|
1519
|
+
return eliza_map_ov_status(rc);
|
|
1520
|
+
}
|
|
1521
|
+
*out_tokens = tokens;
|
|
1522
|
+
*out_K = K;
|
|
1523
|
+
*out_ref_T = ref_T;
|
|
1524
|
+
return ELIZA_OK;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
void eliza_inference_free_tokens(int * tokens) {
|
|
1528
|
+
if (tokens) std::free(tokens);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
/* ---- Native VAD (ABI v3) ------------------------------------------- *
|
|
1532
|
+
*
|
|
1533
|
+
* The JS runtime can use the ONNX Silero path today. Native VAD is an
|
|
1534
|
+
* additive fused-runtime backend; until the fused target wires it,
|
|
1535
|
+
* advertise unsupported and return structured unsupported-operation errors.
|
|
1536
|
+
*/
|
|
1537
|
+
|
|
1538
|
+
int eliza_inference_vad_supported(void) {
|
|
1539
|
+
return 0;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
EliVad * eliza_inference_vad_open(
|
|
1543
|
+
EliInferenceContext * ctx,
|
|
1544
|
+
int sample_rate_hz,
|
|
1545
|
+
char ** out_error) {
|
|
1546
|
+
(void) ctx;
|
|
1547
|
+
(void) sample_rate_hz;
|
|
1548
|
+
eliza_set_error(out_error,
|
|
1549
|
+
"[libelizainference] native VAD is unsupported in this build "
|
|
1550
|
+
"(eliza_inference_vad_supported() == 0); use the ONNX Silero VAD path");
|
|
1551
|
+
return nullptr;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
int eliza_inference_vad_process(
|
|
1555
|
+
EliVad * vad,
|
|
1556
|
+
const float * pcm,
|
|
1557
|
+
size_t n_samples,
|
|
1558
|
+
float * out_probability,
|
|
1559
|
+
char ** out_error) {
|
|
1560
|
+
(void) vad;
|
|
1561
|
+
(void) pcm;
|
|
1562
|
+
(void) n_samples;
|
|
1563
|
+
(void) out_probability;
|
|
1564
|
+
eliza_set_error(out_error, "[libelizainference] native VAD is unsupported in this build");
|
|
1565
|
+
return ELIZA_ERR_NOT_IMPLEMENTED;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
int eliza_inference_vad_reset(
|
|
1569
|
+
EliVad * vad,
|
|
1570
|
+
char ** out_error) {
|
|
1571
|
+
(void) vad;
|
|
1572
|
+
eliza_set_error(out_error, "[libelizainference] native VAD is unsupported in this build");
|
|
1573
|
+
return ELIZA_ERR_NOT_IMPLEMENTED;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
void eliza_inference_vad_close(EliVad * vad) {
|
|
1577
|
+
(void) vad;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/* ---- Streaming LLM (text generation, ABI v4) --------------------- */
|
|
1581
|
+
|
|
1582
|
+
int eliza_inference_llm_stream_supported(void) {
|
|
1583
|
+
return 1;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
EliLlmStream * eliza_inference_llm_stream_open(
|
|
1587
|
+
EliInferenceContext * ctx,
|
|
1588
|
+
const eliza_llm_stream_config_t * cfg,
|
|
1589
|
+
char ** out_error) {
|
|
1590
|
+
if (!ctx || !cfg) {
|
|
1591
|
+
eliza_set_error(out_error,
|
|
1592
|
+
"[libelizainference] llm_stream_open: ctx and cfg are required");
|
|
1593
|
+
return nullptr;
|
|
1594
|
+
}
|
|
1595
|
+
llama_model * model = nullptr;
|
|
1596
|
+
{
|
|
1597
|
+
std::lock_guard<std::mutex> lock(ctx->llm_mutex);
|
|
1598
|
+
int rc = eliza_load_llm_model_locked(ctx, out_error);
|
|
1599
|
+
if (rc != ELIZA_OK) return nullptr;
|
|
1600
|
+
model = ctx->llm_model;
|
|
1601
|
+
}
|
|
1602
|
+
EliLlmStream * stream = new (std::nothrow) EliLlmStream();
|
|
1603
|
+
if (!stream) {
|
|
1604
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_open: out of memory");
|
|
1605
|
+
return nullptr;
|
|
1606
|
+
}
|
|
1607
|
+
stream->ctx = ctx;
|
|
1608
|
+
stream->max_tokens = cfg->max_tokens > 0 ? cfg->max_tokens : 0;
|
|
1609
|
+
llama_context_params cparams = llama_context_default_params();
|
|
1610
|
+
const int n_ctx_train = llama_model_n_ctx_train(model);
|
|
1611
|
+
int n_ctx = eliza_llm_int_env_or_default("ELIZA_LLM_N_CTX", 8192);
|
|
1612
|
+
if (n_ctx_train > 0 && n_ctx > n_ctx_train) n_ctx = n_ctx_train;
|
|
1613
|
+
cparams.n_ctx = (uint32_t) n_ctx;
|
|
1614
|
+
cparams.n_batch = (uint32_t) eliza_llm_int_env_or_default("ELIZA_LLM_N_BATCH", 512);
|
|
1615
|
+
cparams.n_ubatch = cparams.n_batch;
|
|
1616
|
+
cparams.n_threads = eliza_thread_count(false);
|
|
1617
|
+
cparams.n_threads_batch = eliza_thread_count(true);
|
|
1618
|
+
cparams.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_AUTO;
|
|
1619
|
+
stream->lctx = llama_init_from_model(model, cparams);
|
|
1620
|
+
if (!stream->lctx) {
|
|
1621
|
+
delete stream;
|
|
1622
|
+
eliza_set_error(out_error,
|
|
1623
|
+
"[libelizainference] llm_stream_open: failed to init llama context");
|
|
1624
|
+
return nullptr;
|
|
1625
|
+
}
|
|
1626
|
+
stream->sampler = eliza_build_llm_sampler_chain(model, cfg, out_error);
|
|
1627
|
+
if (!stream->sampler) {
|
|
1628
|
+
llama_free(stream->lctx);
|
|
1629
|
+
delete stream;
|
|
1630
|
+
return nullptr;
|
|
1631
|
+
}
|
|
1632
|
+
return stream;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
int eliza_inference_llm_stream_prefill(
|
|
1636
|
+
EliLlmStream * stream,
|
|
1637
|
+
const int32_t * token_ids,
|
|
1638
|
+
size_t num_tokens,
|
|
1639
|
+
char ** out_error) {
|
|
1640
|
+
if (!stream || !stream->lctx) {
|
|
1641
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_prefill: invalid session");
|
|
1642
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1643
|
+
}
|
|
1644
|
+
if (num_tokens == 0) return ELIZA_OK;
|
|
1645
|
+
if (!token_ids) {
|
|
1646
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_prefill: token_ids is NULL");
|
|
1647
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1648
|
+
}
|
|
1649
|
+
std::vector<llama_token> tokens(token_ids, token_ids + num_tokens);
|
|
1650
|
+
const int n_batch = (int) llama_n_batch(stream->lctx);
|
|
1651
|
+
const size_t total = tokens.size();
|
|
1652
|
+
for (size_t off = 0; off < total; off += (size_t) n_batch) {
|
|
1653
|
+
if (stream->cancel.load(std::memory_order_acquire)) {
|
|
1654
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_prefill: cancelled");
|
|
1655
|
+
return ELIZA_ERR_CANCELLED;
|
|
1656
|
+
}
|
|
1657
|
+
const size_t chunk = std::min((size_t) n_batch, total - off);
|
|
1658
|
+
llama_batch batch = llama_batch_get_one(tokens.data() + off, (int32_t) chunk);
|
|
1659
|
+
int32_t rc = llama_decode(stream->lctx, batch);
|
|
1660
|
+
if (rc != 0) {
|
|
1661
|
+
eliza_set_error(out_error,
|
|
1662
|
+
"[libelizainference] llm_stream_prefill: llama_decode failed rc=" +
|
|
1663
|
+
std::to_string(rc));
|
|
1664
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1665
|
+
}
|
|
1666
|
+
stream->n_past += (int) chunk;
|
|
1667
|
+
}
|
|
1668
|
+
return ELIZA_OK;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
int eliza_inference_llm_stream_next(
|
|
1672
|
+
EliLlmStream * stream,
|
|
1673
|
+
int32_t * tokens_out,
|
|
1674
|
+
size_t tokens_cap,
|
|
1675
|
+
size_t * num_tokens_out,
|
|
1676
|
+
char * text_out,
|
|
1677
|
+
size_t text_cap,
|
|
1678
|
+
int32_t * drafter_drafted_out,
|
|
1679
|
+
int32_t * drafter_accepted_out,
|
|
1680
|
+
char ** out_error) {
|
|
1681
|
+
if (num_tokens_out) *num_tokens_out = 0;
|
|
1682
|
+
if (drafter_drafted_out) *drafter_drafted_out = 0;
|
|
1683
|
+
if (drafter_accepted_out) *drafter_accepted_out = 0;
|
|
1684
|
+
if (text_out && text_cap > 0) text_out[0] = '\\0';
|
|
1685
|
+
if (!stream || !stream->lctx || !stream->sampler) {
|
|
1686
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_next: invalid session");
|
|
1687
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1688
|
+
}
|
|
1689
|
+
if (!tokens_out || tokens_cap == 0 || !text_out || text_cap == 0) {
|
|
1690
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_next: output buffers are required");
|
|
1691
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1692
|
+
}
|
|
1693
|
+
if (stream->eos) return 1;
|
|
1694
|
+
const llama_model * model = llama_get_model(stream->lctx);
|
|
1695
|
+
const llama_vocab * vocab = llama_model_get_vocab(model);
|
|
1696
|
+
std::string text;
|
|
1697
|
+
size_t produced = 0;
|
|
1698
|
+
size_t step_cap = tokens_cap;
|
|
1699
|
+
if (stream->max_tokens > 0) {
|
|
1700
|
+
const size_t remaining = (size_t) std::max(0, stream->max_tokens - stream->generated);
|
|
1701
|
+
if (remaining == 0) { stream->eos = true; return 1; }
|
|
1702
|
+
step_cap = std::min(step_cap, remaining);
|
|
1703
|
+
}
|
|
1704
|
+
bool final_step = false;
|
|
1705
|
+
while (produced < step_cap) {
|
|
1706
|
+
if (stream->cancel.load(std::memory_order_acquire)) {
|
|
1707
|
+
eliza_set_error(out_error, "[libelizainference] llm_stream_next: cancelled");
|
|
1708
|
+
return ELIZA_ERR_CANCELLED;
|
|
1709
|
+
}
|
|
1710
|
+
llama_token token = llama_sampler_sample(stream->sampler, stream->lctx, -1);
|
|
1711
|
+
if (llama_vocab_is_eog(vocab, token)) { stream->eos = true; final_step = true; break; }
|
|
1712
|
+
std::string piece = eliza_llama_token_piece(vocab, token);
|
|
1713
|
+
if (!piece.empty() && text.size() + piece.size() + 1 > text_cap) break;
|
|
1714
|
+
/* llama_sampler_sample already accepted the token (advancing the
|
|
1715
|
+
* grammar stack); do NOT accept again or the grammar stack empties. */
|
|
1716
|
+
tokens_out[produced] = (int32_t) token;
|
|
1717
|
+
text += piece;
|
|
1718
|
+
produced += 1;
|
|
1719
|
+
stream->generated += 1;
|
|
1720
|
+
llama_batch batch = llama_batch_get_one(&token, 1);
|
|
1721
|
+
int32_t rc = llama_decode(stream->lctx, batch);
|
|
1722
|
+
if (rc != 0) {
|
|
1723
|
+
eliza_set_error(out_error,
|
|
1724
|
+
"[libelizainference] llm_stream_next: llama_decode failed rc=" +
|
|
1725
|
+
std::to_string(rc));
|
|
1726
|
+
return ELIZA_ERR_FFI_FAULT;
|
|
1727
|
+
}
|
|
1728
|
+
stream->n_past += 1;
|
|
1729
|
+
if (stream->max_tokens > 0 && stream->generated >= stream->max_tokens) {
|
|
1730
|
+
stream->eos = true; final_step = true; break;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
if (text.size() + 1 > text_cap) text.resize(text_cap - 1);
|
|
1734
|
+
std::memcpy(text_out, text.data(), text.size());
|
|
1735
|
+
text_out[text.size()] = '\\0';
|
|
1736
|
+
if (num_tokens_out) *num_tokens_out = produced;
|
|
1737
|
+
return final_step ? 1 : 0;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
int eliza_inference_llm_stream_cancel(EliLlmStream * stream) {
|
|
1741
|
+
if (stream) stream->cancel.store(true, std::memory_order_release);
|
|
1742
|
+
return ELIZA_OK;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
int eliza_inference_llm_stream_save_slot(
|
|
1746
|
+
EliLlmStream * stream, const char * filename, char ** out_error) {
|
|
1747
|
+
(void) stream; (void) filename;
|
|
1748
|
+
eliza_set_error(out_error,
|
|
1749
|
+
"[libelizainference] llm_stream_save_slot is not implemented in this build");
|
|
1750
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
int eliza_inference_llm_stream_restore_slot(
|
|
1754
|
+
EliLlmStream * stream, const char * filename, char ** out_error) {
|
|
1755
|
+
(void) stream; (void) filename;
|
|
1756
|
+
eliza_set_error(out_error,
|
|
1757
|
+
"[libelizainference] llm_stream_restore_slot is not implemented in this build");
|
|
1758
|
+
return ELIZA_ERR_INVALID_ARG;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
void eliza_inference_llm_stream_close(EliLlmStream * stream) {
|
|
1762
|
+
if (!stream) return;
|
|
1763
|
+
if (stream->sampler) { llama_sampler_free(stream->sampler); stream->sampler = nullptr; }
|
|
1764
|
+
if (stream->lctx) { llama_free(stream->lctx); stream->lctx = nullptr; }
|
|
1765
|
+
delete stream;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
void eliza_inference_free_string(char * str) {
|
|
1769
|
+
std::free(str);
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
} // extern "C"
|
|
1773
|
+
`,
|
|
1774
|
+
"utf8",
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
function hasFunctionDeclaration(source, name) {
|
|
1779
|
+
return new RegExp(`\\b${name}\\s*\\(`).test(source);
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
function hasFunctionDefinition(source, name) {
|
|
1783
|
+
return new RegExp(`(?:^|\\n)[^\\n;{}]*\\b${name}\\s*\\(`).test(source);
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
function inspectPreparedOmnivoiceSurface({ graftRoot }) {
|
|
1787
|
+
const srcRoot = path.join(graftRoot, "src");
|
|
1788
|
+
const headerPath = path.join(srcRoot, "omnivoice.h");
|
|
1789
|
+
const implPath = path.join(srcRoot, "omnivoice.cpp");
|
|
1790
|
+
const adapterPath = path.join(srcRoot, "eliza-inference-ffi.cpp");
|
|
1791
|
+
for (const file of [headerPath, implPath, adapterPath]) {
|
|
1792
|
+
if (!fs.existsSync(file)) {
|
|
1793
|
+
throw new Error(
|
|
1794
|
+
`[omnivoice-fuse] prepared graft missing ${file}; refusing stub-only fusion`,
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
const header = fs.readFileSync(headerPath, "utf8");
|
|
1800
|
+
const impl = fs.readFileSync(implPath, "utf8");
|
|
1801
|
+
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
1802
|
+
const missingHeaderSymbols = REQUIRED_PUBLIC_OMNIVOICE_SYMBOLS.filter(
|
|
1803
|
+
(symbol) => !hasFunctionDeclaration(header, symbol),
|
|
1804
|
+
);
|
|
1805
|
+
if (missingHeaderSymbols.length > 0) {
|
|
1806
|
+
throw new Error(
|
|
1807
|
+
`[omnivoice-fuse] prepared omnivoice.h missing required public symbol(s): ${missingHeaderSymbols.join(", ")}. Pin is not compatible with libelizainference ABI v1.`,
|
|
56
1808
|
);
|
|
57
1809
|
}
|
|
58
|
-
|
|
1810
|
+
|
|
1811
|
+
const missingImplSymbols = REQUIRED_PUBLIC_OMNIVOICE_SYMBOLS.filter(
|
|
1812
|
+
(symbol) => !hasFunctionDefinition(impl, symbol),
|
|
1813
|
+
);
|
|
1814
|
+
if (missingImplSymbols.length > 0) {
|
|
1815
|
+
throw new Error(
|
|
1816
|
+
`[omnivoice-fuse] prepared omnivoice.cpp missing required implementation symbol(s): ${missingImplSymbols.join(", ")}. Refusing to build a header-only or stub-only graft.`,
|
|
1817
|
+
);
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
const adapterRequiredCalls = [
|
|
1821
|
+
"ov_init_default_params",
|
|
1822
|
+
"ov_init",
|
|
1823
|
+
"ov_free",
|
|
1824
|
+
"ov_tts_default_params",
|
|
1825
|
+
"ov_synthesize",
|
|
1826
|
+
"ov_audio_free",
|
|
1827
|
+
"ov_last_error",
|
|
1828
|
+
"eliza_inference_asr_transcribe",
|
|
1829
|
+
"mtmd_init_from_file",
|
|
1830
|
+
"mtmd_tokenize",
|
|
1831
|
+
"mtmd_helper_eval_chunks",
|
|
1832
|
+
"llama_decode",
|
|
1833
|
+
"llama_sampler_sample",
|
|
1834
|
+
];
|
|
1835
|
+
const missingAdapterCalls = adapterRequiredCalls.filter(
|
|
1836
|
+
(symbol) => !hasFunctionDeclaration(adapter, symbol),
|
|
1837
|
+
);
|
|
1838
|
+
if (missingAdapterCalls.length > 0) {
|
|
1839
|
+
throw new Error(
|
|
1840
|
+
`[omnivoice-fuse] generated libelizainference adapter is not wired to OmniVoice call(s): ${missingAdapterCalls.join(", ")}`,
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
return {
|
|
1845
|
+
header: path.relative(graftRoot, headerPath),
|
|
1846
|
+
implementation: path.relative(graftRoot, implPath),
|
|
1847
|
+
adapter: path.relative(graftRoot, adapterPath),
|
|
1848
|
+
requiredPublicSymbols: [...REQUIRED_PUBLIC_OMNIVOICE_SYMBOLS],
|
|
1849
|
+
};
|
|
59
1850
|
}
|
|
60
1851
|
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
1852
|
+
function replaceOmnivoiceAnchor(source, from, to, label) {
|
|
1853
|
+
if (!source.includes(from)) {
|
|
1854
|
+
throw new Error(
|
|
1855
|
+
`[omnivoice-fuse] compatibility patch anchor not found: ${label}`,
|
|
1856
|
+
);
|
|
1857
|
+
}
|
|
1858
|
+
return source.replace(from, to);
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
function applyOmnivoiceReferenceEncodeApi({ graftRoot }) {
|
|
1862
|
+
const srcRoot = path.join(graftRoot, "src");
|
|
1863
|
+
|
|
1864
|
+
const ttsHeaderPath = path.join(srcRoot, "pipeline-tts.h");
|
|
1865
|
+
let ttsHeader = fs.readFileSync(ttsHeaderPath, "utf8");
|
|
1866
|
+
if (!ttsHeader.includes("pipeline_tts_encode_reference")) {
|
|
1867
|
+
const anchor = `int pipeline_tts_duration_sec_to_tokens(const PipelineCodec * pc, float duration_sec);
|
|
1868
|
+
|
|
1869
|
+
// Public TTS synthesis entry.`;
|
|
1870
|
+
const replacement = `int pipeline_tts_duration_sec_to_tokens(const PipelineCodec * pc, float duration_sec);
|
|
1871
|
+
|
|
1872
|
+
// Encode a 24 kHz mono reference waveform into row-major [K, ref_T] RVQ
|
|
1873
|
+
// tokens using the same HuBERT + codec preprocessing path as synthesis.
|
|
1874
|
+
// Returns an empty vector and sets ov_last_error on failure.
|
|
1875
|
+
std::vector<int32_t> pipeline_tts_encode_reference(PipelineTTS * pt,
|
|
1876
|
+
PipelineCodec * pc,
|
|
1877
|
+
const float * ref_audio_24k,
|
|
1878
|
+
int ref_n_samples,
|
|
1879
|
+
int * out_K,
|
|
1880
|
+
int * out_ref_T,
|
|
1881
|
+
const char * dump_dir = nullptr);
|
|
1882
|
+
|
|
1883
|
+
// Public TTS synthesis entry.`;
|
|
1884
|
+
ttsHeader = replaceOmnivoiceAnchor(
|
|
1885
|
+
ttsHeader,
|
|
1886
|
+
anchor,
|
|
1887
|
+
replacement,
|
|
1888
|
+
"pipeline-tts.h reference encode declaration",
|
|
1889
|
+
);
|
|
1890
|
+
fs.writeFileSync(ttsHeaderPath, ttsHeader, "utf8");
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
const ttsImplPath = path.join(srcRoot, "pipeline-tts.cpp");
|
|
1894
|
+
let ttsImpl = fs.readFileSync(ttsImplPath, "utf8");
|
|
1895
|
+
if (!ttsImpl.includes("pipeline_tts_encode_reference")) {
|
|
1896
|
+
const anchor = ` return r;
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
ov_status pipeline_tts_synthesize(`;
|
|
1900
|
+
const replacement = ` return r;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
std::vector<int32_t> pipeline_tts_encode_reference(PipelineTTS * pt,
|
|
1904
|
+
PipelineCodec * pc,
|
|
1905
|
+
const float * ref_audio_24k,
|
|
1906
|
+
int ref_n_samples,
|
|
1907
|
+
int * out_K,
|
|
1908
|
+
int * out_ref_T,
|
|
1909
|
+
const char * dump_dir) {
|
|
1910
|
+
if (!pt || !pc || !ref_audio_24k || ref_n_samples <= 0) {
|
|
1911
|
+
ov_set_error("pipeline_tts_encode_reference : invalid arguments");
|
|
1912
|
+
return {};
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
RefEncoded re = tts_encode_ref(pt, pc, ref_audio_24k, ref_n_samples,
|
|
1916
|
+
"", true, dump_dir);
|
|
1917
|
+
if (!re.has_ref || re.ref_codes.empty()) {
|
|
1918
|
+
ov_set_error("pipeline_tts_encode_reference : reference encoding failed");
|
|
1919
|
+
return {};
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
if (out_K) {
|
|
1923
|
+
*out_K = pt->lm.num_audio_codebook;
|
|
1924
|
+
}
|
|
1925
|
+
if (out_ref_T) {
|
|
1926
|
+
*out_ref_T = re.ref_T;
|
|
1927
|
+
}
|
|
1928
|
+
return re.ref_codes;
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
ov_status pipeline_tts_synthesize(`;
|
|
1932
|
+
ttsImpl = replaceOmnivoiceAnchor(
|
|
1933
|
+
ttsImpl,
|
|
1934
|
+
anchor,
|
|
1935
|
+
replacement,
|
|
1936
|
+
"pipeline-tts.cpp reference encode implementation",
|
|
1937
|
+
);
|
|
1938
|
+
fs.writeFileSync(ttsImplPath, ttsImpl, "utf8");
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
const headerPath = path.join(srcRoot, "omnivoice.h");
|
|
1942
|
+
let header = fs.readFileSync(headerPath, "utf8");
|
|
1943
|
+
if (!header.includes("ov_encode_reference")) {
|
|
1944
|
+
const anchor = `OV_API enum ov_status ov_synthesize(struct ov_context * ov, const struct ov_tts_params * params, struct ov_audio * out);
|
|
1945
|
+
|
|
1946
|
+
// Convert a duration in seconds to a frame count using the bundled codec`;
|
|
1947
|
+
const replacement = `OV_API enum ov_status ov_synthesize(struct ov_context * ov, const struct ov_tts_params * params, struct ov_audio * out);
|
|
1948
|
+
|
|
1949
|
+
// Encode a 24 kHz mono fp32 reference waveform through the OmniVoice
|
|
1950
|
+
// tokenizer and return row-major [K, ref_T] int32 RVQ tokens. The returned
|
|
1951
|
+
// buffer is malloc-allocated by the library and must be released with free()
|
|
1952
|
+
// by callers that bind this low-level OmniVoice ABI directly.
|
|
1953
|
+
OV_API enum ov_status ov_encode_reference(struct ov_context * ov,
|
|
1954
|
+
const float * pcm,
|
|
1955
|
+
int n_samples,
|
|
1956
|
+
int32_t ** out_tokens,
|
|
1957
|
+
int * out_K,
|
|
1958
|
+
int * out_ref_T);
|
|
1959
|
+
|
|
1960
|
+
// Convert a duration in seconds to a frame count using the bundled codec`;
|
|
1961
|
+
header = replaceOmnivoiceAnchor(
|
|
1962
|
+
header,
|
|
1963
|
+
anchor,
|
|
1964
|
+
replacement,
|
|
1965
|
+
"omnivoice.h reference encode declaration",
|
|
1966
|
+
);
|
|
1967
|
+
fs.writeFileSync(headerPath, header, "utf8");
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
const implPath = path.join(srcRoot, "omnivoice.cpp");
|
|
1971
|
+
let impl = fs.readFileSync(implPath, "utf8");
|
|
1972
|
+
if (!impl.includes("#include <vector>")) {
|
|
1973
|
+
impl = replaceOmnivoiceAnchor(
|
|
1974
|
+
impl,
|
|
1975
|
+
"#include <string>\n",
|
|
1976
|
+
"#include <string>\n#include <vector>\n",
|
|
1977
|
+
"omnivoice.cpp vector include",
|
|
1978
|
+
);
|
|
1979
|
+
}
|
|
1980
|
+
if (!impl.includes("ov_encode_reference")) {
|
|
1981
|
+
const anchor = `int ov_duration_sec_to_tokens(const struct ov_context * ov, float duration_sec) {`;
|
|
1982
|
+
const replacement = `enum ov_status ov_encode_reference(struct ov_context * ov,
|
|
1983
|
+
const float * pcm,
|
|
1984
|
+
int n_samples,
|
|
1985
|
+
int32_t ** out_tokens,
|
|
1986
|
+
int * out_K,
|
|
1987
|
+
int * out_ref_T) {
|
|
1988
|
+
if (!ov || !pcm || n_samples <= 0 || !out_tokens || !out_K || !out_ref_T) {
|
|
1989
|
+
ov_set_error("ov_encode_reference : invalid arguments");
|
|
1990
|
+
return OV_STATUS_INVALID_PARAMS;
|
|
1991
|
+
}
|
|
1992
|
+
if (!ov->codec_loaded) {
|
|
1993
|
+
ov_set_error("ov_encode_reference : codec not loaded (pass codec_path to ov_init)");
|
|
1994
|
+
ov_log(OV_LOG_ERROR, "[OmniVoice] ov_encode_reference requires a codec-loaded handle");
|
|
1995
|
+
return OV_STATUS_INVALID_PARAMS;
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
try {
|
|
1999
|
+
int K = 0;
|
|
2000
|
+
int ref_T = 0;
|
|
2001
|
+
std::vector<int32_t> tokens =
|
|
2002
|
+
pipeline_tts_encode_reference(&ov->pt, &ov->pc, pcm, n_samples,
|
|
2003
|
+
&K, &ref_T, nullptr);
|
|
2004
|
+
if (tokens.empty() || K <= 0 || ref_T <= 0) {
|
|
2005
|
+
return OV_STATUS_GENERATE_FAILED;
|
|
2006
|
+
}
|
|
2007
|
+
const size_t n_tokens = tokens.size();
|
|
2008
|
+
int32_t * copy = (int32_t *) std::malloc(n_tokens * sizeof(int32_t));
|
|
2009
|
+
if (!copy) {
|
|
2010
|
+
ov_set_error("ov_encode_reference : out of memory");
|
|
2011
|
+
return OV_STATUS_GENERATE_FAILED;
|
|
2012
|
+
}
|
|
2013
|
+
std::memcpy(copy, tokens.data(), n_tokens * sizeof(int32_t));
|
|
2014
|
+
*out_tokens = copy;
|
|
2015
|
+
*out_K = K;
|
|
2016
|
+
*out_ref_T = ref_T;
|
|
2017
|
+
return OV_STATUS_OK;
|
|
2018
|
+
} catch (const std::exception & e) {
|
|
2019
|
+
ov_set_error("%s", e.what());
|
|
2020
|
+
ov_log(OV_LOG_ERROR, "[OmniVoice] %s", e.what());
|
|
2021
|
+
return OV_STATUS_GENERATE_FAILED;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
int ov_duration_sec_to_tokens(const struct ov_context * ov, float duration_sec) {`;
|
|
2026
|
+
impl = replaceOmnivoiceAnchor(
|
|
2027
|
+
impl,
|
|
2028
|
+
anchor,
|
|
2029
|
+
replacement,
|
|
2030
|
+
"omnivoice.cpp reference encode implementation",
|
|
2031
|
+
);
|
|
2032
|
+
}
|
|
2033
|
+
fs.writeFileSync(implPath, impl, "utf8");
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
function applyElizaGgmlCompatibility({ graftRoot, commit }) {
|
|
2037
|
+
const dacPath = path.join(graftRoot, "src", "dac-decoder.h");
|
|
2038
|
+
let source = fs.readFileSync(dacPath, "utf8");
|
|
2039
|
+
const loadCtw = `// Load ConvTranspose1d weights in eliza ggml's native kernel layout.
|
|
2040
|
+
// Source-side layout is (IC, OC, K), represented by ggml as ne=(K, OC, IC).
|
|
2041
|
+
// eliza ggml already ships GGML_OP_CONV_TRANSPOSE_1D for CPU/CUDA/Metal/
|
|
2042
|
+
// Vulkan, while omnivoice's fork used a private col2im_1d op. Keeping the
|
|
2043
|
+
// native layout lets the fused build share the patched eliza ggml without
|
|
2044
|
+
// adding a second custom op.
|
|
2045
|
+
static void dac_load_ctw(struct ggml_tensor * dst, const GGUFModel & gf, const std::string & name) {
|
|
2046
|
+
struct ggml_tensor * mt = ggml_get_tensor(gf.meta, name.c_str());
|
|
2047
|
+
if (!mt) {
|
|
2048
|
+
ov_throw("[DAC] tensor '%s' not found (conv_t1 weight)", name.c_str());
|
|
2049
|
+
}
|
|
2050
|
+
GGML_ASSERT(dst->type == GGML_TYPE_F16);
|
|
2051
|
+
|
|
2052
|
+
const int K = (int) mt->ne[0];
|
|
2053
|
+
const int OC = (int) mt->ne[1];
|
|
2054
|
+
const int IC = (int) mt->ne[2];
|
|
2055
|
+
const size_t n = (size_t) IC * (size_t) OC * (size_t) K;
|
|
2056
|
+
|
|
2057
|
+
GGML_ASSERT(dst->ne[0] == K && dst->ne[1] == OC && dst->ne[2] == IC);
|
|
2058
|
+
|
|
2059
|
+
const void * raw = gf_get_data(gf, name.c_str());
|
|
2060
|
+
if (mt->type == GGML_TYPE_F16) {
|
|
2061
|
+
ggml_backend_tensor_set(dst, raw, 0, n * sizeof(ggml_fp16_t));
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
std::vector<float> f32(n);
|
|
2066
|
+
if (mt->type == GGML_TYPE_F32) {
|
|
2067
|
+
memcpy(f32.data(), raw, n * sizeof(float));
|
|
2068
|
+
} else if (mt->type == GGML_TYPE_BF16) {
|
|
2069
|
+
const uint16_t * p = (const uint16_t *) raw;
|
|
2070
|
+
for (size_t i = 0; i < n; i++) {
|
|
2071
|
+
f32[i] = ggml_bf16_to_fp32(*(const ggml_bf16_t *) &p[i]);
|
|
2072
|
+
}
|
|
2073
|
+
} else {
|
|
2074
|
+
const struct ggml_type_traits * tr = ggml_get_type_traits(mt->type);
|
|
2075
|
+
if (!tr || !tr->to_float) {
|
|
2076
|
+
ov_throw("[DAC] unsupported conv_t1 weight type %s for '%s'", ggml_type_name(mt->type), name.c_str());
|
|
2077
|
+
}
|
|
2078
|
+
tr->to_float(raw, f32.data(), (int64_t) n);
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
std::vector<ggml_fp16_t> packed(n);
|
|
2082
|
+
for (size_t i = 0; i < n; i++) {
|
|
2083
|
+
packed[i] = ggml_fp32_to_fp16(f32[i]);
|
|
2084
|
+
}
|
|
2085
|
+
ggml_backend_tensor_set(dst, packed.data(), 0, n * sizeof(ggml_fp16_t));
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
`;
|
|
2089
|
+
source = replaceBetween(
|
|
2090
|
+
source,
|
|
2091
|
+
"// Pre-permute the ConvTranspose1d weight",
|
|
2092
|
+
"// Allocate one snake pair",
|
|
2093
|
+
loadCtw,
|
|
2094
|
+
);
|
|
2095
|
+
|
|
2096
|
+
const convT = `// ConvTranspose1d using eliza ggml's native GGML_OP_CONV_TRANSPOSE_1D.
|
|
2097
|
+
// The upstream omnivoice fork used a private col2im_1d op with padding.
|
|
2098
|
+
// eliza's native op requires p0=0, so we crop pad samples from both ends
|
|
2099
|
+
// and then apply output_pad to match the original length contract.
|
|
2100
|
+
static struct ggml_tensor * dac_conv_t1d(struct ggml_context * ctx,
|
|
2101
|
+
struct ggml_tensor * w,
|
|
2102
|
+
struct ggml_tensor * b,
|
|
2103
|
+
struct ggml_tensor * x,
|
|
2104
|
+
int stride,
|
|
2105
|
+
int pad,
|
|
2106
|
+
int oc,
|
|
2107
|
+
int output_pad) {
|
|
2108
|
+
struct ggml_tensor * y = ggml_conv_transpose_1d(ctx, w, x, stride, 0, 1);
|
|
2109
|
+
y = ggml_reshape_2d(ctx, y, y->ne[0], y->ne[1]);
|
|
2110
|
+
|
|
2111
|
+
if (pad > 0) {
|
|
2112
|
+
const int64_t cropped = y->ne[0] - 2 * (int64_t) pad;
|
|
2113
|
+
GGML_ASSERT(cropped > 0);
|
|
2114
|
+
GGML_ASSERT(y->ne[1] == oc);
|
|
2115
|
+
y = ggml_view_2d(ctx, y, cropped, y->ne[1], y->nb[1], (size_t) pad * y->nb[0]);
|
|
2116
|
+
y = ggml_cont(ctx, y);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
if (output_pad > 0) {
|
|
2120
|
+
y = ggml_pad(ctx, y, output_pad, 0, 0, 0);
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
if (b) {
|
|
2124
|
+
struct ggml_tensor * b2d = ggml_reshape_2d(ctx, b, 1, b->ne[0]);
|
|
2125
|
+
y = ggml_add(ctx, y, b2d);
|
|
2126
|
+
}
|
|
2127
|
+
return y;
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
`;
|
|
2131
|
+
source = replaceBetween(
|
|
2132
|
+
source,
|
|
2133
|
+
"// ConvTranspose1d via GEMM + col2im_1d",
|
|
2134
|
+
"// Residual unit forward:",
|
|
2135
|
+
convT,
|
|
2136
|
+
);
|
|
2137
|
+
|
|
2138
|
+
source = source.replace(
|
|
2139
|
+
"b.ctw = ggml_new_tensor_2d(ctx, GGML_TYPE_F16, b.in_ch, b.kernel * b.out_ch);",
|
|
2140
|
+
"b.ctw = ggml_new_tensor_3d(ctx, GGML_TYPE_F16, b.kernel, b.out_ch, b.in_ch);",
|
|
2141
|
+
);
|
|
2142
|
+
source = source.replace(
|
|
2143
|
+
"struct ggml_tensor * ctw; // [IC, K*OC] bf16",
|
|
2144
|
+
"struct ggml_tensor * ctw; // [K, OC, IC] bf16",
|
|
2145
|
+
);
|
|
2146
|
+
fs.writeFileSync(dacPath, source, "utf8");
|
|
2147
|
+
|
|
2148
|
+
const codecPath = path.join(graftRoot, "src", "pipeline-codec.cpp");
|
|
2149
|
+
let codecSource = fs.readFileSync(codecPath, "utf8");
|
|
2150
|
+
const codecBackendAnchor = ` pc->bp = bp;
|
|
2151
|
+
pc->backend = bp.backend;
|
|
2152
|
+
ggml_backend_t backend = bp.backend;
|
|
2153
|
+
`;
|
|
2154
|
+
if (!codecSource.includes(codecBackendAnchor)) {
|
|
2155
|
+
throw new Error(
|
|
2156
|
+
`[omnivoice-fuse] compatibility patch anchor not found: pipeline-codec backend selection`,
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
codecSource = codecSource.replace(
|
|
2160
|
+
codecBackendAnchor,
|
|
2161
|
+
` // Keep the MaskGIT/LM path on the selected accelerator, but pin the
|
|
2162
|
+
// audio tokenizer / DAC codec to CPU on Apple Metal. The merged eliza
|
|
2163
|
+
// ggml Metal DAC decode graph has been observed to stall immediately
|
|
2164
|
+
// after "[TTS] Decode"; using CPU here keeps one fused process and one
|
|
2165
|
+
// model lifecycle while avoiding the bad Metal codec scheduler path.
|
|
2166
|
+
BackendPair codec_bp = bp;
|
|
2167
|
+
const char * requested_backend =
|
|
2168
|
+
bp.backend ? ggml_backend_name(bp.backend) : "(null)";
|
|
2169
|
+
const bool requested_metal =
|
|
2170
|
+
requested_backend &&
|
|
2171
|
+
(std::strncmp(requested_backend, "MTL", 3) == 0 ||
|
|
2172
|
+
std::strstr(requested_backend, "Metal") != nullptr);
|
|
2173
|
+
if (requested_metal && bp.cpu_backend) {
|
|
2174
|
+
codec_bp.backend = bp.cpu_backend;
|
|
2175
|
+
codec_bp.has_gpu = false;
|
|
2176
|
+
ov_log(OV_LOG_INFO,
|
|
2177
|
+
"[PipelineCodec] Metal codec fallback: requested=%s selected=%s reason=merged-ggml-dac-decode-stall",
|
|
2178
|
+
requested_backend, ggml_backend_name(codec_bp.backend));
|
|
70
2179
|
}
|
|
2180
|
+
pc->bp = codec_bp;
|
|
2181
|
+
pc->backend = codec_bp.backend;
|
|
2182
|
+
ggml_backend_t backend = codec_bp.backend;
|
|
2183
|
+
`,
|
|
2184
|
+
);
|
|
2185
|
+
const codecSchedulerAnchor = " pc->sched = backend_sched_new(bp, 4096);";
|
|
2186
|
+
if (!codecSource.includes(codecSchedulerAnchor)) {
|
|
2187
|
+
throw new Error(
|
|
2188
|
+
`[omnivoice-fuse] compatibility patch anchor not found: pipeline-codec scheduler backend`,
|
|
2189
|
+
);
|
|
71
2190
|
}
|
|
2191
|
+
codecSource = codecSource.replace(
|
|
2192
|
+
codecSchedulerAnchor,
|
|
2193
|
+
" pc->sched = backend_sched_new(codec_bp, 4096);",
|
|
2194
|
+
);
|
|
2195
|
+
fs.writeFileSync(codecPath, codecSource, "utf8");
|
|
2196
|
+
|
|
2197
|
+
applyOmnivoiceReferenceEncodeApi({ graftRoot });
|
|
2198
|
+
|
|
2199
|
+
fs.writeFileSync(
|
|
2200
|
+
path.join(graftRoot, "src", "version.h"),
|
|
2201
|
+
`#pragma once\n#define OMNIVOICE_VERSION "${commit.slice(0, 12)} (eliza-fused)"\n`,
|
|
2202
|
+
"utf8",
|
|
2203
|
+
);
|
|
2204
|
+
writeElizaFfiAdapter({ graftRoot, commit });
|
|
72
2205
|
}
|
|
73
2206
|
|
|
74
2207
|
// Ensure a clone of omnivoice.cpp at OMNIVOICE_REF lives under
|
|
@@ -116,9 +2249,7 @@ function readOmnivoiceGgmlSubmoduleCommit(checkoutDir) {
|
|
|
116
2249
|
stdio: ["ignore", "pipe", "pipe"],
|
|
117
2250
|
});
|
|
118
2251
|
if (result.status !== 0) return null;
|
|
119
|
-
const match = /^160000\s+commit\s+([0-9a-f]{40})/.exec(
|
|
120
|
-
result.stdout || "",
|
|
121
|
-
);
|
|
2252
|
+
const match = /^160000\s+commit\s+([0-9a-f]{40})/.exec(result.stdout || "");
|
|
122
2253
|
return match ? match[1] : null;
|
|
123
2254
|
}
|
|
124
2255
|
|
|
@@ -151,6 +2282,355 @@ function applyPatches({ patchesDir, llamaCppRoot }) {
|
|
|
151
2282
|
return applied;
|
|
152
2283
|
}
|
|
153
2284
|
|
|
2285
|
+
const QWEN3A_MODEL_CPP = `#include "models.h"
|
|
2286
|
+
|
|
2287
|
+
ggml_cgraph * clip_graph_qwen3a::build() {
|
|
2288
|
+
ggml_tensor * inp = build_inp_raw(1);
|
|
2289
|
+
|
|
2290
|
+
{
|
|
2291
|
+
inp = ggml_conv_2d(ctx0, model.conv2d_1_w, inp, 2, 2, 1, 1, 1, 1);
|
|
2292
|
+
inp = ggml_add(ctx0, inp, model.conv2d_1_b);
|
|
2293
|
+
inp = ggml_gelu_erf(ctx0, inp);
|
|
2294
|
+
|
|
2295
|
+
inp = ggml_conv_2d(ctx0, model.conv2d_2_w, inp, 2, 2, 1, 1, 1, 1);
|
|
2296
|
+
inp = ggml_add(ctx0, inp, model.conv2d_2_b);
|
|
2297
|
+
inp = ggml_gelu_erf(ctx0, inp);
|
|
2298
|
+
|
|
2299
|
+
inp = ggml_conv_2d(ctx0, model.conv2d_3_w, inp, 2, 2, 1, 1, 1, 1);
|
|
2300
|
+
inp = ggml_add(ctx0, inp, model.conv2d_3_b);
|
|
2301
|
+
inp = ggml_gelu_erf(ctx0, inp);
|
|
2302
|
+
|
|
2303
|
+
cb(inp, "after_conv_blocks", -1);
|
|
2304
|
+
|
|
2305
|
+
const int64_t n_pos_after_conv = inp->ne[0];
|
|
2306
|
+
const int64_t n_mel_after_conv = inp->ne[1];
|
|
2307
|
+
|
|
2308
|
+
inp = ggml_cont(ctx0, ggml_permute(ctx0, inp, 0, 2, 3, 1));
|
|
2309
|
+
inp = ggml_reshape_2d(ctx0, inp, n_pos_after_conv, n_mel_after_conv * inp->ne[3]);
|
|
2310
|
+
inp = ggml_cont(ctx0, ggml_transpose(ctx0, inp));
|
|
2311
|
+
|
|
2312
|
+
inp = ggml_mul_mat(ctx0, model.conv_out_w, inp);
|
|
2313
|
+
if (model.conv_out_b) {
|
|
2314
|
+
inp = ggml_add(ctx0, inp, model.conv_out_b);
|
|
2315
|
+
}
|
|
2316
|
+
cb(inp, "after_conv_out", -1);
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
auto n_pos = inp->ne[1];
|
|
2320
|
+
ggml_tensor * pos_embd_selected = ggml_view_2d(
|
|
2321
|
+
ctx0, model.position_embeddings,
|
|
2322
|
+
model.position_embeddings->ne[0], n_pos,
|
|
2323
|
+
model.position_embeddings->nb[1], 0);
|
|
2324
|
+
|
|
2325
|
+
ggml_tensor * cur = build_vit(
|
|
2326
|
+
inp,
|
|
2327
|
+
n_pos,
|
|
2328
|
+
NORM_TYPE_NORMAL,
|
|
2329
|
+
hparams.ffn_op,
|
|
2330
|
+
pos_embd_selected,
|
|
2331
|
+
nullptr);
|
|
2332
|
+
|
|
2333
|
+
cb(cur, "after_transformer", -1);
|
|
2334
|
+
|
|
2335
|
+
cur = build_ffn(cur,
|
|
2336
|
+
model.mm_1_w, model.mm_1_b,
|
|
2337
|
+
nullptr, nullptr,
|
|
2338
|
+
model.mm_2_w, model.mm_2_b,
|
|
2339
|
+
FFN_GELU_ERF,
|
|
2340
|
+
-1);
|
|
2341
|
+
|
|
2342
|
+
cb(cur, "projected", -1);
|
|
2343
|
+
ggml_build_forward_expand(gf, cur);
|
|
2344
|
+
return gf;
|
|
2345
|
+
}
|
|
2346
|
+
`;
|
|
2347
|
+
|
|
2348
|
+
function replaceRequired(source, from, to, label) {
|
|
2349
|
+
if (!source.includes(from)) {
|
|
2350
|
+
throw new Error(`[omnivoice-fuse] qwen3a patch anchor not found: ${label}`);
|
|
2351
|
+
}
|
|
2352
|
+
return source.replace(from, to);
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
function applyElizaQwen3AsrMtmdSupport({ llamaCppRoot }) {
|
|
2356
|
+
const touched = [];
|
|
2357
|
+
|
|
2358
|
+
const clipImplPath = path.join(llamaCppRoot, "tools", "mtmd", "clip-impl.h");
|
|
2359
|
+
let clipImpl = fs.readFileSync(clipImplPath, "utf8");
|
|
2360
|
+
if (!clipImpl.includes("PROJECTOR_TYPE_QWEN3A")) {
|
|
2361
|
+
clipImpl = replaceRequired(
|
|
2362
|
+
clipImpl,
|
|
2363
|
+
" PROJECTOR_TYPE_QWEN2A,\n PROJECTOR_TYPE_GLMA,",
|
|
2364
|
+
" PROJECTOR_TYPE_QWEN2A,\n PROJECTOR_TYPE_QWEN3A,\n PROJECTOR_TYPE_GLMA,",
|
|
2365
|
+
"clip-impl enum",
|
|
2366
|
+
);
|
|
2367
|
+
}
|
|
2368
|
+
if (!clipImpl.includes('{ PROJECTOR_TYPE_QWEN3A, "qwen3a"}')) {
|
|
2369
|
+
clipImpl = replaceRequired(
|
|
2370
|
+
clipImpl,
|
|
2371
|
+
' { PROJECTOR_TYPE_QWEN2A, "qwen2a"},\n { PROJECTOR_TYPE_GLMA, "glma"},',
|
|
2372
|
+
' { PROJECTOR_TYPE_QWEN2A, "qwen2a"},\n { PROJECTOR_TYPE_QWEN3A, "qwen3a"},\n { PROJECTOR_TYPE_GLMA, "glma"},',
|
|
2373
|
+
"clip-impl name map",
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
if (!clipImpl.includes("#define TN_CONV2D")) {
|
|
2377
|
+
clipImpl = replaceRequired(
|
|
2378
|
+
clipImpl,
|
|
2379
|
+
'#define TN_CONV1D "a.conv1d.%d.%s"\n#define TN_MM_AUDIO_MLP',
|
|
2380
|
+
'#define TN_CONV1D "a.conv1d.%d.%s"\n#define TN_CONV2D "a.conv2d.%d.%s"\n#define TN_CONV_OUT "a.conv_out.%s"\n#define TN_MM_AUDIO_MLP',
|
|
2381
|
+
"clip-impl conv2d tensor names",
|
|
2382
|
+
);
|
|
2383
|
+
}
|
|
2384
|
+
if (clipImpl !== fs.readFileSync(clipImplPath, "utf8")) {
|
|
2385
|
+
fs.writeFileSync(clipImplPath, clipImpl, "utf8");
|
|
2386
|
+
touched.push("tools/mtmd/clip-impl.h");
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
const clipModelPath = path.join(
|
|
2390
|
+
llamaCppRoot,
|
|
2391
|
+
"tools",
|
|
2392
|
+
"mtmd",
|
|
2393
|
+
"clip-model.h",
|
|
2394
|
+
);
|
|
2395
|
+
let clipModel = fs.readFileSync(clipModelPath, "utf8");
|
|
2396
|
+
if (!clipModel.includes("conv_out_w")) {
|
|
2397
|
+
clipModel = replaceRequired(
|
|
2398
|
+
clipModel,
|
|
2399
|
+
" ggml_tensor * conv1d_2_w = nullptr;\n ggml_tensor * conv1d_2_b = nullptr;\n ggml_tensor * mm_norm_pre_w = nullptr;",
|
|
2400
|
+
" ggml_tensor * conv1d_2_w = nullptr;\n ggml_tensor * conv1d_2_b = nullptr;\n ggml_tensor * conv_out_w = nullptr;\n ggml_tensor * conv_out_b = nullptr;\n ggml_tensor * mm_norm_pre_w = nullptr;",
|
|
2401
|
+
"clip-model conv_out fields",
|
|
2402
|
+
);
|
|
2403
|
+
}
|
|
2404
|
+
if (!clipModel.includes("// qwen3a")) {
|
|
2405
|
+
clipModel = replaceRequired(
|
|
2406
|
+
clipModel,
|
|
2407
|
+
" ggml_tensor * mm_norm_mid_w = nullptr;\n\n // cogvlm",
|
|
2408
|
+
" ggml_tensor * mm_norm_mid_w = nullptr;\n\n // qwen3a\n ggml_tensor * conv2d_1_w = nullptr;\n ggml_tensor * conv2d_1_b = nullptr;\n ggml_tensor * conv2d_2_w = nullptr;\n ggml_tensor * conv2d_2_b = nullptr;\n ggml_tensor * conv2d_3_w = nullptr;\n ggml_tensor * conv2d_3_b = nullptr;\n\n // cogvlm",
|
|
2409
|
+
"clip-model qwen3a fields",
|
|
2410
|
+
);
|
|
2411
|
+
}
|
|
2412
|
+
if (clipModel !== fs.readFileSync(clipModelPath, "utf8")) {
|
|
2413
|
+
fs.writeFileSync(clipModelPath, clipModel, "utf8");
|
|
2414
|
+
touched.push("tools/mtmd/clip-model.h");
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
const modelsHeaderPath = path.join(
|
|
2418
|
+
llamaCppRoot,
|
|
2419
|
+
"tools",
|
|
2420
|
+
"mtmd",
|
|
2421
|
+
"models",
|
|
2422
|
+
"models.h",
|
|
2423
|
+
);
|
|
2424
|
+
let modelsHeader = fs.readFileSync(modelsHeaderPath, "utf8");
|
|
2425
|
+
if (!modelsHeader.includes("clip_graph_qwen3a")) {
|
|
2426
|
+
modelsHeader = replaceRequired(
|
|
2427
|
+
modelsHeader,
|
|
2428
|
+
"struct clip_graph_kimik25 : clip_graph {",
|
|
2429
|
+
"struct clip_graph_qwen3a : clip_graph {\n clip_graph_qwen3a(clip_ctx * ctx, const clip_image_f32 & img) : clip_graph(ctx, img) {}\n ggml_cgraph * build() override;\n};\n\nstruct clip_graph_kimik25 : clip_graph {",
|
|
2430
|
+
"models.h qwen3a graph declaration",
|
|
2431
|
+
);
|
|
2432
|
+
fs.writeFileSync(modelsHeaderPath, modelsHeader, "utf8");
|
|
2433
|
+
touched.push("tools/mtmd/models/models.h");
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
const qwen3aPath = path.join(
|
|
2437
|
+
llamaCppRoot,
|
|
2438
|
+
"tools",
|
|
2439
|
+
"mtmd",
|
|
2440
|
+
"models",
|
|
2441
|
+
"qwen3a.cpp",
|
|
2442
|
+
);
|
|
2443
|
+
if (!fs.existsSync(qwen3aPath)) {
|
|
2444
|
+
fs.writeFileSync(qwen3aPath, QWEN3A_MODEL_CPP, "utf8");
|
|
2445
|
+
touched.push("tools/mtmd/models/qwen3a.cpp");
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
const mtmdCmakePath = path.join(
|
|
2449
|
+
llamaCppRoot,
|
|
2450
|
+
"tools",
|
|
2451
|
+
"mtmd",
|
|
2452
|
+
"CMakeLists.txt",
|
|
2453
|
+
);
|
|
2454
|
+
let mtmdCmake = fs.readFileSync(mtmdCmakePath, "utf8");
|
|
2455
|
+
if (!mtmdCmake.includes("models/qwen3a.cpp")) {
|
|
2456
|
+
mtmdCmake = replaceRequired(
|
|
2457
|
+
mtmdCmake,
|
|
2458
|
+
" models/qwen3vl.cpp\n models/siglip.cpp",
|
|
2459
|
+
" models/qwen3vl.cpp\n models/qwen3a.cpp\n models/siglip.cpp",
|
|
2460
|
+
"mtmd CMake qwen3a source",
|
|
2461
|
+
);
|
|
2462
|
+
fs.writeFileSync(mtmdCmakePath, mtmdCmake, "utf8");
|
|
2463
|
+
touched.push("tools/mtmd/CMakeLists.txt");
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
const clipPath = path.join(llamaCppRoot, "tools", "mtmd", "clip.cpp");
|
|
2467
|
+
let clip = fs.readFileSync(clipPath, "utf8");
|
|
2468
|
+
const qwen3aDispatchBlock = ` case PROJECTOR_TYPE_QWEN3A:
|
|
2469
|
+
{
|
|
2470
|
+
builder = std::make_unique<clip_graph_qwen3a>(ctx, img);
|
|
2471
|
+
} break;
|
|
2472
|
+
`;
|
|
2473
|
+
const firstQwen3aDispatch = clip.indexOf(qwen3aDispatchBlock);
|
|
2474
|
+
const secondQwen3aDispatch =
|
|
2475
|
+
firstQwen3aDispatch >= 0
|
|
2476
|
+
? clip.indexOf(
|
|
2477
|
+
qwen3aDispatchBlock,
|
|
2478
|
+
firstQwen3aDispatch + qwen3aDispatchBlock.length,
|
|
2479
|
+
)
|
|
2480
|
+
: -1;
|
|
2481
|
+
if (secondQwen3aDispatch >= 0) {
|
|
2482
|
+
clip =
|
|
2483
|
+
clip.slice(0, secondQwen3aDispatch) +
|
|
2484
|
+
clip.slice(secondQwen3aDispatch + qwen3aDispatchBlock.length);
|
|
2485
|
+
}
|
|
2486
|
+
if (!clip.includes("clip_graph_qwen3a")) {
|
|
2487
|
+
clip = replaceRequired(
|
|
2488
|
+
clip,
|
|
2489
|
+
" case PROJECTOR_TYPE_ULTRAVOX:\n case PROJECTOR_TYPE_VOXTRAL:\n case PROJECTOR_TYPE_QWEN2A:",
|
|
2490
|
+
" case PROJECTOR_TYPE_QWEN3A:\n {\n builder = std::make_unique<clip_graph_qwen3a>(ctx, img);\n } break;\n case PROJECTOR_TYPE_ULTRAVOX:\n case PROJECTOR_TYPE_VOXTRAL:\n case PROJECTOR_TYPE_QWEN2A:",
|
|
2491
|
+
"clip.cpp qwen3a graph dispatch",
|
|
2492
|
+
);
|
|
2493
|
+
}
|
|
2494
|
+
if (
|
|
2495
|
+
!clip.includes(
|
|
2496
|
+
"case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_GLMA",
|
|
2497
|
+
)
|
|
2498
|
+
) {
|
|
2499
|
+
clip = replaceRequired(
|
|
2500
|
+
clip,
|
|
2501
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_GLMA:",
|
|
2502
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_GLMA:",
|
|
2503
|
+
"clip.cpp qwen3a hparams",
|
|
2504
|
+
);
|
|
2505
|
+
}
|
|
2506
|
+
if (
|
|
2507
|
+
!clip.includes(
|
|
2508
|
+
"case PROJECTOR_TYPE_QWEN3A:\n {\n model.conv2d_1_w",
|
|
2509
|
+
)
|
|
2510
|
+
) {
|
|
2511
|
+
clip = replaceRequired(
|
|
2512
|
+
clip,
|
|
2513
|
+
" case PROJECTOR_TYPE_VOXTRAL:\n {",
|
|
2514
|
+
' case PROJECTOR_TYPE_QWEN3A:\n {\n model.conv2d_1_w = get_tensor(string_format(TN_CONV2D, 1, "weight"));\n model.conv2d_1_b = get_tensor(string_format(TN_CONV2D, 1, "bias"));\n model.conv2d_2_w = get_tensor(string_format(TN_CONV2D, 2, "weight"));\n model.conv2d_2_b = get_tensor(string_format(TN_CONV2D, 2, "bias"));\n model.conv2d_3_w = get_tensor(string_format(TN_CONV2D, 3, "weight"));\n model.conv2d_3_b = get_tensor(string_format(TN_CONV2D, 3, "bias"));\n model.conv_out_w = get_tensor(string_format(TN_CONV_OUT, "weight"));\n model.conv_out_b = get_tensor(string_format(TN_CONV_OUT, "bias"), false);\n model.mm_1_w = get_tensor(string_format(TN_MM_AUDIO_MLP, 1, "weight"));\n model.mm_1_b = get_tensor(string_format(TN_MM_AUDIO_MLP, 1, "bias"));\n model.mm_2_w = get_tensor(string_format(TN_MM_AUDIO_MLP, 2, "weight"));\n model.mm_2_b = get_tensor(string_format(TN_MM_AUDIO_MLP, 2, "bias"));\n } break;\n case PROJECTOR_TYPE_VOXTRAL:\n {',
|
|
2515
|
+
"clip.cpp qwen3a tensor loads",
|
|
2516
|
+
);
|
|
2517
|
+
}
|
|
2518
|
+
if (
|
|
2519
|
+
!clip.includes(
|
|
2520
|
+
"case PROJECTOR_TYPE_QWEN3A:\n {\n // 3x stride-2 conv2d",
|
|
2521
|
+
)
|
|
2522
|
+
) {
|
|
2523
|
+
clip = replaceRequired(
|
|
2524
|
+
clip,
|
|
2525
|
+
" case PROJECTOR_TYPE_GLMA:\n {",
|
|
2526
|
+
" case PROJECTOR_TYPE_QWEN3A:\n {\n // 3x stride-2 conv2d: each step is floor((n-1)/2)+1\n int n = img->nx;\n n = (n - 1) / 2 + 1;\n n = (n - 1) / 2 + 1;\n n = (n - 1) / 2 + 1;\n n_patches = n;\n } break;\n case PROJECTOR_TYPE_GLMA:\n {",
|
|
2527
|
+
"clip.cpp qwen3a output token count",
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
if (
|
|
2531
|
+
!clip.includes(
|
|
2532
|
+
"case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_GLMA:\n case PROJECTOR_TYPE_ULTRAVOX",
|
|
2533
|
+
)
|
|
2534
|
+
) {
|
|
2535
|
+
clip = replaceRequired(
|
|
2536
|
+
clip,
|
|
2537
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_GLMA:\n case PROJECTOR_TYPE_ULTRAVOX:",
|
|
2538
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_GLMA:\n case PROJECTOR_TYPE_ULTRAVOX:",
|
|
2539
|
+
"clip.cpp qwen3a input setup",
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
if (
|
|
2543
|
+
!clip.includes(
|
|
2544
|
+
"case PROJECTOR_TYPE_QWEN3A:\n return ctx->model.mm_2_w->ne[1];",
|
|
2545
|
+
)
|
|
2546
|
+
) {
|
|
2547
|
+
clip = replaceRequired(
|
|
2548
|
+
clip,
|
|
2549
|
+
" case PROJECTOR_TYPE_QWEN2A:\n return ctx->model.mm_fc_w->ne[1];\n case PROJECTOR_TYPE_GLMA:",
|
|
2550
|
+
" case PROJECTOR_TYPE_QWEN2A:\n return ctx->model.mm_fc_w->ne[1];\n case PROJECTOR_TYPE_QWEN3A:\n return ctx->model.mm_2_w->ne[1];\n case PROJECTOR_TYPE_GLMA:",
|
|
2551
|
+
"clip.cpp qwen3a mmproj embedding dim",
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
if (
|
|
2555
|
+
!clip.includes(
|
|
2556
|
+
"case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_GLMA:\n case PROJECTOR_TYPE_VOXTRAL",
|
|
2557
|
+
)
|
|
2558
|
+
) {
|
|
2559
|
+
clip = replaceRequired(
|
|
2560
|
+
clip,
|
|
2561
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_GLMA:\n case PROJECTOR_TYPE_VOXTRAL:",
|
|
2562
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_GLMA:\n case PROJECTOR_TYPE_VOXTRAL:",
|
|
2563
|
+
"clip.cpp qwen3a whisper preprocessor flag",
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
if (clip !== fs.readFileSync(clipPath, "utf8")) {
|
|
2567
|
+
fs.writeFileSync(clipPath, clip, "utf8");
|
|
2568
|
+
touched.push("tools/mtmd/clip.cpp");
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
const mtmdPath = path.join(llamaCppRoot, "tools", "mtmd", "mtmd.cpp");
|
|
2572
|
+
let mtmd = fs.readFileSync(mtmdPath, "utf8");
|
|
2573
|
+
if (
|
|
2574
|
+
!mtmd.includes(
|
|
2575
|
+
"case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_QWEN25O:",
|
|
2576
|
+
)
|
|
2577
|
+
) {
|
|
2578
|
+
mtmd = replaceRequired(
|
|
2579
|
+
mtmd,
|
|
2580
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_QWEN25O:",
|
|
2581
|
+
" case PROJECTOR_TYPE_QWEN2A:\n case PROJECTOR_TYPE_QWEN3A:\n case PROJECTOR_TYPE_QWEN25O:",
|
|
2582
|
+
"mtmd.cpp qwen3a audio preprocessor",
|
|
2583
|
+
);
|
|
2584
|
+
}
|
|
2585
|
+
// Detect "already applied" in two flavors:
|
|
2586
|
+
// (a) This patch ran on a clean fork that originally had a QWEN2A-only
|
|
2587
|
+
// audio_bos/eos branch → patcher inserted a new QWEN3A branch with
|
|
2588
|
+
// <|audio_start|>/<|audio_end|>.
|
|
2589
|
+
// (b) The fork itself merged QWEN3A under the QWEN2A/QWEN25O audio_bos/eos
|
|
2590
|
+
// branch (fork commit 2f80716c "updates" in v1.1.x+). In that case the
|
|
2591
|
+
// fork has decided QWEN3A uses audio_bos/eos like QWEN2A, and this
|
|
2592
|
+
// eliza-side backport must NOT try to splice in audio_start/end on top
|
|
2593
|
+
// — there is no QWEN2A-only anchor left to replace, and the operator
|
|
2594
|
+
// fork has chosen the token strings. Treat as already applied.
|
|
2595
|
+
const variantA =
|
|
2596
|
+
mtmd.includes('aud_beg = "<|audio_start|>";') &&
|
|
2597
|
+
mtmd.includes("proj == PROJECTOR_TYPE_QWEN3A");
|
|
2598
|
+
const variantB = mtmd.includes(
|
|
2599
|
+
"if (proj == PROJECTOR_TYPE_QWEN2A || proj == PROJECTOR_TYPE_QWEN3A || proj == PROJECTOR_TYPE_QWEN25O) {",
|
|
2600
|
+
);
|
|
2601
|
+
if (!variantA && !variantB) {
|
|
2602
|
+
mtmd = replaceRequired(
|
|
2603
|
+
mtmd,
|
|
2604
|
+
` if (proj == PROJECTOR_TYPE_QWEN2A) {
|
|
2605
|
+
// <|audio_bos|> ... (embeddings) ... <|audio_eos|>
|
|
2606
|
+
aud_beg = "<|audio_bos|>";
|
|
2607
|
+
aud_end = "<|audio_eos|>";
|
|
2608
|
+
`,
|
|
2609
|
+
` if (proj == PROJECTOR_TYPE_QWEN3A) {
|
|
2610
|
+
// <|audio_start|> ... (embeddings replacing <|audio_pad|>) ... <|audio_end|>
|
|
2611
|
+
aud_beg = "<|audio_start|>";
|
|
2612
|
+
aud_end = "<|audio_end|>";
|
|
2613
|
+
|
|
2614
|
+
} else if (proj == PROJECTOR_TYPE_QWEN2A || proj == PROJECTOR_TYPE_QWEN25O) {
|
|
2615
|
+
// <|audio_bos|> ... (embeddings) ... <|audio_eos|>
|
|
2616
|
+
aud_beg = "<|audio_bos|>";
|
|
2617
|
+
aud_end = "<|audio_eos|>";
|
|
2618
|
+
`,
|
|
2619
|
+
"mtmd.cpp qwen3a audio special tokens",
|
|
2620
|
+
);
|
|
2621
|
+
}
|
|
2622
|
+
if (mtmd !== fs.readFileSync(mtmdPath, "utf8")) {
|
|
2623
|
+
fs.writeFileSync(mtmdPath, mtmd, "utf8");
|
|
2624
|
+
touched.push("tools/mtmd/mtmd.cpp");
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
return {
|
|
2628
|
+
name: "eliza-qwen3a-mtmd-backport",
|
|
2629
|
+
status: touched.length > 0 ? "applied" : "already-applied",
|
|
2630
|
+
files: touched,
|
|
2631
|
+
};
|
|
2632
|
+
}
|
|
2633
|
+
|
|
154
2634
|
/**
|
|
155
2635
|
* Main entry. Performs the full prepare phase. All errors propagate.
|
|
156
2636
|
*/
|
|
@@ -169,7 +2649,7 @@ export function prepareOmnivoiceFusion({
|
|
|
169
2649
|
}
|
|
170
2650
|
if (!fs.existsSync(path.join(llamaCppRoot, "ggml", "CMakeLists.txt"))) {
|
|
171
2651
|
throw new Error(
|
|
172
|
-
`[omnivoice-fuse] llamaCppRoot=${llamaCppRoot} missing ggml/CMakeLists.txt; the
|
|
2652
|
+
`[omnivoice-fuse] llamaCppRoot=${llamaCppRoot} missing ggml/CMakeLists.txt; the eliza ggml is required for fusion`,
|
|
173
2653
|
);
|
|
174
2654
|
}
|
|
175
2655
|
|
|
@@ -214,6 +2694,8 @@ export function prepareOmnivoiceFusion({
|
|
|
214
2694
|
path.join(graftRoot, subdir),
|
|
215
2695
|
);
|
|
216
2696
|
}
|
|
2697
|
+
applyElizaGgmlCompatibility({ graftRoot, commit: head });
|
|
2698
|
+
const sourceSurface = inspectPreparedOmnivoiceSurface({ graftRoot });
|
|
217
2699
|
|
|
218
2700
|
// examples/ is data-only (audio prompts, sample text). Copy on a
|
|
219
2701
|
// best-effort basis — the build does not depend on these files. We
|
|
@@ -235,7 +2717,43 @@ export function prepareOmnivoiceFusion({
|
|
|
235
2717
|
|
|
236
2718
|
// Apply any reconciliation patches keyed to specific drifts.
|
|
237
2719
|
const patchesDir = new URL("./patches/", import.meta.url).pathname;
|
|
238
|
-
const
|
|
2720
|
+
const qwen3aBackport = applyElizaQwen3AsrMtmdSupport({ llamaCppRoot });
|
|
2721
|
+
const appliedPatches = [
|
|
2722
|
+
qwen3aBackport,
|
|
2723
|
+
...applyPatches({ patchesDir, llamaCppRoot }),
|
|
2724
|
+
];
|
|
2725
|
+
|
|
2726
|
+
// Stage the Kokoro graft alongside OmniVoice. The Kokoro sources live in
|
|
2727
|
+
// `packages/app-core/scripts/omnivoice-fuse/kokoro-graft/{src,tools}` and
|
|
2728
|
+
// are copied into the same `omnivoice/` directory so they compile into the
|
|
2729
|
+
// same `omnivoice-core` static library + `elizainference` shared library.
|
|
2730
|
+
// See kokoro-llama-cpp-feasibility.md §3.
|
|
2731
|
+
const kokoroStagingDir = new URL("./kokoro-graft/", import.meta.url).pathname;
|
|
2732
|
+
let kokoroSourceCount = 0;
|
|
2733
|
+
if (fs.existsSync(kokoroStagingDir)) {
|
|
2734
|
+
for (const subdir of ["src", "tools"]) {
|
|
2735
|
+
const from = path.join(kokoroStagingDir, subdir);
|
|
2736
|
+
const to = path.join(graftRoot, subdir);
|
|
2737
|
+
if (!fs.existsSync(from)) continue;
|
|
2738
|
+
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
2739
|
+
// Only copy kokoro-* and convert_kokoro_* files; never overwrite
|
|
2740
|
+
// OmniVoice's own files in src/ or tools/. The CMake graft block
|
|
2741
|
+
// globs `kokoro-*.cpp` specifically so the two sets stay
|
|
2742
|
+
// distinguishable on the build side.
|
|
2743
|
+
if (
|
|
2744
|
+
!entry.name.startsWith("kokoro") &&
|
|
2745
|
+
!entry.name.startsWith("convert_kokoro")
|
|
2746
|
+
) {
|
|
2747
|
+
continue;
|
|
2748
|
+
}
|
|
2749
|
+
if (entry.isDirectory()) continue;
|
|
2750
|
+
const srcFile = path.join(from, entry.name);
|
|
2751
|
+
const dstFile = path.join(to, entry.name);
|
|
2752
|
+
fs.copyFileSync(srcFile, dstFile);
|
|
2753
|
+
if (/\.(c|cc|cpp|cxx|h|hpp)$/.test(entry.name)) kokoroSourceCount += 1;
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
239
2757
|
|
|
240
2758
|
// Count source files actually grafted, for the manifest.
|
|
241
2759
|
let sourceCount = 0;
|
|
@@ -258,6 +2776,8 @@ export function prepareOmnivoiceFusion({
|
|
|
258
2776
|
ggmlSubmoduleCommit,
|
|
259
2777
|
graftRoot,
|
|
260
2778
|
sourceCount,
|
|
2779
|
+
sourceSurface,
|
|
261
2780
|
appliedPatches,
|
|
2781
|
+
kokoroSourceCount,
|
|
262
2782
|
};
|
|
263
2783
|
}
|