@happyvertical/smrt-svelte 0.53.0 → 0.53.2

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 (254) hide show
  1. package/package.json +15 -15
  2. package/dist/__tests__/app-state.test.js +0 -156
  3. package/dist/__tests__/data-surface-bridge.test.js +0 -351
  4. package/dist/__tests__/provider-mode-harness.svelte +0 -14
  5. package/dist/__tests__/provider-mode-harness.svelte.d.ts +0 -11
  6. package/dist/__tests__/provider-mode-harness.svelte.d.ts.map +0 -1
  7. package/dist/__tests__/provider-mode-probe.svelte +0 -13
  8. package/dist/__tests__/provider-mode-probe.svelte.d.ts +0 -8
  9. package/dist/__tests__/provider-mode-probe.svelte.d.ts.map +0 -1
  10. package/dist/__tests__/provider-webmcp-harness.svelte +0 -14
  11. package/dist/__tests__/provider-webmcp-harness.svelte.d.ts +0 -8
  12. package/dist/__tests__/provider-webmcp-harness.svelte.d.ts.map +0 -1
  13. package/dist/__tests__/success-never-text.test.js +0 -100
  14. package/dist/__tests__/warm-clients.test.js +0 -186
  15. package/dist/browser-ai/adapters/llm/bitgpu-inference-backend.test.js +0 -464
  16. package/dist/browser-ai/adapters/llm/webllm-inference-backend.test.js +0 -646
  17. package/dist/browser-ai/adapters/stt/browser-speech.test.js +0 -113
  18. package/dist/browser-ai/adapters/stt/dictation-source.test.js +0 -52
  19. package/dist/browser-ai/svelte/components/__tests__/ModelStatusControl.test.js +0 -172
  20. package/dist/components/board/__tests__/Board.test.js +0 -498
  21. package/dist/components/board/__tests__/BoardSsrHarness.svelte +0 -30
  22. package/dist/components/board/__tests__/BoardSsrHarness.svelte.d.ts +0 -19
  23. package/dist/components/board/__tests__/BoardSsrHarness.svelte.d.ts.map +0 -1
  24. package/dist/components/forms/__tests__/AddressInput.behavior.test.js +0 -216
  25. package/dist/components/forms/__tests__/CheckboxInput.test.js +0 -92
  26. package/dist/components/forms/__tests__/DateRangeInput.behavior.test.js +0 -135
  27. package/dist/components/forms/__tests__/DateTimeInput.behavior.test.js +0 -113
  28. package/dist/components/forms/__tests__/FileUpload.error-alert.test.js +0 -37
  29. package/dist/components/forms/__tests__/FileUpload.native-form.test.js +0 -249
  30. package/dist/components/forms/__tests__/FileUpload.test.js +0 -90
  31. package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte +0 -24
  32. package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte.d.ts +0 -10
  33. package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte.d.ts.map +0 -1
  34. package/dist/components/forms/__tests__/Form.behavior.test.js +0 -137
  35. package/dist/components/forms/__tests__/Form.extraction.test.js +0 -68
  36. package/dist/components/forms/__tests__/Form.stt-error.test.js +0 -57
  37. package/dist/components/forms/__tests__/Form.test.js +0 -86
  38. package/dist/components/forms/__tests__/Form.ui-controls.test.js +0 -119
  39. package/dist/components/forms/__tests__/Form.webmcp.test.js +0 -2336
  40. package/dist/components/forms/__tests__/FormMicButton.test.js +0 -92
  41. package/dist/components/forms/__tests__/FormScope.test.js +0 -39
  42. package/dist/components/forms/__tests__/MeasurementInput.behavior.test.js +0 -129
  43. package/dist/components/forms/__tests__/MoneyInput.behavior.test.js +0 -124
  44. package/dist/components/forms/__tests__/NumberInput.behavior.test.js +0 -151
  45. package/dist/components/forms/__tests__/PhoneInput.behavior.test.js +0 -96
  46. package/dist/components/forms/__tests__/SearchInput.test.js +0 -79
  47. package/dist/components/forms/__tests__/SelectInput.behavior.test.js +0 -132
  48. package/dist/components/forms/__tests__/TextInput.behavior.test.js +0 -131
  49. package/dist/components/forms/__tests__/TextareaInput.behavior.test.js +0 -96
  50. package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte +0 -30
  51. package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts +0 -7
  52. package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts.map +0 -1
  53. package/dist/components/forms/__tests__/async-validation-form.fixture.svelte +0 -19
  54. package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts +0 -9
  55. package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts.map +0 -1
  56. package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte +0 -21
  57. package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts +0 -8
  58. package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts.map +0 -1
  59. package/dist/components/forms/__tests__/composite-inputs-a11y.test.js +0 -69
  60. package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte +0 -27
  61. package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts +0 -9
  62. package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts.map +0 -1
  63. package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte +0 -48
  64. package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts +0 -10
  65. package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts.map +0 -1
  66. package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte +0 -26
  67. package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts +0 -13
  68. package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts.map +0 -1
  69. package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte +0 -52
  70. package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts +0 -16
  71. package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts.map +0 -1
  72. package/dist/components/forms/__tests__/form-scope.fixture.svelte +0 -30
  73. package/dist/components/forms/__tests__/form-scope.fixture.svelte.d.ts +0 -10
  74. package/dist/components/forms/__tests__/form-scope.fixture.svelte.d.ts.map +0 -1
  75. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +0 -158
  76. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +0 -51
  77. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +0 -1
  78. package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte +0 -24
  79. package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts +0 -11
  80. package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts.map +0 -1
  81. package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte +0 -105
  82. package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts +0 -42
  83. package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts.map +0 -1
  84. package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte +0 -84
  85. package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte.d.ts +0 -14
  86. package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte.d.ts.map +0 -1
  87. package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte +0 -44
  88. package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts +0 -9
  89. package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts.map +0 -1
  90. package/dist/components/forms/__tests__/mic-keyboard-a11y.test.js +0 -74
  91. package/dist/components/forms/__tests__/policy-field.fixture.svelte +0 -35
  92. package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts +0 -8
  93. package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts.map +0 -1
  94. package/dist/components/forms/__tests__/rich-inputs-a11y.test.js +0 -87
  95. package/dist/components/settings/__tests__/SettingsCatalog.test.js +0 -69
  96. package/dist/components/settings/__tests__/catalog.test.js +0 -46
  97. package/dist/components/workspace/__tests__/AdminShell.responsive.test.js +0 -597
  98. package/dist/components/workspace/__tests__/AdminShell.test.js +0 -572
  99. package/dist/components/workspace/__tests__/RoleShell.test.js +0 -772
  100. package/dist/components/workspace/__tests__/TenantNav.test.js +0 -208
  101. package/dist/components/workspace/__tests__/WorkspaceAccountMenu.test.js +0 -79
  102. package/dist/components/workspace/__tests__/WorkspaceShell.test.js +0 -630
  103. package/dist/components/workspace/__tests__/admin-shell-header-overflow.test.js +0 -25
  104. package/dist/components/workspace/__tests__/admin-shell-hotkeys.test.js +0 -34
  105. package/dist/components/workspace/__tests__/admin-shell-mobile.test.js +0 -217
  106. package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte +0 -52
  107. package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte.d.ts +0 -23
  108. package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte.d.ts.map +0 -1
  109. package/dist/components/workspace/__tests__/admin-shell-page-contracts.test.js +0 -30
  110. package/dist/components/workspace/__tests__/admin-shell-responsive-state.test.js +0 -184
  111. package/dist/components/workspace/__tests__/admin-shell-settings.test.js +0 -25
  112. package/dist/components/workspace/__tests__/admin-shell-state.test.js +0 -286
  113. package/dist/components/workspace/__tests__/admin-shell-theme-hooks.test.js +0 -36
  114. package/dist/components/workspace/__tests__/breadcrumbs-helpers.test.js +0 -141
  115. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte +0 -45
  116. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts +0 -21
  117. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts.map +0 -1
  118. package/dist/components/workspace/__tests__/define-tools-dock.test.js +0 -1188
  119. package/dist/components/workspace/__tests__/harness.svelte +0 -25
  120. package/dist/components/workspace/__tests__/harness.svelte.d.ts +0 -14
  121. package/dist/components/workspace/__tests__/harness.svelte.d.ts.map +0 -1
  122. package/dist/components/workspace/__tests__/index.test.js +0 -28
  123. package/dist/components/workspace/__tests__/legacy-index.test.js +0 -9
  124. package/dist/components/workspace/__tests__/manifest-nav-helpers.test.js +0 -24
  125. package/dist/components/workspace/__tests__/manifest-nav.test.js +0 -599
  126. package/dist/components/workspace/__tests__/nav-helpers.test.js +0 -95
  127. package/dist/components/workspace/__tests__/render-harness.svelte +0 -66
  128. package/dist/components/workspace/__tests__/render-harness.svelte.d.ts +0 -32
  129. package/dist/components/workspace/__tests__/render-harness.svelte.d.ts.map +0 -1
  130. package/dist/components/workspace/__tests__/render-tools-dock.test.js +0 -260
  131. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte +0 -58
  132. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts +0 -16
  133. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts.map +0 -1
  134. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte +0 -41
  135. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts +0 -13
  136. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts.map +0 -1
  137. package/dist/components/workspace/__tests__/shell-chrome-components.test.js +0 -108
  138. package/dist/components/workspace/__tests__/system-feed.test.js +0 -327
  139. package/dist/components/workspace/__tests__/test-icon.svelte +0 -17
  140. package/dist/components/workspace/__tests__/test-icon.svelte.d.ts +0 -19
  141. package/dist/components/workspace/__tests__/test-icon.svelte.d.ts.map +0 -1
  142. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte +0 -38
  143. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts +0 -22
  144. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts.map +0 -1
  145. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +0 -66
  146. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +0 -1
  147. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +0 -115
  148. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts +0 -15
  149. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts.map +0 -1
  150. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.js +0 -7
  151. package/dist/components/workspace/__tests__/typed-tool-fixture.test.js +0 -115
  152. package/dist/components/workspace/__tests__/use-harness-orphan.svelte +0 -9
  153. package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts +0 -19
  154. package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts.map +0 -1
  155. package/dist/components/workspace/__tests__/use-harness.svelte +0 -23
  156. package/dist/components/workspace/__tests__/use-harness.svelte.d.ts +0 -8
  157. package/dist/components/workspace/__tests__/use-harness.svelte.d.ts.map +0 -1
  158. package/dist/components/workspace/__tests__/use-tools-dock.test.js +0 -33
  159. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte +0 -43
  160. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts +0 -11
  161. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts.map +0 -1
  162. package/dist/components/workspace/server/__tests__/compose-availability.test.js +0 -383
  163. package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts +0 -78
  164. package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts.map +0 -1
  165. package/dist/components/workspace/server/__tests__/typed-context-fixture.js +0 -104
  166. package/dist/hooks/__tests__/stt-consumer.fixture.svelte +0 -25
  167. package/dist/hooks/__tests__/stt-consumer.fixture.svelte.d.ts +0 -15
  168. package/dist/hooks/__tests__/stt-consumer.fixture.svelte.d.ts.map +0 -1
  169. package/dist/hooks/__tests__/stt-ownership-harness.svelte +0 -42
  170. package/dist/hooks/__tests__/stt-ownership-harness.svelte.d.ts +0 -20
  171. package/dist/hooks/__tests__/stt-ownership-harness.svelte.d.ts.map +0 -1
  172. package/dist/hooks/__tests__/useSTT-ownership.test.js +0 -102
  173. package/dist/i18n/__tests__/server.spec.js +0 -57
  174. package/dist/internal/logger.test.js +0 -54
  175. package/dist/provider-mode.test.js +0 -86
  176. package/dist/provider-webmcp.test.js +0 -244
  177. package/dist/state/__tests__/app-state-ai-lifecycle.test.js +0 -240
  178. package/dist/state/__tests__/warm-clients.test.js +0 -40
  179. package/dist/web/__tests__/activity-feed-harness.svelte +0 -32
  180. package/dist/web/__tests__/activity-feed-harness.svelte.d.ts +0 -18
  181. package/dist/web/__tests__/activity-feed-harness.svelte.d.ts.map +0 -1
  182. package/dist/web/__tests__/activity-feed.integration.svelte.test.js +0 -190
  183. package/dist/web/__tests__/activity-feed.svelte.test.js +0 -235
  184. package/dist/web/__tests__/assistant-dock.integration.svelte.test.js +0 -204
  185. package/dist/web/__tests__/data-surface-conformance.integration.svelte.test.js +0 -1392
  186. package/dist/web/__tests__/harness.svelte +0 -25
  187. package/dist/web/__tests__/harness.svelte.d.ts +0 -15
  188. package/dist/web/__tests__/harness.svelte.d.ts.map +0 -1
  189. package/dist/web/__tests__/list-data-surface.fixture.svelte +0 -59
  190. package/dist/web/__tests__/list-data-surface.fixture.svelte.d.ts +0 -14
  191. package/dist/web/__tests__/list-data-surface.fixture.svelte.d.ts.map +0 -1
  192. package/dist/web/__tests__/list-data-surface.svelte.test.js +0 -106
  193. package/dist/web/__tests__/list-data-surface.test.js +0 -651
  194. package/dist/web/__tests__/list-sort-surface.fixture.svelte +0 -41
  195. package/dist/web/__tests__/list-sort-surface.fixture.svelte.d.ts +0 -15
  196. package/dist/web/__tests__/list-sort-surface.fixture.svelte.d.ts.map +0 -1
  197. package/dist/web/__tests__/list-sort-surface.svelte.test.js +0 -59
  198. package/dist/web/__tests__/live-collection.svelte.test.js +0 -185
  199. package/dist/web/__tests__/provider-ui-registry.fixture.svelte +0 -43
  200. package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts +0 -13
  201. package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts.map +0 -1
  202. package/dist/web/__tests__/provider-ui-registry.test.js +0 -235
  203. package/dist/web/__tests__/remote-query-harness.svelte +0 -27
  204. package/dist/web/__tests__/remote-query-harness.svelte.d.ts +0 -11
  205. package/dist/web/__tests__/remote-query-harness.svelte.d.ts.map +0 -1
  206. package/dist/web/__tests__/remote-query.svelte.test.js +0 -101
  207. package/dist/web/__tests__/surfaces.child.fixture.svelte +0 -69
  208. package/dist/web/__tests__/surfaces.child.fixture.svelte.d.ts +0 -16
  209. package/dist/web/__tests__/surfaces.child.fixture.svelte.d.ts.map +0 -1
  210. package/dist/web/__tests__/surfaces.fixture.svelte +0 -26
  211. package/dist/web/__tests__/surfaces.fixture.svelte.d.ts +0 -18
  212. package/dist/web/__tests__/surfaces.fixture.svelte.d.ts.map +0 -1
  213. package/dist/web/__tests__/surfaces.svelte.test.js +0 -140
  214. package/dist/web/__tests__/update-available-harness.svelte +0 -46
  215. package/dist/web/__tests__/update-available-harness.svelte.d.ts +0 -22
  216. package/dist/web/__tests__/update-available-harness.svelte.d.ts.map +0 -1
  217. package/dist/web/__tests__/update-available.svelte.test.js +0 -137
  218. package/dist/web/__tests__/view-intent-provider.fixture.svelte +0 -28
  219. package/dist/web/__tests__/view-intent-provider.fixture.svelte.d.ts +0 -13
  220. package/dist/web/__tests__/view-intent-provider.fixture.svelte.d.ts.map +0 -1
  221. package/dist/web/__tests__/view-intent.fixture.svelte +0 -33
  222. package/dist/web/__tests__/view-intent.fixture.svelte.d.ts +0 -15
  223. package/dist/web/__tests__/view-intent.fixture.svelte.d.ts.map +0 -1
  224. package/dist/web/__tests__/view-intent.intents.d.ts +0 -14
  225. package/dist/web/__tests__/view-intent.intents.d.ts.map +0 -1
  226. package/dist/web/__tests__/view-intent.intents.js +0 -38
  227. package/dist/web/__tests__/view-intent.svelte.test.js +0 -244
  228. package/dist/web/__tests__/webmcp-composed.child.fixture.svelte +0 -73
  229. package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts +0 -8
  230. package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts.map +0 -1
  231. package/dist/web/__tests__/webmcp-composed.fixture.svelte +0 -52
  232. package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts +0 -12
  233. package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts.map +0 -1
  234. package/dist/web/__tests__/webmcp-composed.integration.svelte.test.js +0 -251
  235. package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte +0 -16
  236. package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte.d.ts +0 -19
  237. package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte.d.ts.map +0 -1
  238. package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte +0 -11
  239. package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte.d.ts +0 -8
  240. package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte.d.ts.map +0 -1
  241. package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte +0 -20
  242. package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte.d.ts +0 -7
  243. package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte.d.ts.map +0 -1
  244. package/dist/web/__tests__/webmcp-harness-unannotated.svelte +0 -14
  245. package/dist/web/__tests__/webmcp-harness-unannotated.svelte.d.ts +0 -19
  246. package/dist/web/__tests__/webmcp-harness-unannotated.svelte.d.ts.map +0 -1
  247. package/dist/web/__tests__/webmcp-harness.svelte +0 -18
  248. package/dist/web/__tests__/webmcp-harness.svelte.d.ts +0 -7
  249. package/dist/web/__tests__/webmcp-harness.svelte.d.ts.map +0 -1
  250. package/dist/web/__tests__/webmcp-ssr.fixture.svelte +0 -13
  251. package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts +0 -19
  252. package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts.map +0 -1
  253. package/dist/web/__tests__/webmcp-ui.test.js +0 -723
  254. package/dist/web/__tests__/webmcp.test.js +0 -234
