@data-club/ai-hub 0.0.1

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 (344) hide show
  1. package/dist/auth/passwordPolicy.d.ts +55 -0
  2. package/dist/auth/passwordPolicy.d.ts.map +1 -0
  3. package/dist/auth/passwordPolicy.js +63 -0
  4. package/dist/auth/passwordPolicy.js.map +1 -0
  5. package/dist/auth/texts.d.ts +815 -0
  6. package/dist/auth/texts.d.ts.map +1 -0
  7. package/dist/auth/texts.js +429 -0
  8. package/dist/auth/texts.js.map +1 -0
  9. package/dist/client/AIHubClient.d.ts +1058 -0
  10. package/dist/client/AIHubClient.d.ts.map +1 -0
  11. package/dist/client/AIHubClient.js +950 -0
  12. package/dist/client/AIHubClient.js.map +1 -0
  13. package/dist/client/index.d.ts +11 -0
  14. package/dist/client/index.d.ts.map +1 -0
  15. package/dist/client/index.js +9 -0
  16. package/dist/client/index.js.map +1 -0
  17. package/dist/client/sseParser.d.ts +41 -0
  18. package/dist/client/sseParser.d.ts.map +1 -0
  19. package/dist/client/sseParser.js +153 -0
  20. package/dist/client/sseParser.js.map +1 -0
  21. package/dist/client/tokenStorage.d.ts +56 -0
  22. package/dist/client/tokenStorage.d.ts.map +1 -0
  23. package/dist/client/tokenStorage.js +116 -0
  24. package/dist/client/tokenStorage.js.map +1 -0
  25. package/dist/components/AgentsPicker/index.d.ts +70 -0
  26. package/dist/components/AgentsPicker/index.d.ts.map +1 -0
  27. package/dist/components/AgentsPicker/index.js +63 -0
  28. package/dist/components/AgentsPicker/index.js.map +1 -0
  29. package/dist/components/AuthGate/index.d.ts +79 -0
  30. package/dist/components/AuthGate/index.d.ts.map +1 -0
  31. package/dist/components/AuthGate/index.js +61 -0
  32. package/dist/components/AuthGate/index.js.map +1 -0
  33. package/dist/components/CacheBadge/index.d.ts +88 -0
  34. package/dist/components/CacheBadge/index.d.ts.map +1 -0
  35. package/dist/components/CacheBadge/index.js +127 -0
  36. package/dist/components/CacheBadge/index.js.map +1 -0
  37. package/dist/components/ChangePassword/index.d.ts +109 -0
  38. package/dist/components/ChangePassword/index.d.ts.map +1 -0
  39. package/dist/components/ChangePassword/index.js +142 -0
  40. package/dist/components/ChangePassword/index.js.map +1 -0
  41. package/dist/components/ChatShell/ShellHeader.d.ts +44 -0
  42. package/dist/components/ChatShell/ShellHeader.d.ts.map +1 -0
  43. package/dist/components/ChatShell/ShellHeader.js +14 -0
  44. package/dist/components/ChatShell/ShellHeader.js.map +1 -0
  45. package/dist/components/ChatShell/UserMenu.d.ts +48 -0
  46. package/dist/components/ChatShell/UserMenu.d.ts.map +1 -0
  47. package/dist/components/ChatShell/UserMenu.js +86 -0
  48. package/dist/components/ChatShell/UserMenu.js.map +1 -0
  49. package/dist/components/ChatShell/index.d.ts +98 -0
  50. package/dist/components/ChatShell/index.d.ts.map +1 -0
  51. package/dist/components/ChatShell/index.js +124 -0
  52. package/dist/components/ChatShell/index.js.map +1 -0
  53. package/dist/components/DataClubAIHub/index.d.ts +132 -0
  54. package/dist/components/DataClubAIHub/index.d.ts.map +1 -0
  55. package/dist/components/DataClubAIHub/index.js +124 -0
  56. package/dist/components/DataClubAIHub/index.js.map +1 -0
  57. package/dist/components/DataClubAIHubAdmin/AgentEditorModal.d.ts +89 -0
  58. package/dist/components/DataClubAIHubAdmin/AgentEditorModal.d.ts.map +1 -0
  59. package/dist/components/DataClubAIHubAdmin/AgentEditorModal.js +199 -0
  60. package/dist/components/DataClubAIHubAdmin/AgentEditorModal.js.map +1 -0
  61. package/dist/components/DataClubAIHubAdmin/AgentsPage.d.ts +33 -0
  62. package/dist/components/DataClubAIHubAdmin/AgentsPage.d.ts.map +1 -0
  63. package/dist/components/DataClubAIHubAdmin/AgentsPage.js +137 -0
  64. package/dist/components/DataClubAIHubAdmin/AgentsPage.js.map +1 -0
  65. package/dist/components/DataClubAIHubAdmin/CreateUserModal.d.ts +50 -0
  66. package/dist/components/DataClubAIHubAdmin/CreateUserModal.d.ts.map +1 -0
  67. package/dist/components/DataClubAIHubAdmin/CreateUserModal.js +93 -0
  68. package/dist/components/DataClubAIHubAdmin/CreateUserModal.js.map +1 -0
  69. package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.d.ts +49 -0
  70. package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.d.ts.map +1 -0
  71. package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.js +94 -0
  72. package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.js.map +1 -0
  73. package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.d.ts +37 -0
  74. package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.d.ts.map +1 -0
  75. package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.js +44 -0
  76. package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.js.map +1 -0
  77. package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.d.ts +56 -0
  78. package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.d.ts.map +1 -0
  79. package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.js +158 -0
  80. package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.js.map +1 -0
  81. package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.d.ts +29 -0
  82. package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.d.ts.map +1 -0
  83. package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.js +183 -0
  84. package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.js.map +1 -0
  85. package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.d.ts +38 -0
  86. package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.d.ts.map +1 -0
  87. package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.js +294 -0
  88. package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.js.map +1 -0
  89. package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts +36 -0
  90. package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts.map +1 -0
  91. package/dist/components/DataClubAIHubAdmin/SettingsPage.js +373 -0
  92. package/dist/components/DataClubAIHubAdmin/SettingsPage.js.map +1 -0
  93. package/dist/components/DataClubAIHubAdmin/UsersPage.d.ts +47 -0
  94. package/dist/components/DataClubAIHubAdmin/UsersPage.d.ts.map +1 -0
  95. package/dist/components/DataClubAIHubAdmin/UsersPage.js +233 -0
  96. package/dist/components/DataClubAIHubAdmin/UsersPage.js.map +1 -0
  97. package/dist/components/DataClubAIHubAdmin/index.d.ts +87 -0
  98. package/dist/components/DataClubAIHubAdmin/index.d.ts.map +1 -0
  99. package/dist/components/DataClubAIHubAdmin/index.js +137 -0
  100. package/dist/components/DataClubAIHubAdmin/index.js.map +1 -0
  101. package/dist/components/DataClubAIHubLogin/index.d.ts +113 -0
  102. package/dist/components/DataClubAIHubLogin/index.d.ts.map +1 -0
  103. package/dist/components/DataClubAIHubLogin/index.js +123 -0
  104. package/dist/components/DataClubAIHubLogin/index.js.map +1 -0
  105. package/dist/components/EffortControl/index.d.ts +57 -0
  106. package/dist/components/EffortControl/index.d.ts.map +1 -0
  107. package/dist/components/EffortControl/index.js +84 -0
  108. package/dist/components/EffortControl/index.js.map +1 -0
  109. package/dist/components/Layout/index.d.ts +63 -0
  110. package/dist/components/Layout/index.d.ts.map +1 -0
  111. package/dist/components/Layout/index.js +45 -0
  112. package/dist/components/Layout/index.js.map +1 -0
  113. package/dist/components/MainColumn/index.d.ts +69 -0
  114. package/dist/components/MainColumn/index.d.ts.map +1 -0
  115. package/dist/components/MainColumn/index.js +47 -0
  116. package/dist/components/MainColumn/index.js.map +1 -0
  117. package/dist/components/MarkdownRenderer/index.d.ts +66 -0
  118. package/dist/components/MarkdownRenderer/index.d.ts.map +1 -0
  119. package/dist/components/MarkdownRenderer/index.js +153 -0
  120. package/dist/components/MarkdownRenderer/index.js.map +1 -0
  121. package/dist/components/MessageInput/index.d.ts +85 -0
  122. package/dist/components/MessageInput/index.d.ts.map +1 -0
  123. package/dist/components/MessageInput/index.js +139 -0
  124. package/dist/components/MessageInput/index.js.map +1 -0
  125. package/dist/components/MessageList/index.d.ts +156 -0
  126. package/dist/components/MessageList/index.d.ts.map +1 -0
  127. package/dist/components/MessageList/index.js +352 -0
  128. package/dist/components/MessageList/index.js.map +1 -0
  129. package/dist/components/ReasoningSelector/index.d.ts +77 -0
  130. package/dist/components/ReasoningSelector/index.d.ts.map +1 -0
  131. package/dist/components/ReasoningSelector/index.js +156 -0
  132. package/dist/components/ReasoningSelector/index.js.map +1 -0
  133. package/dist/components/ReasoningView/index.d.ts +94 -0
  134. package/dist/components/ReasoningView/index.d.ts.map +1 -0
  135. package/dist/components/ReasoningView/index.js +83 -0
  136. package/dist/components/ReasoningView/index.js.map +1 -0
  137. package/dist/components/ScrollToPresentButton/index.d.ts +54 -0
  138. package/dist/components/ScrollToPresentButton/index.d.ts.map +1 -0
  139. package/dist/components/ScrollToPresentButton/index.js +44 -0
  140. package/dist/components/ScrollToPresentButton/index.js.map +1 -0
  141. package/dist/components/SessionsPanel/SessionTitleModal.d.ts +79 -0
  142. package/dist/components/SessionsPanel/SessionTitleModal.d.ts.map +1 -0
  143. package/dist/components/SessionsPanel/SessionTitleModal.js +102 -0
  144. package/dist/components/SessionsPanel/SessionTitleModal.js.map +1 -0
  145. package/dist/components/SessionsPanel/index.d.ts +100 -0
  146. package/dist/components/SessionsPanel/index.d.ts.map +1 -0
  147. package/dist/components/SessionsPanel/index.js +176 -0
  148. package/dist/components/SessionsPanel/index.js.map +1 -0
  149. package/dist/components/SystemNotice/index.d.ts +66 -0
  150. package/dist/components/SystemNotice/index.d.ts.map +1 -0
  151. package/dist/components/SystemNotice/index.js +81 -0
  152. package/dist/components/SystemNotice/index.js.map +1 -0
  153. package/dist/components/ThemeSwitcher/index.d.ts +66 -0
  154. package/dist/components/ThemeSwitcher/index.d.ts.map +1 -0
  155. package/dist/components/ThemeSwitcher/index.js +73 -0
  156. package/dist/components/ThemeSwitcher/index.js.map +1 -0
  157. package/dist/components/ToolCallView/formatContent.d.ts +36 -0
  158. package/dist/components/ToolCallView/formatContent.d.ts.map +1 -0
  159. package/dist/components/ToolCallView/formatContent.js +53 -0
  160. package/dist/components/ToolCallView/formatContent.js.map +1 -0
  161. package/dist/components/ToolCallView/index.d.ts +120 -0
  162. package/dist/components/ToolCallView/index.d.ts.map +1 -0
  163. package/dist/components/ToolCallView/index.js +104 -0
  164. package/dist/components/ToolCallView/index.js.map +1 -0
  165. package/dist/components/TpmBanner/index.d.ts +53 -0
  166. package/dist/components/TpmBanner/index.d.ts.map +1 -0
  167. package/dist/components/TpmBanner/index.js +116 -0
  168. package/dist/components/TpmBanner/index.js.map +1 -0
  169. package/dist/components/TurnStatusIndicator/index.d.ts +77 -0
  170. package/dist/components/TurnStatusIndicator/index.d.ts.map +1 -0
  171. package/dist/components/TurnStatusIndicator/index.js +122 -0
  172. package/dist/components/TurnStatusIndicator/index.js.map +1 -0
  173. package/dist/components/internal/PasswordInput.d.ts +62 -0
  174. package/dist/components/internal/PasswordInput.d.ts.map +1 -0
  175. package/dist/components/internal/PasswordInput.js +42 -0
  176. package/dist/components/internal/PasswordInput.js.map +1 -0
  177. package/dist/context/AIHubContext.d.ts +220 -0
  178. package/dist/context/AIHubContext.d.ts.map +1 -0
  179. package/dist/context/AIHubContext.js +19 -0
  180. package/dist/context/AIHubContext.js.map +1 -0
  181. package/dist/context/AIHubProvider.d.ts +75 -0
  182. package/dist/context/AIHubProvider.d.ts.map +1 -0
  183. package/dist/context/AIHubProvider.js +954 -0
  184. package/dist/context/AIHubProvider.js.map +1 -0
  185. package/dist/context/index.d.ts +9 -0
  186. package/dist/context/index.d.ts.map +1 -0
  187. package/dist/context/index.js +9 -0
  188. package/dist/context/index.js.map +1 -0
  189. package/dist/context/theme.d.ts +43 -0
  190. package/dist/context/theme.d.ts.map +1 -0
  191. package/dist/context/theme.js +70 -0
  192. package/dist/context/theme.js.map +1 -0
  193. package/dist/context/useAIHub.d.ts +104 -0
  194. package/dist/context/useAIHub.d.ts.map +1 -0
  195. package/dist/context/useAIHub.js +63 -0
  196. package/dist/context/useAIHub.js.map +1 -0
  197. package/dist/context/useAIHubAuth.d.ts +44 -0
  198. package/dist/context/useAIHubAuth.d.ts.map +1 -0
  199. package/dist/context/useAIHubAuth.js +35 -0
  200. package/dist/context/useAIHubAuth.js.map +1 -0
  201. package/dist/index.d.ts +76 -0
  202. package/dist/index.d.ts.map +1 -0
  203. package/dist/index.js +57 -0
  204. package/dist/index.js.map +1 -0
  205. package/dist/primitives/index.d.ts +99 -0
  206. package/dist/primitives/index.d.ts.map +1 -0
  207. package/dist/primitives/index.js +97 -0
  208. package/dist/primitives/index.js.map +1 -0
  209. package/dist/state/affordances.d.ts +182 -0
  210. package/dist/state/affordances.d.ts.map +1 -0
  211. package/dist/state/affordances.js +189 -0
  212. package/dist/state/affordances.js.map +1 -0
  213. package/dist/state/stateReducer.d.ts +72 -0
  214. package/dist/state/stateReducer.d.ts.map +1 -0
  215. package/dist/state/stateReducer.js +122 -0
  216. package/dist/state/stateReducer.js.map +1 -0
  217. package/dist/stories/EffortControl.stories.d.ts +14 -0
  218. package/dist/stories/EffortControl.stories.d.ts.map +1 -0
  219. package/dist/stories/EffortControl.stories.js +43 -0
  220. package/dist/stories/EffortControl.stories.js.map +1 -0
  221. package/dist/stories/MarkdownRenderer.stories.d.ts +25 -0
  222. package/dist/stories/MarkdownRenderer.stories.d.ts.map +1 -0
  223. package/dist/stories/MarkdownRenderer.stories.js +178 -0
  224. package/dist/stories/MarkdownRenderer.stories.js.map +1 -0
  225. package/dist/stories/MessageBubble.stories.d.ts +21 -0
  226. package/dist/stories/MessageBubble.stories.d.ts.map +1 -0
  227. package/dist/stories/MessageBubble.stories.js +59 -0
  228. package/dist/stories/MessageBubble.stories.js.map +1 -0
  229. package/dist/stories/ReasoningView.stories.d.ts +18 -0
  230. package/dist/stories/ReasoningView.stories.d.ts.map +1 -0
  231. package/dist/stories/ReasoningView.stories.js +62 -0
  232. package/dist/stories/ReasoningView.stories.js.map +1 -0
  233. package/dist/stories/ScrollToPresentButton.stories.d.ts +18 -0
  234. package/dist/stories/ScrollToPresentButton.stories.d.ts.map +1 -0
  235. package/dist/stories/ScrollToPresentButton.stories.js +34 -0
  236. package/dist/stories/ScrollToPresentButton.stories.js.map +1 -0
  237. package/dist/stories/SystemNotice.stories.d.ts +17 -0
  238. package/dist/stories/SystemNotice.stories.d.ts.map +1 -0
  239. package/dist/stories/SystemNotice.stories.js +42 -0
  240. package/dist/stories/SystemNotice.stories.js.map +1 -0
  241. package/dist/stories/ThemeSwitcher.stories.d.ts +15 -0
  242. package/dist/stories/ThemeSwitcher.stories.d.ts.map +1 -0
  243. package/dist/stories/ThemeSwitcher.stories.js +35 -0
  244. package/dist/stories/ThemeSwitcher.stories.js.map +1 -0
  245. package/dist/stories/ToolCallView.stories.d.ts +20 -0
  246. package/dist/stories/ToolCallView.stories.d.ts.map +1 -0
  247. package/dist/stories/ToolCallView.stories.js +65 -0
  248. package/dist/stories/ToolCallView.stories.js.map +1 -0
  249. package/dist/stories/TpmBanner.stories.d.ts +24 -0
  250. package/dist/stories/TpmBanner.stories.d.ts.map +1 -0
  251. package/dist/stories/TpmBanner.stories.js +63 -0
  252. package/dist/stories/TpmBanner.stories.js.map +1 -0
  253. package/dist/stories/TurnStatusIndicator.stories.d.ts +25 -0
  254. package/dist/stories/TurnStatusIndicator.stories.d.ts.map +1 -0
  255. package/dist/stories/TurnStatusIndicator.stories.js +56 -0
  256. package/dist/stories/TurnStatusIndicator.stories.js.map +1 -0
  257. package/dist/stories/_mockProvider.d.ts +44 -0
  258. package/dist/stories/_mockProvider.d.ts.map +1 -0
  259. package/dist/stories/_mockProvider.js +84 -0
  260. package/dist/stories/_mockProvider.js.map +1 -0
  261. package/dist/types.d.ts +787 -0
  262. package/dist/types.d.ts.map +1 -0
  263. package/dist/types.js +19 -0
  264. package/dist/types.js.map +1 -0
  265. package/dist/webcomponent/defineWebComponent.d.ts +106 -0
  266. package/dist/webcomponent/defineWebComponent.d.ts.map +1 -0
  267. package/dist/webcomponent/defineWebComponent.js +126 -0
  268. package/dist/webcomponent/defineWebComponent.js.map +1 -0
  269. package/dist/webcomponent/index.d.ts +7 -0
  270. package/dist/webcomponent/index.d.ts.map +1 -0
  271. package/dist/webcomponent/index.js +7 -0
  272. package/dist/webcomponent/index.js.map +1 -0
  273. package/package.json +63 -0
  274. package/src/__lint-canary__/step1-lint-canary.ts.disabled +28 -0
  275. package/src/auth/passwordPolicy.ts +75 -0
  276. package/src/auth/texts.ts +1294 -0
  277. package/src/client/AIHubClient.ts +1718 -0
  278. package/src/client/index.ts +30 -0
  279. package/src/client/sseParser.ts +168 -0
  280. package/src/client/tokenStorage.ts +131 -0
  281. package/src/components/AgentsPicker/index.tsx +147 -0
  282. package/src/components/AuthGate/index.tsx +132 -0
  283. package/src/components/CacheBadge/index.tsx +245 -0
  284. package/src/components/ChangePassword/index.tsx +375 -0
  285. package/src/components/ChatShell/ShellHeader.tsx +80 -0
  286. package/src/components/ChatShell/UserMenu.tsx +196 -0
  287. package/src/components/ChatShell/index.tsx +307 -0
  288. package/src/components/DataClubAIHub/index.tsx +300 -0
  289. package/src/components/DataClubAIHubAdmin/AgentEditorModal.tsx +505 -0
  290. package/src/components/DataClubAIHubAdmin/AgentsPage.tsx +342 -0
  291. package/src/components/DataClubAIHubAdmin/CreateUserModal.tsx +214 -0
  292. package/src/components/DataClubAIHubAdmin/PasswordRevealModal.tsx +204 -0
  293. package/src/components/DataClubAIHubAdmin/ResetPasswordModal.tsx +122 -0
  294. package/src/components/DataClubAIHubAdmin/RotatingMessageEditorModal.tsx +408 -0
  295. package/src/components/DataClubAIHubAdmin/RotatingMessagesPage.tsx +373 -0
  296. package/src/components/DataClubAIHubAdmin/SessionsOverviewPage.tsx +639 -0
  297. package/src/components/DataClubAIHubAdmin/SettingsPage.tsx +979 -0
  298. package/src/components/DataClubAIHubAdmin/UsersPage.tsx +495 -0
  299. package/src/components/DataClubAIHubAdmin/index.tsx +277 -0
  300. package/src/components/DataClubAIHubLogin/index.tsx +282 -0
  301. package/src/components/EffortControl/index.tsx +138 -0
  302. package/src/components/Layout/index.tsx +92 -0
  303. package/src/components/MainColumn/index.tsx +131 -0
  304. package/src/components/MarkdownRenderer/index.tsx +256 -0
  305. package/src/components/MessageInput/index.tsx +283 -0
  306. package/src/components/MessageList/index.tsx +753 -0
  307. package/src/components/ReasoningSelector/index.tsx +268 -0
  308. package/src/components/ReasoningView/index.tsx +183 -0
  309. package/src/components/ScrollToPresentButton/index.tsx +85 -0
  310. package/src/components/SessionsPanel/SessionTitleModal.tsx +256 -0
  311. package/src/components/SessionsPanel/index.tsx +406 -0
  312. package/src/components/SystemNotice/index.tsx +151 -0
  313. package/src/components/ThemeSwitcher/index.tsx +136 -0
  314. package/src/components/ToolCallView/formatContent.ts +50 -0
  315. package/src/components/ToolCallView/index.tsx +274 -0
  316. package/src/components/TpmBanner/index.tsx +172 -0
  317. package/src/components/TurnStatusIndicator/index.tsx +203 -0
  318. package/src/components/internal/PasswordInput.tsx +145 -0
  319. package/src/context/AIHubContext.ts +249 -0
  320. package/src/context/AIHubProvider.tsx +1084 -0
  321. package/src/context/index.ts +9 -0
  322. package/src/context/theme.ts +76 -0
  323. package/src/context/useAIHub.ts +151 -0
  324. package/src/context/useAIHubAuth.ts +65 -0
  325. package/src/index.ts +275 -0
  326. package/src/primitives/index.ts +101 -0
  327. package/src/state/affordances.ts +321 -0
  328. package/src/state/stateReducer.ts +131 -0
  329. package/src/stories/EffortControl.stories.tsx +63 -0
  330. package/src/stories/MarkdownRenderer.stories.tsx +201 -0
  331. package/src/stories/MessageBubble.stories.tsx +101 -0
  332. package/src/stories/ReasoningView.stories.tsx +81 -0
  333. package/src/stories/ScrollToPresentButton.stories.tsx +52 -0
  334. package/src/stories/SystemNotice.stories.tsx +59 -0
  335. package/src/stories/ThemeSwitcher.stories.tsx +55 -0
  336. package/src/stories/ToolCallView.stories.tsx +95 -0
  337. package/src/stories/TpmBanner.stories.tsx +93 -0
  338. package/src/stories/TurnStatusIndicator.stories.tsx +86 -0
  339. package/src/stories/_mockProvider.tsx +116 -0
  340. package/src/styles/CLASSES.md +356 -0
  341. package/src/styles/default.css +2937 -0
  342. package/src/types.ts +867 -0
  343. package/src/webcomponent/defineWebComponent.tsx +193 -0
  344. package/src/webcomponent/index.ts +11 -0
