@happyvertical/smrt-svelte 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. package/AGENTS.md +317 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +185 -0
  5. package/dist/Provider.svelte +204 -0
  6. package/dist/Provider.svelte.d.ts +73 -0
  7. package/dist/Provider.svelte.d.ts.map +1 -0
  8. package/dist/__tests__/app-state.test.js +156 -0
  9. package/dist/__tests__/warm-clients.test.js +186 -0
  10. package/dist/browser-ai/adapters/llm/factory.d.ts +38 -0
  11. package/dist/browser-ai/adapters/llm/factory.d.ts.map +1 -0
  12. package/dist/browser-ai/adapters/llm/factory.js +91 -0
  13. package/dist/browser-ai/adapters/llm/index.d.ts +7 -0
  14. package/dist/browser-ai/adapters/llm/index.d.ts.map +1 -0
  15. package/dist/browser-ai/adapters/llm/index.js +6 -0
  16. package/dist/browser-ai/adapters/llm/types.d.ts +182 -0
  17. package/dist/browser-ai/adapters/llm/types.d.ts.map +1 -0
  18. package/dist/browser-ai/adapters/llm/types.js +43 -0
  19. package/dist/browser-ai/adapters/llm/webllm.d.ts +33 -0
  20. package/dist/browser-ai/adapters/llm/webllm.d.ts.map +1 -0
  21. package/dist/browser-ai/adapters/llm/webllm.js +225 -0
  22. package/dist/browser-ai/adapters/stt/browser-speech.d.ts +31 -0
  23. package/dist/browser-ai/adapters/stt/browser-speech.d.ts.map +1 -0
  24. package/dist/browser-ai/adapters/stt/browser-speech.js +217 -0
  25. package/dist/browser-ai/adapters/stt/factory.d.ts +49 -0
  26. package/dist/browser-ai/adapters/stt/factory.d.ts.map +1 -0
  27. package/dist/browser-ai/adapters/stt/factory.js +110 -0
  28. package/dist/browser-ai/adapters/stt/index.d.ts +9 -0
  29. package/dist/browser-ai/adapters/stt/index.d.ts.map +1 -0
  30. package/dist/browser-ai/adapters/stt/index.js +8 -0
  31. package/dist/browser-ai/adapters/stt/types.d.ts +154 -0
  32. package/dist/browser-ai/adapters/stt/types.d.ts.map +1 -0
  33. package/dist/browser-ai/adapters/stt/types.js +4 -0
  34. package/dist/browser-ai/adapters/stt/whisper-cpp.d.ts +46 -0
  35. package/dist/browser-ai/adapters/stt/whisper-cpp.d.ts.map +1 -0
  36. package/dist/browser-ai/adapters/stt/whisper-cpp.js +348 -0
  37. package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts +51 -0
  38. package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts.map +1 -0
  39. package/dist/browser-ai/adapters/stt/whisper-wasm.js +380 -0
  40. package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts +42 -0
  41. package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts.map +1 -0
  42. package/dist/browser-ai/adapters/tts/browser-synthesis.js +235 -0
  43. package/dist/browser-ai/adapters/tts/factory.d.ts +53 -0
  44. package/dist/browser-ai/adapters/tts/factory.d.ts.map +1 -0
  45. package/dist/browser-ai/adapters/tts/factory.js +92 -0
  46. package/dist/browser-ai/adapters/tts/index.d.ts +7 -0
  47. package/dist/browser-ai/adapters/tts/index.d.ts.map +1 -0
  48. package/dist/browser-ai/adapters/tts/index.js +6 -0
  49. package/dist/browser-ai/adapters/tts/types.d.ts +140 -0
  50. package/dist/browser-ai/adapters/tts/types.d.ts.map +1 -0
  51. package/dist/browser-ai/adapters/tts/types.js +4 -0
  52. package/dist/browser-ai/capabilities/detector.d.ts +38 -0
  53. package/dist/browser-ai/capabilities/detector.d.ts.map +1 -0
  54. package/dist/browser-ai/capabilities/detector.js +211 -0
  55. package/dist/browser-ai/core/errors.d.ts +62 -0
  56. package/dist/browser-ai/core/errors.d.ts.map +1 -0
  57. package/dist/browser-ai/core/errors.js +92 -0
  58. package/dist/browser-ai/core/index.d.ts +6 -0
  59. package/dist/browser-ai/core/index.d.ts.map +1 -0
  60. package/dist/browser-ai/core/index.js +5 -0
  61. package/dist/browser-ai/core/types.d.ts +115 -0
  62. package/dist/browser-ai/core/types.d.ts.map +1 -0
  63. package/dist/browser-ai/core/types.js +34 -0
  64. package/dist/browser-ai/index.d.ts +12 -0
  65. package/dist/browser-ai/index.d.ts.map +1 -0
  66. package/dist/browser-ai/index.js +16 -0
  67. package/dist/browser-ai/svelte/components/AILoadingOverlay.svelte +77 -0
  68. package/dist/browser-ai/svelte/components/AILoadingOverlay.svelte.d.ts +16 -0
  69. package/dist/browser-ai/svelte/components/AILoadingOverlay.svelte.d.ts.map +1 -0
  70. package/dist/browser-ai/svelte/components/CapabilityGate.svelte +57 -0
  71. package/dist/browser-ai/svelte/components/CapabilityGate.svelte.d.ts +15 -0
  72. package/dist/browser-ai/svelte/components/CapabilityGate.svelte.d.ts.map +1 -0
  73. package/dist/browser-ai/svelte/components/DownloadProgress.svelte +141 -0
  74. package/dist/browser-ai/svelte/components/DownloadProgress.svelte.d.ts +15 -0
  75. package/dist/browser-ai/svelte/components/DownloadProgress.svelte.d.ts.map +1 -0
  76. package/dist/browser-ai/svelte/components/STTTest.svelte +379 -0
  77. package/dist/browser-ai/svelte/components/STTTest.svelte.d.ts +9 -0
  78. package/dist/browser-ai/svelte/components/STTTest.svelte.d.ts.map +1 -0
  79. package/dist/browser-ai/svelte/components/VoiceInput.svelte +200 -0
  80. package/dist/browser-ai/svelte/components/VoiceInput.svelte.d.ts +16 -0
  81. package/dist/browser-ai/svelte/components/VoiceInput.svelte.d.ts.map +1 -0
  82. package/dist/browser-ai/svelte/index.d.ts +15 -0
  83. package/dist/browser-ai/svelte/index.d.ts.map +1 -0
  84. package/dist/browser-ai/svelte/index.js +28 -0
  85. package/dist/browser-ai/ui.d.ts +16 -0
  86. package/dist/browser-ai/ui.d.ts.map +1 -0
  87. package/dist/browser-ai/ui.js +67 -0
  88. package/dist/components/admin/AgentAdminPanel.svelte +111 -0
  89. package/dist/components/admin/AgentAdminPanel.svelte.d.ts +25 -0
  90. package/dist/components/admin/AgentAdminPanel.svelte.d.ts.map +1 -0
  91. package/dist/components/admin/AgentAdminTabs.svelte +280 -0
  92. package/dist/components/admin/AgentAdminTabs.svelte.d.ts +23 -0
  93. package/dist/components/admin/AgentAdminTabs.svelte.d.ts.map +1 -0
  94. package/dist/components/admin/AgentSettingsShell.svelte +257 -0
  95. package/dist/components/admin/AgentSettingsShell.svelte.d.ts +33 -0
  96. package/dist/components/admin/AgentSettingsShell.svelte.d.ts.map +1 -0
  97. package/dist/components/admin/index.d.ts +5 -0
  98. package/dist/components/admin/index.d.ts.map +1 -0
  99. package/dist/components/admin/index.js +6 -0
  100. package/dist/components/forms/AddressInput.svelte +500 -0
  101. package/dist/components/forms/AddressInput.svelte.d.ts +36 -0
  102. package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -0
  103. package/dist/components/forms/CheckboxInput.svelte +208 -0
  104. package/dist/components/forms/CheckboxInput.svelte.d.ts +20 -0
  105. package/dist/components/forms/CheckboxInput.svelte.d.ts.map +1 -0
  106. package/dist/components/forms/DateRangeInput.svelte +628 -0
  107. package/dist/components/forms/DateRangeInput.svelte.d.ts +33 -0
  108. package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -0
  109. package/dist/components/forms/DateTimeInput.svelte +521 -0
  110. package/dist/components/forms/DateTimeInput.svelte.d.ts +24 -0
  111. package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -0
  112. package/dist/components/forms/FileUpload.svelte +358 -0
  113. package/dist/components/forms/FileUpload.svelte.d.ts +22 -0
  114. package/dist/components/forms/FileUpload.svelte.d.ts.map +1 -0
  115. package/dist/components/forms/Form.svelte +771 -0
  116. package/dist/components/forms/Form.svelte.d.ts +26 -0
  117. package/dist/components/forms/Form.svelte.d.ts.map +1 -0
  118. package/dist/components/forms/FormGroup.svelte +86 -0
  119. package/dist/components/forms/FormGroup.svelte.d.ts +13 -0
  120. package/dist/components/forms/FormGroup.svelte.d.ts.map +1 -0
  121. package/dist/components/forms/FormMicButton.svelte +179 -0
  122. package/dist/components/forms/FormMicButton.svelte.d.ts +10 -0
  123. package/dist/components/forms/FormMicButton.svelte.d.ts.map +1 -0
  124. package/dist/components/forms/Input.svelte +83 -0
  125. package/dist/components/forms/Input.svelte.d.ts +9 -0
  126. package/dist/components/forms/Input.svelte.d.ts.map +1 -0
  127. package/dist/components/forms/MeasurementInput.svelte +505 -0
  128. package/dist/components/forms/MeasurementInput.svelte.d.ts +35 -0
  129. package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -0
  130. package/dist/components/forms/MoneyInput.svelte +412 -0
  131. package/dist/components/forms/MoneyInput.svelte.d.ts +30 -0
  132. package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -0
  133. package/dist/components/forms/NumberInput.svelte +310 -0
  134. package/dist/components/forms/NumberInput.svelte.d.ts +28 -0
  135. package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -0
  136. package/dist/components/forms/PhoneInput.svelte +530 -0
  137. package/dist/components/forms/PhoneInput.svelte.d.ts +22 -0
  138. package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -0
  139. package/dist/components/forms/SearchInput.svelte +358 -0
  140. package/dist/components/forms/SearchInput.svelte.d.ts +33 -0
  141. package/dist/components/forms/SearchInput.svelte.d.ts.map +1 -0
  142. package/dist/components/forms/Select.svelte +83 -0
  143. package/dist/components/forms/Select.svelte.d.ts +11 -0
  144. package/dist/components/forms/Select.svelte.d.ts.map +1 -0
  145. package/dist/components/forms/SelectInput.svelte +254 -0
  146. package/dist/components/forms/SelectInput.svelte.d.ts +25 -0
  147. package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -0
  148. package/dist/components/forms/TextInput.svelte +415 -0
  149. package/dist/components/forms/TextInput.svelte.d.ts +26 -0
  150. package/dist/components/forms/TextInput.svelte.d.ts.map +1 -0
  151. package/dist/components/forms/Textarea.svelte +85 -0
  152. package/dist/components/forms/Textarea.svelte.d.ts +10 -0
  153. package/dist/components/forms/Textarea.svelte.d.ts.map +1 -0
  154. package/dist/components/forms/TextareaInput.svelte +386 -0
  155. package/dist/components/forms/TextareaInput.svelte.d.ts +26 -0
  156. package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -0
  157. package/dist/components/forms/Toggle.svelte +217 -0
  158. package/dist/components/forms/Toggle.svelte.d.ts +37 -0
  159. package/dist/components/forms/Toggle.svelte.d.ts.map +1 -0
  160. package/dist/components/forms/__tests__/AddressInput.behavior.test.js +122 -0
  161. package/dist/components/forms/__tests__/CheckboxInput.test.js +92 -0
  162. package/dist/components/forms/__tests__/DateRangeInput.behavior.test.js +135 -0
  163. package/dist/components/forms/__tests__/DateTimeInput.behavior.test.js +103 -0
  164. package/dist/components/forms/__tests__/FileUpload.test.js +90 -0
  165. package/dist/components/forms/__tests__/Form.behavior.test.js +137 -0
  166. package/dist/components/forms/__tests__/Form.test.js +58 -0
  167. package/dist/components/forms/__tests__/FormGroup.test.js +48 -0
  168. package/dist/components/forms/__tests__/FormMicButton.test.js +86 -0
  169. package/dist/components/forms/__tests__/Input.test.js +49 -0
  170. package/dist/components/forms/__tests__/MeasurementInput.behavior.test.js +129 -0
  171. package/dist/components/forms/__tests__/MoneyInput.behavior.test.js +124 -0
  172. package/dist/components/forms/__tests__/NumberInput.behavior.test.js +141 -0
  173. package/dist/components/forms/__tests__/PhoneInput.behavior.test.js +96 -0
  174. package/dist/components/forms/__tests__/SearchInput.test.js +79 -0
  175. package/dist/components/forms/__tests__/Select.test.js +37 -0
  176. package/dist/components/forms/__tests__/SelectInput.behavior.test.js +132 -0
  177. package/dist/components/forms/__tests__/TextInput.behavior.test.js +131 -0
  178. package/dist/components/forms/__tests__/Textarea.test.js +39 -0
  179. package/dist/components/forms/__tests__/TextareaInput.behavior.test.js +96 -0
  180. package/dist/components/forms/__tests__/Toggle.test.js +87 -0
  181. package/dist/components/forms/__tests__/composite-inputs-a11y.test.js +69 -0
  182. package/dist/components/forms/__tests__/form-group-input.fixture.svelte +16 -0
  183. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts +9 -0
  184. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts.map +1 -0
  185. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +33 -0
  186. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +12 -0
  187. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +1 -0
  188. package/dist/components/forms/__tests__/rich-inputs-a11y.test.js +87 -0
  189. package/dist/components/forms/index.d.ts +25 -0
  190. package/dist/components/forms/index.d.ts.map +1 -0
  191. package/dist/components/forms/index.js +25 -0
  192. package/dist/components/forms/types.d.ts +33 -0
  193. package/dist/components/forms/types.d.ts.map +1 -0
  194. package/dist/components/forms/types.js +4 -0
  195. package/dist/components/module/ModulePanel.svelte +134 -0
  196. package/dist/components/module/ModulePanel.svelte.d.ts +22 -0
  197. package/dist/components/module/ModulePanel.svelte.d.ts.map +1 -0
  198. package/dist/components/module/index.d.ts +5 -0
  199. package/dist/components/module/index.d.ts.map +1 -0
  200. package/dist/components/module/index.js +4 -0
  201. package/dist/components/workspace/Breadcrumbs.svelte +141 -0
  202. package/dist/components/workspace/Breadcrumbs.svelte.d.ts +21 -0
  203. package/dist/components/workspace/Breadcrumbs.svelte.d.ts.map +1 -0
  204. package/dist/components/workspace/NavTree.svelte +354 -0
  205. package/dist/components/workspace/NavTree.svelte.d.ts +45 -0
  206. package/dist/components/workspace/NavTree.svelte.d.ts.map +1 -0
  207. package/dist/components/workspace/README.md +34 -0
  208. package/dist/components/workspace/RoleShell.svelte +309 -0
  209. package/dist/components/workspace/RoleShell.svelte.d.ts +91 -0
  210. package/dist/components/workspace/RoleShell.svelte.d.ts.map +1 -0
  211. package/dist/components/workspace/WorkspaceShell.svelte +951 -0
  212. package/dist/components/workspace/WorkspaceShell.svelte.d.ts +112 -0
  213. package/dist/components/workspace/WorkspaceShell.svelte.d.ts.map +1 -0
  214. package/dist/components/workspace/__tests__/RoleShell.test.js +772 -0
  215. package/dist/components/workspace/__tests__/WorkspaceShell.test.js +630 -0
  216. package/dist/components/workspace/__tests__/breadcrumbs-helpers.test.js +141 -0
  217. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte +45 -0
  218. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts +21 -0
  219. package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts.map +1 -0
  220. package/dist/components/workspace/__tests__/define-tools-dock.test.js +1010 -0
  221. package/dist/components/workspace/__tests__/harness.svelte +25 -0
  222. package/dist/components/workspace/__tests__/harness.svelte.d.ts +14 -0
  223. package/dist/components/workspace/__tests__/harness.svelte.d.ts.map +1 -0
  224. package/dist/components/workspace/__tests__/index.test.js +37 -0
  225. package/dist/components/workspace/__tests__/manifest-nav-helpers.test.js +24 -0
  226. package/dist/components/workspace/__tests__/manifest-nav.test.js +599 -0
  227. package/dist/components/workspace/__tests__/nav-helpers.test.js +95 -0
  228. package/dist/components/workspace/__tests__/render-harness.svelte +66 -0
  229. package/dist/components/workspace/__tests__/render-harness.svelte.d.ts +32 -0
  230. package/dist/components/workspace/__tests__/render-harness.svelte.d.ts.map +1 -0
  231. package/dist/components/workspace/__tests__/render-tools-dock.test.js +243 -0
  232. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte +58 -0
  233. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts +16 -0
  234. package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts.map +1 -0
  235. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte +41 -0
  236. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts +13 -0
  237. package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts.map +1 -0
  238. package/dist/components/workspace/__tests__/test-icon.svelte +17 -0
  239. package/dist/components/workspace/__tests__/test-icon.svelte.d.ts +19 -0
  240. package/dist/components/workspace/__tests__/test-icon.svelte.d.ts.map +1 -0
  241. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte +38 -0
  242. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts +22 -0
  243. package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts.map +1 -0
  244. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +65 -0
  245. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +1 -0
  246. package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +115 -0
  247. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts +15 -0
  248. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts.map +1 -0
  249. package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.js +7 -0
  250. package/dist/components/workspace/__tests__/typed-tool-fixture.test.js +115 -0
  251. package/dist/components/workspace/__tests__/use-harness-orphan.svelte +9 -0
  252. package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts +19 -0
  253. package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts.map +1 -0
  254. package/dist/components/workspace/__tests__/use-harness.svelte +23 -0
  255. package/dist/components/workspace/__tests__/use-harness.svelte.d.ts +8 -0
  256. package/dist/components/workspace/__tests__/use-harness.svelte.d.ts.map +1 -0
  257. package/dist/components/workspace/__tests__/use-tools-dock.test.js +33 -0
  258. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte +43 -0
  259. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts +11 -0
  260. package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts.map +1 -0
  261. package/dist/components/workspace/breadcrumbs-helpers.d.ts +44 -0
  262. package/dist/components/workspace/breadcrumbs-helpers.d.ts.map +1 -0
  263. package/dist/components/workspace/breadcrumbs-helpers.js +88 -0
  264. package/dist/components/workspace/index.d.ts +16 -0
  265. package/dist/components/workspace/index.d.ts.map +1 -0
  266. package/dist/components/workspace/index.js +14 -0
  267. package/dist/components/workspace/manifest-nav.d.ts +200 -0
  268. package/dist/components/workspace/manifest-nav.d.ts.map +1 -0
  269. package/dist/components/workspace/manifest-nav.js +408 -0
  270. package/dist/components/workspace/nav-helpers.d.ts +36 -0
  271. package/dist/components/workspace/nav-helpers.d.ts.map +1 -0
  272. package/dist/components/workspace/nav-helpers.js +60 -0
  273. package/dist/components/workspace/server/__tests__/compose-availability.test.js +383 -0
  274. package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts +78 -0
  275. package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts.map +1 -0
  276. package/dist/components/workspace/server/__tests__/typed-context-fixture.js +104 -0
  277. package/dist/components/workspace/server/compose-availability.d.ts +73 -0
  278. package/dist/components/workspace/server/compose-availability.d.ts.map +1 -0
  279. package/dist/components/workspace/server/compose-availability.js +114 -0
  280. package/dist/components/workspace/server/index.d.ts +13 -0
  281. package/dist/components/workspace/server/index.d.ts.map +1 -0
  282. package/dist/components/workspace/server/index.js +11 -0
  283. package/dist/components/workspace/server/types.d.ts +108 -0
  284. package/dist/components/workspace/server/types.d.ts.map +1 -0
  285. package/dist/components/workspace/server/types.js +11 -0
  286. package/dist/components/workspace/tools-dock/ToolsDock.svelte +565 -0
  287. package/dist/components/workspace/tools-dock/ToolsDock.svelte.d.ts +14 -0
  288. package/dist/components/workspace/tools-dock/ToolsDock.svelte.d.ts.map +1 -0
  289. package/dist/components/workspace/tools-dock/define-tools-dock.svelte.d.ts +143 -0
  290. package/dist/components/workspace/tools-dock/define-tools-dock.svelte.d.ts.map +1 -0
  291. package/dist/components/workspace/tools-dock/define-tools-dock.svelte.js +487 -0
  292. package/dist/components/workspace/tools-dock/use-tools-dock.d.ts +41 -0
  293. package/dist/components/workspace/tools-dock/use-tools-dock.d.ts.map +1 -0
  294. package/dist/components/workspace/tools-dock/use-tools-dock.js +50 -0
  295. package/dist/components/workspace/types.d.ts +372 -0
  296. package/dist/components/workspace/types.d.ts.map +1 -0
  297. package/dist/components/workspace/types.js +6 -0
  298. package/dist/hooks/index.d.ts +11 -0
  299. package/dist/hooks/index.d.ts.map +1 -0
  300. package/dist/hooks/index.js +10 -0
  301. package/dist/hooks/useAppState.svelte.d.ts +46 -0
  302. package/dist/hooks/useAppState.svelte.d.ts.map +1 -0
  303. package/dist/hooks/useAppState.svelte.js +59 -0
  304. package/dist/hooks/useAuth.svelte.d.ts +41 -0
  305. package/dist/hooks/useAuth.svelte.d.ts.map +1 -0
  306. package/dist/hooks/useAuth.svelte.js +43 -0
  307. package/dist/hooks/useLLM.svelte.d.ts +69 -0
  308. package/dist/hooks/useLLM.svelte.d.ts.map +1 -0
  309. package/dist/hooks/useLLM.svelte.js +85 -0
  310. package/dist/hooks/useSTT.svelte.d.ts +68 -0
  311. package/dist/hooks/useSTT.svelte.d.ts.map +1 -0
  312. package/dist/hooks/useSTT.svelte.js +97 -0
  313. package/dist/hooks/useSocket.svelte.d.ts +45 -0
  314. package/dist/hooks/useSocket.svelte.d.ts.map +1 -0
  315. package/dist/hooks/useSocket.svelte.js +54 -0
  316. package/dist/hooks/useTTS.svelte.d.ts +65 -0
  317. package/dist/hooks/useTTS.svelte.d.ts.map +1 -0
  318. package/dist/hooks/useTTS.svelte.js +93 -0
  319. package/dist/hooks/useTheme.d.ts +13 -0
  320. package/dist/hooks/useTheme.d.ts.map +1 -0
  321. package/dist/hooks/useTheme.js +16 -0
  322. package/dist/i18n/__tests__/server.spec.js +50 -0
  323. package/dist/i18n/server.d.ts +47 -0
  324. package/dist/i18n/server.d.ts.map +1 -0
  325. package/dist/i18n/server.js +58 -0
  326. package/dist/i18n/strings.forms.d.ts +33 -0
  327. package/dist/i18n/strings.forms.d.ts.map +1 -0
  328. package/dist/i18n/strings.forms.js +54 -0
  329. package/dist/i18n/strings.workspace.d.ts +34 -0
  330. package/dist/i18n/strings.workspace.d.ts.map +1 -0
  331. package/dist/i18n/strings.workspace.js +40 -0
  332. package/dist/index.d.ts +18 -0
  333. package/dist/index.d.ts.map +1 -0
  334. package/dist/index.js +23 -0
  335. package/dist/state/__tests__/warm-clients.test.js +40 -0
  336. package/dist/state/app-state.d.ts +308 -0
  337. package/dist/state/app-state.d.ts.map +1 -0
  338. package/dist/state/app-state.js +64 -0
  339. package/dist/state/app-state.svelte.d.ts +196 -0
  340. package/dist/state/app-state.svelte.d.ts.map +1 -0
  341. package/dist/state/app-state.svelte.js +774 -0
  342. package/dist/state/context.d.ts +23 -0
  343. package/dist/state/context.d.ts.map +1 -0
  344. package/dist/state/context.js +32 -0
  345. package/dist/state/form-context.d.ts +59 -0
  346. package/dist/state/form-context.d.ts.map +1 -0
  347. package/dist/state/form-context.js +31 -0
  348. package/dist/state/form-group-context.d.ts +13 -0
  349. package/dist/state/form-group-context.d.ts.map +1 -0
  350. package/dist/state/form-group-context.js +28 -0
  351. package/dist/state/index.d.ts +9 -0
  352. package/dist/state/index.d.ts.map +1 -0
  353. package/dist/state/index.js +8 -0
  354. package/dist/state/warm-clients.d.ts +136 -0
  355. package/dist/state/warm-clients.d.ts.map +1 -0
  356. package/dist/state/warm-clients.js +231 -0
  357. package/package.json +137 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * defineToolsDock - factory for the ToolsDock API
