@elizaos/app-core 2.0.3-beta.4 → 2.0.3-beta.6

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 (97) hide show
  1. package/api/i18n-locale-routes.d.ts +7 -0
  2. package/api/i18n-locale-routes.d.ts.map +1 -0
  3. package/api/i18n-locale-routes.js +58 -0
  4. package/api/ios-local-agent-transport.d.ts +3 -0
  5. package/api/ios-local-agent-transport.d.ts.map +1 -1
  6. package/api/ios-local-agent-transport.js +22 -1
  7. package/api/server.d.ts.map +1 -1
  8. package/api/server.js +5 -0
  9. package/benchmark/cerebras-autowire.d.ts.map +1 -1
  10. package/benchmark/cerebras-autowire.js +9 -2
  11. package/package.json +36 -36
  12. package/packaging/debian/rules +1 -1
  13. package/packaging/flatpak/generate-sources.sh +6 -1
  14. package/packaging/snap/snapcraft.yaml +15 -11
  15. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaAgentService.java +2 -1
  16. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaNativeBridge.java +5 -0
  17. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaStartupTrace.java +28 -0
  18. package/platforms/android/app/src/main/java/ai/elizaos/app/ElizaVoicePlugin.java +1 -1
  19. package/platforms/android/app/src/main/java/ai/elizaos/app/MainActivity.java +1 -0
  20. package/platforms/electrobun/electrobun.config.ts +31 -1
  21. package/platforms/electrobun/package.json +10 -10
  22. package/platforms/electrobun/remotes/local-model/README.md +2 -5
  23. package/platforms/electrobun/remotes/local-model/src/bun/eliza1-catalog.ts +0 -16
  24. package/platforms/electrobun/remotes/local-model/src/dev/phase8-smoke.ts +0 -2
  25. package/platforms/electrobun/scripts/smoke-test.sh +8 -2
  26. package/platforms/electrobun/scripts/stage-macos-release-artifacts.sh +8 -2
  27. package/platforms/electrobun/scripts/sync-web-assets.mjs +31 -2
  28. package/platforms/electrobun/src/bridge/electrobun-boot-config.ts +8 -0
  29. package/platforms/electrobun/src/bridge/electrobun-crypto-ready.ts +5 -1
  30. package/platforms/electrobun/src/bridge/electrobun-direct-rpc.ts +5 -11
  31. package/platforms/electrobun/src/preload.js +1 -1
  32. package/platforms/ios/App/App/Base.lproj/Main.storyboard +1 -1
  33. package/platforms/ios/App/App/ElizaBridgeViewController.swift +22 -0
  34. package/platforms/ios/App/App/ElizaStartupTrace.swift +12 -0
  35. package/platforms/ios/App/App.xcodeproj/project.pbxproj +8 -0
  36. package/runtime/eliza.d.ts.map +1 -1
  37. package/runtime/eliza.js +18 -0
  38. package/runtime/voice-warmup.d.ts +4 -4
  39. package/runtime/voice-warmup.d.ts.map +1 -1
  40. package/runtime/voice-warmup.js +4 -4
  41. package/scripts/aosp/compile-libllama.mjs +25 -5
  42. package/scripts/aosp/compile-libllama.test.mjs +17 -1
  43. package/scripts/assert-required-bundled-packages.test.ts +24 -2
  44. package/scripts/benchmark-preflight.mjs +31 -2
  45. package/scripts/build-bundled-agent-skills-artifact.mjs +32 -8
  46. package/scripts/build-bundled-orchestrator-artifact.mjs +34 -12
  47. package/scripts/build-llama-cpp-mtp.mjs +27 -3
  48. package/scripts/build-patched-electrobun-cli.mjs +30 -2
  49. package/scripts/bun-riscv64/bun-version.json +1 -1
  50. package/scripts/bun-riscv64/validate.sh +21 -8
  51. package/scripts/check-real-local-reset.ts +13 -1
  52. package/scripts/check-sms-gateway-completion-audit.mjs +96 -31
  53. package/scripts/check-sms-gateway-readiness.mjs +54 -17
  54. package/scripts/clean-repo.mjs +21 -3
  55. package/scripts/copy-runtime-node-modules.ts +68 -63
  56. package/scripts/desktop-build.mjs +46 -5
  57. package/scripts/dev-platform-no-install.test.mjs +19 -0
  58. package/scripts/dev-platform.mjs +6 -2
  59. package/scripts/disable-local-eliza-workspace.mjs +23 -1
  60. package/scripts/docker-ci-smoke.sh +6 -5
  61. package/scripts/ensure-avatars.mjs +18 -5
  62. package/scripts/ensure-bundled-workspaces.mjs +4 -15
  63. package/scripts/ensure-type-package-aliases.mjs +47 -3
  64. package/scripts/ffi-stub/Makefile +5 -2
  65. package/scripts/ios-xcframework/build-xcframework.mjs +22 -11
  66. package/scripts/ios-xcframework/run-physical-device-smoke.mjs +99 -6
  67. package/scripts/ios-xcframework/runtime-symbol-shim.c +560 -105
  68. package/scripts/lib/agent-source-watcher.test.mjs +24 -4
  69. package/scripts/lib/apple-entitlement-audit.test.mjs +19 -2
  70. package/scripts/lib/artifact-staleness.test.mts +18 -1
  71. package/scripts/lib/patch-bun-exports.mjs +20 -2
  72. package/scripts/lib/patch-bun-exports.test.mjs +108 -4
  73. package/scripts/lib/renderer-build-manifest.test.mts +18 -1
  74. package/scripts/lib/stage-android-agent.mjs +16 -3
  75. package/scripts/lib/verify-ondevice-artifact.test.mts +18 -1
  76. package/scripts/link-docker-local-app-packages.mjs +26 -1
  77. package/scripts/mas-smoke.test.mjs +25 -9
  78. package/scripts/omnivoice-fuse/prepare.mjs +27 -4
  79. package/scripts/package-electrobun-linux.mjs +22 -7
  80. package/scripts/patch-deps.mjs +18 -5
  81. package/scripts/playwright-ui-live-stack.ts +16 -3
  82. package/scripts/playwright-ui-smoke-api-stub.mjs +167 -2
  83. package/scripts/prepare-ios-cocoapods.sh +5 -1
  84. package/scripts/prune-cdn-local-assets.mjs +52 -5
  85. package/scripts/run-mobile-build-android-app-actions.test.mjs +19 -1
  86. package/scripts/run-mobile-build-mtp-staleness.test.mts +20 -4
  87. package/scripts/run-mobile-build.mjs +74 -16
  88. package/scripts/stage-android-agent.test.mjs +19 -1
  89. package/scripts/stage-desktop-fused-lib.mjs +26 -1
  90. package/scripts/sync-desktop-renderer.mjs +53 -12
  91. package/scripts/test-sms-gateway-software.mjs +20 -4
  92. package/cli/command-format.d.ts +0 -2
  93. package/cli/command-format.d.ts.map +0 -1
  94. package/cli/command-format.js +0 -20
  95. package/register-runtime-hooks.d.ts +0 -2
  96. package/register-runtime-hooks.d.ts.map +0 -1
  97. package/register-runtime-hooks.js +0 -19
@@ -74,6 +74,12 @@ if ! has_electrobun_workspace_root "$REPO_ROOT"; then
74
74
  echo "ERROR: ELIZA_ELECTROBUN_REPO_ROOT is not an Electrobun workspace root: $REPO_ROOT" >&2
75
75
  exit 1
76
76
  fi