@@ -0,0 +1,151 @@
1
+ /**
2
+ * `<SystemNotice />` — banner rendered above `messages_area` for non-fatal
3
+ * system events (TPM wait, recovery resumed, exhausted error). Variants:
4
+ *
5
+ * - `--tpm-wait` — provider rate-limited; recovery in progress
6
+ * - `--resumed` — recovery succeeded; usually auto-dismissed after a brief flash
7
+ * - `--error` — non-recoverable (e.g. `tpm_exhausted`)
8
+ *
9
+ * Pure presentational — the parent (`MessageList` in the monolith) decides
10
+ * which variant to render, what body text to show, and any auto-dismiss
11
+ * timer. Tier-3 wrappers can use the primitive directly with their own
12
+ * content too.
13
+ *
14
+ * Exported under `AIHub.SystemNotice`.
15
+ *
16
+ * @see SPECIFICATIONS.md §9.4 — system_notice events
17
+ * @see ui-sketches/03-chat.md — system_notice
18
+ */
19
+
20
+ import { type ReactNode } from "react";
21
+
22
+ /**
23
+ * BEM class names emitted by `<SystemNotice />`.
24
+ */
25
+ export interface SystemNoticeClassNames {
26
+ /** Outer banner element. */
27
+ root: string;
28
+ /** Modifier — `--tpm-wait`. */
29
+ rootTpmWait: string;
30
+ /** Modifier — `--resumed`. */
31
+ rootResumed: string;
32
+ /** Modifier — `--error`. */
33
+ rootError: string;
34
+ /** Icon span. */
35
+ icon: string;
36
+ /** Body text span. */
37
+ body: string;
38
+ /** Action button (e.g. retry on error variant). */
39
+ action: string;
40
+ }
41
+
42
+ const DEFAULT_CLASS_NAMES: SystemNoticeClassNames = Object.freeze({
43
+ root: "data-club-ai-hub__system-notice",
44
+ rootTpmWait: "data-club-ai-hub__system-notice--tpm-wait",
45
+ rootResumed: "data-club-ai-hub__system-notice--resumed",
46
+ rootError: "data-club-ai-hub__system-notice--error",
47
+ icon: "data-club-ai-hub__system-notice__icon",
48
+ body: "data-club-ai-hub__system-notice__body",
49
+ action: "data-club-ai-hub__system-notice__action",
50
+ }) as SystemNoticeClassNames;
51
+
52
+ /** Props for `<SystemNotice />`. */
53
+ export interface SystemNoticeProps {
54
+ /** Variant — controls the modifier class + the default icon. */
55
+ variant: "tpm-wait" | "resumed" | "error";
56
+ /** Body text (i18n-supplied). */
57
+ message: string;
58
+ /** Override the default icon character for the variant. */
59
+ icon?: string;
60
+ /** Optional inline action button. */
61
+ action?: {
62
+ /** Button label. */
63
+ label: string;
64
+ /** Click handler. */
65
+ onClick: () => void;
66
+ };
67
+ /** Extra class merged onto the root. */
68
+ className?: string;
69
+ /** Per-element class overrides. */
70
+ classNames?: Partial<SystemNoticeClassNames>;
71
+ }
72
+
73
+ /**
74
+ * Default icon glyph per variant.
75
+ */
76
+ function defaultIcon(variant: SystemNoticeProps["variant"]): string {
77
+ switch (variant) {
78
+ case "tpm-wait":
79
+ return "⏱";
80
+ case "resumed":
81
+ return "✓";
82
+ case "error":
83
+ return "⚠";
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Returns the BEM modifier for the variant.
89
+ */
90
+ function modifierForVariant(
91
+ variant: SystemNoticeProps["variant"],
92
+ cls: SystemNoticeClassNames,
93
+ ): string {
94
+ switch (variant) {
95
+ case "tpm-wait":
96
+ return cls.rootTpmWait;
97
+ case "resumed":
98
+ return cls.rootResumed;
99
+ case "error":
100
+ return cls.rootError;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * `role` ARIA value per variant. Error gets `alert` so screen readers
106
+ * announce; wait/resumed get `status` (polite live region).
107
+ */
108
+ function roleForVariant(variant: SystemNoticeProps["variant"]): "alert" | "status" {
109
+ return variant === "error" ? "alert" : "status";
110
+ }
111
+
112
+ /**
113
+ * Renders the notice.
114
+ *
115
+ * @param props - see `SystemNoticeProps`.
116
+ * @returns the rendered notice.
117
+ */
118
+ export function SystemNotice(props: SystemNoticeProps): ReactNode {
119
+ const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
120
+ const icon = props.icon ?? defaultIcon(props.variant);
121
+ const rootClass = [
122
+ cls.root,
123
+ modifierForVariant(props.variant, cls),
124
+ props.className,
125
+ ]
126
+ .filter(Boolean)
127
+ .join(" ");
128
+ return (
129
+ <div
130
+ className={rootClass}
131
+ role={roleForVariant(props.variant)}
132
+ data-testid="system-notice"
133
+ data-variant={props.variant}
134
+ >
135
+ <span className={cls.icon} aria-hidden="true">
136
+ {icon}
137
+ </span>
138
+ <span className={cls.body}>{props.message}</span>
139
+ {props.action ? (
140
+ <button
141
+ type="button"
142
+ className={cls.action}
143
+ onClick={props.action.onClick}
144
+ data-testid="system-notice-action"
145
+ >
146
+ {props.action.label}
147
+ </button>
148
+ ) : null}
149
+ </div>
150
+ );
151
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * `<ThemeSwitcher />` — sun/moon toggle that flips the active theme via
3
+ * `setTheme` from `useAIHub()`.
4
+ *
5
+ * Renders **nothing** when `themeSwitcherEnabled === false` (i.e. the
6
+ * super_admin has disabled the switcher for this deployment per §7.6) —
7
+ * not a disabled control, not a hidden control, but absent from the DOM
8
+ * entirely. That's the contract callers — including `UserMenu` —
9
+ * depend on: a `ThemeSwitcher` inside a conditional is safe to leave in
10
+ * place; the primitive self-suppresses.
11
+ *
12
+ * Optimistic update: clicking the switcher flips the local `theme`
13
+ * value immediately and posts `PATCH /auth/me/preferences { theme }`.
14
+ * On a 409 `theme_switcher_disabled` (server-side switcher disabled
15
+ * mid-call), the provider's `setTheme` reverts the optimistic state and
16
+ * surfaces the error via `onError`.
17
+ *
18
+ * Exported under `AIHub.ThemeSwitcher`.
19
+ *
20
+ * @see SPECIFICATIONS.md §7.6 — theme resolution
21
+ * @see ui-sketches/00-shell.md — `Theme: Light ↔ Dark` item in user menu
22
+ */
23
+
24
+ import { type ReactNode } from "react";
25
+
26
+ import type { AIHubChatTexts } from "../../auth/texts.js";
27
+ import { resolveAIHubTexts, type AIHubTexts, type DeepPartial } from "../../auth/texts.js";
28
+ import { useAIHub } from "../../context/useAIHub.js";
29
+
30
+ /**
31
+ * BEM class names emitted by `<ThemeSwitcher />`.
32
+ */
33
+ export interface ThemeSwitcherClassNames {
34
+ /** The button element. */
35
+ root: string;
36
+ /** Modifier added when the active theme is light. */
37
+ rootLight: string;
38
+ /** Modifier added when the active theme is dark. */
39
+ rootDark: string;
40
+ /** The icon span. */
41
+ icon: string;
42
+ /** The label text span. */
43
+ label: string;
44
+ }
45
+
46
+ const DEFAULT_CLASS_NAMES: ThemeSwitcherClassNames = Object.freeze({
47
+ root: "data-club-ai-hub__theme-switcher",
48
+ rootLight: "data-club-ai-hub__theme-switcher--light",
49
+ rootDark: "data-club-ai-hub__theme-switcher--dark",
50
+ icon: "data-club-ai-hub__theme-switcher__icon",
51
+ label: "data-club-ai-hub__theme-switcher__label",
52
+ }) as ThemeSwitcherClassNames;
53
+
54
+ /**
55
+ * Props for `<ThemeSwitcher />`.
56
+ */
57
+ export interface ThemeSwitcherProps {
58
+ /** Whether to render a label next to the icon. Default true. */
59
+ showLabel?: boolean;
60
+ /** Wrapper-supplied i18n. */
61
+ texts?: DeepPartial<AIHubTexts>;
62
+ /** Extra class merged onto the root. */
63
+ className?: string;
64
+ /** Per-element class overrides. */
65
+ classNames?: Partial<ThemeSwitcherClassNames>;
66
+ /**
67
+ * Forwarded to the underlying button — only used by the test harness
68
+ * + Storybook stories that want to click the switcher without going
69
+ * through the provider's optimistic-update path.
70
+ */
71
+ onClick?: () => void;
72
+ }
73
+
74
+ /**
75
+ * Renders the switcher.
76
+ *
77
+ * @param props - see `ThemeSwitcherProps`.
78
+ * @returns the rendered switcher, or `null` when disabled by config.
79
+ */
80
+ export function ThemeSwitcher(props: ThemeSwitcherProps): ReactNode {
81
+ const { theme, setTheme, themeSwitcherEnabled } = useAIHub();
82
+ const texts = resolveAIHubTexts(props.texts);
83
+ const chatTexts: AIHubChatTexts = texts.chat;
84
+ const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
85
+ const showLabel = props.showLabel ?? true;
86
+
87
+ if (!themeSwitcherEnabled) return null;
88
+
89
+ const isDark = theme === "dark";
90
+ // `aria-checked` reflects "is dark on?" so the switcher is a
91
+ // 2-state switch (light ↔ dark), which matches sketches/00-shell.md.
92
+ const ariaLabel = isDark
93
+ ? chatTexts.themeSwitchToLightAriaLabel
94
+ : chatTexts.themeSwitchToDarkAriaLabel;
95
+ const visualLabel = isDark ? chatTexts.themeLightLabel : chatTexts.themeDarkLabel;
96
+ const icon = isDark ? "☀" : "☾";
97
+ const next: "light" | "dark" = isDark ? "light" : "dark";
98
+
99
+ const rootClass = [
100
+ cls.root,
101
+ isDark ? cls.rootDark : cls.rootLight,
102
+ props.className,
103
+ ]
104
+ .filter(Boolean)
105
+ .join(" ");
106
+
107
+ function handleClick(): void {
108
+ if (props.onClick) {
109
+ props.onClick();
110
+ return;
111
+ }
112
+ void setTheme(next);
113
+ }
114
+
115
+ return (
116
+ <button
117
+ type="button"
118
+ role="switch"
119
+ aria-checked={isDark}
120
+ aria-label={ariaLabel}
121
+ className={rootClass}
122
+ onClick={handleClick}
123
+ data-testid="theme-switcher"
124
+ data-theme-state={theme}
125
+ >
126
+ <span className={cls.icon} aria-hidden="true">
127
+ {icon}
128
+ </span>
129
+ {showLabel ? (
130
+ <span className={cls.label} data-testid="theme-switcher-label">
131
+ {visualLabel}
132
+ </span>
133
+ ) : null}
134
+ </button>
135
+ );
136
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Default display-side formatter for tool-call input/output text rendered
3
+ * inside `<ToolCallView />`.
4
+ *
5
+ * Tool inputs reach the UI as raw JSON text (assembled from
6
+ * `tool_call_input_delta` chunks); tool outputs are either a string from
7
+ * Letta or a `JSON.stringify` of the structured return. In both shapes,
8
+ * any newline inside a string value is encoded as the two-character
9
+ * sequence `\n`, which a `<pre>` element renders as the literal text
10
+ * `\n` instead of an actual line break. Same for `\t` / `\r`. That makes
11
+ * any multi-line tool payload (file diffs, command output, prompts)
12
+ * unreadable.
13
+ *
14
+ * Strategy:
15
+ *
16
+ * 1. Try `JSON.parse(raw)`. If it parses, re-stringify with 2-space
17
+ * indent — that pretty-prints the structure.
18
+ * 2. Whether or not parsing succeeded, replace the whitespace escape
19
+ * sequences (`\n`, `\t`, `\r`, including the `\r\n` pair) with
20
+ * their literal characters so they render as real layout.
21
+ *
22
+ * The output is NOT valid JSON anymore — it's a display form. Other
23
+ * escapes (`\"`, `\\`, `\uXXXX`) are left alone because they're either
24
+ * still meaningful for the reader or rare enough that unescaping them
25
+ * would risk corrupting binary-ish content.
26
+ *
27
+ * Implementation projects that need different behavior (e.g. raw view
28
+ * for debugging) can pass their own `formatContent` to `<ToolCallView />`
29
+ * or pass identity (`(s) => s`).
30
+ *
31
+ * @param raw - the input or output string as carried on
32
+ * `AIHubToolCallRecord` / the streaming tool-call accumulator.
33
+ * @returns the formatted string for display.
34
+ */
35
+ export function formatToolContentForDisplay(raw: string): string {
36
+ if (raw === "") return raw;
37
+ let formatted = raw;
38
+ try {
39
+ const parsed: unknown = JSON.parse(raw);
40
+ formatted = JSON.stringify(parsed, null, 2);
41
+ } catch {
42
+ // Not valid JSON (mid-stream chunk, plain text output, etc.) —
43
+ // fall through to the escape-sequence unwrap on the raw input.
44
+ }
45
+ return formatted
46
+ .replace(/\\r\\n/g, "\n")
47
+ .replace(/\\n/g, "\n")
48
+ .replace(/\\t/g, "\t")
49
+ .replace(/\\r/g, "\r");
50
+ }
@@ -0,0 +1,274 @@
1
+ /**
2
+ * `<ToolCallView />` — collapsible tool-call card inside an assistant
3
+ * bubble.
4
+ *
5
+ * Header carries the tool name + status (`running`/`done`/`error`) +
6
+ * duration. Body shows input + output (or input + error). Default
7
+ * collapsed; click `[▶]` to expand. Tool errors do NOT fail the turn
8
+ * — the card stays as evidence of what happened (§10.3).
9
+ *
10
+ * Step 10 only renders tool calls when `toolCallsVisible` (resolved) is
11
+ * true. The decision lives in `MessageList`.
12
+ *
13
+ * Exported under `AIHub.ToolCallView`.
14
+ *
15
+ * @see SPECIFICATIONS.md §9.3 — tool events
16
+ * @see SPECIFICATIONS.md §10.3 — tool error vs. agent error
17
+ * @see ui-sketches/03-chat.md — tool_call_card
18
+ */
19
+
20
+ import { useState, type ReactNode } from "react";
21
+
22
+ import {
23
+ resolveAIHubTexts,
24
+ type AIHubTexts,
25
+ type DeepPartial,
26
+ } from "../../auth/texts.js";
27
+ import { formatToolContentForDisplay } from "./formatContent.js";
28
+
29
+ /** Status of a tool call. */
30
+ export type ToolCallStatus = "running" | "done" | "error";
31
+
32
+ /** BEM class names emitted by `<ToolCallView />`. */
33
+ export interface ToolCallViewClassNames {
34
+ /** Outer card. */
35
+ root: string;
36
+ /** Modifier — `--collapsed`. */
37
+ rootCollapsed: string;
38
+ /** Modifier — `--expanded`. */
39
+ rootExpanded: string;
40
+ /** Status modifier — `--running`. */
41
+ rootRunning: string;
42
+ /** Status modifier — `--done`. */
43
+ rootDone: string;
44
+ /** Status modifier — `--error`. */
45
+ rootError: string;
46
+ /** Header element. */
47
+ header: string;
48
+ /** Tool name inside header. */
49
+ toolName: string;
50
+ /** Status icon + text inside header. */
51
+ status: string;
52
+ /** Duration text inside header. */
53
+ duration: string;
54
+ /** Expand/collapse toggle. */
55
+ toggle: string;
56
+ /** Body element (mounted only when expanded). */
57
+ body: string;
58
+ /** Modifier on the body — `--error`. */
59
+ bodyError: string;
60
+ /** Input section. */
61
+ inputSection: string;
62
+ /** Output section. */
63
+ outputSection: string;
64
+ /** Section label (Input: / Output: / Error:). */
65
+ sectionLabel: string;
66
+ /** Section pre/code content. */
67
+ sectionContent: string;
68
+ }
69
+
70
+ const DEFAULT_CLASS_NAMES: ToolCallViewClassNames = Object.freeze({
71
+ root: "data-club-ai-hub__tool-call-card",
72
+ rootCollapsed: "data-club-ai-hub__tool-call-card--collapsed",
73
+ rootExpanded: "data-club-ai-hub__tool-call-card--expanded",
74
+ rootRunning: "data-club-ai-hub__tool-call-card--running",
75
+ rootDone: "data-club-ai-hub__tool-call-card--done",
76
+ rootError: "data-club-ai-hub__tool-call-card--error",
77
+ header: "data-club-ai-hub__tool-call-card__header",
78
+ toolName: "data-club-ai-hub__tool-call-card__tool-name",
79
+ status: "data-club-ai-hub__tool-call-card__status",
80
+ duration: "data-club-ai-hub__tool-call-card__duration",
81
+ toggle: "data-club-ai-hub__tool-call-card__toggle",
82
+ body: "data-club-ai-hub__tool-call-card__body",
83
+ bodyError: "data-club-ai-hub__tool-call-card__body--error",
84
+ inputSection: "data-club-ai-hub__tool-call-card__input-section",
85
+ outputSection: "data-club-ai-hub__tool-call-card__output-section",
86
+ sectionLabel: "data-club-ai-hub__tool-call-card__section-label",
87
+ sectionContent: "data-club-ai-hub__tool-call-card__section-content",
88
+ }) as ToolCallViewClassNames;
89
+
90
+ /** Props for `<ToolCallView />`. */
91
+ export interface ToolCallViewProps {
92
+ /** Tool name (e.g. "search_web"). */
93
+ toolName: string;
94
+ /** Current status. Drives the icon + the body's error modifier. */
95
+ status: ToolCallStatus;
96
+ /** Tool input — pretty-printed JSON usually. */
97
+ input: string;
98
+ /** Tool output (only meaningful when `status === "done"`). */
99
+ output?: string;
100
+ /** Error message (only meaningful when `status === "error"`). */
101
+ error?: string;
102
+ /** Duration in seconds, when known. */
103
+ durationSeconds?: number;
104
+ /**
105
+ * Override initial expanded state. Default false (collapsed); the
106
+ * spec's `tool_call_card --collapsed` is the default visual.
107
+ *
108
+ * Ignored when `expanded` is passed (controlled mode).
109
+ */
110
+ defaultExpanded?: boolean;
111
+ /**
112
+ * Controlled expanded state. When set, `<ToolCallView />` defers all
113
+ * expand/collapse decisions to the parent — `onToggle` fires on the
114
+ * user's toggle click and the parent computes the next `expanded`.
115
+ * Used by `<MessageList />` to enforce the accordion +
116
+ * auto-expand-while-streaming rules across blocks. When omitted, the
117
+ * component falls back to internal `useState` (default-collapsed,
118
+ * per-instance toggle) for backward compatibility.
119
+ */
120
+ expanded?: boolean;
121
+ /**
122
+ * Toggle handler for the controlled mode. Fires on the user's click;
123
+ * the parent decides what to do with it. Ignored in uncontrolled mode.
124
+ */
125
+ onToggle?: () => void;
126
+ /** Wrapper-supplied i18n. */
127
+ texts?: DeepPartial<AIHubTexts>;
128
+ /** Extra class merged onto the root. */
129
+ className?: string;
130
+ /** Per-element class overrides. */
131
+ classNames?: Partial<ToolCallViewClassNames>;
132
+ /**
133
+ * Transform applied to the displayed `input` / `output` / `error`
134
+ * strings. Defaults to [[formatToolContentForDisplay]], which
135
+ * JSON-pretty-prints the value (when parseable) and unescapes the
136
+ * whitespace JSON-escape sequences (`\n`, `\t`, `\r`) so they render
137
+ * as actual layout. Pass `(s) => s` to opt out (e.g. for a raw
138
+ * debugging view), or supply a custom formatter to reshape the
139
+ * content (e.g. redact secrets).
140
+ */
141
+ formatContent?: (raw: string) => string;
142
+ }
143
+
144
+ /**
145
+ * Returns the BEM modifier for the status.
146
+ */
147
+ function statusModifier(
148
+ status: ToolCallStatus,
149
+ cls: ToolCallViewClassNames,
150
+ ): string {
151
+ switch (status) {
152
+ case "running":
153
+ return cls.rootRunning;
154
+ case "done":
155
+ return cls.rootDone;
156
+ case "error":
157
+ return cls.rootError;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Returns the i18n status text for the header.
163
+ */
164
+ function statusText(
165
+ status: ToolCallStatus,
166
+ chat: AIHubTexts["chat"],
167
+ ): string {
168
+ switch (status) {
169
+ case "running":
170
+ return chat.toolCallRunningStatus;
171
+ case "done":
172
+ return chat.toolCallDoneStatus;
173
+ case "error":
174
+ return chat.toolCallErrorStatus;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Renders the card.
180
+ *
181
+ * @param props - see `ToolCallViewProps`.
182
+ * @returns the rendered card.
183
+ */
184
+ export function ToolCallView(props: ToolCallViewProps): ReactNode {
185
+ const texts = resolveAIHubTexts(props.texts);
186
+ const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
187
+ const [uncontrolledExpanded, setUncontrolledExpanded] = useState(
188
+ props.defaultExpanded ?? false,
189
+ );
190
+ const isControlled = props.expanded !== undefined;
191
+ const expanded = isControlled ? (props.expanded as boolean) : uncontrolledExpanded;
192
+ const handleToggle = isControlled
193
+ ? props.onToggle ?? (() => {})
194
+ : () => setUncontrolledExpanded((e) => !e);
195
+
196
+ const seconds = props.durationSeconds ?? 0;
197
+ const durationText = seconds > 0 ? `(${seconds.toFixed(1)}s)` : "";
198
+ const formatContent = props.formatContent ?? formatToolContentForDisplay;
199
+
200
+ const rootClass = [
201
+ cls.root,
202
+ expanded ? cls.rootExpanded : cls.rootCollapsed,
203
+ statusModifier(props.status, cls),
204
+ props.className,
205
+ ]
206
+ .filter(Boolean)
207
+ .join(" ");
208
+ const bodyClass = [
209
+ cls.body,
210
+ props.status === "error" ? cls.bodyError : null,
211
+ ]
212
+ .filter(Boolean)
213
+ .join(" ");
214
+
215
+ return (
216
+ <div
217
+ className={rootClass}
218
+ data-testid="tool-call-view"
219
+ data-status={props.status}
220
+ data-expanded={expanded ? "true" : "false"}
221
+ >
222
+ <div className={cls.header}>
223
+ <span className={cls.toolName} data-testid="tool-call-view-name">
224
+ 🔧 {props.toolName}
225
+ </span>
226
+ <span className={cls.status} data-testid="tool-call-view-status">
227
+ {statusText(props.status, texts.chat)}
228
+ </span>
229
+ {durationText ? (
230
+ <span className={cls.duration}>{durationText}</span>
231
+ ) : null}
232
+ <button
233
+ type="button"
234
+ className={cls.toggle}
235
+ onClick={handleToggle}
236
+ aria-expanded={expanded}
237
+ aria-label={
238
+ expanded
239
+ ? texts.chat.toolCallCollapseAriaLabel
240
+ : texts.chat.toolCallExpandAriaLabel
241
+ }
242
+ data-testid="tool-call-view-toggle"
243
+ >
244
+ {expanded ? "▼" : "▶"}
245
+ </button>
246
+ </div>
247
+ {expanded ? (
248
+ <div className={bodyClass} data-testid="tool-call-view-body">
249
+ <div className={cls.inputSection}>
250
+ <div className={cls.sectionLabel}>
251
+ {texts.chat.toolCallInputLabel}
252
+ </div>
253
+ <pre className={cls.sectionContent}>{formatContent(props.input)}</pre>
254
+ </div>
255
+ {props.status === "error" ? (
256
+ <div className={cls.outputSection}>
257
+ <div className={cls.sectionLabel}>
258
+ {texts.chat.toolCallErrorLabel}
259
+ </div>
260
+ <pre className={cls.sectionContent}>{formatContent(props.error ?? "")}</pre>
261
+ </div>
262
+ ) : props.output !== undefined ? (
263
+ <div className={cls.outputSection}>
264
+ <div className={cls.sectionLabel}>
265
+ {texts.chat.toolCallOutputLabel}
266
+ </div>
267
+ <pre className={cls.sectionContent}>{formatContent(props.output)}</pre>
268
+ </div>
269
+ ) : null}
270
+ </div>
271
+ ) : null}
272
+ </div>
273
+ );
274
+ }