@happyvertical/smrt-svelte 0.30.0

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 (357) hide show
  1. package/AGENTS.md +317 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +185 -0
  5. package/dist/Provider.svelte +204 -0
  6. package/dist/Provider.svelte.d.ts +73 -0
  7. package/dist/Provider.svelte.d.ts.map +1 -0
  8. package/dist/__tests__/app-state.test.js +156 -0
  9. package/dist/__tests__/warm-clients.test.js +186 -0
  10. package/dist/browser-ai/adapters/llm/factory.d.ts +38 -0
  11. package/dist/browser-ai/adapters/llm/factory.d.ts.map +1 -0
  12. package/dist/browser-ai/adapters/llm/factory.js +91 -0
  13. package/dist/browser-ai/adapters/llm/index.d.ts +7 -0
  14. package/dist/browser-ai/adapters/llm/index.d.ts.map +1 -0
  15. package/dist/browser-ai/adapters/llm/index.js +6 -0
  16. package/dist/browser-ai/adapters/llm/types.d.ts +182 -0
  17. package/dist/browser-ai/adapters/llm/types.d.ts.map +1 -0
  18. package/dist/browser-ai/adapters/llm/types.js +43 -0
  19. package/dist/browser-ai/adapters/llm/webllm.d.ts +33 -0
  20. package/dist/browser-ai/adapters/llm/webllm.d.ts.map +1 -0
  21. package/dist/browser-ai/adapters/llm/webllm.js +225 -0
  22. package/dist/browser-ai/adapters/stt/browser-speech.d.ts +31 -0
  23. package/dist/browser-ai/adapters/stt/browser-speech.d.ts.map +1 -0
  24. package/dist/browser-ai/adapters/stt/browser-speech.js +217 -0
  25. package/dist/browser-ai/adapters/stt/factory.d.ts +49 -0
  26. package/dist/browser-ai/adapters/stt/factory.d.ts.map +1 -0
  27. package/dist/browser-ai/adapters/stt/factory.js +110 -0
  28. package/dist/browser-ai/adapters/stt/index.d.ts +9 -0
  29. package/dist/browser-ai/adapters/stt/index.d.ts.map +1 -0
  30. package/dist/browser-ai/adapters/stt/index.js +8 -0
  31. package/dist/browser-ai/adapters/stt/types.d.ts +154 -0
  32. package/dist/browser-ai/adapters/stt/types.d.ts.map +1 -0
  33. package/dist/browser-ai/adapters/stt/types.js +4 -0
  34. package/dist/browser-ai/adapters/stt/whisper-cpp.d.ts +46 -0
  35. package/dist/browser-ai/adapters/stt/whisper-cpp.d.ts.map +1 -0
  36. package/dist/browser-ai/adapters/stt/whisper-cpp.js +348 -0
  37. package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts +51 -0
  38. package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts.map +1 -0
  39. package/dist/browser-ai/adapters/stt/whisper-wasm.js +380 -0
  40. package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts +42 -0
  41. package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts.map +1 -0
  42. package/dist/browser-ai/adapters/tts/browser-synthesis.js +235 -0
  43. package/dist/browser-ai/adapters/tts/factory.d.ts +53 -0
  44. package/dist/browser-ai/adapters/tts/factory.d.ts.map +1 -0
  45. package/dist/browser-ai/adapters/tts/factory.js +92 -0
  46. package/dist/browser-ai/adapters/tts/index.d.ts +7 -0
  47. package/dist/browser-ai/adapters/tts/index.d.ts.map +1 -0
  48. package/dist/browser-ai/adapters/tts/index.js +6 -0
  49. package/dist/browser-ai/adapters/tts/types.d.ts +140 -0
  50. package/dist/browser-ai/adapters/tts/types.d.ts.map +1 -0
  51. package/dist/browser-ai/adapters/tts/types.js +4 -0
  52. package/dist/browser-ai/capabilities/detector.d.ts +38 -0
  53. package/dist/browser-ai/capabilities/detector.d.ts.map +1 -0
  54. package/dist/browser-ai/capabilities/detector.js +211 -0
  55. package/dist/browser-ai/core/errors.d.ts +62 -0
  56. package/dist/browser-ai/core/errors.d.ts.map +1 -0
  57. package/dist/browser-ai/core/errors.js +92 -0
  58. package/dist/browser-ai/core/index.d.ts +6 -0
  59. package/dist/browser-ai/core/index.d.ts.map +1 -0
  60. package/dist/browser-ai/core/index.js +5 -0
  61. package/dist/browser-ai/core/types.d.ts +115 -0
  62. package/dist/browser-ai/core/types.d.ts.map +1 -0
  63. package/dist/browser-ai/core/types.js +34 -0
  64. package/dist/browser-ai/index.d.ts +12 -0
  65. package/dist/browser-ai/index.d.ts.map +1 -0
  66. package/dist/browser-ai/index.js +16 -0
  67. package/dist/browser-ai/svelte/components/AILoadingOverlay.svelte +77 -0
  68. package/dist/browser-ai/svelte/components/AILoadingOverlay.svelte.d.ts +16 -0
  69. package/dist/browser-ai/svelte/components/AILoadingOverlay.svelte.d.ts.map +1 -0
  70. package/dist/browser-ai/svelte/components/CapabilityGate.svelte +57 -0
  71. package/dist/browser-ai/svelte/components/CapabilityGate.svelte.d.ts +15 -0
  72. package/dist/browser-ai/svelte/components/CapabilityGate.svelte.d.ts.map +1 -0
  73. package/dist/browser-ai/svelte/components/DownloadProgress.svelte +141 -0
  74. package/dist/browser-ai/svelte/components/DownloadProgress.svelte.d.ts +15 -0
  75. package/dist/browser-ai/svelte/components/DownloadProgress.svelte.d.ts.map +1 -0
  76. package/dist/browser-ai/svelte/components/STTTest.svelte +379 -0
  77. package/dist/browser-ai/svelte/components/STTTest.svelte.d.ts +9 -0
  78. package/dist/browser-ai/svelte/components/STTTest.svelte.d.ts.map +1 -0
  79. package/dist/browser-ai/svelte/components/VoiceInput.svelte +200 -0
  80. package/dist/browser-ai/svelte/components/VoiceInput.svelte.d.ts +16 -0
  81. package/dist/browser-ai/svelte/components/VoiceInput.svelte.d.ts.map +1 -0
  82. package/dist/browser-ai/svelte/index.d.ts +15 -0
  83. package/dist/browser-ai/svelte/index.d.ts.map +1 -0
  84. package/dist/browser-ai/svelte/index.js +28 -0
  85. package/dist/browser-ai/ui.d.ts +16 -0
  86. package/dist/browser-ai/ui.d.ts.map +1 -0
  87. package/dist/browser-ai/ui.js +67 -0
  88. package/dist/components/admin/AgentAdminPanel.svelte +111 -0
  89. package/dist/components/admin/AgentAdminPanel.svelte.d.ts +25 -0
  90. package/dist/components/admin/AgentAdminPanel.svelte.d.ts.map +1 -0
  91. package/dist/components/admin/AgentAdminTabs.svelte +280 -0
  92. package/dist/components/admin/AgentAdminTabs.svelte.d.ts +23 -0
  93. package/dist/components/admin/AgentAdminTabs.svelte.d.ts.map +1 -0
  94. package/dist/components/admin/AgentSettingsShell.svelte +257 -0
  95. package/dist/components/admin/AgentSettingsShell.svelte.d.ts +33 -0
  96. package/dist/components/admin/AgentSettingsShell.svelte.d.ts.map +1 -0
  97. package/dist/components/admin/index.d.ts +5 -0
  98. package/dist/components/admin/index.d.ts.map +1 -0
  99. package/dist/components/admin/index.js +6 -0
  100. package/dist/components/forms/AddressInput.svelte +500 -0
  101. package/dist/components/forms/AddressInput.svelte.d.ts +36 -0
  102. package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -0
  103. package/dist/components/forms/CheckboxInput.svelte +208 -0
  104. package/dist/components/forms/CheckboxInput.svelte.d.ts +20 -0
  105. package/dist/components/forms/CheckboxInput.svelte.d.ts.map +1 -0
  106. package/dist/components/forms/DateRangeInput.svelte +628 -0
  107. package/dist/components/forms/DateRangeInput.svelte.d.ts +33 -0
  108. package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -0
  109. package/dist/components/forms/DateTimeInput.svelte +521 -0
  110. package/dist/components/forms/DateTimeInput.svelte.d.ts +24 -0
  111. package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -0
  112. package/dist/components/forms/FileUpload.svelte +358 -0
  113. package/dist/components/forms/FileUpload.svelte.d.ts +22 -0
  114. package/dist/components/forms/FileUpload.svelte.d.ts.map +1 -0
  115. package/dist/components/forms/Form.svelte +771 -0
  116. package/dist/components/forms/Form.svelte.d.ts +26 -0
  117. package/dist/components/forms/Form.svelte.d.ts.map +1 -0
  118. package/dist/components/forms/FormGroup.svelte +86 -0
  119. package/dist/components/forms/FormGroup.svelte.d.ts +13 -0
  120. package/dist/components/forms/FormGroup.svelte.d.ts.map +1 -0
  121. package/dist/components/forms/FormMicButton.svelte +179 -0
  122. package/dist/components/forms/FormMicButton.svelte.d.ts +10 -0
  123. package/dist/components/forms/FormMicButton.svelte.d.ts.map +1 -0
  124. package/dist/components/forms/Input.svelte +83 -0
  125. package/dist/components/forms/Input.svelte.d.ts +9 -0
  126. package/dist/components/forms/Input.svelte.d.ts.map +1 -0
  127. package/dist/components/forms/MeasurementInput.svelte +505 -0
  128. package/dist/components/forms/MeasurementInput.svelte.d.ts +35 -0
  129. package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -0
  130. package/dist/components/forms/MoneyInput.svelte +412 -0
  131. package/dist/components/forms/MoneyInput.svelte.d.ts +30 -0
  132. package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -0
  133. package/dist/components/forms/NumberInput.svelte +310 -0
  134. package/dist/components/forms/NumberInput.svelte.d.ts +28 -0
  135. package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -0
  136. package/dist/components/forms/PhoneInput.svelte +530 -0
  137. package/dist/components/forms/PhoneInput.svelte.d.ts +22 -0
  138. package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -0
  139. package/dist/components/forms/SearchInput.svelte +358 -0
  140. package/dist/components/forms/SearchInput.svelte.d.ts +33 -0
  141. package/dist/components/forms/SearchInput.svelte.d.ts.map +1 -0
  142. package/dist/components/forms/Select.svelte +83 -0
  143. package/dist/components/forms/Select.svelte.d.ts +11 -0
  144. package/dist/components/forms/Select.svelte.d.ts.map +1 -0
  145. package/dist/components/forms/SelectInput.svelte +254 -0
  146. package/dist/components/forms/SelectInput.svelte.d.ts +25 -0
  147. package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -0
  148. package/dist/components/forms/TextInput.svelte +415 -0
  149. package/dist/components/forms/TextInput.svelte.d.ts +26 -0
  150. package/dist/components/forms/TextInput.svelte.d.ts.map +1 -0
  151. package/dist/components/forms/Textarea.svelte +85 -0
  152. package/dist/components/forms/Textarea.svelte.d.ts +10 -0
  153. package/dist/components/forms/Textarea.svelte.d.ts.map +1 -0
  154. package/dist/components/forms/TextareaInput.svelte +386 -0
  155. package/dist/components/forms/TextareaInput.svelte.d.ts +26 -0
  156. package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -0
  157. package/dist/components/forms/Toggle.svelte +217 -0
  158. package/dist/components/forms/Toggle.svelte.d.ts +37 -0
  159. package/dist/components/forms/Toggle.svelte.d.ts.map +1 -0
  160. package/dist/components/forms/__tests__/AddressInput.behavior.test.js +122 -0
  161. package/dist/components/forms/__tests__/CheckboxInput.test.js +92 -0
  162. package/dist/components/forms/__tests__/DateRangeInput.behavior.test.js +135 -0
  163. package/dist/components/forms/__tests__/DateTimeInput.behavior.test.js +103 -0
  164. package/dist/components/forms/__tests__/FileUpload.test.js +90 -0
  165. package/dist/components/forms/__tests__/Form.behavior.test.js +137 -0
  166. package/dist/components/forms/__tests__/Form.test.js +58 -0
  167. package/dist/components/forms/__tests__/FormGroup.test.js +48 -0
  168. package/dist/components/forms/__tests__/FormMicButton.test.js +86 -0
  169. package/dist/components/forms/__tests__/Input.test.js +49 -0
  170. package/dist/components/forms/__tests__/MeasurementInput.behavior.test.js +129 -0
  171. package/dist/components/forms/__tests__/MoneyInput.behavior.test.js +124 -0
  172. package/dist/components/forms/__tests__/NumberInput.behavior.test.js +141 -0
  173. package/dist/components/forms/__tests__/PhoneInput.behavior.test.js +96 -0
  174. package/dist/components/forms/__tests__/SearchInput.test.js +79 -0
  175. package/dist/components/forms/__tests__/Select.test.js +37 -0
  176. package/dist/components/forms/__tests__/SelectInput.behavior.test.js +132 -0
  177. package/dist/components/forms/__tests__/TextInput.behavior.test.js +131 -0
  178. package/dist/components/forms/__tests__/Textarea.test.js +39 -0
  179. package/dist/components/forms/__tests__/TextareaInput.behavior.test.js +96 -0
  180. package/dist/components/forms/__tests__/Toggle.test.js +87 -0
  181. package/dist/components/forms/__tests__/composite-inputs-a11y.test.js +69 -0
  182. package/dist/components/forms/__tests__/form-group-input.fixture.svelte +16 -0
  183. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts +9 -0
  184. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts.map +1 -0
  185. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +33 -0
  186. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +12 -0
  187. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +1 -0
  188. package/dist/components/forms/__tests__/rich-inputs-a11y.test.js +87 -0
  189. package/dist/components/forms/index.d.ts +25 -0
  190. package/dist/components/forms/index.d.ts.map +1 -0
  191. package/dist/components/forms/index.js +25 -0
  192. package/dist/components/forms/types.d.ts +33 -0
  193. package/dist/components/forms/types.d.ts.map +1 -0
  194. package/dist/components/forms/types.js +4 -0
  195. package/dist/components/module/ModulePanel.svelte +134 -0
  196. package/dist/components/module/ModulePanel.svelte.d.ts +22 -0
  197. package/dist/components/module/ModulePanel.svelte.d.ts.map +1 -0
  198. package/dist/components/module/index.d.ts +5 -0
  199. package/dist/components/module/index.d.ts.map +1 -0
  200. package/dist/components/module/index.js +4 -0
  201. package/dist/components/workspace/Breadcrumbs.svelte +141 -0
  202. package/dist/components/workspace/Breadcrumbs.svelte.d.ts +21 -0
  203. package/dist/components/workspace/Breadcrumbs.svelte.d.ts.map +1 -0
  204. package/dist/components/workspace/NavTree.svelte +354 -0
  205. package/dist/components/workspace/NavTree.svelte.d.ts +45 -0
  206. package/dist/components/workspace/NavTree.svelte.d.ts.map +1 -0
  207. package/dist/components/workspace/README.md +34 -0
  208. package/dist/components/workspace/RoleShell.svelte +309 -0
  209. package/dist/components/workspace/RoleShell.svelte.d.ts +91 -0
  210. package/dist/components/workspace/RoleShell.svelte.d.ts.map +1 -0
  211. package/dist/components/workspace/WorkspaceShell.svelte +951 -0
  212. package/dist/components/workspace/WorkspaceShell.svelte.d.ts +112 -0
  213. package/dist/components/workspace/WorkspaceShell.svelte.d.ts.map +1 -0
  214. package/dist/components/workspace/__tests__/RoleShell.test.js +772 -0
  215. package/dist/components/workspace/__tests__/WorkspaceShell.test.js +630 -0
  216. package/dist/components/workspace/__tests__/breadcrumbs-helpers.test.js +141 -0
  217. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte +45 -0
  218. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts +21 -0
  219. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts.map +1 -0
  220. package/dist/components/workspace/__tests__/define-tools-dock.test.js +1010 -0
  221. package/dist/components/workspace/__tests__/harness.svelte +25 -0
  222. package/dist/components/workspace/__tests__/harness.svelte.d.ts +14 -0
  223. package/dist/components/workspace/__tests__/harness.svelte.d.ts.map +1 -0
  224. package/dist/components/workspace/__tests__/index.test.js +37 -0
  225. package/dist/components/workspace/__tests__/manifest-nav-helpers.test.js +24 -0
  226. package/dist/components/workspace/__tests__/manifest-nav.test.js +599 -0
  227. package/dist/components/workspace/__tests__/nav-helpers.test.js +95 -0
  228. package/dist/components/workspace/__tests__/render-harness.svelte +66 -0
  229. package/dist/components/workspace/__tests__/render-harness.svelte.d.ts +32 -0
  230. package/dist/components/workspace/__tests__/render-harness.svelte.d.ts.map +1 -0
  231. package/dist/components/workspace/__tests__/render-tools-dock.test.js +243 -0
  232. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte +58 -0
  233. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts +16 -0
  234. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts.map +1 -0
  235. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte +41 -0
  236. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts +13 -0
  237. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts.map +1 -0
  238. package/dist/components/workspace/__tests__/test-icon.svelte +17 -0
  239. package/dist/components/workspace/__tests__/test-icon.svelte.d.ts +19 -0
  240. package/dist/components/workspace/__tests__/test-icon.svelte.d.ts.map +1 -0
  241. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte +38 -0
  242. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts +22 -0
  243. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts.map +1 -0
  244. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +65 -0
  245. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +1 -0
  246. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +115 -0
  247. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts +15 -0
  248. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts.map +1 -0
  249. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.js +7 -0
  250. package/dist/components/workspace/__tests__/typed-tool-fixture.test.js +115 -0
  251. package/dist/components/workspace/__tests__/use-harness-orphan.svelte +9 -0
  252. package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts +19 -0
  253. package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts.map +1 -0
  254. package/dist/components/workspace/__tests__/use-harness.svelte +23 -0
  255. package/dist/components/workspace/__tests__/use-harness.svelte.d.ts +8 -0
  256. package/dist/components/workspace/__tests__/use-harness.svelte.d.ts.map +1 -0
  257. package/dist/components/workspace/__tests__/use-tools-dock.test.js +33 -0
  258. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte +43 -0
  259. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts +11 -0
  260. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts.map +1 -0
  261. package/dist/components/workspace/breadcrumbs-helpers.d.ts +44 -0
  262. package/dist/components/workspace/breadcrumbs-helpers.d.ts.map +1 -0
  263. package/dist/components/workspace/breadcrumbs-helpers.js +88 -0
  264. package/dist/components/workspace/index.d.ts +16 -0
  265. package/dist/components/workspace/index.d.ts.map +1 -0
  266. package/dist/components/workspace/index.js +14 -0
  267. package/dist/components/workspace/manifest-nav.d.ts +200 -0
  268. package/dist/components/workspace/manifest-nav.d.ts.map +1 -0
  269. package/dist/components/workspace/manifest-nav.js +408 -0
  270. package/dist/components/workspace/nav-helpers.d.ts +36 -0
  271. package/dist/components/workspace/nav-helpers.d.ts.map +1 -0
  272. package/dist/components/workspace/nav-helpers.js +60 -0
  273. package/dist/components/workspace/server/__tests__/compose-availability.test.js +383 -0
  274. package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts +78 -0
  275. package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts.map +1 -0
  276. package/dist/components/workspace/server/__tests__/typed-context-fixture.js +104 -0
  277. package/dist/components/workspace/server/compose-availability.d.ts +73 -0
  278. package/dist/components/workspace/server/compose-availability.d.ts.map +1 -0
  279. package/dist/components/workspace/server/compose-availability.js +114 -0
  280. package/dist/components/workspace/server/index.d.ts +13 -0
  281. package/dist/components/workspace/server/index.d.ts.map +1 -0
  282. package/dist/components/workspace/server/index.js +11 -0
  283. package/dist/components/workspace/server/types.d.ts +108 -0
  284. package/dist/components/workspace/server/types.d.ts.map +1 -0
  285. package/dist/components/workspace/server/types.js +11 -0
  286. package/dist/components/workspace/tools-dock/ToolsDock.svelte +565 -0
  287. package/dist/components/workspace/tools-dock/ToolsDock.svelte.d.ts +14 -0
  288. package/dist/components/workspace/tools-dock/ToolsDock.svelte.d.ts.map +1 -0
  289. package/dist/components/workspace/tools-dock/define-tools-dock.svelte.d.ts +143 -0
  290. package/dist/components/workspace/tools-dock/define-tools-dock.svelte.d.ts.map +1 -0
  291. package/dist/components/workspace/tools-dock/define-tools-dock.svelte.js +487 -0
  292. package/dist/components/workspace/tools-dock/use-tools-dock.d.ts +41 -0
  293. package/dist/components/workspace/tools-dock/use-tools-dock.d.ts.map +1 -0
  294. package/dist/components/workspace/tools-dock/use-tools-dock.js +50 -0
  295. package/dist/components/workspace/types.d.ts +372 -0
  296. package/dist/components/workspace/types.d.ts.map +1 -0
  297. package/dist/components/workspace/types.js +6 -0
  298. package/dist/hooks/index.d.ts +11 -0
  299. package/dist/hooks/index.d.ts.map +1 -0
  300. package/dist/hooks/index.js +10 -0
  301. package/dist/hooks/useAppState.svelte.d.ts +46 -0
  302. package/dist/hooks/useAppState.svelte.d.ts.map +1 -0
  303. package/dist/hooks/useAppState.svelte.js +59 -0
  304. package/dist/hooks/useAuth.svelte.d.ts +41 -0
  305. package/dist/hooks/useAuth.svelte.d.ts.map +1 -0
  306. package/dist/hooks/useAuth.svelte.js +43 -0
  307. package/dist/hooks/useLLM.svelte.d.ts +69 -0
  308. package/dist/hooks/useLLM.svelte.d.ts.map +1 -0
  309. package/dist/hooks/useLLM.svelte.js +85 -0
  310. package/dist/hooks/useSTT.svelte.d.ts +68 -0
  311. package/dist/hooks/useSTT.svelte.d.ts.map +1 -0
  312. package/dist/hooks/useSTT.svelte.js +97 -0
  313. package/dist/hooks/useSocket.svelte.d.ts +45 -0
  314. package/dist/hooks/useSocket.svelte.d.ts.map +1 -0
  315. package/dist/hooks/useSocket.svelte.js +54 -0
  316. package/dist/hooks/useTTS.svelte.d.ts +65 -0
  317. package/dist/hooks/useTTS.svelte.d.ts.map +1 -0
  318. package/dist/hooks/useTTS.svelte.js +93 -0
  319. package/dist/hooks/useTheme.d.ts +13 -0
  320. package/dist/hooks/useTheme.d.ts.map +1 -0
  321. package/dist/hooks/useTheme.js +16 -0
  322. package/dist/i18n/__tests__/server.spec.js +50 -0
  323. package/dist/i18n/server.d.ts +47 -0
  324. package/dist/i18n/server.d.ts.map +1 -0
  325. package/dist/i18n/server.js +58 -0
  326. package/dist/i18n/strings.forms.d.ts +33 -0
  327. package/dist/i18n/strings.forms.d.ts.map +1 -0
  328. package/dist/i18n/strings.forms.js +54 -0
  329. package/dist/i18n/strings.workspace.d.ts +34 -0
  330. package/dist/i18n/strings.workspace.d.ts.map +1 -0
  331. package/dist/i18n/strings.workspace.js +40 -0
  332. package/dist/index.d.ts +18 -0
  333. package/dist/index.d.ts.map +1 -0
  334. package/dist/index.js +23 -0
  335. package/dist/state/__tests__/warm-clients.test.js +40 -0
  336. package/dist/state/app-state.d.ts +308 -0
  337. package/dist/state/app-state.d.ts.map +1 -0
  338. package/dist/state/app-state.js +64 -0
  339. package/dist/state/app-state.svelte.d.ts +196 -0
  340. package/dist/state/app-state.svelte.d.ts.map +1 -0
  341. package/dist/state/app-state.svelte.js +774 -0
  342. package/dist/state/context.d.ts +23 -0
  343. package/dist/state/context.d.ts.map +1 -0
  344. package/dist/state/context.js +32 -0
  345. package/dist/state/form-context.d.ts +59 -0
  346. package/dist/state/form-context.d.ts.map +1 -0
  347. package/dist/state/form-context.js +31 -0
  348. package/dist/state/form-group-context.d.ts +13 -0
  349. package/dist/state/form-group-context.d.ts.map +1 -0
  350. package/dist/state/form-group-context.js +28 -0
  351. package/dist/state/index.d.ts +9 -0
  352. package/dist/state/index.d.ts.map +1 -0
  353. package/dist/state/index.js +8 -0
  354. package/dist/state/warm-clients.d.ts +136 -0
  355. package/dist/state/warm-clients.d.ts.map +1 -0
  356. package/dist/state/warm-clients.js +231 -0
  357. package/package.json +137 -0
