@elizaos/app-core 2.0.0-beta.3 → 2.0.3-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1466) hide show
  1. package/agent-bridge.d.ts +27 -0
  2. package/agent-bridge.d.ts.map +1 -0
  3. package/agent-bridge.js +26 -0
  4. package/api/__tests__/sandbox-test-helpers.js +1 -1
  5. package/api/auth/audit.d.ts +1 -1
  6. package/api/auth/audit.js +1 -1
  7. package/api/auth/auth-context.d.ts +1 -1
  8. package/api/auth/auth-context.js +1 -1
  9. package/api/auth/bootstrap-token.d.ts +1 -1
  10. package/api/auth/bootstrap-token.js +2 -2
  11. package/api/auth/index.d.ts +9 -10
  12. package/api/auth/index.d.ts.map +1 -1
  13. package/api/auth/index.js +9 -10
  14. package/api/auth/passwords.js +2 -2
  15. package/api/auth/sensitive-rate-limit.d.ts +1 -4
  16. package/api/auth/sensitive-rate-limit.d.ts.map +1 -1
  17. package/api/auth/sensitive-rate-limit.js +6 -6
  18. package/api/auth/sessions.d.ts +1 -1
  19. package/api/auth/sessions.js +2 -2
  20. package/api/auth-bootstrap-routes.d.ts +7 -14
  21. package/api/auth-bootstrap-routes.d.ts.map +1 -1
  22. package/api/auth-bootstrap-routes.js +14 -27
  23. package/api/auth-pairing-routes.d.ts +17 -0
  24. package/api/auth-pairing-routes.d.ts.map +1 -0
  25. package/api/auth-pairing-routes.js +299 -0
  26. package/api/auth-session-routes.d.ts +2 -2
  27. package/api/auth-session-routes.d.ts.map +1 -1
  28. package/api/auth-session-routes.js +36 -15
  29. package/api/auth.d.ts +13 -20
  30. package/api/auth.d.ts.map +1 -1
  31. package/api/auth.js +32 -27
  32. package/api/automations-compat-routes.d.ts +1 -1
  33. package/api/automations-compat-routes.d.ts.map +1 -1
  34. package/api/automations-compat-routes.js +5 -5
  35. package/api/background-tasks-routes.d.ts +4 -0
  36. package/api/background-tasks-routes.d.ts.map +1 -0
  37. package/api/background-tasks-routes.js +63 -0
  38. package/api/catalog-routes.d.ts +1 -1
  39. package/api/catalog-routes.js +3 -3
  40. package/api/cloud-pair-route.d.ts +26 -0
  41. package/api/cloud-pair-route.d.ts.map +1 -0
  42. package/api/cloud-pair-route.js +222 -0
  43. package/api/cloud-voice-routes.d.ts +52 -0
  44. package/api/cloud-voice-routes.d.ts.map +1 -0
  45. package/api/cloud-voice-routes.js +50 -0
  46. package/api/compat-route-shared.d.ts +14 -7
  47. package/api/compat-route-shared.d.ts.map +1 -1
  48. package/api/compat-route-shared.js +27 -188
  49. package/api/credential-resolver.d.ts +2 -2
  50. package/api/credential-resolver.d.ts.map +1 -1
  51. package/api/credential-resolver.js +8 -2
  52. package/api/database-rows-compat-routes.d.ts +1 -1
  53. package/api/database-rows-compat-routes.d.ts.map +1 -1
  54. package/api/database-rows-compat-routes.js +69 -31
  55. package/api/dev-boot-history.d.ts +26 -0
  56. package/api/dev-boot-history.d.ts.map +1 -0
  57. package/api/dev-boot-history.js +69 -0
  58. package/api/dev-compat-routes.d.ts +6 -1
  59. package/api/dev-compat-routes.d.ts.map +1 -1
  60. package/api/dev-compat-routes.js +127 -4
  61. package/api/dev-console-log.d.ts +2 -2
  62. package/api/dev-console-log.d.ts.map +1 -1
  63. package/api/dev-console-log.js +8 -5
  64. package/api/dev-route-catalog.d.ts +58 -0
  65. package/api/dev-route-catalog.d.ts.map +1 -0
  66. package/api/dev-route-catalog.js +477 -0
  67. package/api/dev-stack.d.ts.map +1 -1
  68. package/api/dev-stack.js +6 -9
  69. package/api/drop-status-compat-route.d.ts +3 -0
  70. package/api/drop-status-compat-route.d.ts.map +1 -0
  71. package/api/drop-status-compat-route.js +12 -0
  72. package/api/first-run-routes.d.ts +4 -0
  73. package/api/first-run-routes.d.ts.map +1 -0
  74. package/api/first-run-routes.js +208 -0
  75. package/api/first-run-tts-route.d.ts +19 -0
  76. package/api/first-run-tts-route.d.ts.map +1 -0
  77. package/api/first-run-tts-route.js +59 -0
  78. package/api/internal-routes.d.ts +23 -0
  79. package/api/internal-routes.d.ts.map +1 -0
  80. package/api/internal-routes.js +203 -0
  81. package/api/ios-local-agent-transport.d.ts +36 -0
  82. package/api/ios-local-agent-transport.d.ts.map +1 -0
  83. package/api/ios-local-agent-transport.js +566 -0
  84. package/api/onboarding-voice-lines.d.ts +23 -0
  85. package/api/onboarding-voice-lines.d.ts.map +1 -0
  86. package/api/onboarding-voice-lines.js +8 -0
  87. package/api/perf-instrument.d.ts +43 -0
  88. package/api/perf-instrument.d.ts.map +1 -0
  89. package/api/perf-instrument.js +113 -0
  90. package/api/response.d.ts.map +1 -1
  91. package/api/response.js +14 -14
  92. package/api/runtime-mode-routes.d.ts +1 -1
  93. package/api/runtime-mode-routes.d.ts.map +1 -1
  94. package/api/runtime-mode-routes.js +2 -2
  95. package/api/secrets-inventory-routes.js +2 -2
  96. package/api/secrets-manager-routes.d.ts +1 -1
  97. package/api/secrets-manager-routes.d.ts.map +1 -1
  98. package/api/secrets-manager-routes.js +9 -10
  99. package/api/sensitive-request-routes.d.ts +2 -2
  100. package/api/sensitive-request-routes.js +5 -5
  101. package/api/server-config-filter.d.ts.map +1 -1
  102. package/api/server-config-filter.js +0 -1
  103. package/api/server-cors.d.ts.map +1 -1
  104. package/api/server-cors.js +13 -2
  105. package/api/server-first-run-helpers.d.ts +26 -0
  106. package/api/server-first-run-helpers.d.ts.map +1 -0
  107. package/api/server-first-run-helpers.js +268 -0
  108. package/api/server-security.js +1 -1
  109. package/api/server-startup.d.ts.map +1 -1
  110. package/api/server-startup.js +3 -4
  111. package/api/server-wallet-trade.js +1 -1
  112. package/api/server.d.ts +11 -11
  113. package/api/server.d.ts.map +1 -1
  114. package/api/server.js +227 -139
  115. package/api/setup-contract.d.ts +63 -0
  116. package/api/setup-contract.d.ts.map +1 -0
  117. package/api/setup-contract.js +39 -0
  118. package/api/training-benchmarks.d.ts +97 -0
  119. package/api/training-benchmarks.d.ts.map +1 -0
  120. package/api/training-benchmarks.js +329 -0
  121. package/api/workbench-compat-routes.d.ts +1 -1
  122. package/api/workbench-compat-routes.js +2 -2
  123. package/benchmark/cerebras-autowire.d.ts +28 -0
  124. package/benchmark/cerebras-autowire.d.ts.map +1 -0
  125. package/benchmark/cerebras-autowire.js +62 -0
  126. package/benchmark/lifeops-bench-handler.d.ts +36 -0
  127. package/benchmark/lifeops-bench-handler.d.ts.map +1 -1
  128. package/benchmark/lifeops-bench-handler.js +63 -1
  129. package/benchmark/lifeops-fake-backend.d.ts +39 -0
  130. package/benchmark/lifeops-fake-backend.d.ts.map +1 -1
  131. package/benchmark/lifeops-fake-backend.js +993 -21
  132. package/benchmark/mock-plugin.d.ts.map +1 -1
  133. package/benchmark/mock-plugin.js +0 -24
  134. package/benchmark/plugin.d.ts +2 -1
  135. package/benchmark/plugin.d.ts.map +1 -1
  136. package/benchmark/plugin.js +989 -68
  137. package/benchmark/replay-capture.d.ts +2 -2
  138. package/benchmark/replay-capture.d.ts.map +1 -1
  139. package/benchmark/replay-capture.js +3 -3
  140. package/benchmark/server-utils.d.ts +164 -11
  141. package/benchmark/server-utils.d.ts.map +1 -1
  142. package/benchmark/server-utils.js +625 -62
  143. package/benchmark/server.d.ts.map +1 -1
  144. package/benchmark/server.js +1962 -118
  145. package/boot-profile.d.ts +3 -0
  146. package/boot-profile.d.ts.map +1 -0
  147. package/boot-profile.js +30 -0
  148. package/browser.d.ts +23 -1
  149. package/browser.d.ts.map +1 -1
  150. package/browser.js +20 -1
  151. package/cli/argv.js +1 -1
  152. package/cli/banner.js +1 -1
  153. package/cli/command-format.js +2 -2
  154. package/cli/doctor/checks.d.ts.map +1 -1
  155. package/cli/doctor/checks.js +6 -6
  156. package/cli/plugins-cli.d.ts.map +1 -1
  157. package/cli/plugins-cli.js +82 -32
  158. package/cli/profile.d.ts.map +1 -1
  159. package/cli/profile.js +5 -4
  160. package/cli/program/build-program.js +4 -4
  161. package/cli/program/command-registry.d.ts.map +1 -1
  162. package/cli/program/command-registry.js +13 -11
  163. package/cli/program/help.js +5 -5
  164. package/cli/program/preaction.js +5 -5
  165. package/cli/program/register.auth.d.ts +27 -1
  166. package/cli/program/register.auth.d.ts.map +1 -1
  167. package/cli/program/register.auth.js +193 -12
  168. package/cli/program/register.capability-router.d.ts +29 -0
  169. package/cli/program/register.capability-router.d.ts.map +1 -0
  170. package/cli/program/register.capability-router.js +568 -0
  171. package/cli/program/register.config.js +1 -1
  172. package/cli/program/register.configure.d.ts.map +1 -1
  173. package/cli/program/register.configure.js +1 -1
  174. package/cli/program/register.dashboard.d.ts.map +1 -1
  175. package/cli/program/register.dashboard.js +17 -8
  176. package/cli/program/register.db.d.ts.map +1 -1
  177. package/cli/program/register.db.js +3 -4
  178. package/cli/program/register.doctor.js +7 -7
  179. package/cli/program/register.setup.d.ts.map +1 -1
  180. package/cli/program/register.setup.js +14 -10
  181. package/cli/program/register.start.d.ts.map +1 -1
  182. package/cli/program/register.start.js +5 -3
  183. package/cli/program/register.subclis.js +3 -3
  184. package/cli/program/register.update.d.ts +6 -0
  185. package/cli/program/register.update.d.ts.map +1 -1
  186. package/cli/program/register.update.js +58 -6
  187. package/cli/program.d.ts +1 -1
  188. package/cli/program.js +1 -1
  189. package/cli/run-main.js +4 -4
  190. package/config/app-config.d.ts +2 -0
  191. package/config/app-config.d.ts.map +1 -0
  192. package/config/app-config.js +1 -0
  193. package/connectors/capacitor-jsc.d.ts.map +1 -1
  194. package/connectors/capacitor-jsc.js +16 -10
  195. package/connectors/capacitor-quickjs.d.ts.map +1 -1
  196. package/connectors/capacitor-quickjs.js +18 -13
  197. package/connectors/capacitor-sqlite.d.ts.map +1 -1
  198. package/connectors/capacitor-sqlite.js +27 -12
  199. package/dispatch/approval-queue.d.ts +37 -0
  200. package/dispatch/approval-queue.d.ts.map +1 -0
  201. package/dispatch/approval-queue.js +25 -0
  202. package/dispatch/channel-registry.d.ts +30 -0
  203. package/dispatch/channel-registry.d.ts.map +1 -0
  204. package/dispatch/channel-registry.js +22 -0
  205. package/dispatch/connector-registry.d.ts +39 -0
  206. package/dispatch/connector-registry.d.ts.map +1 -0
  207. package/dispatch/connector-registry.js +24 -0
  208. package/dispatch/index.d.ts +14 -0
  209. package/dispatch/index.d.ts.map +1 -0
  210. package/dispatch/index.js +13 -0
  211. package/dispatch/send-policy.d.ts +36 -0
  212. package/dispatch/send-policy.d.ts.map +1 -0
  213. package/dispatch/send-policy.js +16 -0
  214. package/entry.js +28 -11
  215. package/first-run/first-run-config.d.ts +55 -0
  216. package/first-run/first-run-config.d.ts.map +1 -0
  217. package/first-run/first-run-config.js +178 -0
  218. package/first-run/runtime-target.d.ts +4 -0
  219. package/first-run/runtime-target.d.ts.map +1 -0
  220. package/first-run/runtime-target.js +13 -0
  221. package/index.d.ts +46 -34
  222. package/index.d.ts.map +1 -1
  223. package/index.js +53 -33
  224. package/package.json +166 -51
  225. package/packaging/PUBLISHING_GUIDE.md +20 -20
  226. package/packaging/debian/apt-repo-config/README.md +18 -0
  227. package/packaging/debian/apt-repo-config/conf/distributions +11 -0
  228. package/packaging/flatpak/README.md +26 -16
  229. package/packaging/flatpak/ai.elizaos.App.metainfo.xml +17 -12
  230. package/packaging/flatpak/ai.elizaos.App.store.yml +5 -5
  231. package/packaging/flatpak/ai.elizaos.App.yml +10 -24
  232. package/packaging/flatpak/elizaos-app-wrapper.store.sh +2 -2
  233. package/packaging/flatpak/generate-sources.sh +74 -0
  234. package/packaging/flatpak/node-sources.json +7930 -0
  235. package/packaging/inno/build-inno.ps1 +34 -9
  236. package/packaging/msix/AppxManifest.store.xml +1 -1
  237. package/packaging/msix/README.md +39 -19
  238. package/packaging/msix/build-msix.ps1 +44 -14
  239. package/packaging/snap/snapcraft.yaml +22 -21
  240. package/packaging/test-packaging.sh +2 -2
  241. package/permissions/types.d.ts +1 -1
  242. package/permissions/types.js +1 -1
  243. package/platform/elizaos-agent-browser-stub.d.ts +143 -0
  244. package/platform/elizaos-agent-browser-stub.d.ts.map +1 -0
  245. package/platform/elizaos-agent-browser-stub.js +157 -0
  246. package/platform/elizaos-plugin-elizacloud-browser-stub.d.ts +34 -0
  247. package/platform/elizaos-plugin-elizacloud-browser-stub.d.ts.map +1 -0
  248. package/platform/elizaos-plugin-elizacloud-browser-stub.js +51 -0
  249. package/platform/empty-node-module.d.ts +148 -0
  250. package/platform/empty-node-module.d.ts.map +1 -1
  251. package/platform/empty-node-module.js +140 -3
  252. package/platform/ios-runtime-backends.d.ts +83 -0
  253. package/platform/ios-runtime-backends.d.ts.map +1 -0
  254. package/platform/ios-runtime-backends.js +133 -0
  255. package/platform/ios-runtime-bridge.d.ts +15 -0
  256. package/platform/ios-runtime-bridge.d.ts.map +1 -0
  257. package/platform/ios-runtime-bridge.js +526 -0
  258. package/platform/native-library-policy.d.ts +23 -0
  259. package/platform/native-library-policy.d.ts.map +1 -0
  260. package/platform/native-library-policy.js +112 -0
  261. package/platform/native-plugin-entrypoints.d.ts +19 -0
  262. package/platform/native-plugin-entrypoints.d.ts.map +1 -0
  263. package/platform/native-plugin-entrypoints.js +29 -0
  264. package/platforms/android/README.md +68 -10
  265. package/platforms/android/app/build.gradle +291 -3
  266. package/platforms/android/app/capacitor.build.gradle +18 -1
  267. package/platforms/android/app/proguard-rules.pro +17 -2
  268. package/platforms/android/app/src/androidTest/java/ai/elizaos/app/ElizaOsInstrumentedTest.java +1 -1
  269. package/platforms/android/app/src/main/AndroidManifest.xml +335 -18
  270. package/platforms/android/app/src/main/assets/runners/eliza-tasks.js +177 -0
  271. package/platforms/android/app/src/main/elizavoice-jni/CMakeLists.txt +100 -0
  272. package/platforms/android/app/src/main/elizavoice-jni/elizavoice-jni.cpp +1629 -0
  273. package/platforms/android/app/src/main/java/ai/elizaos/app/AgentPlugin.java +111 -171
  274. package/platforms/android/app/src/main/java/ai/elizaos/app/AndroidVirtualizationBridge.java +284 -0
  275. package/platforms/android/app/src/main/java/ai/elizaos/app/BatteryOptimizationPlugin.java +95 -0
  276. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAccessibilityService.java +55 -0
  277. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAgentService.java +1283 -141
  278. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAndroidSystemBridge.java +83 -0
  279. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAssistActivity.java +50 -1
  280. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBionicInferenceServer.java +740 -0
  281. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBootReceiver.java +90 -8
  282. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaBrowserActivity.java +2 -2
  283. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaCalendarActivity.java +1 -1
  284. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaCameraActivity.java +1 -1
  285. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaClockActivity.java +2 -2
  286. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaContactsActivity.java +1 -1
  287. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaDialActivity.java +1 -1
  288. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaInCallService.java +1 -1
  289. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaMmsReceiver.java +1 -1
  290. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaNativeBridge.java +22 -0
  291. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaNotificationListenerService.java +45 -0
  292. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaQuickActionsWidgetProvider.java +68 -0
  293. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaShareActivity.java +132 -0
  294. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaSmsComposeActivity.java +1 -1
  295. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaSmsGatewayService.java +268 -0
  296. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaSmsReceiver.java +12 -1
  297. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaTasksWorker.java +194 -0
  298. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceCaptureService.java +198 -0
  299. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceNative.java +255 -0
  300. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoicePlugin.java +505 -0
  301. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoiceTileService.java +39 -0
  302. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaWorkScheduler.java +60 -0
  303. package/platforms/android/app/src/main/java/ai/elizaos/app/GatewayConnectionService.java +53 -19
  304. package/platforms/android/app/src/main/java/ai/elizaos/app/MainActivity.java +160 -33
  305. package/platforms/android/app/src/main/java/ai/elizaos/app/ResourceProbePlugin.java +169 -0
  306. package/platforms/android/app/src/main/java/ai/elizaos/app/VoiceCapturePlugin.java +119 -0
  307. package/platforms/android/app/src/main/res/drawable/eliza_widget_background.xml +10 -0
  308. package/platforms/android/app/src/main/res/drawable/eliza_widget_button_background.xml +13 -0
  309. package/platforms/android/app/src/main/res/drawable/splash.png +0 -0
  310. package/platforms/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
  311. package/platforms/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
  312. package/platforms/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
  313. package/platforms/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
  314. package/platforms/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
  315. package/platforms/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
  316. package/platforms/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
  317. package/platforms/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
  318. package/platforms/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
  319. package/platforms/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
  320. package/platforms/android/app/src/main/res/layout/eliza_quick_actions_widget.xml +86 -0
  321. package/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +2 -1
  322. package/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +2 -1
  323. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  324. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  325. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png +0 -0
  326. package/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  327. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  328. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  329. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png +0 -0
  330. package/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  331. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  332. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  333. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png +0 -0
  334. package/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  335. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  336. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  337. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png +0 -0
  338. package/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  339. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  340. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  341. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png +0 -0
  342. package/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  343. package/platforms/android/app/src/main/res/values/android_app_actions.xml +48 -0
  344. package/platforms/android/app/src/main/res/values/colors.xml +12 -0
  345. package/platforms/android/app/src/main/res/values/ic_launcher_background.xml +2 -2
  346. package/platforms/android/app/src/main/res/values/strings.xml +2 -2
  347. package/platforms/android/app/src/main/res/values/styles.xml +28 -1
  348. package/platforms/android/app/src/main/res/xml/eliza_accessibility_service.xml +9 -0
  349. package/platforms/android/app/src/main/res/xml/eliza_quick_actions_widget.xml +13 -0
  350. package/platforms/android/app/src/main/res/xml/shortcuts.xml +121 -0
  351. package/platforms/android/build.gradle +2 -2
  352. package/platforms/android/capacitor-cordova-android-plugins/build.gradle +9 -3
  353. package/platforms/android/capacitor-cordova-android-plugins/cordova.variables.gradle +6 -2
  354. package/platforms/android/capacitor-cordova-android-plugins/src/main/AndroidManifest.xml +7 -2
  355. package/platforms/android/capacitor-cordova-android-plugins/src/main/java/.gitkeep +0 -1
  356. package/platforms/android/capacitor.settings.gradle +66 -16
  357. package/platforms/android/gradle.properties +1 -0
  358. package/platforms/android/update-manifest/generate-manifest.mjs +97 -0
  359. package/platforms/android/update-manifest/schema.json +26 -0
  360. package/platforms/apple-store-entitlements.reviewed.json +155 -0
  361. package/platforms/electrobun/.generated/brand-config.json +3 -2
  362. package/platforms/electrobun/LICENSE +21 -0
  363. package/platforms/electrobun/README.md +15 -1
  364. package/platforms/electrobun/assets/appIcon.icns +0 -0
  365. package/platforms/electrobun/assets/appIcon.ico +0 -0
  366. package/platforms/electrobun/assets/appIcon.iconset/icon_128x128.png +0 -0
  367. package/platforms/electrobun/assets/appIcon.iconset/icon_128x128@2x.png +0 -0
  368. package/platforms/electrobun/assets/appIcon.iconset/icon_16x16.png +0 -0
  369. package/platforms/electrobun/assets/appIcon.iconset/icon_16x16@2x.png +0 -0
  370. package/platforms/electrobun/assets/appIcon.iconset/icon_256x256.png +0 -0
  371. package/platforms/electrobun/assets/appIcon.iconset/icon_256x256@2x.png +0 -0
  372. package/platforms/electrobun/assets/appIcon.iconset/icon_32x32.png +0 -0
  373. package/platforms/electrobun/assets/appIcon.iconset/icon_32x32@2x.png +0 -0
  374. package/platforms/electrobun/assets/appIcon.iconset/icon_512x512.png +0 -0
  375. package/platforms/electrobun/assets/brand-config.json +6 -6
  376. package/platforms/electrobun/biome.json +9 -9
  377. package/platforms/electrobun/docs/capability-collapse-matrix.json +318 -0
  378. package/platforms/electrobun/docs/capability-collapse-matrix.md +129 -0
  379. package/platforms/electrobun/docs/capability-routing.md +86 -0
  380. package/platforms/electrobun/docs/database-boot-policy.md +90 -0
  381. package/platforms/electrobun/docs/riscv64-port.md +175 -0
  382. package/platforms/electrobun/docs/startup-first-run-cleanup.md +18 -0
  383. package/platforms/electrobun/docs/trace-first-annotations.md +52 -0
  384. package/platforms/electrobun/docs/ui-boundary-audit.json +580 -0
  385. package/platforms/electrobun/docs/ui-boundary-audit.md +257 -0
  386. package/platforms/electrobun/electrobun.config.ts +591 -364
  387. package/platforms/electrobun/entitlements/JUSTIFICATIONS.md +141 -0
  388. package/platforms/electrobun/entitlements/README.md +34 -6
  389. package/platforms/electrobun/entitlements/mas-bun.entitlements +15 -0
  390. package/platforms/electrobun/entitlements/mas.entitlements +6 -4
  391. package/platforms/electrobun/native/macos/window-effects.mm +1526 -0
  392. package/platforms/electrobun/package.json +21 -13
  393. package/platforms/electrobun/remotes/fs/README.md +70 -0
  394. package/platforms/electrobun/remotes/fs/electrobun.config.ts +38 -0
  395. package/platforms/electrobun/remotes/fs/package.json +12 -0
  396. package/platforms/electrobun/remotes/fs/plugin.json +25 -0
  397. package/platforms/electrobun/remotes/fs/src/bun/errors.ts +57 -0
  398. package/platforms/electrobun/remotes/fs/src/bun/file-limits.ts +50 -0
  399. package/platforms/electrobun/remotes/fs/src/bun/fs-service.ts +389 -0
  400. package/platforms/electrobun/remotes/fs/src/bun/path-guard.ts +270 -0
  401. package/platforms/electrobun/remotes/fs/src/bun/protocol.ts +149 -0
  402. package/platforms/electrobun/remotes/fs/src/bun/worker.ts +174 -0
  403. package/platforms/electrobun/remotes/fs/src/dev/phase5-smoke.ts +171 -0
  404. package/platforms/electrobun/remotes/fs/src/web/index.html +8 -0
  405. package/platforms/electrobun/remotes/git/README.md +75 -0
  406. package/platforms/electrobun/remotes/git/electrobun.config.ts +44 -0
  407. package/platforms/electrobun/remotes/git/package.json +12 -0
  408. package/platforms/electrobun/remotes/git/plugin.json +31 -0
  409. package/platforms/electrobun/remotes/git/src/bun/errors.ts +69 -0
  410. package/platforms/electrobun/remotes/git/src/bun/git-command.ts +156 -0
  411. package/platforms/electrobun/remotes/git/src/bun/git-service.ts +446 -0
  412. package/platforms/electrobun/remotes/git/src/bun/operation-history.ts +124 -0
  413. package/platforms/electrobun/remotes/git/src/bun/protocol.ts +252 -0
  414. package/platforms/electrobun/remotes/git/src/bun/worker.ts +316 -0
  415. package/platforms/electrobun/remotes/git/src/dev/phase7-smoke.ts +141 -0
  416. package/platforms/electrobun/remotes/git/src/web/index.html +8 -0
  417. package/platforms/electrobun/remotes/local-model/README.md +138 -0
  418. package/platforms/electrobun/remotes/local-model/electrobun.config.ts +46 -0
  419. package/platforms/electrobun/remotes/local-model/package.json +12 -0
  420. package/platforms/electrobun/remotes/local-model/plugin.json +33 -0
  421. package/platforms/electrobun/remotes/local-model/src/bun/download-state.ts +115 -0
  422. package/platforms/electrobun/remotes/local-model/src/bun/eliza1-catalog.ts +405 -0
  423. package/platforms/electrobun/remotes/local-model/src/bun/errors.ts +74 -0
  424. package/platforms/electrobun/remotes/local-model/src/bun/hf-eliza1-client.ts +169 -0
  425. package/platforms/electrobun/remotes/local-model/src/bun/local-inference-api-client.ts +245 -0
  426. package/platforms/electrobun/remotes/local-model/src/bun/model-service.ts +490 -0
  427. package/platforms/electrobun/remotes/local-model/src/bun/protocol.ts +301 -0
  428. package/platforms/electrobun/remotes/local-model/src/bun/worker.ts +248 -0
  429. package/platforms/electrobun/remotes/local-model/src/dev/phase8-smoke.ts +116 -0
  430. package/platforms/electrobun/remotes/local-model/src/web/index.html +13 -0
  431. package/platforms/electrobun/remotes/pty/README.md +65 -0
  432. package/platforms/electrobun/remotes/pty/electrobun.config.ts +47 -0
  433. package/platforms/electrobun/remotes/pty/package.json +12 -0
  434. package/platforms/electrobun/remotes/pty/plugin.json +34 -0
  435. package/platforms/electrobun/remotes/pty/src/bun/errors.ts +57 -0
  436. package/platforms/electrobun/remotes/pty/src/bun/output-buffer.ts +127 -0
  437. package/platforms/electrobun/remotes/pty/src/bun/protocol.ts +192 -0
  438. package/platforms/electrobun/remotes/pty/src/bun/pty-service.ts +562 -0
  439. package/platforms/electrobun/remotes/pty/src/bun/worker.ts +218 -0
  440. package/platforms/electrobun/remotes/pty/src/dev/phase6-smoke.ts +127 -0
  441. package/platforms/electrobun/remotes/pty/src/web/index.html +8 -0
  442. package/platforms/electrobun/remotes/runtime/README.md +370 -0
  443. package/platforms/electrobun/remotes/runtime/electrobun.config.ts +48 -0
  444. package/platforms/electrobun/remotes/runtime/package.json +14 -0
  445. package/platforms/electrobun/remotes/runtime/plugin.json +30 -0
  446. package/platforms/electrobun/remotes/runtime/src/bun/api-client.ts +620 -0
  447. package/platforms/electrobun/remotes/runtime/src/bun/errors.ts +45 -0
  448. package/platforms/electrobun/remotes/runtime/src/bun/log-buffer.ts +33 -0
  449. package/platforms/electrobun/remotes/runtime/src/bun/protocol.ts +366 -0
  450. package/platforms/electrobun/remotes/runtime/src/bun/route-discovery.ts +419 -0
  451. package/platforms/electrobun/remotes/runtime/src/bun/runtime-manager.ts +423 -0
  452. package/platforms/electrobun/remotes/runtime/src/bun/sse-parser.ts +99 -0
  453. package/platforms/electrobun/remotes/runtime/src/bun/stream-manager.ts +887 -0
  454. package/platforms/electrobun/remotes/runtime/src/bun/worker.ts +1231 -0
  455. package/platforms/electrobun/remotes/runtime/src/dev/phase1-smoke.ts +34 -0
  456. package/platforms/electrobun/remotes/runtime/src/dev/phase2-smoke.ts +91 -0
  457. package/platforms/electrobun/remotes/runtime/src/dev/phase3-smoke.ts +137 -0
  458. package/platforms/electrobun/remotes/runtime/src/web/index.css +187 -0
  459. package/platforms/electrobun/remotes/runtime/src/web/index.html +76 -0
  460. package/platforms/electrobun/remotes/runtime/src/web/index.ts +192 -0
  461. package/platforms/electrobun/remotes/surface/README.md +201 -0
  462. package/platforms/electrobun/remotes/surface/electrobun.config.ts +38 -0
  463. package/platforms/electrobun/remotes/surface/package.json +12 -0
  464. package/platforms/electrobun/remotes/surface/plugin.json +28 -0
  465. package/platforms/electrobun/remotes/surface/src/bun/worker.ts +132 -0
  466. package/platforms/electrobun/remotes/surface/src/dev/phase4-smoke.ts +566 -0
  467. package/platforms/electrobun/remotes/surface/src/protocol/event-types.ts +84 -0
  468. package/platforms/electrobun/remotes/surface/src/protocol/runtime-client.ts +673 -0
  469. package/platforms/electrobun/remotes/surface/src/web/app.ts +595 -0
  470. package/platforms/electrobun/remotes/surface/src/web/index.css +460 -0
  471. package/platforms/electrobun/remotes/surface/src/web/index.html +466 -0
  472. package/platforms/electrobun/remotes/surface/src/web/index.ts +5 -0
  473. package/platforms/electrobun/remotes/surface/src/web/render.ts +455 -0
  474. package/platforms/electrobun/remotes/surface/src/web/state.ts +427 -0
  475. package/platforms/electrobun/scripts/build-macos-effects.sh +4 -0
  476. package/platforms/electrobun/scripts/ensure-build-folder.ts +28 -0
  477. package/platforms/electrobun/scripts/local-adhoc-sign-macos.ts +159 -159
  478. package/platforms/electrobun/scripts/postwrap-diagnostics.ts +424 -339
  479. package/platforms/electrobun/scripts/postwrap-sign-runtime-macos.ts +302 -271
  480. package/platforms/electrobun/scripts/smoke-test-windows.ps1 +17 -16
  481. package/platforms/electrobun/scripts/smoke-test.sh +5 -7
  482. package/platforms/electrobun/scripts/sync-web-assets.mjs +13 -13
  483. package/platforms/electrobun/scripts/verify-rpc-handlers.ts +109 -110
  484. package/platforms/electrobun/scripts/verify-windows-installer-proof.ps1 +3 -8
  485. package/platforms/electrobun/src/__stubs__/bun-ffi.ts +31 -31
  486. package/platforms/electrobun/src/__stubs__/electrobun-bun.ts +1 -1
  487. package/platforms/electrobun/src/agent-ready-state.ts +8 -8
  488. package/platforms/electrobun/src/agent-reset-from-main.test.ts +162 -0
  489. package/platforms/electrobun/src/agent-reset-from-main.ts +62 -62
  490. package/platforms/electrobun/src/agent-status-rpc.test.ts +95 -0
  491. package/platforms/electrobun/src/agent-status-rpc.ts +156 -0
  492. package/platforms/electrobun/src/api-base.test.ts +247 -0
  493. package/platforms/electrobun/src/api-base.ts +202 -93
  494. package/platforms/electrobun/src/application-menu-action-registry.ts +9 -9
  495. package/platforms/electrobun/src/application-menu.ts +341 -348
  496. package/platforms/electrobun/src/background-notice.ts +36 -36
  497. package/platforms/electrobun/src/boot-progress.test.ts +188 -0
  498. package/platforms/electrobun/src/boot-progress.ts +111 -0
  499. package/platforms/electrobun/src/brand-config.test.ts +39 -0
  500. package/platforms/electrobun/src/brand-config.ts +141 -129
  501. package/platforms/electrobun/src/bridge/browser-tabs-renderer-registry.ts +28 -28
  502. package/platforms/electrobun/src/bridge/electrobun-boot-config.ts +42 -0
  503. package/platforms/electrobun/src/bridge/electrobun-crypto-ready.ts +120 -0
  504. package/platforms/electrobun/src/bridge/electrobun-direct-rpc.ts +342 -357
  505. package/platforms/electrobun/src/bridge/electrobun-stub.ts +13 -13
  506. package/platforms/electrobun/src/browser-workspace-bridge-server.ts +285 -243
  507. package/platforms/electrobun/src/cloud-auth-window.ts +136 -136
  508. package/platforms/electrobun/src/cloud-disconnect-from-main.ts +90 -90
  509. package/platforms/electrobun/src/config-and-auth-rpc.test.ts +256 -0
  510. package/platforms/electrobun/src/config-and-auth-rpc.ts +302 -0
  511. package/platforms/electrobun/src/conversations-and-character-rpc.test.ts +185 -0
  512. package/platforms/electrobun/src/conversations-and-character-rpc.ts +131 -0
  513. package/platforms/electrobun/src/dashboard-rpc.test.ts +200 -0
  514. package/platforms/electrobun/src/dashboard-rpc.ts +344 -0
  515. package/platforms/electrobun/src/database/database-lock.ts +141 -0
  516. package/platforms/electrobun/src/database/database-mode.ts +149 -0
  517. package/platforms/electrobun/src/database/database-recovery.ts +72 -0
  518. package/platforms/electrobun/src/database/database-snapshot.ts +190 -0
  519. package/platforms/electrobun/src/database/database.test.ts +196 -0
  520. package/platforms/electrobun/src/database/index.ts +5 -0
  521. package/platforms/electrobun/src/database/pglite-paths.ts +100 -0
  522. package/platforms/electrobun/src/desktop-deep-link-events.test.ts +30 -0
  523. package/platforms/electrobun/src/desktop-deep-link-events.ts +17 -0
  524. package/platforms/electrobun/src/desktop-http-request.test.ts +102 -73
  525. package/platforms/electrobun/src/desktop-http-request.ts +97 -85
  526. package/platforms/electrobun/src/desktop-pill-config.test.ts +27 -0
  527. package/platforms/electrobun/src/desktop-pill-config.ts +40 -0
  528. package/platforms/electrobun/src/desktop-test-bridge-server.ts +232 -204
  529. package/platforms/electrobun/src/desktop-tray-config.test.ts +87 -0
  530. package/platforms/electrobun/src/desktop-tray-config.ts +84 -0
  531. package/platforms/electrobun/src/devtools-layout.ts +41 -41
  532. package/platforms/electrobun/src/diagnostic-format.test.ts +71 -0
  533. package/platforms/electrobun/src/diagnostic-format.ts +75 -36
  534. package/platforms/electrobun/src/dynamic-view-rpc-schema.test.ts +37 -0
  535. package/platforms/electrobun/src/dynamic-views/README.md +44 -0
  536. package/platforms/electrobun/src/dynamic-views/demo/agent-run-trace.html +135 -0
  537. package/platforms/electrobun/src/dynamic-views/errors.ts +29 -0
  538. package/platforms/electrobun/src/dynamic-views/host.test.ts +353 -0
  539. package/platforms/electrobun/src/dynamic-views/host.ts +332 -0
  540. package/platforms/electrobun/src/dynamic-views/index.ts +57 -0
  541. package/platforms/electrobun/src/dynamic-views/kiosk-canvas.ts +89 -0
  542. package/platforms/electrobun/src/dynamic-views/registry.test.ts +139 -0
  543. package/platforms/electrobun/src/dynamic-views/registry.ts +196 -0
  544. package/platforms/electrobun/src/dynamic-views/session-manager.test.ts +355 -0
  545. package/platforms/electrobun/src/dynamic-views/session-manager.ts +348 -0
  546. package/platforms/electrobun/src/dynamic-views/types.ts +105 -0
  547. package/platforms/electrobun/src/electrobun-boot-config.test.ts +50 -0
  548. package/platforms/electrobun/src/electrobun-config.test.ts +62 -0
  549. package/platforms/electrobun/src/electrobun-crypto-ready.test.ts +65 -0
  550. package/platforms/electrobun/src/electrobun-window-options.ts +25 -0
  551. package/platforms/electrobun/src/extension-rpc.test.ts +88 -0
  552. package/platforms/electrobun/src/extension-rpc.ts +102 -0
  553. package/platforms/electrobun/src/fatal-shutdown.test.ts +12 -16
  554. package/platforms/electrobun/src/fatal-shutdown.ts +1 -1
  555. package/platforms/electrobun/src/first-party-remotes.test.ts +169 -0
  556. package/platforms/electrobun/src/first-party-remotes.ts +297 -0
  557. package/platforms/electrobun/src/first-run-rpc.test.ts +192 -0
  558. package/platforms/electrobun/src/first-run-rpc.ts +146 -0
  559. package/platforms/electrobun/src/floating-chat-window.ts +181 -181
  560. package/platforms/electrobun/src/inbox-rpc.test.ts +123 -0
  561. package/platforms/electrobun/src/inbox-rpc.ts +158 -0
  562. package/platforms/electrobun/src/index.ts +2608 -2098
  563. package/platforms/electrobun/src/kiosk-mode.ts +50 -0
  564. package/platforms/electrobun/src/launch/index.ts +4 -0
  565. package/platforms/electrobun/src/launch/launch-dynamic-view.ts +37 -0
  566. package/platforms/electrobun/src/launch/launch-orchestrator.test.ts +224 -0
  567. package/platforms/electrobun/src/launch/launch-orchestrator.ts +456 -0
  568. package/platforms/electrobun/src/launch/launch-store.test.ts +97 -0
  569. package/platforms/electrobun/src/launch/launch-store.ts +134 -0
  570. package/platforms/electrobun/src/launch/types.ts +103 -0
  571. package/platforms/electrobun/src/launch/views/launch-diagnostics.html +205 -0
  572. package/platforms/electrobun/src/lifecycle/agent-ready-publish.test.ts +50 -0
  573. package/platforms/electrobun/src/lifecycle/agent-ready-publish.ts +27 -0
  574. package/platforms/electrobun/src/lifecycle/api-base-owner.test.ts +83 -0
  575. package/platforms/electrobun/src/lifecycle/api-base-owner.ts +63 -31
  576. package/platforms/electrobun/src/lifecycle/desktop-session-prime.ts +44 -44
  577. package/platforms/electrobun/src/logger.ts +14 -14
  578. package/platforms/electrobun/src/main-window-runtime.ts +83 -83
  579. package/platforms/electrobun/src/main-window-session.test.ts +109 -0
  580. package/platforms/electrobun/src/main-window-session.ts +87 -51
  581. package/platforms/electrobun/src/menu-reset-from-main.ts +158 -158
  582. package/platforms/electrobun/src/native/agent-env.test.ts +52 -0
  583. package/platforms/electrobun/src/native/agent-runtime-layout.test.ts +42 -0
  584. package/platforms/electrobun/src/native/agent-state-dir.test.ts +91 -0
  585. package/platforms/electrobun/src/native/agent.ts +2133 -1682
  586. package/platforms/electrobun/src/native/auth-bridge.test.ts +67 -0
  587. package/platforms/electrobun/src/native/auth-bridge.ts +464 -360
  588. package/platforms/electrobun/src/native/browser-workspace.ts +723 -471
  589. package/platforms/electrobun/src/native/camera.ts +50 -50
  590. package/platforms/electrobun/src/native/canvas.ts +444 -445
  591. package/platforms/electrobun/src/native/credentials.ts +678 -616
  592. package/platforms/electrobun/src/native/desktop-window.test.ts +416 -0
  593. package/platforms/electrobun/src/native/desktop.ts +2200 -2156
  594. package/platforms/electrobun/src/native/editor-bridge.ts +201 -201
  595. package/platforms/electrobun/src/native/file-watcher.ts +154 -154
  596. package/platforms/electrobun/src/native/gateway.ts +179 -180
  597. package/platforms/electrobun/src/native/gpu-window.ts +256 -256
  598. package/platforms/electrobun/src/native/index.ts +82 -74
  599. package/platforms/electrobun/src/native/location.test.ts +44 -0
  600. package/platforms/electrobun/src/native/location.ts +90 -80
  601. package/platforms/electrobun/src/native/loopback-port.ts +60 -60
  602. package/platforms/electrobun/src/native/mac-window-effects.ts +166 -104
  603. package/platforms/electrobun/src/native/music-player.ts +38 -38
  604. package/platforms/electrobun/src/native/permissions-shared.ts +249 -150
  605. package/platforms/electrobun/src/native/permissions.ts +301 -208
  606. package/platforms/electrobun/src/native/power-state.ts +129 -129
  607. package/platforms/electrobun/src/native/remote-plugin-host.test.ts +1394 -0
  608. package/platforms/electrobun/src/native/remote-plugin-host.ts +1541 -0
  609. package/platforms/electrobun/src/native/screencapture.ts +667 -573
  610. package/platforms/electrobun/src/native/steward.ts +207 -204
  611. package/platforms/electrobun/src/native/swabble.ts +68 -324
  612. package/platforms/electrobun/src/native/talkmode.ts +253 -422
  613. package/platforms/electrobun/src/native/webgpu-browser-support.test.ts +18 -0
  614. package/platforms/electrobun/src/native/webgpu-browser-support.ts +165 -147
  615. package/platforms/electrobun/src/native-onboarding.ts +270 -0
  616. package/platforms/electrobun/src/onboarding-overlay-window.ts +141 -0
  617. package/platforms/electrobun/src/persisted-deployment.ts +91 -0
  618. package/platforms/electrobun/src/pill-window.test.ts +91 -0
  619. package/platforms/electrobun/src/pill-window.ts +99 -0
  620. package/platforms/electrobun/src/preload-validation.ts +44 -44
  621. package/platforms/electrobun/src/preload.js +1 -1
  622. package/platforms/electrobun/src/print-electrobun-dev-settings-banner.ts +120 -120
  623. package/platforms/electrobun/src/renderer-api-proxy.test.ts +73 -0
  624. package/platforms/electrobun/src/renderer-api-proxy.ts +86 -0
  625. package/platforms/electrobun/src/renderer-static.test.ts +53 -0
  626. package/platforms/electrobun/src/renderer-static.ts +144 -57
  627. package/platforms/electrobun/src/rpc-handler-slices.ts +121 -0
  628. package/platforms/electrobun/src/rpc-handlers.test.ts +267 -0
  629. package/platforms/electrobun/src/rpc-handlers.ts +1306 -913
  630. package/platforms/electrobun/src/rpc-parse-utils.ts +57 -0
  631. package/platforms/electrobun/src/rpc-port-resolver.test.ts +45 -0
  632. package/platforms/electrobun/src/rpc-port-resolver.ts +31 -0
  633. package/platforms/electrobun/src/rpc-schema.ts +2556 -1619
  634. package/platforms/electrobun/src/runtime-layout.ts +105 -105
  635. package/platforms/electrobun/src/runtime-permissions.ts +95 -95
  636. package/platforms/electrobun/src/runtime-rpc.test.ts +126 -0
  637. package/platforms/electrobun/src/runtime-rpc.ts +237 -0
  638. package/platforms/electrobun/src/screenshot-dev-server.ts +87 -87
  639. package/platforms/electrobun/src/settings-mutations-rpc.test.ts +193 -0
  640. package/platforms/electrobun/src/settings-mutations-rpc.ts +220 -0
  641. package/platforms/electrobun/src/startup-trace.ts +274 -270
  642. package/platforms/electrobun/src/subscription-rpc.test.ts +89 -0
  643. package/platforms/electrobun/src/subscription-rpc.ts +192 -0
  644. package/platforms/electrobun/src/surface-windows.test.ts +355 -0
  645. package/platforms/electrobun/src/surface-windows.ts +410 -410
  646. package/platforms/electrobun/src/trace/README.md +73 -0
  647. package/platforms/electrobun/src/trace/errors.ts +21 -0
  648. package/platforms/electrobun/src/trace/index.ts +40 -0
  649. package/platforms/electrobun/src/trace/trace-dynamic-view.ts +40 -0
  650. package/platforms/electrobun/src/trace/trace-host-requests.ts +473 -0
  651. package/platforms/electrobun/src/trace/trace-service.test.ts +186 -0
  652. package/platforms/electrobun/src/trace/trace-service.ts +324 -0
  653. package/platforms/electrobun/src/trace/trace-store.test.ts +141 -0
  654. package/platforms/electrobun/src/trace/trace-store.ts +551 -0
  655. package/platforms/electrobun/src/trace/types.ts +250 -0
  656. package/platforms/electrobun/src/trace/views/agent-run-trace.html +311 -0
  657. package/platforms/electrobun/src/types/web-speech.d.ts +28 -28
  658. package/platforms/electrobun/src/types.ts +5 -5
  659. package/platforms/electrobun/src/update-availability.test.ts +72 -0
  660. package/platforms/electrobun/src/update-availability.ts +90 -0
  661. package/platforms/electrobun/src/update-rpc.test.ts +83 -0
  662. package/platforms/electrobun/src/update-rpc.ts +123 -0
  663. package/platforms/electrobun/src/voice/README.md +184 -0
  664. package/platforms/electrobun/src/voice/errors.ts +42 -0
  665. package/platforms/electrobun/src/voice/index.ts +78 -0
  666. package/platforms/electrobun/src/voice/types.ts +316 -0
  667. package/platforms/electrobun/src/voice/voice-host-requests.ts +259 -0
  668. package/platforms/electrobun/src/voice/voice-latency-budget.test.ts +66 -0
  669. package/platforms/electrobun/src/voice/voice-latency-budget.ts +243 -0
  670. package/platforms/electrobun/src/voice/voice-live-validation.test.ts +357 -0
  671. package/platforms/electrobun/src/voice/voice-live-validation.ts +838 -0
  672. package/platforms/electrobun/src/voice/voice-pipeline.ts +250 -0
  673. package/platforms/electrobun/src/voice/voice-playback-adapter.ts +31 -0
  674. package/platforms/electrobun/src/voice/voice-runtime-adapter.test.ts +213 -0
  675. package/platforms/electrobun/src/voice/voice-runtime-adapter.ts +687 -0
  676. package/platforms/electrobun/src/voice/voice-service.test.ts +587 -0
  677. package/platforms/electrobun/src/voice/voice-service.ts +1067 -0
  678. package/platforms/electrobun/src/voice/voice-stream-coordinator.test.ts +115 -0
  679. package/platforms/electrobun/src/voice/voice-stream-coordinator.ts +270 -0
  680. package/platforms/electrobun/src/voice/voice-trace.ts +97 -0
  681. package/platforms/electrobun/src/voice/voice-tts-chunker.test.ts +91 -0
  682. package/platforms/electrobun/src/voice/voice-tts-chunker.ts +194 -0
  683. package/platforms/electrobun/src/windows-cef-profile.ts +88 -88
  684. package/platforms/electrobun/tsconfig.json +88 -12
  685. package/platforms/electrobun/update-channels.json +22 -0
  686. package/platforms/electrobun/vitest.electrobun.config.ts +72 -42
  687. package/platforms/ios/App/App/App.entitlements +4 -0
  688. package/platforms/ios/App/App/AppDelegate.swift +80 -18
  689. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ios-marketing-1024.png +0 -0
  690. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-20x20@1x.png +0 -0
  691. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-20x20@2x.png +0 -0
  692. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-29x29@1x.png +0 -0
  693. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-29x29@2x.png +0 -0
  694. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-40x40@1x.png +0 -0
  695. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-40x40@2x.png +0 -0
  696. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-76x76@1x.png +0 -0
  697. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-76x76@2x.png +0 -0
  698. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-ipad-83_5x83_5@2x.png +0 -0
  699. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-20x20@2x.png +0 -0
  700. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-20x20@3x.png +0 -0
  701. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-29x29@2x.png +0 -0
  702. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-29x29@3x.png +0 -0
  703. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-40x40@2x.png +0 -0
  704. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-40x40@3x.png +0 -0
  705. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-60x60@2x.png +0 -0
  706. package/platforms/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iphone-60x60@3x.png +0 -0
  707. package/platforms/ios/App/App/Base.lproj/LaunchScreen.storyboard +4 -9
  708. package/platforms/ios/App/App/ComputerUseBridge.swift +589 -0
  709. package/platforms/ios/App/App/DeviceActivityMonitorExtension/DeviceActivityMonitorExtension.entitlements +12 -0
  710. package/platforms/ios/App/App/DeviceActivityMonitorExtension/DeviceActivityMonitorExtension.swift +34 -0
  711. package/platforms/ios/App/App/DeviceActivityMonitorExtension/Info.plist +29 -0
  712. package/platforms/ios/App/App/DeviceActivityReportExtension/DeviceActivityReportExtension.entitlements +12 -0
  713. package/platforms/ios/App/App/DeviceActivityReportExtension/DeviceActivityReportExtension.swift +53 -0
  714. package/platforms/ios/App/App/DeviceActivityReportExtension/Info.plist +27 -0
  715. package/platforms/ios/App/App/ElizaAppIntents.swift +183 -0
  716. package/platforms/ios/App/App/ElizaIntentPlugin.swift +342 -5
  717. package/platforms/ios/App/App/Info.plist +17 -1
  718. package/platforms/ios/App/App/runners/eliza-tasks.js +177 -0
  719. package/platforms/ios/App/App.xcodeproj/project.pbxproj +262 -6
  720. package/platforms/ios/App/BroadcastExtension/SampleHandler.swift +100 -0
  721. package/platforms/ios/App/Podfile +5 -0
  722. package/platforms/ios/App/Podfile.lock +83 -59
  723. package/register-runtime-hooks.js +11 -5
  724. package/registry/index.d.ts +1 -5
  725. package/registry/index.d.ts.map +1 -1
  726. package/registry/index.js +10 -68
  727. package/runtime/android-avf-microdroid-bridge.d.ts +29 -0
  728. package/runtime/android-avf-microdroid-bridge.d.ts.map +1 -0
  729. package/runtime/android-avf-microdroid-bridge.js +149 -0
  730. package/runtime/api-dev-settings-banner.d.ts.map +1 -1
  731. package/runtime/api-dev-settings-banner.js +5 -13
  732. package/runtime/app-core-runtime-hooks.d.ts +21 -0
  733. package/runtime/app-core-runtime-hooks.d.ts.map +1 -0
  734. package/runtime/app-core-runtime-hooks.js +10 -0
  735. package/runtime/autonomy-policy.d.ts +2 -0
  736. package/runtime/autonomy-policy.d.ts.map +1 -0
  737. package/runtime/autonomy-policy.js +4 -0
  738. package/runtime/bundled-fused-lib.d.ts +36 -0
  739. package/runtime/bundled-fused-lib.d.ts.map +1 -0
  740. package/runtime/bundled-fused-lib.js +77 -0
  741. package/runtime/channel-plugin-map.d.ts +1 -5
  742. package/runtime/channel-plugin-map.d.ts.map +1 -1
  743. package/runtime/channel-plugin-map.js +11 -31
  744. package/runtime/desktop/AppWindowRenderer.d.ts +17 -0
  745. package/runtime/desktop/AppWindowRenderer.d.ts.map +1 -0
  746. package/runtime/desktop/AppWindowRenderer.js +360 -0
  747. package/runtime/desktop/DesktopSurfaceNavigationRuntime.d.ts +2 -0
  748. package/runtime/desktop/DesktopSurfaceNavigationRuntime.d.ts.map +1 -0
  749. package/runtime/desktop/DesktopSurfaceNavigationRuntime.js +41 -0
  750. package/runtime/desktop/DesktopTrayRuntime.d.ts +2 -0
  751. package/runtime/desktop/DesktopTrayRuntime.d.ts.map +1 -0
  752. package/runtime/desktop/DesktopTrayRuntime.js +174 -0
  753. package/runtime/desktop/DetachedShellRoot.d.ts +10 -0
  754. package/runtime/desktop/DetachedShellRoot.d.ts.map +1 -0
  755. package/runtime/desktop/DetachedShellRoot.js +111 -0
  756. package/runtime/desktop/index.d.ts +6 -0
  757. package/runtime/desktop/index.d.ts.map +1 -0
  758. package/runtime/desktop/index.js +5 -0
  759. package/runtime/desktop/tray-menu.d.ts +20 -0
  760. package/runtime/desktop/tray-menu.d.ts.map +1 -0
  761. package/runtime/desktop/tray-menu.js +143 -0
  762. package/runtime/dev-server.d.ts +1 -1
  763. package/runtime/dev-server.d.ts.map +1 -1
  764. package/runtime/dev-server.js +104 -19
  765. package/runtime/eliza.d.ts +75 -1
  766. package/runtime/eliza.d.ts.map +1 -1
  767. package/runtime/eliza.js +606 -122
  768. package/runtime/ensure-text-to-speech-handler.d.ts.map +1 -1
  769. package/runtime/ensure-text-to-speech-handler.js +10 -3
  770. package/runtime/mobile-safe-runtime.d.ts +181 -2
  771. package/runtime/mobile-safe-runtime.d.ts.map +1 -1
  772. package/runtime/mobile-safe-runtime.js +1019 -12
  773. package/runtime/mode/remote-forwarder.d.ts.map +1 -1
  774. package/runtime/mode/remote-forwarder.js +2 -2
  775. package/runtime/mode/route-mode-guard.d.ts +2 -3
  776. package/runtime/mode/route-mode-guard.d.ts.map +1 -1
  777. package/runtime/mode/route-mode-guard.js +4 -5
  778. package/runtime/mode/route-mode-matrix.d.ts +1 -1
  779. package/runtime/mode/route-mode-matrix.d.ts.map +1 -1
  780. package/runtime/mode/route-mode-matrix.js +14 -1
  781. package/runtime/mode/runtime-mode.d.ts +1 -1
  782. package/runtime/mode/runtime-mode.js +1 -1
  783. package/runtime/runtime-bootstrap-policy.d.ts.map +1 -1
  784. package/runtime/runtime-bootstrap-policy.js +14 -2
  785. package/runtime/telegram-standalone-handler.d.ts.map +1 -1
  786. package/runtime/telegram-standalone-handler.js +10 -9
  787. package/runtime/tts-cache-wiring.d.ts +29 -0
  788. package/runtime/tts-cache-wiring.d.ts.map +1 -0
  789. package/runtime/tts-cache-wiring.js +114 -0
  790. package/runtime/voice-warmup.d.ts +66 -0
  791. package/runtime/voice-warmup.d.ts.map +1 -0
  792. package/runtime/voice-warmup.js +101 -0
  793. package/scripts/android-sms-gateway-template.test.mjs +1014 -0
  794. package/scripts/aosp/README.md +29 -16
  795. package/scripts/aosp/compile-libllama-zig-pin.test.mjs +147 -0
  796. package/scripts/aosp/compile-libllama.mjs +1750 -267
  797. package/scripts/aosp/compile-libllama.test.mjs +133 -0
  798. package/scripts/aosp/compile-shim.mjs +68 -19
  799. package/scripts/aosp/deploy-pixel.mjs +405 -0
  800. package/scripts/aosp/lib/load-variant-config.mjs +3 -3
  801. package/scripts/aosp/llama-cpp-patches/README.md +8 -8
  802. package/scripts/aosp/llama-cpp-patches/apply-patches.mjs +23 -6
  803. package/scripts/aosp/llama-cpp-patches/polarquant/README.md +37 -0
  804. package/scripts/aosp/llama-cpp-patches/qjl/README.md +37 -0
  805. package/scripts/aosp/seccomp-shim/sigsys-handler-arm64.c +169 -0
  806. package/scripts/aosp/seccomp-shim/sigsys-handler-riscv64.c +217 -0
  807. package/scripts/aosp/smoke-cuttlefish.mjs +34 -4
  808. package/scripts/aosp/stage-default-models.mjs +59 -35
  809. package/scripts/aosp/stage-default-models.test.mjs +23 -0
  810. package/scripts/aosp/variant-config-schema.ts +2 -2
  811. package/scripts/assert-required-bundled-packages.test.ts +555 -0
  812. package/scripts/audit-apple-store-sandbox.mjs +146 -0
  813. package/scripts/audit-live-test-surface.mjs +5 -2
  814. package/scripts/build-capacitor-app.mjs +21 -0
  815. package/scripts/build-flatpak.mjs +5 -5
  816. package/scripts/build-helpers/arm64-simd.mjs +72 -0
  817. package/scripts/build-helpers/omnivoice-merged.mjs +87 -0
  818. package/scripts/build-helpers/verify-fused-symbols.mjs +600 -0
  819. package/scripts/build-helpers/verify-fused-symbols.test.mjs +0 -0
  820. package/scripts/build-image.sh +1 -1
  821. package/scripts/build-llama-cpp-mtp.mjs +488 -0
  822. package/scripts/build-native-plugins.mjs +230 -18
  823. package/scripts/build-patched-electrobun-cli.mjs +68 -10
  824. package/scripts/build-win.mjs +1 -1
  825. package/scripts/bun-riscv64/Dockerfile +418 -0
  826. package/scripts/bun-riscv64/README.md +316 -0
  827. package/scripts/bun-riscv64/build.sh +469 -0
  828. package/scripts/bun-riscv64/bun-patches/0001-config-add-riscv64-arch.patch +74 -0
  829. package/scripts/bun-riscv64/bun-patches/0002-flags-add-riscv64-march-mabi.patch +16 -0
  830. package/scripts/bun-riscv64/bun-patches/0003-zig-add-riscv64-target-triple-and-cpu.patch +26 -0
  831. package/scripts/bun-riscv64/bun-patches/0004-webkit-force-local-mode-on-riscv64.patch +33 -0
  832. package/scripts/bun-riscv64/bun-patches/0005-tinycc-disable-on-riscv64.patch +16 -0
  833. package/scripts/bun-riscv64/bun-patches/0006-build-add-riscv64-cli-validation.patch +15 -0
  834. package/scripts/bun-riscv64/bun-patches/0007-deps-per-dep-riscv64-checks.patch +24 -0
  835. package/scripts/bun-riscv64/bun-patches/0008-source-stabilize-riscv64-musl-build.patch +226 -0
  836. package/scripts/bun-riscv64/bun-patches/0009-disable-wasm-streaming-hooks-for-c-loop.patch +162 -0
  837. package/scripts/bun-riscv64/bun-patches/0010-disable-inspector-profiler-for-riscv64-c-loop.patch +80 -0
  838. package/scripts/bun-riscv64/bun-patches/0011-process-arch-add-riscv64.patch +23 -0
  839. package/scripts/bun-riscv64/bun-patches/0012-cpu-features-add-riscv64-fallback.patch +13 -0
  840. package/scripts/bun-riscv64/bun-patches/0013-disable-console-inspector-hooks-for-riscv64-c-loop.patch +43 -0
  841. package/scripts/bun-riscv64/bun-patches/0014-disable-custom-inspector-dispatchers-on-riscv64.patch +127 -0
  842. package/scripts/bun-riscv64/bun-patches/0015-disable-jsc-profiler-builtins-on-riscv64.patch +75 -0
  843. package/scripts/bun-riscv64/bun-patches/0016-node-vm-disable-jit-cached-data-on-riscv64-c-loop.patch +96 -0
  844. package/scripts/bun-riscv64/bun-patches/0017-disable-performance-domjit-signature-on-riscv64-c-loop.patch +34 -0
  845. package/scripts/bun-riscv64/bun-patches/0018-fix-serialized-script-identifier-big-endian-path.patch +19 -0
  846. package/scripts/bun-riscv64/bun-patches/0019-add-wtf-timer-fire-bridge-for-c-loop.patch +24 -0
  847. package/scripts/bun-riscv64/bun-patches/0020-run-riscv64-smoke-test-under-qemu.patch +13 -0
  848. package/scripts/bun-riscv64/bun-patches/0021-fix-riscv64-linux-open-flags.patch +25 -0
  849. package/scripts/bun-riscv64/bun-patches/0022-zlib-riscv64-generic-kernels.patch +25 -0
  850. package/scripts/bun-riscv64/bun-patches/README.md +127 -0
  851. package/scripts/bun-riscv64/bun-version.json +202 -0
  852. package/scripts/bun-riscv64/run-build.sh +162 -0
  853. package/scripts/bun-riscv64/rust-core/0001-riscv64-rust-core-port.patch +868 -0
  854. package/scripts/bun-riscv64/rust-core/0002-second-wave-riscv64-source-gaps.patch +130 -0
  855. package/scripts/bun-riscv64/rust-core/0003-third-wave-riscv64-crash-handler-gaps.patch +78 -0
  856. package/scripts/bun-riscv64/rust-core/0004-rust-target-cpu-riscv64.patch +39 -0
  857. package/scripts/bun-riscv64/rust-core/0005-fifth-wave-riscv64-source-gaps.patch +96 -0
  858. package/scripts/bun-riscv64/rust-core/0006-cpp-wasm-and-inspector-guards-riscv64.patch +91 -0
  859. package/scripts/bun-riscv64/rust-core/0007-bun-alloc-max-align-t-riscv64.patch +36 -0
  860. package/scripts/bun-riscv64/rust-core/0008-workspace-lints-warn-not-deny-riscv64.patch +75 -0
  861. package/scripts/bun-riscv64/rust-core/0009-zigglobalobject-wasm-streaming-guards-riscv64.patch +109 -0
  862. package/scripts/bun-riscv64/rust-core/0010-tcc-externs-stub-on-riscv64.patch +62 -0
  863. package/scripts/bun-riscv64/rust-core/0011-clippy-ptr-cast-lints-warn-riscv64.patch +61 -0
  864. package/scripts/bun-riscv64/rust-core/README.md +80 -0
  865. package/scripts/bun-riscv64/rust-core/webkit-patches/0003-disable-dfg-ftl-on-riscv64.patch +60 -0
  866. package/scripts/bun-riscv64/rust-core/webkit-patches/0004-riscv64-do-not-force-wasm-in-c-loop.patch +31 -0
  867. package/scripts/bun-riscv64/rust-core/webkit-patches/0005-domjit-effect-allow-no-dfg-c-loop.patch +40 -0
  868. package/scripts/bun-riscv64/rust-core/webkit-patches/0006-disable-usewasm-when-webassembly-compiled-out.patch +33 -0
  869. package/scripts/bun-riscv64/rust-core/webkit-patches/0007-restore-dropped-includes-and-llint-fwd-decl.patch +31 -0
  870. package/scripts/bun-riscv64/validate.sh +264 -0
  871. package/scripts/bun-riscv64/webkit-patches/0001-cherry-pick-llint-riscv64.recipe +155 -0
  872. package/scripts/bun-riscv64/webkit-patches/0002-cherry-pick-baseline-jit-riscv64.recipe +40 -0
  873. package/scripts/bun-riscv64/webkit-patches/0003-disable-dfg-ftl-on-riscv64.patch +60 -0
  874. package/scripts/bun-riscv64/webkit-patches/0004-riscv64-do-not-force-wasm-in-c-loop.patch +31 -0
  875. package/scripts/bun-riscv64/webkit-patches/0005-domjit-effect-allow-no-dfg-c-loop.patch +40 -0
  876. package/scripts/bun-riscv64/webkit-patches/0006-disable-usewasm-when-webassembly-compiled-out.patch +33 -0
  877. package/scripts/bun-riscv64/webkit-patches/0007-restore-dropped-includes-and-llint-fwd-decl.patch +72 -0
  878. package/scripts/bun-riscv64/webkit-patches/README.md +146 -0
  879. package/scripts/check-homepage-public-readiness.mjs +353 -0
  880. package/scripts/check-homepage-release-data.mjs +110 -0
  881. package/scripts/check-i18n.mjs +1 -1
  882. package/scripts/check-real-local-chat.ts +147 -0
  883. package/scripts/check-real-local-provisioning.ts +104 -0
  884. package/scripts/check-real-local-reset.ts +249 -0
  885. package/scripts/check-sms-gateway-completion-audit.mjs +428 -0
  886. package/scripts/check-sms-gateway-readiness.mjs +266 -0
  887. package/scripts/clean-repo.mjs +5 -5
  888. package/scripts/codesign-mas.mjs +222 -16
  889. package/scripts/collect-docker-runtime-deps.mjs +229 -0
  890. package/scripts/continue-sms-gateway-work.mjs +121 -0
  891. package/scripts/copy-runtime-node-modules.ts +1050 -195
  892. package/scripts/deploy-cloud-api-production-gateway.mjs +52 -0
  893. package/scripts/desktop-build.mjs +965 -98
  894. package/scripts/dev-platform.mjs +346 -102
  895. package/scripts/dev-startup-smoke.mjs +248 -0
  896. package/scripts/dev-ui.mjs +418 -176
  897. package/scripts/disable-local-eliza-workspace.mjs +35 -0
  898. package/scripts/docker-ci-smoke.sh +465 -96
  899. package/scripts/docker-entrypoint.sh +62 -1
  900. package/scripts/docker-entrypoint.test.ts +283 -0
  901. package/scripts/ensure-avatars.mjs +2 -2
  902. package/scripts/ensure-electrobun-core.mjs +1 -1
  903. package/scripts/ensure-generated-core-proto-js.mjs +1 -1
  904. package/scripts/ensure-type-package-aliases.mjs +62 -5
  905. package/scripts/ensure-vision-deps.mjs +20 -1
  906. package/scripts/entry.ts +1 -1
  907. package/scripts/ffi-stub/Makefile +64 -0
  908. package/scripts/ffi-stub/README.md +391 -0
  909. package/scripts/ffi-stub/asr-ffi-smoke.ts +139 -0
  910. package/scripts/ffi-stub/ffi-stub.c +539 -0
  911. package/scripts/ffi-stub/ffi.h +538 -0
  912. package/scripts/ffi-stub/libelizainference_stub.so +0 -0
  913. package/scripts/ffi-stub/tts-stream-ffi-smoke.ts +349 -0
  914. package/scripts/generate-first-run-voicelines.mjs +194 -0
  915. package/scripts/generate-plugin-index.js +4 -3
  916. package/scripts/generate-static-asset-manifest.mjs +1 -1
  917. package/scripts/i18n-dynamic-keys.json +5 -5
  918. package/scripts/init-submodules.mjs +2 -2
  919. package/scripts/install-android-sms-gateway.md +177 -0
  920. package/scripts/install-android-sms-gateway.mjs +1088 -0
  921. package/scripts/ios-xcframework/README.md +74 -72
  922. package/scripts/ios-xcframework/build-xcframework.mjs +204 -43
  923. package/scripts/ios-xcframework/run-physical-device-smoke.mjs +1943 -0
  924. package/scripts/ios-xcframework/runtime-symbol-shim.c +450 -0
  925. package/scripts/kernel-patches/cpu-polar-kernels.mjs +441 -0
  926. package/scripts/kernel-patches/cpu-simd-kernels.mjs +253 -0
  927. package/scripts/kernel-patches/cpu-thread-parallelism.mjs +368 -0
  928. package/scripts/kernel-patches/cuda-kernels.mjs +117 -0
  929. package/scripts/kernel-patches/metal-kernels.mjs +1698 -109
  930. package/scripts/kernel-patches/server-omnivoice-route.mjs +718 -0
  931. package/scripts/kernel-patches/server-structured-output.mjs +279 -0
  932. package/scripts/kernel-patches/vulkan-dispatch-log.mjs +166 -0
  933. package/scripts/kernel-patches/vulkan-dispatch-log.test.mjs +50 -0
  934. package/scripts/kernel-patches/vulkan-dispatch-patches/01-vulkan-shaders-gen.patch +30 -16
  935. package/scripts/kernel-patches/vulkan-dispatch-patches/02-ggml-vulkan-pipelines.patch +75 -30
  936. package/scripts/kernel-patches/vulkan-kernels.mjs +800 -49
  937. package/scripts/lib/agent-source-watcher.mjs +173 -0
  938. package/scripts/lib/agent-source-watcher.test.mjs +184 -0
  939. package/scripts/lib/api-supervisor.mjs +78 -9
  940. package/scripts/lib/api-supervisor.test.mjs +121 -0
  941. package/scripts/lib/app-dir.mjs +2 -16
  942. package/scripts/lib/apple-entitlement-audit.mjs +655 -0
  943. package/scripts/lib/apple-entitlement-audit.test.mjs +144 -0
  944. package/scripts/lib/artifact-staleness.d.mts +33 -0
  945. package/scripts/lib/artifact-staleness.mjs +122 -0
  946. package/scripts/lib/artifact-staleness.test.mts +98 -0
  947. package/scripts/lib/bun-version-guard.mjs +13 -13
  948. package/scripts/lib/capacitor-plugin-build-needed.mjs +4 -3
  949. package/scripts/lib/capacitor-plugin-names.mjs +30 -14
  950. package/scripts/lib/desktop-preflight.mjs +9 -5
  951. package/scripts/lib/desktop-startup-embedding-warmup-policy.mjs +51 -0
  952. package/scripts/lib/desktop-startup-embedding-warmup-policy.test.mjs +55 -0
  953. package/scripts/lib/duet-bridge.d.mts +63 -0
  954. package/scripts/lib/duet-bridge.mjs +193 -0
  955. package/scripts/lib/ios-plist-url-scheme.mjs +80 -0
  956. package/scripts/lib/mobile-build-decisions.mjs +97 -0
  957. package/scripts/lib/node-path-env.mjs +4 -2
  958. package/scripts/lib/orchestrator-desktop-dev-banner.mjs +12 -3
  959. package/scripts/lib/patch-bun-exports.mjs +90 -27
  960. package/scripts/lib/patch-bun-exports.test.mjs +79 -0
  961. package/scripts/lib/renderer-build-action.mjs +35 -0
  962. package/scripts/lib/renderer-build-action.test.mjs +70 -0
  963. package/scripts/lib/renderer-build-manifest.d.mts +65 -0
  964. package/scripts/lib/renderer-build-manifest.mjs +257 -0
  965. package/scripts/lib/renderer-build-manifest.test.mts +277 -0
  966. package/scripts/lib/stage-android-agent.mjs +757 -99
  967. package/scripts/lib/sync-eliza-env-aliases.mjs +3 -25
  968. package/scripts/lib/ui-smoke-stub-decision.mjs +33 -0
  969. package/scripts/lib/ui-smoke-stub-decision.test.mjs +46 -0
  970. package/scripts/lib/verify-ondevice-artifact.d.mts +16 -0
  971. package/scripts/lib/verify-ondevice-artifact.mjs +61 -0
  972. package/scripts/lib/verify-ondevice-artifact.test.mts +98 -0
  973. package/scripts/lib/vite-renderer-dist-stale.mjs +5 -0
  974. package/scripts/lib/voice-latency-report.mjs +154 -0
  975. package/scripts/lib/websocket-pending-queue.ts +92 -0
  976. package/scripts/lifeops-prompt-benchmark.ts +21 -12
  977. package/scripts/link-docker-local-app-packages.mjs +109 -36
  978. package/scripts/local-stt-bench.ts +192 -0
  979. package/scripts/maintain-cloud-api-production-gateway.mjs +54 -0
  980. package/scripts/mas-smoke.mjs +459 -0
  981. package/scripts/mas-smoke.test.mjs +220 -0
  982. package/scripts/mobile-auth-simulator-smoke.mjs +0 -1
  983. package/scripts/normalize-eliza-capture.ts +97 -0
  984. package/scripts/omnivoice-fuse/prepare.mjs +2543 -23
  985. package/scripts/pack-upstreams.mjs +65 -5
  986. package/scripts/package-electrobun-linux.mjs +303 -0
  987. package/scripts/patch-deps.mjs +5 -3
  988. package/scripts/patches/llama-asr-word-timestamps.patch +218 -0
  989. package/scripts/playwright-ui-live-stack.ts +588 -157
  990. package/scripts/playwright-ui-smoke-api-stub.mjs +3495 -111
  991. package/scripts/pre-review-local.mjs +2 -2
  992. package/scripts/prepare-ios-cocoapods.sh +41 -3
  993. package/scripts/release-check.ts +180 -84
  994. package/scripts/relink-workspace-packages-to-dist.mjs +21 -4
  995. package/scripts/rt.mjs +16 -1
  996. package/scripts/run-biome-check.mjs +1 -1
  997. package/scripts/run-coding-agent-e2e.mjs +3 -3
  998. package/scripts/run-eliza-app-core-script.mjs +34 -0
  999. package/scripts/run-local-plugin-live-smoke.mjs +66 -2
  1000. package/scripts/run-mobile-build-android-app-actions.test.mjs +426 -0
  1001. package/scripts/run-mobile-build-brand-separation.test.mts +33 -0
  1002. package/scripts/run-mobile-build-ios-engine-gate.test.mjs +85 -0
  1003. package/scripts/run-mobile-build-mtp-staleness.test.mts +198 -0
  1004. package/scripts/run-mobile-build.mjs +5082 -610
  1005. package/scripts/run-node-runtime.mjs +184 -7
  1006. package/scripts/run-node-runtime.test.mjs +167 -0
  1007. package/scripts/run-node-tsx.mjs +80 -33
  1008. package/scripts/run-node.mjs +41 -1
  1009. package/scripts/run-production-build.mjs +34 -27
  1010. package/scripts/run-release-check.mjs +19 -0
  1011. package/scripts/run-release-contract-suite.mjs +107 -14
  1012. package/scripts/run-ui-smoke-playwright-suite.mjs +0 -2
  1013. package/scripts/runtime-package-manifest.ts +21 -3
  1014. package/scripts/serve-real-local-agent.ts +72 -0
  1015. package/scripts/setup-upstreams.mjs +42 -1
  1016. package/scripts/sms-gateway-status.mjs +194 -0
  1017. package/scripts/stage-android-agent.test.mjs +97 -0
  1018. package/scripts/stage-desktop-fused-lib.mjs +453 -0
  1019. package/scripts/stage-elizavoice-lib.mjs +363 -0
  1020. package/scripts/startup-integration-script-drift.test.ts +82 -4
  1021. package/scripts/streaming-pipeline-bench.ts +543 -0
  1022. package/scripts/sync-homepage-porkbun-dns.mjs +262 -0
  1023. package/scripts/test-sms-gateway-software.mjs +100 -0
  1024. package/scripts/type-audit.mjs +1 -1
  1025. package/scripts/validate-bluebubbles-outbound.mjs +293 -0
  1026. package/scripts/validate-cdn-assets.mjs +15 -7
  1027. package/scripts/validate-regression-matrix.mjs +109 -8
  1028. package/scripts/verify-android-sms-gateway-e2e.mjs +362 -0
  1029. package/scripts/verify-bluebubbles-gateway-e2e.mjs +191 -0
  1030. package/scripts/verify-bluebubbles-inbound-readiness.mjs +88 -0
  1031. package/scripts/verify-cloud-api-production-deploy.mjs +87 -0
  1032. package/scripts/verify-cloud-sms-onboarding-flow.mjs +336 -0
  1033. package/scripts/verify-ondevice-artifact.mjs +111 -0
  1034. package/scripts/voice/freeze-voice.mjs +521 -0
  1035. package/scripts/voice-attribution-smoke.ts +644 -0
  1036. package/scripts/voice-create-profile.mjs +379 -0
  1037. package/scripts/voice-duet.mjs +1355 -0
  1038. package/scripts/voice-e2e-hardware.ts +877 -0
  1039. package/scripts/voice-interactive.mjs +1721 -0
  1040. package/scripts/voice-latency-report.mjs +96 -0
  1041. package/scripts/voice-latency-report.test.ts +176 -0
  1042. package/scripts/voice-preset/build-default-voice-preset.mjs +249 -0
  1043. package/scripts/voice-preset/build-onboarding-voice.mjs +281 -0
  1044. package/scripts/watch-sms-gateway-readiness.mjs +303 -0
  1045. package/scripts/write-homepage-release-data.mjs +458 -26
  1046. package/security/agent-vault-id.d.ts +2 -2
  1047. package/security/agent-vault-id.js +1 -1
  1048. package/security/hydrate-wallet-keys-from-platform-store.d.ts.map +1 -1
  1049. package/security/hydrate-wallet-keys-from-platform-store.js +23 -14
  1050. package/security/platform-secure-store-node.d.ts +3 -3
  1051. package/security/platform-secure-store-node.js +3 -3
  1052. package/security/wallet-os-store-actions.d.ts +0 -9
  1053. package/security/wallet-os-store-actions.d.ts.map +1 -1
  1054. package/security/wallet-os-store-actions.js +3 -10
  1055. package/services/account-pool.d.ts +23 -14
  1056. package/services/account-pool.d.ts.map +1 -1
  1057. package/services/account-pool.js +86 -24
  1058. package/services/account-usage.d.ts.map +1 -1
  1059. package/services/account-usage.js +2 -5
  1060. package/services/ambient-audio/consent.d.ts +9 -0
  1061. package/services/ambient-audio/consent.d.ts.map +1 -0
  1062. package/services/ambient-audio/consent.js +28 -0
  1063. package/services/ambient-audio/index.d.ts +7 -0
  1064. package/services/ambient-audio/index.d.ts.map +1 -0
  1065. package/services/ambient-audio/index.js +4 -0
  1066. package/services/ambient-audio/replay-buffer.d.ts +14 -0
  1067. package/services/ambient-audio/replay-buffer.d.ts.map +1 -0
  1068. package/services/ambient-audio/replay-buffer.js +66 -0
  1069. package/services/ambient-audio/response-gate.d.ts +3 -0
  1070. package/services/ambient-audio/response-gate.d.ts.map +1 -0
  1071. package/services/ambient-audio/response-gate.js +33 -0
  1072. package/services/ambient-audio/service.d.ts +22 -0
  1073. package/services/ambient-audio/service.d.ts.map +1 -0
  1074. package/services/ambient-audio/service.js +47 -0
  1075. package/services/ambient-audio/types.d.ts +42 -0
  1076. package/services/ambient-audio/types.d.ts.map +1 -0
  1077. package/services/app-updates/update-policy.d.ts +64 -0
  1078. package/services/app-updates/update-policy.d.ts.map +1 -0
  1079. package/services/app-updates/update-policy.js +228 -0
  1080. package/services/auth-store.d.ts +37 -1
  1081. package/services/auth-store.d.ts.map +1 -1
  1082. package/services/auth-store.js +59 -26
  1083. package/services/cloud-jwks-store.d.ts +3 -3
  1084. package/services/cloud-jwks-store.d.ts.map +1 -1
  1085. package/services/cloud-jwks-store.js +5 -8
  1086. package/services/coding-account-bridge.d.ts +71 -0
  1087. package/services/coding-account-bridge.d.ts.map +1 -0
  1088. package/services/coding-account-bridge.js +267 -0
  1089. package/services/connector-target-catalog.d.ts +11 -4
  1090. package/services/connector-target-catalog.d.ts.map +1 -1
  1091. package/services/connector-target-catalog.js +7 -4
  1092. package/services/credential-tunnel-service.d.ts +66 -0
  1093. package/services/credential-tunnel-service.d.ts.map +1 -0
  1094. package/services/credential-tunnel-service.js +227 -0
  1095. package/services/github-credentials.d.ts +1 -1
  1096. package/services/github-credentials.js +1 -1
  1097. package/services/inference-abort.d.ts +47 -0
  1098. package/services/inference-abort.d.ts.map +1 -0
  1099. package/services/inference-abort.js +76 -0
  1100. package/services/persistence.d.ts +2 -3
  1101. package/services/persistence.d.ts.map +1 -1
  1102. package/services/persistence.js +2 -3
  1103. package/services/phrase-chunked-tts.d.ts +136 -0
  1104. package/services/phrase-chunked-tts.d.ts.map +1 -0
  1105. package/services/phrase-chunked-tts.js +208 -0
  1106. package/services/sandbox-registry.d.ts +78 -0
  1107. package/services/sandbox-registry.d.ts.map +1 -0
  1108. package/services/sandbox-registry.js +323 -0
  1109. package/services/secrets-manager-installer.d.ts +8 -1
  1110. package/services/secrets-manager-installer.d.ts.map +1 -1
  1111. package/services/secrets-manager-installer.js +27 -2
  1112. package/services/sensitive-requests/cloud-link-adapter.d.ts +15 -0
  1113. package/services/sensitive-requests/cloud-link-adapter.d.ts.map +1 -0
  1114. package/services/sensitive-requests/cloud-link-adapter.js +73 -0
  1115. package/services/sensitive-requests/index.d.ts +27 -0
  1116. package/services/sensitive-requests/index.d.ts.map +1 -0
  1117. package/services/sensitive-requests/index.js +51 -0
  1118. package/services/sensitive-requests/instruct-dm-only-adapter.d.ts +14 -0
  1119. package/services/sensitive-requests/instruct-dm-only-adapter.d.ts.map +1 -0
  1120. package/services/sensitive-requests/instruct-dm-only-adapter.js +22 -0
  1121. package/services/sensitive-requests/owner-app-inline-adapter.d.ts +3 -0
  1122. package/services/sensitive-requests/owner-app-inline-adapter.d.ts.map +1 -0
  1123. package/services/sensitive-requests/owner-app-inline-adapter.js +146 -0
  1124. package/services/sensitive-requests/owner-app-oauth-adapter.d.ts +3 -0
  1125. package/services/sensitive-requests/owner-app-oauth-adapter.d.ts.map +1 -0
  1126. package/services/sensitive-requests/owner-app-oauth-adapter.js +156 -0
  1127. package/services/sensitive-requests/public-link-adapter.d.ts +14 -0
  1128. package/services/sensitive-requests/public-link-adapter.d.ts.map +1 -0
  1129. package/services/sensitive-requests/public-link-adapter.js +86 -0
  1130. package/services/sensitive-requests/tunnel-link-adapter.d.ts +17 -0
  1131. package/services/sensitive-requests/tunnel-link-adapter.d.ts.map +1 -0
  1132. package/services/sensitive-requests/tunnel-link-adapter.js +38 -0
  1133. package/services/steward-credentials.d.ts +1 -1
  1134. package/services/steward-credentials.d.ts.map +1 -1
  1135. package/services/steward-credentials.js +10 -6
  1136. package/services/steward-sidecar/health-check.d.ts.map +1 -1
  1137. package/services/steward-sidecar/health-check.js +4 -3
  1138. package/services/steward-sidecar/process-management.d.ts +1 -1
  1139. package/services/steward-sidecar/process-management.d.ts.map +1 -1
  1140. package/services/steward-sidecar/process-management.js +9 -3
  1141. package/services/steward-sidecar/types.d.ts +1 -1
  1142. package/services/steward-sidecar/types.d.ts.map +1 -1
  1143. package/services/steward-sidecar/wallet-setup.d.ts +1 -1
  1144. package/services/steward-sidecar/wallet-setup.d.ts.map +1 -1
  1145. package/services/steward-sidecar/wallet-setup.js +8 -7
  1146. package/services/steward-sidecar.d.ts +5 -5
  1147. package/services/steward-sidecar.d.ts.map +1 -1
  1148. package/services/steward-sidecar.js +27 -19
  1149. package/services/task-host-capabilities.d.ts +60 -0
  1150. package/services/task-host-capabilities.d.ts.map +1 -0
  1151. package/services/task-host-capabilities.js +122 -0
  1152. package/services/tool-call-cache/index.d.ts +2 -2
  1153. package/services/tool-call-cache/index.d.ts.map +1 -1
  1154. package/services/tool-call-cache/index.js +1 -1
  1155. package/services/trigger-event-bridge.js +1 -1
  1156. package/services/tunnel-to-mobile/index.d.ts +2 -0
  1157. package/services/tunnel-to-mobile/index.d.ts.map +1 -0
  1158. package/services/tunnel-to-mobile/index.js +1 -0
  1159. package/services/tunnel-to-mobile/tunnel-to-mobile-client.d.ts +105 -0
  1160. package/services/tunnel-to-mobile/tunnel-to-mobile-client.d.ts.map +1 -0
  1161. package/services/tunnel-to-mobile/tunnel-to-mobile-client.js +190 -0
  1162. package/services/vault-bootstrap.d.ts.map +1 -1
  1163. package/services/vault-bootstrap.js +52 -21
  1164. package/services/vault-mirror.d.ts +1 -1
  1165. package/services/vault-mirror.d.ts.map +1 -1
  1166. package/services/vault-mirror.js +29 -6
  1167. package/services/voice-profiles/diarization-pipeline.d.ts +6 -0
  1168. package/services/voice-profiles/diarization-pipeline.d.ts.map +1 -0
  1169. package/services/voice-profiles/diarization-pipeline.js +20 -0
  1170. package/services/voice-profiles/index.d.ts +12 -0
  1171. package/services/voice-profiles/index.d.ts.map +1 -0
  1172. package/services/voice-profiles/index.js +5 -0
  1173. package/services/voice-profiles/nickname-evaluator.d.ts +14 -0
  1174. package/services/voice-profiles/nickname-evaluator.d.ts.map +1 -0
  1175. package/services/voice-profiles/nickname-evaluator.js +46 -0
  1176. package/services/voice-profiles/owner-confidence.d.ts +10 -0
  1177. package/services/voice-profiles/owner-confidence.d.ts.map +1 -0
  1178. package/services/voice-profiles/owner-confidence.js +38 -0
  1179. package/services/voice-profiles/private-challenge.d.ts +20 -0
  1180. package/services/voice-profiles/private-challenge.d.ts.map +1 -0
  1181. package/services/voice-profiles/private-challenge.js +44 -0
  1182. package/services/voice-profiles/store.d.ts +21 -0
  1183. package/services/voice-profiles/store.d.ts.map +1 -0
  1184. package/services/voice-profiles/store.js +50 -0
  1185. package/services/voice-profiles/types.d.ts +38 -0
  1186. package/services/voice-profiles/types.d.ts.map +1 -0
  1187. package/services/voice-profiles/types.js +1 -0
  1188. package/styles/electrobun-mac-window-drag.css +4 -4
  1189. package/test/helpers/__tests__/live-agent-test.smoke.test.ts +43 -70
  1190. package/test/helpers/browser-mocks.ts +2 -2
  1191. package/test/helpers/conditional-tests.ts +2 -2
  1192. package/test/helpers/live-agent-test.ts +537 -551
  1193. package/test/helpers/live-provider.test.ts +95 -5
  1194. package/test/helpers/live-provider.ts +234 -56
  1195. package/test/helpers/live-runtime-server.ts +4 -4
  1196. package/test/helpers/pglite-runtime.ts +1 -1
  1197. package/test/helpers/real-runtime.ts +72 -20
  1198. package/test/helpers/trajectory-harness.ts +11 -7
  1199. package/test/scripts/start-eliza-live.ts +9 -0
  1200. package/test/scripts/test-parallel.mjs +1 -1
  1201. package/test/scripts/test-root-unit.mjs +6 -7
  1202. package/test/scripts/websocket-pending-queue.test.ts +119 -0
  1203. package/test-support/test-helpers.d.ts +0 -33
  1204. package/test-support/test-helpers.d.ts.map +1 -1
  1205. package/test-support/test-helpers.js +81 -189
  1206. package/ui-compat.d.ts +14 -2
  1207. package/ui-compat.d.ts.map +1 -1
  1208. package/ui-compat.js +23 -3
  1209. package/api/auth-pairing-compat-routes.d.ts +0 -17
  1210. package/api/auth-pairing-compat-routes.d.ts.map +0 -1
  1211. package/api/auth-pairing-compat-routes.js +0 -301
  1212. package/api/local-inference-compat-routes.d.ts +0 -16
  1213. package/api/local-inference-compat-routes.d.ts.map +0 -1
  1214. package/api/local-inference-compat-routes.js +0 -617
  1215. package/api/onboarding-compat-routes.d.ts +0 -4
  1216. package/api/onboarding-compat-routes.d.ts.map +0 -1
  1217. package/api/onboarding-compat-routes.js +0 -207
  1218. package/api/plugins-compat-routes.d.ts +0 -103
  1219. package/api/plugins-compat-routes.d.ts.map +0 -1
  1220. package/api/plugins-compat-routes.js +0 -1181
  1221. package/api/server-onboarding-compat.d.ts +0 -31
  1222. package/api/server-onboarding-compat.d.ts.map +0 -1
  1223. package/api/server-onboarding-compat.js +0 -283
  1224. package/benchmark/cua-routes.d.ts +0 -10
  1225. package/benchmark/cua-routes.d.ts.map +0 -1
  1226. package/benchmark/cua-routes.js +0 -179
  1227. package/benchmark/mock-plugin-base.d.ts +0 -9
  1228. package/benchmark/mock-plugin-base.d.ts.map +0 -1
  1229. package/benchmark/mock-plugin-base.js +0 -325
  1230. package/cli/parse-duration.d.ts +0 -5
  1231. package/cli/parse-duration.d.ts.map +0 -1
  1232. package/cli/parse-duration.js +0 -27
  1233. package/patches/llama-cpp-capacitor@0.1.5.patch +0 -2387
  1234. package/platform/agent-browser-stub.d.ts +0 -27
  1235. package/platform/agent-browser-stub.d.ts.map +0 -1
  1236. package/platform/agent-browser-stub.js +0 -16
  1237. package/platforms/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +0 -26
  1238. package/platforms/android/app/src/main/res/drawable/ic_launcher_background.xml +0 -170
  1239. package/platforms/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +0 -34
  1240. package/platforms/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +0 -18
  1241. package/platforms/electrobun/assets/appIcon.iconset/icon_512x512@2x.png +0 -0
  1242. package/platforms/electrobun/assets/appIcon.png +0 -0
  1243. package/platforms/electrobun/scripts/build-whisper-universal.sh +0 -137
  1244. package/platforms/electrobun/scripts/build-whisper.sh +0 -95
  1245. package/platforms/electrobun/scripts/ensure-whisper-model.sh +0 -93
  1246. package/platforms/electrobun/src/libMacWindowEffects.dylib +0 -0
  1247. package/platforms/electrobun/src/native/whisper.ts +0 -280
  1248. package/platforms/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png +0 -0
  1249. package/platforms/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png +0 -0
  1250. package/platforms/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png +0 -0
  1251. package/registry/generate-apps.d.ts +0 -2
  1252. package/registry/generate-apps.d.ts.map +0 -1
  1253. package/registry/generate-apps.js +0 -338
  1254. package/registry/generate.d.ts +0 -2
  1255. package/registry/generate.d.ts.map +0 -1
  1256. package/registry/generate.js +0 -506
  1257. package/registry/loader.d.ts +0 -27
  1258. package/registry/loader.d.ts.map +0 -1
  1259. package/registry/loader.js +0 -111
  1260. package/registry/schema.d.ts +0 -989
  1261. package/registry/schema.d.ts.map +0 -1
  1262. package/registry/schema.js +0 -264
  1263. package/runtime/embedding-manager-support.d.ts +0 -77
  1264. package/runtime/embedding-manager-support.d.ts.map +0 -1
  1265. package/runtime/embedding-manager-support.js +0 -309
  1266. package/runtime/embedding-presets.d.ts +0 -5
  1267. package/runtime/embedding-presets.d.ts.map +0 -1
  1268. package/runtime/embedding-presets.js +0 -47
  1269. package/runtime/embedding-warmup-policy.d.ts +0 -13
  1270. package/runtime/embedding-warmup-policy.d.ts.map +0 -1
  1271. package/runtime/embedding-warmup-policy.js +0 -33
  1272. package/runtime/ensure-local-inference-handler.d.ts +0 -25
  1273. package/runtime/ensure-local-inference-handler.d.ts.map +0 -1
  1274. package/runtime/ensure-local-inference-handler.js +0 -389
  1275. package/runtime/mobile-local-inference-gate.d.ts +0 -21
  1276. package/runtime/mobile-local-inference-gate.d.ts.map +0 -1
  1277. package/runtime/mobile-local-inference-gate.js +0 -24
  1278. package/scripts/aosp/avd-test.mjs +0 -403
  1279. package/scripts/aosp/boot-validate.mjs +0 -536
  1280. package/scripts/aosp/build-aosp.mjs +0 -448
  1281. package/scripts/aosp/build-bootanimation.mjs +0 -178
  1282. package/scripts/aosp/capture-screens.mjs +0 -325
  1283. package/scripts/aosp/e2e-validate.mjs +0 -225
  1284. package/scripts/aosp/lint-init-rc.mjs +0 -258
  1285. package/scripts/aosp/llama-shim/eliza_llama_shim.c +0 -276
  1286. package/scripts/aosp/sim.mjs +0 -277
  1287. package/scripts/aosp/sync-to-aosp.mjs +0 -134
  1288. package/scripts/aosp/validate.mjs +0 -1273
  1289. package/scripts/build-llama-cpp-dflash.mjs +0 -1866
  1290. package/scripts/generate-onboarding-voicelines.mjs +0 -194
  1291. package/scripts/generated/static-asset-manifest.json +0 -4
  1292. package/scripts/normalize-parallax-capture.ts +0 -97
  1293. package/scripts/omnivoice-fuse/Makefile +0 -44
  1294. package/scripts/omnivoice-fuse/README.md +0 -266
  1295. package/scripts/omnivoice-fuse/cmake-graft.mjs +0 -180
  1296. package/scripts/omnivoice-fuse/ffi-stub.c +0 -222
  1297. package/scripts/omnivoice-fuse/ffi.h +0 -158
  1298. package/scripts/omnivoice-fuse/libelizainference_stub.dylib +0 -0
  1299. package/scripts/omnivoice-fuse/verify-symbols.mjs +0 -138
  1300. package/security/cloud-secret-store.d.ts +0 -34
  1301. package/security/cloud-secret-store.d.ts.map +0 -1
  1302. package/security/cloud-secret-store.js +0 -65
  1303. package/security/export-guard.d.ts +0 -34
  1304. package/security/export-guard.d.ts.map +0 -1
  1305. package/security/export-guard.js +0 -127
  1306. package/services/local-inference/__stress__/cache-stress-helpers.d.ts +0 -76
  1307. package/services/local-inference/__stress__/cache-stress-helpers.d.ts.map +0 -1
  1308. package/services/local-inference/__stress__/cache-stress-helpers.js +0 -238
  1309. package/services/local-inference/active-model.d.ts +0 -180
  1310. package/services/local-inference/active-model.d.ts.map +0 -1
  1311. package/services/local-inference/active-model.js +0 -362
  1312. package/services/local-inference/assignments.d.ts +0 -58
  1313. package/services/local-inference/assignments.d.ts.map +0 -1
  1314. package/services/local-inference/assignments.js +0 -179
  1315. package/services/local-inference/backend.d.ts +0 -200
  1316. package/services/local-inference/backend.d.ts.map +0 -1
  1317. package/services/local-inference/backend.js +0 -242
  1318. package/services/local-inference/bundled-models.d.ts +0 -34
  1319. package/services/local-inference/bundled-models.d.ts.map +0 -1
  1320. package/services/local-inference/bundled-models.js +0 -104
  1321. package/services/local-inference/cache-bridge.d.ts +0 -184
  1322. package/services/local-inference/cache-bridge.d.ts.map +0 -1
  1323. package/services/local-inference/cache-bridge.js +0 -333
  1324. package/services/local-inference/catalog.d.ts +0 -57
  1325. package/services/local-inference/catalog.d.ts.map +0 -1
  1326. package/services/local-inference/catalog.js +0 -262
  1327. package/services/local-inference/conversation-registry.d.ts +0 -122
  1328. package/services/local-inference/conversation-registry.d.ts.map +0 -1
  1329. package/services/local-inference/conversation-registry.js +0 -182
  1330. package/services/local-inference/device-bridge.d.ts +0 -139
  1331. package/services/local-inference/device-bridge.d.ts.map +0 -1
  1332. package/services/local-inference/device-bridge.js +0 -774
  1333. package/services/local-inference/dflash-doctor.d.ts +0 -27
  1334. package/services/local-inference/dflash-doctor.d.ts.map +0 -1
  1335. package/services/local-inference/dflash-doctor.js +0 -149
  1336. package/services/local-inference/dflash-server.d.ts +0 -248
  1337. package/services/local-inference/dflash-server.d.ts.map +0 -1
  1338. package/services/local-inference/dflash-server.js +0 -1076
  1339. package/services/local-inference/downloader.d.ts +0 -48
  1340. package/services/local-inference/downloader.d.ts.map +0 -1
  1341. package/services/local-inference/downloader.js +0 -688
  1342. package/services/local-inference/engine.d.ts +0 -282
  1343. package/services/local-inference/engine.d.ts.map +0 -1
  1344. package/services/local-inference/engine.js +0 -743
  1345. package/services/local-inference/external-scanner.d.ts +0 -17
  1346. package/services/local-inference/external-scanner.d.ts.map +0 -1
  1347. package/services/local-inference/external-scanner.js +0 -261
  1348. package/services/local-inference/handler-registry.d.ts +0 -72
  1349. package/services/local-inference/handler-registry.d.ts.map +0 -1
  1350. package/services/local-inference/handler-registry.js +0 -159
  1351. package/services/local-inference/hardware.d.ts +0 -26
  1352. package/services/local-inference/hardware.d.ts.map +0 -1
  1353. package/services/local-inference/hardware.js +0 -139
  1354. package/services/local-inference/hf-search.d.ts +0 -19
  1355. package/services/local-inference/hf-search.d.ts.map +0 -1
  1356. package/services/local-inference/hf-search.js +0 -169
  1357. package/services/local-inference/index.d.ts +0 -10
  1358. package/services/local-inference/index.d.ts.map +0 -1
  1359. package/services/local-inference/index.js +0 -7
  1360. package/services/local-inference/llama-server-metrics.d.ts +0 -108
  1361. package/services/local-inference/llama-server-metrics.d.ts.map +0 -1
  1362. package/services/local-inference/llama-server-metrics.js +0 -175
  1363. package/services/local-inference/manifest/index.d.ts +0 -4
  1364. package/services/local-inference/manifest/index.d.ts.map +0 -1
  1365. package/services/local-inference/manifest/index.js +0 -5
  1366. package/services/local-inference/manifest/schema.d.ts +0 -419
  1367. package/services/local-inference/manifest/schema.d.ts.map +0 -1
  1368. package/services/local-inference/manifest/schema.js +0 -227
  1369. package/services/local-inference/manifest/types.d.ts +0 -23
  1370. package/services/local-inference/manifest/types.d.ts.map +0 -1
  1371. package/services/local-inference/manifest/types.js +0 -5
  1372. package/services/local-inference/manifest/validator.d.ts +0 -43
  1373. package/services/local-inference/manifest/validator.d.ts.map +0 -1
  1374. package/services/local-inference/manifest/validator.js +0 -187
  1375. package/services/local-inference/paths.d.ts +0 -8
  1376. package/services/local-inference/paths.d.ts.map +0 -1
  1377. package/services/local-inference/paths.js +0 -7
  1378. package/services/local-inference/providers.d.ts +0 -61
  1379. package/services/local-inference/providers.d.ts.map +0 -1
  1380. package/services/local-inference/providers.js +0 -334
  1381. package/services/local-inference/ram-budget.d.ts +0 -57
  1382. package/services/local-inference/ram-budget.d.ts.map +0 -1
  1383. package/services/local-inference/ram-budget.js +0 -107
  1384. package/services/local-inference/readiness.d.ts +0 -9
  1385. package/services/local-inference/readiness.d.ts.map +0 -1
  1386. package/services/local-inference/readiness.js +0 -153
  1387. package/services/local-inference/recommendation.d.ts +0 -62
  1388. package/services/local-inference/recommendation.d.ts.map +0 -1
  1389. package/services/local-inference/recommendation.js +0 -309
  1390. package/services/local-inference/registry.d.ts +0 -35
  1391. package/services/local-inference/registry.d.ts.map +0 -1
  1392. package/services/local-inference/registry.js +0 -117
  1393. package/services/local-inference/router-handler.d.ts +0 -51
  1394. package/services/local-inference/router-handler.d.ts.map +0 -1
  1395. package/services/local-inference/router-handler.js +0 -165
  1396. package/services/local-inference/routing-policy.d.ts +0 -55
  1397. package/services/local-inference/routing-policy.d.ts.map +0 -1
  1398. package/services/local-inference/routing-policy.js +0 -195
  1399. package/services/local-inference/routing-preferences.d.ts +0 -8
  1400. package/services/local-inference/routing-preferences.d.ts.map +0 -1
  1401. package/services/local-inference/routing-preferences.js +0 -7
  1402. package/services/local-inference/service.d.ts +0 -88
  1403. package/services/local-inference/service.d.ts.map +0 -1
  1404. package/services/local-inference/service.js +0 -210
  1405. package/services/local-inference/session-pool.d.ts +0 -72
  1406. package/services/local-inference/session-pool.d.ts.map +0 -1
  1407. package/services/local-inference/session-pool.js +0 -125
  1408. package/services/local-inference/types.d.ts +0 -309
  1409. package/services/local-inference/types.d.ts.map +0 -1
  1410. package/services/local-inference/types.js +0 -23
  1411. package/services/local-inference/verify.d.ts +0 -8
  1412. package/services/local-inference/verify.d.ts.map +0 -1
  1413. package/services/local-inference/verify.js +0 -7
  1414. package/services/local-inference/voice/barge-in.d.ts +0 -15
  1415. package/services/local-inference/voice/barge-in.d.ts.map +0 -1
  1416. package/services/local-inference/voice/barge-in.js +0 -20
  1417. package/services/local-inference/voice/engine-bridge.d.ts +0 -256
  1418. package/services/local-inference/voice/engine-bridge.d.ts.map +0 -1
  1419. package/services/local-inference/voice/engine-bridge.js +0 -398
  1420. package/services/local-inference/voice/ffi-bindings.d.ts +0 -114
  1421. package/services/local-inference/voice/ffi-bindings.d.ts.map +0 -1
  1422. package/services/local-inference/voice/ffi-bindings.js +0 -281
  1423. package/services/local-inference/voice/index.d.ts +0 -51
  1424. package/services/local-inference/voice/index.d.ts.map +0 -1
  1425. package/services/local-inference/voice/index.js +0 -50
  1426. package/services/local-inference/voice/lifecycle.d.ts +0 -135
  1427. package/services/local-inference/voice/lifecycle.d.ts.map +0 -1
  1428. package/services/local-inference/voice/lifecycle.js +0 -189
  1429. package/services/local-inference/voice/phoneme-tokenizer.d.ts +0 -58
  1430. package/services/local-inference/voice/phoneme-tokenizer.d.ts.map +0 -1
  1431. package/services/local-inference/voice/phoneme-tokenizer.js +0 -53
  1432. package/services/local-inference/voice/phrase-cache.d.ts +0 -24
  1433. package/services/local-inference/voice/phrase-cache.d.ts.map +0 -1
  1434. package/services/local-inference/voice/phrase-cache.js +0 -32
  1435. package/services/local-inference/voice/phrase-chunker.d.ts +0 -20
  1436. package/services/local-inference/voice/phrase-chunker.d.ts.map +0 -1
  1437. package/services/local-inference/voice/phrase-chunker.js +0 -85
  1438. package/services/local-inference/voice/ring-buffer.d.ts +0 -40
  1439. package/services/local-inference/voice/ring-buffer.d.ts.map +0 -1
  1440. package/services/local-inference/voice/ring-buffer.js +0 -85
  1441. package/services/local-inference/voice/rollback-queue.d.ts +0 -24
  1442. package/services/local-inference/voice/rollback-queue.d.ts.map +0 -1
  1443. package/services/local-inference/voice/rollback-queue.js +0 -49
  1444. package/services/local-inference/voice/scheduler.d.ts +0 -47
  1445. package/services/local-inference/voice/scheduler.d.ts.map +0 -1
  1446. package/services/local-inference/voice/scheduler.js +0 -123
  1447. package/services/local-inference/voice/shared-resources.d.ts +0 -119
  1448. package/services/local-inference/voice/shared-resources.d.ts.map +0 -1
  1449. package/services/local-inference/voice/shared-resources.js +0 -83
  1450. package/services/local-inference/voice/speaker-preset-cache.d.ts +0 -28
  1451. package/services/local-inference/voice/speaker-preset-cache.d.ts.map +0 -1
  1452. package/services/local-inference/voice/speaker-preset-cache.js +0 -44
  1453. package/services/local-inference/voice/types.d.ts +0 -80
  1454. package/services/local-inference/voice/types.d.ts.map +0 -1
  1455. package/services/local-inference/voice/voice-preset-format.d.ts +0 -56
  1456. package/services/local-inference/voice/voice-preset-format.d.ts.map +0 -1
  1457. package/services/local-inference/voice/voice-preset-format.js +0 -184
  1458. package/services/plugin-installer.d.ts +0 -22
  1459. package/services/plugin-installer.d.ts.map +0 -1
  1460. package/services/plugin-installer.js +0 -41
  1461. package/test/helpers/i18n.ts +0 -5
  1462. package/test/helpers/loopback.ts +0 -33
  1463. package/test/helpers/react-test.ts +0 -40
  1464. package/test/helpers/skip-without.ts +0 -53
  1465. package/test/scripts/task-agent-live-smoke.ts +0 -1335
  1466. /package/services/{local-inference/voice → ambient-audio}/types.js +0 -0