77
+ RM_PATH_RECURSIVE="$REPO_ROOT/packages/scripts/rm-path-recursive.mjs"
78
+
79
+ remove_path_recursive() {
80
+ node "$RM_PATH_RECURSIVE" "$@"
81
+ }
82
+
77
83
  APP_DIR="${ELIZA_ELECTROBUN_APP_DIR:-}"
78
84
  if [[ -z "$APP_DIR" ]]; then
79
85
  if [[ -f "$REPO_ROOT/packages/app/package.json" ]]; then
@@ -163,7 +169,7 @@ cleanup() {
163
169
  fi
164
170
  done
165
171
  if [[ -n "$LAUNCH_APP_BUNDLE" && "$LAUNCH_APP_BUNDLE" == /tmp/* && -d "$LAUNCH_APP_BUNDLE" ]]; then
166
- rm -rf "$LAUNCH_APP_BUNDLE"
172
+ remove_path_recursive "$LAUNCH_APP_BUNDLE"
167
173
  fi
168
174
  if [[ -n "$MOUNT_POINT" && -d "$MOUNT_POINT" ]]; then
169
175
  hdiutil detach "$MOUNT_POINT" >/dev/null 2>&1 || true
@@ -619,7 +625,7 @@ EOF
619
625
  process.stdout.write("1");
620
626
  ' "$probe_exec"
621
627
  )"
622
- rm -rf "$probe_root"
628
+ remove_path_recursive "$probe_root"
623
629
 
624
630
  [[ "$MAC_DIRECT_EXEC_PROBE_RC" == "0" ]]
625
631
  }
@@ -3,6 +3,8 @@
3
3
  set -euo pipefail
4
4
 
5
5
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || (cd "$SCRIPT_DIR/../../../../.." && pwd))"
7
+ RM_PATH_RECURSIVE="$REPO_ROOT/packages/scripts/rm-path-recursive.mjs"
6
8
  ARTIFACTS_DIR="${1:-$(cd "$SCRIPT_DIR/.." && pwd)/artifacts}"
7
9
  SKIP_SIGNATURE_CHECK="${ELECTROBUN_SKIP_CODESIGN:-0}"
8
10
  REAL_XCRUN="${ELECTROBUN_REAL_XCRUN:-/usr/bin/xcrun}"
@@ -23,9 +25,13 @@ EXTRACT_DIR="$TMP_ROOT/extracted"
23
25
  DMG_STAGING_DIR="$TMP_ROOT/dmg-staging"
24
26
  TEMP_DMG_PATH=""
25
27
 
28
+ remove_path_recursive() {
29
+ node "$RM_PATH_RECURSIVE" "$@"
30
+ }
31
+
26
32
  cleanup() {
27
33
  if [[ -n "$TMP_ROOT" && -d "$TMP_ROOT" ]]; then
28
- rm -rf "$TMP_ROOT"
34
+ remove_path_recursive "$TMP_ROOT"
29
35
  fi
30
36
  }
31
37
 
@@ -286,7 +292,7 @@ if [[ -z "$APP_BUNDLE_PATH" ]]; then
286
292
  fi
287
293
 
288
294
  STAGED_APP_PATH="$ARTIFACTS_DIR/$(basename "$APP_BUNDLE_PATH")"
289
- rm -rf "$STAGED_APP_PATH"
295
+ remove_path_recursive "$STAGED_APP_PATH"
290
296
  ditto "$APP_BUNDLE_PATH" "$STAGED_APP_PATH"
291
297
 
292
298
  LAUNCHER_PATH="$STAGED_APP_PATH/Contents/MacOS/launcher"
@@ -9,7 +9,8 @@
9
9
  * Resolves the host app via the standard elizaOS layout; run after
10
10
  * `bun run build:web` (or equivalent).
11
11
  */
12
- import { cp, mkdir, rm, stat } from "node:fs/promises";
12
+ import { spawnSync } from "node:child_process";
13
+ import { cp, mkdir, stat } from "node:fs/promises";
13
14
  import path from "node:path";
14
15
  import {
15
16
  resolveElectrobunDir,
@@ -22,6 +23,12 @@ const appRoot = resolveMainAppDir(repoRoot, "app");
22
23
  const electrobunRoot = resolveElectrobunDir(repoRoot);
23
24
  const sourceDir = path.join(appRoot, "dist");
24
25
  const targetDir = path.join(electrobunRoot, "app");
26
+ const rmPathRecursiveScript = path.join(
27
+ repoRoot,
28
+ "packages",
29
+ "scripts",
30
+ "rm-path-recursive.mjs",
31
+ );
25
32
  const LOG_PREFIX = "[Electrobun]";
26
33
 
27
34
  async function ensureDirExists(dir) {
@@ -33,6 +40,28 @@ async function ensureDirExists(dir) {
33
40
  }
34
41
  }
35
42
 
43
+ function rmRecursive(pathToRemove) {
44
+ const result = spawnSync(
45
+ process.execPath,
46
+ [rmPathRecursiveScript, path.resolve(pathToRemove)],
47
+ {
48
+ cwd: repoRoot,
49
+ encoding: "utf8",
50
+ stdio: ["ignore", "pipe", "pipe"],
51
+ },
52
+ );
53
+ if (result.status !== 0) {
54
+ const reason =
55
+ result.stderr?.trim() ||
56
+ result.stdout?.trim() ||
57
+ result.error?.message ||
58
+ `exit status ${String(result.status)}`;
59
+ throw new Error(
60
+ `${LOG_PREFIX} failed to recursively remove ${pathToRemove}: ${reason}`,
61
+ );
62
+ }
63
+ }
64
+
36
65
  if (!(await ensureDirExists(sourceDir))) {
37
66
  console.error(`${LOG_PREFIX} Web build output not found: ${sourceDir}`);
38
67
  console.error(
@@ -41,7 +70,7 @@ if (!(await ensureDirExists(sourceDir))) {
41
70
  process.exit(1);
42
71
  }
43
72
 
44
- await rm(targetDir, { recursive: true, force: true });
73
+ rmRecursive(targetDir);
45
74
  await mkdir(targetDir, { recursive: true });
46
75
  await cp(sourceDir, targetDir, { recursive: true, force: true });
47
76
 
@@ -21,6 +21,14 @@ export type ElectrobunBootConfigWindow = {
21
21
  [BOOT_CONFIG_STORE_KEY]?: ElectrobunBootConfigStore;
22
22
  };
23
23
 
24
+ declare global {
25
+ interface Window {
26
+ [BOOT_CONFIG_WINDOW_KEY]?: ElectrobunBootConfig;
27
+ [LEGACY_BOOT_CONFIG_WINDOW_KEY]?: ElectrobunBootConfig;
28
+ [BOOT_CONFIG_STORE_KEY]?: ElectrobunBootConfigStore;
29
+ }
30
+ }
31
+
24
32
  export function updateElectrobunBootConfig(
25
33
  globalObject: ElectrobunBootConfigWindow,
26
34
  updates: Pick<ElectrobunBootConfig, "apiBase" | "apiToken">,
@@ -21,6 +21,10 @@ export interface ElectrobunCryptoWindow {
21
21
  __electrobun_decrypt?: ElectrobunDecrypt;
22
22
  }
23
23
 
24
+ declare global {
25
+ interface Window extends ElectrobunCryptoWindow {}
26
+ }
27
+
24
28
  export interface ElectrobunCryptoReadyGuardOptions {
25
29
  timeoutMs?: number;
26
30
  pollIntervalMs?: number;
@@ -71,7 +75,7 @@ async function waitForInstalledFunction<
71
75
  * falling into a broken postMessage fallback.
72
76
  */
73
77
  export function installElectrobunCryptoReadyGuards(
74
- globalWindow: ElectrobunCryptoWindow = window as unknown as ElectrobunCryptoWindow,
78
+ globalWindow: ElectrobunCryptoWindow = window,
75
79
  options: ElectrobunCryptoReadyGuardOptions = {},
76
80
  ): boolean {
77
81
  if (!hasSocketRpcGlobals(globalWindow)) {
@@ -15,10 +15,7 @@ import { Electroview } from "electrobun/view";
15
15
  import { httpErrorDiagnosticLevel } from "../diagnostic-format.js";
16
16
  import type { RpcMessageListener } from "../types.js";
17
17
  import { getBrowserTabsRendererImpl } from "./browser-tabs-renderer-registry.js";
18
- import {
19
- type ElectrobunBootConfigWindow,
20
- updateElectrobunBootConfig,
21
- } from "./electrobun-boot-config.js";
18
+ import { updateElectrobunBootConfig } from "./electrobun-boot-config.js";
22
19
  import { ensureElectrobunGlobal } from "./electrobun-stub.js";
23
20
 
24
21
  type RendererRequestHandler = (params: unknown) => Promise<unknown>;
@@ -79,13 +76,10 @@ function dispatchMessage(messageName: string, payload: unknown): void {
79
76
  // Propagate to boot config so the appClient picks up port changes.
80
77
  // We modify it directly instead of importing @elizaos/app-core
81
78
  // to prevent bundling React and the entire UI layer into the preload script.
82
- updateElectrobunBootConfig(
83
- window as unknown as ElectrobunBootConfigWindow,
84
- {
85
- apiBase: apiBaseUpdate.base,
86
- ...(apiBaseUpdate.token ? { apiToken: apiBaseUpdate.token } : {}),
87
- },
88
- );
79
+ updateElectrobunBootConfig(window, {
80
+ apiBase: apiBaseUpdate.base,
81
+ ...(apiBaseUpdate.token ? { apiToken: apiBaseUpdate.token } : {}),
82
+ });
89
83
  }
90
84
 
91
85
  const listeners = listenersByRpcMessage[messageName];
@@ -1 +1 @@
1
- (()=>{function S(e,t){let r=e.map((n)=>`"${n}"`).join(", ");return Error(`This RPC instance cannot ${t} because the transport did not provide one or more of these methods: ${r}`)}function I(e={}){let t={},r={},n=void 0;function o(s){if(r.unregisterHandler)r.unregisterHandler();r=s,r.registerHandler?.($)}function c(s){if(typeof s==="function"){n=s;return}n=(i,u)=>{let p=s[i];if(p)return p(u);let g=s._;if(!g)throw Error(`The requested method has no handler: ${String(i)}`);return g(i,u)}}let{maxRequestTime:a=1000}=e;if(e.transport)o(e.transport);if(e.requestHandler)c(e.requestHandler);if(e._debugHooks)t=e._debugHooks;let R=0;function m(){if(R<=10000000000)return++R;return R=0}let d=new Map,l=new Map;function w(s,...i){let u=i[0];return new Promise((p,g)=>{if(!r.send)throw S(["send"],"make requests");let f=m(),B={type:"request",id:f,method:s,params:u};if(d.set(f,{resolve:p,reject:g}),a!==1/0)l.set(f,setTimeout(()=>{l.delete(f),d.delete(f),g(Error("RPC request timed out."))},a));t.onSend?.(B),r.send(B)})}let q=new Proxy(w,{get:(s,i,u)=>{if(i in s)return Reflect.get(s,i,u);return(p)=>w(i,p)}}),x=q;function T(s,...i){let u=i[0];if(!r.send)throw S(["send"],"send messages");let p={type:"message",id:s,payload:u};t.onSend?.(p),r.send(p)}let v=new Proxy(T,{get:(s,i,u)=>{if(i in s)return Reflect.get(s,i,u);return(p)=>T(i,p)}}),O=v,h=new Map,b=new Set;function Y(s,i){if(!r.registerHandler)throw S(["registerHandler"],"register message listeners");if(s==="*"){b.add(i);return}if(!h.has(s))h.set(s,new Set);h.get(s).add(i)}function U(s,i){if(s==="*"){b.delete(i);return}if(h.get(s)?.delete(i),h.get(s)?.size===0)h.delete(s)}async function $(s){if(t.onReceive?.(s),!("type"in s))throw Error("Message does not contain a type.");if(s.type==="request"){if(!r.send||!n)throw S(["send","requestHandler"],"handle requests");let{id:i,method:u,params:p}=s,g;try{g={type:"response",id:i,success:!0,payload:await n(u,p)}}catch(f){if(!(f instanceof Error))throw f;g={type:"response",id:i,success:!1,error:f.message}}t.onSend?.(g),r.send(g);return}if(s.type==="response"){let i=l.get(s.id);if(i!=null)clearTimeout(i);l.delete(s.id);let{resolve:u,reject:p}=d.get(s.id)??{};if(d.delete(s.id),!s.success)p?.(Error(s.error));else u?.(s.payload);return}if(s.type==="message"){for(let u of b)u(s.id,s.payload);let i=h.get(s.id);if(!i)return;for(let u of i)u(s.payload);return}throw Error(`Unexpected RPC message type: ${s.type}`)}return{setTransport:o,setRequestHandler:c,request:q,requestProxy:x,send:v,sendProxy:O,addMessageListener:Y,removeMessageListener:U,proxy:{send:O,request:x}}}function H(e,t){let r={maxRequestTime:t.maxRequestTime,requestHandler:{...t.handlers.requests,...t.extraRequestHandlers},transport:{registerHandler:()=>{}}},n=I(r),o=t.handlers.messages;if(o)n.addMessageListener("*",(c,a)=>{let R=o["*"];if(R)R(c,a);let m=o[c];if(m)m(a)});return n}var{__electrobunWebviewId:L,__electrobunRpcSocketPort:W}=window;class P{bunSocket;rpc;rpcHandler;constructor(e){this.rpc=e.rpc,this.init()}init(){if(this.initSocketToBun(),window.__electrobun.receiveMessageFromBun=this.receiveMessageFromBun.bind(this),this.rpc)this.rpc.setTransport(this.createTransport())}initSocketToBun(){if(!W||!L)return;let e=new WebSocket(`ws://localhost:${W}/socket?webviewId=${L}`);this.bunSocket=e,e.addEventListener("open",()=>{}),e.addEventListener("message",async(t)=>{let r=t.data;if(typeof r==="string")try{let n=JSON.parse(r),o=await window.__electrobun_decrypt(n.encryptedData,n.iv,n.tag);this.rpcHandler?.(JSON.parse(o))}catch(n){console.error("Error parsing bun message:",n)}else if(r instanceof Blob);else console.error("UNKNOWN DATA TYPE RECEIVED:",t.data)}),e.addEventListener("error",(t)=>{console.error("Socket error:",t)}),e.addEventListener("close",(t)=>{})}createTransport(){let e=this;return{send(t){try{let r=JSON.stringify(t);e.bunBridge(r)}catch(r){console.error("bun: failed to serialize message to webview",r)}},registerHandler(t){e.rpcHandler=t}}}async bunBridge(e){if(this.bunSocket?.readyState===WebSocket.OPEN)try{let{encryptedData:t,iv:r,tag:n}=await window.__electrobun_encrypt(e),c=JSON.stringify({encryptedData:t,iv:r,tag:n});this.bunSocket.send(c);return}catch(t){console.error("Error sending message to bun via socket:",t)}window.__electrobunBunBridge?.postMessage(e)}receiveMessageFromBun(e){if(this.rpcHandler)this.rpcHandler(e)}static defineRPC(e){return H("webview",{...e,extraRequestHandlers:{evaluateJavascriptWithResponse:({script:t})=>new Promise((r)=>{try{let o=Function(t)();if(o instanceof Promise)o.then((c)=>{r(c)}).catch((c)=>{console.error("bun: async script execution failed",c),r(String(c))});else r(o)}catch(n){console.error("bun: failed to eval script",n),r(String(n))}})}})}}function C(e,t){if(e===404&&z(t))return null;return e>=500?"error":"warn"}function z(e){let t=e?.method?.toUpperCase()??"GET";if(t!=="GET"&&t!=="HEAD")return!1;let r=e?.url;if(!r)return!1;let n=r;try{n=new URL(r,"http://localhost").pathname}catch{n=r.split("?")[0]??r}return n==="/api/vincent/status"}var A={evaluate:async(e)=>({ok:!1,error:`BrowserWorkspaceView is not mounted — cannot evaluate tab ${e}`}),getTabRect:async()=>null};function E(){if(typeof window>"u")return A;return window.__ELIZA_BROWSER_TABS_REGISTRY__??A}var Z=Symbol.for("elizaos.app.boot-config"),F=Z;function N(e,t){let n={...e.__ELIZAOS_APP_BOOT_CONFIG__??e.__ELIZA_APP_BOOT_CONFIG__??e[F]?.current??{},...t};return e.__ELIZAOS_APP_BOOT_CONFIG__=n,e.__ELIZA_APP_BOOT_CONFIG__=n,e[F]={current:n},n}function D(){if(typeof window.__electrobun>"u")window.__electrobun={receiveMessageFromBun:(e)=>{},receiveInternalMessageFromBun:(e)=>{}}}var y={},K="__ELIZA_ELECTROBUN_LOG_MIRROR__";function G(e){if(!e||typeof e!=="object")throw Error("Electrobun RPC params must be an object");return e}function k(e,t){let r=e[t];if(typeof r!=="string")throw Error(`Electrobun RPC param "${t}" must be a string`);return r}function j(e,t){let r=e[t];if(typeof r!=="number"||!Number.isFinite(r))throw Error(`Electrobun RPC param "${t}" must be a finite number`);return r}D();function X(e,t){if(e==="apiBaseUpdate"){let n=t;if(window.__ELIZA_API_BASE__=n.base,n.token)Object.defineProperty(window,"__ELIZA_API_TOKEN__",{value:n.token,configurable:!0,writable:!0,enumerable:!1});N(window,{apiBase:n.base,...n.token?{apiToken:n.token}:{}})}let r=y[e];if(!r)return;for(let n of Array.from(r))try{n(t)}catch(o){console.error(`[ElectrobunBridge] Listener error for ${e}:`,o)}}function J(e,t){if(typeof e==="string")X(e,t)}var _=P.defineRPC({maxRequestTime:600000,handlers:{requests:{browserWorkspaceRendererEvaluate:async(e)=>{let t=G(e),r=k(t,"id"),n=k(t,"script"),o=j(t,"timeoutMs");return await E().evaluate(r,n,o)},browserWorkspaceRendererGetTabRect:async(e)=>{let t=G(e);return E().getTabRect(k(t,"id"))}},messages:{"*":J}}});new P({rpc:_});function M(e){if(e instanceof Error)return{name:e.name,message:e.message,stack:e.stack};return e}var V=new Proxy(_.request,{get(e,t,r){let n=Reflect.get(e,t,r);if(typeof n!=="function")return n;return async(o)=>{try{return await n.call(e,o)}catch(c){throw _.request.rendererReportDiagnostic({level:"error",source:"rpc",message:`Electrobun RPC request failed: ${String(t)}`,details:M(c)}).catch(()=>{}),c}}}}),Q={request:V,onMessage:(e,t)=>{if(!y[e])y[e]=new Set;y[e].add(t)},offMessage:(e,t)=>{if(y[e]?.delete(t),y[e]?.size===0)delete y[e]}};window.__ELIZA_ELECTROBUN_RPC__=Q;function ee(){let e=window;if(e[K])return;e[K]=!0;let t=(n,o,c,a)=>{_.request.rendererReportDiagnostic({level:n,source:o,message:c,details:a}).catch(()=>{})},r=["log","info","warn","error"];for(let n of r){let o=console[n].bind(console);console[n]=(...c)=>{o(...c),t(n,"console",c.map((a)=>{if(typeof a==="string")return a;try{return JSON.stringify(a)}catch{return String(a)}}).join(" "))}}if(window.addEventListener("error",(n)=>{let o=n.target;if(o&&(o.src||o.href)){t("error","resource","Failed to load resource",{tagName:o.tagName,src:o.src,href:o.href});return}t("error","window.onerror",n.message||"Unhandled window error",{filename:n.filename,lineno:n.lineno,colno:n.colno})},!0),window.addEventListener("unhandledrejection",(n)=>{t("error","unhandledrejection","Unhandled promise rejection",M(n.reason))}),typeof window.fetch==="function"){let n=window.fetch.bind(window);window.fetch=async(...o)=>{let c=Date.now(),a=o[0],R=o[1],m=typeof a==="string"?a:a instanceof Request?a.url:String(a),d=R?.method??(a instanceof Request?a.method:void 0)??"GET";try{let l=await n(...o),w=l.ok?null:C(l.status,{url:m,method:d});if(w)t(w,"fetch",`HTTP ${l.status} ${l.statusText}`,{url:m,method:d,durationMs:Date.now()-c});return l}catch(l){throw t("error","fetch","Fetch failed",{url:m,method:d,durationMs:Date.now()-c,error:M(l)}),l}}}if(typeof XMLHttpRequest<"u"){let n=XMLHttpRequest.prototype.open,o=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(c,a,...R){return this.__elizaDiag={method:c,url:String(a),startedAt:Date.now()},n.call(this,c,a,...R)},XMLHttpRequest.prototype.send=function(...c){let a=this,R=()=>{let d=a.__elizaDiag;if(!d)return;let l=a.status>=400?C(a.status,{url:d.url,method:d.method}):null;if(l)t(l,"xhr",`HTTP ${a.status}`,{url:d.url,method:d.method,durationMs:Date.now()-d.startedAt})},m=()=>{let d=a.__elizaDiag;t("error","xhr","XMLHttpRequest failed",{url:d?.url,method:d?.method,durationMs:d?Date.now()-d.startedAt:void 0})};return a.addEventListener("loadend",R,{once:!0}),a.addEventListener("error",m,{once:!0}),o.call(this,...c)}}}ee();})();
1
+ (()=>{function w(e,t){let r=e.map((n)=>`"${n}"`).join(", ");return Error(`This RPC instance cannot ${t} because the transport did not provide one or more of these methods: ${r}`)}function I(e={}){let t={},r={},n=void 0;function o(s){if(r.unregisterHandler)r.unregisterHandler();r=s,r.registerHandler?.($)}function c(s){if(typeof s==="function"){n=s;return}n=(i,u)=>{let p=s[i];if(p)return p(u);let g=s._;if(!g)throw Error(`The requested method has no handler: ${String(i)}`);return g(i,u)}}let{maxRequestTime:a=1000}=e;if(e.transport)o(e.transport);if(e.requestHandler)c(e.requestHandler);if(e._debugHooks)t=e._debugHooks;let R=0;function m(){if(R<=10000000000)return++R;return R=0}let d=new Map,l=new Map;function S(s,...i){let u=i[0];return new Promise((p,g)=>{if(!r.send)throw w(["send"],"make requests");let f=m(),B={type:"request",id:f,method:s,params:u};if(d.set(f,{resolve:p,reject:g}),a!==1/0)l.set(f,setTimeout(()=>{l.delete(f),d.delete(f),g(Error("RPC request timed out."))},a));t.onSend?.(B),r.send(B)})}let q=new Proxy(S,{get:(s,i,u)=>{if(i in s)return Reflect.get(s,i,u);return(p)=>S(i,p)}}),T=q;function x(s,...i){let u=i[0];if(!r.send)throw w(["send"],"send messages");let p={type:"message",id:s,payload:u};t.onSend?.(p),r.send(p)}let v=new Proxy(x,{get:(s,i,u)=>{if(i in s)return Reflect.get(s,i,u);return(p)=>x(i,p)}}),O=v,h=new Map,b=new Set;function Y(s,i){if(!r.registerHandler)throw w(["registerHandler"],"register message listeners");if(s==="*"){b.add(i);return}if(!h.has(s))h.set(s,new Set);h.get(s).add(i)}function U(s,i){if(s==="*"){b.delete(i);return}if(h.get(s)?.delete(i),h.get(s)?.size===0)h.delete(s)}async function $(s){if(t.onReceive?.(s),!("type"in s))throw Error("Message does not contain a type.");if(s.type==="request"){if(!r.send||!n)throw w(["send","requestHandler"],"handle requests");let{id:i,method:u,params:p}=s,g;try{g={type:"response",id:i,success:!0,payload:await n(u,p)}}catch(f){if(!(f instanceof Error))throw f;g={type:"response",id:i,success:!1,error:f.message}}t.onSend?.(g),r.send(g);return}if(s.type==="response"){let i=l.get(s.id);if(i!=null)clearTimeout(i);l.delete(s.id);let{resolve:u,reject:p}=d.get(s.id)??{};if(d.delete(s.id),!s.success)p?.(Error(s.error));else u?.(s.payload);return}if(s.type==="message"){for(let u of b)u(s.id,s.payload);let i=h.get(s.id);if(!i)return;for(let u of i)u(s.payload);return}throw Error(`Unexpected RPC message type: ${s.type}`)}return{setTransport:o,setRequestHandler:c,request:q,requestProxy:T,send:v,sendProxy:O,addMessageListener:Y,removeMessageListener:U,proxy:{send:O,request:T}}}function H(e,t){let r={maxRequestTime:t.maxRequestTime,requestHandler:{...t.handlers.requests,...t.extraRequestHandlers},transport:{registerHandler:()=>{}}},n=I(r),o=t.handlers.messages;if(o)n.addMessageListener("*",(c,a)=>{let R=o["*"];if(R)R(c,a);let m=o[c];if(m)m(a)});return n}var{__electrobunWebviewId:L,__electrobunRpcSocketPort:W}=window;class P{bunSocket;rpc;rpcHandler;constructor(e){this.rpc=e.rpc,this.init()}init(){if(this.initSocketToBun(),window.__electrobun.receiveMessageFromBun=this.receiveMessageFromBun.bind(this),this.rpc)this.rpc.setTransport(this.createTransport())}initSocketToBun(){if(!W||!L)return;let e=new WebSocket(`ws://localhost:${W}/socket?webviewId=${L}`);this.bunSocket=e,e.addEventListener("open",()=>{}),e.addEventListener("message",async(t)=>{let r=t.data;if(typeof r==="string")try{let n=JSON.parse(r),o=await window.__electrobun_decrypt(n.encryptedData,n.iv,n.tag);this.rpcHandler?.(JSON.parse(o))}catch(n){console.error("Error parsing bun message:",n)}else if(r instanceof Blob);else console.error("UNKNOWN DATA TYPE RECEIVED:",t.data)}),e.addEventListener("error",(t)=>{console.error("Socket error:",t)}),e.addEventListener("close",(t)=>{})}createTransport(){let e=this;return{send(t){try{let r=JSON.stringify(t);e.bunBridge(r)}catch(r){console.error("bun: failed to serialize message to webview",r)}},registerHandler(t){e.rpcHandler=t}}}async bunBridge(e){if(this.bunSocket?.readyState===WebSocket.OPEN)try{let{encryptedData:t,iv:r,tag:n}=await window.__electrobun_encrypt(e),c=JSON.stringify({encryptedData:t,iv:r,tag:n});this.bunSocket.send(c);return}catch(t){console.error("Error sending message to bun via socket:",t)}window.__electrobunBunBridge?.postMessage(e)}receiveMessageFromBun(e){if(this.rpcHandler)this.rpcHandler(e)}static defineRPC(e){return H("webview",{...e,extraRequestHandlers:{evaluateJavascriptWithResponse:({script:t})=>new Promise((r)=>{try{let o=Function(t)();if(o instanceof Promise)o.then((c)=>{r(c)}).catch((c)=>{console.error("bun: async script execution failed",c),r(String(c))});else r(o)}catch(n){console.error("bun: failed to eval script",n),r(String(n))}})}})}}function C(e,t){if(e===404&&z(t))return null;return e>=500?"error":"warn"}function z(e){let t=e?.method?.toUpperCase()??"GET";if(t!=="GET"&&t!=="HEAD")return!1;let r=e?.url;if(!r)return!1;let n=r;try{n=new URL(r,"http://localhost").pathname}catch{n=r.split("?")[0]??r}return n==="/api/vincent/status"}var A={evaluate:async(e)=>({ok:!1,error:`BrowserWorkspaceView is not mounted — cannot evaluate tab ${e}`}),getTabRect:async()=>null};function E(){if(typeof window>"u")return A;return window.__ELIZA_BROWSER_TABS_REGISTRY__??A}var Z=Symbol.for("elizaos.app.boot-config"),N=Z;function F(e,t){let n={...e.__ELIZAOS_APP_BOOT_CONFIG__??e.__ELIZA_APP_BOOT_CONFIG__??e[N]?.current??{},...t};return e.__ELIZAOS_APP_BOOT_CONFIG__=n,e.__ELIZA_APP_BOOT_CONFIG__=n,e[N]={current:n},n}function D(){if(typeof window.__electrobun>"u")window.__electrobun={receiveMessageFromBun:(e)=>{},receiveInternalMessageFromBun:(e)=>{}}}var y={},K="__ELIZA_ELECTROBUN_LOG_MIRROR__";function G(e){if(!e||typeof e!=="object")throw Error("Electrobun RPC params must be an object");return e}function k(e,t){let r=e[t];if(typeof r!=="string")throw Error(`Electrobun RPC param "${t}" must be a string`);return r}function j(e,t){let r=e[t];if(typeof r!=="number"||!Number.isFinite(r))throw Error(`Electrobun RPC param "${t}" must be a finite number`);return r}D();function X(e,t){if(e==="apiBaseUpdate"){let n=t;if(window.__ELIZA_API_BASE__=n.base,n.token)Object.defineProperty(window,"__ELIZA_API_TOKEN__",{value:n.token,configurable:!0,writable:!0,enumerable:!1});F(window,{apiBase:n.base,...n.token?{apiToken:n.token}:{}})}let r=y[e];if(!r)return;for(let n of Array.from(r))try{n(t)}catch(o){console.error(`[ElectrobunBridge] Listener error for ${e}:`,o)}}function J(e,t){if(typeof e==="string")X(e,t)}var _=P.defineRPC({maxRequestTime:600000,handlers:{requests:{browserWorkspaceRendererEvaluate:async(e)=>{let t=G(e),r=k(t,"id"),n=k(t,"script"),o=j(t,"timeoutMs");return await E().evaluate(r,n,o)},browserWorkspaceRendererGetTabRect:async(e)=>{let t=G(e);return E().getTabRect(k(t,"id"))}},messages:{"*":J}}});new P({rpc:_});function M(e){if(e instanceof Error)return{name:e.name,message:e.message,stack:e.stack};return e}var V=new Proxy(_.request,{get(e,t,r){let n=Reflect.get(e,t,r);if(typeof n!=="function")return n;return async(o)=>{try{return await n.call(e,o)}catch(c){throw _.request.rendererReportDiagnostic({level:"error",source:"rpc",message:`Electrobun RPC request failed: ${String(t)}`,details:M(c)}).catch(()=>{}),c}}}}),Q={request:V,onMessage:(e,t)=>{if(!y[e])y[e]=new Set;y[e].add(t)},offMessage:(e,t)=>{if(y[e]?.delete(t),y[e]?.size===0)delete y[e]}};window.__ELIZA_ELECTROBUN_RPC__=Q;function ee(){let e=window;if(e[K])return;e[K]=!0;let t=(n,o,c,a)=>{_.request.rendererReportDiagnostic({level:n,source:o,message:c,details:a}).catch(()=>{})},r=["log","info","warn","error"];for(let n of r){let o=console[n].bind(console);console[n]=(...c)=>{o(...c),t(n,"console",c.map((a)=>{if(typeof a==="string")return a;try{return JSON.stringify(a)}catch{return String(a)}}).join(" "))}}if(window.addEventListener("error",(n)=>{let o=n.target;if(o&&(o.src||o.href)){t("error","resource","Failed to load resource",{tagName:o.tagName,src:o.src,href:o.href});return}t("error","window.onerror",n.message||"Unhandled window error",{filename:n.filename,lineno:n.lineno,colno:n.colno})},!0),window.addEventListener("unhandledrejection",(n)=>{t("error","unhandledrejection","Unhandled promise rejection",M(n.reason))}),typeof window.fetch==="function"){let n=window.fetch.bind(window);window.fetch=async(...o)=>{let c=Date.now(),a=o[0],R=o[1],m=typeof a==="string"?a:a instanceof Request?a.url:String(a),d=R?.method??(a instanceof Request?a.method:void 0)??"GET";try{let l=await n(...o),S=l.ok?null:C(l.status,{url:m,method:d});if(S)t(S,"fetch",`HTTP ${l.status} ${l.statusText}`,{url:m,method:d,durationMs:Date.now()-c});return l}catch(l){throw t("error","fetch","Fetch failed",{url:m,method:d,durationMs:Date.now()-c,error:M(l)}),l}}}if(typeof XMLHttpRequest<"u"){let n=XMLHttpRequest.prototype.open,o=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(c,a,...R){return this.__elizaDiag={method:c,url:String(a),startedAt:Date.now()},n.call(this,c,a,...R)},XMLHttpRequest.prototype.send=function(...c){let a=this,R=()=>{let d=a.__elizaDiag;if(!d)return;let l=a.status>=400?C(a.status,{url:d.url,method:d.method}):null;if(l)t(l,"xhr",`HTTP ${a.status}`,{url:d.url,method:d.method,durationMs:Date.now()-d.startedAt})},m=()=>{let d=a.__elizaDiag;t("error","xhr","XMLHttpRequest failed",{url:d?.url,method:d?.method,durationMs:d?Date.now()-d.startedAt:void 0})};return a.addEventListener("loadend",R,{once:!0}),a.addEventListener("error",m,{once:!0}),o.call(this,...c)}}}ee();})();
@@ -11,7 +11,7 @@
11
11
  <!--Bridge View Controller-->
12
12
  <scene sceneID="tne-QT-ifu">
13
13
  <objects>
14
- <viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
14
+ <viewController id="BYZ-38-t0r" customClass="ElizaBridgeViewController" customModule="App" customModuleProvider="target" sceneMemberID="viewController"/>
15
15
  <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
16
16
  </objects>
17
17
  </scene>
@@ -0,0 +1,22 @@
1
+ import Capacitor
2
+ import WebKit
3
+
4
+ @objc(ElizaBridgeViewController)
5
+ class ElizaBridgeViewController: CAPBridgeViewController {
6
+ override func webViewConfiguration(for instanceConfiguration: InstanceConfiguration) -> WKWebViewConfiguration {
7
+ let configuration = super.webViewConfiguration(for: instanceConfiguration)
8
+ configuration.userContentController.addUserScript(
9
+ WKUserScript(
10
+ source: ElizaStartupTrace.documentStartScript,
11
+ injectionTime: .atDocumentStart,
12
+ forMainFrameOnly: true
13
+ )
14
+ )
15
+ return configuration
16
+ }
17
+
18
+ override func capacitorDidLoad() {
19
+ super.capacitorDidLoad()
20
+ NSLog("[ElizaStartupTrace] iOS startupTraceId=%@", ElizaStartupTrace.currentId)
21
+ }
22
+ }
@@ -0,0 +1,12 @@
1
+ import Foundation
2
+
3
+ enum ElizaStartupTrace {
4
+ static let currentId: String = {
5
+ let millis = Int(Date().timeIntervalSince1970 * 1000)
6
+ return "ios-\(millis)-\(UUID().uuidString.lowercased())"
7
+ }()
8
+
9
+ static var documentStartScript: String {
10
+ "window.__ELIZA_STARTUP_TRACE_ID__ = \"\(currentId)\";"
11
+ }
12
+ }
@@ -13,6 +13,8 @@
13
13
  504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
14
14
  504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
15
15
  50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
16
+ ELIZAIOSBRIDGE00000000001 /* ElizaBridgeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ELIZAIOSBRIDGE00000000002 /* ElizaBridgeViewController.swift */; };
17
+ ELIZASTARTTRACE000000001 /* ElizaStartupTrace.swift in Sources */ = {isa = PBXBuildFile; fileRef = ELIZASTARTTRACE000000002 /* ElizaStartupTrace.swift */; };
16
18
  A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
17
19
  E1A5105A0000000000000001 /* ElizaAppIntents.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5105A0000000000000002 /* ElizaAppIntents.swift */; };
18
20
  MIPL00010000000000000001 /* ElizaIntentPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = MIPL00010000000000000002 /* ElizaIntentPlugin.swift */; };
@@ -77,6 +79,8 @@
77
79
  504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
78
80
  504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
79
81
  50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
82
+ ELIZAIOSBRIDGE00000000002 /* ElizaBridgeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElizaBridgeViewController.swift; sourceTree = "<group>"; };
83
+ ELIZASTARTTRACE000000002 /* ElizaStartupTrace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElizaStartupTrace.swift; sourceTree = "<group>"; };
80
84
  AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
81
85
  AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
82
86
  E1A5105A0000000000000002 /* ElizaAppIntents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElizaAppIntents.swift; sourceTree = "<group>"; };
@@ -166,6 +170,8 @@
166
170
  children = (
167
171
  50379B222058CBB4000EE86E /* capacitor.config.json */,
168
172
  504EC3071FED79650016851F /* AppDelegate.swift */,
173
+ ELIZASTARTTRACE000000002 /* ElizaStartupTrace.swift */,
174
+ ELIZAIOSBRIDGE00000000002 /* ElizaBridgeViewController.swift */,
169
175
  SCENEDEL00000000000002 /* SceneDelegate.swift */,
170
176
  E1A5105A0000000000000002 /* ElizaAppIntents.swift */,
171
177
  MIPL00010000000000000002 /* ElizaIntentPlugin.swift */,
@@ -447,6 +453,8 @@
447
453
  buildActionMask = 2147483647;
448
454
  files = (
449
455
  504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
456
+ ELIZASTARTTRACE000000001 /* ElizaStartupTrace.swift in Sources */,
457
+ ELIZAIOSBRIDGE00000000001 /* ElizaBridgeViewController.swift in Sources */,
450
458
  SCENEDEL00000000000001 /* SceneDelegate.swift in Sources */,
451
459
  E1A5105A0000000000000001 /* ElizaAppIntents.swift in Sources */,
452
460
  MIPL00010000000000000001 /* ElizaIntentPlugin.swift in Sources */,
@@ -1 +1 @@
1
- {"version":3,"file":"eliza.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/eliza.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eliza.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/eliza.ts"],"names":[],"mappings":"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"}
package/runtime/eliza.js CHANGED
@@ -253,6 +253,7 @@ async function loadAppRoutePluginFromSpecifier(specifier, exportName) {
253
253
  export const __loadAppRoutePluginFromSpecifierForTest = loadAppRoutePluginFromSpecifier;
254
254
  const WORKFLOW_ROUTE_PLUGIN_ID = "@elizaos/plugin-workflow:routes";
255
255
  const WALLET_ROUTE_PLUGIN_ID = "@elizaos/plugin-wallet:routes";
256
+ const AGENT_ORCHESTRATOR_ROUTE_PLUGIN_ID = "@elizaos/plugin-agent-orchestrator:routes";
256
257
  function getRegistryAppRoutePluginLoaders() {
257
258
  return getApps(loadRegistry()).flatMap((app) => {
258
259
  const routePlugin = app.launch.routePlugin;
@@ -346,6 +347,16 @@ function getAppRoutePluginLoaders() {
346
347
  load: () => loadAppRoutePluginFromSpecifier("@elizaos/plugin-wallet/routes/plugin", "walletRoutePlugin"),
347
348
  });
348
349
  }
350
+ // plugin-agent-orchestrator has the same load-order hazard for its
351
+ // `/api/coding-agents/*` and `/api/orchestrator/*` rawPath routes. The main
352
+ // plugin can be present while its route-loader side effect has not populated
353
+ // the registry snapshot yet, leaving the desktop widgets with 404 probes.
354
+ if (!byId.has(AGENT_ORCHESTRATOR_ROUTE_PLUGIN_ID)) {
355
+ byId.set(AGENT_ORCHESTRATOR_ROUTE_PLUGIN_ID, {
356
+ id: AGENT_ORCHESTRATOR_ROUTE_PLUGIN_ID,
357
+ load: () => loadAppRoutePluginFromSpecifier("@elizaos/plugin-agent-orchestrator/setup-routes", "codingAgentRoutePlugin"),
358
+ });
359
+ }
349
360
  const skip = getSkippedAppRoutePluginIds();
350
361
  if (skip.size === 0) {
351
362
  return [...byId.values()];
@@ -832,6 +843,12 @@ async function warmupEmbeddingModelImpl(onProgress) {
832
843
  logger.warn(`[eliza] Embedding model warmup failed (will retry on first use): ${formatError(err)}`);
833
844
  }
834
845
  }
846
+ function isExplicitDesktopCloudOnlyRuntime(env = process.env) {
847
+ const runtimeMode = env.ELIZA_DESKTOP_RUNTIME_MODE?.trim().toLowerCase();
848
+ return (runtimeMode === "cloud" ||
849
+ runtimeMode === "elizacloud" ||
850
+ isTruthyEnvValue(env.ELIZA_DESKTOP_CLOUD_ONLY));
851
+ }
835
852
  /**
836
853
  * Warm local voice models (Whisper STT + Kokoro TTS) in the background AFTER
837
854
  * the runtime is ready, by firing one tiny useModel request at each. Voice
@@ -844,6 +861,7 @@ async function startDeferredVoiceWarmup(runtime) {
844
861
  if (!shouldWarmupVoice({
845
862
  mobile: isMobilePlatform(),
846
863
  skipEnv: isTruthyEnvValue(process.env.ELIZA_SKIP_LOCAL_VOICE_WARMUP),
864
+ cloudOnly: isExplicitDesktopCloudOnlyRuntime(),
847
865
  hotReload: isTruthyEnvValue(process.env.ELIZA_DEV_IS_HOT_RELOAD),
848
866
  })) {
849
867
  return;
@@ -11,10 +11,8 @@
11
11
  * instant — the embedding warmup's spirit, via the path voice already uses.
12
12
  * Nothing in the voice engine is touched.
13
13
  *
14
- * Warmup fires for both local and cloud setups; for cloud providers this means
15
- * two tiny billable API calls per desktop boot (a ~100 ms silent WAV for STT
16
- * and an empty-string TTS), non-blocking and non-fatal. Suppress it entirely
17
- * with ELIZA_SKIP_LOCAL_VOICE_WARMUP=1.
14
+ * Warmup is skipped for mobile, hot-reload respawns, explicit cloud-only
15
+ * desktop runtimes, and ELIZA_SKIP_LOCAL_VOICE_WARMUP=1.
18
16
  */
19
17
  /** Minimal runtime surface we need — avoids importing the heavy AgentRuntime. */
20
18
  export interface VoiceWarmupRuntime {
@@ -25,6 +23,8 @@ export interface VoiceWarmupGate {
25
23
  mobile: boolean;
26
24
  /** ELIZA_SKIP_LOCAL_VOICE_WARMUP is set. */
27
25
  skipEnv: boolean;
26
+ /** The runtime is explicitly cloud-only, so voice loads on first real use. */
27
+ cloudOnly?: boolean;
28
28
  /**
29
29
  * Dev hot-reload respawn (not a cold boot). Each hot-reload spawns a fresh
30
30
  * API child that re-runs the whole boot tail; warming voice every bounce
@@ -1 +1 @@
1
- {"version":3,"file":"voice-warmup.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/voice-warmup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAKhE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAmB7C;AAED,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AA8BF;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,qBAAqB,EAC5B,GAAG,GAAE,OAAiB,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
1
+ {"version":3,"file":"voice-warmup.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/voice-warmup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;IAChB,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAMhE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAmB7C;AAED,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AA8BF;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,qBAAqB,EAC5B,GAAG,GAAE,OAAiB,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
@@ -11,10 +11,8 @@
11
11
  * instant — the embedding warmup's spirit, via the path voice already uses.
12
12
  * Nothing in the voice engine is touched.
13
13
  *
14
- * Warmup fires for both local and cloud setups; for cloud providers this means
15
- * two tiny billable API calls per desktop boot (a ~100 ms silent WAV for STT
16
- * and an empty-string TTS), non-blocking and non-fatal. Suppress it entirely
17
- * with ELIZA_SKIP_LOCAL_VOICE_WARMUP=1.
14
+ * Warmup is skipped for mobile, hot-reload respawns, explicit cloud-only
15
+ * desktop runtimes, and ELIZA_SKIP_LOCAL_VOICE_WARMUP=1.
18
16
  */
19
17
  /** Pure policy: should we warm voice models in the background? */
20
18
  export function shouldWarmupVoice(gate) {
@@ -22,6 +20,8 @@ export function shouldWarmupVoice(gate) {
22
20
  return false;
23
21
  if (gate.skipEnv)
24
22
  return false;
23
+ if (gate.cloudOnly)
24
+ return false;
25
25
  if (gate.hotReload)
26
26
  return false;
27
27
  return true;
@@ -173,7 +173,7 @@
173
173
  // `eliza/` submodule the same algorithm finds the host repo root
174
174
  // (it stops at the first ancestor that has a `package.json`).
175
175
 
176
- import { spawnSync } from "node:child_process";
176
+ import { execFileSync, spawnSync } from "node:child_process";
177
177
  import fs from "node:fs";
178
178
  import os from "node:os";
179
179
  import path from "node:path";
@@ -207,6 +207,12 @@ const here = path.dirname(fileURLToPath(import.meta.url));
207
207
  // On a parent-host invocation that's `<host-root>`; when running
208
208
  // inside the elizaOS source checkout it's the elizaOS repo root.
209
209
  const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
210
+ const RECURSIVE_CLEANUP_SCRIPT = path.join(
211
+ repoRoot,
212
+ "packages",
213
+ "scripts",
214
+ "rm-path-recursive.mjs",
215
+ );
210
216
 
211
217
  // elizaOS/llama.cpp @ 33c888a7b. Composes TBQ (apothic) +
212
218
  // QJL (W1-A) + Q4_POLAR (W1-B) + Metal sources (W1-D) + MTP spec-decode
@@ -413,6 +419,20 @@ export function parseAndroidTarget(target) {
413
419
  return { target, arch, backend, fused, androidAbi };
414
420
  }
415
421
 
422
+ function removeDirectoryRecursive(targetPath) {
423
+ try {
424
+ execFileSync("node", [RECURSIVE_CLEANUP_SCRIPT, path.resolve(targetPath)], {
425
+ encoding: "utf8",
426
+ stdio: "pipe",
427
+ });
428
+ } catch (error) {
429
+ const detail = [error?.stdout, error?.stderr].filter(Boolean).join("\n");
430
+ throw new Error(detail || error?.message || String(error), {
431
+ cause: error,
432
+ });
433
+ }
434
+ }
435
+
416
436
  /**
417
437
  * GGML_VULKAN CMake flags for the android-arm64 Vulkan backend. Points cmake at
418
438
  * the NDK's host `glslc` (the shader compiler ggml-vulkan's codegen invokes),
@@ -508,7 +528,7 @@ export function resolveAndroidVulkanCmakeFlags({
508
528
  ? path.resolve(stagingDir)
509
529
  : path.join(os.tmpdir(), "eliza-vulkan-headers");
510
530
  const stagedVulkan = path.join(incRoot, "vulkan");
511
- fs.rmSync(stagedVulkan, { recursive: true, force: true });
531
+ removeDirectoryRecursive(stagedVulkan);
512
532
  fs.mkdirSync(incRoot, { recursive: true });
513
533
  fs.cpSync(hostVulkanDir, stagedVulkan, { recursive: true });
514
534
  // vulkan_core.h `#include <vk_video/...>` the video-codec extension headers,
@@ -517,7 +537,7 @@ export function resolveAndroidVulkanCmakeFlags({
517
537
  const hostVkVideoDir = path.join(path.dirname(hostVulkanDir), "vk_video");
518
538
  if (fs.existsSync(hostVkVideoDir)) {
519
539
  const stagedVkVideo = path.join(incRoot, "vk_video");
520
- fs.rmSync(stagedVkVideo, { recursive: true, force: true });
540
+ removeDirectoryRecursive(stagedVkVideo);
521
541
  fs.cpSync(hostVkVideoDir, stagedVkVideo, { recursive: true });
522
542
  }
523
543
 
@@ -547,7 +567,7 @@ export function resolveAndroidVulkanCmakeFlags({
547
567
  );
548
568
  }
549
569
  const stagedSpirv = path.join(incRoot, "spirv");
550
- fs.rmSync(stagedSpirv, { recursive: true, force: true });
570
+ removeDirectoryRecursive(stagedSpirv);
551
571
  fs.cpSync(path.join(hostSpirvRoot, "spirv"), stagedSpirv, {
552
572
  recursive: true,
553
573
  });
@@ -1000,7 +1020,7 @@ export function ensureLlamaCppCheckout({
1000
1020
  log(
1001
1021
  `[compile-libllama] Cloning llama.cpp ${LLAMA_CPP_TAG} into ${cacheDir}`,
1002
1022
  );
1003
- fs.rmSync(cacheDir, { recursive: true, force: true });
1023
+ removeDirectoryRecursive(cacheDir);
1004
1024
  fs.mkdirSync(cacheDir, { recursive: true });
1005
1025
  spawn(
1006
1026
  "git",
@@ -1,13 +1,22 @@
1
+ import { execFileSync } from "node:child_process";
1
2
  import fs from "node:fs";
2
3
  import os from "node:os";
3
4
  import path from "node:path";
4
5
  import { afterEach, describe, expect, test } from "vitest";
6
+ import { resolveRepoRootFromImportMeta } from "../lib/repo-root.mjs";
5
7
  import {
6
8
  resolveAndroidNdkHostDir,
7
9
  resolveDefaultAndroidAssetsDir,
8
10
  resolveHomebrewFormulaIncludeDirs,
9
11
  } from "./compile-libllama-paths.mjs";
10
12
 
13
+ const repoRoot = resolveRepoRootFromImportMeta(import.meta.url);
14
+ const cleanupHelperScript = path.join(
15
+ repoRoot,
16
+ "packages",
17
+ "scripts",
18
+ "rm-path-recursive.mjs",
19
+ );
11
20
  const tmpDirs = [];
12
21
 
13
22
  function makeTmpDir() {
@@ -16,9 +25,16 @@ function makeTmpDir() {
16
25
  return dir;
17
26
  }
18
27
 
28
+ function removePathRecursive(targetPath) {
29
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
30
+ cwd: repoRoot,
31
+ stdio: "inherit",
32
+ });
33
+ }
34
+
19
35
  afterEach(() => {
20
36
  while (tmpDirs.length > 0) {
21
- fs.rmSync(tmpDirs.pop(), { recursive: true, force: true });
37
+ removePathRecursive(tmpDirs.pop());
22
38
  }
23
39
  });
24
40
 
@@ -11,8 +11,10 @@
11
11
  * bundle.
12
12
  */
13
13
 
14
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
14
+ import { execFileSync } from "node:child_process";
15
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
15
16
  import path from "node:path";
17
+ import { fileURLToPath } from "node:url";
16
18
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
17
19
 
18
20
  import {
@@ -28,6 +30,26 @@ import {
28
30
  let tmpDir: string;
29
31
  let nodeModulesDir: string;
30
32
 
33
+ const repoRoot = path.resolve(
34
+ path.dirname(fileURLToPath(import.meta.url)),
35
+ "..",
36
+ "..",
37
+ "..",
38
+ );
39
+ const cleanupHelperScript = path.join(
40
+ repoRoot,
41
+ "packages",
42
+ "scripts",
43
+ "rm-path-recursive.mjs",
44
+ );
45
+
46
+ function removePathRecursive(targetPath: string): void {
47
+ execFileSync(process.execPath, [cleanupHelperScript, targetPath], {
48
+ cwd: repoRoot,
49
+ stdio: "inherit",
50
+ });
51
+ }
52
+
31
53
  function writePackageJson(
32
54
  name: string,
33
55
  manifest: Record<string, unknown> = {},
@@ -51,7 +73,7 @@ describe("assertRequiredBundledPackagesLanded", () => {
51
73
  });
52
74
 
53
75
  afterEach(() => {
54
- rmSync(tmpDir, { recursive: true, force: true });
76
+ removePathRecursive(tmpDir);
55
77
  });
56
78
 
57
79
  it("passes when every required package has a package.json", () => {