@@ -0,0 +1,204 @@
1
+ <script lang="ts">
2
+ import {
3
+ createI18nContext,
4
+ type I18nSnapshot,
5
+ setI18nContext,
6
+ } from '@happyvertical/smrt-ui/i18n';
7
+ import type { Snippet } from 'svelte';
8
+ import { onDestroy, untrack } from 'svelte';
9
+ import AILoadingOverlay from './browser-ai/svelte/components/AILoadingOverlay.svelte';
10
+ import type {
11
+ AIConfig,
12
+ AILoadingState,
13
+ AppMode,
14
+ SocketConfig,
15
+ User,
16
+ } from './state/app-state.js';
17
+ import { createAppState } from './state/app-state.svelte.js';
18
+ import { setAppStateContext } from './state/context.js';
19
+
20
+ interface Props {
21
+ /**
22
+ * Initial mode: 'default' | 'smrt'
23
+ * If not provided, mode is auto-detected based on capabilities
24
+ */
25
+ mode?: AppMode;
26
+ /**
27
+ * Whether to auto-enable smrt mode when capabilities are available
28
+ * @default true
29
+ */
30
+ autoEnableSmrt?: boolean;
31
+ /**
32
+ * User object from smrt-users (from your load function)
33
+ * Pass null when not authenticated
34
+ */
35
+ user?: User | null;
36
+ /**
37
+ * Resolved permissions (from PermissionResolver in your load function)
38
+ */
39
+ permissions?: string[];
40
+ /**
41
+ * WebSocket configuration
42
+ * If provided, connects on mount and disconnects on unmount
43
+ */
44
+ socket?: SocketConfig;
45
+ /**
46
+ * AI configuration for preloading and warm clients
47
+ *
48
+ * @example
49
+ * ```svelte
50
+ * <Provider
51
+ * ai={{
52
+ * preload: 'idle',
53
+ * stt: { type: 'whisper-cpp' },
54
+ * showLoadingOverlay: true
55
+ * }}
56
+ * >
57
+ * ...
58
+ * </Provider>
59
+ * ```
60
+ */
61
+ ai?: AIConfig;
62
+ /**
63
+ * Callback when capabilities are detected
64
+ */
65
+ onReady?: () => void;
66
+ /**
67
+ * Callback when mode changes
68
+ */
69
+ onModeChange?: (mode: AppMode) => void;
70
+ /**
71
+ * Callback when AI loading state changes
72
+ */
73
+ onAILoadingChange?: (state: AILoadingState) => void;
74
+ /**
75
+ * i18n snapshot from your load function (`buildI18nSnapshot` on
76
+ * `@happyvertical/smrt-svelte/i18n/server`). Provides the active locale +
77
+ * resolved message templates to `useI18n()` / `<Trans>`. Omit for
78
+ * English-default-only rendering.
79
+ */
80
+ i18n?: I18nSnapshot;
81
+ /**
82
+ * Children to render
83
+ */
84
+ children: Snippet;
85
+ }
86
+
87
+ const {
88
+ mode,
89
+ autoEnableSmrt = true,
90
+ user = null,
91
+ permissions = [],
92
+ socket,
93
+ ai,
94
+ onReady,
95
+ onModeChange,
96
+ onAILoadingChange,
97
+ i18n,
98
+ children,
99
+ }: Props = $props();
100
+
101
+ // Determine if we should show the loading overlay
102
+ const showLoadingOverlay = $derived(ai?.showLoadingOverlay ?? true);
103
+
104
+ // Create app state
105
+ const appState = createAppState({
106
+ onCapabilitiesDetected: () => {
107
+ onReady?.();
108
+ },
109
+ onModeChange: (newMode) => {
110
+ onModeChange?.(newMode);
111
+ },
112
+ onAILoadingChange: (state) => {
113
+ onAILoadingChange?.(state);
114
+ },
115
+ });
116
+
117
+ $effect(() => {
118
+ const currentPreferences = untrack(() => appState.state.session.preferences);
119
+ if (currentPreferences.autoEnableSmrt === autoEnableSmrt) {
120
+ return;
121
+ }
122
+
123
+ appState.updateSession({
124
+ preferences: {
125
+ ...currentPreferences,
126
+ autoEnableSmrt,
127
+ },
128
+ });
129
+ });
130
+
131
+ $effect(() => {
132
+ if (mode) {
133
+ appState.setMode(mode, 'explicit');
134
+ }
135
+ });
136
+
137
+ // Provide context
138
+ setAppStateContext(appState);
139
+
140
+ // i18n: seed the store from the initial snapshot synchronously (untrack — this
141
+ // MUST run during SSR, where $effect does not, so translated strings render on
142
+ // the server), then keep it in sync when the `i18n` prop changes (locale
143
+ // switch). Reads stay synchronous on the client; all async resolution happened
144
+ // server-side in buildI18nSnapshot.
145
+ const i18nStore = untrack(() => createI18nContext(i18n));
146
+ setI18nContext(i18nStore);
147
+ $effect(() => {
148
+ if (i18n) {
149
+ i18nStore.snapshot = i18n;
150
+ }
151
+ });
152
+
153
+ // Initialize on mount (untrack to prevent infinite loop)
154
+ // Skip during SSR - browser-ai APIs require browser environment
155
+ $effect(() => {
156
+ if (typeof window === 'undefined') return;
157
+ untrack(() => {
158
+ appState.initialize();
159
+ });
160
+ });
161
+
162
+ // Sync user and permissions when they change
163
+ $effect(() => {
164
+ appState.setUser(user, permissions);
165
+ });
166
+
167
+ // Manage socket lifecycle (browser-only)
168
+ $effect(() => {
169
+ if (typeof window === 'undefined') return;
170
+ if (socket) {
171
+ // connectSocket already handles disconnecting any existing socket
172
+ appState.connectSocket(socket);
173
+
174
+ // Cleanup when socket prop changes or component unmounts
175
+ return () => {
176
+ appState.disconnectSocket();
177
+ };
178
+ }
179
+ });
180
+
181
+ // Update AI config when it changes (for dynamic config updates, browser-only)
182
+ $effect(() => {
183
+ if (typeof window === 'undefined') return;
184
+ if (ai) {
185
+ untrack(() => {
186
+ appState.setAIConfig(ai);
187
+ });
188
+ }
189
+ });
190
+
191
+ // Cleanup on destroy
192
+ onDestroy(() => {
193
+ appState.disconnectSocket();
194
+ });
195
+ </script>
196
+
197
+ {#if ai && showLoadingOverlay}
198
+ <AILoadingOverlay
199
+ message={ai.loadingMessage}
200
+ dismissible={true}
201
+ />
202
+ {/if}
203
+
204
+ {@render children()}
@@ -0,0 +1,73 @@
1
+ import { type I18nSnapshot } from '@happyvertical/smrt-ui/i18n';
2
+ import type { Snippet } from 'svelte';
3
+ import type { AIConfig, AILoadingState, AppMode, SocketConfig, User } from './state/app-state.js';
4
+ interface Props {
5
+ /**
6
+ * Initial mode: 'default' | 'smrt'
7
+ * If not provided, mode is auto-detected based on capabilities
8
+ */
9
+ mode?: AppMode;
10
+ /**
11
+ * Whether to auto-enable smrt mode when capabilities are available
12
+ * @default true
13
+ */
14
+ autoEnableSmrt?: boolean;
15
+ /**
16
+ * User object from smrt-users (from your load function)
17
+ * Pass null when not authenticated
18
+ */
19
+ user?: User | null;
20
+ /**
21
+ * Resolved permissions (from PermissionResolver in your load function)
22
+ */
23
+ permissions?: string[];
24
+ /**
25
+ * WebSocket configuration
26
+ * If provided, connects on mount and disconnects on unmount
27
+ */
28
+ socket?: SocketConfig;
29
+ /**
30
+ * AI configuration for preloading and warm clients
31
+ *
32
+ * @example
33
+ * ```svelte
34
+ * <Provider
35
+ * ai={{
36
+ * preload: 'idle',
37
+ * stt: { type: 'whisper-cpp' },
38
+ * showLoadingOverlay: true
39
+ * }}
40
+ * >
41
+ * ...
42
+ * </Provider>
43
+ * ```
44
+ */
45
+ ai?: AIConfig;
46
+ /**
47
+ * Callback when capabilities are detected
48
+ */
49
+ onReady?: () => void;
50
+ /**
51
+ * Callback when mode changes
52
+ */
53
+ onModeChange?: (mode: AppMode) => void;
54
+ /**
55
+ * Callback when AI loading state changes
56
+ */
57
+ onAILoadingChange?: (state: AILoadingState) => void;
58
+ /**
59
+ * i18n snapshot from your load function (`buildI18nSnapshot` on
60
+ * `@happyvertical/smrt-svelte/i18n/server`). Provides the active locale +
61
+ * resolved message templates to `useI18n()` / `<Trans>`. Omit for
62
+ * English-default-only rendering.
63
+ */
64
+ i18n?: I18nSnapshot;
65
+ /**
66
+ * Children to render
67
+ */
68
+ children: Snippet;
69
+ }
70
+ declare const Provider: import("svelte").Component<Props, {}, "">;
71
+ type Provider = ReturnType<typeof Provider>;
72
+ export default Provider;
73
+ //# sourceMappingURL=Provider.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Provider.svelte.d.ts","sourceRoot":"","sources":["../src/Provider.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,OAAO,EACP,YAAY,EACZ,IAAI,EACL,MAAM,sBAAsB,CAAC;AAK9B,UAAU,KAAK;IACb;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;;;;;;;;;;;OAeG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACpD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiID,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Tests for app state types and initial state
3
+ */
4
+ import { describe, expect, it } from 'vitest';
5
+ import { createInitialState, } from '../state/app-state.js';
6
+ describe('createInitialState', () => {
7
+ it('creates initial state with correct defaults', () => {
8
+ const state = createInitialState();
9
+ expect(state.mode).toBe('default');
10
+ expect(state.modeSource).toBe('auto');
11
+ expect(state.initialized).toBe(false);
12
+ expect(state.error).toBeNull();
13
+ });
14
+ it('creates initial session with null user', () => {
15
+ const state = createInitialState();
16
+ expect(state.session.user).toBeNull();
17
+ expect(state.session.isAuthenticated).toBe(false);
18
+ expect(state.session.permissions).toEqual([]);
19
+ expect(state.session.preferences).toEqual({});
20
+ });
21
+ it('creates initial socket state as disconnected', () => {
22
+ const state = createInitialState();
23
+ expect(state.socket.status).toBe('disconnected');
24
+ expect(state.socket.reconnectAttempts).toBe(0);
25
+ expect(state.socket.lastError).toBeNull();
26
+ });
27
+ it('creates initial AI state as uninitialized', () => {
28
+ const state = createInitialState();
29
+ expect(state.ai.stt.initState).toBe('uninitialized');
30
+ expect(state.ai.tts.initState).toBe('uninitialized');
31
+ expect(state.ai.llm.initState).toBe('uninitialized');
32
+ });
33
+ });
34
+ describe('UserSession type', () => {
35
+ it('allows null user', () => {
36
+ const session = {
37
+ user: null,
38
+ isAuthenticated: false,
39
+ permissions: [],
40
+ preferences: {},
41
+ };
42
+ expect(session.user).toBeNull();
43
+ expect(session.isAuthenticated).toBe(false);
44
+ });
45
+ it('allows user with permissions', () => {
46
+ const session = {
47
+ user: {
48
+ id: 'user-123',
49
+ profileId: 'profile-456',
50
+ email: 'test@example.com',
51
+ status: 'active',
52
+ lastLoginAt: null,
53
+ },
54
+ isAuthenticated: true,
55
+ permissions: ['articles.create', 'articles.read'],
56
+ preferences: {
57
+ preferredSTT: 'whisper-cpp',
58
+ autoEnableSmrt: true,
59
+ },
60
+ };
61
+ expect(session.user?.email).toBe('test@example.com');
62
+ expect(session.isAuthenticated).toBe(true);
63
+ expect(session.permissions).toContain('articles.create');
64
+ });
65
+ });
66
+ describe('SocketState type', () => {
67
+ it('allows all socket statuses', () => {
68
+ const statuses = [
69
+ 'disconnected',
70
+ 'connecting',
71
+ 'connected',
72
+ 'reconnecting',
73
+ ];
74
+ statuses.forEach((status) => {
75
+ const state = {
76
+ status,
77
+ reconnectAttempts: 0,
78
+ lastError: null,
79
+ };
80
+ expect(state.status).toBe(status);
81
+ });
82
+ });
83
+ });
84
+ describe('SocketConfig type', () => {
85
+ it('allows minimal config with just url', () => {
86
+ const config = {
87
+ url: 'wss://example.com/ws',
88
+ };
89
+ expect(config.url).toBe('wss://example.com/ws');
90
+ expect(config.reconnect).toBeUndefined();
91
+ expect(config.onMessage).toBeUndefined();
92
+ });
93
+ it('allows full config with all options', () => {
94
+ const config = {
95
+ url: 'wss://example.com/ws',
96
+ reconnect: {
97
+ enabled: true,
98
+ maxAttempts: 10,
99
+ baseDelay: 2000,
100
+ },
101
+ onOpen: () => { },
102
+ onMessage: (data) => console.log(data),
103
+ onClose: (event) => console.log(event),
104
+ onError: (event) => console.log(event),
105
+ };
106
+ expect(config.url).toBe('wss://example.com/ws');
107
+ expect(config.reconnect?.enabled).toBe(true);
108
+ expect(config.reconnect?.maxAttempts).toBe(10);
109
+ });
110
+ });
111
+ describe('AIConfig type', () => {
112
+ it('creates initial AI loading state', () => {
113
+ const state = createInitialState();
114
+ expect(state.aiLoading.phase).toBe('idle');
115
+ expect(state.aiLoading.currentAdapter).toBeNull();
116
+ expect(state.aiLoading.overallProgress).toBe(0);
117
+ expect(state.aiLoading.message).toBe('');
118
+ expect(state.aiLoading.loaded).toEqual([]);
119
+ expect(state.aiLoading.failed).toEqual([]);
120
+ expect(state.aiLoading.error).toBeNull();
121
+ });
122
+ });
123
+ describe('AIConfig types', () => {
124
+ it('allows preload strategies', () => {
125
+ const strategies = ['none', 'eager', 'idle', 'on-visible'];
126
+ strategies.forEach((strategy) => {
127
+ expect(strategy).toBeDefined();
128
+ });
129
+ });
130
+ it('allows STT config', () => {
131
+ const sttConfig = {
132
+ type: 'whisper-cpp',
133
+ model: 'tiny.en',
134
+ enabled: true,
135
+ };
136
+ expect(sttConfig.type).toBe('whisper-cpp');
137
+ expect(sttConfig.model).toBe('tiny.en');
138
+ });
139
+ it('allows TTS config', () => {
140
+ const ttsConfig = {
141
+ type: 'browser-synthesis',
142
+ voice: 'Google UK English Female',
143
+ enabled: true,
144
+ };
145
+ expect(ttsConfig.type).toBe('browser-synthesis');
146
+ });
147
+ it('allows LLM config', () => {
148
+ const llmConfig = {
149
+ type: 'webllm',
150
+ model: 'Llama-3.1-8B-Instruct',
151
+ enabled: true,
152
+ };
153
+ expect(llmConfig.type).toBe('webllm');
154
+ expect(llmConfig.model).toBe('Llama-3.1-8B-Instruct');
155
+ });
156
+ });
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Tests for warm client cache
3
+ */
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { clearAllCaches, getCachedLLM, getCachedSTT, getCachedTTS, getCacheStats, removeCachedLLM, removeCachedSTT, removeCachedTTS, setCachedLLM, setCachedSTT, setCachedTTS, updateLLMCacheState, updateSTTCacheState, updateTTSCacheState, } from '../state/warm-clients.js';
6
+ // Mock adapters for testing
7
+ const createMockSTTAdapter = () => ({
8
+ type: 'whisper-cpp',
9
+ dispose: () => Promise.resolve(),
10
+ ensureInitialized: () => Promise.resolve(),
11
+ start: () => Promise.resolve(),
12
+ stop: () => Promise.resolve(),
13
+ onResult: () => { },
14
+ onStart: () => { },
15
+ onEnd: () => { },
16
+ onError: () => { },
17
+ });
18
+ const createMockTTSAdapter = () => ({
19
+ type: 'browser-synthesis',
20
+ dispose: () => Promise.resolve(),
21
+ ensureInitialized: () => Promise.resolve(),
22
+ speak: () => Promise.resolve(),
23
+ stop: () => { },
24
+ pause: () => { },
25
+ resume: () => { },
26
+ getVoices: () => [],
27
+ onStart: () => { },
28
+ onEnd: () => { },
29
+ onError: () => { },
30
+ });
31
+ const createMockLLMAdapter = () => ({
32
+ type: 'webllm',
33
+ currentModel: 'test-model',
34
+ dispose: () => Promise.resolve(),
35
+ ensureInitialized: () => Promise.resolve(),
36
+ message: () => Promise.resolve('response'),
37
+ unloadModel: () => Promise.resolve(),
38
+ });
39
+ describe('warm-clients', () => {
40
+ afterEach(async () => {
41
+ await clearAllCaches();
42
+ });
43
+ describe('STT cache', () => {
44
+ it('caches STT adapter', () => {
45
+ const adapter = createMockSTTAdapter();
46
+ setCachedSTT('whisper-cpp', adapter);
47
+ const cached = getCachedSTT('whisper-cpp');
48
+ expect(cached).toBeDefined();
49
+ expect(cached?.adapter).toBe(adapter);
50
+ expect(cached?.initState).toBe('ready');
51
+ expect(cached?.type).toBe('whisper-cpp');
52
+ });
53
+ it('returns undefined for uncached adapter', () => {
54
+ const cached = getCachedSTT('browser-speech');
55
+ expect(cached).toBeUndefined();
56
+ });
57
+ it('updates cache state', () => {
58
+ const adapter = createMockSTTAdapter();
59
+ setCachedSTT('whisper-cpp', adapter);
60
+ updateSTTCacheState('whisper-cpp', {
61
+ initState: 'initializing',
62
+ downloadProgress: {
63
+ state: 'downloading',
64
+ percent: 50,
65
+ bytesLoaded: 50,
66
+ bytesTotal: 100,
67
+ },
68
+ });
69
+ const cached = getCachedSTT('whisper-cpp');
70
+ expect(cached?.initState).toBe('initializing');
71
+ expect(cached?.downloadProgress?.percent).toBe(50);
72
+ });
73
+ it('removes cached adapter', () => {
74
+ const adapter = createMockSTTAdapter();
75
+ setCachedSTT('whisper-cpp', adapter);
76
+ removeCachedSTT('whisper-cpp');
77
+ const cached = getCachedSTT('whisper-cpp');
78
+ expect(cached).toBeUndefined();
79
+ });
80
+ });
81
+ describe('TTS cache', () => {
82
+ it('caches TTS adapter', () => {
83
+ const adapter = createMockTTSAdapter();
84
+ setCachedTTS('browser-synthesis', adapter);
85
+ const cached = getCachedTTS('browser-synthesis');
86
+ expect(cached).toBeDefined();
87
+ expect(cached?.adapter).toBe(adapter);
88
+ expect(cached?.initState).toBe('ready');
89
+ });
90
+ it('updates cache state', () => {
91
+ const adapter = createMockTTSAdapter();
92
+ setCachedTTS('browser-synthesis', adapter);
93
+ updateTTSCacheState('browser-synthesis', {
94
+ initState: 'error',
95
+ error: new Error('test error'),
96
+ });
97
+ const cached = getCachedTTS('browser-synthesis');
98
+ expect(cached?.initState).toBe('error');
99
+ expect(cached?.error?.message).toBe('test error');
100
+ });
101
+ });
102
+ describe('LLM cache', () => {
103
+ it('caches LLM adapter with model ID', () => {
104
+ const adapter = createMockLLMAdapter();
105
+ setCachedLLM('webllm', adapter, 'test-model');
106
+ const cached = getCachedLLM('webllm', 'test-model');
107
+ expect(cached).toBeDefined();
108
+ expect(cached?.adapter).toBe(adapter);
109
+ expect(cached?.initState).toBe('ready');
110
+ });
111
+ it('caches LLM adapter without model ID', () => {
112
+ const adapter = createMockLLMAdapter();
113
+ setCachedLLM('webllm', adapter);
114
+ const cached = getCachedLLM('webllm');
115
+ expect(cached).toBeDefined();
116
+ expect(cached?.adapter).toBe(adapter);
117
+ });
118
+ it('distinguishes between models', () => {
119
+ const adapter1 = createMockLLMAdapter();
120
+ const adapter2 = {
121
+ ...createMockLLMAdapter(),
122
+ currentModel: 'other-model',
123
+ };
124
+ setCachedLLM('webllm', adapter1, 'model-1');
125
+ setCachedLLM('webllm', adapter2, 'model-2');
126
+ expect(getCachedLLM('webllm', 'model-1')?.adapter).toBe(adapter1);
127
+ expect(getCachedLLM('webllm', 'model-2')?.adapter).toBe(adapter2);
128
+ });
129
+ it('updates cache state', () => {
130
+ const adapter = createMockLLMAdapter();
131
+ setCachedLLM('webllm', adapter, 'test-model');
132
+ updateLLMCacheState('webllm', 'test-model', {
133
+ initState: 'initializing',
134
+ downloadProgress: {
135
+ state: 'downloading',
136
+ percent: 75,
137
+ bytesLoaded: 75,
138
+ bytesTotal: 100,
139
+ },
140
+ });
141
+ const cached = getCachedLLM('webllm', 'test-model');
142
+ expect(cached?.initState).toBe('initializing');
143
+ expect(cached?.downloadProgress?.percent).toBe(75);
144
+ });
145
+ it('removes cached adapter', () => {
146
+ const adapter = createMockLLMAdapter();
147
+ setCachedLLM('webllm', adapter, 'test-model');
148
+ removeCachedLLM('webllm', 'test-model');
149
+ const cached = getCachedLLM('webllm', 'test-model');
150
+ expect(cached).toBeUndefined();
151
+ });
152
+ });
153
+ describe('getCacheStats', () => {
154
+ it('returns empty stats initially', async () => {
155
+ const stats = getCacheStats();
156
+ expect(stats.stt.count).toBe(0);
157
+ expect(stats.tts.count).toBe(0);
158
+ expect(stats.llm.count).toBe(0);
159
+ });
160
+ it('returns correct counts after caching', () => {
161
+ setCachedSTT('whisper-cpp', createMockSTTAdapter());
162
+ setCachedSTT('browser-speech', createMockSTTAdapter());
163
+ setCachedTTS('browser-synthesis', createMockTTSAdapter());
164
+ setCachedLLM('webllm', createMockLLMAdapter(), 'model-1');
165
+ const stats = getCacheStats();
166
+ expect(stats.stt.count).toBe(2);
167
+ expect(stats.stt.types).toContain('whisper-cpp');
168
+ expect(stats.stt.types).toContain('browser-speech');
169
+ expect(stats.tts.count).toBe(1);
170
+ expect(stats.llm.count).toBe(1);
171
+ expect(stats.llm.keys).toContain('webllm:model-1');
172
+ });
173
+ });
174
+ describe('clearAllCaches', () => {
175
+ it('clears all cached adapters', async () => {
176
+ setCachedSTT('whisper-cpp', createMockSTTAdapter());
177
+ setCachedTTS('browser-synthesis', createMockTTSAdapter());
178
+ setCachedLLM('webllm', createMockLLMAdapter());
179
+ await clearAllCaches();
180
+ const stats = getCacheStats();
181
+ expect(stats.stt.count).toBe(0);
182
+ expect(stats.tts.count).toBe(0);
183
+ expect(stats.llm.count).toBe(0);
184
+ });
185
+ });
186
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * LLM adapter factory with type guards
3
+ */
4
+ import type { GetLLMOptions, LLMAdapter } from './types.js';
5
+ /**
6
+ * Create an LLM adapter
7
+ *
8
+ * Uses lazy loading to only import the requested adapter.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * // WebLLM (default)
13
+ * const llm = await getLLM();
14
+ *
15
+ * // With specific model
16
+ * const llm = await getLLM({ defaultModel: 'Llama-3.2-1B-Instruct-q4f16_1-MLC' });
17
+ * ```
18
+ */
19
+ export declare function getLLM(options?: GetLLMOptions): Promise<LLMAdapter>;
20
+ /**
21
+ * Auto-detect and create the best available LLM adapter
22
+ *
23
+ * Selection priority:
24
+ * 1. WebLLM with WebGPU (best performance)
25
+ * 2. Transformers.js as fallback
26
+ *
27
+ * @throws If no LLM adapter is available
28
+ */
29
+ export declare function getLLMAuto(options?: Partial<Omit<GetLLMOptions, 'type'>>): Promise<LLMAdapter>;
30
+ /**
31
+ * Check if a specific LLM backend is available
32
+ */
33
+ export declare function isLLMAvailable(type: 'webllm' | 'transformers-llm'): boolean;
34
+ /**
35
+ * Check if WebGPU is available for accelerated inference
36
+ */
37
+ export declare function hasWebGPU(): boolean;
38
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../src/browser-ai/adapters/llm/factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EAGX,MAAM,YAAY,CAAC;AAkBpB;;;;;;;;;;;;;GAaG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAe7E;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAM,GACjD,OAAO,CAAC,UAAU,CAAC,CAoBrB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,kBAAkB,GAAG,OAAO,CAY3E;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}