@@ -17,11 +17,10 @@
17
17
  * remote -- it simply connects to `http://localhost:{port}`.
18
18
  *
19
19
  * **Port policy (WHY):** we resolve a **free** loopback desktop API port from
20
- * `ELIZA_API_PORT`, `ELIZA_API_PORT`, or `ELIZA_PORT` (see
21
- * `findFirstAvailableLoopbackPort`) instead of SIGKILL-ing listeners by
22
- * default, so two desktop apps can run side by side. Optional
23
- * `ELIZA_AGENT_RECLAIM_STALE_PORT=1` (legacy: `ELIZA_AGENT_RECLAIM_STALE_PORT`)
24
- * restores lsof-based reclaim for single-instance dev.
20
+ * `ELIZA_API_PORT` or `ELIZA_PORT` (see `findFirstAvailableLoopbackPort`)
21
+ * instead of SIGKILL-ing listeners by default, so two desktop apps can run
22
+ * side by side. Optional `ELIZA_AGENT_RECLAIM_STALE_PORT=1` restores
23
+ * lsof-based reclaim for single-instance dev.
25
24
  */
26
25
 
27
26
  import crypto from "node:crypto";
@@ -29,15 +28,30 @@ import fs from "node:fs";
29
28
  import os from "node:os";
30
29
  import path from "node:path";
