@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,234 +0,0 @@
1
- import { registerWebMcpBespokeTool as registerBespokeDirect, reserveWebMcpToolNames, WebMcpToolNameCollisionError, webMcpToolNameOwner, } from '@happyvertical/smrt-web';
2
- import { render } from '@testing-library/svelte';
3
- import { tick } from 'svelte';
4
- import { afterEach, describe, expect, it, vi } from 'vitest';
5
- // Wrap the registrar in a spy so a test can observe *which* policy each
6
- // `useWebMcpTool` effect run handed it, including runs the policy excludes
7
- // before they ever reach document.modelContext.registerTool (#2599).
8
- const registerBespokeSpy = vi.hoisted(() => vi.fn());
9
- vi.mock('@happyvertical/smrt-web', async (importOriginal) => {
10
- const actual = await importOriginal();
11
- registerBespokeSpy.mockImplementation(actual.registerWebMcpBespokeTool);
12
- return { ...actual, registerWebMcpBespokeTool: registerBespokeSpy };
13
- });
14
- import EffectsReactivity from './webmcp-effects-reactivity.fixture.svelte';
15
- import Harness from './webmcp-harness.svelte';
16
- import HarnessReactiveSameName from './webmcp-harness-reactive-samename.svelte';
17
- import HarnessUnannotated from './webmcp-harness-unannotated.svelte';
18
- /**
19
- * Mimics a host that rejects a duplicate tool name while it still considers
20
- * an earlier registration of that name live, and only forgets that name one
21
- * microtask after the earlier registration's abort signal fires — modeling
22
- * a host that does not process deregistration perfectly synchronously with
23
- * `AbortController.abort()`.
24
- */
25
- function installCollisionAwareModelContext() {
26
- const registered = [];
27
- const liveNames = new Set();
28
- document.modelContext = {
29
- async registerTool(tool, options) {
30
- if (liveNames.has(tool.name)) {
31
- throw new Error(`host collision: ${tool.name}`);
32
- }
33
- liveNames.add(tool.name);
34
- registered.push({ name: tool.name, signal: options?.signal });
35
- options?.signal?.addEventListener('abort', () => {
36
- void Promise.resolve().then(() => {
37
- liveNames.delete(tool.name);
38
- });
39
- });
40
- },
41
- };
42
- return { registered, liveNames };
43
- }
44
- function installModelContext() {
45
- const registered = [];
46
- document.modelContext = {
47
- async registerTool(tool, options) {
48
- registered.push({ name: tool.name, signal: options?.signal });
49
- },
50
- };
51
- return registered;
52
- }
53
- afterEach(() => {
54
- delete document.modelContext;
55
- registerBespokeSpy.mockClear();
56
- });
57
- describe('useWebMcpTool', () => {
58
- it('registers on mount, aborts on spec changes, and aborts on unmount', async () => {
59
- const registered = installModelContext();
60
- const view = render(Harness, { props: { version: 1 } });
61
- // Registration now routes through a dynamically imported registrar
62
- // (#2586), so it lands one or more microtasks after mount.
63
- await vi.waitFor(() => expect(registered).toHaveLength(1));
64
- expect(registered[0].name).toBe('harness_tool_1');
65
- expect(registered[0].signal?.aborted).toBe(false);
66
- await view.rerender({ version: 2 });
67
- await vi.waitFor(() => expect(registered).toHaveLength(2));
68
- expect(registered[0].signal?.aborted).toBe(true);
69
- expect(registered[1].name).toBe('harness_tool_2');
70
- view.unmount();
71
- expect(registered[1].signal?.aborted).toBe(true);
72
- });
73
- it('observes asynchronous host rejection and aborts the failed registration', async () => {
74
- let rejectRegistration;
75
- let signal;
76
- document.modelContext = {
77
- registerTool(_tool, options) {
78
- signal = options?.signal;
79
- return new Promise((_resolve, reject) => {
80
- rejectRegistration = reject;
81
- });
82
- },
83
- };
84
- const view = render(Harness);
85
- await vi.waitFor(() => expect(signal).toBeDefined());
86
- expect(signal?.aborted).toBe(false);
87
- rejectRegistration?.(new Error('host collision'));
88
- await vi.waitFor(() => expect(signal?.aborted).toBe(true));
89
- view.unmount();
90
- });
91
- it('is a no-op when WebMCP is unavailable', async () => {
92
- const view = render(Harness);
93
- await tick();
94
- expect(view.container).toHaveTextContent('1');
95
- view.unmount();
96
- });
97
- it('excludes an undeclared tool under the default read-only exposure policy', async () => {
98
- const registered = installModelContext();
99
- const view = render(HarnessUnannotated);
100
- // No Provider ancestor: the hook falls back to the registrar's default
101
- // read-only policy. An undeclared spec classifies destructive (#2586)
102
- // and must never reach document.modelContext.registerTool.
103
- await tick();
104
- await tick();
105
- await tick();
106
- expect(registered).toHaveLength(0);
107
- view.unmount();
108
- expect(registered).toHaveLength(0);
109
- });
110
- it('disposes a registered destructive bespoke tool when a Provider policy tightens from destructive to read (#2586 F2)', async () => {
111
- const registered = installModelContext();
112
- const view = render(EffectsReactivity, {
113
- props: { effects: ['destructive'] },
114
- });
115
- await vi.waitFor(() => expect(registered.map((tool) => tool.name)).toContain('reactivity_destructive_tool'));
116
- expect(registered).toHaveLength(1);
117
- const first = registered[0];
118
- expect(first.signal?.aborted).toBe(false);
119
- // `bespokeContext.effects` is read synchronously at the top of the
120
- // `$effect` body (the F2 fix), so this Provider policy change is
121
- // tracked as a dependency and re-runs the effect: the previously
122
- // registered destructive tool is torn down, and re-registration under
123
- // the new read-only policy is excluded before it ever reaches
124
- // document.modelContext.registerTool again.
125
- await view.rerender({ effects: ['read'] });
126
- await vi.waitFor(() => expect(first.signal?.aborted).toBe(true));
127
- expect(registered).toHaveLength(1);
128
- view.unmount();
129
- });
130
- it('serializes same-name re-registration across rapid reactive reruns without a host collision', async () => {
131
- const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
132
- const { registered, liveNames } = installCollisionAwareModelContext();
133
- const view = render(HarnessReactiveSameName, { props: { version: 1 } });
134
- await vi.waitFor(() => expect(registered.length).toBeGreaterThan(0));
135
- // Three reactive reruns in quick succession, all under the SAME tool
136
- // name. Without serializing against the previous run's registration
137
- // settling, a new run's registration attempt can reach the host before
138
- // it has processed the previous run's abort, producing a host
139
- // collision — this must never happen.
140
- await view.rerender({ version: 2 });
141
- await view.rerender({ version: 3 });
142
- await view.rerender({ version: 4 });
143
- await vi.waitFor(() => {
144
- const live = registered.filter((tool) => !tool.signal?.aborted);
145
- expect(live).toHaveLength(1);
146
- expect(live[0]?.name).toBe('harness_reactive_tool');
147
- });
148
- expect(liveNames.has('harness_reactive_tool')).toBe(true);
149
- expect(warnSpy).not.toHaveBeenCalled();
150
- view.unmount();
151
- warnSpy.mockRestore();
152
- });
153
- it('reports a tool-name collision through its warn path, not as an unhandled rejection (#2613)', async () => {
154
- const registered = installModelContext();
155
- // Stand in for whatever already holds the name — a generated model tool,
156
- // a fixed `smrt_ui_*` tool under a custom prefix, or another mounted
157
- // component. `registerWebMcpBespokeTool` now throws SYNCHRONOUSLY here,
158
- // inside this hook's fire-and-forget `register()`, so without the
159
- // narrowed catch the page would see a global unhandled rejection instead
160
- // of a diagnostic naming the tool and its owner.
161
- const held = reserveWebMcpToolNames(['harness_tool_1'], 'generated');
162
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
163
- const unhandled = vi.fn();
164
- window.addEventListener('unhandledrejection', unhandled);
165
- const view = render(Harness, { props: { version: 1 } });
166
- await vi.waitFor(() => expect(warn).toHaveBeenCalled());
167
- // Two macrotask turns is enough for an unhandled rejection to surface.
168
- await new Promise((resolve) => setTimeout(resolve, 0));
169
- await new Promise((resolve) => setTimeout(resolve, 0));
170
- expect(unhandled).not.toHaveBeenCalled();
171
- expect(registered).toHaveLength(0);
172
- const [message, name, error] = warn.mock.calls[0];
173
- expect(message).toContain('bespoke WebMCP tool registration failed');
174
- expect(name).toBe('harness_tool_1');
175
- expect(error).toBeInstanceOf(WebMcpToolNameCollisionError);
176
- expect(error.owner).toBe('generated');
177
- // The losing registrant strands nothing: the holder keeps the name, and
178
- // unmounting the component leaves it exactly as it was.
179
- expect(webMcpToolNameOwner('harness_tool_1')).toBe('generated');
180
- view.unmount();
181
- expect(webMcpToolNameOwner('harness_tool_1')).toBe('generated');
182
- held.release();
183
- expect(webMcpToolNameOwner('harness_tool_1')).toBeUndefined();
184
- window.removeEventListener('unhandledrejection', unhandled);
185
- warn.mockRestore();
186
- });
187
- it('still propagates a non-collision synchronous registrar throw', async () => {
188
- installModelContext();
189
- // The narrowed catch above must not swallow an authoring error. An
190
- // invalid `effects` policy is the synchronous throw that already existed.
191
- expect(() => registerBespokeDirect({
192
- name: 'harness_tool_1',
193
- description: 'x',
194
- inputSchema: { type: 'object' },
195
- annotations: { readOnlyHint: true },
196
- execute: () => 'ok',
197
- }, { effects: ['nonsense'] })).toThrow(/Invalid WebMCP effect/);
198
- expect(webMcpToolNameOwner('harness_tool_1')).toBeUndefined();
199
- });
200
- it('registers a previously-excluded bespoke tool when a Provider policy loosens to permit it (#2599)', async () => {
201
- const registered = installModelContext();
202
- const view = render(EffectsReactivity, {
203
- props: { effects: ['read'] },
204
- });
205
- // The bespoke tool's static factory declares `destructiveHint: true` and
206
- // has no rune dependencies of its own, so under a read-only Provider
207
- // policy the registrar classifies it destructive and excludes it before
208
- // it ever reaches document.modelContext.registerTool. Wait for that
209
- // first evaluation to actually happen under the read-only policy — the
210
- // registrar is reached through a dynamic import, so without this the
211
- // policy change below could race ahead of the first evaluation and the
212
- // test would pass even if the effect never re-ran.
213
- await vi.waitFor(() => expect(registerBespokeSpy).toHaveBeenCalledTimes(1));
214
- expect(registerBespokeSpy.mock.calls[0][1]).toEqual({
215
- effects: ['read'],
216
- });
217
- expect(registered).toHaveLength(0);
218
- // `bespokeContext.effects` is read synchronously at the top of the
219
- // `$effect` body, so this Provider policy change is tracked as a
220
- // dependency and re-runs the effect even though the component's own
221
- // factory never changed: the registrar is consulted again under the
222
- // loosened policy and the tool newly registers.
223
- await view.rerender({ effects: ['destructive'] });
224
- await vi.waitFor(() => expect(registerBespokeSpy).toHaveBeenCalledTimes(2));
225
- expect(registerBespokeSpy.mock.calls[1][1]).toEqual({
226
- effects: ['destructive'],
227
- });
228
- await vi.waitFor(() => expect(registered.map((tool) => tool.name)).toContain('reactivity_destructive_tool'));
229
- expect(registered).toHaveLength(1);
230
- expect(registered[0].signal?.aborted).toBe(false);
231
- view.unmount();
232
- expect(registered[0].signal?.aborted).toBe(true);
233
- });
234
- });