@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.
Files changed (360) hide show
  1. package/agent-bridge.d.ts +5 -5
  2. package/api/auth/audit.d.ts +1 -1
  3. package/api/auth/auth-context.d.ts +1 -1
  4. package/api/auth/bootstrap-token.d.ts +1 -1
  5. package/api/auth/sessions.d.ts +1 -1
  6. package/api/auth-bootstrap-routes.d.ts +1 -1
  7. package/api/auth-pairing-routes.d.ts +1 -1
  8. package/api/auth-pairing-routes.d.ts.map +1 -1
  9. package/api/auth-pairing-routes.js +2 -3
  10. package/api/auth-session-routes.d.ts +2 -2
  11. package/api/auth.d.ts +1 -1
  12. package/api/automations-compat-routes.d.ts +1 -1
  13. package/api/background-tasks-routes.d.ts +1 -1
  14. package/api/catalog-routes.d.ts +1 -1
  15. package/api/cloud-voice-routes.d.ts +1 -1
  16. package/api/compat-route-shared.d.ts +12 -5
  17. package/api/compat-route-shared.d.ts.map +1 -1
  18. package/api/compat-route-shared.js +22 -187
  19. package/api/database-rows-compat-routes.d.ts +1 -1
  20. package/api/dev-compat-routes.d.ts +1 -1
  21. package/api/dev-route-catalog.d.ts.map +1 -1
  22. package/api/dev-route-catalog.js +20 -0
  23. package/api/drop-status-compat-route.d.ts +3 -0
  24. package/api/drop-status-compat-route.d.ts.map +1 -0
  25. package/api/drop-status-compat-route.js +12 -0
  26. package/api/first-run-routes.d.ts +1 -1
  27. package/api/internal-routes.d.ts +1 -1
  28. package/api/runtime-mode-routes.d.ts +1 -1
  29. package/api/secrets-manager-routes.d.ts.map +1 -1
  30. package/api/sensitive-request-routes.d.ts +2 -2
  31. package/api/server-config-filter.d.ts.map +1 -1
  32. package/api/server-config-filter.js +0 -1
  33. package/api/server-first-run-helpers.d.ts.map +1 -1
  34. package/api/server-first-run-helpers.js +0 -3
  35. package/api/server.d.ts +8 -8
  36. package/api/server.d.ts.map +1 -1
  37. package/api/server.js +13 -59
  38. package/api/training-benchmarks.d.ts +1 -1
  39. package/api/training-benchmarks.d.ts.map +1 -1
  40. package/api/training-benchmarks.js +31 -9
  41. package/api/workbench-compat-routes.d.ts +1 -1
  42. package/benchmark/server-utils.d.ts +2 -2
  43. package/browser.d.ts +4 -4
  44. package/cli/plugins-cli.d.ts.map +1 -1
  45. package/cli/plugins-cli.js +5 -0
  46. package/cli/program/register.auth.d.ts +27 -1
  47. package/cli/program/register.auth.d.ts.map +1 -1
  48. package/cli/program/register.auth.js +187 -0
  49. package/cli/program/register.dashboard.d.ts.map +1 -1
  50. package/cli/program/register.dashboard.js +11 -1
  51. package/cli/program.d.ts +1 -1
  52. package/first-run/first-run-config.d.ts +1 -1
  53. package/index.d.ts +46 -47
  54. package/index.d.ts.map +1 -1
  55. package/index.js +3 -7
  56. package/package.json +42 -36
  57. package/packaging/PUBLISHING_GUIDE.md +20 -20
  58. package/platform/elizaos-agent-browser-stub.d.ts +0 -1
  59. package/platform/elizaos-agent-browser-stub.d.ts.map +1 -1
  60. package/platform/elizaos-agent-browser-stub.js +0 -1
  61. package/platform/ios-runtime-bridge.d.ts.map +1 -1
  62. package/platform/ios-runtime-bridge.js +0 -1
  63. package/platform/native-plugin-entrypoints.d.ts +2 -2
  64. package/platforms/android/app/build.gradle +30 -7
  65. package/platforms/android/app/src/main/elizavoice-jni/elizavoice-jni.cpp +179 -35
  66. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAgentService.java +60 -32
  67. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBionicInferenceServer.java +405 -65
  68. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceNative.java +35 -0
  69. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoicePlugin.java +13 -6
  70. package/platforms/android/app/src/main/res/drawable/splash.png +0 -0
  71. package/platforms/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
  72. package/platforms/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
  73. package/platforms/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
  74. package/platforms/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
  75. package/platforms/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
  76. package/platforms/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
  77. package/platforms/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
  78. package/platforms/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
  79. package/platforms/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
  80. package/platforms/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
  81. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  82. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  83. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png +0 -0
  84. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  85. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  86. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  87. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png +0 -0
  88. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  89. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  90. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  91. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png +0 -0
  92. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  93. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  94. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  95. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png +0 -0
  96. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  97. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  98. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  99. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png +0 -0
  100. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  101. package/platforms/android/app/src/main/res/values/colors.xml +5 -1
  102. package/platforms/android/app/src/main/res/values/ic_launcher_background.xml +1 -1
  103. package/platforms/android/app/src/main/res/values/styles.xml +4 -1
  104. package/platforms/electrobun/electrobun.config.ts +0 -1
  105. package/platforms/electrobun/native/macos/window-effects.mm +4 -0
  106. package/platforms/electrobun/package.json +11 -9
  107. package/platforms/electrobun/remotes/local-model/src/bun/eliza1-catalog.ts +1 -1
  108. package/platforms/electrobun/remotes/runtime/src/dev/phase2-smoke.ts +10 -5
  109. package/platforms/electrobun/remotes/runtime/src/dev/phase3-smoke.ts +11 -15
  110. package/platforms/electrobun/src/application-menu.ts +0 -7
  111. package/platforms/electrobun/src/desktop-http-request.test.ts +30 -1
  112. package/platforms/electrobun/src/desktop-http-request.ts +14 -2
  113. package/platforms/electrobun/src/desktop-test-bridge-server.ts +28 -0
  114. package/platforms/electrobun/src/fatal-shutdown.test.ts +3 -7
  115. package/platforms/electrobun/src/index.ts +64 -13
  116. package/platforms/electrobun/src/lifecycle/api-base-owner.test.ts +83 -0
  117. package/platforms/electrobun/src/lifecycle/api-base-owner.ts +37 -16
  118. package/platforms/electrobun/src/native/agent.ts +28 -17
  119. package/platforms/electrobun/src/native/credentials.ts +6 -1
  120. package/platforms/electrobun/src/native/desktop-window.test.ts +142 -26
  121. package/platforms/electrobun/src/native/desktop.ts +8 -4
  122. package/platforms/electrobun/src/native/index.ts +6 -0
  123. package/platforms/electrobun/src/native/remote-plugin-host.ts +18 -8
  124. package/platforms/electrobun/src/preload.js +1 -1
  125. package/platforms/electrobun/src/voice/voice-live-validation.test.ts +10 -5
  126. package/platforms/electrobun/src/voice/voice-runtime-adapter.ts +3 -2
  127. package/platforms/electrobun/src/voice/voice-service.test.ts +26 -0
  128. package/platforms/electrobun/src/voice/voice-service.ts +57 -17
  129. package/platforms/electrobun/tsconfig.json +17 -1
  130. package/platforms/ios/App/App/Base.lproj/LaunchScreen.storyboard +4 -6
  131. package/registry/index.d.ts +1 -6
  132. package/registry/index.d.ts.map +1 -1
  133. package/registry/index.js +9 -101
  134. package/runtime/android-avf-microdroid-bridge.d.ts +1 -1
  135. package/runtime/bundled-fused-lib.d.ts +36 -0
  136. package/runtime/bundled-fused-lib.d.ts.map +1 -0
  137. package/runtime/bundled-fused-lib.js +77 -0
  138. package/runtime/channel-plugin-map.d.ts +1 -5
  139. package/runtime/channel-plugin-map.d.ts.map +1 -1
  140. package/runtime/channel-plugin-map.js +11 -31
  141. package/runtime/desktop/index.d.ts +5 -5
  142. package/runtime/dev-server.js +11 -2
  143. package/runtime/eliza.d.ts.map +1 -1
  144. package/runtime/eliza.js +18 -8
  145. package/runtime/mode/route-mode-guard.d.ts +1 -1
  146. package/runtime/mode/route-mode-matrix.d.ts +1 -1
  147. package/runtime/voice-warmup.d.ts +4 -19
  148. package/runtime/voice-warmup.d.ts.map +1 -1
  149. package/runtime/voice-warmup.js +4 -14
  150. package/scripts/aosp/README.md +10 -1
  151. package/scripts/aosp/compile-libllama-zig-pin.test.mjs +147 -0
  152. package/scripts/aosp/compile-libllama.mjs +446 -59
  153. package/scripts/aosp/compile-libllama.test.mjs +133 -0
  154. package/scripts/aosp/compile-shim.mjs +21 -1
  155. package/scripts/aosp/deploy-pixel.mjs +1 -1
  156. package/scripts/aosp/stage-default-models.mjs +24 -31
  157. package/scripts/aosp/stage-default-models.test.mjs +23 -0
  158. package/scripts/assert-required-bundled-packages.test.ts +22 -1
  159. package/scripts/build-helpers/verify-fused-symbols.mjs +33 -0
  160. package/scripts/build-helpers/verify-fused-symbols.test.mjs +0 -0
  161. package/scripts/build-image.sh +1 -3
  162. package/scripts/build-llama-cpp-mtp.mjs +17 -16
  163. package/scripts/check-i18n.mjs +0 -1
  164. package/scripts/copy-runtime-node-modules.ts +147 -0
  165. package/scripts/desktop-build.mjs +317 -4
  166. package/scripts/docker-ci-smoke.sh +33 -8
  167. package/scripts/ensure-type-package-aliases.mjs +1 -1
  168. package/scripts/ios-xcframework/run-physical-device-smoke.mjs +1 -1
  169. package/scripts/lib/agent-source-watcher.mjs +0 -1
  170. package/scripts/lib/artifact-staleness.d.mts +33 -0
  171. package/scripts/lib/artifact-staleness.mjs +122 -0
  172. package/scripts/lib/artifact-staleness.test.mts +98 -0
  173. package/scripts/lib/duet-bridge.mjs +1 -1
  174. package/scripts/lib/ios-plist-url-scheme.mjs +80 -0
  175. package/scripts/lib/mobile-build-decisions.mjs +97 -0
  176. package/scripts/lib/renderer-build-manifest.d.mts +65 -0
  177. package/scripts/lib/renderer-build-manifest.mjs +257 -0
  178. package/scripts/lib/renderer-build-manifest.test.mts +277 -0
  179. package/scripts/lib/stage-android-agent.mjs +13 -4
  180. package/scripts/lib/verify-ondevice-artifact.d.mts +16 -0
  181. package/scripts/lib/verify-ondevice-artifact.mjs +61 -0
  182. package/scripts/lib/verify-ondevice-artifact.test.mts +98 -0
  183. package/scripts/lib/websocket-pending-queue.ts +92 -0
  184. package/scripts/link-docker-local-app-packages.mjs +6 -0
  185. package/scripts/playwright-ui-live-stack.ts +430 -144
  186. package/scripts/playwright-ui-smoke-api-stub.mjs +160 -168
  187. package/scripts/run-local-plugin-live-smoke.mjs +1 -6
  188. package/scripts/run-mobile-build-brand-separation.test.mts +33 -0
  189. package/scripts/run-mobile-build-ios-engine-gate.test.mjs +85 -0
  190. package/scripts/run-mobile-build-mtp-staleness.test.mts +198 -0
  191. package/scripts/run-mobile-build.mjs +408 -86
  192. package/scripts/serve-real-local-agent.ts +72 -0
  193. package/scripts/stage-desktop-fused-lib.mjs +43 -14
  194. package/scripts/verify-ondevice-artifact.mjs +111 -0
  195. package/scripts/voice-attribution-smoke.ts +144 -38
  196. package/scripts/voice-duet.mjs +6 -6
  197. package/scripts/voice-e2e-hardware.ts +22 -16
  198. package/scripts/voice-interactive.mjs +16 -45
  199. package/security/agent-vault-id.d.ts +1 -1
  200. package/security/platform-secure-store-node.d.ts +1 -1
  201. package/services/ambient-audio/consent.d.ts +1 -1
  202. package/services/ambient-audio/index.d.ts +6 -6
  203. package/services/ambient-audio/replay-buffer.d.ts +1 -1
  204. package/services/ambient-audio/response-gate.d.ts +1 -1
  205. package/services/ambient-audio/service.d.ts +3 -3
  206. package/services/connector-target-catalog.d.ts +1 -1
  207. package/services/sensitive-requests/index.d.ts +6 -6
  208. package/services/steward-sidecar/wallet-setup.d.ts +1 -1
  209. package/services/steward-sidecar.d.ts +3 -3
  210. package/services/tunnel-to-mobile/index.d.ts +1 -1
  211. package/services/vault-bootstrap.d.ts.map +1 -1
  212. package/services/vault-bootstrap.js +14 -10
  213. package/services/voice-profiles/diarization-pipeline.d.ts +1 -1
  214. package/services/voice-profiles/index.d.ts +11 -11
  215. package/services/voice-profiles/owner-confidence.d.ts +1 -1
  216. package/services/voice-profiles/private-challenge.d.ts +1 -1
  217. package/services/voice-profiles/store.d.ts +1 -1
  218. package/test/helpers/live-provider.test.ts +91 -1
  219. package/test/helpers/live-provider.ts +195 -51
  220. package/test/scripts/websocket-pending-queue.test.ts +119 -0
  221. package/test-support/test-helpers.d.ts +0 -33
  222. package/test-support/test-helpers.d.ts.map +1 -1
  223. package/test-support/test-helpers.js +81 -189
  224. package/ui-compat.d.ts +1 -0
  225. package/ui-compat.d.ts.map +1 -1
  226. package/ui-compat.js +4 -0
  227. package/platforms/electrobun/docs/convergence-audit.json +0 -3505
  228. package/platforms/electrobun/docs/convergence-audit.md +0 -694
  229. package/platforms/electrobun/scripts/ensure-whisper-gguf.sh +0 -55
  230. package/platforms/electrobun/scripts/ensure-whisper-model.sh +0 -35
  231. package/platforms/electrobun/scripts/generate-convergence-audit.ts +0 -1203
  232. package/platforms/electrobun/src/native/whisper-env.test.ts +0 -71
  233. package/platforms/electrobun/src/native/whisper-env.ts +0 -68
  234. package/registry/app-registry.d.ts +0 -14
  235. package/registry/app-registry.d.ts.map +0 -1
  236. package/registry/app-registry.js +0 -29
  237. package/registry/entries/apps/app-polymarket.json +0 -31
  238. package/registry/entries/apps/clawville.json +0 -27
  239. package/registry/entries/apps/companion.json +0 -28
  240. package/registry/entries/apps/database-viewer.json +0 -27
  241. package/registry/entries/apps/defense-of-the-agents.json +0 -27
  242. package/registry/entries/apps/documents.json +0 -30
  243. package/registry/entries/apps/feed.json +0 -27
  244. package/registry/entries/apps/hyperliquid.json +0 -31
  245. package/registry/entries/apps/log-viewer.json +0 -27
  246. package/registry/entries/apps/memory-viewer.json +0 -27
  247. package/registry/entries/apps/model-tester.json +0 -31
  248. package/registry/entries/apps/plugin-viewer.json +0 -27
  249. package/registry/entries/apps/relationship-viewer.json +0 -27
  250. package/registry/entries/apps/runtime-debugger.json +0 -27
  251. package/registry/entries/apps/shopify.json +0 -31
  252. package/registry/entries/apps/skills-viewer.json +0 -27
  253. package/registry/entries/apps/steward.json +0 -31
  254. package/registry/entries/apps/training.json +0 -54
  255. package/registry/entries/apps/trajectory-viewer.json +0 -27
  256. package/registry/entries/apps/vincent.json +0 -31
  257. package/registry/entries/connectors/bluebubbles.json +0 -99
  258. package/registry/entries/connectors/bluesky.json +0 -173
  259. package/registry/entries/connectors/discord.json +0 -119
  260. package/registry/entries/connectors/farcaster.json +0 -174
  261. package/registry/entries/connectors/feishu.json +0 -79
  262. package/registry/entries/connectors/google-chat.json +0 -120
  263. package/registry/entries/connectors/google.json +0 -82
  264. package/registry/entries/connectors/imessage.json +0 -96
  265. package/registry/entries/connectors/instagram.json +0 -64
  266. package/registry/entries/connectors/line.json +0 -86
  267. package/registry/entries/connectors/matrix.json +0 -94
  268. package/registry/entries/connectors/mattermost.json +0 -110
  269. package/registry/entries/connectors/msteams.json +0 -104
  270. package/registry/entries/connectors/nextcloud-talk.json +0 -104
  271. package/registry/entries/connectors/nostr.json +0 -70
  272. package/registry/entries/connectors/signal.json +0 -81
  273. package/registry/entries/connectors/slack.json +0 -102
  274. package/registry/entries/connectors/telegram.json +0 -71
  275. package/registry/entries/connectors/tlon.json +0 -94
  276. package/registry/entries/connectors/twitch.json +0 -110
  277. package/registry/entries/connectors/whatsapp.json +0 -113
  278. package/registry/entries/connectors/x.json +0 -231
  279. package/registry/entries/connectors/zalo.json +0 -112
  280. package/registry/entries/connectors/zalouser.json +0 -122
  281. package/registry/entries/plugins/agent-orchestrator.json +0 -33
  282. package/registry/entries/plugins/agent-skills.json +0 -72
  283. package/registry/entries/plugins/anthropic.json +0 -73
  284. package/registry/entries/plugins/app-control.json +0 -23
  285. package/registry/entries/plugins/auto-trader.json +0 -203
  286. package/registry/entries/plugins/background-runner.json +0 -26
  287. package/registry/entries/plugins/blooio.json +0 -102
  288. package/registry/entries/plugins/browser.json +0 -75
  289. package/registry/entries/plugins/cli.json +0 -40
  290. package/registry/entries/plugins/clipboard.json +0 -44
  291. package/registry/entries/plugins/coding-tools.json +0 -71
  292. package/registry/entries/plugins/commands.json +0 -63
  293. package/registry/entries/plugins/computeruse.json +0 -74
  294. package/registry/entries/plugins/copilot-proxy.json +0 -93
  295. package/registry/entries/plugins/directives.json +0 -63
  296. package/registry/entries/plugins/edge-tts.json +0 -97
  297. package/registry/entries/plugins/elevenlabs.json +0 -169
  298. package/registry/entries/plugins/elizacloud.json +0 -208
  299. package/registry/entries/plugins/evm.json +0 -134
  300. package/registry/entries/plugins/experience.json +0 -34
  301. package/registry/entries/plugins/facewear.json +0 -131
  302. package/registry/entries/plugins/form.json +0 -26
  303. package/registry/entries/plugins/github.json +0 -93
  304. package/registry/entries/plugins/gmail-watch.json +0 -25
  305. package/registry/entries/plugins/goals.json +0 -77
  306. package/registry/entries/plugins/google-genai.json +0 -106
  307. package/registry/entries/plugins/groq.json +0 -93
  308. package/registry/entries/plugins/hedera.json +0 -48
  309. package/registry/entries/plugins/inmemorydb.json +0 -25
  310. package/registry/entries/plugins/linear.json +0 -51
  311. package/registry/entries/plugins/local-inference.json +0 -137
  312. package/registry/entries/plugins/local-storage.json +0 -36
  313. package/registry/entries/plugins/localdb.json +0 -25
  314. package/registry/entries/plugins/mcp.json +0 -44
  315. package/registry/entries/plugins/memory.json +0 -124
  316. package/registry/entries/plugins/minecraft.json +0 -79
  317. package/registry/entries/plugins/moltbook.json +0 -83
  318. package/registry/entries/plugins/music.json +0 -155
  319. package/registry/entries/plugins/mysticism.json +0 -48
  320. package/registry/entries/plugins/nearai.json +0 -82
  321. package/registry/entries/plugins/ngrok.json +0 -69
  322. package/registry/entries/plugins/ollama.json +0 -96
  323. package/registry/entries/plugins/openai.json +0 -189
  324. package/registry/entries/plugins/openrouter.json +0 -188
  325. package/registry/entries/plugins/pdf.json +0 -26
  326. package/registry/entries/plugins/plugin-manager.json +0 -23
  327. package/registry/entries/plugins/prose.json +0 -48
  328. package/registry/entries/plugins/rlm.json +0 -26
  329. package/registry/entries/plugins/roblox.json +0 -88
  330. package/registry/entries/plugins/rss.json +0 -64
  331. package/registry/entries/plugins/s3-storage.json +0 -91
  332. package/registry/entries/plugins/scheduling.json +0 -35
  333. package/registry/entries/plugins/shell.json +0 -94
  334. package/registry/entries/plugins/social-alpha.json +0 -72
  335. package/registry/entries/plugins/tailscale.json +0 -81
  336. package/registry/entries/plugins/tee.json +0 -53
  337. package/registry/entries/plugins/todos.json +0 -26
  338. package/registry/entries/plugins/trajectory-logger.json +0 -33
  339. package/registry/entries/plugins/trust.json +0 -39
  340. package/registry/entries/plugins/tts.json +0 -71
  341. package/registry/entries/plugins/tunnel.json +0 -45
  342. package/registry/entries/plugins/twilio.json +0 -168
  343. package/registry/entries/plugins/vercel-ai-gateway.json +0 -128
  344. package/registry/entries/plugins/video.json +0 -23
  345. package/registry/entries/plugins/vision.json +0 -43
  346. package/registry/entries/plugins/webhooks.json +0 -23
  347. package/registry/entries/plugins/workflow.json +0 -25
  348. package/registry/entries/plugins/xai.json +0 -75
  349. package/registry/loader.d.ts +0 -28
  350. package/registry/loader.d.ts.map +0 -1
  351. package/registry/loader.js +0 -158
  352. package/registry/schema.d.ts +0 -1199
  353. package/registry/schema.d.ts.map +0 -1
  354. package/registry/schema.js +0 -300
  355. package/scripts/patches/llama-mobile-kokoro-tts.patch +0 -480
  356. package/scripts/release-workflow-drift.test.ts +0 -57
  357. package/test/helpers/i18n.ts +0 -5
  358. package/test/helpers/loopback.ts +0 -33
  359. package/test/helpers/react-test.ts +0 -40
  360. 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 workspaceRuntimePackageLooksBuilt(packageName, packageDir) {
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
- # The agent now starts under plain `node` (no tsx loader, #8837). If any
73
- # workspace package shipped without a built dist, link-docker-local-app-packages.mjs
74
- # rewrites its exports to ./src/*.ts, and importing that at runtime throws
75
- # ERR_UNKNOWN_FILE_EXTENSION on the core boot path. Fail fast on that signature
76
- # instead of waiting out the full health timeout.
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
- # F6 (#8812): start under plain `node` the prebuilt dist is compiled JS with
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
@@ -56,7 +56,7 @@ const MATERIALIZED_TYPE_PACKAGES = [
56
56
  "three",
57
57
  "ws",
58
58
  ];
59
- const MATERIALIZED_PACKAGES = ["bun-types"];
59
+ const MATERIALIZED_PACKAGES = ["bun-types", "csstype"];
60
60
 
61
61
  function collectBrokenBundledTypePackages() {
62
62
  const packageNames = new Set();
@@ -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\\":[\\"<|im_end|>\\"]}";
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) {