@elizaos/ui 2.0.0-alpha.526 → 2.0.0-alpha.528

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 (237) hide show
  1. package/apps/app-elizamaker/src/index.d.ts +2 -0
  2. package/apps/app-elizamaker/src/index.d.ts.map +1 -1
  3. package/apps/app-elizamaker/src/index.js +2 -0
  4. package/apps/app-elizamaker/src/init-registry-services.d.ts +18 -0
  5. package/apps/app-elizamaker/src/init-registry-services.d.ts.map +1 -0
  6. package/apps/app-elizamaker/src/init-registry-services.js +63 -0
  7. package/apps/app-elizamaker/src/plugin.d.ts.map +1 -1
  8. package/apps/app-elizamaker/src/plugin.js +7 -0
  9. package/apps/app-elizamaker/src/registry-service-registry.d.ts +4 -0
  10. package/apps/app-elizamaker/src/registry-service-registry.d.ts.map +1 -0
  11. package/apps/app-elizamaker/src/registry-service-registry.js +7 -0
  12. package/apps/app-lifeops/src/automation-node-contributor.d.ts +2 -0
  13. package/apps/app-lifeops/src/automation-node-contributor.d.ts.map +1 -0
  14. package/apps/app-lifeops/src/automation-node-contributor.js +93 -0
  15. package/apps/app-lifeops/src/public.d.ts.map +1 -1
  16. package/apps/app-lifeops/src/public.js +2 -0
  17. package/apps/app-training/src/services/training-service-registry.d.ts +4 -0
  18. package/apps/app-training/src/services/training-service-registry.d.ts.map +1 -0
  19. package/apps/app-training/src/services/training-service-registry.js +7 -0
  20. package/package.json +1 -1
  21. package/packages/agent/src/api/agent-status-routes.d.ts +3 -23
  22. package/packages/agent/src/api/agent-status-routes.d.ts.map +1 -1
  23. package/packages/agent/src/api/agent-status-routes.js +7 -40
  24. package/packages/agent/src/api/coordinator-wiring.d.ts.map +1 -0
  25. package/packages/agent/src/api/misc-routes.d.ts.map +1 -1
  26. package/packages/agent/src/api/misc-routes.js +3 -37
  27. package/packages/agent/src/api/nfa-routes.d.ts.map +1 -1
  28. package/packages/agent/src/api/nfa-routes.js +1 -9
  29. package/packages/agent/src/api/provider-switch-routes.d.ts +8 -7
  30. package/packages/agent/src/api/provider-switch-routes.d.ts.map +1 -1
  31. package/packages/agent/src/api/provider-switch-routes.js +41 -26
  32. package/packages/agent/src/api/server-types.d.ts +0 -6
  33. package/packages/agent/src/api/server-types.d.ts.map +1 -1
  34. package/packages/agent/src/api/server.d.ts.map +1 -1
  35. package/packages/agent/src/api/server.js +31 -138
  36. package/packages/agent/src/api/stream-routes.d.ts.map +1 -1
  37. package/packages/agent/src/api/stream-routes.js +6 -8
  38. package/packages/agent/src/api/wallet-trading-profile.d.ts.map +1 -1
  39. package/packages/agent/src/api/wallet-trading-profile.js +2 -23
  40. package/packages/agent/src/auth/account-storage.d.ts.map +1 -1
  41. package/packages/agent/src/auth/account-storage.js +4 -15
  42. package/packages/agent/src/runtime/eliza.d.ts.map +1 -1
  43. package/packages/agent/src/runtime/eliza.js +2 -6
  44. package/packages/agent/src/runtime/first-time-setup.d.ts.map +1 -1
  45. package/packages/agent/src/runtime/first-time-setup.js +1 -7
  46. package/packages/agent/src/runtime/operations/cold-strategy.d.ts +4 -4
  47. package/packages/agent/src/runtime/operations/cold-strategy.d.ts.map +1 -1
  48. package/packages/agent/src/runtime/operations/cold-strategy.js +13 -46
  49. package/packages/agent/src/runtime/operations/health-checks.d.ts +1 -0
  50. package/packages/agent/src/runtime/operations/health-checks.d.ts.map +1 -1
  51. package/packages/agent/src/runtime/operations/health-checks.js +1 -1
  52. package/packages/agent/src/runtime/operations/health.d.ts.map +1 -1
  53. package/packages/agent/src/runtime/operations/health.js +1 -13
  54. package/packages/agent/src/runtime/operations/index.d.ts +1 -0
  55. package/packages/agent/src/runtime/operations/index.d.ts.map +1 -1
  56. package/packages/agent/src/runtime/operations/index.js +1 -0
  57. package/packages/agent/src/runtime/operations/manager.d.ts +2 -0
  58. package/packages/agent/src/runtime/operations/manager.d.ts.map +1 -1
  59. package/packages/agent/src/runtime/operations/manager.js +27 -7
  60. package/packages/agent/src/runtime/operations/reload-hot.d.ts +4 -1
  61. package/packages/agent/src/runtime/operations/reload-hot.d.ts.map +1 -1
  62. package/packages/agent/src/runtime/operations/reload-hot.js +46 -41
  63. package/packages/agent/src/runtime/operations/repository.d.ts +30 -8
  64. package/packages/agent/src/runtime/operations/repository.d.ts.map +1 -1
  65. package/packages/agent/src/runtime/operations/repository.js +140 -54
  66. package/packages/agent/src/runtime/operations/types.d.ts +26 -24
  67. package/packages/agent/src/runtime/operations/types.d.ts.map +1 -1
  68. package/packages/agent/src/runtime/operations/types.js +8 -20
  69. package/packages/agent/src/runtime/operations/vault-bridge.d.ts +60 -0
  70. package/packages/agent/src/runtime/operations/vault-bridge.d.ts.map +1 -0
  71. package/packages/agent/src/runtime/operations/vault-bridge.js +80 -0
  72. package/packages/agent/src/runtime/plugin-resolver.d.ts.map +1 -1
  73. package/packages/agent/src/runtime/plugin-resolver.js +1 -3
  74. package/packages/agent/src/runtime/plugin-types.d.ts.map +1 -1
  75. package/packages/agent/src/runtime/plugin-types.js +1 -3
  76. package/packages/agent/src/services/app-package-modules.d.ts.map +1 -1
  77. package/packages/agent/src/services/app-package-modules.js +1 -8
  78. package/packages/agent/src/services/app-run-store.d.ts.map +1 -1
  79. package/packages/agent/src/services/app-run-store.js +2 -23
  80. package/packages/agent/src/services/registry-client-local.d.ts.map +1 -1
  81. package/packages/agent/src/services/registry-client-local.js +1 -9
  82. package/packages/agent/src/utils/atomic-json.d.ts +37 -0
  83. package/packages/agent/src/utils/atomic-json.d.ts.map +1 -0
  84. package/packages/agent/src/utils/atomic-json.js +98 -0
  85. package/packages/app-core/src/api/automation-node-contributors.d.ts +14 -0
  86. package/packages/app-core/src/api/automation-node-contributors.d.ts.map +1 -0
  87. package/packages/app-core/src/api/automation-node-contributors.js +14 -0
  88. package/packages/app-core/src/api/client-agent.d.ts +627 -0
  89. package/packages/app-core/src/api/client-agent.d.ts.map +1 -0
  90. package/packages/app-core/src/api/client-agent.js +1442 -0
  91. package/packages/app-core/src/api/client-automations.d.ts +8 -0
  92. package/packages/app-core/src/api/client-automations.d.ts.map +1 -0
  93. package/packages/app-core/src/api/client-automations.js +7 -0
  94. package/packages/app-core/src/api/client-base.d.ts +82 -0
  95. package/packages/app-core/src/api/client-base.d.ts.map +1 -0
  96. package/packages/app-core/src/api/client-base.js +729 -0
  97. package/packages/app-core/src/api/client-browser-workspace.d.ts +25 -0
  98. package/packages/app-core/src/api/client-browser-workspace.d.ts.map +1 -0
  99. package/packages/app-core/src/api/client-browser-workspace.js +98 -0
  100. package/packages/app-core/src/api/client-chat.d.ts +355 -0
  101. package/packages/app-core/src/api/client-chat.d.ts.map +1 -0
  102. package/packages/app-core/src/api/client-chat.js +582 -0
  103. package/packages/app-core/src/api/client-cloud.d.ts +286 -0
  104. package/packages/app-core/src/api/client-cloud.d.ts.map +1 -0
  105. package/packages/app-core/src/api/client-cloud.js +410 -0
  106. package/packages/app-core/src/api/client-computeruse.d.ts +32 -0
  107. package/packages/app-core/src/api/client-computeruse.d.ts.map +1 -0
  108. package/packages/app-core/src/api/client-computeruse.js +16 -0
  109. package/packages/app-core/src/api/client-imessage.d.ts +68 -0
  110. package/packages/app-core/src/api/client-imessage.d.ts.map +1 -0
  111. package/packages/app-core/src/api/client-imessage.js +74 -0
  112. package/packages/app-core/src/api/client-local-inference.d.ts +62 -0
  113. package/packages/app-core/src/api/client-local-inference.d.ts.map +1 -0
  114. package/packages/app-core/src/api/client-local-inference.js +87 -0
  115. package/packages/app-core/src/api/client-n8n.d.ts +27 -0
  116. package/packages/app-core/src/api/client-n8n.d.ts.map +1 -0
  117. package/packages/app-core/src/api/client-n8n.js +61 -0
  118. package/packages/app-core/src/api/client-skills.d.ts +475 -0
  119. package/packages/app-core/src/api/client-skills.d.ts.map +1 -0
  120. package/packages/app-core/src/api/client-skills.js +608 -0
  121. package/packages/app-core/src/api/client-types-babylon.d.ts +254 -0
  122. package/packages/app-core/src/api/client-types-babylon.d.ts.map +1 -0
  123. package/packages/app-core/src/api/client-types-babylon.js +2 -0
  124. package/packages/app-core/src/api/client-types-character.d.ts +39 -0
  125. package/packages/app-core/src/api/client-types-character.d.ts.map +1 -0
  126. package/packages/app-core/src/api/client-types-character.js +1 -0
  127. package/packages/app-core/src/api/client-types-chat.d.ts +428 -0
  128. package/packages/app-core/src/api/client-types-chat.d.ts.map +1 -0
  129. package/packages/app-core/src/api/client-types-chat.js +9 -0
  130. package/packages/app-core/src/api/client-types-config.d.ts +587 -0
  131. package/packages/app-core/src/api/client-types-config.d.ts.map +1 -0
  132. package/packages/app-core/src/api/client-types-config.js +5 -0
  133. package/packages/app-core/src/api/client-types-experience.d.ts +97 -0
  134. package/packages/app-core/src/api/client-types-experience.d.ts.map +1 -0
  135. package/packages/app-core/src/api/client-types-experience.js +1 -0
  136. package/packages/app-core/src/api/client-types-relationships.d.ts +181 -0
  137. package/packages/app-core/src/api/client-types-relationships.d.ts.map +1 -0
  138. package/packages/app-core/src/api/client-types-relationships.js +1 -0
  139. package/packages/app-core/src/api/client-types-steward.d.ts +85 -0
  140. package/packages/app-core/src/api/client-types-steward.d.ts.map +1 -0
  141. package/packages/app-core/src/api/client-types-steward.js +9 -0
  142. package/packages/app-core/src/api/client-types.d.ts +9 -0
  143. package/packages/app-core/src/api/client-types.d.ts.map +1 -0
  144. package/packages/app-core/src/api/client-types.js +12 -0
  145. package/packages/app-core/src/api/client-wallet.d.ts +130 -0
  146. package/packages/app-core/src/api/client-wallet.d.ts.map +1 -0
  147. package/packages/app-core/src/api/client-wallet.js +228 -0
  148. package/packages/app-core/src/api/client.d.ts +36 -0
  149. package/packages/app-core/src/api/client.d.ts.map +1 -0
  150. package/packages/app-core/src/api/client.js +36 -0
  151. package/packages/app-core/src/api/index.d.ts +2 -0
  152. package/packages/app-core/src/api/index.d.ts.map +1 -0
  153. package/packages/app-core/src/api/index.js +1 -0
  154. package/packages/app-core/src/bridge/electrobun-rpc.d.ts +57 -0
  155. package/packages/app-core/src/bridge/electrobun-rpc.d.ts.map +1 -0
  156. package/packages/app-core/src/bridge/electrobun-rpc.js +87 -0
  157. package/packages/app-core/src/bridge/electrobun-runtime.d.ts +3 -0
  158. package/packages/app-core/src/bridge/electrobun-runtime.d.ts.map +1 -0
  159. package/packages/app-core/src/bridge/electrobun-runtime.js +34 -0
  160. package/packages/app-core/src/bridge/native-plugins.d.ts +504 -0
  161. package/packages/app-core/src/bridge/native-plugins.d.ts.map +1 -0
  162. package/packages/app-core/src/bridge/native-plugins.js +67 -0
  163. package/packages/app-core/src/chat/coding-agent-session-state.d.ts +16 -0
  164. package/packages/app-core/src/chat/coding-agent-session-state.d.ts.map +1 -0
  165. package/packages/app-core/src/chat/coding-agent-session-state.js +27 -0
  166. package/packages/app-core/src/components/pages/browser-workspace-wallet.d.ts +80 -0
  167. package/packages/app-core/src/components/pages/browser-workspace-wallet.d.ts.map +1 -0
  168. package/packages/app-core/src/components/pages/browser-workspace-wallet.js +135 -0
  169. package/packages/app-core/src/services/account-pool.d.ts +98 -0
  170. package/packages/app-core/src/services/account-pool.d.ts.map +1 -0
  171. package/packages/app-core/src/services/account-pool.js +506 -0
  172. package/packages/app-core/src/services/account-usage.d.ts +75 -0
  173. package/packages/app-core/src/services/account-usage.d.ts.map +1 -0
  174. package/packages/app-core/src/services/account-usage.js +179 -0
  175. package/packages/app-core/src/services/local-inference/active-model.d.ts +59 -0
  176. package/packages/app-core/src/services/local-inference/active-model.d.ts.map +1 -0
  177. package/packages/app-core/src/services/local-inference/active-model.js +120 -0
  178. package/packages/app-core/src/services/local-inference/device-bridge.d.ts +131 -0
  179. package/packages/app-core/src/services/local-inference/device-bridge.d.ts.map +1 -0
  180. package/packages/app-core/src/services/local-inference/device-bridge.js +748 -0
  181. package/packages/app-core/src/services/local-inference/engine.d.ts +52 -0
  182. package/packages/app-core/src/services/local-inference/engine.d.ts.map +1 -0
  183. package/packages/app-core/src/services/local-inference/engine.js +138 -0
  184. package/packages/app-core/src/services/local-inference/external-scanner.d.ts +17 -0
  185. package/packages/app-core/src/services/local-inference/external-scanner.d.ts.map +1 -0
  186. package/packages/app-core/src/services/local-inference/external-scanner.js +261 -0
  187. package/packages/app-core/src/services/local-inference/handler-registry.d.ts +72 -0
  188. package/packages/app-core/src/services/local-inference/handler-registry.d.ts.map +1 -0
  189. package/packages/app-core/src/services/local-inference/handler-registry.js +160 -0
  190. package/packages/app-core/src/services/local-inference/paths.d.ts +24 -0
  191. package/packages/app-core/src/services/local-inference/paths.d.ts.map +1 -0
  192. package/packages/app-core/src/services/local-inference/paths.js +41 -0
  193. package/packages/app-core/src/services/local-inference/providers.d.ts +61 -0
  194. package/packages/app-core/src/services/local-inference/providers.d.ts.map +1 -0
  195. package/packages/app-core/src/services/local-inference/providers.js +277 -0
  196. package/packages/app-core/src/services/local-inference/registry.d.ts +35 -0
  197. package/packages/app-core/src/services/local-inference/registry.d.ts.map +1 -0
  198. package/packages/app-core/src/services/local-inference/registry.js +108 -0
  199. package/packages/app-core/src/services/local-inference/routing-preferences.d.ts +31 -0
  200. package/packages/app-core/src/services/local-inference/routing-preferences.d.ts.map +1 -0
  201. package/packages/app-core/src/services/local-inference/routing-preferences.js +72 -0
  202. package/packages/app-core/src/services/local-inference/types.d.ts +121 -0
  203. package/packages/app-core/src/services/local-inference/types.d.ts.map +1 -0
  204. package/packages/app-core/src/services/local-inference/types.js +14 -0
  205. package/packages/app-core/src/services/local-inference/verify.d.ts +39 -0
  206. package/packages/app-core/src/services/local-inference/verify.d.ts.map +1 -0
  207. package/packages/app-core/src/services/local-inference/verify.js +104 -0
  208. package/packages/app-core/src/types/index.d.ts +658 -0
  209. package/packages/app-core/src/types/index.d.ts.map +1 -0
  210. package/packages/app-core/src/types/index.js +4 -0
  211. package/packages/app-core/src/utils/assistant-text.d.ts +2 -0
  212. package/packages/app-core/src/utils/assistant-text.d.ts.map +1 -0
  213. package/packages/app-core/src/utils/assistant-text.js +167 -0
  214. package/packages/app-core/src/utils/eliza-globals.d.ts +15 -0
  215. package/packages/app-core/src/utils/eliza-globals.d.ts.map +1 -0
  216. package/packages/app-core/src/utils/eliza-globals.js +50 -0
  217. package/packages/app-core/src/utils/streaming-text.d.ts +9 -0
  218. package/packages/app-core/src/utils/streaming-text.d.ts.map +1 -0
  219. package/packages/app-core/src/utils/streaming-text.js +112 -0
  220. package/packages/shared/src/format-error.d.ts +14 -0
  221. package/packages/shared/src/format-error.d.ts.map +1 -0
  222. package/packages/shared/src/format-error.js +17 -0
  223. package/packages/shared/src/index.d.ts +1 -0
  224. package/packages/shared/src/index.d.ts.map +1 -1
  225. package/packages/shared/src/index.js +1 -0
  226. package/packages/typescript/src/runtime.d.ts +14 -0
  227. package/packages/typescript/src/runtime.d.ts.map +1 -1
  228. package/packages/typescript/src/runtime.js +42 -0
  229. package/packages/typescript/src/services/message.d.ts +8 -0
  230. package/packages/typescript/src/services/message.d.ts.map +1 -1
  231. package/packages/typescript/src/services/message.js +51 -0
  232. package/packages/typescript/src/services/task.d.ts +1 -0
  233. package/packages/typescript/src/services/task.d.ts.map +1 -1
  234. package/packages/typescript/src/services/task.js +26 -3
  235. package/apps/app-task-coordinator/src/api/coordinator-wiring.d.ts.map +0 -1
  236. /package/{apps/app-task-coordinator → packages/agent}/src/api/coordinator-wiring.d.ts +0 -0
  237. /package/{apps/app-task-coordinator → packages/agent}/src/api/coordinator-wiring.js +0 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Account usage probes + local JSONL counters.
