@elizaos/app-core 2.0.3-beta.2 → 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 +5 -5
- package/api/auth/audit.d.ts +1 -1
- package/api/auth/auth-context.d.ts +1 -1
- package/api/auth/bootstrap-token.d.ts +1 -1
- package/api/auth/sessions.d.ts +1 -1
- package/api/auth-bootstrap-routes.d.ts +1 -1
- package/api/auth-pairing-routes.d.ts +1 -1
- package/api/auth-pairing-routes.d.ts.map +1 -1
- package/api/auth-pairing-routes.js +2 -3
- package/api/auth-session-routes.d.ts +2 -2
- package/api/auth.d.ts +1 -1
- package/api/automations-compat-routes.d.ts +1 -1
- package/api/background-tasks-routes.d.ts +1 -1
- package/api/catalog-routes.d.ts +1 -1
- package/api/cloud-voice-routes.d.ts +1 -1
- package/api/compat-route-shared.d.ts +12 -5
- package/api/compat-route-shared.d.ts.map +1 -1
- package/api/compat-route-shared.js +22 -187
- package/api/database-rows-compat-routes.d.ts +1 -1
- package/api/dev-compat-routes.d.ts +1 -1
- package/api/dev-route-catalog.d.ts.map +1 -1
- package/api/dev-route-catalog.js +20 -0
- 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 +1 -1
- package/api/internal-routes.d.ts +1 -1
- package/api/runtime-mode-routes.d.ts +1 -1
- package/api/secrets-manager-routes.d.ts.map +1 -1
- package/api/sensitive-request-routes.d.ts +2 -2
- package/api/server-config-filter.d.ts.map +1 -1
- package/api/server-config-filter.js +0 -1
- package/api/server-first-run-helpers.d.ts.map +1 -1
- package/api/server-first-run-helpers.js +0 -3
- package/api/server.d.ts +8 -8
- package/api/server.d.ts.map +1 -1
- package/api/server.js +13 -59
- package/api/training-benchmarks.d.ts +1 -1
- package/api/training-benchmarks.d.ts.map +1 -1
- package/api/training-benchmarks.js +31 -9
- package/api/workbench-compat-routes.d.ts +1 -1
- package/benchmark/server-utils.d.ts +2 -2
- package/browser.d.ts +4 -4
- package/cli/plugins-cli.d.ts.map +1 -1
- package/cli/plugins-cli.js +5 -0
- 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 +187 -0
- package/cli/program/register.dashboard.d.ts.map +1 -1
- package/cli/program/register.dashboard.js +11 -1
- package/cli/program.d.ts +1 -1
- package/first-run/first-run-config.d.ts +1 -1
- package/index.d.ts +46 -47
- package/index.d.ts.map +1 -1
- package/index.js +3 -7
- package/package.json +42 -36
- package/packaging/PUBLISHING_GUIDE.md +20 -20
- package/platform/elizaos-agent-browser-stub.d.ts +0 -1
- package/platform/elizaos-agent-browser-stub.d.ts.map +1 -1
- package/platform/elizaos-agent-browser-stub.js +0 -1
- package/platform/ios-runtime-bridge.d.ts.map +1 -1
- package/platform/ios-runtime-bridge.js +0 -1
- package/platform/native-plugin-entrypoints.d.ts +2 -2
- package/platforms/android/app/build.gradle +30 -7
- package/platforms/android/app/src/main/elizavoice-jni/elizavoice-jni.cpp +179 -35
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAgentService.java +60 -32
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBionicInferenceServer.java +405 -65
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceNative.java +35 -0
- package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoicePlugin.java +13 -6
- 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/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/colors.xml +5 -1
- package/platforms/android/app/src/main/res/values/ic_launcher_background.xml +1 -1
- package/platforms/android/app/src/main/res/values/styles.xml +4 -1
- package/platforms/electrobun/electrobun.config.ts +0 -1
- package/platforms/electrobun/native/macos/window-effects.mm +4 -0
- package/platforms/electrobun/package.json +11 -9
- package/platforms/electrobun/remotes/local-model/src/bun/eliza1-catalog.ts +1 -1
- package/platforms/electrobun/remotes/runtime/src/dev/phase2-smoke.ts +10 -5
- package/platforms/electrobun/remotes/runtime/src/dev/phase3-smoke.ts +11 -15
- package/platforms/electrobun/src/application-menu.ts +0 -7
- package/platforms/electrobun/src/desktop-http-request.test.ts +30 -1
- package/platforms/electrobun/src/desktop-http-request.ts +14 -2
- package/platforms/electrobun/src/desktop-test-bridge-server.ts +28 -0
- package/platforms/electrobun/src/fatal-shutdown.test.ts +3 -7
- package/platforms/electrobun/src/index.ts +64 -13
- package/platforms/electrobun/src/lifecycle/api-base-owner.test.ts +83 -0
- package/platforms/electrobun/src/lifecycle/api-base-owner.ts +37 -16
- package/platforms/electrobun/src/native/agent.ts +28 -17
- package/platforms/electrobun/src/native/credentials.ts +6 -1
- package/platforms/electrobun/src/native/desktop-window.test.ts +142 -26
- package/platforms/electrobun/src/native/desktop.ts +8 -4
- package/platforms/electrobun/src/native/index.ts +6 -0
- package/platforms/electrobun/src/native/remote-plugin-host.ts +18 -8
- package/platforms/electrobun/src/preload.js +1 -1
- package/platforms/electrobun/src/voice/voice-live-validation.test.ts +10 -5
- package/platforms/electrobun/src/voice/voice-runtime-adapter.ts +3 -2
- package/platforms/electrobun/src/voice/voice-service.test.ts +26 -0
- package/platforms/electrobun/src/voice/voice-service.ts +57 -17
- package/platforms/electrobun/tsconfig.json +17 -1
- package/platforms/ios/App/App/Base.lproj/LaunchScreen.storyboard +4 -6
- package/registry/index.d.ts +1 -6
- package/registry/index.d.ts.map +1 -1
- package/registry/index.js +9 -101
- package/runtime/android-avf-microdroid-bridge.d.ts +1 -1
- 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/index.d.ts +5 -5
- package/runtime/dev-server.js +11 -2
- package/runtime/eliza.d.ts.map +1 -1
- package/runtime/eliza.js +18 -8
- package/runtime/mode/route-mode-guard.d.ts +1 -1
- package/runtime/mode/route-mode-matrix.d.ts +1 -1
- package/runtime/voice-warmup.d.ts +4 -19
- package/runtime/voice-warmup.d.ts.map +1 -1
- package/runtime/voice-warmup.js +4 -14
- package/scripts/aosp/README.md +10 -1
- package/scripts/aosp/compile-libllama-zig-pin.test.mjs +147 -0
- package/scripts/aosp/compile-libllama.mjs +446 -59
- package/scripts/aosp/compile-libllama.test.mjs +133 -0
- package/scripts/aosp/compile-shim.mjs +21 -1
- package/scripts/aosp/deploy-pixel.mjs +1 -1
- package/scripts/aosp/stage-default-models.mjs +24 -31
- package/scripts/aosp/stage-default-models.test.mjs +23 -0
- package/scripts/assert-required-bundled-packages.test.ts +22 -1
- package/scripts/build-helpers/verify-fused-symbols.mjs +33 -0
- package/scripts/build-helpers/verify-fused-symbols.test.mjs +0 -0
- package/scripts/build-image.sh +1 -3
- package/scripts/build-llama-cpp-mtp.mjs +17 -16
- package/scripts/check-i18n.mjs +0 -1
- package/scripts/copy-runtime-node-modules.ts +147 -0
- package/scripts/desktop-build.mjs +317 -4
- package/scripts/docker-ci-smoke.sh +33 -8
- package/scripts/ensure-type-package-aliases.mjs +1 -1
- package/scripts/ios-xcframework/run-physical-device-smoke.mjs +1 -1
- package/scripts/lib/agent-source-watcher.mjs +0 -1
- 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/duet-bridge.mjs +1 -1
- package/scripts/lib/ios-plist-url-scheme.mjs +80 -0
- package/scripts/lib/mobile-build-decisions.mjs +97 -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 +13 -4
- 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/websocket-pending-queue.ts +92 -0
- package/scripts/link-docker-local-app-packages.mjs +6 -0
- package/scripts/playwright-ui-live-stack.ts +430 -144
- package/scripts/playwright-ui-smoke-api-stub.mjs +160 -168
- package/scripts/run-local-plugin-live-smoke.mjs +1 -6
- 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 +408 -86
- package/scripts/serve-real-local-agent.ts +72 -0
- package/scripts/stage-desktop-fused-lib.mjs +43 -14
- package/scripts/verify-ondevice-artifact.mjs +111 -0
- package/scripts/voice-attribution-smoke.ts +144 -38
- package/scripts/voice-duet.mjs +6 -6
- package/scripts/voice-e2e-hardware.ts +22 -16
- package/scripts/voice-interactive.mjs +16 -45
- package/security/agent-vault-id.d.ts +1 -1
- package/security/platform-secure-store-node.d.ts +1 -1
- package/services/ambient-audio/consent.d.ts +1 -1
- package/services/ambient-audio/index.d.ts +6 -6
- package/services/ambient-audio/replay-buffer.d.ts +1 -1
- package/services/ambient-audio/response-gate.d.ts +1 -1
- package/services/ambient-audio/service.d.ts +3 -3
- package/services/connector-target-catalog.d.ts +1 -1
- package/services/sensitive-requests/index.d.ts +6 -6
- package/services/steward-sidecar/wallet-setup.d.ts +1 -1
- package/services/steward-sidecar.d.ts +3 -3
- package/services/tunnel-to-mobile/index.d.ts +1 -1
- package/services/vault-bootstrap.d.ts.map +1 -1
- package/services/vault-bootstrap.js +14 -10
- package/services/voice-profiles/diarization-pipeline.d.ts +1 -1
- package/services/voice-profiles/index.d.ts +11 -11
- package/services/voice-profiles/owner-confidence.d.ts +1 -1
- package/services/voice-profiles/private-challenge.d.ts +1 -1
- package/services/voice-profiles/store.d.ts +1 -1
- package/test/helpers/live-provider.test.ts +91 -1
- package/test/helpers/live-provider.ts +195 -51
- 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 +1 -0
- package/ui-compat.d.ts.map +1 -1
- package/ui-compat.js +4 -0
- package/platforms/electrobun/docs/convergence-audit.json +0 -3505
- package/platforms/electrobun/docs/convergence-audit.md +0 -694
- package/platforms/electrobun/scripts/ensure-whisper-gguf.sh +0 -55
- package/platforms/electrobun/scripts/ensure-whisper-model.sh +0 -35
- package/platforms/electrobun/scripts/generate-convergence-audit.ts +0 -1203
- package/platforms/electrobun/src/native/whisper-env.test.ts +0 -71
- package/platforms/electrobun/src/native/whisper-env.ts +0 -68
- package/registry/app-registry.d.ts +0 -14
- package/registry/app-registry.d.ts.map +0 -1
- package/registry/app-registry.js +0 -29
- package/registry/entries/apps/app-polymarket.json +0 -31
- package/registry/entries/apps/clawville.json +0 -27
- package/registry/entries/apps/companion.json +0 -28
- package/registry/entries/apps/database-viewer.json +0 -27
- package/registry/entries/apps/defense-of-the-agents.json +0 -27
- package/registry/entries/apps/documents.json +0 -30
- package/registry/entries/apps/feed.json +0 -27
- package/registry/entries/apps/hyperliquid.json +0 -31
- package/registry/entries/apps/log-viewer.json +0 -27
- package/registry/entries/apps/memory-viewer.json +0 -27
- package/registry/entries/apps/model-tester.json +0 -31
- package/registry/entries/apps/plugin-viewer.json +0 -27
- package/registry/entries/apps/relationship-viewer.json +0 -27
- package/registry/entries/apps/runtime-debugger.json +0 -27
- package/registry/entries/apps/shopify.json +0 -31
- package/registry/entries/apps/skills-viewer.json +0 -27
- package/registry/entries/apps/steward.json +0 -31
- package/registry/entries/apps/training.json +0 -54
- package/registry/entries/apps/trajectory-viewer.json +0 -27
- package/registry/entries/apps/vincent.json +0 -31
- package/registry/entries/connectors/bluebubbles.json +0 -99
- package/registry/entries/connectors/bluesky.json +0 -173
- package/registry/entries/connectors/discord.json +0 -119
- package/registry/entries/connectors/farcaster.json +0 -174
- package/registry/entries/connectors/feishu.json +0 -79
- package/registry/entries/connectors/google-chat.json +0 -120
- package/registry/entries/connectors/google.json +0 -82
- package/registry/entries/connectors/imessage.json +0 -96
- package/registry/entries/connectors/instagram.json +0 -64
- package/registry/entries/connectors/line.json +0 -86
- package/registry/entries/connectors/matrix.json +0 -94
- package/registry/entries/connectors/mattermost.json +0 -110
- package/registry/entries/connectors/msteams.json +0 -104
- package/registry/entries/connectors/nextcloud-talk.json +0 -104
- package/registry/entries/connectors/nostr.json +0 -70
- package/registry/entries/connectors/signal.json +0 -81
- package/registry/entries/connectors/slack.json +0 -102
- package/registry/entries/connectors/telegram.json +0 -71
- package/registry/entries/connectors/tlon.json +0 -94
- package/registry/entries/connectors/twitch.json +0 -110
- package/registry/entries/connectors/whatsapp.json +0 -113
- package/registry/entries/connectors/x.json +0 -231
- package/registry/entries/connectors/zalo.json +0 -112
- package/registry/entries/connectors/zalouser.json +0 -122
- package/registry/entries/plugins/agent-orchestrator.json +0 -33
- package/registry/entries/plugins/agent-skills.json +0 -72
- package/registry/entries/plugins/anthropic.json +0 -73
- package/registry/entries/plugins/app-control.json +0 -23
- package/registry/entries/plugins/auto-trader.json +0 -203
- package/registry/entries/plugins/background-runner.json +0 -26
- package/registry/entries/plugins/blooio.json +0 -102
- package/registry/entries/plugins/browser.json +0 -75
- package/registry/entries/plugins/cli.json +0 -40
- package/registry/entries/plugins/clipboard.json +0 -44
- package/registry/entries/plugins/coding-tools.json +0 -71
- package/registry/entries/plugins/commands.json +0 -63
- package/registry/entries/plugins/computeruse.json +0 -74
- package/registry/entries/plugins/copilot-proxy.json +0 -93
- package/registry/entries/plugins/directives.json +0 -63
- package/registry/entries/plugins/edge-tts.json +0 -97
- package/registry/entries/plugins/elevenlabs.json +0 -169
- package/registry/entries/plugins/elizacloud.json +0 -208
- package/registry/entries/plugins/evm.json +0 -134
- package/registry/entries/plugins/experience.json +0 -34
- package/registry/entries/plugins/facewear.json +0 -131
- package/registry/entries/plugins/form.json +0 -26
- package/registry/entries/plugins/github.json +0 -93
- package/registry/entries/plugins/gmail-watch.json +0 -25
- package/registry/entries/plugins/goals.json +0 -77
- package/registry/entries/plugins/google-genai.json +0 -106
- package/registry/entries/plugins/groq.json +0 -93
- package/registry/entries/plugins/hedera.json +0 -48
- package/registry/entries/plugins/inmemorydb.json +0 -25
- package/registry/entries/plugins/linear.json +0 -51
- package/registry/entries/plugins/local-inference.json +0 -137
- package/registry/entries/plugins/local-storage.json +0 -36
- package/registry/entries/plugins/localdb.json +0 -25
- package/registry/entries/plugins/mcp.json +0 -44
- package/registry/entries/plugins/memory.json +0 -124
- package/registry/entries/plugins/minecraft.json +0 -79
- package/registry/entries/plugins/moltbook.json +0 -83
- package/registry/entries/plugins/music.json +0 -155
- package/registry/entries/plugins/mysticism.json +0 -48
- package/registry/entries/plugins/nearai.json +0 -82
- package/registry/entries/plugins/ngrok.json +0 -69
- package/registry/entries/plugins/ollama.json +0 -96
- package/registry/entries/plugins/openai.json +0 -189
- package/registry/entries/plugins/openrouter.json +0 -188
- package/registry/entries/plugins/pdf.json +0 -26
- package/registry/entries/plugins/plugin-manager.json +0 -23
- package/registry/entries/plugins/prose.json +0 -48
- package/registry/entries/plugins/rlm.json +0 -26
- package/registry/entries/plugins/roblox.json +0 -88
- package/registry/entries/plugins/rss.json +0 -64
- package/registry/entries/plugins/s3-storage.json +0 -91
- package/registry/entries/plugins/scheduling.json +0 -35
- package/registry/entries/plugins/shell.json +0 -94
- package/registry/entries/plugins/social-alpha.json +0 -72
- package/registry/entries/plugins/tailscale.json +0 -81
- package/registry/entries/plugins/tee.json +0 -53
- package/registry/entries/plugins/todos.json +0 -26
- package/registry/entries/plugins/trajectory-logger.json +0 -33
- package/registry/entries/plugins/trust.json +0 -39
- package/registry/entries/plugins/tts.json +0 -71
- package/registry/entries/plugins/tunnel.json +0 -45
- package/registry/entries/plugins/twilio.json +0 -168
- package/registry/entries/plugins/vercel-ai-gateway.json +0 -128
- package/registry/entries/plugins/video.json +0 -23
- package/registry/entries/plugins/vision.json +0 -43
- package/registry/entries/plugins/webhooks.json +0 -23
- package/registry/entries/plugins/workflow.json +0 -25
- package/registry/entries/plugins/xai.json +0 -75
- package/registry/loader.d.ts +0 -28
- package/registry/loader.d.ts.map +0 -1
- package/registry/loader.js +0 -158
- package/registry/schema.d.ts +0 -1199
- package/registry/schema.d.ts.map +0 -1
- package/registry/schema.js +0 -300
- package/scripts/patches/llama-mobile-kokoro-tts.patch +0 -480
- package/scripts/release-workflow-drift.test.ts +0 -57
- 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
|
@@ -1,480 +0,0 @@
|
|
|
1
|
-
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|
2
|
-
index 588f1339d..82a392654 100644
|
|
3
|
-
--- a/CMakeLists.txt
|
|
4
|
-
+++ b/CMakeLists.txt
|
|
5
|
-
@@ -248,6 +248,17 @@ if (LLAMA_BUILD_COMMON AND LLAMA_BUILD_TOOLS)
|
|
6
|
-
add_subdirectory(tools)
|
|
7
|
-
endif()
|
|
8
|
-
|
|
9
|
-
+if (LLAMA_BUILD_KOKORO)
|
|
10
|
-
+ if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/kokoro/CMakeLists.txt")
|
|
11
|
-
+ message(FATAL_ERROR
|
|
12
|
-
+ "LLAMA_BUILD_KOKORO=ON but tools/kokoro/CMakeLists.txt is missing. "
|
|
13
|
-
+ "Verify the fork contains the Kokoro subtree.")
|
|
14
|
-
+ endif()
|
|
15
|
-
+ if (NOT (LLAMA_BUILD_COMMON AND LLAMA_BUILD_TOOLS))
|
|
16
|
-
+ add_subdirectory(tools/kokoro)
|
|
17
|
-
+ endif()
|
|
18
|
-
+endif()
|
|
19
|
-
+
|
|
20
|
-
if (LLAMA_BUILD_OMNIVOICE)
|
|
21
|
-
if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/omnivoice/CMakeLists.txt")
|
|
22
|
-
message(FATAL_ERROR
|
|
23
|
-
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
|
|
24
|
-
index 4f8887274..c99ee49e3 100644
|
|
25
|
-
--- a/tools/CMakeLists.txt
|
|
26
|
-
+++ b/tools/CMakeLists.txt
|
|
27
|
-
@@ -29,13 +29,6 @@ else()
|
|
28
|
-
add_subdirectory(parser)
|
|
29
|
-
add_subdirectory(tts)
|
|
30
|
-
add_subdirectory(mtmd)
|
|
31
|
-
- if (LLAMA_BUILD_OMNIVOICE)
|
|
32
|
-
- # The merged omnivoice subtree lives under tools/omnivoice/. The
|
|
33
|
-
- # top-level CMakeLists.txt has a parallel add_subdirectory hook for
|
|
34
|
-
- # the embed-as-library case (LLAMA_BUILD_TOOLS=OFF) ; this gate is
|
|
35
|
-
- # the one that fires for the normal standalone build.
|
|
36
|
-
- add_subdirectory(omnivoice)
|
|
37
|
-
- endif()
|
|
38
|
-
if (LLAMA_BUILD_KOKORO)
|
|
39
|
-
# Kokoro-82M (StyleTTS-2 + iSTFTNet) standalone TTS — J2 fork-side
|
|
40
|
-
# replacement for the ONNX runtime path. Produces kokoro_lib +
|
|
41
|
-
@@ -43,6 +36,13 @@ else()
|
|
42
|
-
# `/v1/audio/speech` handler is mounted via server.cpp.
|
|
43
|
-
add_subdirectory(kokoro)
|
|
44
|
-
endif()
|
|
45
|
-
+ if (LLAMA_BUILD_OMNIVOICE)
|
|
46
|
-
+ # The merged omnivoice subtree lives under tools/omnivoice/. The
|
|
47
|
-
+ # top-level CMakeLists.txt has a parallel add_subdirectory hook for
|
|
48
|
-
+ # the embed-as-library case (LLAMA_BUILD_TOOLS=OFF) ; this gate is
|
|
49
|
-
+ # the one that fires for the normal standalone build.
|
|
50
|
-
+ add_subdirectory(omnivoice)
|
|
51
|
-
+ endif()
|
|
52
|
-
if (GGML_RPC)
|
|
53
|
-
add_subdirectory(rpc)
|
|
54
|
-
endif()
|
|
55
|
-
diff --git a/tools/kokoro/CMakeLists.txt b/tools/kokoro/CMakeLists.txt
|
|
56
|
-
index 7c4be7e4d..5e6fad3f5 100644
|
|
57
|
-
--- a/tools/kokoro/CMakeLists.txt
|
|
58
|
-
+++ b/tools/kokoro/CMakeLists.txt
|
|
59
|
-
@@ -44,11 +44,14 @@ if(TARGET ggml-cpu)
|
|
60
|
-
endif()
|
|
61
|
-
|
|
62
|
-
target_compile_features(kokoro_lib PUBLIC cxx_std_17)
|
|
63
|
-
+target_compile_definitions(kokoro_lib PUBLIC LLAMA_BUILD_KOKORO)
|
|
64
|
-
|
|
65
|
-
-# Standalone CLI harness — required by J2 verification (tools/voice-kokoro/).
|
|
66
|
-
-add_executable(kokoro-tts tools/kokoro-tts.cpp)
|
|
67
|
-
-target_link_libraries(kokoro-tts PRIVATE kokoro_lib)
|
|
68
|
-
-install(TARGETS kokoro-tts RUNTIME)
|
|
69
|
-
+option(KOKORO_BUILD_CLI "Build the standalone Kokoro CLI harness" ${LLAMA_BUILD_TOOLS})
|
|
70
|
-
+if(KOKORO_BUILD_CLI)
|
|
71
|
-
+ add_executable(kokoro-tts tools/kokoro-tts.cpp)
|
|
72
|
-
+ target_link_libraries(kokoro-tts PRIVATE kokoro_lib)
|
|
73
|
-
+ install(TARGETS kokoro-tts RUNTIME)
|
|
74
|
-
+endif()
|
|
75
|
-
|
|
76
|
-
# Server-mount handler: compiled into kokoro_lib only when the server target
|
|
77
|
-
# exists. The handler is guarded by `#ifdef LLAMA_BUILD_KOKORO` and pulls in
|
|
78
|
-
@@ -56,7 +59,6 @@ install(TARGETS kokoro-tts RUNTIME)
|
|
79
|
-
# the vendored nlohmann/json.hpp from common's vendor directory.
|
|
80
|
-
if(LLAMA_BUILD_SERVER)
|
|
81
|
-
target_sources(kokoro_lib PRIVATE src/kokoro-server-mount.cpp)
|
|
82
|
-
- target_compile_definitions(kokoro_lib PUBLIC LLAMA_BUILD_KOKORO)
|
|
83
|
-
target_include_directories(kokoro_lib PRIVATE
|
|
84
|
-
${CMAKE_CURRENT_SOURCE_DIR}/../server
|
|
85
|
-
${CMAKE_CURRENT_SOURCE_DIR}/../../vendor)
|
|
86
|
-
diff --git a/tools/kokoro/src/kokoro.cpp b/tools/kokoro/src/kokoro.cpp
|
|
87
|
-
index 93c15594e..a6d7874ce 100644
|
|
88
|
-
--- a/tools/kokoro/src/kokoro.cpp
|
|
89
|
-
+++ b/tools/kokoro/src/kokoro.cpp
|
|
90
|
-
@@ -41,6 +41,7 @@
|
|
91
|
-
#include <atomic>
|
|
92
|
-
#include <cmath>
|
|
93
|
-
#include <cstdio>
|
|
94
|
-
+#include <cstdlib>
|
|
95
|
-
#include <cstring>
|
|
96
|
-
#include <fstream>
|
|
97
|
-
#include <memory>
|
|
98
|
-
@@ -536,7 +537,8 @@ kokoro_status kokoro_synthesize(
|
|
99
|
-
// Build a tiny graph: mag_phase_tensor → ggml_istft → pcm_tensor.
|
|
100
|
-
// mag_phase_tensor shape: ne[0]=n_frames (T), ne[1]=F, ne[2]=2.
|
|
101
|
-
bool used_native_op = false;
|
|
102
|
-
- {
|
|
103
|
-
+ const char * native_istft_env = std::getenv("ELIZA_KOKORO_NATIVE_ISTFT");
|
|
104
|
-
+ if (native_istft_env && std::strcmp(native_istft_env, "1") == 0) {
|
|
105
|
-
ggml_init_params ip = {
|
|
106
|
-
/*.mem_size =*/ 4 * 1024 * 1024,
|
|
107
|
-
/*.mem_buffer =*/ nullptr,
|
|
108
|
-
diff --git a/tools/omnivoice/CMakeLists.txt b/tools/omnivoice/CMakeLists.txt
|
|
109
|
-
index 6e2da9826..bf1189986 100644
|
|
110
|
-
--- a/tools/omnivoice/CMakeLists.txt
|
|
111
|
-
+++ b/tools/omnivoice/CMakeLists.txt
|
|
112
|
-
@@ -149,9 +149,17 @@ endif()
|
|
113
|
-
# suffix on Linux to keep dlopen() happy on the runtime side). Default
|
|
114
|
-
# visibility is `default` (not hidden) because every `eliza_inference_*`
|
|
115
|
-
# entry the JS loader needs is reachable through dlsym.
|
|
116
|
-
-add_library(elizainference SHARED
|
|
117
|
-
- ${OMNIVOICE_CORE_SOURCES}
|
|
118
|
-
- ${OMNIVOICE_FFI_SOURCES})
|
|
119
|
-
+option(ELIZA_OMNIVOICE_STATIC_FFI "Build libelizainference as a static library for iOS XCFramework packaging" OFF)
|
|
120
|
-
+if(ELIZA_OMNIVOICE_STATIC_FFI)
|
|
121
|
-
+ add_library(elizainference STATIC
|
|
122
|
-
+ ${OMNIVOICE_CORE_SOURCES}
|
|
123
|
-
+ ${OMNIVOICE_FFI_SOURCES})
|
|
124
|
-
+ target_compile_definitions(elizainference PUBLIC OMNIVOICE_STATIC)
|
|
125
|
-
+else()
|
|
126
|
-
+ add_library(elizainference SHARED
|
|
127
|
-
+ ${OMNIVOICE_CORE_SOURCES}
|
|
128
|
-
+ ${OMNIVOICE_FFI_SOURCES})
|
|
129
|
-
+endif()
|
|
130
|
-
target_compile_features(elizainference PUBLIC cxx_std_17)
|
|
131
|
-
target_compile_definitions(elizainference
|
|
132
|
-
PRIVATE OMNIVOICE_BUILD ${OMNIVOICE_COMPILE_DEFINITIONS})
|
|
133
|
-
@@ -171,13 +179,19 @@ target_link_libraries(elizainference PUBLIC llama)
|
|
134
|
-
if(TARGET mtmd)
|
|
135
|
-
target_link_libraries(elizainference PUBLIC mtmd)
|
|
136
|
-
endif()
|
|
137
|
-
+if(TARGET kokoro_lib)
|
|
138
|
-
+ target_link_libraries(elizainference PUBLIC kokoro_lib)
|
|
139
|
-
+ target_include_directories(elizainference PRIVATE
|
|
140
|
-
+ ${CMAKE_CURRENT_SOURCE_DIR}/../kokoro/include)
|
|
141
|
-
+ target_compile_definitions(elizainference PRIVATE LLAMA_BUILD_KOKORO)
|
|
142
|
-
+endif()
|
|
143
|
-
set_target_properties(elizainference PROPERTIES
|
|
144
|
-
OUTPUT_NAME elizainference
|
|
145
|
-
POSITION_INDEPENDENT_CODE ON)
|
|
146
|
-
# Apple re-exports llama symbols so the fused .dylib carries everything
|
|
147
|
-
# JS will dlopen() without a second handle. Mirrors the legacy fork-root
|
|
148
|
-
# graft block.
|
|
149
|
-
-if(APPLE)
|
|
150
|
-
+if(APPLE AND NOT ELIZA_OMNIVOICE_STATIC_FFI)
|
|
151
|
-
target_link_options(elizainference PRIVATE
|
|
152
|
-
"LINKER:-reexport_library,$<TARGET_FILE:llama>")
|
|
153
|
-
endif()
|
|
154
|
-
diff --git a/tools/omnivoice/src/eliza-inference-ffi.cpp b/tools/omnivoice/src/eliza-inference-ffi.cpp
|
|
155
|
-
index 1c40c1e66..44cb145f4 100644
|
|
156
|
-
--- a/tools/omnivoice/src/eliza-inference-ffi.cpp
|
|
157
|
-
+++ b/tools/omnivoice/src/eliza-inference-ffi.cpp
|
|
158
|
-
@@ -14,6 +14,9 @@
|
|
159
|
-
// resolve `eliza_inference_*` symbols from this object.
|
|
160
|
-
|
|
161
|
-
#include "eliza-inference-ffi.h"
|
|
162
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
163
|
-
+#include "kokoro.h"
|
|
164
|
-
+#endif
|
|
165
|
-
#include "omnivoice.h"
|
|
166
|
-
#include "llama.h"
|
|
167
|
-
#include "mtmd.h"
|
|
168
|
-
@@ -66,6 +69,14 @@ struct EliInferenceContext {
|
|
169
|
-
std::string bundle_dir;
|
|
170
|
-
std::string tts_model_path;
|
|
171
|
-
std::string codec_model_path;
|
|
172
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
173
|
-
+ std::string kokoro_model_path;
|
|
174
|
-
+ std::string kokoro_voice_path;
|
|
175
|
-
+ eliza_kokoro::kokoro_model_ptr kokoro_model;
|
|
176
|
-
+ eliza_kokoro::kokoro_voice_preset kokoro_voice;
|
|
177
|
-
+ bool kokoro_voice_loaded = false;
|
|
178
|
-
+ bool tts_uses_kokoro = false;
|
|
179
|
-
+#endif
|
|
180
|
-
std::string asr_model_path;
|
|
181
|
-
std::string asr_mmproj_path;
|
|
182
|
-
ov_context * ov = nullptr;
|
|
183
|
-
@@ -339,17 +350,89 @@ static bool eliza_pick_voice_files(
|
|
184
|
-
std::vector<std::string> codec = eliza_find_ggufs(bundle_dir / "codec");
|
|
185
|
-
if (tts.empty()) tts = eliza_find_ggufs(bundle_dir / "voice");
|
|
186
|
-
if (tts.empty()) return false;
|
|
187
|
-
- tts_model = tts[0];
|
|
188
|
-
- if (!codec.empty()) {
|
|
189
|
-
- codec_model = codec[0];
|
|
190
|
-
- } else if (tts.size() > 1) {
|
|
191
|
-
- codec_model = tts[1];
|
|
192
|
-
- } else {
|
|
193
|
-
- codec_model = tts_model;
|
|
194
|
-
+
|
|
195
|
-
+ std::vector<std::string> tts_candidates;
|
|
196
|
-
+ std::vector<std::string> codec_candidates = codec;
|
|
197
|
-
+ for (const std::string & path : tts) {
|
|
198
|
-
+ const std::string lower = eliza_lower_ascii(std::filesystem::path(path).filename().string());
|
|
199
|
-
+ const bool is_omnivoice = lower.find("omnivoice") != std::string::npos;
|
|
200
|
-
+ const bool is_codec = lower.find("tokenizer") != std::string::npos || lower.find("codec") != std::string::npos;
|
|
201
|
-
+ const bool is_other_voice = lower.find("kokoro") != std::string::npos;
|
|
202
|
-
+ if (is_omnivoice && !is_codec && !is_other_voice) {
|
|
203
|
-
+ tts_candidates.push_back(path);
|
|
204
|
-
+ }
|
|
205
|
-
+ if (is_omnivoice && is_codec) {
|
|
206
|
-
+ codec_candidates.push_back(path);
|
|
207
|
-
+ }
|
|
208
|
-
}
|
|
209
|
-
+
|
|
210
|
-
+ if (tts_candidates.empty() || codec_candidates.empty()) {
|
|
211
|
-
+ return false;
|
|
212
|
-
+ }
|
|
213
|
-
+
|
|
214
|
-
+ tts_model = tts_candidates[0];
|
|
215
|
-
+ codec_model = codec_candidates[0];
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
+static bool eliza_path_is_file(const std::filesystem::path & path) {
|
|
220
|
-
+ std::error_code ec;
|
|
221
|
-
+ return std::filesystem::is_regular_file(path, ec);
|
|
222
|
-
+}
|
|
223
|
-
+
|
|
224
|
-
+static bool eliza_pick_kokoro_files(
|
|
225
|
-
+ const std::filesystem::path & bundle_dir,
|
|
226
|
-
+ std::string & model_path,
|
|
227
|
-
+ std::string & voice_path) {
|
|
228
|
-
+ const auto kokoro_dir = bundle_dir / "tts" / "kokoro";
|
|
229
|
-
+ const auto canonical_model = kokoro_dir / "kokoro-82m-v1_0-Q4_K_M.gguf";
|
|
230
|
-
+ if (eliza_path_is_file(canonical_model)) {
|
|
231
|
-
+ model_path = canonical_model.string();
|
|
232
|
-
+ } else {
|
|
233
|
-
+ std::vector<std::string> candidates = eliza_find_ggufs(kokoro_dir);
|
|
234
|
-
+ if (candidates.empty()) return false;
|
|
235
|
-
+ model_path = candidates[0];
|
|
236
|
-
+ }
|
|
237
|
-
+
|
|
238
|
-
+ const auto voices_dir = kokoro_dir / "voices";
|
|
239
|
-
+ const std::vector<std::filesystem::path> preferred = {
|
|
240
|
-
+ voices_dir / "af_bella.bin",
|
|
241
|
-
+ voices_dir / "af_sarah.bin",
|
|
242
|
-
+ voices_dir / "am_adam.bin",
|
|
243
|
-
+ };
|
|
244
|
-
+ for (const auto & candidate : preferred) {
|
|
245
|
-
+ if (eliza_path_is_file(candidate)) {
|
|
246
|
-
+ voice_path = candidate.string();
|
|
247
|
-
+ return true;
|
|
248
|
-
+ }
|
|
249
|
-
+ }
|
|
250
|
-
+
|
|
251
|
-
+ std::error_code ec;
|
|
252
|
-
+ if (!std::filesystem::is_directory(voices_dir, ec)) return false;
|
|
253
|
-
+ std::vector<std::string> voices;
|
|
254
|
-
+ for (const auto & entry : std::filesystem::directory_iterator(voices_dir, ec)) {
|
|
255
|
-
+ if (ec) break;
|
|
256
|
-
+ const auto path = entry.path();
|
|
257
|
-
+ if (path.extension() == ".bin") voices.push_back(path.string());
|
|
258
|
-
+ }
|
|
259
|
-
+ std::sort(voices.begin(), voices.end());
|
|
260
|
-
+ if (voices.empty()) return false;
|
|
261
|
-
+ voice_path = voices[0];
|
|
262
|
-
+ return true;
|
|
263
|
-
+}
|
|
264
|
-
+
|
|
265
|
-
+static bool eliza_tts_prefers_kokoro(const std::filesystem::path & bundle_dir) {
|
|
266
|
-
+ const char * raw = std::getenv("ELIZA_TTS_BACKEND");
|
|
267
|
-
+ if (raw && raw[0] != '\0') {
|
|
268
|
-
+ const std::string value = eliza_lower_ascii(raw);
|
|
269
|
-
+ if (value == "omnivoice" || value == "legacy-omnivoice") return false;
|
|
270
|
-
+ return value == "kokoro" || value == "mobile-kokoro";
|
|
271
|
-
+ }
|
|
272
|
-
+ std::string model_path;
|
|
273
|
-
+ std::string voice_path;
|
|
274
|
-
+ return eliza_pick_kokoro_files(bundle_dir, model_path, voice_path);
|
|
275
|
-
+}
|
|
276
|
-
+
|
|
277
|
-
static bool eliza_pick_asr_files(
|
|
278
|
-
const std::filesystem::path & bundle_dir,
|
|
279
|
-
std::string & asr_model,
|
|
280
|
-
@@ -682,12 +765,61 @@ static void eliza_free_asr(EliInferenceContext * ctx) {
|
|
281
|
-
ctx->asr_sample_rate = 0;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
+static int eliza_load_kokoro_tts(EliInferenceContext * ctx, char ** out_error) {
|
|
285
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
286
|
-
+ if (!ctx) {
|
|
287
|
-
+ eliza_set_error(out_error, "[libelizainference] load_kokoro_tts: ctx is NULL");
|
|
288
|
-
+ return ELIZA_ERR_INVALID_ARG;
|
|
289
|
-
+ }
|
|
290
|
-
+ if (ctx->kokoro_model) return ELIZA_OK;
|
|
291
|
-
+ if (ctx->kokoro_model_path.empty()) {
|
|
292
|
-
+ if (!eliza_pick_kokoro_files(std::filesystem::path(ctx->bundle_dir), ctx->kokoro_model_path, ctx->kokoro_voice_path)) {
|
|
293
|
-
+ eliza_set_error(out_error, std::string("[libelizainference] no Kokoro TTS assets found under ") + (std::filesystem::path(ctx->bundle_dir) / "tts" / "kokoro").string());
|
|
294
|
-
+ return ELIZA_ERR_BUNDLE_INVALID;
|
|
295
|
-
+ }
|
|
296
|
-
+ }
|
|
297
|
-
+
|
|
298
|
-
+ std::string err;
|
|
299
|
-
+ auto model = eliza_kokoro::kokoro_load_model(ctx->kokoro_model_path, err);
|
|
300
|
-
+ if (!model) {
|
|
301
|
-
+ eliza_set_error(out_error, "[libelizainference] kokoro_load_model failed: " + err + " model=" + ctx->kokoro_model_path);
|
|
302
|
-
+ return ELIZA_ERR_FFI_FAULT;
|
|
303
|
-
+ }
|
|
304
|
-
+ const eliza_kokoro::kokoro_hparams * hparams = eliza_kokoro::kokoro_get_hparams(model.get());
|
|
305
|
-
+ const int style_dim = hparams ? hparams->style_dim : 256;
|
|
306
|
-
+ eliza_kokoro::kokoro_voice_preset voice;
|
|
307
|
-
+ err.clear();
|
|
308
|
-
+ eliza_kokoro::kokoro_status voice_rc =
|
|
309
|
-
+ eliza_kokoro::kokoro_load_voice_preset(ctx->kokoro_voice_path, style_dim, voice, err);
|
|
310
|
-
+ if (voice_rc != eliza_kokoro::KOKORO_OK) {
|
|
311
|
-
+ eliza_set_error(out_error, std::string("[libelizainference] kokoro_load_voice_preset failed: ") +
|
|
312
|
-
+ eliza_kokoro::kokoro_status_str(voice_rc) + ": " + err + " voice=" + ctx->kokoro_voice_path);
|
|
313
|
-
+ return ELIZA_ERR_FFI_FAULT;
|
|
314
|
-
+ }
|
|
315
|
-
+ ctx->kokoro_model = std::move(model);
|
|
316
|
-
+ ctx->kokoro_voice = std::move(voice);
|
|
317
|
-
+ ctx->kokoro_voice_loaded = true;
|
|
318
|
-
+ ctx->tts_uses_kokoro = true;
|
|
319
|
-
+ return ELIZA_OK;
|
|
320
|
-
+#else
|
|
321
|
-
+ (void) ctx;
|
|
322
|
-
+ eliza_set_error(out_error, "[libelizainference] Kokoro TTS requested but this slice was built without LLAMA_BUILD_KOKORO");
|
|
323
|
-
+ return ELIZA_ERR_FFI_FAULT;
|
|
324
|
-
+#endif
|
|
325
|
-
+}
|
|
326
|
-
+
|
|
327
|
-
static int eliza_load_tts(EliInferenceContext * ctx, char ** out_error) {
|
|
328
|
-
if (!ctx) {
|
|
329
|
-
eliza_set_error(out_error, "[libelizainference] load_tts: ctx is NULL");
|
|
330
|
-
return ELIZA_ERR_INVALID_ARG;
|
|
331
|
-
}
|
|
332
|
-
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
333
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
334
|
-
+ if (ctx->tts_uses_kokoro && ctx->kokoro_model) return ELIZA_OK;
|
|
335
|
-
+#endif
|
|
336
|
-
+ if (eliza_tts_prefers_kokoro(std::filesystem::path(ctx->bundle_dir))) {
|
|
337
|
-
+ return eliza_load_kokoro_tts(ctx, out_error);
|
|
338
|
-
+ }
|
|
339
|
-
if (ctx->ov) return ELIZA_OK;
|
|
340
|
-
if (ctx->tts_model_path.empty()) {
|
|
341
|
-
if (!eliza_pick_voice_files(std::filesystem::path(ctx->bundle_dir), ctx->tts_model_path, ctx->codec_model_path)) {
|
|
342
|
-
@@ -705,6 +837,10 @@ static int eliza_load_tts(EliInferenceContext * ctx, char ** out_error) {
|
|
343
|
-
if (!ctx->ov) {
|
|
344
|
-
std::string msg = "[libelizainference] ov_init failed: ";
|
|
345
|
-
msg += ov_last_error();
|
|
346
|
-
+ msg += " tts_model=";
|
|
347
|
-
+ msg += ctx->tts_model_path;
|
|
348
|
-
+ msg += " codec_model=";
|
|
349
|
-
+ msg += ctx->codec_model_path;
|
|
350
|
-
eliza_set_error(out_error, msg);
|
|
351
|
-
return ELIZA_ERR_FFI_FAULT;
|
|
352
|
-
}
|
|
353
|
-
@@ -844,6 +980,12 @@ void eliza_inference_destroy(EliInferenceContext * ctx) {
|
|
354
|
-
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
355
|
-
ov_free(ctx->ov);
|
|
356
|
-
ctx->ov = nullptr;
|
|
357
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
358
|
-
+ ctx->kokoro_model.reset();
|
|
359
|
-
+ ctx->kokoro_voice = eliza_kokoro::kokoro_voice_preset();
|
|
360
|
-
+ ctx->kokoro_voice_loaded = false;
|
|
361
|
-
+ ctx->tts_uses_kokoro = false;
|
|
362
|
-
+#endif
|
|
363
|
-
}
|
|
364
|
-
{
|
|
365
|
-
std::lock_guard<std::mutex> lock(ctx->asr_mutex);
|
|
366
|
-
@@ -891,6 +1033,12 @@ int eliza_inference_mmap_evict(
|
|
367
|
-
ov_free(ctx->ov);
|
|
368
|
-
ctx->ov = nullptr;
|
|
369
|
-
}
|
|
370
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
371
|
-
+ ctx->kokoro_model.reset();
|
|
372
|
-
+ ctx->kokoro_voice = eliza_kokoro::kokoro_voice_preset();
|
|
373
|
-
+ ctx->kokoro_voice_loaded = false;
|
|
374
|
-
+ ctx->tts_uses_kokoro = false;
|
|
375
|
-
+#endif
|
|
376
|
-
}
|
|
377
|
-
if (std::strcmp(region_name, "asr") == 0) {
|
|
378
|
-
std::lock_guard<std::mutex> lock(ctx->asr_mutex);
|
|
379
|
-
@@ -917,6 +1065,31 @@ int eliza_inference_tts_synthesize(
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
std::lock_guard<std::mutex> lock(ctx->tts_mutex);
|
|
383
|
-
+#if defined(LLAMA_BUILD_KOKORO)
|
|
384
|
-
+ if (ctx->tts_uses_kokoro) {
|
|
385
|
-
+ if (!ctx->kokoro_model || !ctx->kokoro_voice_loaded) {
|
|
386
|
-
+ eliza_set_error(out_error, "[libelizainference] tts_synthesize: Kokoro region is not acquired; call mmap_acquire(\"tts\") after arming voice");
|
|
387
|
-
+ return ELIZA_ERR_INVALID_ARG;
|
|
388
|
-
+ }
|
|
389
|
-
+ std::string text_owned(text, text_len);
|
|
390
|
-
+ eliza_kokoro::kokoro_audio audio;
|
|
391
|
-
+ std::string err;
|
|
392
|
-
+ const eliza_kokoro::kokoro_status rc =
|
|
393
|
-
+ eliza_kokoro::kokoro_synthesize(ctx->kokoro_model.get(), ctx->kokoro_voice, text_owned, 1.0f, audio, err);
|
|
394
|
-
+ if (rc != eliza_kokoro::KOKORO_OK) {
|
|
395
|
-
+ eliza_set_error(out_error, std::string("[libelizainference] kokoro_synthesize failed: ") +
|
|
396
|
-
+ eliza_kokoro::kokoro_status_str(rc) + ": " + err);
|
|
397
|
-
+ return ELIZA_ERR_FFI_FAULT;
|
|
398
|
-
+ }
|
|
399
|
-
+ if (audio.samples.size() > max_samples) {
|
|
400
|
-
+ eliza_set_error(out_error, "[libelizainference] output buffer too small; required samples=" +
|
|
401
|
-
+ std::to_string(audio.samples.size()));
|
|
402
|
-
+ return ELIZA_ERR_INVALID_ARG;
|
|
403
|
-
+ }
|
|
404
|
-
+ std::memcpy(out_pcm, audio.samples.data(), audio.samples.size() * sizeof(float));
|
|
405
|
-
+ return (int) audio.samples.size();
|
|
406
|
-
+ }
|
|
407
|
-
+#endif
|
|
408
|
-
if (!ctx->ov) {
|
|
409
|
-
eliza_set_error(out_error, "[libelizainference] tts_synthesize: TTS region is not acquired; call mmap_acquire(\"tts\") after arming voice");
|
|
410
|
-
return ELIZA_ERR_INVALID_ARG;
|
|
411
|
-
diff --git a/tools/omnivoice/src/weight-ctx.h b/tools/omnivoice/src/weight-ctx.h
|
|
412
|
-
index e43f57388..ec88229d6 100644
|
|
413
|
-
--- a/tools/omnivoice/src/weight-ctx.h
|
|
414
|
-
+++ b/tools/omnivoice/src/weight-ctx.h
|
|
415
|
-
@@ -11,10 +11,13 @@
|
|
416
|
-
// wctx_alloc(&wctx, backend);
|
|
417
|
-
|
|
418
|
-
#include "ggml-backend.h"
|
|
419
|
-
+#include "ggml-alloc.h"
|
|
420
|
-
#include "ggml.h"
|
|
421
|
-
|
|
422
|
-
+#include <cerrno>
|
|
423
|
-
#include <cstddef>
|
|
424
|
-
#include <cstdio>
|
|
425
|
-
+#include <cstdlib>
|
|
426
|
-
#include <memory>
|
|
427
|
-
#include <vector>
|
|
428
|
-
|
|
429
|
-
@@ -51,18 +54,51 @@ static void wctx_init(WeightCtx * wctx, int n_tensors) {
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
static bool wctx_alloc(WeightCtx * wctx, ggml_backend_t backend) {
|
|
433
|
-
+ ggml_backend_buffer_type_t buft = ggml_backend_get_default_buffer_type(backend);
|
|
434
|
-
+ const size_t estimate = ggml_backend_alloc_ctx_tensors_from_buft_size(wctx->ctx, buft);
|
|
435
|
-
+ const double estimate_mb = (double) estimate / (1024.0 * 1024.0);
|
|
436
|
-
+ const char * budget_env = getenv("ELIZA_TTS_MAX_BACKEND_ALLOC_MB");
|
|
437
|
-
+ double budget_mb = 0.0;
|
|
438
|
-
+ if (budget_env && budget_env[0] != '\0') {
|
|
439
|
-
+ char * end = NULL;
|
|
440
|
-
+ errno = 0;
|
|
441
|
-
+ const double parsed = strtod(budget_env, &end);
|
|
442
|
-
+ if (errno == 0 && end != budget_env && parsed > 0.0) {
|
|
443
|
-
+ budget_mb = parsed;
|
|
444
|
-
+ }
|
|
445
|
-
+ }
|
|
446
|
-
+ fprintf(stderr,
|
|
447
|
-
+ "[WeightCtx] alloc preflight buft=%s tensors=%zu estimate=%.1f MB budget=%.1f MB\n",
|
|
448
|
-
+ ggml_backend_buft_name(buft),
|
|
449
|
-
+ wctx->pending.size(),
|
|
450
|
-
+ estimate_mb,
|
|
451
|
-
+ budget_mb);
|
|
452
|
-
+ if (budget_mb > 0.0 && estimate_mb > budget_mb) {
|
|
453
|
-
+ fprintf(stderr,
|
|
454
|
-
+ "[WeightCtx] FATAL: backend allocation estimate %.1f MB exceeds budget %.1f MB\n",
|
|
455
|
-
+ estimate_mb,
|
|
456
|
-
+ budget_mb);
|
|
457
|
-
+ return false;
|
|
458
|
-
+ }
|
|
459
|
-
wctx->buffer = ggml_backend_alloc_ctx_tensors(wctx->ctx, backend);
|
|
460
|
-
if (!wctx->buffer) {
|
|
461
|
-
fprintf(stderr, "[WeightCtx] FATAL: failed to allocate backend buffer\n");
|
|
462
|
-
return false;
|
|
463
|
-
}
|
|
464
|
-
+ fprintf(stderr, "[WeightCtx] alloc buffer ok\n");
|
|
465
|
-
// Mark as weight buffer so ggml_backend_sched assigns ops to the correct
|
|
466
|
-
// backend based on weight location (avoids fallback through expansion).
|
|
467
|
-
ggml_backend_buffer_set_usage(wctx->buffer, GGML_BACKEND_BUFFER_USAGE_WEIGHTS);
|
|
468
|
-
size_t total = 0;
|
|
469
|
-
+ size_t index = 0;
|
|
470
|
-
for (auto & pc : wctx->pending) {
|
|
471
|
-
+ if (index == 0 || index % 32 == 0 || index + 1 == wctx->pending.size()) {
|
|
472
|
-
+ fprintf(stderr, "[WeightCtx] copy tensor %zu/%zu bytes=%zu\n", index + 1, wctx->pending.size(),
|
|
473
|
-
+ pc.nbytes);
|
|
474
|
-
+ }
|
|
475
|
-
ggml_backend_tensor_set(pc.tensor, pc.src, pc.offset, pc.nbytes);
|
|
476
|
-
total += pc.nbytes;
|
|
477
|
-
+ index += 1;
|
|
478
|
-
}
|
|
479
|
-
fprintf(stderr, "[WeightCtx] Loaded %zu tensors, %.1f MB into backend\n", wctx->pending.size(),
|
|
480
|
-
(float) total / (1024 * 1024));
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { describe, expect, it } from "vitest";
|
|
5
|
-
|
|
6
|
-
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const repoRoot = path.resolve(scriptDir, "..", "..", "..");
|
|
8
|
-
|
|
9
|
-
function readRepoFile(relativePath: string) {
|
|
10
|
-
return fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
describe("release workflow drift", () => {
|
|
14
|
-
it("keeps release readiness wired to generated metadata and release:check", () => {
|
|
15
|
-
const workflow = readRepoFile(".github/workflows/release-electrobun.yml");
|
|
16
|
-
|
|
17
|
-
expect(workflow).toContain("name: Release readiness checks");
|
|
18
|
-
expect(workflow).toContain(
|
|
19
|
-
"ELIZA_RELEASE_TAG: $" + "{{ needs.prepare.outputs.tag }}",
|
|
20
|
-
);
|
|
21
|
-
expect(workflow).toContain('ELIZA_VALIDATE_CDN: "1"');
|
|
22
|
-
expect(workflow).toContain(
|
|
23
|
-
"node packages/app-core/scripts/write-homepage-release-data.mjs",
|
|
24
|
-
);
|
|
25
|
-
expect(workflow).toContain(
|
|
26
|
-
"node packages/app-core/scripts/generate-static-asset-manifest.mjs",
|
|
27
|
-
);
|
|
28
|
-
expect(workflow).toContain("bun run release:check");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("keeps release contract validation on Electrobun pull requests", () => {
|
|
32
|
-
const workflow = readRepoFile(
|
|
33
|
-
".github/workflows/test-electrobun-release.yml",
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
expect(workflow).toContain("bun run test:release:contract");
|
|
37
|
-
expect(workflow).not.toContain(
|
|
38
|
-
"uses: ./.github/workflows/release-electrobun.yml",
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("keeps release-only mobile builders manually dispatched", () => {
|
|
43
|
-
const androidWorkflow = readRepoFile(".github/workflows/build-android.yml");
|
|
44
|
-
const iosWorkflow = readRepoFile(".github/workflows/build-ios.yml");
|
|
45
|
-
|
|
46
|
-
expect(androidWorkflow).toContain("workflow_dispatch:");
|
|
47
|
-
expect(iosWorkflow).toContain("workflow_dispatch:");
|
|
48
|
-
expect(androidWorkflow).not.toContain("types: [created]");
|
|
49
|
-
expect(iosWorkflow).not.toContain("types: [created]");
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("keeps Android Play release using the cloud Android build", () => {
|
|
53
|
-
const workflow = readRepoFile(".github/workflows/android-release.yml");
|
|
54
|
-
|
|
55
|
-
expect(workflow).toContain("bun run build:android:cloud");
|
|
56
|
-
});
|
|
57
|
-
});
|
package/test/helpers/i18n.ts
DELETED
package/test/helpers/loopback.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import net from "node:net";
|
|
2
|
-
|
|
3
|
-
let loopbackAvailabilityPromise: Promise<boolean> | null = null;
|
|
4
|
-
|
|
5
|
-
export function canBindLoopback(): Promise<boolean> {
|
|
6
|
-
if (loopbackAvailabilityPromise) {
|
|
7
|
-
return loopbackAvailabilityPromise;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
loopbackAvailabilityPromise = new Promise((resolve) => {
|
|
11
|
-
const server = net.createServer();
|
|
12
|
-
let settled = false;
|
|
13
|
-
|
|
14
|
-
const finish = (value: boolean) => {
|
|
15
|
-
if (settled) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
settled = true;
|
|
19
|
-
server.removeAllListeners();
|
|
20
|
-
resolve(value);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
server.once("error", () => {
|
|
24
|
-
finish(false);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
server.listen(0, "127.0.0.1", () => {
|
|
28
|
-
server.close(() => finish(true));
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
return loopbackAvailabilityPromise;
|
|
33
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/** Small `react-test-renderer` helpers shared by component tests. */
|
|
2
|
-
|
|
3
|
-
import type TestRenderer from "react-test-renderer";
|
|
4
|
-
import { act } from "react-test-renderer";
|
|
5
|
-
|
|
6
|
-
/** Returns the direct string children for a rendered node. */
|
|
7
|
-
export function text(node: TestRenderer.ReactTestInstance): string {
|
|
8
|
-
return node.children
|
|
9
|
-
.map((child) => (typeof child === "string" ? child : ""))
|
|
10
|
-
.join("")
|
|
11
|
-
.trim();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** Returns the recursive string content for a rendered node. */
|
|
15
|
-
export function textOf(node: TestRenderer.ReactTestInstance): string {
|
|
16
|
-
return node.children
|
|
17
|
-
.map((child) => (typeof child === "string" ? child : textOf(child)))
|
|
18
|
-
.join("");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Finds a button by label. */
|
|
22
|
-
export function findButtonByText(
|
|
23
|
-
root: TestRenderer.ReactTestInstance,
|
|
24
|
-
label: string,
|
|
25
|
-
): TestRenderer.ReactTestInstance {
|
|
26
|
-
const matches = root.findAll(
|
|
27
|
-
(node) => node.type === "button" && text(node) === label,
|
|
28
|
-
);
|
|
29
|
-
if (!matches[0]) {
|
|
30
|
-
throw new Error(`Button "${label}" not found`);
|
|
31
|
-
}
|
|
32
|
-
return matches[0];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** Flushes pending React effects. */
|
|
36
|
-
export async function flush(): Promise<void> {
|
|
37
|
-
await act(async () => {
|
|
38
|
-
await Promise.resolve();
|
|
39
|
-
});
|
|
40
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/** Env-based gates for live and integration tests. */
|
|
2
|
-
|
|
3
|
-
import { describe, it, test } from "vitest";
|
|
4
|
-
import { isLiveTestEnabled, selectLiveProvider } from "./live-provider.ts";
|
|
5
|
-
|
|
6
|
-
/** Skips the current suite when required env vars are missing. */
|
|
7
|
-
export function skipWithout(envVarOrVars: string | string[]): void {
|
|
8
|
-
const vars = Array.isArray(envVarOrVars) ? envVarOrVars : [envVarOrVars];
|
|
9
|
-
const missing = vars.filter((v) => !process.env[v]?.trim());
|
|
10
|
-
if (missing.length > 0) {
|
|
11
|
-
test.skip(`Missing env: ${missing.join(", ")}`);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** Returns a `describe.skipIf` wrapper for env-based gates. */
|
|
16
|
-
export function describeWithout(envVarOrVars: string | string[]) {
|
|
17
|
-
const vars = Array.isArray(envVarOrVars) ? envVarOrVars : [envVarOrVars];
|
|
18
|
-
const missing = vars.some((v) => !process.env[v]?.trim());
|
|
19
|
-
return describe.skipIf(missing);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** Returns an `it.skipIf` wrapper for env-based gates. */
|
|
23
|
-
export function itWithout(envVarOrVars: string | string[]) {
|
|
24
|
-
const vars = Array.isArray(envVarOrVars) ? envVarOrVars : [envVarOrVars];
|
|
25
|
-
const missing = vars.some((v) => !process.env[v]?.trim());
|
|
26
|
-
return it.skipIf(missing);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Skips unless the live-test gate is enabled. */
|
|
30
|
-
export function skipWithoutLive(): void {
|
|
31
|
-
if (!isLiveTestEnabled()) {
|
|
32
|
-
test.skip("ELIZA_LIVE_TEST=1 not set");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** `describe.skipIf` wrapper for the live-test gate. */
|
|
37
|
-
export const describeLive = describe.skipIf(!isLiveTestEnabled());
|
|
38
|
-
|
|
39
|
-
/** `it.skipIf` wrapper for the live-test gate. */
|
|
40
|
-
export const itLive = it.skipIf(!isLiveTestEnabled());
|
|
41
|
-
|
|
42
|
-
/** Skips unless at least one LLM provider API key is available. */
|
|
43
|
-
export function skipWithoutAnyLLM(): void {
|
|
44
|
-
if (!selectLiveProvider()) {
|
|
45
|
-
test.skip("No LLM provider API key available");
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** `describe.skipIf` wrapper for LLM availability. */
|
|
50
|
-
export const describeLLM = describe.skipIf(!selectLiveProvider());
|
|
51
|
-
|
|
52
|
-
/** `it.skipIf` wrapper for LLM availability. */
|
|
53
|
-
export const itLLM = it.skipIf(!selectLiveProvider());
|