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.
- package/README.md +69 -74
- package/dist/client/analytics-dashboard.html +509 -0
- package/dist/client/analytics.json +598 -0
- package/dist/client/assets/_sessionKey-xUqdePGW.js +97 -0
- package/dist/client/assets/agents-BiadNAEz.js +2 -0
- package/dist/client/assets/agents-screen-C5TPJbry.js +1 -0
- package/dist/client/assets/button-seqh98ae.js +1 -0
- package/dist/client/assets/{connect-BRasuRbB.js → connect-DlVsi-ya.js} +2 -2
- package/dist/client/assets/file-explorer-screen-B0hwrjdF.js +1 -0
- package/dist/client/assets/files-dkr2U72N.js +2 -0
- package/dist/client/assets/index-CwoJpeG1.js +153 -0
- package/dist/client/assets/{index-DHGnKfAU.js → index-D1Et4XlM.js} +1 -1
- package/dist/client/assets/keyboard-shortcuts-dialog-zdnAmDiH.js +1 -0
- package/dist/client/assets/{main-BAHT5yqU.js → main-DOBfHXDF.js} +12 -12
- package/dist/client/assets/opencami-logo-Bxp_4d3X.js +1 -0
- package/dist/client/assets/react-DD8SkMJn.js +1 -0
- package/dist/client/assets/search-dialog-Ck1AQreu.js +1 -0
- package/dist/client/assets/session-export-dialog-Bh3zH4nZ.js +1 -0
- package/dist/client/assets/settings-dialog-CvUsgnnZ.js +1 -0
- package/dist/client/assets/styles-DogPvrGY.css +1 -0
- package/dist/client/assets/switch-BoGcWcnr.js +1 -0
- package/dist/client/assets/use-file-explorer-state-B5JLNsSa.js +12 -0
- package/dist/client/assets/useButton-csSB2uQJ.js +9 -0
- package/dist/client/manifest.json +8 -2
- package/dist/server/assets/{_sessionKey-qlAPF_Ft.js → _sessionKey-DQwkBUS7.js} +981 -229
- package/dist/server/assets/_tanstack-start-manifest_v-cW8K1Mnv.js +4 -0
- package/dist/server/assets/agents-Dz_i76VW.js +11 -0
- package/dist/server/assets/agents-screen-CqQPJndp.js +587 -0
- package/dist/server/assets/{connect-BWI_6rCm.js → connect-CIDOw12K.js} +34 -2
- package/dist/server/assets/{file-explorer-screen-DJXPEG_J.js → file-explorer-screen-BzvgvV8m.js} +7 -58
- package/dist/server/assets/{files-CONoVTGD.js → files-BxvRDIWU.js} +1 -1
- package/dist/server/assets/{index-Bp8QskbI.js → index-BwD7ufHE.js} +4 -3
- package/dist/server/assets/{index-COu2idHm.js → index-CmbNTqa2.js} +105 -14
- package/dist/server/assets/{keyboard-shortcuts-dialog-D5hqVX2v.js → keyboard-shortcuts-dialog-7OEtXUlW.js} +2 -2
- package/dist/server/assets/opencami-logo-C-43FL3R.js +24 -0
- package/dist/server/assets/{router-DbxyvprK.js → router-5qObg5aX.js} +368 -74
- package/dist/server/assets/{search-dialog-JY8C3mqa.js → search-dialog-BE2ZBkj0.js} +44 -12
- package/dist/server/assets/{session-export-dialog-D87uafPD.js → session-export-dialog-DRVbC8Q-.js} +2 -2
- package/dist/server/assets/{settings-dialog-CBj7njLM.js → settings-dialog-BBQcU55J.js} +204 -41
- package/dist/server/assets/switch-DnX0MjGS.js +28 -0
- package/dist/server/assets/tooltip-gbV6rEVv.js +60 -0
- package/dist/server/assets/{menu-D6n4DB0U.js → use-file-explorer-state-DMHdtb7D.js} +56 -57
- package/dist/server/server.js +2 -2
- package/package.json +1 -1
- package/dist/client/assets/_sessionKey-B-MBYHgD.js +0 -95
- package/dist/client/assets/abap-BdImnpbu.js +0 -1
- package/dist/client/assets/actionscript-3-CfeIJUat.js +0 -1
- package/dist/client/assets/ada-bCR0ucgS.js +0 -1
- package/dist/client/assets/andromeeda-C-Jbm3Hp.js +0 -1
- package/dist/client/assets/angular-html-CU67Zn6k.js +0 -1
- package/dist/client/assets/angular-ts-BwZT4LLn.js +0 -1
- package/dist/client/assets/apache-Pmp26Uib.js +0 -1
- package/dist/client/assets/apex-D8_7TLub.js +0 -1
- package/dist/client/assets/apl-dKokRX4l.js +0 -1
- package/dist/client/assets/applescript-Co6uUVPk.js +0 -1
- package/dist/client/assets/ara-BRHolxvo.js +0 -1
- package/dist/client/assets/asciidoc-Dv7Oe6Be.js +0 -1
- package/dist/client/assets/asm-D_Q5rh1f.js +0 -1
- package/dist/client/assets/astro-CbQHKStN.js +0 -1
- package/dist/client/assets/aurora-x-D-2ljcwZ.js +0 -1
- package/dist/client/assets/awk-DMzUqQB5.js +0 -1
- package/dist/client/assets/ayu-dark-CmMr59Fi.js +0 -1
- package/dist/client/assets/ballerina-BFfxhgS-.js +0 -1
- package/dist/client/assets/bat-BkioyH1T.js +0 -1
- package/dist/client/assets/beancount-k_qm7-4y.js +0 -1
- package/dist/client/assets/berry-uYugtg8r.js +0 -1
- package/dist/client/assets/bibtex-CHM0blh-.js +0 -1
- package/dist/client/assets/bicep-Bmn6On1c.js +0 -1
- package/dist/client/assets/blade-D4QpJJKB.js +0 -1
- package/dist/client/assets/bsl-BO_Y6i37.js +0 -1
- package/dist/client/assets/button-D_9OBT_f.js +0 -1
- package/dist/client/assets/c-BIGW1oBm.js +0 -1
- package/dist/client/assets/c3-VCDPK7BO.js +0 -1
- package/dist/client/assets/cadence-Bv_4Rxtq.js +0 -1
- package/dist/client/assets/cairo-KRGpt6FW.js +0 -1
- package/dist/client/assets/catppuccin-frappe-DFWUc33u.js +0 -1
- package/dist/client/assets/catppuccin-latte-C9dUb6Cb.js +0 -1
- package/dist/client/assets/catppuccin-macchiato-DQyhUUbL.js +0 -1
- package/dist/client/assets/catppuccin-mocha-D87Tk5Gz.js +0 -1
- package/dist/client/assets/clarity-D53aC0YG.js +0 -1
- package/dist/client/assets/clojure-P80f7IUj.js +0 -1
- package/dist/client/assets/cmake-D1j8_8rp.js +0 -1
- package/dist/client/assets/cobol-nwyudZeR.js +0 -1
- package/dist/client/assets/codeowners-Bp6g37R7.js +0 -1
- package/dist/client/assets/codeql-DsOJ9woJ.js +0 -1
- package/dist/client/assets/coffee-Ch7k5sss.js +0 -1
- package/dist/client/assets/common-lisp-Cg-RD9OK.js +0 -1
- package/dist/client/assets/coq-DkFqJrB1.js +0 -1
- package/dist/client/assets/cpp-CofmeUqb.js +0 -1
- package/dist/client/assets/crystal-tKQVLTB8.js +0 -1
- package/dist/client/assets/csharp-K5feNrxe.js +0 -1
- package/dist/client/assets/css-DPfMkruS.js +0 -1
- package/dist/client/assets/csv-fuZLfV_i.js +0 -1
- package/dist/client/assets/cue-D82EKSYY.js +0 -1
- package/dist/client/assets/cypher-COkxafJQ.js +0 -1
- package/dist/client/assets/d-85-TOEBH.js +0 -1
- package/dist/client/assets/dark-plus-C3mMm8J8.js +0 -1
- package/dist/client/assets/dart-CF10PKvl.js +0 -1
- package/dist/client/assets/dax-CEL-wOlO.js +0 -1
- package/dist/client/assets/desktop-BmXAJ9_W.js +0 -1
- package/dist/client/assets/diff-D97Zzqfu.js +0 -1
- package/dist/client/assets/docker-BcOcwvcX.js +0 -1
- package/dist/client/assets/dotenv-Da5cRb03.js +0 -1
- package/dist/client/assets/dracula-BzJJZx-M.js +0 -1
- package/dist/client/assets/dracula-soft-BXkSAIEj.js +0 -1
- package/dist/client/assets/dream-maker-BtqSS_iP.js +0 -1
- package/dist/client/assets/edge-BkV0erSs.js +0 -1
- package/dist/client/assets/elixir-CDX3lj18.js +0 -1
- package/dist/client/assets/elm-DbKCFpqz.js +0 -1
- package/dist/client/assets/emacs-lisp-C9XAeP06.js +0 -1
- package/dist/client/assets/erb-BOJIQeun.js +0 -1
- package/dist/client/assets/erlang-DsQrWhSR.js +0 -1
- package/dist/client/assets/everforest-dark-BgDCqdQA.js +0 -1
- package/dist/client/assets/everforest-light-C8M2exoo.js +0 -1
- package/dist/client/assets/fennel-BYunw83y.js +0 -1
- package/dist/client/assets/file-explorer-screen-Daf4rIq9.js +0 -1
- package/dist/client/assets/files-ByeIMLfw.js +0 -2
- package/dist/client/assets/fish-BvzEVeQv.js +0 -1
- package/dist/client/assets/fluent-C4IJs8-o.js +0 -1
- package/dist/client/assets/fortran-fixed-form-CkoXwp7k.js +0 -1
- package/dist/client/assets/fortran-free-form-BxgE0vQu.js +0 -1
- package/dist/client/assets/fsharp-CXgrBDvD.js +0 -1
- package/dist/client/assets/gdresource-B7Tvp0Sc.js +0 -1
- package/dist/client/assets/gdscript-DTMYz4Jt.js +0 -1
- package/dist/client/assets/gdshader-DkwncUOv.js +0 -1
- package/dist/client/assets/genie-D0YGMca9.js +0 -1
- package/dist/client/assets/gherkin-DyxjwDmM.js +0 -1
- package/dist/client/assets/git-commit-F4YmCXRG.js +0 -1
- package/dist/client/assets/git-rebase-r7XF79zn.js +0 -1
- package/dist/client/assets/github-dark-DHJKELXO.js +0 -1
- package/dist/client/assets/github-dark-default-Cuk6v7N8.js +0 -1
- package/dist/client/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
- package/dist/client/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
- package/dist/client/assets/github-light-DAi9KRSo.js +0 -1
- package/dist/client/assets/github-light-default-D7oLnXFd.js +0 -1
- package/dist/client/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
- package/dist/client/assets/gleam-BspZqrRM.js +0 -1
- package/dist/client/assets/glimmer-js-Rg0-pVw9.js +0 -1
- package/dist/client/assets/glimmer-ts-U6CK756n.js +0 -1
- package/dist/client/assets/glsl-DplSGwfg.js +0 -1
- package/dist/client/assets/gn-n2N0HUVH.js +0 -1
- package/dist/client/assets/gnuplot-DdkO51Og.js +0 -1
- package/dist/client/assets/go-Dn2_MT6a.js +0 -1
- package/dist/client/assets/graphql-ChdNCCLP.js +0 -1
- package/dist/client/assets/groovy-gcz8RCvz.js +0 -1
- package/dist/client/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -1
- package/dist/client/assets/gruvbox-dark-medium-GsRaNv29.js +0 -1
- package/dist/client/assets/gruvbox-dark-soft-CVdnzihN.js +0 -1
- package/dist/client/assets/gruvbox-light-hard-CH1njM8p.js +0 -1
- package/dist/client/assets/gruvbox-light-medium-DRw_LuNl.js +0 -1
- package/dist/client/assets/gruvbox-light-soft-hJgmCMqR.js +0 -1
- package/dist/client/assets/hack-CaT9iCJl.js +0 -1
- package/dist/client/assets/haml-B8DHNrY2.js +0 -1
- package/dist/client/assets/handlebars-BL8al0AC.js +0 -1
- package/dist/client/assets/haskell-Df6bDoY_.js +0 -1
- package/dist/client/assets/haxe-CzTSHFRz.js +0 -1
- package/dist/client/assets/hcl-BWvSN4gD.js +0 -1
- package/dist/client/assets/hjson-D5-asLiD.js +0 -1
- package/dist/client/assets/hlsl-D3lLCCz7.js +0 -1
- package/dist/client/assets/houston-DnULxvSX.js +0 -1
- package/dist/client/assets/html-GMplVEZG.js +0 -1
- package/dist/client/assets/html-derivative-BFtXZ54Q.js +0 -1
- package/dist/client/assets/http-jrhK8wxY.js +0 -1
- package/dist/client/assets/hurl-irOxFIW8.js +0 -1
- package/dist/client/assets/hxml-Bvhsp5Yf.js +0 -1
- package/dist/client/assets/hy-DFXneXwc.js +0 -1
- package/dist/client/assets/imba-DGztddWO.js +0 -1
- package/dist/client/assets/index-ByUDBI-n.js +0 -14
- package/dist/client/assets/ini-BEwlwnbL.js +0 -1
- package/dist/client/assets/java-CylS5w8V.js +0 -1
- package/dist/client/assets/javascript-wDzz0qaB.js +0 -1
- package/dist/client/assets/jinja-4LBKfQ-Z.js +0 -1
- package/dist/client/assets/jison-wvAkD_A8.js +0 -1
- package/dist/client/assets/json-Cp-IABpG.js +0 -1
- package/dist/client/assets/json5-C9tS-k6U.js +0 -1
- package/dist/client/assets/jsonc-Des-eS-w.js +0 -1
- package/dist/client/assets/jsonl-DcaNXYhu.js +0 -1
- package/dist/client/assets/jsonnet-DFQXde-d.js +0 -1
- package/dist/client/assets/jssm-C2t-YnRu.js +0 -1
- package/dist/client/assets/jsx-g9-lgVsj.js +0 -1
- package/dist/client/assets/julia-CxzCAyBv.js +0 -1
- package/dist/client/assets/kanagawa-dragon-CkXjmgJE.js +0 -1
- package/dist/client/assets/kanagawa-lotus-CfQXZHmo.js +0 -1
- package/dist/client/assets/kanagawa-wave-DWedfzmr.js +0 -1
- package/dist/client/assets/kdl-DV7GczEv.js +0 -1
- package/dist/client/assets/keyboard-shortcuts-dialog-agsWJ36q.js +0 -1
- package/dist/client/assets/kotlin-BdnUsdx6.js +0 -1
- package/dist/client/assets/kusto-DZf3V79B.js +0 -1
- package/dist/client/assets/laserwave-DUszq2jm.js +0 -1
- package/dist/client/assets/latex-B4uzh10-.js +0 -1
- package/dist/client/assets/lean-BZvkOJ9d.js +0 -1
- package/dist/client/assets/less-B1dDrJ26.js +0 -1
- package/dist/client/assets/light-plus-B7mTdjB0.js +0 -1
- package/dist/client/assets/liquid-DYVedYrR.js +0 -1
- package/dist/client/assets/llvm-BtvRca6l.js +0 -1
- package/dist/client/assets/log-2UxHyX5q.js +0 -1
- package/dist/client/assets/logo-BtOb2qkB.js +0 -1
- package/dist/client/assets/lua-BbnMAYS6.js +0 -1
- package/dist/client/assets/luau-C-HG3fhB.js +0 -1
- package/dist/client/assets/make-CHLpvVh8.js +0 -1
- package/dist/client/assets/markdown-Cvjx9yec.js +0 -1
- package/dist/client/assets/marko-DZsq8hO1.js +0 -1
- package/dist/client/assets/material-theme-D5KoaKCx.js +0 -1
- package/dist/client/assets/material-theme-darker-BfHTSMKl.js +0 -1
- package/dist/client/assets/material-theme-lighter-B0m2ddpp.js +0 -1
- package/dist/client/assets/material-theme-ocean-CyktbL80.js +0 -1
- package/dist/client/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
- package/dist/client/assets/matlab-D7o27uSR.js +0 -1
- package/dist/client/assets/mdc-DUICxH0z.js +0 -1
- package/dist/client/assets/mdx-Cmh6b_Ma.js +0 -1
- package/dist/client/assets/menu-BhVaz8Ly.js +0 -20
- package/dist/client/assets/mermaid-mWjccvbQ.js +0 -1
- package/dist/client/assets/min-dark-CafNBF8u.js +0 -1
- package/dist/client/assets/min-light-CTRr51gU.js +0 -1
- package/dist/client/assets/mipsasm-CKIfxQSi.js +0 -1
- package/dist/client/assets/mojo-B93PlW-d.js +0 -1
- package/dist/client/assets/monokai-D4h5O-jR.js +0 -1
- package/dist/client/assets/moonbit-Ba13S78F.js +0 -1
- package/dist/client/assets/move-Bu9oaDYs.js +0 -1
- package/dist/client/assets/narrat-DRg8JJMk.js +0 -1
- package/dist/client/assets/nextflow-BrzmwbiE.js +0 -1
- package/dist/client/assets/nginx-DknmC5AR.js +0 -1
- package/dist/client/assets/night-owl-C39BiMTA.js +0 -1
- package/dist/client/assets/nim-CVrawwO9.js +0 -1
- package/dist/client/assets/nix-CwoSXNpI.js +0 -1
- package/dist/client/assets/nord-Ddv68eIx.js +0 -1
- package/dist/client/assets/nushell-C-sUppwS.js +0 -1
- package/dist/client/assets/objective-c-DXmwc3jG.js +0 -1
- package/dist/client/assets/objective-cpp-CLxacb5B.js +0 -1
- package/dist/client/assets/ocaml-C0hk2d4L.js +0 -1
- package/dist/client/assets/one-dark-pro-DVMEJ2y_.js +0 -1
- package/dist/client/assets/one-light-PoHY5YXO.js +0 -1
- package/dist/client/assets/openscad-C4EeE6gA.js +0 -1
- package/dist/client/assets/pascal-D93ZcfNL.js +0 -1
- package/dist/client/assets/perl-C0TMdlhV.js +0 -1
- package/dist/client/assets/php-CDn_0X-4.js +0 -1
- package/dist/client/assets/pkl-u5AG7uiY.js +0 -1
- package/dist/client/assets/plastic-3e1v2bzS.js +0 -1
- package/dist/client/assets/plsql-ChMvpjG-.js +0 -1
- package/dist/client/assets/po-BTJTHyun.js +0 -1
- package/dist/client/assets/poimandres-CS3Unz2-.js +0 -1
- package/dist/client/assets/polar-C0HS_06l.js +0 -1
- package/dist/client/assets/postcss-CXtECtnM.js +0 -1
- package/dist/client/assets/powerquery-CEu0bR-o.js +0 -1
- package/dist/client/assets/powershell-Dpen1YoG.js +0 -1
- package/dist/client/assets/prisma-Dd19v3D-.js +0 -1
- package/dist/client/assets/prolog-CbFg5uaA.js +0 -1
- package/dist/client/assets/proto-C7zT0LnQ.js +0 -1
- package/dist/client/assets/pug-CGlum2m_.js +0 -1
- package/dist/client/assets/puppet-BMWR74SV.js +0 -1
- package/dist/client/assets/purescript-CklMAg4u.js +0 -1
- package/dist/client/assets/python-B6aJPvgy.js +0 -1
- package/dist/client/assets/qml-3beO22l8.js +0 -1
- package/dist/client/assets/qmldir-C8lEn-DE.js +0 -1
- package/dist/client/assets/qss-IeuSbFQv.js +0 -1
- package/dist/client/assets/r-Dspwwk_N.js +0 -1
- package/dist/client/assets/racket-BqYA7rlc.js +0 -1
- package/dist/client/assets/raku-DXvB9xmW.js +0 -1
- package/dist/client/assets/razor-C1TweQQi.js +0 -1
- package/dist/client/assets/red-bN70gL4F.js +0 -1
- package/dist/client/assets/reg-C-SQnVFl.js +0 -1
- package/dist/client/assets/regexp-CDVJQ6XC.js +0 -1
- package/dist/client/assets/rel-C3B-1QV4.js +0 -1
- package/dist/client/assets/riscv-BM1_JUlF.js +0 -1
- package/dist/client/assets/rose-pine-dawn-DHQR4-dF.js +0 -1
- package/dist/client/assets/rose-pine-moon-D4_iv3hh.js +0 -1
- package/dist/client/assets/rose-pine-qdsjHGoJ.js +0 -1
- package/dist/client/assets/rosmsg-BJDFO7_C.js +0 -1
- package/dist/client/assets/rst-B0xPkSld.js +0 -1
- package/dist/client/assets/ruby-BvKwtOVI.js +0 -1
- package/dist/client/assets/rust-B1yitclQ.js +0 -1
- package/dist/client/assets/sas-cz2c8ADy.js +0 -1
- package/dist/client/assets/sass-Cj5Yp3dK.js +0 -1
- package/dist/client/assets/scala-C151Ov-r.js +0 -1
- package/dist/client/assets/scheme-C98Dy4si.js +0 -1
- package/dist/client/assets/scss-OYdSNvt2.js +0 -1
- package/dist/client/assets/sdbl-DVxCFoDh.js +0 -1
- package/dist/client/assets/search-dialog-CHwnOyPS.js +0 -1
- package/dist/client/assets/session-export-dialog-uOlDUzgX.js +0 -1
- package/dist/client/assets/settings-dialog-D0aYDkAM.js +0 -1
- package/dist/client/assets/shaderlab-Dg9Lc6iA.js +0 -1
- package/dist/client/assets/shellscript-Yzrsuije.js +0 -1
- package/dist/client/assets/shellsession-BADoaaVG.js +0 -1
- package/dist/client/assets/slack-dark-BthQWCQV.js +0 -1
- package/dist/client/assets/slack-ochin-DqwNpetd.js +0 -1
- package/dist/client/assets/smalltalk-BERRCDM3.js +0 -1
- package/dist/client/assets/snazzy-light-Bw305WKR.js +0 -1
- package/dist/client/assets/solarized-dark-DXbdFlpD.js +0 -1
- package/dist/client/assets/solarized-light-L9t79GZl.js +0 -1
- package/dist/client/assets/solidity-rGO070M0.js +0 -1
- package/dist/client/assets/soy-Brmx7dQM.js +0 -1
- package/dist/client/assets/sparql-rVzFXLq3.js +0 -1
- package/dist/client/assets/splunk-BtCnVYZw.js +0 -1
- package/dist/client/assets/sql-BLtJtn59.js +0 -1
- package/dist/client/assets/ssh-config-_ykCGR6B.js +0 -1
- package/dist/client/assets/stata-BH5u7GGu.js +0 -1
- package/dist/client/assets/styles-7aVSlb6l.css +0 -1
- package/dist/client/assets/stylus-BEDo0Tqx.js +0 -1
- package/dist/client/assets/svelte-zxCyuUbr.js +0 -1
- package/dist/client/assets/swift-Dg5xB15N.js +0 -1
- package/dist/client/assets/synthwave-84-CbfX1IO0.js +0 -1
- package/dist/client/assets/system-verilog-CnnmHF94.js +0 -1
- package/dist/client/assets/systemd-4A_iFExJ.js +0 -1
- package/dist/client/assets/talonscript-CkByrt1z.js +0 -1
- package/dist/client/assets/tasl-QIJgUcNo.js +0 -1
- package/dist/client/assets/tcl-dwOrl1Do.js +0 -1
- package/dist/client/assets/templ-W15q3VgB.js +0 -1
- package/dist/client/assets/terraform-BETggiCN.js +0 -1
- package/dist/client/assets/tex-CvyZ59Mk.js +0 -1
- package/dist/client/assets/tokyo-night-hegEt444.js +0 -1
- package/dist/client/assets/toml-vGWfd6FD.js +0 -1
- package/dist/client/assets/ts-tags-zn1MmPIZ.js +0 -1
- package/dist/client/assets/tsv-B_m7g4N7.js +0 -1
- package/dist/client/assets/tsx-COt5Ahok.js +0 -1
- package/dist/client/assets/turtle-BsS91CYL.js +0 -1
- package/dist/client/assets/twig-CO9l9SDP.js +0 -1
- package/dist/client/assets/typescript-BPQ3VLAy.js +0 -1
- package/dist/client/assets/typespec-BGHnOYBU.js +0 -1
- package/dist/client/assets/typst-DHCkPAjA.js +0 -1
- package/dist/client/assets/v-BcVCzyr7.js +0 -1
- package/dist/client/assets/vala-CsfeWuGM.js +0 -1
- package/dist/client/assets/vb-D17OF-Vu.js +0 -1
- package/dist/client/assets/verilog-BQ8w6xss.js +0 -1
- package/dist/client/assets/vesper-DU1UobuO.js +0 -1
- package/dist/client/assets/vhdl-CeAyd5Ju.js +0 -1
- package/dist/client/assets/viml-CJc9bBzg.js +0 -1
- package/dist/client/assets/vitesse-black-Bkuqu6BP.js +0 -1
- package/dist/client/assets/vitesse-dark-D0r3Knsf.js +0 -1
- package/dist/client/assets/vitesse-light-CVO1_9PV.js +0 -1
- package/dist/client/assets/vue-DN_0RTcg.js +0 -1
- package/dist/client/assets/vue-html-AaS7Mt5G.js +0 -1
- package/dist/client/assets/vue-vine-CQOfvN7w.js +0 -1
- package/dist/client/assets/vyper-CDx5xZoG.js +0 -1
- package/dist/client/assets/wasm-CG6Dc4jp.js +0 -1
- package/dist/client/assets/wasm-MzD3tlZU.js +0 -1
- package/dist/client/assets/wenyan-BV7otONQ.js +0 -1
- package/dist/client/assets/wgsl-Dx-B1_4e.js +0 -1
- package/dist/client/assets/wikitext-BhOHFoWU.js +0 -1
- package/dist/client/assets/wit-5i3qLPDT.js +0 -1
- package/dist/client/assets/wolfram-lXgVvXCa.js +0 -1
- package/dist/client/assets/xml-sdJ4AIDG.js +0 -1
- package/dist/client/assets/xsl-CtQFsRM5.js +0 -1
- package/dist/client/assets/yaml-Buea-lGh.js +0 -1
- package/dist/client/assets/zenscript-DVFEvuxE.js +0 -1
- package/dist/client/assets/zig-VOosw3JB.js +0 -1
- 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
|
-
|
|
3
|
+
A beautiful web client for [OpenClaw](https://github.com/openclaw/openclaw).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g opencami
|
|
7
|
+
opencami
|
|
8
|
+
```
|
|
6
9
|
|
|
7
|
-
[](https://www.npmjs.com/package/opencami)
|
|
8
11
|
[](LICENSE)
|
|
9
12
|
|
|
10
13
|

|
|
11
14
|
|
|
12
|
-
##
|
|
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
|
-
|
|
21
|
-
📁 Session folders · 🦎 OpenCami chat folder · 📌 Pin sessions · 🗑️ Bulk delete · 🛡️ Protected sessions
|
|
17
|
+
Install globally and run:
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
🎨 Model selector · 🎭 Persona picker · 🦎 Chameleon theme · 🔤 Text size control
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g opencami
|
|
21
|
+
opencami
|
|
22
|
+
```
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
📂 File explorer · 🖼️ Image attachments
|
|
24
|
+
That's it. Opens your browser to the chat interface.
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
🏷️ Smart titles · 💡 Smart follow-ups · 💬 Slash commands
|
|
26
|
+
### Options
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
📱 Install as app · 🔄 Offline support · 🚀 Auto-update
|
|
35
|
+
### Docker
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
```bash
|
|
38
|
+
docker build -t opencami .
|
|
39
|
+
docker run -p 3000:3000 opencami
|
|
40
|
+
```
|
|
42
41
|
|
|
43
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
90
|
+
Built on top of [WebClaw](https://github.com/ibelick/webclaw) by [@ibelick](https://github.com/ibelick).
|
|
87
91
|
|
|
88
|
-
|
|
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
|
-
|
|
94
|
+
Dockerfile by [@deblanco](https://github.com/deblanco) ([PR #7](https://github.com/ibelick/webclaw/pull/7)).
|
|
100
95
|
|
|
101
|
-
|
|
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
|
-
##
|
|
98
|
+
## Links
|
|
106
99
|
|
|
107
|
-
|
|
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
|
-
|
|
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>
|