@@ -1,113 +0,0 @@
1
- /**
2
- * BrowserSpeechSTTAdapter errors: every Web Speech error reaches `onError`
3
- * with its code (`speechError`), including an `aborted` the adapter did not
4
- * cause, and through smrt-ui's `Dictation` Brave's "starts, then `network`"
5
- * becomes a plain error instead of a silent stop.
6
- */
7
- import { Dictation } from '@happyvertical/smrt-ui/forms';
8
- import { afterEach, describe, expect, it, vi } from 'vitest';
9
- import { BrowserSpeechSTTAdapter, } from './browser-speech.js';
10
- import { createSttDictationSource } from './dictation-source.js';
11
- class FakeRecognition {
12
- static last = null;
13
- /** What the browser does after start(): Brave errors with `network`. */
14
- static afterStart = null;
15
- lang = '';
16
- continuous = false;
17
- interimResults = false;
18
- maxAlternatives = 1;
19
- onresult = null;
20
- onerror = null;
21
- onstart = null;
22
- onend = null;
23
- constructor() {
24
- FakeRecognition.last = this;
25
- }
26
- start = vi.fn(() => {
27
- this.onstart?.();
28
- FakeRecognition.afterStart?.(this);
29
- });
30
- stop = vi.fn(() => this.onend?.());
31
- abort = vi.fn(() => {
32
- this.onerror?.({ error: 'aborted', message: '' });
33
- this.onend?.();
34
- });
35
- fail(code) {
36
- this.onerror?.({ error: code, message: '' });
37
- this.onend?.();
38
- }
39
- }
40
- function install() {
41
- window.webkitSpeechRecognition =
42
- FakeRecognition;
43
- }
44
- afterEach(() => {
45
- delete window
46
- .webkitSpeechRecognition;
47
- FakeRecognition.last = null;
48
- FakeRecognition.afterStart = null;
49
- });
50
- describe('BrowserSpeechSTTAdapter errors', () => {
51
- it.each([
52
- 'network',
53
- 'not-allowed',
54
- 'service-not-allowed',
55
- 'no-speech',
56
- 'audio-capture',
57
- 'aborted',
58
- 'language-not-supported',
59
- ])('reports %s with its code', async (code) => {
60
- install();
61
- const adapter = new BrowserSpeechSTTAdapter();
62
- const errors = [];
63
- adapter.onError((error) => errors.push(error));
64
- await adapter.start({ continuous: true });
65
- FakeRecognition.last?.fail(code);
66
- expect(errors).toHaveLength(1);
67
- expect(errors[0].speechError).toBe(code);
68
- });
69
- it('does not report the abort it caused itself', async () => {
70
- install();
71
- const adapter = new BrowserSpeechSTTAdapter();
72
- const onError = vi.fn();
73
- adapter.onError(onError);
74
- await adapter.start();
75
- adapter.abort();
76
- expect(onError).not.toHaveBeenCalled();
77
- });
78
- });
79
- describe('Dictation over the browser adapter', () => {
80
- it("Brave: it beeps, then 'network' — shown as unavailable, not a silent stop", async () => {
81
- install();
82
- FakeRecognition.afterStart = (r) => queueMicrotask(() => r.fail('network'));
83
- const log = vi.fn();
84
- const beep = vi.fn(async () => true);
85
- const dictation = new Dictation({
86
- source: createSttDictationSource(),
87
- onText: () => { },
88
- beep,
89
- log,
90
- requestMicrophone: false,
91
- });
92
- await dictation.start();
93
- await vi.waitFor(() => expect(dictation.state).toBe('error'));
94
- expect(beep).toHaveBeenCalled();
95
- expect(dictation.errorKind).toBe('unsupported');
96
- expect(dictation.errorCode).toBe('network');
97
- expect(log).toHaveBeenCalledWith(expect.objectContaining({ kind: 'unsupported', code: 'network' }));
98
- });
99
- it('an end straight after starting with no error is a failure too', async () => {
100
- install();
101
- FakeRecognition.afterStart = (r) => queueMicrotask(() => r.onend?.());
102
- const dictation = new Dictation({
103
- source: createSttDictationSource(),
104
- onText: () => { },
105
- beep: false,
106
- log: () => { },
107
- requestMicrophone: false,
108
- });
109
- await dictation.start();
110
- await vi.waitFor(() => expect(dictation.state).toBe('error'));
111
- expect(dictation.errorKind).toBe('interrupted');
112
- });
113
- });
@@ -1,52 +0,0 @@
1
- /**
2
- * createSttDictationSource: the browser speech adapter, created once and
3
- * lazily, and rejected plainly where the browser has no speech recognition.
4
- */
5
- import { afterEach, describe, expect, it, vi } from 'vitest';
6
- import { createSttDictationSource } from './dictation-source.js';
7
- class FakeRecognition {
8
- lang = '';
9
- continuous = false;
10
- interimResults = false;
11
- maxAlternatives = 1;
12
- onresult = null;
13
- onerror = null;
14
- onstart = null;
15
- onend = null;
16
- start = vi.fn(() => this.onstart?.());
17
- stop = vi.fn(() => this.onend?.());
18
- abort = vi.fn();
19
- }
20
- describe('createSttDictationSource', () => {
21
- afterEach(() => {
22
- delete window.SpeechRecognition;
23
- delete window
24
- .webkitSpeechRecognition;
25
- });
26
- it('creates one browser speech adapter, on first use', async () => {
27
- window.webkitSpeechRecognition =
28
- FakeRecognition;
29
- const provide = createSttDictationSource();
30
- const first = await provide();
31
- const second = await provide();
32
- expect(first).toBe(second);
33
- expect(first.type).toBe('browser-speech');
34
- const onStart = vi.fn();
35
- first.onStart(onStart);
36
- await first.start({
37
- language: 'en-CA',
38
- continuous: true,
39
- interimResults: true,
40
- });
41
- expect(onStart).toHaveBeenCalled();
42
- });
43
- it('rejects with CapabilityNotAvailableError without speech recognition, then can retry', async () => {
44
- const provide = createSttDictationSource();
45
- await expect(provide()).rejects.toMatchObject({
46
- name: 'CapabilityNotAvailableError',
47
- });
48
- window.SpeechRecognition =
49
- FakeRecognition;
50
- await expect(provide()).resolves.toBeTruthy();
51
- });
52
- });
@@ -1,172 +0,0 @@
1
- /**
2
- * `ModelStatusControl` — the user-facing model lifecycle surface.
3
- *
4
- * The states that matter here are the ones a user acts on: whether the model is
5
- * loaded, whether it can be loaded on this device at all, and what a download
6
- * is doing. The `unavailable` case is asserted explicitly because offering a
7
- * Load button on a device that cannot run the model is the failure this control
8
- * exists to prevent.
9
- */
10
- import { expectNoA11yViolations } from '@happyvertical/smrt-ui/test-support/a11y';
11
- import { render, screen } from '@testing-library/svelte';
12
- import userEvent from '@testing-library/user-event';
13
- import { tick } from 'svelte';
14
- import { describe, expect, it, vi } from 'vitest';
15
- import ModelStatusControl from '../ModelStatusControl.svelte';
16
- function makeBackend(initial = {}) {
17
- let status = initial.status ?? 'idle';
18
- let progress;
19
- const listeners = new Set();
20
- const backend = {
21
- id: 'local',
22
- kind: 'local',
23
- get status() {
24
- return status;
25
- },
26
- get progress() {
27
- return progress;
28
- },
29
- loadCalls: 0,
30
- unloadCalls: 0,
31
- loadImpl: async () => { },
32
- setStatus(next) {
33
- status = next;
34
- for (const listener of [...listeners])
35
- listener();
36
- },
37
- setProgress(next) {
38
- progress = next;
39
- for (const listener of [...listeners])
40
- listener();
41
- },
42
- async load() {
43
- backend.loadCalls += 1;
44
- await backend.loadImpl();
45
- },
46
- async unload() {
47
- backend.unloadCalls += 1;
48
- status = 'idle';
49
- for (const listener of [...listeners])
50
- listener();
51
- },
52
- async chat() {
53
- return { content: '' };
54
- },
55
- async *stream() {
56
- yield '';
57
- },
58
- subscribe(listener) {
59
- listeners.add(listener);
60
- return () => {
61
- listeners.delete(listener);
62
- };
63
- },
64
- };
65
- return backend;
66
- }
67
- describe('ModelStatusControl', () => {
68
- it('offers a load action when the model is not loaded', async () => {
69
- const backend = makeBackend({ status: 'idle' });
70
- render(ModelStatusControl, { props: { backend } });
71
- expect(screen.getByRole('status')).toHaveTextContent('Not loaded');
72
- await userEvent.click(screen.getByRole('button', { name: 'Load model' }));
73
- expect(backend.loadCalls).toBe(1);
74
- });
75
- it('offers a release action once the model is ready', async () => {
76
- const backend = makeBackend({ status: 'ready' });
77
- render(ModelStatusControl, { props: { backend } });
78
- expect(screen.getByRole('status')).toHaveTextContent('Ready');
79
- await userEvent.click(screen.getByRole('button', { name: 'Unload' }));
80
- expect(backend.unloadCalls).toBe(1);
81
- });
82
- it('hides the release action when the host opts out', () => {
83
- const backend = makeBackend({ status: 'ready' });
84
- render(ModelStatusControl, {
85
- props: { backend, allowUnload: false },
86
- });
87
- expect(screen.queryByRole('button', { name: 'Unload' })).toBeNull();
88
- });
89
- it('never offers a load action on a device that cannot run the model', () => {
90
- const backend = makeBackend({ status: 'unavailable' });
91
- render(ModelStatusControl, { props: { backend } });
92
- expect(screen.getByRole('status')).toHaveTextContent('Not available on this device');
93
- // The point of the state: no affordance that cannot succeed.
94
- expect(screen.queryByRole('button')).toBeNull();
95
- expect(screen.getByText(/will use the server route/)).toBeInTheDocument();
96
- });
97
- it('offers no action for a backend that cannot load or unload', () => {
98
- // A route-kind backend defines neither method and always reports `ready`;
99
- // offering an Unload that silently does nothing is the same defect as
100
- // offering a Load on an unavailable device.
101
- const backend = makeBackend({ status: 'ready' });
102
- // "A backend with no unload" is not hypothetical: it is the route backend.
103
- delete backend.load;
104
- delete backend.unload;
105
- render(ModelStatusControl, { props: { backend } });
106
- expect(screen.getByRole('status')).toHaveTextContent('Ready');
107
- expect(screen.queryByRole('button')).toBeNull();
108
- });
109
- it('offers no load action for an idle backend without load', () => {
110
- const backend = makeBackend({ status: 'idle' });
111
- delete backend.load;
112
- render(ModelStatusControl, { props: { backend } });
113
- expect(screen.getByRole('status')).toHaveTextContent('Not loaded');
114
- expect(screen.queryByRole('button')).toBeNull();
115
- });
116
- it('renders download progress while loading', () => {
117
- const backend = makeBackend({ status: 'loading' });
118
- backend.setProgress({
119
- state: 'downloading',
120
- bytesLoaded: 250_000,
121
- bytesTotal: 500_000,
122
- percent: 50,
123
- });
124
- render(ModelStatusControl, { props: { backend } });
125
- expect(screen.getByRole('status')).toHaveTextContent('Loading');
126
- expect(screen.getByText('Downloading model')).toBeInTheDocument();
127
- expect(screen.getByText('50%')).toBeInTheDocument();
128
- });
129
- it('offers a retry after a failed load', async () => {
130
- const backend = makeBackend({ status: 'error' });
131
- render(ModelStatusControl, { props: { backend } });
132
- expect(screen.getByRole('status')).toHaveTextContent('Load failed');
133
- await userEvent.click(screen.getByRole('button', { name: 'Retry' }));
134
- expect(backend.loadCalls).toBe(1);
135
- });
136
- it('surfaces a rejected load inline and to the host', async () => {
137
- const backend = makeBackend({ status: 'idle' });
138
- backend.loadImpl = async () => {
139
- throw new Error('out of memory');
140
- };
141
- const onerror = vi.fn();
142
- render(ModelStatusControl, { props: { backend, onerror } });
143
- await userEvent.click(screen.getByRole('button', { name: 'Load model' }));
144
- await tick();
145
- expect(await screen.findByRole('alert')).toHaveTextContent('out of memory');
146
- expect(onerror).toHaveBeenCalledWith(expect.any(Error));
147
- });
148
- it('follows a backend status change without a host re-render', async () => {
149
- const backend = makeBackend({ status: 'idle' });
150
- render(ModelStatusControl, { props: { backend } });
151
- expect(screen.getByRole('status')).toHaveTextContent('Not loaded');
152
- backend.setStatus('ready');
153
- await tick();
154
- expect(screen.getByRole('status')).toHaveTextContent('Ready');
155
- });
156
- it('has no accessibility violations in any state', async () => {
157
- for (const status of [
158
- 'unavailable',
159
- 'idle',
160
- 'loading',
161
- 'ready',
162
- 'error',
163
- ]) {
164
- const backend = makeBackend({ status });
165
- const { container, unmount } = render(ModelStatusControl, {
166
- props: { backend },
167
- });
168
- await expectNoA11yViolations(container);
169
- unmount();
170
- }
171
- });
172
- });