opencami 1.0.0 → 1.2.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 (346) hide show
  1. package/README.md +69 -74
  2. package/dist/client/analytics-dashboard.html +509 -0
  3. package/dist/client/analytics.json +598 -0
  4. package/dist/client/assets/_sessionKey-xUqdePGW.js +97 -0
  5. package/dist/client/assets/agents-BiadNAEz.js +2 -0
  6. package/dist/client/assets/agents-screen-C5TPJbry.js +1 -0
  7. package/dist/client/assets/button-seqh98ae.js +1 -0
  8. package/dist/client/assets/{connect-BRasuRbB.js → connect-DlVsi-ya.js} +2 -2
  9. package/dist/client/assets/file-explorer-screen-B0hwrjdF.js +1 -0
  10. package/dist/client/assets/files-dkr2U72N.js +2 -0
  11. package/dist/client/assets/index-CwoJpeG1.js +153 -0
  12. package/dist/client/assets/{index-DHGnKfAU.js → index-D1Et4XlM.js} +1 -1
  13. package/dist/client/assets/keyboard-shortcuts-dialog-zdnAmDiH.js +1 -0
  14. package/dist/client/assets/{main-BAHT5yqU.js → main-DOBfHXDF.js} +12 -12
  15. package/dist/client/assets/opencami-logo-Bxp_4d3X.js +1 -0
  16. package/dist/client/assets/react-DD8SkMJn.js +1 -0
  17. package/dist/client/assets/search-dialog-Ck1AQreu.js +1 -0
  18. package/dist/client/assets/session-export-dialog-Bh3zH4nZ.js +1 -0
  19. package/dist/client/assets/settings-dialog-CvUsgnnZ.js +1 -0
  20. package/dist/client/assets/styles-DogPvrGY.css +1 -0
  21. package/dist/client/assets/switch-BoGcWcnr.js +1 -0
  22. package/dist/client/assets/use-file-explorer-state-B5JLNsSa.js +12 -0
  23. package/dist/client/assets/useButton-csSB2uQJ.js +9 -0
  24. package/dist/client/manifest.json +8 -2
  25. package/dist/server/assets/{_sessionKey-qlAPF_Ft.js → _sessionKey-DQwkBUS7.js} +981 -229
  26. package/dist/server/assets/_tanstack-start-manifest_v-cW8K1Mnv.js +4 -0
  27. package/dist/server/assets/agents-Dz_i76VW.js +11 -0
  28. package/dist/server/assets/agents-screen-CqQPJndp.js +587 -0
  29. package/dist/server/assets/{connect-BWI_6rCm.js → connect-CIDOw12K.js} +34 -2
  30. package/dist/server/assets/{file-explorer-screen-DJXPEG_J.js → file-explorer-screen-BzvgvV8m.js} +7 -58
  31. package/dist/server/assets/{files-CONoVTGD.js → files-BxvRDIWU.js} +1 -1
  32. package/dist/server/assets/{index-Bp8QskbI.js → index-BwD7ufHE.js} +4 -3
  33. package/dist/server/assets/{index-COu2idHm.js → index-CmbNTqa2.js} +105 -14
  34. package/dist/server/assets/{keyboard-shortcuts-dialog-D5hqVX2v.js → keyboard-shortcuts-dialog-7OEtXUlW.js} +2 -2
  35. package/dist/server/assets/opencami-logo-C-43FL3R.js +24 -0
  36. package/dist/server/assets/{router-DbxyvprK.js → router-5qObg5aX.js} +368 -74
  37. package/dist/server/assets/{search-dialog-JY8C3mqa.js → search-dialog-BE2ZBkj0.js} +44 -12
  38. package/dist/server/assets/{session-export-dialog-D87uafPD.js → session-export-dialog-DRVbC8Q-.js} +2 -2
  39. package/dist/server/assets/{settings-dialog-CBj7njLM.js → settings-dialog-BBQcU55J.js} +204 -41
  40. package/dist/server/assets/switch-DnX0MjGS.js +28 -0
  41. package/dist/server/assets/tooltip-gbV6rEVv.js +60 -0
  42. package/dist/server/assets/{menu-D6n4DB0U.js → use-file-explorer-state-DMHdtb7D.js} +56 -57
  43. package/dist/server/server.js +2 -2
  44. package/package.json +1 -1
  45. package/dist/client/assets/_sessionKey-B-MBYHgD.js +0 -95
  46. package/dist/client/assets/abap-BdImnpbu.js +0 -1
  47. package/dist/client/assets/actionscript-3-CfeIJUat.js +0 -1
  48. package/dist/client/assets/ada-bCR0ucgS.js +0 -1
  49. package/dist/client/assets/andromeeda-C-Jbm3Hp.js +0 -1
  50. package/dist/client/assets/angular-html-CU67Zn6k.js +0 -1
  51. package/dist/client/assets/angular-ts-BwZT4LLn.js +0 -1
  52. package/dist/client/assets/apache-Pmp26Uib.js +0 -1
  53. package/dist/client/assets/apex-D8_7TLub.js +0 -1
  54. package/dist/client/assets/apl-dKokRX4l.js +0 -1
  55. package/dist/client/assets/applescript-Co6uUVPk.js +0 -1
  56. package/dist/client/assets/ara-BRHolxvo.js +0 -1
  57. package/dist/client/assets/asciidoc-Dv7Oe6Be.js +0 -1
  58. package/dist/client/assets/asm-D_Q5rh1f.js +0 -1
  59. package/dist/client/assets/astro-CbQHKStN.js +0 -1
  60. package/dist/client/assets/aurora-x-D-2ljcwZ.js +0 -1
  61. package/dist/client/assets/awk-DMzUqQB5.js +0 -1
  62. package/dist/client/assets/ayu-dark-CmMr59Fi.js +0 -1
  63. package/dist/client/assets/ballerina-BFfxhgS-.js +0 -1
  64. package/dist/client/assets/bat-BkioyH1T.js +0 -1
  65. package/dist/client/assets/beancount-k_qm7-4y.js +0 -1
  66. package/dist/client/assets/berry-uYugtg8r.js +0 -1
  67. package/dist/client/assets/bibtex-CHM0blh-.js +0 -1
  68. package/dist/client/assets/bicep-Bmn6On1c.js +0 -1
  69. package/dist/client/assets/blade-D4QpJJKB.js +0 -1
  70. package/dist/client/assets/bsl-BO_Y6i37.js +0 -1
  71. package/dist/client/assets/button-D_9OBT_f.js +0 -1
  72. package/dist/client/assets/c-BIGW1oBm.js +0 -1
  73. package/dist/client/assets/c3-VCDPK7BO.js +0 -1
  74. package/dist/client/assets/cadence-Bv_4Rxtq.js +0 -1
  75. package/dist/client/assets/cairo-KRGpt6FW.js +0 -1
  76. package/dist/client/assets/catppuccin-frappe-DFWUc33u.js +0 -1
  77. package/dist/client/assets/catppuccin-latte-C9dUb6Cb.js +0 -1
  78. package/dist/client/assets/catppuccin-macchiato-DQyhUUbL.js +0 -1
  79. package/dist/client/assets/catppuccin-mocha-D87Tk5Gz.js +0 -1
  80. package/dist/client/assets/clarity-D53aC0YG.js +0 -1
  81. package/dist/client/assets/clojure-P80f7IUj.js +0 -1
  82. package/dist/client/assets/cmake-D1j8_8rp.js +0 -1
  83. package/dist/client/assets/cobol-nwyudZeR.js +0 -1
  84. package/dist/client/assets/codeowners-Bp6g37R7.js +0 -1
  85. package/dist/client/assets/codeql-DsOJ9woJ.js +0 -1
  86. package/dist/client/assets/coffee-Ch7k5sss.js +0 -1
  87. package/dist/client/assets/common-lisp-Cg-RD9OK.js +0 -1
  88. package/dist/client/assets/coq-DkFqJrB1.js +0 -1
  89. package/dist/client/assets/cpp-CofmeUqb.js +0 -1
  90. package/dist/client/assets/crystal-tKQVLTB8.js +0 -1
  91. package/dist/client/assets/csharp-K5feNrxe.js +0 -1
  92. package/dist/client/assets/css-DPfMkruS.js +0 -1
  93. package/dist/client/assets/csv-fuZLfV_i.js +0 -1
  94. package/dist/client/assets/cue-D82EKSYY.js +0 -1
  95. package/dist/client/assets/cypher-COkxafJQ.js +0 -1
  96. package/dist/client/assets/d-85-TOEBH.js +0 -1
  97. package/dist/client/assets/dark-plus-C3mMm8J8.js +0 -1
  98. package/dist/client/assets/dart-CF10PKvl.js +0 -1
  99. package/dist/client/assets/dax-CEL-wOlO.js +0 -1
  100. package/dist/client/assets/desktop-BmXAJ9_W.js +0 -1
  101. package/dist/client/assets/diff-D97Zzqfu.js +0 -1
  102. package/dist/client/assets/docker-BcOcwvcX.js +0 -1
  103. package/dist/client/assets/dotenv-Da5cRb03.js +0 -1
  104. package/dist/client/assets/dracula-BzJJZx-M.js +0 -1
  105. package/dist/client/assets/dracula-soft-BXkSAIEj.js +0 -1
  106. package/dist/client/assets/dream-maker-BtqSS_iP.js +0 -1
  107. package/dist/client/assets/edge-BkV0erSs.js +0 -1
  108. package/dist/client/assets/elixir-CDX3lj18.js +0 -1
  109. package/dist/client/assets/elm-DbKCFpqz.js +0 -1
  110. package/dist/client/assets/emacs-lisp-C9XAeP06.js +0 -1
  111. package/dist/client/assets/erb-BOJIQeun.js +0 -1
  112. package/dist/client/assets/erlang-DsQrWhSR.js +0 -1
  113. package/dist/client/assets/everforest-dark-BgDCqdQA.js +0 -1
  114. package/dist/client/assets/everforest-light-C8M2exoo.js +0 -1
  115. package/dist/client/assets/fennel-BYunw83y.js +0 -1
  116. package/dist/client/assets/file-explorer-screen-Daf4rIq9.js +0 -1
  117. package/dist/client/assets/files-ByeIMLfw.js +0 -2
  118. package/dist/client/assets/fish-BvzEVeQv.js +0 -1
  119. package/dist/client/assets/fluent-C4IJs8-o.js +0 -1
  120. package/dist/client/assets/fortran-fixed-form-CkoXwp7k.js +0 -1
  121. package/dist/client/assets/fortran-free-form-BxgE0vQu.js +0 -1
  122. package/dist/client/assets/fsharp-CXgrBDvD.js +0 -1
  123. package/dist/client/assets/gdresource-B7Tvp0Sc.js +0 -1
  124. package/dist/client/assets/gdscript-DTMYz4Jt.js +0 -1
  125. package/dist/client/assets/gdshader-DkwncUOv.js +0 -1
  126. package/dist/client/assets/genie-D0YGMca9.js +0 -1
  127. package/dist/client/assets/gherkin-DyxjwDmM.js +0 -1
  128. package/dist/client/assets/git-commit-F4YmCXRG.js +0 -1
  129. package/dist/client/assets/git-rebase-r7XF79zn.js +0 -1
  130. package/dist/client/assets/github-dark-DHJKELXO.js +0 -1
  131. package/dist/client/assets/github-dark-default-Cuk6v7N8.js +0 -1
  132. package/dist/client/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
  133. package/dist/client/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
  134. package/dist/client/assets/github-light-DAi9KRSo.js +0 -1
  135. package/dist/client/assets/github-light-default-D7oLnXFd.js +0 -1
  136. package/dist/client/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
  137. package/dist/client/assets/gleam-BspZqrRM.js +0 -1
  138. package/dist/client/assets/glimmer-js-Rg0-pVw9.js +0 -1
  139. package/dist/client/assets/glimmer-ts-U6CK756n.js +0 -1
  140. package/dist/client/assets/glsl-DplSGwfg.js +0 -1
  141. package/dist/client/assets/gn-n2N0HUVH.js +0 -1
  142. package/dist/client/assets/gnuplot-DdkO51Og.js +0 -1
  143. package/dist/client/assets/go-Dn2_MT6a.js +0 -1
  144. package/dist/client/assets/graphql-ChdNCCLP.js +0 -1
  145. package/dist/client/assets/groovy-gcz8RCvz.js +0 -1
  146. package/dist/client/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -1
  147. package/dist/client/assets/gruvbox-dark-medium-GsRaNv29.js +0 -1
  148. package/dist/client/assets/gruvbox-dark-soft-CVdnzihN.js +0 -1
  149. package/dist/client/assets/gruvbox-light-hard-CH1njM8p.js +0 -1
  150. package/dist/client/assets/gruvbox-light-medium-DRw_LuNl.js +0 -1
  151. package/dist/client/assets/gruvbox-light-soft-hJgmCMqR.js +0 -1
  152. package/dist/client/assets/hack-CaT9iCJl.js +0 -1
  153. package/dist/client/assets/haml-B8DHNrY2.js +0 -1
  154. package/dist/client/assets/handlebars-BL8al0AC.js +0 -1
  155. package/dist/client/assets/haskell-Df6bDoY_.js +0 -1
  156. package/dist/client/assets/haxe-CzTSHFRz.js +0 -1
  157. package/dist/client/assets/hcl-BWvSN4gD.js +0 -1
  158. package/dist/client/assets/hjson-D5-asLiD.js +0 -1
  159. package/dist/client/assets/hlsl-D3lLCCz7.js +0 -1
  160. package/dist/client/assets/houston-DnULxvSX.js +0 -1
  161. package/dist/client/assets/html-GMplVEZG.js +0 -1
  162. package/dist/client/assets/html-derivative-BFtXZ54Q.js +0 -1
  163. package/dist/client/assets/http-jrhK8wxY.js +0 -1
  164. package/dist/client/assets/hurl-irOxFIW8.js +0 -1
  165. package/dist/client/assets/hxml-Bvhsp5Yf.js +0 -1
  166. package/dist/client/assets/hy-DFXneXwc.js +0 -1
  167. package/dist/client/assets/imba-DGztddWO.js +0 -1
  168. package/dist/client/assets/index-ByUDBI-n.js +0 -14
  169. package/dist/client/assets/ini-BEwlwnbL.js +0 -1
  170. package/dist/client/assets/java-CylS5w8V.js +0 -1
  171. package/dist/client/assets/javascript-wDzz0qaB.js +0 -1
  172. package/dist/client/assets/jinja-4LBKfQ-Z.js +0 -1
  173. package/dist/client/assets/jison-wvAkD_A8.js +0 -1
  174. package/dist/client/assets/json-Cp-IABpG.js +0 -1
  175. package/dist/client/assets/json5-C9tS-k6U.js +0 -1
  176. package/dist/client/assets/jsonc-Des-eS-w.js +0 -1
  177. package/dist/client/assets/jsonl-DcaNXYhu.js +0 -1
  178. package/dist/client/assets/jsonnet-DFQXde-d.js +0 -1
  179. package/dist/client/assets/jssm-C2t-YnRu.js +0 -1
  180. package/dist/client/assets/jsx-g9-lgVsj.js +0 -1
  181. package/dist/client/assets/julia-CxzCAyBv.js +0 -1
  182. package/dist/client/assets/kanagawa-dragon-CkXjmgJE.js +0 -1
  183. package/dist/client/assets/kanagawa-lotus-CfQXZHmo.js +0 -1
  184. package/dist/client/assets/kanagawa-wave-DWedfzmr.js +0 -1
  185. package/dist/client/assets/kdl-DV7GczEv.js +0 -1
  186. package/dist/client/assets/keyboard-shortcuts-dialog-agsWJ36q.js +0 -1
  187. package/dist/client/assets/kotlin-BdnUsdx6.js +0 -1
  188. package/dist/client/assets/kusto-DZf3V79B.js +0 -1
  189. package/dist/client/assets/laserwave-DUszq2jm.js +0 -1
  190. package/dist/client/assets/latex-B4uzh10-.js +0 -1
  191. package/dist/client/assets/lean-BZvkOJ9d.js +0 -1
  192. package/dist/client/assets/less-B1dDrJ26.js +0 -1
  193. package/dist/client/assets/light-plus-B7mTdjB0.js +0 -1
  194. package/dist/client/assets/liquid-DYVedYrR.js +0 -1
  195. package/dist/client/assets/llvm-BtvRca6l.js +0 -1
  196. package/dist/client/assets/log-2UxHyX5q.js +0 -1
  197. package/dist/client/assets/logo-BtOb2qkB.js +0 -1
  198. package/dist/client/assets/lua-BbnMAYS6.js +0 -1
  199. package/dist/client/assets/luau-C-HG3fhB.js +0 -1
  200. package/dist/client/assets/make-CHLpvVh8.js +0 -1
  201. package/dist/client/assets/markdown-Cvjx9yec.js +0 -1
  202. package/dist/client/assets/marko-DZsq8hO1.js +0 -1
  203. package/dist/client/assets/material-theme-D5KoaKCx.js +0 -1
  204. package/dist/client/assets/material-theme-darker-BfHTSMKl.js +0 -1
  205. package/dist/client/assets/material-theme-lighter-B0m2ddpp.js +0 -1
  206. package/dist/client/assets/material-theme-ocean-CyktbL80.js +0 -1
  207. package/dist/client/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
  208. package/dist/client/assets/matlab-D7o27uSR.js +0 -1
  209. package/dist/client/assets/mdc-DUICxH0z.js +0 -1
  210. package/dist/client/assets/mdx-Cmh6b_Ma.js +0 -1
  211. package/dist/client/assets/menu-BhVaz8Ly.js +0 -20
  212. package/dist/client/assets/mermaid-mWjccvbQ.js +0 -1
  213. package/dist/client/assets/min-dark-CafNBF8u.js +0 -1
  214. package/dist/client/assets/min-light-CTRr51gU.js +0 -1
  215. package/dist/client/assets/mipsasm-CKIfxQSi.js +0 -1
  216. package/dist/client/assets/mojo-B93PlW-d.js +0 -1
  217. package/dist/client/assets/monokai-D4h5O-jR.js +0 -1
  218. package/dist/client/assets/moonbit-Ba13S78F.js +0 -1
  219. package/dist/client/assets/move-Bu9oaDYs.js +0 -1
  220. package/dist/client/assets/narrat-DRg8JJMk.js +0 -1
  221. package/dist/client/assets/nextflow-BrzmwbiE.js +0 -1
  222. package/dist/client/assets/nginx-DknmC5AR.js +0 -1
  223. package/dist/client/assets/night-owl-C39BiMTA.js +0 -1
  224. package/dist/client/assets/nim-CVrawwO9.js +0 -1
  225. package/dist/client/assets/nix-CwoSXNpI.js +0 -1
  226. package/dist/client/assets/nord-Ddv68eIx.js +0 -1
  227. package/dist/client/assets/nushell-C-sUppwS.js +0 -1
  228. package/dist/client/assets/objective-c-DXmwc3jG.js +0 -1
  229. package/dist/client/assets/objective-cpp-CLxacb5B.js +0 -1
  230. package/dist/client/assets/ocaml-C0hk2d4L.js +0 -1
  231. package/dist/client/assets/one-dark-pro-DVMEJ2y_.js +0 -1
  232. package/dist/client/assets/one-light-PoHY5YXO.js +0 -1
  233. package/dist/client/assets/openscad-C4EeE6gA.js +0 -1
  234. package/dist/client/assets/pascal-D93ZcfNL.js +0 -1
  235. package/dist/client/assets/perl-C0TMdlhV.js +0 -1
  236. package/dist/client/assets/php-CDn_0X-4.js +0 -1
  237. package/dist/client/assets/pkl-u5AG7uiY.js +0 -1
  238. package/dist/client/assets/plastic-3e1v2bzS.js +0 -1
  239. package/dist/client/assets/plsql-ChMvpjG-.js +0 -1
  240. package/dist/client/assets/po-BTJTHyun.js +0 -1
  241. package/dist/client/assets/poimandres-CS3Unz2-.js +0 -1
  242. package/dist/client/assets/polar-C0HS_06l.js +0 -1
  243. package/dist/client/assets/postcss-CXtECtnM.js +0 -1
  244. package/dist/client/assets/powerquery-CEu0bR-o.js +0 -1
  245. package/dist/client/assets/powershell-Dpen1YoG.js +0 -1
  246. package/dist/client/assets/prisma-Dd19v3D-.js +0 -1
  247. package/dist/client/assets/prolog-CbFg5uaA.js +0 -1
  248. package/dist/client/assets/proto-C7zT0LnQ.js +0 -1
  249. package/dist/client/assets/pug-CGlum2m_.js +0 -1
  250. package/dist/client/assets/puppet-BMWR74SV.js +0 -1
  251. package/dist/client/assets/purescript-CklMAg4u.js +0 -1
  252. package/dist/client/assets/python-B6aJPvgy.js +0 -1
  253. package/dist/client/assets/qml-3beO22l8.js +0 -1
  254. package/dist/client/assets/qmldir-C8lEn-DE.js +0 -1
  255. package/dist/client/assets/qss-IeuSbFQv.js +0 -1
  256. package/dist/client/assets/r-Dspwwk_N.js +0 -1
  257. package/dist/client/assets/racket-BqYA7rlc.js +0 -1
  258. package/dist/client/assets/raku-DXvB9xmW.js +0 -1
  259. package/dist/client/assets/razor-C1TweQQi.js +0 -1
  260. package/dist/client/assets/red-bN70gL4F.js +0 -1
  261. package/dist/client/assets/reg-C-SQnVFl.js +0 -1
  262. package/dist/client/assets/regexp-CDVJQ6XC.js +0 -1
  263. package/dist/client/assets/rel-C3B-1QV4.js +0 -1
  264. package/dist/client/assets/riscv-BM1_JUlF.js +0 -1
  265. package/dist/client/assets/rose-pine-dawn-DHQR4-dF.js +0 -1
  266. package/dist/client/assets/rose-pine-moon-D4_iv3hh.js +0 -1
  267. package/dist/client/assets/rose-pine-qdsjHGoJ.js +0 -1
  268. package/dist/client/assets/rosmsg-BJDFO7_C.js +0 -1
  269. package/dist/client/assets/rst-B0xPkSld.js +0 -1
  270. package/dist/client/assets/ruby-BvKwtOVI.js +0 -1
  271. package/dist/client/assets/rust-B1yitclQ.js +0 -1
  272. package/dist/client/assets/sas-cz2c8ADy.js +0 -1
  273. package/dist/client/assets/sass-Cj5Yp3dK.js +0 -1
  274. package/dist/client/assets/scala-C151Ov-r.js +0 -1
  275. package/dist/client/assets/scheme-C98Dy4si.js +0 -1
  276. package/dist/client/assets/scss-OYdSNvt2.js +0 -1
  277. package/dist/client/assets/sdbl-DVxCFoDh.js +0 -1
  278. package/dist/client/assets/search-dialog-CHwnOyPS.js +0 -1
  279. package/dist/client/assets/session-export-dialog-uOlDUzgX.js +0 -1
  280. package/dist/client/assets/settings-dialog-D0aYDkAM.js +0 -1
  281. package/dist/client/assets/shaderlab-Dg9Lc6iA.js +0 -1
  282. package/dist/client/assets/shellscript-Yzrsuije.js +0 -1
  283. package/dist/client/assets/shellsession-BADoaaVG.js +0 -1
  284. package/dist/client/assets/slack-dark-BthQWCQV.js +0 -1
  285. package/dist/client/assets/slack-ochin-DqwNpetd.js +0 -1
  286. package/dist/client/assets/smalltalk-BERRCDM3.js +0 -1
  287. package/dist/client/assets/snazzy-light-Bw305WKR.js +0 -1
  288. package/dist/client/assets/solarized-dark-DXbdFlpD.js +0 -1
  289. package/dist/client/assets/solarized-light-L9t79GZl.js +0 -1
  290. package/dist/client/assets/solidity-rGO070M0.js +0 -1
  291. package/dist/client/assets/soy-Brmx7dQM.js +0 -1
  292. package/dist/client/assets/sparql-rVzFXLq3.js +0 -1
  293. package/dist/client/assets/splunk-BtCnVYZw.js +0 -1
  294. package/dist/client/assets/sql-BLtJtn59.js +0 -1
  295. package/dist/client/assets/ssh-config-_ykCGR6B.js +0 -1
  296. package/dist/client/assets/stata-BH5u7GGu.js +0 -1
  297. package/dist/client/assets/styles-7aVSlb6l.css +0 -1
  298. package/dist/client/assets/stylus-BEDo0Tqx.js +0 -1
  299. package/dist/client/assets/svelte-zxCyuUbr.js +0 -1
  300. package/dist/client/assets/swift-Dg5xB15N.js +0 -1
  301. package/dist/client/assets/synthwave-84-CbfX1IO0.js +0 -1
  302. package/dist/client/assets/system-verilog-CnnmHF94.js +0 -1
  303. package/dist/client/assets/systemd-4A_iFExJ.js +0 -1
  304. package/dist/client/assets/talonscript-CkByrt1z.js +0 -1
  305. package/dist/client/assets/tasl-QIJgUcNo.js +0 -1
  306. package/dist/client/assets/tcl-dwOrl1Do.js +0 -1
  307. package/dist/client/assets/templ-W15q3VgB.js +0 -1
  308. package/dist/client/assets/terraform-BETggiCN.js +0 -1
  309. package/dist/client/assets/tex-CvyZ59Mk.js +0 -1
  310. package/dist/client/assets/tokyo-night-hegEt444.js +0 -1
  311. package/dist/client/assets/toml-vGWfd6FD.js +0 -1
  312. package/dist/client/assets/ts-tags-zn1MmPIZ.js +0 -1
  313. package/dist/client/assets/tsv-B_m7g4N7.js +0 -1
  314. package/dist/client/assets/tsx-COt5Ahok.js +0 -1
  315. package/dist/client/assets/turtle-BsS91CYL.js +0 -1
  316. package/dist/client/assets/twig-CO9l9SDP.js +0 -1
  317. package/dist/client/assets/typescript-BPQ3VLAy.js +0 -1
  318. package/dist/client/assets/typespec-BGHnOYBU.js +0 -1
  319. package/dist/client/assets/typst-DHCkPAjA.js +0 -1
  320. package/dist/client/assets/v-BcVCzyr7.js +0 -1
  321. package/dist/client/assets/vala-CsfeWuGM.js +0 -1
  322. package/dist/client/assets/vb-D17OF-Vu.js +0 -1
  323. package/dist/client/assets/verilog-BQ8w6xss.js +0 -1
  324. package/dist/client/assets/vesper-DU1UobuO.js +0 -1
  325. package/dist/client/assets/vhdl-CeAyd5Ju.js +0 -1
  326. package/dist/client/assets/viml-CJc9bBzg.js +0 -1
  327. package/dist/client/assets/vitesse-black-Bkuqu6BP.js +0 -1
  328. package/dist/client/assets/vitesse-dark-D0r3Knsf.js +0 -1
  329. package/dist/client/assets/vitesse-light-CVO1_9PV.js +0 -1
  330. package/dist/client/assets/vue-DN_0RTcg.js +0 -1
  331. package/dist/client/assets/vue-html-AaS7Mt5G.js +0 -1
  332. package/dist/client/assets/vue-vine-CQOfvN7w.js +0 -1
  333. package/dist/client/assets/vyper-CDx5xZoG.js +0 -1
  334. package/dist/client/assets/wasm-CG6Dc4jp.js +0 -1
  335. package/dist/client/assets/wasm-MzD3tlZU.js +0 -1
  336. package/dist/client/assets/wenyan-BV7otONQ.js +0 -1
  337. package/dist/client/assets/wgsl-Dx-B1_4e.js +0 -1
  338. package/dist/client/assets/wikitext-BhOHFoWU.js +0 -1
  339. package/dist/client/assets/wit-5i3qLPDT.js +0 -1
  340. package/dist/client/assets/wolfram-lXgVvXCa.js +0 -1
  341. package/dist/client/assets/xml-sdJ4AIDG.js +0 -1
  342. package/dist/client/assets/xsl-CtQFsRM5.js +0 -1
  343. package/dist/client/assets/yaml-Buea-lGh.js +0 -1
  344. package/dist/client/assets/zenscript-DVFEvuxE.js +0 -1
  345. package/dist/client/assets/zig-VOosw3JB.js +0 -1
  346. package/dist/server/assets/_tanstack-start-manifest_v-El8F-kd-.js +0 -4
