@happyvertical/smrt-svelte 0.55.6 → 0.55.8

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 (318) hide show
  1. package/AGENTS.md +9 -31
  2. package/README.md +195 -5
  3. package/agents/browser-ai.md +47 -0
  4. package/agents/command-palette.md +85 -0
  5. package/agents/import-export.md +62 -0
  6. package/agents/overview-surfaces.md +255 -0
  7. package/agents/screens.md +57 -0
  8. package/agents/workspace.md +202 -5
  9. package/dist/browser-ai/adapters/stt/dictation-source.d.ts.map +1 -1
  10. package/dist/browser-ai/adapters/stt/dictation-source.js +8 -2
  11. package/dist/browser-ai/adapters/stt/factory.d.ts +6 -3
  12. package/dist/browser-ai/adapters/stt/factory.d.ts.map +1 -1
  13. package/dist/browser-ai/adapters/stt/factory.js +19 -9
  14. package/dist/browser-ai/adapters/stt/index.d.ts +3 -1
  15. package/dist/browser-ai/adapters/stt/index.d.ts.map +1 -1
  16. package/dist/browser-ai/adapters/stt/index.js +3 -1
  17. package/dist/browser-ai/adapters/stt/local-speech-model.d.ts +111 -0
  18. package/dist/browser-ai/adapters/stt/local-speech-model.d.ts.map +1 -0
  19. package/dist/browser-ai/adapters/stt/local-speech-model.js +377 -0
  20. package/dist/browser-ai/adapters/stt/local-speech.d.ts +82 -0
  21. package/dist/browser-ai/adapters/stt/local-speech.d.ts.map +1 -0
  22. package/dist/browser-ai/adapters/stt/local-speech.js +317 -0
  23. package/dist/browser-ai/adapters/stt/local-speech.worker.d.ts +2 -0
  24. package/dist/browser-ai/adapters/stt/local-speech.worker.d.ts.map +1 -0
  25. package/dist/browser-ai/adapters/stt/local-speech.worker.js +32 -0
  26. package/dist/browser-ai/adapters/stt/transformers-env.d.ts +8 -0
  27. package/dist/browser-ai/adapters/stt/transformers-env.d.ts.map +1 -0
  28. package/dist/browser-ai/adapters/stt/transformers-env.js +17 -0
  29. package/dist/browser-ai/adapters/stt/types.d.ts +54 -9
  30. package/dist/browser-ai/adapters/stt/types.d.ts.map +1 -1
  31. package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts +5 -0
  32. package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts.map +1 -1
  33. package/dist/browser-ai/adapters/tts/browser-synthesis.js +83 -55
  34. package/dist/browser-ai/capabilities/speech-probe.d.ts +29 -0
  35. package/dist/browser-ai/capabilities/speech-probe.d.ts.map +1 -0
  36. package/dist/browser-ai/capabilities/speech-probe.js +19 -0
  37. package/dist/browser-ai/core/errors.d.ts +9 -0
  38. package/dist/browser-ai/core/errors.d.ts.map +1 -1
  39. package/dist/browser-ai/core/errors.js +12 -0
  40. package/dist/browser-ai/index.d.ts +1 -0
  41. package/dist/browser-ai/index.d.ts.map +1 -1
  42. package/dist/browser-ai/index.js +1 -0
  43. package/dist/components/app/AppShell.svelte +587 -33
  44. package/dist/components/app/AppShell.svelte.d.ts +75 -4
  45. package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
  46. package/dist/components/app/DockToggles.svelte +0 -1
  47. package/dist/components/app/dock-toggle.d.ts +7 -1
  48. package/dist/components/app/dock-toggle.d.ts.map +1 -1
  49. package/dist/components/app/index.d.ts +2 -1
  50. package/dist/components/app/index.d.ts.map +1 -1
  51. package/dist/components/app/slot-item.d.ts +21 -0
  52. package/dist/components/app/slot-item.d.ts.map +1 -0
  53. package/dist/components/app/slot-item.js +1 -0
  54. package/dist/components/command-palette/CommandPalette.svelte +75 -0
  55. package/dist/components/command-palette/CommandPalette.svelte.d.ts +22 -0
  56. package/dist/components/command-palette/CommandPalette.svelte.d.ts.map +1 -0
  57. package/dist/components/command-palette/CommandPaletteDialog.svelte +406 -0
  58. package/dist/components/command-palette/CommandPaletteDialog.svelte.d.ts +18 -0
  59. package/dist/components/command-palette/CommandPaletteDialog.svelte.d.ts.map +1 -0
  60. package/dist/components/command-palette/CommandPaletteTrigger.svelte +91 -0
  61. package/dist/components/command-palette/CommandPaletteTrigger.svelte.d.ts +17 -0
  62. package/dist/components/command-palette/CommandPaletteTrigger.svelte.d.ts.map +1 -0
  63. package/dist/components/command-palette/context.d.ts +18 -0
  64. package/dist/components/command-palette/context.d.ts.map +1 -0
  65. package/dist/components/command-palette/context.js +38 -0
  66. package/dist/components/command-palette/controller.svelte.d.ts +70 -0
  67. package/dist/components/command-palette/controller.svelte.d.ts.map +1 -0
  68. package/dist/components/command-palette/controller.svelte.js +379 -0
  69. package/dist/components/command-palette/hotkeys.d.ts +30 -0
  70. package/dist/components/command-palette/hotkeys.d.ts.map +1 -0
  71. package/dist/components/command-palette/hotkeys.js +161 -0
  72. package/dist/components/command-palette/index.d.ts +19 -0
  73. package/dist/components/command-palette/index.d.ts.map +1 -0
  74. package/dist/components/command-palette/index.js +17 -0
  75. package/dist/components/command-palette/match.d.ts +38 -0
  76. package/dist/components/command-palette/match.d.ts.map +1 -0
  77. package/dist/components/command-palette/match.js +172 -0
  78. package/dist/components/command-palette/providers.d.ts +159 -0
  79. package/dist/components/command-palette/providers.d.ts.map +1 -0
  80. package/dist/components/command-palette/providers.js +345 -0
  81. package/dist/components/command-palette/rank.d.ts +20 -0
  82. package/dist/components/command-palette/rank.d.ts.map +1 -0
  83. package/dist/components/command-palette/rank.js +74 -0
  84. package/dist/components/command-palette/types.d.ts +119 -0
  85. package/dist/components/command-palette/types.d.ts.map +1 -0
  86. package/dist/components/command-palette/types.js +10 -0
  87. package/dist/components/command-palette/use-provider.svelte.d.ts +14 -0
  88. package/dist/components/command-palette/use-provider.svelte.d.ts.map +1 -0
  89. package/dist/components/command-palette/use-provider.svelte.js +23 -0
  90. package/dist/components/forms/AddressInput.svelte +2 -15
  91. package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -1
  92. package/dist/components/forms/DateRangeInput.svelte +2 -15
  93. package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -1
  94. package/dist/components/forms/DateTimeInput.svelte +8 -15
  95. package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -1
  96. package/dist/components/forms/MeasurementInput.svelte +2 -15
  97. package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -1
  98. package/dist/components/forms/MoneyInput.svelte +8 -25
  99. package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -1
  100. package/dist/components/forms/NumberInput.svelte +7 -15
  101. package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -1
  102. package/dist/components/forms/PhoneInput.svelte +7 -15
  103. package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -1
  104. package/dist/components/forms/SelectInput.svelte +34 -40
  105. package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -1
  106. package/dist/components/forms/TextInput.svelte +20 -37
  107. package/dist/components/forms/TextInput.svelte.d.ts.map +1 -1
  108. package/dist/components/forms/TextareaInput.svelte +19 -35
  109. package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -1
  110. package/dist/components/import-export/ImportExport.svelte +678 -0
  111. package/dist/components/import-export/ImportExport.svelte.d.ts +5 -0
  112. package/dist/components/import-export/ImportExport.svelte.d.ts.map +1 -0
  113. package/dist/components/import-export/collection-adapter.d.ts +35 -0
  114. package/dist/components/import-export/collection-adapter.d.ts.map +1 -0
  115. package/dist/components/import-export/collection-adapter.js +42 -0
  116. package/dist/components/import-export/csv.d.ts +60 -0
  117. package/dist/components/import-export/csv.d.ts.map +1 -0
  118. package/dist/components/import-export/csv.js +192 -0
  119. package/dist/components/import-export/download.d.ts +4 -0
  120. package/dist/components/import-export/download.d.ts.map +1 -0
  121. package/dist/components/import-export/download.js +17 -0
  122. package/dist/components/import-export/export.d.ts +25 -0
  123. package/dist/components/import-export/export.d.ts.map +1 -0
  124. package/dist/components/import-export/export.js +68 -0
  125. package/dist/components/import-export/fields.d.ts +48 -0
  126. package/dist/components/import-export/fields.d.ts.map +1 -0
  127. package/dist/components/import-export/fields.js +103 -0
  128. package/dist/components/import-export/index.d.ts +12 -0
  129. package/dist/components/import-export/index.d.ts.map +1 -0
  130. package/dist/components/import-export/index.js +9 -0
  131. package/dist/components/import-export/mapping.d.ts +12 -0
  132. package/dist/components/import-export/mapping.d.ts.map +1 -0
  133. package/dist/components/import-export/mapping.js +38 -0
  134. package/dist/components/import-export/props.d.ts +34 -0
  135. package/dist/components/import-export/props.d.ts.map +1 -0
  136. package/dist/components/import-export/props.js +1 -0
  137. package/dist/components/import-export/report.d.ts +13 -0
  138. package/dist/components/import-export/report.d.ts.map +1 -0
  139. package/dist/components/import-export/report.js +50 -0
  140. package/dist/components/import-export/runner.d.ts +17 -0
  141. package/dist/components/import-export/runner.d.ts.map +1 -0
  142. package/dist/components/import-export/runner.js +39 -0
  143. package/dist/components/import-export/types.d.ts +100 -0
  144. package/dist/components/import-export/types.d.ts.map +1 -0
  145. package/dist/components/import-export/types.js +6 -0
  146. package/dist/components/import-export/validate.d.ts +39 -0
  147. package/dist/components/import-export/validate.d.ts.map +1 -0
  148. package/dist/components/import-export/validate.js +268 -0
  149. package/dist/components/overview/OverviewGrid.svelte +579 -0
  150. package/dist/components/overview/OverviewGrid.svelte.d.ts +5 -0
  151. package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -0
  152. package/dist/components/overview/WidgetOptionsForm.svelte +193 -0
  153. package/dist/components/overview/WidgetOptionsForm.svelte.d.ts +5 -0
  154. package/dist/components/overview/WidgetOptionsForm.svelte.d.ts.map +1 -0
  155. package/dist/components/overview/controller.svelte.d.ts +92 -0
  156. package/dist/components/overview/controller.svelte.d.ts.map +1 -0
  157. package/dist/components/overview/controller.svelte.js +336 -0
  158. package/dist/components/overview/format.d.ts +13 -0
  159. package/dist/components/overview/format.d.ts.map +1 -0
  160. package/dist/components/overview/format.js +45 -0
  161. package/dist/components/overview/grid-types.d.ts +52 -0
  162. package/dist/components/overview/grid-types.d.ts.map +1 -0
  163. package/dist/components/overview/grid-types.js +1 -0
  164. package/dist/components/overview/index.d.ts +24 -0
  165. package/dist/components/overview/index.d.ts.map +1 -0
  166. package/dist/components/overview/index.js +22 -0
  167. package/dist/components/overview/load.d.ts +30 -0
  168. package/dist/components/overview/load.d.ts.map +1 -0
  169. package/dist/components/overview/load.js +92 -0
  170. package/dist/components/overview/markdown.d.ts +53 -0
  171. package/dist/components/overview/markdown.d.ts.map +1 -0
  172. package/dist/components/overview/markdown.js +203 -0
  173. package/dist/components/overview/model.d.ts +100 -0
  174. package/dist/components/overview/model.d.ts.map +1 -0
  175. package/dist/components/overview/model.js +460 -0
  176. package/dist/components/overview/recipe-widgets.d.ts +77 -0
  177. package/dist/components/overview/recipe-widgets.d.ts.map +1 -0
  178. package/dist/components/overview/recipe-widgets.js +151 -0
  179. package/dist/components/overview/registry.d.ts +45 -0
  180. package/dist/components/overview/registry.d.ts.map +1 -0
  181. package/dist/components/overview/registry.js +112 -0
  182. package/dist/components/overview/resize.d.ts +25 -0
  183. package/dist/components/overview/resize.d.ts.map +1 -0
  184. package/dist/components/overview/resize.js +41 -0
  185. package/dist/components/overview/schema.d.ts +34 -0
  186. package/dist/components/overview/schema.d.ts.map +1 -0
  187. package/dist/components/overview/schema.js +180 -0
  188. package/dist/components/overview/server.d.ts +14 -0
  189. package/dist/components/overview/server.d.ts.map +1 -0
  190. package/dist/components/overview/server.js +13 -0
  191. package/dist/components/overview/types.d.ts +235 -0
  192. package/dist/components/overview/types.d.ts.map +1 -0
  193. package/dist/components/overview/types.js +17 -0
  194. package/dist/components/overview/widgets/ChartWidget.svelte +111 -0
  195. package/dist/components/overview/widgets/ChartWidget.svelte.d.ts +6 -0
  196. package/dist/components/overview/widgets/ChartWidget.svelte.d.ts.map +1 -0
  197. package/dist/components/overview/widgets/MetricWidget.svelte +86 -0
  198. package/dist/components/overview/widgets/MetricWidget.svelte.d.ts +6 -0
  199. package/dist/components/overview/widgets/MetricWidget.svelte.d.ts.map +1 -0
  200. package/dist/components/overview/widgets/NoteWidget.svelte +61 -0
  201. package/dist/components/overview/widgets/NoteWidget.svelte.d.ts +5 -0
  202. package/dist/components/overview/widgets/NoteWidget.svelte.d.ts.map +1 -0
  203. package/dist/components/overview/widgets/RecordListWidget.svelte +91 -0
  204. package/dist/components/overview/widgets/RecordListWidget.svelte.d.ts +6 -0
  205. package/dist/components/overview/widgets/RecordListWidget.svelte.d.ts.map +1 -0
  206. package/dist/components/overview/widgets/ShortcutsWidget.svelte +80 -0
  207. package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts +6 -0
  208. package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts.map +1 -0
  209. package/dist/components/overview/widgets/core.d.ts +44 -0
  210. package/dist/components/overview/widgets/core.d.ts.map +1 -0
  211. package/dist/components/overview/widgets/core.js +222 -0
  212. package/dist/components/overview/widgets/data.d.ts +76 -0
  213. package/dist/components/overview/widgets/data.d.ts.map +1 -0
  214. package/dist/components/overview/widgets/data.js +40 -0
  215. package/dist/components/screens/DetailScreen.svelte +220 -0
  216. package/dist/components/screens/DetailScreen.svelte.d.ts +5 -0
  217. package/dist/components/screens/DetailScreen.svelte.d.ts.map +1 -0
  218. package/dist/components/screens/EditForm.svelte +313 -0
  219. package/dist/components/screens/EditForm.svelte.d.ts +5 -0
  220. package/dist/components/screens/EditForm.svelte.d.ts.map +1 -0
  221. package/dist/components/screens/ListScreen.svelte +191 -0
  222. package/dist/components/screens/ListScreen.svelte.d.ts +5 -0
  223. package/dist/components/screens/ListScreen.svelte.d.ts.map +1 -0
  224. package/dist/components/screens/RecipeScreens.svelte +237 -0
  225. package/dist/components/screens/RecipeScreens.svelte.d.ts +5 -0
  226. package/dist/components/screens/RecipeScreens.svelte.d.ts.map +1 -0
  227. package/dist/components/screens/fields.d.ts +54 -0
  228. package/dist/components/screens/fields.d.ts.map +1 -0
  229. package/dist/components/screens/fields.js +229 -0
  230. package/dist/components/screens/index.d.ts +8 -0
  231. package/dist/components/screens/index.d.ts.map +1 -0
  232. package/dist/components/screens/index.js +6 -0
  233. package/dist/components/screens/types.d.ts +215 -0
  234. package/dist/components/screens/types.d.ts.map +1 -0
  235. package/dist/components/screens/types.js +1 -0
  236. package/dist/components/screens/values.d.ts +62 -0
  237. package/dist/components/screens/values.d.ts.map +1 -0
  238. package/dist/components/screens/values.js +289 -0
  239. package/dist/components/sortable/Sortable.svelte +6 -33
  240. package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -1
  241. package/dist/components/sortable/announce.d.ts +5 -0
  242. package/dist/components/sortable/announce.d.ts.map +1 -0
  243. package/dist/components/sortable/announce.js +33 -0
  244. package/dist/components/sortable/controller.svelte.d.ts +10 -0
  245. package/dist/components/sortable/controller.svelte.d.ts.map +1 -1
  246. package/dist/components/sortable/controller.svelte.js +29 -7
  247. package/dist/components/workspace/admin-shell/AdminShell.svelte +424 -58
  248. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +27 -2
  249. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
  250. package/dist/components/workspace/admin-shell/ShellBrand.svelte +86 -0
  251. package/dist/components/workspace/admin-shell/ShellBrand.svelte.d.ts +18 -0
  252. package/dist/components/workspace/admin-shell/ShellBrand.svelte.d.ts.map +1 -0
  253. package/dist/components/workspace/admin-shell/ShellIconButton.svelte +77 -0
  254. package/dist/components/workspace/admin-shell/ShellIconButton.svelte.d.ts +26 -0
  255. package/dist/components/workspace/admin-shell/ShellIconButton.svelte.d.ts.map +1 -0
  256. package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +88 -16
  257. package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte.d.ts.map +1 -1
  258. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte +531 -0
  259. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts +26 -0
  260. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts.map +1 -0
  261. package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte +57 -0
  262. package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte.d.ts +22 -0
  263. package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte.d.ts.map +1 -0
  264. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte +290 -0
  265. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts +32 -0
  266. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts.map +1 -0
  267. package/dist/components/workspace/admin-shell/TenantNav.svelte +67 -2
  268. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +8 -0
  269. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
  270. package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts +67 -0
  271. package/dist/components/workspace/admin-shell/layout-controller.svelte.d.ts.map +1 -1
  272. package/dist/components/workspace/admin-shell/layout-controller.svelte.js +129 -1
  273. package/dist/components/workspace/admin-shell/layout.d.ts +122 -0
  274. package/dist/components/workspace/admin-shell/layout.d.ts.map +1 -1
  275. package/dist/components/workspace/admin-shell/layout.js +410 -10
  276. package/dist/components/workspace/admin-shell/settings.js +4 -4
  277. package/dist/components/workspace/admin-shell/shell-icons.d.ts +45 -0
  278. package/dist/components/workspace/admin-shell/shell-icons.d.ts.map +1 -0
  279. package/dist/components/workspace/admin-shell/shell-icons.js +66 -0
  280. package/dist/components/workspace/admin-shell/slot-labels.d.ts +33 -0
  281. package/dist/components/workspace/admin-shell/slot-labels.d.ts.map +1 -0
  282. package/dist/components/workspace/admin-shell/slot-labels.js +33 -0
  283. package/dist/components/workspace/admin-shell/slots.d.ts +50 -0
  284. package/dist/components/workspace/admin-shell/slots.d.ts.map +1 -0
  285. package/dist/components/workspace/admin-shell/slots.js +77 -0
  286. package/dist/components/workspace/admin-shell/state.svelte.d.ts +35 -0
  287. package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
  288. package/dist/components/workspace/admin-shell/state.svelte.js +111 -0
  289. package/dist/components/workspace/admin-shell/types.d.ts +101 -1
  290. package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
  291. package/dist/components/workspace/index.d.ts +9 -2
  292. package/dist/components/workspace/index.d.ts.map +1 -1
  293. package/dist/components/workspace/index.js +6 -0
  294. package/dist/components/workspace/manifest-nav.d.ts +20 -0
  295. package/dist/components/workspace/manifest-nav.d.ts.map +1 -1
  296. package/dist/components/workspace/manifest-nav.js +42 -13
  297. package/dist/i18n/server.d.ts +6 -0
  298. package/dist/i18n/server.d.ts.map +1 -1
  299. package/dist/i18n/server.js +6 -0
  300. package/dist/i18n/strings.import-export.d.ts +88 -0
  301. package/dist/i18n/strings.import-export.d.ts.map +1 -0
  302. package/dist/i18n/strings.import-export.js +88 -0
  303. package/dist/i18n/strings.overview.d.ts +100 -0
  304. package/dist/i18n/strings.overview.d.ts.map +1 -0
  305. package/dist/i18n/strings.overview.js +107 -0
  306. package/dist/i18n/strings.palette.d.ts +18 -0
  307. package/dist/i18n/strings.palette.d.ts.map +1 -0
  308. package/dist/i18n/strings.palette.js +18 -0
  309. package/dist/i18n/strings.screens.d.ts +31 -0
  310. package/dist/i18n/strings.screens.d.ts.map +1 -0
  311. package/dist/i18n/strings.screens.js +31 -0
  312. package/dist/i18n/strings.workspace.d.ts +49 -0
  313. package/dist/i18n/strings.workspace.d.ts.map +1 -1
  314. package/dist/i18n/strings.workspace.js +49 -0
  315. package/package.json +59 -19
  316. package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts +0 -51
  317. package/dist/browser-ai/adapters/stt/whisper-wasm.d.ts.map +0 -1
  318. package/dist/browser-ai/adapters/stt/whisper-wasm.js +0 -380
