@elizaos/plugin-local-inference 2.0.0-beta.1 → 2.0.11-beta.7

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 (676) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/package.json +81 -15
  4. package/src/actions/generate-media.d.ts +59 -0
  5. package/src/actions/generate-media.d.ts.map +1 -0
  6. package/src/actions/generate-media.ts +647 -0
  7. package/src/actions/identify-speaker.d.ts +23 -0
  8. package/src/actions/identify-speaker.d.ts.map +1 -0
  9. package/src/actions/identify-speaker.ts +171 -0
  10. package/src/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
  11. package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
  12. package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
  13. package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
  14. package/src/adapters/capacitor-llama/environment.ts +71 -0
  15. package/src/adapters/capacitor-llama/index.browser.ts +83 -0
  16. package/src/adapters/capacitor-llama/index.ts +807 -0
  17. package/src/adapters/capacitor-llama/loader.ts +109 -0
  18. package/src/adapters/capacitor-llama/structured-output.ts +165 -0
  19. package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
  20. package/src/adapters/capacitor-llama/types.ts +374 -0
  21. package/src/backends/apple-foundation.ts +127 -0
  22. package/src/index.d.ts +7 -0
  23. package/src/index.d.ts.map +1 -0
  24. package/src/index.ts +54 -0
  25. package/src/local-inference-routes.d.ts +38 -0
  26. package/src/local-inference-routes.d.ts.map +1 -0
  27. package/src/local-inference-routes.test.ts +344 -0
  28. package/src/local-inference-routes.ts +1543 -0
  29. package/src/provider.d.ts +21 -0
  30. package/src/provider.d.ts.map +1 -0
  31. package/src/provider.ts +1171 -0
  32. package/src/routes/compat-helpers.d.ts +18 -0
  33. package/src/routes/compat-helpers.d.ts.map +1 -0
  34. package/src/routes/compat-helpers.ts +274 -0
  35. package/src/routes/family-member-route.d.ts +62 -0
  36. package/src/routes/family-member-route.d.ts.map +1 -0
  37. package/src/routes/family-member-route.ts +353 -0
  38. package/src/routes/index.d.ts +19 -0
  39. package/src/routes/index.d.ts.map +1 -0
  40. package/src/routes/index.ts +60 -0
  41. package/src/routes/live-diarization-route.d.ts +26 -0
  42. package/src/routes/live-diarization-route.d.ts.map +1 -0
  43. package/src/routes/live-diarization-route.test.ts +213 -0
  44. package/src/routes/live-diarization-route.ts +122 -0
  45. package/src/routes/local-inference-asr-route.d.ts +4 -0
  46. package/src/routes/local-inference-asr-route.d.ts.map +1 -0
  47. package/src/routes/local-inference-asr-route.test.ts +190 -0
  48. package/src/routes/local-inference-asr-route.ts +213 -0
  49. package/src/routes/local-inference-compat-routes.d.ts +16 -0
  50. package/src/routes/local-inference-compat-routes.d.ts.map +1 -0
  51. package/src/routes/local-inference-compat-routes.test.ts +423 -0
  52. package/src/routes/local-inference-compat-routes.ts +782 -0
  53. package/src/routes/local-inference-tts-route.d.ts +7 -0
  54. package/src/routes/local-inference-tts-route.d.ts.map +1 -0
  55. package/src/routes/local-inference-tts-route.test.ts +179 -0
  56. package/src/routes/local-inference-tts-route.ts +230 -0
  57. package/src/routes/voice-first-run-routes.d.ts +62 -0
  58. package/src/routes/voice-first-run-routes.d.ts.map +1 -0
  59. package/src/routes/voice-first-run-routes.ts +524 -0
  60. package/src/routes/voice-models-routes.d.ts +62 -0
  61. package/src/routes/voice-models-routes.d.ts.map +1 -0
  62. package/src/routes/voice-models-routes.ts +554 -0
  63. package/src/routes/voice-profile-plugin-routes.d.ts +19 -0
  64. package/src/routes/voice-profile-plugin-routes.d.ts.map +1 -0
  65. package/src/routes/voice-profile-plugin-routes.ts +138 -0
  66. package/src/routes/voice-profiles-management-routes.d.ts +52 -0
  67. package/src/routes/voice-profiles-management-routes.d.ts.map +1 -0
  68. package/src/routes/voice-profiles-management-routes.ts +476 -0
  69. package/src/routes/voice-speaker-profile-routes.d.ts +57 -0
  70. package/src/routes/voice-speaker-profile-routes.d.ts.map +1 -0
  71. package/src/routes/voice-speaker-profile-routes.ts +199 -0
  72. package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
  73. package/src/runtime/capacitor-llama.d.ts +25 -0
  74. package/src/runtime/embedding-manager-support.d.ts +77 -0
  75. package/src/runtime/embedding-manager-support.d.ts.map +1 -0
  76. package/src/runtime/embedding-manager-support.ts +497 -0
  77. package/src/runtime/embedding-presets.d.ts +16 -0
  78. package/src/runtime/embedding-presets.d.ts.map +1 -0
  79. package/src/runtime/embedding-presets.ts +81 -0
  80. package/src/runtime/embedding-warmup-policy.d.ts +14 -0
  81. package/src/runtime/embedding-warmup-policy.d.ts.map +1 -0
  82. package/src/runtime/embedding-warmup-policy.test.ts +53 -0
  83. package/src/runtime/embedding-warmup-policy.ts +48 -0
  84. package/src/runtime/ensure-local-inference-handler.d.ts +53 -0
  85. package/src/runtime/ensure-local-inference-handler.d.ts.map +1 -0
  86. package/src/runtime/ensure-local-inference-handler.test.ts +528 -0
  87. package/src/runtime/ensure-local-inference-handler.ts +1398 -0
  88. package/src/runtime/index.d.ts +14 -0
  89. package/src/runtime/index.d.ts.map +1 -0
  90. package/src/runtime/index.ts +27 -0
  91. package/src/runtime/mobile-local-inference-gate.d.ts +31 -0
  92. package/src/runtime/mobile-local-inference-gate.d.ts.map +1 -0
  93. package/src/runtime/mobile-local-inference-gate.test.ts +69 -0
  94. package/src/runtime/mobile-local-inference-gate.ts +44 -0
  95. package/src/runtime/voice-entity-binding.d.ts +103 -0
  96. package/src/runtime/voice-entity-binding.d.ts.map +1 -0
  97. package/src/runtime/voice-entity-binding.transcript.test.ts +69 -0
  98. package/src/runtime/voice-entity-binding.ts +328 -0
  99. package/src/services/README.md +71 -0
  100. package/src/services/__tests__/backend-selector.test.ts +101 -0
  101. package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
  102. package/src/services/__tests__/gpu-autotune.test.ts +400 -0
  103. package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
  104. package/src/services/__tests__/planner-grammar.test.ts +372 -0
  105. package/src/services/__tests__/runtime-target.test.ts +176 -0
  106. package/src/services/active-model-switch-rollback.test.ts +183 -0
  107. package/src/services/active-model.d.ts +282 -0
  108. package/src/services/active-model.d.ts.map +1 -0
  109. package/src/services/active-model.ts +1213 -0
  110. package/src/services/asr/errors.d.ts +21 -0
  111. package/src/services/asr/errors.d.ts.map +1 -0
  112. package/src/services/asr/errors.ts +50 -0
  113. package/src/services/asr/hash.d.ts +28 -0
  114. package/src/services/asr/hash.d.ts.map +1 -0
  115. package/src/services/asr/hash.ts +49 -0
  116. package/src/services/asr/index.d.ts +76 -0
  117. package/src/services/asr/index.d.ts.map +1 -0
  118. package/src/services/asr/index.ts +178 -0
  119. package/src/services/asr/types.d.ts +91 -0
  120. package/src/services/asr/types.d.ts.map +1 -0
  121. package/src/services/asr/types.ts +95 -0
  122. package/src/services/assignments.d.ts +71 -0
  123. package/src/services/assignments.d.ts.map +1 -0
  124. package/src/services/assignments.test.ts +80 -0
  125. package/src/services/assignments.ts +230 -0
  126. package/src/services/backend-selector.ts +95 -0
  127. package/src/services/backend.d.ts +346 -0
  128. package/src/services/backend.d.ts.map +1 -0
  129. package/src/services/backend.ts +612 -0
  130. package/src/services/bundled-models.d.ts +34 -0
  131. package/src/services/bundled-models.d.ts.map +1 -0
  132. package/src/services/bundled-models.ts +129 -0
  133. package/src/services/cache-bridge.d.ts +206 -0
  134. package/src/services/cache-bridge.d.ts.map +1 -0
  135. package/src/services/cache-bridge.test.ts +516 -0
  136. package/src/services/cache-bridge.ts +423 -0
  137. package/src/services/catalog.d.ts +10 -0
  138. package/src/services/catalog.d.ts.map +1 -0
  139. package/src/services/catalog.test.ts +240 -0
  140. package/src/services/catalog.ts +27 -0
  141. package/src/services/checkpoint-client.d.ts +109 -0
  142. package/src/services/checkpoint-client.d.ts.map +1 -0
  143. package/src/services/checkpoint-client.ts +258 -0
  144. package/src/services/checkpoint-manager.ts +474 -0
  145. package/src/services/cloud-fallback.d.ts +102 -0
  146. package/src/services/cloud-fallback.d.ts.map +1 -0
  147. package/src/services/cloud-fallback.ts +230 -0
  148. package/src/services/conversation-registry.d.ts +142 -0
  149. package/src/services/conversation-registry.d.ts.map +1 -0
  150. package/src/services/conversation-registry.test.ts +235 -0
  151. package/src/services/conversation-registry.ts +264 -0
  152. package/src/services/desktop-fused-ffi-backend-runtime.d.ts +92 -0
  153. package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
  154. package/src/services/desktop-fused-ffi-backend-runtime.ts +333 -0
  155. package/src/services/device-bridge.d.ts +188 -0
  156. package/src/services/device-bridge.d.ts.map +1 -0
  157. package/src/services/device-bridge.ts +1237 -0
  158. package/src/services/device-resource-metrics.d.ts +149 -0
  159. package/src/services/device-resource-metrics.d.ts.map +1 -0
  160. package/src/services/device-resource-metrics.test.ts +98 -0
  161. package/src/services/device-resource-metrics.ts +346 -0
  162. package/src/services/device-tier.d.ts +115 -0
  163. package/src/services/device-tier.d.ts.map +1 -0
  164. package/src/services/device-tier.test.ts +371 -0
  165. package/src/services/device-tier.ts +410 -0
  166. package/src/services/downloader.d.ts +82 -0
  167. package/src/services/downloader.d.ts.map +1 -0
  168. package/src/services/downloader.test.ts +724 -0
  169. package/src/services/downloader.ts +899 -0
  170. package/src/services/engine-direct-bundle.test.ts +58 -0
  171. package/src/services/engine-streaming.test.ts +80 -0
  172. package/src/services/engine.d.ts +534 -0
  173. package/src/services/engine.d.ts.map +1 -0
  174. package/src/services/engine.ts +1891 -0
  175. package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
  176. package/src/services/ensure-local-artifacts.test.ts +368 -0
  177. package/src/services/ensure-local-artifacts.ts +351 -0
  178. package/src/services/external-scanner.d.ts +17 -0
  179. package/src/services/external-scanner.d.ts.map +1 -0
  180. package/src/services/external-scanner.ts +312 -0
  181. package/src/services/ffi-llm-mock.ts +354 -0
  182. package/src/services/ffi-llm-streaming-abi.ts +442 -0
  183. package/src/services/ffi-streaming-backend.d.ts +180 -0
  184. package/src/services/ffi-streaming-backend.d.ts.map +1 -0
  185. package/src/services/ffi-streaming-backend.ts +382 -0
  186. package/src/services/ffi-streaming-runner.d.ts +122 -0
  187. package/src/services/ffi-streaming-runner.d.ts.map +1 -0
  188. package/src/services/ffi-streaming-runner.test.ts +60 -0
  189. package/src/services/ffi-streaming-runner.ts +354 -0
  190. package/src/services/ffi-unload-ordering.test.ts +162 -0
  191. package/src/services/gpu-autotune.ts +534 -0
  192. package/src/services/gpu-detect.ts +139 -0
  193. package/src/services/handler-registry.d.ts +72 -0
  194. package/src/services/handler-registry.d.ts.map +1 -0
  195. package/src/services/handler-registry.ts +240 -0
  196. package/src/services/hardware.d.ts +63 -0
  197. package/src/services/hardware.d.ts.map +1 -0
  198. package/src/services/hardware.test.ts +183 -0
  199. package/src/services/hardware.ts +404 -0
  200. package/src/services/hf-search.d.ts +26 -0
  201. package/src/services/hf-search.d.ts.map +1 -0
  202. package/src/services/hf-search.test.ts +69 -0
  203. package/src/services/hf-search.ts +420 -0
  204. package/src/services/image-description-runtime.d.ts +14 -0
  205. package/src/services/image-description-runtime.d.ts.map +1 -0
  206. package/src/services/image-description-runtime.test.ts +61 -0
  207. package/src/services/image-description-runtime.ts +118 -0
  208. package/src/services/imagegen/aosp-unavailable.d.ts +134 -0
  209. package/src/services/imagegen/aosp-unavailable.d.ts.map +1 -0
  210. package/src/services/imagegen/aosp-unavailable.ts +229 -0
  211. package/src/services/imagegen/backend-selector.d.ts +118 -0
  212. package/src/services/imagegen/backend-selector.d.ts.map +1 -0
  213. package/src/services/imagegen/backend-selector.ts +281 -0
  214. package/src/services/imagegen/coreml-unavailable.d.ts +105 -0
  215. package/src/services/imagegen/coreml-unavailable.d.ts.map +1 -0
  216. package/src/services/imagegen/coreml-unavailable.ts +237 -0
  217. package/src/services/imagegen/errors.d.ts +16 -0
  218. package/src/services/imagegen/errors.d.ts.map +1 -0
  219. package/src/services/imagegen/errors.ts +40 -0
  220. package/src/services/imagegen/index.d.ts +58 -0
  221. package/src/services/imagegen/index.d.ts.map +1 -0
  222. package/src/services/imagegen/index.ts +144 -0
  223. package/src/services/imagegen/mflux.d.ts +74 -0
  224. package/src/services/imagegen/mflux.d.ts.map +1 -0
  225. package/src/services/imagegen/mflux.ts +313 -0
  226. package/src/services/imagegen/sd-cpp.d.ts +180 -0
  227. package/src/services/imagegen/sd-cpp.d.ts.map +1 -0
  228. package/src/services/imagegen/sd-cpp.ts +718 -0
  229. package/src/services/imagegen/tensorrt-unavailable.d.ts +83 -0
  230. package/src/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
  231. package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
  232. package/src/services/imagegen/types.d.ts +181 -0
  233. package/src/services/imagegen/types.d.ts.map +1 -0
  234. package/src/services/imagegen/types.ts +193 -0
  235. package/src/services/index.d.ts +30 -0
  236. package/src/services/index.d.ts.map +1 -0
  237. package/src/services/index.ts +225 -0
  238. package/src/services/inference-capabilities.d.ts +132 -0
  239. package/src/services/inference-capabilities.d.ts.map +1 -0
  240. package/src/services/inference-capabilities.test.ts +75 -0
  241. package/src/services/inference-capabilities.ts +204 -0
  242. package/src/services/inference-telemetry.d.ts +59 -0
  243. package/src/services/inference-telemetry.d.ts.map +1 -0
  244. package/src/services/inference-telemetry.ts +143 -0
  245. package/src/services/ios-llama-streaming.ts +248 -0
  246. package/src/services/kv-spill.d.ts +189 -0
  247. package/src/services/kv-spill.d.ts.map +1 -0
  248. package/src/services/kv-spill.test.ts +222 -0
  249. package/src/services/kv-spill.ts +356 -0
  250. package/src/services/latency-trace.d.ts +346 -0
  251. package/src/services/latency-trace.d.ts.map +1 -0
  252. package/src/services/latency-trace.test.ts +266 -0
  253. package/src/services/latency-trace.ts +844 -0
  254. package/src/services/llama-server-metrics.ts +304 -0
  255. package/src/services/llm-streaming-binding.d.ts +96 -0
  256. package/src/services/llm-streaming-binding.d.ts.map +1 -0
  257. package/src/services/llm-streaming-binding.ts +136 -0
  258. package/src/services/load-args.d.ts +82 -0
  259. package/src/services/load-args.d.ts.map +1 -0
  260. package/src/services/load-args.ts +81 -0
  261. package/src/services/manifest/eliza-1.manifest.v1.json +708 -0
  262. package/src/services/manifest/index.d.ts +4 -0
  263. package/src/services/manifest/index.d.ts.map +1 -0
  264. package/src/services/manifest/index.ts +66 -0
  265. package/src/services/manifest/manifest.test.ts +693 -0
  266. package/src/services/manifest/schema.d.ts +715 -0
  267. package/src/services/manifest/schema.d.ts.map +1 -0
  268. package/src/services/manifest/schema.ts +655 -0
  269. package/src/services/manifest/types.d.ts +30 -0
  270. package/src/services/manifest/types.d.ts.map +1 -0
  271. package/src/services/manifest/types.ts +55 -0
  272. package/src/services/manifest/validator.d.ts +66 -0
  273. package/src/services/manifest/validator.d.ts.map +1 -0
  274. package/src/services/manifest/validator.ts +569 -0
  275. package/src/services/memory-arbiter.d.ts +343 -0
  276. package/src/services/memory-arbiter.d.ts.map +1 -0
  277. package/src/services/memory-arbiter.test.ts +419 -0
  278. package/src/services/memory-arbiter.ts +1000 -0
  279. package/src/services/memory-monitor.d.ts +119 -0
  280. package/src/services/memory-monitor.d.ts.map +1 -0
  281. package/src/services/memory-monitor.test.ts +208 -0
  282. package/src/services/memory-monitor.ts +296 -0
  283. package/src/services/memory-pressure.d.ts +127 -0
  284. package/src/services/memory-pressure.d.ts.map +1 -0
  285. package/src/services/memory-pressure.ts +413 -0
  286. package/src/services/mtp-doctor.d.ts +13 -0
  287. package/src/services/mtp-doctor.d.ts.map +1 -0
  288. package/src/services/mtp-doctor.ts +78 -0
  289. package/src/services/network-policy.d.ts +127 -0
  290. package/src/services/network-policy.d.ts.map +1 -0
  291. package/src/services/network-policy.ts +346 -0
  292. package/src/services/paths.d.ts +6 -0
  293. package/src/services/paths.d.ts.map +1 -0
  294. package/src/services/paths.ts +25 -0
  295. package/src/services/planner-skeleton.d.ts +124 -0
  296. package/src/services/planner-skeleton.d.ts.map +1 -0
  297. package/src/services/planner-skeleton.ts +175 -0
  298. package/src/services/providers.d.ts +38 -0
  299. package/src/services/providers.d.ts.map +1 -0
  300. package/src/services/providers.ts +507 -0
  301. package/src/services/ram-budget-cache.test.ts +163 -0
  302. package/src/services/ram-budget.d.ts +110 -0
  303. package/src/services/ram-budget.d.ts.map +1 -0
  304. package/src/services/ram-budget.ts +0 -0
  305. package/src/services/readiness.d.ts +9 -0
  306. package/src/services/readiness.d.ts.map +1 -0
  307. package/src/services/readiness.test.ts +87 -0
  308. package/src/services/readiness.ts +238 -0
  309. package/src/services/recommendation.d.ts +111 -0
  310. package/src/services/recommendation.d.ts.map +1 -0
  311. package/src/services/recommendation.ts +672 -0
  312. package/src/services/registry.d.ts +35 -0
  313. package/src/services/registry.d.ts.map +1 -0
  314. package/src/services/registry.ts +151 -0
  315. package/src/services/router-handler.d.ts +92 -0
  316. package/src/services/router-handler.d.ts.map +1 -0
  317. package/src/services/router-handler.test.ts +45 -0
  318. package/src/services/router-handler.ts +376 -0
  319. package/src/services/routing-policy.d.ts +55 -0
  320. package/src/services/routing-policy.d.ts.map +1 -0
  321. package/src/services/routing-policy.ts +228 -0
  322. package/src/services/routing-preferences.d.ts +8 -0
  323. package/src/services/routing-preferences.d.ts.map +1 -0
  324. package/src/services/routing-preferences.ts +15 -0
  325. package/src/services/runtime-target.d.ts +98 -0
  326. package/src/services/runtime-target.d.ts.map +1 -0
  327. package/src/services/runtime-target.ts +154 -0
  328. package/src/services/service.d.ts +128 -0
  329. package/src/services/service.d.ts.map +1 -0
  330. package/src/services/service.test.ts +223 -0
  331. package/src/services/service.ts +735 -0
  332. package/src/services/session-pool.d.ts +72 -0
  333. package/src/services/session-pool.d.ts.map +1 -0
  334. package/src/services/session-pool.ts +153 -0
  335. package/src/services/structured-output/deterministic-repair.d.ts +23 -0
  336. package/src/services/structured-output/deterministic-repair.d.ts.map +1 -0
  337. package/src/services/structured-output/deterministic-repair.test.ts +169 -0
  338. package/src/services/structured-output/deterministic-repair.ts +443 -0
  339. package/src/services/structured-output/index.ts +4 -0
  340. package/src/services/structured-output.d.ts +311 -0
  341. package/src/services/structured-output.d.ts.map +1 -0
  342. package/src/services/structured-output.test.ts +483 -0
  343. package/src/services/structured-output.ts +712 -0
  344. package/src/services/transcription-priority.test.ts +211 -0
  345. package/src/services/tts/errors.ts +46 -0
  346. package/src/services/tts/index.ts +214 -0
  347. package/src/services/tts/tts-audio-cache.ts +235 -0
  348. package/src/services/tts/types.ts +157 -0
  349. package/src/services/types.d.ts +19 -0
  350. package/src/services/types.d.ts.map +1 -0
  351. package/src/services/types.ts +55 -0
  352. package/src/services/verify-on-device.d.ts +34 -0
  353. package/src/services/verify-on-device.d.ts.map +1 -0
  354. package/src/services/verify-on-device.test.ts +87 -0
  355. package/src/services/verify-on-device.ts +127 -0
  356. package/src/services/verify.d.ts +8 -0
  357. package/src/services/verify.d.ts.map +1 -0
  358. package/src/services/verify.ts +13 -0
  359. package/src/services/vision/aosp-unavailable.d.ts +115 -0
  360. package/src/services/vision/aosp-unavailable.d.ts.map +1 -0
  361. package/src/services/vision/aosp-unavailable.ts +163 -0
  362. package/src/services/vision/capacitor-llama.d.ts +99 -0
  363. package/src/services/vision/capacitor-llama.d.ts.map +1 -0
  364. package/src/services/vision/capacitor-llama.ts +255 -0
  365. package/src/services/vision/cloud-fallback.d.ts +47 -0
  366. package/src/services/vision/cloud-fallback.d.ts.map +1 -0
  367. package/src/services/vision/cloud-fallback.test.ts +243 -0
  368. package/src/services/vision/cloud-fallback.ts +268 -0
  369. package/src/services/vision/fallback-chain.test.ts +86 -0
  370. package/src/services/vision/hash.d.ts +71 -0
  371. package/src/services/vision/hash.d.ts.map +1 -0
  372. package/src/services/vision/hash.ts +157 -0
  373. package/src/services/vision/index.d.ts +95 -0
  374. package/src/services/vision/index.d.ts.map +1 -0
  375. package/src/services/vision/index.ts +251 -0
  376. package/src/services/vision/llama-server.d.ts +73 -0
  377. package/src/services/vision/llama-server.d.ts.map +1 -0
  378. package/src/services/vision/llama-server.ts +177 -0
  379. package/src/services/vision/types.d.ts +153 -0
  380. package/src/services/vision/types.d.ts.map +1 -0
  381. package/src/services/vision/types.ts +154 -0
  382. package/src/services/vision/vast-fallback.d.ts +18 -0
  383. package/src/services/vision/vast-fallback.d.ts.map +1 -0
  384. package/src/services/vision/vast-fallback.ts +127 -0
  385. package/src/services/vision-embedding-cache.d.ts +98 -0
  386. package/src/services/vision-embedding-cache.d.ts.map +1 -0
  387. package/src/services/vision-embedding-cache.ts +189 -0
  388. package/src/services/voice/VOICE_WORKBENCH.md +88 -0
  389. package/src/services/voice/__test-helpers__/fake-ffi.ts +92 -0
  390. package/src/services/voice/__test-helpers__/synthetic-speech.ts +124 -0
  391. package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
  392. package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
  393. package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
  394. package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
  395. package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
  396. package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
  397. package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
  398. package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
  399. package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
  400. package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
  401. package/src/services/voice/__tests__/turn-detector-resolver.test.ts +197 -0
  402. package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
  403. package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
  404. package/src/services/voice/audio-frame-consumer.d.ts +212 -0
  405. package/src/services/voice/audio-frame-consumer.d.ts.map +1 -0
  406. package/src/services/voice/audio-frame-consumer.test.ts +343 -0
  407. package/src/services/voice/audio-frame-consumer.ts +491 -0
  408. package/src/services/voice/barge-in.d.ts +112 -0
  409. package/src/services/voice/barge-in.d.ts.map +1 -0
  410. package/src/services/voice/barge-in.test.ts +244 -0
  411. package/src/services/voice/barge-in.ts +336 -0
  412. package/src/services/voice/cancellation-coordinator.d.ts +127 -0
  413. package/src/services/voice/cancellation-coordinator.d.ts.map +1 -0
  414. package/src/services/voice/cancellation-coordinator.test.ts +196 -0
  415. package/src/services/voice/cancellation-coordinator.ts +269 -0
  416. package/src/services/voice/checkpoint-manager.d.ts +199 -0
  417. package/src/services/voice/checkpoint-manager.d.ts.map +1 -0
  418. package/src/services/voice/checkpoint-manager.ts +401 -0
  419. package/src/services/voice/checkpoint-policy.ts +336 -0
  420. package/src/services/voice/composite-eot-classifier.test.ts +59 -0
  421. package/src/services/voice/e2e-harness.test.ts +182 -0
  422. package/src/services/voice/e2e-harness.ts +743 -0
  423. package/src/services/voice/eager-context-builder.d.ts +170 -0
  424. package/src/services/voice/eager-context-builder.d.ts.map +1 -0
  425. package/src/services/voice/eager-context-builder.ts +262 -0
  426. package/src/services/voice/eliza1-eot-scorer.d.ts +124 -0
  427. package/src/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
  428. package/src/services/voice/eliza1-eot-scorer.ts +242 -0
  429. package/src/services/voice/embedding-server.ts +200 -0
  430. package/src/services/voice/embedding.d.ts +133 -0
  431. package/src/services/voice/embedding.d.ts.map +1 -0
  432. package/src/services/voice/embedding.test.ts +148 -0
  433. package/src/services/voice/embedding.ts +244 -0
  434. package/src/services/voice/emotion-attribution.d.ts +68 -0
  435. package/src/services/voice/emotion-attribution.d.ts.map +1 -0
  436. package/src/services/voice/emotion-attribution.test.ts +129 -0
  437. package/src/services/voice/emotion-attribution.ts +361 -0
  438. package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
  439. package/src/services/voice/engine-bridge.d.ts +746 -0
  440. package/src/services/voice/engine-bridge.d.ts.map +1 -0
  441. package/src/services/voice/engine-bridge.test.ts +384 -0
  442. package/src/services/voice/engine-bridge.ts +2226 -0
  443. package/src/services/voice/eot-classifier-ggml.d.ts +179 -0
  444. package/src/services/voice/eot-classifier-ggml.d.ts.map +1 -0
  445. package/src/services/voice/eot-classifier-ggml.ts +566 -0
  446. package/src/services/voice/eot-classifier.d.ts +214 -0
  447. package/src/services/voice/eot-classifier.d.ts.map +1 -0
  448. package/src/services/voice/eot-classifier.ts +533 -0
  449. package/src/services/voice/errors.d.ts +20 -0
  450. package/src/services/voice/errors.d.ts.map +1 -0
  451. package/src/services/voice/errors.ts +32 -0
  452. package/src/services/voice/expressive-tags.d.ts +158 -0
  453. package/src/services/voice/expressive-tags.d.ts.map +1 -0
  454. package/src/services/voice/expressive-tags.ts +405 -0
  455. package/src/services/voice/ffi-bindings.d.ts +636 -0
  456. package/src/services/voice/ffi-bindings.d.ts.map +1 -0
  457. package/src/services/voice/ffi-bindings.test.ts +671 -0
  458. package/src/services/voice/ffi-bindings.ts +3050 -0
  459. package/src/services/voice/first-line-cache.d.ts +181 -0
  460. package/src/services/voice/first-line-cache.d.ts.map +1 -0
  461. package/src/services/voice/first-line-cache.ts +725 -0
  462. package/src/services/voice/fused-eot-scorer.d.ts +51 -0
  463. package/src/services/voice/fused-eot-scorer.d.ts.map +1 -0
  464. package/src/services/voice/fused-eot-scorer.ts +135 -0
  465. package/src/services/voice/index.d.ts +91 -0
  466. package/src/services/voice/index.d.ts.map +1 -0
  467. package/src/services/voice/index.ts +481 -0
  468. package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +151 -0
  469. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +151 -0
  470. package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
  471. package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
  472. package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
  473. package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
  474. package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
  475. package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +231 -0
  476. package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
  477. package/src/services/voice/kokoro/index.ts +79 -0
  478. package/src/services/voice/kokoro/kokoro-backend.d.ts +72 -0
  479. package/src/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
  480. package/src/services/voice/kokoro/kokoro-backend.ts +207 -0
  481. package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
  482. package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
  483. package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
  484. package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
  485. package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
  486. package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
  487. package/src/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
  488. package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
  489. package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
  490. package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
  491. package/src/services/voice/kokoro/phonemizer.d.ts +50 -0
  492. package/src/services/voice/kokoro/phonemizer.d.ts.map +1 -0
  493. package/src/services/voice/kokoro/phonemizer.ts +344 -0
  494. package/src/services/voice/kokoro/pick-runtime.d.ts +61 -0
  495. package/src/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
  496. package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
  497. package/src/services/voice/kokoro/pick-runtime.ts +130 -0
  498. package/src/services/voice/kokoro/runtime-selection.d.ts +92 -0
  499. package/src/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
  500. package/src/services/voice/kokoro/runtime-selection.ts +237 -0
  501. package/src/services/voice/kokoro/types.d.ts +82 -0
  502. package/src/services/voice/kokoro/types.d.ts.map +1 -0
  503. package/src/services/voice/kokoro/types.ts +95 -0
  504. package/src/services/voice/kokoro/voice-presets.d.ts +23 -0
  505. package/src/services/voice/kokoro/voice-presets.d.ts.map +1 -0
  506. package/src/services/voice/kokoro/voice-presets.ts +129 -0
  507. package/src/services/voice/kokoro/voices.d.ts +30 -0
  508. package/src/services/voice/kokoro/voices.d.ts.map +1 -0
  509. package/src/services/voice/kokoro/voices.ts +64 -0
  510. package/src/services/voice/lifecycle.d.ts +135 -0
  511. package/src/services/voice/lifecycle.d.ts.map +1 -0
  512. package/src/services/voice/lifecycle.test.ts +315 -0
  513. package/src/services/voice/lifecycle.ts +301 -0
  514. package/src/services/voice/live-diarization-session.d.ts +96 -0
  515. package/src/services/voice/live-diarization-session.d.ts.map +1 -0
  516. package/src/services/voice/live-diarization-session.ts +289 -0
  517. package/src/services/voice/mic-source.d.ts +136 -0
  518. package/src/services/voice/mic-source.d.ts.map +1 -0
  519. package/src/services/voice/mic-source.test.ts +210 -0
  520. package/src/services/voice/mic-source.ts +503 -0
  521. package/src/services/voice/optimistic-policy.d.ts +109 -0
  522. package/src/services/voice/optimistic-policy.d.ts.map +1 -0
  523. package/src/services/voice/optimistic-policy.test.ts +101 -0
  524. package/src/services/voice/optimistic-policy.ts +192 -0
  525. package/src/services/voice/optimistic-rollback.ts +343 -0
  526. package/src/services/voice/partial-stabilizer.d.ts +73 -0
  527. package/src/services/voice/partial-stabilizer.d.ts.map +1 -0
  528. package/src/services/voice/partial-stabilizer.test.ts +68 -0
  529. package/src/services/voice/partial-stabilizer.ts +140 -0
  530. package/src/services/voice/phoneme-tokenizer.d.ts +49 -0
  531. package/src/services/voice/phoneme-tokenizer.d.ts.map +1 -0
  532. package/src/services/voice/phoneme-tokenizer.ts +158 -0
  533. package/src/services/voice/phrase-cache.d.ts +76 -0
  534. package/src/services/voice/phrase-cache.d.ts.map +1 -0
  535. package/src/services/voice/phrase-cache.test.ts +242 -0
  536. package/src/services/voice/phrase-cache.ts +186 -0
  537. package/src/services/voice/phrase-chunker.d.ts +62 -0
  538. package/src/services/voice/phrase-chunker.d.ts.map +1 -0
  539. package/src/services/voice/phrase-chunker.test.ts +239 -0
  540. package/src/services/voice/phrase-chunker.ts +281 -0
  541. package/src/services/voice/pipeline-impls.d.ts +151 -0
  542. package/src/services/voice/pipeline-impls.d.ts.map +1 -0
  543. package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
  544. package/src/services/voice/pipeline-impls.test.ts +292 -0
  545. package/src/services/voice/pipeline-impls.ts +315 -0
  546. package/src/services/voice/pipeline.d.ts +216 -0
  547. package/src/services/voice/pipeline.d.ts.map +1 -0
  548. package/src/services/voice/pipeline.ts +505 -0
  549. package/src/services/voice/prefill-client.d.ts +123 -0
  550. package/src/services/voice/prefill-client.d.ts.map +1 -0
  551. package/src/services/voice/prefill-client.ts +316 -0
  552. package/src/services/voice/prefix-preserving-queue.d.ts +113 -0
  553. package/src/services/voice/prefix-preserving-queue.d.ts.map +1 -0
  554. package/src/services/voice/prefix-preserving-queue.ts +162 -0
  555. package/src/services/voice/profile-store.d.ts +248 -0
  556. package/src/services/voice/profile-store.d.ts.map +1 -0
  557. package/src/services/voice/profile-store.ts +887 -0
  558. package/src/services/voice/ring-buffer.d.ts +40 -0
  559. package/src/services/voice/ring-buffer.d.ts.map +1 -0
  560. package/src/services/voice/ring-buffer.ts +105 -0
  561. package/src/services/voice/rollback-queue.d.ts +24 -0
  562. package/src/services/voice/rollback-queue.d.ts.map +1 -0
  563. package/src/services/voice/rollback-queue.ts +74 -0
  564. package/src/services/voice/samantha-preset-placeholder.d.ts +67 -0
  565. package/src/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
  566. package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
  567. package/src/services/voice/samantha-preset-placeholder.ts +148 -0
  568. package/src/services/voice/samantha-preset-regenerator.d.ts +87 -0
  569. package/src/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
  570. package/src/services/voice/samantha-preset-regenerator.ts +393 -0
  571. package/src/services/voice/scheduler.d.ts +146 -0
  572. package/src/services/voice/scheduler.d.ts.map +1 -0
  573. package/src/services/voice/scheduler.t2.test.ts +141 -0
  574. package/src/services/voice/scheduler.ts +927 -0
  575. package/src/services/voice/shared-resources.d.ts +190 -0
  576. package/src/services/voice/shared-resources.d.ts.map +1 -0
  577. package/src/services/voice/shared-resources.ts +320 -0
  578. package/src/services/voice/speaker/attribution-pipeline.d.ts +74 -0
  579. package/src/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
  580. package/src/services/voice/speaker/attribution-pipeline.ts +386 -0
  581. package/src/services/voice/speaker/diarizer-fused.d.ts +59 -0
  582. package/src/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
  583. package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
  584. package/src/services/voice/speaker/diarizer-fused.ts +154 -0
  585. package/src/services/voice/speaker/diarizer.d.ts +75 -0
  586. package/src/services/voice/speaker/diarizer.d.ts.map +1 -0
  587. package/src/services/voice/speaker/diarizer.ts +218 -0
  588. package/src/services/voice/speaker/encoder-fused.d.ts +60 -0
  589. package/src/services/voice/speaker/encoder-fused.d.ts.map +1 -0
  590. package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
  591. package/src/services/voice/speaker/encoder-fused.ts +138 -0
  592. package/src/services/voice/speaker/encoder-ggml.d.ts +33 -0
  593. package/src/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
  594. package/src/services/voice/speaker/encoder-ggml.ts +79 -0
  595. package/src/services/voice/speaker/encoder.d.ts +37 -0
  596. package/src/services/voice/speaker/encoder.d.ts.map +1 -0
  597. package/src/services/voice/speaker/encoder.ts +105 -0
  598. package/src/services/voice/speaker-imprint.d.ts +83 -0
  599. package/src/services/voice/speaker-imprint.d.ts.map +1 -0
  600. package/src/services/voice/speaker-imprint.test.ts +185 -0
  601. package/src/services/voice/speaker-imprint.ts +312 -0
  602. package/src/services/voice/speaker-preset-cache.d.ts +77 -0
  603. package/src/services/voice/speaker-preset-cache.d.ts.map +1 -0
  604. package/src/services/voice/speaker-preset-cache.test.ts +154 -0
  605. package/src/services/voice/speaker-preset-cache.ts +195 -0
  606. package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
  607. package/src/services/voice/system-audio-sink.d.ts +73 -0
  608. package/src/services/voice/system-audio-sink.d.ts.map +1 -0
  609. package/src/services/voice/system-audio-sink.test.ts +29 -0
  610. package/src/services/voice/system-audio-sink.ts +366 -0
  611. package/src/services/voice/transcriber.d.ts +244 -0
  612. package/src/services/voice/transcriber.d.ts.map +1 -0
  613. package/src/services/voice/transcriber.test.ts +392 -0
  614. package/src/services/voice/transcriber.ts +704 -0
  615. package/src/services/voice/turn-controller.d.ts +183 -0
  616. package/src/services/voice/turn-controller.d.ts.map +1 -0
  617. package/src/services/voice/turn-controller.test.ts +575 -0
  618. package/src/services/voice/turn-controller.ts +596 -0
  619. package/src/services/voice/types.d.ts +643 -0
  620. package/src/services/voice/types.d.ts.map +1 -0
  621. package/src/services/voice/types.ts +699 -0
  622. package/src/services/voice/vad.d.ts +282 -0
  623. package/src/services/voice/vad.d.ts.map +1 -0
  624. package/src/services/voice/vad.test.ts +480 -0
  625. package/src/services/voice/vad.ts +827 -0
  626. package/src/services/voice/vad.v1-v4.test.ts +222 -0
  627. package/src/services/voice/voice-budget.d.ts +241 -0
  628. package/src/services/voice/voice-budget.d.ts.map +1 -0
  629. package/src/services/voice/voice-budget.test.ts +420 -0
  630. package/src/services/voice/voice-budget.ts +656 -0
  631. package/src/services/voice/voice-duet.test.ts +375 -0
  632. package/src/services/voice/voice-emotion-classifier.d.ts +95 -0
  633. package/src/services/voice/voice-emotion-classifier.d.ts.map +1 -0
  634. package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
  635. package/src/services/voice/voice-emotion-classifier.ts +273 -0
  636. package/src/services/voice/voice-preset-format.d.ts +158 -0
  637. package/src/services/voice/voice-preset-format.d.ts.map +1 -0
  638. package/src/services/voice/voice-preset-format.ts +700 -0
  639. package/src/services/voice/voice-preset-generator.test.ts +89 -0
  640. package/src/services/voice/voice-profile-artifact.d.ts +116 -0
  641. package/src/services/voice/voice-profile-artifact.d.ts.map +1 -0
  642. package/src/services/voice/voice-profile-artifact.test.ts +138 -0
  643. package/src/services/voice/voice-profile-artifact.ts +518 -0
  644. package/src/services/voice/voice-profile-routes.d.ts +83 -0
  645. package/src/services/voice/voice-profile-routes.d.ts.map +1 -0
  646. package/src/services/voice/voice-profile-routes.test.ts +429 -0
  647. package/src/services/voice/voice-profile-routes.ts +425 -0
  648. package/src/services/voice/voice-scenario.ts +154 -0
  649. package/src/services/voice/voice-settings.d.ts +82 -0
  650. package/src/services/voice/voice-settings.d.ts.map +1 -0
  651. package/src/services/voice/voice-settings.ts +172 -0
  652. package/src/services/voice/voice-state-machine.d.ts +364 -0
  653. package/src/services/voice/voice-state-machine.d.ts.map +1 -0
  654. package/src/services/voice/voice-state-machine.ts +727 -0
  655. package/src/services/voice/voice-workbench-report.test.ts +168 -0
  656. package/src/services/voice/voice-workbench-report.ts +326 -0
  657. package/src/services/voice/voice-workbench.test.ts +158 -0
  658. package/src/services/voice/voice.test.ts +1070 -0
  659. package/src/services/voice/wake-word-ggml.d.ts +101 -0
  660. package/src/services/voice/wake-word-ggml.d.ts.map +1 -0
  661. package/src/services/voice/wake-word-ggml.ts +320 -0
  662. package/src/services/voice/wake-word.d.ts +255 -0
  663. package/src/services/voice/wake-word.d.ts.map +1 -0
  664. package/src/services/voice/wake-word.test.ts +298 -0
  665. package/src/services/voice/wake-word.ts +554 -0
  666. package/src/services/voice/wrap-with-first-line-cache.d.ts +70 -0
  667. package/src/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
  668. package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
  669. package/src/services/voice-model-updater.d.ts +240 -0
  670. package/src/services/voice-model-updater.d.ts.map +1 -0
  671. package/src/services/voice-model-updater.ts +724 -0
  672. package/src/services/voice-prewarm.d.ts +3 -0
  673. package/src/services/voice-prewarm.d.ts.map +1 -0
  674. package/src/services/voice-prewarm.ts +51 -0
  675. package/dist/index.d.ts +0 -37
  676. package/dist/index.js +0 -1098
