@theokit/ui 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (715) hide show
  1. package/CHANGELOG.md +1325 -0
  2. package/DESIGN.md +456 -0
  3. package/LICENSE +201 -0
  4. package/NOTICE +38 -0
  5. package/README.md +467 -0
  6. package/dist/chunk-27ENTTY7.js +146 -0
  7. package/dist/chunk-27ENTTY7.js.map +1 -0
  8. package/dist/chunk-2H6TQELG.js +33 -0
  9. package/dist/chunk-2H6TQELG.js.map +1 -0
  10. package/dist/chunk-2L6MRJD4.js +120 -0
  11. package/dist/chunk-2L6MRJD4.js.map +1 -0
  12. package/dist/chunk-2Y5V2PAL.js +80 -0
  13. package/dist/chunk-2Y5V2PAL.js.map +1 -0
  14. package/dist/chunk-34NAFDVL.js +46 -0
  15. package/dist/chunk-34NAFDVL.js.map +1 -0
  16. package/dist/chunk-36KJGXEK.js +112 -0
  17. package/dist/chunk-36KJGXEK.js.map +1 -0
  18. package/dist/chunk-3BMYYNN6.js +124 -0
  19. package/dist/chunk-3BMYYNN6.js.map +1 -0
  20. package/dist/chunk-3OHV7EEI.js +34 -0
  21. package/dist/chunk-3OHV7EEI.js.map +1 -0
  22. package/dist/chunk-3QKTS6F5.js +88 -0
  23. package/dist/chunk-3QKTS6F5.js.map +1 -0
  24. package/dist/chunk-3TBXLYNM.js +42 -0
  25. package/dist/chunk-3TBXLYNM.js.map +1 -0
  26. package/dist/chunk-4AM2HSXU.js +67 -0
  27. package/dist/chunk-4AM2HSXU.js.map +1 -0
  28. package/dist/chunk-4BCGKM65.js +44 -0
  29. package/dist/chunk-4BCGKM65.js.map +1 -0
  30. package/dist/chunk-4D3JILQX.js +145 -0
  31. package/dist/chunk-4D3JILQX.js.map +1 -0
  32. package/dist/chunk-4EJU2GBG.js +48 -0
  33. package/dist/chunk-4EJU2GBG.js.map +1 -0
  34. package/dist/chunk-4WKO3G5C.js +110 -0
  35. package/dist/chunk-4WKO3G5C.js.map +1 -0
  36. package/dist/chunk-53XPKI7Q.js +97 -0
  37. package/dist/chunk-53XPKI7Q.js.map +1 -0
  38. package/dist/chunk-55TDVDPG.js +58 -0
  39. package/dist/chunk-55TDVDPG.js.map +1 -0
  40. package/dist/chunk-56BJLFW7.js +26 -0
  41. package/dist/chunk-56BJLFW7.js.map +1 -0
  42. package/dist/chunk-5HOQLE6Y.js +35 -0
  43. package/dist/chunk-5HOQLE6Y.js.map +1 -0
  44. package/dist/chunk-5TY3NYF5.js +144 -0
  45. package/dist/chunk-5TY3NYF5.js.map +1 -0
  46. package/dist/chunk-5VOSCJKQ.js +92 -0
  47. package/dist/chunk-5VOSCJKQ.js.map +1 -0
  48. package/dist/chunk-65NVO6TK.js +171 -0
  49. package/dist/chunk-65NVO6TK.js.map +1 -0
  50. package/dist/chunk-6A5TPCKP.js +64 -0
  51. package/dist/chunk-6A5TPCKP.js.map +1 -0
  52. package/dist/chunk-6CO4LEXZ.js +41 -0
  53. package/dist/chunk-6CO4LEXZ.js.map +1 -0
  54. package/dist/chunk-6FVUPNPG.js +56 -0
  55. package/dist/chunk-6FVUPNPG.js.map +1 -0
  56. package/dist/chunk-76YWTIWK.js +106 -0
  57. package/dist/chunk-76YWTIWK.js.map +1 -0
  58. package/dist/chunk-7EI7424P.js +78 -0
  59. package/dist/chunk-7EI7424P.js.map +1 -0
  60. package/dist/chunk-AHTVYOPQ.js +26 -0
  61. package/dist/chunk-AHTVYOPQ.js.map +1 -0
  62. package/dist/chunk-AJTJNHKK.js +85 -0
  63. package/dist/chunk-AJTJNHKK.js.map +1 -0
  64. package/dist/chunk-AMT3CPMC.js +155 -0
  65. package/dist/chunk-AMT3CPMC.js.map +1 -0
  66. package/dist/chunk-AX5EH73R.js +59 -0
  67. package/dist/chunk-AX5EH73R.js.map +1 -0
  68. package/dist/chunk-B3VAJSZ2.js +35 -0
  69. package/dist/chunk-B3VAJSZ2.js.map +1 -0
  70. package/dist/chunk-B4CQMQ64.js +25 -0
  71. package/dist/chunk-B4CQMQ64.js.map +1 -0
  72. package/dist/chunk-BMRZXT5T.js +115 -0
  73. package/dist/chunk-BMRZXT5T.js.map +1 -0
  74. package/dist/chunk-BYZ6OFH4.js +73 -0
  75. package/dist/chunk-BYZ6OFH4.js.map +1 -0
  76. package/dist/chunk-C55VUQ7N.js +156 -0
  77. package/dist/chunk-C55VUQ7N.js.map +1 -0
  78. package/dist/chunk-D4GEAV4C.js +91 -0
  79. package/dist/chunk-D4GEAV4C.js.map +1 -0
  80. package/dist/chunk-DC43CHAM.js +152 -0
  81. package/dist/chunk-DC43CHAM.js.map +1 -0
  82. package/dist/chunk-DKCRLN35.js +92 -0
  83. package/dist/chunk-DKCRLN35.js.map +1 -0
  84. package/dist/chunk-DN5BUDBI.js +86 -0
  85. package/dist/chunk-DN5BUDBI.js.map +1 -0
  86. package/dist/chunk-DOLKDYMS.js +88 -0
  87. package/dist/chunk-DOLKDYMS.js.map +1 -0
  88. package/dist/chunk-DW34WXCG.js +28 -0
  89. package/dist/chunk-DW34WXCG.js.map +1 -0
  90. package/dist/chunk-DZAAKHGZ.js +135 -0
  91. package/dist/chunk-DZAAKHGZ.js.map +1 -0
  92. package/dist/chunk-E4IRSSHO.js +116 -0
  93. package/dist/chunk-E4IRSSHO.js.map +1 -0
  94. package/dist/chunk-E67WQXBV.js +104 -0
  95. package/dist/chunk-E67WQXBV.js.map +1 -0
  96. package/dist/chunk-EG6IHP3H.js +128 -0
  97. package/dist/chunk-EG6IHP3H.js.map +1 -0
  98. package/dist/chunk-EO7LOXG2.js +82 -0
  99. package/dist/chunk-EO7LOXG2.js.map +1 -0
  100. package/dist/chunk-EWDN56AS.js +24 -0
  101. package/dist/chunk-EWDN56AS.js.map +1 -0
  102. package/dist/chunk-F5P5P2SC.js +141 -0
  103. package/dist/chunk-F5P5P2SC.js.map +1 -0
  104. package/dist/chunk-FAWPRZTM.js +79 -0
  105. package/dist/chunk-FAWPRZTM.js.map +1 -0
  106. package/dist/chunk-FGYJ2WPX.js +36 -0
  107. package/dist/chunk-FGYJ2WPX.js.map +1 -0
  108. package/dist/chunk-GBG3I5I5.js +46 -0
  109. package/dist/chunk-GBG3I5I5.js.map +1 -0
  110. package/dist/chunk-GDMCDW66.js +19 -0
  111. package/dist/chunk-GDMCDW66.js.map +1 -0
  112. package/dist/chunk-H6HSQCOW.js +80 -0
  113. package/dist/chunk-H6HSQCOW.js.map +1 -0
  114. package/dist/chunk-HDM4RCIF.js +111 -0
  115. package/dist/chunk-HDM4RCIF.js.map +1 -0
  116. package/dist/chunk-HNTOGGVD.js +77 -0
  117. package/dist/chunk-HNTOGGVD.js.map +1 -0
  118. package/dist/chunk-HQW2ABO4.js +28 -0
  119. package/dist/chunk-HQW2ABO4.js.map +1 -0
  120. package/dist/chunk-HRDRGZ2Y.js +76 -0
  121. package/dist/chunk-HRDRGZ2Y.js.map +1 -0
  122. package/dist/chunk-HUOVA7SF.js +83 -0
  123. package/dist/chunk-HUOVA7SF.js.map +1 -0
  124. package/dist/chunk-ITA3SNOR.js +133 -0
  125. package/dist/chunk-ITA3SNOR.js.map +1 -0
  126. package/dist/chunk-IYNUPG2G.js +61 -0
  127. package/dist/chunk-IYNUPG2G.js.map +1 -0
  128. package/dist/chunk-JJ65ZI4P.js +199 -0
  129. package/dist/chunk-JJ65ZI4P.js.map +1 -0
  130. package/dist/chunk-JRBGZ6NI.js +106 -0
  131. package/dist/chunk-JRBGZ6NI.js.map +1 -0
  132. package/dist/chunk-K45OO62F.js +108 -0
  133. package/dist/chunk-K45OO62F.js.map +1 -0
  134. package/dist/chunk-KDTKA667.js +67 -0
  135. package/dist/chunk-KDTKA667.js.map +1 -0
  136. package/dist/chunk-KI7KZBSN.js +142 -0
  137. package/dist/chunk-KI7KZBSN.js.map +1 -0
  138. package/dist/chunk-KOJ7XOPZ.js +87 -0
  139. package/dist/chunk-KOJ7XOPZ.js.map +1 -0
  140. package/dist/chunk-KQTHJ22B.js +82 -0
  141. package/dist/chunk-KQTHJ22B.js.map +1 -0
  142. package/dist/chunk-KRC43RZR.js +77 -0
  143. package/dist/chunk-KRC43RZR.js.map +1 -0
  144. package/dist/chunk-LJQOEGQ2.js +116 -0
  145. package/dist/chunk-LJQOEGQ2.js.map +1 -0
  146. package/dist/chunk-LKRNUSKZ.js +149 -0
  147. package/dist/chunk-LKRNUSKZ.js.map +1 -0
  148. package/dist/chunk-LLL7QQ52.js +76 -0
  149. package/dist/chunk-LLL7QQ52.js.map +1 -0
  150. package/dist/chunk-LQ4B5X4Y.js +56 -0
  151. package/dist/chunk-LQ4B5X4Y.js.map +1 -0
  152. package/dist/chunk-M3FSLEHQ.js +76 -0
  153. package/dist/chunk-M3FSLEHQ.js.map +1 -0
  154. package/dist/chunk-M5G3O6H6.js +57 -0
  155. package/dist/chunk-M5G3O6H6.js.map +1 -0
  156. package/dist/chunk-M6JIC5PU.js +81 -0
  157. package/dist/chunk-M6JIC5PU.js.map +1 -0
  158. package/dist/chunk-N2HJ3SLS.js +186 -0
  159. package/dist/chunk-N2HJ3SLS.js.map +1 -0
  160. package/dist/chunk-NGZWBFTP.js +45 -0
  161. package/dist/chunk-NGZWBFTP.js.map +1 -0
  162. package/dist/chunk-OAKCXT35.js +34 -0
  163. package/dist/chunk-OAKCXT35.js.map +1 -0
  164. package/dist/chunk-OSD3U3HT.js +54 -0
  165. package/dist/chunk-OSD3U3HT.js.map +1 -0
  166. package/dist/chunk-OUXESQ2R.js +42 -0
  167. package/dist/chunk-OUXESQ2R.js.map +1 -0
  168. package/dist/chunk-OY2LJHMJ.js +43 -0
  169. package/dist/chunk-OY2LJHMJ.js.map +1 -0
  170. package/dist/chunk-OYEZR4CN.js +221 -0
  171. package/dist/chunk-OYEZR4CN.js.map +1 -0
  172. package/dist/chunk-P57HUMAE.js +66 -0
  173. package/dist/chunk-P57HUMAE.js.map +1 -0
  174. package/dist/chunk-P6Y2PI6L.js +82 -0
  175. package/dist/chunk-P6Y2PI6L.js.map +1 -0
  176. package/dist/chunk-PA7TDXUQ.js +51 -0
  177. package/dist/chunk-PA7TDXUQ.js.map +1 -0
  178. package/dist/chunk-PPBGGNPV.js +112 -0
  179. package/dist/chunk-PPBGGNPV.js.map +1 -0
  180. package/dist/chunk-PRH4HKND.js +48 -0
  181. package/dist/chunk-PRH4HKND.js.map +1 -0
  182. package/dist/chunk-PSPAZJUQ.js +32 -0
  183. package/dist/chunk-PSPAZJUQ.js.map +1 -0
  184. package/dist/chunk-Q5G5CGZ2.js +170 -0
  185. package/dist/chunk-Q5G5CGZ2.js.map +1 -0
  186. package/dist/chunk-QDAF3LP7.js +89 -0
  187. package/dist/chunk-QDAF3LP7.js.map +1 -0
  188. package/dist/chunk-QGVIGNJ3.js +37 -0
  189. package/dist/chunk-QGVIGNJ3.js.map +1 -0
  190. package/dist/chunk-QNUITYSY.js +68 -0
  191. package/dist/chunk-QNUITYSY.js.map +1 -0
  192. package/dist/chunk-QSWVN3RT.js +116 -0
  193. package/dist/chunk-QSWVN3RT.js.map +1 -0
  194. package/dist/chunk-QTLQZ7OJ.js +110 -0
  195. package/dist/chunk-QTLQZ7OJ.js.map +1 -0
  196. package/dist/chunk-QYAMLIG2.js +84 -0
  197. package/dist/chunk-QYAMLIG2.js.map +1 -0
  198. package/dist/chunk-REILH4XF.js +128 -0
  199. package/dist/chunk-REILH4XF.js.map +1 -0
  200. package/dist/chunk-S6SSK6QX.js +80 -0
  201. package/dist/chunk-S6SSK6QX.js.map +1 -0
  202. package/dist/chunk-SA7ED3PN.js +68 -0
  203. package/dist/chunk-SA7ED3PN.js.map +1 -0
  204. package/dist/chunk-SIJOEM4N.js +55 -0
  205. package/dist/chunk-SIJOEM4N.js.map +1 -0
  206. package/dist/chunk-SLOKAAH2.js +70 -0
  207. package/dist/chunk-SLOKAAH2.js.map +1 -0
  208. package/dist/chunk-TR6NPSMX.js +85 -0
  209. package/dist/chunk-TR6NPSMX.js.map +1 -0
  210. package/dist/chunk-TSZ5DEAT.js +106 -0
  211. package/dist/chunk-TSZ5DEAT.js.map +1 -0
  212. package/dist/chunk-TUNVF45W.js +127 -0
  213. package/dist/chunk-TUNVF45W.js.map +1 -0
  214. package/dist/chunk-TXOBNSQ5.js +63 -0
  215. package/dist/chunk-TXOBNSQ5.js.map +1 -0
  216. package/dist/chunk-U44DRLMM.js +88 -0
  217. package/dist/chunk-U44DRLMM.js.map +1 -0
  218. package/dist/chunk-U4THNRV5.js +114 -0
  219. package/dist/chunk-U4THNRV5.js.map +1 -0
  220. package/dist/chunk-UAZOFC4W.js +72 -0
  221. package/dist/chunk-UAZOFC4W.js.map +1 -0
  222. package/dist/chunk-UGKI466V.js +12 -0
  223. package/dist/chunk-UGKI466V.js.map +1 -0
  224. package/dist/chunk-VM4RMQQN.js +11 -0
  225. package/dist/chunk-VM4RMQQN.js.map +1 -0
  226. package/dist/chunk-VQ37VLAS.js +54 -0
  227. package/dist/chunk-VQ37VLAS.js.map +1 -0
  228. package/dist/chunk-VT7VSYH5.js +73 -0
  229. package/dist/chunk-VT7VSYH5.js.map +1 -0
  230. package/dist/chunk-VTIRUCLZ.js +57 -0
  231. package/dist/chunk-VTIRUCLZ.js.map +1 -0
  232. package/dist/chunk-VVBAEYKI.js +202 -0
  233. package/dist/chunk-VVBAEYKI.js.map +1 -0
  234. package/dist/chunk-WHFIQUCC.js +120 -0
  235. package/dist/chunk-WHFIQUCC.js.map +1 -0
  236. package/dist/chunk-WPSESV5Z.js +74 -0
  237. package/dist/chunk-WPSESV5Z.js.map +1 -0
  238. package/dist/chunk-WXEXCHEN.js +51 -0
  239. package/dist/chunk-WXEXCHEN.js.map +1 -0
  240. package/dist/chunk-X2DDPD3D.js +113 -0
  241. package/dist/chunk-X2DDPD3D.js.map +1 -0
  242. package/dist/chunk-X7VIMKLD.js +127 -0
  243. package/dist/chunk-X7VIMKLD.js.map +1 -0
  244. package/dist/chunk-XJ3EG6XY.js +30 -0
  245. package/dist/chunk-XJ3EG6XY.js.map +1 -0
  246. package/dist/chunk-XOT5HWSF.js +23 -0
  247. package/dist/chunk-XOT5HWSF.js.map +1 -0
  248. package/dist/chunk-Y72IP43U.js +117 -0
  249. package/dist/chunk-Y72IP43U.js.map +1 -0
  250. package/dist/chunk-YD6FLXBV.js +61 -0
  251. package/dist/chunk-YD6FLXBV.js.map +1 -0
  252. package/dist/chunk-YEQQGYYO.js +1022 -0
  253. package/dist/chunk-YEQQGYYO.js.map +1 -0
  254. package/dist/chunk-YYW6AEIT.js +46 -0
  255. package/dist/chunk-YYW6AEIT.js.map +1 -0
  256. package/dist/chunk-ZEVGXKRU.js +104 -0
  257. package/dist/chunk-ZEVGXKRU.js.map +1 -0
  258. package/dist/chunk-ZKSMMLDP.js +74 -0
  259. package/dist/chunk-ZKSMMLDP.js.map +1 -0
  260. package/dist/chunk-ZU6IM6PK.js +101 -0
  261. package/dist/chunk-ZU6IM6PK.js.map +1 -0
  262. package/dist/chunk-ZUS5KZGO.js +714 -0
  263. package/dist/chunk-ZUS5KZGO.js.map +1 -0
  264. package/dist/chunk-ZVS2GOT2.js +58 -0
  265. package/dist/chunk-ZVS2GOT2.js.map +1 -0
  266. package/dist/chunk-ZXPDS6DH.js +3 -0
  267. package/dist/chunk-ZXPDS6DH.js.map +1 -0
  268. package/dist/chunk-ZZQQJX5Z.js +173 -0
  269. package/dist/chunk-ZZQQJX5Z.js.map +1 -0
  270. package/dist/components.css +2 -0
  271. package/dist/composites/account-menu/index.js +6 -0
  272. package/dist/composites/account-menu/index.js.map +1 -0
  273. package/dist/composites/agent-composer/index.js +7 -0
  274. package/dist/composites/agent-composer/index.js.map +1 -0
  275. package/dist/composites/agent-editor/index.js +10 -0
  276. package/dist/composites/agent-editor/index.js.map +1 -0
  277. package/dist/composites/agent-stream/index.js +12 -0
  278. package/dist/composites/agent-stream/index.js.map +1 -0
  279. package/dist/composites/agent-timeline/index.js +5 -0
  280. package/dist/composites/agent-timeline/index.js.map +1 -0
  281. package/dist/composites/approval-card/index.js +5 -0
  282. package/dist/composites/approval-card/index.js.map +1 -0
  283. package/dist/composites/chat-composer/index.js +6 -0
  284. package/dist/composites/chat-composer/index.js.map +1 -0
  285. package/dist/composites/chat-message/index.js +6 -0
  286. package/dist/composites/chat-message/index.js.map +1 -0
  287. package/dist/composites/code-block/index.js +5 -0
  288. package/dist/composites/code-block/index.js.map +1 -0
  289. package/dist/composites/command-palette/index.js +5 -0
  290. package/dist/composites/command-palette/index.js.map +1 -0
  291. package/dist/composites/confirm-dialog/index.js +7 -0
  292. package/dist/composites/confirm-dialog/index.js.map +1 -0
  293. package/dist/composites/cron-jobs-list/index.js +5 -0
  294. package/dist/composites/cron-jobs-list/index.js.map +1 -0
  295. package/dist/composites/data-table/index.js +10 -0
  296. package/dist/composites/data-table/index.js.map +1 -0
  297. package/dist/composites/deployment-row/index.js +5 -0
  298. package/dist/composites/deployment-row/index.js.map +1 -0
  299. package/dist/composites/domain-config/index.js +7 -0
  300. package/dist/composites/domain-config/index.js.map +1 -0
  301. package/dist/composites/env-var-editor/index.js +7 -0
  302. package/dist/composites/env-var-editor/index.js.map +1 -0
  303. package/dist/composites/mcp-server-list/index.js +5 -0
  304. package/dist/composites/mcp-server-list/index.js.map +1 -0
  305. package/dist/composites/page-shell/index.js +7 -0
  306. package/dist/composites/page-shell/index.js.map +1 -0
  307. package/dist/composites/permission-modal/index.js +6 -0
  308. package/dist/composites/permission-modal/index.js.map +1 -0
  309. package/dist/composites/preview-env-card/index.js +6 -0
  310. package/dist/composites/preview-env-card/index.js.map +1 -0
  311. package/dist/composites/preview-panel/index.js +5 -0
  312. package/dist/composites/preview-panel/index.js.map +1 -0
  313. package/dist/composites/project-card/index.js +6 -0
  314. package/dist/composites/project-card/index.js.map +1 -0
  315. package/dist/composites/rollback-ui/index.js +6 -0
  316. package/dist/composites/rollback-ui/index.js.map +1 -0
  317. package/dist/composites/rule-editor/index.js +11 -0
  318. package/dist/composites/rule-editor/index.js.map +1 -0
  319. package/dist/composites/skill-editor/index.js +11 -0
  320. package/dist/composites/skill-editor/index.js.map +1 -0
  321. package/dist/composites/skills-list/index.js +5 -0
  322. package/dist/composites/skills-list/index.js.map +1 -0
  323. package/dist/composites/stability-bundle-viewer/index.js +4 -0
  324. package/dist/composites/stability-bundle-viewer/index.js.map +1 -0
  325. package/dist/composites/task-header/index.js +5 -0
  326. package/dist/composites/task-header/index.js.map +1 -0
  327. package/dist/composites/usage-meter/index.js +5 -0
  328. package/dist/composites/usage-meter/index.js.map +1 -0
  329. package/dist/fonts/LICENSE-GEIST.txt +92 -0
  330. package/dist/fonts/geist-400.woff2 +0 -0
  331. package/dist/fonts/geist-500.woff2 +0 -0
  332. package/dist/fonts/geist-600.woff2 +0 -0
  333. package/dist/fonts/geist-mono-400.woff2 +0 -0
  334. package/dist/fonts/geist-mono-500.woff2 +0 -0
  335. package/dist/fonts/geist-mono-600.woff2 +0 -0
  336. package/dist/fonts-cdn.css +28 -0
  337. package/dist/fonts.css +75 -0
  338. package/dist/index.d.ts +4621 -0
  339. package/dist/index.js +1338 -0
  340. package/dist/index.js.map +1 -0
  341. package/dist/plugin-D5xmXqYb.d.ts +172 -0
  342. package/dist/preset-v3-legacy.d.ts +35 -0
  343. package/dist/preset-v3-legacy.js +159 -0
  344. package/dist/preset-v3-legacy.js.map +1 -0
  345. package/dist/preset.css +27 -0
  346. package/dist/primitives/action-bar/index.js +4 -0
  347. package/dist/primitives/action-bar/index.js.map +1 -0
  348. package/dist/primitives/agent-error-card/index.js +5 -0
  349. package/dist/primitives/agent-error-card/index.js.map +1 -0
  350. package/dist/primitives/agent-event/index.js +4 -0
  351. package/dist/primitives/agent-event/index.js.map +1 -0
  352. package/dist/primitives/agent-handoff/index.js +4 -0
  353. package/dist/primitives/agent-handoff/index.js.map +1 -0
  354. package/dist/primitives/agent-profile/index.js +4 -0
  355. package/dist/primitives/agent-profile/index.js.map +1 -0
  356. package/dist/primitives/agent-starting-state/index.js +5 -0
  357. package/dist/primitives/agent-starting-state/index.js.map +1 -0
  358. package/dist/primitives/agent-streaming/index.js +5 -0
  359. package/dist/primitives/agent-streaming/index.js.map +1 -0
  360. package/dist/primitives/alert/index.js +4 -0
  361. package/dist/primitives/alert/index.js.map +1 -0
  362. package/dist/primitives/artifact-preview/index.js +4 -0
  363. package/dist/primitives/artifact-preview/index.js.map +1 -0
  364. package/dist/primitives/attachment-chip/index.js +4 -0
  365. package/dist/primitives/attachment-chip/index.js.map +1 -0
  366. package/dist/primitives/audit-log-entry/index.js +4 -0
  367. package/dist/primitives/audit-log-entry/index.js.map +1 -0
  368. package/dist/primitives/auto-compact-notice/index.js +5 -0
  369. package/dist/primitives/auto-compact-notice/index.js.map +1 -0
  370. package/dist/primitives/avatar/index.js +4 -0
  371. package/dist/primitives/avatar/index.js.map +1 -0
  372. package/dist/primitives/badge/index.js +4 -0
  373. package/dist/primitives/badge/index.js.map +1 -0
  374. package/dist/primitives/branch-indicator/index.js +4 -0
  375. package/dist/primitives/branch-indicator/index.js.map +1 -0
  376. package/dist/primitives/browser-controls/index.js +4 -0
  377. package/dist/primitives/browser-controls/index.js.map +1 -0
  378. package/dist/primitives/build-log-stream/index.js +5 -0
  379. package/dist/primitives/build-log-stream/index.js.map +1 -0
  380. package/dist/primitives/button/index.js +4 -0
  381. package/dist/primitives/button/index.js.map +1 -0
  382. package/dist/primitives/capability-indicator/index.js +4 -0
  383. package/dist/primitives/capability-indicator/index.js.map +1 -0
  384. package/dist/primitives/card/index.js +4 -0
  385. package/dist/primitives/card/index.js.map +1 -0
  386. package/dist/primitives/channel-card/index.js +4 -0
  387. package/dist/primitives/channel-card/index.js.map +1 -0
  388. package/dist/primitives/chat-thread/index.js +5 -0
  389. package/dist/primitives/chat-thread/index.js.map +1 -0
  390. package/dist/primitives/checkbox/index.js +4 -0
  391. package/dist/primitives/checkbox/index.js.map +1 -0
  392. package/dist/primitives/context-card/index.js +4 -0
  393. package/dist/primitives/context-card/index.js.map +1 -0
  394. package/dist/primitives/context-window-bar/index.js +4 -0
  395. package/dist/primitives/context-window-bar/index.js.map +1 -0
  396. package/dist/primitives/copy-button/index.js +4 -0
  397. package/dist/primitives/copy-button/index.js.map +1 -0
  398. package/dist/primitives/cost-meter/index.js +4 -0
  399. package/dist/primitives/cost-meter/index.js.map +1 -0
  400. package/dist/primitives/created-files-card/index.js +4 -0
  401. package/dist/primitives/created-files-card/index.js.map +1 -0
  402. package/dist/primitives/cron-job-card/index.js +4 -0
  403. package/dist/primitives/cron-job-card/index.js.map +1 -0
  404. package/dist/primitives/danger-zone/index.js +4 -0
  405. package/dist/primitives/danger-zone/index.js.map +1 -0
  406. package/dist/primitives/dialog/index.js +4 -0
  407. package/dist/primitives/dialog/index.js.map +1 -0
  408. package/dist/primitives/diff-viewer/index.js +4 -0
  409. package/dist/primitives/diff-viewer/index.js.map +1 -0
  410. package/dist/primitives/dropdown-menu/index.js +4 -0
  411. package/dist/primitives/dropdown-menu/index.js.map +1 -0
  412. package/dist/primitives/empty-state/index.js +4 -0
  413. package/dist/primitives/empty-state/index.js.map +1 -0
  414. package/dist/primitives/export-chat-dialog/index.js +4 -0
  415. package/dist/primitives/export-chat-dialog/index.js.map +1 -0
  416. package/dist/primitives/folder-context-card/index.js +4 -0
  417. package/dist/primitives/folder-context-card/index.js.map +1 -0
  418. package/dist/primitives/folder-selector/index.js +4 -0
  419. package/dist/primitives/folder-selector/index.js.map +1 -0
  420. package/dist/primitives/form-field/index.js +4 -0
  421. package/dist/primitives/form-field/index.js.map +1 -0
  422. package/dist/primitives/gateway-status-indicator/index.js +4 -0
  423. package/dist/primitives/gateway-status-indicator/index.js.map +1 -0
  424. package/dist/primitives/hook-config/index.js +4 -0
  425. package/dist/primitives/hook-config/index.js.map +1 -0
  426. package/dist/primitives/hook-event-log/index.js +4 -0
  427. package/dist/primitives/hook-event-log/index.js.map +1 -0
  428. package/dist/primitives/input/index.js +4 -0
  429. package/dist/primitives/input/index.js.map +1 -0
  430. package/dist/primitives/intent-selector/index.js +4 -0
  431. package/dist/primitives/intent-selector/index.js.map +1 -0
  432. package/dist/primitives/label/index.js +4 -0
  433. package/dist/primitives/label/index.js.map +1 -0
  434. package/dist/primitives/lane-board/index.js +4 -0
  435. package/dist/primitives/lane-board/index.js.map +1 -0
  436. package/dist/primitives/login-split/index.js +4 -0
  437. package/dist/primitives/login-split/index.js.map +1 -0
  438. package/dist/primitives/mcp-server-card/index.js +4 -0
  439. package/dist/primitives/mcp-server-card/index.js.map +1 -0
  440. package/dist/primitives/memory-editor/index.js +4 -0
  441. package/dist/primitives/memory-editor/index.js.map +1 -0
  442. package/dist/primitives/mention-menu/index.js +4 -0
  443. package/dist/primitives/mention-menu/index.js.map +1 -0
  444. package/dist/primitives/metrics-panel/index.js +4 -0
  445. package/dist/primitives/metrics-panel/index.js.map +1 -0
  446. package/dist/primitives/model-card/index.js +4 -0
  447. package/dist/primitives/model-card/index.js.map +1 -0
  448. package/dist/primitives/model-selector/index.js +4 -0
  449. package/dist/primitives/model-selector/index.js.map +1 -0
  450. package/dist/primitives/pagination/index.js +4 -0
  451. package/dist/primitives/pagination/index.js.map +1 -0
  452. package/dist/primitives/permission-matrix/index.js +4 -0
  453. package/dist/primitives/permission-matrix/index.js.map +1 -0
  454. package/dist/primitives/pin-input/index.js +4 -0
  455. package/dist/primitives/pin-input/index.js.map +1 -0
  456. package/dist/primitives/plan-badge/index.js +4 -0
  457. package/dist/primitives/plan-badge/index.js.map +1 -0
  458. package/dist/primitives/progress/index.js +4 -0
  459. package/dist/primitives/progress/index.js.map +1 -0
  460. package/dist/primitives/progress-checklist/index.js +4 -0
  461. package/dist/primitives/progress-checklist/index.js.map +1 -0
  462. package/dist/primitives/project-switcher/index.js +4 -0
  463. package/dist/primitives/project-switcher/index.js.map +1 -0
  464. package/dist/primitives/quick-action-chips/index.js +4 -0
  465. package/dist/primitives/quick-action-chips/index.js.map +1 -0
  466. package/dist/primitives/radio-group/index.js +4 -0
  467. package/dist/primitives/radio-group/index.js.map +1 -0
  468. package/dist/primitives/recent-folders-list/index.js +4 -0
  469. package/dist/primitives/recent-folders-list/index.js.map +1 -0
  470. package/dist/primitives/rule-card/index.js +4 -0
  471. package/dist/primitives/rule-card/index.js.map +1 -0
  472. package/dist/primitives/run-stats/index.js +4 -0
  473. package/dist/primitives/run-stats/index.js.map +1 -0
  474. package/dist/primitives/run-status-pill/index.js +4 -0
  475. package/dist/primitives/run-status-pill/index.js.map +1 -0
  476. package/dist/primitives/running-tasks-panel/index.js +4 -0
  477. package/dist/primitives/running-tasks-panel/index.js.map +1 -0
  478. package/dist/primitives/scroll-area/index.js +4 -0
  479. package/dist/primitives/scroll-area/index.js.map +1 -0
  480. package/dist/primitives/select/index.js +4 -0
  481. package/dist/primitives/select/index.js.map +1 -0
  482. package/dist/primitives/session-list-item/index.js +4 -0
  483. package/dist/primitives/session-list-item/index.js.map +1 -0
  484. package/dist/primitives/session-timeline/index.js +4 -0
  485. package/dist/primitives/session-timeline/index.js.map +1 -0
  486. package/dist/primitives/sheet/index.js +4 -0
  487. package/dist/primitives/sheet/index.js.map +1 -0
  488. package/dist/primitives/sidebar/index.js +4 -0
  489. package/dist/primitives/sidebar/index.js.map +1 -0
  490. package/dist/primitives/skeleton/index.js +5 -0
  491. package/dist/primitives/skeleton/index.js.map +1 -0
  492. package/dist/primitives/skill-card/index.js +4 -0
  493. package/dist/primitives/skill-card/index.js.map +1 -0
  494. package/dist/primitives/social-auth-row/index.js +4 -0
  495. package/dist/primitives/social-auth-row/index.js.map +1 -0
  496. package/dist/primitives/stat-tile/index.js +4 -0
  497. package/dist/primitives/stat-tile/index.js.map +1 -0
  498. package/dist/primitives/status-dot/index.js +4 -0
  499. package/dist/primitives/status-dot/index.js.map +1 -0
  500. package/dist/primitives/steps-rail/index.js +4 -0
  501. package/dist/primitives/steps-rail/index.js.map +1 -0
  502. package/dist/primitives/sub-agent-dispatch/index.js +4 -0
  503. package/dist/primitives/sub-agent-dispatch/index.js.map +1 -0
  504. package/dist/primitives/switch/index.js +4 -0
  505. package/dist/primitives/switch/index.js.map +1 -0
  506. package/dist/primitives/system-prompt-editor/index.js +4 -0
  507. package/dist/primitives/system-prompt-editor/index.js.map +1 -0
  508. package/dist/primitives/table/index.js +4 -0
  509. package/dist/primitives/table/index.js.map +1 -0
  510. package/dist/primitives/tabs/index.js +4 -0
  511. package/dist/primitives/tabs/index.js.map +1 -0
  512. package/dist/primitives/task-plan/index.js +4 -0
  513. package/dist/primitives/task-plan/index.js.map +1 -0
  514. package/dist/primitives/terminal-panel/index.js +5 -0
  515. package/dist/primitives/terminal-panel/index.js.map +1 -0
  516. package/dist/primitives/textarea/index.js +4 -0
  517. package/dist/primitives/textarea/index.js.map +1 -0
  518. package/dist/primitives/thinking-level-selector/index.js +4 -0
  519. package/dist/primitives/thinking-level-selector/index.js.map +1 -0
  520. package/dist/primitives/timestamp/index.js +4 -0
  521. package/dist/primitives/timestamp/index.js.map +1 -0
  522. package/dist/primitives/toast/index.js +4 -0
  523. package/dist/primitives/toast/index.js.map +1 -0
  524. package/dist/primitives/token-usage-chart/index.js +4 -0
  525. package/dist/primitives/token-usage-chart/index.js.map +1 -0
  526. package/dist/primitives/tool-call/index.js +4 -0
  527. package/dist/primitives/tool-call/index.js.map +1 -0
  528. package/dist/primitives/tool-call-card/index.js +4 -0
  529. package/dist/primitives/tool-call-card/index.js.map +1 -0
  530. package/dist/primitives/tool-result/index.js +4 -0
  531. package/dist/primitives/tool-result/index.js.map +1 -0
  532. package/dist/primitives/tools-list/index.js +4 -0
  533. package/dist/primitives/tools-list/index.js.map +1 -0
  534. package/dist/primitives/tooltip/index.js +4 -0
  535. package/dist/primitives/tooltip/index.js.map +1 -0
  536. package/dist/primitives/topnav/index.js +4 -0
  537. package/dist/primitives/topnav/index.js.map +1 -0
  538. package/dist/primitives/update-banner/index.js +4 -0
  539. package/dist/primitives/update-banner/index.js.map +1 -0
  540. package/dist/slide/index.d.ts +212 -0
  541. package/dist/slide/index.js +3 -0
  542. package/dist/slide/index.js.map +1 -0
  543. package/dist/slide/plugins/emoji/index.d.ts +29 -0
  544. package/dist/slide/plugins/emoji/index.js +157 -0
  545. package/dist/slide/plugins/emoji/index.js.map +1 -0
  546. package/dist/slide/plugins/math/index.d.ts +13 -0
  547. package/dist/slide/plugins/math/index.js +145 -0
  548. package/dist/slide/plugins/math/index.js.map +1 -0
  549. package/dist/slide/plugins/mermaid/index.d.ts +55 -0
  550. package/dist/slide/plugins/mermaid/index.js +218 -0
  551. package/dist/slide/plugins/mermaid/index.js.map +1 -0
  552. package/dist/slide/plugins/shiki/index.d.ts +18 -0
  553. package/dist/slide/plugins/shiki/index.js +87 -0
  554. package/dist/slide/plugins/shiki/index.js.map +1 -0
  555. package/dist/slide/themes/default.css +256 -0
  556. package/dist/slide/themes/layouts.css +143 -0
  557. package/dist/slide/themes/violet-forge.css +256 -0
  558. package/dist/slide-deck/index.css +52 -0
  559. package/dist/slide-deck/index.css.map +1 -0
  560. package/dist/slide-deck/index.d.ts +377 -0
  561. package/dist/slide-deck/index.js +1111 -0
  562. package/dist/slide-deck/index.js.map +1 -0
  563. package/dist/styles-v3-legacy.css +88 -0
  564. package/dist/styles.css +137 -0
  565. package/dist/tokens-v4.css +187 -0
  566. package/dist/tokens.css +230 -0
  567. package/dist/vite-plugin.d.ts +29 -0
  568. package/dist/vite-plugin.js +76 -0
  569. package/dist/vite-plugin.js.map +1 -0
  570. package/dist/whiteboard/index.d.ts +258 -0
  571. package/dist/whiteboard/index.js +738 -0
  572. package/dist/whiteboard/index.js.map +1 -0
  573. package/llms.txt +273 -0
  574. package/package.json +800 -0
  575. package/registry/index.json +856 -0
  576. package/registry/r/account-menu.json +24 -0
  577. package/registry/r/action-bar.json +22 -0
  578. package/registry/r/agent-composer.json +22 -0
  579. package/registry/r/agent-editor.json +27 -0
  580. package/registry/r/agent-error-card.json +22 -0
  581. package/registry/r/agent-event.json +24 -0
  582. package/registry/r/agent-handoff.json +22 -0
  583. package/registry/r/agent-profile.json +23 -0
  584. package/registry/r/agent-starting-state.json +22 -0
  585. package/registry/r/agent-stream.json +27 -0
  586. package/registry/r/agent-streaming.json +22 -0
  587. package/registry/r/agent-timeline.json +22 -0
  588. package/registry/r/agent-types.json +15 -0
  589. package/registry/r/alert.json +22 -0
  590. package/registry/r/approval-card.json +25 -0
  591. package/registry/r/artifact-preview.json +22 -0
  592. package/registry/r/attachment-chip.json +24 -0
  593. package/registry/r/audit-log-entry.json +23 -0
  594. package/registry/r/auto-compact-notice.json +22 -0
  595. package/registry/r/avatar.json +23 -0
  596. package/registry/r/badge.json +22 -0
  597. package/registry/r/browser-controls.json +22 -0
  598. package/registry/r/build-log-stream.json +19 -0
  599. package/registry/r/button.json +23 -0
  600. package/registry/r/capability-indicator.json +23 -0
  601. package/registry/r/card.json +22 -0
  602. package/registry/r/chat-composer.json +23 -0
  603. package/registry/r/chat-message.json +129 -0
  604. package/registry/r/chat-thread.json +20 -0
  605. package/registry/r/chat-types.json +15 -0
  606. package/registry/r/checkbox.json +24 -0
  607. package/registry/r/cn.json +19 -0
  608. package/registry/r/code-block.json +21 -0
  609. package/registry/r/command-palette.json +25 -0
  610. package/registry/r/confirm-dialog.json +25 -0
  611. package/registry/r/context-card.json +23 -0
  612. package/registry/r/context-window-bar.json +20 -0
  613. package/registry/r/copy-button.json +22 -0
  614. package/registry/r/cost-meter.json +22 -0
  615. package/registry/r/created-files-card.json +23 -0
  616. package/registry/r/cron-job-card.json +22 -0
  617. package/registry/r/cron-jobs-list.json +23 -0
  618. package/registry/r/danger-zone.json +20 -0
  619. package/registry/r/data-table.json +27 -0
  620. package/registry/r/deployment-row.json +23 -0
  621. package/registry/r/dialog.json +23 -0
  622. package/registry/r/diff-viewer.json +20 -0
  623. package/registry/r/domain-config.json +25 -0
  624. package/registry/r/dropdown-menu.json +23 -0
  625. package/registry/r/empty-state.json +20 -0
  626. package/registry/r/env-var-editor.json +25 -0
  627. package/registry/r/folder-context-card.json +23 -0
  628. package/registry/r/folder-selector.json +22 -0
  629. package/registry/r/form-field.json +23 -0
  630. package/registry/r/hook-config.json +22 -0
  631. package/registry/r/hook-event-log.json +22 -0
  632. package/registry/r/input.json +22 -0
  633. package/registry/r/intent-selector.json +24 -0
  634. package/registry/r/label.json +22 -0
  635. package/registry/r/lane-board.json +20 -0
  636. package/registry/r/live-region-context.json +16 -0
  637. package/registry/r/login-split.json +20 -0
  638. package/registry/r/mcp-server-card.json +22 -0
  639. package/registry/r/mcp-server-list.json +23 -0
  640. package/registry/r/memory-editor.json +23 -0
  641. package/registry/r/mention-menu.json +23 -0
  642. package/registry/r/metrics-panel.json +22 -0
  643. package/registry/r/mode-types.json +15 -0
  644. package/registry/r/model-card.json +23 -0
  645. package/registry/r/model-selector.json +23 -0
  646. package/registry/r/page-shell.json +25 -0
  647. package/registry/r/pagination.json +22 -0
  648. package/registry/r/permission-matrix.json +22 -0
  649. package/registry/r/permission-modal.json +24 -0
  650. package/registry/r/permission-types.json +15 -0
  651. package/registry/r/pin-input.json +20 -0
  652. package/registry/r/plan-badge.json +20 -0
  653. package/registry/r/preview-env-card.json +25 -0
  654. package/registry/r/preview-panel.json +21 -0
  655. package/registry/r/progress-checklist.json +23 -0
  656. package/registry/r/progress.json +20 -0
  657. package/registry/r/project-card.json +25 -0
  658. package/registry/r/project-switcher.json +22 -0
  659. package/registry/r/quick-action-chips.json +21 -0
  660. package/registry/r/radio-group.json +23 -0
  661. package/registry/r/recent-folders-list.json +22 -0
  662. package/registry/r/rollback-ui.json +24 -0
  663. package/registry/r/rule-card.json +23 -0
  664. package/registry/r/rule-editor.json +28 -0
  665. package/registry/r/rule-types.json +18 -0
  666. package/registry/r/run-stats.json +22 -0
  667. package/registry/r/running-tasks-panel.json +22 -0
  668. package/registry/r/safe-href.json +16 -0
  669. package/registry/r/scroll-area.json +22 -0
  670. package/registry/r/select.json +24 -0
  671. package/registry/r/session-list-item.json +20 -0
  672. package/registry/r/session-timeline.json +22 -0
  673. package/registry/r/sheet.json +24 -0
  674. package/registry/r/sidebar.json +19 -0
  675. package/registry/r/skeleton.json +19 -0
  676. package/registry/r/skill-card.json +24 -0
  677. package/registry/r/skill-editor.json +28 -0
  678. package/registry/r/skills-list.json +23 -0
  679. package/registry/r/slide-deck.json +130 -0
  680. package/registry/r/slide-plugin-emoji.json +28 -0
  681. package/registry/r/slide-plugin-math.json +24 -0
  682. package/registry/r/slide-plugin-mermaid.json +23 -0
  683. package/registry/r/slide-plugin-shiki.json +23 -0
  684. package/registry/r/slide.json +123 -0
  685. package/registry/r/social-auth-row.json +21 -0
  686. package/registry/r/stat-tile.json +22 -0
  687. package/registry/r/status-dot.json +20 -0
  688. package/registry/r/steps-rail.json +20 -0
  689. package/registry/r/sub-agent-dispatch.json +22 -0
  690. package/registry/r/switch.json +23 -0
  691. package/registry/r/system-prompt-editor.json +22 -0
  692. package/registry/r/table.json +22 -0
  693. package/registry/r/tabs.json +22 -0
  694. package/registry/r/tailwind-preset.json +19 -0
  695. package/registry/r/task-header.json +24 -0
  696. package/registry/r/task-plan.json +22 -0
  697. package/registry/r/task-types.json +15 -0
  698. package/registry/r/terminal-panel.json +22 -0
  699. package/registry/r/textarea.json +22 -0
  700. package/registry/r/theme-provider.json +59 -0
  701. package/registry/r/theme-script.json +18 -0
  702. package/registry/r/theo-ui-provider.json +20 -0
  703. package/registry/r/timestamp.json +20 -0
  704. package/registry/r/toast.json +30 -0
  705. package/registry/r/token-usage-chart.json +20 -0
  706. package/registry/r/tokens.json +21 -0
  707. package/registry/r/tool-call-card.json +23 -0
  708. package/registry/r/tool-call.json +22 -0
  709. package/registry/r/tool-result.json +20 -0
  710. package/registry/r/tools-list.json +23 -0
  711. package/registry/r/tooltip.json +22 -0
  712. package/registry/r/topnav.json +22 -0
  713. package/registry/r/types.json +15 -0
  714. package/registry/r/usage-meter.json +21 -0
  715. package/registry/r/whiteboard.json +101 -0
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "audit-log-entry",
4
+ "type": "registry:ui",
5
+ "title": "AuditLogEntry",
6
+ "description": "One row in the agent audit log.",
7
+ "dependencies": [
8
+ "lucide-react"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
12
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json",
13
+ "https://usetheodev.github.io/theo-ui/r/types.json"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "components/primitives/audit-log-entry/audit-log-entry.tsx",
18
+ "type": "registry:ui",
19
+ "target": "components/ui/audit-log-entry.tsx",
20
+ "content": "import { Bot, ShieldAlert, User } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport type { IconComponent } from \"@/lib/types\";\n\nexport type AuditActorKind = \"user\" | \"agent\" | \"system\";\n\nexport type AuditSeverity = \"info\" | \"warning\" | \"error\";\n\nexport interface AuditEntry {\n id: string;\n /** Who triggered the action. */\n actor: { kind: AuditActorKind; name: string };\n /** Verb / action label, e.g. \"wrote file\", \"ran command\". */\n action: string;\n /** Target of the action (file path, command, etc). */\n target?: ReactNode;\n /** ISO timestamp / friendly label. */\n timestamp: string;\n severity?: AuditSeverity;\n /** Optional detail block (multi-line). */\n detail?: ReactNode;\n}\n\ninterface AuditLogEntryProps extends HTMLAttributes<HTMLElement> {\n entry: AuditEntry;\n}\n\nconst ACTOR_ICON: Record<AuditActorKind, IconComponent> = {\n user: User,\n agent: Bot,\n system: ShieldAlert,\n};\n\nconst SEVERITY_CLASS: Record<AuditSeverity, string> = {\n info: \"text-muted-foreground\",\n warning: \"text-warning\",\n error: \"text-destructive\",\n};\n\n/**\n * AuditLogEntry — one row in the agent audit log. Tells the user exactly\n * who did what and when. Severity colors the timestamp and target.\n */\nconst AuditLogEntry = forwardRef<HTMLElement, AuditLogEntryProps>(\n ({ className, entry, ...props }, ref) => {\n const Icon = ACTOR_ICON[entry.actor.kind];\n const sev = entry.severity ?? \"info\";\n return (\n <article\n ref={ref}\n className={cn(\n \"grid grid-cols-[auto_1fr_auto] items-start gap-3 border-border/30 border-b px-3 py-2\",\n \"last:border-b-0\",\n className,\n )}\n {...props}\n >\n <span\n className={cn(\n \"mt-0.5 grid size-7 place-items-center rounded-md bg-muted text-muted-foreground\",\n sev === \"warning\" && \"text-warning\",\n sev === \"error\" && \"text-destructive\",\n )}\n aria-hidden=\"true\"\n >\n <Icon className=\"size-3.5\" />\n </span>\n <div className=\"min-w-0\">\n <p className=\"flex flex-wrap items-baseline gap-2 text-body-sm\">\n <span className=\"font-medium font-mono text-code-sm text-foreground\">\n {entry.actor.name}\n </span>\n <span className={cn(\"font-mono text-code-sm\", SEVERITY_CLASS[sev])}>\n {entry.action}\n </span>\n {entry.target ? (\n <span className=\"truncate font-mono text-code-sm text-foreground/80\">\n {entry.target}\n </span>\n ) : null}\n </p>\n {entry.detail ? (\n <div className=\"mt-1 rounded-md bg-muted/40 px-2.5 py-1.5 font-mono text-code-sm text-muted-foreground\">\n {entry.detail}\n </div>\n ) : null}\n </div>\n <span className=\"shrink-0 font-mono text-label text-muted-foreground tabular-nums\">\n {entry.timestamp}\n </span>\n </article>\n );\n },\n);\nAuditLogEntry.displayName = \"AuditLogEntry\";\n\nexport { AuditLogEntry };\n"
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "auto-compact-notice",
4
+ "type": "registry:ui",
5
+ "title": "AutoCompactNotice",
6
+ "description": "Inline banner warning the user that the agent is",
7
+ "dependencies": [
8
+ "lucide-react"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
12
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "components/primitives/auto-compact-notice/auto-compact-notice.tsx",
17
+ "type": "registry:ui",
18
+ "target": "components/ui/auto-compact-notice.tsx",
19
+ "content": "import { Sparkles, X } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { useInLiveRegion } from \"@/lib/live-region-context\";\n\ninterface AutoCompactNoticeProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Optional custom title. */\n title?: ReactNode;\n /**\n * How many turns until the next auto-compaction. Used to render an inline\n * countdown chip.\n */\n turnsRemaining?: number;\n /** Approx tokens that will be removed/summarized. */\n tokensToCompact?: number;\n onCompactNow?: () => void;\n onDismiss?: () => void;\n}\n\nconst formatTokens = (n: number) => {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;\n return `${n}`;\n};\n\n/**\n * AutoCompactNotice — inline banner warning the user that the agent is\n * about to summarize / compact older context. Lets them act early (compact\n * now) or dismiss.\n *\n * Critical for transparency: a user must not be surprised by silent context\n * loss. This component announces it before it happens.\n */\nconst AutoCompactNotice = forwardRef<HTMLElement, AutoCompactNoticeProps>(\n (\n {\n className,\n title = \"Auto-compaction soon\",\n turnsRemaining,\n tokensToCompact,\n onCompactNow,\n onDismiss,\n ...props\n },\n ref,\n ) => {\n // T4.1 (MF-4): omit aria-live when nested inside a container live region.\n const inLiveRegion = useInLiveRegion();\n return (\n <aside\n ref={ref}\n aria-live={inLiveRegion ? undefined : \"polite\"}\n className={cn(\n \"grid grid-cols-[auto_1fr_auto] items-start gap-3 rounded-lg border border-warning/40 bg-warning/10 px-4 py-3\",\n className,\n )}\n {...props}\n >\n <Sparkles className=\"mt-0.5 size-4 shrink-0 text-warning\" aria-hidden=\"true\" />\n <div className=\"grid gap-1\">\n <p className=\"flex items-baseline gap-2 font-medium text-body-sm text-foreground\">\n {title}\n {turnsRemaining !== undefined ? (\n <span className=\"inline-flex items-center rounded-full bg-warning/20 px-2 py-0.5 font-mono text-label text-warning tabular-nums\">\n {turnsRemaining} {turnsRemaining === 1 ? \"turn\" : \"turns\"} left\n </span>\n ) : null}\n </p>\n <p className=\"text-body-sm text-muted-foreground\">\n Older context will be summarized to make room.\n {tokensToCompact !== undefined ? (\n <>\n {\" \"}\n About{\" \"}\n <span className=\"font-mono tabular-nums\">\n {formatTokens(tokensToCompact)} tokens\n </span>{\" \"}\n will be replaced by a recap.\n </>\n ) : null}\n </p>\n {onCompactNow ? (\n <button\n type=\"button\"\n onClick={onCompactNow}\n className=\"mt-1 inline-flex w-fit items-center rounded-md border border-warning/40 bg-card px-2.5 py-1 font-mono text-label text-warning hover:bg-warning/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n Compact now\n </button>\n ) : null}\n </div>\n {onDismiss ? (\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"rounded-md p-1 text-warning hover:bg-warning/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <X className=\"size-3.5\" />\n </button>\n ) : null}\n </aside>\n );\n },\n);\nAutoCompactNotice.displayName = \"AutoCompactNotice\";\n\nexport { AutoCompactNotice };\n"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "avatar",
4
+ "type": "registry:ui",
5
+ "title": "Avatar",
6
+ "description": "User/team avatar with safe fallback to initials.",
7
+ "dependencies": [
8
+ "@radix-ui/react-avatar",
9
+ "class-variance-authority"
10
+ ],
11
+ "registryDependencies": [
12
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
13
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "components/primitives/avatar/avatar.tsx",
18
+ "type": "registry:ui",
19
+ "target": "components/ui/avatar.tsx",
20
+ "content": "import * as AvatarPrimitive from \"@radix-ui/react-avatar\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ElementRef } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Avatar — user/team avatar with safe fallback to initials.\n *\n * Composition:\n * <Avatar size=\"md\">\n * <Avatar.Image src=\"…\" alt=\"…\" />\n * <Avatar.Fallback>AA</Avatar.Fallback>\n * </Avatar>\n *\n * Built on Radix Avatar (handles image load failures → fallback automatically).\n * Sizes scale on the root; fallback inherits the size's text scale.\n */\n\nconst avatarVariants = cva(\n [\n \"relative inline-flex shrink-0 overflow-hidden rounded-full\",\n \"border border-border/40 bg-muted text-foreground\",\n ],\n {\n variants: {\n size: {\n xs: \"size-6 text-label\",\n sm: \"size-7 text-label\",\n md: \"size-9 text-body-sm\",\n lg: \"size-12 text-body-md\",\n xl: \"size-16 text-title-md\",\n },\n tone: {\n muted: \"bg-muted text-foreground\",\n primary: \"bg-primary text-primary-foreground\",\n accent: \"bg-accent text-accent-foreground\",\n },\n },\n defaultVariants: { size: \"md\", tone: \"muted\" },\n },\n);\n\ninterface AvatarProps\n extends ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n VariantProps<typeof avatarVariants> {}\n\nconst AvatarRoot = forwardRef<ElementRef<typeof AvatarPrimitive.Root>, AvatarProps>(\n ({ className, size, tone, ...props }, ref) => (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, tone }), className)}\n {...props}\n />\n ),\n);\nAvatarRoot.displayName = \"Avatar\";\n\nconst AvatarImage = forwardRef<\n ElementRef<typeof AvatarPrimitive.Image>,\n ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square size-full object-cover\", className)}\n {...props}\n />\n));\nAvatarImage.displayName = \"Avatar.Image\";\n\nconst AvatarFallback = forwardRef<\n ElementRef<typeof AvatarPrimitive.Fallback>,\n ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n \"flex h-full w-full items-center justify-center font-medium leading-none\",\n className,\n )}\n delayMs={300}\n {...props}\n />\n));\nAvatarFallback.displayName = \"Avatar.Fallback\";\n\nconst Avatar = /*#__PURE__*/ Object.assign(AvatarRoot, {\n Image: AvatarImage,\n Fallback: AvatarFallback,\n});\n\nexport { Avatar, avatarVariants };\n"
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "badge",
4
+ "type": "registry:ui",
5
+ "title": "Badge",
6
+ "description": "Small status / tag indicator with semantic variants (default, primary, success, warning, destructive, info).",
7
+ "dependencies": [
8
+ "class-variance-authority"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
12
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "components/primitives/badge/badge.tsx",
17
+ "type": "registry:ui",
18
+ "target": "components/ui/badge.tsx",
19
+ "content": "import { type VariantProps, cva } from \"class-variance-authority\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Badge — small status / tag indicator.\n *\n * Variants:\n * - default muted surface, hairline border\n * - primary violet outline + soft violet bg\n * - accent burnt sienna (celebration / pro / beta)\n * - success deploy succeeded\n * - warning attention needed\n * - destructive failed\n * - outline transparent, just border\n *\n * Status dots are inlined via `<Badge.Dot />` for things like \"Building…\",\n * \"Running\", \"Failed\" rows in deployment lists.\n */\nconst badgeVariants = cva(\n [\n \"inline-flex items-center gap-1.5 rounded-full border\",\n \"font-sans uppercase tracking-wider\",\n \"transition-colors\",\n ],\n {\n variants: {\n variant: {\n default: \"border-border/40 bg-muted text-muted-foreground\",\n primary: \"border-primary/30 bg-primary/10 text-primary\",\n accent: \"border-accent/40 bg-accent/15 text-accent\",\n success: \"border-success/40 bg-success/15 text-success\",\n warning: \"border-warning/40 bg-warning/15 text-warning\",\n destructive: \"border-destructive/40 bg-destructive/15 text-destructive\",\n outline: \"border-border bg-transparent text-foreground\",\n },\n size: {\n sm: \"px-2 py-0.5 text-label-caps\",\n md: \"px-2.5 py-0.5 text-label\",\n lg: \"px-3 py-1 text-body-md\",\n },\n },\n defaultVariants: { variant: \"default\", size: \"md\" },\n },\n);\n\nexport interface BadgeProps\n extends HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {}\n\nconst Badge = forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant, size, ...props }, ref) => (\n <span ref={ref} className={cn(badgeVariants({ variant, size }), className)} {...props} />\n ),\n);\nBadge.displayName = \"Badge\";\n\ninterface BadgeDotProps extends HTMLAttributes<HTMLSpanElement> {\n pulse?: boolean;\n tone?: \"primary\" | \"accent\" | \"success\" | \"warning\" | \"destructive\" | \"muted\";\n}\n\nconst toneClass: Record<NonNullable<BadgeDotProps[\"tone\"]>, string> = {\n primary: \"bg-primary\",\n accent: \"bg-accent\",\n success: \"bg-success\",\n warning: \"bg-warning\",\n destructive: \"bg-destructive\",\n muted: \"bg-muted-foreground\",\n};\n\nconst Dot = forwardRef<HTMLSpanElement, BadgeDotProps>(\n ({ className, pulse = false, tone = \"success\", ...props }, ref) => (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n \"inline-block size-1.5 rounded-full\",\n toneClass[tone],\n pulse && \"animate-pulse-glow\",\n className,\n )}\n {...props}\n />\n ),\n);\nDot.displayName = \"Badge.Dot\";\n\nconst BadgeWithDot = Badge as typeof Badge & { Dot: typeof Dot };\nBadgeWithDot.Dot = Dot;\n\nexport { BadgeWithDot as Badge, badgeVariants };\n"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "browser-controls",
4
+ "type": "registry:ui",
5
+ "title": "BrowserControls",
6
+ "description": "Back/forward/reload + URL bar.",
7
+ "dependencies": [
8
+ "lucide-react"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
12
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "components/primitives/browser-controls/browser-controls.tsx",
17
+ "type": "registry:ui",
18
+ "target": "components/ui/browser-controls.tsx",
19
+ "content": "import { ArrowLeft, ArrowRight, RotateCw } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\ninterface BrowserControlsProps extends HTMLAttributes<HTMLDivElement> {\n url: string;\n onUrlChange?: (next: string) => void;\n onBack?: () => void;\n onForward?: () => void;\n onReload?: () => void;\n /**\n * Disable URL editing (some previews are read-only).\n */\n readOnlyUrl?: boolean;\n}\n\n/**\n * BrowserControls — back/forward/reload + URL bar.\n *\n * Used as the top of PreviewPanel in the Code workspace.\n */\nconst BrowserControls = forwardRef<HTMLDivElement, BrowserControlsProps>(\n ({ className, url, onUrlChange, onBack, onForward, onReload, readOnlyUrl, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"flex items-center gap-1 border-border/40 border-b bg-card px-3 py-2\",\n className,\n )}\n {...props}\n >\n <NavBtn aria-label=\"Back\" {...(onBack ? { onClick: onBack } : {})}>\n <ArrowLeft className=\"size-3.5\" />\n </NavBtn>\n <NavBtn aria-label=\"Forward\" {...(onForward ? { onClick: onForward } : {})}>\n <ArrowRight className=\"size-3.5\" />\n </NavBtn>\n <NavBtn aria-label=\"Reload\" {...(onReload ? { onClick: onReload } : {})}>\n <RotateCw className=\"size-3.5\" />\n </NavBtn>\n <input\n type=\"url\"\n value={url}\n onChange={(e) => onUrlChange?.(e.target.value)}\n readOnly={readOnlyUrl ?? !onUrlChange}\n aria-label=\"Address\"\n className={cn(\n \"ml-2 h-7 flex-1 rounded-md border border-border/40 bg-muted/40 px-2\",\n \"font-mono text-code-sm text-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n )}\n />\n </div>\n ),\n);\nBrowserControls.displayName = \"BrowserControls\";\n\nfunction NavBtn({\n onClick,\n children,\n \"aria-label\": ariaLabel,\n}: {\n onClick?: () => void;\n children: ReactNode;\n \"aria-label\": string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel}\n disabled={!onClick}\n className={cn(\n \"rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"disabled:opacity-30 disabled:hover:bg-transparent\",\n )}\n >\n {children}\n </button>\n );\n}\n\nexport { BrowserControls };\n"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "build-log-stream",
4
+ "type": "registry:block",
5
+ "title": "BuildLogStream",
6
+ "description": "Terminal-like log viewer with timestamps + level coloring.",
7
+ "registryDependencies": [
8
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
9
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
10
+ ],
11
+ "files": [
12
+ {
13
+ "path": "components/primitives/build-log-stream/build-log-stream.tsx",
14
+ "type": "registry:block",
15
+ "target": "components/blocks/build-log-stream.tsx",
16
+ "content": "import { forwardRef, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { useInLiveRegion } from \"@/lib/live-region-context\";\n\nexport type LogLevel = \"info\" | \"warn\" | \"error\" | \"success\" | \"debug\";\n\nexport interface LogLine {\n id: string;\n timestamp: string;\n level: LogLevel;\n message: string;\n source?: string;\n}\n\nconst levelClasses: Record<LogLevel, string> = {\n info: \"text-foreground\",\n warn: \"text-warning\",\n error: \"text-destructive\",\n success: \"text-success\",\n debug: \"text-muted-foreground\",\n};\n\nconst levelLabels: Record<LogLevel, string> = {\n info: \"INFO\",\n warn: \"WARN\",\n error: \"ERROR\",\n success: \" OK \",\n debug: \"DBG \",\n};\n\ninterface BuildLogStreamProps extends HTMLAttributes<HTMLDivElement> {\n lines: LogLine[];\n /**\n * If true, shows level filter chips above the stream.\n */\n filterable?: boolean;\n /**\n * Controlled filter — which levels are visible. Empty Set = show all.\n *\n * Pick one mode: either always pass `visibleLevels` + `onVisibleLevelsChange`\n * (controlled), or never (uncontrolled). Mixing the two between renders is\n * not supported and may produce surprising state.\n */\n visibleLevels?: Set<LogLevel>;\n onVisibleLevelsChange?: (levels: Set<LogLevel>) => void;\n /**\n * Height of the scrollable region.\n */\n height?: string | number;\n /**\n * Maximum number of lines rendered. When exceeded, only the tail is shown\n * and a banner indicates truncation. Defaults to 2000 — set higher with\n * caution; React reconciliation cost scales linearly.\n */\n maxLines?: number;\n /**\n * Screen-reader live-region politeness for newly appended lines. Defaults\n * to `\"off\"` because build-log streams can be high-volume; opt into\n * `\"polite\"` only when running the build in the foreground.\n */\n live?: \"off\" | \"polite\";\n}\n\nconst ALL_LEVELS: LogLevel[] = [\"info\", \"warn\", \"error\", \"success\", \"debug\"];\n\n/**\n * BuildLogStream — terminal-like log viewer with timestamps + level coloring.\n *\n * Used in Code workspace and PaaS deployment views. Geist Mono throughout.\n * Lines fade in via animate-fade-in-up on mount; new lines (when prepended/appended)\n * are not animated to avoid feedback noise (consumer's responsibility to render\n * incrementally if needed).\n */\nconst BuildLogStream = forwardRef<HTMLDivElement, BuildLogStreamProps>(\n (\n {\n className,\n lines,\n filterable = true,\n visibleLevels,\n onVisibleLevelsChange,\n height = \"320px\",\n maxLines = 2000,\n live = \"off\",\n ...props\n },\n ref,\n ) => {\n // T4.1 (MF-4): suppress own aria-live when nested in container live region.\n const inLiveRegion = useInLiveRegion();\n const effectiveLive = inLiveRegion ? \"off\" : live;\n const [internalLevels, setInternalLevels] = useState<Set<LogLevel>>(new Set());\n const levels = visibleLevels ?? internalLevels;\n const updateLevels = onVisibleLevelsChange ?? setInternalLevels;\n\n // MEDIUM-002 / T6.5: warn (dev-only) when a consumer flips between\n // controlled and uncontrolled — React's own warning handles `value`/\n // `defaultValue` on form inputs but doesn't see our custom prop pair.\n const wasControlled = useRef<boolean | null>(null);\n useEffect(() => {\n if (typeof process === \"undefined\" || process.env.NODE_ENV === \"production\") return;\n const isControlled = visibleLevels !== undefined;\n if (wasControlled.current === null) {\n wasControlled.current = isControlled;\n return;\n }\n if (wasControlled.current !== isControlled) {\n // biome-ignore lint/suspicious/noConsole: dev-only diagnostic (MEDIUM-002)\n console.warn(\n `[@theokit/ui] BuildLogStream: \\`visibleLevels\\` prop switched between ${\n wasControlled.current ? \"controlled\" : \"uncontrolled\"\n } and ${isControlled ? \"controlled\" : \"uncontrolled\"} between renders. Pick one mode and keep it consistent.`,\n );\n wasControlled.current = isControlled;\n }\n }, [visibleLevels]);\n\n const filtered = useMemo(() => {\n if (levels.size === 0) return lines;\n return lines.filter((l) => levels.has(l.level));\n }, [lines, levels]);\n\n const truncated = filtered.length > maxLines;\n const visible = truncated ? filtered.slice(filtered.length - maxLines) : filtered;\n const hiddenCount = truncated ? filtered.length - maxLines : 0;\n\n const toggle = (level: LogLevel) => {\n const next = new Set(levels);\n if (next.has(level)) next.delete(level);\n else next.add(level);\n updateLevels(next);\n };\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-2\", className)} {...props}>\n {filterable ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {ALL_LEVELS.map((level) => {\n const active = levels.size === 0 || levels.has(level);\n return (\n <button\n key={level}\n type=\"button\"\n onClick={() => toggle(level)}\n aria-pressed={active}\n className={cn(\n \"rounded-md border px-2 py-1 font-mono text-label uppercase tracking-wider\",\n \"transition-colors duration-base ease-out-soft\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n active\n ? cn(\"border-border/60 bg-muted\", levelClasses[level])\n : \"border-border/30 text-muted-foreground/50 hover:text-muted-foreground\",\n )}\n >\n {level}\n </button>\n );\n })}\n </div>\n ) : null}\n <div\n className={cn(\"overflow-y-auto rounded-lg border bg-card\", \"font-mono text-code-sm\")}\n style={{ height }}\n >\n {truncated ? (\n <output className=\"block border-border/30 border-b bg-muted/40 px-4 py-1.5 text-label text-muted-foreground\">\n Showing last {maxLines.toLocaleString()} of {filtered.length.toLocaleString()} lines (\n {hiddenCount.toLocaleString()} earlier lines hidden)\n </output>\n ) : null}\n {visible.length === 0 ? (\n <p className=\"px-4 py-3 text-muted-foreground\">No log lines.</p>\n ) : (\n <ol className=\"divide-y divide-border/30\" aria-live={effectiveLive} aria-atomic=\"false\">\n {visible.map((line) => (\n <li\n key={line.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-3 px-4 py-1.5 leading-relaxed hover:bg-muted/30\"\n >\n <span className=\"select-none text-muted-foreground\">{line.timestamp}</span>\n <span className={cn(\"select-none font-bold\", levelClasses[line.level])}>\n [{levelLabels[line.level]}]\n </span>\n <span className={levelClasses[line.level]}>\n {line.source ? (\n <span className=\"mr-2 text-muted-foreground\">{line.source}:</span>\n ) : null}\n {line.message}\n </span>\n </li>\n ))}\n </ol>\n )}\n </div>\n </div>\n );\n },\n);\nBuildLogStream.displayName = \"BuildLogStream\";\n\nexport { BuildLogStream };\n"
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "button",
4
+ "type": "registry:ui",
5
+ "title": "Button",
6
+ "description": "Primitive action element in the Violet Forge design system.",
7
+ "dependencies": [
8
+ "@radix-ui/react-slot",
9
+ "class-variance-authority"
10
+ ],
11
+ "registryDependencies": [
12
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
13
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "components/primitives/button/button.tsx",
18
+ "type": "registry:ui",
19
+ "target": "components/ui/button.tsx",
20
+ "content": "import { Slot } from \"@radix-ui/react-slot\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { forwardRef } from \"react\";\nimport type { ButtonHTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Button — primitive action element in the Violet Forge design system.\n *\n * Variants:\n * - primary Theo violet fill, glow on hover (signature)\n * - secondary surface with hairline border\n * - accent burnt-sienna fill, celebratory actions\n * - ghost transparent, hover lifts surface\n * - link text-only, primary color, underline on hover\n * - destructive for irreversible actions\n *\n * Sizes: sm (32px) · md (40px, default) · lg (48px) · icon (square 40px)\n *\n * `asChild` swaps the root for the consumer's element (Radix Slot pattern).\n */\nconst buttonVariants = cva(\n [\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg\",\n // NIT-004: `font-medium` (500) aligns with the design-system.md UI weight.\n // Previously `font-bold` (700) exceeded the normative 400/500/600 weight\n // range declared for Geist Sans in the Violet Forge identity.\n \"font-medium font-sans tracking-tight\",\n \"transition-[box-shadow,background-color,color,transform] duration-base ease-out-soft\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n // Tailwind v4 dropped the `button { cursor: pointer }` preflight rule\n // (https://tailwindcss.com/docs/upgrade-guide#default-button-cursor) so\n // every <button> now shows the default arrow cursor. Restore the\n // \"clickable hand\" explicitly for the Button primitive; the\n // `disabled:pointer-events-none` rule below short-circuits cursor\n // application for disabled state (no events → cursor is moot).\n // `aria-disabled:cursor-default` is a belt-and-suspenders override\n // for paths where pointer-events still flow.\n \"cursor-pointer disabled:cursor-default aria-disabled:cursor-default\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n ],\n {\n variants: {\n variant: {\n primary: [\n \"bg-primary text-primary-foreground\",\n \"hover:bg-primary hover:shadow-glow\",\n \"active:scale-[0.98] active:bg-primary-deep active:shadow-none\",\n ],\n secondary: [\n \"border border-border bg-secondary text-secondary-foreground\",\n \"hover:bg-muted\",\n \"active:scale-[0.98]\",\n ],\n accent: [\"bg-accent text-accent-foreground\", \"hover:bg-accent-deep\", \"active:scale-[0.98]\"],\n ghost: [\n \"bg-transparent text-foreground\",\n \"hover:bg-muted\",\n \"active:scale-[0.98] active:bg-secondary\",\n ],\n link: [\n \"bg-transparent text-primary underline-offset-4\",\n \"hover:text-primary-deep hover:underline\",\n \"h-auto p-0\",\n ],\n destructive: [\n \"bg-destructive text-destructive-foreground\",\n \"hover:bg-destructive/90\",\n \"active:scale-[0.98]\",\n ],\n },\n size: {\n sm: \"h-8 px-3 text-body-sm\",\n // md: tier ajustável via density (CSS var on :root). See D3 ADR of\n // faang-density-tightening plan. Default `comfortable` density makes\n // this 36px (--theo-control-h: 2.25rem). sm and lg stay hardcoded.\n md: \"h-[var(--theo-control-h,2.25rem)] px-[var(--theo-control-px,0.875rem)] text-body-sm\",\n lg: \"h-11 px-4 text-body-md\",\n icon: \"h-[var(--theo-control-h,2.25rem)] w-[var(--theo-control-h,2.25rem)] p-0\",\n },\n },\n defaultVariants: {\n variant: \"primary\",\n size: \"md\",\n },\n },\n);\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, type, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n ref={ref}\n type={asChild ? undefined : (type ?? \"button\")}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n"
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "capability-indicator",
4
+ "type": "registry:ui",
5
+ "title": "CapabilityIndicator",
6
+ "description": "Row of chips showing what the agent can currently do.",
7
+ "dependencies": [
8
+ "lucide-react"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
12
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json",
13
+ "https://usetheodev.github.io/theo-ui/r/types.json"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "components/primitives/capability-indicator/capability-indicator.tsx",
18
+ "type": "registry:ui",
19
+ "target": "components/ui/capability-indicator.tsx",
20
+ "content": "import {\n AlertCircle,\n Eye,\n Network,\n Pencil,\n Rocket,\n Sparkles,\n Terminal,\n Trash2,\n} from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport type { IconComponent } from \"@/lib/types\";\n\nexport type CapabilityState = \"enabled\" | \"disabled\" | \"blocked\" | \"active\";\n\nexport interface Capability {\n id: string;\n /** Visible label. */\n label: ReactNode;\n /** Optional icon override. */\n icon?: IconComponent;\n /** Default state. */\n state?: CapabilityState;\n /** Tooltip / longer description. */\n hint?: ReactNode;\n}\n\ninterface CapabilityIndicatorProps extends HTMLAttributes<HTMLDivElement> {\n capabilities: Capability[];\n}\n\n/**\n * CapabilityIndicator — row of chips showing what the agent can currently do.\n *\n * Critical for transparency: the user should always see (e.g. in a top bar)\n * whether the agent has read/write/exec/network access enabled. The \"active\"\n * state pulses when a capability is in use.\n */\nconst stateClasses: Record<CapabilityState, string> = {\n enabled: \"border-success/40 bg-success/10 text-success\",\n active: \"border-primary/50 bg-primary/15 text-primary\",\n disabled: \"border-border/40 bg-muted text-muted-foreground line-through\",\n blocked: \"border-destructive/40 bg-destructive/10 text-destructive\",\n};\n\nconst CapabilityIndicator = forwardRef<HTMLUListElement, CapabilityIndicatorProps>(\n ({ className, capabilities, ...props }, ref) => (\n <ul\n ref={ref}\n aria-label=\"Agent capabilities\"\n className={cn(\"flex flex-wrap items-center gap-1.5\", className)}\n {...(props as HTMLAttributes<HTMLUListElement>)}\n >\n {capabilities.map((c) => {\n const Icon = c.icon ?? AlertCircle;\n const state = c.state ?? \"enabled\";\n return (\n <li\n key={c.id}\n title={typeof c.hint === \"string\" ? c.hint : undefined}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5\",\n \"font-sans text-label\",\n \"transition-colors\",\n stateClasses[state],\n )}\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\"size-3 shrink-0\", state === \"active\" && \"animate-pulse\")}\n />\n {c.label}\n </li>\n );\n })}\n </ul>\n ),\n);\nCapabilityIndicator.displayName = \"CapabilityIndicator\";\n\n/** Common capability presets — re-use these so apps don't reinvent labels. */\nexport const capabilityPresets = {\n read: { id: \"read\", label: \"Read files\", icon: Eye } as const,\n write: { id: \"write\", label: \"Write files\", icon: Pencil } as const,\n delete: { id: \"delete\", label: \"Delete files\", icon: Trash2 } as const,\n bash: { id: \"bash\", label: \"Run shell\", icon: Terminal } as const,\n network: { id: \"network\", label: \"Network\", icon: Network } as const,\n deploy: { id: \"deploy\", label: \"Deploy\", icon: Rocket } as const,\n llm: { id: \"llm\", label: \"Sub-agents\", icon: Sparkles } as const,\n};\n\nexport { CapabilityIndicator };\n"
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "card",
4
+ "type": "registry:ui",
5
+ "title": "Card",
6
+ "description": "Surface container for grouping related content.",
7
+ "dependencies": [
8
+ "@radix-ui/react-slot"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
12
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "components/primitives/card/card.tsx",
17
+ "type": "registry:ui",
18
+ "target": "components/ui/card.tsx",
19
+ "content": "import { Slot } from \"@radix-ui/react-slot\";\nimport { createContext, forwardRef, useContext } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Card — surface container for grouping related content.\n *\n * Composition pattern (shadcn-style):\n * <Card>\n * <Card.Header>\n * <Card.Title>…</Card.Title>\n * <Card.Description>…</Card.Description>\n * </Card.Header>\n * <Card.Body>…</Card.Body>\n * <Card.Footer>…</Card.Footer>\n * </Card>\n *\n * The `size` prop on the root propagates to subparts via Context, so a\n * single declaration controls padding + heading scale across the compound.\n * Subparts used in isolation default to `md`. Subparts do NOT accept a `size`\n * prop of their own — use `className` for granular per-subpart tweaks.\n * (EC-8, edge-case review 2026-05-20.)\n */\n\ntype CardSize = \"sm\" | \"md\" | \"lg\";\n\ninterface CardContextValue {\n size: CardSize;\n}\n\nconst CardContext = createContext<CardContextValue>({ size: \"md\" });\n\nconst useCardSize = (): CardSize => useContext(CardContext).size;\n\ninterface CardRootProps extends HTMLAttributes<HTMLDivElement> {\n size?: CardSize;\n}\n\nconst Root = forwardRef<HTMLDivElement, CardRootProps>(\n ({ className, size = \"md\", ...props }, ref) => (\n <CardContext.Provider value={{ size }}>\n <div\n ref={ref}\n className={cn(\n \"rounded-xl border bg-card text-card-foreground shadow-md\",\n \"transition-shadow duration-base ease-out-soft\",\n className,\n )}\n {...props}\n />\n </CardContext.Provider>\n ),\n);\nRoot.displayName = \"Card\";\n\nconst headerPadBySize: Record<CardSize, string> = {\n sm: \"gap-1 p-3 pb-1.5\",\n md: \"gap-1.5 p-5 pb-2.5\",\n lg: \"gap-2 p-6 pb-3\",\n};\n\nconst Header = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const size = useCardSize();\n return (\n <div ref={ref} className={cn(\"flex flex-col\", headerPadBySize[size], className)} {...props} />\n );\n },\n);\nHeader.displayName = \"Card.Header\";\n\nconst titleFontBySize: Record<CardSize, string> = {\n sm: \"text-title-md\",\n md: \"text-title-lg\",\n lg: \"text-headline\",\n};\n\ninterface TitleProps extends HTMLAttributes<HTMLHeadingElement> {\n /**\n * When true, renders the child element with the Card.Title styles applied\n * (Radix Slot pattern). Use to swap the default `<h3>` for `<h1>` / `<h2>`\n * when the heading hierarchy requires it.\n */\n asChild?: boolean;\n}\n\nconst Title = forwardRef<HTMLHeadingElement, TitleProps>(\n ({ className, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"h3\";\n const size = useCardSize();\n return (\n <Comp\n ref={ref}\n className={cn(\n \"font-display text-foreground tracking-tight\",\n titleFontBySize[size],\n className,\n )}\n {...props}\n />\n );\n },\n);\nTitle.displayName = \"Card.Title\";\n\nconst Description = forwardRef<HTMLParagraphElement, HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => (\n <p ref={ref} className={cn(\"text-body-sm text-muted-foreground\", className)} {...props} />\n ),\n);\nDescription.displayName = \"Card.Description\";\n\nconst bodyPadBySize: Record<CardSize, string> = {\n sm: \"p-3 pt-1.5\",\n md: \"p-5 pt-2.5\",\n lg: \"p-6 pt-3\",\n};\n\nconst Body = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const size = useCardSize();\n return <div ref={ref} className={cn(bodyPadBySize[size], className)} {...props} />;\n },\n);\nBody.displayName = \"Card.Body\";\n\nconst footerPadBySize: Record<CardSize, string> = {\n sm: \"gap-2 p-3 pt-2\",\n md: \"gap-3 p-5 pt-3\",\n lg: \"gap-4 p-6 pt-4\",\n};\n\nconst Footer = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const size = useCardSize();\n return (\n <div\n ref={ref}\n className={cn(\n \"flex items-center border-border/40 border-t\",\n footerPadBySize[size],\n className,\n )}\n {...props}\n />\n );\n },\n);\nFooter.displayName = \"Card.Footer\";\n\nconst Card = /*#__PURE__*/ Object.assign(Root, {\n Header,\n Title,\n Description,\n Body,\n Footer,\n});\n\nexport { Card };\n"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "chat-composer",
4
+ "type": "registry:ui",
5
+ "title": "ChatComposer",
6
+ "description": "Message input area, shared by Chat / Code / Infra modes.",
7
+ "dependencies": [
8
+ "lucide-react"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://usetheodev.github.io/theo-ui/r/button.json",
12
+ "https://usetheodev.github.io/theo-ui/r/cn.json",
13
+ "https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "components/composites/chat-composer/chat-composer.tsx",
18
+ "type": "registry:ui",
19
+ "target": "components/ui/chat-composer.tsx",
20
+ "content": "import { Mic, Paperclip, Send, Square } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type {\n FormEvent,\n HTMLAttributes,\n KeyboardEvent,\n ReactNode,\n TextareaHTMLAttributes,\n} from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { Button } from \"@/components/ui/button\";\n\nexport type ComposerMode = \"chat\" | \"code\" | \"infra\";\n\ninterface ChatComposerProps extends Omit<HTMLAttributes<HTMLFormElement>, \"onSubmit\"> {\n mode?: ComposerMode;\n value: string;\n onValueChange: (next: string) => void;\n onSubmit?: (value: string) => void;\n /**\n * If true, the composer is in \"agent running\" state — Send becomes a Stop button.\n */\n running?: boolean;\n onStop?: () => void;\n /**\n * Slot above the textarea — used for the folder selector in Infra mode.\n */\n contextSlot?: ReactNode;\n /**\n * Slot above the textarea for attachments / chips.\n */\n attachmentsSlot?: ReactNode;\n /**\n * Slot on the bottom-left of the action row (e.g. custom toggles).\n * Overrides the default attach button entirely when provided.\n */\n leadingActions?: ReactNode;\n /**\n * Slot on the bottom-right (e.g. model selector). Send/stop is appended after this.\n */\n trailingActions?: ReactNode;\n /**\n * Optional attach-file callback. If omitted (and `leadingActions` is also\n * omitted), no attach button is rendered. This avoids fake affordances per\n * Quality Gate §7.\n */\n onAttach?: () => void;\n /**\n * Optional voice-input callback. If omitted, no mic button is rendered.\n * Same rationale as `onAttach`.\n */\n onVoiceInput?: () => void;\n /**\n * Accessible label for the textarea. Falls back to a mode-aware default.\n */\n textareaLabel?: string;\n /**\n * Textarea placeholder. Defaults change by mode.\n */\n placeholder?: string;\n /**\n * Extra textarea props (rows, maxLength…).\n */\n textareaProps?: Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"value\" | \"onChange\">;\n}\n\nconst defaultPlaceholder: Record<ComposerMode, string> = {\n chat: \"How can I help you today?\",\n code: \"Type / for commands\",\n infra: \"Ask about deploys, metrics, env, or rollback…\",\n};\n\nconst defaultTextareaLabel: Record<ComposerMode, string> = {\n chat: \"Chat message\",\n code: \"Code prompt\",\n infra: \"Infra command\",\n};\n\n/**\n * ChatComposer — message input area, shared by Chat / Code / Infra modes.\n *\n * Visual:\n * - chat / infra → soft card with violet ring on focus, generous padding\n * - code → compact dense form with mono font, slash prefix hint\n *\n * Stateless: caller controls `value` + handles `onSubmit`. Submit fires on Enter\n * (without Shift). Shift+Enter inserts a newline.\n *\n * Optional affordances (mic, attach) are opt-in via `onVoiceInput` / `onAttach`\n * — Quality Gate §7 forbids rendering fake controls without behavior.\n */\nconst ChatComposer = forwardRef<HTMLFormElement, ChatComposerProps>(\n (\n {\n className,\n mode = \"chat\",\n value,\n onValueChange,\n onSubmit,\n running = false,\n onStop,\n contextSlot,\n attachmentsSlot,\n leadingActions,\n trailingActions,\n onAttach,\n onVoiceInput,\n textareaLabel,\n placeholder,\n textareaProps,\n ...props\n },\n ref,\n ) => {\n const handleSubmit = (e: FormEvent) => {\n e.preventDefault();\n if (running) return;\n if (!value.trim()) return;\n onSubmit?.(value);\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n if (running) return;\n if (!value.trim()) return;\n onSubmit?.(value);\n }\n };\n\n const isCode = mode === \"code\";\n\n return (\n <form\n ref={ref}\n onSubmit={handleSubmit}\n className={cn(\n \"rounded-2xl border bg-card text-card-foreground transition-shadow\",\n \"focus-within:border-primary/60 focus-within:shadow-glow\",\n isCode && \"rounded-xl shadow-sm\",\n className,\n )}\n {...props}\n >\n {contextSlot ? (\n <div className=\"border-border/40 border-b px-3 pt-3\">{contextSlot}</div>\n ) : null}\n\n {attachmentsSlot ? (\n <div className=\"flex flex-wrap gap-2 px-4 pt-3\">{attachmentsSlot}</div>\n ) : null}\n\n <textarea\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={onKeyDown}\n placeholder={placeholder ?? defaultPlaceholder[mode]}\n aria-label={textareaLabel ?? defaultTextareaLabel[mode]}\n rows={isCode ? 1 : 2}\n {...textareaProps}\n className={cn(\n \"w-full resize-none bg-transparent px-4 py-3\",\n \"placeholder:text-muted-foreground\",\n \"focus:outline-none\",\n isCode ? \"font-mono text-code-md\" : \"min-h-[3.5rem] font-sans text-body-md\",\n textareaProps?.className,\n )}\n />\n\n <div\n className={cn(\n \"flex items-center justify-between gap-2 border-border/40 border-t px-3 py-2\",\n )}\n >\n <div className=\"flex items-center gap-1\">\n {leadingActions !== undefined ? (\n leadingActions\n ) : onAttach ? (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n type=\"button\"\n onClick={onAttach}\n aria-label=\"Attach file\"\n >\n <Paperclip />\n </Button>\n ) : null}\n </div>\n <div className=\"flex items-center gap-2\">\n {trailingActions}\n {onVoiceInput ? (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n type=\"button\"\n onClick={onVoiceInput}\n aria-label=\"Voice input\"\n >\n <Mic />\n </Button>\n ) : null}\n {running ? (\n <Button\n type=\"button\"\n onClick={onStop}\n size=\"icon\"\n variant=\"destructive\"\n aria-label=\"Stop generation\"\n >\n <Square />\n </Button>\n ) : (\n <Button type=\"submit\" size=\"icon\" disabled={!value.trim()} aria-label=\"Send message\">\n <Send />\n </Button>\n )}\n </div>\n </div>\n </form>\n );\n },\n);\nChatComposer.displayName = \"ChatComposer\";\n\nexport { ChatComposer };\n"
21
+ }
22
+ ]
23
+ }