@aprovan/patchwork-chat 0.1.0-dev.03aaf5b

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 (324) hide show
  1. package/.turbo/turbo-build.log +319 -0
  2. package/.utcp_config.json +14 -0
  3. package/.working/widgets/27060b91-a2a5-4272-b243-6eb904bd4070/main.tsx +107 -0
  4. package/LICENSE +373 -0
  5. package/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  6. package/dist/assets/abap-BdImnpbu.js +1 -0
  7. package/dist/assets/actionscript-3-CoDkCxhg.js +1 -0
  8. package/dist/assets/ada-bCR0ucgS.js +1 -0
  9. package/dist/assets/andromeeda-C4gqWexZ.js +1 -0
  10. package/dist/assets/angular-html-CU67Zn6k.js +1 -0
  11. package/dist/assets/angular-ts-BwZT4LLn.js +1 -0
  12. package/dist/assets/apache-Pmp26Uib.js +1 -0
  13. package/dist/assets/apex-D8_7TLub.js +1 -0
  14. package/dist/assets/apl-dKokRX4l.js +1 -0
  15. package/dist/assets/applescript-Co6uUVPk.js +1 -0
  16. package/dist/assets/ara-BRHolxvo.js +1 -0
  17. package/dist/assets/asciidoc-Dv7Oe6Be.js +1 -0
  18. package/dist/assets/asm-D_Q5rh1f.js +1 -0
  19. package/dist/assets/astro-CbQHKStN.js +1 -0
  20. package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
  21. package/dist/assets/awk-DMzUqQB5.js +1 -0
  22. package/dist/assets/ayu-dark-CMjwMIkn.js +1 -0
  23. package/dist/assets/ayu-light-C47S-Tmv.js +1 -0
  24. package/dist/assets/ayu-mirage-CjoLj4QM.js +1 -0
  25. package/dist/assets/ballerina-BFfxhgS-.js +1 -0
  26. package/dist/assets/bat-BkioyH1T.js +1 -0
  27. package/dist/assets/beancount-k_qm7-4y.js +1 -0
  28. package/dist/assets/berry-uYugtg8r.js +1 -0
  29. package/dist/assets/bibtex-CHM0blh-.js +1 -0
  30. package/dist/assets/bicep-Bmn6On1c.js +1 -0
  31. package/dist/assets/blade-D4QpJJKB.js +1 -0
  32. package/dist/assets/bsl-BO_Y6i37.js +1 -0
  33. package/dist/assets/c-BIGW1oBm.js +1 -0
  34. package/dist/assets/c3-VCDPK7BO.js +1 -0
  35. package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
  36. package/dist/assets/cairo-KRGpt6FW.js +1 -0
  37. package/dist/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  38. package/dist/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  39. package/dist/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  40. package/dist/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  41. package/dist/assets/clarity-D53aC0YG.js +1 -0
  42. package/dist/assets/clojure-P80f7IUj.js +1 -0
  43. package/dist/assets/cmake-D1j8_8rp.js +1 -0
  44. package/dist/assets/cobol-nwyudZeR.js +1 -0
  45. package/dist/assets/codeowners-Bp6g37R7.js +1 -0
  46. package/dist/assets/codeql-DsOJ9woJ.js +1 -0
  47. package/dist/assets/coffee-Ch7k5sss.js +1 -0
  48. package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
  49. package/dist/assets/coq-DkFqJrB1.js +1 -0
  50. package/dist/assets/cpp-CofmeUqb.js +1 -0
  51. package/dist/assets/crystal-tKQVLTB8.js +1 -0
  52. package/dist/assets/csharp-COcwbKMJ.js +1 -0
  53. package/dist/assets/css-DPfMkruS.js +1 -0
  54. package/dist/assets/csv-fuZLfV_i.js +1 -0
  55. package/dist/assets/cue-D82EKSYY.js +1 -0
  56. package/dist/assets/cypher-COkxafJQ.js +1 -0
  57. package/dist/assets/d-85-TOEBH.js +1 -0
  58. package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
  59. package/dist/assets/dart-CF10PKvl.js +1 -0
  60. package/dist/assets/dax-CEL-wOlO.js +1 -0
  61. package/dist/assets/desktop-BmXAJ9_W.js +1 -0
  62. package/dist/assets/diff-D97Zzqfu.js +1 -0
  63. package/dist/assets/docker-BcOcwvcX.js +1 -0
  64. package/dist/assets/dotenv-Da5cRb03.js +1 -0
  65. package/dist/assets/dracula-BzJJZx-M.js +1 -0
  66. package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
  67. package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
  68. package/dist/assets/edge-BkV0erSs.js +1 -0
  69. package/dist/assets/elixir-CDX3lj18.js +1 -0
  70. package/dist/assets/elm-DbKCFpqz.js +1 -0
  71. package/dist/assets/emacs-lisp-C9XAeP06.js +1 -0
  72. package/dist/assets/erb-CgJxNhIT.js +1 -0
  73. package/dist/assets/erlang-DsQrWhSR.js +1 -0
  74. package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
  75. package/dist/assets/everforest-light-C8M2exoo.js +1 -0
  76. package/dist/assets/fennel-BYunw83y.js +1 -0
  77. package/dist/assets/fish-BvzEVeQv.js +1 -0
  78. package/dist/assets/fluent-C4IJs8-o.js +1 -0
  79. package/dist/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  80. package/dist/assets/fortran-free-form-BxgE0vQu.js +1 -0
  81. package/dist/assets/fsharp-CXgrBDvD.js +1 -0
  82. package/dist/assets/gdresource-BOOCDP_w.js +1 -0
  83. package/dist/assets/gdscript-C5YyOfLZ.js +1 -0
  84. package/dist/assets/gdshader-DkwncUOv.js +1 -0
  85. package/dist/assets/genie-D0YGMca9.js +1 -0
  86. package/dist/assets/gherkin-DyxjwDmM.js +1 -0
  87. package/dist/assets/git-commit-F4YmCXRG.js +1 -0
  88. package/dist/assets/git-rebase-r7XF79zn.js +1 -0
  89. package/dist/assets/github-dark-DHJKELXO.js +1 -0
  90. package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
  91. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  92. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  93. package/dist/assets/github-light-DAi9KRSo.js +1 -0
  94. package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
  95. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  96. package/dist/assets/gleam-BspZqrRM.js +1 -0
  97. package/dist/assets/glimmer-js-Rg0-pVw9.js +1 -0
  98. package/dist/assets/glimmer-ts-U6CK756n.js +1 -0
  99. package/dist/assets/glsl-DplSGwfg.js +1 -0
  100. package/dist/assets/gn-n2N0HUVH.js +1 -0
  101. package/dist/assets/gnuplot-DdkO51Og.js +1 -0
  102. package/dist/assets/go-CxLEBnE3.js +1 -0
  103. package/dist/assets/graphql-ChdNCCLP.js +1 -0
  104. package/dist/assets/groovy-gcz8RCvz.js +1 -0
  105. package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  106. package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  107. package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  108. package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  109. package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  110. package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  111. package/dist/assets/hack-CaT9iCJl.js +1 -0
  112. package/dist/assets/haml-B8DHNrY2.js +1 -0
  113. package/dist/assets/handlebars-BL8al0AC.js +1 -0
  114. package/dist/assets/haskell-Df6bDoY_.js +1 -0
  115. package/dist/assets/haxe-CzTSHFRz.js +1 -0
  116. package/dist/assets/hcl-BWvSN4gD.js +1 -0
  117. package/dist/assets/hjson-D5-asLiD.js +1 -0
  118. package/dist/assets/hlsl-D3lLCCz7.js +1 -0
  119. package/dist/assets/horizon-BUw7H-hv.js +1 -0
  120. package/dist/assets/houston-DnULxvSX.js +1 -0
  121. package/dist/assets/html-GMplVEZG.js +1 -0
  122. package/dist/assets/html-derivative-BFtXZ54Q.js +1 -0
  123. package/dist/assets/http-jrhK8wxY.js +1 -0
  124. package/dist/assets/hurl-irOxFIW8.js +1 -0
  125. package/dist/assets/hxml-Bvhsp5Yf.js +1 -0
  126. package/dist/assets/hy-DFXneXwc.js +1 -0
  127. package/dist/assets/imba-DGztddWO.js +1 -0
  128. package/dist/assets/index-BswF5IWJ.js +1467 -0
  129. package/dist/assets/index-Ct0GSTdJ.css +1 -0
  130. package/dist/assets/ini-BEwlwnbL.js +1 -0
  131. package/dist/assets/java-CylS5w8V.js +1 -0
  132. package/dist/assets/javascript-wDzz0qaB.js +1 -0
  133. package/dist/assets/jinja-4LBKfQ-Z.js +1 -0
  134. package/dist/assets/jison-wvAkD_A8.js +1 -0
  135. package/dist/assets/json-Cp-IABpG.js +1 -0
  136. package/dist/assets/json5-C9tS-k6U.js +1 -0
  137. package/dist/assets/jsonc-Des-eS-w.js +1 -0
  138. package/dist/assets/jsonl-DcaNXYhu.js +1 -0
  139. package/dist/assets/jsonnet-DFQXde-d.js +1 -0
  140. package/dist/assets/jssm-C2t-YnRu.js +1 -0
  141. package/dist/assets/jsx-g9-lgVsj.js +1 -0
  142. package/dist/assets/julia-CxzCAyBv.js +1 -0
  143. package/dist/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  144. package/dist/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  145. package/dist/assets/kanagawa-wave-DWedfzmr.js +1 -0
  146. package/dist/assets/kdl-DV7GczEv.js +1 -0
  147. package/dist/assets/kotlin-BdnUsdx6.js +1 -0
  148. package/dist/assets/kusto-DZf3V79B.js +1 -0
  149. package/dist/assets/laserwave-DUszq2jm.js +1 -0
  150. package/dist/assets/latex-DGMBWnxU.js +1 -0
  151. package/dist/assets/lean-BZvkOJ9d.js +1 -0
  152. package/dist/assets/less-B1dDrJ26.js +1 -0
  153. package/dist/assets/light-plus-B7mTdjB0.js +1 -0
  154. package/dist/assets/liquid-DYVedYrR.js +1 -0
  155. package/dist/assets/llvm-BtvRca6l.js +1 -0
  156. package/dist/assets/log-2UxHyX5q.js +1 -0
  157. package/dist/assets/logo-BtOb2qkB.js +1 -0
  158. package/dist/assets/lua-BaeVxFsk.js +1 -0
  159. package/dist/assets/luau-C-HG3fhB.js +1 -0
  160. package/dist/assets/make-CHLpvVh8.js +1 -0
  161. package/dist/assets/markdown-Cvjx9yec.js +1 -0
  162. package/dist/assets/marko-DZsq8hO1.js +1 -0
  163. package/dist/assets/material-theme-D5KoaKCx.js +1 -0
  164. package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
  165. package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  166. package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
  167. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  168. package/dist/assets/matlab-D7o27uSR.js +1 -0
  169. package/dist/assets/mdc-DUICxH0z.js +1 -0
  170. package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
  171. package/dist/assets/mermaid-mWjccvbQ.js +1 -0
  172. package/dist/assets/min-dark-CafNBF8u.js +1 -0
  173. package/dist/assets/min-light-CTRr51gU.js +1 -0
  174. package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
  175. package/dist/assets/mojo-B93PlW-d.js +1 -0
  176. package/dist/assets/monokai-D4h5O-jR.js +1 -0
  177. package/dist/assets/moonbit-Ba13S78F.js +1 -0
  178. package/dist/assets/move-IF9eRakj.js +1 -0
  179. package/dist/assets/narrat-DRg8JJMk.js +1 -0
  180. package/dist/assets/nextflow-BrzmwbiE.js +1 -0
  181. package/dist/assets/nginx-BpAMiNFr.js +1 -0
  182. package/dist/assets/night-owl-C39BiMTA.js +1 -0
  183. package/dist/assets/night-owl-light-CMTm3GFP.js +1 -0
  184. package/dist/assets/nim-CVrawwO9.js +1 -0
  185. package/dist/assets/nix-CwoSXNpI.js +1 -0
  186. package/dist/assets/nord-Ddv68eIx.js +1 -0
  187. package/dist/assets/nushell-C-sUppwS.js +1 -0
  188. package/dist/assets/objective-c-DXmwc3jG.js +1 -0
  189. package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
  190. package/dist/assets/ocaml-C0hk2d4L.js +1 -0
  191. package/dist/assets/odin-BBf5iR-q.js +1 -0
  192. package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  193. package/dist/assets/one-light-C3Wv6jpd.js +1 -0
  194. package/dist/assets/openscad-C4EeE6gA.js +1 -0
  195. package/dist/assets/pascal-D93ZcfNL.js +1 -0
  196. package/dist/assets/perl-C0TMdlhV.js +1 -0
  197. package/dist/assets/php-Dhbhpdrm.js +1 -0
  198. package/dist/assets/pkl-u5AG7uiY.js +1 -0
  199. package/dist/assets/plastic-3e1v2bzS.js +1 -0
  200. package/dist/assets/plsql-ChMvpjG-.js +1 -0
  201. package/dist/assets/po-BTJTHyun.js +1 -0
  202. package/dist/assets/poimandres-CS3Unz2-.js +1 -0
  203. package/dist/assets/polar-C0HS_06l.js +1 -0
  204. package/dist/assets/postcss-CXtECtnM.js +1 -0
  205. package/dist/assets/powerquery-CEu0bR-o.js +1 -0
  206. package/dist/assets/powershell-Dpen1YoG.js +1 -0
  207. package/dist/assets/prisma-Dd19v3D-.js +1 -0
  208. package/dist/assets/prolog-CbFg5uaA.js +1 -0
  209. package/dist/assets/proto-C7zT0LnQ.js +1 -0
  210. package/dist/assets/pug-CGlum2m_.js +1 -0
  211. package/dist/assets/puppet-BMWR74SV.js +1 -0
  212. package/dist/assets/purescript-CklMAg4u.js +1 -0
  213. package/dist/assets/python-B6aJPvgy.js +1 -0
  214. package/dist/assets/qml-3beO22l8.js +1 -0
  215. package/dist/assets/qmldir-C8lEn-DE.js +1 -0
  216. package/dist/assets/qss-IeuSbFQv.js +1 -0
  217. package/dist/assets/r-Dspwwk_N.js +1 -0
  218. package/dist/assets/racket-BqYA7rlc.js +1 -0
  219. package/dist/assets/raku-DXvB9xmW.js +1 -0
  220. package/dist/assets/razor-Uh8Bk_45.js +1 -0
  221. package/dist/assets/red-bN70gL4F.js +1 -0
  222. package/dist/assets/reg-C-SQnVFl.js +1 -0
  223. package/dist/assets/regexp-CDVJQ6XC.js +1 -0
  224. package/dist/assets/rel-C3B-1QV4.js +1 -0
  225. package/dist/assets/riscv-BM1_JUlF.js +1 -0
  226. package/dist/assets/ron-BhRPY-oY.js +1 -0
  227. package/dist/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
  228. package/dist/assets/rose-pine-moon-D4_iv3hh.js +1 -0
  229. package/dist/assets/rose-pine-qdsjHGoJ.js +1 -0
  230. package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
  231. package/dist/assets/rst-D5oM4XIm.js +1 -0
  232. package/dist/assets/ruby-Cw6WdidG.js +1 -0
  233. package/dist/assets/rust-B1yitclQ.js +1 -0
  234. package/dist/assets/sas-cz2c8ADy.js +1 -0
  235. package/dist/assets/sass-Cj5Yp3dK.js +1 -0
  236. package/dist/assets/scala-C151Ov-r.js +1 -0
  237. package/dist/assets/scheme-C98Dy4si.js +1 -0
  238. package/dist/assets/scss-OYdSNvt2.js +1 -0
  239. package/dist/assets/sdbl-DVxCFoDh.js +1 -0
  240. package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
  241. package/dist/assets/shellscript-Yzrsuije.js +1 -0
  242. package/dist/assets/shellsession-BADoaaVG.js +1 -0
  243. package/dist/assets/slack-dark-BthQWCQV.js +1 -0
  244. package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
  245. package/dist/assets/smalltalk-BERRCDM3.js +1 -0
  246. package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
  247. package/dist/assets/solarized-dark-DXbdFlpD.js +1 -0
  248. package/dist/assets/solarized-light-L9t79GZl.js +1 -0
  249. package/dist/assets/solidity-rGO070M0.js +1 -0
  250. package/dist/assets/soy-Brmx7dQM.js +1 -0
  251. package/dist/assets/sparql-rVzFXLq3.js +1 -0
  252. package/dist/assets/splunk-BtCnVYZw.js +1 -0
  253. package/dist/assets/sql-BLtJtn59.js +1 -0
  254. package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
  255. package/dist/assets/stata-BH5u7GGu.js +1 -0
  256. package/dist/assets/stylus-BEDo0Tqx.js +1 -0
  257. package/dist/assets/surrealql-Bq5Q-fJD.js +1 -0
  258. package/dist/assets/svelte-zxCyuUbr.js +1 -0
  259. package/dist/assets/swift-Dg5xB15N.js +1 -0
  260. package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
  261. package/dist/assets/system-verilog-CnnmHF94.js +1 -0
  262. package/dist/assets/systemd-4A_iFExJ.js +1 -0
  263. package/dist/assets/talonscript-CkByrt1z.js +1 -0
  264. package/dist/assets/tasl-QIJgUcNo.js +1 -0
  265. package/dist/assets/tcl-dwOrl1Do.js +1 -0
  266. package/dist/assets/templ-P3uqSqPl.js +1 -0
  267. package/dist/assets/terraform-BETggiCN.js +1 -0
  268. package/dist/assets/tex-CvyZ59Mk.js +1 -0
  269. package/dist/assets/tokyo-night-hegEt444.js +1 -0
  270. package/dist/assets/toml-vGWfd6FD.js +1 -0
  271. package/dist/assets/ts-tags-zn1MmPIZ.js +1 -0
  272. package/dist/assets/tsv-B_m7g4N7.js +1 -0
  273. package/dist/assets/tsx-COt5Ahok.js +1 -0
  274. package/dist/assets/turtle-BsS91CYL.js +1 -0
  275. package/dist/assets/twig-ChbOoGGc.js +1 -0
  276. package/dist/assets/typescript-BPQ3VLAy.js +1 -0
  277. package/dist/assets/typespec-BGHnOYBU.js +1 -0
  278. package/dist/assets/typst-DHCkPAjA.js +1 -0
  279. package/dist/assets/v-BcVCzyr7.js +1 -0
  280. package/dist/assets/vala-CsfeWuGM.js +1 -0
  281. package/dist/assets/vb-D17OF-Vu.js +1 -0
  282. package/dist/assets/verilog-BQ8w6xss.js +1 -0
  283. package/dist/assets/vesper-DU1UobuO.js +1 -0
  284. package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
  285. package/dist/assets/viml-CJc9bBzg.js +1 -0
  286. package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
  287. package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
  288. package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
  289. package/dist/assets/vue-DN_0RTcg.js +1 -0
  290. package/dist/assets/vue-html-AaS7Mt5G.js +1 -0
  291. package/dist/assets/vue-vine-CQOfvN7w.js +1 -0
  292. package/dist/assets/vyper-CDx5xZoG.js +1 -0
  293. package/dist/assets/wasm-CG6Dc4jp.js +1 -0
  294. package/dist/assets/wasm-MzD3tlZU.js +1 -0
  295. package/dist/assets/wenyan-BV7otONQ.js +1 -0
  296. package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
  297. package/dist/assets/wikitext-BhOHFoWU.js +1 -0
  298. package/dist/assets/wit-5i3qLPDT.js +1 -0
  299. package/dist/assets/wolfram-lXgVvXCa.js +1 -0
  300. package/dist/assets/xml-sdJ4AIDG.js +1 -0
  301. package/dist/assets/xsl-CtQFsRM5.js +1 -0
  302. package/dist/assets/yaml-Buea-lGh.js +1 -0
  303. package/dist/assets/zenscript-DVFEvuxE.js +1 -0
  304. package/dist/assets/zig-VOosw3JB.js +1 -0
  305. package/dist/index.html +18 -0
  306. package/index.html +17 -0
  307. package/package.json +55 -0
  308. package/postcss.config.js +6 -0
  309. package/src/App.tsx +7 -0
  310. package/src/components/ui/avatar.tsx +48 -0
  311. package/src/components/ui/badge.tsx +36 -0
  312. package/src/components/ui/button.tsx +56 -0
  313. package/src/components/ui/card.tsx +86 -0
  314. package/src/components/ui/collapsible.tsx +9 -0
  315. package/src/components/ui/dialog.tsx +60 -0
  316. package/src/components/ui/input.tsx +25 -0
  317. package/src/components/ui/scroll-area.tsx +46 -0
  318. package/src/index.css +190 -0
  319. package/src/lib/utils.ts +6 -0
  320. package/src/main.tsx +10 -0
  321. package/src/pages/ChatPage.tsx +461 -0
  322. package/tailwind.config.js +71 -0
  323. package/tsconfig.json +25 -0
  324. package/vite.config.ts +26 -0