31
30
  import {
32
- resolveApiToken,
33
- resolveDesktopApiPort,
34
- resolveDisableAutoApiToken,
35
- setApiToken,
31
+ resolveApiToken,
32
+ resolveDesktopApiPort,
33
+ resolveDisableAutoApiToken,
34
+ setApiToken,
36
35
  } from "@elizaos/shared";
37
36
  import { Utils } from "electrobun/bun";
38
37
  import { resolveDesktopRuntimeMode } from "../api-base";
39
38
  import { getBrandConfig } from "../brand-config";
40
39
  import { DEFAULT_API_PORT } from "../constants";
40
+ import {
41
+ acquireDatabaseStartupLock,
42
+ applyDatabaseResolutionToEnv,
43
+ backupPgliteDirectory,
44
+ classifyDatabaseError,
45
+ createDatabaseSnapshot,
46
+ createUnknownDatabaseSnapshot,
47
+ type DatabaseSnapshot,
48
+ type DatabaseStartupLock,
49
+ ensurePgliteDataDir,
50
+ redactDatabaseTarget,
51
+ resetPgliteDirectory,
52
+ resolveDatabaseMode,
53
+ updateDatabaseSnapshotStatus,
54
+ } from "../database";
41
55
  import { logger } from "../logger";
42
56
  import { recordStartupPhase, resolveStartupBundlePath } from "../startup-trace";