package/README.md CHANGED
@@ -1,111 +1,106 @@
1
1
  # OpenCami 🦎
2
2
 
3
- > **Web chat client for [OpenClaw](https://github.com/openclaw/openclaw)** — AI chat interface with PWA support, smart titles, voice playback & more.
3
+ A beautiful web client for [OpenClaw](https://github.com/openclaw/openclaw).
4
4
 
5
- Forked from [WebClaw](https://github.com/ibelick/webclaw).
5
+ ```bash
6
+ npm install -g opencami
7
+ opencami
8
+ ```
6
9
 
7
- [![OpenCami](https://img.shields.io/badge/OpenCami-🦎-green)](https://opencami.xyz)
10
+ [![npm](https://img.shields.io/npm/v/opencami)](https://www.npmjs.com/package/opencami)
8
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
9
12
 
10
13
  ![OpenCami Chat Interface](docs/screenshots/opencami-chat.jpg)
11
14
 
12
- ## Features
13
-
14
- **Core:**
15
- 💬 Multi-session chat · 🎨 Theme support · ⚙️ Settings dialog · 📝 Markdown rendering · 📱 Mobile-responsive
16
-
17
- **Communication:**
18
- ⚡ Real-time streaming · 🔊 Voice playback (TTS)
15
+ ## Quick Start
19
16
 
20
- **Organization:**
21
- 📁 Session folders · 🦎 OpenCami chat folder · 📌 Pin sessions · 🗑️ Bulk delete · 🛡️ Protected sessions
17
+ Install globally and run:
22
18
 
23
- **Search & Navigation:**
24
- 🔍 Conversation search · ⌨️ Keyboard shortcuts · 📥 Export conversations
25
-
26
- **Customization:**
27
- 🎨 Model selector · 🎭 Persona picker · 🦎 Chameleon theme · 🔤 Text size control
19
+ ```bash
20
+ npm install -g opencami
21
+ opencami
22
+ ```
28
23
 
29
- **Files:**
30
- 📂 File explorer · 🖼️ Image attachments
24
+ That's it. Opens your browser to the chat interface.
31
25
 
32
- **Smart Features:**
33
- 🏷️ Smart titles · 💡 Smart follow-ups · 💬 Slash commands
26
+ ### Options
34
27
 
35
- **Mobile:**
36
- 👉 Swipe gestures · ⚡ Lazy loading · 📱 Native Android APK (Capacitor)
28
+ | Flag | Description | Default |
29
+ |------|-------------|---------|
30
+ | `--port` | Port to serve on | `3000` |
31
+ | `--gateway` | OpenClaw gateway URL | `ws://127.0.0.1:18789` |
32
+ | `--host` | Bind address | `localhost` |
33
+ | `--no-open` | Don't open browser | — |
37
34
 
38
- **PWA:**
39
- 📱 Install as app · 🔄 Offline support · 🚀 Auto-update
35
+ ### Docker
40
36
 
41
- → **[See detailed feature descriptions in docs/features.md](docs/features.md)**
37
+ ```bash
38
+ docker build -t opencami .
39
+ docker run -p 3000:3000 opencami
40
+ ```
42
41
 
43
- ## 🚀 Quick Start
42
+ ## Features
43
+
44
+ ⚡ **Real-time streaming** — persistent WebSocket + SSE, token-by-token\
45
+ 🔍 **Conversation search** — current session (⌘F) and global (⌘⇧F)\
46
+ 🔊 **Voice playback (TTS)** — ElevenLabs → OpenAI → Edge TTS fallback chain\
47
+ 🎤 **Voice input (STT)** — ElevenLabs Scribe → OpenAI Whisper → Browser Web Speech API\
48
+ 🔧 **TTS/STT provider selection** — choose provider and voice in Settings\
49
+ 📂 **File explorer** — 30+ file types, built-in editor, path jailing\
50
+ 🎭 **Persona picker** — 20 personas, integrated with the personas skill\
51
+ 🤖 **Agent manager** — sidebar panel for managing agents\
52
+ 🎨 **Model selector** — switch models on the fly\
53
+ 🏷️ **Smart titles** — LLM-generated session titles\
54
+ 💡 **Smart follow-ups** — contextual suggestions after each response\
55
+ 🖼️ **Image attachments** — with compression for the 512KB WS limit\
56
+ 🔎 **Search sources badge** — expandable badge with favicons for search results\
57
+ 📁 **Session folders** — grouped by kind (chats, subagents, cron, other)\
58
+ 📌 **Pin sessions** — pinned always on top\
59
+ 📥 **Export** — Markdown, JSON, or plain text\
60
+ 🔤 **Text size** — S / M / L / XL\
61
+ 🦎 **Chameleon theme** — adaptive color scheme\
62
+ 📱 **PWA** — installable, offline shell, auto-update\
63
+ ⌨️ **Keyboard shortcuts** — full keyboard navigation\
64
+ 💬 **Slash commands** — inline help and actions
65
+
66
+ ## Development
44
67
 
45
68
  ```bash
46
- # Clone
47
69
  git clone https://github.com/robbyczgw-cla/opencami.git
48
70
  cd opencami
49
-
50
- # Install
51
71
  npm install
52
-
53
- # Configure
54
72
  cp .env.example .env.local
55
- # Edit .env.local with your Gateway URL and token
56
-
57
- # Run
58
73
  npm run dev
59
74
  ```
60
75
 
61
- Open http://localhost:3001
62
-
63
- ## 📱 Install as PWA
64
-
65
- 1. Open OpenCami in your browser
66
- 2. **Android:** Tap ⋮ menu → "Install app" or "Add to Home Screen"
67
- 3. **iOS:** Tap Share → "Add to Home Screen"
76
+ Then open the URL printed by Vite in your terminal.
68
77
 
69
- ## 📚 Documentation
78
+ > Dev port notes: this repo's `npm run dev` script uses port `3002`. If you run Vite directly with the config default, it targets `3003` and auto-falls back to the next free port.
70
79
 
71
- - **[Features](docs/features.md)** — Detailed feature descriptions
72
- - **[Architecture](docs/architecture.md)** — Technical overview
73
- - **[Deployment](docs/deployment.md)** — Self-hosting guide
74
- - **[Contributing](docs/contributing.md)** — Development workflow
75
- - **[Changelog](docs/changelog.md)** — Version history
80
+ ## Documentation
76
81
 
77
- ## 🔄 Upstream Contributions
82
+ - [Features](docs/features.md)
83
+ - [Architecture](docs/architecture.md)
84
+ - [Deployment](docs/deployment.md)
85
+ - [Contributing](docs/contributing.md)
86
+ - [Changelog](CHANGELOG.md)
78
87
 
79
- PRs submitted to [ibelick/webclaw](https://github.com/ibelick/webclaw):
80
- - ✅ [PR #1](https://github.com/ibelick/webclaw/pull/1) — Locale fix (MERGED)
81
- - ⏳ [PR #4](https://github.com/ibelick/webclaw/pull/4) — Image attachments
82
- - ⏳ [PR #9](https://github.com/ibelick/webclaw/pull/9) — Conversation search
83
- - ⏳ [PR #10](https://github.com/ibelick/webclaw/pull/10) — Conversation export
84
- - ⏳ [PR #11](https://github.com/ibelick/webclaw/pull/11) — Text size setting
88
+ ## Credits
85
89
 
86
- ## 🗺️ Roadmap
90
+ Built on top of [WebClaw](https://github.com/ibelick/webclaw) by [@ibelick](https://github.com/ibelick).
87
91
 
88
- - [x] 🔊 Voice Playback (multi-provider TTS)
89
- - [x] 🎭 Persona Picker
90
- - [x] 🎨 Model Selector
91
- - [x] 📱 PWA Support
92
- - [x] ⚡ Real-Time Streaming
93
- - [x] 📂 File Explorer
94
- - [ ] 🔔 Push Notifications (PWA)
95
- - [ ] 🎤 Voice Input (Whisper transcription)
96
- - [ ] 📎 File Uploads (PDFs, docs, code)
97
- - [ ] 📊 Usage Dashboard
92
+ File Explorer by [@balin-ar](https://github.com/balin-ar) ([PR #2](https://github.com/ibelick/webclaw/pull/2)).
98
93
 
99
- ## 🙏 Credits
94
+ Dockerfile by [@deblanco](https://github.com/deblanco) ([PR #7](https://github.com/ibelick/webclaw/pull/7)).
100
95
 
101
- - **[WebClaw](https://github.com/ibelick/webclaw)** by [Julien Thibeaut](https://github.com/ibelick) — Original project
102
- - **[balin-ar](https://github.com/balin-ar)** — File Explorer with built-in text editor ([PR #2](https://github.com/ibelick/webclaw/pull/2))
103
- - **[OpenClaw](https://github.com/openclaw/openclaw)** — The gateway that powers it all
96
+ Powered by [OpenClaw](https://github.com/openclaw/openclaw).
104
97
 
105
- ## 📄 License
98
+ ## Links
106
99
 
107
- MIT See [LICENSE](LICENSE)
100
+ - 🌐 [opencami.xyz](https://opencami.xyz)
101
+ - 📦 [npm](https://www.npmjs.com/package/opencami)
102
+ - 💻 [GitHub](https://github.com/robbyczgw-cla/opencami)
108
103
 
109
- ---
104
+ ## License
110
105
 
111
- 🌐 **[opencami.xyz](https://opencami.xyz)** · Built with 💚 by the OpenCami community
106
+ [MIT](LICENSE)
@@ -0,0 +1,509 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>OpenCami Analytics 🦎</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;700&family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
+ <style>
10
+ :root {
11
+ --bg-primary: #0a0a0f;
12
+ --bg-card: #12121a;
13
+ --bg-card-hover: #181824;
14
+ --bg-row-hover: #1a1a28;
15
+ --border: #1e1e2e;
16
+ --text-primary: #e8e8ed;
17
+ --text-secondary: #6b6b7b;
18
+ --text-muted: #3a3a4a;
19
+ --accent-cyan: #00e5ff;
20
+ --accent-amber: #ffab00;
21
+ --accent-emerald: #00e676;
22
+ --accent-rose: #ff5272;
23
+ --accent-violet: #b388ff;
24
+ --accent-blue: #40c4ff;
25
+ --accent-orange: #ff9100;
26
+ --font-sans: 'Outfit', sans-serif;
27
+ --font-mono: 'JetBrains Mono', monospace;
28
+ }
29
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
30
+ body {
31
+ background: var(--bg-primary);
32
+ color: var(--text-primary);
33
+ font-family: var(--font-sans);
34
+ line-height: 1.5;
35
+ min-height: 100vh;
36
+ overflow-x: hidden;
37
+ }
38
+ .container { max-width: 1480px; margin: 0 auto; padding: 1.5rem; }
39
+
40
+ .header {
41
+ display: flex; justify-content: space-between; align-items: baseline;
42
+ margin-bottom: 2rem; padding-bottom: 1rem;
43
+ border-bottom: 1px solid var(--border);
44
+ }
45
+ .header h1 { font-size: 1.5rem; font-weight: 600; letter-spacing: -0.02em; }
46
+ .header h1 span { color: var(--accent-cyan); }
47
+ .header .meta { text-align: right; }
48
+ .header .updated { font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-secondary); }
49
+ .header .date-range { font-size: 0.8rem; color: var(--text-secondary); margin-top: 0.15rem; }
50
+
51
+ /* Hero Stats - 5 cards */
52
+ .hero-stats {
53
+ display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.75rem;
54
+ margin-bottom: 1.5rem;
55
+ }
56
+ .stat-card {
57
+ background: var(--bg-card); border: 1px solid var(--border);
58
+ border-radius: 10px; padding: 1.2rem 1rem;
59
+ position: relative; overflow: hidden;
60
+ opacity: 0; transform: translateY(12px);
61
+ animation: cardIn 0.4s ease forwards;
62
+ }
63
+ .stat-card::before {
64
+ content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
65
+ }
66
+ .stat-card:nth-child(1)::before { background: var(--accent-cyan); }
67
+ .stat-card:nth-child(2)::before { background: var(--accent-amber); }
68
+ .stat-card:nth-child(3)::before { background: var(--accent-emerald); }
69
+ .stat-card:nth-child(4)::before { background: var(--accent-rose); }
70
+ .stat-card:nth-child(5)::before { background: var(--accent-violet); }
71
+ .stat-card:nth-child(1) { animation-delay: 0s; }
72
+ .stat-card:nth-child(2) { animation-delay: 0.05s; }
73
+ .stat-card:nth-child(3) { animation-delay: 0.1s; }
74
+ .stat-card:nth-child(4) { animation-delay: 0.15s; }
75
+ .stat-card:nth-child(5) { animation-delay: 0.2s; }
76
+ .stat-card .label {
77
+ font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.1em;
78
+ color: var(--text-secondary); margin-bottom: 0.4rem; font-weight: 500;
79
+ }
80
+ .stat-card .value {
81
+ font-family: var(--font-mono); font-size: 1.8rem; font-weight: 700;
82
+ letter-spacing: -0.03em;
83
+ }
84
+ .stat-card:nth-child(1) .value { color: var(--accent-cyan); }
85
+ .stat-card:nth-child(2) .value { color: var(--accent-amber); }
86
+ .stat-card:nth-child(3) .value { color: var(--accent-emerald); }
87
+ .stat-card:nth-child(4) .value { color: var(--accent-rose); }
88
+ .stat-card:nth-child(5) .value { color: var(--accent-violet); }
89
+
90
+ /* Dashboard grid */
91
+ .dashboard-grid {
92
+ display: grid;
93
+ grid-template-columns: 1fr 1fr;
94
+ gap: 0.75rem;
95
+ }
96
+ .card {
97
+ background: var(--bg-card); border: 1px solid var(--border);
98
+ border-radius: 10px; padding: 1.25rem;
99
+ opacity: 0; transform: translateY(12px);
100
+ animation: cardIn 0.4s ease forwards;
101
+ }
102
+ .card.wide { grid-column: 1 / -1; }
103
+ .card h2 {
104
+ font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.12em;
105
+ color: var(--text-secondary); margin-bottom: 1rem; font-weight: 500;
106
+ display: flex; align-items: center; gap: 0.5rem;
107
+ }
108
+ .card h2 .badge {
109
+ font-family: var(--font-mono); font-size: 0.6rem; background: rgba(0,229,255,0.1);
110
+ color: var(--accent-cyan); padding: 0.15rem 0.5rem; border-radius: 4px;
111
+ text-transform: none; letter-spacing: 0;
112
+ }
113
+ .card canvas { max-height: 260px; }
114
+
115
+ /* Model table */
116
+ .model-table { width: 100%; border-collapse: collapse; font-size: 0.78rem; }
117
+ .model-table th {
118
+ text-align: left; font-size: 0.6rem; text-transform: uppercase;
119
+ letter-spacing: 0.08em; color: var(--text-muted); font-weight: 500;
120
+ padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--border);
121
+ }
122
+ .model-table th.right, .model-table td.right { text-align: right; }
123
+ .model-table td {
124
+ padding: 0.55rem 0.6rem; border-bottom: 1px solid rgba(30,30,46,0.5);
125
+ font-family: var(--font-mono); font-size: 0.72rem;
126
+ }
127
+ .model-table tr:hover td { background: var(--bg-row-hover); }
128
+ .model-table .model-name { color: var(--accent-cyan); font-weight: 500; }
129
+ .model-table .provider-badge {
130
+ font-size: 0.58rem; padding: 0.12rem 0.4rem; border-radius: 3px;
131
+ font-family: var(--font-sans); font-weight: 500; display: inline-block;
132
+ }
133
+ .provider-anthropic { background: rgba(179,136,255,0.15); color: var(--accent-violet); }
134
+ .provider-openai-codex { background: rgba(0,230,118,0.12); color: var(--accent-emerald); }
135
+ .provider-openrouter { background: rgba(255,145,0,0.12); color: var(--accent-orange); }
136
+ .provider-synthetic, .provider-synthetic-openai { background: rgba(64,196,255,0.12); color: var(--accent-blue); }
137
+ .provider-openclaw { background: rgba(255,82,114,0.12); color: var(--accent-rose); }
138
+ .provider-unknown { background: rgba(58,58,74,0.3); color: var(--text-secondary); }
139
+ .model-table .bar-cell { width: 30%; }
140
+ .model-table .bar-bg {
141
+ height: 6px; background: rgba(255,255,255,0.04); border-radius: 3px;
142
+ overflow: hidden; position: relative;
143
+ }
144
+ .model-table .bar-fill {
145
+ height: 100%; border-radius: 3px; transition: width 0.8s ease;
146
+ }
147
+ .token-dim { color: var(--text-secondary); }
148
+
149
+ /* Provider cards */
150
+ .providers-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.6rem; }
151
+ .provider-card {
152
+ background: var(--bg-primary); border: 1px solid var(--border);
153
+ border-radius: 8px; padding: 0.9rem;
154
+ }
155
+ .provider-card .prov-name {
156
+ font-family: var(--font-mono); font-size: 0.8rem; font-weight: 500;
157
+ margin-bottom: 0.4rem;
158
+ }
159
+ .provider-card .prov-stat {
160
+ font-size: 0.65rem; color: var(--text-secondary); line-height: 1.9;
161
+ }
162
+ .provider-card .prov-stat strong {
163
+ font-family: var(--font-mono); color: var(--text-primary); font-weight: 400;
164
+ }
165
+
166
+ /* Agent cards */
167
+ .agents-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 0.6rem; }
168
+ .agent-item {
169
+ background: var(--bg-primary); border: 1px solid var(--border);
170
+ border-radius: 8px; padding: 0.9rem;
171
+ }
172
+ .agent-item .agent-name {
173
+ font-family: var(--font-mono); font-size: 0.8rem; font-weight: 500;
174
+ color: var(--accent-cyan); margin-bottom: 0.35rem;
175
+ }
176
+ .agent-item .agent-stat {
177
+ font-size: 0.65rem; color: var(--text-secondary); line-height: 1.9;
178
+ }
179
+ .agent-item .agent-stat strong {
180
+ font-family: var(--font-mono); color: var(--text-primary); font-weight: 400;
181
+ }
182
+
183
+ .footer {
184
+ text-align: center; padding: 1.5rem 0 0.5rem;
185
+ font-size: 0.7rem; color: var(--text-muted);
186
+ font-family: var(--font-mono);
187
+ }
188
+
189
+ @keyframes cardIn { to { opacity: 1; transform: translateY(0); } }
190
+
191
+ @media (max-width: 900px) {
192
+ .hero-stats { grid-template-columns: repeat(3, 1fr); }
193
+ .dashboard-grid { grid-template-columns: 1fr; }
194
+ .stat-card .value { font-size: 1.4rem; }
195
+ .header { flex-direction: column; gap: 0.5rem; }
196
+ }
197
+ @media (max-width: 600px) {
198
+ .hero-stats { grid-template-columns: repeat(2, 1fr); }
199
+ .model-table { font-size: 0.65rem; }
200
+ }
201
+ </style>
202
+ </head>
203
+ <body>
204
+ <div class="container">
205
+ <div class="header">
206
+ <div>
207
+ <h1><span>OpenCami</span> Analytics 🦎</h1>
208
+ <div class="date-range" id="dateRange"></div>
209
+ </div>
210
+ <div class="meta">
211
+ <div class="updated" id="updatedAt"></div>
212
+ </div>
213
+ </div>
214
+
215
+ <div class="hero-stats">
216
+ <div class="stat-card"><div class="label">Total Tokens</div><div class="value" id="totalTokens">—</div></div>
217
+ <div class="stat-card"><div class="label">Messages</div><div class="value" id="totalMessages">—</div></div>
218
+ <div class="stat-card"><div class="label">Sessions</div><div class="value" id="totalSessions">—</div></div>
219
+ <div class="stat-card"><div class="label">Models</div><div class="value" id="totalModels">—</div></div>
220
+ <div class="stat-card"><div class="label">Agents</div><div class="value" id="totalAgents">—</div></div>
221
+ </div>
222
+
223
+ <div class="dashboard-grid">
224
+ <!-- Daily tokens -->
225
+ <div class="card wide" style="animation-delay:0.25s">
226
+ <h2>Daily Token Usage</h2>
227
+ <canvas id="dailyChart"></canvas>
228
+ </div>
229
+
230
+ <!-- By Model - THE BIG ONE -->
231
+ <div class="card wide" style="animation-delay:0.3s">
232
+ <h2>Token Usage by Model <span class="badge" id="modelCount"></span></h2>
233
+ <div style="overflow-x:auto">
234
+ <table class="model-table" id="modelTable">
235
+ <thead>
236
+ <tr>
237
+ <th>Model</th>
238
+ <th>Provider</th>
239
+ <th class="right">Total Tokens</th>
240
+ <th class="right">Messages</th>
241
+ <th class="right">Tokens/Msg</th>
242
+ <th class="bar-cell">Share</th>
243
+ </tr>
244
+ </thead>
245
+ <tbody id="modelBody"></tbody>
246
+ </table>
247
+ </div>
248
+ </div>
249
+
250
+ <!-- By Provider -->
251
+ <div class="card" style="animation-delay:0.35s">
252
+ <h2>By Provider</h2>
253
+ <div class="providers-grid" id="providersGrid"></div>
254
+ </div>
255
+
256
+ <!-- Token Breakdown -->
257
+ <div class="card" style="animation-delay:0.38s">
258
+ <h2>Token Breakdown</h2>
259
+ <canvas id="tokenBreakdownChart"></canvas>
260
+ </div>
261
+
262
+ <!-- Activity by Hour -->
263
+ <div class="card" style="animation-delay:0.42s">
264
+ <h2>Activity by Hour <span class="badge">UTC</span></h2>
265
+ <canvas id="hourChart"></canvas>
266
+ </div>
267
+
268
+ <!-- Top Tools -->
269
+ <div class="card" style="animation-delay:0.45s">
270
+ <h2>Top Tools <span class="badge" id="toolCount"></span></h2>
271
+ <canvas id="toolsChart"></canvas>
272
+ </div>
273
+
274
+ <!-- Agents -->
275
+ <div class="card wide" style="animation-delay:0.5s">
276
+ <h2>By Agent</h2>
277
+ <div class="agents-grid" id="agentsGrid"></div>
278
+ </div>
279
+ </div>
280
+
281
+ <div class="footer">🦎 OpenCami Analytics — tokens only, no dollars</div>
282
+ </div>
283
+
284
+ <script>
285
+ const SAMPLE = {
286
+ generatedAt: "2026-02-09T09:00:00Z",
287
+ daily: Array.from({length:25},(_,i)=>{
288
+ const d=new Date(2026,0,16+i);
289
+ return {date:d.toISOString().slice(0,10),totalTokens:Math.round(15e6+Math.random()*85e6),sessions:Math.round(3+Math.random()*20),messages:Math.round(300+Math.random()*2000)};
290
+ }),
291
+ byModel:[
292
+ {model:"claude-opus-4-5",provider:"anthropic",totalTokens:1406133099,messages:14400},
293
+ {model:"claude-sonnet-4-5",provider:"anthropic",totalTokens:426049002,messages:5858},
294
+ {model:"claude-opus-4-6",provider:"anthropic",totalTokens:424354704,messages:3950},
295
+ {model:"gpt-5.2",provider:"openai-codex",totalTokens:71158180,messages:1162},
296
+ {model:"claude-haiku-4-5",provider:"anthropic",totalTokens:36245539,messages:1036},
297
+ ],
298
+ byAgent:[
299
+ {agent:"main",totalTokens:2407067242,sessions:734,messages:37580},
300
+ {agent:"codex",totalTokens:16342194,sessions:3,messages:251},
301
+ ],
302
+ byHour: Array.from({length:24},(_,h)=>({hour:h,messages:Math.round(100+Math.random()*2900)})),
303
+ topTools:[{tool:"exec",count:9826},{tool:"read",count:2357},{tool:"process",count:1910},{tool:"bash",count:1572},{tool:"edit",count:1203}],
304
+ totals:{tokens:2439095843,sessions:760,messages:38564,dateRange:"2026-01-16 to 2026-02-09"}
305
+ };
306
+
307
+ Chart.defaults.color = '#6b6b7b';
308
+ Chart.defaults.font.family = "'JetBrains Mono', monospace";
309
+ Chart.defaults.font.size = 10;
310
+ Chart.defaults.plugins.legend.display = false;
311
+ Chart.defaults.scale.grid = { color: 'rgba(255,255,255,0.04)', drawBorder: false };
312
+
313
+ function fmtNum(n) {
314
+ if (n >= 1e9) return (n/1e9).toFixed(1) + 'B';
315
+ if (n >= 1e6) return (n/1e6).toFixed(1) + 'M';
316
+ if (n >= 1e3) return (n/1e3).toFixed(1) + 'K';
317
+ return n.toString();
318
+ }
319
+
320
+ function fmtNumPrecise(n) {
321
+ if (n >= 1e9) return (n/1e9).toFixed(2) + 'B';
322
+ if (n >= 1e6) return (n/1e6).toFixed(1) + 'M';
323
+ if (n >= 1e3) return (n/1e3).toFixed(1) + 'K';
324
+ return n.toLocaleString();
325
+ }
326
+
327
+ function fmtComma(n) { return Math.round(n).toLocaleString(); }
328
+
329
+ const providerColors = {
330
+ anthropic: '#b388ff',
331
+ 'openai-codex': '#00e676',
332
+ openrouter: '#ff9100',
333
+ synthetic: '#40c4ff',
334
+ 'synthetic-openai': '#40c4ff',
335
+ openclaw: '#ff5272',
336
+ unknown: '#3a3a4a'
337
+ };
338
+
339
+ const modelBarColors = ['#00e5ff','#b388ff','#ffab00','#00e676','#ff5272','#40c4ff','#ff9100','#e040fb','#69f0ae','#ffd740','#ff6e40','#448aff'];
340
+
341
+ function render(data) {
342
+ document.getElementById('updatedAt').textContent = 'Updated ' + new Date(data.generatedAt).toLocaleString();
343
+ document.getElementById('dateRange').textContent = data.totals.dateRange;
344
+
345
+ // Hero stats
346
+ const realModels = data.byModel.filter(m => m.model !== 'unknown' && m.model !== 'delivery-mirror');
347
+ document.getElementById('totalTokens').textContent = fmtNum(data.totals.tokens);
348
+ document.getElementById('totalMessages').textContent = fmtNum(data.totals.messages);
349
+ document.getElementById('totalSessions').textContent = fmtComma(data.totals.sessions);
350
+ document.getElementById('totalModels').textContent = realModels.length;
351
+ document.getElementById('totalAgents').textContent = data.byAgent.length;
352
+
353
+ // Daily tokens chart
354
+ new Chart(document.getElementById('dailyChart'), {
355
+ type: 'line',
356
+ data: {
357
+ labels: data.daily.map(d => d.date.slice(5)),
358
+ datasets: [{
359
+ data: data.daily.map(d => d.totalTokens),
360
+ borderColor: '#00e5ff',
361
+ backgroundColor: 'rgba(0,229,255,0.06)',
362
+ fill: true, tension: 0.3, pointRadius: 2.5, pointHoverRadius: 6,
363
+ borderWidth: 2, pointBackgroundColor: '#00e5ff'
364
+ }]
365
+ },
366
+ options: {
367
+ scales: {
368
+ y: { ticks: { callback: v => fmtNum(v) } }
369
+ },
370
+ plugins: {
371
+ tooltip: {
372
+ callbacks: {
373
+ label: c => fmtComma(c.raw) + ' tokens',
374
+ title: t => t[0].label
375
+ }
376
+ }
377
+ }
378
+ }
379
+ });
380
+
381
+ // Model table
382
+ const models = [...data.byModel]
383
+ .filter(m => m.totalTokens > 0 || (m.messages > 0 && m.model !== 'unknown'))
384
+ .sort((a, b) => b.totalTokens - a.totalTokens);
385
+ const maxTokens = models[0]?.totalTokens || 1;
386
+ const tbody = document.getElementById('modelBody');
387
+ document.getElementById('modelCount').textContent = models.length + ' models';
388
+
389
+ models.forEach((m, i) => {
390
+ const pct = (m.totalTokens / maxTokens * 100).toFixed(1);
391
+ const tpm = m.messages > 0 ? Math.round(m.totalTokens / m.messages) : 0;
392
+ const provClass = 'provider-' + (m.provider || 'unknown').replace(/[^a-z-]/g, '');
393
+ const color = modelBarColors[i % modelBarColors.length];
394
+ const tr = document.createElement('tr');
395
+ tr.innerHTML = `
396
+ <td class="model-name">${m.model}</td>
397
+ <td><span class="provider-badge ${provClass}">${m.provider}</span></td>
398
+ <td class="right">${fmtNumPrecise(m.totalTokens)}</td>
399
+ <td class="right">${fmtComma(m.messages)}</td>
400
+ <td class="right"><span class="token-dim">${fmtNum(tpm)}</span></td>
401
+ <td class="bar-cell"><div class="bar-bg"><div class="bar-fill" style="width:${pct}%;background:${color}"></div></div></td>
402
+ `;
403
+ tbody.appendChild(tr);
404
+ });
405
+
406
+ // By Provider - aggregate
407
+ const provMap = {};
408
+ data.byModel.forEach(m => {
409
+ const p = m.provider || 'unknown';
410
+ if (!provMap[p]) provMap[p] = { tokens: 0, messages: 0, models: [] };
411
+ provMap[p].tokens += m.totalTokens;
412
+ provMap[p].messages += m.messages;
413
+ if (m.model !== 'unknown' && m.model !== 'delivery-mirror') provMap[p].models.push(m.model);
414
+ });
415
+ const providers = Object.entries(provMap).sort((a, b) => b[1].tokens - a[1].tokens);
416
+ const provGrid = document.getElementById('providersGrid');
417
+ providers.forEach(([name, p]) => {
418
+ const color = providerColors[name] || '#6b6b7b';
419
+ provGrid.innerHTML += `<div class="provider-card">
420
+ <div class="prov-name" style="color:${color}">${name}</div>
421
+ <div class="prov-stat">Tokens <strong>${fmtNumPrecise(p.tokens)}</strong></div>
422
+ <div class="prov-stat">Messages <strong>${fmtComma(p.messages)}</strong></div>
423
+ <div class="prov-stat">Models <strong>${p.models.length}</strong></div>
424
+ </div>`;
425
+ });
426
+
427
+ // Token Breakdown donut - use overall split estimate from model data
428
+ // Since we don't have per-token-type data, show total tokens distribution by model category
429
+ // Actually let's do a by-provider donut
430
+ new Chart(document.getElementById('tokenBreakdownChart'), {
431
+ type: 'doughnut',
432
+ data: {
433
+ labels: providers.map(([n]) => n),
434
+ datasets: [{
435
+ data: providers.map(([, p]) => p.tokens),
436
+ backgroundColor: providers.map(([n]) => providerColors[n] || '#3a3a4a'),
437
+ borderWidth: 0,
438
+ spacing: 2
439
+ }]
440
+ },
441
+ options: {
442
+ cutout: '65%',
443
+ plugins: {
444
+ legend: { display: true, position: 'right', labels: { font: { size: 10 }, padding: 8, boxWidth: 12 } },
445
+ tooltip: { callbacks: { label: c => c.label + ': ' + fmtNumPrecise(c.raw) + ' tokens' } }
446
+ }
447
+ }
448
+ });
449
+
450
+ // Activity by hour
451
+ const maxH = Math.max(...data.byHour.map(x => x.messages));
452
+ new Chart(document.getElementById('hourChart'), {
453
+ type: 'bar',
454
+ data: {
455
+ labels: data.byHour.map(h => h.hour.toString().padStart(2, '0')),
456
+ datasets: [{
457
+ data: data.byHour.map(h => h.messages),
458
+ backgroundColor: data.byHour.map(h => {
459
+ const t = h.messages / maxH;
460
+ return `rgba(0,229,255,${0.12 + t * 0.88})`;
461
+ }),
462
+ borderRadius: 3, barThickness: 14
463
+ }]
464
+ },
465
+ options: {
466
+ scales: {
467
+ x: { ticks: { maxRotation: 0 } },
468
+ y: { ticks: { callback: v => fmtNum(v) } }
469
+ },
470
+ plugins: { tooltip: { callbacks: { label: c => fmtComma(c.raw) + ' messages' } } }
471
+ }
472
+ });
473
+
474
+ // Tools
475
+ const tools = data.topTools.slice(0, 15);
476
+ document.getElementById('toolCount').textContent = data.topTools.length + ' tools';
477
+ new Chart(document.getElementById('toolsChart'), {
478
+ type: 'bar',
479
+ data: {
480
+ labels: tools.map(t => t.tool),
481
+ datasets: [{
482
+ data: tools.map(t => t.count),
483
+ backgroundColor: 'rgba(255,171,0,0.65)',
484
+ borderRadius: 3, barThickness: 14
485
+ }]
486
+ },
487
+ options: {
488
+ indexAxis: 'y',
489
+ plugins: { tooltip: { callbacks: { label: c => fmtComma(c.raw) + ' calls' } } }
490
+ }
491
+ });
492
+
493
+ // Agents
494
+ const agents = [...data.byAgent].sort((a, b) => b.totalTokens - a.totalTokens);
495
+ const agGrid = document.getElementById('agentsGrid');
496
+ agents.forEach(a => {
497
+ agGrid.innerHTML += `<div class="agent-item">
498
+ <div class="agent-name">${a.agent}</div>
499
+ <div class="agent-stat">Tokens <strong>${fmtNumPrecise(a.totalTokens)}</strong></div>
500
+ <div class="agent-stat">Messages <strong>${fmtComma(a.messages)}</strong></div>
501
+ <div class="agent-stat">Sessions <strong>${a.sessions}</strong></div>
502
+ </div>`;
503
+ });
504
+ }
505
+
506
+ fetch('analytics.json').then(r => r.json()).then(render).catch(() => render(SAMPLE));
507
+ </script>
508
+ </body>
509
+ </html>