@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,866 @@
1
+ "use client";
2
+
3
+ import { useViewDisclosure } from "./deploy-ui-context";
4
+ import { memo, useCallback, useRef, useState } from "react";
5
+ import { DisclosureChevron } from "../disclosure-chevron";
6
+ import { DotMatrix, type DotMatrixState } from "../DotMatrix";
7
+ import { useTurnOutcome } from "../turn-outcome";
8
+ import {
9
+ toolApprovalAcceptsText,
10
+ useScrollLock,
11
+ useToolCallElapsed,
12
+ type ToolApprovalOption,
13
+ type ToolCallMessagePart,
14
+ type ToolCallMessagePartProps,
15
+ type ToolCallMessagePartStatus,
16
+ type ToolCallMessagePartComponent,
17
+ } from "@assistant-ui/react";
18
+ import {
19
+ Collapsible,
20
+ CollapsibleContent,
21
+ CollapsibleTrigger,
22
+ } from "./ui/collapsible";
23
+ import { cn } from "../../../lib/utils";
24
+ import { useExportKeepMounted } from "../../../replay/export-mount";
25
+ import { toolRowTitle } from "./tool-display";
26
+ import { Button } from "./ui/button";
27
+ import { Textarea } from "./ui/textarea";
28
+ import { readGloomberbAttribution } from "@digithings-ai/ui";
29
+ import { ChatNoticeContent, chatNoticeRootProps } from "./chat-notice";
30
+ import { JsonView } from "./json-view";
31
+ import { stockRadius, useStockShape } from "./stock-shape";
32
+ import { EN_TRACE_T, useTraceT, type TraceT } from "../trace-i18n";
33
+ import {
34
+ effectiveToolStatus,
35
+ resolveToolStatus,
36
+ toolRowStatus,
37
+ } from "../trace-grouping/tool-row";
38
+
39
+ const ANIMATION_DURATION = 200;
40
+
41
+ const pressable = "active:scale-[0.98]";
42
+
43
+ export const formatToolDuration = (ms: number) => {
44
+ if (!Number.isFinite(ms) || ms < 0) return "0ms";
45
+ const rounded = Math.round(ms);
46
+ if (rounded < 1000) return `${rounded}ms`;
47
+ const whole = ` (${rounded}ms)`;
48
+ const seconds = rounded / 1000;
49
+ if (seconds < 10) return `${(Math.floor(seconds * 10) / 10).toFixed(1)}s${whole}`;
50
+ if (seconds < 60) return `${Math.floor(seconds)}s${whole}`;
51
+ return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s${whole}`;
52
+ };
53
+
54
+ // Shared with the base skins' tool rows (`trace-grouping/tool-row.ts`).
55
+ export { resolveToolStatus };
56
+
57
+ export type ToolFallbackRootProps = Omit<
58
+ React.ComponentProps<typeof Collapsible>,
59
+ "open" | "onOpenChange"
60
+ > & {
61
+ open?: boolean;
62
+ onOpenChange?: (open: boolean) => void;
63
+ defaultOpen?: boolean;
64
+ };
65
+
66
+ function ToolFallbackRoot({
67
+ className,
68
+ open: controlledOpen,
69
+ onOpenChange: controlledOnOpenChange,
70
+ defaultOpen = false,
71
+ children,
72
+ ...props
73
+ }: ToolFallbackRootProps) {
74
+ const collapsibleRef = useRef<HTMLDivElement>(null);
75
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
76
+ const lockScroll = useScrollLock(collapsibleRef, ANIMATION_DURATION);
77
+
78
+ const isControlled = controlledOpen !== undefined;
79
+ const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
80
+
81
+ const handleOpenChange = useCallback(
82
+ (open: boolean) => {
83
+ lockScroll();
84
+ if (!isControlled) {
85
+ setUncontrolledOpen(open);
86
+ }
87
+ controlledOnOpenChange?.(open);
88
+ },
89
+ [lockScroll, isControlled, controlledOnOpenChange],
90
+ );
91
+
92
+ return (
93
+ <Collapsible
94
+ ref={collapsibleRef}
95
+ data-slot="tool-fallback-root"
96
+ open={isOpen}
97
+ onOpenChange={handleOpenChange}
98
+ className={cn(
99
+ "aui-tool-fallback-root group/tool-fallback-root w-full",
100
+ className,
101
+ )}
102
+ style={
103
+ {
104
+ "--animation-duration": `${ANIMATION_DURATION}ms`,
105
+ } as React.CSSProperties
106
+ }
107
+ {...props}
108
+ >
109
+ {children}
110
+ </Collapsible>
111
+ );
112
+ }
113
+
114
+ type ToolStatus = ToolCallMessagePartStatus["type"];
115
+
116
+ const statusMatrix: Record<ToolStatus, DotMatrixState> = {
117
+ running: "tool",
118
+ complete: "success",
119
+ incomplete: "error",
120
+ "requires-action": "warning",
121
+ };
122
+
123
+ function ToolFallbackDuration({
124
+ className,
125
+ ...props
126
+ }: React.ComponentProps<"span">) {
127
+ const elapsedMs = useToolCallElapsed();
128
+ if (elapsedMs === undefined) return null;
129
+
130
+ return (
131
+ <span
132
+ data-slot="tool-fallback-duration"
133
+ className={cn(
134
+ "aui-tool-fallback-duration text-ink-mute text-xs tabular-nums",
135
+ className,
136
+ )}
137
+ {...props}
138
+ >
139
+ {formatToolDuration(elapsedMs)}
140
+ </span>
141
+ );
142
+ }
143
+
144
+ /**
145
+ * The row's words and glyph for a tool status: upstream assistant-ui wording,
146
+ * one word per state. Shared with the private-session row
147
+ * (`gallery-thread/private-work-step.tsx`), which must read exactly the same.
148
+ */
149
+ export function toolTriggerLabel(
150
+ status: ToolCallMessagePartStatus | undefined,
151
+ tr: TraceT = EN_TRACE_T,
152
+ ): {
153
+ label: string;
154
+ matrixState: DotMatrixState;
155
+ isRunning: boolean;
156
+ isCancelled: boolean;
157
+ } {
158
+ const { label, statusType, isRunning, isCancelled } = toolRowStatus(status, tr);
159
+ const matrixState: DotMatrixState = isCancelled
160
+ ? "idle"
161
+ : statusMatrix[statusType];
162
+ return { label, matrixState, isRunning, isCancelled };
163
+ }
164
+
165
+ function ToolFallbackTrigger({
166
+ toolName,
167
+ title,
168
+ status,
169
+ className,
170
+ ...props
171
+ }: React.ComponentProps<typeof CollapsibleTrigger> & {
172
+ toolName: string;
173
+ title?: string;
174
+ status?: ToolCallMessagePartStatus;
175
+ }) {
176
+ const { label, matrixState, isRunning, isCancelled } = toolTriggerLabel(status, useTraceT());
177
+
178
+ return (
179
+ <CollapsibleTrigger
180
+ data-slot="tool-fallback-trigger"
181
+ className={cn(
182
+ "aui-tool-fallback-trigger group/trigger text-ink-mute hover:text-ink flex w-fit origin-left items-center gap-2 py-1.5 text-sm transition-[color,scale] active:scale-[0.98]",
183
+ className,
184
+ )}
185
+ {...props}
186
+ >
187
+ <DotMatrix
188
+ state={matrixState}
189
+ decorative
190
+ className="aui-tool-fallback-trigger-icon size-4 shrink-0"
191
+ />
192
+ <span
193
+ data-slot="tool-fallback-trigger-label"
194
+ className={cn(
195
+ "aui-tool-fallback-trigger-label-wrapper inline-block text-start leading-none text-ink",
196
+ isCancelled && "text-ink-mute line-through",
197
+ isRunning && "shimmer motion-reduce:animate-none",
198
+ )}
199
+ >
200
+ {label}: <b>{title ?? toolName}</b>
201
+ </span>
202
+ <ToolFallbackDuration />
203
+ <DisclosureChevron />
204
+ </CollapsibleTrigger>
205
+ );
206
+ }
207
+
208
+ function ToolFallbackContent({
209
+ className,
210
+ children,
211
+ ...props
212
+ }: React.ComponentProps<typeof CollapsibleContent>) {
213
+ const keepMounted = useExportKeepMounted();
214
+ return (
215
+ <CollapsibleContent
216
+ keepMounted={keepMounted}
217
+ data-slot="tool-fallback-content"
218
+ className={cn(
219
+ "aui-tool-fallback-content relative overflow-hidden text-sm outline-none",
220
+ "group/collapsible-content ease-[cubic-bezier(0.32,0.72,0,1)] motion-reduce:animate-none",
221
+ "data-closed:animate-collapsible-up",
222
+ "data-open:animate-collapsible-down",
223
+ "data-closed:fill-mode-forwards",
224
+ "data-closed:pointer-events-none",
225
+ "[--tw-duration:var(--animation-duration)]",
226
+ className,
227
+ )}
228
+ {...props}
229
+ >
230
+ <div
231
+ className={cn(
232
+ "flex flex-col gap-2 ps-6 pt-1 pb-2 ease-[cubic-bezier(0.32,0.72,0,1)] motion-reduce:animate-none",
233
+ "group-data-open/collapsible-content:animate-in group-data-open/collapsible-content:fade-in-0 group-data-open/collapsible-content:blur-in-[2px] group-data-open/collapsible-content:slide-in-from-top-1",
234
+ "group-data-closed/collapsible-content:animate-out group-data-closed/collapsible-content:fade-out-0 group-data-closed/collapsible-content:blur-out-[2px] group-data-closed/collapsible-content:slide-out-to-top-1",
235
+ "group-data-closed/collapsible-content:animation-duration-(--animation-duration) group-data-open/collapsible-content:animation-duration-(--animation-duration)",
236
+ )}
237
+ >
238
+ {children}
239
+ </div>
240
+ </CollapsibleContent>
241
+ );
242
+ }
243
+
244
+ function ToolFallbackArgs({
245
+ argsText,
246
+ className,
247
+ ...props
248
+ }: React.ComponentProps<"div"> & {
249
+ argsText?: string;
250
+ }) {
251
+ if (!argsText) return null;
252
+
253
+ // DIG-4459: the full arguments, pretty-printed and highlighted. While the
254
+ // call streams the text may be partial JSON; formatJsonDump repairs it for
255
+ // display and falls back to the raw text, never a cut-off copy.
256
+ return (
257
+ <div
258
+ data-slot="tool-fallback-args"
259
+ className={cn("aui-tool-fallback-args", className)}
260
+ {...props}
261
+ >
262
+ <p className="aui-tool-fallback-args-header text-ink-mute text-xs font-medium">
263
+ Arguments:
264
+ </p>
265
+ <JsonView
266
+ value={argsText}
267
+ slot="tool-fallback-args-json"
268
+ className="aui-tool-fallback-args-value mt-1"
269
+ />
270
+ </div>
271
+ );
272
+ }
273
+
274
+ function ToolFallbackResult({
275
+ result,
276
+ className,
277
+ ...props
278
+ }: React.ComponentProps<"div"> & {
279
+ result?: unknown;
280
+ }) {
281
+ if (result === undefined) return null;
282
+
283
+ return (
284
+ <div
285
+ data-slot="tool-fallback-result"
286
+ className={cn("aui-tool-fallback-result", className)}
287
+ {...props}
288
+ >
289
+ <p className="aui-tool-fallback-result-header text-ink-mute text-xs font-medium">
290
+ Result:
291
+ </p>
292
+ <JsonView
293
+ value={result}
294
+ slot="tool-fallback-result-json"
295
+ className="aui-tool-fallback-result-content mt-1"
296
+ />
297
+ </div>
298
+ );
299
+ }
300
+
301
+ function ToolFallbackAttribution({
302
+ result,
303
+ className,
304
+ ...props
305
+ }: React.ComponentProps<"div"> & {
306
+ result?: unknown;
307
+ }) {
308
+ const attribution = readGloomberbAttribution(result);
309
+ if (!attribution) return null;
310
+
311
+ return (
312
+ <div
313
+ data-slot="tool-fallback-attribution"
314
+ className={cn(
315
+ "aui-tool-fallback-attribution text-ink-mute flex flex-wrap items-baseline gap-x-2 gap-y-1 text-xs",
316
+ className,
317
+ )}
318
+ {...props}
319
+ >
320
+ <span>{attribution.attribution}</span>
321
+ {attribution.delayNotice ? <span>· {attribution.delayNotice}</span> : null}
322
+ {attribution.sourceUrl ? (
323
+ <a
324
+ href={attribution.sourceUrl}
325
+ target="_blank"
326
+ rel="noopener noreferrer"
327
+ className="aui-tool-fallback-attribution-link text-ink/90 underline-offset-2 hover:underline"
328
+ >
329
+ Open in Gloomberb
330
+ </a>
331
+ ) : null}
332
+ </div>
333
+ );
334
+ }
335
+
336
+ /** The tool's own error, whole: a string as-is, anything else as JSON. */
337
+ export function toolErrorText(error: unknown): string | null {
338
+ if (error === undefined || error === null || error === "") return null;
339
+ if (typeof error === "string") {
340
+ const trimmed = error.trim();
341
+ if (!trimmed) return null;
342
+ try {
343
+ const parsed = JSON.parse(trimmed);
344
+ if (parsed && typeof parsed === "object") return JSON.stringify(parsed, null, 2);
345
+ } catch {
346
+ /* plain text */
347
+ }
348
+ return error;
349
+ }
350
+ if (error instanceof Error) return error.stack ?? error.message;
351
+ try {
352
+ return JSON.stringify(error, null, 2);
353
+ } catch {
354
+ return String(error);
355
+ }
356
+ }
357
+
358
+ function ToolFallbackError({
359
+ status,
360
+ className,
361
+ ...props
362
+ }: React.ComponentProps<"div"> & {
363
+ status?: ToolCallMessagePartStatus;
364
+ }) {
365
+ const tr = useTraceT();
366
+ const stock = useStockShape();
367
+ if (status?.type !== "incomplete") return null;
368
+
369
+ const errorText = toolErrorText(status.error);
370
+ if (!errorText) return null;
371
+
372
+ const isCancelled = status.reason === "cancelled";
373
+ // First line is the headline; the full text (traceback, payload) follows,
374
+ // folded when it is long. The arguments stay visible above this box.
375
+ const [firstLine = errorText, ...rest] = errorText.split("\n");
376
+ const hasMore = rest.some((line) => line.trim());
377
+ const tone = isCancelled ? "status" : "error";
378
+
379
+ return (
380
+ <div
381
+ {...chatNoticeRootProps(tone, cn("aui-tool-fallback-error", className), stock)}
382
+ data-slot="tool-fallback-error"
383
+ {...props}
384
+ >
385
+ <ChatNoticeContent
386
+ tone={tone}
387
+ title={
388
+ <>
389
+ <span className="aui-tool-fallback-error-header">
390
+ {isCancelled ? tr.t("cancelledPrefix") : tr.t("errorPrefix")}{" "}
391
+ </span>
392
+ <span className="aui-tool-fallback-error-reason">{firstLine}</span>
393
+ </>
394
+ }
395
+ detail={hasMore ? rest.join("\n") : undefined}
396
+ />
397
+ </div>
398
+ );
399
+ }
400
+
401
+ const APPROVED_RESULT = "Approved by user";
402
+ const DENIED_RESULT = "User denied tool execution";
403
+
404
+ const APPROVAL_OPTION_DEFAULT_LABELS: Record<string, string> = {
405
+ "allow-once": "Allow",
406
+ "allow-always": "Always allow",
407
+ "reject-once": "Deny",
408
+ "reject-always": "Always deny",
409
+ };
410
+
411
+ const isKnownKind = (kind: string) =>
412
+ Object.hasOwn(APPROVAL_OPTION_DEFAULT_LABELS, kind);
413
+
414
+ const isAllowKind = (kind: string) =>
415
+ kind === "allow-once" || kind === "allow-always";
416
+
417
+ const approvalOptionLabel = (option: ToolApprovalOption) =>
418
+ option.label ??
419
+ (isKnownKind(option.kind)
420
+ ? APPROVAL_OPTION_DEFAULT_LABELS[option.kind]
421
+ : undefined) ??
422
+ option.id;
423
+
424
+ /**
425
+ * A request that declares how it wants to be presented is asking a question,
426
+ * not gating an action, so a refusal is not one of the answers it accepts.
427
+ */
428
+ const isQuestion = (approval: ToolCallMessagePart["approval"]) =>
429
+ approval?.display === "select" || approval?.display === "text";
430
+
431
+ const offersInterruptAction = (
432
+ status: ToolCallMessagePartStatus | undefined,
433
+ approval: ToolCallMessagePart["approval"],
434
+ interrupt: ToolCallMessagePart["interrupt"],
435
+ ) =>
436
+ // Only an explicit approval/interrupt request is a human gate. A server-run
437
+ // tool whose output never arrived (stream cut by a cold start / restart) is
438
+ // also "requires-action" (reason "tool-calls"); never offer Allow/Deny for it
439
+ // -- digichat tools are server-executed and read-only.
440
+ status?.type === "requires-action" && (approval != null || interrupt != null);
441
+
442
+ function ToolFallbackApproval({
443
+ className,
444
+ addResult,
445
+ resume,
446
+ interrupt,
447
+ approval,
448
+ respondToApproval,
449
+ status,
450
+ ...props
451
+ }: React.ComponentProps<"div"> &
452
+ Partial<
453
+ Pick<
454
+ ToolCallMessagePartProps,
455
+ "addResult" | "resume" | "respondToApproval" | "status"
456
+ >
457
+ > & {
458
+ interrupt?: ToolCallMessagePart["interrupt"];
459
+ approval?: ToolCallMessagePart["approval"];
460
+ }) {
461
+ const stock = useStockShape();
462
+ const [submitted, setSubmitted] = useState(false);
463
+ const [confirmingId, setConfirmingId] = useState<string | null>(null);
464
+ const [answer, setAnswer] = useState("");
465
+ const [error, setError] = useState<string | null>(null);
466
+
467
+ if (
468
+ approval != null &&
469
+ (approval.approved !== undefined || approval.resolution !== undefined)
470
+ )
471
+ return null;
472
+
473
+ if (!offersInterruptAction(status, approval, interrupt)) return null;
474
+
475
+ // A declared option list is a host constraint: the kit never adds an
476
+ // approval path beyond it, and preserves a refusal path only where the
477
+ // request is an action the user may refuse.
478
+ const declaredOptions = respondToApproval ? approval?.options : undefined;
479
+ const acceptsText =
480
+ approval != null &&
481
+ respondToApproval != null &&
482
+ toolApprovalAcceptsText(approval);
483
+
484
+ // A refused response leaves the request open, so the controls come back
485
+ // rather than staying spent on a decision the runtime never recorded.
486
+ const submit = (send: () => Promise<void> | void) => {
487
+ setSubmitted(true);
488
+ setError(null);
489
+ void (async () => {
490
+ try {
491
+ await send();
492
+ } catch (sendError) {
493
+ setSubmitted(false);
494
+ setError(
495
+ sendError instanceof Error ? sendError.message : String(sendError),
496
+ );
497
+ }
498
+ })();
499
+ };
500
+
501
+ const respond = (approved: boolean) => {
502
+ if (submitted) return;
503
+ if (
504
+ approval != null &&
505
+ approval.approved === undefined &&
506
+ respondToApproval
507
+ ) {
508
+ submit(() => respondToApproval({ approved, ...typedAnswer() }));
509
+ } else if (interrupt) {
510
+ submit(() => resume?.({ approved }));
511
+ } else if (
512
+ status?.type === "requires-action" &&
513
+ status.reason === "interrupt"
514
+ ) {
515
+ return;
516
+ } else {
517
+ submit(() => addResult?.(approved ? APPROVED_RESULT : DENIED_RESULT));
518
+ }
519
+ };
520
+
521
+ const respondWithOption = (option: ToolApprovalOption) => {
522
+ if (submitted) return;
523
+ setConfirmingId(null);
524
+ // A custom kind has no decision class for the runtime to derive, and
525
+ // responding without one throws; picking a declared option is an answer,
526
+ // so it resolves as approved.
527
+ submit(() =>
528
+ respondToApproval?.(
529
+ isKnownKind(option.kind)
530
+ ? { optionId: option.id, ...typedAnswer() }
531
+ : { optionId: option.id, approved: true, ...typedAnswer() },
532
+ ),
533
+ );
534
+ };
535
+
536
+ const typedAnswer = () => (answer.trim() ? { text: answer } : {});
537
+
538
+ const submitAnswer = () => {
539
+ if (submitted || !answer.trim()) return;
540
+ submit(() => respondToApproval?.({ text: answer }));
541
+ };
542
+
543
+ const handleOption = (option: ToolApprovalOption) => {
544
+ if (option.confirm) {
545
+ setConfirmingId(option.id);
546
+ } else {
547
+ respondWithOption(option);
548
+ }
549
+ };
550
+
551
+ const confirming =
552
+ confirmingId != null
553
+ ? declaredOptions?.find((o) => o.id === confirmingId)
554
+ : undefined;
555
+
556
+ const question = isQuestion(approval);
557
+
558
+ const promptText = approval?.prompt ? (
559
+ <p className="aui-tool-fallback-approval-prompt text-ink">
560
+ {approval.prompt}
561
+ </p>
562
+ ) : null;
563
+
564
+ const errorText = error ? (
565
+ <p
566
+ role="alert"
567
+ className="aui-tool-fallback-approval-error text-danger text-xs"
568
+ >
569
+ {error}
570
+ </p>
571
+ ) : null;
572
+
573
+ const answerField = acceptsText ? (
574
+ <div className="aui-tool-fallback-approval-answer flex flex-col items-start gap-2">
575
+ <Textarea
576
+ value={answer}
577
+ onChange={(event) => setAnswer(event.target.value)}
578
+ disabled={submitted}
579
+ aria-label={question ? (approval?.prompt ?? "Answer") : "Note"}
580
+ placeholder={
581
+ question ? "Type your answer" : "Add a note to your decision"
582
+ }
583
+ />
584
+ {question && (
585
+ <Button
586
+ size="sm"
587
+ className={pressable}
588
+ onClick={submitAnswer}
589
+ disabled={submitted || !answer.trim()}
590
+ >
591
+ Send
592
+ </Button>
593
+ )}
594
+ </div>
595
+ ) : null;
596
+
597
+ if (confirming) {
598
+ const confirmMeta =
599
+ typeof confirming.confirm === "object" ? confirming.confirm : undefined;
600
+ const confirmDescription =
601
+ confirmMeta?.description ?? confirming.description;
602
+ return (
603
+ <div
604
+ data-slot="tool-fallback-approval-confirm"
605
+ className={cn(
606
+ "aui-tool-fallback-approval-confirm flex flex-col gap-2 pt-1",
607
+ className,
608
+ )}
609
+ {...props}
610
+ >
611
+ <p className="aui-tool-fallback-approval-confirm-title font-semibold">
612
+ {confirmMeta?.title ?? `${approvalOptionLabel(confirming)}?`}
613
+ </p>
614
+ {confirmDescription && (
615
+ <p className="aui-tool-fallback-approval-confirm-description text-ink-mute">
616
+ {confirmDescription}
617
+ </p>
618
+ )}
619
+ {confirming.grants && confirming.grants.length > 0 && (
620
+ <ul className="aui-tool-fallback-approval-confirm-grants flex flex-col gap-1">
621
+ {confirming.grants.map((grant) => (
622
+ <li key={grant}>
623
+ <code className={cn("aui-tool-fallback-approval-confirm-grant bg-surface-2 px-1.5 py-0.5 text-xs", stockRadius(stock, "rounded"))}>
624
+ {grant}
625
+ </code>
626
+ </li>
627
+ ))}
628
+ </ul>
629
+ )}
630
+ <div className="flex items-center gap-2">
631
+ <Button
632
+ size="sm"
633
+ className={pressable}
634
+ onClick={() => respondWithOption(confirming)}
635
+ disabled={submitted}
636
+ >
637
+ Confirm
638
+ </Button>
639
+ <Button
640
+ size="sm"
641
+ variant="outline"
642
+ className={pressable}
643
+ onClick={() => setConfirmingId(null)}
644
+ disabled={submitted}
645
+ >
646
+ Back
647
+ </Button>
648
+ </div>
649
+ </div>
650
+ );
651
+ }
652
+
653
+ if (declaredOptions && declaredOptions.length > 0) {
654
+ const allowOptions = declaredOptions.filter((o) => isAllowKind(o.kind));
655
+ const customOptions = declaredOptions.filter((o) => !isKnownKind(o.kind));
656
+ const rejectOptions = declaredOptions.filter(
657
+ (o) => isKnownKind(o.kind) && !isAllowKind(o.kind),
658
+ );
659
+ return (
660
+ <div
661
+ data-slot="tool-fallback-approval"
662
+ className={cn(
663
+ "aui-tool-fallback-approval flex flex-col gap-2 pt-1",
664
+ className,
665
+ )}
666
+ {...props}
667
+ >
668
+ {promptText}
669
+ <div className="flex flex-wrap items-center gap-2">
670
+ {[...allowOptions, ...customOptions, ...rejectOptions].map(
671
+ (option) => (
672
+ <Button
673
+ key={option.id}
674
+ size="sm"
675
+ variant={option === allowOptions[0] ? "default" : "outline"}
676
+ className={pressable}
677
+ onClick={() => handleOption(option)}
678
+ disabled={submitted}
679
+ >
680
+ {approvalOptionLabel(option)}
681
+ </Button>
682
+ ),
683
+ )}
684
+ {rejectOptions.length === 0 && !question && (
685
+ <Button
686
+ size="sm"
687
+ variant="outline"
688
+ className={pressable}
689
+ onClick={() => respond(false)}
690
+ disabled={submitted}
691
+ >
692
+ Deny
693
+ </Button>
694
+ )}
695
+ </div>
696
+ {answerField}
697
+ {errorText}
698
+ </div>
699
+ );
700
+ }
701
+
702
+ // A question carries no decision to fabricate, so it renders only what the
703
+ // request declared, even when that leaves nothing to act on here.
704
+ if (question) {
705
+ return (
706
+ <div
707
+ data-slot="tool-fallback-approval"
708
+ className={cn(
709
+ "aui-tool-fallback-approval flex flex-col gap-2 pt-1",
710
+ className,
711
+ )}
712
+ {...props}
713
+ >
714
+ {promptText}
715
+ {answerField}
716
+ {errorText}
717
+ </div>
718
+ );
719
+ }
720
+
721
+ return (
722
+ <div
723
+ data-slot="tool-fallback-approval"
724
+ className={cn(
725
+ "aui-tool-fallback-approval flex flex-col gap-2 pt-1",
726
+ className,
727
+ )}
728
+ {...props}
729
+ >
730
+ {promptText}
731
+ <div className="flex items-center gap-2">
732
+ <Button
733
+ size="sm"
734
+ className={pressable}
735
+ onClick={() => respond(true)}
736
+ disabled={submitted}
737
+ >
738
+ Allow
739
+ </Button>
740
+ <Button
741
+ size="sm"
742
+ variant="outline"
743
+ className={pressable}
744
+ onClick={() => respond(false)}
745
+ disabled={submitted}
746
+ >
747
+ Deny
748
+ </Button>
749
+ </div>
750
+ {answerField}
751
+ {errorText}
752
+ </div>
753
+ );
754
+ }
755
+
756
+ const ToolFallbackImpl: ToolCallMessagePartComponent = ({
757
+ toolName,
758
+ argsText,
759
+ result,
760
+ status,
761
+ isError,
762
+ addResult,
763
+ resume,
764
+ interrupt,
765
+ approval,
766
+ respondToApproval,
767
+ }) => {
768
+ const outcome = useTurnOutcome();
769
+ const resolved = resolveToolStatus(status, isError, result);
770
+ // A call still waiting on a result when the turn was stopped will never
771
+ // get one: show it cancelled, not "Waiting on tool". A call that waits on
772
+ // the visitor (approval, interrupt) keeps its controls.
773
+ const effectiveStatus = effectiveToolStatus(
774
+ resolved,
775
+ outcome,
776
+ offersInterruptAction(resolved, approval, interrupt),
777
+ );
778
+ const isCancelled =
779
+ effectiveStatus?.type === "incomplete" &&
780
+ effectiveStatus.reason === "cancelled";
781
+ const isErrorStatus =
782
+ effectiveStatus?.type === "incomplete" &&
783
+ effectiveStatus.reason === "error";
784
+ const isRequiresAction = effectiveStatus?.type === "requires-action";
785
+ const shouldRenderApproval =
786
+ isRequiresAction &&
787
+ offersInterruptAction(effectiveStatus, approval, interrupt);
788
+
789
+ // /view verbose opens the cards; a call that waits on the visitor always does.
790
+ const { toolCardOpen } = useViewDisclosure();
791
+ const [open, setOpen] = useState(isRequiresAction || toolCardOpen);
792
+ const [prevRequiresAction, setPrevRequiresAction] =
793
+ useState(isRequiresAction);
794
+ if (isRequiresAction !== prevRequiresAction) {
795
+ setPrevRequiresAction(isRequiresAction);
796
+ if (isRequiresAction) setOpen(true);
797
+ }
798
+
799
+ return (
800
+ <ToolFallbackRoot open={open} onOpenChange={setOpen}>
801
+ <ToolFallbackTrigger
802
+ toolName={toolName}
803
+ title={toolRowTitle(toolName)}
804
+ status={effectiveStatus}
805
+ />
806
+ <ToolFallbackContent>
807
+ <ToolFallbackArgs
808
+ argsText={argsText}
809
+ className={cn(isCancelled && "opacity-60")}
810
+ />
811
+ {/* DIG-4459: the error goes under the arguments, never instead of them. */}
812
+ <ToolFallbackError status={effectiveStatus} />
813
+ {shouldRenderApproval && (
814
+ <ToolFallbackApproval
815
+ addResult={addResult}
816
+ resume={resume}
817
+ interrupt={interrupt}
818
+ approval={approval}
819
+ respondToApproval={respondToApproval}
820
+ status={effectiveStatus}
821
+ />
822
+ )}
823
+ {!isCancelled && !isErrorStatus && (
824
+ <>
825
+ <ToolFallbackResult result={result} />
826
+ <ToolFallbackAttribution result={result} />
827
+ </>
828
+ )}
829
+ </ToolFallbackContent>
830
+ </ToolFallbackRoot>
831
+ );
832
+ };
833
+
834
+ const ToolFallback = memo(
835
+ ToolFallbackImpl,
836
+ ) as unknown as ToolCallMessagePartComponent & {
837
+ Root: typeof ToolFallbackRoot;
838
+ Trigger: typeof ToolFallbackTrigger;
839
+ Content: typeof ToolFallbackContent;
840
+ Args: typeof ToolFallbackArgs;
841
+ Result: typeof ToolFallbackResult;
842
+ Error: typeof ToolFallbackError;
843
+ Approval: typeof ToolFallbackApproval;
844
+ };
845
+
846
+ ToolFallback.displayName = "ToolFallback";
847
+ ToolFallback.Root = ToolFallbackRoot;
848
+ ToolFallback.Trigger = ToolFallbackTrigger;
849
+ ToolFallback.Content = ToolFallbackContent;
850
+ ToolFallback.Args = ToolFallbackArgs;
851
+ ToolFallback.Result = ToolFallbackResult;
852
+ ToolFallback.Error = ToolFallbackError;
853
+ ToolFallback.Approval = ToolFallbackApproval;
854
+
855
+ export {
856
+ ToolFallback,
857
+ ToolFallbackRoot,
858
+ ToolFallbackTrigger,
859
+ ToolFallbackContent,
860
+ ToolFallbackArgs,
861
+ ToolFallbackResult,
862
+ ToolFallbackError,
863
+ ToolFallbackApproval,
864
+ ToolFallbackAttribution,
865
+ ToolFallbackDuration,
866
+ };