@happyvertical/smrt-svelte 0.53.1 → 0.53.3

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,240 +0,0 @@
1
- /**
2
- * Regression tests for the browser-AI warm-cache lifecycle (T2 #1403):
3
- *
4
- * - R1 (listener leak): warm-cached adapters survive Provider remounts. Each
5
- * manager that subscribes must capture + later remove its listeners on
6
- * dispose(), and a shared adapter must never accumulate more than one live
7
- * listener set across managers.
8
- * - R2 (state lies): dispose() must not leave a disposed adapter cached as
9
- * 'ready'; unloadLLM() must downgrade the warm-cache entry so the next init
10
- * re-runs (reports progress) instead of cache-hitting a model-less adapter.
11
- * - R3 (scheduler thrash): setAIConfig() must no-op on a deep-equal config
12
- * (inline `ai={{…}}` literal => new identity every render), and concurrent
13
- * executePreload() passes must be guarded.
14
- * - R7 (nit): the empty-config early-return must reset loaded/failed too.
15
- */
16
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
17
- // --- Fakes -----------------------------------------------------------------
18
- /**
19
- * A fake STT/TTS adapter whose event-subscription methods return real
20
- * unsubscribe handles backed by Sets — so a test can read the live listener
21
- * count and prove subscriptions are torn down (R1).
22
- */
23
- function makeFakeSTT(type = 'whisper-cpp') {
24
- const sets = {
25
- result: new Set(),
26
- start: new Set(),
27
- end: new Set(),
28
- error: new Set(),
29
- };
30
- const sub = (set, cb) => {
31
- set.add(cb);
32
- return () => {
33
- set.delete(cb);
34
- };
35
- };
36
- return {
37
- type,
38
- dispose: vi.fn(async () => { }),
39
- ensureInitialized: vi.fn(async () => { }),
40
- start: vi.fn(async () => { }),
41
- stop: vi.fn(async () => { }),
42
- abort: vi.fn(),
43
- isListening: () => false,
44
- onResult: (cb) => sub(sets.result, cb),
45
- onStart: (cb) => sub(sets.start, cb),
46
- onEnd: (cb) => sub(sets.end, cb),
47
- onError: (cb) => sub(sets.error, cb),
48
- /** total live listeners across all event sets */
49
- listenerCount: () => sets.result.size + sets.start.size + sets.end.size + sets.error.size,
50
- };
51
- }
52
- function makeFakeTTS(type = 'browser-synthesis') {
53
- const sets = {
54
- start: new Set(),
55
- end: new Set(),
56
- error: new Set(),
57
- };
58
- const sub = (set, cb) => {
59
- set.add(cb);
60
- return () => {
61
- set.delete(cb);
62
- };
63
- };
64
- return {
65
- type,
66
- dispose: vi.fn(async () => { }),
67
- ensureInitialized: vi.fn(async () => { }),
68
- speak: vi.fn(async () => { }),
69
- stop: vi.fn(),
70
- pause: vi.fn(),
71
- resume: vi.fn(),
72
- getVoices: () => [],
73
- onStart: (cb) => sub(sets.start, cb),
74
- onEnd: (cb) => sub(sets.end, cb),
75
- onError: (cb) => sub(sets.error, cb),
76
- listenerCount: () => sets.start.size + sets.end.size + sets.error.size,
77
- };
78
- }
79
- function makeFakeLLM(type = 'webllm', model = 'tiny-model') {
80
- return {
81
- type,
82
- currentModel: model,
83
- dispose: vi.fn(async () => { }),
84
- ensureInitialized: vi.fn(async () => { }),
85
- unloadModel: vi.fn(async () => { }),
86
- message: vi.fn(async () => 'ok'),
87
- };
88
- }
89
- // --- Module mocks ----------------------------------------------------------
90
- // The manager imports the AI factories + capability helpers from the browser-ai
91
- // barrel. Mock only those; keep everything else (types) real via importOriginal.
92
- const fakeSTT = makeFakeSTT();
93
- const fakeTTS = makeFakeTTS();
94
- const fakeLLM = makeFakeLLM();
95
- vi.mock('../../browser-ai/index.js', async (importOriginal) => {
96
- const actual = await importOriginal();
97
- return {
98
- ...actual,
99
- detectCapabilities: () => ({}),
100
- canEnableSmrtMode: () => false,
101
- getSTT: vi.fn(async () => fakeSTT),
102
- getTTS: vi.fn(async () => fakeTTS),
103
- getLLM: vi.fn(async () => fakeLLM),
104
- };
105
- });
106
- import { createAppState, } from '../app-state.svelte.js';
107
- import { clearAllCaches, getCachedLLM, getCachedSTT } from '../warm-clients.js';
108
- beforeEach(async () => {
109
- await clearAllCaches();
110
- });
111
- afterEach(async () => {
112
- await clearAllCaches();
113
- vi.clearAllMocks();
114
- });
115
- describe('R1: warm-adapter listener lifecycle', () => {
116
- it("removes a manager's listeners on dispose()", async () => {
117
- const m = createAppState();
118
- await m.initializeSTT({ type: 'whisper-cpp' });
119
- expect(fakeSTT.listenerCount()).toBeGreaterThan(0);
120
- await m.dispose();
121
- expect(fakeSTT.listenerCount()).toBe(0);
122
- });
123
- it('does not accumulate listeners across remounts of the same cached adapter', async () => {
124
- // Manager 1 subscribes then disposes.
125
- const m1 = createAppState();
126
- await m1.initializeSTT({ type: 'whisper-cpp' });
127
- const afterFirst = fakeSTT.listenerCount();
128
- await m1.dispose();
129
- // Manager 2 cache-hits the SAME warm adapter, subscribes, disposes.
130
- const m2 = createAppState();
131
- await m2.initializeSTT({ type: 'whisper-cpp' });
132
- // Exactly one manager's worth of listeners while live — not doubled.
133
- expect(fakeSTT.listenerCount()).toBe(afterFirst);
134
- await m2.dispose();
135
- expect(fakeSTT.listenerCount()).toBe(0);
136
- });
137
- it('keeps at most one live listener set when two managers coexist', async () => {
138
- const m1 = createAppState();
139
- await m1.initializeSTT({ type: 'whisper-cpp' });
140
- const single = fakeSTT.listenerCount();
141
- // A second live manager taking over the shared adapter must evict the
142
- // first's listeners rather than stack a second set.
143
- const m2 = createAppState();
144
- await m2.initializeSTT({ type: 'whisper-cpp' });
145
- expect(fakeSTT.listenerCount()).toBe(single);
146
- await m1.dispose();
147
- await m2.dispose();
148
- expect(fakeSTT.listenerCount()).toBe(0);
149
- });
150
- it('removes TTS listeners on dispose()', async () => {
151
- const m = createAppState();
152
- await m.initializeTTS({ type: 'browser-synthesis' });
153
- expect(fakeTTS.listenerCount()).toBeGreaterThan(0);
154
- await m.dispose();
155
- expect(fakeTTS.listenerCount()).toBe(0);
156
- });
157
- it('subscribing the same adapter twice on one manager is idempotent', async () => {
158
- const m = createAppState();
159
- await m.initializeSTT({ type: 'whisper-cpp' });
160
- const once = fakeSTT.listenerCount();
161
- // Second init cache-hits and re-enters subscribeToSTTEvents.
162
- await m.initializeSTT({ type: 'whisper-cpp' });
163
- expect(fakeSTT.listenerCount()).toBe(once);
164
- await m.dispose();
165
- });
166
- });
167
- describe('R2: dispose()/unloadLLM() do not leave the cache lying', () => {
168
- it('dispose() leaves the warm STT adapter intact (not disposed) and cached ready', async () => {
169
- const m = createAppState();
170
- await m.initializeSTT({ type: 'whisper-cpp' });
171
- await m.dispose();
172
- // Cached adapter survives navigation and was NOT disposed — so a later
173
- // init won't restore a dead engine reported as 'ready'.
174
- const cached = getCachedSTT('whisper-cpp');
175
- expect(cached?.initState).toBe('ready');
176
- expect(cached?.adapter).toBe(fakeSTT);
177
- expect(fakeSTT.dispose).not.toHaveBeenCalled();
178
- });
179
- it('unloadLLM() downgrades the warm-cache entry to uninitialized', async () => {
180
- const m = createAppState();
181
- await m.initializeLLM('tiny-model', { type: 'webllm' });
182
- expect(getCachedLLM('webllm', 'tiny-model')?.initState).toBe('ready');
183
- await m.unloadLLM();
184
- // Next initializeLLM must re-run (report progress) rather than cache-hit a
185
- // model-less adapter reported as 'ready'.
186
- expect(getCachedLLM('webllm', 'tiny-model')?.initState).toBe('uninitialized');
187
- await m.dispose();
188
- });
189
- });
190
- describe('R3: setAIConfig scheduler thrash + preload re-entrancy', () => {
191
- it('no-ops on a deep-equal config of a different identity', async () => {
192
- const m = createAppState();
193
- const spy = vi.spyOn(m, 'schedulePreload');
194
- m.setAIConfig({ preload: 'none', stt: { type: 'whisper-cpp' } });
195
- const callsAfterFirst = spy.mock.calls.length;
196
- expect(callsAfterFirst).toBeGreaterThan(0);
197
- // Same shape, brand-new object literal (what an inline `ai={{…}}` produces).
198
- m.setAIConfig({ preload: 'none', stt: { type: 'whisper-cpp' } });
199
- expect(spy.mock.calls.length).toBe(callsAfterFirst); // no re-schedule
200
- });
201
- it('re-schedules when the config actually changes', async () => {
202
- const m = createAppState();
203
- const spy = vi.spyOn(m, 'schedulePreload');
204
- m.setAIConfig({ preload: 'none', stt: { type: 'whisper-cpp' } });
205
- const before = spy.mock.calls.length;
206
- m.setAIConfig({ preload: 'none', stt: { type: 'whisper-wasm' } });
207
- expect(spy.mock.calls.length).toBe(before + 1);
208
- });
209
- it('guards executePreload against concurrent passes', async () => {
210
- const m = createAppState();
211
- m.setAIConfig({
212
- preload: 'none',
213
- stt: { type: 'whisper-cpp' },
214
- });
215
- const exec = m.executePreload.bind(m);
216
- // Two overlapping passes: the second must early-return (guarded), so the
217
- // STT factory is invoked once, not twice.
218
- const { getSTT } = (await import('../../browser-ai/index.js'));
219
- getSTT.mockClear();
220
- await Promise.all([exec(), exec()]);
221
- expect(getSTT).toHaveBeenCalledTimes(1);
222
- await m.dispose();
223
- });
224
- });
225
- describe('R7: empty-config preload early-return resets loaded/failed', () => {
226
- it('clears stale loaded/failed entries', async () => {
227
- const m = createAppState();
228
- // Seed stale entries through a normal pass, then re-run with empty config.
229
- m.setAIConfig({ preload: 'none', stt: { type: 'whisper-cpp' } });
230
- await m.executePreload();
231
- expect(m.aiLoading.loaded.length).toBeGreaterThan(0);
232
- // Now an empty config — the early-return path must reset loaded/failed.
233
- m.setAIConfig({ preload: 'none' });
234
- await m.executePreload();
235
- expect(m.aiLoading.phase).toBe('idle');
236
- expect(m.aiLoading.loaded).toEqual([]);
237
- expect(m.aiLoading.failed).toEqual([]);
238
- await m.dispose();
239
- });
240
- });
@@ -1,40 +0,0 @@
1
- /**
2
- * Unit tests for the warm client cache (coverage uplift, S6 gate). Module-level
3
- * Map caches for STT/TTS/LLM adapters — get/set/update/remove + stats.
4
- */
5
- import { describe, expect, it, vi } from 'vitest';
6
- import { getCachedLLM, getCachedSTT, getCachedTTS, getCacheStats, removeCachedLLM, removeCachedSTT, removeCachedTTS, setCachedLLM, setCachedSTT, setCachedTTS, updateLLMCacheState, updateSTTCacheState, updateTTSCacheState, } from '../warm-clients';
7
- const fakeAdapter = () => ({ dispose: vi.fn() });
8
- describe('warm client cache', () => {
9
- it('STT: set / get / update / remove', () => {
10
- const adapter = fakeAdapter();
11
- setCachedSTT('whisper-wasm', adapter);
12
- expect(getCachedSTT('whisper-wasm')?.adapter).toBe(adapter);
13
- updateSTTCacheState('whisper-wasm', { downloadProgress: 50 });
14
- expect(getCachedSTT('whisper-wasm')?.downloadProgress).toBe(50);
15
- removeCachedSTT('whisper-wasm');
16
- expect(getCachedSTT('whisper-wasm')).toBeUndefined();
17
- });
18
- it('TTS: set / get / update / remove', () => {
19
- const adapter = fakeAdapter();
20
- setCachedTTS('browser-synthesis', adapter);
21
- expect(getCachedTTS('browser-synthesis')?.adapter).toBe(adapter);
22
- updateTTSCacheState('browser-synthesis', { initState: 'ready' });
23
- removeCachedTTS('browser-synthesis');
24
- expect(getCachedTTS('browser-synthesis')).toBeUndefined();
25
- });
26
- it('LLM: set / get / update / remove', () => {
27
- const adapter = fakeAdapter();
28
- setCachedLLM('webllm', adapter);
29
- expect(getCachedLLM('webllm')?.adapter).toBe(adapter);
30
- updateLLMCacheState('webllm', { downloadProgress: 10 });
31
- removeCachedLLM('webllm');
32
- expect(getCachedLLM('webllm')).toBeUndefined();
33
- });
34
- it('getCacheStats reports cache contents', () => {
35
- setCachedSTT('whisper-cpp', fakeAdapter());
36
- const stats = getCacheStats();
37
- expect(stats).toBeDefined();
38
- removeCachedSTT('whisper-cpp');
39
- });
40
- });
@@ -1,32 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * Integration harness — invokes activityFeed() inside a component-init scope so
4
- * the `$effect` it (and the underlying `liveCollection`) installs wires up to a
5
- * real component lifecycle, then hands the feed handle back to the test.
6
- */
7
- import type { SmrtWebCollection } from '@happyvertical/smrt-web';
8
- import type { ShellState } from '../../components/workspace/index.js';
9
- import {
10
- type ActivityFeedHandle,
11
- type ActivityFeedMap,
12
- activityFeed,
13
- } from '../activity-feed.svelte.js';
14
-
15
- interface Props {
16
- collection: SmrtWebCollection<Record<string, unknown>>;
17
- shell: ShellState;
18
- map: ActivityFeedMap<Record<string, unknown>>;
19
- onReady: (handle: ActivityFeedHandle) => void;
20
- }
21
-
22
- const props: Props = $props();
23
- // This harness intentionally snapshots its props during setup.
24
- // svelte-ignore state_referenced_locally
25
- const handle = activityFeed({
26
- collection: props.collection,
27
- shell: props.shell,
28
- map: props.map,
29
- });
30
- // svelte-ignore state_referenced_locally
31
- props.onReady(handle);
32
- </script>
@@ -1,18 +0,0 @@
1
- /**
2
- * Integration harness — invokes activityFeed() inside a component-init scope so
3
- * the `$effect` it (and the underlying `liveCollection`) installs wires up to a
4
- * real component lifecycle, then hands the feed handle back to the test.
5
- */
6
- import type { SmrtWebCollection } from '@happyvertical/smrt-web';
7
- import type { ShellState } from '../../components/workspace/index.js';
8
- import { type ActivityFeedHandle, type ActivityFeedMap } from '../activity-feed.svelte.js';
9
- interface Props {
10
- collection: SmrtWebCollection<Record<string, unknown>>;
11
- shell: ShellState;
12
- map: ActivityFeedMap<Record<string, unknown>>;
13
- onReady: (handle: ActivityFeedHandle) => void;
14
- }
15
- declare const ActivityFeedHarness: import("svelte").Component<Props, {}, "">;
16
- type ActivityFeedHarness = ReturnType<typeof ActivityFeedHarness>;
17
- export default ActivityFeedHarness;
18
- //# sourceMappingURL=activity-feed-harness.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"activity-feed-harness.svelte.d.ts","sourceRoot":"","sources":["../../../src/web/__tests__/activity-feed-harness.svelte.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EAErB,MAAM,4BAA4B,CAAC;AAGpC,UAAU,KAAK;IACb,UAAU,EAAE,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C;AAsBD,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
@@ -1,190 +0,0 @@
1
- /**
2
- * Integration test for the AdminShell activity feed adapter (#1779) end to end.
3
- *
4
- * Unlike the reconciler unit tests (which feed plain arrays), this exercises the
5
- * FULL stack — `activityFeed` → `liveCollection` → the real `@happyvertical/smrt-web`
6
- * collection with its client-data engine — through a mounted harness, so the
7
- * `$effect` that drives reconciliation has a genuine component-init scope. Only
8
- * the network boundary is mocked (the generated REST fetchers passed to
9
- * `createSmrtCollection`); the engine, live view, runes reactivity, and the real
10
- * `ShellState` are all live. This proves the reactive wiring drives the shell:
11
- * a loaded row and an optimistic insert both surface as shell activities.
12
- */
13
- import { createSmrtCollection, } from '@happyvertical/smrt-web';
14
- import { flushSync, mount, unmount } from 'svelte';
15
- import { afterEach, describe, expect, it } from 'vitest';
16
- import { createShellState } from '../../components/workspace/admin-shell/state.svelte.js';
17
- import Harness from './activity-feed-harness.svelte';
18
- function jobDefinition(name) {
19
- return {
20
- name,
21
- objectRef: '@test/smrt-svelte:RenderJob',
22
- className: 'RenderJob',
23
- endpoint: `/${name}`,
24
- idField: 'id',
25
- actions: ['create', 'get', 'list'],
26
- fields: {
27
- title: { type: 'text', required: true },
28
- state: { type: 'text' },
29
- },
30
- };
31
- }
32
- /** Scripted stand-in for the generated REST fetchers (see live-collection test). */
33
- function makeScriptedFetchers(initialRows) {
34
- const serverRows = [...initialRows];
35
- const fetchers = {
36
- list: async () => serverRows.map((row) => ({ ...row })),
37
- create: async (data) => {
38
- const created = { ...data, id: `server-${serverRows.length + 1}` };
39
- serverRows.push(created);
40
- return { ...created };
41
- },
42
- };
43
- return { fetchers };
44
- }
45
- const mapJob = (row) => ({
46
- kind: 'render-job',
47
- scope: 'focus',
48
- label: row.title,
49
- status: row.state ?? 'running',
50
- });
51
- function mountFeed(collection, shell) {
52
- const target = document.createElement('div');
53
- document.body.appendChild(target);
54
- let exposed = undefined;
55
- const component = mount(Harness, {
56
- target,
57
- props: {
58
- // The harness is typed against the base object shape; JobData is a
59
- // structural subtype, so this cross-cast is purely nominal.
60
- collection: collection,
61
- shell,
62
- map: mapJob,
63
- onReady: (handle) => {
64
- exposed = handle;
65
- },
66
- },
67
- });
68
- return {
69
- handle: exposed,
70
- teardown: () => {
71
- unmount(component);
72
- target.remove();
73
- },
74
- };
75
- }
76
- describe('activityFeed (integration)', () => {
77
- const cleanup = [];
78
- afterEach(() => {
79
- for (const fn of cleanup.splice(0))
80
- fn();
81
- });
82
- it('reconciles loaded collection rows into shell activities', async () => {
83
- const scripted = makeScriptedFetchers([
84
- { id: 'job-1', title: 'Render intro', state: 'running' },
85
- { id: 'job-2', title: 'Render outro', state: 'queued' },
86
- ]);
87
- const collection = createSmrtCollection(jobDefinition('feed-load'), {
88
- fetchers: scripted.fetchers,
89
- staleTimeMs: 60_000,
90
- });
91
- const shell = createShellState();
92
- const mounted = mountFeed(collection, shell);
93
- cleanup.push(mounted.teardown);
94
- await collection.preload();
95
- flushSync();
96
- const activities = shell.listActivities();
97
- expect(activities.map((a) => a.id).sort()).toEqual(['job-1', 'job-2']);
98
- expect(activities.every((a) => a.kind === 'render-job')).toBe(true);
99
- // Homed to the focus edge (right) per the map's scope.
100
- expect(shell.listActivities({ edge: 'right' })).toHaveLength(2);
101
- });
102
- it('surfaces an optimistic insert as a shell activity reactively', async () => {
103
- const scripted = makeScriptedFetchers([
104
- { id: 'job-1', title: 'Render intro', state: 'running' },
105
- ]);
106
- const collection = createSmrtCollection(jobDefinition('feed-insert'), {
107
- fetchers: scripted.fetchers,
108
- staleTimeMs: 60_000,
109
- });
110
- const shell = createShellState();
111
- const mounted = mountFeed(collection, shell);
112
- cleanup.push(mounted.teardown);
113
- await collection.preload();
114
- flushSync();
115
- expect(shell.listActivities()).toHaveLength(1);
116
- // An optimistic insert appears in the live view synchronously → the feed
117
- // reconciles it into the shell on the reactive tick.
118
- const tx = collection.insert({
119
- id: 'local-1',
120
- title: 'Render credits',
121
- state: 'running',
122
- });
123
- flushSync();
124
- expect(shell
125
- .listActivities()
126
- .map((a) => a.label)
127
- .sort()).toEqual(['Render credits', 'Render intro']);
128
- // Once persisted, the server-assigned row replaces the optimistic one; the
129
- // activity for the temp id is removed and the server row's activity remains.
130
- await tx.isPersisted.promise;
131
- flushSync();
132
- const labels = shell
133
- .listActivities()
134
- .map((a) => a.label)
135
- .sort();
136
- expect(labels).toEqual(['Render credits', 'Render intro']);
137
- // The optimistic-id activity is gone; the server id is present.
138
- const ids = shell.listActivities().map((a) => a.id);
139
- expect(ids).toContain('server-2');
140
- expect(ids).not.toContain('local-1');
141
- });
142
- it('dispose() retracts the feed activities from the shell', async () => {
143
- const scripted = makeScriptedFetchers([
144
- { id: 'job-1', title: 'Render intro', state: 'running' },
145
- ]);
146
- const collection = createSmrtCollection(jobDefinition('feed-dispose'), {
147
- fetchers: scripted.fetchers,
148
- staleTimeMs: 60_000,
149
- });
150
- const shell = createShellState();
151
- const mounted = mountFeed(collection, shell);
152
- cleanup.push(mounted.teardown);
153
- await collection.preload();
154
- flushSync();
155
- expect(shell.listActivities()).toHaveLength(1);
156
- mounted.handle.dispose();
157
- expect(shell.listActivities()).toHaveLength(0);
158
- expect(mounted.handle.isDisposed).toBe(true);
159
- });
160
- it('auto-retracts the feed activities when the host component unmounts', async () => {
161
- const scripted = makeScriptedFetchers([
162
- { id: 'job-1', title: 'Render intro', state: 'running' },
163
- { id: 'job-2', title: 'Render outro', state: 'queued' },
164
- ]);
165
- const collection = createSmrtCollection(jobDefinition('feed-unmount'), {
166
- fetchers: scripted.fetchers,
167
- staleTimeMs: 60_000,
168
- });
169
- const shell = createShellState();
170
- // An activity from another source must survive the feed's unmount.
171
- shell.upsertActivity({
172
- id: 'external-1',
173
- label: 'External',
174
- kind: 'other',
175
- scope: 'app',
176
- status: 'running',
177
- });
178
- const mounted = mountFeed(collection, shell);
179
- await collection.preload();
180
- flushSync();
181
- expect(shell.listActivities()).toHaveLength(3);
182
- // Unmount WITHOUT calling dispose() manually: the adapter's $effect teardown
183
- // must retract exactly its own activities, leaving the external one intact.
184
- mounted.teardown();
185
- flushSync();
186
- const remaining = shell.listActivities();
187
- expect(remaining).toHaveLength(1);
188
- expect(remaining[0].id).toBe('external-1');
189
- });
190
- });