43
57
  import type { SendToWebview } from "../types.js";
@@ -48,46 +62,47 @@ import { findFirstAvailableLoopbackPort } from "./loopback-port";
48
62
  // ---------------------------------------------------------------------------
49
63
 
50
64
  interface AgentStatus {
51
- state: "not_started" | "starting" | "running" | "stopped" | "error";
52
- agentName: string | null;
53
- port: number | null;
54
- startedAt: number | null;
55
- error: string | null;
65
+ state: "not_started" | "starting" | "running" | "stopped" | "error";
66
+ agentName: string | null;
67
+ port: number | null;
68
+ startedAt: number | null;
69
+ error: string | null;
56
70
  }
57
71
 
58
72
  export interface StartupDiagnosticsSnapshot {
59
- state: AgentStatus["state"];
60
- phase: string;
61
- updatedAt: string;
62
- lastError: string | null;
63
- agentName: string | null;
64
- port: number | null;
65
- startedAt: number | null;
66
- platform: string;
67
- arch: string;
68
- configDir: string;
69
- logPath: string;
70
- statusPath: string;
73
+ state: AgentStatus["state"];
74
+ phase: string;
75
+ updatedAt: string;
76
+ lastError: string | null;
77
+ agentName: string | null;
78
+ port: number | null;
79
+ startedAt: number | null;
80
+ platform: string;
81
+ arch: string;
82
+ configDir: string;
83
+ logPath: string;
84
+ statusPath: string;
85
+ database: DatabaseSnapshot;
71
86
  }
72
87
 
73
88
  export interface BugReportBundleResult {
74
- directory: string;
75
- reportMarkdownPath: string;
76
- reportJsonPath: string;
77
- startupLogPath: string | null;
78
- startupStatusPath: string | null;
89
+ directory: string;
90
+ reportMarkdownPath: string;
91
+ reportJsonPath: string;
92
+ startupLogPath: string | null;
93
+ startupStatusPath: string | null;
79
94
  }
80
95
 
81
96
  import type {
82
- ExistingElizaInstallInfo,
83
- ExistingElizaInstallSource,
84
- StateDirMigrationResult,
97
+ ExistingElizaInstallInfo,
98
+ ExistingElizaInstallSource,
99
+ StateDirMigrationResult,
85
100
  } from "../rpc-schema";
86
101
 
87
102
  export type {
88
- ExistingElizaInstallInfo,
89
- ExistingElizaInstallSource,
90
- StateDirMigrationResult,
103
+ ExistingElizaInstallInfo,
104
+ ExistingElizaInstallSource,
105
+ StateDirMigrationResult,
91
106
  };
92
107
 
93
108
  // Subprocess type from Bun.spawn
@@ -104,283 +119,408 @@ const WINDOWS_ABS_PATH_RE = /^[A-Za-z]:[\\/]/;
104
119
  const ELIZA_CONFIG_FILENAME = "eliza.json";
105
120
 
106
121
  export function getHealthPollTimeoutMs(
107
- env: NodeJS.ProcessEnv = process.env,
108
- platform: string = process.platform,
122
+ env: NodeJS.ProcessEnv = process.env,
123
+ platform: string = process.platform,
109
124
  ): number {
110
- const raw = env.ELIZA_AGENT_HEALTH_TIMEOUT_MS?.trim();
111
- if (raw) {
112
- const parsed = Number.parseInt(raw, 10);
113
- if (Number.isFinite(parsed) && parsed > 0) {
114
- return parsed;
115
- }
116
- }
117
-
118
- // Windows packaged first-run startup can include PGLite initialization plus
119
- // a GGUF embedding model download before /api/health comes online.
120
- return platform === "win32" ? 240_000 : 120_000;
125
+ const raw = env.ELIZA_AGENT_HEALTH_TIMEOUT_MS?.trim();
126
+ if (raw) {
127
+ const parsed = Number.parseInt(raw, 10);
128
+ if (Number.isFinite(parsed) && parsed > 0) {
129
+ return parsed;
130
+ }
131
+ }
132
+
133
+ // Windows packaged first-run startup can include PGLite initialization plus
134
+ // a GGUF embedding model download before /api/health comes online.
135
+ return platform === "win32" ? 240_000 : 120_000;
121
136
  }
122
137
 
123
138
  function isPosixAbsolutePath(value: string): boolean {
124
- return value.startsWith("/") && !WINDOWS_ABS_PATH_RE.test(value);
139
+ return value.startsWith("/") && !WINDOWS_ABS_PATH_RE.test(value);
125
140
  }
126
141
 
127
142
  function resolvePortablePath(value: string): string {
128
- if (isPosixAbsolutePath(value) || WINDOWS_ABS_PATH_RE.test(value)) {
129
- return value;
130
- }
131
- return path.resolve(value);
143
+ if (isPosixAbsolutePath(value) || WINDOWS_ABS_PATH_RE.test(value)) {
144
+ return value;
145
+ }
146
+ return path.resolve(value);
132
147
  }
133
148
 
134
149
  function dirnamePortable(value: string): string {
135
- return isPosixAbsolutePath(value)
136
- ? path.posix.dirname(value)
137
- : path.dirname(value);
150
+ return isPosixAbsolutePath(value)
151
+ ? path.posix.dirname(value)
152
+ : path.dirname(value);
138
153
  }
139
154
 
140
155
  function joinPortable(base: string, ...parts: string[]): string {
141
- return isPosixAbsolutePath(base)
142
- ? path.posix.join(base, ...parts)
143
- : path.join(base, ...parts);
156
+ return isPosixAbsolutePath(base)
157
+ ? path.posix.join(base, ...parts)
158
+ : path.join(base, ...parts);
144
159
  }
145
160
 
146
161
  function resolveRelativePortable(base: string, relativePath: string): string {
147
- return isPosixAbsolutePath(base)
148
- ? path.posix.resolve(base, relativePath)
149
- : path.resolve(base, relativePath);
162
+ return isPosixAbsolutePath(base)
163
+ ? path.posix.resolve(base, relativePath)
164
+ : path.resolve(base, relativePath);
150
165
  }
151
166
 
152
167
  function getDefaultModuleDir(): string {
153
- return import.meta.dir ?? path.join(process.cwd(), "src");
168
+ return import.meta.dir;
154
169
  }
155
170
 
156
171
  function normalizeEnvPath(value: string | undefined): string | null {
157
- const trimmed = value?.trim();
158
- return trimmed ? resolvePortablePath(trimmed) : null;
172
+ const trimmed = value?.trim();
173
+ return trimmed ? resolvePortablePath(trimmed) : null;
159
174
  }
160
175
 
161
176
  function isStoreBuildVariant(env: NodeJS.ProcessEnv = process.env): boolean {
162
- const raw =
163
- env.MILADY_BUILD_VARIANT?.trim() || env.ELIZA_BUILD_VARIANT?.trim();
164
- return raw?.toLowerCase() === "store";
177
+ const raw = env.ELIZA_BUILD_VARIANT?.trim();
178
+ return raw?.toLowerCase() === "store";
179
+ }
180
+
181
+ function resolveBrandAwareNamespace(
182
+ envNamespace: string | undefined,
183
+ brandNamespace = getBrandConfig().namespace || "eliza",
184
+ ): string {
185
+ const trimmed = envNamespace?.trim();
186
+ if (!trimmed) return brandNamespace;
187
+ if (trimmed === "eliza" && brandNamespace !== "eliza") return brandNamespace;
188
+ return trimmed;
165
189
  }
166
190
 
167
191
  function resolveStateNamespace(env: NodeJS.ProcessEnv = process.env): string {
168
- return env.ELIZA_NAMESPACE?.trim() || getBrandConfig().namespace || "eliza";
192
+ return resolveBrandAwareNamespace(env.ELIZA_NAMESPACE);
193
+ }
194
+
195
+ export function resolveDesktopChildNamespace(
196
+ env: Record<string, string | undefined>,
197
+ brandNamespace?: string,
198
+ ): string {
199
+ return resolveBrandAwareNamespace(env.ELIZA_NAMESPACE, brandNamespace);
169
200
  }
170
201
 
171
202
  function resolveExplicitStateDir(env: NodeJS.ProcessEnv): string | null {
172
- return (
173
- normalizeEnvPath(env.MILADY_STATE_DIR) ??
174
- normalizeEnvPath(env.ELIZA_STATE_DIR)
175
- );
203
+ return normalizeEnvPath(env.ELIZA_STATE_DIR);
204
+ }
205
+
206
+ function isTruthyDesktopEnv(value: string | undefined): boolean {
207
+ const normalized = value?.trim().toLowerCase();
208
+ return normalized === "1" || normalized === "true" || normalized === "yes";
209
+ }
210
+
211
+ export function applyPackagedStartupEmbeddingWarmupPolicy(
212
+ childEnv: Record<string, string>,
213
+ packagedRuntime: boolean,
214
+ ): void {
215
+ if (!packagedRuntime) {
216
+ return;
217
+ }
218
+
219
+ const explicitSkip = childEnv.ELIZA_SKIP_LOCAL_EMBEDDING_WARMUP?.trim();
220
+ if (explicitSkip) {
221
+ childEnv.ELIZA_SKIP_LOCAL_EMBEDDING_WARMUP = explicitSkip;
222
+ return;
223
+ }
224
+
225
+ if (
226
+ isTruthyDesktopEnv(childEnv.ELIZA_ENABLE_STARTUP_LOCAL_EMBEDDING_WARMUP)
227
+ ) {
228
+ return;
229
+ }
230
+
231
+ childEnv.ELIZA_SKIP_LOCAL_EMBEDDING_WARMUP = "1";
232
+ }
233
+
234
+ /**
235
+ * Default the desktop-spawned agent to deferring the post-ready boot tail so
236
+ * `/api/health` flips `ready:true` (and the renderer reaches first paint /
237
+ * usable chat) before app-route plugins, training hooks, sensitive-request
238
+ * adapters, the trigger bridge, the connector catalog, and voice warmup finish.
239
+ *
240
+ * The trade-off is a brief window after "ready" where feature routes registered
241
+ * by app-route plugins (e.g. lifeops/steward/training) can 404 until the
242
+ * background tail completes — acceptable on desktop where first paint latency is
243
+ * far more visible than a sub-second feature-route gap.
244
+ *
245
+ * Only sets the default when `ELIZA_DEFER_APP_ROUTES` is unset, so an explicit
246
+ * `0`/`1` from the user or a test harness always wins. The production CLI
247
+ * `serve` path (not spawned here) is untouched and keeps the awaited-inline tail.
248
+ */
249
+ export function applyDesktopDeferAppRoutesPolicy(
250
+ childEnv: Record<string, string>,
251
+ ): void {
252
+ if (childEnv.ELIZA_DEFER_APP_ROUTES?.trim()) {
253
+ return;
254
+ }
255
+ childEnv.ELIZA_DEFER_APP_ROUTES = "1";
256
+ }
257
+
258
+ export function prependDesktopChildPathDirectory(
259
+ childEnv: Record<string, string | undefined>,
260
+ directory: string,
261
+ ): boolean {
262
+ const existingPathKey =
263
+ childEnv.PATH !== undefined
264
+ ? "PATH"
265
+ : childEnv.Path !== undefined
266
+ ? "Path"
267
+ : "PATH";
268
+ const existingPath = childEnv[existingPathKey]?.trim();
269
+ if (!existingPath) {
270
+ childEnv[existingPathKey] = directory;
271
+ return true;
272
+ }
273
+ if (existingPath.split(path.delimiter).includes(directory)) {
274
+ return false;
275
+ }
276
+ childEnv[existingPathKey] = `${directory}${path.delimiter}${existingPath}`;
277
+ return true;
176
278
  }
177
279
 
178
280
  function resolveStoreUserDataStateDir(): string {
179
- const userData = Utils.paths.userData || resolveConfigDir();
180
- return path.join(userData, "state");
281
+ const userData = Utils.paths.userData || resolveConfigDir();
282
+ return path.join(userData, "state");
283
+ }
284
+
285
+ function resolveXdgStateHome(opts?: {
286
+ env?: NodeJS.ProcessEnv;
287
+ homedir?: string;
288
+ }): string {
289
+ const env = opts?.env ?? process.env;
290
+ const explicit = normalizeEnvPath(env.XDG_STATE_HOME);
291
+ if (explicit) return explicit;
292
+ return joinPortable(opts?.homedir ?? os.homedir(), ".local", "state");
293
+ }
294
+
295
+ function resolveDefaultDesktopStateDir(opts?: {
296
+ env?: NodeJS.ProcessEnv;
297
+ homedir?: string;
298
+ }): string {
299
+ const env = opts?.env ?? process.env;
300
+ return joinPortable(resolveXdgStateHome(opts), resolveStateNamespace(env));
301
+ }
302
+
303
+ function resolveLegacyDotStateDir(opts?: {
304
+ env?: NodeJS.ProcessEnv;
305
+ homedir?: string;
306
+ }): string {
307
+ return joinPortable(
308
+ opts?.homedir ?? os.homedir(),
309
+ `.${resolveStateNamespace(opts?.env ?? process.env)}`,
310
+ );
181
311
  }
182
312
 
183
313
  export function resolveDesktopChildStateDir(opts?: {
184
- env?: NodeJS.ProcessEnv;
185
- homedir?: string;
314
+ env?: NodeJS.ProcessEnv;
315
+ homedir?: string;
186
316
  }): string {
187
- const env = opts?.env ?? process.env;
188
- const explicit = resolveExplicitStateDir(env);
189
- if (explicit) return explicit;
190
- if (isStoreBuildVariant(env)) return resolveStoreUserDataStateDir();
191
- return joinPortable(
192
- opts?.homedir ?? os.homedir(),
193
- `.${resolveStateNamespace(env)}`,
194
- );
317
+ const env = opts?.env ?? process.env;
318
+ const explicit = resolveExplicitStateDir(env);
319
+ if (explicit) return explicit;
320
+ if (isStoreBuildVariant(env)) return resolveStoreUserDataStateDir();
321
+ return resolveDefaultDesktopStateDir(opts);
195
322
  }
196
323
 
197
324
  function applyDesktopChildStateEnv(childEnv: Record<string, string>): void {
198
- if (!isStoreBuildVariant(childEnv as NodeJS.ProcessEnv)) return;
199
- const stateDir = resolveDesktopChildStateDir({
200
- env: childEnv as NodeJS.ProcessEnv,
201
- });
202
- fs.mkdirSync(stateDir, { recursive: true });
203
- childEnv.MILADY_STATE_DIR = stateDir;
204
- childEnv.ELIZA_STATE_DIR = stateDir;
325
+ const stateDir = resolveDesktopChildStateDir({
326
+ env: childEnv as NodeJS.ProcessEnv,
327
+ });
328
+ fs.mkdirSync(stateDir, { recursive: true });
329
+ childEnv.ELIZA_STATE_DIR = stateDir;
330
+ }
331
+
332
+ export function applyWindowsNativeInferenceDefaults(
333
+ childEnv: Record<string, string>,
334
+ platform: NodeJS.Platform = process.platform,
335
+ ): void {
336
+ if (platform !== "win32") return;
337
+
338
+ // node-llama-cpp crashes Bun on Windows during packaged startup.
339
+ // Disable local embeddings until upstream fix lands.
340
+ childEnv.ELIZA_DISABLE_LOCAL_EMBEDDINGS = "1";
341
+
342
+ // The fused elizaOS llama.cpp / OmniVoice runtime can trip GGML's
343
+ // uncaught-exception backtrace guard inside packaged Bun unless this is set
344
+ // before any native GGML library is loaded.
345
+ if (!childEnv.GGML_NO_BACKTRACE?.trim()) {
346
+ childEnv.GGML_NO_BACKTRACE = "1";
347
+ }
205
348
  }
206
349
 
207
350
  function listStateEntries(stateDir: string): string[] {
208
- try {
209
- return fs
210
- .readdirSync(stateDir)
211
- .filter(
212
- (entry) => entry !== "." && entry !== ".." && entry !== ".DS_Store",
213
- );
214
- } catch {
215
- return [];
216
- }
351
+ try {
352
+ return fs
353
+ .readdirSync(stateDir)
354
+ .filter(
355
+ (entry) => entry !== "." && entry !== ".." && entry !== ".DS_Store",
356
+ );
357
+ } catch {
358
+ return [];
359
+ }
217
360
  }
218
361
 
219
362
  function buildExistingElizaInstallCandidates(opts?: {
220
- env?: NodeJS.ProcessEnv;
221
- homedir?: string;
363
+ env?: NodeJS.ProcessEnv;
364
+ homedir?: string;
222
365
  }): Array<{
223
- source: ExistingElizaInstallSource;
224
- stateDir: string;
225
- configPath: string;
366
+ source: ExistingElizaInstallSource;
367
+ stateDir: string;
368
+ configPath: string;
226
369
  }> {
227
- const env = opts?.env ?? process.env;
228
- const homedir = opts?.homedir ?? os.homedir();
229
- const configPathFromEnv =
230
- normalizeEnvPath(env.MILADY_CONFIG_PATH) ??
231
- normalizeEnvPath(env.ELIZA_CONFIG_PATH);
232
- const stateDirFromEnv = resolveExplicitStateDir(env);
233
- const defaultStateDir = joinPortable(
234
- homedir,
235
- `.${resolveStateNamespace(env)}`,
236
- );
237
-
238
- const candidates = [
239
- configPathFromEnv
240
- ? {
241
- source: "config-path-env" as const,
242
- stateDir: dirnamePortable(configPathFromEnv),
243
- configPath: configPathFromEnv,
244
- }
245
- : null,
246
- stateDirFromEnv
247
- ? {
248
- source: "state-dir-env" as const,
249
- stateDir: stateDirFromEnv,
250
- configPath: joinPortable(stateDirFromEnv, ELIZA_CONFIG_FILENAME),
251
- }
252
- : null,
253
- {
254
- source: "default-state-dir" as const,
255
- stateDir: defaultStateDir,
256
- configPath: joinPortable(defaultStateDir, ELIZA_CONFIG_FILENAME),
257
- },
258
- ].filter((candidate): candidate is NonNullable<typeof candidate> =>
259
- Boolean(candidate),
260
- );
261
-
262
- return candidates.filter(
263
- (candidate, index, all) =>
264
- all.findIndex(
265
- (other) =>
266
- other.stateDir === candidate.stateDir &&
267
- other.configPath === candidate.configPath,
268
- ) === index,
269
- );
370
+ const env = opts?.env ?? process.env;
371
+ const homedir = opts?.homedir ?? os.homedir();
372
+ const configPathFromEnv = normalizeEnvPath(env.ELIZA_CONFIG_PATH);
373
+ const stateDirFromEnv = resolveExplicitStateDir(env);
374
+ const defaultStateDir = resolveDefaultDesktopStateDir({ env, homedir });
375
+ const legacyStateDir = resolveLegacyDotStateDir({ env, homedir });
376
+
377
+ const candidates = [
378
+ configPathFromEnv
379
+ ? {
380
+ source: "config-path-env" as const,
381
+ stateDir: dirnamePortable(configPathFromEnv),
382
+ configPath: configPathFromEnv,
383
+ }
384
+ : null,
385
+ stateDirFromEnv
386
+ ? {
387
+ source: "state-dir-env" as const,
388
+ stateDir: stateDirFromEnv,
389
+ configPath: joinPortable(stateDirFromEnv, ELIZA_CONFIG_FILENAME),
390
+ }
391
+ : null,
392
+ {
393
+ source: "default-state-dir" as const,
394
+ stateDir: defaultStateDir,
395
+ configPath: joinPortable(defaultStateDir, ELIZA_CONFIG_FILENAME),
396
+ },
397
+ legacyStateDir !== defaultStateDir
398
+ ? {
399
+ source: "legacy-dot-state-dir" as const,
400
+ stateDir: legacyStateDir,
401
+ configPath: joinPortable(legacyStateDir, ELIZA_CONFIG_FILENAME),
402
+ }
403
+ : null,
404
+ ].filter((candidate): candidate is NonNullable<typeof candidate> =>
405
+ Boolean(candidate),
406
+ );
407
+
408
+ return candidates.filter(
409
+ (candidate, index, all) =>
410
+ all.findIndex(
411
+ (other) =>
412
+ other.stateDir === candidate.stateDir &&
413
+ other.configPath === candidate.configPath,
414
+ ) === index,
415
+ );
270
416
  }
271
417
 
272
418
  export function inspectExistingElizaInstall(opts?: {
273
- env?: NodeJS.ProcessEnv;
274
- homedir?: string;
419
+ env?: NodeJS.ProcessEnv;
420
+ homedir?: string;
275
421
  }): ExistingElizaInstallInfo {
276
- const candidates = buildExistingElizaInstallCandidates(opts);
277
-
278
- for (const candidate of candidates) {
279
- const configExists = fs.existsSync(candidate.configPath);
280
- const stateDirExists = fs.existsSync(candidate.stateDir);
281
- const hasStateEntries =
282
- stateDirExists && listStateEntries(candidate.stateDir).length > 0;
283
-
284
- if (configExists || hasStateEntries) {
285
- return {
286
- detected: true,
287
- stateDir: candidate.stateDir,
288
- configPath: candidate.configPath,
289
- configExists,
290
- stateDirExists,
291
- hasStateEntries,
292
- source: candidate.source,
293
- };
294
- }
295
- }
296
-
297
- const fallback = candidates[0] ?? {
298
- source: "default-state-dir" as const,
299
- stateDir: joinPortable(
300
- opts?.homedir ?? os.homedir(),
301
- `.${resolveStateNamespace(opts?.env ?? process.env)}`,
302
- ),
303
- configPath: joinPortable(
304
- joinPortable(
305
- opts?.homedir ?? os.homedir(),
306
- `.${resolveStateNamespace(opts?.env ?? process.env)}`,
307
- ),
308
- ELIZA_CONFIG_FILENAME,
309
- ),
310
- };
311
-
312
- return {
313
- detected: false,
314
- stateDir: fallback.stateDir,
315
- configPath: fallback.configPath,
316
- configExists: false,
317
- stateDirExists: fs.existsSync(fallback.stateDir),
318
- hasStateEntries: false,
319
- source: fallback.source,
320
- };
422
+ const candidates = buildExistingElizaInstallCandidates(opts);
423
+
424
+ for (const candidate of candidates) {
425
+ const configExists = fs.existsSync(candidate.configPath);
426
+ const stateDirExists = fs.existsSync(candidate.stateDir);
427
+ const hasStateEntries =
428
+ stateDirExists && listStateEntries(candidate.stateDir).length > 0;
429
+
430
+ if (configExists || hasStateEntries) {
431
+ return {
432
+ detected: true,
433
+ stateDir: candidate.stateDir,
434
+ configPath: candidate.configPath,
435
+ configExists,
436
+ stateDirExists,
437
+ hasStateEntries,
438
+ source: candidate.source,
439
+ };
440
+ }
441
+ }
442
+
443
+ const fallback = candidates[0] ?? {
444
+ source: "default-state-dir" as const,
445
+ stateDir: resolveDefaultDesktopStateDir(opts),
446
+ configPath: joinPortable(
447
+ resolveDefaultDesktopStateDir(opts),
448
+ ELIZA_CONFIG_FILENAME,
449
+ ),
450
+ };
451
+
452
+ return {
453
+ detected: false,
454
+ stateDir: fallback.stateDir,
455
+ configPath: fallback.configPath,
456
+ configExists: false,
457
+ stateDirExists: fs.existsSync(fallback.stateDir),
458
+ hasStateEntries: false,
459
+ source: fallback.source,
460
+ };
321
461
  }
322
462
 
