@digithings-ai/ui 0.0.0-stage → 0.1.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 (424) hide show
  1. package/README.md +48 -2
  2. package/package.json +143 -4
  3. package/src/components/NavShell.tsx +776 -0
  4. package/src/components/SocialRow.tsx +87 -0
  5. package/src/components/Spinner.tsx +27 -0
  6. package/src/components/StackLogo.tsx +40 -0
  7. package/src/components/Terminal.tsx +110 -0
  8. package/src/components/TerminalManifest.tsx +212 -0
  9. package/src/components/ThemeProvider.tsx +271 -0
  10. package/src/components/account/AuthCard.tsx +309 -0
  11. package/src/components/assistant-ui/elements/mermaid-diagram.aui.tsx +63 -0
  12. package/src/components/assistant-ui/elements/mermaid-diagram.tsx +340 -0
  13. package/src/components/brand/BrandWordmark.tsx +32 -0
  14. package/src/components/changelog/ReleaseRail.tsx +81 -0
  15. package/src/components/changelog/index.ts +1 -0
  16. package/src/components/chat/ChatCodeBlock.tsx +67 -0
  17. package/src/components/chat/ChatMarkdown.tsx +66 -0
  18. package/src/components/chat/ChatMarkdownSource.tsx +203 -0
  19. package/src/components/chat/ChatMermaidBlock.tsx +202 -0
  20. package/src/components/chat/ChatMessage.tsx +77 -0
  21. package/src/components/chat/ChatPlayback.tsx +422 -0
  22. package/src/components/chat/ChatStreamCursor.tsx +25 -0
  23. package/src/components/chat/ChatThinking.tsx +113 -0
  24. package/src/components/chat/ChatToolCall.tsx +190 -0
  25. package/src/components/chat/ChatTranscript.tsx +60 -0
  26. package/src/components/chat/ChatWidgetFrame.tsx +107 -0
  27. package/src/components/chat/DigichatBootLoader.tsx +683 -0
  28. package/src/components/chat/DigichatLauncher.tsx +361 -0
  29. package/src/components/chat/DigichatThread.tsx +118 -0
  30. package/src/components/chat/DigichatThreadList.tsx +54 -0
  31. package/src/components/chat/DigichatWordmark.tsx +24 -0
  32. package/src/components/chat/DotMatrix.tsx +650 -0
  33. package/src/components/chat/boot-lab.tsx +766 -0
  34. package/src/components/chat/boot-signal.ts +144 -0
  35. package/src/components/chat/chat-surfaces.ts +52 -0
  36. package/src/components/chat/connection-status.ts +40 -0
  37. package/src/components/chat/digichat-wordmark.ts +355 -0
  38. package/src/components/chat/disclosure-chevron.tsx +49 -0
  39. package/src/components/chat/followable-href.ts +9 -0
  40. package/src/components/chat/gallery-thread/action-icons.tsx +25 -0
  41. package/src/components/chat/gallery-thread/attachment.aui.tsx +262 -0
  42. package/src/components/chat/gallery-thread/block-caret.tsx +439 -0
  43. package/src/components/chat/gallery-thread/cn.ts +1 -0
  44. package/src/components/chat/gallery-thread/composer-keyboard.ts +106 -0
  45. package/src/components/chat/gallery-thread/composer-trigger-popover.aui.tsx +235 -0
  46. package/src/components/chat/gallery-thread/css.d.ts +6 -0
  47. package/src/components/chat/gallery-thread/file.tsx +238 -0
  48. package/src/components/chat/gallery-thread/follow-up-suggestions.aui.tsx +92 -0
  49. package/src/components/chat/gallery-thread/format-json-dump.ts +112 -0
  50. package/src/components/chat/gallery-thread/hooks/use-attachment-src.ts +46 -0
  51. package/src/components/chat/gallery-thread/hooks/use-copy-to-clipboard.ts +9 -0
  52. package/src/components/chat/gallery-thread/image.tsx +519 -0
  53. package/src/components/chat/gallery-thread/markdown-text.tsx +278 -0
  54. package/src/components/chat/gallery-thread/message-error.aui.tsx +105 -0
  55. package/src/components/chat/gallery-thread/message-timing.aui.tsx +143 -0
  56. package/src/components/chat/gallery-thread/private-work-step.tsx +188 -0
  57. package/src/components/chat/gallery-thread/reasoning.tsx +332 -0
  58. package/src/components/chat/gallery-thread/scroll-mode.ts +174 -0
  59. package/src/components/chat/gallery-thread/source.tsx +76 -0
  60. package/src/components/chat/gallery-thread/thread.aui.tsx +1619 -0
  61. package/src/components/chat/gallery-thread/tooltip-icon-button.tsx +53 -0
  62. package/src/components/chat/gallery-thread/typed-welcome-copy.tsx +18 -0
  63. package/src/components/chat/gallery-thread/ui/tooltip.tsx +22 -0
  64. package/src/components/chat/gallery-thread/work-chain-summary.tsx +48 -0
  65. package/src/components/chat/gallery-thread/work-chain.tsx +110 -0
  66. package/src/components/chat/gallery-thread/work-status.ts +66 -0
  67. package/src/components/chat/overlay-scrollbar.tsx +86 -0
  68. package/src/components/chat/sanitize-mermaid-svg.ts +38 -0
  69. package/src/components/chat/skins/SOURCE.md +36 -0
  70. package/src/components/chat/skins/base/attachment.aui.tsx +287 -0
  71. package/src/components/chat/skins/base/aui-default/README.md +45 -0
  72. package/src/components/chat/skins/base/aui-default/collapsible-root.tsx +19 -0
  73. package/src/components/chat/skins/base/aui-default/collapsible.tsx +21 -0
  74. package/src/components/chat/skins/base/aui-default/reasoning.aui.tsx +120 -0
  75. package/src/components/chat/skins/base/aui-default/reasoning.tsx +331 -0
  76. package/src/components/chat/skins/base/aui-default/surfaces.ts +7 -0
  77. package/src/components/chat/skins/base/aui-default/tool-fallback.aui.tsx +772 -0
  78. package/src/components/chat/skins/base/aui-default/tool-group.aui.tsx +241 -0
  79. package/src/components/chat/skins/base/docs-model-options.ts +6 -0
  80. package/src/components/chat/skins/base/elements/assistant-trace.aui.tsx +169 -0
  81. package/src/components/chat/skins/base/elements/composer-trigger-popover.aui.tsx +271 -0
  82. package/src/components/chat/skins/base/elements/directive-text.aui.tsx +29 -0
  83. package/src/components/chat/skins/base/elements/directive-text.tsx +76 -0
  84. package/src/components/chat/skins/base/elements/message-timing.aui.tsx +104 -0
  85. package/src/components/chat/skins/base/elements/model-selector.aui.tsx +140 -0
  86. package/src/components/chat/skins/base/elements/model-selector.tsx +720 -0
  87. package/src/components/chat/skins/base/elements/quote.aui.tsx +290 -0
  88. package/src/components/chat/skins/base/elements/work-chain.tsx +100 -0
  89. package/src/components/chat/skins/base/markdown-text.tsx +294 -0
  90. package/src/components/chat/skins/base/model.ts +1 -0
  91. package/src/components/chat/skins/base/thread.tsx +1050 -0
  92. package/src/components/chat/skins/base/tooltip-icon-button.tsx +56 -0
  93. package/src/components/chat/skins/base/ui/avatar.tsx +115 -0
  94. package/src/components/chat/skins/base/ui/badge.tsx +51 -0
  95. package/src/components/chat/skins/base/ui/button.tsx +67 -0
  96. package/src/components/chat/skins/base/ui/command.tsx +185 -0
  97. package/src/components/chat/skins/base/ui/dialog.tsx +168 -0
  98. package/src/components/chat/skins/base/ui/dot-matrix.tsx +267 -0
  99. package/src/components/chat/skins/base/ui/popover.tsx +97 -0
  100. package/src/components/chat/skins/base/ui/skeleton.tsx +20 -0
  101. package/src/components/chat/skins/base/ui/textarea.tsx +24 -0
  102. package/src/components/chat/skins/base/ui/tooltip.tsx +73 -0
  103. package/src/components/chat/skins/base-assistant-ui/config-provider.tsx +90 -0
  104. package/src/components/chat/skins/base-assistant-ui/defaults.ts +419 -0
  105. package/src/components/chat/skins/base-assistant-ui/index.tsx +44 -0
  106. package/src/components/chat/skins/chatgpt.tsx +448 -0
  107. package/src/components/chat/skins/claude.tsx +380 -0
  108. package/src/components/chat/skins/digichat-composer-toolbar.tsx +151 -0
  109. package/src/components/chat/skins/digichat-context-meter-shares.ts +158 -0
  110. package/src/components/chat/skins/digichat-context-meter.tsx +243 -0
  111. package/src/components/chat/skins/digichat-meter-tone.ts +26 -0
  112. package/src/components/chat/skins/digichat-usage-meter.tsx +103 -0
  113. package/src/components/chat/skins/digichat.tsx +144 -0
  114. package/src/components/chat/skins/expo-react-native.tsx +29 -0
  115. package/src/components/chat/skins/gemini.tsx +322 -0
  116. package/src/components/chat/skins/grok-icon.tsx +34 -0
  117. package/src/components/chat/skins/grok.tsx +369 -0
  118. package/src/components/chat/skins/index.ts +46 -0
  119. package/src/components/chat/skins/perplexity.tsx +462 -0
  120. package/src/components/chat/skins/product-page-assistant/assistant-modal.tsx +73 -0
  121. package/src/components/chat/skins/product-page-assistant/index.tsx +19 -0
  122. package/src/components/chat/skins/product-page-assistant/product-dashboard.tsx +164 -0
  123. package/src/components/chat/skins/react-ink.tsx +97 -0
  124. package/src/components/chat/skins/thread-skin-host-contract.ts +102 -0
  125. package/src/components/chat/skins/thread-skin-view.tsx +156 -0
  126. package/src/components/chat/skins/thread-skins.ts +143 -0
  127. package/src/components/chat/skins/tooltip-icon-button.tsx +35 -0
  128. package/src/components/chat/skins/ui/dropdown-menu.tsx +272 -0
  129. package/src/components/chat/skins/webpage-assistant/assistant-config.ts +238 -0
  130. package/src/components/chat/skins/webpage-assistant/assistant-modal.tsx +78 -0
  131. package/src/components/chat/skins/webpage-assistant/config-provider.tsx +132 -0
  132. package/src/components/chat/skins/webpage-assistant/docs-app.tsx +106 -0
  133. package/src/components/chat/skins/webpage-assistant/docs-article.tsx +109 -0
  134. package/src/components/chat/skins/webpage-assistant/docs-assistant.tsx +73 -0
  135. package/src/components/chat/skins/webpage-assistant/docs-nav.tsx +81 -0
  136. package/src/components/chat/skins/webpage-assistant/host-ui.ts +79 -0
  137. package/src/components/chat/skins/webpage-assistant/index.tsx +12 -0
  138. package/src/components/chat/skins/webpage-assistant/markdown-page.tsx +11 -0
  139. package/src/components/chat/skins/webpage-assistant/pages.ts +9 -0
  140. package/src/components/chat/skins/webpage-assistant/types.ts +178 -0
  141. package/src/components/chat/skins/webpage-assistant/use-mobile.ts +19 -0
  142. package/src/components/chat/stock/SOURCE.md +90 -0
  143. package/src/components/chat/stock/artifacts-panel.tsx +305 -0
  144. package/src/components/chat/stock/attachment.aui.tsx +280 -0
  145. package/src/components/chat/stock/chat-notice.tsx +143 -0
  146. package/src/components/chat/stock/chat-private-mode.tsx +64 -0
  147. package/src/components/chat/stock/deploy-ui-context.tsx +89 -0
  148. package/src/components/chat/stock/embed-chat-prefs.tsx +471 -0
  149. package/src/components/chat/stock/file.tsx +265 -0
  150. package/src/components/chat/stock/follow-up-suggestions.aui.tsx +83 -0
  151. package/src/components/chat/stock/image.tsx +531 -0
  152. package/src/components/chat/stock/index.ts +129 -0
  153. package/src/components/chat/stock/json-view.tsx +140 -0
  154. package/src/components/chat/stock/markdown-text.tsx +319 -0
  155. package/src/components/chat/stock/message-error.aui.tsx +96 -0
  156. package/src/components/chat/stock/message-export-menu.tsx +156 -0
  157. package/src/components/chat/stock/palette-row-preview.tsx +26 -0
  158. package/src/components/chat/stock/reasoning.aui.tsx +120 -0
  159. package/src/components/chat/stock/reasoning.tsx +335 -0
  160. package/src/components/chat/stock/skin-chrome.tsx +81 -0
  161. package/src/components/chat/stock/skin-credit.tsx +63 -0
  162. package/src/components/chat/stock/skin-palette-bridge.tsx +235 -0
  163. package/src/components/chat/stock/skin-palette-context.ts +16 -0
  164. package/src/components/chat/stock/skin-runtime.tsx +52 -0
  165. package/src/components/chat/stock/skin-slash-palette.tsx +393 -0
  166. package/src/components/chat/stock/skin-types.ts +217 -0
  167. package/src/components/chat/stock/stock-chat-prefs-host.tsx +501 -0
  168. package/src/components/chat/stock/stock-send-gate.tsx +94 -0
  169. package/src/components/chat/stock/stock-shape.tsx +39 -0
  170. package/src/components/chat/stock/thread.aui.tsx +645 -0
  171. package/src/components/chat/stock/tool-display.ts +6 -0
  172. package/src/components/chat/stock/tool-fallback.aui.tsx +866 -0
  173. package/src/components/chat/stock/tool-group.aui.tsx +244 -0
  174. package/src/components/chat/stock/tool-surface.ts +120 -0
  175. package/src/components/chat/stock/tooltip-icon-button.tsx +49 -0
  176. package/src/components/chat/stock/ui/avatar.tsx +108 -0
  177. package/src/components/chat/stock/ui/button.tsx +81 -0
  178. package/src/components/chat/stock/ui/collapsible.tsx +21 -0
  179. package/src/components/chat/stock/ui/dialog.tsx +163 -0
  180. package/src/components/chat/stock/ui/skeleton.tsx +13 -0
  181. package/src/components/chat/stock/ui/textarea.tsx +20 -0
  182. package/src/components/chat/stock/ui/tooltip.tsx +68 -0
  183. package/src/components/chat/stock/use-attachment-src.ts +42 -0
  184. package/src/components/chat/stock/use-copy-to-clipboard.ts +29 -0
  185. package/src/components/chat/strip-model-boilerplate.ts +42 -0
  186. package/src/components/chat/suggestion-cycle.tsx +230 -0
  187. package/src/components/chat/suggestion-scroll-row.tsx +81 -0
  188. package/src/components/chat/trace-grouping/chain-group-by.ts +44 -0
  189. package/src/components/chat/trace-grouping/chain-state.ts +141 -0
  190. package/src/components/chat/trace-grouping/index.ts +32 -0
  191. package/src/components/chat/trace-grouping/tool-row.ts +74 -0
  192. package/src/components/chat/trace-grouping/use-deploy-work-disclosure.ts +35 -0
  193. package/src/components/chat/trace-grouping/use-work-chain.ts +103 -0
  194. package/src/components/chat/trace-i18n/core.ts +48 -0
  195. package/src/components/chat/trace-i18n/index.tsx +23 -0
  196. package/src/components/chat/trace-i18n/locales/en.ts +24 -0
  197. package/src/components/chat/trace-i18n/locales/fr.ts +28 -0
  198. package/src/components/chat/trace-i18n/types.ts +35 -0
  199. package/src/components/chat/trace-spacing.ts +249 -0
  200. package/src/components/chat/transcript/activity-view.ts +375 -0
  201. package/src/components/chat/transcript/chat-export.ts +133 -0
  202. package/src/components/chat/transcript/index.ts +10 -0
  203. package/src/components/chat/transcript/save-file.ts +209 -0
  204. package/src/components/chat/transcript/transcript-markdown.ts +428 -0
  205. package/src/components/chat/transcript/types.ts +81 -0
  206. package/src/components/chat/turn-outcome.ts +52 -0
  207. package/src/components/chat/use-warmup-phase.ts +18 -0
  208. package/src/components/chat/work-status-lead.tsx +49 -0
  209. package/src/components/chrome.tsx +264 -0
  210. package/src/components/command-palette/CommandPalette.tsx +404 -0
  211. package/src/components/command-palette/index.ts +6 -0
  212. package/src/components/contact/ContactMailto.tsx +112 -0
  213. package/src/components/contact/index.ts +5 -0
  214. package/src/components/conviction/ConvictionMeter.tsx +40 -0
  215. package/src/components/conviction/SignedConvictionBadge.tsx +26 -0
  216. package/src/components/conviction/index.ts +7 -0
  217. package/src/components/data-layout/BentoGrid.tsx +52 -0
  218. package/src/components/data-layout/CardRail.tsx +150 -0
  219. package/src/components/data-layout/DotMatrixStat.tsx +65 -0
  220. package/src/components/data-layout/FeatureCell.tsx +80 -0
  221. package/src/components/data-layout/MediaFrame.tsx +125 -0
  222. package/src/components/data-layout/ModuleGrid.tsx +735 -0
  223. package/src/components/data-layout/Odometer.tsx +149 -0
  224. package/src/components/data-layout/ProductFrame.tsx +79 -0
  225. package/src/components/data-layout/TestimonialWall.tsx +139 -0
  226. package/src/components/data-layout/index.ts +19 -0
  227. package/src/components/data-layout/treemap.ts +368 -0
  228. package/src/components/deck/DeckStack.tsx +243 -0
  229. package/src/components/desk/DataTable.tsx +373 -0
  230. package/src/components/desk/KpiGrid.tsx +80 -0
  231. package/src/components/desk/Sparkline.tsx +63 -0
  232. package/src/components/desk/StateBlock.tsx +132 -0
  233. package/src/components/desk/index.ts +18 -0
  234. package/src/components/diagrams/ArchitectureDiagram.tsx +350 -0
  235. package/src/components/diagrams/ArchitectureTour.tsx +912 -0
  236. package/src/components/diagrams/TerminalSchematic.tsx +192 -0
  237. package/src/components/diagrams/architecture-svg.tsx +384 -0
  238. package/src/components/diagrams/index.ts +30 -0
  239. package/src/components/diagrams/mermaid-theme.ts +115 -0
  240. package/src/components/diagrams/tour-camera.ts +171 -0
  241. package/src/components/docs/CodeTabs.tsx +90 -0
  242. package/src/components/docs/CopyCommand.tsx +151 -0
  243. package/src/components/docs/DocsLayout.tsx +197 -0
  244. package/src/components/docs/DocsSearch.tsx +97 -0
  245. package/src/components/docs/Endpoint.tsx +135 -0
  246. package/src/components/document/DocumentFrame.tsx +43 -0
  247. package/src/components/document/GlyphList.tsx +51 -0
  248. package/src/components/document/PageTitle.tsx +44 -0
  249. package/src/components/document/Prose.tsx +38 -0
  250. package/src/components/document/Section.tsx +55 -0
  251. package/src/components/document/index.ts +13 -0
  252. package/src/components/effects-chrome/AnnouncementBar.tsx +88 -0
  253. package/src/components/effects-chrome/HorizontalScrollTrack.tsx +461 -0
  254. package/src/components/effects-chrome/Pipeline.tsx +226 -0
  255. package/src/components/effects-chrome/RotatingPrompts.tsx +116 -0
  256. package/src/components/effects-chrome/StackingPanels.tsx +101 -0
  257. package/src/components/effects-chrome/TabStrip.tsx +232 -0
  258. package/src/components/effects-chrome/ToastStack.tsx +201 -0
  259. package/src/components/effects-chrome/horizontal-track-core.ts +70 -0
  260. package/src/components/effects-chrome/index.ts +35 -0
  261. package/src/components/emblems.tsx +188 -0
  262. package/src/components/faviconTheme.ts +23 -0
  263. package/src/components/figure/Figure.tsx +38 -0
  264. package/src/components/figure/index.ts +2 -0
  265. package/src/components/finance-charts/DrawdownPlot.tsx +76 -0
  266. package/src/components/finance-charts/EquityCurve.tsx +71 -0
  267. package/src/components/finance-charts/PriceChart.tsx +119 -0
  268. package/src/components/finance-charts/chart-host.tsx +236 -0
  269. package/src/components/finance-charts/chart-scale.ts +93 -0
  270. package/src/components/finance-charts/demo-data.ts +88 -0
  271. package/src/components/finance-charts/index.ts +46 -0
  272. package/src/components/finance-charts/lw-chart.tsx +292 -0
  273. package/src/components/finance-composites/MarketBar.tsx +243 -0
  274. package/src/components/finance-composites/OrderBook.tsx +133 -0
  275. package/src/components/finance-composites/PerformanceDashboard.tsx +185 -0
  276. package/src/components/finance-composites/SortableTable.tsx +144 -0
  277. package/src/components/finance-composites/StockTicker.tsx +65 -0
  278. package/src/components/finance-composites/SyncedTearsheet.tsx +226 -0
  279. package/src/components/finance-composites/index.ts +28 -0
  280. package/src/components/finance-tearsheet/KpiStrip.tsx +49 -0
  281. package/src/components/finance-tearsheet/LiveBadge.tsx +29 -0
  282. package/src/components/finance-tearsheet/ReturnsMatrix.tsx +321 -0
  283. package/src/components/finance-tearsheet/StrategyTearsheet.tsx +99 -0
  284. package/src/components/finance-tearsheet/TearsheetCard.tsx +54 -0
  285. package/src/components/finance-tearsheet/TradeLogTable.tsx +73 -0
  286. package/src/components/finance-tearsheet/charts.tsx +2624 -0
  287. package/src/components/finance-tearsheet/demo-data.ts +177 -0
  288. package/src/components/finance-tearsheet/format.ts +41 -0
  289. package/src/components/finance-tearsheet/index.ts +120 -0
  290. package/src/components/finance-tearsheet/print.ts +52 -0
  291. package/src/components/finance-tearsheet/risk-bands.ts +48 -0
  292. package/src/components/finance-tearsheet/stats.ts +35 -0
  293. package/src/components/finance-tearsheet/strategy-sheet-model.ts +238 -0
  294. package/src/components/finance-tearsheet/types.ts +58 -0
  295. package/src/components/footer/FooterCells.tsx +109 -0
  296. package/src/components/footer/index.ts +6 -0
  297. package/src/components/graph.tsx +158 -0
  298. package/src/components/icons.tsx +98 -0
  299. package/src/components/landing/PixelWordmark.tsx +36 -0
  300. package/src/components/logos.ts +39 -0
  301. package/src/components/marquee/Marquee.tsx +204 -0
  302. package/src/components/metrics/PerfMetrics.tsx +68 -0
  303. package/src/components/metrics/StatCounter.tsx +104 -0
  304. package/src/components/page-geometry.tsx +177 -0
  305. package/src/components/pricing/Pricing.tsx +174 -0
  306. package/src/components/pricing/PricingMatrix.tsx +219 -0
  307. package/src/components/prose/index.ts +2 -0
  308. package/src/components/prose/prose.tsx +86 -0
  309. package/src/components/repo-activity/RepoActivity.tsx +599 -0
  310. package/src/components/repo-activity/RepoHeatmap.tsx +225 -0
  311. package/src/components/repo-activity/demo.ts +201 -0
  312. package/src/components/repo-activity/fetch.ts +211 -0
  313. package/src/components/repo-activity/heatmap.ts +123 -0
  314. package/src/components/repo-activity/index.ts +28 -0
  315. package/src/components/repo-activity/types.ts +99 -0
  316. package/src/components/stages/NumberedStages.tsx +116 -0
  317. package/src/components/symbols/marks.tsx +116 -0
  318. package/src/components/symbols/terminal-lockup.tsx +136 -0
  319. package/src/components/symbols/terminal-marks.tsx +226 -0
  320. package/src/components/terminal/ChatResponseLoader.tsx +67 -0
  321. package/src/components/terminal/ContainerBootLoader.tsx +82 -0
  322. package/src/components/terminal/TerminalStepCaret.tsx +202 -0
  323. package/src/components/themeInit.ts +24 -0
  324. package/src/components/typography/MotionReveal.tsx +108 -0
  325. package/src/components/typography/TypewriterReveal.tsx +101 -0
  326. package/src/components/typography/WordReveal.tsx +143 -0
  327. package/src/data/modules.ts +378 -0
  328. package/src/data/subsystems.ts +101 -0
  329. package/src/index.ts +587 -0
  330. package/src/lib/base-path.ts +60 -0
  331. package/src/lib/cx.ts +25 -0
  332. package/src/lib/gloomberb.ts +69 -0
  333. package/src/lib/record.ts +19 -0
  334. package/src/lib/stub-payload.ts +183 -0
  335. package/src/lib/useBodyScrollLock.ts +44 -0
  336. package/src/lib/utils.ts +6 -0
  337. package/src/motion/primitives.tsx +105 -0
  338. package/src/motion/scroll-glide.ts +62 -0
  339. package/src/motion/scrolly-core.ts +38 -0
  340. package/src/motion/scrolly.tsx +95 -0
  341. package/src/navigation/HashScrollManager.tsx +167 -0
  342. package/src/navigation/hashScroll.ts +78 -0
  343. package/src/replay/browser.ts +280 -0
  344. package/src/replay/chat-export-run.ts +121 -0
  345. package/src/replay/export-format.ts +25 -0
  346. package/src/replay/export-mount.ts +32 -0
  347. package/src/replay/filename.ts +54 -0
  348. package/src/replay/index.ts +21 -0
  349. package/src/replay/redact-dom.ts +178 -0
  350. package/src/replay/redact.ts +113 -0
  351. package/src/replay/snapshot.ts +659 -0
  352. package/src/styles/account-auth.css +339 -0
  353. package/src/styles/brand-wordmark.css +11 -0
  354. package/src/styles/card-rail.css +120 -0
  355. package/src/styles/chat-aui.css +1143 -0
  356. package/src/styles/chat-core.css +469 -0
  357. package/src/styles/chat-digichat.css +2531 -0
  358. package/src/styles/chat-math.css +70 -0
  359. package/src/styles/chat-skin-palette.css +138 -0
  360. package/src/styles/chat-stock-menu.css +37 -0
  361. package/src/styles/chat-widgets.css +190 -0
  362. package/src/styles/command-palette.css +372 -0
  363. package/src/styles/controls-core.css +2261 -0
  364. package/src/styles/controls-overlay.css +603 -0
  365. package/src/styles/data-layout.css +288 -0
  366. package/src/styles/deck.css +141 -0
  367. package/src/styles/diagrams.css +1860 -0
  368. package/src/styles/digichat-app-theme.css +250 -0
  369. package/src/styles/digichat-boot-loader.css +487 -0
  370. package/src/styles/digichat-launcher.css +377 -0
  371. package/src/styles/docs.css +165 -0
  372. package/src/styles/effects-chrome.css +888 -0
  373. package/src/styles/finance-composites.css +214 -0
  374. package/src/styles/finance-tearsheet-overlay.css +90 -0
  375. package/src/styles/finance-tearsheet.css +945 -0
  376. package/src/styles/marquee.css +168 -0
  377. package/src/styles/metrics.css +82 -0
  378. package/src/styles/nav-shell.css +551 -0
  379. package/src/styles/pricing.css +79 -0
  380. package/src/styles/repo-activity.css +575 -0
  381. package/src/styles/stages.css +69 -0
  382. package/src/styles/terminal-loaders.css +122 -0
  383. package/src/styles/terminal-manifest.css +228 -0
  384. package/src/styles/web-theme.css +1007 -0
  385. package/src/styles/word-reveal.css +204 -0
  386. package/src/theme/apply-theme.ts +214 -0
  387. package/src/theme/index.ts +27 -0
  388. package/src/theme/palette-registry.ts +855 -0
  389. package/src/theme/tui-prefs.ts +64 -0
  390. package/src/ui/alert.tsx +78 -0
  391. package/src/ui/avatar.tsx +104 -0
  392. package/src/ui/badge.tsx +75 -0
  393. package/src/ui/breadcrumb.tsx +61 -0
  394. package/src/ui/button.tsx +67 -0
  395. package/src/ui/card.tsx +139 -0
  396. package/src/ui/checkbox.tsx +27 -0
  397. package/src/ui/collapsible.tsx +32 -0
  398. package/src/ui/date-pager.tsx +325 -0
  399. package/src/ui/dialog.tsx +157 -0
  400. package/src/ui/dropdown-menu.tsx +267 -0
  401. package/src/ui/empty-state.tsx +165 -0
  402. package/src/ui/field.tsx +104 -0
  403. package/src/ui/form.tsx +36 -0
  404. package/src/ui/icon-button.tsx +36 -0
  405. package/src/ui/index.ts +34 -0
  406. package/src/ui/input.tsx +33 -0
  407. package/src/ui/kbd.tsx +30 -0
  408. package/src/ui/label.tsx +32 -0
  409. package/src/ui/pager.tsx +119 -0
  410. package/src/ui/pagination.tsx +126 -0
  411. package/src/ui/radio-group.tsx +51 -0
  412. package/src/ui/search-bar.tsx +85 -0
  413. package/src/ui/segmented-control.tsx +76 -0
  414. package/src/ui/select.tsx +257 -0
  415. package/src/ui/separator.tsx +24 -0
  416. package/src/ui/sheet.tsx +141 -0
  417. package/src/ui/skeleton.tsx +76 -0
  418. package/src/ui/slider.tsx +76 -0
  419. package/src/ui/switch.tsx +31 -0
  420. package/src/ui/table.tsx +179 -0
  421. package/src/ui/tabs.tsx +89 -0
  422. package/src/ui/tags-input.tsx +168 -0
  423. package/src/ui/textarea.tsx +17 -0
  424. package/src/ui/tooltip.tsx +71 -0
