@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
|
@@ -57,6 +57,10 @@ const ALLOW_REGISTRY_FETCH =
|
|
|
57
57
|
process.env.ELIZA_RUNTIME_COPY_ALLOW_REGISTRY_FETCH === "1";
|
|
58
58
|
const DEP_SKIP = new Set(["typescript", "@types/node"]);
|
|
59
59
|
const ALWAYS_HOISTED_PACKAGES = new Set([
|
|
60
|
+
// @brighter/storage-adapter-s3 accepts broad S3 client ranges; reuse the
|
|
61
|
+
// runtime root copy instead of nesting a private AWS SDK tree that exceeds
|
|
62
|
+
// Electrobun's tar-safe path limits.
|
|
63
|
+
"@aws-sdk/client-s3",
|
|
60
64
|
"@elizaos/core",
|
|
61
65
|
"commander",
|
|
62
66
|
"pg",
|
|
@@ -159,6 +163,13 @@ const registryPackageIndex = new Map<string, ResolvedPackage>();
|
|
|
159
163
|
const trackedPackageIndex = new Map<string, ResolvedPackage>();
|
|
160
164
|
const workspacePackageIndex = new Map<string, ResolvedPackage[]>();
|
|
161
165
|
let workspacePackageIndexBuilt = false;
|
|
166
|
+
let activeRuntimeCopyTargetNodeModules: string | null = null;
|
|
167
|
+
|
|
168
|
+
function resolveBunCommand(): string {
|
|
169
|
+
return path.basename(process.execPath).startsWith("bun")
|
|
170
|
+
? process.execPath
|
|
171
|
+
: (process.env.BUN ?? "bun");
|
|
172
|
+
}
|
|
162
173
|
|
|
163
174
|
function isRequiredRuntimeDocDirectory(entryPath: string): boolean {
|
|
164
175
|
const normalizedPath = entryPath.split(path.sep).join("/");
|
|
@@ -371,6 +382,14 @@ function packagePath(name: string, baseDir: string): string {
|
|
|
371
382
|
return path.join(baseDir, name);
|
|
372
383
|
}
|
|
373
384
|
|
|
385
|
+
function isPathInsideOrEqual(candidate: string, parent: string): boolean {
|
|
386
|
+
const relative = path.relative(parent, candidate);
|
|
387
|
+
return (
|
|
388
|
+
relative === "" ||
|
|
389
|
+
(!relative.startsWith("..") && !path.isAbsolute(relative))
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
374
393
|
function addWorkspacePackageCandidate(
|
|
375
394
|
name: string,
|
|
376
395
|
resolved: ResolvedPackage,
|
|
@@ -962,6 +981,16 @@ function copyPackageDirSync(
|
|
|
962
981
|
});
|
|
963
982
|
return;
|
|
964
983
|
} catch (error) {
|
|
984
|
+
if (
|
|
985
|
+
error &&
|
|
986
|
+
typeof error === "object" &&
|
|
987
|
+
(error as { code?: string }).code === "ENAMETOOLONG"
|
|
988
|
+
) {
|
|
989
|
+
throw new Error(
|
|
990
|
+
`[runtime-copy] path too long while copying ${name} from ${sourceDir} to ${copyDest}`,
|
|
991
|
+
{ cause: error },
|
|
992
|
+
);
|
|
993
|
+
}
|
|
965
994
|
if (!isEnoentError(error) || attempt === maxAttempts - 1) {
|
|
966
995
|
throw error;
|
|
967
996
|
}
|
|
@@ -1848,6 +1877,12 @@ function collectInstalledPackageDirs(
|
|
|
1848
1877
|
|
|
1849
1878
|
const addCandidate = (candidate: string): void => {
|
|
1850
1879
|
if (!fs.existsSync(candidate) || seen.has(candidate)) return;
|
|
1880
|
+
if (
|
|
1881
|
+
activeRuntimeCopyTargetNodeModules &&
|
|
1882
|
+
isPathInsideOrEqual(candidate, activeRuntimeCopyTargetNodeModules)
|
|
1883
|
+
) {
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1851
1886
|
seen.add(candidate);
|
|
1852
1887
|
candidates.push(candidate);
|
|
1853
1888
|
};
|
|
@@ -2070,6 +2105,42 @@ type CopyTargetOptions = {
|
|
|
2070
2105
|
resolvedVersion: string | null;
|
|
2071
2106
|
};
|
|
2072
2107
|
|
|
2108
|
+
function findReusableAncestorNodeModules({
|
|
2109
|
+
name,
|
|
2110
|
+
requesterDestDir,
|
|
2111
|
+
rootDestDir,
|
|
2112
|
+
resolvedVersion,
|
|
2113
|
+
}: Pick<
|
|
2114
|
+
CopyTargetOptions,
|
|
2115
|
+
"name" | "requesterDestDir" | "rootDestDir" | "resolvedVersion"
|
|
2116
|
+
>): string | null {
|
|
2117
|
+
const root = path.resolve(rootDestDir);
|
|
2118
|
+
let currentDir = requesterDestDir;
|
|
2119
|
+
|
|
2120
|
+
while (true) {
|
|
2121
|
+
const candidateNodeModules = path.join(currentDir, "node_modules");
|
|
2122
|
+
const candidatePackageDir = packagePath(name, candidateNodeModules);
|
|
2123
|
+
const candidateManifest = path.join(candidatePackageDir, "package.json");
|
|
2124
|
+
|
|
2125
|
+
if (
|
|
2126
|
+
fs.existsSync(candidateManifest) &&
|
|
2127
|
+
getPackageVersion(candidateManifest) === resolvedVersion
|
|
2128
|
+
) {
|
|
2129
|
+
return candidateNodeModules;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
if (path.resolve(currentDir) === root) {
|
|
2133
|
+
return null;
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
const parentDir = path.dirname(currentDir);
|
|
2137
|
+
if (parentDir === currentDir) {
|
|
2138
|
+
return null;
|
|
2139
|
+
}
|
|
2140
|
+
currentDir = parentDir;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2073
2144
|
export function selectCopyTargetNodeModules({
|
|
2074
2145
|
name,
|
|
2075
2146
|
requesterDestDir,
|
|
@@ -2097,6 +2168,16 @@ export function selectCopyTargetNodeModules({
|
|
|
2097
2168
|
return targetNodeModules;
|
|
2098
2169
|
}
|
|
2099
2170
|
|
|
2171
|
+
const reusableAncestorNodeModules = findReusableAncestorNodeModules({
|
|
2172
|
+
name,
|
|
2173
|
+
requesterDestDir,
|
|
2174
|
+
rootDestDir,
|
|
2175
|
+
resolvedVersion,
|
|
2176
|
+
});
|
|
2177
|
+
if (reusableAncestorNodeModules) {
|
|
2178
|
+
return reusableAncestorNodeModules;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2100
2181
|
return path.join(requesterDestDir, "node_modules");
|
|
2101
2182
|
}
|
|
2102
2183
|
|
|
@@ -2208,6 +2289,69 @@ function getRequiredRuntimeEntryPaths(pkgJsonPath: string): string[] {
|
|
|
2208
2289
|
return [...entries].sort();
|
|
2209
2290
|
}
|
|
2210
2291
|
|
|
2292
|
+
function workspacePackageNeedsRuntimeBuild(packageJsonPath: string): boolean {
|
|
2293
|
+
for (const entryPath of getRequiredRuntimeEntryPaths(packageJsonPath)) {
|
|
2294
|
+
if (!runtimeManifestEntryExists(path.dirname(packageJsonPath), entryPath)) {
|
|
2295
|
+
return true;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
return false;
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
function packageHasBuildScript(packageJsonPath: string): boolean {
|
|
2302
|
+
try {
|
|
2303
|
+
const manifest = readJson<{ scripts?: Record<string, unknown> }>(
|
|
2304
|
+
packageJsonPath,
|
|
2305
|
+
);
|
|
2306
|
+
return typeof manifest.scripts?.build === "string";
|
|
2307
|
+
} catch {
|
|
2308
|
+
return false;
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
function ensureWorkspaceRuntimeEntriesBuilt(
|
|
2313
|
+
packageNames: Iterable<string>,
|
|
2314
|
+
): void {
|
|
2315
|
+
buildWorkspacePackageIndex();
|
|
2316
|
+
const built = new Set<string>();
|
|
2317
|
+
|
|
2318
|
+
for (const packageName of [...new Set(packageNames)].sort()) {
|
|
2319
|
+
if (!isPackageNameCompatibleWithCurrentPlatform(packageName)) continue;
|
|
2320
|
+
|
|
2321
|
+
for (const candidate of workspacePackageIndex.get(packageName) ?? []) {
|
|
2322
|
+
if (built.has(candidate.sourceDir)) continue;
|
|
2323
|
+
if (!isPackageCompatibleWithCurrentPlatform(candidate.packageJsonPath)) {
|
|
2324
|
+
continue;
|
|
2325
|
+
}
|
|
2326
|
+
if (!workspacePackageNeedsRuntimeBuild(candidate.packageJsonPath)) {
|
|
2327
|
+
continue;
|
|
2328
|
+
}
|
|
2329
|
+
if (!packageHasBuildScript(candidate.packageJsonPath)) {
|
|
2330
|
+
continue;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
console.log(
|
|
2334
|
+
`[runtime-copy] building ${packageName} workspace runtime entries`,
|
|
2335
|
+
);
|
|
2336
|
+
try {
|
|
2337
|
+
execFileSync(resolveBunCommand(), ["run", "build"], {
|
|
2338
|
+
cwd: candidate.sourceDir,
|
|
2339
|
+
env: { ...process.env, FORCE_COLOR: "0" },
|
|
2340
|
+
stdio: "inherit",
|
|
2341
|
+
});
|
|
2342
|
+
} catch (error) {
|
|
2343
|
+
if (workspacePackageNeedsRuntimeBuild(candidate.packageJsonPath)) {
|
|
2344
|
+
throw error;
|
|
2345
|
+
}
|
|
2346
|
+
console.warn(
|
|
2347
|
+
`[runtime-copy] warning: ${packageName} build exited non-zero after producing required runtime entries; continuing`,
|
|
2348
|
+
);
|
|
2349
|
+
}
|
|
2350
|
+
built.add(candidate.sourceDir);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2211
2355
|
// Post-copy assertion: missingAlwaysBundled catches resolve failures, but
|
|
2212
2356
|
// can't catch a transitive-walk filter silently skipping a CORE plugin or
|
|
2213
2357
|
// pruneCopiedPackageDir removing a load-bearing package.json or entrypoint.
|
|
@@ -2292,6 +2436,7 @@ function assertTarSafeRuntimePaths(targetDist: string): void {
|
|
|
2292
2436
|
function main(): void {
|
|
2293
2437
|
const { scanDir, targetDist } = parseArgs(process.argv.slice(2));
|
|
2294
2438
|
const targetNodeModules = path.join(targetDist, "node_modules");
|
|
2439
|
+
activeRuntimeCopyTargetNodeModules = targetNodeModules;
|
|
2295
2440
|
|
|
2296
2441
|
if (!fs.existsSync(scanDir)) {
|
|
2297
2442
|
throw new Error(`scan dir does not exist: ${scanDir}`);
|
|
@@ -2339,6 +2484,7 @@ function main(): void {
|
|
|
2339
2484
|
return shouldBundle;
|
|
2340
2485
|
}),
|
|
2341
2486
|
);
|
|
2487
|
+
ensureWorkspaceRuntimeEntriesBuilt([...alwaysBundled, ...discovered]);
|
|
2342
2488
|
const queue: QueueEntry[] = [...new Set([...alwaysBundled, ...discovered])]
|
|
2343
2489
|
.sort()
|
|
2344
2490
|
.map((name) => ({
|
|
@@ -2478,6 +2624,7 @@ function main(): void {
|
|
|
2478
2624
|
);
|
|
2479
2625
|
}
|
|
2480
2626
|
} finally {
|
|
2627
|
+
activeRuntimeCopyTargetNodeModules = null;
|
|
2481
2628
|
releaseRuntimeCopyLock();
|
|
2482
2629
|
}
|
|
2483
2630
|
}
|
|
@@ -5,6 +5,7 @@ import fs from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { resolveElectrobunDir, resolveMainAppDir } from "./lib/app-dir.mjs";
|
|
8
|
+
import { maxMtimeUnder } from "./lib/artifact-staleness.mjs";
|
|
8
9
|
import {
|
|
9
10
|
buildWindowsRepairSteps,
|
|
10
11
|
classifyElectrobunViewFailure,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
isSupportedBunVersion,
|
|
14
15
|
} from "./lib/desktop-preflight.mjs";
|
|
15
16
|
import { appIdentityEnv } from "./lib/read-app-identity.mjs";
|
|
17
|
+
import { assertRendererRebuiltSince } from "./lib/renderer-build-manifest.mjs";
|
|
16
18
|
|
|
17
19
|
const ROOT = process.cwd();
|
|
18
20
|
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -488,6 +490,26 @@ function runPackageBinary(binary, binaryArgs, options = {}) {
|
|
|
488
490
|
fail(`Could not find bunx or npx to run ${binary}.`);
|
|
489
491
|
}
|
|
490
492
|
|
|
493
|
+
function resolveLocalPackageBinary(binary, cwdCandidates = []) {
|
|
494
|
+
const executableNames =
|
|
495
|
+
process.platform === "win32"
|
|
496
|
+
? [`${binary}.cmd`, `${binary}.exe`, binary]
|
|
497
|
+
: [binary];
|
|
498
|
+
const candidates = [];
|
|
499
|
+
|
|
500
|
+
for (const cwd of cwdCandidates) {
|
|
501
|
+
for (const executableName of executableNames) {
|
|
502
|
+
candidates.push(path.join(cwd, "node_modules", ".bin", executableName));
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
for (const executableName of executableNames) {
|
|
507
|
+
candidates.push(path.join(ROOT, "node_modules", ".bin", executableName));
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;
|
|
511
|
+
}
|
|
512
|
+
|
|
491
513
|
function runBunPackageBinary(binary, binaryArgs, options = {}) {
|
|
492
514
|
const bunx = which("bunx");
|
|
493
515
|
if (bunx) {
|
|
@@ -499,6 +521,15 @@ function runBunPackageBinary(binary, binaryArgs, options = {}) {
|
|
|
499
521
|
}
|
|
500
522
|
|
|
501
523
|
function runElectrobun(commandArgs, options = {}) {
|
|
524
|
+
const local = resolveLocalPackageBinary(
|
|
525
|
+
"electrobun",
|
|
526
|
+
[options.cwd, ELECTROBUN_DIR].filter(Boolean),
|
|
527
|
+
);
|
|
528
|
+
if (local) {
|
|
529
|
+
run(local, commandArgs, options);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
502
533
|
const direct = which("electrobun");
|
|
503
534
|
if (direct) {
|
|
504
535
|
run(direct, commandArgs, options);
|
|
@@ -802,10 +833,7 @@ function ensureWorkspaceRuntimePackageBuilt(packageName, packageDir) {
|
|
|
802
833
|
});
|
|
803
834
|
}
|
|
804
835
|
|
|
805
|
-
function
|
|
806
|
-
const distDir = path.join(packageDir, "dist");
|
|
807
|
-
if (!fs.existsSync(distDir)) return false;
|
|
808
|
-
|
|
836
|
+
function workspaceRuntimePackageMarkersPresent(packageName, distDir) {
|
|
809
837
|
if (packageName === "@elizaos/core") {
|
|
810
838
|
return (
|
|
811
839
|
fs.existsSync(path.join(distDir, "node", "index.node.js")) &&
|
|
@@ -825,6 +853,31 @@ function workspaceRuntimePackageLooksBuilt(packageName, packageDir) {
|
|
|
825
853
|
return true;
|
|
826
854
|
}
|
|
827
855
|
|
|
856
|
+
function workspaceRuntimePackageLooksBuilt(packageName, packageDir) {
|
|
857
|
+
const distDir = path.join(packageDir, "dist");
|
|
858
|
+
if (!fs.existsSync(distDir)) return false;
|
|
859
|
+
if (!workspaceRuntimePackageMarkersPresent(packageName, distDir))
|
|
860
|
+
return false;
|
|
861
|
+
|
|
862
|
+
// Presence of the marker files isn't enough — a dist built from older sources
|
|
863
|
+
// would silently reuse stale runtime code (issue #9309). Reuse only when the
|
|
864
|
+
// dist is at least as new as the package's src. ELIZA_DESKTOP_TRUST_RUNTIME_-
|
|
865
|
+
// PACKAGE_DIST=1 bypasses the mtime check for environments where checkout
|
|
866
|
+
// mtimes are unreliable.
|
|
867
|
+
if (process.env.ELIZA_DESKTOP_TRUST_RUNTIME_PACKAGE_DIST === "1") return true;
|
|
868
|
+
const srcDir = path.join(packageDir, "src");
|
|
869
|
+
if (!fs.existsSync(srcDir)) return true;
|
|
870
|
+
const srcMtime = maxMtimeUnder(srcDir);
|
|
871
|
+
const distMtime = maxMtimeUnder(distDir);
|
|
872
|
+
if (srcMtime > distMtime) {
|
|
873
|
+
console.log(
|
|
874
|
+
`[desktop-build] ${packageName} dist is stale (src newer than dist) — rebuilding`,
|
|
875
|
+
);
|
|
876
|
+
return false;
|
|
877
|
+
}
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
880
|
+
|
|
828
881
|
function ensureWorkspaceRuntimePackagesBuilt() {
|
|
829
882
|
ensureWorkspaceRuntimePackageBuilt("@elizaos/core", CORE_PACKAGE_DIR);
|
|
830
883
|
ensureWorkspaceRuntimePackageBuilt("@elizaos/shared", SHARED_PACKAGE_DIR);
|
|
@@ -982,6 +1035,251 @@ function copyRuntimeNodeModulesWithRetry() {
|
|
|
982
1035
|
}
|
|
983
1036
|
}
|
|
984
1037
|
|
|
1038
|
+
const FUSED_LIB_STAGE_SCRIPT = path.join(
|
|
1039
|
+
SCRIPT_DIR,
|
|
1040
|
+
"stage-desktop-fused-lib.mjs",
|
|
1041
|
+
);
|
|
1042
|
+
// "auto" → the stager picks the host's best backend (Metal on macOS, CUDA when
|
|
1043
|
+
// nvcc is present, else CPU) with the CPU fallback always baked in, so a local
|
|
1044
|
+
// `--build-fused-lib` produces "CPU + platform GPU" for the build host.
|
|
1045
|
+
const FUSED_LIB_VARIANT =
|
|
1046
|
+
getArgValue(args, "fused-lib-variant") ??
|
|
1047
|
+
process.env.ELIZA_DESKTOP_FUSED_LIB_VARIANT ??
|
|
1048
|
+
"auto";
|
|
1049
|
+
// Where the fused lib is staged so the Electrobun copy (dist -> eliza-dist)
|
|
1050
|
+
// carries it; app-core's runtime probe (ensureBundledFusedLibDir) then finds
|
|
1051
|
+
// `<eliza-dist>/local-inference/lib` with no env wiring.
|
|
1052
|
+
const FUSED_LIB_OUT_DIR = path.join(ROOT, "dist", "local-inference", "lib");
|
|
1053
|
+
|
|
1054
|
+
function fusedLibFilenames() {
|
|
1055
|
+
if (process.platform === "darwin") return ["libelizainference.dylib"];
|
|
1056
|
+
if (process.platform === "win32")
|
|
1057
|
+
return ["elizainference.dll", "libelizainference.dll"];
|
|
1058
|
+
return ["libelizainference.so"];
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
function fusedLibAlreadyStaged() {
|
|
1062
|
+
return fusedLibFilenames().some((name) =>
|
|
1063
|
+
fs.existsSync(path.join(FUSED_LIB_OUT_DIR, name)),
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// Provenance for the staged fused lib so the reuse gate never silently reuses a
|
|
1068
|
+
// lib built for a DIFFERENT variant/platform than this build targets (#9309).
|
|
1069
|
+
const FUSED_LIB_SIDECAR = path.join(FUSED_LIB_OUT_DIR, "staged-fused-lib.json");
|
|
1070
|
+
|
|
1071
|
+
function readFusedLibSidecar() {
|
|
1072
|
+
try {
|
|
1073
|
+
return JSON.parse(fs.readFileSync(FUSED_LIB_SIDECAR, "utf8"));
|
|
1074
|
+
} catch {
|
|
1075
|
+
return null;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
function writeFusedLibSidecar() {
|
|
1080
|
+
fs.mkdirSync(FUSED_LIB_OUT_DIR, { recursive: true });
|
|
1081
|
+
fs.writeFileSync(
|
|
1082
|
+
FUSED_LIB_SIDECAR,
|
|
1083
|
+
`${JSON.stringify(
|
|
1084
|
+
{
|
|
1085
|
+
variant: FUSED_LIB_VARIANT,
|
|
1086
|
+
platform: process.platform,
|
|
1087
|
+
builtAt: new Date().toISOString(),
|
|
1088
|
+
},
|
|
1089
|
+
null,
|
|
1090
|
+
2,
|
|
1091
|
+
)}\n`,
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* A staged lib whose provenance sidecar names a DIFFERENT variant/platform than
|
|
1097
|
+
* this build targets — a confirmed wrong-variant lib we must not ship.
|
|
1098
|
+
*/
|
|
1099
|
+
function fusedLibStagedVariantMismatch() {
|
|
1100
|
+
if (!fusedLibAlreadyStaged()) return false;
|
|
1101
|
+
const sidecar = readFusedLibSidecar();
|
|
1102
|
+
if (!sidecar) return false; // no provenance ≠ wrong provenance
|
|
1103
|
+
return (
|
|
1104
|
+
sidecar.variant !== FUSED_LIB_VARIANT ||
|
|
1105
|
+
sidecar.platform !== process.platform
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Whether a staged lib can be reused. A lib with a matching sidecar is reused; a
|
|
1111
|
+
* sidecar-less lib (e.g. a prebuilt artifact a CI step dropped into
|
|
1112
|
+
* dist/local-inference/lib) is TRUSTED and reused — we can't confirm its variant
|
|
1113
|
+
* but it was deliberately staged. Only a sidecar that names a different
|
|
1114
|
+
* variant/platform forces a rebuild.
|
|
1115
|
+
*/
|
|
1116
|
+
function fusedLibStagedForCurrentVariant() {
|
|
1117
|
+
return fusedLibAlreadyStaged() && !fusedLibStagedVariantMismatch();
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
const FUSED_LIB_FORK_DIR = path.join(
|
|
1121
|
+
PLUGIN_LOCAL_INFERENCE_PACKAGE_DIR,
|
|
1122
|
+
"native",
|
|
1123
|
+
"llama.cpp",
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1126
|
+
/**
|
|
1127
|
+
* Ensure the native llama.cpp fork submodule is checked out (the fused build
|
|
1128
|
+
* needs its CMakeLists). Release CI checks out with `submodules: false`, so the
|
|
1129
|
+
* fork is absent; init just the one path on demand rather than requiring the
|
|
1130
|
+
* workflow to fetch every submodule. Returns true if the fork is present after.
|
|
1131
|
+
*/
|
|
1132
|
+
function ensureFusedLibSubmodule() {
|
|
1133
|
+
if (fs.existsSync(path.join(FUSED_LIB_FORK_DIR, "CMakeLists.txt")))
|
|
1134
|
+
return true;
|
|
1135
|
+
const rel = path.relative(ROOT, FUSED_LIB_FORK_DIR).split(path.sep).join("/");
|
|
1136
|
+
console.log(
|
|
1137
|
+
`[desktop-build] Native fork missing; initializing submodule ${rel}`,
|
|
1138
|
+
);
|
|
1139
|
+
// NB: no --depth/shallow here — a shallow submodule fetch fails with
|
|
1140
|
+
// "Server does not allow request for unadvertised object <sha>" when the
|
|
1141
|
+
// recorded gitlink commit isn't the remote tip, which is common. Reliability
|
|
1142
|
+
// over speed: this path must actually produce the fork.
|
|
1143
|
+
spawnSync(
|
|
1144
|
+
"git",
|
|
1145
|
+
["-C", ROOT, "submodule", "update", "--init", "--recursive", rel],
|
|
1146
|
+
{ stdio: "inherit" },
|
|
1147
|
+
);
|
|
1148
|
+
return fs.existsSync(path.join(FUSED_LIB_FORK_DIR, "CMakeLists.txt"));
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* Build + stage the fused `libelizainference` into the desktop bundle so a
|
|
1153
|
+
* COMPILED app ships with working local inference — no first-run download, no
|
|
1154
|
+
* manual `build:fused-desktop`. The "auto" variant bakes CPU in and layers the
|
|
1155
|
+
* host's best GPU backend (Metal on macOS; CUDA when nvcc is present; else CPU),
|
|
1156
|
+
* so it works on every host.
|
|
1157
|
+
*
|
|
1158
|
+
* Gating:
|
|
1159
|
+
* - Reuses an already-staged lib (a prior build, or a prebuilt artifact a CI
|
|
1160
|
+
* step dropped into dist/local-inference/lib).
|
|
1161
|
+
* - Builds when explicitly asked (`--build-fused-lib` /
|
|
1162
|
+
* ELIZA_DESKTOP_BUILD_FUSED_LIB=1) OR automatically on CI release builds
|
|
1163
|
+
* (CI=true) — initializing the native submodule on demand. Off for plain
|
|
1164
|
+
* local dev builds (keeps iteration fast).
|
|
1165
|
+
* - An EXPLICIT request hard-fails if it can't produce the lib (unless
|
|
1166
|
+
* ELIZA_DESKTOP_FUSED_LIB_OPTIONAL=1). A CI auto-build is BEST-EFFORT: a
|
|
1167
|
+
* missing toolchain or a build failure warns and ships without the lib
|
|
1168
|
+
* (cloud fallback) rather than breaking the release. Set
|
|
1169
|
+
* ELIZA_DESKTOP_FUSED_LIB_REQUIRED=1 to make CI auto-builds hard-fail too.
|
|
1170
|
+
*/
|
|
1171
|
+
function stageDesktopFusedLib() {
|
|
1172
|
+
const explicitlyRequested =
|
|
1173
|
+
getBooleanArg(args, "build-fused-lib") ||
|
|
1174
|
+
process.env.ELIZA_DESKTOP_BUILD_FUSED_LIB === "1";
|
|
1175
|
+
const ciAutoBuild = process.env.CI === "true";
|
|
1176
|
+
const shouldBuild = explicitlyRequested || ciAutoBuild;
|
|
1177
|
+
const required =
|
|
1178
|
+
(explicitlyRequested ||
|
|
1179
|
+
process.env.ELIZA_DESKTOP_FUSED_LIB_REQUIRED === "1") &&
|
|
1180
|
+
process.env.ELIZA_DESKTOP_FUSED_LIB_OPTIONAL !== "1";
|
|
1181
|
+
|
|
1182
|
+
if (
|
|
1183
|
+
fusedLibStagedForCurrentVariant() &&
|
|
1184
|
+
process.env.ELIZA_DESKTOP_REBUILD_FUSED_LIB !== "1"
|
|
1185
|
+
) {
|
|
1186
|
+
console.log(
|
|
1187
|
+
`[desktop-build] Reusing already-staged fused lib in ${FUSED_LIB_OUT_DIR} ` +
|
|
1188
|
+
`(variant=${FUSED_LIB_VARIANT}, ${process.platform})`,
|
|
1189
|
+
);
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// A staged lib whose sidecar names a DIFFERENT variant/platform is a confirmed
|
|
1194
|
+
// wrong-variant lib — never silently reused. (A sidecar-less drop-in is trusted
|
|
1195
|
+
// and was already reused above.)
|
|
1196
|
+
const variantMismatch = fusedLibStagedVariantMismatch();
|
|
1197
|
+
if (variantMismatch) {
|
|
1198
|
+
const sidecar = readFusedLibSidecar();
|
|
1199
|
+
console.warn(
|
|
1200
|
+
`[desktop-build] Staged fused lib does not match this build ` +
|
|
1201
|
+
`(want variant=${FUSED_LIB_VARIANT}/${process.platform}, found ` +
|
|
1202
|
+
`${sidecar.variant}/${sidecar.platform}). ` +
|
|
1203
|
+
`It will be rebuilt to avoid shipping a wrong-variant native lib.`,
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
if (!shouldBuild) {
|
|
1208
|
+
if (variantMismatch) {
|
|
1209
|
+
// Can't rebuild here (no toolchain requested) and the staged lib is the
|
|
1210
|
+
// wrong variant — drop it so the app cleanly falls back to cloud inference
|
|
1211
|
+
// instead of dlopen()-ing a mismatched backend on the device.
|
|
1212
|
+
for (const name of fusedLibFilenames()) {
|
|
1213
|
+
fs.rmSync(path.join(FUSED_LIB_OUT_DIR, name), { force: true });
|
|
1214
|
+
}
|
|
1215
|
+
fs.rmSync(FUSED_LIB_SIDECAR, { force: true });
|
|
1216
|
+
console.warn(
|
|
1217
|
+
"[desktop-build] Removed the mismatched fused lib; this build ships without " +
|
|
1218
|
+
"local inference. Rebuild with --build-fused-lib to stage the right variant.",
|
|
1219
|
+
);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
console.log(
|
|
1223
|
+
"[desktop-build] Skipping fused libelizainference build (local-inference will be " +
|
|
1224
|
+
"unavailable in this build). Enable with --build-fused-lib or " +
|
|
1225
|
+
"ELIZA_DESKTOP_BUILD_FUSED_LIB=1 (CI release builds enable it automatically).",
|
|
1226
|
+
);
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
// Surface a hard failure for an explicit request that can't proceed; otherwise
|
|
1231
|
+
// warn and ship without the lib so a release never breaks on the native build.
|
|
1232
|
+
const giveUp = (reason) => {
|
|
1233
|
+
if (required) {
|
|
1234
|
+
fail(
|
|
1235
|
+
`Cannot build the fused libelizainference for the desktop bundle: ${reason}. ` +
|
|
1236
|
+
"Install the toolchain / init submodules, or set " +
|
|
1237
|
+
"ELIZA_DESKTOP_FUSED_LIB_OPTIONAL=1 to ship without local inference.",
|
|
1238
|
+
);
|
|
1239
|
+
}
|
|
1240
|
+
console.warn(
|
|
1241
|
+
`[desktop-build] Skipping fused libelizainference build — ${reason}. ` +
|
|
1242
|
+
"The compiled app will fall back to cloud inference.",
|
|
1243
|
+
);
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
if (!which("cmake")) {
|
|
1247
|
+
giveUp("cmake not found on PATH");
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
if (!ensureFusedLibSubmodule()) {
|
|
1251
|
+
giveUp(`native fork not available at ${FUSED_LIB_FORK_DIR}`);
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
fs.mkdirSync(FUSED_LIB_OUT_DIR, { recursive: true });
|
|
1256
|
+
run(
|
|
1257
|
+
"node",
|
|
1258
|
+
[
|
|
1259
|
+
FUSED_LIB_STAGE_SCRIPT,
|
|
1260
|
+
"--variant",
|
|
1261
|
+
FUSED_LIB_VARIANT,
|
|
1262
|
+
"--out",
|
|
1263
|
+
FUSED_LIB_OUT_DIR,
|
|
1264
|
+
],
|
|
1265
|
+
{
|
|
1266
|
+
cwd: ROOT,
|
|
1267
|
+
// A CI auto-build that fails must not abort the whole release; an explicit
|
|
1268
|
+
// request is allowed to hard-fail.
|
|
1269
|
+
allowFailure: !required,
|
|
1270
|
+
label: `Building + staging fused libelizainference (${FUSED_LIB_VARIANT}) into the desktop bundle`,
|
|
1271
|
+
},
|
|
1272
|
+
);
|
|
1273
|
+
|
|
1274
|
+
if (!fusedLibAlreadyStaged()) {
|
|
1275
|
+
giveUp("the build produced no lib in the output dir");
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
// Record provenance so a later build with a different variant/platform won't
|
|
1279
|
+
// silently reuse this lib.
|
|
1280
|
+
writeFusedLibSidecar();
|
|
1281
|
+
}
|
|
1282
|
+
|
|
985
1283
|
function stageDesktopBuild() {
|
|
986
1284
|
ensureWorkspaceCheckoutPresent();
|
|
987
1285
|
ensureAppDirs();
|
|
@@ -989,6 +1287,11 @@ function stageDesktopBuild() {
|
|
|
989
1287
|
ensureRootRuntimeBundle();
|
|
990
1288
|
ensureWorkspaceRuntimePackagesBuilt();
|
|
991
1289
|
|
|
1290
|
+
// Build + bundle the fused local-inference native lib so the packaged app
|
|
1291
|
+
// serves local AI out of the box. Gated (see stageDesktopFusedLib) so plain
|
|
1292
|
+
// dev builds stay fast; auto-built best-effort on CI release builds.
|
|
1293
|
+
stageDesktopFusedLib();
|
|
1294
|
+
|
|
992
1295
|
runBun(["run", "generate:css-strings"], {
|
|
993
1296
|
cwd: UI_PACKAGE_DIR,
|
|
994
1297
|
label: "Generating UI runtime CSS string modules",
|
|
@@ -1017,11 +1320,21 @@ function stageDesktopBuild() {
|
|
|
1017
1320
|
|
|
1018
1321
|
ensureUiGeneratedAssets();
|
|
1019
1322
|
|
|
1323
|
+
// Capture the moment the renderer build starts so we can prove afterward that
|
|
1324
|
+
// a FRESH bundle was produced — not a stale dist silently reused (issue #9309).
|
|
1325
|
+
const rendererBuildStartedAt = Date.now() - 1000;
|
|
1020
1326
|
runBunPackageBinary("vite", ["build"], {
|
|
1021
1327
|
cwd: APP_DIR,
|
|
1022
1328
|
env: desktopRendererBuildEnv(),
|
|
1023
1329
|
label: `Building renderer bundle (VITE_APP_VARIANT=${variant}, ELIZA_BUILD_VARIANT=${buildVariant})`,
|
|
1024
1330
|
});
|
|
1331
|
+
// Fail loudly if the renderer manifest is missing or predates this build (a
|
|
1332
|
+
// cached/stale dist was reused) or was built for a different variant.
|
|
1333
|
+
assertRendererRebuiltSince(path.join(APP_DIR, "dist"), {
|
|
1334
|
+
notBefore: rendererBuildStartedAt,
|
|
1335
|
+
expectVariant: buildVariant,
|
|
1336
|
+
label: "desktop",
|
|
1337
|
+
});
|
|
1025
1338
|
|
|
1026
1339
|
runDesktopPreflight();
|
|
1027
1340
|
|
|
@@ -69,11 +69,12 @@ BOOT_CRASH_PATTERNS=(
|
|
|
69
69
|
'ERR_MODULE_NOT_FOUND'
|
|
70
70
|
'ERR_REQUIRE_ESM'
|
|
71
71
|
'MODULE_NOT_FOUND'
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
72
|
+
# Defense-in-depth: the agent boots under the tsx loader (see APP_CMD_START),
|
|
73
|
+
# so .ts extensions resolve at runtime today. But if a workspace package ever
|
|
74
|
+
# shipped without a built dist, link-docker-local-app-packages.mjs rewrites its
|
|
75
|
+
# exports to ./src/*.ts, and importing that under a tsx-less or mislinked boot
|
|
76
|
+
# would throw ERR_UNKNOWN_FILE_EXTENSION on the core boot path. Fail fast on that
|
|
77
|
+
# signature instead of waiting out the full health timeout.
|
|
77
78
|
'ERR_UNKNOWN_FILE_EXTENSION'
|
|
78
79
|
'Unknown file extension'
|
|
79
80
|
'Failed to start'
|
|
@@ -224,9 +225,7 @@ load_env_file "deploy/deploy.env"
|
|
|
224
225
|
|
|
225
226
|
APP_IMAGE="${APP_IMAGE:-eliza/agent}"
|
|
226
227
|
APP_ENTRYPOINT="${APP_ENTRYPOINT:-$AGENT_DIR/dist/bin.js}"
|
|
227
|
-
|
|
228
|
-
# `.ts` specifiers rewritten to `.js`, so the tsx loader only added startup tax.
|
|
229
|
-
APP_CMD_START="${APP_CMD_START:-node ${APP_ENTRYPOINT} start}"
|
|
228
|
+
APP_CMD_START="${APP_CMD_START:-node --import /opt/tsx/node_modules/tsx/dist/loader.mjs ${APP_ENTRYPOINT} start}"
|
|
230
229
|
APP_PORT="${APP_PORT:-2138}"
|
|
231
230
|
APP_API_BIND="${APP_API_BIND:-127.0.0.1}"
|
|
232
231
|
OCI_SOURCE="${OCI_SOURCE:-}"
|
|
@@ -479,11 +478,37 @@ boot_verify() {
|
|
|
479
478
|
log "[boot-kpi] WARNING: jq or budgets.json unavailable; using default coldReadyMs budget ${budget_default}ms"
|
|
480
479
|
fi
|
|
481
480
|
|
|
481
|
+
# Record runner contention alongside readyMs (#8812 item 5). Boot is
|
|
482
|
+
# single-threaded and import-bound, so a heavily loaded runner inflates
|
|
483
|
+
# readyMs; we log loadavg/cpu so a breach can be triaged, and (below) refuse
|
|
484
|
+
# to FAIL on a breach when the runner is clearly overloaded, so enforcement
|
|
485
|
+
# only catches a genuine boot-time regression — not transient runner load.
|
|
486
|
+
local load1="" cpus="" contended="false"
|
|
487
|
+
if [[ -r /proc/loadavg ]]; then
|
|
488
|
+
load1="$(cut -d' ' -f1 /proc/loadavg 2>/dev/null || true)"
|
|
489
|
+
fi
|
|
490
|
+
cpus="$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)"
|
|
491
|
+
log "[boot-kpi] runner loadavg(1m)=${load1:-?} cpus=${cpus}"
|
|
492
|
+
# Heavy contention = loadavg(1m) above 2x the cpu count. Float compare via
|
|
493
|
+
# awk (no bc dependency); guarded so a missing loadavg never trips it.
|
|
494
|
+
if [[ -n "$load1" && "$cpus" =~ ^[0-9]+$ ]]; then
|
|
495
|
+
if awk -v l="$load1" -v c="$cpus" 'BEGIN{exit !(l > 2*c)}' 2>/dev/null; then
|
|
496
|
+
contended="true"
|
|
497
|
+
fi
|
|
498
|
+
fi
|
|
499
|
+
|
|
482
500
|
log "[boot-kpi] cold readyMs=${ready_ms} budget=${budget}"
|
|
483
501
|
log "[boot-kpi] peakRss: not measured (docker stats samples instantaneously, not boot peak)"
|
|
484
502
|
|
|
485
503
|
if (( ready_ms > budget )); then
|
|
486
504
|
local msg="boot-kpi cold readyMs=${ready_ms} exceeded budget=${budget} (boot.coldReadyMs)"
|
|
505
|
+
if [[ "${BOOT_KPI_ENFORCE:-}" == "1" && "$contended" == "true" ]]; then
|
|
506
|
+
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
|
|
507
|
+
printf '::warning::%s — runner contended (loadavg %s over %s cpus), not failing\n' "$msg" "$load1" "$cpus" >&2
|
|
508
|
+
fi
|
|
509
|
+
log "[boot-kpi] WARNING (runner contended, loadavg ${load1} over ${cpus} cpus — not failing): $msg"
|
|
510
|
+
return 0
|
|
511
|
+
fi
|
|
487
512
|
if [[ "${BOOT_KPI_ENFORCE:-}" == "1" ]]; then
|
|
488
513
|
if [[ "${GITHUB_ACTIONS:-}" == "true" ]]; then
|
|
489
514
|
printf '::error::%s\n' "$msg" >&2
|
|
@@ -1437,7 +1437,7 @@ char * eliza_ios_text_benchmark_run(const char * model_path, const char * mode)
|
|
|
1437
1437
|
const int use_cpu = mode && strcmp(mode, "cpu") == 0;
|
|
1438
1438
|
const char * ctx_params_cpu = "{\\"n_ctx\\":512,\\"n_batch\\":512,\\"n_ubatch\\":128,\\"no_gpu_devices\\":true,\\"n_gpu_layers\\":0,\\"flash_attn\\":false,\\"use_mmap\\":true,\\"n_threads\\":4}";
|
|
1439
1439
|
const char * ctx_params_metal = "{\\"n_ctx\\":512,\\"n_batch\\":512,\\"n_ubatch\\":128,\\"n_gpu_layers\\":999,\\"flash_attn\\":true,\\"use_mmap\\":true,\\"n_threads\\":4}";
|
|
1440
|
-
const char * completion_params = "{\\"n_predict\\":32,\\"temperature\\":0,\\"seed\\":42,\\"top_k\\":1,\\"n_threads\\":4,\\"stop\\":[\\"
|
|
1440
|
+
const char * completion_params = "{\\"n_predict\\":32,\\"temperature\\":0,\\"seed\\":42,\\"top_k\\":1,\\"n_threads\\":4,\\"stop\\":[\\"<end_of_turn>\\"]}";
|
|
1441
1441
|
const char * prompt = "You are Eliza. Write one short benchmark sentence.";
|
|
1442
1442
|
int64_t ctx = llama_init_context(model_path, use_cpu ? ctx_params_cpu : ctx_params_metal);
|
|
1443
1443
|
if (ctx <= 0) {
|