@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,178 @@
1
+ export type BuiltInDocsToolId = "searchDocs" | "openPage" | "generateCodeSnippet";
2
+
3
+ export type DocsToolId = BuiltInDocsToolId | (string & {});
4
+
5
+ export type DocsToolRenderer = "sourceResults" | "pagePreview" | "codeSnippet" | "generic";
6
+
7
+ export type DemoFlowId = "auth401" | "webhooks" | "codeExample";
8
+
9
+ export type SuggestedPrompt = {
10
+ title: string;
11
+ description?: string;
12
+ prompt?: string;
13
+ flowId?: DemoFlowId;
14
+ };
15
+
16
+ export type DocsToolConfig = {
17
+ id: DocsToolId;
18
+ displayName: string;
19
+ aiDescription: string;
20
+ realImplementationHint: string;
21
+ rendererType: DocsToolRenderer;
22
+ inputSchema?: Record<string, unknown>;
23
+ outputSchema?: Record<string, unknown>;
24
+ mockResponse?: unknown;
25
+ };
26
+
27
+ export type DocsPage = {
28
+ id: string;
29
+ title: string;
30
+ section: string;
31
+ description: string;
32
+ url: string;
33
+ markdown: string;
34
+ keywords: string[];
35
+ relatedPageIds: string[];
36
+ };
37
+
38
+ export type CodeSnippet = {
39
+ topic: string;
40
+ language: "curl" | "typescript" | "python";
41
+ code: string;
42
+ notes: string[];
43
+ docsUrl: string;
44
+ };
45
+
46
+ export type SearchResult = {
47
+ pageId: string;
48
+ title: string;
49
+ section: string;
50
+ url: string;
51
+ snippet: string;
52
+ score: number;
53
+ };
54
+
55
+ export type SearchDocsOutput = {
56
+ query: string;
57
+ results: SearchResult[];
58
+ };
59
+
60
+ export type OpenPageOutput = {
61
+ pageId: string;
62
+ title: string;
63
+ section: string;
64
+ url: string;
65
+ description: string;
66
+ relatedPageIds: string[];
67
+ };
68
+
69
+ export type GenerateCodeSnippetOutput = CodeSnippet;
70
+
71
+ export type DocsToolInputById = {
72
+ searchDocs: { query: string; limit?: number };
73
+ openPage: { pageId: string };
74
+ generateCodeSnippet: { topic: string; language?: "curl" | "typescript" | "python" };
75
+ };
76
+
77
+ export type DocsToolOutputById = {
78
+ searchDocs: SearchDocsOutput;
79
+ openPage: OpenPageOutput;
80
+ generateCodeSnippet: GenerateCodeSnippetOutput;
81
+ };
82
+
83
+ export type SearchDocsDemoFlowStep = {
84
+ id: string;
85
+ assistantText: string;
86
+ toolId: "searchDocs";
87
+ input: DocsToolInputById["searchDocs"];
88
+ output: DocsToolOutputById["searchDocs"];
89
+ };
90
+
91
+ export type OpenPageDemoFlowStep = {
92
+ id: string;
93
+ assistantText: string;
94
+ toolId: "openPage";
95
+ input: DocsToolInputById["openPage"];
96
+ output: DocsToolOutputById["openPage"];
97
+ };
98
+
99
+ export type GenerateCodeSnippetDemoFlowStep = {
100
+ id: string;
101
+ assistantText: string;
102
+ toolId: "generateCodeSnippet";
103
+ input: DocsToolInputById["generateCodeSnippet"];
104
+ output: DocsToolOutputById["generateCodeSnippet"];
105
+ };
106
+
107
+ export type DemoFlowStep =
108
+ | SearchDocsDemoFlowStep
109
+ | OpenPageDemoFlowStep
110
+ | GenerateCodeSnippetDemoFlowStep
111
+ | {
112
+ id: string;
113
+ assistantText: string;
114
+ toolId: DocsToolId;
115
+ input: unknown;
116
+ output: unknown;
117
+ };
118
+
119
+ export type DemoFlowConfig = {
120
+ triggerPhrases: string[];
121
+ title: string;
122
+ steps: DemoFlowStep[];
123
+ finalResponse: string;
124
+ };
125
+
126
+ export type DocsAssistantConfig = {
127
+ productName: string;
128
+ docsName: string;
129
+ assistantName: string;
130
+ welcome: {
131
+ headline: string;
132
+ body: string;
133
+ };
134
+ labels: {
135
+ currentPage: string;
136
+ source: string;
137
+ relatedPages: string;
138
+ openPage: string;
139
+ headerSearch: string;
140
+ articleCtaTitle: string;
141
+ articleCtaBody: string;
142
+ articleCtaAction: string;
143
+ composerPlaceholder: string;
144
+ previewWarning: string;
145
+ };
146
+ suggestedPrompts: SuggestedPrompt[];
147
+ tools: DocsToolConfig[];
148
+ demoModeNotice: string;
149
+ demoFlows: Record<DemoFlowId, DemoFlowConfig>;
150
+ };
151
+
152
+ export type BrandTheme = {
153
+ accent: string;
154
+ surface: string;
155
+ border: string;
156
+ mutedText: string;
157
+ focusRing: string;
158
+ };
159
+
160
+ export type DocsNavGroup = {
161
+ label: string;
162
+ pageIds: string[];
163
+ };
164
+
165
+ export type DocsHostUiSpec = {
166
+ version: 1;
167
+ root: {
168
+ type: "ContentShell";
169
+ props: {
170
+ productName: string;
171
+ docsName: string;
172
+ defaultPageId: string;
173
+ pages: DocsPage[];
174
+ assistantPlacement?: "sidebar" | "modal";
175
+ navGroups?: DocsNavGroup[];
176
+ };
177
+ };
178
+ };
@@ -0,0 +1,19 @@
1
+ import * as React from "react";
2
+
3
+ const MOBILE_BREAKPOINT = 768;
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
12
+ };
13
+ mql.addEventListener("change", onChange);
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
15
+ return () => mql.removeEventListener("change", onChange);
16
+ }, []);
17
+
18
+ return !!isMobile;
19
+ }
@@ -0,0 +1,90 @@
1
+ # Stock assistant-ui (baseline preview)
2
+
3
+ Copies of the public assistant-ui **base** registry (`https://r.assistant-ui.com/base/…`)
4
+ plus the matching shadcn **base-nova** primitives those files import
5
+ (button, tooltip, collapsible, dialog, avatar, skeleton, textarea).
6
+
7
+ The only edits here are:
8
+
9
+ - import paths rewritten to this folder
10
+ - `dialog.tsx` close icon uses `lucide-react` `XIcon` instead of their
11
+ registry `IconPlaceholder` (that module is not in this app)
12
+ - `tool-fallback.aui.tsx` adds the Gloomberb attribution footer
13
+ (`ToolFallbackAttribution`, reading `readGloomberbAttribution` from
14
+ `@digithings-ai/ui`) under the Result pane — the same line the first-party
15
+ gallery thread renders (#4098). No other styling changes.
16
+
17
+ ## Shape: the base skin's radii
18
+
19
+ Inside the stock Thread every corner follows the base skin (assistant-ui's
20
+ base registry, `https://r.assistant-ui.com/base/*.json`, deps
21
+ `@assistant-ui/react@^0.15.32`, and shadcn **base-nova**,
22
+ `https://ui.shadcn.com/r/styles/base-nova/*.json`): `--composer-radius: 1.5rem`
23
+ (composer and user bubble, the base skin's `--radius-thread`), `rounded-full` composer buttons and
24
+ scroll-to-bottom, `rounded-xl` more-menu / dialog / code block, `rounded-lg`
25
+ menu items, reasoning and tool-group, `rounded-md` suggestions, notices and
26
+ tooltips, base-nova button sizes. Never put a zero-radius shell back.
27
+
28
+ Some of these files (button, tooltip, textarea, markdown, notices, tool
29
+ fallback, reasoning, tool group, JSON view) are also used by other skins, which
30
+ keep their own square house radius. They read `useStockShape()` from
31
+ `stock-shape.tsx`; `StockShapeProvider` wraps the stock `Thread`, so only the
32
+ stock skin gets the rounded shapes. Pinned by `thread-defaults.source.test.ts`,
33
+ `stock-more-menu.source.test.ts` and `stock-shape.render.test.tsx`.
34
+
35
+ Host components passed through the Thread's `components` prop (`Welcome`,
36
+ `Footer`, `AssistantMessage`, `ToolFallback`, `ToolGroup`, `ReasoningGroup`)
37
+ render inside `StockShapeProvider` too, so any of these shared files they use
38
+ round the same way. Portals opened outside the provider (and every other
39
+ skin) keep the square default: the context defaults to `false`.
40
+
41
+ ## Colour: the raised surface
42
+
43
+ The stock parts paint their raised fill (user bubble, table heads, skeletons,
44
+ dialog, inline code, hovers) with `bg-surface-2` and `bg-surface-2/<n>`.
45
+ `styles/chat-aui.css` defines that utility (`@utility bg-surface-*`) scoped to
46
+ the stock thread (its root carries `data-stock-thread`) and the stock portals
47
+ rendered from it (the dialog carries `data-stock-portal` inside
48
+ `StockShapeProvider`, via `stockPortalProps`). It is never page-wide and has
49
+ no theme colour: anywhere else the class matches no declaration, so host
50
+ chrome around the thread (the docs page's outline Button) and other skins that
51
+ reuse stock parts (markdown, tool cards) keep their own background. The "…"
52
+ menu gets its panel from `styles/chat-stock-menu.css`.
53
+
54
+ ## Trace: the base skin's work chain
55
+
56
+ The stock Thread draws reasoning and tool calls with the base skin's trace
57
+ (`../skins/base/elements/assistant-trace.aui.tsx`, shared with the base
58
+ Thread): one collapsible work chain per turn ("Working" / "Worked", folded
59
+ "Used 3 tools"), a collapsible reasoning box and `N tool calls` group inside
60
+ it, and assistant-ui's own collapsible tool card (arguments, result) for each
61
+ call. Grouping and fold rules are `../trace-grouping`; the parts are
62
+ `../skins/base/aui-default` (see its README). Text, files, images and the
63
+ loading indicator stay the stock ones. A host's `ToolFallback`, `ToolGroup`
64
+ or `ReasoningGroup` still replaces the matching piece.
65
+
66
+ What changes for deploys that host the stock Thread (webpage assistant,
67
+ product page assistant, Expo preview, `/baseline`):
68
+
69
+ - Reasoning or tool calls set to "off" in the deploy's work disclosure are now
70
+ hidden in the stock thread too.
71
+ - `locked_open` now pins the work chain open, as in the base skin.
72
+ - The default tool card is now the base skin's (assistant-ui's collapsible
73
+ card), not the stock `ToolFallback`.
74
+ - The shape gating (`useStockShape`) in the stock `reasoning.tsx`,
75
+ `tool-group.aui.tsx` and `tool-fallback.aui.tsx` is no longer reached from
76
+ the stock thread; it still applies wherever another skin mounts those parts.
77
+
78
+ Do not restyle these files for digichat. `/baseline` mounts this Thread with no extra chrome.
79
+
80
+ Full elements catalog (what else exists upstream and how to attach it):
81
+ [`packages/ui/ASSISTANT_UI_ELEMENTS.md`](../../../../../../packages/ui/ASSISTANT_UI_ELEMENTS.md).
82
+
83
+ ## License
84
+
85
+ The assistant-ui registry files are copied from
86
+ [assistant-ui/assistant-ui](https://github.com/assistant-ui/assistant-ui)
87
+ (MIT License, Copyright (c) 2026 AgentbaseAI Inc., as in the LICENSE of
88
+ `@assistant-ui/react@0.15.32`) and the base-nova
89
+ primitives from [shadcn-ui/ui](https://github.com/shadcn-ui/ui) (MIT License,
90
+ Copyright (c) 2023 shadcn); both notices apply to the vendored files here.
@@ -0,0 +1,305 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Session artifact surface (DIG-2882, over DIG-2784 / PR #5390).
5
+ *
6
+ * Two client surfaces live here because they answer the same question from
7
+ * opposite ends: `/artifacts` lists what this session produced, and a link the
8
+ * model embedded in a reply opens one of those rows.
9
+ *
10
+ * **Every media-type decision is the server's.** The list route answers with a
11
+ * `viewable` flag it computed from its own inline list; this file never
12
+ * re-derives it, so the browser and the `Content-Disposition` the blob route
13
+ * sends can never disagree about the same row.
14
+ *
15
+ * **Link lifetime is the server's too.** `bindLink` binds a token to a session
16
+ * and the blob route answers `410 session_expired` for a token the session no
17
+ * longer owns. A dead token is therefore a normal outcome here, not an error
18
+ * to dump at the reader - see `ArtifactLink`.
19
+ */
20
+
21
+ import { useCallback, useEffect, useState, type ReactNode } from "react";
22
+
23
+ import { cn } from "../../../lib/utils";
24
+ import { p, stripBasePath } from "../../../lib/base-path";
25
+ import { StateBlock } from "../../desk/StateBlock";
26
+
27
+ /** The list route the server already ships (see `.../artifacts/route.ts`). */
28
+ export type ArtifactRow = {
29
+ id: string;
30
+ /** The token the store minted. Present on the list row, so no minting here. */
31
+ token: string;
32
+ name: string;
33
+ mediaType: string;
34
+ byteSize: number;
35
+ kind: string;
36
+ summary: string | null;
37
+ createdAt: string | number | Date;
38
+ /** Server-computed. Never recomputed client-side. */
39
+ viewable: boolean;
40
+ };
41
+
42
+ /**
43
+ * `GET /api/conversations/[id]/artifacts` - the panel's only read.
44
+ *
45
+ * The path carries the base path the app is served under (DIG-5121): the app
46
+ * answers under /chat/api/conversations/… and nowhere else, so a
47
+ * root-absolute path would 404 the moment the app moves.
48
+ */
49
+ export function artifactListPath(conversationId: string): string {
50
+ return p(`/api/conversations/${encodeURIComponent(conversationId)}/artifacts`);
51
+ }
52
+
53
+ /** The link target, carrying the token the store minted. */
54
+ export function artifactBlobPath(conversationId: string, token: string): string {
55
+ return `${artifactListPath(conversationId)}/blob?token=${encodeURIComponent(token)}`;
56
+ }
57
+
58
+ const BLOB_PATH = /^\/api\/conversations\/[^/]+\/artifacts\/blob$/;
59
+
60
+ /**
61
+ * True when an href is a session artifact link. Pure string work on the path
62
+ * so it runs identically in the browser and in a test - `new URL(href, base)`
63
+ * would make an href without a scheme host-dependent, and a link that is
64
+ * "maybe an artifact" depending on where it was parsed is not a predicate.
65
+ *
66
+ * The base path is stripped first: the app hands out the link already
67
+ * prefixed (/chat/api/conversations/…), and the predicate is about the app's
68
+ * own path, not about where the app happens to be served.
69
+ */
70
+ export function isArtifactBlobHref(href: string | undefined | null): boolean {
71
+ if (!href) return false;
72
+ const path = href.split(/[?#]/, 1)[0] ?? "";
73
+ return BLOB_PATH.test(stripBasePath(path));
74
+ }
75
+
76
+ /** Deterministic, locale-free size label. Never used to decide anything. */
77
+ export function formatArtifactSize(byteSize: number): string {
78
+ if (!Number.isFinite(byteSize) || byteSize < 0) return "-";
79
+ if (byteSize < 1024) return `${Math.trunc(byteSize)} B`;
80
+ const units = ["KB", "MB", "GB"];
81
+ let value = byteSize / 1024;
82
+ let unit = 0;
83
+ while (value >= 1024 && unit < units.length - 1) {
84
+ value /= 1024;
85
+ unit += 1;
86
+ }
87
+ const rounded = Math.round(value * 10) / 10;
88
+ return `${rounded} ${units[unit]}`;
89
+ }
90
+
91
+ /** ISO date if we can get one, else the raw value. Never throws. */
92
+ export function formatArtifactDate(createdAt: string | number | Date): string {
93
+ const d = createdAt instanceof Date ? createdAt : new Date(createdAt);
94
+ return Number.isNaN(d.getTime()) ? "-" : d.toISOString().slice(0, 10);
95
+ }
96
+
97
+ /** Injectable seams so tests never need a network or a real `window`. */
98
+ export type ArtifactIo = {
99
+ fetchImpl?: typeof fetch;
100
+ /** Opens the blob in a new tab. Return false if the browser refused. */
101
+ openInNewTab?: (url: string) => boolean;
102
+ /** Same-tab fallback when a new tab was refused or is not wanted. */
103
+ navigate?: (url: string) => void;
104
+ };
105
+
106
+ function defaultOpenInNewTab(url: string): boolean {
107
+ const w = window.open(url, "_blank", "noopener,noreferrer");
108
+ return typeof w !== "undefined" && w !== null;
109
+ }
110
+
111
+ function defaultNavigate(url: string): void {
112
+ window.location.assign(url);
113
+ }
114
+
115
+ export function ArtifactsPanel({
116
+ conversationId,
117
+ open,
118
+ onClose,
119
+ fetchImpl,
120
+ openInNewTab = defaultOpenInNewTab,
121
+ navigate = defaultNavigate,
122
+ }: ArtifactIo & {
123
+ conversationId: string | null;
124
+ open: boolean;
125
+ onClose: () => void;
126
+ }) {
127
+ const [rows, setRows] = useState<ArtifactRow[] | null>(null);
128
+ const [state, setState] = useState<"idle" | "loading" | "error">("idle");
129
+
130
+ const load = useCallback(async () => {
131
+ if (!conversationId) {
132
+ setRows([]);
133
+ setState("idle");
134
+ return;
135
+ }
136
+ setState("loading");
137
+ try {
138
+ const doFetch = fetchImpl ?? fetch;
139
+ const res = await doFetch(artifactListPath(conversationId));
140
+ if (!res.ok) {
141
+ setRows(null);
142
+ setState("error");
143
+ return;
144
+ }
145
+ const body = (await res.json()) as { artifacts?: ArtifactRow[] };
146
+ const artifacts = Array.isArray(body.artifacts) ? body.artifacts : [];
147
+ setRows(artifacts);
148
+ setState("idle");
149
+ } catch {
150
+ setRows(null);
151
+ setState("error");
152
+ }
153
+ }, [conversationId, fetchImpl]);
154
+
155
+ useEffect(() => {
156
+ if (!open) return;
157
+ void load();
158
+ }, [open, load]);
159
+
160
+ if (!open) return null;
161
+
162
+ return (
163
+ <div
164
+ className="aui-artifacts-panel border-hair bg-surface-2 fixed inset-y-0 end-0 z-50 flex w-full max-w-sm flex-col border-s"
165
+ data-artifacts-panel=""
166
+ role="dialog"
167
+ aria-label="Session artifacts"
168
+ >
169
+ <header className="border-hair flex items-center justify-between border-b px-4 py-3">
170
+ <h2 className="text-sm font-semibold">Files this session produced</h2>
171
+ <button
172
+ type="button"
173
+ onClick={onClose}
174
+ className="text-ink-mute hover:text-ink text-sm"
175
+ >
176
+ Close
177
+ </button>
178
+ </header>
179
+
180
+ {!conversationId ? (
181
+ <StateBlock
182
+ kind="withheld"
183
+ title="No session store."
184
+ reason="This chat was not opened with a conversation, so it cannot list artifacts."
185
+ className="m-4"
186
+ />
187
+ ) : state === "loading" ? (
188
+ <StateBlock
189
+ kind="loading"
190
+ title="Reading session files."
191
+ className="m-4"
192
+ />
193
+ ) : state === "error" ? (
194
+ <StateBlock
195
+ kind="error"
196
+ title="Could not load this session's files."
197
+ reason="The artifact route did not answer."
198
+ onRetry={() => void load()}
199
+ className="m-4"
200
+ />
201
+ ) : !rows || rows.length === 0 ? (
202
+ <StateBlock
203
+ kind="empty"
204
+ title="No files in this session yet."
205
+ reason="They appear here as the assistant produces them."
206
+ className="m-4"
207
+ />
208
+ ) : (
209
+ <ul className="flex-1 overflow-y-auto">
210
+ {rows.map((row) => (
211
+ <li key={row.id} className="border-hair border-b last:border-b-0">
212
+ <button
213
+ type="button"
214
+ className="flex w-full flex-col gap-1 px-4 py-3 text-start hover:bg-accent/50"
215
+ onClick={() => {
216
+ const url = artifactBlobPath(conversationId, row.token);
217
+ // The row decides, via the server's own flag. No media-type
218
+ // list is duplicated here on purpose.
219
+ if (row.viewable) {
220
+ if (!openInNewTab(url)) navigate(url);
221
+ } else {
222
+ navigate(url);
223
+ }
224
+ }}
225
+ >
226
+ <span className="text-sm font-medium">{row.name}</span>
227
+ <span className="text-ink-mute text-xs">
228
+ {row.mediaType} · {formatArtifactSize(row.byteSize)} ·{" "}
229
+ {formatArtifactDate(row.createdAt)}
230
+ </span>
231
+ </button>
232
+ </li>
233
+ ))}
234
+ </ul>
235
+ )}
236
+ </div>
237
+ );
238
+ }
239
+
240
+ /**
241
+ * The `a:` override for artifact links in an assistant reply (DoD 3).
242
+ *
243
+ * A session artifact link is clickable and carries the token the store
244
+ * minted. The failure case is the reason this component exists: a dead token
245
+ * answers `410 session_expired`, and following that link normally would show
246
+ * the reader a raw JSON error body. So the click is intercepted, the link is
247
+ * probed, and a dead one becomes a sentence in place instead.
248
+ *
249
+ * Any non-artifact href never reaches here - `markdown-text.tsx` routes on
250
+ * `isArtifactBlobHref` and renders its plain anchor otherwise.
251
+ */
252
+ export function ArtifactLink({
253
+ href,
254
+ className,
255
+ children,
256
+ fetchImpl,
257
+ openInNewTab = defaultOpenInNewTab,
258
+ navigate = defaultNavigate,
259
+ }: ArtifactIo & {
260
+ href: string;
261
+ className?: string;
262
+ children?: ReactNode;
263
+ }) {
264
+ const [expired, setExpired] = useState(false);
265
+
266
+ const onClick = useCallback(
267
+ async (event: React.MouseEvent<HTMLAnchorElement>) => {
268
+ event.preventDefault();
269
+ setExpired(false);
270
+ try {
271
+ const doFetch = fetchImpl ?? fetch;
272
+ const res = await doFetch(href, { method: "GET" });
273
+ if (res.status === 410) {
274
+ setExpired(true);
275
+ return;
276
+ }
277
+ } catch {
278
+ // Could not probe: let the browser go to the link rather than guess.
279
+ }
280
+ if (!openInNewTab(href)) navigate(href);
281
+ },
282
+ [href, fetchImpl, openInNewTab, navigate],
283
+ );
284
+
285
+ return (
286
+ <>
287
+ <a
288
+ className={cn(
289
+ "aui-md-a text-accent hover:text-accent/80 underline underline-offset-2",
290
+ className,
291
+ )}
292
+ href={href}
293
+ onClick={onClick}
294
+ >
295
+ {children}
296
+ </a>
297
+ {expired ? (
298
+ <span className="aui-artifact-expired text-ink-mute ms-1 text-xs">
299
+ This artifact link belongs to a chat session that has ended. Open
300
+ /artifacts in the current chat to list this session&apos;s files.
301
+ </span>
302
+ ) : null}
303
+ </>
304
+ );
305
+ }