3
+ *
4
+ * Creates a reactive {@link ToolsDockApi} instance backed by Svelte 5 runes
5
+ * (`$state`) and registers it in Svelte context under {@link TOOLS_DOCK_KEY}.
6
+ * Inside a `<ToolsDock>` provider tree, descendants (tools, deep panels,
7
+ * arbitrary consumers) read the same instance via {@link useToolsDock}.
8
+ *
9
+ * The dock is intentionally domain-agnostic:
10
+ * - Tool IDs are arbitrary strings (no enum).
11
+ * - Availability is controlled via the optional `fetchAvailability` callback;
12
+ * when omitted, every registered tool is available.
13
+ * - Persistence is opt-in via `storageKey` and is SSR-safe.
14
+ * - Inter-tool messaging happens through a typed pub/sub bus (`emit`/`on`)
15
+ * in lieu of `window.dispatchEvent` patterns from older portals.
16
+ *
17
+ * @example Register a dock and a tool
18
+ * ```ts
19
+ * // somewhere in a +layout.svelte:
20
+ * import { defineToolsDock } from '@happyvertical/smrt-svelte/workspace';
21
+ * import ChatTool from './ChatTool.svelte';
22
+ *
23
+ * const dock = defineToolsDock({
24
+ * tools: [{ id: 'chat', label: 'Chat', component: ChatTool }],
25
+ * storageKey: 'app-name:tools-dock:v1',
26
+ * });
27
+ * ```
28
+ *
29
+ * @remarks ModuleUIRegistry integration point
30
+ *
31
+ * Consumer apps that want tools to come from `@happyvertical/smrt-*` module
32
+ * packages (commerce, content, etc.) can populate `options.tools` from the
33
+ * `ModuleUIRegistry` (see {@link ../../../registry/module-registry}) — e.g.
34
+ * by walking `ModuleUIRegistry.getModules()` and pulling components from a
35
+ * conventional slot id like `'tools-dock'`. This is left to consumers so the
36
+ * dock has zero coupling to the registry; the surface area exposed here
37
+ * (`ToolDef[]`) is what such an adapter would produce.
38
+ */
39
+ import type { AvailableTool, ToolDef, ToolsDockApi, ToolsDockContext } from '../types.js';
40
+ /**
41
+ * Svelte context key for the active ToolsDock API instance.
42
+ */
43
+ export declare const TOOLS_DOCK_KEY: unique symbol;
44
+ /**
45
+ * Options accepted by {@link defineToolsDock}.
46
+ *
47
+ * `TData` types the shape of `context.data` passed through `setContext()` /
48
+ * `fetchAvailability` — narrow it at the factory site to get a typed
49
+ * `ctx.data` inside the availability callback without manual casts.
50
+ * Defaults to `Record<string, unknown>` so existing callers keep compiling.
51
+ *
52
+ * `TActions` types the shape of `context.actions` and flows the same way.
53
+ * Defaults to `Record<string, (...args: any[]) => unknown>` so the untyped
54
+ * `dock.setContext({ actions: { triggerSave() {} } })` pattern keeps
55
+ * compiling without a generic argument. The constraint is a self-mapped
56
+ * `{ [K in keyof TActions]: (...args: any[]) => any }` so interface-style
57
+ * action maps (without a string index signature) satisfy the bound —
58
+ * see the JSDoc on {@link ToolsDockContext} for rationale.
59
+ *
60
+ * Tools themselves are stored as `ToolDef[]` (the generics are erased at
61
+ * registration). Inside a tool component, type the prop locally — see the
62
+ * JSDoc on {@link ToolDef.component} for the recommended pattern.
63
+ */
64
+ export interface DefineToolsDockOptions<TData = Record<string, unknown>, TActions extends {
65
+ [K in keyof TActions]: (...args: any[]) => any;
66
+ } = Record<string, (...args: any[]) => unknown>> {
67
+ /** Registered tools. Order is preserved when rendering the activation rail/topbar. */
68
+ tools: ToolDef[];
69
+ /**
70
+ * Optional backend-driven gating callback. Returns the subset of tools that
71
+ * should be exposed for the current `context`. When omitted, every
72
+ * registered tool is treated as available.
73
+ *
74
+ * The callback may return tool ids that aren't present in `tools` — these
75
+ * are ignored. Conversely, tools missing from the callback's response are
76
+ * hidden from the dock UI.
77
+ *
78
+ * The `ctx` parameter is typed against the factory's `TData` / `TActions`
79
+ * generics — narrow them at the factory site for typed access to
80
+ * `ctx.data` / `ctx.actions` here without manual casts.
81
+ */
82
+ fetchAvailability?: (ctx: ToolsDockContext<TData, TActions> | null) => Promise<AvailableTool[]>;
83
+ /**
84
+ * Optional `localStorage` key. When provided, the dock will persist a small
85
+ * `{ isOpen, activeTool }` blob and hydrate it on mount. Persistence is
86
+ * SSR-safe — no `localStorage` access happens at module scope or during
87
+ * initial render on the server.
88
+ */
89
+ storageKey?: string;
90
+ /**
91
+ * Activation UI layout. Defaults to `'rail'`.
92
+ *
93
+ * - `'rail'`: vertical icon rail with the panel contained inside the
94
+ * dock's own aside. Safe to compose alongside `<WorkspaceShell>`'s
95
+ * `inspector` snippet — they don't fight for positioning.
96
+ * - `'topbar'`: inline activation buttons with a SEPARATE
97
+ * `position: fixed` panel anchored to the bottom-right of the
98
+ * viewport. **Do not also use `<WorkspaceShell>`'s `inspector`
99
+ * snippet in this mode** — the shell renders its own
100
+ * `position: fixed` inspector with no z-index coordination, and the
101
+ * two panels will visibly overlap. Render `<ToolsDock layout='topbar'>`
102
+ * inside the shell's `topbarActions` snippet and leave the inspector
103
+ * slot unused.
104
+ */
105
+ layout?: 'rail' | 'topbar';
106
+ /** Initial open state. Hydration from storage takes precedence. Defaults to `false`. */
107
+ initialOpen?: boolean;
108
+ }
109
+ /**
110
+ * Internal extension of {@link ToolsDockApi} with framework-only members:
111
+ * the registered tools, the configured layout, and the persistence key.
112
+ *
113
+ * Mirrors the same `<TData, TActions>` generics as {@link ToolsDockApi} so
114
+ * the narrowed `context` / `setContext()` signatures from
115
+ * `defineToolsDock<TData, TActions>(...)` flow through to consumers that
116
+ * hold the returned instance directly. Defaults preserve back-compat for
117
+ * untyped callers (`defineToolsDock({...})`).
118
+ */
119
+ export interface ToolsDockInstance<TData = Record<string, unknown>, TActions extends {
120
+ [K in keyof TActions]: (...args: any[]) => any;
121
+ } = Record<string, (...args: any[]) => unknown>> extends ToolsDockApi<TData, TActions> {
122
+ readonly tools: ReadonlyArray<ToolDef>;
123
+ readonly layout: 'rail' | 'topbar';
124
+ readonly storageKey: string | null;
125
+ /** Internal: hydrate persisted state from `localStorage` (called by `<ToolsDock>` on mount). */
126
+ hydrate(): void;
127
+ /** Internal: persist current state to `localStorage`. */
128
+ persist(): void;
129
+ }
130
+ /**
131
+ * Create a tools-dock instance and register it on Svelte context.
132
+ *
133
+ * Must be called inside a Svelte component initialization scope (`<script>`
134
+ * top level, `+layout.svelte`, etc.) — `setContext` requires it.
135
+ *
136
+ * @param options factory options
137
+ * @returns the {@link ToolsDockInstance} (a {@link ToolsDockApi} plus
138
+ * framework metadata `<ToolsDock>` consumes when rendering)
139
+ */
140
+ export declare function defineToolsDock<TData = Record<string, unknown>, TActions extends {
141
+ [K in keyof TActions]: (...args: any[]) => any;
142
+ } = Record<string, (...args: any[]) => unknown>>(options: DefineToolsDockOptions<TData, TActions>): ToolsDockInstance<TData, TActions>;
143
+ //# sourceMappingURL=define-tools-dock.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-tools-dock.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/tools-dock/define-tools-dock.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,OAAO,EACP,YAAY,EACZ,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,eAAO,MAAM,cAAc,eAA4B,CAAC;AAExD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,sBAAsB,CACrC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,SAAS;KAAG,CAAC,IAAI,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG;CAAE,GAAG,MAAM,CAC1E,MAAM,EACN,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAC5B;IAED,sFAAsF;IACtF,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,EAAE,CAClB,GAAG,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAI,KAC1C,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC3B,wFAAwF;IACxF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB,CAChC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,SAAS;KAAG,CAAC,IAAI,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG;CAAE,GAAG,MAAM,CAC1E,MAAM,EACN,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAC5B,CACD,SAAQ,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gGAAgG;IAChG,OAAO,IAAI,IAAI,CAAC;IAChB,yDAAyD;IACzD,OAAO,IAAI,IAAI,CAAC;CACjB;AAiDD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,SAAS;KAAG,CAAC,IAAI,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG;CAAE,GAAG,MAAM,CAC1E,MAAM,EACN,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAC5B,EAED,OAAO,EAAE,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,GAC/C,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAyZpC"}
@@ -0,0 +1,487 @@
1
+ /**
2
+ * defineToolsDock - factory for the ToolsDock API
3
+ *
4
+ * Creates a reactive {@link ToolsDockApi} instance backed by Svelte 5 runes
5
+ * (`$state`) and registers it in Svelte context under {@link TOOLS_DOCK_KEY}.
6
+ * Inside a `<ToolsDock>` provider tree, descendants (tools, deep panels,
7
+ * arbitrary consumers) read the same instance via {@link useToolsDock}.
8
+ *
9
+ * The dock is intentionally domain-agnostic:
10
+ * - Tool IDs are arbitrary strings (no enum).
11
+ * - Availability is controlled via the optional `fetchAvailability` callback;
12
+ * when omitted, every registered tool is available.
13
+ * - Persistence is opt-in via `storageKey` and is SSR-safe.
14
+ * - Inter-tool messaging happens through a typed pub/sub bus (`emit`/`on`)
15
+ * in lieu of `window.dispatchEvent` patterns from older portals.
16
+ *
17
+ * @example Register a dock and a tool
18
+ * ```ts
19
+ * // somewhere in a +layout.svelte:
20
+ * import { defineToolsDock } from '@happyvertical/smrt-svelte/workspace';
21
+ * import ChatTool from './ChatTool.svelte';
22
+ *
23
+ * const dock = defineToolsDock({
24
+ * tools: [{ id: 'chat', label: 'Chat', component: ChatTool }],
25
+ * storageKey: 'app-name:tools-dock:v1',
26
+ * });
27
+ * ```
28
+ *
29
+ * @remarks ModuleUIRegistry integration point
30
+ *
31
+ * Consumer apps that want tools to come from `@happyvertical/smrt-*` module
32
+ * packages (commerce, content, etc.) can populate `options.tools` from the
33
+ * `ModuleUIRegistry` (see {@link ../../../registry/module-registry}) — e.g.
34
+ * by walking `ModuleUIRegistry.getModules()` and pulling components from a
35
+ * conventional slot id like `'tools-dock'`. This is left to consumers so the
36
+ * dock has zero coupling to the registry; the surface area exposed here
37
+ * (`ToolDef[]`) is what such an adapter would produce.
38
+ */
39
+ import { setContext, untrack } from 'svelte';
40
+ /**
41
+ * Svelte context key for the active ToolsDock API instance.
42
+ */
43
+ export const TOOLS_DOCK_KEY = Symbol('smrt-tools-dock');
44
+ // Availability fetches are token-gated for race-safety (stale results are
45
+ // dropped — see `refreshAvailability`). We deliberately do NOT debounce by
46
+ // default because:
47
+ // - `setContext` is typically called from `$effect` on route changes, not
48
+ // in a tight loop
49
+ // - debouncing complicates testing without buying meaningful protection
50
+ // given the token-based stale-result drop
51
+ // Consumers that need debounce can wrap their own setContext call.
52
+ function isBrowser() {
53
+ return typeof window !== 'undefined';
54
+ }
55
+ function safeReadStorage(key) {
56
+ if (!isBrowser())
57
+ return null;
58
+ try {
59
+ const raw = window.localStorage.getItem(key);
60
+ if (!raw)
61
+ return null;
62
+ const parsed = JSON.parse(raw);
63
+ if (!parsed || typeof parsed !== 'object')
64
+ return null;
65
+ const { isOpen, activeTool } = parsed;
66
+ return {
67
+ isOpen: typeof isOpen === 'boolean' ? isOpen : undefined,
68
+ activeTool: typeof activeTool === 'string' || activeTool === null
69
+ ? activeTool
70
+ : undefined,
71
+ };
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ function safeWriteStorage(key, payload) {
78
+ if (!isBrowser())
79
+ return;
80
+ try {
81
+ window.localStorage.setItem(key, JSON.stringify(payload));
82
+ }
83
+ catch {
84
+ // Quota errors, private browsing, etc. — silently drop.
85
+ }
86
+ }
87
+ /**
88
+ * Create a tools-dock instance and register it on Svelte context.
89
+ *
90
+ * Must be called inside a Svelte component initialization scope (`<script>`
91
+ * top level, `+layout.svelte`, etc.) — `setContext` requires it.
92
+ *
93
+ * @param options factory options
94
+ * @returns the {@link ToolsDockInstance} (a {@link ToolsDockApi} plus
95
+ * framework metadata `<ToolsDock>` consumes when rendering)
96
+ */
97
+ export function defineToolsDock(options) {
98
+ const layout = options.layout ?? 'rail';
99
+ const storageKey = options.storageKey ?? null;
100
+ const fetchAvailability = options.fetchAvailability;
101
+ const registeredTools = options.tools.slice();
102
+ const registeredIds = new Set(registeredTools.map((t) => t.id));
103
+ // Reactive state
104
+ let isOpen = $state(Boolean(options.initialOpen));
105
+ let activeTool = $state(null);
106
+ let context = $state(null);
107
+ // Shadow of the last raw context reference passed to `setContextValue`.
108
+ // Used for strict-equality short-circuiting: Svelte 5 wraps stored object
109
+ // `$state` values in a Proxy, so `ctx === context` would never match the
110
+ // original input. Comparing against this shadow gives us proxy-free
111
+ // reference equality and avoids the `state_proxy_equality_mismatch`
112
+ // warning.
113
+ let rawContextRef = null;
114
+ let availableTools = $state(registeredTools.map((t) => ({ id: t.id, label: t.label, badge: t.badge })));
115
+ // Race-handle: each fetchAvailability call gets a token; only the most
116
+ // recent token may apply its result.
117
+ let availabilityToken = 0;
118
+ /**
119
+ * Set to `true` once the factory has finished wiring the instance. Used
120
+ * to gate `'dock:change'` emits so handlers can't run before the instance
121
+ * exists / is registered on context. Mutations issued from inside the
122
+ * factory body (e.g. `applyAvailability` running during initial
123
+ * availability snapshot) are silent.
124
+ */
125
+ let ready = false;
126
+ // Pub/sub bus
127
+ const listeners = new Map();
128
+ function emit(event, payload) {
129
+ const set = listeners.get(event);
130
+ if (!set || set.size === 0)
131
+ return;
132
+ // Copy so handlers that unsubscribe themselves don't mutate during iteration.
133
+ for (const handler of Array.from(set)) {
134
+ try {
135
+ handler(payload);
136
+ }
137
+ catch (err) {
138
+ // Don't let one handler kill the rest.
139
+ if (isBrowser())
140
+ console.error('[ToolsDock] handler error', err);
141
+ }
142
+ }
143
+ }
144
+ function on(event, handler) {
145
+ let set = listeners.get(event);
146
+ if (!set) {
147
+ set = new Set();
148
+ listeners.set(event, set);
149
+ }
150
+ set.add(handler);
151
+ return () => {
152
+ const current = listeners.get(event);
153
+ if (!current)
154
+ return;
155
+ current.delete(handler);
156
+ if (current.size === 0)
157
+ listeners.delete(event);
158
+ };
159
+ }
160
+ /**
161
+ * Emit the appropriate dock-owned change events. Guarded by the `ready`
162
+ * flag so handlers can't run during factory construction (before the
163
+ * instance is fully wired / registered on Svelte context). Always reads
164
+ * the latest `$state` values so handlers see the post-update state,
165
+ * regardless of how many updates happened in a single call.
166
+ *
167
+ * The `$state` reads are wrapped in `untrack` so that when this is
168
+ * invoked from inside a Svelte `$effect` (e.g. `<ToolsDock>`'s effect
169
+ * forwarding the `context` prop into `dock.setContext`), the reads do
170
+ * NOT become dependencies of that effect. Without this guard, a
171
+ * subsequent `open()` / `close()` would re-run the calling effect,
172
+ * which would call `setContext` again, triggering another availability
173
+ * fetch and another emit — an infinite-ish feedback loop.
174
+ *
175
+ * Three events fan out from a single call, each gated by what actually
176
+ * changed:
177
+ * - `'dock:state-changed'` — fired when `stateChanged` is true (open /
178
+ * close / toggle / availability cleared the active tool)
179
+ * - `'dock:context-changed'` — fired when `contextChanged` is true
180
+ * (`setContext` saw a different reference)
181
+ * - `'dock:change'` — legacy event, fired whenever this is called.
182
+ * Stays for back-compat; consumers should prefer the granular pair.
183
+ *
184
+ * Callers that only see a badge/label refresh (no state or context
185
+ * change) still funnel through here so the legacy `'dock:change'`
186
+ * subscribers see badge updates — but `stateChanged` / `contextChanged`
187
+ * both stay `false`, keeping the granular events silent.
188
+ */
189
+ function emitChange(opts) {
190
+ if (!ready)
191
+ return;
192
+ const snapshot = untrack(() => ({
193
+ isOpen,
194
+ activeTool,
195
+ context,
196
+ }));
197
+ if (opts.stateChanged) {
198
+ emit('dock:state-changed', {
199
+ isOpen: snapshot.isOpen,
200
+ activeTool: snapshot.activeTool,
201
+ });
202
+ }
203
+ if (opts.contextChanged) {
204
+ emit('dock:context-changed', {
205
+ context: snapshot.context,
206
+ });
207
+ }
208
+ emit('dock:change', snapshot);
209
+ }
210
+ /**
211
+ * Discriminating comparison of two availability snapshots. Returns true
212
+ * when the new snapshot differs from the previous one in any user-visible
213
+ * way (id ordering, badge value, or label). Used by `applyAvailability`
214
+ * to decide whether to fire a `'dock:change'` event: refreshes that
215
+ * resolve to byte-identical availability (the common no-op case when a
216
+ * side-channel signal fires but underlying data didn't change) stay
217
+ * silent, avoiding spurious work in consumer-side `'dock:change'`
218
+ * mirrors.
219
+ *
220
+ * Both inputs come from `registeredTools.filter(...).map(...)` in the
221
+ * same registration order, so a positional comparison is sufficient.
222
+ */
223
+ function availabilityActuallyChanged(prev, next) {
224
+ if (prev.length !== next.length)
225
+ return true;
226
+ for (let i = 0; i < prev.length; i++) {
227
+ const a = prev[i];
228
+ const b = next[i];
229
+ if (a.id !== b.id)
230
+ return true;
231
+ if ((a.badge ?? null) !== (b.badge ?? null))
232
+ return true;
233
+ if ((a.label ?? '') !== (b.label ?? ''))
234
+ return true;
235
+ }
236
+ return false;
237
+ }
238
+ function applyAvailability(next) {
239
+ // Filter to registered tools, preserve registration order, merge labels/badges.
240
+ const byId = new Map(next.map((t) => [t.id, t]));
241
+ const prev = availableTools;
242
+ availableTools = registeredTools
243
+ .filter((t) => byId.has(t.id))
244
+ .map((t) => {
245
+ const reported = byId.get(t.id);
246
+ // Distinguish "key absent" (fall back to registered default) from
247
+ // "key present with null" (explicitly clear the badge).
248
+ const reportedBadge = reported && 'badge' in reported ? reported.badge : undefined;
249
+ return {
250
+ id: t.id,
251
+ label: reported?.label ?? t.label,
252
+ badge: reportedBadge !== undefined ? reportedBadge : (t.badge ?? null),
253
+ };
254
+ });
255
+ let stateChanged = false;
256
+ let anyChange = false;
257
+ // If the active tool is no longer available, clear it. Auto-close policy:
258
+ //
259
+ // - If the available set is now empty, close the dock too (nothing left
260
+ // to show — leaving `isOpen: true, activeTool: null` would render a
261
+ // floating empty panel in the topbar layout).
262
+ // - If other tools remain, the dock stays open with `activeTool: null`.
263
+ // Consumers see the cleared state via `'dock:state-changed'` and can
264
+ // decide what to do (auto-pick the first remaining tool via
265
+ // `dock.open(availableTools[0].id)`, or surface a "select a tool"
266
+ // hint). The primitive stays policy-free — there's no universally
267
+ // correct auto-selection (the previously-active tool's adjacency to
268
+ // any specific replacement is consumer-specific).
269
+ if (activeTool && !availableTools.some((t) => t.id === activeTool)) {
270
+ activeTool = null;
271
+ if (isOpen && availableTools.length === 0) {
272
+ isOpen = false;
273
+ }
274
+ // Persist the cleared state so the factory's persistence guarantees
275
+ // don't depend on the <ToolsDock> component being mounted to rescue
276
+ // them via its $effect.
277
+ persist();
278
+ stateChanged = true;
279
+ anyChange = true;
280
+ }
281
+ // Even when the active tool stayed put, the availability set may have
282
+ // shifted in ways consumers care about (badge counts, label overrides,
283
+ // tools appearing/disappearing). Emit so consumers mirroring
284
+ // `availableTools` into their own state (badges in topbars, etc.) see
285
+ // the update without polling.
286
+ if (!anyChange) {
287
+ anyChange = availabilityActuallyChanged(prev, availableTools);
288
+ }
289
+ if (anyChange) {
290
+ // Pure badge/label refresh (no `stateChanged`, no context change)
291
+ // still fires the legacy `'dock:change'` event for back-compat with
292
+ // consumers mirroring `availableTools` — but stays silent on the
293
+ // granular pair, which is the point of the U2 split.
294
+ emitChange({ stateChanged, contextChanged: false });
295
+ }
296
+ }
297
+ function refreshAvailability() {
298
+ if (!fetchAvailability) {
299
+ // Static availability — every registered tool.
300
+ applyAvailability(registeredTools.map((t) => ({
301
+ id: t.id,
302
+ label: t.label,
303
+ badge: t.badge,
304
+ })));
305
+ return;
306
+ }
307
+ const token = ++availabilityToken;
308
+ // Internally we store `context` as the default-generic shape; the
309
+ // factory's `TData` / `TActions` only constrain the public callback
310
+ // signature. Cast at the call boundary to thread the consumer's narrowed
311
+ // type through without polluting the runtime store with the generic.
312
+ const snapshotCtx = context;
313
+ // Funnel both synchronous throws (argument validation, undefined
314
+ // dereferences before the promise is returned) and asynchronous
315
+ // rejections through the same error path so neither escapes
316
+ // `setContext` to the component.
317
+ let pending;
318
+ try {
319
+ pending = Promise.resolve(fetchAvailability(snapshotCtx));
320
+ }
321
+ catch (err) {
322
+ pending = Promise.reject(err);
323
+ }
324
+ void pending
325
+ .then((result) => {
326
+ if (token !== availabilityToken)
327
+ return; // stale
328
+ applyAvailability(Array.isArray(result) ? result : []);
329
+ })
330
+ .catch(() => {
331
+ if (token !== availabilityToken)
332
+ return;
333
+ // On error, surface zero availability rather than stale state.
334
+ applyAvailability([]);
335
+ });
336
+ }
337
+ function persist() {
338
+ if (!storageKey)
339
+ return;
340
+ safeWriteStorage(storageKey, { isOpen, activeTool });
341
+ }
342
+ function hydrate() {
343
+ if (!storageKey)
344
+ return;
345
+ const persisted = safeReadStorage(storageKey);
346
+ if (!persisted)
347
+ return;
348
+ if (typeof persisted.isOpen === 'boolean') {
349
+ isOpen = persisted.isOpen;
350
+ }
351
+ if (typeof persisted.activeTool === 'string' &&
352
+ registeredIds.has(persisted.activeTool)) {
353
+ activeTool = persisted.activeTool;
354
+ }
355
+ }
356
+ function open(id) {
357
+ const prevIsOpen = isOpen;
358
+ const prevActive = activeTool;
359
+ if (id) {
360
+ if (!availableTools.some((t) => t.id === id))
361
+ return; // unavailable — no-op
362
+ activeTool = id;
363
+ }
364
+ else if (!activeTool && availableTools.length > 0) {
365
+ activeTool = availableTools[0].id;
366
+ }
367
+ isOpen = true;
368
+ persist();
369
+ // Skip emit when nothing observable changed — avoids spurious
370
+ // 'dock:change' events when consumers idempotently call open() on the
371
+ // already-active tool.
372
+ if (isOpen !== prevIsOpen || activeTool !== prevActive) {
373
+ emitChange({ stateChanged: true, contextChanged: false });
374
+ }
375
+ }
376
+ function close() {
377
+ if (!isOpen) {
378
+ // Already closed — persist (cheap, no-op when nothing changed) but
379
+ // skip emit so consumers don't see spurious 'dock:change' events.
380
+ persist();
381
+ return;
382
+ }
383
+ isOpen = false;
384
+ persist();
385
+ emitChange({ stateChanged: true, contextChanged: false });
386
+ }
387
+ function toggle(id) {
388
+ const prevIsOpen = isOpen;
389
+ const prevActive = activeTool;
390
+ if (id) {
391
+ if (!availableTools.some((t) => t.id === id))
392
+ return;
393
+ if (isOpen && activeTool === id) {
394
+ isOpen = false;
395
+ }
396
+ else {
397
+ activeTool = id;
398
+ isOpen = true;
399
+ }
400
+ persist();
401
+ if (isOpen !== prevIsOpen || activeTool !== prevActive) {
402
+ emitChange({ stateChanged: true, contextChanged: false });
403
+ }
404
+ return;
405
+ }
406
+ isOpen = !isOpen;
407
+ if (isOpen && !activeTool && availableTools.length > 0) {
408
+ activeTool = availableTools[0].id;
409
+ }
410
+ persist();
411
+ if (isOpen !== prevIsOpen || activeTool !== prevActive) {
412
+ emitChange({ stateChanged: true, contextChanged: false });
413
+ }
414
+ }
415
+ function setContextValue(ctx) {
416
+ // Strict-equality short-circuit: passing the same context reference is a
417
+ // no-op. Skips both the availability refresh and the `'dock:change'`
418
+ // emit so consumers (e.g. `<ToolsDock>`'s context-forwarding `$effect`)
419
+ // can call this repeatedly without amplifying side effects. Consumers
420
+ // who want a "force refresh" can pass a fresh object or `null` first.
421
+ //
422
+ // Compare against `rawContextRef` (a non-reactive shadow) rather than the
423
+ // `$state` value, because Svelte 5 wraps object `$state` in a Proxy and
424
+ // the original input would never `===` the proxied stored value.
425
+ //
426
+ // Internally the `context` `$state` is typed as the default
427
+ // `ToolsDockContext` so the runtime store stays generic-erased — the
428
+ // narrowed type only lives on the public boundary (this function
429
+ // signature and the `instance.context` getter).
430
+ const erased = ctx;
431
+ if (erased === rawContextRef)
432
+ return;
433
+ rawContextRef = erased;
434
+ context = erased;
435
+ if (fetchAvailability)
436
+ refreshAvailability();
437
+ // Emit AFTER kicking off availability refresh. The refresh is async and
438
+ // may emit a second event later if it clears `activeTool` — that is
439
+ // the intended behaviour (one event per observable state transition).
440
+ // `contextChanged: true` fires `'dock:context-changed'`; `stateChanged`
441
+ // stays false here because `setContext` itself doesn't touch isOpen/
442
+ // activeTool (the async availability refresh handles that).
443
+ emitChange({ stateChanged: false, contextChanged: true });
444
+ }
445
+ const instance = {
446
+ // Reactive getters — keep the api surface read-only.
447
+ get isOpen() {
448
+ return isOpen;
449
+ },
450
+ get activeTool() {
451
+ return activeTool;
452
+ },
453
+ get availableTools() {
454
+ return availableTools;
455
+ },
456
+ // Internal `context` `$state` is typed as the default-generic shape so
457
+ // the runtime store stays homogeneous. Cast at the public boundary —
458
+ // structurally a `ToolsDockContext<TData, TActions>` IS a
459
+ // `ToolsDockContext<defaults>` (the generics flow covariantly through
460
+ // the field shapes); the cast threads the consumer's narrowed type
461
+ // through to the API surface without forcing the internal store to
462
+ // carry the generic.
463
+ get context() {
464
+ return context;
465
+ },
466
+ open,
467
+ close,
468
+ toggle,
469
+ setContext: setContextValue,
470
+ refreshAvailability,
471
+ emit,
472
+ on,
473
+ // Framework-only members:
474
+ tools: registeredTools,
475
+ layout,
476
+ storageKey,
477
+ hydrate,
478
+ persist,
479
+ };
480
+ setContext(TOOLS_DOCK_KEY, instance);
481
+ // From this point forward, mutations may emit `'dock:change'`. Anything
482
+ // that ran during the factory body above (e.g. seeding `availableTools`
483
+ // from the registered tools) is treated as part of initialization and
484
+ // stays silent.
485
+ ready = true;
486
+ return instance;
487
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * useToolsDock - read the {@link ToolsDockApi} from Svelte context.
3
+ *
4
+ * Tools and arbitrary descendants of `<ToolsDock>` use this to obtain the
5
+ * dock instance that owns them — open/close themselves, push events through
6
+ * the typed bus, react to the current `context`, etc.
7
+ *
8
+ * Throws a clear error if called outside a `<ToolsDock>` provider tree so
9
+ * misuse fails loudly during development rather than producing silent nulls.
10
+ *
11
+ * The returned `dock.context` is the default {@link ToolsDockContext} shape.
12
+ * For typed access from within a tool body, the recommended pattern is to
13
+ * type the component's own `context` prop locally — see the JSDoc on
14
+ * {@link ToolDef.component} for an example. (`ToolDef` deliberately erases
15
+ * its context generic at registration time so the dock can store tools as
16
+ * a single homogeneous `ToolDef[]`.)
17
+ *
18
+ * @example
19
+ * ```svelte
20
+ * <script lang="ts">
21
+ * import { useToolsDock } from '@happyvertical/smrt-svelte/workspace';
22
+ * const dock = useToolsDock();
23
+ * </script>
24
+ *
25
+ * <button type="button" onclick={() => dock.close()}>Close</button>
26
+ * ```
27
+ */
28
+ import type { ToolsDockApi } from '../types.js';
29
+ /**
30
+ * Retrieve the {@link ToolsDockApi} from Svelte context.
31
+ *
32
+ * @throws Error when called outside a `<ToolsDock>` provider tree
33
+ */
34
+ export declare function useToolsDock(): ToolsDockApi;
35
+ /**
36
+ * Non-throwing variant — returns `null` outside a provider. Useful for
37
+ * optional integrations where a tool should degrade gracefully if not
38
+ * embedded inside a `<ToolsDock>`.
39
+ */
40
+ export declare function tryUseToolsDock(): ToolsDockApi | null;
41
+ //# sourceMappingURL=use-tools-dock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tools-dock.d.ts","sourceRoot":"","sources":["../../../../src/components/workspace/tools-dock/use-tools-dock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,YAAY,CAS3C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAErD"}