@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,273 @@
1
+ /**
2
+ * Integration tests for `ensureLocalArtifacts`.
3
+ *
4
+ * The orchestrator's unit tests (`ensure-local-artifacts.test.ts`) inject a
5
+ * tiny `vi.fn()`-shaped service. These integration tests stand up a more
6
+ * realistic shape of `LocalInferenceService` — full method test doubles with
7
+ * `vi.fn` recording and configurable behavior — so the wiring inside the
8
+ * service surface (`startDownload`, `getInstalled`, `getHardware`) is
9
+ * exercised the way the real boot path would call it. The four-mode matrix
10
+ * (cloud / remote / local + signedInCloud / local + !signedInCloud), the
11
+ * already-installed short-circuit, and per-artifact failure isolation are
12
+ * covered.
13
+ *
14
+ * Note on test lane: filename ends in `.integration.test.ts`. The default
15
+ * vitest config picks this up via the `*.test.ts` glob; lanes that exclude
16
+ * integration tests should run it explicitly via the path
17
+ * (see Part 3 of the parallel-sweep brief).
18
+ */
19
+
20
+ import { beforeEach, describe, expect, it, vi } from "vitest";
21
+
22
+ import { ensureLocalArtifacts } from "./ensure-local-artifacts";
23
+ import type { LocalInferenceService } from "./service";
24
+ import type { DownloadJob, HardwareProbe, InstalledModel } from "./types";
25
+
26
+ interface MockService {
27
+ service: LocalInferenceService;
28
+ startDownload: ReturnType<typeof vi.fn>;
29
+ getHardware: ReturnType<typeof vi.fn>;
30
+ getInstalled: ReturnType<typeof vi.fn>;
31
+ }
32
+
33
+ function makeJob(modelId: string): DownloadJob {
34
+ return {
35
+ jobId: `job-${modelId}`,
36
+ modelId,
37
+ state: "queued",
38
+ received: 0,
39
+ total: 1024,
40
+ bytesPerSec: 0,
41
+ etaMs: null,
42
+ startedAt: new Date().toISOString(),
43
+ updatedAt: new Date().toISOString(),
44
+ };
45
+ }
46
+
47
+ function defaultHardware(): HardwareProbe {
48
+ return {
49
+ totalRamGb: 16,
50
+ freeRamGb: 8,
51
+ gpu: null,
52
+ cpuCores: 8,
53
+ platform: "darwin",
54
+ arch: "arm64",
55
+ appleSilicon: true,
56
+ recommendedBucket: "mid",
57
+ source: "os-fallback",
58
+ };
59
+ }
60
+
61
+ interface MockServiceOverrides {
62
+ installed?: InstalledModel[];
63
+ hardware?: HardwareProbe;
64
+ startDownloadImpl?: (modelId: string) => Promise<DownloadJob>;
65
+ }
66
+
67
+ function makeMockService(overrides: MockServiceOverrides = {}): MockService {
68
+ const installed = overrides.installed ?? [];
69
+ const hardware = overrides.hardware ?? defaultHardware();
70
+
71
+ const startDownload = vi.fn(
72
+ overrides.startDownloadImpl ??
73
+ (async (modelId: string) => makeJob(modelId)),
74
+ );
75
+ const getHardware = vi.fn(async () => hardware);
76
+ const getInstalled = vi.fn(async () => installed);
77
+
78
+ const service = {
79
+ startDownload,
80
+ getHardware,
81
+ getInstalled,
82
+ } as unknown as LocalInferenceService;
83
+
84
+ return { service, startDownload, getHardware, getInstalled };
85
+ }
86
+
87
+ function makeLogger() {
88
+ return { info: vi.fn(), warn: vi.fn() };
89
+ }
90
+
91
+ describe("ensureLocalArtifacts integration", () => {
92
+ beforeEach(() => {
93
+ vi.clearAllMocks();
94
+ });
95
+
96
+ describe("mode matrix", () => {
97
+ it("cloud mode skips downloads (no service calls, artifacts: [], complete: true)", async () => {
98
+ const mock = makeMockService();
99
+
100
+ const result = await ensureLocalArtifacts({
101
+ mode: "cloud",
102
+ signedInCloud: true,
103
+ service: mock.service,
104
+ logger: makeLogger(),
105
+ });
106
+
107
+ expect(result).toEqual({ artifacts: [], complete: true });
108
+ expect(mock.startDownload).not.toHaveBeenCalled();
109
+ expect(mock.getHardware).not.toHaveBeenCalled();
110
+ expect(mock.getInstalled).not.toHaveBeenCalled();
111
+ });
112
+
113
+ it("remote mode skips downloads (no service calls, artifacts: [], complete: true)", async () => {
114
+ const mock = makeMockService();
115
+
116
+ const result = await ensureLocalArtifacts({
117
+ mode: "remote",
118
+ signedInCloud: false,
119
+ service: mock.service,
120
+ logger: makeLogger(),
121
+ });
122
+
123
+ expect(result).toEqual({ artifacts: [], complete: true });
124
+ expect(mock.startDownload).not.toHaveBeenCalled();
125
+ });
126
+
127
+ it("local mode + signedInCloud=true enqueues 3 artifacts (embedding/tts/stt) — not text", async () => {
128
+ const mock = makeMockService();
129
+
130
+ const result = await ensureLocalArtifacts({
131
+ mode: "local",
132
+ tier: "2b",
133
+ signedInCloud: true,
134
+ service: mock.service,
135
+ logger: makeLogger(),
136
+ });
137
+
138
+ const kinds = result.artifacts.map((a) => a.kind);
139
+ expect(kinds.sort()).toEqual(["embedding", "stt", "tts"]);
140
+ expect(kinds).not.toContain("text");
141
+ expect(result.artifacts.every((a) => a.status === "started")).toBe(true);
142
+ expect(result.complete).toBe(true);
143
+ expect(mock.startDownload).toHaveBeenCalledTimes(3);
144
+ });
145
+
146
+ it("local mode + signedInCloud=false enqueues all 4 artifacts (incl. text)", async () => {
147
+ const mock = makeMockService();
148
+
149
+ const result = await ensureLocalArtifacts({
150
+ mode: "local",
151
+ tier: "2b",
152
+ signedInCloud: false,
153
+ service: mock.service,
154
+ logger: makeLogger(),
155
+ });
156
+
157
+ const kinds = result.artifacts.map((a) => a.kind);
158
+ expect(kinds.sort()).toEqual(["embedding", "stt", "text", "tts"]);
159
+ expect(result.artifacts.find((a) => a.kind === "text")?.status).toBe(
160
+ "started",
161
+ );
162
+ expect(mock.startDownload).toHaveBeenCalledTimes(4);
163
+ expect(result.complete).toBe(true);
164
+ });
165
+
166
+ it("local-only mode mirrors local for the artifact selection (4 with !signedInCloud)", async () => {
167
+ const mock = makeMockService();
168
+
169
+ const result = await ensureLocalArtifacts({
170
+ mode: "local-only",
171
+ tier: "2b",
172
+ signedInCloud: false,
173
+ service: mock.service,
174
+ logger: makeLogger(),
175
+ });
176
+
177
+ expect(mock.startDownload).toHaveBeenCalledTimes(4);
178
+ expect(result.complete).toBe(true);
179
+ });
180
+ });
181
+
182
+ describe("already-installed short-circuit", () => {
183
+ it("records each kind as already-installed when the bundle is staged on disk", async () => {
184
+ const installed: InstalledModel[] = [
185
+ {
186
+ id: "eliza-1-2b",
187
+ displayName: "eliza-1-2b",
188
+ path: "/tmp/eliza-1-2b.gguf",
189
+ sizeBytes: 1024,
190
+ installedAt: new Date().toISOString(),
191
+ lastUsedAt: null,
192
+ source: "eliza-download",
193
+ },
194
+ ];
195
+ // Pin the tier so the test does not depend on which tier the
196
+ // recommender's hardware ladder lands on for `defaultHardware()`.
197
+ const mock = makeMockService({ installed });
198
+
199
+ const result = await ensureLocalArtifacts({
200
+ mode: "local",
201
+ tier: "2b",
202
+ signedInCloud: false,
203
+ service: mock.service,
204
+ logger: makeLogger(),
205
+ });
206
+
207
+ expect(mock.startDownload).not.toHaveBeenCalled();
208
+ expect(result.artifacts).toHaveLength(4); // includes text
209
+ expect(
210
+ result.artifacts.every((a) => a.status === "already-installed"),
211
+ ).toBe(true);
212
+ expect(result.artifacts.every((a) => a.modelId === "eliza-1-2b")).toBe(
213
+ true,
214
+ );
215
+ expect(result.complete).toBe(true);
216
+ });
217
+ });
218
+
219
+ describe("failure isolation", () => {
220
+ it("one startDownload rejection does not collapse the others; result is partial", async () => {
221
+ // First call rejects; subsequent calls succeed. The orchestrator wraps
222
+ // each artifact in its own settled slot, so the other downloads still
223
+ // count as `started` and the aggregate is `complete: false`.
224
+ const mock = makeMockService({
225
+ startDownloadImpl: async (modelId: string) => {
226
+ if (mock.startDownload.mock.calls.length === 1) {
227
+ throw new Error("simulated download backend failure");
228
+ }
229
+ return makeJob(modelId);
230
+ },
231
+ });
232
+
233
+ const result = await ensureLocalArtifacts({
234
+ mode: "local",
235
+ tier: "2b",
236
+ signedInCloud: false,
237
+ service: mock.service,
238
+ logger: makeLogger(),
239
+ });
240
+
241
+ const statuses = result.artifacts.map((a) => a.status);
242
+ expect(statuses).toContain("failed");
243
+ expect(statuses).toContain("started");
244
+ expect(statuses.filter((s) => s === "started").length).toBe(3);
245
+ expect(statuses.filter((s) => s === "failed").length).toBe(1);
246
+ expect(result.complete).toBe(false);
247
+
248
+ const failed = result.artifacts.find((a) => a.status === "failed");
249
+ expect(failed?.reason).toContain("simulated download backend failure");
250
+ });
251
+
252
+ it("a getInstalled() failure does not stop the downloads — orchestrator still fires every kind", async () => {
253
+ const mock = makeMockService();
254
+ // Override the auto-success mock with one that throws.
255
+ mock.getInstalled.mockImplementationOnce(async () => {
256
+ throw new Error("disk read failed");
257
+ });
258
+
259
+ const result = await ensureLocalArtifacts({
260
+ mode: "local",
261
+ tier: "2b",
262
+ signedInCloud: true,
263
+ service: mock.service,
264
+ logger: makeLogger(),
265
+ });
266
+
267
+ // Three downloads (embedding/tts/stt) all fired despite the install probe failure.
268
+ expect(mock.startDownload).toHaveBeenCalledTimes(3);
269
+ expect(result.complete).toBe(true);
270
+ expect(result.artifacts.every((a) => a.status === "started")).toBe(true);
271
+ });
272
+ });
273
+ });
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Tests for the local-artifact orchestrator. Every test injects a test-double
3
+ * `LocalInferenceService` so the real downloader / hardware probe stay out
4
+ * of the picture — the orchestrator's contract is "trigger parallel
5
+ * downloads via the service facade", and the test verifies exactly that.
6
+ */
7
+
8
+ import { beforeEach, describe, expect, it, vi } from "vitest";
9
+
10
+ import { ensureLocalArtifacts } from "./ensure-local-artifacts";
11
+ import type { LocalInferenceService } from "./service";
12
+ import type { DownloadJob, HardwareProbe, InstalledModel } from "./types";
13
+
14
+ interface FakeServiceState {
15
+ hardware: HardwareProbe;
16
+ installed: InstalledModel[];
17
+ startDownload: ReturnType<typeof vi.fn>;
18
+ getHardware: ReturnType<typeof vi.fn>;
19
+ getInstalled: ReturnType<typeof vi.fn>;
20
+ }
21
+
22
+ function makeJob(modelId: string): DownloadJob {
23
+ return {
24
+ jobId: `job-${modelId}`,
25
+ modelId,
26
+ state: "queued",
27
+ received: 0,
28
+ total: 1024,
29
+ bytesPerSec: 0,
30
+ etaMs: null,
31
+ startedAt: new Date().toISOString(),
32
+ updatedAt: new Date().toISOString(),
33
+ };
34
+ }
35
+
36
+ /**
37
+ * Default probe is a modest Apple Silicon laptop — the recommender's ladder
38
+ * lands on an Eliza-1 tier for this shape, which keeps the assertions
39
+ * concrete (per-tier assertions pin the tier explicitly via the `tier`
40
+ * arg so they decouple from `recommendation.ts` changes).
41
+ */
42
+ function defaultHardware(): HardwareProbe {
43
+ return {
44
+ totalRamGb: 16,
45
+ freeRamGb: 8,
46
+ gpu: null,
47
+ cpuCores: 8,
48
+ platform: "darwin",
49
+ arch: "arm64",
50
+ appleSilicon: true,
51
+ recommendedBucket: "mid",
52
+ source: "os-fallback",
53
+ };
54
+ }
55
+
56
+ function makeService(overrides: Partial<FakeServiceState> = {}): {
57
+ service: LocalInferenceService;
58
+ state: FakeServiceState;
59
+ } {
60
+ const startDownload = vi.fn(async (modelId: string) => makeJob(modelId));
61
+ const installed = overrides.installed ?? [];
62
+ const hardware = overrides.hardware ?? defaultHardware();
63
+ const getHardware = vi.fn(async () => hardware);
64
+ const getInstalled = vi.fn(async () => installed);
65
+
66
+ const state: FakeServiceState = {
67
+ hardware,
68
+ installed,
69
+ startDownload,
70
+ getHardware,
71
+ getInstalled,
72
+ };
73
+
74
+ const service = {
75
+ startDownload,
76
+ getHardware,
77
+ getInstalled,
78
+ // Other methods on the real facade are never touched by the
79
+ // orchestrator; the type-cast below is the seam.
80
+ } as unknown as LocalInferenceService;
81
+
82
+ return { service, state };
83
+ }
84
+
85
+ function makeLogger() {
86
+ return { info: vi.fn(), warn: vi.fn() };
87
+ }
88
+
89
+ describe("ensureLocalArtifacts", () => {
90
+ beforeEach(() => {
91
+ vi.clearAllMocks();
92
+ });
93
+
94
+ it("skips downloads in cloud mode (complete=true)", async () => {
95
+ const { service, state } = makeService();
96
+ const logger = makeLogger();
97
+
98
+ const result = await ensureLocalArtifacts({
99
+ mode: "cloud",
100
+ signedInCloud: true,
101
+ service,
102
+ logger,
103
+ });
104
+
105
+ expect(result.complete).toBe(true);
106
+ expect(result.artifacts).toEqual([]);
107
+ expect(state.startDownload).not.toHaveBeenCalled();
108
+ expect(state.getHardware).not.toHaveBeenCalled();
109
+ expect(state.getInstalled).not.toHaveBeenCalled();
110
+ });
111
+
112
+ it("skips downloads in remote mode", async () => {
113
+ const { service, state } = makeService();
114
+
115
+ const result = await ensureLocalArtifacts({
116
+ mode: "remote",
117
+ signedInCloud: false,
118
+ service,
119
+ logger: makeLogger(),
120
+ });
121
+
122
+ expect(result.complete).toBe(true);
123
+ expect(result.artifacts).toEqual([]);
124
+ expect(state.startDownload).not.toHaveBeenCalled();
125
+ });
126
+
127
+ it("local + signedInCloud=true triggers embedding/tts/stt but skips text", async () => {
128
+ const { service, state } = makeService();
129
+ const logger = makeLogger();
130
+
131
+ const result = await ensureLocalArtifacts({
132
+ mode: "local",
133
+ tier: "2b",
134
+ signedInCloud: true,
135
+ service,
136
+ logger,
137
+ });
138
+
139
+ const kinds = result.artifacts.map((a) => a.kind);
140
+ expect(kinds).toEqual(expect.arrayContaining(["embedding", "tts", "stt"]));
141
+ expect(kinds).not.toContain("text");
142
+ expect(result.artifacts.every((a) => a.status === "started")).toBe(true);
143
+ expect(result.complete).toBe(true);
144
+
145
+ // startDownload should fire once per artifact kind. The downloader
146
+ // is internally idempotent on the modelId, so even when several
147
+ // calls share the same id (the bundle today) all three slots
148
+ // produce a `started` outcome.
149
+ expect(state.startDownload).toHaveBeenCalledTimes(3);
150
+ });
151
+
152
+ it("local + signedInCloud=false triggers all four artifacts including text", async () => {
153
+ const { service, state } = makeService();
154
+
155
+ const result = await ensureLocalArtifacts({
156
+ mode: "local",
157
+ tier: "2b",
158
+ signedInCloud: false,
159
+ service,
160
+ logger: makeLogger(),
161
+ });
162
+
163
+ const kinds = result.artifacts.map((a) => a.kind);
164
+ expect(kinds).toEqual(
165
+ expect.arrayContaining(["embedding", "tts", "stt", "text"]),
166
+ );
167
+ expect(result.artifacts.find((a) => a.kind === "text")?.status).toBe(
168
+ "started",
169
+ );
170
+ expect(state.startDownload).toHaveBeenCalledTimes(4);
171
+ expect(result.complete).toBe(true);
172
+ });
173
+
174
+ it("local-only mode behaves identically to local for artifact selection", async () => {
175
+ const { service, state } = makeService();
176
+
177
+ await ensureLocalArtifacts({
178
+ mode: "local-only",
179
+ tier: "2b",
180
+ signedInCloud: false,
181
+ service,
182
+ logger: makeLogger(),
183
+ });
184
+
185
+ expect(state.startDownload).toHaveBeenCalledTimes(4);
186
+ });
187
+
188
+ it("respects an explicit tier override (skips hardware probe)", async () => {
189
+ const { service, state } = makeService();
190
+
191
+ const result = await ensureLocalArtifacts({
192
+ mode: "local",
193
+ tier: "9b",
194
+ signedInCloud: false,
195
+ service,
196
+ logger: makeLogger(),
197
+ });
198
+
199
+ expect(state.getHardware).not.toHaveBeenCalled();
200
+ expect(result.artifacts.every((a) => a.modelId === "eliza-1-9b")).toBe(
201
+ true,
202
+ );
203
+ });
204
+
205
+ it("runs the four downloads in parallel via Promise.allSettled", async () => {
206
+ const order: string[] = [];
207
+ // Build the resolver alongside the Promise so TypeScript can pin the
208
+ // resolver as a non-null callable — the executor-pattern leaves the
209
+ // resolver typed as `(() => void) | null` after narrowing.
210
+ let resolveGate!: () => void;
211
+ const gate = new Promise<void>((resolve) => {
212
+ resolveGate = resolve;
213
+ });
214
+
215
+ const startDownload = vi.fn(async (modelId: string) => {
216
+ order.push(`enter:${modelId}`);
217
+ await gate;
218
+ order.push(`exit:${modelId}`);
219
+ return makeJob(modelId);
220
+ });
221
+ const getHardware = vi.fn(async () => defaultHardware());
222
+ const getInstalled = vi.fn(async () => []);
223
+ const service = {
224
+ startDownload,
225
+ getHardware,
226
+ getInstalled,
227
+ } as unknown as LocalInferenceService;
228
+
229
+ const promise = ensureLocalArtifacts({
230
+ mode: "local",
231
+ tier: "2b",
232
+ signedInCloud: false,
233
+ service,
234
+ logger: makeLogger(),
235
+ });
236
+
237
+ // Wait one microtask cycle so every artifact has a chance to enter.
238
+ await new Promise((r) => setTimeout(r, 0));
239
+
240
+ // Four artifacts must all have entered before any can exit — that's
241
+ // what "parallel" buys us. If the orchestrator awaited them
242
+ // sequentially, only one would have entered by now.
243
+ const enters = order.filter((e) => e.startsWith("enter:")).length;
244
+ expect(enters).toBe(4);
245
+
246
+ resolveGate();
247
+ await promise;
248
+ expect(order.filter((e) => e.startsWith("exit:")).length).toBe(4);
249
+ });
250
+
251
+ it("records already-installed when the chosen bundle is present", async () => {
252
+ // Pin the tier so the test is decoupled from the recommender's
253
+ // platform-class ladder (which on the test's modest Apple-Silicon
254
+ // probe may land on a different tier). The orchestrator's contract is
255
+ // "skip when installed"; the tier picker is a separate concern
256
+ // already covered by `recommendation.test.ts`.
257
+ const installed: InstalledModel[] = [
258
+ {
259
+ id: "eliza-1-2b",
260
+ displayName: "eliza-1-2b",
261
+ path: "/tmp/eliza-1-2b.gguf",
262
+ sizeBytes: 1024,
263
+ installedAt: new Date().toISOString(),
264
+ lastUsedAt: null,
265
+ source: "eliza-download",
266
+ },
267
+ ];
268
+ const { service, state } = makeService({ installed });
269
+
270
+ const result = await ensureLocalArtifacts({
271
+ mode: "local",
272
+ tier: "2b",
273
+ signedInCloud: false,
274
+ service,
275
+ logger: makeLogger(),
276
+ });
277
+
278
+ expect(state.startDownload).not.toHaveBeenCalled();
279
+ expect(
280
+ result.artifacts.every((a) => a.status === "already-installed"),
281
+ ).toBe(true);
282
+ expect(result.complete).toBe(true);
283
+ });
284
+
285
+ it("does not fail the orchestrator on individual artifact failures", async () => {
286
+ const startDownload = vi.fn(async (modelId: string) => {
287
+ // First call rejects; subsequent calls succeed. The orchestrator
288
+ // must wrap each artifact independently so one failure doesn't
289
+ // collapse the others.
290
+ if (startDownload.mock.calls.length === 1) {
291
+ throw new Error("simulated network failure");
292
+ }
293
+ return makeJob(modelId);
294
+ });
295
+ const service = {
296
+ startDownload,
297
+ getHardware: vi.fn(async () => defaultHardware()),
298
+ getInstalled: vi.fn(async () => []),
299
+ } as unknown as LocalInferenceService;
300
+ const logger = makeLogger();
301
+
302
+ const result = await ensureLocalArtifacts({
303
+ mode: "local",
304
+ tier: "2b",
305
+ signedInCloud: false,
306
+ service,
307
+ logger,
308
+ });
309
+
310
+ const statuses = result.artifacts.map((a) => a.status);
311
+ expect(statuses).toContain("failed");
312
+ expect(statuses).toContain("started");
313
+ expect(result.complete).toBe(false);
314
+ const failed = result.artifacts.find((a) => a.status === "failed");
315
+ expect(failed?.reason).toContain("simulated network failure");
316
+ });
317
+
318
+ it("returns a skipped result when the recommender finds no fitting tier", async () => {
319
+ // A device with 0 GB of RAM defeats every tier's floor; the
320
+ // recommender returns null and the orchestrator records skipped
321
+ // outcomes per kind.
322
+ const hardware: HardwareProbe = {
323
+ ...defaultHardware(),
324
+ totalRamGb: 0,
325
+ freeRamGb: 0,
326
+ };
327
+ const { service, state } = makeService({ hardware });
328
+
329
+ const result = await ensureLocalArtifacts({
330
+ mode: "local",
331
+ signedInCloud: false,
332
+ service,
333
+ logger: makeLogger(),
334
+ });
335
+
336
+ expect(state.startDownload).not.toHaveBeenCalled();
337
+ expect(result.complete).toBe(false);
338
+ expect(result.artifacts.every((a) => a.status === "skipped")).toBe(true);
339
+ expect(result.artifacts.length).toBe(4); // includes text since signedInCloud=false
340
+ });
341
+
342
+ it("tolerates a getInstalled() failure and still triggers the downloads", async () => {
343
+ const startDownload = vi.fn(async (modelId: string) => makeJob(modelId));
344
+ const service = {
345
+ startDownload,
346
+ getHardware: vi.fn(async () => defaultHardware()),
347
+ getInstalled: vi.fn(async () => {
348
+ throw new Error("disk read failed");
349
+ }),
350
+ } as unknown as LocalInferenceService;
351
+ const logger = makeLogger();
352
+
353
+ const result = await ensureLocalArtifacts({
354
+ mode: "local",
355
+ tier: "2b",
356
+ signedInCloud: true,
357
+ service,
358
+ logger,
359
+ });
360
+
361
+ // Three downloads (embedding/tts/stt) — text skipped due to
362
+ // signedInCloud — and every one fired despite the install probe
363
+ // failure.
364
+ expect(startDownload).toHaveBeenCalledTimes(3);
365
+ expect(result.complete).toBe(true);
366
+ expect(logger.warn).toHaveBeenCalled();
367
+ });
368
+ });