323
463
  export function migrateDesktopStateDirFromPath(
324
- fromPath: string,
325
- opts?: { env?: NodeJS.ProcessEnv },
464
+ fromPath: string,
465
+ opts?: { env?: NodeJS.ProcessEnv },
326
466
  ): StateDirMigrationResult {
327
- const source = resolvePortablePath(fromPath);
328
- const target = resolveDesktopChildStateDir({ env: opts?.env ?? process.env });
329
-
330
- if (source === target) {
331
- return {
332
- ok: true,
333
- migrated: false,
334
- fromPath: source,
335
- toPath: target,
336
- skippedReason: "same-path",
337
- };
338
- }
339
-
340
- try {
341
- const stat = fs.statSync(source);
342
- if (!stat.isDirectory()) {
343
- return {
344
- ok: true,
345
- migrated: false,
346
- fromPath: source,
347
- toPath: target,
348
- skippedReason: "source-not-directory",
349
- };
350
- }
351
- } catch {
352
- return {
353
- ok: true,
354
- migrated: false,
355
- fromPath: source,
356
- toPath: target,
357
- skippedReason: "source-missing",
358
- };
359
- }
360
-
361
- try {
362
- fs.mkdirSync(target, { recursive: true });
363
- fs.cpSync(source, target, {
364
- recursive: true,
365
- force: false,
366
- errorOnExist: false,
367
- dereference: false,
368
- });
369
- return {
370
- ok: true,
371
- migrated: true,
372
- fromPath: source,
373
- toPath: target,
374
- };
375
- } catch (err) {
376
- return {
377
- ok: false,
378
- migrated: false,
379
- fromPath: source,
380
- toPath: target,
381
- error: err instanceof Error ? err.message : String(err),
382
- };
383
- }
467
+ const source = resolvePortablePath(fromPath);
468
+ const target = resolveDesktopChildStateDir({ env: opts?.env ?? process.env });
469
+
470
+ if (source === target) {
471
+ return {
472
+ ok: true,
473
+ migrated: false,
474
+ fromPath: source,
475
+ toPath: target,
476
+ skippedReason: "same-path",
477
+ };
478
+ }
479
+
480
+ try {
481
+ const stat = fs.statSync(source);
482
+ if (!stat.isDirectory()) {
483
+ return {
484
+ ok: true,
485
+ migrated: false,
486
+ fromPath: source,
487
+ toPath: target,
488
+ skippedReason: "source-not-directory",
489
+ };
490
+ }
491
+ } catch {
492
+ return {
493
+ ok: true,
494
+ migrated: false,
495
+ fromPath: source,
496
+ toPath: target,
497
+ skippedReason: "source-missing",
498
+ };
499
+ }
500
+
501
+ try {
502
+ fs.mkdirSync(target, { recursive: true });
503
+ fs.cpSync(source, target, {
504
+ recursive: true,
505
+ force: false,
506
+ errorOnExist: false,
507
+ dereference: false,
508
+ });
509
+ return {
510
+ ok: true,
511
+ migrated: true,
512
+ fromPath: source,
513
+ toPath: target,
514
+ };
515
+ } catch (err) {
516
+ return {
517
+ ok: false,
518
+ migrated: false,
519
+ fromPath: source,
520
+ toPath: target,
521
+ error: err instanceof Error ? err.message : String(err),
522
+ };
523
+ }
384
524
  }
385
525
 
386
526
  // ---------------------------------------------------------------------------
