@axhub/genie 0.1.8 → 0.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 +1 -1
- package/dist/api-docs.html +6 -6
- package/dist/assets/App-BfaNALgf.js +504 -0
- package/dist/assets/App-qxJ8_QYu.css +32 -0
- package/dist/assets/ReviewApp-DIT2yWk-.js +1 -0
- package/dist/assets/_basePickBy-Dz3NcIVK.js +1 -0
- package/dist/assets/_baseUniq-DON_Sg7x.js +1 -0
- package/dist/assets/abap-BdImnpbu.js +1 -0
- package/dist/assets/actionscript-3-CoDkCxhg.js +1 -0
- package/dist/assets/ada-bCR0ucgS.js +1 -0
- package/dist/assets/andromeeda-C4gqWexZ.js +1 -0
- package/dist/assets/angular-html-CU67Zn6k.js +1 -0
- package/dist/assets/angular-ts-BwZT4LLn.js +1 -0
- package/dist/assets/apache-Pmp26Uib.js +1 -0
- package/dist/assets/apex-D8_7TLub.js +1 -0
- package/dist/assets/apl-dKokRX4l.js +1 -0
- package/dist/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/assets/ara-BRHolxvo.js +1 -0
- package/dist/assets/arc-Y4G80q-l.js +1 -0
- package/dist/assets/architectureDiagram-2XIMDMQ5-D_qR4657.js +36 -0
- package/dist/assets/asciidoc-Ve4PFQV2.js +1 -0
- package/dist/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/assets/astro-CbQHKStN.js +1 -0
- package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/assets/awk-DMzUqQB5.js +1 -0
- package/dist/assets/ayu-dark-DYE7WIF3.js +1 -0
- package/dist/assets/ayu-light-BA47KaF1.js +1 -0
- package/dist/assets/ayu-mirage-32ctXXKs.js +1 -0
- package/dist/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/assets/bat-BkioyH1T.js +1 -0
- package/dist/assets/beancount-k_qm7-4y.js +1 -0
- package/dist/assets/berry-uYugtg8r.js +1 -0
- package/dist/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/assets/bird2-DPOp833l.js +1 -0
- package/dist/assets/blade-D4QpJJKB.js +1 -0
- package/dist/assets/blockDiagram-WCTKOSBZ-NsmAlV5_.js +132 -0
- package/dist/assets/bsl-BO_Y6i37.js +1 -0
- package/dist/assets/c-BIGW1oBm.js +1 -0
- package/dist/assets/c3-eo99z4R2.js +1 -0
- package/dist/assets/c4Diagram-IC4MRINW-cbOJM4yr.js +10 -0
- package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
- package/dist/assets/cairo-KRGpt6FW.js +1 -0
- package/dist/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/dist/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/dist/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/dist/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/dist/assets/channel-C6KNnXlA.js +1 -0
- package/dist/assets/chunk-4BX2VUAB-bLBhl74J.js +1 -0
- package/dist/assets/chunk-55IACEB6-D8kNkDUO.js +1 -0
- package/dist/assets/chunk-FMBD7UC4-BjR6UbXB.js +15 -0
- package/dist/assets/chunk-JSJVCQXG-luNqWn64.js +1 -0
- package/dist/assets/chunk-KX2RTZJC-CNnKm6dK.js +1 -0
- package/dist/assets/chunk-NQ4KR5QH-Cp9gb43u.js +220 -0
- package/dist/assets/chunk-QZHKN3VN-HlVYo2Oq.js +1 -0
- package/dist/assets/chunk-WL4C6EOR-CjSZoOGO.js +189 -0
- package/dist/assets/clarity-D53aC0YG.js +1 -0
- package/dist/assets/classDiagram-VBA2DB6C-BQlzzlH7.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-BQlzzlH7.js +1 -0
- package/dist/assets/clojure-P80f7IUj.js +1 -0
- package/dist/assets/clone-DMxS3qWP.js +1 -0
- package/dist/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/assets/cobol-nwyudZeR.js +1 -0
- package/dist/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/assets/codeql-DsOJ9woJ.js +1 -0
- package/dist/assets/coffee-Ch7k5sss.js +1 -0
- package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/dist/assets/coq-DkFqJrB1.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-DZWRjeEd.js +1 -0
- package/dist/assets/cpp-CofmeUqb.js +1 -0
- package/dist/assets/crystal-tKQVLTB8.js +1 -0
- package/dist/assets/csharp-COcwbKMJ.js +1 -0
- package/dist/assets/css-DPfMkruS.js +1 -0
- package/dist/assets/csv-fuZLfV_i.js +1 -0
- package/dist/assets/cue-D82EKSYY.js +1 -0
- package/dist/assets/cypher-COkxafJQ.js +1 -0
- package/dist/assets/cytoscape.esm-2ZfV8NB5.js +331 -0
- package/dist/assets/d-85-TOEBH.js +1 -0
- package/dist/assets/dagre-KLK3FWXG-yAzUmqI7.js +4 -0
- package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/assets/dart-CF10PKvl.js +1 -0
- package/dist/assets/dax-CEL-wOlO.js +1 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/assets/diagram-E7M64L7V-CvzlIvDJ.js +24 -0
- package/dist/assets/diagram-IFDJBPK2-DFMIJpuM.js +43 -0
- package/dist/assets/diagram-P4PSJMXO-KL-J3gyb.js +24 -0
- package/dist/assets/diff-D97Zzqfu.js +1 -0
- package/dist/assets/docker-BcOcwvcX.js +1 -0
- package/dist/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/assets/edge-BkV0erSs.js +1 -0
- package/dist/assets/elixir-CDX3lj18.js +1 -0
- package/dist/assets/elm-DbKCFpqz.js +1 -0
- package/dist/assets/emacs-lisp-C9XAeP06.js +1 -0
- package/dist/assets/erDiagram-INFDFZHY-BXszHbTM.js +70 -0
- package/dist/assets/erb-B12qg9BL.js +1 -0
- package/dist/assets/erlang-DsQrWhSR.js +1 -0
- package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/assets/fennel-BYunw83y.js +1 -0
- package/dist/assets/fish-BvzEVeQv.js +1 -0
- package/dist/assets/flowDiagram-PKNHOUZH-Ba43NVp6.js +162 -0
- package/dist/assets/fluent-C4IJs8-o.js +1 -0
- package/dist/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
- package/dist/assets/fortran-free-form-BxgE0vQu.js +1 -0
- package/dist/assets/fsharp-CXgrBDvD.js +1 -0
- package/dist/assets/ganttDiagram-A5KZAMGK-uLHfhCrg.js +292 -0
- package/dist/assets/gdresource-BOOCDP_w.js +1 -0
- package/dist/assets/gdscript-C5YyOfLZ.js +1 -0
- package/dist/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/assets/genie-D0YGMca9.js +1 -0
- package/dist/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/assets/git-rebase-r7XF79zn.js +1 -0
- package/dist/assets/gitGraphDiagram-K3NZZRJ6-BTEuFaiL.js +65 -0
- package/dist/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/assets/gleam-BspZqrRM.js +1 -0
- package/dist/assets/glimmer-js-Rg0-pVw9.js +1 -0
- package/dist/assets/glimmer-ts-U6CK756n.js +1 -0
- package/dist/assets/glsl-DplSGwfg.js +1 -0
- package/dist/assets/gn-n2N0HUVH.js +1 -0
- package/dist/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/assets/go-CxLEBnE3.js +1 -0
- package/dist/assets/graph-h2nuWjx4.js +1 -0
- package/dist/assets/graphql-ChdNCCLP.js +1 -0
- package/dist/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/dist/assets/hack-CaT9iCJl.js +1 -0
- package/dist/assets/haml-B8DHNrY2.js +1 -0
- package/dist/assets/handlebars-BL8al0AC.js +1 -0
- package/dist/assets/haskell-Df6bDoY_.js +1 -0
- package/dist/assets/haxe-CzTSHFRz.js +1 -0
- package/dist/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/assets/highlighted-body-TPN3WLV5-C6BY7XZJ.js +1 -0
- package/dist/assets/hjson-D5-asLiD.js +1 -0
- package/dist/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/assets/horizon-BUw7H-hv.js +1 -0
- package/dist/assets/horizon-bright-Cn-bp-IR.js +1 -0
- package/dist/assets/houston-DnULxvSX.js +1 -0
- package/dist/assets/html-GMplVEZG.js +1 -0
- package/dist/assets/html-derivative-BFtXZ54Q.js +1 -0
- package/dist/assets/http-jrhK8wxY.js +1 -0
- package/dist/assets/hurl-irOxFIW8.js +1 -0
- package/dist/assets/hxml-Bvhsp5Yf.js +1 -0
- package/dist/assets/hy-DFXneXwc.js +1 -0
- package/dist/assets/imba-DGztddWO.js +1 -0
- package/dist/assets/index-2198VgsK.css +1 -0
- package/dist/assets/index-C6Bb2jGF.js +2 -0
- package/dist/assets/infoDiagram-LFFYTUFH-BOLfvCIq.js +2 -0
- package/dist/assets/ini-BEwlwnbL.js +1 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-PHBUUO56-BRzQ1ee5.js +70 -0
- package/dist/assets/java-CylS5w8V.js +1 -0
- package/dist/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/assets/jinja-4LBKfQ-Z.js +1 -0
- package/dist/assets/jison-wvAkD_A8.js +1 -0
- package/dist/assets/journeyDiagram-4ABVD52K-DXm_VcMy.js +139 -0
- package/dist/assets/json-Cp-IABpG.js +1 -0
- package/dist/assets/json5-C9tS-k6U.js +1 -0
- package/dist/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/assets/jssm-C2t-YnRu.js +1 -0
- package/dist/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/assets/julia-CxzCAyBv.js +1 -0
- package/dist/assets/just-Cw27pwNe.js +1 -0
- package/dist/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/dist/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/dist/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/dist/assets/kanban-definition-K7BYSVSG-D_oyzopl.js +89 -0
- package/dist/assets/kdl-DV7GczEv.js +1 -0
- package/dist/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/assets/kusto-DZf3V79B.js +1 -0
- package/dist/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/assets/latex-CWtU0Tv5.js +1 -0
- package/dist/assets/layout-Q8YoR_E1.js +1 -0
- package/dist/assets/lean-BZvkOJ9d.js +1 -0
- package/dist/assets/less-B1dDrJ26.js +1 -0
- package/dist/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/assets/linear-B3qNg7di.js +1 -0
- package/dist/assets/liquid-DYVedYrR.js +1 -0
- package/dist/assets/llvm-DjAJT7YJ.js +1 -0
- package/dist/assets/log-2UxHyX5q.js +1 -0
- package/dist/assets/logo-BtOb2qkB.js +1 -0
- package/dist/assets/lua-BaeVxFsk.js +1 -0
- package/dist/assets/luau-C-HG3fhB.js +1 -0
- package/dist/assets/make-CHLpvVh8.js +1 -0
- package/dist/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/assets/marko-CnJfTvn9.js +1 -0
- package/dist/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/assets/matlab-D7o27uSR.js +1 -0
- package/dist/assets/mdc-BMNejdWA.js +1 -0
- package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/assets/mermaid-O7DHMXV3-BVZ_4MKo.js +988 -0
- package/dist/assets/mermaid-mWjccvbQ.js +1 -0
- package/dist/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/assets/min-light-CTRr51gU.js +1 -0
- package/dist/assets/mindmap-definition-YRQLILUH-CjulgYdi.js +68 -0
- package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
- package/dist/assets/mojo-rZm6bMo-.js +1 -0
- package/dist/assets/monokai-D4h5O-jR.js +1 -0
- package/dist/assets/moonbit-_H4v1dQx.js +1 -0
- package/dist/assets/move-IF9eRakj.js +1 -0
- package/dist/assets/narrat-DRg8JJMk.js +1 -0
- package/dist/assets/nextflow-Zz6hmt5N.js +1 -0
- package/dist/assets/nextflow-groovy-BeH2EWoN.js +1 -0
- package/dist/assets/nginx-BpAMiNFr.js +1 -0
- package/dist/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/assets/night-owl-light-CMTm3GFP.js +1 -0
- package/dist/assets/nim-CVrawwO9.js +1 -0
- package/dist/assets/nix-CwoSXNpI.js +1 -0
- package/dist/assets/nord-Ddv68eIx.js +1 -0
- package/dist/assets/nushell-Cz2AlsmD.js +1 -0
- package/dist/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/assets/odin-BBf5iR-q.js +1 -0
- package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/dist/assets/one-light-C3Wv6jpd.js +1 -0
- package/dist/assets/openscad-C4EeE6gA.js +1 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/assets/perl-C0TMdlhV.js +1 -0
- package/dist/assets/php-Dhbhpdrm.js +1 -0
- package/dist/assets/pieDiagram-SKSYHLDU-8VzrefxA.js +30 -0
- package/dist/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/assets/po-BTJTHyun.js +1 -0
- package/dist/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/assets/polar-C0HS_06l.js +1 -0
- package/dist/assets/postcss-CXtECtnM.js +1 -0
- package/dist/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/assets/powershell-Dpen1YoG.js +1 -0
- package/dist/assets/prisma-Dd19v3D-.js +1 -0
- package/dist/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/assets/proto-C7zT0LnQ.js +1 -0
- package/dist/assets/pug-CGlum2m_.js +1 -0
- package/dist/assets/puppet-BMWR74SV.js +1 -0
- package/dist/assets/purescript-CklMAg4u.js +1 -0
- package/dist/assets/python-B6aJPvgy.js +1 -0
- package/dist/assets/qml-3beO22l8.js +1 -0
- package/dist/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/assets/qss-IeuSbFQv.js +1 -0
- package/dist/assets/quadrantDiagram-337W2JSQ-CFh-ijm2.js +7 -0
- package/dist/assets/r-Dspwwk_N.js +1 -0
- package/dist/assets/racket-BqYA7rlc.js +1 -0
- package/dist/assets/raku-DXvB9xmW.js +1 -0
- package/dist/assets/razor-Uh8Bk_45.js +1 -0
- package/dist/assets/red-bN70gL4F.js +1 -0
- package/dist/assets/reg-C-SQnVFl.js +1 -0
- package/dist/assets/regexp-CDVJQ6XC.js +1 -0
- package/dist/assets/rel-C3B-1QV4.js +1 -0
- package/dist/assets/requirementDiagram-Z7DCOOCP-BNPlTs5Q.js +73 -0
- package/dist/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/assets/ron-D8l8udqQ.js +1 -0
- package/dist/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
- package/dist/assets/rose-pine-moon-D4_iv3hh.js +1 -0
- package/dist/assets/rose-pine-qdsjHGoJ.js +1 -0
- package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/assets/rst-BrH8l1NY.js +1 -0
- package/dist/assets/ruby-Dw2BHqvy.js +1 -0
- package/dist/assets/rust-B1yitclQ.js +1 -0
- package/dist/assets/sankeyDiagram-WA2Y5GQK-C5l_hYst.js +10 -0
- package/dist/assets/sas-cz2c8ADy.js +1 -0
- package/dist/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/assets/scala-C151Ov-r.js +1 -0
- package/dist/assets/scheme-C98Dy4si.js +1 -0
- package/dist/assets/scss-OYdSNvt2.js +1 -0
- package/dist/assets/sdbl-DVxCFoDh.js +1 -0
- package/dist/assets/sequenceDiagram-2WXFIKYE-B4a_rQw8.js +145 -0
- package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/dist/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/assets/shellsession-BADoaaVG.js +1 -0
- package/dist/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/assets/smalltalk-BERRCDM3.js +1 -0
- package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/dist/assets/solarized-light-L9t79GZl.js +1 -0
- package/dist/assets/solidity-rGO070M0.js +1 -0
- package/dist/assets/soy-Brmx7dQM.js +1 -0
- package/dist/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/assets/splunk-BtCnVYZw.js +1 -0
- package/dist/assets/sql-BLtJtn59.js +1 -0
- package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/assets/stata-BH5u7GGu.js +1 -0
- package/dist/assets/stateDiagram-RAJIS63D-Bt4mMmKB.js +1 -0
- package/dist/assets/stateDiagram-v2-FVOUBMTO-6NYMazfq.js +1 -0
- package/dist/assets/stylus-BEDo0Tqx.js +1 -0
- package/dist/assets/surrealql-Bq5Q-fJD.js +1 -0
- package/dist/assets/svelte-C_ipcX3V.js +1 -0
- package/dist/assets/swift-D82vCrfD.js +1 -0
- package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/assets/system-verilog-CnnmHF94.js +1 -0
- package/dist/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/assets/talonscript-CkByrt1z.js +1 -0
- package/dist/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/assets/templ-P3uqSqPl.js +1 -0
- package/dist/assets/terraform-BETggiCN.js +1 -0
- package/dist/assets/tex-idrVyKtj.js +1 -0
- package/dist/assets/timeline-definition-YZTLITO2-CLYvSw_R.js +61 -0
- package/dist/assets/tokyo-night-hegEt444.js +1 -0
- package/dist/assets/toml-vGWfd6FD.js +1 -0
- package/dist/assets/treemap-KZPCXAKY-ksND0hZK.js +162 -0
- package/dist/assets/ts-tags-zn1MmPIZ.js +1 -0
- package/dist/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/assets/tsx-COt5Ahok.js +1 -0
- package/dist/assets/turtle-BsS91CYL.js +1 -0
- package/dist/assets/twig-DNn4PbVi.js +1 -0
- package/dist/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/assets/typespec-BGHnOYBU.js +1 -0
- package/dist/assets/typst-DHCkPAjA.js +1 -0
- package/dist/assets/v-BcVCzyr7.js +1 -0
- package/dist/assets/vala-CsfeWuGM.js +1 -0
- package/dist/assets/vb-D17OF-Vu.js +1 -0
- package/dist/assets/{vendor-codemirror-B88_OPWf.js → vendor-codemirror-Dz7_EqNA.js} +3 -3
- package/dist/assets/{vendor-react-C3RJLQGO.js → vendor-react-Cpt6D04s.js} +11 -11
- package/dist/assets/vennDiagram-LZ73GAT5-CaQg4oZK.js +34 -0
- package/dist/assets/verilog-BQ8w6xss.js +1 -0
- package/dist/assets/vesper-DU1UobuO.js +1 -0
- package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/assets/viml-CJc9bBzg.js +1 -0
- package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/assets/vue-DN_0RTcg.js +1 -0
- package/dist/assets/vue-html-AaS7Mt5G.js +1 -0
- package/dist/assets/vue-vine-CQOfvN7w.js +1 -0
- package/dist/assets/vyper-CDx5xZoG.js +1 -0
- package/dist/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/assets/wikitext-BhOHFoWU.js +1 -0
- package/dist/assets/wit-5i3qLPDT.js +1 -0
- package/dist/assets/wolfram-lXgVvXCa.js +1 -0
- package/dist/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/assets/xychartDiagram-JWTSCODW-C8dCbTeM.js +7 -0
- package/dist/assets/yaml-Buea-lGh.js +1 -0
- package/dist/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/assets/zig-VOosw3JB.js +1 -0
- package/dist/index.html +35 -21
- package/dist/manifest.json +1 -1
- package/dist/sw.js +18 -46
- package/package.json +12 -8
- package/server/bin/codex-sdk-wrapper.js +49 -0
- package/server/channels/runtime/AgentRuntimeAdapter.js +2 -5
- package/server/channels/store/ChannelStore.js +73 -107
- package/server/claude-sdk.js +160 -6
- package/server/cli.js +590 -32
- package/server/cli.test.js +76 -0
- package/server/database/db.js +438 -372
- package/server/external-agent/auth.js +88 -0
- package/server/external-agent/service.js +1052 -0
- package/server/external-agent/service.test.js +41 -0
- package/server/external-agent/ws.js +1526 -0
- package/server/external-agent/ws.test.js +289 -0
- package/server/gemini-cli.js +108 -20
- package/server/index.js +115 -121
- package/server/load-env.js +16 -13
- package/server/openai-codex.js +165 -11
- package/server/opencode-cli.js +3 -2
- package/server/projects.js +432 -338
- package/server/routes/agent.js +347 -459
- package/server/routes/auth.js +14 -36
- package/server/routes/cli-auth.js +60 -113
- package/server/routes/commands.js +16 -26
- package/server/routes/git.js +5 -16
- package/server/routes/projects.js +2 -7
- package/server/routes/session-core.js +177 -0
- package/server/session-core/abortSession.js +48 -0
- package/server/session-core/eventStore.js +139 -0
- package/server/session-core/providerAdapters.js +84 -0
- package/server/session-core/providerDiscovery.js +235 -0
- package/server/session-core/runtimeState.js +390 -0
- package/server/session-core/runtimeWriter.js +59 -0
- package/server/utils/agentCallback.js +273 -0
- package/server/utils/agentImages.js +253 -0
- package/server/utils/codexPath.js +47 -0
- package/server/utils/defaultWorkingDirectory.js +34 -0
- package/shared/conversationEvents.js +1071 -0
- package/shared/modelConstants.js +18 -24
- package/dist/assets/index-CVjMty4a.js +0 -902
- package/dist/assets/index-eo5scY_Z.css +0 -32
- package/server/cursor-cli.js +0 -276
- package/server/database/init.sql +0 -98
- package/server/routes/cursor.js +0 -795
package/server/database/db.js
CHANGED
|
@@ -1,469 +1,535 @@
|
|
|
1
|
-
import
|
|
1
|
+
import crypto from 'crypto';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs';
|
|
4
|
-
import crypto from 'crypto';
|
|
5
4
|
import { fileURLToPath } from 'url';
|
|
6
5
|
import { dirname } from 'path';
|
|
7
6
|
|
|
8
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
8
|
const __dirname = dirname(__filename);
|
|
10
9
|
|
|
11
|
-
// ANSI color codes for terminal output
|
|
12
10
|
const colors = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
reset: '\x1b[0m',
|
|
12
|
+
bright: '\x1b[1m',
|
|
13
|
+
cyan: '\x1b[36m',
|
|
14
|
+
dim: '\x1b[2m',
|
|
17
15
|
};
|
|
18
16
|
|
|
19
17
|
const c = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
info: (text) => `${colors.cyan}${text}${colors.reset}`,
|
|
19
|
+
bright: (text) => `${colors.bright}${text}${colors.reset}`,
|
|
20
|
+
dim: (text) => `${colors.dim}${text}${colors.reset}`,
|
|
23
21
|
};
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
const DB_PATH = process.env.DATABASE_PATH || path.join(__dirname, 'auth.db');
|
|
27
|
-
const INIT_SQL_PATH = path.join(__dirname, 'init.sql');
|
|
28
|
-
|
|
29
|
-
// Ensure database directory exists if custom path is provided
|
|
30
|
-
if (process.env.DATABASE_PATH) {
|
|
31
|
-
const dbDir = path.dirname(DB_PATH);
|
|
32
|
-
try {
|
|
33
|
-
if (!fs.existsSync(dbDir)) {
|
|
34
|
-
fs.mkdirSync(dbDir, { recursive: true });
|
|
35
|
-
console.log(`Created database directory: ${dbDir}`);
|
|
36
|
-
}
|
|
37
|
-
} catch (error) {
|
|
38
|
-
console.error(`Failed to create database directory ${dbDir}:`, error.message);
|
|
39
|
-
throw error;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Create database connection
|
|
44
|
-
const db = new Database(DB_PATH);
|
|
45
|
-
|
|
46
|
-
// Show app installation path prominently
|
|
23
|
+
const DATA_FILE_PATH = process.env.DATA_FILE_PATH || path.join(__dirname, 'state.json');
|
|
47
24
|
const appInstallPath = path.join(__dirname, '../..');
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
25
|
+
|
|
26
|
+
const DEFAULT_STATE = Object.freeze({
|
|
27
|
+
meta: {
|
|
28
|
+
version: 1,
|
|
29
|
+
counters: {
|
|
30
|
+
userId: 0,
|
|
31
|
+
apiKeyId: 0,
|
|
32
|
+
credentialId: 0,
|
|
33
|
+
allowedUserId: 0,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
users: [],
|
|
37
|
+
apiKeys: [],
|
|
38
|
+
credentials: [],
|
|
39
|
+
channelPlugins: [],
|
|
40
|
+
channelAllowedUsers: [],
|
|
41
|
+
channelSessions: [],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
let stateCache = null;
|
|
45
|
+
|
|
46
|
+
function cloneDefaultState() {
|
|
47
|
+
return JSON.parse(JSON.stringify(DEFAULT_STATE));
|
|
54
48
|
}
|
|
55
|
-
console.log(c.dim('═'.repeat(60)));
|
|
56
|
-
console.log('');
|
|
57
|
-
|
|
58
|
-
const tableExists = (tableName) => {
|
|
59
|
-
const row = db
|
|
60
|
-
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
61
|
-
.get(tableName);
|
|
62
|
-
return !!row;
|
|
63
|
-
};
|
|
64
49
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
function ensureDataDirectory() {
|
|
51
|
+
const dataDir = path.dirname(DATA_FILE_PATH);
|
|
52
|
+
if (!fs.existsSync(dataDir)) {
|
|
53
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
54
|
+
console.log(`Created data directory: ${dataDir}`);
|
|
68
55
|
}
|
|
69
|
-
|
|
70
|
-
};
|
|
56
|
+
}
|
|
71
57
|
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
58
|
+
function normalizeState(rawState) {
|
|
59
|
+
const nextState = cloneDefaultState();
|
|
60
|
+
const source = rawState && typeof rawState === 'object' ? rawState : {};
|
|
61
|
+
const meta = source.meta && typeof source.meta === 'object' ? source.meta : {};
|
|
62
|
+
const counters = meta.counters && typeof meta.counters === 'object' ? meta.counters : {};
|
|
63
|
+
|
|
64
|
+
nextState.meta.version = Number.isFinite(Number(meta.version)) ? Number(meta.version) : 1;
|
|
65
|
+
nextState.meta.counters.userId = Number.isFinite(Number(counters.userId)) ? Number(counters.userId) : 0;
|
|
66
|
+
nextState.meta.counters.apiKeyId = Number.isFinite(Number(counters.apiKeyId)) ? Number(counters.apiKeyId) : 0;
|
|
67
|
+
nextState.meta.counters.credentialId = Number.isFinite(Number(counters.credentialId)) ? Number(counters.credentialId) : 0;
|
|
68
|
+
nextState.meta.counters.allowedUserId = Number.isFinite(Number(counters.allowedUserId)) ? Number(counters.allowedUserId) : 0;
|
|
69
|
+
|
|
70
|
+
nextState.users = Array.isArray(source.users) ? source.users : [];
|
|
71
|
+
nextState.apiKeys = Array.isArray(source.apiKeys) ? source.apiKeys : [];
|
|
72
|
+
nextState.credentials = Array.isArray(source.credentials) ? source.credentials : [];
|
|
73
|
+
nextState.channelPlugins = Array.isArray(source.channelPlugins) ? source.channelPlugins : [];
|
|
74
|
+
nextState.channelAllowedUsers = Array.isArray(source.channelAllowedUsers) ? source.channelAllowedUsers : [];
|
|
75
|
+
nextState.channelSessions = Array.isArray(source.channelSessions) ? source.channelSessions : [];
|
|
76
|
+
|
|
77
|
+
return nextState;
|
|
78
|
+
}
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
80
|
+
function persistStateSync(nextState) {
|
|
81
|
+
ensureDataDirectory();
|
|
82
|
+
const tempPath = `${DATA_FILE_PATH}.tmp`;
|
|
83
|
+
fs.writeFileSync(tempPath, `${JSON.stringify(nextState, null, 2)}\n`, 'utf8');
|
|
84
|
+
fs.renameSync(tempPath, DATA_FILE_PATH);
|
|
85
|
+
stateCache = nextState;
|
|
86
|
+
}
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'channel_allowed_users'")
|
|
87
|
-
.get();
|
|
88
|
-
const tableSql = String(tableSqlRow?.sql || '');
|
|
89
|
-
const hasLegacyUserIdUnique = /user_id\s+TEXT\s+UNIQUE/i.test(tableSql);
|
|
90
|
-
const needsRebuild = !columns.includes('platform_type') || hasLegacyUserIdUnique;
|
|
91
|
-
|
|
92
|
-
if (needsRebuild) {
|
|
93
|
-
console.log('Running migration: Rebuilding channel_allowed_users with platform isolation');
|
|
94
|
-
const beforeCount = db.prepare('SELECT COUNT(*) AS count FROM channel_allowed_users').get()?.count || 0;
|
|
95
|
-
|
|
96
|
-
db.transaction(() => {
|
|
97
|
-
db.exec('ALTER TABLE channel_allowed_users RENAME TO channel_allowed_users_old');
|
|
98
|
-
db.exec(`
|
|
99
|
-
CREATE TABLE channel_allowed_users (
|
|
100
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
101
|
-
platform_type TEXT NOT NULL DEFAULT 'lark',
|
|
102
|
-
user_id TEXT NOT NULL,
|
|
103
|
-
display_name TEXT,
|
|
104
|
-
note TEXT,
|
|
105
|
-
is_active BOOLEAN DEFAULT 1,
|
|
106
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
107
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
108
|
-
)
|
|
109
|
-
`);
|
|
110
|
-
|
|
111
|
-
const oldColumns = getTableColumns('channel_allowed_users_old');
|
|
112
|
-
const hasOldPlatformType = oldColumns.includes('platform_type');
|
|
113
|
-
|
|
114
|
-
if (hasOldPlatformType) {
|
|
115
|
-
db.exec(`
|
|
116
|
-
INSERT INTO channel_allowed_users (id, platform_type, user_id, display_name, note, is_active, created_at, updated_at)
|
|
117
|
-
SELECT id, COALESCE(platform_type, 'lark'), user_id, display_name, note, is_active, created_at, updated_at
|
|
118
|
-
FROM channel_allowed_users_old
|
|
119
|
-
`);
|
|
120
|
-
} else {
|
|
121
|
-
db.exec(`
|
|
122
|
-
INSERT INTO channel_allowed_users (id, platform_type, user_id, display_name, note, is_active, created_at, updated_at)
|
|
123
|
-
SELECT id, 'lark', user_id, display_name, note, is_active, created_at, updated_at
|
|
124
|
-
FROM channel_allowed_users_old
|
|
125
|
-
`);
|
|
126
|
-
}
|
|
88
|
+
function loadStateSync() {
|
|
89
|
+
ensureDataDirectory();
|
|
127
90
|
|
|
128
|
-
|
|
129
|
-
|
|
91
|
+
if (stateCache) {
|
|
92
|
+
return stateCache;
|
|
93
|
+
}
|
|
130
94
|
|
|
131
|
-
|
|
132
|
-
|
|
95
|
+
if (!fs.existsSync(DATA_FILE_PATH)) {
|
|
96
|
+
const initialState = cloneDefaultState();
|
|
97
|
+
persistStateSync(initialState);
|
|
98
|
+
return initialState;
|
|
133
99
|
}
|
|
134
100
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_channel_allowed_users_platform_type ON channel_allowed_users(platform_type)');
|
|
139
|
-
db.exec('CREATE INDEX IF NOT EXISTS idx_channel_allowed_users_active ON channel_allowed_users(is_active)');
|
|
140
|
-
};
|
|
101
|
+
const raw = fs.readFileSync(DATA_FILE_PATH, 'utf8').trim();
|
|
102
|
+
const parsed = raw ? JSON.parse(raw) : {};
|
|
103
|
+
const normalized = normalizeState(parsed);
|
|
141
104
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return;
|
|
105
|
+
if (JSON.stringify(parsed || {}) !== JSON.stringify(normalized)) {
|
|
106
|
+
persistStateSync(normalized);
|
|
107
|
+
return normalized;
|
|
145
108
|
}
|
|
146
109
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
db.exec("ALTER TABLE channel_sessions ADD COLUMN platform_type TEXT NOT NULL DEFAULT 'lark'");
|
|
151
|
-
}
|
|
110
|
+
stateCache = normalized;
|
|
111
|
+
return normalized;
|
|
112
|
+
}
|
|
152
113
|
|
|
153
|
-
|
|
114
|
+
function getStateSnapshot() {
|
|
115
|
+
return loadStateSync();
|
|
116
|
+
}
|
|
154
117
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
118
|
+
function updateStateSync(mutator) {
|
|
119
|
+
const currentState = getStateSnapshot();
|
|
120
|
+
const workingCopy = JSON.parse(JSON.stringify(currentState));
|
|
121
|
+
const result = mutator(workingCopy);
|
|
122
|
+
persistStateSync(workingCopy);
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
162
125
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
126
|
+
function nextCounter(state, key) {
|
|
127
|
+
state.meta.counters[key] = Number(state.meta.counters[key] || 0) + 1;
|
|
128
|
+
return state.meta.counters[key];
|
|
129
|
+
}
|
|
167
130
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
131
|
+
function nowIso() {
|
|
132
|
+
return new Date().toISOString();
|
|
133
|
+
}
|
|
172
134
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
135
|
+
function sanitizeActiveUser(user) {
|
|
136
|
+
if (!user || user.is_active === false) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
177
139
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
db.exec('ALTER TABLE users ADD COLUMN has_completed_onboarding BOOLEAN DEFAULT 0');
|
|
181
|
-
}
|
|
140
|
+
return user;
|
|
141
|
+
}
|
|
182
142
|
|
|
183
|
-
|
|
184
|
-
|
|
143
|
+
function toUserPublic(user) {
|
|
144
|
+
const activeUser = sanitizeActiveUser(user);
|
|
145
|
+
if (!activeUser) return null;
|
|
146
|
+
return {
|
|
147
|
+
id: activeUser.id,
|
|
148
|
+
username: activeUser.username,
|
|
149
|
+
created_at: activeUser.created_at,
|
|
150
|
+
last_login: activeUser.last_login,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
185
153
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
throw error;
|
|
190
|
-
}
|
|
191
|
-
};
|
|
154
|
+
function findActiveUserById(state, userId) {
|
|
155
|
+
return sanitizeActiveUser(state.users.find((user) => user.id === userId));
|
|
156
|
+
}
|
|
192
157
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const initSQL = fs.readFileSync(INIT_SQL_PATH, 'utf8');
|
|
197
|
-
db.exec(initSQL);
|
|
198
|
-
console.log('Database initialized successfully');
|
|
199
|
-
runMigrations();
|
|
200
|
-
} catch (error) {
|
|
201
|
-
console.error('Error initializing database:', error.message);
|
|
202
|
-
throw error;
|
|
203
|
-
}
|
|
204
|
-
};
|
|
158
|
+
function findActiveUserByUsername(state, username) {
|
|
159
|
+
return sanitizeActiveUser(state.users.find((user) => user.username === username));
|
|
160
|
+
}
|
|
205
161
|
|
|
206
|
-
// User database operations
|
|
207
162
|
const userDb = {
|
|
208
|
-
|
|
209
|
-
hasUsers: () => {
|
|
210
|
-
try {
|
|
211
|
-
const row = db.prepare('SELECT COUNT(*) as count FROM users').get();
|
|
212
|
-
return row.count > 0;
|
|
213
|
-
} catch (err) {
|
|
214
|
-
throw err;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
163
|
+
hasUsers: () => getStateSnapshot().users.some((user) => user.is_active !== false),
|
|
217
164
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return { id: result.lastInsertRowid, username };
|
|
224
|
-
} catch (err) {
|
|
225
|
-
throw err;
|
|
165
|
+
registerUser: (username, passwordHash) => updateStateSync((state) => {
|
|
166
|
+
if (state.users.some((user) => user.is_active !== false)) {
|
|
167
|
+
const error = new Error('User already exists. This is a single-user system.');
|
|
168
|
+
error.code = 'USER_EXISTS';
|
|
169
|
+
throw error;
|
|
226
170
|
}
|
|
227
|
-
},
|
|
228
171
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
return row;
|
|
234
|
-
} catch (err) {
|
|
235
|
-
throw err;
|
|
172
|
+
if (state.users.some((user) => user.username === username)) {
|
|
173
|
+
const error = new Error('Username already exists');
|
|
174
|
+
error.code = 'USERNAME_EXISTS';
|
|
175
|
+
throw error;
|
|
236
176
|
}
|
|
237
|
-
},
|
|
238
177
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
178
|
+
const timestamp = nowIso();
|
|
179
|
+
const user = {
|
|
180
|
+
id: nextCounter(state, 'userId'),
|
|
181
|
+
username,
|
|
182
|
+
password_hash: passwordHash,
|
|
183
|
+
created_at: timestamp,
|
|
184
|
+
last_login: timestamp,
|
|
185
|
+
is_active: true,
|
|
186
|
+
git_name: null,
|
|
187
|
+
git_email: null,
|
|
188
|
+
has_completed_onboarding: false,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
state.users.push(user);
|
|
192
|
+
return { id: user.id, username: user.username };
|
|
193
|
+
}),
|
|
194
|
+
|
|
195
|
+
createUser: (username, passwordHash) => updateStateSync((state) => {
|
|
196
|
+
if (state.users.some((user) => user.username === username)) {
|
|
197
|
+
const error = new Error('Username already exists');
|
|
198
|
+
error.code = 'USERNAME_EXISTS';
|
|
199
|
+
throw error;
|
|
245
200
|
}
|
|
246
|
-
},
|
|
247
201
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
202
|
+
const user = {
|
|
203
|
+
id: nextCounter(state, 'userId'),
|
|
204
|
+
username,
|
|
205
|
+
password_hash: passwordHash,
|
|
206
|
+
created_at: nowIso(),
|
|
207
|
+
last_login: null,
|
|
208
|
+
is_active: true,
|
|
209
|
+
git_name: null,
|
|
210
|
+
git_email: null,
|
|
211
|
+
has_completed_onboarding: false,
|
|
212
|
+
};
|
|
213
|
+
state.users.push(user);
|
|
214
|
+
return { id: user.id, username: user.username };
|
|
215
|
+
}),
|
|
216
|
+
|
|
217
|
+
getUserByUsername: (username) => findActiveUserByUsername(getStateSnapshot(), username) || null,
|
|
218
|
+
|
|
219
|
+
updateLastLogin: (userId) => updateStateSync((state) => {
|
|
220
|
+
const user = findActiveUserById(state, userId);
|
|
221
|
+
if (user) {
|
|
222
|
+
user.last_login = nowIso();
|
|
255
223
|
}
|
|
256
|
-
},
|
|
224
|
+
}),
|
|
225
|
+
|
|
226
|
+
getUserById: (userId) => toUserPublic(findActiveUserById(getStateSnapshot(), userId)),
|
|
257
227
|
|
|
258
228
|
getFirstUser: () => {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return row;
|
|
262
|
-
} catch (err) {
|
|
263
|
-
throw err;
|
|
264
|
-
}
|
|
229
|
+
const user = getStateSnapshot().users.find((entry) => entry.is_active !== false);
|
|
230
|
+
return toUserPublic(user);
|
|
265
231
|
},
|
|
266
232
|
|
|
267
|
-
updateGitConfig: (userId, gitName, gitEmail) => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
},
|
|
233
|
+
updateGitConfig: (userId, gitName, gitEmail) => updateStateSync((state) => {
|
|
234
|
+
const user = findActiveUserById(state, userId);
|
|
235
|
+
if (!user) return;
|
|
236
|
+
user.git_name = gitName || null;
|
|
237
|
+
user.git_email = gitEmail || null;
|
|
238
|
+
}),
|
|
275
239
|
|
|
276
240
|
getGitConfig: (userId) => {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
return
|
|
280
|
-
} catch (err) {
|
|
281
|
-
throw err;
|
|
241
|
+
const user = findActiveUserById(getStateSnapshot(), userId);
|
|
242
|
+
if (!user) {
|
|
243
|
+
return null;
|
|
282
244
|
}
|
|
245
|
+
return {
|
|
246
|
+
git_name: user.git_name || null,
|
|
247
|
+
git_email: user.git_email || null,
|
|
248
|
+
};
|
|
283
249
|
},
|
|
284
250
|
|
|
285
|
-
completeOnboarding: (userId) => {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
} catch (err) {
|
|
290
|
-
throw err;
|
|
251
|
+
completeOnboarding: (userId) => updateStateSync((state) => {
|
|
252
|
+
const user = findActiveUserById(state, userId);
|
|
253
|
+
if (user) {
|
|
254
|
+
user.has_completed_onboarding = true;
|
|
291
255
|
}
|
|
292
|
-
},
|
|
256
|
+
}),
|
|
293
257
|
|
|
294
258
|
hasCompletedOnboarding: (userId) => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
} catch (err) {
|
|
299
|
-
throw err;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
259
|
+
const user = findActiveUserById(getStateSnapshot(), userId);
|
|
260
|
+
return !!user?.has_completed_onboarding;
|
|
261
|
+
},
|
|
302
262
|
};
|
|
303
263
|
|
|
304
|
-
// API Keys database operations
|
|
305
264
|
const apiKeysDb = {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
265
|
+
generateApiKey: () => `ck_${crypto.randomBytes(32).toString('hex')}`,
|
|
266
|
+
|
|
267
|
+
createApiKey: (userId, keyName) => updateStateSync((state) => {
|
|
268
|
+
const timestamp = nowIso();
|
|
269
|
+
const entry = {
|
|
270
|
+
id: nextCounter(state, 'apiKeyId'),
|
|
271
|
+
user_id: userId,
|
|
272
|
+
key_name: keyName,
|
|
273
|
+
api_key: apiKeysDb.generateApiKey(),
|
|
274
|
+
created_at: timestamp,
|
|
275
|
+
last_used: null,
|
|
276
|
+
is_active: true,
|
|
277
|
+
};
|
|
278
|
+
state.apiKeys.push(entry);
|
|
279
|
+
return { id: entry.id, keyName: entry.key_name, apiKey: entry.api_key };
|
|
280
|
+
}),
|
|
281
|
+
|
|
282
|
+
getApiKeys: (userId) => getStateSnapshot().apiKeys
|
|
283
|
+
.filter((entry) => entry.user_id === userId)
|
|
284
|
+
.sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))
|
|
285
|
+
.map((entry) => ({ ...entry })),
|
|
286
|
+
|
|
287
|
+
validateApiKey: (apiKey) => updateStateSync((state) => {
|
|
288
|
+
const entry = state.apiKeys.find((item) => item.api_key === apiKey && item.is_active !== false);
|
|
289
|
+
if (!entry) {
|
|
290
|
+
return null;
|
|
320
291
|
}
|
|
321
|
-
},
|
|
322
292
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const rows = db.prepare('SELECT id, key_name, api_key, created_at, last_used, is_active FROM api_keys WHERE user_id = ? ORDER BY created_at DESC').all(userId);
|
|
327
|
-
return rows;
|
|
328
|
-
} catch (err) {
|
|
329
|
-
throw err;
|
|
293
|
+
const user = findActiveUserById(state, entry.user_id);
|
|
294
|
+
if (!user) {
|
|
295
|
+
return null;
|
|
330
296
|
}
|
|
331
|
-
},
|
|
332
297
|
|
|
333
|
-
|
|
334
|
-
validateApiKey: (apiKey) => {
|
|
335
|
-
try {
|
|
336
|
-
const row = db.prepare(`
|
|
337
|
-
SELECT u.id, u.username, ak.id as api_key_id
|
|
338
|
-
FROM api_keys ak
|
|
339
|
-
JOIN users u ON ak.user_id = u.id
|
|
340
|
-
WHERE ak.api_key = ? AND ak.is_active = 1 AND u.is_active = 1
|
|
341
|
-
`).get(apiKey);
|
|
342
|
-
|
|
343
|
-
if (row) {
|
|
344
|
-
// Update last_used timestamp
|
|
345
|
-
db.prepare('UPDATE api_keys SET last_used = CURRENT_TIMESTAMP WHERE id = ?').run(row.api_key_id);
|
|
346
|
-
}
|
|
298
|
+
entry.last_used = nowIso();
|
|
347
299
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
300
|
+
return {
|
|
301
|
+
id: user.id,
|
|
302
|
+
username: user.username,
|
|
303
|
+
api_key_id: entry.id,
|
|
304
|
+
};
|
|
305
|
+
}),
|
|
353
306
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const result = stmt.run(apiKeyId, userId);
|
|
359
|
-
return result.changes > 0;
|
|
360
|
-
} catch (err) {
|
|
361
|
-
throw err;
|
|
307
|
+
deleteApiKey: (userId, apiKeyId) => updateStateSync((state) => {
|
|
308
|
+
const index = state.apiKeys.findIndex((entry) => entry.id === apiKeyId && entry.user_id === userId);
|
|
309
|
+
if (index < 0) {
|
|
310
|
+
return false;
|
|
362
311
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
return
|
|
371
|
-
} catch (err) {
|
|
372
|
-
throw err;
|
|
312
|
+
state.apiKeys.splice(index, 1);
|
|
313
|
+
return true;
|
|
314
|
+
}),
|
|
315
|
+
|
|
316
|
+
toggleApiKey: (userId, apiKeyId, isActive) => updateStateSync((state) => {
|
|
317
|
+
const entry = state.apiKeys.find((item) => item.id === apiKeyId && item.user_id === userId);
|
|
318
|
+
if (!entry) {
|
|
319
|
+
return false;
|
|
373
320
|
}
|
|
374
|
-
|
|
321
|
+
entry.is_active = !!isActive;
|
|
322
|
+
return true;
|
|
323
|
+
}),
|
|
375
324
|
};
|
|
376
325
|
|
|
377
|
-
// User credentials database operations (for GitHub tokens, GitLab tokens, etc.)
|
|
378
326
|
const credentialsDb = {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
327
|
+
createCredential: (userId, credentialName, credentialType, credentialValue, description = null) => updateStateSync((state) => {
|
|
328
|
+
const entry = {
|
|
329
|
+
id: nextCounter(state, 'credentialId'),
|
|
330
|
+
user_id: userId,
|
|
331
|
+
credential_name: credentialName,
|
|
332
|
+
credential_type: credentialType,
|
|
333
|
+
credential_value: credentialValue,
|
|
334
|
+
description,
|
|
335
|
+
created_at: nowIso(),
|
|
336
|
+
is_active: true,
|
|
337
|
+
};
|
|
338
|
+
state.credentials.push(entry);
|
|
339
|
+
return { id: entry.id, credentialName: entry.credential_name, credentialType: entry.credential_type };
|
|
340
|
+
}),
|
|
341
|
+
|
|
342
|
+
getCredentials: (userId, credentialType = null) => getStateSnapshot().credentials
|
|
343
|
+
.filter((entry) => entry.user_id === userId && (!credentialType || entry.credential_type === credentialType))
|
|
344
|
+
.sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))
|
|
345
|
+
.map(({ credential_value, ...rest }) => ({ ...rest })),
|
|
346
|
+
|
|
347
|
+
getActiveCredential: (userId, credentialType) => {
|
|
348
|
+
const match = getStateSnapshot().credentials
|
|
349
|
+
.filter((entry) => entry.user_id === userId && entry.credential_type === credentialType && entry.is_active !== false)
|
|
350
|
+
.sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))[0];
|
|
351
|
+
return match?.credential_value || null;
|
|
388
352
|
},
|
|
389
353
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
354
|
+
getCredentialById: (userId, credentialId, credentialType = null) => {
|
|
355
|
+
const entry = getStateSnapshot().credentials.find((item) => (
|
|
356
|
+
item.id === credentialId
|
|
357
|
+
&& item.user_id === userId
|
|
358
|
+
&& item.is_active !== false
|
|
359
|
+
&& (!credentialType || item.credential_type === credentialType)
|
|
360
|
+
));
|
|
361
|
+
return entry ? { ...entry } : null;
|
|
362
|
+
},
|
|
395
363
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
364
|
+
deleteCredential: (userId, credentialId) => updateStateSync((state) => {
|
|
365
|
+
const index = state.credentials.findIndex((entry) => entry.id === credentialId && entry.user_id === userId);
|
|
366
|
+
if (index < 0) {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
state.credentials.splice(index, 1);
|
|
370
|
+
return true;
|
|
371
|
+
}),
|
|
372
|
+
|
|
373
|
+
toggleCredential: (userId, credentialId, isActive) => updateStateSync((state) => {
|
|
374
|
+
const entry = state.credentials.find((item) => item.id === credentialId && item.user_id === userId);
|
|
375
|
+
if (!entry) {
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
entry.is_active = !!isActive;
|
|
379
|
+
return true;
|
|
380
|
+
}),
|
|
381
|
+
};
|
|
400
382
|
|
|
401
|
-
|
|
383
|
+
const githubTokensDb = {
|
|
384
|
+
createGithubToken: (userId, tokenName, githubToken, description = null) => credentialsDb.createCredential(userId, tokenName, 'github_token', githubToken, description),
|
|
385
|
+
getGithubTokens: (userId) => credentialsDb.getCredentials(userId, 'github_token'),
|
|
386
|
+
getActiveGithubToken: (userId) => credentialsDb.getActiveCredential(userId, 'github_token'),
|
|
387
|
+
getGithubTokenById: (userId, tokenId) => credentialsDb.getCredentialById(userId, tokenId, 'github_token'),
|
|
388
|
+
deleteGithubToken: (userId, tokenId) => credentialsDb.deleteCredential(userId, tokenId),
|
|
389
|
+
toggleGithubToken: (userId, tokenId, isActive) => credentialsDb.toggleCredential(userId, tokenId, isActive),
|
|
390
|
+
};
|
|
402
391
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
throw err;
|
|
407
|
-
}
|
|
392
|
+
const channelDb = {
|
|
393
|
+
getPlugin(pluginId) {
|
|
394
|
+
return getStateSnapshot().channelPlugins.find((entry) => entry.id === pluginId) || null;
|
|
408
395
|
},
|
|
409
396
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
397
|
+
upsertPlugin(plugin) {
|
|
398
|
+
return updateStateSync((state) => {
|
|
399
|
+
const index = state.channelPlugins.findIndex((entry) => entry.id === plugin.id);
|
|
400
|
+
if (index >= 0) {
|
|
401
|
+
state.channelPlugins[index] = { ...state.channelPlugins[index], ...plugin };
|
|
402
|
+
} else {
|
|
403
|
+
state.channelPlugins.push({ ...plugin });
|
|
404
|
+
}
|
|
405
|
+
return { ...state.channelPlugins.find((entry) => entry.id === plugin.id) };
|
|
406
|
+
});
|
|
418
407
|
},
|
|
419
408
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
return result.changes > 0;
|
|
426
|
-
} catch (err) {
|
|
427
|
-
throw err;
|
|
428
|
-
}
|
|
409
|
+
listAllowedUsers(platform) {
|
|
410
|
+
return getStateSnapshot().channelAllowedUsers
|
|
411
|
+
.filter((entry) => entry.platform_type === platform)
|
|
412
|
+
.sort((left, right) => String(right.created_at).localeCompare(String(left.created_at)))
|
|
413
|
+
.map((entry) => ({ ...entry }));
|
|
429
414
|
},
|
|
430
415
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
};
|
|
416
|
+
addAllowedUser(platform, { userId, displayName = null, note = null }) {
|
|
417
|
+
return updateStateSync((state) => {
|
|
418
|
+
const duplicate = state.channelAllowedUsers.find((entry) => entry.platform_type === platform && entry.user_id === userId);
|
|
419
|
+
if (duplicate) {
|
|
420
|
+
const error = new Error('Allowed user already exists');
|
|
421
|
+
error.code = 'CHANNEL_ALLOWED_USER_EXISTS';
|
|
422
|
+
throw error;
|
|
423
|
+
}
|
|
442
424
|
|
|
443
|
-
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
425
|
+
const timestamp = nowIso();
|
|
426
|
+
const entry = {
|
|
427
|
+
id: nextCounter(state, 'allowedUserId'),
|
|
428
|
+
platform_type: platform,
|
|
429
|
+
user_id: userId,
|
|
430
|
+
display_name: displayName,
|
|
431
|
+
note,
|
|
432
|
+
is_active: true,
|
|
433
|
+
created_at: timestamp,
|
|
434
|
+
updated_at: timestamp,
|
|
435
|
+
};
|
|
436
|
+
state.channelAllowedUsers.push(entry);
|
|
437
|
+
return { ...entry };
|
|
438
|
+
});
|
|
447
439
|
},
|
|
448
|
-
|
|
449
|
-
|
|
440
|
+
|
|
441
|
+
removeAllowedUser(platform, id) {
|
|
442
|
+
return updateStateSync((state) => {
|
|
443
|
+
const index = state.channelAllowedUsers.findIndex((entry) => entry.platform_type === platform && entry.id === id);
|
|
444
|
+
if (index < 0) return false;
|
|
445
|
+
state.channelAllowedUsers.splice(index, 1);
|
|
446
|
+
return true;
|
|
447
|
+
});
|
|
450
448
|
},
|
|
451
|
-
|
|
452
|
-
|
|
449
|
+
|
|
450
|
+
toggleAllowedUser(platform, id, isActive) {
|
|
451
|
+
return updateStateSync((state) => {
|
|
452
|
+
const entry = state.channelAllowedUsers.find((item) => item.platform_type === platform && item.id === id);
|
|
453
|
+
if (!entry) return false;
|
|
454
|
+
entry.is_active = !!isActive;
|
|
455
|
+
entry.updated_at = nowIso();
|
|
456
|
+
return true;
|
|
457
|
+
});
|
|
453
458
|
},
|
|
454
|
-
|
|
455
|
-
|
|
459
|
+
|
|
460
|
+
isAllowedUser(platform, userId) {
|
|
461
|
+
return !!getStateSnapshot().channelAllowedUsers.find((entry) => entry.platform_type === platform && entry.user_id === userId && entry.is_active !== false);
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
getChannelSession({ platform, userId, chatId, backend }) {
|
|
465
|
+
const entry = getStateSnapshot().channelSessions.find((item) => (
|
|
466
|
+
item.platform_type === platform
|
|
467
|
+
&& item.user_id === userId
|
|
468
|
+
&& item.chat_id === chatId
|
|
469
|
+
&& item.backend === backend
|
|
470
|
+
));
|
|
471
|
+
return entry ? { ...entry } : null;
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
upsertChannelSession({ platform, userId, chatId, backend, providerSessionId, projectPath }) {
|
|
475
|
+
return updateStateSync((state) => {
|
|
476
|
+
const timestamp = nowIso();
|
|
477
|
+
const existing = state.channelSessions.find((item) => (
|
|
478
|
+
item.platform_type === platform
|
|
479
|
+
&& item.user_id === userId
|
|
480
|
+
&& item.chat_id === chatId
|
|
481
|
+
&& item.backend === backend
|
|
482
|
+
));
|
|
483
|
+
|
|
484
|
+
if (existing) {
|
|
485
|
+
existing.provider_session_id = providerSessionId || null;
|
|
486
|
+
existing.project_path = projectPath || null;
|
|
487
|
+
existing.updated_at = timestamp;
|
|
488
|
+
return { ...existing };
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const entry = {
|
|
492
|
+
id: crypto.randomUUID(),
|
|
493
|
+
platform_type: platform,
|
|
494
|
+
user_id: userId,
|
|
495
|
+
chat_id: chatId,
|
|
496
|
+
backend,
|
|
497
|
+
provider_session_id: providerSessionId || null,
|
|
498
|
+
project_path: projectPath || null,
|
|
499
|
+
updated_at: timestamp,
|
|
500
|
+
};
|
|
501
|
+
state.channelSessions.push(entry);
|
|
502
|
+
return { ...entry };
|
|
503
|
+
});
|
|
456
504
|
},
|
|
457
|
-
toggleGithubToken: (userId, tokenId, isActive) => {
|
|
458
|
-
return credentialsDb.toggleCredential(userId, tokenId, isActive);
|
|
459
|
-
}
|
|
460
505
|
};
|
|
461
506
|
|
|
507
|
+
async function initializeDatabase() {
|
|
508
|
+
const state = getStateSnapshot();
|
|
509
|
+
|
|
510
|
+
console.log('');
|
|
511
|
+
console.log(c.dim('═'.repeat(60)));
|
|
512
|
+
console.log(`${c.info('[INFO]')} App Installation: ${c.bright(appInstallPath)}`);
|
|
513
|
+
console.log(`${c.info('[INFO]')} Data File: ${c.dim(path.relative(appInstallPath, DATA_FILE_PATH))}`);
|
|
514
|
+
if (process.env.DATA_FILE_PATH) {
|
|
515
|
+
console.log(` ${c.dim('(Using custom DATA_FILE_PATH from environment)')}`);
|
|
516
|
+
}
|
|
517
|
+
console.log(c.dim('═'.repeat(60)));
|
|
518
|
+
console.log('');
|
|
519
|
+
console.log('Data file initialized successfully');
|
|
520
|
+
return state;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function getDataFilePath() {
|
|
524
|
+
return DATA_FILE_PATH;
|
|
525
|
+
}
|
|
526
|
+
|
|
462
527
|
export {
|
|
463
|
-
db,
|
|
464
528
|
initializeDatabase,
|
|
529
|
+
getDataFilePath,
|
|
465
530
|
userDb,
|
|
466
531
|
apiKeysDb,
|
|
467
532
|
credentialsDb,
|
|
468
|
-
githubTokensDb
|
|
533
|
+
githubTokensDb,
|
|
534
|
+
channelDb,
|
|
469
535
|
};
|