package/AGENTS.md CHANGED
@@ -13,11 +13,15 @@ subpath you are editing. This file keeps what holds in every module.
13
13
  | `src/i18n/` (`./i18n` + `./i18n/server`) | `defineMessages` / `useI18n` / `<Trans>` / `buildI18nSnapshot`, the template-vs-render split, and hardcoded-string enforcement | [agents/i18n.md](agents/i18n.md) |
14
14
  | `src/themes/` + `src/theme/` | which theme system is canonical and the full `--smrt-*` design-token vocabulary with its alias rules | [agents/themes.md](agents/themes.md) |
15
15
  | `src/test-support/` + `__tests__/` | the golden-test harness and pattern for Svelte component tests | [agents/testing.md](agents/testing.md) |
16
+ | `src/components/import-export/` (`./import-export`) | `ImportExport` CSV/TSV import (column mapping, validation preview, error report) and export (column selection) driven by collection definitions + resolved field policy, over a pure Node-tested CSV layer (#3715) | [agents/import-export.md](agents/import-export.md) |
16
17
  | `src/components/settings/` (`./settings`) | `SettingsCatalog`, `paginateSettingsCatalog`, and the summary-vs-detail scalability contract | [agents/settings.md](agents/settings.md) |
18
+ | `src/components/screens/` (`./screens`) | `RecipeScreens` / `ListScreen` / `DetailScreen` / `EditForm`: list, view, create and edit derived from a generated web definition plus resolved field policy; pure `deriveScreenFields` selection, minor-unit money handling, transport-neutral source (#3718) | [agents/screens.md](agents/screens.md) |
17
19
  | `src/components/app/` (`./app`) | `AppShell` (Provider + ThemeProvider + theme CSS + AdminShell + nav/dock slots), `OwnerSetupForm` (props-driven first-run owner form), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp`. Browser-only; no `$app/*` or server imports | [agents/workspace.md](agents/workspace.md#app-shell-and-owner-setup-app) |
18
20
  | `src/components/workspace/` (`./workspace` + `./web`) | the AdminShell family and its principles, the legacy ToolsDock surface, the `./web` activity-feed and `updateAvailable` adapters, and server-side dock gates | [agents/workspace.md](agents/workspace.md) |
21
+ | `src/components/command-palette/` (`./command-palette`) | `CommandPalette` trigger + dialog, `PaletteProvider` contract, nav and manifest providers (#3713) | [agents/command-palette.md](agents/command-palette.md) |
22
+ | `src/components/overview/` (`./overview` + `./overview/server`) | customizable overview surfaces: `OverviewGrid` flow grid (span 1-4, keyboard reorder/resize) joined to the shell's layout edit mode, host-owned `createOverview` controller, widget registry with versioned option schemas validated on save and load, the server `load(options, ctx)` contract (`loadOverview`), the metric/chart/records/shortcuts/note core widgets, and `registerRecipeWidgets` (recipe `widget` surfaces to registry registrations, injected module resolver) (#3727) | [agents/overview-surfaces.md](agents/overview-surfaces.md) |
19
23
  | `src/web/remote-query.svelte.ts` | Svelte 5 binding for query-shaped remote pages: rows, page, totals, loading/refreshing/stale/error, retry, last-updated, and query-scoped live subscriptions (#2445) | — |
20
- | `src/web/list-data-surface.svelte.ts` (`mountListDataSurface`) | One-call registration of an existing, non-`DataTable` list (already mirroring a headless `DataTableController`) as a mounted `DataSurfaceDescriptor` — a same-behavior port of `registerContentListDataSurface`'s registration/translation logic (`@happyvertical/smrt-content/svelte`), generalized off ContentList's view-mode concept, so any custom list markup can adopt it directly instead of hand-mirroring the registry contract. Not yet unified behind a shared `@happyvertical/smrt-ui/data` implementation (#2917) — this copy is currently ahead; see its own module doc comment for the current, authoritative list of divergences #2917 must adopt rather than assume parity (#2906) | — |
24
+ | `src/web/list-data-surface.svelte.ts` (`mountListDataSurface`) | Registers an existing non-`DataTable` list (mirroring a `DataTableController`) as a mounted `DataSurfaceDescriptor`; a same-behavior port of `registerContentListDataSurface`, not yet unified behind smrt-ui (#2917). The module doc comment is the authoritative list of divergences (#2906) | — |
21
25
  | `src/web/webmcp-provider.ts` | Provider config for generated data/model WebMCP tools: definitions, effect policy, namespace, budget, legacy/canonical filters, and fetcher seams (#2520) | — |
22
26
  | `src/web/webmcp-ui.ts` | Fixed, low-cardinality WebMCP adapter over the Provider's mounted form-control and data-surface registries (#2521) | — |
23
27
  | `src/web/webmcp.svelte.ts` (`useWebMcpTool`) | Component-owned bespoke WebMCP tool. Routes through `@happyvertical/smrt-web`'s `registerWebMcpBespokeTool`, so it shares the fail-closed effect classification and `effects` exposure policy of generated tools — undeclared `annotations` classify destructive and are excluded by default. `namespace` and `maxTools` never apply to a bespoke tool (#2586) | — |
@@ -205,35 +209,9 @@ for a data-surface one — for exactly the component's lifetime.
205
209
 
206
210
  - **Preload strategies**: `none`, `eager`, `idle` (recommended), `on-visible`
207
211
  - **Warm client cache**: module-level Map survives navigation/remounts -- avoids re-downloading WASM/models
208
- - **Adapters**: STT (browser-speech, whisper-cpp, whisper-wasm), TTS (browser-synthesis), LLM (webllm, transformers-llm)
212
+ - **Adapters**: STT (browser-speech, whisper-cpp, whisper-local = alias whisper-wasm), TTS (browser-synthesis), LLM (webllm, transformers-llm)
209
213
  - Cache API: `getCachedSTT()`, `getCachedTTS()`, `getCachedLLM()`, `getCacheStats()`, `clearAllCaches()`
210
- - **Inference backends (browser-ai)**: two `@happyvertical/smrt-web/ai` `InferenceBackend`s, both
211
- `kind: 'local'`, both refusing `tool`/`function` messages, non-string content, `tool_calls` and
212
- `options.tools` with `InferencePathError` (`unsupported_message`) through the SHARED
213
- `assertTextOnlyTurn`, so a per-call switch between backends never changes what a turn means.
214
- - `createWebLlmInferenceBackend()` wraps an `LLMAdapter` — `status` derives from the adapter's
215
- `initState` (plus an explicit in-flight flag, because the adapter only flips to `initializing`
216
- after its own awaits), `progress` mirrors `DownloadProgressInfo`, and `load()`/`unload()` drive
217
- `ensureInitialized`/`unloadModel`. It reports `unavailable` without WebGPU so an `auto` path skips
218
- it. Pass `adapter` to share the app-state-managed warm-cached adapter; construct once, so two
219
- callers cannot each start an unshared adapter and a second download.
220
- Its `loadModule` option matters: the default `importOptional()` resolves a VARIABLE specifier,
221
- which a browser cannot resolve (`TypeError: Failed to resolve module specifier`) — a host that has
222
- `@mlc-ai/web-llm` must pass `() => import('@mlc-ai/web-llm')` so the bundler rewrites a static one.
223
- It does NOT forward `signal` (the adapter has no cancellation seam).
224
- - `createBitGpuInferenceBackend()` wraps `bitgpu` (MIT, optional peer), the engine behind the
225
- Bonsai WebGPU demo PrismML's own docs list as their in-browser option. `loadBitGpu`/`loadChat`
226
- are REQUIRED loaders (`() => import('bitgpu')`, `() => import('bitgpu/chat')`) — a static import
227
- here would fail the build for every consumer without the optional peer, and a bare specifier is
228
- not resolvable by a browser either. `bitgpu`'s `LoadProgress.phase` maps to `InferenceProgress`
229
- (`manifest`/`weights` → `downloading`, `pipelines` → `extracting`). Unlike the WebLLM backend it
230
- **forwards `signal`** — bitgpu aborts a live generation — and it does NOT lazily load: weights
231
- run to GBs, so a turn before `load()` fails with a named reason. `model` in the per-call options
232
- is ignored (one engine binds one model), and bitgpu's tools/JSON-schema/think support is
233
- deliberately left unexposed for now so the text-only invariant holds across backends.
234
- - **`ModelStatusControl.svelte`**: the user-facing model lifecycle surface (state, Load/Unload,
235
- download progress) driven entirely by a backend's own `status`/`progress`/`subscribe`, so it works
236
- without a `<Provider>` ancestor. `unavailable` is a first-class state that offers NO load action.
214
+ - **On-device speech and inference backends** (`whisper-local`/`moonshine` adapters, `createWebLlmInferenceBackend`, `createBitGpuInferenceBackend`, `ModelStatusControl`): see [agents/browser-ai.md](agents/browser-ai.md).
237
215
 
238
216
  ## Permission Action
239
217
 
@@ -257,5 +235,5 @@ for a data-surface one — for exactly the component's lifetime.
257
235
  - `@happyvertical/smrt-types` (shared types) — includes the identity data contracts (`User`, `Role`, `Membership`, `Tenant`) the role/membership components type against, so no dependency on `smrt-users` / `smrt-profiles` is needed
258
236
  - `@happyvertical/smrt-ui` (UI runtime: primitives, theme system, i18n client, module registry) is a hard `dependency`. The agent-admin shells that used to type against `@happyvertical/smrt-agents/ui` moved to `@happyvertical/smrt-agents/svelte` (#1589), so `smrt-agents` is no longer a dependency here — this drops smrt-svelte below smrt-agents in the package DAG.
259
237
  - `@happyvertical/smrt-languages` is a hard `dependency` (not an optional peer): the Node-only `/i18n/server` subpath imports its resolver. The browser bundle still excludes it — the client `/i18n` layer never imports the languages root, so it tree-shakes out.
260
- - `@happyvertical/logger` (SDK) is a `dependency` — the console logger used for voice/AI error reporting in the form components. Consume it **only** through `src/internal/logger.ts`, never `createLogger()` at module scope: `createLogger()` reads `HAVE_LOGGER_LEVEL` from `process.env`, so a top-level call throws `ReferenceError: process is not defined` in the browser and kills client-side hydration under `vite dev` (prod builds tree-shake/define it away, so this only bites in dev). The `internal/logger` wrapper constructs the logger lazily and falls back to a bare `ConsoleLogger` when `process.env` is absent, keeping this browser-reachable module (imported by `Provider` + the form primitives) safe.
261
- - Peer (all optional): `svelte` >=5.18.2, plus the browser-AI engines (`@huggingface/transformers`, `@mlc-ai/web-llm`, `@remotion/whisper-web`, `@xenova/transformers`) and `chrono-node`.
238
+ - `@happyvertical/logger` (SDK) is a `dependency` for voice/AI error reporting in the form components. Consume it **only** through `src/internal/logger.ts`, never `createLogger()` at module scope: it reads `process.env`, which throws `ReferenceError` in the browser under `vite dev` and kills hydration. The wrapper builds the logger lazily and falls back to a bare `ConsoleLogger`.
239
+ - Peer (all optional): `svelte` >=5.18.2, plus the browser-AI engines (`@happyvertical/speech`, `@huggingface/transformers`, `@mlc-ai/web-llm`, `@remotion/whisper-web`) and `chrono-node`.
package/README.md CHANGED
@@ -32,6 +32,50 @@ pipeline (`opportunity.stage`) without importing `@happyvertical/smrt-projects`.
32
32
 
33
33
  Svelte 5 component library for the s-m-r-t framework. Provides UI components, browser AI integration (STT/TTS/LLM with warm cache), a theme system, permission-aware rendering, and module UI registry for agent admin panels.
34
34
 
35
+ ## Import and export
36
+
37
+ `@happyvertical/smrt-svelte/import-export` provides `ImportExport`, a CSV and
38
+ TSV import/export panel for any collection. Spreadsheet users save as CSV;
39
+ there is no `.xlsx` reader. Import is a guided flow: pick a file, map each
40
+ column to a field (auto-detected from the field name, label, or alias),
41
+ check a validation preview, then import. The preview is the dry run and writes
42
+ nothing. Rows that fail validation are listed by file line with the offending
43
+ value, and are downloadable as a CSV error report. Valid rows are created one
44
+ request each, so a server rejection fails only that row. Export lets the user
45
+ choose columns, delimiter, and header style; the default `name` headers
46
+ re-import cleanly.
47
+
48
+ The columns come from the same sources as the generated forms:
49
+ `fieldsFromCollectionDefinition(definition, { policy })` reads the collection
50
+ definition (the manifest) and a resolved field policy. A policy-`hidden` field
51
+ is neither imported nor exported, a `locked` field is never overwritten, and a
52
+ resolved default fills an empty or unmapped cell. `createCollectionImportExport`
53
+ binds the panel to the generated CRUD fetchers, so import and export go through
54
+ the same authorized REST routes as every other client.
55
+
56
+ ```svelte
57
+ <script lang="ts">
58
+ import {
59
+ ImportExport,
60
+ createCollectionImportExport,
61
+ } from '@happyvertical/smrt-svelte/import-export';
62
+
63
+ const io = createCollectionImportExport({ definition, fetchers, fieldOptions: { policy } });
64
+ </script>
65
+
66
+ <ImportExport
67
+ fields={io.fields}
68
+ createRecord={io.createRecord}
69
+ loadRows={io.loadRows}
70
+ filename="products"
71
+ />
72
+ ```
73
+
74
+ The CSV layer (`parseTable`, `validateRows`, `buildExportFile`, `runImport`)
75
+ is pure and runs in Node. Exports neutralize spreadsheet formulas in text
76
+ cells. See [agents/import-export.md](./agents/import-export.md) for the
77
+ contract.
78
+
35
79
  ## Sortable and shell layout
36
80
 
37
81
  `@happyvertical/smrt-svelte/sortable` provides `Sortable`, an accessible
@@ -40,7 +84,7 @@ items that share Board's drag engine. `AppShell` lets users customize their
40
84
  shell: pass `layout` and `onlayoutchange` to own persistence (for example in an
41
85
  exported app blueprint), or neither to store it in the user's settings. Mount
42
86
  `ShellLayoutEditor` (from `/app` or `/workspace`) on a settings page, and call
43
- `useShellLayout()` to make the same changes from code or an assistant. See
87
+ `useShellLayout()` to make the same changes from code or an assistant. Users can rename sections and individual navigation entries (`items`, `renameItem`), hide section titles, and create or delete their own sections. See
44
88
  `agents/workspace.md`; the pure `ShellLayout` model is published without Svelte
45
89
  as `@happyvertical/smrt-svelte/workspace/layout`.
46
90
 
@@ -50,6 +94,16 @@ as `@happyvertical/smrt-svelte/workspace/layout`.
50
94
  </AppShell>
51
95
  ```
52
96
 
97
+ Opt in to editing the real shell in place with `layoutEditing` on `AppShell`: a
98
+ pencil toggle ("Edit layout", highlighted while editing; press again or Escape to exit) joins the header (as does the app title, a movable
99
+ `item:brand` in `header.start`), and while on, every slot is a
100
+ labelled drop zone, shell items and navigation get grips (drag, or Space and
101
+ arrow keys), section headings get icon overlays and a floating toolbar, and
102
+ hidden regions show as strips. Apps add per-section icon buttons (an Options
103
+ gear, Help) with `sectionActions`; pass `layoutEditing={{ floating: true }}` to pin the
104
+ toggle in the top-right corner instead of the header; `useShellLayout()` exposes `editing` and
105
+ `setEditing`. See `agents/workspace.md`.
106
+
53
107
  ## Installation
54
108
 
55
109
  ```bash
@@ -288,6 +342,60 @@ bind legacy name-based cleanup to registrations made by that caller, so
288
342
  overlapping same-name fields can unmount in either order without retaining a
289
343
  detached control.
290
344
 
345
+ ### Voice typing where the browser cannot (on-device Whisper and Moonshine)
346
+
347
+ Browsers differ on speech recognition: Chrome and Safari have it, Firefox does
348
+ not, and Brave has the API without a speech service behind it. `probeBrowserSpeech()`
349
+ says which you have (`'works' | 'missing' | 'unreliable'`) without a network
350
+ call or a microphone prompt. For the last two, offer a one-time model download
351
+ and dictate with a speech model running in the browser (WebGPU where available,
352
+ single-thread WASM otherwise; no cross-origin isolation needed). The engine is
353
+ `@happyvertical/speech/local` (an optional peer, `>=0.102.5`, as is
354
+ `@huggingface/transformers`).
355
+
356
+ | `model` | Size | Notes |
357
+ | --- | --- | --- |
358
+ | `moonshine-tiny` (`onnx-community/moonshine-tiny-ONNX`) | ~32 MB | English, fastest: best for live dictation |
359
+ | `moonshine-base` (`onnx-community/moonshine-base-ONNX`) | ~67 MB | English, more accurate |
360
+ | `whisper-tiny.en` (default) | ~45 MB | English |
361
+ | `whisper-base.en` / `whisper-small.en` | ~85 / ~260 MB | English |
362
+ | any Hugging Face id, e.g. `onnx-community/whisper-base` | varies | multilingual Whisper |
363
+
364
+ ```ts
365
+ import {
366
+ createLocalSpeechModel,
367
+ createSttDictationSource,
368
+ probeBrowserSpeech,
369
+ } from '@happyvertical/smrt-svelte/browser-ai';
370
+ // The worker is the one module that imports the optional peers statically,
371
+ // so only apps that build it bundle them.
372
+ import SpeechWorker from '@happyvertical/smrt-svelte/browser-ai/whisper-worker?worker';
373
+
374
+ if ((await probeBrowserSpeech()) !== 'works') {
375
+ const model = createLocalSpeechModel({
376
+ model: 'moonshine-tiny',
377
+ createWorker: () => new SpeechWorker(),
378
+ loadSpeech: () => import('@happyvertical/speech/local'),
379
+ });
380
+ model.estimateSize(); // ~32 MB, for the consent text
381
+ await model.isCached(); // already downloaded on this device?
382
+ await model.load({ onProgress, signal }); // downloading -> extracting ("Getting ready") -> complete; abort() cancels
383
+ const dictation = createSttDictationSource({ type: 'moonshine', modelHandle: model });
384
+ }
385
+ ```
386
+
387
+ `createWhisperLocalModel`, `{ type: 'whisper-local' }` and the `whisper-wasm`
388
+ alias keep working. Without `createWorker` the model runs on the page's thread
389
+ and `loadModule: () => import('@huggingface/transformers')` supplies the
390
+ runtime. With a worker, `device` and `dtype` are the worker entry's (`auto`
391
+ and `q8`).
392
+
393
+ Push-to-talk: the microphone records until stopped, then one final result is
394
+ emitted. For hands-free dictation (each sentence written down when the speaker
395
+ pauses) give smrt-ui's `Dictation` `mode: 'hands-free'` and
396
+ `createHandsFreeCapture`; these adapters' `transcribePcm()` writes down each
397
+ utterance. English-only models (`*.en`, Moonshine) ignore a requested language.
398
+
291
399
  ### Form Components
292
400
 
293
401
  ```svelte
@@ -496,6 +604,12 @@ keys the shell renders exactly as before.
496
604
  focus (unless something inside already has it) and returns it on close;
497
605
  Escape or a scrim click closes it, sliding it back out as the scrim fades
498
606
  (no motion under `prefers-reduced-motion`). Resizing applies only while docked.
607
+ - **Railless edges**: `rail: false` gives a side edge no rail (no tool buttons, open or closed); closed, it takes
608
+ no space and renders nothing to see or tab to, and opens from elsewhere (a
609
+ header dock toggle, `useShellDock()`). Pair it with `presentation: 'overlay'`
610
+ for a chat that slides over the page. Layout edit mode leaves a railless edge
611
+ as it is (closed stays closed) and, while editing, shows a small "Open
612
+ <tool>" tab on the shell's right edge when it has content.
499
613
  - **Kept panels**: `keepMounted: true` keeps a collapsed edge's panel content
500
614
  (`appPanel`, `tenantPanel`, the focus panel, `systemPanel`) mounted with the
501
615
  `hidden` attribute instead of unmounting it, so component state (a chat
@@ -520,10 +634,67 @@ keys the shell renders exactly as before.
520
634
  - **Migration guide** (first-generation `WorkspaceShell`/`RoleShell` →
521
635
  `AdminShell`; adoption is additive and non-breaking):
522
636
  [`src/components/workspace/MIGRATION.md`](./src/components/workspace/MIGRATION.md)
523
- - **Playground demos**: `playground/src/routes/admin-shell` exercises all four
637
+ - **Playground demos**: `playground/src/routes/command-palette` shows the palette in the header slot;
638
+ `playground/src/routes/admin-shell` exercises all four
524
639
  scopes, focus tools, and activities; `admin-shell-activity-feed` and
525
640
  `admin-shell-system-feed` show live feeds.
526
641
 
642
+ ### Command palette and global search
643
+
644
+ `@happyvertical/smrt-svelte/command-palette` is a keyboard-first "find anything"
645
+ dialog (Ctrl/Cmd+K) with a provider contract. Anything can register rows: the
646
+ shell navigation, "New invoice" commands and cross-model record search derived
647
+ from the manifest, or your own commands.
648
+
649
+ ```ts
650
+ import {
651
+ CommandPalette,
652
+ createCommandPalette,
653
+ createModelProviders,
654
+ createNavigationProvider,
655
+ } from '@happyvertical/smrt-svelte/command-palette';
656
+
657
+ const palette = createCommandPalette({
658
+ navigate: goto,
659
+ providers: [
660
+ createNavigationProvider({ nav, groups }),
661
+ ...createModelProviders({ manifest, pagesBasePath: '/app' }),
662
+ ],
663
+ });
664
+ ```
665
+
666
+ Render `<CommandPalette {palette} />` as an `AppShell` `slotItems` entry
667
+ (usually `header.center`). See
668
+ [`agents/command-palette.md`](./agents/command-palette.md) for the provider
669
+ contract, accessibility behavior, and the record-search limits.
670
+
671
+ ### Customizable overviews
672
+
673
+ `@happyvertical/smrt-svelte/overview` turns an overview page into a grid of
674
+ registered widgets (metric, chart, record list, shortcuts, note) that admins
675
+ reorder, resize, configure, add and remove in the shell's layout edit mode,
676
+ inside an allowed set the page declares. A saved overview is declarative data:
677
+ widget options are validated against versioned schemas on save and on load, and
678
+ widget data comes from a server `load(options, ctx)` that runs inside the page's
679
+ load with the user's permissions, so the page renders fully on the server.
680
+ Persistence is host-owned (the same pattern as the shell layout).
681
+
682
+ ```ts
683
+ import {
684
+ createOverview,
685
+ OverviewGrid,
686
+ registerCoreWidgets,
687
+ } from '@happyvertical/smrt-svelte/overview';
688
+ import {
689
+ defineOverview,
690
+ loadOverview,
691
+ resolveOverview,
692
+ } from '@happyvertical/smrt-svelte/overview/server';
693
+ ```
694
+
695
+ See [`agents/overview-surfaces.md`](./agents/overview-surfaces.md) for the data
696
+ model, the validation rules, the server load contract and the extension points.
697
+
527
698
  ## Exports
528
699
 
529
700
  ### Entry Points
@@ -535,10 +706,15 @@ importable, even if it appears in `dist/`.
535
706
  |-------------|----------|
536
707
  | `@happyvertical/smrt-svelte` | `Provider`, hooks (`useAppState`, `useAuth`, `useLLM`, `useSocket`, `useSTT`, `useTheme`, `useTTS`), app state/context, `ModulePanel`, and the form components below |
537
708
  | `@happyvertical/smrt-svelte/forms` | Form inputs (TextInput, Select, MoneyInput, DateTimeInput, Toggle, etc.) |
709
+ | `@happyvertical/smrt-svelte/import-export` | `ImportExport` (CSV/TSV import with column mapping, validation preview and error report; export with column selection), `createCollectionImportExport`, `fieldsFromCollectionDefinition`, and the pure CSV layer |
538
710
  | `@happyvertical/smrt-svelte/settings` | Server-paged settings search, selection, and list/detail layout (`SettingsCatalog`, `paginateSettingsCatalog`) |
711
+ | `@happyvertical/smrt-svelte/screens` | List, view, create and edit screens derived from a generated web definition and resolved field policy (`RecipeScreens`, `ListScreen`, `DetailScreen`, `EditForm`) |
539
712
  | `@happyvertical/smrt-svelte/workspace` | AdminShell, ShellState, tenant nav, focus tools, settings, activities, and system/app panels |
540
- | `@happyvertical/smrt-svelte/app` | `AppShell` (Provider + themes + AdminShell + nav/dock slots, `dockToggles` header buttons), `OwnerSetupForm` (first-run owner setup), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp` |
713
+ | `@happyvertical/smrt-svelte/app` | `AppShell` (Provider + themes + AdminShell + nav/dock slots, `dockToggles` buttons and host `slots` for the header/footer/sidebar regions), `OwnerSetupForm` (first-run owner setup), `ShellSettingsPage`, `RuntimeDiagnosticsWebMcp` |
541
714
  | `@happyvertical/smrt-svelte/app/runtime-diagnostics` | Svelte-free diagnostics WebMCP registration and its tool name/endpoint constants, importable from server routes |
715
+ | `@happyvertical/smrt-svelte/command-palette` | Global search and command palette: `CommandPalette` (shell-slot trigger plus dialog), `createCommandPalette`, the provider contract, and the navigation and manifest-driven model providers |
716
+ | `@happyvertical/smrt-svelte/overview` | Customizable overview surfaces: `OverviewGrid` (flow grid with keyboard reorder and resize), `createOverview` (host-owned controller), the widget registry (`registerWidget`), `registerCoreWidgets` (metric, chart, record list, shortcuts, note) and `shortcutsFromNav` |
717
+ | `@happyvertical/smrt-svelte/overview/server` | Svelte-free half of the overview surface: the data model (`resolveOverview`, `checkOverviewOverride`), option-schema validation, `WidgetRegistry`, and `loadOverview` for a page's server load |
542
718
  | `@happyvertical/smrt-svelte/workspace/legacy` | Opt-in ToolsDock compatibility surface for applications migrating to AdminShell |
543
719
  | `@happyvertical/smrt-svelte/workspace/server` | Server-side workspace helpers (Node only) |
544
720
  | `@happyvertical/smrt-svelte/workspace/live` | `systemFeed` — the AdminShell system scope (jobs/schedules/dispatch) polled from an app status endpoint; deliberately carries no `smrt-web` dependency |
@@ -634,6 +810,11 @@ all other currencies render their ISO code for deterministic SSR hydration.
634
810
 
635
811
  `getCachedSTT`, `getCachedTTS`, `getCachedLLM`, `getCacheStats`, `clearAllCaches`
636
812
 
813
+ Browser speech synthesis honors `stop()`, replacement `speak()` calls, and
814
+ `dispose()` while voices are loading. Canceled `speak()` promises resolve even
815
+ when the browser emits no completion event; `onEnd` is reserved for natural
816
+ completion. Events from canceled utterances are ignored.
817
+
637
818
  ## Dependencies
638
819
 
639
820
  - `@happyvertical/smrt-types` -- shared type definitions
@@ -671,8 +852,10 @@ updates retain their existing behavior.
671
852
 
672
853
  Use `shell.setPanelState(edge, 'hidden' | 'collapsed' | 'expanded')` to persist
673
854
  runtime panel preferences; app-configured hidden edges remain unavailable.
674
- AdminShell keeps a discoverable tenant collapse control with supplied navigation
675
- (`showTenantToggle={false}` opts out), a Menu opener in narrow layouts, and the
855
+ AdminShell's edge toggle buttons and WASD hotkeys are opt-in via `edgeToggles`
856
+ (default `false`: regions lay out inline; pass `true`, or a per-edge map, to
857
+ keep the drop-down behaviour; `showTenantToggle` is a deprecated alias for
858
+ `edgeToggles.left`), a Menu opener in narrow layouts, and the
676
859
  system toggle alongside a custom `systemBar` that has a `systemPanel` to open
677
860
  (a `systemBar` with no `systemPanel` owns the bottom band and draws no toggle). Closed narrow drawers are inert;
678
861
  opening focuses the first control, and closing or Escape restores the opener.
@@ -688,6 +871,13 @@ canonical 48px target; omit density to inherit the theme, or choose
688
871
  `"comfortable"`. Account menus in the shell app bar open below the bar so the
689
872
  existing footer's default placement stays reachable on narrow screens.
690
873
 
874
+ Sections-only navigation: pass `navMode="sections"` to `AppShell` and give
875
+ each `ShellNavGroup` an `icon` and `href`; the sidebar then lists only the
876
+ sections, and the section's page renders its entries with `ShellSectionMenu`
877
+ (`meta`/`actions` snippets for counts and "New ..." links). In layout edit mode
878
+ the menu rows get grip, rename and hide controls, and the sidebar's section
879
+ toolbar gets an icon picker (`useShellLayout().setSectionIcon`).
880
+
691
881
  `TenantNav` accepts optional `groups: ShellNavGroup[]` (`{ heading, items }`)
692
882
  next to its existing flat `items`. Each group has a labelled `role="group"` and
693
883
  native disclosure summary; keyboard and touch users can collapse it even in the
@@ -0,0 +1,47 @@
1
+ # smrt-svelte/browser-ai
2
+
3
+ Module semantics for `src/browser-ai/`. Package orientation and cross-module
4
+ invariants live in [../AGENTS.md](../AGENTS.md); read that first.
5
+
6
+ - **On-device speech** (`whisper-local` = alias `whisper-wasm`, and `moonshine`): thin adapters over
7
+ `@happyvertical/speech/local` (`LocalTranscriber`, or its worker host `serveLocalTranscriber`).
8
+ Push-to-talk (record on `start()`, transcribe on `stop()`, one final result) plus `transcribePcm()`
9
+ for smrt-ui's hands-free mode. Default `onnx-community/whisper-tiny.en` q8 (~45 MB, Cache
10
+ Storage); `model: 'moonshine-tiny'` (~32 MB) / `'moonshine-base'` (~67 MB) or any HF id
11
+ (`LOCAL_SPEECH_MODELS`); WebGPU else single-thread WASM (no COOP/COEP needed). The package never
12
+ imports the peers: a host passes `createWorker` (build it from
13
+ `@happyvertical/smrt-svelte/browser-ai/whisper-worker?worker`, alias `speech-worker`, the one module
14
+ that imports `@happyvertical/speech/local` and `@huggingface/transformers` statically) plus
15
+ `loadSpeech: () => import('@happyvertical/speech/local')`, or `loadModule` for the page thread.
16
+ `createLocalSpeechModel()` (alias `createWhisperLocalModel()`) / `adapter.model` is the consent API
17
+ (`estimateSize`, `isCached`, `load({ onProgress, signal })` with `downloading` -> `extracting` ->
18
+ `complete`); share it via `modelHandle`. English-only handling of `language`/`task` lives in the speech
19
+ package. `probeBrowserSpeech()` -> `works | missing | unreliable` (no network, no mic prompt)
20
+ decides whether to offer it. Sources set `stopTimeoutMs` so `Dictation` waits for the transcription.
21
+ - **Inference backends (browser-ai)**: two `@happyvertical/smrt-web/ai` `InferenceBackend`s, both
22
+ `kind: 'local'`, both refusing `tool`/`function` messages, non-string content, `tool_calls` and
23
+ `options.tools` with `InferencePathError` (`unsupported_message`) through the SHARED
24
+ `assertTextOnlyTurn`, so a per-call switch between backends never changes what a turn means.
25
+ - `createWebLlmInferenceBackend()` wraps an `LLMAdapter` — `status` derives from the adapter's
26
+ `initState` (plus an explicit in-flight flag, because the adapter only flips to `initializing`
27
+ after its own awaits), `progress` mirrors `DownloadProgressInfo`, and `load()`/`unload()` drive
28
+ `ensureInitialized`/`unloadModel`. It reports `unavailable` without WebGPU so an `auto` path skips
29
+ it. Pass `adapter` to share the app-state-managed warm-cached adapter; construct once, so two
30
+ callers cannot each start an unshared adapter and a second download.
31
+ Its `loadModule` option matters: the default `importOptional()` resolves a VARIABLE specifier,
32
+ which a browser cannot resolve (`TypeError: Failed to resolve module specifier`) — a host that has
33
+ `@mlc-ai/web-llm` must pass `() => import('@mlc-ai/web-llm')` so the bundler rewrites a static one.
34
+ It does NOT forward `signal` (the adapter has no cancellation seam).
35
+ - `createBitGpuInferenceBackend()` wraps `bitgpu` (MIT, optional peer), the engine behind the
36
+ Bonsai WebGPU demo PrismML's own docs list as their in-browser option. `loadBitGpu`/`loadChat`
37
+ are REQUIRED loaders (`() => import('bitgpu')`, `() => import('bitgpu/chat')`) — a static import
38
+ here would fail the build for every consumer without the optional peer, and a bare specifier is
39
+ not resolvable by a browser either. `bitgpu`'s `LoadProgress.phase` maps to `InferenceProgress`
40
+ (`manifest`/`weights` → `downloading`, `pipelines` → `extracting`). Unlike the WebLLM backend it
41
+ **forwards `signal`** — bitgpu aborts a live generation — and it does NOT lazily load: weights
42
+ run to GBs, so a turn before `load()` fails with a named reason. `model` in the per-call options
43
+ is ignored (one engine binds one model), and bitgpu's tools/JSON-schema/think support is
44
+ deliberately left unexposed for now so the text-only invariant holds across backends.
45
+ - **`ModelStatusControl.svelte`**: the user-facing model lifecycle surface (state, Load/Unload,
46
+ download progress) driven entirely by a backend's own `status`/`progress`/`subscribe`, so it works
47
+ without a `<Provider>` ancestor. `unavailable` is a first-class state that offers NO load action.
@@ -0,0 +1,85 @@
1
+ # smrt-svelte/command-palette
2
+
3
+ Module semantics for `src/components/command-palette/` (`./command-palette`).
4
+ Package orientation and cross-module invariants live in
5
+ [../AGENTS.md](../AGENTS.md); the shell it sits in is in
6
+ [workspace.md](workspace.md).
7
+
8
+ ## Shape
9
+
10
+ - **Controller** (`controller.svelte.ts`): `createCommandPalette({ providers,
11
+ navigate, onError, searchDebounceMs, maxPerGroup })`. Owns open/query state,
12
+ the provider registry, local and remote rows, the highlight, and `activate`.
13
+ `setCommandPalette(controller)` puts it on context (call it above the
14
+ `AppShell`) so any descendant can `useCommandPaletteProvider(provider)`; that
15
+ hook is a no-op without a palette.
16
+ - **Components**: `CommandPalette` = `CommandPaletteTrigger` + `CommandPaletteDialog`.
17
+ Mount it **once**: the dialog owns the global shortcut (`hotkeys`, default
18
+ `['Mod+K']`; `false` for none). Place it with `AppShell` `slotItems`
19
+ (`header.center` is the usual slot); it is a movable item like any other.
20
+ Without a `palette` prop or context it builds one from `providers`/`navigate`.
21
+ - **Pure core**: `match.ts` (accent/case-insensitive, multi-term, word-start
22
+ then in-order fuzzy; returns title ranges), `rank.ts` (groups, limits,
23
+ boost), `hotkeys.ts` (`Mod` = Ctrl or Meta). Node-testable, no Svelte.
24
+
25
+ ## Provider contract (`types.ts`)
26
+
27
+ A `PaletteProvider` is `{ id, label, order?, items?, search?, minQueryLength?,
28
+ limit? }`.
29
+
30
+ - `items(ctx)` rows are re-read **every time the palette opens** and matched
31
+ locally by the palette. Sync results land in the same tick; async ones fill
32
+ in (`busy`).
33
+ - `search(query, { signal, limit })` runs after the debounce with an abort
34
+ signal that fires on the next keystroke or close. Its rows are shown as
35
+ returned (not re-filtered); earlier rows stay until the new ones arrive. A
36
+ superseded result is dropped, never shown.
37
+ - Registering an id again replaces the provider; a stale disposer is a no-op.
38
+ The replaced provider's cached rows are cleared and its in-flight `items` or
39
+ `search` results (and failures) are dropped, never shown or reported.
40
+ - Authorization stays with the provider. A failing provider is reported through
41
+ `onError` (default: logger warning) and marked in `failedProviders`; the
42
+ palette keeps working. The palette is not a security boundary.
43
+ - A row with `run` runs; else a row with `href` goes through `navigate`
44
+ (default `window.location.assign`; SvelteKit apps pass `goto`). The palette
45
+ closes first, then runs.
46
+
47
+ ## Shipped providers (`providers.ts`)
48
+
49
+ - `createNavigationProvider({ nav, groups })`: rows for the shell nav. Pass
50
+ getters over `useShellLayout().applied` to honor sections a user hid.
51
+ - `createModelProviders({ manifest, ... })` returns `[commands, records]`:
52
+ - eligibility is `navigableManifestEntries` (exported from
53
+ `workspace/manifest-nav.ts`), so it agrees with manifest-derived nav;
54
+ - commands: "New <noun>" for models whose REST `create` route exists;
55
+ destinations come from `hrefs` or the `<pagesBasePath>/<collection>[/new|/id]`
56
+ convention (the app owns its page routes);
57
+ - records: `GET <apiBasePath>/<collection>?<field>[like]=%q%` per model, one
58
+ text field each (first of `title`, `name`, `displayName`, ... that is a
59
+ non-sensitive, non-enum text field; override with `searchFields`), capped by
60
+ `maxModels` and `concurrency`, interleaved so one model cannot crowd out
61
+ the rest. The default fetch reads the generated list envelope
62
+ `{ items, count, limit, offset }` (a bare array also works; any other body
63
+ counts as no results). 401/403/404 mean "no results" for that model; the search throws
64
+ only when **every** request fails.
65
+ - Known limit: `LIKE` is case-insensitive on SQLite and case-sensitive on
66
+ PostgreSQL (sdk#1192). Supply `searchRows` to use a server search endpoint
67
+ instead.
68
+
69
+ ## Accessibility and keyboard
70
+
71
+ WAI-ARIA combobox: focus stays in the search box; `aria-activedescendant`
72
+ names the highlighted option; options sit in labelled groups inside a
73
+ `listbox`; a polite status region announces counts and "no results". Up/Down
74
+ (wrapping, skipping disabled rows), PageUp/PageDown, Enter, Escape (the
75
+ `Modal` closes). Disabled rows stay visible with their reason as the tooltip.
76
+ A bare-key shortcut (`/`) never fires while typing in a field or during IME
77
+ composition; a modified one (`Mod+K`) does. Strings are in
78
+ `src/i18n/strings.palette.ts` (registered in `i18n/server.ts`); provider group
79
+ labels default to English and are options on the shipped providers.
80
+
81
+ ## Not yet wired
82
+
83
+ Recipe surfaces (#3708): a recipe will declare the palette as a shell widget
84
+ and its own providers (for example an assistant provider) once non-model
85
+ surfaces exist. Until then hosts mount `CommandPalette` themselves.
@@ -0,0 +1,62 @@
1
+ # smrt-svelte/import-export
2
+
3
+ Module semantics for `src/components/import-export/` (`./import-export`).
4
+ Package orientation and cross-module invariants live in
5
+ [../AGENTS.md](../AGENTS.md); read that first.
6
+
7
+ ## Shape
8
+
9
+ `ImportExport.svelte` is a thin shell over a pure layer. The pure files import
10
+ no Svelte or DOM API and are unit-tested in Node; keep logic there, not in the
11
+ component.
12
+
13
+ | File | Owns |
14
+ |------|------|
15
+ | `csv.ts` | RFC 4180 parse/format, delimiter detection, BOM, formula neutralization |
16
+ | `validate.ts` | `coerceCell`, `validateMapping`, `validateRows` (the dry run) |
17
+ | `mapping.ts` | `autoMapColumns`, `setColumnTarget` |
18
+ | `fields.ts` | `fieldsFromCollectionDefinition`: manifest + resolved field policy to `ImportExportField[]` |
19
+ | `collection-adapter.ts` | `createCollectionImportExport`: generated CRUD fetchers to `createRecord` / `loadRows` |
20
+ | `runner.ts` | `runImport`: bounded-concurrency create, per-row failures, abort |
21
+ | `export.ts` / `report.ts` | `buildExportFile`, `buildErrorReport` |
22
+ | `download.ts` | the only DOM touch: Blob download (overridable via `ondownload`) |
23
+
24
+ ## Invariants
25
+
26
+ - **Field policy is a hard boundary.** A supplied resolved policy is an
27
+ allowlist: a field it omits is neither importable nor exportable (manifest
28
+ defaults apply only with no policy). `hidden` fields are neither importable
29
+ nor exportable; `locked` fields are not importable but keep their resolved
30
+ default; tenant fields (`tenantId`) are never imported (the server sets
31
+ them). `id` is export-only. Do not add a path that writes a non-importable
32
+ field: only importable and `locked` fields take a default; hidden and tenant
33
+ defaults never enter the payload.
34
+ - **Nothing is written during validation.** `validateRows` returns no records
35
+ while `mappingIssues` is non-empty (an unmapped required field would be
36
+ written without its value). `records` only ever holds fully valid rows;
37
+ there is no partial-row import.
38
+ - **Strict typing.** Integers must be JavaScript-safe integers (money is
39
+ integer minor units, never decimals); datetimes are strict ISO 8601 with a
40
+ missing offset meaning UTC; `3/5/2026` is rejected, not guessed. Booleans
41
+ accept `true/false/yes/no/y/n/1/0/on/off`. Enum matching is
42
+ case-insensitive and writes the canonical option.
43
+ - **Defaults fill empties.** An empty or unmapped cell takes the field's
44
+ resolved default; a required field with a default is satisfied.
45
+ - **Exports are spreadsheet-safe.** Text cells starting with `= + - @`, tab or
46
+ CR are prefixed with `'`; numeric and boolean columns are exempt so negative
47
+ numbers survive. Import strips that prefix back off text cells. The error
48
+ report is neutralized too, because it echoes user data.
49
+ - **Export never truncates silently.** `loadRows` pages with `limit`/`offset`
50
+ and throws `ExportLimitError` past `maxRows` (default 50,000).
51
+ - **Row failures are per row.** `runImport` continues past a rejected row and
52
+ reports it by file line; abort stops starting new rows and counts in-flight
53
+ ones.
54
+ - **Messages are i18n keys.** Issue text lives under `ui.importExport.issue.*`
55
+ in `src/i18n/strings.import-export.ts` (registered in `i18n/server.ts`);
56
+ `describeIssue` falls back to English defaults for the pure layer.
57
+
58
+ ## Not here
59
+
60
+ Native `.xlsx` read/write (save as CSV first), server-side dry-run endpoints,
61
+ upsert-by-key, and recipe/nav wiring (offering the panel on list screens waits
62
+ on the recipe surface contract, #3708).