@@ -396,268 +536,269 @@ export function migrateDesktopStateDirFromPath(
396
536
  * to mock process globals.
397
537
  */
398
538
  export function resolveConfigDir(opts?: {
399
- platform?: string;
400
- appdata?: string;
401
- homedir?: string;
539
+ platform?: string;
540
+ appdata?: string;
541
+ homedir?: string;
402
542
  }): string {
403
- const platform = opts?.platform ?? process.platform;
404
- const homedir = opts?.homedir ?? os.homedir();
405
- const dirName = getBrandConfig().configDirName;
406
- if (platform === "win32") {
407
- const roaming =
408
- opts?.appdata ??
409
- process.env.APPDATA ??
410
- joinPortable(homedir, "AppData", "Roaming");
411
- return joinPortable(roaming, dirName);
412
- }
413
- return joinPortable(homedir, ".config", dirName);
543
+ const platform = opts?.platform ?? process.platform;
544
+ const homedir = opts?.homedir ?? os.homedir();
545
+ const dirName = getBrandConfig().configDirName;
546
+ if (platform === "win32") {
547
+ const roaming =
548
+ opts?.appdata ??
549
+ process.env.APPDATA ??
550
+ joinPortable(homedir, "AppData", "Roaming");
551
+ return joinPortable(roaming, dirName);
552
+ }
553
+ return joinPortable(homedir, ".config", dirName);
414
554
  }
415
555
 
416
556
  export function ensureDesktopApiToken(
417
- env: NodeJS.ProcessEnv = process.env,
557
+ env: NodeJS.ProcessEnv = process.env,
418
558
  ): string {
419
- const existingToken = resolveApiToken(env);
420
- if (existingToken) {
421
- setApiToken(env, existingToken);
422
- return existingToken;
423
- }
424
-
425
- if (resolveDisableAutoApiToken(env)) {
426
- return "";
427
- }
428
-
429
- const generated = crypto.randomBytes(16).toString("hex");
430
- setApiToken(env, generated);
431
- return generated;
559
+ const existingToken = resolveApiToken(env);
560
+ if (existingToken) {
561
+ setApiToken(env, existingToken);
562
+ return existingToken;
563
+ }
564
+
565
+ if (resolveDisableAutoApiToken(env)) {
566
+ return "";
567
+ }
568
+
569
+ const generated = crypto.randomBytes(16).toString("hex");
570
+ setApiToken(env, generated);
571
+ return generated;
432
572
  }
433
573
 
434
574
  export function configureDesktopLocalApiAuth(
435
- env: NodeJS.ProcessEnv = process.env,
575
+ env: NodeJS.ProcessEnv = process.env,
436
576
  ): string {
437
- const token = ensureDesktopApiToken(env);
438
- env.ELIZA_PAIRING_DISABLED = "1";
439
- return token;
577
+ const token = ensureDesktopApiToken(env);
578
+ env.ELIZA_PAIRING_DISABLED = "1";
579
+ return token;
440
580
  }
441
581
 
442
582
  function getDesktopApiToken(
443
- env: NodeJS.ProcessEnv = process.env,
583
+ env: NodeJS.ProcessEnv = process.env,
444
584
  ): string | null {
445
- return resolveApiToken(env);
585
+ return resolveApiToken(env);
446
586
  }
447
587
 
448
588
  function getDesktopApiHeaders(
449
- env: NodeJS.ProcessEnv = process.env,
589
+ env: NodeJS.ProcessEnv = process.env,
450
590
  ): Record<string, string> | undefined {
451
- const token = getDesktopApiToken(env);
452
- if (!token) return undefined;
453
- return {
454
- Authorization: `Bearer ${token}`,
455
- "X-Api-Key": token,
456
- "X-Api-Token": token,
457
- };
591
+ const token = getDesktopApiToken(env);
592
+ if (!token) return undefined;
593
+ return {
594
+ Authorization: `Bearer ${token}`,
595
+ "X-Api-Key": token,
596
+ "X-Api-Token": token,
597
+ };
458
598
  }
459
599
 
460
600
  let diagnosticLogPath: string | null = null;
461
601
  let startupStatusPath: string | null = null;
462
602
 
463
603
  export function getDiagnosticLogPath(): string {
464
- if (diagnosticLogPath !== null) return diagnosticLogPath;
465
- try {
466
- const configDir = resolveConfigDir();
467
- if (!fs.existsSync(configDir)) {
468
- fs.mkdirSync(configDir, { recursive: true });
469
- }
470
- diagnosticLogPath = path.join(
471
- configDir,
472
- getBrandConfig().startupLogFileName,
473
- );
474
- } catch {
475
- // Fallback to temp dir
476
- diagnosticLogPath = path.join(
477
- os.tmpdir(),
478
- getBrandConfig().startupLogFileName,
479
- );
480
- }
481
- return diagnosticLogPath;
604
+ if (diagnosticLogPath !== null) return diagnosticLogPath;
605
+ try {
606
+ const configDir = resolveConfigDir();
607
+ if (!fs.existsSync(configDir)) {
608
+ fs.mkdirSync(configDir, { recursive: true });
609
+ }
610
+ diagnosticLogPath = path.join(
611
+ configDir,
612
+ getBrandConfig().startupLogFileName,
613
+ );
614
+ } catch {
615
+ // Fallback to temp dir
616
+ diagnosticLogPath = path.join(
617
+ os.tmpdir(),
618
+ getBrandConfig().startupLogFileName,
619
+ );
620
+ }
621
+ return diagnosticLogPath;
482
622
  }
483
623
 
484
624
  export function getStartupStatusPath(): string {
485
- if (startupStatusPath !== null) return startupStatusPath;
486
- try {
487
- const configDir = resolveConfigDir();
488
- if (!fs.existsSync(configDir)) {
489
- fs.mkdirSync(configDir, { recursive: true });
490
- }
491
- startupStatusPath = path.join(configDir, "startup-status.json");
492
- } catch {
493
- startupStatusPath = path.join(os.tmpdir(), "startup-status.json");
494
- }
495
- return startupStatusPath;
625
+ if (startupStatusPath !== null) return startupStatusPath;
626
+ try {
627
+ const configDir = resolveConfigDir();
628
+ if (!fs.existsSync(configDir)) {
629
+ fs.mkdirSync(configDir, { recursive: true });
630
+ }
631
+ startupStatusPath = path.join(configDir, "startup-status.json");
632
+ } catch {
633
+ startupStatusPath = path.join(os.tmpdir(), "startup-status.json");
634
+ }
635
+ return startupStatusPath;
496
636
  }
497
637
 
498
638
  export function diagnosticLog(message: string): void {
499
- const timestamp = new Date().toISOString();
500
- const line = `[${timestamp}] ${message}\n`;
501
- console.log(message);
502
- try {
503
- const logPath = getDiagnosticLogPath();
504
- fs.appendFileSync(logPath, line);
505
- } catch {
506
- // Ignore write errors
507
- }
639
+ const timestamp = new Date().toISOString();
640
+ const line = `[${timestamp}] ${message}\n`;
641
+ console.log(message);
642
+ try {
643
+ const logPath = getDiagnosticLogPath();
644
+ fs.appendFileSync(logPath, line);
645
+ } catch {
646
+ // Ignore write errors
647
+ }
508
648
  }
509
649
 
510
650
  /** One-line, truncated error string safe for UI (status.error). */
511
651
  function shortError(err: unknown, maxLen = 280): string {
512
- const raw =
513
- err instanceof Error
514
- ? err.message || (err.stack ?? String(err))
515
- : String(err);
516
- const oneLine = raw.replace(/\s+/g, " ").trim();
517
- if (oneLine.length <= maxLen) return oneLine;
518
- return `${oneLine.slice(0, maxLen)}... (see logs for full details)`;
652
+ const raw =
653
+ err instanceof Error
654
+ ? err.message || (err.stack ?? String(err))
655
+ : String(err);
656
+ const oneLine = raw.replace(/\s+/g, " ").trim();
657
+ if (oneLine.length <= maxLen) return oneLine;
658
+ return `${oneLine.slice(0, maxLen)}... (see logs for full details)`;
519
659
  }
520
660
 
521
661
  export function redactSensitiveDiagnostics(input: string): string {
522
- return input
523
- .replace(
524
- /(authorization\s*[:=]\s*bearer\s+)([a-z0-9._-]+)/gi,
525
- "$1[REDACTED]",
526
- )
527
- .replace(
528
- /((?:x-api-key|x-api-token|api[_-]?key|bearer[_-]?token|access[_-]?token|secret|password)\s*[:=]\s*)([^\s]+)/gi,
529
- "$1[REDACTED]",
530
- );
662
+ return input
663
+ .replace(
664
+ /(authorization\s*[:=]\s*bearer\s+)([a-z0-9._-]+)/gi,
665
+ "$1[REDACTED]",
666
+ )
667
+ .replace(
668
+ /((?:x-api-key|x-api-token|api[_-]?key|bearer[_-]?token|access[_-]?token|secret|password)\s*[:=]\s*)([^\s]+)/gi,
669
+ "$1[REDACTED]",
670
+ );
531
671
  }
532
672
 
533
673
  function readFileTail(filePath: string, maxChars = 16_000): string {
534
- try {
535
- const content = fs.readFileSync(filePath, "utf8");
536
- return redactSensitiveDiagnostics(content.slice(-maxChars));
537
- } catch {
538
- return "";
539
- }
674
+ try {
675
+ const content = fs.readFileSync(filePath, "utf8");
676
+ return redactSensitiveDiagnostics(content.slice(-maxChars));
677
+ } catch {
678
+ return "";
679
+ }
540
680
  }
541
681
 
542
682
  function writeStartupDiagnosticsSnapshot(
543
- snapshot: StartupDiagnosticsSnapshot,
683
+ snapshot: StartupDiagnosticsSnapshot,
544
684
  ): void {
545
- try {
546
- fs.writeFileSync(
547
- getStartupStatusPath(),
548
- `${JSON.stringify(snapshot, null, 2)}\n`,
549
- "utf8",
550
- );
551
- } catch {
552
- // Ignore write errors
553
- }
685
+ try {
686
+ fs.writeFileSync(
687
+ getStartupStatusPath(),
688
+ `${JSON.stringify(snapshot, null, 2)}\n`,
689
+ "utf8",
690
+ );
691
+ } catch {
692
+ // Ignore write errors
693
+ }
554
694
  }
555
695
 
556
696
  export function getStartupDiagnosticsSnapshot(): StartupDiagnosticsSnapshot {
557
- let parsed: Partial<StartupDiagnosticsSnapshot> | null = null;
558
- try {
559
- parsed = JSON.parse(
560
- fs.readFileSync(getStartupStatusPath(), "utf8"),
561
- ) as Partial<StartupDiagnosticsSnapshot> | null;
562
- } catch {
563
- parsed = null;
564
- }
565
-
566
- return {
567
- state: parsed?.state ?? "not_started",
568
- phase: parsed?.phase ?? "unknown",
569
- updatedAt: parsed?.updatedAt ?? new Date().toISOString(),
570
- lastError: parsed?.lastError ?? null,
571
- agentName: parsed?.agentName ?? null,
572
- port: parsed?.port ?? null,
573
- startedAt: parsed?.startedAt ?? null,
574
- platform: parsed?.platform ?? process.platform,
575
- arch: parsed?.arch ?? process.arch,
576
- configDir: parsed?.configDir ?? resolveConfigDir(),
577
- logPath: parsed?.logPath ?? getDiagnosticLogPath(),
578
- statusPath: parsed?.statusPath ?? getStartupStatusPath(),
579
- };
697
+ let parsed: Partial<StartupDiagnosticsSnapshot> | null = null;
698
+ try {
699
+ parsed = JSON.parse(
700
+ fs.readFileSync(getStartupStatusPath(), "utf8"),
701
+ ) as Partial<StartupDiagnosticsSnapshot> | null;
702
+ } catch {
703
+ parsed = null;
704
+ }
705
+
706
+ return {
707
+ state: parsed?.state ?? "not_started",
708
+ phase: parsed?.phase ?? "unknown",
709
+ updatedAt: parsed?.updatedAt ?? new Date().toISOString(),
710
+ lastError: parsed?.lastError ?? null,
711
+ agentName: parsed?.agentName ?? null,
712
+ port: parsed?.port ?? null,
713
+ startedAt: parsed?.startedAt ?? null,
714
+ platform: parsed?.platform ?? process.platform,
715
+ arch: parsed?.arch ?? process.arch,
716
+ configDir: parsed?.configDir ?? resolveConfigDir(),
717
+ logPath: parsed?.logPath ?? getDiagnosticLogPath(),
718
+ statusPath: parsed?.statusPath ?? getStartupStatusPath(),
719
+ database: parsed?.database ?? createUnknownDatabaseSnapshot(),
720
+ };
580
721
  }
581
722
 
582
723
  export function getStartupDiagnosticLogTail(maxChars = 16_000): string {
583
- return readFileTail(getDiagnosticLogPath(), maxChars);
724
+ return readFileTail(getDiagnosticLogPath(), maxChars);
584
725
  }
585
726
 
586
727
  function sanitizeBugReportPrefix(prefix: string | undefined): string {
587
- const trimmed = prefix?.trim();
588
- if (!trimmed) return "bug-report";
589
-
590
- const sanitized = trimmed
591
- .replace(/[\\/]+/g, "-")
592
- .replace(/\.\.+/g, "-")
593
- .replace(/[^a-zA-Z0-9._-]+/g, "-")
594
- .replace(/-+/g, "-")
595
- .replace(/^[._-]+|[._-]+$/g, "")
596
- .slice(0, 64);
597
-
598
- return sanitized || "bug-report";
728
+ const trimmed = prefix?.trim();
729
+ if (!trimmed) return "bug-report";
730
+
731
+ const sanitized = trimmed
732
+ .replace(/[\\/]+/g, "-")
733
+ .replace(/\.\.+/g, "-")
734
+ .replace(/[^a-zA-Z0-9._-]+/g, "-")
735
+ .replace(/-+/g, "-")
736
+ .replace(/^[._-]+|[._-]+$/g, "")
737
+ .slice(0, 64);
738
+
739
+ return sanitized || "bug-report";
599
740
  }
600
741
  export function createBugReportBundle(options: {
601
- reportMarkdown: string;
602
- reportJson: Record<string, unknown>;
603
- prefix?: string;
742
+ reportMarkdown: string;
743
+ reportJson: Record<string, unknown>;
744
+ prefix?: string;
604
745
  }): BugReportBundleResult {
605
- const configDir = resolveConfigDir();
606
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
607
- const prefix = sanitizeBugReportPrefix(options.prefix);
608
- const directory = path.join(
609
- configDir,
610
- "bug-reports",
611
- `${prefix}-${timestamp}`,
612
- );
613
- const reportMarkdownPath = path.join(directory, "report.md");
614
- const reportJsonPath = path.join(directory, "report.json");
615
- const logPath = getDiagnosticLogPath();
616
- const statusPath = getStartupStatusPath();
617
- const startupLogTarget = path.join(
618
- directory,
619
- getBrandConfig().startupLogFileName,
620
- );
621
- const startupStatusTarget = path.join(directory, "startup-status.json");
622
- const startupDiagnostics = getStartupDiagnosticsSnapshot();
623
- const includeLogTail =
624
- typeof options.reportJson.attachLogs === "boolean"
625
- ? options.reportJson.attachLogs
626
- : true;
627
- const startupLogTail = includeLogTail ? getStartupDiagnosticLogTail() : "";
628
- const normalizedReportJson = {
629
- ...options.reportJson,
630
- startupDiagnostics,
631
- startupLogTail,
632
- };
633
-
634
- fs.mkdirSync(directory, { recursive: true });
635
- fs.writeFileSync(reportMarkdownPath, options.reportMarkdown, "utf8");
636
- fs.writeFileSync(
637
- reportJsonPath,
638
- `${JSON.stringify(normalizedReportJson, null, 2)}\n`,
639
- "utf8",
640
- );
641
-
642
- let copiedLogPath: string | null = null;
643
- let copiedStatusPath: string | null = null;
644
-
645
- if (fs.existsSync(logPath)) {
646
- fs.copyFileSync(logPath, startupLogTarget);
647
- copiedLogPath = startupLogTarget;
648
- }
649
- if (fs.existsSync(statusPath)) {
650
- fs.copyFileSync(statusPath, startupStatusTarget);
651
- copiedStatusPath = startupStatusTarget;
652
- }
653
-
654
- return {
655
- directory,
656
- reportMarkdownPath,
657
- reportJsonPath,
658
- startupLogPath: copiedLogPath,
659
- startupStatusPath: copiedStatusPath,
660
- };
746
+ const configDir = resolveConfigDir();
747
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
748
+ const prefix = sanitizeBugReportPrefix(options.prefix);
749
+ const directory = path.join(
750
+ configDir,
751
+ "bug-reports",
752
+ `${prefix}-${timestamp}`,
753
+ );
754
+ const reportMarkdownPath = path.join(directory, "report.md");
755
+ const reportJsonPath = path.join(directory, "report.json");
756
+ const logPath = getDiagnosticLogPath();
757
+ const statusPath = getStartupStatusPath();
758
+ const startupLogTarget = path.join(
759
+ directory,
760
+ getBrandConfig().startupLogFileName,
761
+ );
762
+ const startupStatusTarget = path.join(directory, "startup-status.json");
763
+ const startupDiagnostics = getStartupDiagnosticsSnapshot();
764
+ const includeLogTail =
765
+ typeof options.reportJson.attachLogs === "boolean"
766
+ ? options.reportJson.attachLogs
767
+ : true;
768
+ const startupLogTail = includeLogTail ? getStartupDiagnosticLogTail() : "";
769
+ const normalizedReportJson = {
770
+ ...options.reportJson,
771
+ startupDiagnostics,
772
+ startupLogTail,
773
+ };
774
+
775
+ fs.mkdirSync(directory, { recursive: true });
776
+ fs.writeFileSync(reportMarkdownPath, options.reportMarkdown, "utf8");
777
+ fs.writeFileSync(
778
+ reportJsonPath,
779
+ `${JSON.stringify(normalizedReportJson, null, 2)}\n`,
780
+ "utf8",
781
+ );
782
+
783
+ let copiedLogPath: string | null = null;
784
+ let copiedStatusPath: string | null = null;
785
+
786
+ if (fs.existsSync(logPath)) {
787
+ fs.copyFileSync(logPath, startupLogTarget);
788
+ copiedLogPath = startupLogTarget;
789
+ }
790
+ if (fs.existsSync(statusPath)) {
791
+ fs.copyFileSync(statusPath, startupStatusTarget);
792
+ copiedStatusPath = startupStatusTarget;
793
+ }
794
+
795
+ return {
796
+ directory,
797
+ reportMarkdownPath,
798
+ reportJsonPath,
799
+ startupLogPath: copiedLogPath,
800
+ startupStatusPath: copiedStatusPath,
801
+ };
661
802
  }
662
803
 
663
804
  // ---------------------------------------------------------------------------
@@ -672,255 +813,260 @@ export function createBugReportBundle(options: {
672
813
  * 2. Walk up from import.meta.dir to find the runtime dist dir as a sibling
673
814
  */
674
815
  export function getRuntimeDistFallbackCandidates(
675
- moduleDir: string = getDefaultModuleDir(),
676
- execPath: string = process.execPath,
816
+ moduleDir: string = getDefaultModuleDir(),
817
+ execPath: string = process.execPath,
677
818
  ): string[] {
678
- const execDir = execPath ? dirnamePortable(execPath) : moduleDir;
679
- const distDir = getBrandConfig().runtimeDistDirName;
680
-
681
- return [
682
- // macOS: inside .app bundle (Contents/Resources/app/<dist>)
683
- resolveRelativePortable(execDir, `../Resources/app/${distDir}`),
684
- // Windows NSIS/portable: resources/app/<dist> next to exe
685
- resolveRelativePortable(execDir, `resources/app/${distDir}`),
686
- resolveRelativePortable(execDir, `../resources/app/${distDir}`),
687
- resolveRelativePortable(moduleDir, `app/${distDir}`),
688
- resolveRelativePortable(moduleDir, `../${distDir}`),
689
- resolveRelativePortable(moduleDir, `../app/${distDir}`),
690
- resolveRelativePortable(moduleDir, `../../../${distDir}`),
691
- // Legacy eliza-dist fallback for existing packaged builds
692
- resolveRelativePortable(execDir, "../Resources/app/eliza-dist"),
693
- resolveRelativePortable(execDir, "resources/app/eliza-dist"),
694
- resolveRelativePortable(moduleDir, "../eliza-dist"),
695
- resolveRelativePortable(moduleDir, "../../../eliza-dist"),
696
- ].filter((candidate, index, all) => all.indexOf(candidate) === index);
819
+ const execDir = execPath ? dirnamePortable(execPath) : moduleDir;
820
+ const distDir = getBrandConfig().runtimeDistDirName;
821
+
822
+ return [
823
+ // macOS: inside .app bundle (Contents/Resources/app/<dist>)
824
+ resolveRelativePortable(execDir, `../Resources/app/${distDir}`),
825
+ // Windows NSIS/portable: resources/app/<dist> next to exe
826
+ resolveRelativePortable(execDir, `resources/app/${distDir}`),
827
+ resolveRelativePortable(execDir, `../resources/app/${distDir}`),
828
+ resolveRelativePortable(moduleDir, `app/${distDir}`),
829
+ resolveRelativePortable(moduleDir, `../${distDir}`),
830
+ resolveRelativePortable(moduleDir, `../app/${distDir}`),
831
+ resolveRelativePortable(moduleDir, `../../../${distDir}`),
832
+ // Legacy eliza-dist fallback for existing packaged builds
833
+ resolveRelativePortable(execDir, "../Resources/app/eliza-dist"),
834
+ resolveRelativePortable(execDir, "resources/app/eliza-dist"),
835
+ resolveRelativePortable(moduleDir, "../eliza-dist"),
836
+ resolveRelativePortable(moduleDir, "../../../eliza-dist"),
837
+ ].filter((candidate, index, all) => all.indexOf(candidate) === index);
697
838
  }
698
839
 
699
840
  export function isPackagedDesktopRuntime(
700
- moduleDir: string = getDefaultModuleDir(),
701
- execPath: string = process.execPath,
841
+ moduleDir: string = getDefaultModuleDir(),
842
+ execPath: string = process.execPath,
702
843
  ): boolean {
703
- const normalizedModuleDir = moduleDir.replaceAll("\\", "/");
704
- const normalizedExecPath = execPath.replaceAll("\\", "/").toLowerCase();
705
- const looksLikePackagedExec =
706
- normalizedExecPath.includes(".app/contents/") ||
707
- normalizedExecPath.includes("/self-extraction/") ||
708
- normalizedExecPath.endsWith("/launcher") ||
709
- normalizedExecPath.endsWith("/launcher.exe");
710
- if (process.env.ELIZA_DIST_PATH?.trim() && !looksLikePackagedExec) {
711
- return false;
712
- }
713
- if (!normalizedModuleDir.includes("/src/")) {
714
- return true;
715
- }
716
-
717
- return looksLikePackagedExec;
844
+ const normalizedModuleDir = moduleDir.replaceAll("\\", "/");
845
+ const normalizedExecPath = execPath.replaceAll("\\", "/").toLowerCase();
846
+ const looksLikePackagedExec =
847
+ normalizedExecPath.includes(".app/contents/") ||
848
+ normalizedExecPath.includes("/self-extraction/") ||
849
+ normalizedExecPath.endsWith("/launcher") ||
850
+ normalizedExecPath.endsWith("/launcher.exe");
851
+ if (process.env.ELIZA_DIST_PATH?.trim() && !looksLikePackagedExec) {
852
+ return false;
853
+ }
854
+ if (!normalizedModuleDir.includes("/src/")) {
855
+ return true;
856
+ }
857
+
858
+ return looksLikePackagedExec;
718
859
  }
719
860
 
720
861
  export function resolveBunExecutablePath(opts?: {
721
- execPath?: string;
722
- moduleDir?: string;
723
- platform?: string;
862
+ execPath?: string;
863
+ moduleDir?: string;
864
+ platform?: string;
724
865
  }): string {
725
- const execPath = opts?.execPath ?? process.execPath;
726
- const moduleDir = opts?.moduleDir ?? getDefaultModuleDir();
727
- const platform = opts?.platform ?? process.platform;
728
- const packagedRuntime = isPackagedDesktopRuntime(moduleDir, execPath);
729
- const looksLikeMacBundleExec = execPath.includes(".app/Contents/MacOS/");
730
- const executableName =
731
- platform === "win32" && !looksLikeMacBundleExec ? "bun.exe" : "bun";
732
- const execDir = execPath ? dirnamePortable(execPath) : "";
733
- const packagedCandidates = [
734
- execPath,
735
- execDir ? joinPortable(execDir, executableName) : "",
736
- execDir
737
- ? resolveRelativePortable(
738
- execDir,
739
- `../Resources/app/bun/${executableName}`,
740
- )
741
- : "",
742
- execDir
743
- ? resolveRelativePortable(
744
- execDir,
745
- `../Resources/app/bun/bin/${executableName}`,
746
- )
747
- : "",
748
- moduleDir ? joinPortable(moduleDir, executableName) : "",
749
- moduleDir ? joinPortable(moduleDir, "bin", executableName) : "",
750
- moduleDir
751
- ? resolveRelativePortable(moduleDir, `../bun/${executableName}`)
752
- : "",
753
- moduleDir
754
- ? resolveRelativePortable(moduleDir, `../bun/bin/${executableName}`)
755
- : "",
756
- ].filter(Boolean);
757
-
758
- for (const candidate of packagedCandidates) {
759
- if (!fs.existsSync(candidate)) continue;
760
- if (
761
- path.basename(candidate).toLowerCase() === executableName.toLowerCase()
762
- ) {
763
- return candidate;
764
- }
765
- }
766
-
767
- if (packagedRuntime) {
768
- return (
769
- packagedCandidates.find(
770
- (candidate) =>
771
- path.basename(candidate).toLowerCase() ===
772
- executableName.toLowerCase(),
773
- ) ?? executableName
774
- );
775
- }
776
-
777
- const _candidates = [
778
- execPath,
779
- execDir ? joinPortable(execDir, executableName) : "",
780
- ].filter(Boolean);
781
-
782
- const bunGlobal = Bun as { which?: (binary: string) => string | null };
783
- const whichCandidate =
784
- typeof bunGlobal.which === "function" ? bunGlobal.which("bun") : null;
785
- if (whichCandidate) return whichCandidate;
786
-
787
- // Windows: bun is not always on PATH; check well-known install locations.
788
- if (process.platform === "win32") {
789
- const localAppData =
790
- process.env.LOCALAPPDATA ??
791
- joinPortable(os.homedir(), "AppData", "Local");
792
- const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
793
- const winCandidates = [
794
- joinPortable(localAppData, "bun", "bun.exe"),
795
- joinPortable(programFiles, "bun", "bun.exe"),
796
- joinPortable(os.homedir(), ".bun", "bin", "bun.exe"),
797
- ];
798
- for (const candidate of winCandidates) {
799
- if (fs.existsSync(candidate)) return candidate;
800
- }
801
- }
802
-
803
- return "bun";
866
+ const execPath = opts?.execPath ?? process.execPath;
867
+ const moduleDir = opts?.moduleDir ?? getDefaultModuleDir();
868
+ const platform = opts?.platform ?? process.platform;
869
+ const packagedRuntime = isPackagedDesktopRuntime(moduleDir, execPath);
870
+ const looksLikeMacBundleExec = execPath.includes(".app/Contents/MacOS/");
871
+ const executableName =
872
+ platform === "win32" && !looksLikeMacBundleExec ? "bun.exe" : "bun";
873
+ const execDir = execPath ? dirnamePortable(execPath) : "";
874
+ const packagedCandidates = [
875
+ execPath,
876
+ execDir ? joinPortable(execDir, executableName) : "",
877
+ execDir
878
+ ? resolveRelativePortable(
879
+ execDir,
880
+ `../Resources/app/bun/${executableName}`,
881
+ )
882
+ : "",
883
+ execDir
884
+ ? resolveRelativePortable(
885
+ execDir,
886
+ `../Resources/app/bun/bin/${executableName}`,
887
+ )
888
+ : "",
889
+ moduleDir ? joinPortable(moduleDir, executableName) : "",
890
+ moduleDir ? joinPortable(moduleDir, "bin", executableName) : "",
891
+ moduleDir
892
+ ? resolveRelativePortable(moduleDir, `../bun/${executableName}`)
893
+ : "",
894
+ moduleDir
895
+ ? resolveRelativePortable(moduleDir, `../bun/bin/${executableName}`)
896
+ : "",
897
+ ].filter(Boolean);
898
+
899
+ for (const candidate of packagedCandidates) {
900
+ if (!fs.existsSync(candidate)) continue;
901
+ if (
902
+ path.basename(candidate).toLowerCase() === executableName.toLowerCase()
903
+ ) {
904
+ return candidate;
905
+ }
906
+ }
907
+
908
+ if (packagedRuntime) {
909
+ return (
910
+ packagedCandidates.find(
911
+ (candidate) =>
912
+ path.basename(candidate).toLowerCase() ===
913
+ executableName.toLowerCase(),
914
+ ) ?? executableName
915
+ );
916
+ }
917
+
918
+ const _candidates = [
919
+ execPath,
920
+ execDir ? joinPortable(execDir, executableName) : "",
921
+ ].filter(Boolean);
922
+
923
+ const bunGlobal = Bun as { which?: (binary: string) => string | null };
924
+ const whichCandidate =
925
+ typeof bunGlobal.which === "function" ? bunGlobal.which("bun") : null;
926
+ if (whichCandidate) return whichCandidate;
927
+
928
+ // Windows: bun is not always on PATH; check well-known install locations.
929
+ if (process.platform === "win32") {
930
+ const localAppData =
931
+ process.env.LOCALAPPDATA ??
932
+ joinPortable(os.homedir(), "AppData", "Local");
933
+ const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
934
+ const winCandidates = [
935
+ joinPortable(localAppData, "bun", "bun.exe"),
936
+ joinPortable(programFiles, "bun", "bun.exe"),
937
+ joinPortable(os.homedir(), ".bun", "bin", "bun.exe"),
938
+ ];
939
+ for (const candidate of winCandidates) {
940
+ if (fs.existsSync(candidate)) return candidate;
941
+ }
942
+ }
943
+
944
+ return "bun";
804
945
  }
805
946
 
806
947
  export function resolveRuntimeDistPath(opts?: {
807
- env?: NodeJS.ProcessEnv;
808
- moduleDir?: string;
809
- execPath?: string;
948
+ env?: NodeJS.ProcessEnv;
949
+ moduleDir?: string;
950
+ execPath?: string;
810
951
  }): string {
811
- const env = opts?.env ?? process.env;
812
- const moduleDir = opts?.moduleDir ?? getDefaultModuleDir();
813
- const execPath = opts?.execPath ?? process.execPath;
814
- const packagedRuntime = isPackagedDesktopRuntime(moduleDir, execPath);
815
- const distDir = getBrandConfig().runtimeDistDirName;
816
- const fallbackCandidates = getRuntimeDistFallbackCandidates(
817
- moduleDir,
818
- execPath,
819
- );
820
-
821
- if (packagedRuntime) {
822
- for (const candidate of fallbackCandidates) {
823
- if (fs.existsSync(candidate)) {
824
- return candidate;
825
- }
826
- }
827
- const fallback = fallbackCandidates[0];
828
- diagnosticLog(
829
- `[Agent] Could not find packaged runtime dist; using fallback: ${fallback}`,
830
- );
831
- return fallback;
832
- }
833
-
834
- // 1. Env override
835
- const envPath = env.ELIZA_DIST_PATH;
836
- if (envPath) {
837
- const resolved = resolvePortablePath(envPath);
838
- if (fs.existsSync(resolved)) {
839
- return resolved;
840
- }
841
- diagnosticLog(
842
- `[Agent] ELIZA_DIST_PATH set but does not exist: ${resolved}`,
843
- );
844
- }
845
-
846
- // 2. Walk up from import.meta.dir looking for runtime dist or dev dist
847
- let dir = moduleDir;
848
- const maxDepth = 15;
849
- for (let i = 0; i < maxDepth; i++) {
850
- // Packaged: runtime dist sibling
851
- const runtimeDist = joinPortable(dir, distDir);
852
- if (fs.existsSync(runtimeDist)) {
853
- return runtimeDist;
854
- }
855
- // Legacy eliza-dist sibling (existing packaged builds)
856
- const legacyDist = joinPortable(dir, "eliza-dist");
857
- if (fs.existsSync(legacyDist)) {
858
- return legacyDist;
859
- }
860
- // Dev monorepo: dist/ sibling containing the canonical CLI entrypoint
861
- const devDist = joinPortable(dir, "dist");
862
- if (fs.existsSync(joinPortable(devDist, "entry.js"))) {
863
- return devDist;
864
- }
865
- const parent = dirnamePortable(dir);
866
- if (parent === dir) break; // reached filesystem root
867
- dir = parent;
868
- }
869
-
870
- // 3. Packaged/dev fallbacks derived from the launcher path and module dir.
871
- for (const candidate of fallbackCandidates) {
872
- if (fs.existsSync(candidate)) {
873
- diagnosticLog(
874
- `[Agent] Could not find runtime dist by walking up; using fallback: ${candidate}`,
875
- );
876
- return candidate;
877
- }
878
- }
879
-
880
- const fallback = fallbackCandidates[0];
881
- diagnosticLog(
882
- `[Agent] Could not find runtime dist by walking up; using fallback: ${fallback}`,
883
- );
884
- return fallback;
952
+ const env = opts?.env ?? process.env;
953
+ const moduleDir = opts?.moduleDir ?? getDefaultModuleDir();
954
+ const execPath = opts?.execPath ?? process.execPath;
955
+ const packagedRuntime = isPackagedDesktopRuntime(moduleDir, execPath);
956
+ const distDir = getBrandConfig().runtimeDistDirName;
957
+ const fallbackCandidates = getRuntimeDistFallbackCandidates(
958
+ moduleDir,
959
+ execPath,
960
+ );
961
+
962
+ if (packagedRuntime) {
963
+ for (const candidate of fallbackCandidates) {
964
+ if (fs.existsSync(candidate)) {
965
+ return candidate;
966
+ }
967
+ }
968
+ const fallback = fallbackCandidates[0];
969
+ diagnosticLog(
970
+ `[Agent] Could not find packaged runtime dist; using fallback: ${fallback}`,
971
+ );
972
+ return fallback;
973
+ }
974
+
975
+ // 1. Env override
976
+ const envPath = env.ELIZA_DIST_PATH;
977
+ if (envPath) {
978
+ const resolved = resolvePortablePath(envPath);
979
+ if (fs.existsSync(resolved)) {
980
+ return resolved;
981
+ }
982
+ diagnosticLog(
983
+ `[Agent] ELIZA_DIST_PATH set but does not exist: ${resolved}`,
984
+ );
985
+ }
986
+
987
+ // 2. Walk up from import.meta.dir looking for runtime dist or dev dist
988
+ let dir = moduleDir;
989
+ const maxDepth = 15;
990
+ for (let i = 0; i < maxDepth; i++) {
991
+ // Packaged: runtime dist sibling
992
+ const runtimeDist = joinPortable(dir, distDir);
993
+ if (fs.existsSync(runtimeDist)) {
994
+ return runtimeDist;
995
+ }
996
+ // Legacy eliza-dist sibling (existing packaged builds)
997
+ const legacyDist = joinPortable(dir, "eliza-dist");
998
+ if (fs.existsSync(legacyDist)) {
999
+ return legacyDist;
1000
+ }
1001
+ // Dev monorepo: dist/ sibling containing the canonical CLI entrypoint
1002
+ const devDist = joinPortable(dir, "dist");
1003
+ if (fs.existsSync(joinPortable(devDist, "entry.js"))) {
1004
+ return devDist;
1005
+ }
1006
+ const parent = dirnamePortable(dir);
1007
+ if (parent === dir) break; // reached filesystem root
1008
+ dir = parent;
1009
+ }
1010
+
1011
+ // 3. Packaged/dev fallbacks derived from the launcher path and module dir.
1012
+ for (const candidate of fallbackCandidates) {
1013
+ if (fs.existsSync(candidate)) {
1014
+ diagnosticLog(
1015
+ `[Agent] Could not find runtime dist by walking up; using fallback: ${candidate}`,
1016
+ );
1017
+ return candidate;
1018
+ }
1019
+ }
1020
+
1021
+ const fallback = fallbackCandidates[0];
1022
+ diagnosticLog(
1023
+ `[Agent] Could not find runtime dist by walking up; using fallback: ${fallback}`,
1024
+ );
1025
+ return fallback;
885
1026
  }
886
1027
 
887
1028
  export function buildChildNodePaths(
888
- runtimeDistPath: string,
889
- opts?: { packagedRuntime?: boolean },
1029
+ runtimeDistPath: string,
1030
+ opts?: { packagedRuntime?: boolean },
890
1031
  ): string[] {
891
- const nodePaths = new Set<string>();
892
- const distModules = joinPortable(runtimeDistPath, "node_modules");
893
- if (fs.existsSync(distModules)) {
894
- nodePaths.add(distModules);
895
- }
896
-
897
- if (opts?.packagedRuntime) {
898
- return [...nodePaths];
899
- }
900
-
901
- let searchDir = runtimeDistPath;
902
- while (searchDir !== dirnamePortable(searchDir)) {
903
- const candidate = joinPortable(searchDir, "node_modules");
904
- if (fs.existsSync(candidate) && candidate !== distModules) {
905
- nodePaths.add(candidate);
906
- break;
907
- }
908
- searchDir = dirnamePortable(searchDir);
909
- }
910
-
911
- return [...nodePaths];
1032
+ const nodePaths = new Set<string>();
1033
+ const distModules = joinPortable(runtimeDistPath, "node_modules");
1034
+ if (fs.existsSync(distModules)) {
1035
+ nodePaths.add(distModules);
1036
+ }
1037
+
1038
+ if (opts?.packagedRuntime) {
1039
+ return [...nodePaths];
1040
+ }
1041
+
1042
+ let searchDir = runtimeDistPath;
1043
+ while (searchDir !== dirnamePortable(searchDir)) {
1044
+ const candidate = joinPortable(searchDir, "node_modules");
1045
+ if (fs.existsSync(candidate) && candidate !== distModules) {
1046
+ nodePaths.add(candidate);
1047
+ break;
1048
+ }
1049
+ searchDir = dirnamePortable(searchDir);
1050
+ }
1051
+
1052
+ return [...nodePaths];
912
1053
  }
913
1054
 
914
- function resolveRuntimeEntryPath(runtimeDistPath: string): string | null {
915
- const candidates = [joinPortable(runtimeDistPath, "entry.js")];
916
-
917
- for (const candidate of candidates) {
918
- if (fs.existsSync(candidate)) {
919
- return candidate;
920
- }
921
- }
922
-
923
- return null;
1055
+ export function resolveRuntimeEntryPath(
1056
+ runtimeDistPath: string,
1057
+ ): string | null {
1058
+ const candidates = [
1059
+ joinPortable(runtimeDistPath, "entry.js"),
1060
+ joinPortable(runtimeDistPath, "runtime", "entry.js"),
1061
+ ];
1062
+
1063
+ for (const candidate of candidates) {
1064
+ if (fs.existsSync(candidate)) {
1065
+ return candidate;
1066
+ }
1067
+ }
1068
+
1069
+ return null;
924
1070
  }
925
1071
 
926
1072
  // ---------------------------------------------------------------------------
@@ -928,52 +1074,97 @@ function resolveRuntimeEntryPath(runtimeDistPath: string): string | null {
928
1074
  // ---------------------------------------------------------------------------
929
1075
 
930
1076
  async function waitForHealthy(
931
- getPort: () => number,
932
- timeoutMs: number = getHealthPollTimeoutMs(),
933
- childProcess?: BunSubprocess | null,
1077
+ getPort: () => number,
1078
+ timeoutMs: number = getHealthPollTimeoutMs(),
1079
+ childProcess?: BunSubprocess | null,
934
1080
  ): Promise<boolean> {
935
- const deadline = Date.now() + timeoutMs;
936
- const headers = getDesktopApiHeaders();
937
-
938
- while (Date.now() < deadline) {
939
- // Bail early if the child process has already exited
940
- if (childProcess && childProcess.exitCode !== null) {
941
- return false;
942
- }
943
-
944
- const port = getPort();
945
- const url = `http://127.0.0.1:${port}/api/health`;
946
- try {
947
- const response = await fetch(url, {
948
- headers,
949
- signal: AbortSignal.timeout(2_000),
950
- });
951
- if (response.ok) {
952
- const health = (await response.json().catch(() => null)) as {
953
- ready?: boolean;
954
- agentState?: string;
955
- startup?: { phase?: string };
956
- } | null;
957
- if (!health) {
958
- return true;
959
- }
960
- if (typeof health.ready === "boolean") {
961
- if (health.ready) {
962
- return true;
963
- }
964
- } else if (
965
- health.agentState !== "starting" &&
966
- health.agentState !== "restarting"
967
- ) {
968
- return true;
969
- }
970
- }
971
- } catch {
972
- // Server not ready yet
973
- }
974
- await Bun.sleep(HEALTH_POLL_INTERVAL_MS);
975
- }
976
- return false;
1081
+ const deadline = Date.now() + timeoutMs;
1082
+ const headers = getDesktopApiHeaders();
1083
+
1084
+ while (Date.now() < deadline) {
1085
+ // Bail early if the child process has already exited
1086
+ if (childProcess && childProcess.exitCode !== null) {
1087
+ return false;
1088
+ }
1089
+
1090
+ const port = getPort();
1091
+ const url = `http://127.0.0.1:${port}/api/health`;
1092
+ try {
1093
+ const response = await fetch(url, {
1094
+ headers,
1095
+ signal: AbortSignal.timeout(2_000),
1096
+ });
1097
+ if (response.ok) {
1098
+ const health = (await response.json().catch(() => null)) as {
1099
+ ready?: boolean;
1100
+ agentState?: string;
1101
+ startup?: { phase?: string };
1102
+ } | null;
1103
+ if (!health) {
1104
+ return true;
1105
+ }
1106
+ if (typeof health.ready === "boolean") {
1107
+ if (health.ready) {
1108
+ return true;
1109
+ }
1110
+ } else if (
1111
+ health.agentState !== "starting" &&
1112
+ health.agentState !== "restarting"
1113
+ ) {
1114
+ return true;
1115
+ }
1116
+ }
1117
+ if (await isStartupStatusReachable(port, headers)) {
1118
+ return true;
1119
+ }
1120
+ } catch {
1121
+ if (await isStartupStatusReachable(port, headers)) {
1122
+ return true;
1123
+ }
1124
+ }
1125
+ await Bun.sleep(HEALTH_POLL_INTERVAL_MS);
1126
+ }
1127
+ return false;
1128
+ }
1129
+
1130
+ function isRecord(value: unknown): value is Record<string, unknown> {
1131
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1132
+ }
1133
+
1134
+ function isNonFatalStartupStatus(value: unknown): boolean {
1135
+ if (!isRecord(value)) return false;
1136
+ const startup = value.startup;
1137
+ if (!isRecord(startup)) return false;
1138
+ const phase = startup.phase;
1139
+ if (
1140
+ phase === "fatal" ||
1141
+ phase === "startup_failed" ||
1142
+ phase === "runtime_entry_missing"
1143
+ ) {
1144
+ return false;
1145
+ }
1146
+ return (
1147
+ typeof phase === "string" ||
1148
+ typeof startup.embeddingPhase === "string" ||
1149
+ typeof startup.embeddingDetail === "string"
1150
+ );
1151
+ }
1152
+
1153
+ async function isStartupStatusReachable(
1154
+ port: number,
1155
+ headers: Record<string, string> | undefined,
1156
+ ): Promise<boolean> {
1157
+ try {
1158
+ const response = await fetch(`http://127.0.0.1:${port}/api/status`, {
1159
+ headers,
1160
+ signal: AbortSignal.timeout(2_000),
1161
+ });
1162
+ const body = await response.json().catch(() => null);
1163
+ if (response.ok) return true;
1164
+ return isNonFatalStartupStatus(body);
1165
+ } catch {
1166
+ return false;
1167
+ }
977
1168
  }
978
1169
 
979
1170
  // ---------------------------------------------------------------------------
@@ -981,171 +1172,172 @@ async function waitForHealthy(
981
1172
  // ---------------------------------------------------------------------------
982
1173
 
983
1174
  async function watchStdoutForReady(
984
- stream: ReadableStream<Uint8Array>,
985
- onLine: (line: string) => void,
986
- signal: AbortSignal,
1175
+ stream: ReadableStream<Uint8Array>,
1176
+ onLine: (line: string) => void,
1177
+ signal: AbortSignal,
987
1178
  ): Promise<void> {
988
- const decoder = new TextDecoder();
989
- let buffer = "";
990
-
991
- try {
992
- const reader = stream.getReader();
993
- while (!signal.aborted) {
994
- const { done, value } = await reader.read();
995
- if (done) break;
996
-
997
- buffer += decoder.decode(value, { stream: true });
998
- const lines = buffer.split("\n");
999
- buffer = lines.pop() ?? "";
1000
-
1001
- for (const line of lines) {
1002
- if (line.trim()) {
1003
- onLine(line);
1004
- }
1005
- }
1006
- }
1007
- // Flush remaining buffer
1008
- if (buffer.trim()) {
1009
- onLine(buffer);
1010
- }
1011
- reader.releaseLock();
1012
- } catch (err) {
1013
- if (!signal.aborted) {
1014
- diagnosticLog(
1015
- `[Agent] stdout watcher error: ${err instanceof Error ? err.message : String(err)}`,
1016
- );
1017
- }
1018
- }
1179
+ const decoder = new TextDecoder();
1180
+ let buffer = "";
1181
+
1182
+ try {
1183
+ const reader = stream.getReader();
1184
+ while (!signal.aborted) {
1185
+ const { done, value } = await reader.read();
1186
+ if (done) break;
1187
+
1188
+ buffer += decoder.decode(value, { stream: true });
1189
+ const lines = buffer.split("\n");
1190
+ buffer = lines.pop() ?? "";
1191
+
1192
+ for (const line of lines) {
1193
+ if (line.trim()) {
1194
+ onLine(line);
1195
+ }
1196
+ }
1197
+ }
1198
+ // Flush remaining buffer
1199
+ if (buffer.trim()) {
1200
+ onLine(buffer);
1201
+ }
1202
+ reader.releaseLock();
1203
+ } catch (err) {
1204
+ if (!signal.aborted) {
1205
+ diagnosticLog(
1206
+ `[Agent] stdout watcher error: ${err instanceof Error ? err.message : String(err)}`,
1207
+ );
1208
+ }
1209
+ }
1019
1210
  }
1020
1211
 
1021
1212
  async function drainStderrToLog(
1022
- stream: ReadableStream<Uint8Array>,
1023
- signal: AbortSignal,
1024
- onLine?: (line: string) => void,
1213
+ stream: ReadableStream<Uint8Array>,
1214
+ signal: AbortSignal,
1215
+ onLine?: (line: string) => void,
1025
1216
  ): Promise<void> {
1026
- const decoder = new TextDecoder();
1027
- let buffer = "";
1028
-
1029
- try {
1030
- const reader = stream.getReader();
1031
- while (!signal.aborted) {
1032
- const { done, value } = await reader.read();
1033
- if (done) break;
1034
-
1035
- buffer += decoder.decode(value, { stream: true });
1036
- const lines = buffer.split("\n");
1037
- buffer = lines.pop() ?? "";
1038
-
1039
- for (const line of lines) {
1040
- if (line.trim()) {
1041
- diagnosticLog(`[Agent][stderr] ${line}`);
1042
- onLine?.(line);
1043
- }
1044
- }
1045
- }
1046
- if (buffer.trim()) {
1047
- diagnosticLog(`[Agent][stderr] ${buffer}`);
1048
- onLine?.(buffer);
1049
- }
1050
- reader.releaseLock();
1051
- } catch (err) {
1052
- if (!signal.aborted) {
1053
- diagnosticLog(
1054
- `[Agent] stderr drain error: ${err instanceof Error ? err.message : String(err)}`,
1055
- );
1056
- }
1057
- }
1217
+ const decoder = new TextDecoder();
1218
+ let buffer = "";
1219
+
1220
+ try {
1221
+ const reader = stream.getReader();
1222
+ while (!signal.aborted) {
1223
+ const { done, value } = await reader.read();
1224
+ if (done) break;
1225
+
1226
+ buffer += decoder.decode(value, { stream: true });
1227
+ const lines = buffer.split("\n");
1228
+ buffer = lines.pop() ?? "";
1229
+
1230
+ for (const line of lines) {
1231
+ if (line.trim()) {
1232
+ diagnosticLog(`[Agent][stderr] ${line}`);
1233
+ onLine?.(line);
1234
+ }
1235
+ }
1236
+ }
1237
+ if (buffer.trim()) {
1238
+ diagnosticLog(`[Agent][stderr] ${buffer}`);
1239
+ onLine?.(buffer);
1240
+ }
1241
+ reader.releaseLock();
1242
+ } catch (err) {
1243
+ if (!signal.aborted) {
1244
+ diagnosticLog(
1245
+ `[Agent] stderr drain error: ${err instanceof Error ? err.message : String(err)}`,
1246
+ );
1247
+ }
1248
+ }
1058
1249
  }
1059
1250
 
1060
1251
  const PGLITE_LOCK_RE =
1061
- /pglite data dir is already in use|database is locked|lock file already exists/i;
1252
+ /pglite data dir is already in use|database is locked|lock file already exists/i;
1062
1253
  const PGLITE_RECOVERY_RE =
1063
- /failed query:\s*(?:create schema if not exists|create table if not exists life_)|aborted\(\)\. build with -sassertions|database disk image is malformed|file is not a database|malformed database schema|checksum mismatch|checkpoint failed|wal file/i;
1254
+ /failed query:\s*(?:create schema if not exists|create table if not exists life_)|aborted\(\)\. build with -sassertions|database disk image is malformed|file is not a database|malformed database schema|checksum mismatch|checkpoint failed|wal file/i;
1064
1255
 
1065
1256
  function shouldAutoRecoverPgliteFailure(line: string): boolean {
1066
- if (PGLITE_LOCK_RE.test(line)) {
1067
- return false;
1068
- }
1069
-
1070
- return (
1071
- PGLITE_RECOVERY_RE.test(line) ||
1072
- (/corrupt/i.test(line) && /pglite|sqlite/i.test(line))
1073
- );
1257
+ if (PGLITE_LOCK_RE.test(line)) {
1258
+ return false;
1259
+ }
1260
+
1261
+ return (
1262
+ PGLITE_RECOVERY_RE.test(line) ||
1263
+ (/corrupt/i.test(line) && /pglite|sqlite/i.test(line))
1264
+ );
1074
1265
  }
1075
1266
 
1076
1267
  /**
1077
1268
  * Opt-in: kill processes listening on `port` (lsof + SIGKILL). Default off so a
1078
1269
  * second desktop instance can coexist on the same machine when ports differ.
1079
- * Set ELIZA_AGENT_RECLAIM_STALE_PORT=1 (legacy: ELIZA_AGENT_RECLAIM_STALE_PORT)
1080
- * to restore the old “take over default port behavior.
1270
+ * Set ELIZA_AGENT_RECLAIM_STALE_PORT=1 to restore the old "take over default
1271
+ * port" behavior.
1272
+ */
1273
+ /**
1274
+ * PIDs listening on `port`. POSIX uses `lsof`; Windows uses
1275
+ * `Get-NetTCPConnection` (locale-independent and returns the owning PID
1276
+ * directly — `lsof` does not exist on Windows, so the reclaim was a silent
1277
+ * no-op there before).
1081
1278
  */
1279
+ function listListeningPids(port: number): number[] {
1280
+ const result =
1281
+ process.platform === "win32"
1282
+ ? Bun.spawnSync([
1283
+ "powershell.exe",
1284
+ "-NoProfile",
1285
+ "-Command",
1286
+ `(Get-NetTCPConnection -LocalPort ${port} -State Listen -ErrorAction SilentlyContinue).OwningProcess`,
1287
+ ])
1288
+ : Bun.spawnSync(["lsof", "-ti", `tcp:${port}`]);
1289
+ return new TextDecoder()
1290
+ .decode(result.stdout)
1291
+ .trim()
1292
+ .split(/\r?\n/)
1293
+ .map((p) => parseInt(p.trim(), 10))
1294
+ .filter((n) => !Number.isNaN(n));
1295
+ }
1296
+
1082
1297
  async function maybeReclaimPortWithSigkill(port: number): Promise<void> {
1083
- const raw = process.env.ELIZA_AGENT_RECLAIM_STALE_PORT?.trim().toLowerCase();
1084
- if (raw !== "1" && raw !== "true" && raw !== "yes") {
1085
- return;
1086
- }
1087
- try {
1088
- const lsofResult = Bun.spawnSync(["lsof", "-ti", `tcp:${port}`]);
1089
- const pids = new TextDecoder()
1090
- .decode(lsofResult.stdout)
1091
- .trim()
1092
- .split("\n")
1093
- .filter(Boolean);
1094
- for (const pid of pids) {
1095
- const numPid = parseInt(pid, 10);
1096
- if (!Number.isNaN(numPid) && numPid !== process.pid) {
1097
- diagnosticLog(
1098
- `[Agent] Reclaim: killing process ${numPid} on port ${port} (ELIZA_AGENT_RECLAIM_STALE_PORT)`,
1099
- );
1100
- try {
1101
- process.kill(numPid, "SIGKILL");
1102
- } catch {
1103
- // Process may have already exited
1104
- }
1105
- }
1106
- }
1107
- if (pids.length > 0) {
1108
- await new Promise((r) => setTimeout(r, 500));
1109
- }
1110
- } catch {
1111
- // lsof missing — ignore
1112
- }
1113
- }
1114
-
1115
- function resolvePgliteDataDir(): string {
1116
- return joinPortable(
1117
- os.homedir(),
1118
- `.${getBrandConfig().namespace}`,
1119
- "workspace",
1120
- ".eliza",
1121
- ".elizadb",
1122
- );
1298
+ const raw = process.env.ELIZA_AGENT_RECLAIM_STALE_PORT?.trim().toLowerCase();
1299
+ if (raw !== "1" && raw !== "true" && raw !== "yes") {
1300
+ return;
1301
+ }
1302
+ try {
1303
+ const pids = listListeningPids(port);
1304
+ for (const numPid of pids) {
1305
+ if (numPid !== process.pid) {
1306
+ diagnosticLog(
1307
+ `[Agent] Reclaim: killing process ${numPid} on port ${port} (ELIZA_AGENT_RECLAIM_STALE_PORT)`,
1308
+ );
1309
+ try {
1310
+ process.kill(numPid, "SIGKILL");
1311
+ } catch {
1312
+ // Process may have already exited
1313
+ }
1314
+ }
1315
+ }
1316
+ if (pids.length > 0) {
1317
+ await new Promise((r) => setTimeout(r, 500));
1318
+ }
1319
+ } catch {
1320
+ // port-listing tool missing — ignore
1321
+ }
1123
1322
  }
1124
1323
 
1125
- /**
1126
- * Removes only the PGLite database folder (agent memory / conversations).
1127
- * GGUF embedding weights live under `MODELS_DIR` / `~/.eliza/models` by default — never deleted here.
1128
- */
1129
- function deletePgliteDataDir(): void {
1130
- const dir = resolvePgliteDataDir();
1131
- if (path.basename(dir) !== ".elizadb") {
1132
- diagnosticLog(
1133
- `[Agent] deletePgliteDataDir: refused basename must be .elizadb, got: ${dir}`,
1134
- );
1135
- return;
1136
- }
1137
- try {
1138
- if (fs.existsSync(dir)) {
1139
- fs.rmSync(dir, { recursive: true, force: true });
1140
- diagnosticLog(
1141
- `[Agent] Deleted PGLite data dir (GGUF model cache elsewhere): ${dir}`,
1142
- );
1143
- }
1144
- } catch (err) {
1145
- diagnosticLog(
1146
- `[Agent] Failed to delete PGLite data dir: ${err instanceof Error ? err.message : String(err)}`,
1147
- );
1148
- }
1324
+ function resolveDatabaseAppStateDir(
1325
+ env: NodeJS.ProcessEnv = process.env,
1326
+ ): string {
1327
+ const stateDir = resolveDesktopChildStateDir({ env });
1328
+ fs.mkdirSync(stateDir, { recursive: true });
1329
+ return stateDir;
1330
+ }
1331
+
1332
+ function resolveManagedPgliteDataDir(): string | null {
1333
+ const resolution = resolveDatabaseMode({
1334
+ env: process.env as Record<string, string | undefined>,
1335
+ packagedDesktop: isPackagedDesktopRuntime(),
1336
+ appStateDir: resolveDatabaseAppStateDir(process.env),
1337
+ });
1338
+ return resolution.mode === "pglite-persistent"
1339
+ ? (resolution.pgliteDataDir ?? null)
1340
+ : null;
1149
1341
  }
1150
1342
 
1151
1343
  // ---------------------------------------------------------------------------
@@ -1153,800 +1345,1059 @@ function deletePgliteDataDir(): void {
1153
1345
  // ---------------------------------------------------------------------------
1154
1346
 
1155
1347
  export class AgentManager {
1156
- private sendToWebview: SendToWebview | null = null;
1157
- private readonly statusListeners = new Set<
1158
- (status: Readonly<AgentStatus>) => void
1159
- >();
1160
- private status: AgentStatus = {
1161
- state: "not_started",
1162
- agentName: null,
1163
- port: null,
1164
- startedAt: null,
1165
- error: null,
1166
- };
1167
- private childProcess: BunSubprocess | null = null;
1168
- private stdioAbortController: AbortController | null = null;
1169
- private hasPgliteError = false;
1170
- private pgliteRecoveryDone = false;
1171
- private startupPhase = "not_started";
1172
-
1173
- constructor() {
1174
- this.persistStartupDiagnostics();
1175
- }
1176
-
1177
- setSendToWebview(fn: SendToWebview): void {
1178
- this.sendToWebview = fn;
1179
- }
1180
-
1181
- onStatusChange(
1182
- listener: (status: Readonly<AgentStatus>) => void,
1183
- ): () => void {
1184
- this.statusListeners.add(listener);
1185
- return () => {
1186
- this.statusListeners.delete(listener);
1187
- };
1188
- }
1189
-
1190
- /** Start the agent runtime as a child process. Idempotent. */
1191
- async start(): Promise<AgentStatus> {
1192
- recordStartupPhase("agent_start_entered", {
1193
- pid: process.pid,
1194
- exec_path: process.execPath,
1195
- bundle_path: resolveStartupBundlePath(process.execPath),
1196
- });
1197
- this.setStartupPhase("start_requested");
1198
- recordStartupPhase("agent_start_entered", {
1199
- pid: process.pid,
1200
- exec_path: process.execPath,
1201
- bundle_path: resolveStartupBundlePath(process.execPath),
1202
- });
1203
- diagnosticLog(
1204
- `[Agent] start() called, current state: ${this.status.state}`,
1205
- );
1206
- diagnosticLog(`[Agent] Diagnostic log file: ${getDiagnosticLogPath()}`);
1207
-
1208
- if (this.status.state === "running" || this.status.state === "starting") {
1209
- return this.status;
1210
- }
1211
-
1212
- const runtimeMode = resolveDesktopRuntimeMode(
1213
- process.env as Record<string, string | undefined>,
1214
- );
1215
- if (runtimeMode.mode !== "local") {
1216
- const reason =
1217
- runtimeMode.mode === "external"
1218
- ? `Embedded desktop runtime is disabled because ${runtimeMode.externalApi.source} points at ${runtimeMode.externalApi.base}.`
1219
- : "Embedded desktop runtime is disabled by ELIZA_DESKTOP_SKIP_EMBEDDED_AGENT=1.";
1220
- diagnosticLog(`[Agent] ${reason}`);
1221
- this.setStartupPhase("startup_disabled", reason);
1222
- throw new Error(reason);
1223
- }
1224
-
1225
- let packagedRuntime: boolean;
1226
- let apiPort: number;
1227
- let preferredPort: number;
1228
- try {
1229
- configureDesktopLocalApiAuth();
1230
- packagedRuntime = isPackagedDesktopRuntime();
1231
-
1232
- // Reset per-startup flags
1233
- this.pgliteRecoveryDone = false;
1234
-
1235
- // Clean up any stale process before starting
1236
- if (this.childProcess) {
1237
- await this.killChildProcess();
1238
- }
1239
-
1240
- preferredPort = resolveDesktopApiPort(process.env) || DEFAULT_API_PORT;
1241
- diagnosticLog(
1242
- `[Agent] Preferred port: ${preferredPort} (packaged: ${packagedRuntime})`,
1243
- );
1244
- if (!packagedRuntime) {
1245
- await maybeReclaimPortWithSigkill(preferredPort);
1246
- }
1247
- apiPort = await findFirstAvailableLoopbackPort(preferredPort);
1248
- } catch (err) {
1249
- const msg =
1250
- err instanceof Error ? err.message : "Failed during pre-startup";
1251
- diagnosticLog(`[Agent] ${msg}`);
1252
- this.status = {
1253
- state: "error",
1254
- agentName: null,
1255
- port: null,
1256
- startedAt: null,
1257
- error: msg,
1258
- };
1259
- recordStartupPhase("fatal", {
1260
- port: null,
1261
- error: msg,
1262
- });
1263
- this.setStartupPhase("port_allocation_failed", msg);
1264
- this.emitStatus();
1265
- return this.status;
1266
- }
1267
- if (apiPort !== preferredPort) {
1268
- diagnosticLog(
1269
- `[Agent] Port ${preferredPort} busy — using ${apiPort} for embedded API (set ELIZA_AGENT_RECLAIM_STALE_PORT=1 to try reclaiming the preferred port first)`,
1270
- );
1271
- }
1272
- recordStartupPhase("port_selected", {
1273
- port: apiPort,
1274
- });
1275
-
1276
- this.status = {
1277
- state: "starting",
1278
- agentName: null,
1279
- port: null,
1280
- startedAt: null,
1281
- error: null,
1282
- };
1283
- this.setStartupPhase("starting_runtime");
1284
- this.emitStatus();
1285
-
1286
- try {
1287
- // Resolve the bundled runtime dist path.
1288
- this.setStartupPhase("resolving_runtime");
1289
- const runtimeDistPath = resolveRuntimeDistPath();
1290
- diagnosticLog(`[Agent] Resolved runtime dist: ${runtimeDistPath}`);
1291
-
1292
- // Packaged builds can expose the runnable entry either at the dist root
1293
- // or under runtime/. Prefer the root file but accept both layouts.
1294
- const runtimeEntryPath = resolveRuntimeEntryPath(runtimeDistPath);
1295
- if (!runtimeEntryPath) {
1296
- const distExists = fs.existsSync(runtimeDistPath);
1297
- let contents = "<directory missing>";
1298
- if (distExists) {
1299
- try {
1300
- contents = fs.readdirSync(runtimeDistPath).join(", ");
1301
- } catch {
1302
- contents = "<unreadable>";
1303
- }
1304
- }
1305
- const errMsg = `No runnable runtime entry found in ${runtimeDistPath} (checked entry.js; dist exists: ${distExists}, contents: ${contents})`;
1306
- diagnosticLog(`[Agent] ${errMsg}`);
1307
- this.status = {
1308
- state: "error",
1309
- agentName: null,
1310
- port: null,
1311
- startedAt: null,
1312
- error: errMsg,
1313
- };
1314
- recordStartupPhase("fatal", {
1315
- port: apiPort,
1316
- error: errMsg,
1317
- });
1318
- this.setStartupPhase("runtime_entry_missing", errMsg);
1319
- recordStartupPhase("fatal", {
1320
- port: apiPort,
1321
- error: errMsg,
1322
- });
1323
- this.emitStatus();
1324
- return this.status;
1325
- }
1326
-
1327
- diagnosticLog(`[Agent] runtime entry: exists (${runtimeEntryPath})`);
1328
- recordStartupPhase("runtime_path_resolved", {
1329
- port: apiPort,
1330
- });
1331
-
1332
- diagnosticLog(`[Agent] Starting child process on port ${apiPort}...`);
1333
- this.setStartupPhase("spawning_runtime");
1334
-
1335
- // Build NODE_PATH so the child can find node_modules
1336
- const nodePaths = buildChildNodePaths(runtimeDistPath, {
1337
- packagedRuntime,
1338
- });
1339
- if (packagedRuntime && nodePaths.length === 0) {
1340
- const errMsg =
1341
- `Packaged runtime is missing bundle-local node_modules under ${runtimeDistPath}; ` +
1342
- "refusing to inherit the parent NODE_PATH";
1343
- diagnosticLog(`[Agent] ${errMsg}`);
1344
- this.status = {
1345
- state: "error",
1346
- agentName: null,
1347
- port: apiPort,
1348
- startedAt: null,
1349
- error: errMsg,
1350
- };
1351
- recordStartupPhase("fatal", {
1352
- port: apiPort,
1353
- error: errMsg,
1354
- });
1355
- this.emitStatus();
1356
- return this.status;
1357
- }
1358
-
1359
- const childEnv: Record<string, string> = {
1360
- ...(process.env as Record<string, string>),
1361
- ELIZA_API_PORT: String(apiPort),
1362
- ELIZA_PORT: String(apiPort),
1363
- };
1364
- childEnv.ELIZA_NAMESPACE =
1365
- childEnv.ELIZA_NAMESPACE?.trim() || getBrandConfig().namespace;
1366
- childEnv.ELIZA_NAMESPACE =
1367
- childEnv.ELIZA_NAMESPACE?.trim() || childEnv.ELIZA_NAMESPACE;
1368
- applyDesktopChildStateEnv(childEnv);
1369
- delete childEnv.ELIZA_PORT;
1370
- delete childEnv.NODE_PATH;
1371
-
1372
- // node-llama-cpp crashes Bun on Windows during packaged startup.
1373
- // Disable local embeddings until upstream fix lands.
1374
- if (process.platform === "win32") {
1375
- childEnv.ELIZA_DISABLE_LOCAL_EMBEDDINGS = "1";
1376
- }
1377
-
1378
- // Propagate PGlite data dir from parent env so CI/smoke test overrides
1379
- // (e.g. a short Windows path avoiding MAX_PATH issues) reach the runtime.
1380
- if (process.env.PGLITE_DATA_DIR) {
1381
- childEnv.PGLITE_DATA_DIR = process.env.PGLITE_DATA_DIR;
1382
- }
1383
-
1384
- if (nodePaths.length > 0) {
1385
- childEnv.NODE_PATH = nodePaths.join(path.delimiter);
1386
- diagnosticLog(`[Agent] Child NODE_PATH: ${childEnv.NODE_PATH}`);
1387
- }
1388
-
1389
- const bunExecutable = resolveBunExecutablePath();
1390
- diagnosticLog(`[Agent] Using Bun executable: ${bunExecutable}`);
1391
- diagnosticLog(
1392
- `[Agent] Bun exists on disk: ${fs.existsSync(bunExecutable)}`,
1393
- );
1394
-
1395
- // Ensure bun's directory is on PATH so child_process.exec calls
1396
- // (e.g. plugin-manager running `bun add ...`) can find it.
1397
- const bunDir = path.dirname(bunExecutable);
1398
- const existingPath = childEnv.PATH ?? "";
1399
- if (!existingPath.split(path.delimiter).includes(bunDir)) {
1400
- childEnv.PATH = bunDir + path.delimiter + existingPath;
1401
- diagnosticLog(`[Agent] Prepended bun dir to child PATH: ${bunDir}`);
1402
- }
1403
-
1404
- // Spawn the child process
1405
- const spawnTime = Date.now();
1406
- const proc = Bun.spawn(
1407
- [bunExecutable, "run", runtimeEntryPath, "start"],
1408
- {
1409
- cwd: runtimeDistPath,
1410
- env: childEnv,
1411
- stdout: "pipe",
1412
- stderr: "pipe",
1413
- },
1414
- );
1415
-
1416
- this.childProcess = proc;
1417
- diagnosticLog(
1418
- `[Agent] Child spawned pid=${proc.pid} elapsed=${Date.now() - spawnTime}ms`,
1419
- );
1420
- recordStartupPhase("child_spawned", {
1421
- port: apiPort,
1422
- child_pid: proc.pid,
1423
- });
1424
-
1425
- // Set up abort controller for stdio watchers
1426
- this.stdioAbortController = new AbortController();
1427
- const { signal } = this.stdioAbortController;
1428
-
1429
- // Surface the port immediately while waiting for ready
1430
- this.status = {
1431
- ...this.status,
1432
- port: apiPort,
1433
- };
1434
- this.emitStatus();
1435
-
1436
- // Track whether we detected the "listening" message from stdout
1437
- let detectedListening = false;
1438
-
1439
- // Watch stdout for "listening on port" or similar ready messages
1440
- if (proc.stdout) {
1441
- watchStdoutForReady(
1442
- proc.stdout,
1443
- (line: string) => {
1444
- diagnosticLog(`[Agent][stdout] ${line}`);
1445
- const lower = line.toLowerCase();
1446
- // Parse dynamic port from "[eliza-api] Listening on http://host:PORT"
1447
- const portMatch = line.match(
1448
- /Listening on https?:\/\/[^:]+:(\d+)/i,
1449
- );
1450
- if (portMatch) {
1451
- const parsedPort = parseInt(portMatch[1], 10);
1452
- if (!Number.isNaN(parsedPort) && parsedPort > 0) {
1453
- if (parsedPort !== apiPort) {
1454
- diagnosticLog(
1455
- `[Agent] Server bound to dynamic port ${parsedPort} (requested ${apiPort})`,
1456
- );
1457
- apiPort = parsedPort;
1458
- }
1459
- detectedListening = true;
1460
- }
1461
- } else if (
1462
- lower.includes("listening on port") ||
1463
- lower.includes("server started") ||
1464
- lower.includes("ready on")
1465
- ) {
1466
- detectedListening = true;
1467
- }
1468
- // Update status port so callers see the actual bound port
1469
- this.status = { ...this.status, port: apiPort };
1470
- this.emitStatus();
1471
- },
1472
- signal,
1473
- ).catch(() => {
1474
- // Stream ended or aborted -- expected on shutdown
1475
- });
1476
- }
1477
-
1478
- // Drain stderr to diagnostic log; detect PGLite migration failures
1479
- this.hasPgliteError = false;
1480
- if (proc.stderr) {
1481
- drainStderrToLog(proc.stderr, signal, (line) => {
1482
- if (shouldAutoRecoverPgliteFailure(line)) {
1483
- this.hasPgliteError = true;
1484
- }
1485
- }).catch(() => {
1486
- // Stream ended or aborted -- expected on shutdown
1487
- });
1488
- }
1489
-
1490
- // Monitor child process exit
1491
- this.monitorChildExit(proc);
1492
-
1493
- // Wait for the health endpoint to respond
1494
- // Use a getter so the health check follows dynamic port reassignment from stdout
1495
- diagnosticLog(
1496
- `[Agent] Waiting for health endpoint at http://127.0.0.1:${apiPort}/api/health ...`,
1497
- );
1498
- this.setStartupPhase("waiting_for_health");
1499
- const healthPollTimeoutMs = getHealthPollTimeoutMs();
1500
- const healthy = await waitForHealthy(
1501
- () => apiPort,
1502
- healthPollTimeoutMs,
1503
- proc,
1504
- );
1505
-
1506
- if (!healthy) {
1507
- // Check if process already exited
1508
- if (proc.exitCode !== null) {
1509
- const errMsg = `Child process exited with code ${proc.exitCode} before becoming healthy`;
1510
- diagnosticLog(`[Agent] ${errMsg}`);
1511
- this.childProcess = null;
1512
- this.status = {
1513
- state: "error",
1514
- agentName: null,
1515
- port: apiPort,
1516
- startedAt: null,
1517
- error: errMsg,
1518
- };
1519
- recordStartupPhase("fatal", {
1520
- port: apiPort,
1521
- child_pid: proc.pid,
1522
- error: errMsg,
1523
- exit_code: proc.exitCode,
1524
- });
1525
- this.setStartupPhase("startup_failed", errMsg);
1526
- recordStartupPhase("fatal", {
1527
- port: apiPort,
1528
- child_pid: proc.pid,
1529
- error: errMsg,
1530
- exit_code: proc.exitCode,
1531
- });
1532
- this.emitStatus();
1533
- return this.status;
1534
- }
1535
-
1536
- const errMsg = detectedListening
1537
- ? "Server reported listening but health check timed out"
1538
- : `Health check timed out after ${healthPollTimeoutMs}ms`;
1539
- diagnosticLog(`[Agent] ${errMsg}`);
1540
- this.status = {
1541
- state: "error",
1542
- agentName: null,
1543
- port: apiPort,
1544
- startedAt: null,
1545
- error: errMsg,
1546
- };
1547
- recordStartupPhase("fatal", {
1548
- port: apiPort,
1549
- child_pid: proc.pid,
1550
- error: errMsg,
1551
- });
1552
- this.setStartupPhase("startup_failed", errMsg);
1553
- recordStartupPhase("fatal", {
1554
- port: apiPort,
1555
- child_pid: proc.pid,
1556
- error: errMsg,
1557
- });
1558
- this.emitStatus();
1559
- return this.status;
1560
- }
1561
- recordStartupPhase("health_ready", {
1562
- port: apiPort,
1563
- child_pid: proc.pid,
1564
- });
1565
-
1566
- this.setStartupPhase("fetching_agent_metadata");
1567
- const startedAt = Date.now();
1568
- const startupMs = startedAt - spawnTime;
1569
-
1570
- this.status = {
1571
- state: "running",
1572
- agentName: getBrandConfig().appName,
1573
- port: apiPort,
1574
- startedAt,
1575
- error: null,
1576
- };
1577
- this.setStartupPhase("ready", null);
1578
- this.emitStatus();
1579
- diagnosticLog(
1580
- `[Agent] Runtime ready -- port: ${apiPort}, pid: ${proc.pid}, startup_ms: ${startupMs}`,
1581
- );
1582
- recordStartupPhase("runtime_ready", {
1583
- port: apiPort,
1584
- child_pid: proc.pid,
1585
- });
1586
- void this.refreshAgentMetadata(proc, apiPort, startupMs);
1587
- return this.status;
1588
- } catch (err) {
1589
- const errMsg =
1590
- err instanceof Error ? err.stack || err.message : String(err);
1591
- diagnosticLog(`[Agent] Failed to start: ${errMsg}`);
1592
- recordStartupPhase("fatal", {
1593
- port: this.status.port,
1594
- error: errMsg,
1595
- });
1596
-
1597
- // Clean up child if it was spawned
1598
- if (this.childProcess) {
1599
- await this.killChildProcess();
1600
- }
1601
-
1602
- this.status = {
1603
- state: "error",
1604
- agentName: null,
1605
- port: this.status.port, // preserve port if set
1606
- startedAt: null,
1607
- error: shortError(err),
1608
- };
1609
- this.setStartupPhase("startup_failed", shortError(err));
1610
- this.emitStatus();
1611
- return this.status;
1612
- }
1613
- }
1614
-
1615
- /** Stop the agent runtime. */
1616
- async stop(): Promise<void> {
1617
- if (this.status.state !== "running" && this.status.state !== "starting") {
1618
- return;
1619
- }
1620
-
1621
- diagnosticLog("[Agent] Stopping...");
1622
- this.setStartupPhase("stopping");
1623
-
1624
- // Abort stdio watchers
1625
- if (this.stdioAbortController) {
1626
- this.stdioAbortController.abort();
1627
- this.stdioAbortController = null;
1628
- }
1629
-
1630
- await this.killChildProcess();
1631
-
1632
- this.status = {
1633
- state: "stopped",
1634
- agentName: this.status.agentName,
1635
- port: null,
1636
- startedAt: null,
1637
- error: null,
1638
- };
1639
- this.setStartupPhase("stopped", null);
1640
- this.emitStatus();
1641
- diagnosticLog("[Agent] Runtime stopped");
1642
- }
1643
-
1644
- /**
1645
- * Restart the agent runtime -- stops the current instance and starts a
1646
- * fresh one, picking up config/plugin changes.
1647
- */
1648
- async restart(): Promise<AgentStatus> {
1649
- diagnosticLog("[Agent] Restart requested -- stopping current runtime...");
1650
- this.setStartupPhase("restart_requested");
1651
- await this.stop();
1652
- diagnosticLog("[Agent] Restarting...");
1653
- return this.start();
1654
- }
1655
-
1656
- /**
1657
- * Used after `POST /api/agent/reset`: stop the child, delete local PGLite
1658
- * (conversations / agent memory under `~/.${getBrandConfig().namespace}/workspace/.eliza/.elizadb`),
1659
- * then start fresh. Does not remove downloaded **GGUF** models (`MODELS_DIR`,
1660
- * default ~/.eliza/models), env-backed wallet keys, or eliza.json (the API
1661
- * reset already rewrote config on disk).
1662
- *
1663
- * When `ELIZA_DESKTOP_API_BASE` points at an external dev API (e.g. :31337),
1664
- * the embedded child is never used — this is a no-op so the renderer can
1665
- * bounce the real API via `POST /api/agent/restart` instead.
1666
- */
1667
- async restartClearingLocalDb(): Promise<AgentStatus> {
1668
- const runtimeMode = resolveDesktopRuntimeMode(
1669
- process.env as Record<string, string | undefined>,
1670
- );
1671
- if (runtimeMode.mode !== "local") {
1672
- diagnosticLog(
1673
- `[Agent] restartClearingLocalDb skipped — mode=${runtimeMode.mode} externalBase=${runtimeMode.externalApi.base ?? "n/a"} source=${runtimeMode.externalApi.source ?? "n/a"} (renderer uses POST /api/agent/restart)`,
1674
- );
1675
- return this.getStatus();
1676
- }
1677
-
1678
- diagnosticLog(
1679
- `[Agent] restartClearingLocalDb: local mode — stop → rm PGLite (${resolvePgliteDataDir()}) → start`,
1680
- );
1681
- await this.stop();
1682
- this.hasPgliteError = false;
1683
- this.pgliteRecoveryDone = false;
1684
- deletePgliteDataDir();
1685
- const next = await this.start();
1686
- diagnosticLog(
1687
- `[Agent] restartClearingLocalDb: start() finished state=${next.state} port=${next.port ?? "null"}`,
1688
- );
1689
- return next;
1690
- }
1691
-
1692
- getStatus(): AgentStatus {
1693
- return { ...this.status };
1694
- }
1695
-
1696
- inspectExistingInstall(): ExistingElizaInstallInfo {
1697
- return inspectExistingElizaInstall();
1698
- }
1699
-
1700
- migrateStateDir(params: { fromPath: string }): StateDirMigrationResult {
1701
- return migrateDesktopStateDirFromPath(params.fromPath);
1702
- }
1703
-
1704
- getPort(): number | null {
1705
- return this.status.port;
1706
- }
1707
-
1708
- /** Clean up on app quit. */
1709
- async dispose(): Promise<void> {
1710
- if (this.stdioAbortController) {
1711
- this.stdioAbortController.abort();
1712
- this.stdioAbortController = null;
1713
- }
1714
- try {
1715
- await this.killChildProcess();
1716
- } catch (err) {
1717
- logger.warn(
1718
- `[Agent] dispose error: ${err instanceof Error ? err.message : String(err)}`,
1719
- );
1720
- }
1721
- }
1722
-
1723
- // -----------------------------------------------------------------------
1724
- // Private helpers
1725
- // -----------------------------------------------------------------------
1726
-
1727
- private emitStatus(): void {
1728
- this.persistStartupDiagnostics();
1729
- if (this.sendToWebview) {
1730
- this.sendToWebview("agentStatusUpdate", this.status);
1731
- }
1732
- const statusSnapshot = { ...this.status };
1733
- for (const listener of this.statusListeners) {
1734
- try {
1735
- listener(statusSnapshot);
1736
- } catch (err) {
1737
- logger.warn(
1738
- `[Agent] status listener failed: ${err instanceof Error ? err.message : String(err)}`,
1739
- );
1740
- }
1741
- }
1742
- }
1743
-
1744
- private async refreshAgentMetadata(
1745
- proc: BunSubprocess,
1746
- port: number,
1747
- startupMs: number,
1748
- ): Promise<void> {
1749
- const agentName = await this.fetchAgentName(port);
1750
- if (
1751
- this.childProcess !== proc ||
1752
- this.status.state !== "running" ||
1753
- this.status.port !== port
1754
- ) {
1755
- return;
1756
- }
1757
-
1758
- if (this.status.agentName !== agentName) {
1759
- this.status = {
1760
- ...this.status,
1761
- agentName,
1762
- };
1763
- this.emitStatus();
1764
- }
1765
-
1766
- diagnosticLog(
1767
- `[Agent] Runtime started -- agent: ${agentName}, port: ${port}, pid: ${proc.pid}, startup_ms: ${startupMs}`,
1768
- );
1769
- recordStartupPhase("metadata_ready", {
1770
- port,
1771
- child_pid: proc.pid,
1772
- });
1773
- }
1774
- private setStartupPhase(phase: string, lastError?: string | null): void {
1775
- this.startupPhase = phase;
1776
- this.persistStartupDiagnostics(lastError);
1777
- }
1778
-
1779
- private persistStartupDiagnostics(lastError?: string | null): void {
1780
- writeStartupDiagnosticsSnapshot({
1781
- state: this.status.state,
1782
- phase: this.startupPhase,
1783
- updatedAt: new Date().toISOString(),
1784
- lastError: lastError ?? this.status.error,
1785
- agentName: this.status.agentName,
1786
- port: this.status.port,
1787
- startedAt: this.status.startedAt,
1788
- platform: process.platform,
1789
- arch: process.arch,
1790
- configDir: resolveConfigDir(),
1791
- logPath: getDiagnosticLogPath(),
1792
- statusPath: getStartupStatusPath(),
1793
- });
1794
- }
1795
-
1796
- /**
1797
- * Monitor the child process for unexpected exits and update status.
1798
- */
1799
- private monitorChildExit(proc: BunSubprocess): void {
1800
- // Bun.spawn provides an `exited` promise that resolves when the process exits
1801
- proc.exited
1802
- .then((exitCode: number) => {
1803
- // Only update status if this is still our active child process
1804
- if (this.childProcess !== proc) return;
1805
-
1806
- const wasRunning = this.status.state === "running";
1807
- const wasStarting = this.status.state === "starting";
1808
-
1809
- if (wasRunning || wasStarting) {
1810
- diagnosticLog(
1811
- `[Agent] Child process exited unexpectedly with code ${exitCode} (pid: ${proc.pid})`,
1812
- );
1813
- recordStartupPhase("fatal", {
1814
- port: this.status.port,
1815
- child_pid: proc.pid,
1816
- error: `Process exited unexpectedly with code ${exitCode}`,
1817
- exit_code: exitCode,
1818
- });
1819
- this.childProcess = null;
1820
-
1821
- // Auto-recover from PGLite migration failures by deleting the DB
1822
- // and spawning a fresh process (new process = fresh WASM state).
1823
- if (this.hasPgliteError && !this.pgliteRecoveryDone) {
1824
- this.pgliteRecoveryDone = true;
1825
- diagnosticLog(
1826
- "[Agent] PGLite migration error detected — deleting DB and retrying with fresh process",
1827
- );
1828
- deletePgliteDataDir();
1829
- this.status = {
1830
- state: "not_started",
1831
- agentName: null,
1832
- port: null,
1833
- startedAt: null,
1834
- error: null,
1835
- };
1836
- this.setStartupPhase("recovering_pglite");
1837
- // Delay slightly so OS releases file handles before respawn
1838
- setTimeout(() => void this.start(), 500);
1839
- return;
1840
- }
1841
-
1842
- this.status = {
1843
- state: "error",
1844
- agentName: this.status.agentName,
1845
- port: this.status.port,
1846
- startedAt: null,
1847
- error: `Process exited unexpectedly with code ${exitCode}`,
1848
- };
1849
- this.setStartupPhase(
1850
- "process_exited_unexpectedly",
1851
- `Process exited unexpectedly with code ${exitCode}`,
1852
- );
1853
- this.emitStatus();
1854
- } else {
1855
- // Expected exit (we called stop)
1856
- this.childProcess = null;
1857
- }
1858
- })
1859
- .catch((err: unknown) => {
1860
- if (this.childProcess !== proc) return;
1861
- diagnosticLog(
1862
- `[Agent] Child process exited with error: ${err instanceof Error ? err.message : String(err)}`,
1863
- );
1864
- recordStartupPhase("fatal", {
1865
- port: this.status.port,
1866
- child_pid: proc.pid,
1867
- error: err instanceof Error ? err.message : String(err),
1868
- });
1869
- this.childProcess = null;
1870
- if (
1871
- this.status.state === "running" ||
1872
- this.status.state === "starting"
1873
- ) {
1874
- this.status = {
1875
- state: "error",
1876
- agentName: this.status.agentName,
1877
- port: this.status.port,
1878
- startedAt: null,
1879
- error: shortError(err),
1880
- };
1881
- this.setStartupPhase("process_exit_error", shortError(err));
1882
- this.emitStatus();
1883
- }
1884
- });
1885
- }
1886
-
1887
- /**
1888
- * Kill the child process gracefully with SIGTERM, escalating to SIGKILL
1889
- * after a timeout.
1890
- */
1891
- private async killChildProcess(): Promise<void> {
1892
- const proc = this.childProcess;
1893
- if (!proc) return;
1894
-
1895
- this.childProcess = null;
1896
-
1897
- // Already exited
1898
- if (proc.exitCode !== null) return;
1899
-
1900
- diagnosticLog(`[Agent] Sending SIGTERM to pid ${proc.pid}`);
1901
- proc.kill("SIGTERM");
1902
-
1903
- // Wait for graceful shutdown or timeout
1904
- const exited = await Promise.race([
1905
- proc.exited.then(() => true as const),
1906
- Bun.sleep(SIGTERM_GRACE_MS).then(() => false as const),
1907
- ]);
1908
-
1909
- if (!exited) {
1910
- diagnosticLog(
1911
- `[Agent] Process did not exit within ${SIGTERM_GRACE_MS}ms, sending SIGKILL`,
1912
- );
1913
- try {
1914
- proc.kill("SIGKILL");
1915
- } catch {
1916
- // Process may have already exited between check and kill
1917
- }
1918
- // Wait briefly for SIGKILL to take effect
1919
- await Promise.race([proc.exited.catch(() => {}), Bun.sleep(1_000)]);
1920
- }
1921
-
1922
- diagnosticLog("[Agent] Child process terminated");
1923
- }
1924
-
1925
- /**
1926
- * Attempt to fetch the agent name from the running API server.
1927
- * Falls back to the configured desktop app name if the endpoint is unavailable.
1928
- */
1929
- private async fetchAgentName(port: number): Promise<string> {
1930
- try {
1931
- const headers = getDesktopApiHeaders();
1932
- const response = await fetch(`http://127.0.0.1:${port}/api/agents`, {
1933
- headers,
1934
- signal: AbortSignal.timeout(AGENT_NAME_FETCH_TIMEOUT_MS),
1935
- });
1936
- if (response.ok) {
1937
- const data = (await response.json()) as
1938
- | { agents?: Array<{ name?: string }> }
1939
- | Array<{ name?: string }>;
1940
- const agents = Array.isArray(data) ? data : data.agents;
1941
- if (agents && agents.length > 0 && agents[0].name) {
1942
- return agents[0].name;
1943
- }
1944
- }
1945
- } catch {
1946
- diagnosticLog("[Agent] Could not fetch agent name, using default");
1947
- }
1948
- return getBrandConfig().appName;
1949
- }
1348
+ private sendToWebview: SendToWebview | null = null;
1349
+ private readonly statusListeners = new Set<
1350
+ (status: Readonly<AgentStatus>) => void
1351
+ >();
1352
+ private status: AgentStatus = {
1353
+ state: "not_started",
1354
+ agentName: null,
1355
+ port: null,
1356
+ startedAt: null,
1357
+ error: null,
1358
+ };
1359
+ private childProcess: BunSubprocess | null = null;
1360
+ private stdioAbortController: AbortController | null = null;
1361
+ private hasPgliteError = false;
1362
+ private pgliteRecoveryDone = false;
1363
+ private startupPhase = "not_started";
1364
+ private databaseSnapshot: DatabaseSnapshot = createUnknownDatabaseSnapshot();
1365
+ private databaseStartupLock: DatabaseStartupLock | null = null;
1366
+
1367
+ constructor() {
1368
+ this.persistStartupDiagnostics();
1369
+ }
1370
+
1371
+ setSendToWebview(fn: SendToWebview): void {
1372
+ this.sendToWebview = fn;
1373
+ }
1374
+
1375
+ onStatusChange(
1376
+ listener: (status: Readonly<AgentStatus>) => void,
1377
+ ): () => void {
1378
+ this.statusListeners.add(listener);
1379
+ return () => {
1380
+ this.statusListeners.delete(listener);
1381
+ };
1382
+ }
1383
+
1384
+ /** Start the agent runtime as a child process. Idempotent. */
1385
+ async start(): Promise<AgentStatus> {
1386
+ recordStartupPhase("agent_start_entered", {
1387
+ pid: process.pid,
1388
+ exec_path: process.execPath,
1389
+ bundle_path: resolveStartupBundlePath(process.execPath),
1390
+ });
1391
+ this.setStartupPhase("start_requested");
1392
+ recordStartupPhase("agent_start_entered", {
1393
+ pid: process.pid,
1394
+ exec_path: process.execPath,
1395
+ bundle_path: resolveStartupBundlePath(process.execPath),
1396
+ });
1397
+ diagnosticLog(
1398
+ `[Agent] start() called, current state: ${this.status.state}`,
1399
+ );
1400
+ diagnosticLog(`[Agent] Diagnostic log file: ${getDiagnosticLogPath()}`);
1401
+
1402
+ if (this.status.state === "running" || this.status.state === "starting") {
1403
+ return this.status;
1404
+ }
1405
+
1406
+ const runtimeMode = resolveDesktopRuntimeMode(
1407
+ process.env as Record<string, string | undefined>,
1408
+ );
1409
+ if (runtimeMode.mode !== "local") {
1410
+ const reason =
1411
+ runtimeMode.mode === "external"
1412
+ ? `Embedded desktop runtime is disabled because ${runtimeMode.externalApi.source} points at ${runtimeMode.externalApi.base}.`
1413
+ : "Embedded desktop runtime is disabled by ELIZA_DESKTOP_SKIP_EMBEDDED_AGENT=1.";
1414
+ diagnosticLog(`[Agent] ${reason}`);
1415
+ this.setStartupPhase("startup_disabled", reason);
1416
+ throw new Error(reason);
1417
+ }
1418
+
1419
+ let packagedRuntime: boolean;
1420
+ let apiPort: number;
1421
+ let preferredPort: number;
1422
+ try {
1423
+ configureDesktopLocalApiAuth();
1424
+ packagedRuntime = isPackagedDesktopRuntime();
1425
+
1426
+ // Reset per-startup flags
1427
+ this.pgliteRecoveryDone = false;
1428
+
1429
+ // Clean up any stale process before starting
1430
+ if (this.childProcess) {
1431
+ await this.killChildProcess();
1432
+ }
1433
+
1434
+ preferredPort = resolveDesktopApiPort(process.env) || DEFAULT_API_PORT;
1435
+ diagnosticLog(
1436
+ `[Agent] Preferred port: ${preferredPort} (packaged: ${packagedRuntime})`,
1437
+ );
1438
+ if (!packagedRuntime) {
1439
+ await maybeReclaimPortWithSigkill(preferredPort);
1440
+ }
1441
+ apiPort = await findFirstAvailableLoopbackPort(preferredPort);
1442
+ } catch (err) {
1443
+ const msg =
1444
+ err instanceof Error ? err.message : "Failed during pre-startup";
1445
+ diagnosticLog(`[Agent] ${msg}`);
1446
+ this.status = {
1447
+ state: "error",
1448
+ agentName: null,
1449
+ port: null,
1450
+ startedAt: null,
1451
+ error: msg,
1452
+ };
1453
+ recordStartupPhase("fatal", {
1454
+ port: null,
1455
+ error: msg,
1456
+ });
1457
+ this.setStartupPhase("port_allocation_failed", msg);
1458
+ this.emitStatus();
1459
+ return this.status;
1460
+ }
1461
+ if (apiPort !== preferredPort) {
1462
+ diagnosticLog(
1463
+ `[Agent] Port ${preferredPort} busy — using ${apiPort} for embedded API (set ELIZA_AGENT_RECLAIM_STALE_PORT=1 to try reclaiming the preferred port first)`,
1464
+ );
1465
+ }
1466
+ recordStartupPhase("port_selected", {
1467
+ port: apiPort,
1468
+ });
1469
+
1470
+ this.status = {
1471
+ state: "starting",
1472
+ agentName: null,
1473
+ port: null,
1474
+ startedAt: null,
1475
+ error: null,
1476
+ };
1477
+ this.setStartupPhase("starting_runtime");
1478
+ this.emitStatus();
1479
+
1480
+ try {
1481
+ // Resolve the bundled runtime dist path.
1482
+ this.setStartupPhase("resolving_runtime");
1483
+ const runtimeDistPath = resolveRuntimeDistPath();
1484
+ diagnosticLog(`[Agent] Resolved runtime dist: ${runtimeDistPath}`);
1485
+
1486
+ // Packaged builds can expose the runnable entry either at the dist root
1487
+ // or under runtime/. Prefer the root file but accept both layouts.
1488
+ const runtimeEntryPath = resolveRuntimeEntryPath(runtimeDistPath);
1489
+ if (!runtimeEntryPath) {
1490
+ const distExists = fs.existsSync(runtimeDistPath);
1491
+ let contents = "<directory missing>";
1492
+ if (distExists) {
1493
+ try {
1494
+ contents = fs.readdirSync(runtimeDistPath).join(", ");
1495
+ } catch {
1496
+ contents = "<unreadable>";
1497
+ }
1498
+ }
1499
+ const errMsg = `No runnable runtime entry found in ${runtimeDistPath} (checked entry.js; dist exists: ${distExists}, contents: ${contents})`;
1500
+ diagnosticLog(`[Agent] ${errMsg}`);
1501
+ this.status = {
1502
+ state: "error",
1503
+ agentName: null,
1504
+ port: null,
1505
+ startedAt: null,
1506
+ error: errMsg,
1507
+ };
1508
+ recordStartupPhase("fatal", {
1509
+ port: apiPort,
1510
+ error: errMsg,
1511
+ });
1512
+ this.setStartupPhase("runtime_entry_missing", errMsg);
1513
+ recordStartupPhase("fatal", {
1514
+ port: apiPort,
1515
+ error: errMsg,
1516
+ });
1517
+ this.emitStatus();
1518
+ return this.status;
1519
+ }
1520
+
1521
+ diagnosticLog(`[Agent] runtime entry: exists (${runtimeEntryPath})`);
1522
+ recordStartupPhase("runtime_path_resolved", {
1523
+ port: apiPort,
1524
+ });
1525
+
1526
+ diagnosticLog(`[Agent] Starting child process on port ${apiPort}...`);
1527
+ this.setStartupPhase("spawning_runtime");
1528
+
1529
+ // Build NODE_PATH so the child can find node_modules
1530
+ const nodePaths = buildChildNodePaths(runtimeDistPath, {
1531
+ packagedRuntime,
1532
+ });
1533
+ if (packagedRuntime && nodePaths.length === 0) {
1534
+ const errMsg =
1535
+ `Packaged runtime is missing bundle-local node_modules under ${runtimeDistPath}; ` +
1536
+ "refusing to inherit the parent NODE_PATH";
1537
+ diagnosticLog(`[Agent] ${errMsg}`);
1538
+ this.status = {
1539
+ state: "error",
1540
+ agentName: null,
1541
+ port: apiPort,
1542
+ startedAt: null,
1543
+ error: errMsg,
1544
+ };
1545
+ recordStartupPhase("fatal", {
1546
+ port: apiPort,
1547
+ error: errMsg,
1548
+ });
1549
+ this.emitStatus();
1550
+ return this.status;
1551
+ }
1552
+
1553
+ const childEnv: Record<string, string> = {
1554
+ ...(process.env as Record<string, string>),
1555
+ ELIZA_API_PORT: String(apiPort),
1556
+ ELIZA_PORT: String(apiPort),
1557
+ };
1558
+ childEnv.ELIZA_NAMESPACE = resolveDesktopChildNamespace(childEnv);
1559
+ applyDesktopChildStateEnv(childEnv);
1560
+ delete childEnv.ELIZA_PORT;
1561
+ delete childEnv.NODE_PATH;
1562
+
1563
+ const databaseResolution = resolveDatabaseMode({
1564
+ env: childEnv,
1565
+ packagedDesktop: packagedRuntime,
1566
+ appStateDir: childEnv.ELIZA_STATE_DIR,
1567
+ cwd: runtimeDistPath,
1568
+ });
1569
+ applyDatabaseResolutionToEnv(childEnv, databaseResolution);
1570
+ const effectiveTarget =
1571
+ databaseResolution.mode === "postgres"
1572
+ ? redactDatabaseTarget(databaseResolution.postgresUrl)
1573
+ : (databaseResolution.pgliteDataDir ?? null);
1574
+ this.databaseSnapshot = createDatabaseSnapshot({
1575
+ mode: databaseResolution.mode,
1576
+ status: "resolving",
1577
+ postgresUrlSet: databaseResolution.mode === "postgres",
1578
+ databaseUrlMapped: databaseResolution.databaseUrlMapped,
1579
+ pgliteDataDir: databaseResolution.pgliteDataDir ?? null,
1580
+ effectiveTarget,
1581
+ warnings: databaseResolution.warnings,
1582
+ });
1583
+ this.persistStartupDiagnostics();
1584
+ diagnosticLog(
1585
+ `[Agent] Database mode: ${databaseResolution.mode} source=${databaseResolution.source} target=${effectiveTarget ?? "runtime-default"}`,
1586
+ );
1587
+ recordStartupPhase("database_mode_resolved", {
1588
+ port: apiPort,
1589
+ });
1590
+ if (
1591
+ databaseResolution.mode === "pglite-persistent" &&
1592
+ databaseResolution.pgliteDataDir
1593
+ ) {
1594
+ try {
1595
+ ensurePgliteDataDir(databaseResolution.pgliteDataDir);
1596
+ const lockResult = acquireDatabaseStartupLock(
1597
+ databaseResolution.pgliteDataDir,
1598
+ );
1599
+ if (!lockResult.ok) {
1600
+ const errMsg = lockResult.error;
1601
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
1602
+ this.databaseSnapshot,
1603
+ "locked",
1604
+ {
1605
+ error: errMsg,
1606
+ lock: lockResult.snapshot,
1607
+ },
1608
+ );
1609
+ this.persistStartupDiagnostics(errMsg);
1610
+ this.status = {
1611
+ state: "error",
1612
+ agentName: null,
1613
+ port: apiPort,
1614
+ startedAt: null,
1615
+ error: errMsg,
1616
+ };
1617
+ this.emitStatus();
1618
+ return this.status;
1619
+ }
1620
+ this.databaseStartupLock = lockResult.lock;
1621
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
1622
+ this.databaseSnapshot,
1623
+ "starting",
1624
+ {
1625
+ lock: lockResult.lock.snapshot,
1626
+ },
1627
+ );
1628
+ this.persistStartupDiagnostics();
1629
+ } catch (error) {
1630
+ const message =
1631
+ error instanceof Error ? error.message : String(error);
1632
+ const status = classifyDatabaseError(message);
1633
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
1634
+ this.databaseSnapshot,
1635
+ status,
1636
+ {
1637
+ error: message,
1638
+ },
1639
+ );
1640
+ this.persistStartupDiagnostics(message);
1641
+ this.status = {
1642
+ state: "error",
1643
+ agentName: null,
1644
+ port: apiPort,
1645
+ startedAt: null,
1646
+ error: message,
1647
+ };
1648
+ this.emitStatus();
1649
+ return this.status;
1650
+ }
1651
+ } else if (
1652
+ databaseResolution.mode === "postgres" ||
1653
+ databaseResolution.mode === "pglite-memory"
1654
+ ) {
1655
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
1656
+ this.databaseSnapshot,
1657
+ "starting",
1658
+ );
1659
+ this.persistStartupDiagnostics();
1660
+ }
1661
+
1662
+ applyWindowsNativeInferenceDefaults(childEnv);
1663
+ applyPackagedStartupEmbeddingWarmupPolicy(childEnv, packagedRuntime);
1664
+ applyDesktopDeferAppRoutesPolicy(childEnv);
1665
+
1666
+ if (nodePaths.length > 0) {
1667
+ childEnv.NODE_PATH = nodePaths.join(path.delimiter);
1668
+ diagnosticLog(`[Agent] Child NODE_PATH: ${childEnv.NODE_PATH}`);
1669
+ }
1670
+
1671
+ const bunExecutable = resolveBunExecutablePath();
1672
+ diagnosticLog(`[Agent] Using Bun executable: ${bunExecutable}`);
1673
+ diagnosticLog(
1674
+ `[Agent] Bun exists on disk: ${fs.existsSync(bunExecutable)}`,
1675
+ );
1676
+
1677
+ // Ensure bun's directory is on PATH so child_process.exec calls
1678
+ // (e.g. plugin-manager running `bun add ...`) can find it.
1679
+ const bunDir = path.dirname(bunExecutable);
1680
+ if (prependDesktopChildPathDirectory(childEnv, bunDir)) {
1681
+ diagnosticLog(`[Agent] Prepended bun dir to child PATH: ${bunDir}`);
1682
+ }
1683
+
1684
+ // Spawn the child process
1685
+ const spawnTime = Date.now();
1686
+ const proc = Bun.spawn(
1687
+ [bunExecutable, "run", runtimeEntryPath, "start"],
1688
+ {
1689
+ cwd: runtimeDistPath,
1690
+ env: childEnv,
1691
+ stdout: "pipe",
1692
+ stderr: "pipe",
1693
+ },
1694
+ );
1695
+
1696
+ this.childProcess = proc;
1697
+ diagnosticLog(
1698
+ `[Agent] Child spawned pid=${proc.pid} elapsed=${Date.now() - spawnTime}ms`,
1699
+ );
1700
+ recordStartupPhase("child_spawned", {
1701
+ port: apiPort,
1702
+ child_pid: proc.pid,
1703
+ });
1704
+
1705
+ // Set up abort controller for stdio watchers
1706
+ this.stdioAbortController = new AbortController();
1707
+ const { signal } = this.stdioAbortController;
1708
+
1709
+ // Surface the port immediately while waiting for ready
1710
+ this.status = {
1711
+ ...this.status,
1712
+ port: apiPort,
1713
+ };
1714
+ this.emitStatus();
1715
+
1716
+ // Track whether we detected the "listening" message from stdout
1717
+ let detectedListening = false;
1718
+
1719
+ // Watch stdout for "listening on port" or similar ready messages
1720
+ if (proc.stdout) {
1721
+ watchStdoutForReady(
1722
+ proc.stdout,
1723
+ (line: string) => {
1724
+ diagnosticLog(`[Agent][stdout] ${line}`);
1725
+ const lower = line.toLowerCase();
1726
+ // Parse dynamic port from "[eliza-api] Listening on http://host:PORT"
1727
+ const portMatch = line.match(
1728
+ /Listening on https?:\/\/[^:]+:(\d+)/i,
1729
+ );
1730
+ if (portMatch) {
1731
+ const parsedPort = parseInt(portMatch[1], 10);
1732
+ if (!Number.isNaN(parsedPort) && parsedPort > 0) {
1733
+ if (parsedPort !== apiPort) {
1734
+ diagnosticLog(
1735
+ `[Agent] Server bound to dynamic port ${parsedPort} (requested ${apiPort})`,
1736
+ );
1737
+ apiPort = parsedPort;
1738
+ }
1739
+ detectedListening = true;
1740
+ }
1741
+ } else if (
1742
+ lower.includes("listening on port") ||
1743
+ lower.includes("server started") ||
1744
+ lower.includes("ready on")
1745
+ ) {
1746
+ detectedListening = true;
1747
+ }
1748
+ // Update status port so callers see the actual bound port
1749
+ this.status = { ...this.status, port: apiPort };
1750
+ this.emitStatus();
1751
+ },
1752
+ signal,
1753
+ ).catch(() => {
1754
+ // Stream ended or aborted -- expected on shutdown
1755
+ });
1756
+ }
1757
+
1758
+ // Drain stderr to diagnostic log; detect PGLite migration failures
1759
+ this.hasPgliteError = false;
1760
+ if (proc.stderr) {
1761
+ drainStderrToLog(proc.stderr, signal, (line) => {
1762
+ this.updateDatabaseSnapshotFromRuntimeLog(line);
1763
+ if (shouldAutoRecoverPgliteFailure(line)) {
1764
+ this.hasPgliteError = true;
1765
+ }
1766
+ }).catch(() => {
1767
+ // Stream ended or aborted -- expected on shutdown
1768
+ });
1769
+ }
1770
+
1771
+ // Monitor child process exit
1772
+ this.monitorChildExit(proc);
1773
+
1774
+ // Wait for the health endpoint to respond
1775
+ // Use a getter so the health check follows dynamic port reassignment from stdout
1776
+ diagnosticLog(
1777
+ `[Agent] Waiting for health endpoint at http://127.0.0.1:${apiPort}/api/health ...`,
1778
+ );
1779
+ this.setStartupPhase("waiting_for_health");
1780
+ const healthPollTimeoutMs = getHealthPollTimeoutMs();
1781
+ const healthy = await waitForHealthy(
1782
+ () => apiPort,
1783
+ healthPollTimeoutMs,
1784
+ proc,
1785
+ );
1786
+
1787
+ if (!healthy) {
1788
+ // Check if process already exited
1789
+ if (proc.exitCode !== null) {
1790
+ const errMsg = `Child process exited with code ${proc.exitCode} before becoming healthy`;
1791
+ diagnosticLog(`[Agent] ${errMsg}`);
1792
+ this.childProcess = null;
1793
+ this.status = {
1794
+ state: "error",
1795
+ agentName: null,
1796
+ port: apiPort,
1797
+ startedAt: null,
1798
+ error: errMsg,
1799
+ };
1800
+ recordStartupPhase("fatal", {
1801
+ port: apiPort,
1802
+ child_pid: proc.pid,
1803
+ error: errMsg,
1804
+ exit_code: proc.exitCode,
1805
+ });
1806
+ this.setStartupPhase("startup_failed", errMsg);
1807
+ recordStartupPhase("fatal", {
1808
+ port: apiPort,
1809
+ child_pid: proc.pid,
1810
+ error: errMsg,
1811
+ exit_code: proc.exitCode,
1812
+ });
1813
+ this.releaseDatabaseStartupLock();
1814
+ this.emitStatus();
1815
+ return this.status;
1816
+ }
1817
+
1818
+ const errMsg = detectedListening
1819
+ ? "Server reported listening but health check timed out"
1820
+ : `Health check timed out after ${healthPollTimeoutMs}ms`;
1821
+ diagnosticLog(`[Agent] ${errMsg}`);
1822
+ this.status = {
1823
+ state: "error",
1824
+ agentName: null,
1825
+ port: apiPort,
1826
+ startedAt: null,
1827
+ error: errMsg,
1828
+ };
1829
+ recordStartupPhase("fatal", {
1830
+ port: apiPort,
1831
+ child_pid: proc.pid,
1832
+ error: errMsg,
1833
+ });
1834
+ this.setStartupPhase("startup_failed", errMsg);
1835
+ recordStartupPhase("fatal", {
1836
+ port: apiPort,
1837
+ child_pid: proc.pid,
1838
+ error: errMsg,
1839
+ });
1840
+ this.releaseDatabaseStartupLock();
1841
+ this.emitStatus();
1842
+ return this.status;
1843
+ }
1844
+ recordStartupPhase("health_ready", {
1845
+ port: apiPort,
1846
+ child_pid: proc.pid,
1847
+ });
1848
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
1849
+ this.databaseSnapshot,
1850
+ "ready",
1851
+ {
1852
+ migrationStatus:
1853
+ this.databaseSnapshot.migrationStatus?.failed === true
1854
+ ? this.databaseSnapshot.migrationStatus
1855
+ : {
1856
+ running: false,
1857
+ completed: true,
1858
+ failed: false,
1859
+ },
1860
+ lock: {
1861
+ held: false,
1862
+ },
1863
+ },
1864
+ );
1865
+ this.releaseDatabaseStartupLock();
1866
+
1867
+ this.setStartupPhase("fetching_agent_metadata");
1868
+ const startedAt = Date.now();
1869
+ const startupMs = startedAt - spawnTime;
1870
+
1871
+ this.status = {
1872
+ state: "running",
1873
+ agentName: getBrandConfig().appName,
1874
+ port: apiPort,
1875
+ startedAt,
1876
+ error: null,
1877
+ };
1878
+ this.setStartupPhase("ready", null);
1879
+ this.emitStatus();
1880
+ diagnosticLog(
1881
+ `[Agent] Runtime ready -- port: ${apiPort}, pid: ${proc.pid}, startup_ms: ${startupMs}`,
1882
+ );
1883
+ recordStartupPhase("runtime_ready", {
1884
+ port: apiPort,
1885
+ child_pid: proc.pid,
1886
+ });
1887
+ void this.refreshAgentMetadata(proc, apiPort, startupMs);
1888
+ return this.status;
1889
+ } catch (err) {
1890
+ const errMsg =
1891
+ err instanceof Error ? err.stack || err.message : String(err);
1892
+ diagnosticLog(`[Agent] Failed to start: ${errMsg}`);
1893
+ recordStartupPhase("fatal", {
1894
+ port: this.status.port,
1895
+ error: errMsg,
1896
+ });
1897
+
1898
+ // Clean up child if it was spawned
1899
+ if (this.childProcess) {
1900
+ await this.killChildProcess();
1901
+ }
1902
+ this.releaseDatabaseStartupLock();
1903
+
1904
+ this.status = {
1905
+ state: "error",
1906
+ agentName: null,
1907
+ port: this.status.port, // preserve port if set
1908
+ startedAt: null,
1909
+ error: shortError(err),
1910
+ };
1911
+ this.setStartupPhase("startup_failed", shortError(err));
1912
+ this.emitStatus();
1913
+ return this.status;
1914
+ }
1915
+ }
1916
+
1917
+ /** Stop the agent runtime. */
1918
+ async stop(): Promise<void> {
1919
+ if (this.status.state !== "running" && this.status.state !== "starting") {
1920
+ return;
1921
+ }
1922
+
1923
+ diagnosticLog("[Agent] Stopping...");
1924
+ this.setStartupPhase("stopping");
1925
+
1926
+ // Abort stdio watchers
1927
+ if (this.stdioAbortController) {
1928
+ this.stdioAbortController.abort();
1929
+ this.stdioAbortController = null;
1930
+ }
1931
+
1932
+ await this.killChildProcess();
1933
+ this.releaseDatabaseStartupLock();
1934
+
1935
+ this.status = {
1936
+ state: "stopped",
1937
+ agentName: this.status.agentName,
1938
+ port: null,
1939
+ startedAt: null,
1940
+ error: null,
1941
+ };
1942
+ this.setStartupPhase("stopped", null);
1943
+ this.emitStatus();
1944
+ diagnosticLog("[Agent] Runtime stopped");
1945
+ }
1946
+
1947
+ /**
1948
+ * Restart the agent runtime -- stops the current instance and starts a
1949
+ * fresh one, picking up config/plugin changes.
1950
+ */
1951
+ async restart(): Promise<AgentStatus> {
1952
+ diagnosticLog("[Agent] Restart requested -- stopping current runtime...");
1953
+ this.setStartupPhase("restart_requested");
1954
+ await this.stop();
1955
+ diagnosticLog("[Agent] Restarting...");
1956
+ return this.start();
1957
+ }
1958
+
1959
+ /**
1960
+ * Used after `POST /api/agent/reset`: stop the child, delete local PGLite
1961
+ * (conversations / agent memory under the active state-dir workspace),
1962
+ * then start fresh. Does not remove downloaded **GGUF** models (`MODELS_DIR`,
1963
+ * env-backed wallet keys, or eliza.json (the API reset already rewrote
1964
+ * config on disk).
1965
+ *
1966
+ * When `ELIZA_DESKTOP_API_BASE` points at an external dev API (e.g. :31337),
1967
+ * the embedded child is never used — this is a no-op so the renderer can
1968
+ * bounce the real API via `POST /api/agent/restart` instead.
1969
+ */
1970
+ async restartClearingLocalDb(): Promise<AgentStatus> {
1971
+ const runtimeMode = resolveDesktopRuntimeMode(
1972
+ process.env as Record<string, string | undefined>,
1973
+ );
1974
+ if (runtimeMode.mode !== "local") {
1975
+ diagnosticLog(
1976
+ `[Agent] restartClearingLocalDb skipped — mode=${runtimeMode.mode} externalBase=${runtimeMode.externalApi.base ?? "n/a"} source=${runtimeMode.externalApi.source ?? "n/a"} (renderer uses POST /api/agent/restart)`,
1977
+ );
1978
+ return this.getStatus();
1979
+ }
1980
+
1981
+ const dataDir = resolveManagedPgliteDataDir();
1982
+ if (!dataDir) {
1983
+ const message =
1984
+ "Local PGlite reset is unavailable for the active database mode.";
1985
+ diagnosticLog(`[Agent] restartClearingLocalDb skipped — ${message}`);
1986
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
1987
+ this.databaseSnapshot,
1988
+ "error",
1989
+ { error: message },
1990
+ );
1991
+ return this.getStatus();
1992
+ }
1993
+
1994
+ diagnosticLog(
1995
+ `[Agent] restartClearingLocalDb: local mode stop backup/reset PGLite (${dataDir}) start`,
1996
+ );
1997
+ await this.stop();
1998
+ this.hasPgliteError = false;
1999
+ this.pgliteRecoveryDone = false;
2000
+ const reset = resetPgliteDirectory(dataDir);
2001
+ diagnosticLog(
2002
+ `[Agent] PGLite backup/reset completed backup=${reset.backup.backupDir ?? "none"} removed=${reset.removed}`,
2003
+ );
2004
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
2005
+ this.databaseSnapshot,
2006
+ "starting",
2007
+ { error: null },
2008
+ );
2009
+ const next = await this.start();
2010
+ diagnosticLog(
2011
+ `[Agent] restartClearingLocalDb: start() finished state=${next.state} port=${next.port ?? "null"}`,
2012
+ );
2013
+ return next;
2014
+ }
2015
+
2016
+ getStatus(): AgentStatus {
2017
+ return { ...this.status };
2018
+ }
2019
+
2020
+ getDatabaseSnapshot(): DatabaseSnapshot {
2021
+ return this.databaseSnapshot;
2022
+ }
2023
+
2024
+ previewDatabaseRecovery(): {
2025
+ snapshot: DatabaseSnapshot;
2026
+ actions: DatabaseSnapshot["recoveryActions"];
2027
+ } {
2028
+ return {
2029
+ snapshot: this.databaseSnapshot,
2030
+ actions: this.databaseSnapshot.recoveryActions,
2031
+ };
2032
+ }
2033
+
2034
+ backupPgliteDatabase(): ReturnType<typeof backupPgliteDirectory> {
2035
+ const dataDir =
2036
+ this.databaseSnapshot.pgliteDataDir ?? resolveManagedPgliteDataDir();
2037
+ if (!dataDir) {
2038
+ throw new Error("No persistent PGlite data directory is active.");
2039
+ }
2040
+ const result = backupPgliteDirectory(dataDir);
2041
+ diagnosticLog(
2042
+ `[Agent] PGLite backup created: ${result.backupDir ?? "none"} reason=${result.reason ?? "created"}`,
2043
+ );
2044
+ return result;
2045
+ }
2046
+
2047
+ async resetPgliteDatabase(params?: {
2048
+ restart?: boolean;
2049
+ }): Promise<
2050
+ ReturnType<typeof resetPgliteDirectory> & { restarted: boolean }
2051
+ > {
2052
+ const dataDir =
2053
+ this.databaseSnapshot.pgliteDataDir ?? resolveManagedPgliteDataDir();
2054
+ if (!dataDir) {
2055
+ throw new Error("No persistent PGlite data directory is active.");
2056
+ }
2057
+ await this.stop();
2058
+ const result = resetPgliteDirectory(dataDir);
2059
+ diagnosticLog(
2060
+ `[Agent] PGLite reset completed backup=${result.backup.backupDir ?? "none"} removed=${result.removed}`,
2061
+ );
2062
+ if (params?.restart === true) {
2063
+ await this.start();
2064
+ return { ...result, restarted: true };
2065
+ }
2066
+ return { ...result, restarted: false };
2067
+ }
2068
+
2069
+ inspectExistingInstall(): ExistingElizaInstallInfo {
2070
+ return inspectExistingElizaInstall();
2071
+ }
2072
+
2073
+ migrateStateDir(params: { fromPath: string }): StateDirMigrationResult {
2074
+ return migrateDesktopStateDirFromPath(params.fromPath);
2075
+ }
2076
+
2077
+ getPort(): number | null {
2078
+ return this.status.port;
2079
+ }
2080
+
2081
+ /** Clean up on app quit. */
2082
+ async dispose(): Promise<void> {
2083
+ if (this.stdioAbortController) {
2084
+ this.stdioAbortController.abort();
2085
+ this.stdioAbortController = null;
2086
+ }
2087
+ try {
2088
+ await this.killChildProcess();
2089
+ this.releaseDatabaseStartupLock();
2090
+ } catch (err) {
2091
+ logger.warn(
2092
+ `[Agent] dispose error: ${err instanceof Error ? err.message : String(err)}`,
2093
+ );
2094
+ }
2095
+ }
2096
+
2097
+ // -----------------------------------------------------------------------
2098
+ // Private helpers
2099
+ // -----------------------------------------------------------------------
2100
+
2101
+ private emitStatus(): void {
2102
+ this.persistStartupDiagnostics();
2103
+ if (this.sendToWebview) {
2104
+ this.sendToWebview("agentStatusUpdate", this.status);
2105
+ }
2106
+ const statusSnapshot = { ...this.status };
2107
+ for (const listener of this.statusListeners) {
2108
+ try {
2109
+ listener(statusSnapshot);
2110
+ } catch (err) {
2111
+ logger.warn(
2112
+ `[Agent] status listener failed: ${err instanceof Error ? err.message : String(err)}`,
2113
+ );
2114
+ }
2115
+ }
2116
+ }
2117
+
2118
+ private async refreshAgentMetadata(
2119
+ proc: BunSubprocess,
2120
+ port: number,
2121
+ startupMs: number,
2122
+ ): Promise<void> {
2123
+ const agentName = await this.fetchAgentName(port);
2124
+ if (
2125
+ this.childProcess !== proc ||
2126
+ this.status.state !== "running" ||
2127
+ this.status.port !== port
2128
+ ) {
2129
+ return;
2130
+ }
2131
+
2132
+ if (this.status.agentName !== agentName) {
2133
+ this.status = {
2134
+ ...this.status,
2135
+ agentName,
2136
+ };
2137
+ this.emitStatus();
2138
+ }
2139
+
2140
+ diagnosticLog(
2141
+ `[Agent] Runtime started -- agent: ${agentName}, port: ${port}, pid: ${proc.pid}, startup_ms: ${startupMs}`,
2142
+ );
2143
+ recordStartupPhase("metadata_ready", {
2144
+ port,
2145
+ child_pid: proc.pid,
2146
+ });
2147
+ }
2148
+ private setStartupPhase(phase: string, lastError?: string | null): void {
2149
+ this.startupPhase = phase;
2150
+ this.persistStartupDiagnostics(lastError);
2151
+ }
2152
+
2153
+ private persistStartupDiagnostics(lastError?: string | null): void {
2154
+ writeStartupDiagnosticsSnapshot({
2155
+ state: this.status.state,
2156
+ phase: this.startupPhase,
2157
+ updatedAt: new Date().toISOString(),
2158
+ lastError: lastError ?? this.status.error,
2159
+ agentName: this.status.agentName,
2160
+ port: this.status.port,
2161
+ startedAt: this.status.startedAt,
2162
+ platform: process.platform,
2163
+ arch: process.arch,
2164
+ configDir: resolveConfigDir(),
2165
+ logPath: getDiagnosticLogPath(),
2166
+ statusPath: getStartupStatusPath(),
2167
+ database: this.databaseSnapshot,
2168
+ });
2169
+ }
2170
+
2171
+ private releaseDatabaseStartupLock(): void {
2172
+ if (!this.databaseStartupLock) return;
2173
+ this.databaseStartupLock.release();
2174
+ this.databaseStartupLock = null;
2175
+ }
2176
+
2177
+ private updateDatabaseSnapshotFromRuntimeLog(line: string): void {
2178
+ const lower = line.toLowerCase();
2179
+ if (lower.includes("starting migrations")) {
2180
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
2181
+ this.databaseSnapshot,
2182
+ "migrating",
2183
+ {
2184
+ migrationStatus: {
2185
+ running: true,
2186
+ completed: false,
2187
+ failed: false,
2188
+ },
2189
+ },
2190
+ );
2191
+ this.persistStartupDiagnostics();
2192
+ recordStartupPhase("database_migration_started", {
2193
+ port: this.status.port,
2194
+ });
2195
+ return;
2196
+ }
2197
+ if (lower.includes("all migrations completed successfully")) {
2198
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
2199
+ this.databaseSnapshot,
2200
+ "starting",
2201
+ {
2202
+ migrationStatus: {
2203
+ running: false,
2204
+ completed: true,
2205
+ failed: false,
2206
+ },
2207
+ },
2208
+ );
2209
+ this.persistStartupDiagnostics();
2210
+ recordStartupPhase("database_migration_completed", {
2211
+ port: this.status.port,
2212
+ });
2213
+ return;
2214
+ }
2215
+ if (
2216
+ lower.includes("migration failed") ||
2217
+ lower.includes("migration(s) failed")
2218
+ ) {
2219
+ const pluginMatch = line.match(/pluginName[":=\s]+["']?([^"',\s}]+)/);
2220
+ const error = redactSensitiveDiagnostics(line);
2221
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
2222
+ this.databaseSnapshot,
2223
+ "migration-failed",
2224
+ {
2225
+ error,
2226
+ migrationStatus: {
2227
+ running: false,
2228
+ completed: false,
2229
+ failed: true,
2230
+ failedPlugin: pluginMatch?.[1],
2231
+ error,
2232
+ },
2233
+ },
2234
+ );
2235
+ this.persistStartupDiagnostics(error);
2236
+ recordStartupPhase("database_migration_failed", {
2237
+ port: this.status.port,
2238
+ error,
2239
+ });
2240
+ return;
2241
+ }
2242
+ const status = classifyDatabaseError(line);
2243
+ if (status === "error") return;
2244
+ const error = redactSensitiveDiagnostics(line);
2245
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
2246
+ this.databaseSnapshot,
2247
+ status,
2248
+ { error },
2249
+ );
2250
+ this.persistStartupDiagnostics(error);
2251
+ }
2252
+
2253
+ /**
2254
+ * Monitor the child process for unexpected exits and update status.
2255
+ */
2256
+ private monitorChildExit(proc: BunSubprocess): void {
2257
+ // Bun.spawn provides an `exited` promise that resolves when the process exits
2258
+ proc.exited
2259
+ .then((exitCode: number) => {
2260
+ // Only update status if this is still our active child process
2261
+ if (this.childProcess !== proc) return;
2262
+
2263
+ const wasRunning = this.status.state === "running";
2264
+ const wasStarting = this.status.state === "starting";
2265
+
2266
+ if (wasRunning || wasStarting) {
2267
+ diagnosticLog(
2268
+ `[Agent] Child process exited unexpectedly with code ${exitCode} (pid: ${proc.pid})`,
2269
+ );
2270
+ recordStartupPhase("fatal", {
2271
+ port: this.status.port,
2272
+ child_pid: proc.pid,
2273
+ error: `Process exited unexpectedly with code ${exitCode}`,
2274
+ exit_code: exitCode,
2275
+ });
2276
+ this.childProcess = null;
2277
+
2278
+ if (this.hasPgliteError && !this.pgliteRecoveryDone) {
2279
+ this.pgliteRecoveryDone = true;
2280
+ const error =
2281
+ "PGLite startup or migration failed. Use database recovery to backup/reset local data or switch to Postgres.";
2282
+ diagnosticLog(`[Agent] ${error}`);
2283
+ this.databaseSnapshot = updateDatabaseSnapshotStatus(
2284
+ this.databaseSnapshot,
2285
+ classifyDatabaseError(error),
2286
+ { error },
2287
+ );
2288
+ }
2289
+
2290
+ this.status = {
2291
+ state: "error",
2292
+ agentName: this.status.agentName,
2293
+ port: this.status.port,
2294
+ startedAt: null,
2295
+ error: `Process exited unexpectedly with code ${exitCode}`,
2296
+ };
2297
+ this.setStartupPhase(
2298
+ "process_exited_unexpectedly",
2299
+ `Process exited unexpectedly with code ${exitCode}`,
2300
+ );
2301
+ this.releaseDatabaseStartupLock();
2302
+ this.emitStatus();
2303
+ } else {
2304
+ // Expected exit (we called stop)
2305
+ this.childProcess = null;
2306
+ this.releaseDatabaseStartupLock();
2307
+ }
2308
+ })
2309
+ .catch((err: unknown) => {
2310
+ if (this.childProcess !== proc) return;
2311
+ diagnosticLog(
2312
+ `[Agent] Child process exited with error: ${err instanceof Error ? err.message : String(err)}`,
2313
+ );
2314
+ recordStartupPhase("fatal", {
2315
+ port: this.status.port,
2316
+ child_pid: proc.pid,
2317
+ error: err instanceof Error ? err.message : String(err),
2318
+ });
2319
+ this.childProcess = null;
2320
+ this.releaseDatabaseStartupLock();
2321
+ if (
2322
+ this.status.state === "running" ||
2323
+ this.status.state === "starting"
2324
+ ) {
2325
+ this.status = {
2326
+ state: "error",
2327
+ agentName: this.status.agentName,
2328
+ port: this.status.port,
2329
+ startedAt: null,
2330
+ error: shortError(err),
2331
+ };
2332
+ this.setStartupPhase("process_exit_error", shortError(err));
2333
+ this.emitStatus();
2334
+ }
2335
+ });
2336
+ }
2337
+
2338
+ /**
2339
+ * Kill the child process gracefully with SIGTERM, escalating to SIGKILL
2340
+ * after a timeout.
2341
+ */
2342
+ private async killChildProcess(): Promise<void> {
2343
+ const proc = this.childProcess;
2344
+ if (!proc) return;
2345
+
2346
+ this.childProcess = null;
2347
+
2348
+ // Already exited
2349
+ if (proc.exitCode !== null) return;
2350
+
2351
+ diagnosticLog(`[Agent] Sending SIGTERM to pid ${proc.pid}`);
2352
+ proc.kill("SIGTERM");
2353
+
2354
+ // Wait for graceful shutdown or timeout
2355
+ const exited = await Promise.race([
2356
+ proc.exited.then(() => true as const),
2357
+ Bun.sleep(SIGTERM_GRACE_MS).then(() => false as const),
2358
+ ]);
2359
+
2360
+ if (!exited) {
2361
+ diagnosticLog(
2362
+ `[Agent] Process did not exit within ${SIGTERM_GRACE_MS}ms, sending SIGKILL`,
2363
+ );
2364
+ try {
2365
+ proc.kill("SIGKILL");
2366
+ } catch {
2367
+ // Process may have already exited between check and kill
2368
+ }
2369
+ // Wait briefly for SIGKILL to take effect
2370
+ await Promise.race([proc.exited.catch(() => {}), Bun.sleep(1_000)]);
2371
+ }
2372
+
2373
+ diagnosticLog("[Agent] Child process terminated");
2374
+ }
2375
+
2376
+ /**
2377
+ * Attempt to fetch the agent name from the running API server.
2378
+ * Falls back to the configured desktop app name if the endpoint is unavailable.
2379
+ */
2380
+ private async fetchAgentName(port: number): Promise<string> {
2381
+ try {
2382
+ const headers = getDesktopApiHeaders();
2383
+ const response = await fetch(`http://127.0.0.1:${port}/api/agents`, {
2384
+ headers,
2385
+ signal: AbortSignal.timeout(AGENT_NAME_FETCH_TIMEOUT_MS),
2386
+ });
2387
+ if (response.ok) {
2388
+ const data = (await response.json()) as
2389
+ | { agents?: Array<{ name?: string }> }
2390
+ | Array<{ name?: string }>;
2391
+ const agents = Array.isArray(data) ? data : data.agents;
2392
+ if (agents && agents.length > 0 && agents[0].name) {
2393
+ return agents[0].name;
2394
+ }
2395
+ }
2396
+ } catch {
2397
+ diagnosticLog("[Agent] Could not fetch agent name, using default");
2398
+ }
2399
+ return getBrandConfig().appName;
2400
+ }
1950
2401
  }
1951
2402
 
1952
2403
  // ---------------------------------------------------------------------------
@@ -1956,8 +2407,8 @@ export class AgentManager {
1956
2407
  let agentManager: AgentManager | null = null;
1957
2408
 
1958
2409
  export function getAgentManager(): AgentManager {
1959
- if (!agentManager) {
1960
- agentManager = new AgentManager();
1961
- }
1962
- return agentManager;
2410
+ if (!agentManager) {
2411
+ agentManager = new AgentManager();
2412
+ }
2413
+ return agentManager;
1963
2414
  }