@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
@@ -1,6 +1,14 @@
1
1
  import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
2
- import { existsSync } from "node:fs";
3
- import { access, cp, mkdtemp, readFile, rm } from "node:fs/promises";
2
+ import { existsSync, rmSync } from "node:fs";
3
+ import {
4
+ access,
5
+ cp,
6
+ mkdir,
7
+ mkdtemp,
8
+ readFile,
9
+ rm,
10
+ writeFile,
11
+ } from "node:fs/promises";
4
12
  import {
5
13
  createServer,
6
14
  type IncomingMessage,
@@ -12,13 +20,22 @@ import path from "node:path";
12
20
  import { setTimeout as sleep } from "node:timers/promises";
13
21
  import { WebSocket, WebSocketServer } from "ws";
14
22
  import { buildFirstRunRuntimeConfig } from "../src/first-run/first-run-config.ts";
23
+ import { createLiveRuntimeChildEnv } from "../test/helpers/live-child-env.ts";
15
24
  import {
16
25
  getFirstRunProviderForLiveProvider,
17
- selectLiveProvider,
26
+ selectLiveProviderAsync,
18
27
  } from "../test/helpers/live-provider.ts";
19
28
  import { resolveMainAppDir } from "./lib/app-dir.mjs";
20
29
  import { shouldForceStubStack } from "./lib/ui-smoke-stub-decision.mjs";
21
30
  import { viteRendererBuildNeeded } from "./lib/vite-renderer-dist-stale.mjs";
31
+ import {
32
+ clearPendingWebSocketQueue,
33
+ createPendingWebSocketQueueState,
34
+ DEFAULT_PENDING_WEBSOCKET_QUEUE_LIMITS,
35
+ drainPendingWebSocketQueue,
36
+ enqueuePendingWebSocketMessage,
37
+ type WebSocketSendData,
38
+ } from "./lib/websocket-pending-queue.ts";
22
39
 
23
40
  const REPO_ROOT = path.resolve(import.meta.dirname, "..", "..", "..");
24
41
  const APP_DIR = resolveMainAppDir(REPO_ROOT, "app");
@@ -36,12 +53,55 @@ const UI_SMOKE_STUB_SCRIPT = path.join(
36
53
  const READY_TIMEOUT_MS = 180_000;
37
54
  const API_PORT = Number(process.env.ELIZA_UI_SMOKE_API_PORT ?? "31337");
38
55
  const UI_PORT = Number(process.env.ELIZA_UI_SMOKE_PORT ?? "2138");
39
- const LIVE_PROVIDER = selectLiveProvider();
56
+ const UI_SMOKE_RUN_ID = process.env.ELIZA_UI_SMOKE_RUN_ID?.trim() ?? "";
57
+ const LIVE_PROVIDER = await selectLiveProviderAsync();
40
58
  // Precedence (force-stub > live opt-in > CI default) lives in one tested helper.
41
59
  // The key behavior: ELIZA_UI_SMOKE_LIVE_STACK=1 overrides the CI-based stub force
42
60
  // so a genuinely-real lane is possible (GitHub Actions always sets CI=true, which
43
61
  // would otherwise re-force the stub even when a provider key was supplied).
44
62
  const FORCE_STUB_STACK = shouldForceStubStack(process.env);
63
+ const LIVE_STACK_OPTIONAL_VIEW_PLUGIN_ENTRIES = [
64
+ "calendar",
65
+ "inbox",
66
+ "todos",
67
+ "wallet-ui",
68
+ ] as const;
69
+ const LIVE_STACK_OPTIONAL_VIEW_PLUGIN_PACKAGES: ReadonlyArray<{
70
+ id: (typeof LIVE_STACK_OPTIONAL_VIEW_PLUGIN_ENTRIES)[number];
71
+ dir: string;
72
+ requiredBuildOutputs: readonly string[];
73
+ }> = [
74
+ {
75
+ id: "calendar",
76
+ dir: "plugin-calendar",
77
+ requiredBuildOutputs: [
78
+ "dist/index.js",
79
+ "dist/plugin.js",
80
+ "dist/views/bundle.js",
81
+ ],
82
+ },
83
+ {
84
+ id: "inbox",
85
+ dir: "plugin-inbox",
86
+ requiredBuildOutputs: [
87
+ "dist/index.js",
88
+ "dist/plugin.js",
89
+ "dist/views/bundle.js",
90
+ ],
91
+ },
92
+ {
93
+ id: "todos",
94
+ dir: "plugin-todos",
95
+ requiredBuildOutputs: ["dist/index.js", "dist/views/bundle.js"],
96
+ },
97
+ {
98
+ id: "wallet-ui",
99
+ dir: "plugin-wallet-ui",
100
+ requiredBuildOutputs: ["dist/index.js", "dist/views/bundle.js"],
101
+ },
102
+ ];
103
+ const pendingStateDirs = new Set<string>();
104
+ const ownedStateDirs = new Set<string>();
45
105
 
46
106
  type StartedStack = {
47
107
  apiBase: string;
@@ -51,6 +111,45 @@ type StartedStack = {
51
111
  uiServer: Server;
52
112
  };
53
113
 
114
+ async function createStateDir(prefix: string): Promise<string> {
115
+ const stateDir = await mkdtemp(path.join(os.tmpdir(), prefix));
116
+ pendingStateDirs.add(stateDir);
117
+ if (UI_SMOKE_RUN_ID) {
118
+ await writeFile(
119
+ path.join(stateDir, ".eliza-ui-smoke-run-id"),
120
+ `${UI_SMOKE_RUN_ID}\n`,
121
+ "utf8",
122
+ );
123
+ }
124
+ return stateDir;
125
+ }
126
+
127
+ function markStateDirOwnedByStack(stateDir: string): void {
128
+ pendingStateDirs.delete(stateDir);
129
+ ownedStateDirs.add(stateDir);
130
+ }
131
+
132
+ async function cleanupPendingStateDirs(): Promise<void> {
133
+ const stateDirs = Array.from(pendingStateDirs);
134
+ pendingStateDirs.clear();
135
+ await Promise.all(
136
+ stateDirs.map((stateDir) => rm(stateDir, { force: true, recursive: true })),
137
+ );
138
+ }
139
+
140
+ function cleanupKnownStateDirsSync(): void {
141
+ const stateDirs = new Set([...pendingStateDirs, ...ownedStateDirs]);
142
+ pendingStateDirs.clear();
143
+ ownedStateDirs.clear();
144
+ for (const stateDir of stateDirs) {
145
+ try {
146
+ rmSync(stateDir, { force: true, recursive: true });
147
+ } catch {
148
+ // Best effort during process teardown.
149
+ }
150
+ }
151
+ }
152
+
54
153
  function resolveBunCommand(): string {
55
154
  const bunFromEnv = process.env.BUN?.trim();
56
155
  if (bunFromEnv && existsSync(bunFromEnv)) {
@@ -268,17 +367,15 @@ function relayWebSocket(args: {
268
367
  : undefined,
269
368
  });
270
369
 
271
- const pendingClientMessages: Array<{
272
- data: Parameters<WebSocket["send"]>[0];
273
- isBinary: boolean;
274
- }> = [];
370
+ const pendingClientQueue =
371
+ createPendingWebSocketQueueState<WebSocketSendData>();
275
372
 
276
- const closeSocket = (socket: WebSocket) => {
373
+ const closeSocket = (socket: WebSocket, code?: number, reason?: string) => {
277
374
  if (
278
375
  socket.readyState === WebSocket.OPEN ||
279
376
  socket.readyState === WebSocket.CONNECTING
280
377
  ) {
281
- socket.close();
378
+ socket.close(code, reason);
282
379
  }
283
380
  };
284
381
 
@@ -288,12 +385,25 @@ function relayWebSocket(args: {
288
385
  return;
289
386
  }
290
387
  if (upstreamSocket.readyState === WebSocket.CONNECTING) {
291
- pendingClientMessages.push({ data, isBinary });
388
+ const accepted = enqueuePendingWebSocketMessage(
389
+ pendingClientQueue,
390
+ { data, isBinary },
391
+ DEFAULT_PENDING_WEBSOCKET_QUEUE_LIMITS,
392
+ );
393
+ if (!accepted) {
394
+ clearPendingWebSocketQueue(pendingClientQueue);
395
+ closeSocket(
396
+ args.clientSocket,
397
+ 1009,
398
+ "Pending websocket queue overflow",
399
+ );
400
+ closeSocket(upstreamSocket);
401
+ }
292
402
  }
293
403
  });
294
404
 
295
405
  upstreamSocket.on("open", () => {
296
- for (const message of pendingClientMessages.splice(0)) {
406
+ for (const message of drainPendingWebSocketQueue(pendingClientQueue)) {
297
407
  upstreamSocket.send(message.data, { binary: message.isBinary });
298
408
  }
299
409
  });
@@ -306,16 +416,20 @@ function relayWebSocket(args: {
306
416
  });
307
417
 
308
418
  args.clientSocket.on("close", () => {
419
+ clearPendingWebSocketQueue(pendingClientQueue);
309
420
  closeSocket(upstreamSocket);
310
421
  });
311
422
  upstreamSocket.on("close", () => {
423
+ clearPendingWebSocketQueue(pendingClientQueue);
312
424
  closeSocket(args.clientSocket);
313
425
  });
314
426
 
315
427
  args.clientSocket.on("error", () => {
428
+ clearPendingWebSocketQueue(pendingClientQueue);
316
429
  closeSocket(upstreamSocket);
317
430
  });
318
431
  upstreamSocket.on("error", () => {
432
+ clearPendingWebSocketQueue(pendingClientQueue);
319
433
  closeSocket(args.clientSocket);
320
434
  });
321
435
  }
@@ -407,6 +521,29 @@ async function waitForChildExit(
407
521
  });
408
522
  }
409
523
 
524
+ async function closeUiServer(uiServer: Server | null): Promise<void> {
525
+ if (!uiServer) return;
526
+ try {
527
+ await new Promise<void>((resolve, reject) =>
528
+ uiServer.close((error) => (error ? reject(error) : resolve())),
529
+ );
530
+ } catch {
531
+ // Best effort during shutdown.
532
+ }
533
+ }
534
+
535
+ async function stopApiChild(
536
+ apiChild: ChildProcessWithoutNullStreams | null,
537
+ ): Promise<void> {
538
+ if (!apiChild || apiChild.exitCode != null) return;
539
+ apiChild.kill("SIGTERM");
540
+ const exitedAfterTerm = await waitForChildExit(apiChild, 5_000);
541
+ if (!exitedAfterTerm && apiChild.exitCode == null) {
542
+ apiChild.kill("SIGKILL");
543
+ await waitForChildExit(apiChild, 5_000);
544
+ }
545
+ }
546
+
410
547
  async function fetchJson<T>(url: string): Promise<T> {
411
548
  const response = await fetch(url);
412
549
  if (!response.ok) {
@@ -465,6 +602,54 @@ async function waitForJsonPredicate<T>(
465
602
  : new Error(`Timed out waiting for ${url}`);
466
603
  }
467
604
 
605
+ function createProcessLogSignal(matchText: string): {
606
+ observe: (chunk: Buffer | string) => void;
607
+ wait: (timeoutMs: number, label: string) => Promise<void>;
608
+ } {
609
+ let matched = false;
610
+ let tail = "";
611
+ const waiters = new Set<() => void>();
612
+
613
+ return {
614
+ observe(chunk) {
615
+ if (matched) {
616
+ return;
617
+ }
618
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
619
+ tail = `${tail}${text}`.slice(-Math.max(matchText.length * 2, 4096));
620
+ if (!tail.includes(matchText)) {
621
+ return;
622
+ }
623
+ matched = true;
624
+ tail = "";
625
+ for (const resolve of waiters) {
626
+ resolve();
627
+ }
628
+ waiters.clear();
629
+ },
630
+ async wait(timeoutMs, label) {
631
+ if (matched) {
632
+ return;
633
+ }
634
+ await new Promise<void>((resolve, reject) => {
635
+ const timeout = setTimeout(() => {
636
+ cleanup();
637
+ reject(new Error(`Timed out waiting for ${label}`));
638
+ }, timeoutMs);
639
+ const finish = () => {
640
+ cleanup();
641
+ resolve();
642
+ };
643
+ const cleanup = () => {
644
+ clearTimeout(timeout);
645
+ waiters.delete(finish);
646
+ };
647
+ waiters.add(finish);
648
+ });
649
+ },
650
+ };
651
+ }
652
+
468
653
  async function ensureUiDistReady(): Promise<void> {
469
654
  const distIndex = path.join(APP_DIST_DIR, "index.html");
470
655
  let needsBuild = false;
@@ -605,56 +790,138 @@ async function submitFirstRun(apiBase: string): Promise<void> {
605
790
  );
606
791
  }
607
792
 
608
- async function startStubStack(): Promise<StartedStack> {
609
- const stateDir = await mkdtemp(
610
- path.join(os.tmpdir(), "eliza-ui-smoke-stub-"),
793
+ async function seedLiveStackConfig(stateDir: string): Promise<void> {
794
+ await mkdir(stateDir, { recursive: true });
795
+ const configPath = path.join(stateDir, "eliza.json");
796
+ await writeFile(
797
+ configPath,
798
+ `${JSON.stringify(
799
+ {
800
+ logging: { level: "error" },
801
+ plugins: {
802
+ entries: Object.fromEntries(
803
+ LIVE_STACK_OPTIONAL_VIEW_PLUGIN_ENTRIES.map((pluginId) => [
804
+ pluginId,
805
+ { enabled: true },
806
+ ]),
807
+ ),
808
+ },
809
+ },
810
+ null,
811
+ 2,
812
+ )}\n`,
813
+ "utf8",
611
814
  );
612
- const uiDistDir = await snapshotUiDist(stateDir);
613
- const apiBase = `http://127.0.0.1:${API_PORT}`;
614
- const apiChild = spawn("node", [UI_SMOKE_STUB_SCRIPT], {
615
- cwd: REPO_ROOT,
616
- env: {
617
- ...process.env,
618
- FORCE_COLOR: "0",
619
- ELIZA_UI_SMOKE_API_PORT: String(API_PORT),
620
- ELIZA_UI_SMOKE_STUB_IGNORE_SIGTERM: "1",
621
- },
622
- stdio: ["ignore", "pipe", "pipe"],
623
- });
815
+ }
624
816
 
625
- apiChild.stdout.on("data", (chunk) => {
626
- process.stdout.write(`[ui-smoke][stub] ${chunk}`);
627
- });
628
- apiChild.stderr.on("data", (chunk) => {
629
- process.stdout.write(`[ui-smoke][stub-err] ${chunk}`);
630
- });
817
+ async function ensureLiveStackOptionalViewPluginsReady(): Promise<void> {
818
+ for (const plugin of LIVE_STACK_OPTIONAL_VIEW_PLUGIN_PACKAGES) {
819
+ const pluginDir = path.join(REPO_ROOT, "plugins", plugin.dir);
820
+ const outputPaths = plugin.requiredBuildOutputs.map((output) =>
821
+ path.join(pluginDir, output),
822
+ );
823
+ const missingOutputPaths: string[] = [];
824
+ for (const outputPath of outputPaths) {
825
+ try {
826
+ await access(outputPath);
827
+ } catch {
828
+ missingOutputPaths.push(outputPath);
829
+ }
830
+ }
831
+ if (missingOutputPaths.length === 0) continue;
631
832
 
632
- await waitForJson<{ complete: boolean }>(`${apiBase}/api/first-run/status`);
633
- await waitForJsonPredicate<{ state?: string }>(
634
- `${apiBase}/api/status`,
635
- (status) => status.state === "running",
636
- READY_TIMEOUT_MS,
637
- );
638
- await waitForJsonPredicate<{ session?: { kind?: string } }>(
639
- `${apiBase}/api/auth/me`,
640
- (me) => me.session?.kind === "local",
641
- READY_TIMEOUT_MS,
642
- );
833
+ const logs: string[] = [];
834
+ const child = spawn(resolveBunCommand(), ["run", "build"], {
835
+ cwd: pluginDir,
836
+ env: {
837
+ ...process.env,
838
+ FORCE_COLOR: "0",
839
+ },
840
+ stdio: ["ignore", "pipe", "pipe"],
841
+ });
842
+ child.stdout.on("data", (chunk) => logs.push(String(chunk)));
843
+ child.stderr.on("data", (chunk) => logs.push(String(chunk)));
643
844
 
644
- const uiServer = await startUiProxyServer({
645
- apiBase,
646
- port: UI_PORT,
647
- uiDistDir,
648
- });
649
- process.env.ELIZA_API_PORT = String(API_PORT);
845
+ const BUILD_TIMEOUT_MS = 300_000;
846
+ const exited = await waitForChildExit(child, BUILD_TIMEOUT_MS);
847
+ if (!exited) {
848
+ child.kill("SIGKILL");
849
+ throw new Error(
850
+ `Timed out building optional live-stack plugin ${plugin.id} after ${BUILD_TIMEOUT_MS}ms.\n${logs.join("").slice(-8_000)}`,
851
+ );
852
+ }
853
+ if (child.exitCode !== 0) {
854
+ throw new Error(
855
+ `Failed to build optional live-stack plugin ${plugin.id}.\n${logs.join("").slice(-8_000)}`,
856
+ );
857
+ }
858
+ for (const outputPath of outputPaths) {
859
+ await access(outputPath);
860
+ }
861
+ }
862
+ }
650
863
 
651
- return {
652
- apiBase,
653
- apiChild,
654
- stateDir,
655
- uiBase: `http://127.0.0.1:${UI_PORT}`,
656
- uiServer,
657
- };
864
+ async function startStubStack(): Promise<StartedStack> {
865
+ const stateDir = await createStateDir("eliza-ui-smoke-stub-");
866
+ let apiChild: ChildProcessWithoutNullStreams | null = null;
867
+ let uiServer: Server | null = null;
868
+ try {
869
+ const uiDistDir = await snapshotUiDist(stateDir);
870
+ const apiBase = `http://127.0.0.1:${API_PORT}`;
871
+ apiChild = spawn("node", [UI_SMOKE_STUB_SCRIPT], {
872
+ cwd: REPO_ROOT,
873
+ env: {
874
+ ...process.env,
875
+ FORCE_COLOR: "0",
876
+ ELIZA_UI_SMOKE_API_PORT: String(API_PORT),
877
+ ELIZA_UI_SMOKE_STUB_IGNORE_SIGTERM: "1",
878
+ },
879
+ stdio: ["ignore", "pipe", "pipe"],
880
+ });
881
+
882
+ apiChild.stdout.on("data", (chunk) => {
883
+ process.stdout.write(`[ui-smoke][stub] ${chunk}`);
884
+ });
885
+ apiChild.stderr.on("data", (chunk) => {
886
+ process.stdout.write(`[ui-smoke][stub-err] ${chunk}`);
887
+ });
888
+
889
+ await waitForJson<{ complete: boolean }>(`${apiBase}/api/first-run/status`);
890
+ await waitForJsonPredicate<{ state?: string }>(
891
+ `${apiBase}/api/status`,
892
+ (status) => status.state === "running",
893
+ READY_TIMEOUT_MS,
894
+ );
895
+ await waitForJsonPredicate<{ session?: { kind?: string } }>(
896
+ `${apiBase}/api/auth/me`,
897
+ (me) => me.session?.kind === "local",
898
+ READY_TIMEOUT_MS,
899
+ );
900
+
901
+ uiServer = await startUiProxyServer({
902
+ apiBase,
903
+ port: UI_PORT,
904
+ uiDistDir,
905
+ });
906
+ process.env.ELIZA_API_PORT = String(API_PORT);
907
+ markStateDirOwnedByStack(stateDir);
908
+ const startedApiChild = apiChild;
909
+ const startedUiServer = uiServer;
910
+
911
+ return {
912
+ apiBase,
913
+ apiChild: startedApiChild,
914
+ stateDir,
915
+ uiBase: `http://127.0.0.1:${UI_PORT}`,
916
+ uiServer: startedUiServer,
917
+ };
918
+ } catch (error) {
919
+ await closeUiServer(uiServer);
920
+ await stopApiChild(apiChild);
921
+ await rm(stateDir, { force: true, recursive: true });
922
+ pendingStateDirs.delete(stateDir);
923
+ throw error;
924
+ }
658
925
  }
659
926
 
660
927
  async function startRealStack(): Promise<StartedStack> {
@@ -664,84 +931,112 @@ async function startRealStack(): Promise<StartedStack> {
664
931
  return startStubStack();
665
932
  }
666
933
 
667
- const stateDir = await mkdtemp(
668
- path.join(os.tmpdir(), "eliza-ui-smoke-live-"),
669
- );
670
- const uiDistDir = await snapshotUiDist(stateDir);
671
- const apiBase = `http://127.0.0.1:${API_PORT}`;
672
- const apiChild = spawn(
673
- "node",
674
- [
675
- path.join(REPO_ROOT, "packages/app-core/scripts/run-node-tsx.mjs"),
676
- path.join(REPO_ROOT, "packages/app-core/src/runtime/eliza.ts"),
677
- ],
678
- {
679
- cwd: REPO_ROOT,
680
- env: {
681
- ...process.env,
682
- ALLOW_NO_DATABASE: "",
683
- FORCE_COLOR: "0",
684
- ELIZA_API_PORT: String(API_PORT),
685
- ELIZA_HOME_PORT: String(UI_PORT),
686
- ELIZA_PORT: String(API_PORT),
687
- ELIZA_STATE_DIR: stateDir,
934
+ await ensureLiveStackOptionalViewPluginsReady();
935
+
936
+ const stateDir = await createStateDir("eliza-ui-smoke-live-");
937
+ let apiChild: ChildProcessWithoutNullStreams | null = null;
938
+ let uiServer: Server | null = null;
939
+ try {
940
+ await seedLiveStackConfig(stateDir);
941
+ const uiDistDir = await snapshotUiDist(stateDir);
942
+ const apiBase = `http://127.0.0.1:${API_PORT}`;
943
+ const deferredBootComplete = createProcessLogSignal(
944
+ "[eliza-boot] deferred:complete",
945
+ );
946
+ apiChild = spawn(
947
+ "node",
948
+ [
949
+ path.join(REPO_ROOT, "packages/app-core/scripts/run-node-tsx.mjs"),
950
+ path.join(REPO_ROOT, "packages/app-core/src/runtime/eliza.ts"),
951
+ ],
952
+ {
953
+ cwd: REPO_ROOT,
954
+ env: createLiveRuntimeChildEnv({
955
+ ...(LIVE_PROVIDER?.env ?? {}),
956
+ ALLOW_NO_DATABASE: "",
957
+ FORCE_COLOR: "0",
958
+ ELIZA_API_PORT: String(API_PORT),
959
+ ELIZA_HOME_PORT: String(UI_PORT),
960
+ ELIZA_PORT: String(API_PORT),
961
+ ELIZA_STATE_DIR: stateDir,
962
+ }),
963
+ stdio: ["ignore", "pipe", "pipe"],
688
964
  },
689
- stdio: ["ignore", "pipe", "pipe"],
690
- },
691
- );
965
+ );
692
966
 
693
- apiChild.stdout.on("data", (chunk) => {
694
- process.stdout.write(`[ui-smoke][api] ${chunk}`);
695
- });
696
- apiChild.stderr.on("data", (chunk) => {
697
- process.stdout.write(`[ui-smoke][api-err] ${chunk}`);
698
- });
967
+ apiChild.stdout.on("data", (chunk) => {
968
+ deferredBootComplete.observe(chunk);
969
+ process.stdout.write(`[ui-smoke][api] ${chunk}`);
970
+ });
971
+ apiChild.stderr.on("data", (chunk) => {
972
+ deferredBootComplete.observe(chunk);
973
+ process.stdout.write(`[ui-smoke][api-err] ${chunk}`);
974
+ });
699
975
 
700
- await waitForJson<{ complete: boolean }>(`${apiBase}/api/first-run/status`);
701
- // Cloud-live mode (ELIZA_UI_SMOKE_CLOUD_LIVE=1) leaves first-run UNcompleted so
702
- // the spec can drive the real cloud onboarding (login -> provision) through the
703
- // UI against real Eliza Cloud. The default lane auto-completes a local first-run
704
- // so chat/view specs land on a ready agent.
705
- const skipAutoFirstRun = process.env.ELIZA_UI_SMOKE_CLOUD_LIVE === "1";
706
- if (!skipAutoFirstRun) {
707
- const onboardingStatus = await fetchJson<{ complete: boolean }>(
708
- `${apiBase}/api/first-run/status`,
709
- );
710
- if (!onboardingStatus.complete) {
711
- await submitFirstRun(apiBase);
712
- }
976
+ await waitForJson<{ complete: boolean }>(`${apiBase}/api/first-run/status`);
977
+ // Cloud-live mode (ELIZA_UI_SMOKE_CLOUD_LIVE=1) leaves first-run UNcompleted so
978
+ // the spec can drive the real cloud onboarding (login -> provision) through the
979
+ // UI against real Eliza Cloud. The default lane auto-completes a local first-run
980
+ // so chat/view specs land on a ready agent.
981
+ const skipAutoFirstRun = process.env.ELIZA_UI_SMOKE_CLOUD_LIVE === "1";
982
+ if (!skipAutoFirstRun) {
983
+ const onboardingStatus = await fetchJson<{ complete: boolean }>(
984
+ `${apiBase}/api/first-run/status`,
985
+ );
986
+ if (!onboardingStatus.complete) {
987
+ await submitFirstRun(apiBase);
988
+ }
713
989
 
714
- await waitForJsonPredicate<{ complete: boolean }>(
715
- `${apiBase}/api/first-run/status`,
716
- (status) => status.complete === true,
990
+ await waitForJsonPredicate<{ complete: boolean }>(
991
+ `${apiBase}/api/first-run/status`,
992
+ (status) => status.complete === true,
993
+ READY_TIMEOUT_MS,
994
+ );
995
+ }
996
+ await waitForJsonPredicate<{ state?: string }>(
997
+ `${apiBase}/api/status`,
998
+ (status) => status.state === "running",
717
999
  READY_TIMEOUT_MS,
718
1000
  );
719
- }
720
- await waitForJsonPredicate<{ state?: string }>(
721
- `${apiBase}/api/status`,
722
- (status) => status.state === "running",
723
- READY_TIMEOUT_MS,
724
- );
725
- await waitForJsonPredicate<{ session?: { kind?: string } }>(
726
- `${apiBase}/api/auth/me`,
727
- (me) => me.session?.kind === "local",
728
- READY_TIMEOUT_MS,
729
- );
730
-
731
- const uiServer = await startUiProxyServer({
732
- apiBase,
733
- port: UI_PORT,
734
- uiDistDir,
735
- });
736
- process.env.ELIZA_API_PORT = String(API_PORT);
1001
+ await waitForJsonPredicate<{ session?: { kind?: string } }>(
1002
+ `${apiBase}/api/auth/me`,
1003
+ (me) => me.session?.kind === "local",
1004
+ READY_TIMEOUT_MS,
1005
+ );
1006
+ if (!skipAutoFirstRun) {
1007
+ // App-control and plugin views are deferred capabilities. Treat the live
1008
+ // harness as ready only after those runtime plugins have had a chance to
1009
+ // register; otherwise chat-driven view switching can race boot.
1010
+ await deferredBootComplete.wait(
1011
+ READY_TIMEOUT_MS,
1012
+ "deferred runtime plugin registration",
1013
+ );
1014
+ }
737
1015
 
738
- return {
739
- apiBase,
740
- apiChild,
741
- stateDir,
742
- uiBase: `http://127.0.0.1:${UI_PORT}`,
743
- uiServer,
744
- };
1016
+ uiServer = await startUiProxyServer({
1017
+ apiBase,
1018
+ port: UI_PORT,
1019
+ uiDistDir,
1020
+ });
1021
+ process.env.ELIZA_API_PORT = String(API_PORT);
1022
+ markStateDirOwnedByStack(stateDir);
1023
+ const startedApiChild = apiChild;
1024
+ const startedUiServer = uiServer;
1025
+
1026
+ return {
1027
+ apiBase,
1028
+ apiChild: startedApiChild,
1029
+ stateDir,
1030
+ uiBase: `http://127.0.0.1:${UI_PORT}`,
1031
+ uiServer: startedUiServer,
1032
+ };
1033
+ } catch (error) {
1034
+ await closeUiServer(uiServer);
1035
+ await stopApiChild(apiChild);
1036
+ await rm(stateDir, { force: true, recursive: true });
1037
+ pendingStateDirs.delete(stateDir);
1038
+ throw error;
1039
+ }
745
1040
  }
746
1041
 
747
1042
  async function stopRealStack(stack: StartedStack | null): Promise<void> {
@@ -749,35 +1044,25 @@ async function stopRealStack(stack: StartedStack | null): Promise<void> {
749
1044
  return;
750
1045
  }
751
1046
 
752
- try {
753
- await new Promise<void>((resolve, reject) =>
754
- stack.uiServer.close((error) => (error ? reject(error) : resolve())),
755
- );
756
- } catch {
757
- // Best effort during shutdown.
758
- }
759
-
760
- if (stack.apiChild.exitCode == null) {
761
- stack.apiChild.kill("SIGTERM");
762
- const exitedAfterTerm = await waitForChildExit(stack.apiChild, 5_000);
763
- if (!exitedAfterTerm && stack.apiChild.exitCode == null) {
764
- stack.apiChild.kill("SIGKILL");
765
- await waitForChildExit(stack.apiChild, 5_000);
766
- }
767
- }
1047
+ await closeUiServer(stack.uiServer);
1048
+ await stopApiChild(stack.apiChild);
768
1049
 
769
1050
  await rm(stack.stateDir, { force: true, recursive: true });
1051
+ ownedStateDirs.delete(stack.stateDir);
770
1052
  }
771
1053
 
772
1054
  let stack: StartedStack | null = null;
773
1055
  let shuttingDown = false;
774
1056
 
1057
+ process.once("exit", cleanupKnownStateDirsSync);
1058
+
775
1059
  async function shutdown(exitCode: number): Promise<void> {
776
1060
  if (shuttingDown) {
777
1061
  return;
778
1062
  }
779
1063
  shuttingDown = true;
780
1064
  await stopRealStack(stack);
1065
+ await cleanupPendingStateDirs();
781
1066
  process.exit(exitCode);
782
1067
  }
783
1068
 
@@ -808,5 +1093,6 @@ try {
808
1093
  }`,
809
1094
  );
810
1095
  await stopRealStack(stack);
1096
+ await cleanupPendingStateDirs();
811
1097
  process.exit(1);
812
1098
  }