@@ -0,0 +1,507 @@
1
+ /**
2
+ * Provider registry.
3
+ *
4
+ * Treats every inference source the same way — cloud subscription, cloud
5
+ * API, Eliza-1 local runtime, paired-device bridge, Capacitor on-device
6
+ * — each is a `ProviderDefinition` with an `id`, a human label, a set of
7
+ * supported model slots, and a pluggable `getEnableState()` that inspects
8
+ * whatever underlying gate controls it (API key presence, subscription
9
+ * status, env flag, file on disk).
10
+ *
11
+ * The cloud-provider status readers are intentionally permissive: they
12
+ * report what they can introspect without depending on the specific
13
+ * cloud-plugin internals, and hand off to the existing ProviderSwitcher
14
+ * UI for actual enable/disable via `configureHref`. That avoids the
15
+ * "combined enable matrix is an architectural project" problem by making
16
+ * configuration navigable rather than centralised.
17
+ */
18
+
19
+ import fs from "node:fs/promises";
20
+ import type {
21
+ ProviderEnableState,
22
+ ProviderId,
23
+ ProviderMeta,
24
+ ProviderStatus,
25
+ } from "@elizaos/shared";
26
+ import { deviceBridge } from "./device-bridge";
27
+ import { handlerRegistry } from "./handler-registry";
28
+ import { localInferenceRoot } from "./paths";
29
+
30
+ /**
31
+ * Runtime provider descriptor. Extends the UI-safe `ProviderMeta` with a
32
+ * callable `getEnableState()` that inspects env vars, fs, or device-bridge
33
+ * sockets. Server-side only — UI code reads `ProviderMeta` /
34
+ * `ProviderStatus` from `@elizaos/shared` instead.
35
+ */
36
+ export interface ProviderDefinition extends ProviderMeta {
37
+ /**
38
+ * Read the current enable state. For cloud providers we inspect env
39
+ * vars or config fragments; for local we check file presence; for
40
+ * device-bridge we check connected-device count.
41
+ */
42
+ getEnableState(): Promise<ProviderEnableState>;
43
+ }
44
+
45
+ export type { ProviderEnableState, ProviderId, ProviderMeta, ProviderStatus };
46
+
47
+ /** Resolve which slots have at least one registered handler from this provider. */
48
+ export function getRegisteredSlotsForProvider(providerId: string): string[] {
49
+ const regs = handlerRegistry.getAll();
50
+ const slots = new Set<string>();
51
+ for (const r of regs) {
52
+ if (r.provider === providerId) slots.add(r.modelType);
53
+ }
54
+ return [...slots];
55
+ }
56
+
57
+ // ── Built-in provider definitions ────────────────────────────────────
58
+
59
+ const LOCAL_PROVIDER: ProviderDefinition = {
60
+ id: "eliza-local-inference",
61
+ label: "Eliza-1 local runtime",
62
+ kind: "local",
63
+ description:
64
+ "On-device Eliza-1 inference with the optimized local runtime. The bundle serves text, embeddings, TTS, and transcription from one local provider.",
65
+ supportedSlots: [
66
+ "TEXT_SMALL",
67
+ "TEXT_LARGE",
68
+ "TEXT_EMBEDDING",
69
+ "TEXT_TO_SPEECH",
70
+ "TRANSCRIPTION",
71
+ ],
72
+ async getEnableState(): Promise<ProviderEnableState> {
73
+ // Enabled when at least one model file lives under our root and the
74
+ // binding is loadable. We don't force-load node-llama-cpp here — that
75
+ // would tie up GPU memory just for a status probe.
76
+ try {
77
+ const entries = await fs.readdir(`${localInferenceRoot()}/models`, {
78
+ withFileTypes: true,
79
+ });
80
+ const hasModel = entries.some(
81
+ (e) =>
82
+ (e.isFile() && e.name.toLowerCase().endsWith(".gguf")) ||
83
+ (e.isDirectory() && e.name.toLowerCase().endsWith(".bundle")),
84
+ );
85
+ if (!hasModel)
86
+ return { enabled: false, reason: "No local model installed" };
87
+ return {
88
+ enabled: true,
89
+ reason: "Eliza-1 model installed; native local runtime available",
90
+ };
91
+ } catch {
92
+ return { enabled: false, reason: "No local model installed" };
93
+ }
94
+ },
95
+ configureHref: "#local-inference-panel",
96
+ };
97
+
98
+ const DEVICE_BRIDGE_PROVIDER: ProviderDefinition = {
99
+ id: "eliza-device-bridge",
100
+ label: "Paired device bridge",
101
+ kind: "device-bridge",
102
+ description:
103
+ "Inference on a paired mobile or desktop device over WebSocket. Useful when the agent runs in a container but the model lives on your phone or laptop.",
104
+ // The bridge can carry an `embed` frame to a paired device that has the
105
+ // local-embedding plugin loaded; whether the active device actually
106
+ // serves it is reflected in `registeredSlots`.
107
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE", "TEXT_EMBEDDING"],
108
+ async getEnableState(): Promise<ProviderEnableState> {
109
+ const bridgeEnabled =
110
+ process.env.ELIZA_DEVICE_BRIDGE_ENABLED?.trim() === "1";
111
+ if (!bridgeEnabled) {
112
+ return {
113
+ enabled: false,
114
+ reason: "Set ELIZA_DEVICE_BRIDGE_ENABLED=1 to enable",
115
+ };
116
+ }
117
+ const status = deviceBridge.status();
118
+ if (status.connected) {
119
+ return {
120
+ enabled: true,
121
+ reason: `${status.devices.length} device(s) connected`,
122
+ };
123
+ }
124
+ return {
125
+ enabled: true,
126
+ reason: "Waiting for a device to connect",
127
+ };
128
+ },
129
+ configureHref: "#device-bridge-status",
130
+ };
131
+
132
+ const CAPACITOR_LLAMA_PROVIDER: ProviderDefinition = {
133
+ id: "capacitor-llama",
134
+ label: "eliza-1-2b runtime",
135
+ kind: "local",
136
+ description:
137
+ "Runs Eliza-1 natively on iOS or Android via Capacitor. Only available in mobile builds.",
138
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
139
+ async getEnableState(): Promise<ProviderEnableState> {
140
+ const cap = (globalThis as Record<string, unknown>).Capacitor as
141
+ | { isNativePlatform?: () => boolean }
142
+ | undefined;
143
+ if (cap?.isNativePlatform?.()) {
144
+ return {
145
+ enabled: true,
146
+ reason: "Native Capacitor runtime detected",
147
+ };
148
+ }
149
+ return {
150
+ enabled: false,
151
+ reason: "Only available in iOS/Android builds",
152
+ };
153
+ },
154
+ configureHref: null,
155
+ };
156
+
157
+ const ANTHROPIC_PROVIDER: ProviderDefinition = {
158
+ id: "anthropic",
159
+ label: "Anthropic API",
160
+ kind: "cloud-api",
161
+ description: "Claude models via the Anthropic API. Requires an API key.",
162
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
163
+ async getEnableState(): Promise<ProviderEnableState> {
164
+ const key = process.env.ANTHROPIC_API_KEY?.trim();
165
+ return key
166
+ ? { enabled: true, reason: "API key set" }
167
+ : { enabled: false, reason: "No API key" };
168
+ },
169
+ configureHref: "#ai-model",
170
+ };
171
+
172
+ const OPENAI_PROVIDER: ProviderDefinition = {
173
+ id: "openai",
174
+ label: "OpenAI API",
175
+ kind: "cloud-api",
176
+ description: "GPT models via the OpenAI API. Requires an API key.",
177
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE", "TEXT_EMBEDDING"],
178
+ async getEnableState(): Promise<ProviderEnableState> {
179
+ const key = process.env.OPENAI_API_KEY?.trim();
180
+ return key
181
+ ? { enabled: true, reason: "API key set" }
182
+ : { enabled: false, reason: "No API key" };
183
+ },
184
+ configureHref: "#ai-model",
185
+ };
186
+
187
+ const GROK_PROVIDER: ProviderDefinition = {
188
+ id: "grok",
189
+ label: "Grok API",
190
+ kind: "cloud-api",
191
+ description: "xAI Grok models. Requires an API key.",
192
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
193
+ async getEnableState(): Promise<ProviderEnableState> {
194
+ const key =
195
+ process.env.GROK_API_KEY?.trim() ?? process.env.XAI_API_KEY?.trim();
196
+ return key
197
+ ? { enabled: true, reason: "API key set" }
198
+ : { enabled: false, reason: "No API key" };
199
+ },
200
+ configureHref: "#ai-model",
201
+ };
202
+
203
+ const ELIZACLOUD_PROVIDER: ProviderDefinition = {
204
+ id: "elizacloud",
205
+ label: "Eliza Cloud",
206
+ kind: "cloud-subscription",
207
+ description:
208
+ "Eliza-hosted inference routed through your subscription. No API key to manage.",
209
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE", "TEXT_EMBEDDING"],
210
+ async getEnableState(): Promise<ProviderEnableState> {
211
+ const token =
212
+ process.env.ELIZA_CLOUD_TOKEN?.trim() ??
213
+ process.env.ELIZACLOUD_TOKEN?.trim() ??
214
+ process.env.ELIZAOS_API_KEY?.trim();
215
+ return token
216
+ ? { enabled: true, reason: "Cloud token set" }
217
+ : { enabled: false, reason: "Not signed in" };
218
+ },
219
+ configureHref: "#ai-model",
220
+ };
221
+
222
+ const ANTHROPIC_SUBSCRIPTION_PROVIDER: ProviderDefinition = {
223
+ id: "anthropic-subscription",
224
+ label: "Claude subscription",
225
+ kind: "cloud-subscription",
226
+ description: "Claude Code task-agent access through linked accounts.",
227
+ // Claude.ai OAuth subscriptions serve text + structured-object generation
228
+ // through Anthropic's chat models. Embeddings are not exposed by the
229
+ // subscription path (Anthropic does not ship an embeddings endpoint), so
230
+ // TEXT_EMBEDDING is intentionally omitted — that slot needs a separate
231
+ // API-key provider.
232
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
233
+ async getEnableState(): Promise<ProviderEnableState> {
234
+ return subscriptionEnableState("anthropic-subscription");
235
+ },
236
+ configureHref: "#ai-model",
237
+ };
238
+
239
+ const OPENAI_CODEX_PROVIDER: ProviderDefinition = {
240
+ id: "openai-codex",
241
+ label: "Codex subscription",
242
+ kind: "cloud-subscription",
243
+ description: "Codex and ChatGPT subscription access through linked accounts.",
244
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
245
+ async getEnableState(): Promise<ProviderEnableState> {
246
+ return subscriptionEnableState("openai-codex");
247
+ },
248
+ configureHref: "#ai-model",
249
+ };
250
+
251
+ const GEMINI_CLI_PROVIDER: ProviderDefinition = {
252
+ id: "gemini-cli",
253
+ label: "Gemini CLI subscription",
254
+ kind: "cloud-subscription",
255
+ description: "Gemini CLI task-agent access through linked accounts.",
256
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
257
+ async getEnableState(): Promise<ProviderEnableState> {
258
+ return subscriptionEnableState("gemini-cli");
259
+ },
260
+ configureHref: "#ai-model",
261
+ };
262
+
263
+ const ZAI_CODING_PROVIDER: ProviderDefinition = {
264
+ id: "zai-coding",
265
+ label: "z.ai Coding Plan",
266
+ kind: "cloud-subscription",
267
+ description:
268
+ "GLM coding-plan access through linked z.ai Coding Plan accounts.",
269
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
270
+ async getEnableState(): Promise<ProviderEnableState> {
271
+ return subscriptionEnableState("zai-coding");
272
+ },
273
+ configureHref: "#ai-model",
274
+ };
275
+
276
+ const KIMI_CODING_PROVIDER: ProviderDefinition = {
277
+ id: "kimi-coding",
278
+ label: "Kimi Code",
279
+ kind: "cloud-subscription",
280
+ description: "Kimi coding-plan access through linked Kimi Code accounts.",
281
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
282
+ async getEnableState(): Promise<ProviderEnableState> {
283
+ return subscriptionEnableState("kimi-coding");
284
+ },
285
+ configureHref: "#ai-model",
286
+ };
287
+
288
+ const DEEPSEEK_CODING_PROVIDER: ProviderDefinition = {
289
+ id: "deepseek-coding",
290
+ label: "DeepSeek Coding Plan",
291
+ kind: "cloud-subscription",
292
+ description:
293
+ "Unavailable until DeepSeek exposes a first-party coding subscription flow that can be integrated without API-key substitution.",
294
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
295
+ async getEnableState(): Promise<ProviderEnableState> {
296
+ return subscriptionEnableState("deepseek-coding");
297
+ },
298
+ configureHref: "#ai-model",
299
+ };
300
+
301
+ const GOOGLE_PROVIDER: ProviderDefinition = {
302
+ id: "google",
303
+ label: "Google (Gemini)",
304
+ kind: "cloud-api",
305
+ description: "Gemini models via Google Generative AI. Requires an API key.",
306
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
307
+ async getEnableState(): Promise<ProviderEnableState> {
308
+ const key =
309
+ process.env.GOOGLE_API_KEY?.trim() ?? process.env.GEMINI_API_KEY?.trim();
310
+ return key
311
+ ? { enabled: true, reason: "API key set" }
312
+ : { enabled: false, reason: "No API key" };
313
+ },
314
+ configureHref: "#ai-model",
315
+ };
316
+
317
+ const MISTRAL_PROVIDER: ProviderDefinition = {
318
+ id: "mistral",
319
+ label: "Mistral API",
320
+ kind: "cloud-api",
321
+ description: "Mistral models via la Plateforme. Requires an API key.",
322
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
323
+ async getEnableState(): Promise<ProviderEnableState> {
324
+ const key = process.env.MISTRAL_API_KEY?.trim();
325
+ return key
326
+ ? { enabled: true, reason: "API key set" }
327
+ : { enabled: false, reason: "No API key" };
328
+ },
329
+ configureHref: "#ai-model",
330
+ };
331
+
332
+ const DEEPSEEK_PROVIDER: ProviderDefinition = {
333
+ id: "deepseek",
334
+ label: "DeepSeek API",
335
+ kind: "cloud-api",
336
+ description: "DeepSeek models via API key or linked account pool.",
337
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
338
+ async getEnableState(): Promise<ProviderEnableState> {
339
+ return apiKeyOrLinkedAccountState("deepseek-api", ["DEEPSEEK_API_KEY"]);
340
+ },
341
+ configureHref: "#ai-model",
342
+ };
343
+
344
+ const ZAI_PROVIDER: ProviderDefinition = {
345
+ id: "zai",
346
+ label: "z.ai API",
347
+ kind: "cloud-api",
348
+ description: "GLM models via z.ai API key or linked account pool.",
349
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
350
+ async getEnableState(): Promise<ProviderEnableState> {
351
+ return apiKeyOrLinkedAccountState("zai-api", [
352
+ "ZAI_API_KEY",
353
+ "Z_AI_API_KEY",
354
+ ]);
355
+ },
356
+ configureHref: "#ai-model",
357
+ };
358
+
359
+ const NEARAI_PROVIDER: ProviderDefinition = {
360
+ id: "nearai",
361
+ label: "NEAR AI Cloud",
362
+ kind: "cloud-api",
363
+ description:
364
+ "TEE-backed private inference via NEAR AI Cloud. Requires an API key.",
365
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
366
+ async getEnableState(): Promise<ProviderEnableState> {
367
+ const key = process.env.NEARAI_API_KEY?.trim();
368
+ return key
369
+ ? { enabled: true, reason: "API key set" }
370
+ : { enabled: false, reason: "No API key" };
371
+ },
372
+ configureHref: "#ai-model",
373
+ };
374
+
375
+ const MOONSHOT_PROVIDER: ProviderDefinition = {
376
+ id: "moonshot",
377
+ label: "Kimi / Moonshot API",
378
+ kind: "cloud-api",
379
+ description: "Kimi models via Moonshot API key or linked account pool.",
380
+ supportedSlots: ["TEXT_SMALL", "TEXT_LARGE"],
381
+ async getEnableState(): Promise<ProviderEnableState> {
382
+ return apiKeyOrLinkedAccountState("moonshot-api", [
383
+ "MOONSHOT_API_KEY",
384
+ "KIMI_API_KEY",
385
+ ]);
386
+ },
387
+ configureHref: "#ai-model",
388
+ };
389
+
390
+ export const BUILT_IN_PROVIDERS: readonly ProviderDefinition[] = [
391
+ LOCAL_PROVIDER,
392
+ DEVICE_BRIDGE_PROVIDER,
393
+ CAPACITOR_LLAMA_PROVIDER,
394
+ ANTHROPIC_SUBSCRIPTION_PROVIDER,
395
+ OPENAI_CODEX_PROVIDER,
396
+ GEMINI_CLI_PROVIDER,
397
+ ZAI_CODING_PROVIDER,
398
+ KIMI_CODING_PROVIDER,
399
+ DEEPSEEK_CODING_PROVIDER,
400
+ ELIZACLOUD_PROVIDER,
401
+ ANTHROPIC_PROVIDER,
402
+ OPENAI_PROVIDER,
403
+ DEEPSEEK_PROVIDER,
404
+ ZAI_PROVIDER,
405
+ NEARAI_PROVIDER,
406
+ MOONSHOT_PROVIDER,
407
+ GOOGLE_PROVIDER,
408
+ GROK_PROVIDER,
409
+ MISTRAL_PROVIDER,
410
+ ];
411
+
412
+ interface LinkedAccountLike {
413
+ enabled?: boolean;
414
+ health?: string;
415
+ }
416
+
417
+ type OptionalAccountPoolModule = {
418
+ getDefaultAccountPool?: () => {
419
+ list?: (providerId: string) => LinkedAccountLike[];
420
+ };
421
+ };
422
+
423
+ async function listLinkedAccounts(
424
+ providerId: string,
425
+ ): Promise<LinkedAccountLike[]> {
426
+ try {
427
+ const dynamicImport = new Function("id", "return import(id)") as (
428
+ id: string,
429
+ ) => Promise<OptionalAccountPoolModule>;
430
+ const appCoreAccountPoolSpecifier = "@elizaos/app-core/account-pool";
431
+ const mod = await dynamicImport(appCoreAccountPoolSpecifier);
432
+ const pool = mod.getDefaultAccountPool?.();
433
+ return pool?.list?.(providerId) ?? [];
434
+ } catch {
435
+ return [];
436
+ }
437
+ }
438
+
439
+ async function apiKeyOrLinkedAccountState(
440
+ providerId: "deepseek-api" | "zai-api" | "moonshot-api",
441
+ envKeys: readonly string[],
442
+ ): Promise<ProviderEnableState> {
443
+ const hasEnv = envKeys.some((key) => process.env[key]?.trim());
444
+ if (hasEnv) return { enabled: true, reason: "API key set" };
445
+ const accounts = (await listLinkedAccounts(providerId)).filter(
446
+ (account) => account.enabled && account.health === "ok",
447
+ );
448
+ if (accounts.length === 0) {
449
+ return { enabled: false, reason: "No API key or linked account" };
450
+ }
451
+ return {
452
+ enabled: true,
453
+ reason: `${accounts.length} linked account${accounts.length === 1 ? "" : "s"}`,
454
+ };
455
+ }
456
+
457
+ type SubscriptionProviderStatusId =
458
+ | "anthropic-subscription"
459
+ | "openai-codex"
460
+ | "gemini-cli"
461
+ | "zai-coding"
462
+ | "kimi-coding"
463
+ | "deepseek-coding";
464
+
465
+ async function subscriptionEnableState(
466
+ providerId: SubscriptionProviderStatusId,
467
+ ): Promise<ProviderEnableState> {
468
+ if (providerId === "deepseek-coding") {
469
+ return {
470
+ enabled: false,
471
+ reason: "Unavailable: no first-party coding subscription integration",
472
+ };
473
+ }
474
+ const accounts = (await listLinkedAccounts(providerId)).filter(
475
+ (account) => account.enabled && account.health === "ok",
476
+ );
477
+ if (accounts.length === 0) {
478
+ const reason =
479
+ providerId === "gemini-cli"
480
+ ? "No linked account; run gemini auth login"
481
+ : "No linked account";
482
+ return { enabled: false, reason };
483
+ }
484
+ return {
485
+ enabled: true,
486
+ reason: `${accounts.length} linked account${accounts.length === 1 ? "" : "s"}`,
487
+ };
488
+ }
489
+
490
+ export async function snapshotProviders(): Promise<ProviderStatus[]> {
491
+ const entries = await Promise.all(
492
+ BUILT_IN_PROVIDERS.map(async (def) => {
493
+ const state = await def.getEnableState();
494
+ return {
495
+ id: def.id,
496
+ label: def.label,
497
+ kind: def.kind,
498
+ description: def.description,
499
+ supportedSlots: def.supportedSlots,
500
+ configureHref: def.configureHref,
501
+ enableState: state,
502
+ registeredSlots: getRegisteredSlotsForProvider(def.id),
503
+ } satisfies ProviderStatus;
504
+ }),
505
+ );
506
+ return entries;
507
+ }
@@ -0,0 +1,163 @@
1
+ /**
2
+ * defaultManifestLoader memoizes the manifest read+parse+validate keyed on the
3
+ * installed bundle's `manifestSha256`. Proves: (1) a repeated load with the same
4
+ * SHA does NOT re-read disk, (2) a changed SHA re-reads (self-invalidation), and
5
+ * (3) the test reset clears it. The SHA is the validated manifest's content
6
+ * hash, so a re-download with different RAM budgets never returns a stale value.
7
+ */
8
+ import fs from "node:fs";
9
+ import os from "node:os";
10
+ import path from "node:path";
11
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
12
+ import {
13
+ REQUIRED_KERNELS_BY_TIER,
14
+ validateManifest,
15
+ } from "./manifest/index.js";
16
+ import type { Eliza1Manifest } from "./manifest/types.js";
17
+ import {
18
+ __resetManifestCacheForTests,
19
+ defaultManifestLoader,
20
+ } from "./ram-budget.js";
21
+ import type { InstalledModel } from "./types.js";
22
+
23
+ const SHA = "0".repeat(64);
24
+
25
+ function validManifest(): Eliza1Manifest {
26
+ const backend = {
27
+ status: "pass" as const,
28
+ atCommit: "abc1234",
29
+ report: "r.txt",
30
+ };
31
+ const manifest: Eliza1Manifest = {
32
+ id: "eliza-1-9b",
33
+ tier: "9b",
34
+ version: "1.0.0",
35
+ publishedAt: "2026-05-10T00:00:00Z",
36
+ lineage: {
37
+ text: { base: "eliza-1-text-backbone", license: "apache-2.0" },
38
+ voice: { base: "eliza-1-voice-backbone", license: "apache-2.0" },
39
+ asr: { base: "eliza-1-asr", license: "apache-2.0" },
40
+ vad: { base: "eliza-1-vad", license: "apache-2.0" },
41
+ drafter: { base: "eliza-1-mtp-drafter", license: "apache-2.0" },
42
+ vision: { base: "eliza-1-vision", license: "apache-2.0" },
43
+ },
44
+ files: {
45
+ text: [{ path: "text/eliza-1-9b-128k.gguf", ctx: 131072, sha256: SHA }],
46
+ voice: [{ path: "tts/omnivoice-base-Q4_K_M.gguf", sha256: SHA }],
47
+ asr: [{ path: "asr/asr.gguf", sha256: SHA }],
48
+ vision: [{ path: "vision/mmproj-9b.gguf", sha256: SHA }],
49
+ mtp: [{ path: "mtp/drafter-9b.gguf", sha256: SHA }],
50
+ cache: [{ path: "cache/voice-preset-default.bin", sha256: SHA }],
51
+ vad: [{ path: "vad/silero-vad-v5.gguf", sha256: SHA }],
52
+ },
53
+ kernels: {
54
+ required: [...REQUIRED_KERNELS_BY_TIER["9b"]],
55
+ optional: [],
56
+ verifiedBackends: {
57
+ metal: backend,
58
+ vulkan: backend,
59
+ cuda: backend,
60
+ rocm: backend,
61
+ cpu: backend,
62
+ },
63
+ },
64
+ evals: {
65
+ textEval: { score: 0.71, passed: true },
66
+ voiceRtf: { rtf: 0.42, passed: true },
67
+ asrWer: { wer: 0.05, passed: true },
68
+ vadLatencyMs: {
69
+ median: 16,
70
+ boundaryMs: 24,
71
+ endpointMs: 80,
72
+ falseBargeInRate: 0.01,
73
+ passed: true,
74
+ },
75
+ mtp: { acceptanceRate: 0.72, speedup: 1.8, passed: true },
76
+ e2eLoopOk: true,
77
+ thirtyTurnOk: true,
78
+ },
79
+ ramBudgetMb: { min: 7000, recommended: 9500 },
80
+ defaultEligible: true,
81
+ };
82
+ return manifest;
83
+ }
84
+
85
+ let dir: string;
86
+ let modelPath: string;
87
+
88
+ beforeEach(() => {
89
+ __resetManifestCacheForTests();
90
+ dir = fs.mkdtempSync(path.join(os.tmpdir(), "ram-budget-cache-"));
91
+ // Canonical layout: GGUF in text/, manifest at the bundle root, so the
92
+ // loader's dirname(dirname(path)) candidate hits on the first probe.
93
+ fs.mkdirSync(path.join(dir, "text"), { recursive: true });
94
+ modelPath = path.join(dir, "text", "eliza-1-9b-128k.gguf");
95
+ const manifest = validManifest();
96
+ expect(validateManifest(manifest).ok).toBe(true); // fixture sanity
97
+ fs.writeFileSync(
98
+ path.join(dir, "eliza-1.manifest.json"),
99
+ JSON.stringify(manifest),
100
+ );
101
+ });
102
+
103
+ afterEach(() => {
104
+ vi.restoreAllMocks();
105
+ __resetManifestCacheForTests();
106
+ fs.rmSync(dir, { recursive: true, force: true });
107
+ });
108
+
109
+ function installed(sha: string): InstalledModel {
110
+ return {
111
+ id: "eliza-1-9b",
112
+ displayName: "Eliza-1 9B",
113
+ path: modelPath,
114
+ sizeBytes: 1,
115
+ manifestSha256: sha,
116
+ installedAt: "2026-05-10T00:00:00Z",
117
+ lastUsedAt: null,
118
+ source: "eliza-download",
119
+ };
120
+ }
121
+
122
+ function manifestReadCount(spy: ReturnType<typeof vi.spyOn>): number {
123
+ return spy.mock.calls.filter(
124
+ (c) => typeof c[0] === "string" && c[0].endsWith("eliza-1.manifest.json"),
125
+ ).length;
126
+ }
127
+
128
+ describe("defaultManifestLoader manifest cache", () => {
129
+ it("reads disk once for repeated loads with the same manifestSha256", () => {
130
+ const spy = vi.spyOn(fs, "readFileSync");
131
+ const first = defaultManifestLoader("eliza-1-9b", installed("sha-A"));
132
+ const second = defaultManifestLoader("eliza-1-9b", installed("sha-A"));
133
+ expect(first?.ramBudgetMb.recommended).toBe(9500);
134
+ expect(second).toBe(first); // identical cached object
135
+ expect(manifestReadCount(spy)).toBe(1);
136
+ });
137
+
138
+ it("re-reads when the manifestSha256 changes (self-invalidation)", () => {
139
+ const spy = vi.spyOn(fs, "readFileSync");
140
+ defaultManifestLoader("eliza-1-9b", installed("sha-A"));
141
+ defaultManifestLoader("eliza-1-9b", installed("sha-B"));
142
+ expect(manifestReadCount(spy)).toBe(2);
143
+ });
144
+
145
+ it("does not cache when no manifestSha256 is present (legacy installs)", () => {
146
+ const spy = vi.spyOn(fs, "readFileSync");
147
+ const legacy: InstalledModel = {
148
+ ...installed("ignored"),
149
+ manifestSha256: undefined,
150
+ };
151
+ defaultManifestLoader("eliza-1-9b", legacy);
152
+ defaultManifestLoader("eliza-1-9b", legacy);
153
+ expect(manifestReadCount(spy)).toBe(2);
154
+ });
155
+
156
+ it("__resetManifestCacheForTests forces a re-read", () => {
157
+ const spy = vi.spyOn(fs, "readFileSync");
158
+ defaultManifestLoader("eliza-1-9b", installed("sha-A"));
159
+ __resetManifestCacheForTests();
160
+ defaultManifestLoader("eliza-1-9b", installed("sha-A"));
161
+ expect(manifestReadCount(spy)).toBe(2);
162
+ });
163
+ });