@@ -0,0 +1,471 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Session-only embed/popup prefs (#3733 / #3736). Reload and `/new` reset:
5
+ * /digisearch and /digivault on, /websearch on, language English, view
6
+ * balanced, thinking auto. Not localStorage.
7
+ */
8
+
9
+ import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from "react";
10
+ import {
11
+ matchesMobileDensityViewport,
12
+ readStoredDensity,
13
+ resolveTraceDensity,
14
+ writeStoredDensity,
15
+ type TraceDensity,
16
+ } from "../trace-spacing";
17
+ import {
18
+ readStoredScrollMode,
19
+ resolveScrollMode,
20
+ writeStoredScrollMode,
21
+ type ScrollMode,
22
+ } from "../gallery-thread/scroll-mode";
23
+ import type { PaletteName, ResolvedTheme, ThemePreference } from "../../../theme/apply-theme";
24
+ import {
25
+ normalizeViewPref,
26
+ type ThinkingMode,
27
+ type ViewMode,
28
+ type SkinMcpServerConfig,
29
+ } from "./skin-types";
30
+
31
+ export type EmbedChatPrefs = {
32
+ webSearch: boolean;
33
+ digisearch: boolean;
34
+ vault: boolean;
35
+ /** Extra catalog / MCP server ids → enabled. Missing key means on. */
36
+ extra: Record<string, boolean>;
37
+ /** Session MCP JSON (user-added + operator overlays). Reload / /new clears. */
38
+ mcpCustom: SkinMcpServerConfig[];
39
+ language: string;
40
+ /** Chain-of-thought view mode (reasoning + tool calls). */
41
+ view: ViewMode;
42
+ /** Reasoning-only override on top of `view`. */
43
+ thinking: ThinkingMode;
44
+ model: string;
45
+ effort: string;
46
+ /** Web-search engine id (auto/internal/exa/tavily/parallel/firecrawl/tinyfish). */
47
+ searchEngine: string;
48
+ /** The model/provider/MCP/context row under the composer. */
49
+ toolbar: boolean;
50
+ /** `always` keeps scrollbars in their reserved gutter; `auto` shows them on scroll. */
51
+ scrollbars: "always" | "auto";
52
+ /** Worked-chain rhythm. A stored user choice wins over the deployment default. */
53
+ density: TraceDensity;
54
+ /**
55
+ * `follow` anchors the sent question at the top and chases the stream;
56
+ * `free` never moves the viewport. A stored user choice wins over the
57
+ * deployment default.
58
+ */
59
+ scroll: ScrollMode;
60
+ };
61
+
62
+ export const DEFAULT_EMBED_CHAT_PREFS: EmbedChatPrefs = {
63
+ webSearch: true,
64
+ digisearch: true,
65
+ vault: true,
66
+ extra: {},
67
+ mcpCustom: [],
68
+ // Session defaults mirror the app (`DEFAULT_LANGUAGE_CODE` / `DEFAULT_VIEW_MODE`
69
+ // / `DEFAULT_THINKING_MODE`): English, balanced, auto. Literals keep the
70
+ // package free of app imports (WS4); hosts inject their own via the factory.
71
+ language: "en",
72
+ view: "balanced",
73
+ thinking: "auto",
74
+ model: "",
75
+ effort: "medium",
76
+ searchEngine: "",
77
+ toolbar: true,
78
+ scrollbars: "always",
79
+ density: "default",
80
+ scroll: "follow",
81
+ };
82
+
83
+ /**
84
+ * Session chrome seeded from a deployment. Density re-reads storage so a
85
+ * user's palette choice survives `/new`; the rest return to the deployment.
86
+ */
87
+ export function chromePrefsFromDeploy(
88
+ input: {
89
+ density?: string | null;
90
+ effort?: string | null;
91
+ searchEngine?: string | null;
92
+ toolbar?: boolean | null;
93
+ scrollbars?: "always" | "auto" | null;
94
+ scroll?: "follow" | "free" | null;
95
+ } = {},
96
+ storage?: { getItem(key: string): string | null } | null,
97
+ context: { mobile?: boolean } = {},
98
+ ): Pick<
99
+ EmbedChatPrefs,
100
+ "density" | "effort" | "searchEngine" | "toolbar" | "scrollbars" | "scroll"
101
+ > {
102
+ const effort = input.effort?.trim().toLowerCase();
103
+ return {
104
+ density: resolveTraceDensity(
105
+ storage === undefined ? readStoredDensity() : readStoredDensity(storage),
106
+ input.density,
107
+ context,
108
+ ),
109
+ effort: effort === "low" || effort === "medium" || effort === "high" ? effort : "medium",
110
+ searchEngine: input.searchEngine?.trim() ?? "",
111
+ toolbar: input.toolbar !== false,
112
+ scrollbars: input.scrollbars === "auto" ? "auto" : "always",
113
+ scroll: resolveScrollMode(
114
+ storage === undefined ? readStoredScrollMode() : readStoredScrollMode(storage),
115
+ input.scroll,
116
+ ),
117
+ };
118
+ }
119
+
120
+ /**
121
+ * The reset paths (`/new`, `/clear`, `/compact`, the thread's new-thread
122
+ * button) rebuild chrome from the deployment. Density must resolve exactly the
123
+ * way the mount effect does — a stored choice first, then the phone default —
124
+ * or a phone drops back to the deployment rhythm on the first reset and never
125
+ * returns, because the embed client does not remount. Other chrome still
126
+ * returns to the deployment.
127
+ */
128
+ export function resetChromePrefsFromDeploy(
129
+ input: Parameters<typeof chromePrefsFromDeploy>[0] = {},
130
+ ): ReturnType<typeof chromePrefsFromDeploy> {
131
+ return chromePrefsFromDeploy(input, undefined, {
132
+ mobile: matchesMobileDensityViewport(),
133
+ });
134
+ }
135
+
136
+ /**
137
+ * Apply a stored `dt-density` after hydration, and the mobile default when the
138
+ * user has never chosen one. The first render uses the deployment density on
139
+ * both server and client, so `data-density` matches; afterwards a stored choice
140
+ * (or an airy mobile default) re-renders once.
141
+ *
142
+ * Order is stored user choice > mobile default (airy) > deployment default >
143
+ * "default" — see `resolveTraceDensity`.
144
+ */
145
+ export function useStoredDensityAfterMount(
146
+ setPrefs: (update: (prev: EmbedChatPrefs) => EmbedChatPrefs) => void,
147
+ ): void {
148
+ useEffect(() => {
149
+ const mobile = matchesMobileDensityViewport();
150
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- storage and matchMedia are client-only; reading them during render would mismatch the server HTML
151
+ setPrefs((prev) => {
152
+ const next = resolveTraceDensity(readStoredDensity(), prev.density, { mobile });
153
+ return prev.density === next ? prev : { ...prev, density: next };
154
+ });
155
+ }, [setPrefs]);
156
+ }
157
+
158
+ export function persistDensity(density: TraceDensity): void {
159
+ writeStoredDensity(density);
160
+ }
161
+
162
+ /**
163
+ * Apply a stored `dt-scroll` after hydration. The first render uses the
164
+ * deployment default on both server and client, so the viewport props match;
165
+ * a visitor who chose a mode re-renders once.
166
+ */
167
+ export function useStoredScrollAfterMount(
168
+ setPrefs: (update: (prev: EmbedChatPrefs) => EmbedChatPrefs) => void,
169
+ ): void {
170
+ useEffect(() => {
171
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- localStorage is client-only; reading it during render would mismatch the server HTML
172
+ setPrefs((prev) => {
173
+ const stored = readStoredScrollMode();
174
+ return !stored || prev.scroll === stored ? prev : { ...prev, scroll: stored };
175
+ });
176
+ }, [setPrefs]);
177
+ }
178
+
179
+ export function persistScroll(mode: ScrollMode): void {
180
+ writeStoredScrollMode(mode);
181
+ }
182
+
183
+ /**
184
+ * The package cannot import `@/lib/languages` / `@/lib/view-modes`, so hosts
185
+ * pass their own defaults; called with no overrides it returns the app
186
+ * defaults above, byte-for-byte.
187
+ */
188
+ export function createDefaultEmbedChatPrefs(
189
+ defaults?: { language?: string; view?: ViewMode; thinking?: ThinkingMode },
190
+ ): EmbedChatPrefs {
191
+ return {
192
+ ...DEFAULT_EMBED_CHAT_PREFS,
193
+ ...(defaults?.language !== undefined ? { language: defaults.language } : null),
194
+ ...(defaults?.view !== undefined ? { view: normalizeViewPref(defaults.view) } : null),
195
+ ...(defaults?.thinking !== undefined ? { thinking: defaults.thinking } : null),
196
+ };
197
+ }
198
+
199
+ export type CatalogToolRow = {
200
+ id: string;
201
+ label?: string;
202
+ default?: boolean;
203
+ /** Individual tools under this entry (per-tool session toggles). */
204
+ tools?: Array<{ id: string; label?: string; group?: string }>;
205
+ };
206
+
207
+ /** A look-only overlay on the prefs while the palette hovers a visual row. */
208
+ export type EmbedChatPrefsPreview = Partial<Pick<EmbedChatPrefs, "view" | "density" | "scrollbars">>;
209
+
210
+ export type EmbedChatPrefsApi = {
211
+ /** What renders: the committed prefs with any live preview on top. */
212
+ prefs: EmbedChatPrefs;
213
+ /**
214
+ * The prefs as chosen, without a preview. Menus read this for the checked
215
+ * row and for toggles. The provider fills it; absent means `prefs`.
216
+ */
217
+ committedPrefs?: EmbedChatPrefs;
218
+ /**
219
+ * Show a visual setting before it is chosen (palette hover / arrow keys).
220
+ * Never persisted; `null` drops the preview. The provider fills it.
221
+ */
222
+ previewPrefs?: (patch: EmbedChatPrefsPreview | null) => void;
223
+ /**
224
+ * Paint a theme before it is chosen, without storing it. `null` drops the
225
+ * preview. Hosts that own the theme (`setTheme`) provide it; the document
226
+ * theme previews through `applyDocumentTheme(..., { persist: false })`.
227
+ */
228
+ previewTheme?: (next: { preference: ThemePreference; palette: PaletteName } | null) => void;
229
+ setWebSearch: (value: boolean) => void;
230
+ setDigisearch: (value: boolean) => void;
231
+ setVault: (value: boolean) => void;
232
+ setExtraTool: (id: string, value: boolean) => void;
233
+ extraToolOn: (id: string) => boolean;
234
+ setMcpConfig: (config: SkinMcpServerConfig, previousId?: string) => void;
235
+ removeMcpConfig: (id: string) => void;
236
+ setLanguage: (code: string) => void;
237
+ /**
238
+ * The tenant's chat languages, for the composer language chip and the
239
+ * `/language` page. Absent (or fewer than two) means no chip and every
240
+ * supported language on `/language`; set, `/language` offers only these.
241
+ */
242
+ languageOptions?: { code: string; short: string; label: string }[];
243
+ /**
244
+ * The only languages `setLanguage` accepts (a tenant's `locales.languages`,
245
+ * one or more). `setLanguage` ignores any other code; the menus and the
246
+ * session tool read this to offer or refuse. Absent means any supported
247
+ * language.
248
+ */
249
+ allowedLanguages?: readonly string[];
250
+ /** Footer credit in the session language: `${lead} digithings ${tail}`. */
251
+ credit?: { lead: string; tail: string };
252
+ setView: (mode: ViewMode) => void;
253
+ setThinking: (value: ThinkingMode) => void;
254
+ setModel: (id: string) => void;
255
+ setEffort: (effort: string) => void;
256
+ setSearchEngine: (engine: string) => void;
257
+ setToolbar: (visible: boolean) => void;
258
+ setScrollbars: (mode: "always" | "auto") => void;
259
+ setDensity: (density: TraceDensity) => void;
260
+ setScroll: (mode: ScrollMode) => void;
261
+ reset: () => void;
262
+ tenantAllowsWeb: boolean;
263
+ showByok: boolean;
264
+ /**
265
+ * The backend that serves this chat, as a display label (an own-key
266
+ * provider id, or the house backend id). The host owns the provider
267
+ * vocabulary; absent means unknown, so the composer chip stays hidden
268
+ * rather than naming a backend that may be wrong.
269
+ */
270
+ providerLabel?: string;
271
+ showModels: boolean;
272
+ /**
273
+ * Model id the turn sends, including a bring-your-own-key binding.
274
+ * Sizes the context meter only. An empty session still sends no
275
+ * X-Digi-Model.
276
+ */
277
+ meterModel?: string;
278
+ /**
279
+ * Render gate for the context meter. The toolbar draws the bar only
280
+ * when this is true.
281
+ */
282
+ showContextMeter?: boolean;
283
+ /**
284
+ * The trial gate's own turn budget, when the host runs one. The toolbar
285
+ * draws this in place of the context meter: a turn budget is the number
286
+ * that stops the visitor, and it exists even where the backend reports no
287
+ * token usage. Absent means "no gate", so the context meter keeps the slot.
288
+ */
289
+ usage?: { used: number; limit: number };
290
+ hasDigisearch: boolean;
291
+ hasVault: boolean;
292
+ hasSessions: boolean;
293
+ /** A session artifact surface exists here. Gates the /artifacts row. */
294
+ hasArtifacts: boolean;
295
+ allowUserMcp: boolean;
296
+ allowAddMcp: boolean;
297
+ catalogTools: CatalogToolRow[];
298
+ /** Operator MCP servers (ids/labels only — never URLs). */
299
+ mcpServers: CatalogToolRow[];
300
+ sessionKey: string;
301
+ openSettings: () => void;
302
+ /** Dedicated help panel: what the assistant can do and how to use it. */
303
+ openHelp: () => void;
304
+ openTools: () => void;
305
+ openMcp: (seed?: string) => void;
306
+ openByok: (seed?: string) => void;
307
+ openModels: () => void;
308
+ openEffort: () => void;
309
+ openSearchEngine: () => void;
310
+ openView: () => void;
311
+ openDensity: () => void;
312
+ /**
313
+ * Hide `/theme` and ignore a typed one. No host sets this today: tenant
314
+ * embeds offer `/theme` through `themeState` / `setTheme` (2.6.6). The full
315
+ * app leaves this unset.
316
+ */
317
+ themeLocked?: boolean;
318
+ /**
319
+ * Model ids this chat offers (the picker's list). The model's
320
+ * session_set_model is checked against it, so a pick the server would
321
+ * refuse is reported back instead of breaking the next turn.
322
+ */
323
+ availableModels?: readonly string[];
324
+ /** Open the mode + palette picker. No-op when the host does not provide it. */
325
+ openTheme?: () => void;
326
+ /**
327
+ * Host-owned theme (tenant embeds). When set, `/theme` and its picker read
328
+ * this instead of the document-wide `dt-theme` / `dt-palette` keys, and a
329
+ * pick goes through `setTheme` rather than `applyDocumentTheme`, so it is
330
+ * not written to localStorage. `auto` drops the pick (back to the host's
331
+ * default). The full app leaves both unset.
332
+ */
333
+ themeState?: { preference: ThemePreference; palette: PaletteName; resolved: ResolvedTheme };
334
+ setTheme?: (preference: ThemePreference, palette: PaletteName) => void;
335
+ openThinking: () => void;
336
+ openLanguage: () => void;
337
+ openSessions: () => void;
338
+ openArtifacts: () => void;
339
+ newThread: () => void;
340
+ compactThread: () => void | Promise<void>;
341
+ undo: () => void;
342
+ redo: () => void;
343
+ /**
344
+ * Who may flip a tool. `agent` (Foundry) and `locked` (OCC session lock,
345
+ * or allowUserToggle false) list every tool and MCP server with no toggle.
346
+ * Omit means the host still toggles.
347
+ */
348
+ toolControl?: "toggle" | "locked" | "agent";
349
+ /** Text after the pane command. The open pane filters on it. */
350
+ paletteQuery?: string;
351
+ /** Composer writer used by menu rows. The skin binds it to `setText`. */
352
+ setComposerDraft?: (text: string) => void;
353
+ /**
354
+ * True only after a skin called `bindComposerDraft`. The writer exists on
355
+ * every host, and until a skin binds it the sink is a no-op, so the menu
356
+ * must close and change pages itself.
357
+ */
358
+ composerDraftBound?: boolean;
359
+ bindComposerDraft?: (setText: (text: string) => void) => void;
360
+ /**
361
+ * Download the whole conversation (`/export`, the settings menu). The
362
+ * skin binds it from inside the runtime, so a host without a skin bound
363
+ * leaves `threadExportBound` false.
364
+ */
365
+ exportThread?: (format: "md" | "html") => void;
366
+ threadExportBound?: boolean;
367
+ bindThreadExport?: (run: (format: "md" | "html") => void) => void;
368
+ /** One palette frame. `keep` leaves a button-opened menu alone. */
369
+ syncPalette?: (next: {
370
+ kind: "closed" | "commands" | "pane";
371
+ menu: "close" | "keep" | string;
372
+ filter: string;
373
+ }) => void;
374
+ };
375
+
376
+ const EmbedChatPrefsContext = createContext<EmbedChatPrefsApi | null>(null);
377
+
378
+ export function EmbedChatPrefsProvider({
379
+ value,
380
+ children,
381
+ }: {
382
+ value: EmbedChatPrefsApi;
383
+ children: ReactNode;
384
+ }) {
385
+ // One preview overlay for every consumer below (thread, skin, toolbar), so
386
+ // a hovered view / density / scrollbar row renders in every host without
387
+ // touching the host's committed state or storage.
388
+ const [preview, setPreview] = useState<EmbedChatPrefsPreview | null>(null);
389
+ const merged = useMemo((): EmbedChatPrefsApi => {
390
+ // A nested provider keeps the outer overlay.
391
+ if (value.previewPrefs) return value;
392
+ const committedPrefs = value.prefs;
393
+ return {
394
+ ...value,
395
+ prefs: preview ? { ...committedPrefs, ...preview } : committedPrefs,
396
+ committedPrefs,
397
+ previewPrefs: setPreview,
398
+ };
399
+ }, [value, preview]);
400
+ return (
401
+ <EmbedChatPrefsContext.Provider value={merged}>{children}</EmbedChatPrefsContext.Provider>
402
+ );
403
+ }
404
+
405
+ /** The prefs as chosen, ignoring a live preview. */
406
+ export function committedChatPrefs(api: Pick<EmbedChatPrefsApi, "prefs" | "committedPrefs">): EmbedChatPrefs {
407
+ return api.committedPrefs ?? api.prefs;
408
+ }
409
+
410
+ /**
411
+ * The look a main-palette row would give, for rows that flip a purely visual
412
+ * setting in place (`/scrollbar`). Null for everything else.
413
+ */
414
+ export function slashRowPreview(id: string, prefs: EmbedChatPrefs): EmbedChatPrefsPreview | null {
415
+ if (id === "scrollbar") return { scrollbars: prefs.scrollbars === "always" ? "auto" : "always" };
416
+ return null;
417
+ }
418
+
419
+ export function useEmbedChatPrefsOptional(): EmbedChatPrefsApi | null {
420
+ return useContext(EmbedChatPrefsContext);
421
+ }
422
+
423
+ export function useEmbedChatPrefs(): EmbedChatPrefsApi {
424
+ const ctx = useContext(EmbedChatPrefsContext);
425
+ if (!ctx) {
426
+ throw new Error("useEmbedChatPrefs requires EmbedChatPrefsProvider");
427
+ }
428
+ return ctx;
429
+ }
430
+
431
+ /** Catalog ids to send as X-Digi-Disabled-Tools (web search uses its own header). */
432
+ export function disabledCatalogIds(prefs: EmbedChatPrefs): string[] {
433
+ const out: string[] = [];
434
+ if (!prefs.digisearch) out.push("digisearch");
435
+ if (!prefs.vault) out.push("digivault");
436
+ for (const [id, on] of Object.entries(prefs.extra)) {
437
+ if (!on && id.trim()) out.push(id);
438
+ }
439
+ return out;
440
+ }
441
+
442
+ /** Catalog + operator MCP ids for slash/settings (never URLs). */
443
+ export function catalogToolsFromClient(cfg: {
444
+ tools: { catalog: CatalogToolRow[] };
445
+ mcp: { servers: CatalogToolRow[] };
446
+ }): CatalogToolRow[] {
447
+ const seen = new Set<string>();
448
+ const out: CatalogToolRow[] = [];
449
+ for (const t of [...cfg.tools.catalog, ...cfg.mcp.servers]) {
450
+ const id = t.id.trim();
451
+ if (!id || seen.has(id)) continue;
452
+ seen.add(id);
453
+ out.push({
454
+ id,
455
+ ...(t.label ? { label: t.label } : {}),
456
+ ...(typeof t.default === "boolean" ? { default: t.default } : {}),
457
+ ...(t.tools?.length ? { tools: t.tools.map((x) => ({ ...x })) } : {}),
458
+ });
459
+ }
460
+ return out;
461
+ }
462
+
463
+ /** Extra catalog/MCP ids with `default: false` start off for this session. */
464
+ export function extraOffFromCatalog(tools: readonly CatalogToolRow[]): Record<string, boolean> {
465
+ const extra: Record<string, boolean> = {};
466
+ for (const t of tools) {
467
+ if (t.id === "digisearch" || t.id === "digivault" || t.id === "web_search") continue;
468
+ if (t.default === false) extra[t.id] = false;
469
+ }
470
+ return extra;
471
+ }