3
+ *
4
+ * Two responsibilities:
5
+ * 1. Probe provider usage APIs (`pollAnthropicUsage`, `pollCodexUsage`)
6
+ * to populate the `LinkedAccountUsage` snapshot on each account.
7
+ * 2. Maintain append-only JSONL counters per `(providerId, accountId, day)`
8
+ * so we can answer "calls made today / tokens used / errors" without
9
+ * re-reading every trajectory.
10
+ *
11
+ * The probes throw on HTTP error so the caller can decide whether to mark
12
+ * the account as `rate-limited` / `needs-reauth` / `invalid`. The counters
13
+ * are best-effort and synchronous — at our scale appendFileSync is fine.
14
+ */
15
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
16
+ import os from "node:os";
17
+ import path from "node:path";
18
+ const ANTHROPIC_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
19
+ const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
20
+ function utilizationToPct(value) {
21
+ if (typeof value !== "number" || !Number.isFinite(value))
22
+ return undefined;
23
+ // Provider returns either 0..1 (legacy) or 0..100 — both are normalized
24
+ // to percent. Anthropic ships 0..1, so we always multiply.
25
+ return Math.max(0, Math.min(100, value * 100));
26
+ }
27
+ function normalizeResetTimestamp(value) {
28
+ if (typeof value === "number" && Number.isFinite(value)) {
29
+ // Heuristic: epoch seconds vs ms. Seconds will be ~1.7e9 today; ms is ~1.7e12.
30
+ return value < 1e12 ? value * 1000 : value;
31
+ }
32
+ if (typeof value === "string" && value.length > 0) {
33
+ const parsed = Date.parse(value);
34
+ return Number.isFinite(parsed) ? parsed : undefined;
35
+ }
36
+ return undefined;
37
+ }
38
+ /**
39
+ * Probe Anthropic's OAuth usage endpoint.
40
+ *
41
+ * Endpoint: `GET https://api.anthropic.com/api/oauth/usage`
42
+ * Headers : `Authorization: Bearer <accessToken>`,
43
+ * `anthropic-beta: oauth-2025-04-20`,
44
+ * `Content-Type: application/json`
45
+ *
46
+ * Handles both legacy flat (`five_hour_utilization`) and new nested
47
+ * (`five_hour: { utilization }`) response shapes. Throws on any HTTP
48
+ * error with the status code included in the message.
49
+ */
50
+ export async function pollAnthropicUsage(accessToken, fetchImpl = fetch) {
51
+ const res = await fetchImpl(ANTHROPIC_USAGE_URL, {
52
+ method: "GET",
53
+ headers: {
54
+ Authorization: `Bearer ${accessToken}`,
55
+ "anthropic-beta": "oauth-2025-04-20",
56
+ "Content-Type": "application/json",
57
+ },
58
+ });
59
+ if (!res.ok) {
60
+ throw new Error(`Anthropic usage probe failed: HTTP ${res.status}`);
61
+ }
62
+ const payload = (await res.json());
63
+ const fiveHour = payload.five_hour;
64
+ const sevenDay = payload.seven_day;
65
+ const sessionPct = utilizationToPct(fiveHour?.utilization) ??
66
+ utilizationToPct(payload.five_hour_utilization);
67
+ const weeklyPct = utilizationToPct(sevenDay?.utilization) ??
68
+ utilizationToPct(payload.seven_day_utilization);
69
+ const resetsAt = normalizeResetTimestamp(fiveHour?.resets_at) ??
70
+ normalizeResetTimestamp(payload.five_hour_resets_at);
71
+ return {
72
+ refreshedAt: Date.now(),
73
+ ...(sessionPct !== undefined ? { sessionPct } : {}),
74
+ ...(weeklyPct !== undefined ? { weeklyPct } : {}),
75
+ ...(resetsAt !== undefined ? { resetsAt } : {}),
76
+ };
77
+ }
78
+ /**
79
+ * Probe Codex / ChatGPT's usage endpoint.
80
+ *
81
+ * Endpoint: `GET https://chatgpt.com/backend-api/wham/usage`
82
+ * Headers : `Authorization: Bearer <accessToken>`,
83
+ * `ChatGPT-Account-Id: <openAIAccountId>`,
84
+ * `User-Agent: codex-cli`
85
+ *
86
+ * `used_percent` is already on the 0..100 scale. `reset_at` is epoch
87
+ * seconds. Codex has no weekly equivalent, so `weeklyPct` stays undefined.
88
+ */
89
+ export async function pollCodexUsage(accessToken, accountId, fetchImpl = fetch) {
90
+ const res = await fetchImpl(CODEX_USAGE_URL, {
91
+ method: "GET",
92
+ headers: {
93
+ Authorization: `Bearer ${accessToken}`,
94
+ "ChatGPT-Account-Id": accountId,
95
+ "User-Agent": "codex-cli",
96
+ },
97
+ });
98
+ if (!res.ok) {
99
+ throw new Error(`Codex usage probe failed: HTTP ${res.status}`);
100
+ }
101
+ const payload = (await res.json());
102
+ const primary = payload.rate_limit?.primary_window;
103
+ let sessionPct;
104
+ if (typeof primary?.used_percent === "number" &&
105
+ Number.isFinite(primary.used_percent)) {
106
+ sessionPct = Math.max(0, Math.min(100, primary.used_percent));
107
+ }
108
+ const resetsAt = normalizeResetTimestamp(primary?.reset_at);
109
+ return {
110
+ refreshedAt: Date.now(),
111
+ ...(sessionPct !== undefined ? { sessionPct } : {}),
112
+ ...(resetsAt !== undefined ? { resetsAt } : {}),
113
+ };
114
+ }
115
+ // Local JSONL counters.
116
+ function elizaHome() {
117
+ return process.env.ELIZA_HOME || path.join(os.homedir(), ".eliza");
118
+ }
119
+ function dayStamp(ts = Date.now()) {
120
+ const d = new Date(ts);
121
+ const yyyy = d.getUTCFullYear();
122
+ const mm = String(d.getUTCMonth() + 1).padStart(2, "0");
123
+ const dd = String(d.getUTCDate()).padStart(2, "0");
124
+ return `${yyyy}-${mm}-${dd}`;
125
+ }
126
+ function counterFile(providerId, accountId, ts = Date.now()) {
127
+ return path.join(elizaHome(), "usage", providerId, accountId, `${dayStamp(ts)}.jsonl`);
128
+ }
129
+ /**
130
+ * Append a usage entry for the given `(providerId, accountId)` pair.
131
+ * One line per call, written synchronously with mode 0o600. The day
132
+ * directory is created on demand.
133
+ */
134
+ export function recordCall(providerId, accountId, entry) {
135
+ const ts = Date.now();
136
+ const line = { ts, ...entry };
137
+ const file = counterFile(providerId, accountId, ts);
138
+ const dir = path.dirname(file);
139
+ if (!existsSync(dir)) {
140
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
141
+ }
142
+ appendFileSync(file, `${JSON.stringify(line)}\n`, {
143
+ flag: "a",
144
+ mode: 0o600,
145
+ });
146
+ }
147
+ /**
148
+ * Read today's JSONL and aggregate `(calls, tokens, errors)`. Lines that
149
+ * fail to parse are skipped silently (best-effort).
150
+ */
151
+ export function readTodayCounters(providerId, accountId) {
152
+ const file = counterFile(providerId, accountId);
153
+ if (!existsSync(file)) {
154
+ return { calls: 0, tokens: 0, errors: 0 };
155
+ }
156
+ const raw = readFileSync(file, "utf-8");
157
+ let calls = 0;
158
+ let tokens = 0;
159
+ let errors = 0;
160
+ for (const line of raw.split("\n")) {
161
+ if (!line.trim())
162
+ continue;
163
+ let parsed;
164
+ try {
165
+ parsed = JSON.parse(line);
166
+ }
167
+ catch {
168
+ continue;
169
+ }
170
+ calls += 1;
171
+ if (typeof parsed.tokens === "number" && Number.isFinite(parsed.tokens)) {
172
+ tokens += parsed.tokens;
173
+ }
174
+ if (parsed.ok === false) {
175
+ errors += 1;
176
+ }
177
+ }
178
+ return { calls, tokens, errors };
179
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Coordinates which model is currently loaded into the plugin-local-ai
3
+ * runtime. Milady runs one inference model at a time; switching models
4
+ * unloads the previous one first so we don't double-allocate VRAM.
5
+ *
6
+ * This module *does not* talk to `node-llama-cpp` directly. The plugin
7
+ * owns the native binding; we ask it to swap via a small runtime service
8
+ * registered under the name "localInferenceLoader". When the plugin is not
9
+ * enabled, we still track the user's preferred active model so the
10
+ * preference survives enabling the plugin later.
11
+ */
12
+ import type { AgentRuntime } from "@elizaos/core";
13
+ import type { ActiveModelState, InstalledModel } from "./types";
14
+ export interface LocalInferenceLoader {
15
+ loadModel(args: {
16
+ modelPath: string;
17
+ }): Promise<void>;
18
+ unloadModel(): Promise<void>;
19
+ currentModelPath(): string | null;
20
+ /**
21
+ * Optional generation surface. When a loader implements this, the runtime
22
+ * handler (`ensure-local-inference-handler.ts`) routes TEXT_SMALL /
23
+ * TEXT_LARGE requests through it instead of the standalone engine. Mobile
24
+ * builds populate this via the Capacitor adapter; desktop leaves it
25
+ * unimplemented and falls back to the `LocalInferenceEngine`.
26
+ */
27
+ generate?(args: {
28
+ prompt: string;
29
+ stopSequences?: string[];
30
+ maxTokens?: number;
31
+ temperature?: number;
32
+ }): Promise<string>;
33
+ /**
34
+ * Optional embedding surface. When a loader implements this, the runtime
35
+ * handler routes `TEXT_EMBEDDING` requests through it. The AOSP bun:ffi
36
+ * loader populates this directly via `llama_get_embeddings_seq`; the
37
+ * device-bridge loader populates it by dispatching an `embed` frame to
38
+ * the connected device. Loaders that cannot embed leave this undefined,
39
+ * and the runtime falls back to its non-local embedding provider chain.
40
+ */
41
+ embed?(args: {
42
+ input: string;
43
+ }): Promise<{
44
+ embedding: number[];
45
+ tokens: number;
46
+ }>;
47
+ }
48
+ export declare class ActiveModelCoordinator {
49
+ private state;
50
+ private readonly listeners;
51
+ snapshot(): ActiveModelState;
52
+ subscribe(listener: (state: ActiveModelState) => void): () => void;
53
+ private emit;
54
+ /** Return the loader service from the current runtime, if registered. */
55
+ private getLoader;
56
+ switchTo(runtime: AgentRuntime | null, installed: InstalledModel): Promise<ActiveModelState>;
57
+ unload(runtime: AgentRuntime | null): Promise<ActiveModelState>;
58
+ }
59
+ //# sourceMappingURL=active-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-model.d.ts","sourceRoot":"","sources":["../../../../../../../app-core/src/services/local-inference/active-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,IAAI,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACvC,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAYD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,KAAK,CAIX;IAEF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgD;IAE1E,QAAQ,IAAI,gBAAgB;IAI5B,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlE,OAAO,CAAC,IAAI;IAWZ,yEAAyE;IACzE,OAAO,CAAC,SAAS;IAUX,QAAQ,CACZ,OAAO,EAAE,YAAY,GAAG,IAAI,EAC5B,SAAS,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC;IA0CtB,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAsBtE"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Coordinates which model is currently loaded into the plugin-local-ai
3
+ * runtime. Milady runs one inference model at a time; switching models
4
+ * unloads the previous one first so we don't double-allocate VRAM.
5
+ *
6
+ * This module *does not* talk to `node-llama-cpp` directly. The plugin
7
+ * owns the native binding; we ask it to swap via a small runtime service
8
+ * registered under the name "localInferenceLoader". When the plugin is not
9
+ * enabled, we still track the user's preferred active model so the
10
+ * preference survives enabling the plugin later.
11
+ */
12
+ import { localInferenceEngine } from "./engine";
13
+ import { touchMiladyModel } from "./registry";
14
+ function isLoader(value) {
15
+ if (!value || typeof value !== "object")
16
+ return false;
17
+ const candidate = value;
18
+ return (typeof candidate.loadModel === "function" &&
19
+ typeof candidate.unloadModel === "function" &&
20
+ typeof candidate.currentModelPath === "function");
21
+ }
22
+ export class ActiveModelCoordinator {
23
+ state = {
24
+ modelId: null,
25
+ loadedAt: null,
26
+ status: "idle",
27
+ };
28
+ listeners = new Set();
29
+ snapshot() {
30
+ return { ...this.state };
31
+ }
32
+ subscribe(listener) {
33
+ this.listeners.add(listener);
34
+ return () => {
35
+ this.listeners.delete(listener);
36
+ };
37
+ }
38
+ emit() {
39
+ const current = { ...this.state };
40
+ for (const listener of this.listeners) {
41
+ try {
42
+ listener(current);
43
+ }
44
+ catch {
45
+ this.listeners.delete(listener);
46
+ }
47
+ }
48
+ }
49
+ /** Return the loader service from the current runtime, if registered. */
50
+ getLoader(runtime) {
51
+ if (!runtime)
52
+ return null;
53
+ const candidate = runtime.getService?.("localInferenceLoader");
54
+ return isLoader(candidate) ? candidate : null;
55
+ }
56
+ async switchTo(runtime, installed) {
57
+ this.state = {
58
+ modelId: installed.id,
59
+ loadedAt: null,
60
+ status: "loading",
61
+ };
62
+ this.emit();
63
+ // Prefer a runtime-registered loader (plugin-local-ai or equivalent)
64
+ // when present — it will already have warmed up the right configuration.
65
+ // Otherwise, fall back to the standalone engine, which is the default
66
+ // path for users who haven't separately enabled plugin-local-ai.
67
+ const loader = this.getLoader(runtime);
68
+ try {
69
+ if (loader) {
70
+ await loader.unloadModel();
71
+ await loader.loadModel({ modelPath: installed.path });
72
+ }
73
+ else {
74
+ await localInferenceEngine.load(installed.path);
75
+ }
76
+ this.state = {
77
+ modelId: installed.id,
78
+ loadedAt: new Date().toISOString(),
79
+ status: "ready",
80
+ };
81
+ if (installed.source === "milady-download") {
82
+ await touchMiladyModel(installed.id);
83
+ }
84
+ }
85
+ catch (err) {
86
+ this.state = {
87
+ modelId: installed.id,
88
+ loadedAt: null,
89
+ status: "error",
90
+ error: err instanceof Error ? err.message : String(err),
91
+ };
92
+ }
93
+ this.emit();
94
+ return this.snapshot();
95
+ }
96
+ async unload(runtime) {
97
+ const loader = this.getLoader(runtime);
98
+ try {
99
+ if (loader) {
100
+ await loader.unloadModel();
101
+ }
102
+ else {
103
+ await localInferenceEngine.unload();
104
+ }
105
+ }
106
+ catch (err) {
107
+ this.state = {
108
+ modelId: null,
109
+ loadedAt: null,
110
+ status: "error",
111
+ error: err instanceof Error ? err.message : String(err),
112
+ };
113
+ this.emit();
114
+ return this.snapshot();
115
+ }
116
+ this.state = { modelId: null, loadedAt: null, status: "idle" };
117
+ this.emit();
118
+ return this.snapshot();
119
+ }
120
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Device-bridge: agent-side half of the "inference on the user's phone,
3
+ * agent in a container" architecture.
4
+ *
5
+ * Multi-device aware. Any number of devices can dial in; each `generate`
6
+ * is routed to the highest-scoring connected device at call time. A phone
7
+ * and a Mac paired to the same agent → requests go to the Mac; when the
8
+ * Mac disconnects, new requests fall through to the phone automatically.
9
+ *
10
+ * Scoring (higher = preferred):
11
+ * - desktop / electrobun: 100 base
12
+ * - ios / android: 10 base
13
+ * - per GB of total RAM: +2
14
+ * - per GB of VRAM: +5 (dedicated GPU wins big)
15
+ * - has loaded the right model already: +50 (avoid a swap)
16
+ *
17
+ * Disconnect tolerance
18
+ * --------------------
19
+ * A pending request stays in `pendingGenerates` until either (a) a device
20
+ * (same or different) returns a matching correlation-id, or (b) the
21
+ * timeout fires. On any device (re)connect we re-route orphaned
22
+ * generates to the new best device.
23
+ *
24
+ * Durability
25
+ * ----------
26
+ * Pending requests are best-effort persisted to a JSON log under
27
+ * `$ELIZA_STATE_DIR/local-inference/pending-requests.json` so a brief
28
+ * agent restart doesn't lose the queue. Persistence is async and
29
+ * non-blocking — failures fall back to in-memory only.
30
+ */
31
+ import type { Server as HttpServer } from "node:http";
32
+ import type { AgentRuntime } from "@elizaos/core";
33
+ interface DeviceCapabilities {
34
+ platform: "ios" | "android" | "web" | "electrobun" | "desktop";
35
+ deviceModel: string;
36
+ totalRamGb: number;
37
+ cpuCores: number;
38
+ gpu: {
39
+ backend: "metal" | "vulkan" | "gpu-delegate" | "cuda";
40
+ available: boolean;
41
+ totalVramGb?: number;
42
+ } | null;
43
+ }
44
+ export interface DeviceSummary {
45
+ deviceId: string;
46
+ capabilities: DeviceCapabilities;
47
+ loadedPath: string | null;
48
+ connectedSince: string;
49
+ score: number;
50
+ activeRequests: number;
51
+ isPrimary: boolean;
52
+ }
53
+ export interface DeviceBridgeStatus {
54
+ /** True if any device is currently connected. */
55
+ connected: boolean;
56
+ devices: DeviceSummary[];
57
+ /** Device id of the current best-score device, or null when none. */
58
+ primaryDeviceId: string | null;
59
+ /** Total generates/loads/unloads queued (either in-flight or awaiting a device). */
60
+ pendingRequests: number;
61
+ deviceId: string | null;
62
+ capabilities: DeviceCapabilities | null;
63
+ loadedPath: string | null;
64
+ connectedSince: string | null;
65
+ }
66
+ export declare class DeviceBridge {
67
+ private readonly devices;
68
+ private wss;
69
+ private restored;
70
+ private readonly pendingLoads;
71
+ private readonly pendingUnloads;
72
+ private readonly pendingGenerates;
73
+ private readonly pendingEmbeds;
74
+ private readonly statusListeners;
75
+ private readonly expectedPairingToken;
76
+ status(): DeviceBridgeStatus;
77
+ private countRouted;
78
+ subscribeStatus(listener: (status: DeviceBridgeStatus) => void): () => void;
79
+ private emitStatus;
80
+ attachToHttpServer(server: HttpServer): Promise<void>;
81
+ private handleConnection;
82
+ private onDeviceRegistered;
83
+ private onDeviceDisconnected;
84
+ private handleDeviceMessage;
85
+ private sendToDevice;
86
+ /** Highest-scoring connected device, optionally boosted for an already-loaded model. */
87
+ private pickBestDevice;
88
+ loadModel(args: {
89
+ modelPath: string;
90
+ contextSize?: number;
91
+ useGpu?: boolean;
92
+ }): Promise<void>;
93
+ unloadModel(): Promise<void>;
94
+ currentModelPath(): string | null;
95
+ embed(args: {
96
+ input: string;
97
+ }): Promise<{
98
+ embedding: number[];
99
+ tokens: number;
100
+ }>;
101
+ generate(args: {
102
+ prompt: string;
103
+ stopSequences?: string[];
104
+ maxTokens?: number;
105
+ temperature?: number;
106
+ }): Promise<string>;
107
+ private pendingLogPath;
108
+ /**
109
+ * Rewrite the pending-generate log. Called after every mutation to the
110
+ * pendingGenerates map. We only persist `generate` — loads/unloads are
111
+ * bound to a specific device's current state and aren't safely replayable
112
+ * across restart.
113
+ */
114
+ private persistPendingGenerates;
115
+ /**
116
+ * On startup, read persisted pending requests back into memory. Their
117
+ * promises are gone (the original caller's process is dead) so they can
118
+ * only be resolved externally — for now we just re-queue them with a
119
+ * fresh timeout, and the first device that connects will process them.
120
+ * If nothing consumes them within the timeout they reject quietly.
121
+ *
122
+ * Stale entries older than 24h are purged rather than resurrected.
123
+ */
124
+ private restorePendingGenerates;
125
+ }
126
+ export declare const deviceBridge: DeviceBridge;
127
+ export declare function registerDeviceBridgeLoader(runtime: AgentRuntime & {
128
+ registerService?: (name: string, impl: unknown) => unknown;
129
+ }): void;
130
+ export {};
131
+ //# sourceMappingURL=device-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-bridge.d.ts","sourceRoot":"","sources":["../../../../../../../app-core/src/services/local-inference/device-bridge.ts"],"names":[],"mappings":"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"}