@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,554 @@
1
+ /**
2
+ * Local-runtime compat routes for the voice sub-model auto-updater
3
+ * (R5-versioning §3 + §4 + §5).
4
+ *
5
+ * Mirrors the signed Cloud catalog endpoint
6
+ * (`cloud/apps/api/v1/voice-models/catalog/route.ts`) for the on-device
7
+ * surface so the UI can talk to the local runtime without depending on
8
+ * Cloud being reachable. The endpoints expose:
9
+ *
10
+ * GET /api/local-inference/voice-models
11
+ * → { installations: VoiceModelInstallationView[] }
12
+ * Resolves currently-installed versions by reading the bundle voice
13
+ * directory (`<state-dir>/models/voice/`) and matching filenames
14
+ * against `VOICE_MODEL_VERSIONS`.
15
+ *
16
+ * GET /api/local-inference/voice-models/check
17
+ * → { lastCheckedAt, statuses: VoiceModelStatus[] }
18
+ * Invokes `VoiceModelUpdater.check()` which walks the cascade
19
+ * (Cloud → GitHub → HF) and returns a per-id decision.
20
+ *
21
+ * POST /api/local-inference/voice-models/:id/update
22
+ * → { ok: true, finalPath, sha256, sizeBytes }
23
+ * Triggers `downloadVoiceModel()` for the named id, gated on
24
+ * `NetworkPolicy` evaluation per R5 §4. Refuses when the policy
25
+ * decision is not `allow=true`.
26
+ *
27
+ * POST /api/local-inference/voice-models/:id/pin
28
+ * Body: { pinned: boolean }
29
+ * → { ok: true, id, pinned }
30
+ * Toggles the on-disk pin file so the auto-updater skips this id.
31
+ *
32
+ * GET /api/local-inference/voice-models/preferences
33
+ * → { preferences: NetworkPolicyPreferences, isOwner: boolean }
34
+ *
35
+ * POST /api/local-inference/voice-models/preferences
36
+ * Body: Partial<NetworkPolicyPreferences>
37
+ * → { ok: true, preferences }
38
+ * Writes the user's Wi-Fi/cellular/metered policy preferences.
39
+ * Per R5 §5.4 the cellular + metered toggles are OWNER-only — the
40
+ * route returns 403 if a non-OWNER caller tries to flip them.
41
+ *
42
+ * Preferences land at
43
+ * `<state-dir>/local-inference/voice-update-prefs.json`; the pin set is
44
+ * stored as a sibling `voice-update-pins.json`.
45
+ */
46
+
47
+ import fsp from "node:fs/promises";
48
+ import type * as http from "node:http";
49
+ import path from "node:path";
50
+ import {
51
+ logger,
52
+ resolveStateDir,
53
+ sendJson,
54
+ sendJsonError,
55
+ } from "@elizaos/core";
56
+ import {
57
+ DEFAULT_NETWORK_POLICY_PREFERENCES,
58
+ type NetworkPolicyPreferences,
59
+ VOICE_MODEL_VERSIONS,
60
+ type VoiceModelId,
61
+ type VoiceModelVersion,
62
+ } from "@elizaos/shared";
63
+ import { evaluateRuntimePolicy } from "../services/network-policy";
64
+ import {
65
+ downloadVoiceModel,
66
+ VoiceModelDownloadError,
67
+ type VoiceModelStatus,
68
+ VoiceModelUpdater,
69
+ } from "../services/voice-model-updater";
70
+ import { readCompatJsonBody } from "./compat-helpers";
71
+
72
+ const ROUTE_PREFIX = "/api/local-inference/voice-models";
73
+
74
+ /** All known voice model ids (used to validate path params). */
75
+ const KNOWN_VOICE_MODEL_IDS: ReadonlySet<string> = new Set(
76
+ VOICE_MODEL_VERSIONS.map((v) => v.id),
77
+ );
78
+
79
+ export interface VoiceModelInstallationView {
80
+ readonly id: VoiceModelId;
81
+ readonly installedVersion: string | null;
82
+ readonly pinned: boolean;
83
+ readonly lastError: string | null;
84
+ }
85
+
86
+ interface PreferencesFile {
87
+ autoUpdateOnWifi: boolean;
88
+ autoUpdateOnCellular: boolean;
89
+ autoUpdateOnMetered: boolean;
90
+ quietHours: Array<{ start: string; end: string }>;
91
+ }
92
+
93
+ interface PinsFile {
94
+ pinned: VoiceModelId[];
95
+ }
96
+
97
+ /* ----------------------------------------------------------------- *
98
+ * Owner gate — the cellular + metered toggles are OWNER-only. *
99
+ * The runtime writes `ELIZA_ADMIN_ENTITY_ID` after voice-first-run *
100
+ * completes (see voice-first-run-routes.ts §POST /complete). *
101
+ * ----------------------------------------------------------------- */
102
+
103
+ /**
104
+ * `isOwnerRequest()` strategy:
105
+ *
106
+ * 1. If `ELIZA_ADMIN_ENTITY_ID` is unset, no OWNER exists yet — return
107
+ * `false` (gate stays locked). This is the safe default during first
108
+ * boot before voice first-run completes.
109
+ * 2. If the request carries `X-Eliza-Entity-Id` (set by the UI shell for
110
+ * authenticated sessions), compare against the admin id. Equality
111
+ * matches case-insensitively because entity ids are UUIDv4.
112
+ * 3. Otherwise return `false`. The UI surfaces the toggle as
113
+ * "Owner only" rather than throwing — the route still 403s on a
114
+ * POST that tries to flip a locked toggle.
115
+ */
116
+ function isOwnerRequest(req: http.IncomingMessage): boolean {
117
+ const adminId = process.env.ELIZA_ADMIN_ENTITY_ID?.trim();
118
+ if (!adminId) return false;
119
+ const header = req.headers["x-eliza-entity-id"];
120
+ const value = typeof header === "string" ? header.trim() : null;
121
+ if (!value) return false;
122
+ return value.toLowerCase() === adminId.toLowerCase();
123
+ }
124
+
125
+ /* ----------------------------------------------------------------- *
126
+ * State-dir helpers — pure I/O around the prefs + pins files. *
127
+ * ----------------------------------------------------------------- */
128
+
129
+ function voicePrefsDir(): string {
130
+ return path.join(resolveStateDir(process.env), "local-inference");
131
+ }
132
+ function voicePrefsPath(): string {
133
+ return path.join(voicePrefsDir(), "voice-update-prefs.json");
134
+ }
135
+ function voicePinsPath(): string {
136
+ return path.join(voicePrefsDir(), "voice-update-pins.json");
137
+ }
138
+ function bundleVoiceDir(): string {
139
+ return path.join(resolveStateDir(process.env), "models", "voice");
140
+ }
141
+ function voiceStagingDir(): string {
142
+ return path.join(resolveStateDir(process.env), "cache", "voice-staging");
143
+ }
144
+
145
+ async function readPreferences(): Promise<NetworkPolicyPreferences> {
146
+ try {
147
+ const raw = await fsp.readFile(voicePrefsPath(), "utf8");
148
+ const parsed = JSON.parse(raw) as Partial<PreferencesFile>;
149
+ return normalizePrefs(parsed);
150
+ } catch (err) {
151
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") {
152
+ return DEFAULT_NETWORK_POLICY_PREFERENCES;
153
+ }
154
+ logger.warn(
155
+ { err },
156
+ "[voice-models-routes] failed to read voice-update-prefs.json — using defaults",
157
+ );
158
+ return DEFAULT_NETWORK_POLICY_PREFERENCES;
159
+ }
160
+ }
161
+
162
+ async function writePreferences(
163
+ prefs: NetworkPolicyPreferences,
164
+ ): Promise<void> {
165
+ await fsp.mkdir(voicePrefsDir(), { recursive: true });
166
+ const out: PreferencesFile = {
167
+ autoUpdateOnWifi: prefs.autoUpdateOnWifi,
168
+ autoUpdateOnCellular: prefs.autoUpdateOnCellular,
169
+ autoUpdateOnMetered: prefs.autoUpdateOnMetered,
170
+ quietHours: prefs.quietHours.map((q) => ({ start: q.start, end: q.end })),
171
+ };
172
+ await fsp.writeFile(voicePrefsPath(), JSON.stringify(out, null, 2), "utf8");
173
+ }
174
+
175
+ function normalizePrefs(
176
+ candidate: Partial<PreferencesFile> | null | undefined,
177
+ ): NetworkPolicyPreferences {
178
+ const def = DEFAULT_NETWORK_POLICY_PREFERENCES;
179
+ if (!candidate || typeof candidate !== "object") return def;
180
+ const quietHours = Array.isArray(candidate.quietHours)
181
+ ? candidate.quietHours
182
+ .filter(
183
+ (q): q is { start: string; end: string } =>
184
+ !!q &&
185
+ typeof q === "object" &&
186
+ typeof (q as { start: unknown }).start === "string" &&
187
+ typeof (q as { end: unknown }).end === "string",
188
+ )
189
+ .map((q) => ({ start: q.start, end: q.end }))
190
+ : def.quietHours;
191
+ return {
192
+ autoUpdateOnWifi:
193
+ typeof candidate.autoUpdateOnWifi === "boolean"
194
+ ? candidate.autoUpdateOnWifi
195
+ : def.autoUpdateOnWifi,
196
+ autoUpdateOnCellular:
197
+ typeof candidate.autoUpdateOnCellular === "boolean"
198
+ ? candidate.autoUpdateOnCellular
199
+ : def.autoUpdateOnCellular,
200
+ autoUpdateOnMetered:
201
+ typeof candidate.autoUpdateOnMetered === "boolean"
202
+ ? candidate.autoUpdateOnMetered
203
+ : def.autoUpdateOnMetered,
204
+ quietHours,
205
+ };
206
+ }
207
+
208
+ async function readPins(): Promise<Set<VoiceModelId>> {
209
+ try {
210
+ const raw = await fsp.readFile(voicePinsPath(), "utf8");
211
+ const parsed = JSON.parse(raw) as Partial<PinsFile>;
212
+ if (!Array.isArray(parsed.pinned)) return new Set();
213
+ return new Set(
214
+ parsed.pinned.filter((id): id is VoiceModelId =>
215
+ KNOWN_VOICE_MODEL_IDS.has(id),
216
+ ),
217
+ );
218
+ } catch (err) {
219
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") return new Set();
220
+ logger.warn(
221
+ { err },
222
+ "[voice-models-routes] failed to read voice-update-pins.json — treating as empty",
223
+ );
224
+ return new Set();
225
+ }
226
+ }
227
+
228
+ async function writePins(pins: ReadonlySet<VoiceModelId>): Promise<void> {
229
+ await fsp.mkdir(voicePrefsDir(), { recursive: true });
230
+ const out: PinsFile = { pinned: Array.from(pins).sort() };
231
+ await fsp.writeFile(voicePinsPath(), JSON.stringify(out, null, 2), "utf8");
232
+ }
233
+
234
+ /* ----------------------------------------------------------------- *
235
+ * Installed-version resolution *
236
+ * Filenames written by `downloadVoiceModel` follow the pattern *
237
+ * `<id>-<version>-<original-asset-name>` *
238
+ * so we can recover `installedVersion` by directory listing. *
239
+ * ----------------------------------------------------------------- */
240
+
241
+ const INSTALLED_FILENAME_RE =
242
+ /^([a-z0-9-]+)-(\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?)-/;
243
+
244
+ export async function resolveInstalledVersions(
245
+ dir: string = bundleVoiceDir(),
246
+ ): Promise<Map<VoiceModelId, string>> {
247
+ const installed = new Map<VoiceModelId, string>();
248
+ let entries: string[];
249
+ try {
250
+ entries = await fsp.readdir(dir);
251
+ } catch (err) {
252
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") return installed;
253
+ throw err;
254
+ }
255
+ for (const entry of entries) {
256
+ const m = INSTALLED_FILENAME_RE.exec(entry);
257
+ if (!m) continue;
258
+ const id = m[1] as VoiceModelId;
259
+ const version = m[2] as string;
260
+ if (!KNOWN_VOICE_MODEL_IDS.has(id)) continue;
261
+ const prior = installed.get(id);
262
+ if (!prior || prior < version) installed.set(id, version);
263
+ }
264
+ return installed;
265
+ }
266
+
267
+ /* ----------------------------------------------------------------- *
268
+ * Updater dependency-injection hook (tests inject a fake updater). *
269
+ * ----------------------------------------------------------------- */
270
+
271
+ let updaterOverride: VoiceModelUpdater | null = null;
272
+
273
+ export function setVoiceModelsUpdater(updater: VoiceModelUpdater | null): void {
274
+ updaterOverride = updater;
275
+ }
276
+
277
+ function getUpdater(): VoiceModelUpdater {
278
+ if (updaterOverride) return updaterOverride;
279
+ return new VoiceModelUpdater({});
280
+ }
281
+
282
+ /* ----------------------------------------------------------------- *
283
+ * Download dependency-injection hook (tests inject a fake downloader *
284
+ * avoid touching the network). *
285
+ * ----------------------------------------------------------------- */
286
+
287
+ type DownloadFn = typeof downloadVoiceModel;
288
+ let downloadOverride: DownloadFn | null = null;
289
+
290
+ export function setVoiceModelDownloader(fn: DownloadFn | null): void {
291
+ downloadOverride = fn;
292
+ }
293
+
294
+ function getDownloader(): DownloadFn {
295
+ return downloadOverride ?? downloadVoiceModel;
296
+ }
297
+
298
+ /* ----------------------------------------------------------------- *
299
+ * Bundle-version override (tests pass a deterministic bundle version *
300
+ * so the updater's decision rule is reproducible). *
301
+ * ----------------------------------------------------------------- */
302
+
303
+ let bundleVersionOverride: string | null = null;
304
+ export function setVoiceModelsBundleVersionForTest(
305
+ bundleVersion: string | null,
306
+ ): void {
307
+ bundleVersionOverride = bundleVersion;
308
+ }
309
+
310
+ function resolveBundleVersion(): string {
311
+ if (bundleVersionOverride !== null) return bundleVersionOverride;
312
+ return process.env.ELIZA_BUNDLE_VERSION?.trim() ?? "0.0.0";
313
+ }
314
+
315
+ /* ----------------------------------------------------------------- *
316
+ * Route handler *
317
+ * ----------------------------------------------------------------- */
318
+
319
+ export async function handleVoiceModelsRoutes(
320
+ req: http.IncomingMessage,
321
+ res: http.ServerResponse,
322
+ ): Promise<boolean> {
323
+ const method = (req.method ?? "GET").toUpperCase();
324
+ const url = new URL(req.url ?? "/", "http://localhost");
325
+ const pathname = url.pathname;
326
+ if (!pathname.startsWith(ROUTE_PREFIX)) return false;
327
+
328
+ // GET /api/local-inference/voice-models
329
+ if (method === "GET" && pathname === ROUTE_PREFIX) {
330
+ const [installed, pins] = await Promise.all([
331
+ resolveInstalledVersions(),
332
+ readPins(),
333
+ ]);
334
+ const ids = new Set<VoiceModelId>([
335
+ ...VOICE_MODEL_VERSIONS.map((v) => v.id),
336
+ ...installed.keys(),
337
+ ]);
338
+ const installations: VoiceModelInstallationView[] = Array.from(ids)
339
+ .sort()
340
+ .map((id) => ({
341
+ id,
342
+ installedVersion: installed.get(id) ?? null,
343
+ pinned: pins.has(id),
344
+ lastError: null,
345
+ }));
346
+ sendJson(res, { installations });
347
+ return true;
348
+ }
349
+
350
+ // GET /api/local-inference/voice-models/check
351
+ if (method === "GET" && pathname === `${ROUTE_PREFIX}/check`) {
352
+ const [installed, pins] = await Promise.all([
353
+ resolveInstalledVersions(),
354
+ readPins(),
355
+ ]);
356
+ const updater = getUpdater();
357
+ let statuses: ReadonlyArray<VoiceModelStatus>;
358
+ try {
359
+ statuses = await updater.check(
360
+ { installed, bundleVersion: resolveBundleVersion() },
361
+ { pinned: pins },
362
+ { force: url.searchParams.get("force") === "1" },
363
+ );
364
+ } catch (err) {
365
+ logger.warn(
366
+ { err },
367
+ "[voice-models-routes] updater.check failed — surfacing as 502",
368
+ );
369
+ sendJsonError(
370
+ res,
371
+ err instanceof Error ? err.message : "updater check failed",
372
+ 502,
373
+ );
374
+ return true;
375
+ }
376
+ sendJson(res, {
377
+ lastCheckedAt: new Date().toISOString(),
378
+ statuses: statuses.map(serializeStatus),
379
+ });
380
+ return true;
381
+ }
382
+
383
+ // GET /api/local-inference/voice-models/preferences
384
+ if (method === "GET" && pathname === `${ROUTE_PREFIX}/preferences`) {
385
+ const preferences = await readPreferences();
386
+ sendJson(res, { preferences, isOwner: isOwnerRequest(req) });
387
+ return true;
388
+ }
389
+
390
+ // POST /api/local-inference/voice-models/preferences
391
+ if (method === "POST" && pathname === `${ROUTE_PREFIX}/preferences`) {
392
+ const body = await readCompatJsonBody(req, res);
393
+ if (!body) return true;
394
+ const owner = isOwnerRequest(req);
395
+ const current = await readPreferences();
396
+ // Build the candidate by overlaying provided fields onto current.
397
+ const candidate = normalizePrefs({
398
+ autoUpdateOnWifi:
399
+ typeof body.autoUpdateOnWifi === "boolean"
400
+ ? body.autoUpdateOnWifi
401
+ : current.autoUpdateOnWifi,
402
+ autoUpdateOnCellular:
403
+ typeof body.autoUpdateOnCellular === "boolean"
404
+ ? body.autoUpdateOnCellular
405
+ : current.autoUpdateOnCellular,
406
+ autoUpdateOnMetered:
407
+ typeof body.autoUpdateOnMetered === "boolean"
408
+ ? body.autoUpdateOnMetered
409
+ : current.autoUpdateOnMetered,
410
+ quietHours: Array.isArray(body.quietHours)
411
+ ? (body.quietHours as Array<{ start: string; end: string }>)
412
+ : current.quietHours.map((q) => ({ start: q.start, end: q.end })),
413
+ });
414
+ // OWNER gate: only the OWNER can flip cellular or metered to true.
415
+ if (
416
+ !owner &&
417
+ (candidate.autoUpdateOnCellular !== current.autoUpdateOnCellular ||
418
+ candidate.autoUpdateOnMetered !== current.autoUpdateOnMetered)
419
+ ) {
420
+ sendJsonError(
421
+ res,
422
+ "cellular + metered auto-update toggles are owner-only",
423
+ 403,
424
+ );
425
+ return true;
426
+ }
427
+ await writePreferences(candidate);
428
+ sendJson(res, { ok: true, preferences: candidate });
429
+ return true;
430
+ }
431
+
432
+ // POST /api/local-inference/voice-models/:id/update | :id/pin
433
+ const idActionMatch =
434
+ method === "POST"
435
+ ? /^\/api\/local-inference\/voice-models\/([^/]+)\/(update|pin)$/.exec(
436
+ pathname,
437
+ )
438
+ : null;
439
+ if (idActionMatch) {
440
+ const rawId = decodeURIComponent(idActionMatch[1] ?? "");
441
+ const action = idActionMatch[2] as "update" | "pin";
442
+ if (!KNOWN_VOICE_MODEL_IDS.has(rawId)) {
443
+ sendJsonError(res, `unknown voice model id: ${rawId}`, 404);
444
+ return true;
445
+ }
446
+ const id = rawId as VoiceModelId;
447
+ if (action === "pin") {
448
+ const body = await readCompatJsonBody(req, res);
449
+ if (!body) return true;
450
+ const pinned = body.pinned === true;
451
+ const pins = await readPins();
452
+ if (pinned) pins.add(id);
453
+ else pins.delete(id);
454
+ await writePins(pins);
455
+ sendJson(res, { ok: true, id, pinned });
456
+ return true;
457
+ }
458
+ // action === "update"
459
+ const updater = getUpdater();
460
+ const [installed, pins] = await Promise.all([
461
+ resolveInstalledVersions(),
462
+ readPins(),
463
+ ]);
464
+ let statuses: ReadonlyArray<VoiceModelStatus>;
465
+ try {
466
+ statuses = await updater.check(
467
+ { installed, bundleVersion: resolveBundleVersion() },
468
+ { pinned: pins },
469
+ { force: true },
470
+ );
471
+ } catch (err) {
472
+ sendJsonError(
473
+ res,
474
+ err instanceof Error ? err.message : "updater check failed",
475
+ 502,
476
+ );
477
+ return true;
478
+ }
479
+ const status = statuses.find((s) => s.id === id);
480
+ if (!status?.latestKnown) {
481
+ sendJsonError(res, `no candidate version for ${id}`, 404);
482
+ return true;
483
+ }
484
+ // R5 §4 — gate the download on the network policy decision.
485
+ const prefs = await readPreferences();
486
+ const totalBytes = status.latestKnown.ggufAssets.reduce(
487
+ (sum, a) => sum + a.sizeBytes,
488
+ 0,
489
+ );
490
+ const networkPolicy = await evaluateRuntimePolicy({
491
+ prefs,
492
+ estimatedBytes: totalBytes,
493
+ });
494
+ if (!networkPolicy.allow) {
495
+ sendJsonError(
496
+ res,
497
+ `network policy refused (reason=${networkPolicy.reason})`,
498
+ 409,
499
+ );
500
+ return true;
501
+ }
502
+ // First asset only; this endpoint handles one published voice archive per request.
503
+ if (status.latestKnown.ggufAssets.length === 0) {
504
+ sendJsonError(res, `no assets published for ${id}`, 409);
505
+ return true;
506
+ }
507
+ const controller = new AbortController();
508
+ try {
509
+ const result = await getDownloader()({
510
+ version: status.latestKnown,
511
+ bundleVoiceDir: bundleVoiceDir(),
512
+ stagingDir: voiceStagingDir(),
513
+ assetIndex: 0,
514
+ networkPolicy,
515
+ signal: controller.signal,
516
+ });
517
+ sendJson(res, {
518
+ ok: true,
519
+ id,
520
+ version: status.latestKnown.version,
521
+ finalPath: result.finalPath,
522
+ sha256: result.sha256,
523
+ sizeBytes: result.sizeBytes,
524
+ });
525
+ } catch (err) {
526
+ if (err instanceof VoiceModelDownloadError) {
527
+ sendJsonError(res, err.message, 502);
528
+ return true;
529
+ }
530
+ throw err;
531
+ }
532
+ return true;
533
+ }
534
+
535
+ return false;
536
+ }
537
+
538
+ function serializeStatus(s: VoiceModelStatus): {
539
+ id: VoiceModelId;
540
+ installedVersion: string | null;
541
+ pinned: boolean;
542
+ latestKnown: VoiceModelVersion | null;
543
+ allow: boolean;
544
+ reason: VoiceModelStatus["decision"]["reason"];
545
+ } {
546
+ return {
547
+ id: s.id,
548
+ installedVersion: s.installedVersion,
549
+ pinned: s.pinned,
550
+ latestKnown: s.latestKnown,
551
+ allow: s.decision.allow,
552
+ reason: s.decision.reason,
553
+ };
554
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Plugin-route registration for the voice-profile HTTP surface (issue #8234).
3
+ *
4
+ * `handleVoiceSpeakerProfileRoutes` (bind/unbind a recognized voice to an
5
+ * elizaOS entity) and `handleVoiceProfilesManagementRoutes` (the server half
6
+ * of the `VoiceProfileSection` management UI) are prefix dispatchers, but the
7
+ * only server mount of `handleLocalInferenceRoutes` is gated behind
8
+ * `/api/local-inference*` path prefixes — so neither the `/v1/voice/
9
+ * speaker-profiles` nor the `/api/voice/profiles` namespace was reachable
10
+ * over HTTP. Registering them as `rawPath` routes on the plugin object puts
11
+ * them on `runtime.routes`, which both the upstream agent server and the
12
+ * app-core dashboard server dispatch.
13
+ *
14
+ * Every route is private: the host dispatcher answers 401 for
15
+ * unauthenticated callers before the handler runs.
16
+ */
17
+ import { type Route } from "@elizaos/core";
18
+ export declare const voiceProfilePluginRoutes: Route[];
19
+ //# sourceMappingURL=voice-profile-plugin-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-profile-plugin-routes.d.ts","sourceRoot":"","sources":["voice-profile-plugin-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,KAAK,KAAK,EAAiB,MAAM,eAAe,CAAC;AAqC1D,eAAO,MAAM,wBAAwB,EAAE,KAAK,EAkF3C,CAAC"}