@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,79 @@
1
+ /**
2
+ * `AIHub.AuthGate` — the auth-state router.
3
+ *
4
+ * Reads `useAIHubAuth()` and renders:
5
+ *
6
+ * - `<DataClubAIHubLogin />` when no user is present.
7
+ * - `<DataClubAIHubChangePassword variant="forced" />` when a user is
8
+ * present but `mustChangePassword === true`.
9
+ * - `children` (the chat / admin / whatever) otherwise.
10
+ *
11
+ * While the provider is still hydrating from a stored token (`hydrating ===
12
+ * true`) the gate renders nothing — preventing a one-frame flash of the
13
+ * login card before the cached session resolves.
14
+ *
15
+ * Tier 3 wrappers compose this primitive as the second layer (after
16
+ * `AIHub.Provider`) so the auth UX is handled automatically; Tier 1 / 2
17
+ * wrappers get the same behavior for free via `<DataClubAIHub />`.
18
+ *
19
+ * @see SPECIFICATIONS.md §7.1 — exports
20
+ * @see SPECIFICATIONS.md §7.2.1 — auth-owned-by-library policy
21
+ * @see SPECIFICATIONS.md §7.9 — Tier-3 composition example
22
+ * @see ui-sketches/01-login.md
23
+ * @see ui-sketches/02-change-password.md
24
+ */
25
+ import { type ReactNode } from "react";
26
+ import type { AIHubTexts, DeepPartial } from "../../auth/texts.js";
27
+ import { type AIHubLoginClassNames } from "../DataClubAIHubLogin/index.js";
28
+ import { type AIHubChangePasswordClassNames } from "../ChangePassword/index.js";
29
+ /**
30
+ * Props for `AIHub.AuthGate`. The branding / i18n props mirror
31
+ * `<DataClubAIHub />` — Tier 3 wrappers pass them through here so the
32
+ * auto-rendered Login + ChangePassword screens get branded without the
33
+ * wrapper having to render those screens manually.
34
+ */
35
+ export interface AuthGateProps {
36
+ /**
37
+ * Rendered when the user is authenticated and is not in the forced
38
+ * change-password state. The wrapper is responsible for the actual
39
+ * chat / admin tree.
40
+ */
41
+ children: ReactNode;
42
+ /**
43
+ * Title text on the login card. Forwarded to `<DataClubAIHubLogin />`.
44
+ * Defaults to `"ai-hub"`.
45
+ */
46
+ productName?: string;
47
+ /**
48
+ * Placeholder shown inside the username input on the login card.
49
+ * Forwarded to `<DataClubAIHubLogin />`. Defaults to empty.
50
+ */
51
+ usernamePlaceholder?: string;
52
+ /**
53
+ * Wrapper-supplied i18n applied to both auto-rendered auth screens.
54
+ */
55
+ texts?: DeepPartial<AIHubTexts>;
56
+ /** Per-element class overrides forwarded to `<DataClubAIHubLogin />`. */
57
+ loginClassNames?: Partial<AIHubLoginClassNames>;
58
+ /**
59
+ * Per-element class overrides forwarded to
60
+ * `<DataClubAIHubChangePassword />`.
61
+ */
62
+ changePasswordClassNames?: Partial<AIHubChangePasswordClassNames>;
63
+ /**
64
+ * Optional `className` forwarded onto the login root.
65
+ */
66
+ loginClassName?: string;
67
+ /**
68
+ * Optional `className` forwarded onto the change-password root.
69
+ */
70
+ changePasswordClassName?: string;
71
+ }
72
+ /**
73
+ * Renders the right screen for the current auth state.
74
+ *
75
+ * @param props - see `AuthGateProps`.
76
+ * @returns the rendered subtree.
77
+ */
78
+ export declare function AuthGate(props: AuthGateProps): ReactNode;
79
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/AuthGate/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,6BAA6B,EACnC,MAAM,4BAA4B,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAChC,yEAAyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAChD;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;IAClE;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CA2CxD"}
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * `AIHub.AuthGate` — the auth-state router.
4
+ *
5
+ * Reads `useAIHubAuth()` and renders:
6
+ *
7
+ * - `<DataClubAIHubLogin />` when no user is present.
8
+ * - `<DataClubAIHubChangePassword variant="forced" />` when a user is
9
+ * present but `mustChangePassword === true`.
10
+ * - `children` (the chat / admin / whatever) otherwise.
11
+ *
12
+ * While the provider is still hydrating from a stored token (`hydrating ===
13
+ * true`) the gate renders nothing — preventing a one-frame flash of the
14
+ * login card before the cached session resolves.
15
+ *
16
+ * Tier 3 wrappers compose this primitive as the second layer (after
17
+ * `AIHub.Provider`) so the auth UX is handled automatically; Tier 1 / 2
18
+ * wrappers get the same behavior for free via `<DataClubAIHub />`.
19
+ *
20
+ * @see SPECIFICATIONS.md §7.1 — exports
21
+ * @see SPECIFICATIONS.md §7.2.1 — auth-owned-by-library policy
22
+ * @see SPECIFICATIONS.md §7.9 — Tier-3 composition example
23
+ * @see ui-sketches/01-login.md
24
+ * @see ui-sketches/02-change-password.md
25
+ */
26
+ import {} from "react";
27
+ import { useAIHubAuth } from "../../context/useAIHubAuth.js";
28
+ import { DataClubAIHubLogin, } from "../DataClubAIHubLogin/index.js";
29
+ import { DataClubAIHubChangePassword, } from "../ChangePassword/index.js";
30
+ /**
31
+ * Renders the right screen for the current auth state.
32
+ *
33
+ * @param props - see `AuthGateProps`.
34
+ * @returns the rendered subtree.
35
+ */
36
+ export function AuthGate(props) {
37
+ const auth = useAIHubAuth();
38
+ if (auth.hydrating) {
39
+ // Render nothing — we don't know yet whether the stored token is valid.
40
+ // FOUC-of-login-card avoidance.
41
+ return null;
42
+ }
43
+ if (!auth.user) {
44
+ return (_jsx(DataClubAIHubLogin, { ...(props.productName !== undefined ? { productName: props.productName } : {}), ...(props.usernamePlaceholder !== undefined
45
+ ? { usernamePlaceholder: props.usernamePlaceholder }
46
+ : {}), ...(props.texts !== undefined ? { texts: props.texts } : {}), ...(props.loginClassNames !== undefined
47
+ ? { classNames: props.loginClassNames }
48
+ : {}), ...(props.loginClassName !== undefined
49
+ ? { className: props.loginClassName }
50
+ : {}) }));
51
+ }
52
+ if (auth.mustChangePassword) {
53
+ return (_jsx(DataClubAIHubChangePassword, { variant: "forced", ...(props.texts !== undefined ? { texts: props.texts } : {}), ...(props.changePasswordClassNames !== undefined
54
+ ? { classNames: props.changePasswordClassNames }
55
+ : {}), ...(props.changePasswordClassName !== undefined
56
+ ? { className: props.changePasswordClassName }
57
+ : {}) }));
58
+ }
59
+ return _jsx(_Fragment, { children: props.children });
60
+ }
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/AuthGate/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EACL,kBAAkB,GAEnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,2BAA2B,GAE5B,MAAM,4BAA4B,CAAC;AA8CpC;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAE5B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,wEAAwE;QACxE,gCAAgC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CACL,KAAC,kBAAkB,OACb,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC3E,CAAC,KAAK,CAAC,mBAAmB,KAAK,SAAS;gBAC1C,CAAC,CAAC,EAAE,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,EAAE;gBACpD,CAAC,CAAC,EAAE,CAAC,KACH,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACzD,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS;gBACtC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,eAAe,EAAE;gBACvC,CAAC,CAAC,EAAE,CAAC,KACH,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS;gBACrC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,cAAc,EAAE;gBACrC,CAAC,CAAC,EAAE,CAAC,GACP,CACH,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,OAAO,CACL,KAAC,2BAA2B,IAC1B,OAAO,EAAC,QAAQ,KACZ,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACzD,CAAC,KAAK,CAAC,wBAAwB,KAAK,SAAS;gBAC/C,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,wBAAwB,EAAE;gBAChD,CAAC,CAAC,EAAE,CAAC,KACH,CAAC,KAAK,CAAC,uBAAuB,KAAK,SAAS;gBAC9C,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,uBAAuB,EAAE;gBAC9C,CAAC,CAAC,EAAE,CAAC,GACP,CACH,CAAC;IACJ,CAAC;IAED,OAAO,4BAAG,KAAK,CAAC,QAAQ,GAAI,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * `<CacheBadge />` — small per-message badge surfacing provider token
3
+ * usage on an assistant bubble. Renders an inline icon + a compact
4
+ * token count, with the full breakdown in a `title`-attribute tooltip
5
+ * on hover.
6
+ *
7
+ * **What it shows.** Letta reports five things per assistant turn (via
8
+ * `AIHubMessageUsage`): input tokens, output tokens, cache-read tokens
9
+ * (prompt-cache HIT — provider charged ~0.1x), cache-write tokens
10
+ * (provider charged ~1.25x, Anthropic only), reasoning tokens, and a
11
+ * rolling context-window estimate.
12
+ *
13
+ * The headline number we show in the badge is the **cache-hit
14
+ * percentage of the prompt** — `cache_read / (input + cache_read +
15
+ * cache_write)`. That number is the single most useful at-a-glance
16
+ * signal:
17
+ * - 0% → cache is cold (cost is the worst case)
18
+ * - 80% → ~10x cheaper system prompt than a cold turn
19
+ *
20
+ * The full numbers live in the tooltip. We use the native `title`
21
+ * attribute instead of a custom popover to keep the component
22
+ * lightweight and dependency-free (no portals, no animation, no
23
+ * focus management — perfect for a peripheral info chip).
24
+ *
25
+ * **When to render.** Only when the parent passes a `usage` prop with
26
+ * at least one non-null number. Messages without a usage stamp (e.g.
27
+ * historical conversations from before this feature shipped, or
28
+ * tool-only assistant turns where Letta didn't report anything)
29
+ * simply don't render the badge.
30
+ *
31
+ * Exported under `AIHub.CacheBadge` (re-exported via the namespace).
32
+ *
33
+ * @see AIHubMessageUsage in `../../types.ts`
34
+ * @see SPECIFICATIONS.md §9.4 — `usage` SSE event
35
+ */
36
+ import type { ReactNode } from "react";
37
+ import type { AIHubMessageUsage } from "../../types.js";
38
+ /** BEM class names emitted by `<CacheBadge />`. */
39
+ export interface CacheBadgeClassNames {
40
+ /** Outer span; `data-cache-state="hot|warm|cold|none"` for skinning. */
41
+ root: string;
42
+ /** The leading icon character (default 💾). */
43
+ icon: string;
44
+ /** The headline percentage label. */
45
+ label: string;
46
+ }
47
+ /** Localizable strings for the badge headline + tooltip. */
48
+ export interface CacheBadgeTexts {
49
+ /** Headline shown when there's no cache info at all (e.g. providers that don't report). */
50
+ noCacheLabel: string;
51
+ /** Headline shown when this turn was a full cache miss (no tokens served from cache). */
52
+ missLabel: string;
53
+ /** Headline shown when this turn was a cache priming write — read=0 but write>0. */
54
+ writePrimingLabel: string;
55
+ /** Headline prefix for cache hits — full text is `${hitLabel} ${N}%`. */
56
+ hitLabel: string;
57
+ /** Tooltip line prefixes. Keep short — the tooltip is `title` only. */
58
+ hitTooltipLabel: string;
59
+ writeTooltipLabel: string;
60
+ inputLabel: string;
61
+ outputLabel: string;
62
+ reasoningLabel: string;
63
+ contextLabel: string;
64
+ totalLabel: string;
65
+ }
66
+ export declare const DEFAULT_TEXTS: CacheBadgeTexts;
67
+ /** Props for `<CacheBadge />`. */
68
+ export interface CacheBadgeProps {
69
+ /** Per-message usage, as returned by `GET /sessions/:id/messages`. */
70
+ usage: AIHubMessageUsage;
71
+ /** Optional class-name overrides. */
72
+ classNames?: Partial<CacheBadgeClassNames>;
73
+ /** Optional text overrides (l10n). */
74
+ texts?: Partial<CacheBadgeTexts>;
75
+ }
76
+ /**
77
+ * Computes the cache-hit ratio (0..1) over the prompt-side tokens.
78
+ *
79
+ * Denominator: `input + cache_read + cache_write` — every prompt
80
+ * token the provider saw, regardless of whether it served from cache
81
+ * or wrote new. We exclude `output` and `reasoning` because those
82
+ * are completion-side and can't benefit from prompt caching.
83
+ *
84
+ * Exported so the test suite can assert numerically.
85
+ */
86
+ export declare function computeCacheHitRatio(usage: AIHubMessageUsage): number | null;
87
+ export declare function CacheBadge({ usage, classNames, texts, }: CacheBadgeProps): ReactNode;
88
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/CacheBadge/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,mDAAmD;AACnD,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;CACf;AAQD,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC9B,2FAA2F;IAC3F,YAAY,EAAE,MAAM,CAAC;IACrB,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,eAYP,CAAC;AAEtB,kCAAkC;AAClC,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,KAAK,EAAE,iBAAiB,CAAC;IACzB,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3C,sCAAsC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAO5E;AAsFD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,UAAU,EACV,KAAK,GACN,EAAE,eAAe,GAAG,SAAS,CAqC7B"}
@@ -0,0 +1,127 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const DEFAULT_CLASS_NAMES = Object.freeze({
3
+ root: "data-club-ai-hub__cache-badge",
4
+ icon: "data-club-ai-hub__cache-badge__icon",
5
+ label: "data-club-ai-hub__cache-badge__label",
6
+ });
7
+ export const DEFAULT_TEXTS = Object.freeze({
8
+ noCacheLabel: "no data",
9
+ missLabel: "MISS",
10
+ writePrimingLabel: "PRIMING",
11
+ hitLabel: "HIT",
12
+ hitTooltipLabel: "Cache hit",
13
+ writeTooltipLabel: "Cache write",
14
+ inputLabel: "Input",
15
+ outputLabel: "Output",
16
+ reasoningLabel: "Reasoning",
17
+ contextLabel: "Context",
18
+ totalLabel: "Total",
19
+ });
20
+ /**
21
+ * Computes the cache-hit ratio (0..1) over the prompt-side tokens.
22
+ *
23
+ * Denominator: `input + cache_read + cache_write` — every prompt
24
+ * token the provider saw, regardless of whether it served from cache
25
+ * or wrote new. We exclude `output` and `reasoning` because those
26
+ * are completion-side and can't benefit from prompt caching.
27
+ *
28
+ * Exported so the test suite can assert numerically.
29
+ */
30
+ export function computeCacheHitRatio(usage) {
31
+ const read = usage.cache_read ?? 0;
32
+ const write = usage.cache_write ?? 0;
33
+ const input = usage.input ?? 0;
34
+ const denom = read + write + input;
35
+ if (denom === 0)
36
+ return null;
37
+ return read / denom;
38
+ }
39
+ function bucketState(usage, ratio) {
40
+ if (ratio === null)
41
+ return "none";
42
+ if (ratio === 0) {
43
+ // No cache hit. Distinguish full-miss (nothing cached anywhere)
44
+ // from priming (we WROTE to the cache this turn — next turn will
45
+ // benefit). The latter is good news, the former is bad news, so
46
+ // the user-facing labels should differ.
47
+ return (usage.cache_write ?? 0) > 0 ? "priming" : "miss";
48
+ }
49
+ if (ratio >= 0.6)
50
+ return "hot";
51
+ if (ratio >= 0.1)
52
+ return "warm";
53
+ return "cold";
54
+ }
55
+ /** Formats a token count as a compact human-readable string: 1234 → 1.2k. */
56
+ function formatTokens(n) {
57
+ if (n === null || n === undefined)
58
+ return "—";
59
+ if (n < 1000)
60
+ return String(n);
61
+ if (n < 1_000_000)
62
+ return `${(n / 1000).toFixed(1)}k`;
63
+ return `${(n / 1_000_000).toFixed(2)}M`;
64
+ }
65
+ /** Builds the `title`-attribute tooltip text from the usage object. */
66
+ function buildTooltip(usage, texts) {
67
+ const lines = [];
68
+ if (usage.cache_read !== null && usage.cache_read !== undefined) {
69
+ lines.push(`${texts.hitTooltipLabel}: ${formatTokens(usage.cache_read)}`);
70
+ }
71
+ if (usage.cache_write !== null && usage.cache_write !== undefined) {
72
+ lines.push(`${texts.writeTooltipLabel}: ${formatTokens(usage.cache_write)}`);
73
+ }
74
+ if (usage.input !== null && usage.input !== undefined) {
75
+ lines.push(`${texts.inputLabel}: ${formatTokens(usage.input)}`);
76
+ }
77
+ if (usage.output !== null && usage.output !== undefined) {
78
+ lines.push(`${texts.outputLabel}: ${formatTokens(usage.output)}`);
79
+ }
80
+ if (usage.reasoning !== null && usage.reasoning !== undefined && usage.reasoning > 0) {
81
+ lines.push(`${texts.reasoningLabel}: ${formatTokens(usage.reasoning)}`);
82
+ }
83
+ if (usage.context !== null && usage.context !== undefined) {
84
+ lines.push(`${texts.contextLabel}: ${formatTokens(usage.context)}`);
85
+ }
86
+ if (usage.total !== null && usage.total !== undefined) {
87
+ lines.push(`${texts.totalLabel}: ${formatTokens(usage.total)}`);
88
+ }
89
+ return lines.join("\n");
90
+ }
91
+ /** Returns true when the usage object has at least one usable numeric field. */
92
+ function hasAnyData(usage) {
93
+ return ((usage.input ?? null) !== null ||
94
+ (usage.output ?? null) !== null ||
95
+ (usage.cache_read ?? null) !== null ||
96
+ (usage.cache_write ?? null) !== null ||
97
+ (usage.reasoning ?? null) !== null ||
98
+ (usage.context ?? null) !== null ||
99
+ (usage.total ?? null) !== null);
100
+ }
101
+ export function CacheBadge({ usage, classNames, texts, }) {
102
+ if (!hasAnyData(usage))
103
+ return null;
104
+ const cls = { ...DEFAULT_CLASS_NAMES, ...(classNames ?? {}) };
105
+ const t = { ...DEFAULT_TEXTS, ...(texts ?? {}) };
106
+ const ratio = computeCacheHitRatio(usage);
107
+ const state = bucketState(usage, ratio);
108
+ // Headline label — varies by state so the user gets an immediate
109
+ // diagnostic signal at-a-glance.
110
+ let headline;
111
+ if (state === "none") {
112
+ headline = t.noCacheLabel;
113
+ }
114
+ else if (state === "miss") {
115
+ headline = t.missLabel;
116
+ }
117
+ else if (state === "priming") {
118
+ headline = t.writePrimingLabel;
119
+ }
120
+ else {
121
+ // hot / warm / cold — ratio is guaranteed non-null here.
122
+ headline = `${t.hitLabel} ${Math.round((ratio ?? 0) * 100)}%`;
123
+ }
124
+ const tooltip = buildTooltip(usage, t);
125
+ return (_jsxs("span", { className: cls.root, "data-testid": "cache-badge", "data-cache-state": state, title: tooltip, role: "status", "aria-label": tooltip, children: [_jsx("span", { className: cls.icon, "aria-hidden": "true", children: "\uD83D\uDCBE" }), _jsx("span", { className: cls.label, children: headline })] }));
126
+ }
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/CacheBadge/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * `<DataClubAIHubChangePassword />` — the built-in change-password screen.
3
+ *
4
+ * Two variants in one component:
5
+ *
6
+ * - **Forced** (`variant="forced"`) — auto-rendered after login when
7
+ * `useAIHubAuth().mustChangePassword === true`. No `current_password`
8
+ * field, no cancel button (there is nowhere else to go), with an
9
+ * `intro_message` explaining the requirement. Submit calls
10
+ * `client.changePassword(null, newPassword)` — the change-only token
11
+ * is itself the proof of authentication.
12
+ * - **Voluntary** (`variant="voluntary"`) — opened from the user-menu
13
+ * ([00-shell.md](ui-sketches/00-shell.md)). Includes `current_password`
14
+ * and a `Cancel` button that fires `onCancel`. Submit calls
15
+ * `client.changePassword(currentPassword, newPassword)`.
16
+ *
17
+ * Each password field carries its own `show_password_toggle` — the
18
+ * regression-guard for the per-field pattern is in
19
+ * `__tests__/components/ChangePassword.test.tsx`.
20
+ *
21
+ * The client mirrors the §8.5 password policy via
22
+ * `validatePasswordPolicyClient` so the form surfaces too-short /
23
+ * too-simple errors *before* sending; the server is authoritative and
24
+ * its banner wins if the two ever disagree.
25
+ *
26
+ * @see SPECIFICATIONS.md §7.2.1 (and §7.3 — auth is owned by the library)
27
+ * @see SPECIFICATIONS.md §8.5 — password policy + forced/voluntary semantics
28
+ * @see ui-sketches/02-change-password.md — visual contract
29
+ */
30
+ import { type ReactNode } from "react";
31
+ import { type AIHubTexts, type DeepPartial } from "../../auth/texts.js";
32
+ /**
33
+ * BEM class names emitted by `<DataClubAIHubChangePassword />`. Wrappers
34
+ * pass a partial map via `classNames` to override individual entries for
35
+ * utility-CSS frameworks.
36
+ */
37
+ export interface AIHubChangePasswordClassNames {
38
+ /** Outer page wrapper (centers the card in the viewport). */
39
+ root: string;
40
+ /** The card itself. */
41
+ card: string;
42
+ /** Gradient title at the top. */
43
+ title: string;
44
+ /** Intro message (forced variant only). */
45
+ intro: string;
46
+ /** Error banner shown above the form on failure. */
47
+ errorBanner: string;
48
+ /** Form container. */
49
+ form: string;
50
+ /** Label / field group wrapper. */
51
+ fieldGroup: string;
52
+ /** `<label>` for an input. */
53
+ fieldLabel: string;
54
+ /** Inline field-level error message. */
55
+ fieldError: string;
56
+ /** Password input wrapper (input + show toggle). */
57
+ passwordWrapper: string;
58
+ /** The password `<input>` itself. */
59
+ passwordInput: string;
60
+ /** The show/hide-password toggle button. */
61
+ passwordToggle: string;
62
+ /** Submit button. */
63
+ submitButton: string;
64
+ /** Cancel button (voluntary variant only). */
65
+ cancelButton: string;
66
+ /** Spinner glyph rendered inside the submit button while saving. */
67
+ spinner: string;
68
+ }
69
+ /**
70
+ * Props for `<DataClubAIHubChangePassword />`. See §7.2.1.
71
+ */
72
+ export interface DataClubAIHubChangePasswordProps {
73
+ /**
74
+ * Which variant to render. **`"forced"`** (default — what `AuthGate`
75
+ * mounts after a successful login with `is_initial_password=true`) hides
76
+ * the current-password field + cancel button, and shows an intro
77
+ * message. **`"voluntary"`** (from the user-menu) shows all three fields
78
+ * + a cancel button.
79
+ */
80
+ variant?: "forced" | "voluntary";
81
+ /**
82
+ * Fires after a successful password change. The provider has already
83
+ * stored the fresh session token + refreshed `/auth/me` when this fires,
84
+ * so the caller can read the now-updated `useAIHubAuth().user` directly.
85
+ */
86
+ onChanged?: () => void;
87
+ /**
88
+ * Fires when the user clicks Cancel on the voluntary variant. Ignored on
89
+ * the forced variant (there is nowhere else to go).
90
+ */
91
+ onCancel?: () => void;
92
+ /** Extra class merged onto the root wrapper alongside the BEM defaults. */
93
+ className?: string;
94
+ /** Per-element class-name overrides. */
95
+ classNames?: Partial<AIHubChangePasswordClassNames>;
96
+ /**
97
+ * Wrapper-supplied i18n. Missing keys fall back to English defaults.
98
+ * Only the `changePassword` namespace is consulted by this component.
99
+ */
100
+ texts?: DeepPartial<AIHubTexts>;
101
+ }
102
+ /**
103
+ * Renders the change-password card.
104
+ *
105
+ * @param props - see `DataClubAIHubChangePasswordProps`.
106
+ * @returns the rendered card.
107
+ */
108
+ export declare function DataClubAIHubChangePassword(props: DataClubAIHubChangePasswordProps): ReactNode;
109
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ChangePassword/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjE,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAI7B;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AA0BD;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACjC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACpD;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,gCAAgC,GACtC,SAAS,CAoOX"}
@@ -0,0 +1,142 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * `<DataClubAIHubChangePassword />` — the built-in change-password screen.
4
+ *
5
+ * Two variants in one component:
6
+ *
7
+ * - **Forced** (`variant="forced"`) — auto-rendered after login when
8
+ * `useAIHubAuth().mustChangePassword === true`. No `current_password`
9
+ * field, no cancel button (there is nowhere else to go), with an
10
+ * `intro_message` explaining the requirement. Submit calls
11
+ * `client.changePassword(null, newPassword)` — the change-only token
12
+ * is itself the proof of authentication.
13
+ * - **Voluntary** (`variant="voluntary"`) — opened from the user-menu
14
+ * ([00-shell.md](ui-sketches/00-shell.md)). Includes `current_password`
15
+ * and a `Cancel` button that fires `onCancel`. Submit calls
16
+ * `client.changePassword(currentPassword, newPassword)`.
17
+ *
18
+ * Each password field carries its own `show_password_toggle` — the
19
+ * regression-guard for the per-field pattern is in
20
+ * `__tests__/components/ChangePassword.test.tsx`.
21
+ *
22
+ * The client mirrors the §8.5 password policy via
23
+ * `validatePasswordPolicyClient` so the form surfaces too-short /
24
+ * too-simple errors *before* sending; the server is authoritative and
25
+ * its banner wins if the two ever disagree.
26
+ *
27
+ * @see SPECIFICATIONS.md §7.2.1 (and §7.3 — auth is owned by the library)
28
+ * @see SPECIFICATIONS.md §8.5 — password policy + forced/voluntary semantics
29
+ * @see ui-sketches/02-change-password.md — visual contract
30
+ */
31
+ import { useState } from "react";
32
+ import { AIHubRequestError } from "../../client/AIHubClient.js";
33
+ import { useAIHubAuth } from "../../context/useAIHubAuth.js";
34
+ import { resolveAIHubTexts, } from "../../auth/texts.js";
35
+ import { validatePasswordPolicyClient } from "../../auth/passwordPolicy.js";
36
+ import { PasswordInput } from "../internal/PasswordInput.js";
37
+ /**
38
+ * Default BEM class names. Stable, kebab-case, scoped under
39
+ * `data-club-ai-hub__change-password`. Wrappers override individual entries
40
+ * via `classNames`.
41
+ */
42
+ const DEFAULT_CLASS_NAMES = Object.freeze({
43
+ root: "data-club-ai-hub__change-password",
44
+ card: "data-club-ai-hub__change-password-card",
45
+ title: "data-club-ai-hub__change-password-card__title",
46
+ intro: "data-club-ai-hub__change-password-card__intro",
47
+ errorBanner: "data-club-ai-hub__change-password-card__error",
48
+ form: "data-club-ai-hub__change-password-card__form",
49
+ fieldGroup: "data-club-ai-hub__change-password-card__field",
50
+ fieldLabel: "data-club-ai-hub__change-password-card__label",
51
+ fieldError: "data-club-ai-hub__change-password-card__field-error",
52
+ passwordWrapper: "data-club-ai-hub__change-password-card__password",
53
+ passwordInput: "data-club-ai-hub__change-password-card__input data-club-ai-hub__change-password-card__input--password",
54
+ passwordToggle: "data-club-ai-hub__change-password-card__toggle",
55
+ submitButton: "data-club-ai-hub__change-password-card__submit",
56
+ cancelButton: "data-club-ai-hub__change-password-card__cancel",
57
+ spinner: "data-club-ai-hub__spinner",
58
+ });
59
+ /**
60
+ * Renders the change-password card.
61
+ *
62
+ * @param props - see `DataClubAIHubChangePasswordProps`.
63
+ * @returns the rendered card.
64
+ */
65
+ export function DataClubAIHubChangePassword(props) {
66
+ const auth = useAIHubAuth();
67
+ const variant = props.variant ?? "forced";
68
+ const classes = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
69
+ const texts = resolveAIHubTexts(props.texts).changePassword;
70
+ const [currentPassword, setCurrentPassword] = useState("");
71
+ const [newPassword, setNewPassword] = useState("");
72
+ const [confirmPassword, setConfirmPassword] = useState("");
73
+ const [submitting, setSubmitting] = useState(false);
74
+ const [errorMessage, setErrorMessage] = useState(null);
75
+ // Client-side validation produces an inline field-error message — separate
76
+ // from the top-of-card error banner, which is reserved for server errors.
77
+ const fieldError = (() => {
78
+ if (newPassword.length === 0 && confirmPassword.length === 0)
79
+ return null;
80
+ const policy = validatePasswordPolicyClient(newPassword);
81
+ if (!policy.ok) {
82
+ if (policy.code === "password_too_short")
83
+ return texts.passwordTooShortError;
84
+ return texts.passwordTooSimpleError;
85
+ }
86
+ if (confirmPassword.length > 0 && newPassword !== confirmPassword) {
87
+ return texts.passwordsMustMatchError;
88
+ }
89
+ return null;
90
+ })();
91
+ // Submit-disable predicate: voluntary needs all three; forced needs two.
92
+ const fieldsFilled = newPassword.length > 0 &&
93
+ confirmPassword.length > 0 &&
94
+ newPassword === confirmPassword &&
95
+ (variant === "forced" || currentPassword.length > 0);
96
+ const submitDisabled = submitting || !fieldsFilled || fieldError !== null;
97
+ const handleSubmit = async (e) => {
98
+ e.preventDefault();
99
+ if (submitDisabled)
100
+ return;
101
+ setSubmitting(true);
102
+ setErrorMessage(null);
103
+ try {
104
+ await auth.changePassword(variant === "voluntary" ? currentPassword : null, newPassword);
105
+ props.onChanged?.();
106
+ }
107
+ catch (err) {
108
+ if (err instanceof AIHubRequestError) {
109
+ // Map the wire error code to a localized banner. Server's
110
+ // password-policy errors trump the client mirror — the server is
111
+ // authoritative (§8.5).
112
+ if (err.code === "password_too_short") {
113
+ setErrorMessage(texts.passwordTooShortError);
114
+ }
115
+ else if (err.code === "password_too_simple") {
116
+ setErrorMessage(texts.passwordTooSimpleError);
117
+ }
118
+ else if (err.code === "unauthorized" || err.status === 401) {
119
+ setErrorMessage(texts.invalidCurrentPasswordError);
120
+ }
121
+ else if (err.code === "network") {
122
+ setErrorMessage(texts.networkError);
123
+ }
124
+ else {
125
+ // Fall back to the server message — it's safe to surface per §9.
126
+ setErrorMessage(err.message || texts.networkError);
127
+ }
128
+ }
129
+ else {
130
+ setErrorMessage(texts.networkError);
131
+ }
132
+ }
133
+ finally {
134
+ setSubmitting(false);
135
+ }
136
+ };
137
+ const rootClass = props.className !== undefined
138
+ ? `${classes.root} ${props.className}`
139
+ : classes.root;
140
+ return (_jsx("div", { className: rootClass, "data-testid": "change-password-root", "data-variant": variant, children: _jsxs("div", { className: classes.card, role: "form", "aria-labelledby": "dc-aih-change-password-title", children: [_jsx("h1", { id: "dc-aih-change-password-title", className: classes.title, children: texts.title }), variant === "forced" ? (_jsx("p", { className: classes.intro, "data-testid": "change-password-intro", children: texts.forcedChangePasswordIntro })) : null, errorMessage !== null ? (_jsx("div", { className: classes.errorBanner, role: "alert", "aria-live": "polite", "data-testid": "change-password-error", children: errorMessage })) : null, _jsxs("form", { className: classes.form, onSubmit: handleSubmit, noValidate: true, children: [variant === "voluntary" ? (_jsxs("div", { className: classes.fieldGroup, children: [_jsx("label", { htmlFor: "dc-aih-change-current", className: classes.fieldLabel, children: texts.currentPasswordLabel }), _jsx(PasswordInput, { id: "dc-aih-change-current", value: currentPassword, onChange: setCurrentPassword, name: "current_password", autoComplete: "current-password", disabled: submitting, required: true, autoFocus: true, showAriaLabel: texts.showPasswordAriaLabel, hideAriaLabel: texts.hidePasswordAriaLabel, wrapperClassName: classes.passwordWrapper, inputClassName: classes.passwordInput, toggleClassName: classes.passwordToggle, testId: "change-current-field" })] })) : null, _jsxs("div", { className: classes.fieldGroup, children: [_jsx("label", { htmlFor: "dc-aih-change-new", className: classes.fieldLabel, children: texts.newPasswordLabel }), _jsx(PasswordInput, { id: "dc-aih-change-new", value: newPassword, onChange: setNewPassword, name: "new_password", autoComplete: "new-password", disabled: submitting, required: true, ...(variant === "forced" ? { autoFocus: true } : {}), showAriaLabel: texts.showPasswordAriaLabel, hideAriaLabel: texts.hidePasswordAriaLabel, wrapperClassName: classes.passwordWrapper, inputClassName: classes.passwordInput, toggleClassName: classes.passwordToggle, testId: "change-new-field" })] }), _jsxs("div", { className: classes.fieldGroup, children: [_jsx("label", { htmlFor: "dc-aih-change-confirm", className: classes.fieldLabel, children: texts.confirmPasswordLabel }), _jsx(PasswordInput, { id: "dc-aih-change-confirm", value: confirmPassword, onChange: setConfirmPassword, name: "confirm_password", autoComplete: "new-password", disabled: submitting, required: true, showAriaLabel: texts.showPasswordAriaLabel, hideAriaLabel: texts.hidePasswordAriaLabel, wrapperClassName: classes.passwordWrapper, inputClassName: classes.passwordInput, toggleClassName: classes.passwordToggle, testId: "change-confirm-field" }), fieldError !== null ? (_jsx("div", { className: classes.fieldError, role: "status", "aria-live": "polite", "data-testid": "change-password-field-error", children: fieldError })) : null] }), _jsx("button", { type: "submit", className: classes.submitButton, disabled: submitDisabled, "data-testid": "change-password-submit", children: submitting ? (_jsxs(_Fragment, { children: [_jsx("span", { className: classes.spinner, "aria-hidden": "true" }), texts.savingButton] })) : (texts.changePasswordButton) }), variant === "voluntary" ? (_jsx("button", { type: "button", className: classes.cancelButton, onClick: () => props.onCancel?.(), disabled: submitting, "data-testid": "change-password-cancel", children: texts.cancelButton })) : null] })] }) }));
141
+ }
142
+ //# sourceMappingURL=index.js.map