@axhub/genie 0.1.7 → 0.1.9
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 +2 -2
- package/dist/assets/App-IUhj6pRQ.js +546 -0
- package/dist/assets/App-qxJ8_QYu.css +32 -0
- package/dist/assets/ReviewApp-B8aNlXpI.js +1 -0
- package/dist/assets/_basePickBy-DF_C8v-X.js +1 -0
- package/dist/assets/_baseUniq-Dl8X6bvw.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-TwO_Ni8v.js +1 -0
- package/dist/assets/architectureDiagram-2XIMDMQ5-Dgm9kjQy.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-BhTxXYHE.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-D3xrrPyf.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-D6xYGBae.js +1 -0
- package/dist/assets/chunk-4BX2VUAB-Fb3wkGSX.js +1 -0
- package/dist/assets/chunk-55IACEB6-CQwPJLM_.js +1 -0
- package/dist/assets/chunk-FMBD7UC4-B3SocdK3.js +15 -0
- package/dist/assets/chunk-JSJVCQXG-4LjhKVWX.js +1 -0
- package/dist/assets/chunk-KX2RTZJC-B5NX8jxL.js +1 -0
- package/dist/assets/chunk-NQ4KR5QH-6puKzw3k.js +220 -0
- package/dist/assets/chunk-QZHKN3VN-CxscPgdC.js +1 -0
- package/dist/assets/chunk-WL4C6EOR-uBFUeI3B.js +189 -0
- package/dist/assets/clarity-D53aC0YG.js +1 -0
- package/dist/assets/classDiagram-VBA2DB6C-CAq2xBD7.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-CAq2xBD7.js +1 -0
- package/dist/assets/clojure-P80f7IUj.js +1 -0
- package/dist/assets/clone-Ci5Ji0hp.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-DlbARPn2.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-D5rHdqja.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-1UmM7jTs.js +24 -0
- package/dist/assets/diagram-IFDJBPK2-BiB8xLQb.js +43 -0
- package/dist/assets/diagram-P4PSJMXO-D0DHiPZv.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-CnRJ2Jix.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-CEgo6QRr.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-BIuQLJvD.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-BgM4MazK.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-CAfp4sq_.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-qMmmT5JC.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-DIJsxqXa.css +1 -0
- package/dist/assets/index-DLN_-tVh.js +2 -0
- package/dist/assets/infoDiagram-LFFYTUFH-CWSerJ0x.js +2 -0
- package/dist/assets/ini-BEwlwnbL.js +1 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-PHBUUO56-CzeVsiJ6.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-D_NYt9lf.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-CX7AUuup.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-DSvVDs_y.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-CVh3kWAl.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-CrPRD2Zy.js +964 -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-w_orDc4B.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-Ddit1h2q.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-DVw1s8Ut.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-DQPZpp_9.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-CfbFynOx.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-BO9n1wra.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-CRL3ceNd.js +1 -0
- package/dist/assets/stateDiagram-v2-FVOUBMTO-CZOgjDCg.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-BR7smGEM.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-DkR8x0Kw.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-D5if-Qdt.js} +3 -3
- package/dist/assets/{vendor-react-C3RJLQGO.js → vendor-react-CSz7XC90.js} +11 -11
- package/dist/assets/vennDiagram-LZ73GAT5-DS7XpPV_.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-BgjSBvNS.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 +37 -23
- package/dist/manifest.json +2 -2
- package/dist/sw.js +18 -46
- package/package.json +12 -7
- package/server/bin/codex-sdk-wrapper.js +49 -0
- package/server/channels/core/ChannelManager.js +399 -0
- package/server/channels/core/PluginManager.js +59 -0
- package/server/channels/index.js +3 -0
- package/server/channels/plugins/BasePlugin.js +46 -0
- package/server/channels/plugins/dingtalk/DingTalkAdapter.js +156 -0
- package/server/channels/plugins/dingtalk/DingTalkPlugin.js +592 -0
- package/server/channels/plugins/dingtalk/index.js +2 -0
- package/server/channels/plugins/lark/LarkAdapter.js +100 -0
- package/server/channels/plugins/lark/LarkCards.js +43 -0
- package/server/channels/plugins/lark/LarkPlugin.js +260 -0
- package/server/channels/runtime/AgentRuntimeAdapter.js +176 -0
- package/server/channels/runtime/DingTalkStreamWriter.js +105 -0
- package/server/channels/runtime/LarkStreamWriter.js +99 -0
- package/server/channels/store/ChannelStore.js +202 -0
- package/server/claude-sdk.js +151 -3
- package/server/cli.js +21 -21
- package/server/database/db.js +449 -275
- package/server/gemini-cli.js +106 -19
- package/server/index.js +87 -108
- package/server/load-env.js +16 -13
- package/server/openai-codex.js +146 -10
- package/server/projects.js +340 -331
- package/server/routes/agent.js +429 -30
- package/server/routes/auth.js +14 -36
- package/server/routes/channels.js +221 -0
- package/server/routes/cli-auth.js +117 -124
- 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/runtimeWriter.js +55 -0
- package/server/utils/agentCallback.js +273 -0
- package/server/utils/codexPath.js +47 -0
- package/shared/conversationEvents.js +1031 -0
- package/shared/modelConstants.js +18 -24
- package/dist/assets/index-C2r-Jzfw.js +0 -897
- package/dist/assets/index-COkoBQi5.css +0 -32
- package/server/cursor-cli.js +0 -276
- package/server/database/init.sql +0 -52
- package/server/routes/cursor.js +0 -795
package/server/projects.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* PROJECT DISCOVERY AND MANAGEMENT SYSTEM
|
|
3
3
|
* ========================================
|
|
4
4
|
*
|
|
5
|
-
* This module manages project discovery for
|
|
5
|
+
* This module manages project discovery for Claude CLI and local agent sessions.
|
|
6
6
|
*
|
|
7
7
|
* ## Architecture Overview
|
|
8
8
|
*
|
|
@@ -11,11 +11,9 @@
|
|
|
11
11
|
* - Contains .jsonl files with conversation history including 'cwd' field
|
|
12
12
|
* - Project metadata stored in ~/.claude/project-config.json
|
|
13
13
|
*
|
|
14
|
-
* 2. **
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* - Contains session directories with SQLite databases (store.db)
|
|
18
|
-
* - Project path is NOT stored in the database - only in the MD5 hash
|
|
14
|
+
* 2. **Manual project metadata**
|
|
15
|
+
* - Project metadata is stored in ~/.claude/project-config.json
|
|
16
|
+
* - Manually added workspaces remain visible even without existing sessions
|
|
19
17
|
*
|
|
20
18
|
* ## Project Discovery Strategy
|
|
21
19
|
*
|
|
@@ -24,25 +22,15 @@
|
|
|
24
22
|
* - Extract actual project path from .jsonl files (cwd field)
|
|
25
23
|
* - Fall back to decoded directory name if no sessions exist
|
|
26
24
|
*
|
|
27
|
-
* 2. **
|
|
28
|
-
* - For each KNOWN project (from Claude or manually added)
|
|
29
|
-
* - Compute MD5 hash of the project's absolute path
|
|
30
|
-
* - Check if ~/.cursor/chats/{md5_hash}/ directory exists
|
|
31
|
-
* - Read session metadata from SQLite store.db files
|
|
32
|
-
*
|
|
33
|
-
* 3. **Manual Project Addition**:
|
|
25
|
+
* 2. **Manual Project Addition**:
|
|
34
26
|
* - Users can manually add project paths via UI
|
|
35
27
|
* - Stored in ~/.claude/project-config.json with 'manuallyAdded' flag
|
|
36
|
-
* - Allows discovering
|
|
28
|
+
* - Allows discovering additional local provider sessions without Claude sessions
|
|
37
29
|
*
|
|
38
30
|
* ## Critical Limitations
|
|
39
31
|
*
|
|
40
|
-
* - **CANNOT discover Cursor-only projects**: From a quick check, there was no mention of
|
|
41
|
-
* the cwd of each project. if someone has the time, you can try to reverse engineer it.
|
|
42
|
-
*
|
|
43
32
|
* - **Project relocation breaks history**: If a project directory is moved or renamed,
|
|
44
|
-
*
|
|
45
|
-
* path is known and manually added.
|
|
33
|
+
* existing local session history may no longer align with the new path.
|
|
46
34
|
*
|
|
47
35
|
* ## Error Handling
|
|
48
36
|
*
|
|
@@ -59,12 +47,10 @@
|
|
|
59
47
|
|
|
60
48
|
import { promises as fs } from 'fs';
|
|
61
49
|
import fsSync from 'fs';
|
|
50
|
+
import os from 'os';
|
|
62
51
|
import path from 'path';
|
|
63
52
|
import readline from 'readline';
|
|
64
53
|
import crypto from 'crypto';
|
|
65
|
-
import sqlite3 from 'sqlite3';
|
|
66
|
-
import { open } from 'sqlite';
|
|
67
|
-
import os from 'os';
|
|
68
54
|
import { parseCodexTokenCountInfo } from './utils/codexTokenUsage.js';
|
|
69
55
|
|
|
70
56
|
// Import TaskMaster detection functions
|
|
@@ -197,12 +183,131 @@ async function detectTaskMasterFolder(projectPath) {
|
|
|
197
183
|
|
|
198
184
|
// Cache for extracted project directories
|
|
199
185
|
const projectDirectoryCache = new Map();
|
|
186
|
+
const PROVIDER_SESSION_LOOKUP_CACHE_TTL_MS = 5000;
|
|
187
|
+
const providerSessionLookupCache = {
|
|
188
|
+
codex: { key: null, data: null, promise: null, expiresAt: 0 },
|
|
189
|
+
gemini: { key: null, data: null, promise: null, expiresAt: 0 },
|
|
190
|
+
opencode: { key: null, data: null, promise: null, expiresAt: 0 }
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
function normalizeComparableProjectPath(projectPath) {
|
|
194
|
+
if (typeof projectPath !== 'string' || !projectPath.trim()) {
|
|
195
|
+
return '';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const withoutWindowsLongPathPrefix = projectPath.startsWith('\\\\?\\')
|
|
199
|
+
? projectPath.slice(4)
|
|
200
|
+
: projectPath;
|
|
201
|
+
|
|
202
|
+
return path.normalize(withoutWindowsLongPathPrefix);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function groupSessionsByNormalizedProjectPath(projectPaths, sessions, limit = 5) {
|
|
206
|
+
const groupedSessions = new Map();
|
|
207
|
+
const trackedPaths = new Set(
|
|
208
|
+
(projectPaths || [])
|
|
209
|
+
.map(normalizeComparableProjectPath)
|
|
210
|
+
.filter(Boolean)
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
for (const normalizedPath of trackedPaths) {
|
|
214
|
+
groupedSessions.set(normalizedPath, []);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
for (const session of sessions) {
|
|
218
|
+
const normalizedCwd = normalizeComparableProjectPath(session?.cwd);
|
|
219
|
+
if (!normalizedCwd || !trackedPaths.has(normalizedCwd)) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
groupedSessions.get(normalizedCwd).push(session);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const [normalizedPath, grouped] of groupedSessions.entries()) {
|
|
227
|
+
grouped.sort((a, b) => new Date(b.lastActivity || 0) - new Date(a.lastActivity || 0));
|
|
228
|
+
groupedSessions.set(normalizedPath, limit > 0 ? grouped.slice(0, limit) : grouped);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return groupedSessions;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function findFilesRecursively(rootDir, matcher) {
|
|
235
|
+
const discoveredFiles = [];
|
|
236
|
+
|
|
237
|
+
const walk = async (dir) => {
|
|
238
|
+
try {
|
|
239
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
240
|
+
for (const entry of entries) {
|
|
241
|
+
const fullPath = path.join(dir, entry.name);
|
|
242
|
+
if (entry.isDirectory()) {
|
|
243
|
+
await walk(fullPath);
|
|
244
|
+
} else if (matcher(entry.name, fullPath, entry)) {
|
|
245
|
+
discoveredFiles.push(fullPath);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
} catch (_) {
|
|
249
|
+
// Skip unreadable directories without failing the whole discovery pass.
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
await fs.access(rootDir);
|
|
255
|
+
} catch (_) {
|
|
256
|
+
return [];
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
await walk(rootDir);
|
|
260
|
+
return discoveredFiles;
|
|
261
|
+
}
|
|
200
262
|
|
|
201
263
|
// Clear cache when needed (called when project files change)
|
|
202
264
|
function clearProjectDirectoryCache() {
|
|
203
265
|
projectDirectoryCache.clear();
|
|
204
266
|
}
|
|
205
267
|
|
|
268
|
+
function clearProviderSessionLookupCaches() {
|
|
269
|
+
for (const cacheEntry of Object.values(providerSessionLookupCache)) {
|
|
270
|
+
cacheEntry.key = null;
|
|
271
|
+
cacheEntry.data = null;
|
|
272
|
+
cacheEntry.promise = null;
|
|
273
|
+
cacheEntry.expiresAt = 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async function getCachedProviderSessionLookup(providerName, cacheKey, buildLookup) {
|
|
278
|
+
const cacheEntry = providerSessionLookupCache[providerName];
|
|
279
|
+
|
|
280
|
+
if (!cacheEntry) {
|
|
281
|
+
return buildLookup();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (
|
|
285
|
+
cacheEntry.key === cacheKey &&
|
|
286
|
+
cacheEntry.data &&
|
|
287
|
+
cacheEntry.expiresAt > Date.now()
|
|
288
|
+
) {
|
|
289
|
+
return cacheEntry.data;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (cacheEntry.key === cacheKey && cacheEntry.promise) {
|
|
293
|
+
return cacheEntry.promise;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
cacheEntry.key = cacheKey;
|
|
297
|
+
cacheEntry.promise = Promise.resolve()
|
|
298
|
+
.then(buildLookup)
|
|
299
|
+
.then((lookup) => {
|
|
300
|
+
cacheEntry.data = lookup;
|
|
301
|
+
cacheEntry.expiresAt = Date.now() + PROVIDER_SESSION_LOOKUP_CACHE_TTL_MS;
|
|
302
|
+
return lookup;
|
|
303
|
+
})
|
|
304
|
+
.finally(() => {
|
|
305
|
+
cacheEntry.promise = null;
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
return cacheEntry.promise;
|
|
309
|
+
}
|
|
310
|
+
|
|
206
311
|
// Load project configuration file
|
|
207
312
|
async function loadProjectConfig() {
|
|
208
313
|
const configPath = path.join(os.homedir(), '.claude', 'project-config.json');
|
|
@@ -385,6 +490,7 @@ async function getProjects(progressCallback = null) {
|
|
|
385
490
|
const config = await loadProjectConfig();
|
|
386
491
|
const projects = [];
|
|
387
492
|
const existingProjects = new Set();
|
|
493
|
+
const projectDefinitions = [];
|
|
388
494
|
let totalProjects = 0;
|
|
389
495
|
let processedProjects = 0;
|
|
390
496
|
let directories = [];
|
|
@@ -420,8 +526,6 @@ async function getProjects(progressCallback = null) {
|
|
|
420
526
|
});
|
|
421
527
|
}
|
|
422
528
|
|
|
423
|
-
const projectPath = path.join(claudeDir, entry.name);
|
|
424
|
-
|
|
425
529
|
// Extract actual project directory from JSONL sessions
|
|
426
530
|
const actualProjectDir = await extractProjectDirectory(entry.name);
|
|
427
531
|
|
|
@@ -430,81 +534,14 @@ async function getProjects(progressCallback = null) {
|
|
|
430
534
|
const autoDisplayName = await generateDisplayName(entry.name, actualProjectDir);
|
|
431
535
|
const fullPath = actualProjectDir;
|
|
432
536
|
|
|
433
|
-
|
|
537
|
+
projectDefinitions.push({
|
|
434
538
|
name: entry.name,
|
|
435
539
|
path: actualProjectDir,
|
|
436
540
|
displayName: customName || autoDisplayName,
|
|
437
541
|
fullPath: fullPath,
|
|
438
542
|
isCustomName: !!customName,
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
codexSessions: [],
|
|
442
|
-
opencodeSessions: [],
|
|
443
|
-
geminiSessions: []
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
// Try to get sessions for this project (just first 5 for performance)
|
|
447
|
-
try {
|
|
448
|
-
const sessionResult = await getSessions(entry.name, 5, 0);
|
|
449
|
-
project.sessions = sessionResult.sessions || [];
|
|
450
|
-
project.sessionMeta = {
|
|
451
|
-
hasMore: sessionResult.hasMore,
|
|
452
|
-
total: sessionResult.total
|
|
453
|
-
};
|
|
454
|
-
} catch (e) {
|
|
455
|
-
console.warn(`Could not load sessions for project ${entry.name}:`, e.message);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Also fetch Cursor sessions for this project
|
|
459
|
-
try {
|
|
460
|
-
project.cursorSessions = await getCursorSessions(actualProjectDir);
|
|
461
|
-
} catch (e) {
|
|
462
|
-
console.warn(`Could not load Cursor sessions for project ${entry.name}:`, e.message);
|
|
463
|
-
project.cursorSessions = [];
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// Also fetch Codex sessions for this project
|
|
467
|
-
try {
|
|
468
|
-
project.codexSessions = await getCodexSessions(actualProjectDir);
|
|
469
|
-
} catch (e) {
|
|
470
|
-
console.warn(`Could not load Codex sessions for project ${entry.name}:`, e.message);
|
|
471
|
-
project.codexSessions = [];
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
try {
|
|
475
|
-
project.geminiSessions = await getGeminiSessions(actualProjectDir);
|
|
476
|
-
} catch (e) {
|
|
477
|
-
console.warn(`Could not load Gemini sessions for project ${entry.name}:`, e.message);
|
|
478
|
-
project.geminiSessions = [];
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
try {
|
|
482
|
-
project.opencodeSessions = await getOpencodeSessions(actualProjectDir);
|
|
483
|
-
} catch (e) {
|
|
484
|
-
console.warn(`Could not load OpenCode sessions for project ${entry.name}:`, e.message);
|
|
485
|
-
project.opencodeSessions = [];
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Add TaskMaster detection
|
|
489
|
-
try {
|
|
490
|
-
const taskMasterResult = await detectTaskMasterFolder(actualProjectDir);
|
|
491
|
-
project.taskmaster = {
|
|
492
|
-
hasTaskmaster: taskMasterResult.hasTaskmaster,
|
|
493
|
-
hasEssentialFiles: taskMasterResult.hasEssentialFiles,
|
|
494
|
-
metadata: taskMasterResult.metadata,
|
|
495
|
-
status: taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles ? 'configured' : 'not-configured'
|
|
496
|
-
};
|
|
497
|
-
} catch (e) {
|
|
498
|
-
console.warn(`Could not detect TaskMaster for project ${entry.name}:`, e.message);
|
|
499
|
-
project.taskmaster = {
|
|
500
|
-
hasTaskmaster: false,
|
|
501
|
-
hasEssentialFiles: false,
|
|
502
|
-
metadata: null,
|
|
503
|
-
status: 'error'
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
projects.push(project);
|
|
543
|
+
isManuallyAdded: false
|
|
544
|
+
});
|
|
508
545
|
}
|
|
509
546
|
} catch (error) {
|
|
510
547
|
// If the directory doesn't exist (ENOENT), that's okay - just continue with empty projects
|
|
@@ -544,74 +581,80 @@ async function getProjects(progressCallback = null) {
|
|
|
544
581
|
}
|
|
545
582
|
}
|
|
546
583
|
|
|
547
|
-
|
|
584
|
+
projectDefinitions.push({
|
|
548
585
|
name: projectName,
|
|
549
586
|
path: actualProjectDir,
|
|
550
587
|
displayName: projectConfig.displayName || await generateDisplayName(projectName, actualProjectDir),
|
|
551
588
|
fullPath: actualProjectDir,
|
|
552
589
|
isCustomName: !!projectConfig.displayName,
|
|
553
|
-
isManuallyAdded: true
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
opencodeSessions: [],
|
|
558
|
-
geminiSessions: []
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
// Try to fetch Cursor sessions for manual projects too
|
|
562
|
-
try {
|
|
563
|
-
project.cursorSessions = await getCursorSessions(actualProjectDir);
|
|
564
|
-
} catch (e) {
|
|
565
|
-
console.warn(`Could not load Cursor sessions for manual project ${projectName}:`, e.message);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Try to fetch Codex sessions for manual projects too
|
|
569
|
-
try {
|
|
570
|
-
project.codexSessions = await getCodexSessions(actualProjectDir);
|
|
571
|
-
} catch (e) {
|
|
572
|
-
console.warn(`Could not load Codex sessions for manual project ${projectName}:`, e.message);
|
|
573
|
-
}
|
|
590
|
+
isManuallyAdded: true
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
}
|
|
574
594
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
595
|
+
const uniqueProjectPaths = Array.from(new Set(
|
|
596
|
+
projectDefinitions
|
|
597
|
+
.map((definition) => normalizeComparableProjectPath(definition.fullPath))
|
|
598
|
+
.filter(Boolean)
|
|
599
|
+
));
|
|
600
|
+
|
|
601
|
+
const [codexSessionsByProjectPath, geminiSessionsByProjectPath, opencodeSessionsByProjectPath] = await Promise.all([
|
|
602
|
+
buildCodexSessionsLookup(uniqueProjectPaths, { limit: 5 }),
|
|
603
|
+
buildGeminiSessionsLookup(uniqueProjectPaths, { limit: 5 }),
|
|
604
|
+
buildOpencodeSessionsLookup(uniqueProjectPaths, { limit: 5 })
|
|
605
|
+
]);
|
|
606
|
+
|
|
607
|
+
for (const definition of projectDefinitions) {
|
|
608
|
+
const normalizedProjectPath = normalizeComparableProjectPath(definition.fullPath);
|
|
609
|
+
const project = {
|
|
610
|
+
name: definition.name,
|
|
611
|
+
path: definition.path,
|
|
612
|
+
displayName: definition.displayName,
|
|
613
|
+
fullPath: definition.fullPath,
|
|
614
|
+
isCustomName: definition.isCustomName,
|
|
615
|
+
isManuallyAdded: !!definition.isManuallyAdded,
|
|
616
|
+
sessions: [],
|
|
617
|
+
codexSessions: codexSessionsByProjectPath.get(normalizedProjectPath) || [],
|
|
618
|
+
opencodeSessions: opencodeSessionsByProjectPath.get(normalizedProjectPath) || [],
|
|
619
|
+
geminiSessions: geminiSessionsByProjectPath.get(normalizedProjectPath) || []
|
|
620
|
+
};
|
|
580
621
|
|
|
622
|
+
if (!definition.isManuallyAdded) {
|
|
581
623
|
try {
|
|
582
|
-
|
|
624
|
+
const sessionResult = await getSessions(definition.name, 5, 0);
|
|
625
|
+
project.sessions = sessionResult.sessions || [];
|
|
626
|
+
project.sessionMeta = {
|
|
627
|
+
hasMore: sessionResult.hasMore,
|
|
628
|
+
total: sessionResult.total
|
|
629
|
+
};
|
|
583
630
|
} catch (e) {
|
|
584
|
-
console.warn(`Could not load
|
|
631
|
+
console.warn(`Could not load sessions for project ${definition.name}:`, e.message);
|
|
585
632
|
}
|
|
633
|
+
}
|
|
586
634
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
hasTaskmaster: false,
|
|
608
|
-
hasEssentialFiles: false,
|
|
609
|
-
error: error.message
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
projects.push(project);
|
|
635
|
+
try {
|
|
636
|
+
const taskMasterResult = await detectTaskMasterFolder(definition.fullPath);
|
|
637
|
+
const taskMasterStatus = definition.isManuallyAdded
|
|
638
|
+
? (taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles ? 'taskmaster-only' : 'not-configured')
|
|
639
|
+
: (taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles ? 'configured' : 'not-configured');
|
|
640
|
+
|
|
641
|
+
project.taskmaster = {
|
|
642
|
+
status: taskMasterStatus,
|
|
643
|
+
hasTaskmaster: taskMasterResult.hasTaskmaster,
|
|
644
|
+
hasEssentialFiles: taskMasterResult.hasEssentialFiles,
|
|
645
|
+
metadata: taskMasterResult.metadata
|
|
646
|
+
};
|
|
647
|
+
} catch (error) {
|
|
648
|
+
console.warn(`TaskMaster detection failed for project ${definition.name}:`, error.message);
|
|
649
|
+
project.taskmaster = {
|
|
650
|
+
status: 'error',
|
|
651
|
+
hasTaskmaster: false,
|
|
652
|
+
hasEssentialFiles: false,
|
|
653
|
+
error: error.message
|
|
654
|
+
};
|
|
614
655
|
}
|
|
656
|
+
|
|
657
|
+
projects.push(project);
|
|
615
658
|
}
|
|
616
659
|
|
|
617
660
|
// Emit completion after all projects (including manual) are processed
|
|
@@ -1094,15 +1137,6 @@ async function deleteProject(projectName, force = false) {
|
|
|
1094
1137
|
} catch (err) {
|
|
1095
1138
|
console.warn('Failed to delete Codex sessions:', err.message);
|
|
1096
1139
|
}
|
|
1097
|
-
|
|
1098
|
-
// Delete Cursor sessions directory if it exists
|
|
1099
|
-
try {
|
|
1100
|
-
const hash = crypto.createHash('md5').update(projectPath).digest('hex');
|
|
1101
|
-
const cursorProjectDir = path.join(os.homedir(), '.cursor', 'chats', hash);
|
|
1102
|
-
await fs.rm(cursorProjectDir, { recursive: true, force: true });
|
|
1103
|
-
} catch (err) {
|
|
1104
|
-
// Cursor dir may not exist, ignore
|
|
1105
|
-
}
|
|
1106
1140
|
}
|
|
1107
1141
|
|
|
1108
1142
|
// Remove from project config
|
|
@@ -1139,7 +1173,7 @@ async function addProjectManually(projectPath, displayName = null) {
|
|
|
1139
1173
|
}
|
|
1140
1174
|
|
|
1141
1175
|
// Allow adding projects even if the directory exists - this enables tracking
|
|
1142
|
-
// existing Claude Code
|
|
1176
|
+
// existing Claude Code projects in the UI
|
|
1143
1177
|
|
|
1144
1178
|
// Add to config as manually added project
|
|
1145
1179
|
config[projectName] = {
|
|
@@ -1160,174 +1194,28 @@ async function addProjectManually(projectPath, displayName = null) {
|
|
|
1160
1194
|
fullPath: absolutePath,
|
|
1161
1195
|
displayName: displayName || await generateDisplayName(projectName, absolutePath),
|
|
1162
1196
|
isManuallyAdded: true,
|
|
1163
|
-
sessions: [],
|
|
1164
|
-
cursorSessions: [],
|
|
1165
|
-
codexSessions: [],
|
|
1197
|
+
sessions: [], codexSessions: [],
|
|
1166
1198
|
opencodeSessions: [],
|
|
1167
1199
|
geminiSessions: []
|
|
1168
1200
|
};
|
|
1169
1201
|
}
|
|
1170
1202
|
|
|
1171
|
-
// Fetch Cursor sessions for a given project path
|
|
1172
|
-
async function getCursorSessions(projectPath) {
|
|
1173
|
-
try {
|
|
1174
|
-
// Calculate cwdID hash for the project path (Cursor uses MD5 hash)
|
|
1175
|
-
const cwdId = crypto.createHash('md5').update(projectPath).digest('hex');
|
|
1176
|
-
const cursorChatsPath = path.join(os.homedir(), '.cursor', 'chats', cwdId);
|
|
1177
|
-
|
|
1178
|
-
// Check if the directory exists
|
|
1179
|
-
try {
|
|
1180
|
-
await fs.access(cursorChatsPath);
|
|
1181
|
-
} catch (error) {
|
|
1182
|
-
// No sessions for this project
|
|
1183
|
-
return [];
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
// List all session directories
|
|
1187
|
-
const sessionDirs = await fs.readdir(cursorChatsPath);
|
|
1188
|
-
const sessions = [];
|
|
1189
|
-
|
|
1190
|
-
for (const sessionId of sessionDirs) {
|
|
1191
|
-
const sessionPath = path.join(cursorChatsPath, sessionId);
|
|
1192
|
-
const storeDbPath = path.join(sessionPath, 'store.db');
|
|
1193
|
-
|
|
1194
|
-
try {
|
|
1195
|
-
// Check if store.db exists
|
|
1196
|
-
await fs.access(storeDbPath);
|
|
1197
|
-
|
|
1198
|
-
// Capture store.db mtime as a reliable fallback timestamp
|
|
1199
|
-
let dbStatMtimeMs = null;
|
|
1200
|
-
try {
|
|
1201
|
-
const stat = await fs.stat(storeDbPath);
|
|
1202
|
-
dbStatMtimeMs = stat.mtimeMs;
|
|
1203
|
-
} catch (_) {}
|
|
1204
|
-
|
|
1205
|
-
// Open SQLite database
|
|
1206
|
-
const db = await open({
|
|
1207
|
-
filename: storeDbPath,
|
|
1208
|
-
driver: sqlite3.Database,
|
|
1209
|
-
mode: sqlite3.OPEN_READONLY
|
|
1210
|
-
});
|
|
1211
|
-
|
|
1212
|
-
// Get metadata from meta table
|
|
1213
|
-
const metaRows = await db.all(`
|
|
1214
|
-
SELECT key, value FROM meta
|
|
1215
|
-
`);
|
|
1216
|
-
|
|
1217
|
-
// Parse metadata
|
|
1218
|
-
let metadata = {};
|
|
1219
|
-
for (const row of metaRows) {
|
|
1220
|
-
if (row.value) {
|
|
1221
|
-
try {
|
|
1222
|
-
// Try to decode as hex-encoded JSON
|
|
1223
|
-
const hexMatch = row.value.toString().match(/^[0-9a-fA-F]+$/);
|
|
1224
|
-
if (hexMatch) {
|
|
1225
|
-
const jsonStr = Buffer.from(row.value, 'hex').toString('utf8');
|
|
1226
|
-
metadata[row.key] = JSON.parse(jsonStr);
|
|
1227
|
-
} else {
|
|
1228
|
-
metadata[row.key] = row.value.toString();
|
|
1229
|
-
}
|
|
1230
|
-
} catch (e) {
|
|
1231
|
-
metadata[row.key] = row.value.toString();
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
// Get message count
|
|
1237
|
-
const messageCountResult = await db.get(`
|
|
1238
|
-
SELECT COUNT(*) as count FROM blobs
|
|
1239
|
-
`);
|
|
1240
|
-
|
|
1241
|
-
await db.close();
|
|
1242
|
-
|
|
1243
|
-
// Extract session info
|
|
1244
|
-
const sessionName = metadata.title || metadata.sessionTitle || 'Untitled Session';
|
|
1245
|
-
|
|
1246
|
-
// Determine timestamp - prefer createdAt from metadata, fall back to db file mtime
|
|
1247
|
-
let createdAt = null;
|
|
1248
|
-
if (metadata.createdAt) {
|
|
1249
|
-
createdAt = new Date(metadata.createdAt).toISOString();
|
|
1250
|
-
} else if (dbStatMtimeMs) {
|
|
1251
|
-
createdAt = new Date(dbStatMtimeMs).toISOString();
|
|
1252
|
-
} else {
|
|
1253
|
-
createdAt = new Date().toISOString();
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
sessions.push({
|
|
1257
|
-
id: sessionId,
|
|
1258
|
-
name: sessionName,
|
|
1259
|
-
createdAt: createdAt,
|
|
1260
|
-
lastActivity: createdAt, // For compatibility with Claude sessions
|
|
1261
|
-
messageCount: messageCountResult.count || 0,
|
|
1262
|
-
projectPath: projectPath
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
|
-
} catch (error) {
|
|
1266
|
-
console.warn(`Could not read Cursor session ${sessionId}:`, error.message);
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
// Sort sessions by creation time (newest first)
|
|
1271
|
-
sessions.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
|
1272
|
-
|
|
1273
|
-
// Return only the first 5 sessions for performance
|
|
1274
|
-
return sessions.slice(0, 5);
|
|
1275
|
-
|
|
1276
|
-
} catch (error) {
|
|
1277
|
-
console.error('Error fetching Cursor sessions:', error);
|
|
1278
|
-
return [];
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
// Fetch Codex sessions for a given project path
|
|
1284
1203
|
async function getCodexSessions(projectPath, options = {}) {
|
|
1285
1204
|
const { limit = 5 } = options;
|
|
1286
1205
|
try {
|
|
1287
|
-
const codexSessionsDir = path.join(os.homedir(), '.codex', 'sessions');
|
|
1288
1206
|
const sessions = [];
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
// No Codex sessions directory
|
|
1295
|
-
return [];
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
|
-
// Recursively find all .jsonl files in the sessions directory
|
|
1299
|
-
const findJsonlFiles = async (dir) => {
|
|
1300
|
-
const files = [];
|
|
1301
|
-
try {
|
|
1302
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
1303
|
-
for (const entry of entries) {
|
|
1304
|
-
const fullPath = path.join(dir, entry.name);
|
|
1305
|
-
if (entry.isDirectory()) {
|
|
1306
|
-
files.push(...await findJsonlFiles(fullPath));
|
|
1307
|
-
} else if (entry.name.endsWith('.jsonl')) {
|
|
1308
|
-
files.push(fullPath);
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
} catch (error) {
|
|
1312
|
-
// Skip directories we can't read
|
|
1313
|
-
}
|
|
1314
|
-
return files;
|
|
1315
|
-
};
|
|
1316
|
-
|
|
1317
|
-
const jsonlFiles = await findJsonlFiles(codexSessionsDir);
|
|
1207
|
+
const normalizedProjectPath = normalizeComparableProjectPath(projectPath);
|
|
1208
|
+
const jsonlFiles = await findFilesRecursively(
|
|
1209
|
+
path.join(os.homedir(), '.codex', 'sessions'),
|
|
1210
|
+
(entryName) => entryName.endsWith('.jsonl')
|
|
1211
|
+
);
|
|
1318
1212
|
|
|
1319
1213
|
// Process each file to find sessions matching the project path
|
|
1320
1214
|
for (const filePath of jsonlFiles) {
|
|
1321
1215
|
try {
|
|
1322
1216
|
const sessionData = await parseCodexSessionFile(filePath);
|
|
1323
1217
|
|
|
1324
|
-
|
|
1325
|
-
// Handle Windows long paths with \\?\ prefix
|
|
1326
|
-
const sessionCwd = sessionData?.cwd || '';
|
|
1327
|
-
const cleanSessionCwd = sessionCwd.startsWith('\\\\?\\') ? sessionCwd.slice(4) : sessionCwd;
|
|
1328
|
-
const cleanProjectPath = projectPath.startsWith('\\\\?\\') ? projectPath.slice(4) : projectPath;
|
|
1329
|
-
|
|
1330
|
-
if (sessionData && (sessionData.cwd === projectPath || cleanSessionCwd === cleanProjectPath || path.relative(cleanSessionCwd, cleanProjectPath) === '')) {
|
|
1218
|
+
if (sessionData && normalizeComparableProjectPath(sessionData.cwd) === normalizedProjectPath) {
|
|
1331
1219
|
sessions.push({
|
|
1332
1220
|
id: sessionData.id,
|
|
1333
1221
|
summary: sessionData.summary || 'Codex Session',
|
|
@@ -1364,25 +1252,12 @@ const OPENCODE_SESSION_DIR_CANDIDATES = [
|
|
|
1364
1252
|
async function findOpencodeSessionFiles() {
|
|
1365
1253
|
const files = [];
|
|
1366
1254
|
|
|
1367
|
-
const walk = async (dirPath) => {
|
|
1368
|
-
try {
|
|
1369
|
-
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
1370
|
-
for (const entry of entries) {
|
|
1371
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
1372
|
-
if (entry.isDirectory()) {
|
|
1373
|
-
await walk(fullPath);
|
|
1374
|
-
} else if (entry.isFile() && entry.name.endsWith('.jsonl')) {
|
|
1375
|
-
files.push(fullPath);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
} catch (_) {}
|
|
1379
|
-
};
|
|
1380
|
-
|
|
1381
1255
|
for (const baseDir of OPENCODE_SESSION_DIR_CANDIDATES) {
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1256
|
+
const discovered = await findFilesRecursively(
|
|
1257
|
+
baseDir,
|
|
1258
|
+
(entryName, _fullPath, entry) => entry.isFile() && entryName.endsWith('.jsonl')
|
|
1259
|
+
);
|
|
1260
|
+
files.push(...discovered);
|
|
1386
1261
|
}
|
|
1387
1262
|
|
|
1388
1263
|
return Array.from(new Set(files));
|
|
@@ -1852,6 +1727,120 @@ async function parseGeminiSessionFile(filePath) {
|
|
|
1852
1727
|
};
|
|
1853
1728
|
}
|
|
1854
1729
|
|
|
1730
|
+
async function buildCodexSessionsLookup(projectPaths, options = {}) {
|
|
1731
|
+
const { limit = 5 } = options;
|
|
1732
|
+
const normalizedProjectPaths = Array.from(new Set(
|
|
1733
|
+
(projectPaths || []).map(normalizeComparableProjectPath).filter(Boolean)
|
|
1734
|
+
));
|
|
1735
|
+
|
|
1736
|
+
if (normalizedProjectPaths.length === 0) {
|
|
1737
|
+
return new Map();
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
const cacheKey = JSON.stringify({ projectPaths: normalizedProjectPaths, limit });
|
|
1741
|
+
return getCachedProviderSessionLookup('codex', cacheKey, async () => {
|
|
1742
|
+
const jsonlFiles = await findFilesRecursively(
|
|
1743
|
+
path.join(os.homedir(), '.codex', 'sessions'),
|
|
1744
|
+
(entryName) => entryName.endsWith('.jsonl')
|
|
1745
|
+
);
|
|
1746
|
+
|
|
1747
|
+
const sessions = [];
|
|
1748
|
+
for (const filePath of jsonlFiles) {
|
|
1749
|
+
try {
|
|
1750
|
+
const sessionData = await parseCodexSessionFile(filePath);
|
|
1751
|
+
if (sessionData?.id) {
|
|
1752
|
+
sessions.push({
|
|
1753
|
+
id: sessionData.id,
|
|
1754
|
+
summary: sessionData.summary || 'Codex Session',
|
|
1755
|
+
messageCount: sessionData.messageCount || 0,
|
|
1756
|
+
lastActivity: sessionData.timestamp ? new Date(sessionData.timestamp) : new Date(),
|
|
1757
|
+
cwd: sessionData.cwd,
|
|
1758
|
+
model: sessionData.model,
|
|
1759
|
+
filePath,
|
|
1760
|
+
provider: 'codex'
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
} catch (error) {
|
|
1764
|
+
console.warn(`Could not parse Codex session file ${filePath}:`, error.message);
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
return groupSessionsByNormalizedProjectPath(normalizedProjectPaths, sessions, limit);
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
async function buildOpencodeSessionsLookup(projectPaths, options = {}) {
|
|
1773
|
+
const { limit = 5 } = options;
|
|
1774
|
+
const normalizedProjectPaths = Array.from(new Set(
|
|
1775
|
+
(projectPaths || []).map(normalizeComparableProjectPath).filter(Boolean)
|
|
1776
|
+
));
|
|
1777
|
+
|
|
1778
|
+
if (normalizedProjectPaths.length === 0) {
|
|
1779
|
+
return new Map();
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
const cacheKey = JSON.stringify({ projectPaths: normalizedProjectPaths, limit });
|
|
1783
|
+
return getCachedProviderSessionLookup('opencode', cacheKey, async () => {
|
|
1784
|
+
const sessionFiles = await findOpencodeSessionFiles();
|
|
1785
|
+
const sessions = [];
|
|
1786
|
+
|
|
1787
|
+
for (const filePath of sessionFiles) {
|
|
1788
|
+
const sessionData = await parseOpencodeSessionFile(filePath);
|
|
1789
|
+
if (sessionData?.id) {
|
|
1790
|
+
sessions.push(sessionData);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
return groupSessionsByNormalizedProjectPath(normalizedProjectPaths, sessions, limit);
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
async function buildGeminiSessionsLookup(projectPaths, options = {}) {
|
|
1799
|
+
const { limit = 5 } = options;
|
|
1800
|
+
const normalizedProjectPaths = Array.from(new Set(
|
|
1801
|
+
(projectPaths || []).map(normalizeComparableProjectPath).filter(Boolean)
|
|
1802
|
+
));
|
|
1803
|
+
|
|
1804
|
+
const cacheKey = JSON.stringify({ projectPaths: normalizedProjectPaths, limit });
|
|
1805
|
+
return getCachedProviderSessionLookup('gemini', cacheKey, async () => {
|
|
1806
|
+
const sessionsByProjectPath = new Map();
|
|
1807
|
+
|
|
1808
|
+
for (const normalizedProjectPath of normalizedProjectPaths) {
|
|
1809
|
+
const projectHash = crypto.createHash('sha256').update(normalizedProjectPath).digest('hex');
|
|
1810
|
+
const chatsDir = path.join(os.homedir(), '.gemini', 'tmp', projectHash, 'chats');
|
|
1811
|
+
|
|
1812
|
+
try {
|
|
1813
|
+
const entries = await fs.readdir(chatsDir, { withFileTypes: true });
|
|
1814
|
+
const sessionFiles = entries
|
|
1815
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
|
|
1816
|
+
.map((entry) => path.join(chatsDir, entry.name));
|
|
1817
|
+
|
|
1818
|
+
const sessions = [];
|
|
1819
|
+
for (const filePath of sessionFiles) {
|
|
1820
|
+
try {
|
|
1821
|
+
const sessionData = await parseGeminiSessionFile(filePath);
|
|
1822
|
+
if (sessionData?.id) {
|
|
1823
|
+
sessions.push(sessionData);
|
|
1824
|
+
}
|
|
1825
|
+
} catch (error) {
|
|
1826
|
+
console.warn(`Could not parse Gemini session file ${filePath}:`, error.message);
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
sessions.sort((a, b) => new Date(b.lastActivity || 0) - new Date(a.lastActivity || 0));
|
|
1831
|
+
sessionsByProjectPath.set(
|
|
1832
|
+
normalizedProjectPath,
|
|
1833
|
+
limit > 0 ? sessions.slice(0, limit) : sessions
|
|
1834
|
+
);
|
|
1835
|
+
} catch (_) {
|
|
1836
|
+
sessionsByProjectPath.set(normalizedProjectPath, []);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
return sessionsByProjectPath;
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1855
1844
|
async function getGeminiSessionMessages(sessionId, limit = null, offset = 0) {
|
|
1856
1845
|
try {
|
|
1857
1846
|
const geminiTmpDir = path.join(os.homedir(), '.gemini', 'tmp');
|
|
@@ -1966,9 +1955,16 @@ async function parseCodexSessionFile(filePath) {
|
|
|
1966
1955
|
crlfDelay: Infinity
|
|
1967
1956
|
});
|
|
1968
1957
|
|
|
1958
|
+
const isUsableCodexModel = (value) => {
|
|
1959
|
+
if (typeof value !== 'string') return false;
|
|
1960
|
+
const normalized = value.trim().toLowerCase();
|
|
1961
|
+
return normalized.length > 0 && normalized !== 'custom' && normalized !== 'default';
|
|
1962
|
+
};
|
|
1963
|
+
|
|
1969
1964
|
let sessionMeta = null;
|
|
1970
1965
|
let lastTimestamp = null;
|
|
1971
1966
|
let lastUserMessage = null;
|
|
1967
|
+
let lastResolvedModel = null;
|
|
1972
1968
|
let messageCount = 0;
|
|
1973
1969
|
|
|
1974
1970
|
for await (const line of rl) {
|
|
@@ -1990,6 +1986,16 @@ async function parseCodexSessionFile(filePath) {
|
|
|
1990
1986
|
timestamp: entry.timestamp,
|
|
1991
1987
|
git: entry.payload.git
|
|
1992
1988
|
};
|
|
1989
|
+
|
|
1990
|
+
if (isUsableCodexModel(entry.payload.model)) {
|
|
1991
|
+
lastResolvedModel = entry.payload.model;
|
|
1992
|
+
} else if (isUsableCodexModel(entry.payload.model_provider)) {
|
|
1993
|
+
lastResolvedModel = entry.payload.model_provider;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
if (entry.type === 'turn_context' && isUsableCodexModel(entry.payload?.model)) {
|
|
1998
|
+
lastResolvedModel = entry.payload.model;
|
|
1993
1999
|
}
|
|
1994
2000
|
|
|
1995
2001
|
// Count messages and extract user messages for summary
|
|
@@ -2013,6 +2019,7 @@ async function parseCodexSessionFile(filePath) {
|
|
|
2013
2019
|
if (sessionMeta) {
|
|
2014
2020
|
return {
|
|
2015
2021
|
...sessionMeta,
|
|
2022
|
+
model: lastResolvedModel || sessionMeta.model || null,
|
|
2016
2023
|
timestamp: lastTimestamp || sessionMeta.timestamp,
|
|
2017
2024
|
summary: lastUserMessage ?
|
|
2018
2025
|
(lastUserMessage.length > 50 ? lastUserMessage.substring(0, 50) + '...' : lastUserMessage) :
|
|
@@ -2309,10 +2316,12 @@ export {
|
|
|
2309
2316
|
saveProjectConfig,
|
|
2310
2317
|
extractProjectDirectory,
|
|
2311
2318
|
clearProjectDirectoryCache,
|
|
2319
|
+
clearProviderSessionLookupCaches,
|
|
2312
2320
|
getCodexSessions,
|
|
2313
2321
|
getCodexSessionMessages,
|
|
2314
2322
|
getOpencodeSessions,
|
|
2315
2323
|
getOpencodeSessionMessages,
|
|
2324
|
+
getGeminiSessions,
|
|
2316
2325
|
getGeminiSessionMessages,
|
|
2317
2326
|
deleteCodexSession,
|
|
2318
2327
|
deleteOpencodeSession
|