@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,672 @@
1
+ import {
2
+ DEFAULT_ELIGIBLE_MODEL_IDS,
3
+ type Eliza1TierId,
4
+ eliza1TierPublishStatus,
5
+ FIRST_RUN_DEFAULT_MODEL_ID,
6
+ MODEL_CATALOG,
7
+ } from "./catalog";
8
+ import {
9
+ canSetAsDefault,
10
+ type Eliza1Backend,
11
+ type Eliza1DeviceCaps,
12
+ type Eliza1Manifest,
13
+ SUPPORTED_BACKENDS_BY_TIER,
14
+ } from "./manifest";
15
+ import {
16
+ assessRamFit,
17
+ defaultManifestLoader,
18
+ type ManifestLoader,
19
+ } from "./ram-budget";
20
+ import type {
21
+ CatalogModel,
22
+ CatalogQuantizationVariant,
23
+ HardwareFitLevel,
24
+ HardwareProbe,
25
+ InstalledModel,
26
+ TextGenerationSlot,
27
+ } from "./types";
28
+
29
+ const TIER_0_8B: Eliza1TierId = "eliza-1-0_8b";
30
+ const TIER_2B: Eliza1TierId = "eliza-1-2b";
31
+ const TIER_4B: Eliza1TierId = "eliza-1-4b";
32
+ const TIER_9B: Eliza1TierId = "eliza-1-9b";
33
+ const TIER_27B: Eliza1TierId = "eliza-1-27b";
34
+
35
+ export type RecommendationPlatformClass =
36
+ | "mobile"
37
+ | "apple-silicon"
38
+ | "linux-gpu"
39
+ | "linux-cpu"
40
+ | "desktop-gpu"
41
+ | "desktop-cpu";
42
+
43
+ export interface RecommendedModelSelection {
44
+ slot: TextGenerationSlot;
45
+ platformClass: RecommendationPlatformClass;
46
+ model: CatalogModel | null;
47
+ fit: HardwareFitLevel | null;
48
+ reason: string;
49
+ alternatives: CatalogModel[];
50
+ }
51
+
52
+ const BYTES_PER_GB = 1024 ** 3;
53
+
54
+ /**
55
+ * Per-platform slot ladders. Every default-recommended entry is an
56
+ * Eliza-1 tier (the only default-eligible line — see catalog.ts and
57
+ * `packages/inference/AGENTS.md` §2). Ladders bias toward the smallest
58
+ * tier that fits the platform; desktops/servers pick larger tiers
59
+ * first when memory headroom allows.
60
+ */
61
+ const SLOT_LADDERS: Record<
62
+ RecommendationPlatformClass,
63
+ Record<TextGenerationSlot, ReadonlyArray<Eliza1TierId>>
64
+ > = {
65
+ mobile: {
66
+ TEXT_SMALL: [TIER_0_8B],
67
+ TEXT_LARGE: [TIER_4B, TIER_2B, TIER_0_8B],
68
+ },
69
+ "apple-silicon": {
70
+ TEXT_SMALL: [TIER_0_8B, TIER_2B, TIER_4B],
71
+ TEXT_LARGE: [TIER_27B, TIER_9B, TIER_4B, TIER_2B, TIER_0_8B],
72
+ },
73
+ "linux-gpu": {
74
+ TEXT_SMALL: [TIER_0_8B, TIER_2B, TIER_4B],
75
+ TEXT_LARGE: [TIER_27B, TIER_9B, TIER_4B, TIER_2B, TIER_0_8B],
76
+ },
77
+ "linux-cpu": {
78
+ TEXT_SMALL: [TIER_0_8B, TIER_2B, TIER_4B],
79
+ TEXT_LARGE: [TIER_9B, TIER_4B, TIER_2B, TIER_0_8B],
80
+ },
81
+ "desktop-gpu": {
82
+ TEXT_SMALL: [TIER_0_8B, TIER_2B, TIER_4B],
83
+ TEXT_LARGE: [TIER_27B, TIER_9B, TIER_4B, TIER_2B, TIER_0_8B],
84
+ },
85
+ "desktop-cpu": {
86
+ TEXT_SMALL: [TIER_0_8B, TIER_2B, TIER_4B],
87
+ TEXT_LARGE: [TIER_9B, TIER_4B, TIER_2B, TIER_0_8B],
88
+ },
89
+ };
90
+
91
+ function catalogById(catalog: CatalogModel[]): Map<string, CatalogModel> {
92
+ return new Map(catalog.map((model) => [model.id, model]));
93
+ }
94
+
95
+ function chatCandidates(catalog: CatalogModel[]): CatalogModel[] {
96
+ return catalog.filter((model) => !model.hiddenFromCatalog);
97
+ }
98
+
99
+ export function classifyRecommendationPlatform(
100
+ hardware: HardwareProbe,
101
+ ): RecommendationPlatformClass {
102
+ // Mobile detection comes from the typed `hardware.mobile.platform`
103
+ // field (`"ios" | "android" | "web"`). `NodeJS.Platform` doesn't
104
+ // include those values — the previous `process.platform as string`
105
+ // cast was hiding that the cast was the only way the comparison
106
+ // type-checked. Reading the proper typed field is both safer and
107
+ // accurate when a host advertises mobile via the mobile probe.
108
+ const mobilePlatform = hardware.mobile?.platform;
109
+ if (mobilePlatform === "android" || mobilePlatform === "ios") return "mobile";
110
+
111
+ const platform = hardware.platform;
112
+ if (hardware.appleSilicon) return "apple-silicon";
113
+ if (platform === "linux" && hardware.gpu) return "linux-gpu";
114
+ if (platform === "linux") return "linux-cpu";
115
+ if (hardware.gpu) return "desktop-gpu";
116
+ return "desktop-cpu";
117
+ }
118
+
119
+ export function catalogDownloadSizeGb(
120
+ model: CatalogModel,
121
+ catalog: CatalogModel[] = MODEL_CATALOG,
122
+ ): number {
123
+ void catalog;
124
+ return model.sizeGb;
125
+ }
126
+
127
+ export function catalogDownloadSizeBytes(
128
+ model: CatalogModel,
129
+ catalog: CatalogModel[] = MODEL_CATALOG,
130
+ ): number {
131
+ return Math.round(catalogDownloadSizeGb(model, catalog) * BYTES_PER_GB);
132
+ }
133
+
134
+ export function selectBestQuantizationVariant(
135
+ model: CatalogModel,
136
+ ): CatalogQuantizationVariant | null {
137
+ const quantization = model.quantization;
138
+ if (!quantization) return null;
139
+ return (
140
+ quantization.variants.find(
141
+ (variant) => variant.id === quantization.defaultVariantId,
142
+ ) ??
143
+ quantization.variants.find((variant) => variant.status === "published") ??
144
+ quantization.variants[0] ??
145
+ null
146
+ );
147
+ }
148
+
149
+ const MB_PER_GB = 1024;
150
+
151
+ /**
152
+ * Memory the model can actually use on this host, in GB. On Apple Silicon
153
+ * and mobile the GPU shares system RAM, so total RAM acts as the budget.
154
+ * On discrete-GPU x86 the KV cache + weights live wherever the layers do —
155
+ * weight VRAM higher. CPU-only hosts can give about half of RAM to a model
156
+ * before paging hurts.
157
+ */
158
+ function effectiveMemoryGb(probe: HardwareProbe): number {
159
+ if (probe.appleSilicon) return probe.totalRamGb;
160
+ if (probe.gpu) {
161
+ return Math.max(probe.gpu.totalVramGb, probe.totalRamGb * 0.5);
162
+ }
163
+ return probe.totalRamGb * 0.5;
164
+ }
165
+
166
+ /**
167
+ * Download-size guardrail layered on top of the RAM-budget fit decision:
168
+ * a bundle whose on-disk footprint is a large fraction of the available
169
+ * memory will swap even if the RAM-budget floor says it boots. Returns
170
+ * `"wontfit"` / `"tight"` / `null` ("the size is fine; defer to the
171
+ * RAM-budget level"). Ratios match the historical `assessFit` (desktop)
172
+ * and `mobileFit` (mobile) thresholds.
173
+ */
174
+ function downloadSizeGuardrail(
175
+ hardware: HardwareProbe,
176
+ model: CatalogModel,
177
+ catalog: CatalogModel[],
178
+ isMobile: boolean,
179
+ ): HardwareFitLevel | null {
180
+ const sizeGb = catalogDownloadSizeGb(model, catalog);
181
+ const memGb = isMobile ? hardware.totalRamGb : effectiveMemoryGb(hardware);
182
+ const wontFitRatio = isMobile ? 0.8 : 0.9;
183
+ const tightRatio = isMobile ? 0.65 : 0.7;
184
+ if (sizeGb > memGb * wontFitRatio) return "wontfit";
185
+ if (sizeGb > memGb * tightRatio) return "tight";
186
+ return null;
187
+ }
188
+
189
+ export function assessCatalogModelFit(
190
+ hardware: HardwareProbe,
191
+ model: CatalogModel,
192
+ catalog: CatalogModel[] = MODEL_CATALOG,
193
+ options: { installed?: InstalledModel; manifestLoader?: ManifestLoader } = {},
194
+ ): HardwareFitLevel {
195
+ const isMobile = classifyRecommendationPlatform(hardware) === "mobile";
196
+ const memGb = isMobile ? hardware.totalRamGb : effectiveMemoryGb(hardware);
197
+ // Single source of truth for the RAM floor + fits-vs-tight cutoff:
198
+ // `ram-budget.assessRamFit`. The recommender works in "memory available
199
+ // to the model" terms (VRAM-weighted on GPU hosts), so the OS headroom
200
+ // reserve is already discounted — pass `reserveMb: 0`.
201
+ const ramFit = assessRamFit(model, memGb * MB_PER_GB, {
202
+ installed: options.installed,
203
+ manifestLoader: options.manifestLoader ?? defaultManifestLoader,
204
+ reserveMb: 0,
205
+ });
206
+ if (!ramFit.fits) return "wontfit";
207
+ const sizeLevel = downloadSizeGuardrail(hardware, model, catalog, isMobile);
208
+ if (sizeLevel === "wontfit") return "wontfit";
209
+ if (sizeLevel === "tight" || ramFit.level === "tight") return "tight";
210
+ return "fits";
211
+ }
212
+
213
+ function canFit(
214
+ hardware: HardwareProbe,
215
+ model: CatalogModel,
216
+ catalog: CatalogModel[],
217
+ options: { installed?: InstalledModel; manifestLoader?: ManifestLoader } = {},
218
+ ): boolean {
219
+ if (!hasUsableCpuBackendForRecommendation(hardware)) return false;
220
+ return assessCatalogModelFit(hardware, model, catalog, options) !== "wontfit";
221
+ }
222
+
223
+ function hasUsableCpuBackendForRecommendation(
224
+ hardware: HardwareProbe,
225
+ ): boolean {
226
+ if (hardware.gpu) return true;
227
+ if (hardware.arch !== "arm64" && hardware.arch !== "arm") return true;
228
+ return hardware.cpuFeatures?.neon === true;
229
+ }
230
+
231
+ /**
232
+ * True when every kernel listed in `model.runtime.optimizations.requiresKernel`
233
+ * is advertised as `true` in the binary's CAPABILITIES.json kernels map.
234
+ *
235
+ * `binaryKernels === null` means we have no probe (older binary, or
236
+ * llama-server isn't installed). In that case we trust the catalog —
237
+ * filtering would hide every kernel-required model and the dispatcher's
238
+ * load-time check will surface the real error if/when the user tries to
239
+ * activate it.
240
+ *
241
+ * `unsupportedKernels` is a soft signal layered on top: when the binary
242
+ * has no satisfied `requiresKernel` anchor and exposes only an unsupported
243
+ * backend (OpenVINO-only Intel build for an Eliza-1 text tier), drop the
244
+ * tier so the recommender doesn't suggest a path that has no kernel route.
245
+ * A binary that already satisfies `requiresKernel` stays eligible even
246
+ * when it also advertises an unsupported backend (e.g. OpenVINO
247
+ * co-compiled — the dispatcher steers the spawn off OpenVINO via
248
+ * `applyUnsupportedKernelEnv` at runtime).
249
+ */
250
+ function kernelRequirementsSatisfied(
251
+ model: CatalogModel,
252
+ binaryKernels: Partial<Record<string, boolean>> | null,
253
+ ): boolean {
254
+ const required = model.runtime?.optimizations?.requiresKernel ?? [];
255
+ if (!binaryKernels) return true;
256
+ if (required.length > 0) {
257
+ return required.every((k) => binaryKernels[k] === true);
258
+ }
259
+ const unsupported = model.runtime?.optimizations?.unsupportedKernels ?? [];
260
+ return !unsupported.some((k) => binaryKernels[k] === true);
261
+ }
262
+
263
+ function modelsFromLadder(
264
+ ids: ReadonlyArray<string>,
265
+ catalog: CatalogModel[],
266
+ ): CatalogModel[] {
267
+ const byId = catalogById(catalog);
268
+ return ids.flatMap((id) => {
269
+ const model = byId.get(id);
270
+ return model ? [model] : [];
271
+ });
272
+ }
273
+
274
+ /**
275
+ * True when this host has enough memory headroom to serve the long-context
276
+ * KV cache for a 64k+ window. Threshold mirrors the "16 GB workstation"
277
+ * line from the porting plan — a 64k context for an 8B model at fp16 KV
278
+ * occupies ~4 GB; with TurboQuant compression it fits inside 1 GB. Below
279
+ * 16 GB total we keep the historical short-context preference.
280
+ *
281
+ * For GPU hosts we look at total VRAM, since the KV cache lives wherever
282
+ * the layers do; for CPU-only hosts we look at total RAM.
283
+ */
284
+ const LONG_CONTEXT_RAM_BUMP_THRESHOLD_GB = 16;
285
+ const LONG_CONTEXT_MIN_LENGTH = 65536;
286
+
287
+ function hasLongContextHeadroom(hardware: HardwareProbe): boolean {
288
+ const vramGb = hardware.gpu?.totalVramGb ?? 0;
289
+ if (vramGb >= LONG_CONTEXT_RAM_BUMP_THRESHOLD_GB) return true;
290
+ return hardware.totalRamGb >= LONG_CONTEXT_RAM_BUMP_THRESHOLD_GB;
291
+ }
292
+
293
+ function isLongContextModel(model: CatalogModel): boolean {
294
+ return (
295
+ typeof model.contextLength === "number" &&
296
+ model.contextLength >= LONG_CONTEXT_MIN_LENGTH
297
+ );
298
+ }
299
+
300
+ function fallbackCandidates(
301
+ slot: TextGenerationSlot,
302
+ hardware: HardwareProbe,
303
+ catalog: CatalogModel[],
304
+ budgetOptions: BudgetOptions,
305
+ ): CatalogModel[] {
306
+ const candidates = chatCandidates(catalog).filter(
307
+ (model) =>
308
+ DEFAULT_ELIGIBLE_MODEL_IDS.has(model.id) &&
309
+ canFit(
310
+ hardware,
311
+ model,
312
+ catalog,
313
+ budgetOptionsForModel(model, budgetOptions),
314
+ ),
315
+ );
316
+ const preferLongContext = hasLongContextHeadroom(hardware);
317
+ return candidates.sort((left, right) => {
318
+ if (preferLongContext) {
319
+ const leftLong = isLongContextModel(left) ? 1 : 0;
320
+ const rightLong = isLongContextModel(right) ? 1 : 0;
321
+ if (leftLong !== rightLong) return rightLong - leftLong;
322
+ }
323
+ const sizeDelta =
324
+ catalogDownloadSizeGb(right, catalog) -
325
+ catalogDownloadSizeGb(left, catalog);
326
+ return slot === "TEXT_LARGE" ? sizeDelta : -sizeDelta;
327
+ });
328
+ }
329
+
330
+ export interface RecommendationOptions {
331
+ /**
332
+ * Kernels actually advertised by the installed llama-server binary
333
+ * (parsed from CAPABILITIES.json next to it). When provided, models
334
+ * declaring `requiresKernel` not satisfied by this map are filtered
335
+ * out so we don't recommend a model the user can't actually run on
336
+ * this binary. Pass null/omit when no probe is available — recommender
337
+ * trusts the catalog and the dispatcher's load-time check.
338
+ */
339
+ binaryKernels?: Partial<Record<string, boolean>> | null;
340
+ /**
341
+ * Models the user has already installed. When an Eliza-1 tier in this
342
+ * list has a published `eliza-1.manifest.json` next to its bundle,
343
+ * the recommender consults `manifest.ramBudgetMb` instead of the
344
+ * catalog's coarse `minRamGb` scalar. See `./ram-budget.ts`.
345
+ */
346
+ installed?: ReadonlyArray<InstalledModel>;
347
+ /**
348
+ * Test-only override for the manifest reader. Production callers leave
349
+ * this unset and the helper reads `eliza-1.manifest.json` from disk.
350
+ */
351
+ manifestLoader?: ManifestLoader;
352
+ }
353
+
354
+ interface BudgetOptions {
355
+ installed: ReadonlyArray<InstalledModel>;
356
+ manifestLoader: ManifestLoader;
357
+ }
358
+
359
+ function budgetOptionsForModel(
360
+ model: CatalogModel,
361
+ budget: BudgetOptions,
362
+ ): { installed?: InstalledModel; manifestLoader: ManifestLoader } {
363
+ return {
364
+ installed: budget.installed.find((m) => m.id === model.id),
365
+ manifestLoader: budget.manifestLoader,
366
+ };
367
+ }
368
+
369
+ function resolveBudgetOptions(options: RecommendationOptions): BudgetOptions {
370
+ return {
371
+ installed: options.installed ?? [],
372
+ manifestLoader: options.manifestLoader ?? defaultManifestLoader,
373
+ };
374
+ }
375
+
376
+ export function selectRecommendedModelForSlot(
377
+ slot: TextGenerationSlot,
378
+ hardware: HardwareProbe,
379
+ catalog: CatalogModel[] = MODEL_CATALOG,
380
+ options: RecommendationOptions = {},
381
+ ): RecommendedModelSelection {
382
+ const platformClass = classifyRecommendationPlatform(hardware);
383
+ const ladder = modelsFromLadder(SLOT_LADDERS[platformClass][slot], catalog);
384
+ const binaryKernels = options.binaryKernels ?? null;
385
+ const budget = resolveBudgetOptions(options);
386
+ const eligible = ladder.filter(
387
+ (model) =>
388
+ canFit(hardware, model, catalog, budgetOptionsForModel(model, budget)) &&
389
+ kernelRequirementsSatisfied(model, binaryKernels),
390
+ );
391
+
392
+ // On hosts with >= 16 GB RAM/VRAM, give long-context (>= 64k) ladder
393
+ // entries a small bump so we surface 128k models when they fit. The
394
+ // ladder order still wins when long-context availability is the same
395
+ // for every entry (or when the host doesn't have the headroom).
396
+ const ranked =
397
+ slot === "TEXT_LARGE" &&
398
+ eligible.length > 0 &&
399
+ hasLongContextHeadroom(hardware)
400
+ ? rankLadderByLongContext(eligible)
401
+ : eligible;
402
+
403
+ const alternatives =
404
+ ranked.length > 0
405
+ ? ranked
406
+ : fallbackCandidates(slot, hardware, catalog, budget).filter((model) =>
407
+ kernelRequirementsSatisfied(model, binaryKernels),
408
+ );
409
+ const model = alternatives[0] ?? null;
410
+ const fit = model
411
+ ? assessCatalogModelFit(
412
+ hardware,
413
+ model,
414
+ catalog,
415
+ budgetOptionsForModel(model, budget),
416
+ )
417
+ : null;
418
+ return {
419
+ slot,
420
+ platformClass,
421
+ model,
422
+ fit,
423
+ reason: model
424
+ ? `${platformClass} ${slot} ladder selected ${model.id}`
425
+ : `${platformClass} ${slot} ladder has no fitting catalog model`,
426
+ alternatives,
427
+ };
428
+ }
429
+
430
+ /**
431
+ * Stable sort that pulls long-context models toward the front while
432
+ * preserving relative order within each group. Used only on hosts with
433
+ * the long-context RAM/VRAM headroom — the ladder order remains the
434
+ * tie-breaker so native-runtime preferences survive.
435
+ */
436
+ function rankLadderByLongContext(ladder: CatalogModel[]): CatalogModel[] {
437
+ return ladder
438
+ .map((model, idx) => ({ model, idx, long: isLongContextModel(model) }))
439
+ .sort((left, right) => {
440
+ if (left.long !== right.long) return right.long ? 1 : -1;
441
+ return left.idx - right.idx;
442
+ })
443
+ .map((entry) => entry.model);
444
+ }
445
+
446
+ // ---------------------------------------------------------------------------
447
+ // Default-eligibility on this device — the recommendation-engine gate that
448
+ // consults the bundle's `eliza-1.manifest.json` (`kernels.verifiedBackends`,
449
+ // `evals`, `defaultEligible`) against the device hardware + the bundle's
450
+ // on-device verify state. See `packages/inference/AGENTS.md` §6 + §7.
451
+ // ---------------------------------------------------------------------------
452
+
453
+ /**
454
+ * Project a `HardwareProbe` onto the `Eliza1DeviceCaps` shape the manifest
455
+ * validator's `canSetAsDefault` consumes. CPU is always available; a probed
456
+ * GPU contributes exactly its one backend (`cuda` / `metal` / `vulkan`). RAM
457
+ * is the device total, in MB — `canSetAsDefault` compares against the
458
+ * manifest's `ramBudgetMb.min` floor, not the headroom-discounted figure the
459
+ * ladder uses, because the floor is "will it boot at all".
460
+ */
461
+ export function deviceCapsFromProbe(hardware: HardwareProbe): Eliza1DeviceCaps {
462
+ const backends: Eliza1Backend[] =
463
+ hardware.arch === "arm64" || hardware.arch === "arm"
464
+ ? hardware.cpuFeatures?.neon === true
465
+ ? ["cpu"]
466
+ : []
467
+ : ["cpu"];
468
+ if (hardware.gpu) backends.push(hardware.gpu.backend);
469
+ return {
470
+ availableBackends: backends,
471
+ ramMb: Math.round(hardware.totalRamGb * 1024),
472
+ cpuFeatures: hardware.cpuFeatures,
473
+ };
474
+ }
475
+
476
+ export type BundleDefaultEligibility =
477
+ | { canBeDefault: true }
478
+ | {
479
+ canBeDefault: false;
480
+ reason:
481
+ | "no-manifest"
482
+ | "not-default-eligible"
483
+ | "ram-below-floor"
484
+ | "kernels-unverified-on-device"
485
+ | "not-verified-on-device";
486
+ detail: string;
487
+ };
488
+
489
+ /**
490
+ * True iff this installed Eliza-1 bundle may be offered as the recommended
491
+ * default on this device. The full set of conditions (any one failing →
492
+ * not default):
493
+ *
494
+ * - the bundle ships a validated `eliza-1.manifest.json`,
495
+ * - the manifest is contract-valid (every required kernel declared, every
496
+ * required eval green for a strict release, lineage/files consistent —
497
+ * enforced by `canSetAsDefault` → `collectContractErrors`),
498
+ * - the device exposes at least one backend the manifest verified `pass` on
499
+ * out of the tier's supported set,
500
+ * - the device RAM meets the manifest's `ramBudgetMb.min` floor,
501
+ * - the bundle has passed the one-time on-device verify pass
502
+ * (`InstalledModel.bundleVerifiedAt` is set) — a materialized-but-unverified
503
+ * bundle is never auto-selected, per AGENTS.md §7.
504
+ *
505
+ * `manifest.defaultEligible: true` is NOT required at the gate level — a
506
+ * `base-v1-candidate` bundle that passes every above condition is allowed
507
+ * to fill an empty default slot. The recommender prefers a strict release
508
+ * (`defaultEligible: true`) over a candidate when both are installed.
509
+ */
510
+ export function canBundleBeDefaultOnDevice(
511
+ installed: InstalledModel,
512
+ hardware: HardwareProbe,
513
+ options: { manifestLoader?: ManifestLoader } = {},
514
+ ): BundleDefaultEligibility {
515
+ const loader = options.manifestLoader ?? defaultManifestLoader;
516
+ const manifest: Eliza1Manifest | null = loader(installed.id, installed);
517
+ if (!manifest) {
518
+ return {
519
+ canBeDefault: false,
520
+ reason: "no-manifest",
521
+ detail: `${installed.id}: no validated eliza-1.manifest.json next to the bundle`,
522
+ };
523
+ }
524
+ if (!installed.bundleVerifiedAt) {
525
+ return {
526
+ canBeDefault: false,
527
+ reason: "not-verified-on-device",
528
+ detail: `${installed.id}: bundle materialized but the on-device verify pass (load → 1-token text → 1-phrase voice → barge-in) has not run`,
529
+ };
530
+ }
531
+ const caps = deviceCapsFromProbe(hardware);
532
+ if (canSetAsDefault(manifest, caps)) return { canBeDefault: true };
533
+
534
+ // canSetAsDefault returned false — disambiguate why so the UI/log is precise.
535
+ if (manifest.ramBudgetMb.min > caps.ramMb) {
536
+ return {
537
+ canBeDefault: false,
538
+ reason: "ram-below-floor",
539
+ detail: `${installed.id}: device RAM ${caps.ramMb} MB is below the manifest floor ${manifest.ramBudgetMb.min} MB`,
540
+ };
541
+ }
542
+ const supported = new Set<Eliza1Backend>(
543
+ SUPPORTED_BACKENDS_BY_TIER[manifest.tier],
544
+ );
545
+ const verifiedOnDeviceBackend = caps.availableBackends.some(
546
+ (b) =>
547
+ supported.has(b) &&
548
+ manifest.kernels.verifiedBackends[b].status === "pass",
549
+ );
550
+ if (!verifiedOnDeviceBackend) {
551
+ const deviceBackends = caps.availableBackends.join(", ");
552
+ return {
553
+ canBeDefault: false,
554
+ reason: "kernels-unverified-on-device",
555
+ detail: `${installed.id}: no backend the device exposes (${deviceBackends}) has a 'pass' kernel-verify report in the manifest`,
556
+ };
557
+ }
558
+ // RAM ok, backend ok — the failure must be a manifest-contract path the
559
+ // validator caught (e.g. a required-eval gate not passed for a strict
560
+ // release, a lineage/files mismatch, an inconsistent provenance block).
561
+ // All contract failures make the bundle ineligible to be the device default.
562
+ return {
563
+ canBeDefault: false,
564
+ reason: "not-default-eligible",
565
+ detail: `${installed.id}: manifest failed the contract check (an eval gate, kernel-coverage rule, or lineage/files consistency rule)`,
566
+ };
567
+ }
568
+
569
+ export function selectRecommendedModels(
570
+ hardware: HardwareProbe,
571
+ catalog: CatalogModel[] = MODEL_CATALOG,
572
+ options: RecommendationOptions = {},
573
+ ): Record<TextGenerationSlot, RecommendedModelSelection> {
574
+ return {
575
+ TEXT_SMALL: selectRecommendedModelForSlot(
576
+ "TEXT_SMALL",
577
+ hardware,
578
+ catalog,
579
+ options,
580
+ ),
581
+ TEXT_LARGE: selectRecommendedModelForSlot(
582
+ "TEXT_LARGE",
583
+ hardware,
584
+ catalog,
585
+ options,
586
+ ),
587
+ };
588
+ }
589
+
590
+ /**
591
+ * Pick the model the engine should auto-load on first run when no user
592
+ * preference exists. Always resolves to an Eliza-1 default-eligible
593
+ * tier — never a non-Eliza catalog entry, never a HF-search result.
594
+ *
595
+ * Resolution order:
596
+ * 1. `FIRST_RUN_DEFAULT_MODEL_ID` when present in the catalog, in the
597
+ * default-eligible set, and not marked `publishStatus: "pending"`.
598
+ * 2. The first default-eligible, non-pending chat entry in the catalog
599
+ * as a fallback when the preferred id is missing or its HF bundle
600
+ * isn't published yet (elizaOS/eliza#7629). The fall-through walks
601
+ * the catalog in order, so the maintainer can keep
602
+ * `FIRST_RUN_DEFAULT_MODEL_ID` pointed at the *intended* default
603
+ * while the publish pipeline catches up.
604
+ * 3. If every default-eligible tier is pending, last-resort to ANY
605
+ * default-eligible tier — the device download path will fail
606
+ * cleanly with a 404 rather than silently picking a private
607
+ * non-Eliza model.
608
+ *
609
+ * Returns null only when no default-eligible entry exists at all —
610
+ * which means the catalog is misconfigured and the caller should
611
+ * surface a hard error rather than degrade silently.
612
+ */
613
+ export function recommendForFirstRun(
614
+ catalog: CatalogModel[] = MODEL_CATALOG,
615
+ ): CatalogModel | null {
616
+ const byId = catalogById(catalog);
617
+ const isEligibleChat = (model: CatalogModel): boolean =>
618
+ !model.hiddenFromCatalog && DEFAULT_ELIGIBLE_MODEL_IDS.has(model.id);
619
+ const publishStatusFor = (model: CatalogModel): "published" | "pending" =>
620
+ model.publishStatus ?? eliza1TierPublishStatus(model.id as Eliza1TierId);
621
+ const isPublishedEligibleChat = (model: CatalogModel): boolean =>
622
+ isEligibleChat(model) && publishStatusFor(model) === "published";
623
+
624
+ const preferred = byId.get(FIRST_RUN_DEFAULT_MODEL_ID);
625
+ if (preferred && isPublishedEligibleChat(preferred)) return preferred;
626
+
627
+ // Preferred is missing or its bundle is still being published — walk the
628
+ // catalog for the first eligible chat tier whose bundle IS published.
629
+ const fallbackPublished = catalog.find(isPublishedEligibleChat);
630
+ if (fallbackPublished) return fallbackPublished;
631
+
632
+ // Every eligible tier is "pending" — last-resort to the preferred tier
633
+ // when it exists in the catalog, otherwise the first default-eligible
634
+ // chat entry. Either path lets the downloader emit a clear "manifest
635
+ // 404" message rather than silently picking a non-Eliza model.
636
+ if (preferred && isEligibleChat(preferred)) return preferred;
637
+ return catalog.find(isEligibleChat) ?? null;
638
+ }
639
+
640
+ export function chooseSmallerFallbackModel(
641
+ currentModelId: string,
642
+ hardware: HardwareProbe,
643
+ slot: TextGenerationSlot = "TEXT_LARGE",
644
+ catalog: CatalogModel[] = MODEL_CATALOG,
645
+ options: RecommendationOptions = {},
646
+ ): CatalogModel | null {
647
+ const byId = catalogById(catalog);
648
+ const current = byId.get(currentModelId);
649
+ const currentSize = current
650
+ ? catalogDownloadSizeGb(current, catalog)
651
+ : Number.POSITIVE_INFINITY;
652
+ const platformClass = classifyRecommendationPlatform(hardware);
653
+ const budget = resolveBudgetOptions(options);
654
+ const ladderFallback = modelsFromLadder(
655
+ SLOT_LADDERS[platformClass][slot],
656
+ catalog,
657
+ )
658
+ .filter((model) => model.id !== currentModelId)
659
+ .filter((model) => catalogDownloadSizeGb(model, catalog) < currentSize)
660
+ .filter((model) =>
661
+ canFit(hardware, model, catalog, budgetOptionsForModel(model, budget)),
662
+ )[0];
663
+ if (ladderFallback) return ladderFallback;
664
+
665
+ return (
666
+ fallbackCandidates(slot, hardware, catalog, budget)
667
+ .filter((model) => model.id !== currentModelId)
668
+ .filter(
669
+ (model) => catalogDownloadSizeGb(model, catalog) < currentSize,
670
+ )[0] ?? null
671
+ );
672
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * On-disk registry of installed models.
3
+ *
4
+ * Two sources feed the registry:
5
+ * 1. Eliza-owned downloads (source: "eliza-download") — written on
6
+ * successful completion by the downloader.
7
+ * 2. External scans (source: "external-scan") — merged in at read time
8
+ * from `scanExternalModels()`. These are never persisted to the
9
+ * registry file; a rescan runs whenever we read.
10
+ *
11
+ * The JSON file only holds Eliza-owned entries. That way, if a user
12
+ * cleans up LM Studio models we don't show stale ghosts.
13
+ */
14
+ import type { InstalledModel } from "./types";
15
+ /**
16
+ * Return all models currently usable: persisted Eliza downloads plus a
17
+ * fresh external-tool scan. External duplicates of Eliza-owned files are
18
+ * filtered out by path.
19
+ */
20
+ export declare function listInstalledModels(): Promise<InstalledModel[]>;
21
+ /** Add or update a Eliza-owned entry. External entries are rejected. */
22
+ export declare function upsertElizaModel(model: InstalledModel): Promise<void>;
23
+ /** Mark an existing Eliza-owned model as most-recently-used. */
24
+ export declare function touchElizaModel(id: string): Promise<void>;
25
+ /**
26
+ * Delete a Eliza-owned model from the registry and from disk.
27
+ *
28
+ * Refuses if the model was discovered from another tool — Eliza must not
29
+ * touch files it doesn't own. Callers surface that refusal as a 4xx.
30
+ */
31
+ export declare function removeElizaModel(id: string): Promise<{
32
+ removed: boolean;
33
+ reason?: "external" | "not-found";
34
+ }>;
35
+ //# sourceMappingURL=registry.d.ts.map