package/src/index.css ADDED
@@ -0,0 +1,190 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 100%;
8
+ --foreground: 222.2 84% 4.9%;
9
+ --card: 0 0% 100%;
10
+ --card-foreground: 222.2 84% 4.9%;
11
+ --popover: 0 0% 100%;
12
+ --popover-foreground: 222.2 84% 4.9%;
13
+ --primary: 222.2 47.4% 11.2%;
14
+ --primary-foreground: 210 40% 98%;
15
+ --secondary: 210 40% 96.1%;
16
+ --secondary-foreground: 222.2 47.4% 11.2%;
17
+ --muted: 210 40% 96.1%;
18
+ --muted-foreground: 215.4 16.3% 46.9%;
19
+ --accent: 210 40% 96.1%;
20
+ --accent-foreground: 222.2 47.4% 11.2%;
21
+ --destructive: 0 84.2% 60.2%;
22
+ --destructive-foreground: 210 40% 98%;
23
+ --border: 214.3 31.8% 91.4%;
24
+ --input: 214.3 31.8% 91.4%;
25
+ --ring: 222.2 84% 4.9%;
26
+ --radius: 0.5rem;
27
+ }
28
+
29
+ .dark {
30
+ --background: 222.2 84% 4.9%;
31
+ --foreground: 210 40% 98%;
32
+ --card: 222.2 84% 4.9%;
33
+ --card-foreground: 210 40% 98%;
34
+ --popover: 222.2 84% 4.9%;
35
+ --popover-foreground: 210 40% 98%;
36
+ --primary: 210 40% 98%;
37
+ --primary-foreground: 222.2 47.4% 11.2%;
38
+ --secondary: 217.2 32.6% 17.5%;
39
+ --secondary-foreground: 210 40% 98%;
40
+ --muted: 217.2 32.6% 17.5%;
41
+ --muted-foreground: 215 20.2% 65.1%;
42
+ --accent: 217.2 32.6% 17.5%;
43
+ --accent-foreground: 210 40% 98%;
44
+ --destructive: 0 62.8% 30.6%;
45
+ --destructive-foreground: 210 40% 98%;
46
+ --border: 217.2 32.6% 17.5%;
47
+ --input: 217.2 32.6% 17.5%;
48
+ --ring: 212.7 26.8% 83.9%;
49
+ }
50
+ }
51
+
52
+ @layer base {
53
+ * {
54
+ @apply border-border;
55
+ }
56
+ body {
57
+ @apply bg-background text-foreground;
58
+ }
59
+ }
60
+
61
+ /* Tiptap Markdown Editor Styles */
62
+ .markdown-editor .tiptap {
63
+ outline: none;
64
+ }
65
+
66
+ .markdown-editor .tiptap p {
67
+ margin: 0;
68
+ }
69
+
70
+ .markdown-editor .tiptap > * + * {
71
+ margin-top: 0.5em;
72
+ }
73
+
74
+ /* Placeholder styling */
75
+ .markdown-editor .tiptap p.is-editor-empty:first-child::before {
76
+ color: hsl(var(--muted-foreground));
77
+ content: attr(data-placeholder);
78
+ float: left;
79
+ height: 0;
80
+ pointer-events: none;
81
+ }
82
+
83
+ /* Inline code */
84
+ .markdown-editor .tiptap code {
85
+ background-color: hsl(var(--muted));
86
+ border-radius: 0.25rem;
87
+ padding: 0.125rem 0.25rem;
88
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
89
+ font-size: 0.875em;
90
+ }
91
+
92
+ /* Code blocks */
93
+ .markdown-editor .tiptap pre {
94
+ background-color: hsl(var(--muted));
95
+ border-radius: 0.375rem;
96
+ padding: 0.5rem 0.75rem;
97
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
98
+ font-size: 0.875em;
99
+ overflow-x: auto;
100
+ }
101
+
102
+ .markdown-editor .tiptap pre code {
103
+ background: none;
104
+ padding: 0;
105
+ font-size: inherit;
106
+ }
107
+
108
+ /* Blockquotes */
109
+ .markdown-editor .tiptap blockquote {
110
+ border-left: 4px solid hsl(var(--muted-foreground) / 0.3);
111
+ padding-left: 1rem;
112
+ font-style: italic;
113
+ color: hsl(var(--muted-foreground));
114
+ }
115
+
116
+ /* Lists */
117
+ .markdown-editor .tiptap ul,
118
+ .markdown-editor .tiptap ol {
119
+ padding-left: 1.5rem;
120
+ margin: 0.25em 0;
121
+ }
122
+
123
+ .markdown-editor .tiptap ul {
124
+ list-style-type: disc;
125
+ }
126
+
127
+ .markdown-editor .tiptap ol {
128
+ list-style-type: decimal;
129
+ }
130
+
131
+ .markdown-editor .tiptap li {
132
+ margin: 0.125em 0;
133
+ }
134
+
135
+ /* Headings - more subtle for chat input */
136
+ .markdown-editor .tiptap h1,
137
+ .markdown-editor .tiptap h2,
138
+ .markdown-editor .tiptap h3 {
139
+ font-weight: 600;
140
+ line-height: 1.25;
141
+ }
142
+
143
+ .markdown-editor .tiptap h1 {
144
+ font-size: 1.25em;
145
+ }
146
+
147
+ .markdown-editor .tiptap h2 {
148
+ font-size: 1.125em;
149
+ }
150
+
151
+ .markdown-editor .tiptap h3 {
152
+ font-size: 1em;
153
+ }
154
+
155
+ /* Bold & Italic */
156
+ .markdown-editor .tiptap strong {
157
+ font-weight: 600;
158
+ }
159
+
160
+ .markdown-editor .tiptap em {
161
+ font-style: italic;
162
+ }
163
+
164
+ /* Strikethrough */
165
+ .markdown-editor .tiptap s {
166
+ text-decoration: line-through;
167
+ }
168
+
169
+ /* Code block wrapper with language input */
170
+ .markdown-editor .code-block-wrapper {
171
+ display: flex;
172
+ flex-direction: column;
173
+ }
174
+
175
+ .markdown-editor .code-block-wrapper pre {
176
+ margin: 0;
177
+ }
178
+
179
+ .markdown-editor .code-block-wrapper .language-input-wrapper {
180
+ user-select: none;
181
+ pointer-events: auto;
182
+ }
183
+
184
+ .markdown-editor .code-block-wrapper .language-input {
185
+ background: transparent;
186
+ user-select: text !important;
187
+ pointer-events: auto !important;
188
+ cursor: text;
189
+ -webkit-user-select: text !important;
190
+ }
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import App from './App';
4
+ import './index.css';
5
+
6
+ ReactDOM.createRoot(document.getElementById('root')!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>,
10
+ );
@@ -0,0 +1,461 @@
1
+ import { useChat } from '@ai-sdk/react';
2
+ import { DefaultChatTransport } from 'ai';
3
+ import { useState, useRef, useEffect, useMemo, useCallback, createContext, useContext } from 'react';
4
+ import {
5
+ Send,
6
+ Loader2,
7
+ Wrench,
8
+ AlertCircle,
9
+ Brain,
10
+ ChevronDown,
11
+ } from 'lucide-react';
12
+ import { Button } from '@/components/ui/button';
13
+ import { ScrollArea } from '@/components/ui/scroll-area';
14
+ import { Avatar, AvatarFallback } from '@/components/ui/avatar';
15
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
16
+ import { Badge } from '@/components/ui/badge';
17
+ import {
18
+ Collapsible,
19
+ CollapsibleContent,
20
+ CollapsibleTrigger,
21
+ } from '@/components/ui/collapsible';
22
+ import Markdown from 'react-markdown';
23
+ import remarkGfm from 'remark-gfm';
24
+ import type { UIMessage } from 'ai';
25
+ import { createCompiler, type Compiler } from '@aprovan/patchwork-compiler';
26
+ import {
27
+ extractCodeBlocks,
28
+ CodePreview,
29
+ MarkdownEditor,
30
+ ServicesInspector,
31
+ type ServiceInfo,
32
+ } from '@aprovan/patchwork-editor';
33
+
34
+ const APROVAN_LOGO =
35
+ 'https://raw.githubusercontent.com/AprovanLabs/aprovan.com/main/docs/assets/social-labs.png';
36
+
37
+ interface PatchworkContext {
38
+ compiler: Compiler | null;
39
+ namespaces: string[];
40
+ }
41
+
42
+ const PatchworkCtx = createContext<PatchworkContext>({ compiler: null, namespaces: [] });
43
+ const useCompiler = () => useContext(PatchworkCtx).compiler;
44
+ const useServices = () => useContext(PatchworkCtx).namespaces;
45
+
46
+ function TextPart({ text, isUser }: { text: string; isUser: boolean }) {
47
+ const compiler = useCompiler();
48
+ const services = useServices();
49
+
50
+ if (isUser) {
51
+ return (
52
+ <div className="prose prose-sm prose-invert prose-p:my-1 prose-headings:my-2 prose-ul:my-1 prose-ol:my-1 prose-li:my-0 prose-pre:my-2 prose-code:before:content-none prose-code:after:content-none">
53
+ <Markdown remarkPlugins={[remarkGfm]}>{text}</Markdown>
54
+ </div>
55
+ );
56
+ }
57
+
58
+ const parts = extractCodeBlocks(text);
59
+
60
+ return (
61
+ <div className="prose prose-sm dark:prose-invert prose-p:my-1 prose-headings:my-2 prose-ul:my-1 prose-ol:my-1 prose-li:my-0 prose-pre:my-2 prose-code:before:content-none prose-code:after:content-none">
62
+ {parts.map((part, index) => {
63
+ if (part.type === 'code') {
64
+ return (
65
+ <CodePreview
66
+ key={index}
67
+ code={part.content}
68
+ compiler={compiler}
69
+ services={services}
70
+ filePath={part.attributes?.path}
71
+ entrypoint="main.tsx"
72
+ />
73
+ );
74
+ }
75
+ return <Markdown key={index} remarkPlugins={[remarkGfm]}>{part.content}</Markdown>;
76
+ })}
77
+ </div>
78
+ );
79
+ }
80
+
81
+ function ReasoningPart({
82
+ text,
83
+ isStreaming,
84
+ }: {
85
+ text: string;
86
+ isStreaming?: boolean;
87
+ }) {
88
+ return (
89
+ <Collapsible defaultOpen={isStreaming}>
90
+ <CollapsibleTrigger className="flex items-center gap-2 text-yellow-700 dark:text-yellow-400 hover:opacity-80 w-full">
91
+ <Brain className="h-4 w-4" />
92
+ <span className="text-xs font-medium">Thinking</span>
93
+ {isStreaming && <Loader2 className="h-3 w-3 animate-spin" />}
94
+ <ChevronDown className="h-3 w-3 ml-auto transition-transform [[data-state=open]>&]:rotate-180" />
95
+ </CollapsibleTrigger>
96
+ <CollapsibleContent>
97
+ <div className="mt-2 p-3 rounded border-l-4 border-yellow-500 bg-yellow-50 dark:bg-yellow-950/50">
98
+ <p className="text-sm text-muted-foreground italic whitespace-pre-wrap">
99
+ {text}
100
+ </p>
101
+ </div>
102
+ </CollapsibleContent>
103
+ </Collapsible>
104
+ );
105
+ }
106
+
107
+ function ToolPart({
108
+ toolName,
109
+ state,
110
+ input,
111
+ output,
112
+ errorText,
113
+ }: {
114
+ toolName: string;
115
+ state: string;
116
+ input: unknown;
117
+ output?: unknown;
118
+ errorText?: string;
119
+ }) {
120
+ const isRunning = state === 'input-streaming' || state === 'input-available';
121
+ const hasError = state === 'output-error';
122
+
123
+ return (
124
+ <Collapsible className="my-1 w-full">
125
+ <CollapsibleTrigger className="inline-flex items-center gap-2 px-3 py-1 rounded-full border bg-muted/50 hover:bg-muted text-xs transition-colors">
126
+ <Wrench className="h-3 w-3 text-muted-foreground" />
127
+ <span className="font-mono">{toolName}</span>
128
+ <span className="w-3 h-3 flex items-center justify-center">
129
+ {isRunning && (
130
+ <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
131
+ )}
132
+ {hasError && <AlertCircle className="h-3 w-3 text-destructive" />}
133
+ </span>
134
+ <ChevronDown className="h-3 w-3 text-muted-foreground transition-transform [[data-state=open]>&]:rotate-180" />
135
+ </CollapsibleTrigger>
136
+
137
+ <CollapsibleContent className="mt-2 p-3 rounded-lg border bg-white space-y-2">
138
+ {input !== undefined && (
139
+ <div>
140
+ <span className="text-xs font-medium text-muted-foreground">
141
+ Input
142
+ </span>
143
+ <div className="mt-1 p-2 bg-muted/30 rounded text-xs overflow-auto max-h-48">
144
+ <pre className="whitespace-pre-wrap break-words m-0">
145
+ {typeof input === 'string'
146
+ ? input
147
+ : JSON.stringify(input, null, 2)}
148
+ </pre>
149
+ </div>
150
+ </div>
151
+ )}
152
+
153
+ {output !== undefined && (
154
+ <div>
155
+ <span className="text-xs font-medium text-muted-foreground">
156
+ Output
157
+ </span>
158
+ <div className="mt-1 p-2 bg-muted/30 rounded text-xs overflow-auto max-h-48">
159
+ <pre className="whitespace-pre-wrap break-words m-0">
160
+ {typeof output === 'string'
161
+ ? output
162
+ : JSON.stringify(output, null, 2)}
163
+ </pre>
164
+ </div>
165
+ </div>
166
+ )}
167
+
168
+ {errorText && (
169
+ <div className="text-sm text-destructive flex items-center gap-2">
170
+ <AlertCircle className="h-4 w-4 shrink-0" />
171
+ <span className="break-words">{errorText}</span>
172
+ </div>
173
+ )}
174
+ </CollapsibleContent>
175
+ </Collapsible>
176
+ );
177
+ }
178
+
179
+ function MessageBubble({ message }: { message: UIMessage }) {
180
+ const isUser = message.role === 'user';
181
+ const isStreaming = message.parts?.some(
182
+ (p) =>
183
+ 'state' in p &&
184
+ (p.state === 'input-streaming' || p.state === 'input-available'),
185
+ );
186
+
187
+ return (
188
+ <div className={`flex gap-3 ${isUser ? 'justify-end' : 'justify-start'}`}>
189
+ {!isUser && (
190
+ <Avatar className="h-8 w-8 shrink-0">
191
+ <img
192
+ src={APROVAN_LOGO}
193
+ alt="Assistant"
194
+ className="rounded-full"
195
+ />
196
+ <AvatarFallback className="bg-primary text-primary-foreground">
197
+ A
198
+ </AvatarFallback>
199
+ </Avatar>
200
+ )}
201
+
202
+ <div
203
+ className={`flex flex-col gap-1 max-w-[80%] min-w-0 ${
204
+ isUser ? 'items-end' : 'items-start'
205
+ }`}
206
+ >
207
+ <div className="flex items-center gap-2 h-5">
208
+ <span className="text-xs text-muted-foreground capitalize">
209
+ {message.role}
210
+ </span>
211
+ {isStreaming && (
212
+ <Badge
213
+ variant="outline"
214
+ className="text-xs"
215
+ >
216
+ <Loader2 className="h-3 w-3 mr-1 animate-spin" />
217
+ streaming
218
+ </Badge>
219
+ )}
220
+ </div>
221
+
222
+ <div
223
+ className={`rounded-lg px-4 py-2 overflow-hidden w-full ${
224
+ isUser ? 'bg-primary text-primary-foreground' : 'bg-muted'
225
+ }`}
226
+ >
227
+ {message.parts?.map((part, i) => {
228
+ if (part.type === 'text') {
229
+ return (
230
+ <TextPart
231
+ key={i}
232
+ text={part.text}
233
+ isUser={isUser}
234
+ />
235
+ );
236
+ }
237
+
238
+ if (part.type === 'reasoning') {
239
+ return (
240
+ <ReasoningPart
241
+ key={i}
242
+ text={part.text}
243
+ isStreaming={part.state === 'streaming'}
244
+ />
245
+ );
246
+ }
247
+
248
+ if (part.type.startsWith('tool-') || part.type === 'dynamic-tool') {
249
+ const toolPart = part as {
250
+ type: string;
251
+ toolName?: string;
252
+ toolCallId: string;
253
+ state: string;
254
+ input?: unknown;
255
+ output?: unknown;
256
+ errorText?: string;
257
+ };
258
+ const toolName =
259
+ toolPart.toolName ?? part.type.replace('tool-', '');
260
+ return (
261
+ <ToolPart
262
+ key={i}
263
+ toolName={toolName}
264
+ state={toolPart.state}
265
+ input={toolPart.input}
266
+ output={toolPart.output}
267
+ errorText={toolPart.errorText}
268
+ />
269
+ );
270
+ }
271
+
272
+ return null;
273
+ })}
274
+ </div>
275
+ </div>
276
+
277
+ {isUser && (
278
+ <Avatar className="h-8 w-8 shrink-0">
279
+ <AvatarFallback className="bg-secondary">U</AvatarFallback>
280
+ </Avatar>
281
+ )}
282
+ </div>
283
+ );
284
+ }
285
+
286
+ const PROXY_URL = '/api/proxy';
287
+ const IMAGE_SPEC = '@aprovan/patchwork-image-shadcn';
288
+ // Local proxy for loading image packages, esm.sh for widget imports
289
+ const IMAGE_CDN_URL = import.meta.env.DEV ? '/_local-packages' : 'https://esm.sh';
290
+ const WIDGET_CDN_URL = 'https://esm.sh'; // Widget imports need esm.sh bundles like @packagedcn
291
+
292
+ export default function ChatPage() {
293
+ const [input, setInput] = useState('What\'s the weather in Houston, Texas like?');
294
+ const [compiler, setCompiler] = useState<Compiler | null>(null);
295
+ const [namespaces, setNamespaces] = useState<string[]>([]);
296
+ const [services, setServices] = useState<ServiceInfo[]>([]);
297
+ const scrollRef = useRef<HTMLDivElement>(null);
298
+
299
+ useEffect(() => {
300
+ // Fetch available services
301
+ fetch('/api/services')
302
+ .then((res) => res.json())
303
+ .then((data) => {
304
+ setNamespaces(data.namespaces ?? []);
305
+ // In dev mode, also store full service details for inspection
306
+ if (import.meta.env.DEV && data.services) {
307
+ setServices(data.services);
308
+ }
309
+ })
310
+ .catch(() => {
311
+ setNamespaces([]);
312
+ setServices([]);
313
+ });
314
+
315
+ // Initialize compiler
316
+ createCompiler({
317
+ image: IMAGE_SPEC,
318
+ proxyUrl: PROXY_URL,
319
+ cdnBaseUrl: IMAGE_CDN_URL,
320
+ widgetCdnBaseUrl: WIDGET_CDN_URL,
321
+ })
322
+ .then(setCompiler)
323
+ .catch(console.error);
324
+ }, []);
325
+
326
+ const patchworkCtx = useMemo(() => ({ compiler, namespaces }), [compiler, namespaces]);
327
+
328
+ const transport = useMemo(
329
+ () =>
330
+ new DefaultChatTransport({
331
+ body: () => ({
332
+ metadata: {
333
+ patchwork: { compilers: [IMAGE_SPEC] },
334
+ },
335
+ }),
336
+ }),
337
+ [],
338
+ );
339
+
340
+ const { messages, sendMessage, status, error } = useChat({ transport });
341
+
342
+ const isLoading = status === 'submitted' || status === 'streaming';
343
+
344
+ const handleSubmit = useCallback((e?: React.FormEvent) => {
345
+ e?.preventDefault();
346
+ if (!input.trim()) return;
347
+ sendMessage({ text: input });
348
+ setInput('');
349
+ }, [input, sendMessage]);
350
+
351
+ useEffect(() => {
352
+ scrollRef.current?.scrollTo({
353
+ top: scrollRef.current.scrollHeight,
354
+ behavior: 'smooth',
355
+ });
356
+ }, [messages]);
357
+
358
+ return (
359
+ <PatchworkCtx.Provider value={patchworkCtx}>
360
+ <div className="flex flex-col h-screen max-w-4xl mx-auto p-4">
361
+ <Card className="flex-1 flex flex-col min-h-0 overflow-hidden border">
362
+ <CardHeader className="border-b py-3">
363
+ <CardTitle className="flex items-center gap-3">
364
+ <img
365
+ src={APROVAN_LOGO}
366
+ alt="Aprovan"
367
+ className="h-8 w-8 rounded-full"
368
+ />
369
+ <span className="text-lg">patchwork</span>
370
+ <ServicesInspector namespaces={namespaces} services={services} />
371
+ </CardTitle>
372
+ </CardHeader>
373
+
374
+ <CardContent className="flex-1 p-0 min-h-0">
375
+ <ScrollArea
376
+ className="h-full"
377
+ ref={scrollRef}
378
+ >
379
+ <div className="p-4 space-y-4">
380
+ {messages.length === 0 ? (
381
+ <div className="text-center text-muted-foreground py-12">
382
+ <img
383
+ src={APROVAN_LOGO}
384
+ alt=""
385
+ className="h-12 w-12 mx-auto mb-4 opacity-50 rounded-full"
386
+ />
387
+ <p>Start a conversation</p>
388
+ </div>
389
+ ) : (
390
+ messages.map((msg) => (
391
+ <MessageBubble
392
+ key={msg.id}
393
+ message={msg}
394
+ />
395
+ ))
396
+ )}
397
+
398
+ {isLoading &&
399
+ messages[messages.length - 1]?.role !== 'assistant' && (
400
+ <div className="flex gap-3 justify-start">
401
+ <Avatar className="h-8 w-8 shrink-0">
402
+ <img
403
+ src={APROVAN_LOGO}
404
+ alt=""
405
+ className="rounded-full"
406
+ />
407
+ <AvatarFallback>A</AvatarFallback>
408
+ </Avatar>
409
+ <div className="flex flex-col gap-1">
410
+ <div className="h-5" />
411
+ <div className="bg-muted rounded-lg px-4 py-2">
412
+ <Loader2 className="h-4 w-4 animate-spin" />
413
+ </div>
414
+ </div>
415
+ </div>
416
+ )}
417
+ </div>
418
+ </ScrollArea>
419
+ </CardContent>
420
+
421
+ {error && (
422
+ <div className="px-4 py-2 bg-destructive/10 text-destructive text-sm flex items-center gap-2">
423
+ <AlertCircle className="h-4 w-4" />
424
+ {error.message}
425
+ </div>
426
+ )}
427
+
428
+ <div className="p-4 border-t">
429
+ <form
430
+ onSubmit={handleSubmit}
431
+ className="flex gap-2 items-end"
432
+ >
433
+ <MarkdownEditor
434
+ value={input}
435
+ onChange={setInput}
436
+ onSubmit={() => {
437
+ if (!isLoading && input.trim()) {
438
+ handleSubmit();
439
+ }
440
+ }}
441
+ placeholder="Type a message... (Shift+Enter for new line)"
442
+ disabled={isLoading}
443
+ />
444
+ <Button
445
+ type="submit"
446
+ disabled={isLoading || !input.trim()}
447
+ className="shrink-0"
448
+ >
449
+ {isLoading ? (
450
+ <Loader2 className="h-4 w-4 animate-spin" />
451
+ ) : (
452
+ <Send className="h-4 w-4" />
453
+ )}
454
+ </Button>
455
+ </form>
456
+ </div>
457
+ </Card>
458
+ </div>
459
+ </PatchworkCtx.Provider>
460
+ );
461
+ }